~n-muench/ubuntu/maverick/open-vm-tools/open-vm-tools.fix-632101

« back to all changes in this revision

Viewing changes to lib/guestInfo/guestInfoPosix.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-10-18 12:28:19 UTC
  • mfrom: (1.1.7 upstream) (2.4.9 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091018122819-00vqew6m0ztpqcqp
Tags: 2009.10.15-201664-1
MergingĀ upstreamĀ versionĀ 2009.10.15-201664.

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) 2005 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
16
16
 *
17
17
 *********************************************************/
18
18
 
19
 
 
20
 
/*
21
 
 * guestInfoPosix.c --
22
 
 *
23
 
 *    Routines to get guest information. These are invoked by guestInfoServer
24
 
 *    which writes this information into Vmdb.
25
 
 *
 
19
/**
 
20
 * @file guestInfoPosix.c
 
21
 *
 
22
 * Contains POSIX-specific bits of GuestInfo collector library.
26
23
 */
27
24
 
28
 
#ifndef VMX86_DEVEL
29
 
 
30
 
#endif
31
 
 
32
25
#include <stdio.h>
33
26
#include <stdlib.h>
34
27
#include <string.h>
 
28
#include <glib.h>
35
29
#include <fcntl.h>
36
30
#ifdef sun
37
31
# include <sys/systeminfo.h>
51
45
#  include <dnet.h>
52
46
# endif
53
47
#endif
 
48
 
 
49
#include <netinet/in.h>
 
50
#include <arpa/nameser.h>
 
51
#include <resolv.h>
 
52
 
 
53
#ifdef __linux__
 
54
#   include <net/if.h>
 
55
#endif
 
56
 
 
57
 
 
58
/*
 
59
 * resolver(3) and IPv6:
 
60
 *
 
61
 * The ISC BIND resolver included various IPv6 implementations over time, but
 
62
 * unfortunately the ISC hadn't bumped __RES accordingly.  (__RES is -supposed-
 
63
 * to behave as a version datestamp for the resolver interface.)  Similarly
 
64
 * the GNU C Library forked resolv.h and made modifications of their own, also
 
65
 * without changing __RES.
 
66
 *
 
67
 * glibc 2.1.92 included a patch which provides IPv6 name server support by
 
68
 * embedding in6_addr pointers in _res._u._ext.  Since I only care about major
 
69
 * and minor numbers, though, I'm going to condition this impl. on glibc 2.2.
 
70
 *
 
71
 * ISC, OTOH, provided accessing IPv6 servers via a res_getservers API.
 
72
 * TTBOMK, this went public with BIND 8.3.0.  Unfortunately __RES wasn't
 
73
 * bumped for this release, so instead I'm going to assume that appearance with
 
74
 * that release of a new macro, RES_F_DNS0ERR, implies this API is available.
 
75
 * (For internal builds, we'll know instantly when a build breaks.  The down-
 
76
 * side is that this could cause some trouble for Open VM Tools users. ,_,)
 
77
 *
 
78
 * resolv.h version     IPv6 API        __RES
 
79
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
80
 * glibc 2.2+           _ext            19991006
 
81
 * BIND 8.3.0           getservers      19991006
 
82
 * BIND 8.3.4+          getservers      20030124(+?)
 
83
 *
 
84
 * To distinguish between the variants where __RES == 19991006, I'll
 
85
 * discriminate on the existence of new macros included with the appropriate
 
86
 * version.
 
87
 */
 
88
 
 
89
#if defined __GLIBC__
 
90
#   if __GLIBC_PREREQ(2,2)
 
91
#      define      RESOLVER_IPV6_EXT
 
92
#   endif // __GLIBC_PREREQ(2,2)
 
93
#elif (__RES > 19991006 || (__RES == 19991006 && defined RES_F_EDNS0ERR))
 
94
#   define      RESOLVER_IPV6_GETSERVERS
 
95
#endif // if defined __GLIBC__
 
96
 
 
97
 
54
98
#include "util.h"
55
99
#include "sys/utsname.h"
56
100
#include "sys/ioctl.h"
62
106
#include "guest_os.h"
63
107
#include "guestApp.h"
64
108
#include "guestInfo.h"
65
 
 
66
 
 
67
 
/*
68
 
 *-----------------------------------------------------------------------------
69
 
 *
70
 
 * GuestInfoGetFqdn--
71
 
 *
72
 
 *      Return the guest's fully qualified domain name.
73
 
 *      This is just a thin wrapper around gethostname.
74
 
 *
75
 
 * Return value:
76
 
 *      Returns TRUE on success and FALSE on failure.
77
 
 *      Returns the guest's fully qualified domain name.
78
 
 *
79
 
 * Side effects:
80
 
 *      None
81
 
 *
82
 
 *-----------------------------------------------------------------------------
 
109
#include "xdrutil.h"
 
110
#ifdef USE_SLASH_PROC
 
111
#   include "slashProc.h"
 
112
#endif
 
113
#include "netutil.h"
 
114
#include "file.h"
 
115
 
 
116
 
 
117
/*
 
118
 * Local functions
 
119
 */
 
120
 
 
121
 
 
122
#ifndef NO_DNET
 
123
static void RecordNetworkAddress(GuestNicV3 *nic, const struct addr *addr);
 
124
static int ReadInterfaceDetails(const struct intf_entry *entry, void *arg);
 
125
static Bool RecordResolverInfo(NicInfoV3 *nicInfo);
 
126
static void RecordResolverNS(DnsConfigInfo *dnsConfigInfo);
 
127
static Bool RecordRoutingInfo(NicInfoV3 *nicInfo);
 
128
#endif
 
129
 
 
130
 
 
131
/*
 
132
 ******************************************************************************
 
133
 * GuestInfoGetFqdn --                                                   */ /**
 
134
 *
 
135
 * @copydoc GuestInfo_GetFqdn
 
136
 *
 
137
 ******************************************************************************
83
138
 */
84
139
 
85
140
Bool
96
151
}
97
152
 
98
153
 
99
 
#ifndef NO_DNET
100
 
/*
101
 
 *-----------------------------------------------------------------------------
102
 
 *
103
 
 * RecordNetworkAddress --
104
 
 *
105
 
 *      Massages a dnet(3)-style interface address (IPv4 or IPv6) and stores it
106
 
 *      as part of a GuestNic structure.
107
 
 *
108
 
 * Results:
109
 
 *      If addr is IPv4 or IPv6, it will be appended to the GuestNic's list of
110
 
 *      IP addresses.
111
 
 *
112
 
 * Side effects:
113
 
 *      None.
114
 
 *
115
 
 *-----------------------------------------------------------------------------
 
154
/*
 
155
 ******************************************************************************
 
156
 * GuestInfoGetNicInfo --                                                */ /**
 
157
 *
 
158
 * @copydoc GuestInfo_GetNicInfo
 
159
 *
 
160
 ******************************************************************************
 
161
 */
 
162
 
 
163
Bool
 
164
GuestInfoGetNicInfo(NicInfoV3 *nicInfo) // OUT
 
165
{
 
166
#ifndef NO_DNET
 
167
   intf_t *intf;
 
168
 
 
169
   /* Get a handle to read the network interface configuration details. */
 
170
   if ((intf = intf_open()) == NULL) {
 
171
      Debug("GuestInfo: Error, failed NULL result from intf_open()\n");
 
172
      return FALSE;
 
173
   }
 
174
 
 
175
   if (intf_loop(intf, ReadInterfaceDetails, nicInfo) < 0) {
 
176
      intf_close(intf);
 
177
      Debug("GuestInfo: Error, negative result from intf_loop\n");
 
178
      return FALSE;
 
179
   }
 
180
 
 
181
   intf_close(intf);
 
182
 
 
183
   if (!RecordResolverInfo(nicInfo)) {
 
184
      return FALSE;
 
185
   }
 
186
 
 
187
   if (!RecordRoutingInfo(nicInfo)) {
 
188
      return FALSE;
 
189
   }
 
190
 
 
191
   return TRUE;
 
192
#else
 
193
   return FALSE;
 
194
#endif
 
195
}
 
196
 
 
197
 
 
198
/*
 
199
 * Local functions
 
200
 */
 
201
 
 
202
 
 
203
#ifndef NO_DNET
 
204
/*
 
205
 ******************************************************************************
 
206
 * RecordNetworkAddress --                                               */ /**
 
207
 *
 
208
 * @brief Massages a dnet(3)-style interface address (IPv4 or IPv6) and stores
 
209
 *        it as part of a GuestNicV3 structure.
 
210
 *
 
211
 * @param[in]  nic      Operand NIC.
 
212
 * @param[in]  addr     dnet(3) address.
 
213
 *
 
214
 ******************************************************************************
116
215
 */
117
216
 
118
217
static void
119
 
RecordNetworkAddress(GuestNic *nic,             // IN: operand NIC
 
218
RecordNetworkAddress(GuestNicV3 *nic,           // IN: operand NIC
120
219
                     const struct addr *addr)   // IN: dnet(3) address to process
121
220
{
122
 
   char ipAddress[NICINFO_MAX_IP_LEN];
123
 
   VmIpAddress *ip = NULL;
 
221
   struct sockaddr_storage ss;
 
222
   struct sockaddr *sa = (struct sockaddr *)&ss;
124
223
 
125
 
   switch (addr->addr_type) {
126
 
   case ADDR_TYPE_IP:
127
 
      /*
128
 
       * GuestNicInfo clients expect IPv4 addresses and netmasks to be stored
129
 
       * as strings in separate fields.  As such, we'll use ip_ntop instead of
130
 
       * addr_ntop to get a string without the netmask bits.
131
 
       */
132
 
      ip_ntop(&addr->addr_ip, ipAddress, sizeof ipAddress);
133
 
      ip = GuestInfoAddIpAddress(nic, ipAddress, INFO_IP_ADDRESS_FAMILY_IPV4);
134
 
      if (ip) {
135
 
         GuestInfoAddSubnetMask(ip, addr->addr_bits, TRUE);
136
 
      }
137
 
      break;
138
 
   case ADDR_TYPE_IP6:
139
 
      ip6_ntop(&addr->addr_ip6, ipAddress, sizeof ipAddress);
140
 
      ip = GuestInfoAddIpAddress(nic, ipAddress, INFO_IP_ADDRESS_FAMILY_IPV6);
141
 
      if (ip) {
142
 
         GuestInfoAddSubnetMask(ip, addr->addr_bits, FALSE);
143
 
      }
144
 
      break;
145
 
   default:
146
 
      Debug("%s: Unknown address type: %hu\n", __func__, addr->addr_type);
147
 
      break;
148
 
   }
 
224
   memset(&ss, 0, sizeof ss);
 
225
   addr_ntos(addr, sa);
 
226
   GuestInfoAddIpAddress(nic, sa, addr->addr_bits, NULL, NULL);
149
227
}
150
228
 
151
229
 
152
230
/*
153
 
 *-----------------------------------------------------------------------------
154
 
 *
155
 
 * ReadInterfaceDetails --
156
 
 *
157
 
 *      Callback function called by libdnet when iterating over all the
158
 
 *      NICs on the host.
159
 
 *
160
 
 * Return value:
161
 
 *      Returns 0 on success and -1 on failure.
162
 
 *      Adds the MAC addresses of all NICs and their corresponding IPs.
163
 
 *
164
 
 * Side effects:
165
 
 *      Memory is allocated for each NIC, as well as IP addresses of all NICs
166
 
 *      on successful return.
167
 
 *
168
 
 *-----------------------------------------------------------------------------
 
231
 ******************************************************************************
 
232
 * ReadInterfaceDetails --                                               */ /**
 
233
 *
 
234
 * @brief Callback function called by libdnet when iterating over all the NICs
 
235
 * on the host.
 
236
 *
 
237
 * @param[in]  entry    Current interface entry.
 
238
 * @param[in]  arg      Pointer to NicInfoV3 container.
 
239
 *
 
240
 * @note New GuestNicV3 structures are added to the NicInfoV3 structure.
 
241
 *
 
242
 * @retval 0    Success.
 
243
 * @retval -1   Failure.
 
244
 *
 
245
 ******************************************************************************
169
246
 */
170
247
 
171
 
int
 
248
static int
172
249
ReadInterfaceDetails(const struct intf_entry *entry,  // IN: current interface entry
173
250
                     void *arg)                       // IN: Pointer to the GuestNicList
174
251
{
175
252
   int i;
176
 
   GuestNicList *nicInfo = arg;
177
 
 
178
 
   if ((entry->intf_type & INTF_TYPE_ETH) == INTF_TYPE_ETH) {
179
 
      GuestNic *nic;
 
253
   NicInfoV3 *nicInfo = arg;
 
254
 
 
255
   ASSERT(entry);
 
256
   ASSERT(arg);
 
257
 
 
258
   if (entry->intf_type == INTF_TYPE_ETH) {
 
259
      GuestNicV3 *nic = NULL;
180
260
      char macAddress[NICINFO_MAC_LEN];
181
261
 
182
262
      Str_Sprintf(macAddress, sizeof macAddress, "%s",
183
263
                  addr_ntoa(&entry->intf_link_addr));
184
 
      nic = GuestInfoAddNicEntry(nicInfo, macAddress);
185
 
 
186
 
      if (nic == NULL) {
187
 
         return -1;
188
 
      }
 
264
      nic = GuestInfoAddNicEntry(nicInfo, macAddress, NULL, NULL);
 
265
      ASSERT_MEM_ALLOC(nic);
189
266
 
190
267
      /* Record the "primary" address. */
191
268
      if (entry->intf_addr.addr_type == ADDR_TYPE_IP ||
205
282
 
206
283
   return 0;
207
284
}
208
 
#endif
209
285
 
210
286
 
211
287
/*
212
 
 *-----------------------------------------------------------------------------
213
 
 *
214
 
 * GuestInfoGetNicInfo --
215
 
 *
216
 
 *      Return MAC addresses of all the NICs in the guest and their
217
 
 *      corresponding IP addresses.
218
 
 *
219
 
 * Return value:
220
 
 *      Returns TRUE on success and FALSE on failure.
221
 
 *      Return MAC addresses of all NICs and their corresponding IPs.
222
 
 *
223
 
 * Side effects:
224
 
 *      Memory is allocated for each NIC, as well as IP addresses of all NICs
225
 
 *      on successful return.
226
 
 *
227
 
 *-----------------------------------------------------------------------------
 
288
 ******************************************************************************
 
289
 * RecordResolverInfo --                                                 */ /**
 
290
 *
 
291
 * @brief Query resolver(3), mapping settings to DnsConfigInfo.
 
292
 *
 
293
 * @param[out] nicInfo  NicInfoV3 container.
 
294
 *
 
295
 * @retval TRUE         Values collected, attached to @a nicInfo.
 
296
 * @retval FALSE        Something went wrong.  @a nicInfo is unharmed.
 
297
 *
 
298
 ******************************************************************************
228
299
 */
229
300
 
230
 
Bool
231
 
GuestInfoGetNicInfo(GuestNicList *nicInfo)   // OUT
 
301
static Bool
 
302
RecordResolverInfo(NicInfoV3 *nicInfo)  // OUT
232
303
{
233
 
#ifndef NO_DNET
234
 
   intf_t *intf;
235
 
 
236
 
   memset(nicInfo, 0, sizeof *nicInfo);
237
 
 
238
 
   /* Get a handle to read the network interface configuration details. */
239
 
   if ((intf = intf_open()) == NULL) {
240
 
      Debug("GuestInfo: Error, failed NULL result from intf_open()\n");
241
 
      return FALSE;
242
 
   }
243
 
 
244
 
   if (intf_loop(intf, ReadInterfaceDetails, nicInfo) < 0) {
245
 
      intf_close(intf);
246
 
      Debug("GuestInfo: Error, negative result from intf_loop\n");
247
 
      return FALSE;
248
 
   }
249
 
 
250
 
   intf_close(intf);
 
304
   DnsConfigInfo *dnsConfigInfo = NULL;
 
305
   char namebuf[DNSINFO_MAX_ADDRLEN + 1];
 
306
   char **s;
 
307
 
 
308
   if (res_init() == -1) {
 
309
      return FALSE;
 
310
   }
 
311
 
 
312
   dnsConfigInfo = Util_SafeCalloc(1, sizeof *dnsConfigInfo);
 
313
 
 
314
   /*
 
315
    * Copy in the host name.
 
316
    */
 
317
   if (!GuestInfoGetFqdn(sizeof namebuf, namebuf)) {
 
318
      goto fail;
 
319
   }
 
320
   dnsConfigInfo->hostName =
 
321
      Util_SafeCalloc(1, sizeof *dnsConfigInfo->hostName);
 
322
   *dnsConfigInfo->hostName = Util_SafeStrdup(namebuf);
 
323
 
 
324
   /*
 
325
    * Repeat with the domain name.
 
326
    */
 
327
   dnsConfigInfo->domainName =
 
328
      Util_SafeCalloc(1, sizeof *dnsConfigInfo->domainName);
 
329
   *dnsConfigInfo->domainName = Util_SafeStrdup(_res.defdname);
 
330
 
 
331
   /*
 
332
    * Name servers.
 
333
    */
 
334
   RecordResolverNS(dnsConfigInfo);
 
335
 
 
336
   /*
 
337
    * Search suffixes.
 
338
    */
 
339
   for (s = _res.dnsrch; *s; s++) {
 
340
      DnsHostname *suffix = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, searchSuffixes, 1);
 
341
      ASSERT_MEM_ALLOC(suffix);
 
342
      *suffix = Util_SafeStrdup(*s);
 
343
   }
 
344
 
 
345
   /*
 
346
    * "Commit" dnsConfigInfo to nicInfo.
 
347
    */
 
348
   nicInfo->dnsConfigInfo = dnsConfigInfo;
 
349
 
251
350
   return TRUE;
252
 
#else
 
351
 
 
352
fail:
 
353
   VMX_XDR_FREE(xdr_DnsConfigInfo, dnsConfigInfo);
 
354
   free(dnsConfigInfo);
253
355
   return FALSE;
254
 
#endif
255
 
}
 
356
}
 
357
 
 
358
 
 
359
/*
 
360
 ******************************************************************************
 
361
 * RecordResolverNS --                                                   */ /**
 
362
 *
 
363
 * @brief Copies name servers used by resolver(3) to @a dnsConfigInfo.
 
364
 *
 
365
 * @param[out] dnsConfigInfo    Destination DnsConfigInfo container.
 
366
 *
 
367
 ******************************************************************************
 
368
 */
 
369
 
 
370
static void
 
371
RecordResolverNS(DnsConfigInfo *dnsConfigInfo) // IN
 
372
{
 
373
   int i;
 
374
 
 
375
#if defined RESOLVER_IPV6_GETSERVERS
 
376
   {
 
377
      union res_sockaddr_union *ns;
 
378
      ns = Util_SafeCalloc(_res.nscount, sizeof *ns);
 
379
      if (res_getservers(&_res, ns, _res.nscount) != _res.nscount) {
 
380
         Warning("%s: res_getservers failed.\n", __func__);
 
381
         return;
 
382
      }
 
383
      for (i = 0; i < _res.nscount; i++) {
 
384
         struct sockaddr *sa = (struct sockaddr *)&ns[i];
 
385
         if (sa->sa_family == AF_INET || sa->sa_family == AF_INET6) {
 
386
            TypedIpAddress *ip = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, serverList, 1);
 
387
            ASSERT_MEM_ALLOC(ip);
 
388
            GuestInfoSockaddrToTypedIpAddress(sa, ip);
 
389
         }
 
390
      }
 
391
   }
 
392
#else                                   // if defined RESOLVER_IPV6_GETSERVERS
 
393
   {
 
394
      /*
 
395
       * Name servers (IPv4).
 
396
       */
 
397
      for (i = 0; i < MAXNS; i++) {
 
398
         struct sockaddr_in *sin = &_res.nsaddr_list[i];
 
399
         if (sin->sin_family == AF_INET) {
 
400
            TypedIpAddress *ip = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, serverList, 1);
 
401
            ASSERT_MEM_ALLOC(ip);
 
402
            GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin, ip);
 
403
         }
 
404
      }
 
405
#   if defined RESOLVER_IPV6_EXT
 
406
      /*
 
407
       * Name servers (IPv6).
 
408
       */
 
409
      for (i = 0; i < MAXNS; i++) {
 
410
         struct sockaddr_in6 *sin6 = _res._u._ext.nsaddrs[i];
 
411
         if (sin6) {
 
412
            TypedIpAddress *ip = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, serverList, 1);
 
413
            ASSERT_MEM_ALLOC(ip);
 
414
            GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin6, ip);
 
415
         }
 
416
      }
 
417
#   endif                               //    if defined RESOLVER_IPV6_EXT
 
418
   }
 
419
#endif                                  // if !defined RESOLVER_IPV6_GETSERVERS
 
420
}
 
421
 
 
422
 
 
423
#ifdef USE_SLASH_PROC
 
424
/*
 
425
 ******************************************************************************
 
426
 * RecordRoutingInfoIPv4 --                                              */ /**
 
427
 *
 
428
 * @brief Query the IPv4 routing subsystem and pack up contents
 
429
 * (struct rtentry) into InetCidrRouteEntries.
 
430
 *
 
431
 * @param[out] nicInfo  NicInfoV3 container.
 
432
 *
 
433
 * @note Do not call this routine without first populating @a nicInfo 's NIC
 
434
 * list.
 
435
 *
 
436
 * @retval TRUE         Values collected, attached to @a nicInfo.
 
437
 * @retval FALSE        Something went wrong.  @a nicInfo is unharmed.
 
438
 *
 
439
 ******************************************************************************
 
440
 */
 
441
 
 
442
static Bool
 
443
RecordRoutingInfoIPv4(NicInfoV3 *nicInfo)
 
444
{
 
445
   GPtrArray *routes = NULL;
 
446
   guint i;
 
447
   Bool ret = FALSE;
 
448
 
 
449
   if ((routes = SlashProcNet_GetRoute()) == NULL) {
 
450
      return FALSE;
 
451
   }
 
452
 
 
453
   for (i = 0; i < routes->len; i++) {
 
454
      struct rtentry *rtentry;
 
455
      struct sockaddr_in *sin_dst;
 
456
      struct sockaddr_in *sin_gateway;
 
457
      struct sockaddr_in *sin_genmask;
 
458
      InetCidrRouteEntry *icre;
 
459
      uint32_t ifIndex;
 
460
 
 
461
      rtentry = g_ptr_array_index(routes, i);
 
462
 
 
463
      if ((rtentry->rt_flags & RTF_UP) == 0 ||
 
464
          !GuestInfoGetNicInfoIfIndex(nicInfo,
 
465
                                      if_nametoindex(rtentry->rt_dev),
 
466
                                      &ifIndex)) {
 
467
         continue;
 
468
      }
 
469
 
 
470
      icre = XDRUTIL_ARRAYAPPEND(nicInfo, routes, 1);
 
471
      ASSERT_MEM_ALLOC(icre);
 
472
 
 
473
      sin_dst = (struct sockaddr_in *)&rtentry->rt_dst;
 
474
      sin_gateway = (struct sockaddr_in *)&rtentry->rt_gateway;
 
475
      sin_genmask = (struct sockaddr_in *)&rtentry->rt_genmask;
 
476
 
 
477
      GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_dst,
 
478
                                        &icre->inetCidrRouteDest);
 
479
 
 
480
      addr_stob((struct sockaddr *)sin_genmask,
 
481
                (uint16_t *)&icre->inetCidrRoutePfxLen);
 
482
 
 
483
      /*
 
484
       * Gateways are optional (ex: one can bind a route to an interface w/o
 
485
       * specifying a next hop address).
 
486
       */
 
487
      if (rtentry->rt_flags & RTF_GATEWAY) {
 
488
         TypedIpAddress *ip = Util_SafeCalloc(1, sizeof *ip);
 
489
         GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin_gateway, ip);
 
490
         icre->inetCidrRouteNextHop = ip;
 
491
      }
 
492
 
 
493
      /*
 
494
       * Interface, metric.
 
495
       */
 
496
      icre->inetCidrRouteIfIndex = ifIndex;
 
497
      icre->inetCidrRouteMetric = rtentry->rt_metric;
 
498
   }
 
499
 
 
500
   ret = TRUE;
 
501
 
 
502
   SlashProcNet_FreeRoute(routes);
 
503
   return ret;
 
504
}
 
505
 
 
506
 
 
507
/*
 
508
 ******************************************************************************
 
509
 * RecordRoutingInfoIPv6 --                                              */ /**
 
510
 *
 
511
 * @brief Query the IPv6 routing subsystem and pack up contents
 
512
 * (struct in6_rtmsg) into InetCidrRouteEntries.
 
513
 *
 
514
 * @param[out] nicInfo  NicInfoV3 container.
 
515
 *
 
516
 * @note Do not call this routine without first populating @a nicInfo 's NIC
 
517
 * list.
 
518
 *
 
519
 * @retval TRUE         Values collected, attached to @a nicInfo.
 
520
 * @retval FALSE        Something went wrong.  @a nicInfo is unharmed.
 
521
 *
 
522
 ******************************************************************************
 
523
 */
 
524
 
 
525
static Bool
 
526
RecordRoutingInfoIPv6(NicInfoV3 *nicInfo)
 
527
{
 
528
   GPtrArray *routes = NULL;
 
529
   guint i;
 
530
   Bool ret = FALSE;
 
531
 
 
532
   if ((routes = SlashProcNet_GetRoute6()) == NULL) {
 
533
      return FALSE;
 
534
   }
 
535
 
 
536
   for (i = 0; i < routes->len; i++) {
 
537
      struct sockaddr_storage ss;
 
538
      struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
 
539
      struct in6_rtmsg *in6_rtmsg;
 
540
      InetCidrRouteEntry *icre;
 
541
      uint32_t ifIndex = -1;
 
542
 
 
543
      in6_rtmsg = g_ptr_array_index(routes, i);
 
544
 
 
545
      if ((in6_rtmsg->rtmsg_flags & RTF_UP) == 0 ||
 
546
          !GuestInfoGetNicInfoIfIndex(nicInfo, in6_rtmsg->rtmsg_ifindex,
 
547
                                      &ifIndex)) {
 
548
         continue;
 
549
      }
 
550
 
 
551
      icre = XDRUTIL_ARRAYAPPEND(nicInfo, routes, 1);
 
552
      ASSERT_MEM_ALLOC(icre);
 
553
 
 
554
      /*
 
555
       * Destination.
 
556
       */
 
557
      sin6->sin6_family = AF_INET6;
 
558
      sin6->sin6_addr = in6_rtmsg->rtmsg_dst;
 
559
      GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin6,
 
560
                                        &icre->inetCidrRouteDest);
 
561
 
 
562
      icre->inetCidrRoutePfxLen = in6_rtmsg->rtmsg_dst_len;
 
563
 
 
564
      /*
 
565
       * Next hop.
 
566
       */
 
567
      if (in6_rtmsg->rtmsg_flags & RTF_GATEWAY) {
 
568
         TypedIpAddress *ip = Util_SafeCalloc(1, sizeof *ip);
 
569
         sin6->sin6_addr = in6_rtmsg->rtmsg_gateway;
 
570
         GuestInfoSockaddrToTypedIpAddress((struct sockaddr *)sin6, ip);
 
571
         icre->inetCidrRouteNextHop = ip;
 
572
      }
 
573
 
 
574
      /*
 
575
       * Interface, metric.
 
576
       */
 
577
      icre->inetCidrRouteIfIndex = ifIndex;
 
578
      icre->inetCidrRouteMetric = in6_rtmsg->rtmsg_metric;
 
579
   }
 
580
 
 
581
   ret = TRUE;
 
582
 
 
583
   SlashProcNet_FreeRoute6(routes);
 
584
   return ret;
 
585
}
 
586
 
 
587
 
 
588
/*
 
589
 ******************************************************************************
 
590
 * RecordRoutingInfo --                                                  */ /**
 
591
 *
 
592
 * @brief Query the routing subsystem and pack up contents into
 
593
 * InetCidrRouteEntries.
 
594
 *
 
595
 * @param[out] nicInfo  NicInfoV3 container.
 
596
 *
 
597
 * @note Do not call this routine without first populating @a nicInfo 's NIC
 
598
 * list.
 
599
 *
 
600
 * @retval TRUE         Values collected, attached to @a nicInfo.
 
601
 * @retval FALSE        Something went wrong.
 
602
 *
 
603
 ******************************************************************************
 
604
 */
 
605
 
 
606
static Bool
 
607
RecordRoutingInfo(NicInfoV3 *nicInfo)
 
608
{
 
609
   Bool ret = TRUE;
 
610
 
 
611
   if (File_Exists("/proc/net/route") && !RecordRoutingInfoIPv4(nicInfo)) {
 
612
      Warning("%s: Unable to collect IPv4 routing table.\n", __func__);
 
613
      ret = FALSE;
 
614
   }
 
615
 
 
616
   if (File_Exists("/proc/net/ipv6_route") && !RecordRoutingInfoIPv6(nicInfo)) {
 
617
      Warning("%s: Unable to collect IPv6 routing table.\n", __func__);
 
618
      ret = FALSE;
 
619
   }
 
620
 
 
621
   return ret;
 
622
}
 
623
 
 
624
#else                                           // ifdef USE_SLASH_PROC
 
625
static Bool
 
626
RecordRoutingInfo(NicInfoV3 *nicInfo)
 
627
{
 
628
   return TRUE;
 
629
}
 
630
#endif                                          // else
 
631
 
 
632
#endif // ifndef NO_DNET