~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/guestInfo/guestInfoServer.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*********************************************************
2
 
 * Copyright (C) 1998 VMware, Inc. All rights reserved.
 
2
 * Copyright (C) 1998-2010 VMware, Inc. All rights reserved.
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or modify it
5
5
 * under the terms of the GNU Lesser General Public License as published
67
67
 
68
68
 
69
69
/**
 
70
 * Upper bound for value sizes, based on gethostname(2):
 
71
 *
 
72
 *    SUS2 guarantees that "Host names are limited to 255 bytes".
 
73
 *
 
74
 * We can't modify MAX_VALUE_LEN since it's used in wire-level definitions
 
75
 * (such as PartitionEntry).
 
76
 */
 
77
#define GUESTINFO_MAX_VALUE_SIZE    256
 
78
 
 
79
MY_ASSERTS(GI_SIZE_ASSERTS,
 
80
           ASSERT_ON_COMPILE(GUESTINFO_MAX_VALUE_SIZE >= MAX_VALUE_LEN);
 
81
)
 
82
 
 
83
/**
70
84
 * Default poll interval is 30s (in milliseconds).
71
85
 */
72
86
#define GUESTINFO_TIME_INTERVAL_MSEC 30000
78
92
 */
79
93
 
80
94
typedef struct _GuestInfoCache{
81
 
   char value[INFO_MAX][MAX_VALUE_LEN]; /* Stores values of all key-value pairs. */
 
95
   /* Stores values of all key-value pairs. */
 
96
   char value[INFO_MAX][GUESTINFO_MAX_VALUE_SIZE];
82
97
   NicInfoV3     *nicInfo;
83
 
   GuestDiskInfo diskInfo;
 
98
   GuestDiskInfo *diskInfo;
84
99
} GuestInfoCache;
85
100
 
86
101
 
109
124
 
110
125
static Bool vmResumed;
111
126
 
 
127
 
 
128
/*
 
129
 * Local functions
 
130
 */
 
131
 
 
132
 
112
133
static Bool GuestInfoUpdateVmdb(ToolsAppCtx *ctx, GuestInfoType infoType, void *info);
113
134
static Bool SetGuestInfo(ToolsAppCtx *ctx, GuestInfoType key,
114
 
                         const char *value, char delimiter);
115
 
static Bool DiskInfoChanged(PGuestDiskInfo diskInfo);
 
135
                         const char *value);
 
136
static void SendUptime(ToolsAppCtx *ctx);
 
137
static Bool DiskInfoChanged(const GuestDiskInfo *diskInfo);
116
138
static void GuestInfoClearCache(void);
117
139
static GuestNicList *NicInfoV3ToV2(const NicInfoV3 *infoV3);
118
140
static void TweakGatherLoop(ToolsAppCtx *ctx, gboolean enable);
119
141
 
120
142
 
121
 
/**
122
 
 * Lauches the VM support process in the guest when requested by the host.
123
 
 *
124
 
 * @param[in]  data     RPC request data.
125
 
 *
126
 
 * @return TRUE on success.
 
143
/*
 
144
 ******************************************************************************
 
145
 * GuestInfoVMSupport --                                                 */ /**
 
146
 *
 
147
 * Launches the vm-support process.  Data returned asynchronously via RPCI.
 
148
 *
 
149
 * @param[in]   data     RPC request data.
 
150
 *
 
151
 * @return      TRUE if able to launch script, FALSE if script failed.
 
152
 *
 
153
 ******************************************************************************
127
154
 */
128
155
 
129
156
static gboolean
201
228
 
202
229
/*
203
230
 ******************************************************************************
204
 
 * GuestInfoServerConfReload --                                          */ /**
205
 
 *
206
 
 * @brief Reconfigures the poll loop interval upon config file reload.
207
 
 *
208
 
 * @param[in]  src     The source object.
209
 
 * @param[in]  ctx     The application context.
210
 
 * @param[in]  data    Unused.
211
 
 *
212
 
 ******************************************************************************
213
 
 */
214
 
 
215
 
static void
216
 
GuestInfoServerConfReload(gpointer src,
217
 
                          ToolsAppCtx *ctx,
218
 
                          gpointer data)
219
 
{
220
 
   TweakGatherLoop(ctx, TRUE);
221
 
}
222
 
 
223
 
 
224
 
/*
225
 
 ******************************************************************************
226
 
 * GuestInfoServerIOFreeze --                                           */ /**
227
 
 *
228
 
 * IO freeze signal handler. Disables info gathering while I/O is frozen.
229
 
 * See bug 529653.
230
 
 *
231
 
 * @param[in]  src      The source object.
232
 
 * @param[in]  ctx      The application context.
233
 
 * @param[in]  freeze   Whether I/O is being frozen.
234
 
 * @param[in]  data     Unused.
235
 
 *
236
 
 ******************************************************************************
237
 
 */
238
 
 
239
 
static void
240
 
GuestInfoServerIOFreeze(gpointer src,
241
 
                        ToolsAppCtx *ctx,
242
 
                        gboolean freeze,
243
 
                        gpointer data)
244
 
{
245
 
   TweakGatherLoop(ctx, !freeze);
246
 
}
247
 
 
248
 
 
249
 
/**
250
 
 * Cleanup internal data on shutdown.
251
 
 *
252
 
 * @param[in]  src     The source object.
253
 
 * @param[in]  ctx     Unused.
254
 
 * @param[in]  data    Unused.
255
 
 */
256
 
 
257
 
static void
258
 
GuestInfoServerShutdown(gpointer src,
259
 
                        ToolsAppCtx *ctx,
260
 
                        gpointer data)
261
 
{
262
 
   GuestInfoClearCache();
263
 
 
264
 
   if (gatherTimeoutSource != NULL) {
265
 
      g_source_destroy(gatherTimeoutSource);
266
 
      gatherTimeoutSource = NULL;
267
 
   }
268
 
}
269
 
 
270
 
 
271
 
/**
272
 
 * Reset callback - sets the internal flag that says we should purge all
273
 
 * caches.
274
 
 *
275
 
 * @param[in]  src      The source object.
276
 
 * @param[in]  ctx      Unused.
277
 
 * @param[in]  data     Unused.
278
 
 */
279
 
 
280
 
static void
281
 
GuestInfoServerReset(gpointer src,
282
 
                     ToolsAppCtx *ctx,
283
 
                     gpointer data)
284
 
{
285
 
   vmResumed = TRUE;
286
 
}
287
 
 
288
 
 
289
 
/**
290
 
 * Send the guest uptime through the backdoor, if @a set is TRUE.
291
 
 *
292
 
 * @param[in]  src      The source object.
293
 
 * @param[in]  ctx      The application context.
294
 
 * @param[in]  set      Whether capabilities are being set.
295
 
 * @param[in]  data     Unused.
296
 
 *
297
 
 * @return NULL
298
 
 */
299
 
 
300
 
static GArray *
301
 
GuestInfoServerSendUptime(gpointer src,
302
 
                          ToolsAppCtx *ctx,
303
 
                          gboolean set,
304
 
                          gpointer data)
305
 
{
306
 
   if (set) {
307
 
      gchar *uptime = g_strdup_printf("%"FMT64"u", System_Uptime());
308
 
      g_debug("Setting guest uptime to '%s'\n", uptime);
309
 
      GuestInfoUpdateVmdb(ctx, INFO_UPTIME, uptime);
310
 
      g_free(uptime);
311
 
   }
312
 
   return NULL;
313
 
}
314
 
 
315
 
 
316
 
/**
317
 
 * Responds to a "broadcastIP" Set_Option command, by sending the primary IP
318
 
 * back to the VMX.
319
 
 *
320
 
 * @param[in]  src      The source object.
321
 
 * @param[in]  ctx      The application context.
322
 
 * @param[in]  option   Option name.
323
 
 * @param[in]  value    Option value.
324
 
 * @param[in]  data     Unused.
325
 
 */
326
 
 
327
 
static gboolean
328
 
GuestInfoServerSetOption(gpointer src,
329
 
                         ToolsAppCtx *ctx,
330
 
                         const gchar *option,
331
 
                         const gchar *value,
332
 
                         gpointer data)
333
 
{
334
 
   char *ip;
335
 
   Bool ret = FALSE;
336
 
 
337
 
   if (strcmp(option, TOOLSOPTION_BROADCASTIP) != 0) {
338
 
      goto exit;
339
 
   }
340
 
 
341
 
   if (strcmp(value, "0") == 0) {
342
 
      ret = TRUE;
343
 
      goto exit;
344
 
   }
345
 
 
346
 
   if (strcmp(value, "1") != 0) {
347
 
      goto exit;
348
 
   }
349
 
 
350
 
   ip = NetUtil_GetPrimaryIP();
351
 
 
352
 
   if (ip != NULL) {
353
 
      gchar *msg;
354
 
      msg = g_strdup_printf("info-set guestinfo.ip %s", ip);
355
 
      ret = RpcChannel_Send(ctx->rpc, msg, strlen(msg) + 1, NULL, NULL);
356
 
      vm_free(ip);
357
 
      g_free(msg);
358
 
   }
359
 
 
360
 
exit:
361
 
   return (gboolean) ret;
362
 
}
363
 
 
364
 
 
365
 
/**
366
 
 * Periodically collects all the desired guest information and updates VMDB.
 
231
 * GuestInfoGather --                                                    */ /**
 
232
 *
 
233
 * Collects all the desired guest information and updates the VMX.
367
234
 *
368
235
 * @param[in]  data     The application context.
369
236
 *
370
 
 * @return TRUE.
 
237
 * @return TRUE to indicate that the timer should be rescheduled.
 
238
 *
 
239
 ******************************************************************************
371
240
 */
372
241
 
373
242
static gboolean
374
243
GuestInfoGather(gpointer data)
375
244
{
376
 
   char name[255];
377
 
   char osNameFull[MAX_VALUE_LEN];
378
 
   char osName[MAX_VALUE_LEN];
 
245
   char name[GUESTINFO_MAX_VALUE_SIZE];
 
246
   char osNameFull[GUESTINFO_MAX_VALUE_SIZE];
 
247
   char osName[GUESTINFO_MAX_VALUE_SIZE];
379
248
   gboolean disableQueryDiskInfo;
380
249
   NicInfoV3 *nicInfo = NULL;
381
 
   GuestDiskInfo diskInfo;
 
250
   GuestDiskInfo *diskInfo = NULL;
382
251
#if defined(_WIN32) || defined(linux)
383
252
   GuestMemInfo vmStats = {0};
 
253
   gboolean perfmonEnabled;
384
254
#endif
385
255
   ToolsAppCtx *ctx = data;
386
256
 
413
283
      g_key_file_get_boolean(ctx->config, CONFGROUPNAME_GUESTINFO,
414
284
                             CONFNAME_GUESTINFO_DISABLEQUERYDISKINFO, NULL);
415
285
   if (!disableQueryDiskInfo) {
416
 
      if (!GuestInfo_GetDiskInfo(&diskInfo)) {
 
286
      if ((diskInfo = GuestInfo_GetDiskInfo()) == NULL) {
417
287
         g_warning("Failed to get disk info.\n");
418
288
      } else {
419
 
         if (!GuestInfoUpdateVmdb(ctx, INFO_DISK_FREE_SPACE, &diskInfo)) {
 
289
         if (GuestInfoUpdateVmdb(ctx, INFO_DISK_FREE_SPACE, diskInfo)) {
 
290
            GuestInfo_FreeDiskInfo(gInfoCache.diskInfo);
 
291
            gInfoCache.diskInfo = diskInfo;
 
292
         } else {
420
293
            g_warning("Failed to update VMDB\n.");
 
294
            GuestInfo_FreeDiskInfo(diskInfo);
421
295
         }
422
 
         GuestInfo_FreeDiskInfo(&diskInfo);
423
296
      }
424
297
   }
425
298
 
426
 
   if (!GuestInfo_GetFqdn(sizeof name, name)) {
 
299
   if (!System_GetNodeName(sizeof name, name)) {
427
300
      g_warning("Failed to get netbios name.\n");
428
301
   } else if (!GuestInfoUpdateVmdb(ctx, INFO_DNS_NAME, name)) {
429
302
      g_warning("Failed to update VMDB.\n");
448
321
   }
449
322
 
450
323
   /* Send the uptime to VMX so that it can detect soft resets. */
451
 
   GuestInfoServerSendUptime(NULL, ctx, TRUE, NULL);
 
324
   SendUptime(ctx);
452
325
 
453
326
#if defined(_WIN32) || defined(linux)
454
327
   /* Send the vmstats to the VMX. */
 
328
   perfmonEnabled = !g_key_file_get_boolean(ctx->config,
 
329
                                            CONFGROUPNAME_GUESTINFO,
 
330
                                            CONFNAME_GUESTINFO_DISABLEPERFMON,
 
331
                                            NULL);
455
332
 
456
 
   if (!GuestInfo_PerfMon(&vmStats)) {
457
 
      g_warning("Failed to get vmstats.\n");
458
 
   } else {
459
 
      vmStats.version = 1;
460
 
      if (!GuestInfoUpdateVmdb(ctx, INFO_MEMORY, &vmStats)) {
461
 
         g_warning("Failed to send vmstats.\n");
 
333
   if (perfmonEnabled) {
 
334
      if (!GuestInfo_PerfMon(&vmStats)) {
 
335
         g_warning("Failed to get vmstats.\n");
 
336
      } else {
 
337
         vmStats.version = 1;
 
338
         if (!GuestInfoUpdateVmdb(ctx, INFO_MEMORY, &vmStats)) {
 
339
            g_warning("Failed to send vmstats.\n");
 
340
         }
462
341
      }
463
342
   }
464
343
#endif
468
347
 
469
348
 
470
349
/*
471
 
 *----------------------------------------------------------------------
472
 
 *
473
 
 * GuestInfoConvertNicInfoToNicInfoV1 --
474
 
 *
475
 
 *      Convert the new dynamic nicInfoNew to fixed size struct GuestNicInfoV1.
476
 
 *
477
 
 * Results:
478
 
 *      TRUE if successfully converted
479
 
 *      FALSE otherwise
480
 
 *
481
 
 * Side effects:
482
 
 *      If number of NICs or number of IP addresses on any of the NICs
483
 
 *      exceeding MAX_NICS and MAX_IPS respectively, the extra ones
484
 
 *      are truncated, on successful return.
485
 
 *
486
 
 *----------------------------------------------------------------------
 
350
 ******************************************************************************
 
351
 * GuestInfoConvertNicInfoToNicInfoV1 --                                 */ /**
 
352
 *
 
353
 * Converts V3 XDR NicInfo to hand-packed GuestNicInfoV1.
 
354
 *
 
355
 * @note Any NICs above MAX_NICS or IPs above MAX_IPS will be truncated.
 
356
 *
 
357
 * @param[in]  info   V3 input data.
 
358
 * @param[out] infoV1 V1 output data.
 
359
 *
 
360
 * @retval TRUE Conversion succeeded.
 
361
 * @retval FALSE Conversion failed.
 
362
 *
 
363
 ******************************************************************************
487
364
 */
488
365
 
489
366
void
490
 
GuestInfoConvertNicInfoToNicInfoV1(NicInfoV3 *info,           // IN
491
 
                                   GuestNicInfoV1 *infoV1)    // OUT
 
367
GuestInfoConvertNicInfoToNicInfoV1(NicInfoV3 *info,
 
368
                                   GuestNicInfoV1 *infoV1)
492
369
{
493
370
   uint32 maxNics;
494
371
   u_int i;
543
420
 
544
421
 
545
422
/*
546
 
 *-----------------------------------------------------------------------------
547
 
 *
548
 
 * GuestInfoUpdateVmdb --
549
 
 *
550
 
 *    Update VMDB with new guest information.
551
 
 *    This is the only function that should need to change when the VMDB pipe
552
 
 *    is implemented. Since we dont currently have a VMDB instance in the guest
553
 
 *    the function updates the VMDB instance on the host. Updates are sent only
554
 
 *    if the values have changed.
555
 
 *
556
 
 * Result
557
 
 *    TRUE on success, FALSE on failure.
558
 
 *
559
 
 * Side-effects
560
 
 *    VMDB is updated if the given value has changed.
561
 
 *
562
 
 *-----------------------------------------------------------------------------
 
423
 ******************************************************************************
 
424
 * GuestInfoUpdateVmdb --                                                */ /**
 
425
 *
 
426
 * Push singular GuestInfo snippets to the VMX.
 
427
 *
 
428
 * @note Data are cached, so updates are sent only if they have changed.
 
429
 *
 
430
 * @param[in] ctx       Application context.
 
431
 * @param[in] infoType  Guest information type.
 
432
 * @param[in] info      Type-specific information.
 
433
 *
 
434
 * @retval TRUE  Update sent successfully.
 
435
 * @retval FALSE Had trouble with serialization or transmission.
 
436
 *
 
437
 ******************************************************************************
563
438
 */
564
439
 
565
440
Bool
592
467
         break;
593
468
      }
594
469
 
595
 
      if (!SetGuestInfo(ctx, infoType, (char *)info, 0)) {
 
470
      if (!SetGuestInfo(ctx, infoType, (char *)info)) {
596
471
         g_warning("Failed to update key/value pair for type %d.\n", infoType);
597
472
         return FALSE;
598
473
      }
599
474
 
600
475
      /* Update the value in the cache as well. */
601
 
      Str_Strcpy(gInfoCache.value[infoType], (char *)info, MAX_VALUE_LEN);
 
476
      Str_Strcpy(gInfoCache.value[infoType],
 
477
                 (char *)info,
 
478
                 sizeof gInfoCache.value[infoType]);
602
479
      break;
603
480
 
604
481
   case INFO_IPADDRESS:
653
530
               /* Write preamble and serialized nic info to XDR stream. */
654
531
               if (!DynXdr_AppendRaw(&xdrs, request, strlen(request)) ||
655
532
                   !xdr_GuestNicProto(&xdrs, &message)) {
656
 
                  g_warning("Error serializing nic info v2 data.");
 
533
                  g_warning("Error serializing nic info v%d data.", message.ver);
657
534
                  DynXdr_Destroy(&xdrs, TRUE);
658
535
                  return FALSE;
659
536
               }
784
661
            break;
785
662
         }
786
663
 
 
664
         ASSERT((pdi->numEntries && pdi->partitionList) ||
 
665
                (!pdi->numEntries && !pdi->partitionList));
 
666
 
787
667
         requestSize += sizeof pdi->numEntries +
788
668
                        sizeof *pdi->partitionList * pdi->numEntries;
789
 
         request = (char *)calloc(requestSize, sizeof (char));
790
 
         if (request == NULL) {
791
 
            g_warning("Could not allocate memory for request.\n");
792
 
            break;
793
 
         }
 
669
         request = Util_SafeCalloc(requestSize, sizeof *request);
794
670
 
795
671
         Str_Sprintf(request, requestSize, "%s  %d ", GUEST_INFO_COMMAND,
796
672
                     INFO_DISK_FREE_SPACE);
816
692
          * it's safe to send it from 64-bit Tools to a 32-bit VMX, etc.
817
693
          */
818
694
         memcpy(request + offset, &partitionCount, sizeof partitionCount);
819
 
         memcpy(request + offset + sizeof partitionCount, pdi->partitionList,
820
 
                sizeof *pdi->partitionList * pdi->numEntries);
 
695
 
 
696
         /*
 
697
          * Conditioned because memcpy(dst, NULL, 0) -may- lead to undefined
 
698
          * behavior.
 
699
          */
 
700
         if (pdi->partitionList) {
 
701
            memcpy(request + offset + sizeof partitionCount, pdi->partitionList,
 
702
                   sizeof *pdi->partitionList * pdi->numEntries);
 
703
         }
821
704
 
822
705
         g_debug("sizeof request is %d\n", requestSize);
823
706
         status = RpcChannel_Send(ctx->rpc, request, requestSize, &reply, &replyLen);
835
718
 
836
719
         g_debug("Updated disk info information\n");
837
720
 
838
 
         if (!GuestInfo_CopyDiskInfo(&gInfoCache.diskInfo, pdi)) {
839
 
            g_warning("Could not cache the disk info data.\n");
840
 
            return FALSE;
841
 
         }
842
 
 
843
721
         break;
844
722
      }
845
723
   default:
853
731
 
854
732
 
855
733
/*
856
 
 *----------------------------------------------------------------------
857
 
 *
858
 
 * SetGuestInfo --
859
 
 *
860
 
 *      Ask Vmx to write some information about the guest into VMDB.
861
 
 *
862
 
 * Results:
863
 
 *
864
 
 *      TRUE/FALSE depending on whether the RPCI succeeded or failed.
865
 
 *
866
 
 * Side effects:
867
 
 *
868
 
 *      None.
869
 
 *
870
 
 *----------------------------------------------------------------------
 
734
 ******************************************************************************
 
735
 * SendUptime --                                                         */ /**
 
736
 *
 
737
 * Send the guest uptime through the backdoor.
 
738
 *
 
739
 * @param[in]  ctx      The application context.
 
740
 *
 
741
 ******************************************************************************
 
742
 */
 
743
 
 
744
static void
 
745
SendUptime(ToolsAppCtx *ctx)
 
746
{
 
747
   gchar *uptime = g_strdup_printf("%"FMT64"u", System_Uptime());
 
748
   g_debug("Setting guest uptime to '%s'\n", uptime);
 
749
   GuestInfoUpdateVmdb(ctx, INFO_UPTIME, uptime);
 
750
   g_free(uptime);
 
751
}
 
752
 
 
753
 
 
754
/*
 
755
 ******************************************************************************
 
756
 * SetGuestInfo --                                                       */ /**
 
757
 *
 
758
 * Sends a simple key-value update request to the VMX.
 
759
 *
 
760
 * @param[in] ctx       Application context.
 
761
 * @param[in] key       VMDB key to set
 
762
 * @param[in] value     GuestInfo data
 
763
 *
 
764
 * @retval TRUE  RPCI succeeded.
 
765
 * @retval FALSE RPCI failed.
 
766
 *
 
767
 ******************************************************************************
871
768
 */
872
769
 
873
770
Bool
874
 
SetGuestInfo(ToolsAppCtx *ctx,   // IN: application context
875
 
             GuestInfoType key,  // IN: the VMDB key to set
876
 
             const char *value,  // IN:
877
 
             char delimiter)     // IN: delimiting character for the rpc
878
 
                                 //     message. 0 indicates default.
 
771
SetGuestInfo(ToolsAppCtx *ctx,
 
772
             GuestInfoType key,
 
773
             const char *value)
879
774
{
880
775
   Bool status;
881
776
   char *reply;
885
780
   ASSERT(key);
886
781
   ASSERT(value);
887
782
 
888
 
   if (!delimiter) {
889
 
      delimiter = GUESTINFO_DEFAULT_DELIMITER;
890
 
   }
891
 
 
 
783
   /*
 
784
    * XXX Consider retiring this runtime "delimiter" business and just
 
785
    * insert raw spaces into the format string.
 
786
    */
892
787
   msg = g_strdup_printf("%s %c%d%c%s", GUEST_INFO_COMMAND,
893
 
                         delimiter, key, delimiter, value);
 
788
                         GUESTINFO_DEFAULT_DELIMITER, key,
 
789
                         GUESTINFO_DEFAULT_DELIMITER, value);
894
790
 
895
791
   status = RpcChannel_Send(ctx->rpc, msg, strlen(msg) + 1, &reply, &replyLen);
896
792
   g_free(msg);
909
805
 
910
806
 
911
807
/*
912
 
 *-----------------------------------------------------------------------------
913
 
 *
914
 
 * GuestInfoFindMacAddress --
915
 
 *
916
 
 *      Locates a NIC with the given MAC address in the NIC list.
917
 
 *
918
 
 * Return value:
919
 
 *      If there is an entry in nicInfo which corresponds to this MAC address,
920
 
 *      it is returned. If not NULL is returned.
921
 
 *
922
 
 * Side effects:
923
 
 *      None
924
 
 *
925
 
 *-----------------------------------------------------------------------------
 
808
 ******************************************************************************
 
809
 * GuestInfoFindMacAddress --                                            */ /**
 
810
 *
 
811
 * Locates a NIC with the given MAC address in the NIC list.
 
812
 *
 
813
 * @param[in] nicInfo    NicInfoV3 container.
 
814
 * @param[in] macAddress Requested MAC address.
 
815
 *
 
816
 * @return Valid pointer if NIC found, else NULL.
 
817
 *
 
818
 ******************************************************************************
926
819
 */
927
820
 
 
821
 
928
822
GuestNicV3 *
929
823
GuestInfoFindMacAddress(NicInfoV3 *nicInfo,     // IN/OUT
930
824
                        const char *macAddress) // IN
943
837
 
944
838
 
945
839
/*
946
 
 *----------------------------------------------------------------------
947
 
 *
948
 
 * DiskInfoChanged --
949
 
 *
950
 
 *      Checks whether disk info information just obtained is different from
951
 
 *      the information last sent to VMDB.
952
 
 *
953
 
 * Results:
954
 
 *
955
 
 *      TRUE if the disk info has changed, FALSE otherwise.
956
 
 *
957
 
 * Side effects:
958
 
 *
959
 
 *      None.
960
 
 *
961
 
 *----------------------------------------------------------------------
 
840
 ******************************************************************************
 
841
 * DiskInfoChanged --                                                    */ /**
 
842
 *
 
843
 * Checks whether disk info information just obtained is different from the
 
844
 * information last sent to the VMX.
 
845
 *
 
846
 * @param[in]  diskInfo New disk info.
 
847
 *
 
848
 * @retval TRUE  Data has changed.
 
849
 * @retval FALSE Data has not changed.
 
850
 *
 
851
 ******************************************************************************
962
852
 */
963
853
 
964
 
Bool
965
 
DiskInfoChanged(PGuestDiskInfo diskInfo)     // IN:
 
854
static Bool
 
855
DiskInfoChanged(const GuestDiskInfo *diskInfo)
966
856
{
967
857
   int index;
968
858
   char *name;
970
860
   int matchedPartition;
971
861
   PGuestDiskInfo cachedDiskInfo;
972
862
 
973
 
   cachedDiskInfo = &gInfoCache.diskInfo;
 
863
   cachedDiskInfo = gInfoCache.diskInfo;
 
864
 
 
865
   if (cachedDiskInfo == diskInfo) {
 
866
      return FALSE;
 
867
      /* Implies that either cachedDiskInfo or diskInfo != NULL. */
 
868
   } else if (!cachedDiskInfo || !diskInfo) {
 
869
      return TRUE;
 
870
   }
974
871
 
975
872
   if (cachedDiskInfo->numEntries != diskInfo->numEntries) {
976
873
      g_debug("Number of disks has changed\n");
1013
910
 
1014
911
 
1015
912
/*
1016
 
 *----------------------------------------------------------------------
1017
 
 *
1018
 
 * GuestInfoClearCache --
1019
 
 *
1020
 
 *    Clears the cached guest info data.
1021
 
 *
1022
 
 * Results:
1023
 
 *    None.
1024
 
 *
1025
 
 * Side effects:
1026
 
 *    gInfoCache is cleared.
1027
 
 *
1028
 
 *----------------------------------------------------------------------
 
913
 ******************************************************************************
 
914
 * GuestInfoClearCache --                                                */ /**
 
915
 *
 
916
 * Clears the cached guest info data.
 
917
 *
 
918
 ******************************************************************************
1029
919
 */
1030
920
 
1031
921
static void
1037
927
      gInfoCache.value[i][0] = 0;
1038
928
   }
1039
929
 
1040
 
   GuestInfo_FreeDiskInfo(&gInfoCache.diskInfo);
 
930
   GuestInfo_FreeDiskInfo(gInfoCache.diskInfo);
 
931
   gInfoCache.diskInfo = NULL;
1041
932
 
1042
933
   GuestInfo_FreeNicInfo(gInfoCache.nicInfo);
1043
934
   gInfoCache.nicInfo = NULL;
1186
1077
/*
1187
1078
 ******************************************************************************
1188
1079
 * BEGIN Tools Core Services goodies.
1189
 
 *
1190
 
 * TODO Move GuestInfoServerShutdown and friends within this block.  Saving
1191
 
 * that for a later changeset.
1192
 
 */
1193
 
 
1194
 
 
1195
 
/**
 
1080
 */
 
1081
 
 
1082
 
 
1083
/*
 
1084
 ******************************************************************************
 
1085
 * GuestInfoServerConfReload --                                          */ /**
 
1086
 *
 
1087
 * @brief Reconfigures the poll loop interval upon config file reload.
 
1088
 *
 
1089
 * @param[in]  src     The source object.
 
1090
 * @param[in]  ctx     The application context.
 
1091
 * @param[in]  data    Unused.
 
1092
 *
 
1093
 ******************************************************************************
 
1094
 */
 
1095
 
 
1096
static void
 
1097
GuestInfoServerConfReload(gpointer src,
 
1098
                          ToolsAppCtx *ctx,
 
1099
                          gpointer data)
 
1100
{
 
1101
   TweakGatherLoop(ctx, TRUE);
 
1102
}
 
1103
 
 
1104
 
 
1105
/*
 
1106
 ******************************************************************************
 
1107
 * GuestInfoServerIOFreeze --                                           */ /**
 
1108
 *
 
1109
 * IO freeze signal handler. Disables info gathering while I/O is frozen.
 
1110
 * See bug 529653.
 
1111
 *
 
1112
 * @param[in]  src      The source object.
 
1113
 * @param[in]  ctx      The application context.
 
1114
 * @param[in]  freeze   Whether I/O is being frozen.
 
1115
 * @param[in]  data     Unused.
 
1116
 *
 
1117
 ******************************************************************************
 
1118
 */
 
1119
 
 
1120
static void
 
1121
GuestInfoServerIOFreeze(gpointer src,
 
1122
                        ToolsAppCtx *ctx,
 
1123
                        gboolean freeze,
 
1124
                        gpointer data)
 
1125
{
 
1126
   TweakGatherLoop(ctx, !freeze);
 
1127
}
 
1128
 
 
1129
 
 
1130
/*
 
1131
 ******************************************************************************
 
1132
 * GuestInfoServerShutdown --                                            */ /**
 
1133
 *
 
1134
 * Cleanup internal data on shutdown.
 
1135
 *
 
1136
 * @param[in]  src     The source object.
 
1137
 * @param[in]  ctx     Unused.
 
1138
 * @param[in]  data    Unused.
 
1139
 *
 
1140
 ******************************************************************************
 
1141
 */
 
1142
 
 
1143
static void
 
1144
GuestInfoServerShutdown(gpointer src,
 
1145
                        ToolsAppCtx *ctx,
 
1146
                        gpointer data)
 
1147
{
 
1148
   GuestInfoClearCache();
 
1149
 
 
1150
   if (gatherTimeoutSource != NULL) {
 
1151
      g_source_destroy(gatherTimeoutSource);
 
1152
      gatherTimeoutSource = NULL;
 
1153
   }
 
1154
 
 
1155
#ifdef _WIN32
 
1156
   NetUtil_FreeIpHlpApiDll();
 
1157
#endif
 
1158
}
 
1159
 
 
1160
 
 
1161
/*
 
1162
 ******************************************************************************
 
1163
 * GuestInfoServerReset --                                               */ /**
 
1164
 *
 
1165
 * Reset callback - sets the internal flag that says we should purge all
 
1166
 * caches.
 
1167
 *
 
1168
 * @param[in]  src      The source object.
 
1169
 * @param[in]  ctx      Unused.
 
1170
 * @param[in]  data     Unused.
 
1171
 *
 
1172
 ******************************************************************************
 
1173
 */
 
1174
 
 
1175
static void
 
1176
GuestInfoServerReset(gpointer src,
 
1177
                     ToolsAppCtx *ctx,
 
1178
                     gpointer data)
 
1179
{
 
1180
   vmResumed = TRUE;
 
1181
}
 
1182
 
 
1183
 
 
1184
/*
 
1185
 ******************************************************************************
 
1186
 * GuestInfoServerSendCaps --                                            */ /**
 
1187
 *
 
1188
 * Send capabilities callback.  If setting capabilities, sends VM's uptime.
 
1189
 *
 
1190
 * This is weird.  There's sort of an old Tools <-> VMX understanding that
 
1191
 * vmsvc should report the guest's uptime in response to a "what're your
 
1192
 * capabilities?" RPC.
 
1193
 *
 
1194
 * @param[in]  src      The source object.
 
1195
 * @param[in]  ctx      The application context.
 
1196
 * @param[in]  set      TRUE if setting capabilities, FALSE if unsetting them.
 
1197
 * @param[in]  data     Client data.
 
1198
 *
 
1199
 * @retval NULL This function returns no capabilities.
 
1200
 *
 
1201
 ******************************************************************************
 
1202
 */
 
1203
 
 
1204
static GArray *
 
1205
GuestInfoServerSendCaps(gpointer src,
 
1206
                        ToolsAppCtx *ctx,
 
1207
                        gboolean set,
 
1208
                        gpointer data)
 
1209
{
 
1210
   if (set) {
 
1211
      SendUptime(ctx);
 
1212
   }
 
1213
   return NULL;
 
1214
}
 
1215
 
 
1216
 
 
1217
/*
 
1218
 ******************************************************************************
 
1219
 * GuestInfoServerSetOption --                                           */ /**
 
1220
 *
 
1221
 * Responds to a "broadcastIP" Set_Option command, by sending the primary IP
 
1222
 * back to the VMX.
 
1223
 *
 
1224
 * @param[in]  src      The source object.
 
1225
 * @param[in]  ctx      The application context.
 
1226
 * @param[in]  option   Option name.
 
1227
 * @param[in]  value    Option value.
 
1228
 * @param[in]  data     Unused.
 
1229
 *
 
1230
 ******************************************************************************
 
1231
 */
 
1232
 
 
1233
static gboolean
 
1234
GuestInfoServerSetOption(gpointer src,
 
1235
                         ToolsAppCtx *ctx,
 
1236
                         const gchar *option,
 
1237
                         const gchar *value,
 
1238
                         gpointer data)
 
1239
{
 
1240
   char *ip;
 
1241
   Bool ret = FALSE;
 
1242
 
 
1243
   if (strcmp(option, TOOLSOPTION_BROADCASTIP) != 0) {
 
1244
      goto exit;
 
1245
   }
 
1246
 
 
1247
   if (strcmp(value, "0") == 0) {
 
1248
      ret = TRUE;
 
1249
      goto exit;
 
1250
   }
 
1251
 
 
1252
   if (strcmp(value, "1") != 0) {
 
1253
      goto exit;
 
1254
   }
 
1255
 
 
1256
   ip = NetUtil_GetPrimaryIP();
 
1257
 
 
1258
   if (ip != NULL) {
 
1259
      gchar *msg;
 
1260
      msg = g_strdup_printf("info-set guestinfo.ip %s", ip);
 
1261
      ret = RpcChannel_Send(ctx->rpc, msg, strlen(msg) + 1, NULL, NULL);
 
1262
      vm_free(ip);
 
1263
      g_free(msg);
 
1264
   }
 
1265
 
 
1266
exit:
 
1267
   return (gboolean) ret;
 
1268
}
 
1269
 
 
1270
 
 
1271
/*
 
1272
 ******************************************************************************
 
1273
 * ToolsOnLoad --                                                        */ /**
 
1274
 *
1196
1275
 * Plugin entry point. Initializes internal plugin state.
1197
1276
 *
1198
1277
 * @param[in]  ctx   The app context.
1199
1278
 *
1200
1279
 * @return The registration data.
 
1280
 *
 
1281
 ******************************************************************************
1201
1282
 */
1202
1283
 
1203
1284
TOOLS_MODULE_EXPORT ToolsPluginData *
1218
1299
         { RPC_VMSUPPORT_START, GuestInfoVMSupport, &regData, NULL, NULL, 0 }
1219
1300
      };
1220
1301
      ToolsPluginSignalCb sigs[] = {
1221
 
         { TOOLS_CORE_SIG_CAPABILITIES, GuestInfoServerSendUptime, NULL },
 
1302
         { TOOLS_CORE_SIG_CAPABILITIES, GuestInfoServerSendCaps, NULL },
1222
1303
         { TOOLS_CORE_SIG_CONF_RELOAD, GuestInfoServerConfReload, NULL },
1223
1304
         { TOOLS_CORE_SIG_IO_FREEZE, GuestInfoServerIOFreeze, NULL },
1224
1305
         { TOOLS_CORE_SIG_RESET, GuestInfoServerReset, NULL },
1230
1311
         { TOOLS_APP_SIGNALS, VMTools_WrapArray(sigs, sizeof *sigs, ARRAYSIZE(sigs)) }
1231
1312
      };
1232
1313
 
 
1314
#ifdef _WIN32
 
1315
      if (NetUtil_LoadIpHlpApiDll() != ERROR_SUCCESS) {
 
1316
         g_warning("Failed to load iphlpapi.dll.  Cannot report networking details.\n");
 
1317
         return NULL;
 
1318
      }
 
1319
#endif
 
1320
 
1233
1321
      regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs));
1234
1322
 
1235
1323
      memset(&gInfoCache, 0, sizeof gInfoCache);
1236
 
      GuestInfo_InitDiskInfo(&gInfoCache.diskInfo);
1237
1324
      vmResumed = FALSE;
1238
1325
 
1239
1326
      /*