]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Fix the missing IP aliases in the guest info.
authorOliver Kurth <okurth@vmware.com>
Tue, 19 Feb 2019 20:51:32 +0000 (12:51 -0800)
committerOliver Kurth <okurth@vmware.com>
Tue, 19 Feb 2019 20:51:32 +0000 (12:51 -0800)
IP aliases were missing in the guest info when libdnet is not used.

Previously tried to use the MAC address as the key to identify the IP aliases
on Linux.  However, that didn't work for vlan devices which share the same
MAC as the parent NIC.  The previous attempt was backed out.

Ideally, need to find a way to map the label name to the NIC name, but
have not been able to find a simple solution for this.  There might be a
netlink based solution but it is way too costly to do.

After more investigation, found out that a valid IP alias name must start
with the original NIC name followed by a colon.  Even though the ip addr allows
any string as the start of the NIC name, configuration file requires the colon.
In addition, ifconfig would error out when the name is not of the standard:
  ens192wwwww: error fetching interface information: Device not found

Therefore, a correctly configured system should use eth0:1, ens192:2 etc.

A lookup of libdnet source revealed the same assumption in the libdnet code.

/* Get addresses for this interface. */
for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap;
ifr = NEXTIFR(ifr)) {
/* XXX - Linux, Solaris ifaliases */
if ((p = strchr(ifr->ifr_name, ':')) != NULL)
*p = '\0';

Therefore, doing just the same.  Look for the colon, then trim it, and then
compare it with the NIC name.

open-vm-tools/lib/nicInfo/nicInfoPosix.c

index 708f4ad4551415ec31a10395d38a1ec8a8731b81..1e0fee3f30973bcdb80eceee44e2cbf2006dac5c 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2014-2018 VMware, Inc. All rights reserved.
+ * Copyright (C) 2014-2019 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -239,6 +239,39 @@ CountNetmaskBitsV6(struct sockaddr *netmask)
 }
 
 
+/*
+ ******************************************************************************
+ * IpEntryMatchesDevice --                                               */ /**
+ *
+ * @brief Check if the IP entry matches the network device.
+ *
+ * @param[in]   devName the device name
+ * @param[in]   label   the IP entry name
+ *
+ * @retval      TRUE if the IP entry name matches the device name
+ *              FALSE otherwise.
+ *
+ ******************************************************************************
+ */
+
+static Bool
+IpEntryMatchesDevice(const char *devName,
+                     const char *label)
+{
+   char *p;
+   size_t n;
+
+   if ((p = strchr(label, ':')) != NULL) {
+      n = p - label;
+   } else {
+      n = strlen(label);
+   }
+
+   /* compare sub string label[0, n) with a null terminated string devName */
+   return (0 == strncmp(devName, label, n) && '\0' == devName[n]);
+}
+
+
 /*
  ******************************************************************************
  * GuestInfoGetInterface --                                              */ /**
@@ -305,13 +338,13 @@ GuestInfoGetInterface(struct ifaddrs *ifaddrs,
             break;
          }
          /*
-          * Now look for all IPv4 and IPv6 interfaces with the same
-          * interface name as the current AF_PACKET interface.
+          * Now look for all IPv4 and IPv6 interfaces that match
+          * the current AF_PACKET interface.
           */
          for (ip = ifaddrs; ip != NULL; ip = ip->ifa_next) {
             struct sockaddr *sa = (struct sockaddr *)ip->ifa_addr;
             if (sa != NULL &&
-                strncmp(ip->ifa_name, pkt->ifa_name, IFNAMSIZ) == 0) {
+                IpEntryMatchesDevice(pkt->ifa_name, ip->ifa_name)) {
                int family = sa->sa_family;
                Bool goodAddress = FALSE;
                unsigned nBits = 0;