~n-muench/open-vm-tools/devel

« back to all changes in this revision

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

  • Committer: Nate Muench
  • Date: 2011-05-05 00:27:16 UTC
  • Revision ID: nowiwilldestroyabydos@gmail.com-20110505002716-f87n4uvh2hg3crrk
Merge with Natty, Enable shared folders

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2008 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/**
 
20
 * @file guestInfo.c
 
21
 *
 
22
 *      Library backing parts of the vm.GuestInfo VIM APIs.
 
23
 */
 
24
 
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
 
 
28
#if defined _WIN32
 
29
#   include <ws2tcpip.h>
 
30
#endif
 
31
 
 
32
#include "vm_assert.h"
 
33
#include "debug.h"
 
34
#include "getlibInt.h"
 
35
#include "str.h"
 
36
#include "util.h"
 
37
#include "xdrutil.h"
 
38
#include "netutil.h"
 
39
#include "wiper.h"
 
40
 
 
41
 
 
42
/**
 
43
 * Helper to initialize an opaque struct member.
 
44
 *
 
45
 * @todo Move to xdrutil.h?  Sticking point is dependency on Util_SafeMalloc.
 
46
 */
 
47
#define XDRUTIL_SAFESETOPAQUE(ptr, type, src, size)                     \
 
48
   do {                                                                 \
 
49
      (ptr)->type##_len = (size);                                       \
 
50
      (ptr)->type##_val = Util_SafeMalloc((size));                      \
 
51
      memcpy((ptr)->type##_val, (src), (size));                         \
 
52
   } while (0)
 
53
 
 
54
 
 
55
/*
 
56
 * Global functions.
 
57
 */
 
58
 
 
59
 
 
60
/*
 
61
 ******************************************************************************
 
62
 * GuestInfo_GetFqdn --                                                  */ /**
 
63
 *
 
64
 * @brief Returns the guest's hostname (aka fully qualified domain name, FQDN).
 
65
 *
 
66
 * @param[in]  outBufLen Size of outBuf.
 
67
 * @param[out] outBuf    Output buffer.
 
68
 *
 
69
 * @retval TRUE  Success.  Hostname written to @a outBuf.
 
70
 * @retval FALSE Failure.
 
71
 *
 
72
 ******************************************************************************
 
73
 */
 
74
 
 
75
Bool
 
76
GuestInfo_GetFqdn(int outBufLen,
 
77
                  char fqdn[])
 
78
{
 
79
   return GuestInfoGetFqdn(outBufLen, fqdn);
 
80
}
 
81
 
 
82
 
 
83
/*
 
84
 ******************************************************************************
 
85
 * GuestInfo_GetNicInfo --                                               */ /**
 
86
 *
 
87
 * @brief Returns guest networking configuration (and some runtime state).
 
88
 *
 
89
 * @param[out] nicInfo  Will point to a newly allocated NicInfo.
 
90
 *
 
91
 * @note
 
92
 * Caller is responsible for freeing @a nicInfo with GuestInfo_FreeNicInfo.
 
93
 *
 
94
 * @retval TRUE  Success.  @a nicInfo now points to a populated NicInfoV3.
 
95
 * @retval FALSE Failure.
 
96
 *
 
97
 ******************************************************************************
 
98
 */
 
99
 
 
100
Bool
 
101
GuestInfo_GetNicInfo(NicInfoV3 **nicInfo)
 
102
{
 
103
   Bool retval = FALSE;
 
104
 
 
105
   *nicInfo = Util_SafeCalloc(1, sizeof (struct NicInfoV3));
 
106
 
 
107
   retval = GuestInfoGetNicInfo(*nicInfo);
 
108
   if (!retval) {
 
109
      free(*nicInfo);
 
110
      *nicInfo = NULL;
 
111
   }
 
112
 
 
113
   return retval;
 
114
}
 
115
 
 
116
 
 
117
/*
 
118
 ******************************************************************************
 
119
 * GuestInfo_FreeNicInfo --                                              */ /**
 
120
 *
 
121
 * @brief Frees a NicInfoV3 structure and all memory it points to.
 
122
 *
 
123
 * @param[in] nicInfo   Pointer to NicInfoV3 container.
 
124
 *
 
125
 * @sa GuestInfo_GetNicInfo
 
126
 *
 
127
 ******************************************************************************
 
128
 */
 
129
 
 
130
void
 
131
GuestInfo_FreeNicInfo(NicInfoV3 *nicInfo)
 
132
{
 
133
   if (nicInfo != NULL) {
 
134
      VMX_XDR_FREE(xdr_NicInfoV3, nicInfo);
 
135
      free(nicInfo);
 
136
   }
 
137
}
 
138
 
 
139
 
 
140
/*
 
141
 ******************************************************************************
 
142
 * GuestInfo_FreeDiskInfo --                                             */ /**
 
143
 *
 
144
 * @brief Frees memory allocated by GuestInfoGetDiskInfo.
 
145
 *
 
146
 * @param[in] di    DiskInfo container.
 
147
 *
 
148
 ******************************************************************************
 
149
 */
 
150
 
 
151
void
 
152
GuestInfo_FreeDiskInfo(GuestDiskInfo *di)
 
153
{
 
154
   if (di) {
 
155
      free(di->partitionList);
 
156
      free(di);
 
157
   }
 
158
}
 
159
 
 
160
 
 
161
/*
 
162
 * Private library functions.
 
163
 */
 
164
 
 
165
 
 
166
/*
 
167
 ******************************************************************************
 
168
 * GuestInfoGetDiskInfoWiper --                                          */ /**
 
169
 *
 
170
 * Uses wiper library to enumerate fixed volumes and lookup utilization data.
 
171
 *
 
172
 * @return Pointer to a GuestDiskInfo structure on success or NULL on failure.
 
173
 *         Caller should free returned pointer with GuestInfoFreeDiskInfo.
 
174
 *
 
175
 ******************************************************************************
 
176
 */
 
177
 
 
178
GuestDiskInfo *
 
179
GuestInfoGetDiskInfoWiper(void)
 
180
{
 
181
   WiperPartition_List pl;
 
182
   DblLnkLst_Links *curr;
 
183
   unsigned int partCount = 0;
 
184
   uint64 freeBytes = 0;
 
185
   uint64 totalBytes = 0;
 
186
   unsigned int partNameSize = 0;
 
187
   Bool success = FALSE;
 
188
   GuestDiskInfo *di;
 
189
 
 
190
   /* Get partition list. */
 
191
   if (!WiperPartition_Open(&pl)) {
 
192
      g_debug("GetDiskInfo: ERROR: could not get partition list\n");
 
193
      return FALSE;
 
194
   }
 
195
 
 
196
   di = Util_SafeCalloc(1, sizeof *di);
 
197
   partNameSize = sizeof (di->partitionList)[0].name;
 
198
 
 
199
   DblLnkLst_ForEach(curr, &pl.link) {
 
200
      WiperPartition *part = DblLnkLst_Container(curr, WiperPartition, link);
 
201
 
 
202
      if (part->type != PARTITION_UNSUPPORTED) {
 
203
         PPartitionEntry newPartitionList;
 
204
         PPartitionEntry partEntry;
 
205
         unsigned char *error;
 
206
 
 
207
         error = WiperSinglePartition_GetSpace(part, &freeBytes, &totalBytes);
 
208
         if (strlen(error)) {
 
209
            g_debug("GetDiskInfo: ERROR: could not get space for partition %s: %s\n",
 
210
                    part->mountPoint, error);
 
211
            goto out;
 
212
         }
 
213
 
 
214
         if (strlen(part->mountPoint) + 1 > partNameSize) {
 
215
            g_debug("GetDiskInfo: ERROR: Partition name buffer too small\n");
 
216
            goto out;
 
217
         }
 
218
 
 
219
         newPartitionList = Util_SafeRealloc(di->partitionList,
 
220
                                             (partCount + 1) *
 
221
                                             sizeof *di->partitionList);
 
222
 
 
223
         partEntry = &newPartitionList[partCount++];
 
224
         Str_Strcpy(partEntry->name, part->mountPoint, partNameSize);
 
225
         partEntry->freeBytes = freeBytes;
 
226
         partEntry->totalBytes = totalBytes;
 
227
 
 
228
         di->partitionList = newPartitionList;
 
229
      }
 
230
   }
 
231
 
 
232
   di->numEntries = partCount;
 
233
   success = TRUE;
 
234
 
 
235
out:
 
236
   if (!success) {
 
237
      GuestInfo_FreeDiskInfo(di);
 
238
      di = NULL;
 
239
   }
 
240
   WiperPartition_Close(&pl);
 
241
   return di;
 
242
}
 
243
 
 
244
 
 
245
/*
 
246
 ******************************************************************************
 
247
 * GuestInfoAddNicEntry --                                               */ /**
 
248
 *
 
249
 * @brief GuestNicV3 constructor.
 
250
 *
 
251
 * @param[in,out] nicInfo     List of NICs.
 
252
 * @param[in]     macAddress  MAC address of new NIC.
 
253
 * @param[in]     dnsInfo     Per-NIC DNS config state.
 
254
 * @param[in]     winsInfo    Per-NIC WINS config state.
 
255
 *
 
256
 * @note The returned GuestNic will take ownership of @a dnsInfo and
 
257
 *       @a winsInfo  The caller must not free it directly.
 
258
 *
 
259
 * @return Pointer to the new NIC, or NULL if NIC limit was reached.
 
260
 *
 
261
 ******************************************************************************
 
262
 */
 
263
 
 
264
GuestNicV3 *
 
265
GuestInfoAddNicEntry(NicInfoV3 *nicInfo,
 
266
                     const char macAddress[NICINFO_MAC_LEN],
 
267
                     DnsConfigInfo *dnsInfo,
 
268
                     WinsConfigInfo *winsInfo)
 
269
{
 
270
   GuestNicV3 *newNic;
 
271
 
 
272
   /* Check to see if we're going above our limit. See bug 605821. */
 
273
   if (nicInfo->nics.nics_len == NICINFO_MAX_NICS) {
 
274
      g_message("%s: NIC limit (%d) reached, skipping overflow.",
 
275
                __FUNCTION__, NICINFO_MAX_NICS);
 
276
      return NULL;
 
277
   }
 
278
 
 
279
   newNic = XDRUTIL_ARRAYAPPEND(nicInfo, nics, 1);
 
280
   ASSERT_MEM_ALLOC(newNic);
 
281
 
 
282
   newNic->macAddress = Util_SafeStrdup(macAddress);
 
283
   newNic->dnsConfigInfo = dnsInfo;
 
284
   newNic->winsConfigInfo = winsInfo;
 
285
 
 
286
   return newNic;
 
287
}
 
288
 
 
289
 
 
290
/*
 
291
 ******************************************************************************
 
292
 * GuestInfoAddIpAddress --                                              */ /**
 
293
 *
 
294
 * @brief Add an IP address entry into the GuestNic.
 
295
 *
 
296
 * @param[in,out] nic      The NIC information.
 
297
 * @param[in]     sockAddr The new IP address.
 
298
 * @param[in]     pfxLen   Prefix length (use 0 if unknown).
 
299
 * @param[in]     origin   Address's origin.  (Optional.)
 
300
 * @param[in]     status   Address's status.  (Optional.)
 
301
 *
 
302
 * @return Newly allocated IP address struct, NULL on failure.
 
303
 *
 
304
 ******************************************************************************
 
305
 */
 
306
 
 
307
IpAddressEntry *
 
308
GuestInfoAddIpAddress(GuestNicV3 *nic,
 
309
                      const struct sockaddr *sockAddr,
 
310
                      InetAddressPrefixLength pfxLen,
 
311
                      const IpAddressOrigin *origin,
 
312
                      const IpAddressStatus *status)
 
313
{
 
314
   IpAddressEntry *ip;
 
315
 
 
316
   ASSERT(sockAddr);
 
317
 
 
318
   /* Check to see if we're going above our limit. See bug 605821. */
 
319
   if (nic->ips.ips_len == NICINFO_MAX_IPS) {
 
320
      g_message("%s: IP address limit (%d) reached, skipping overflow.",
 
321
                __FUNCTION__, NICINFO_MAX_IPS);
 
322
      return NULL;
 
323
   }
 
324
 
 
325
   ip = XDRUTIL_ARRAYAPPEND(nic, ips, 1);
 
326
   ASSERT_MEM_ALLOC(ip);
 
327
 
 
328
   ASSERT_ON_COMPILE(sizeof *origin == sizeof *ip->ipAddressOrigin);
 
329
   ASSERT_ON_COMPILE(sizeof *status == sizeof *ip->ipAddressStatus);
 
330
 
 
331
   switch (sockAddr->sa_family) {
 
332
   case AF_INET:
 
333
      {
 
334
         static const IpAddressStatus defaultStatus = IAS_PREFERRED;
 
335
 
 
336
         GuestInfoSockaddrToTypedIpAddress(sockAddr, &ip->ipAddressAddr);
 
337
 
 
338
         ip->ipAddressPrefixLength = pfxLen;
 
339
         ip->ipAddressOrigin = origin ? Util_DupeThis(origin, sizeof *origin) : NULL;
 
340
         ip->ipAddressStatus = status ? Util_DupeThis(status, sizeof *status) :
 
341
            Util_DupeThis(&defaultStatus, sizeof defaultStatus);
 
342
      }
 
343
      break;
 
344
   case AF_INET6:
 
345
      {
 
346
         static const IpAddressStatus defaultStatus = IAS_UNKNOWN;
 
347
 
 
348
         GuestInfoSockaddrToTypedIpAddress(sockAddr, &ip->ipAddressAddr);
 
349
 
 
350
         ip->ipAddressPrefixLength = pfxLen;
 
351
         ip->ipAddressOrigin = origin ? Util_DupeThis(origin, sizeof *origin) : NULL;
 
352
         ip->ipAddressStatus = status ? Util_DupeThis(status, sizeof *status) :
 
353
            Util_DupeThis(&defaultStatus, sizeof defaultStatus);
 
354
      }
 
355
      break;
 
356
   default:
 
357
      NOT_REACHED();
 
358
   }
 
359
 
 
360
   return ip;
 
361
}
 
362
 
 
363
 
 
364
/*
 
365
 ******************************************************************************
 
366
 * GuestInfoSockaddrToTypedIpAddress --                                  */ /**
 
367
 *
 
368
 * @brief Converts a <tt>struct sockaddr</tt> to a @c TypedIpAddress.
 
369
 *
 
370
 * @param[in]  sa       Source @c sockaddr.
 
371
 * @param[out] typedIp  Destination @c TypedIpAddress.
 
372
 *
 
373
 * @warning Caller is responsible for making sure source is AF_INET or
 
374
 * AF_INET6.
 
375
 *
 
376
 ******************************************************************************
 
377
 */
 
378
 
 
379
void
 
380
GuestInfoSockaddrToTypedIpAddress(const struct sockaddr *sa,
 
381
                                  TypedIpAddress *typedIp)
 
382
{
 
383
   struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 
384
   struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
 
385
 
 
386
   switch (sa->sa_family) {
 
387
   case AF_INET:
 
388
      typedIp->ipAddressAddrType = IAT_IPV4;
 
389
      XDRUTIL_SAFESETOPAQUE(&typedIp->ipAddressAddr, InetAddress,
 
390
                            &sin->sin_addr.s_addr,
 
391
                            sizeof sin->sin_addr.s_addr);
 
392
      break;
 
393
   case AF_INET6:
 
394
      typedIp->ipAddressAddrType = IAT_IPV6;
 
395
      XDRUTIL_SAFESETOPAQUE(&typedIp->ipAddressAddr, InetAddress,
 
396
                            &sin6->sin6_addr.s6_addr,
 
397
                            sizeof sin6->sin6_addr.s6_addr);
 
398
      break;
 
399
   default:
 
400
      NOT_REACHED();
 
401
   }
 
402
}
 
403
 
 
404
 
 
405
#if defined linux || defined _WIN32
 
406
/*
 
407
 ******************************************************************************
 
408
 * GuestInfoGetNicInfoIfIndex --                                         */ /**
 
409
 *
 
410
 * @brief Given a local interface's index, find its corresponding location in the
 
411
 * NicInfoV3 @c nics vector.
 
412
 *
 
413
 * @param[in]  nicInfo     NIC container.
 
414
 * @param[in]  ifIndex     Device to search for.
 
415
 * @param[out] nicifIndex  Array offset, if found.
 
416
 *
 
417
 * @retval TRUE  Device found.
 
418
 * @retval FALSE Device not found.
 
419
 *
 
420
 ******************************************************************************
 
421
 */
 
422
 
 
423
Bool
 
424
GuestInfoGetNicInfoIfIndex(NicInfoV3 *nicInfo,
 
425
                           int ifIndex,
 
426
                           int *nicIfIndex)
 
427
{
 
428
   char hwAddrString[NICINFO_MAC_LEN];
 
429
   unsigned char hwAddr[16];
 
430
   IanaIfType ifType;
 
431
   Bool ret = FALSE;
 
432
   u_int i;
 
433
 
 
434
   ASSERT(nicInfo);
 
435
   ASSERT(nicIfIndex);
 
436
 
 
437
   if (NetUtil_GetHardwareAddress(ifIndex, hwAddr, sizeof hwAddr,
 
438
                                  &ifType) != 6 ||
 
439
       ifType != IANA_IFTYPE_ETHERNETCSMACD) {
 
440
      return FALSE;
 
441
   }
 
442
 
 
443
   Str_Sprintf(hwAddrString, sizeof hwAddrString,
 
444
               "%02x:%02x:%02x:%02x:%02x:%02x",
 
445
               hwAddr[0], hwAddr[1], hwAddr[2],
 
446
               hwAddr[3], hwAddr[4], hwAddr[5]);
 
447
 
 
448
   XDRUTIL_FOREACH(i, nicInfo, nics) {
 
449
      GuestNicV3 *nic = XDRUTIL_GETITEM(nicInfo, nics, i);
 
450
      if (!strcasecmp(nic->macAddress, hwAddrString)) {
 
451
         *nicIfIndex = i;
 
452
         ret = TRUE;
 
453
         break;
 
454
      }
 
455
   }
 
456
 
 
457
   return ret;
 
458
}
 
459
#endif // if defined linux || defined _WIN32
 
460
 
 
461
 
 
462
/*
 
463
 * XXX
 
464
 */
 
465
 
 
466
 
 
467
/**
 
468
 * Return a copy of arbitrary memory.
 
469
 *
 
470
 * @param[in] source     Source address.
 
471
 * @param[in] sourceSize Number of bytes to allocate, copy.
 
472
 *
 
473
 * @return Pointer to newly allocated memory.
 
474
 *
 
475
 * @todo Determine if I'm duplicating functionality.
 
476
 * @todo Move this to bora/lib/util or whatever.
 
477
 */
 
478
 
 
479
void *
 
480
Util_DupeThis(const void *source,
 
481
              size_t sourceSize)
 
482
{
 
483
   void *dest;
 
484
 
 
485
   ASSERT(source);
 
486
 
 
487
   dest = Util_SafeMalloc(sourceSize);
 
488
   memcpy(dest, source, sourceSize);
 
489
 
 
490
   return dest;
 
491
}