]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
GuestInfo: Add option to exclude network interfaces
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:52 +0000 (11:23 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:52 +0000 (11:23 -0700)
VMs running docker can have hundred of virtual network interfaces.
Also, docker creates one virtual network interface 'docker0' with
an IPv4 address. This address is useless outside the VM, and should
not be propagated via GuestInfo, or even as the primary network
address.

This change adds on option for tools.conf to exclude specific
network interface names using patterns with wildcards. This makes
it easy to exclude virtual docker interface names with the option

exclude-nics=docker*,veth*

For convenience, the option is set to docker*,veth* by default,
except for Windows, where it is "vEthernet*". To
send information of all interfaces, including docker* and veth*,
the option needs to be set to an empty value: exclude-nics=

open-vm-tools/lib/include/conf.h
open-vm-tools/lib/include/nicInfo.h
open-vm-tools/lib/nicInfo/nicInfo.c
open-vm-tools/lib/nicInfo/nicInfoPosix.c
open-vm-tools/libvmtools/vmtoolsConfig.c
open-vm-tools/services/plugins/guestInfo/guestInfoServer.c

index 5813c956b48ada7d2043e6046e5987b15aea4867..d6da7e339f2f2f059a67d7de2d7cf15fb57a670c 100644 (file)
  */
 #define CONFNAME_GUESTINFO_ENABLESTATLOGGING "enable-stat-logging"
 
+/**
+ * Set a comma separated list of network interface names that shall be ignored.
+ *
+ * @note interface names can use wildcards like '*' and '?'
+ *
+ * @param string comma separated list of interface name patterns.
+ */
+
+#define CONFNAME_GUESTINFO_EXCLUDENICS "exclude-nics"
+
 /*
  * END GuestInfo goodies.
  ******************************************************************************
index 6d116e519a2e46e39ae248714c551d89b0123102..506d1546153bc79daa1c1da49e19b35d3fb340ab 100644 (file)
@@ -74,4 +74,8 @@ Bool
 GuestInfo_IsEqual_WinsConfigInfo(const WinsConfigInfo *a,
                                  const WinsConfigInfo *b);
 
+void GuestInfo_SetIfaceExcludeList(char **list);
+
+Bool GuestInfo_IfaceIsExcluded(const char *name);
+
 #endif
index 9975dec60523339747815e90780339b3ee28561a..88aab30ddeb750a1041a5689eed55a4da7526932 100644 (file)
@@ -38,6 +38,7 @@
 #include "netutil.h"
 #include "wiper.h"
 
+GPtrArray *gIfaceExcludePatterns = NULL;
 
 /**
  * Helper to initialize an opaque struct member.
@@ -57,6 +58,72 @@ static void * Util_DupeThis(const void *source, size_t sourceSize);
  * Global functions.
  */
 
+/*
+ ******************************************************************************
+ *
+ * GuestInfo_SetIfaceExcludeList --
+ *
+ * @brief Set list of network interfaces to be ignored.
+ *
+ * @param[in] NULL terminated array of pointers to strings with patterns
+ *
+ * @sa gIfaceExcludePatterns will be set
+ *
+ ******************************************************************************
+ */
+
+void
+GuestInfo_SetIfaceExcludeList(char **list)
+{
+   guint i;
+
+   if (gIfaceExcludePatterns != NULL) {
+      g_ptr_array_free(gIfaceExcludePatterns, TRUE);
+      gIfaceExcludePatterns = NULL;
+   }
+
+   if (list != NULL) {
+      gIfaceExcludePatterns =
+         g_ptr_array_new_with_free_func((GDestroyNotify) &g_pattern_spec_free);
+      for (i = 0; list[i] != NULL; i++) {
+         if (list[i][0] != '\0') {
+            g_ptr_array_add(gIfaceExcludePatterns, g_pattern_spec_new(list[i]));
+         }
+      }
+   }
+}
+
+/*
+ ******************************************************************************
+ *
+ * GuestInfo_IfaceIsExcluded --
+ *
+ * @brief Determine if a specific interface name shall be excluded.
+ *
+ * @param[in] The interface name.
+ *
+ * @retval TRUE if interface name shall be excluded.
+ *
+ ******************************************************************************
+*/
+
+Bool
+GuestInfo_IfaceIsExcluded(const char *name)
+{
+   int i;
+
+   if (gIfaceExcludePatterns != NULL && name != NULL) {
+      for(i = 0; i < gIfaceExcludePatterns->len; i++) {
+         if (g_pattern_match_string(g_ptr_array_index(gIfaceExcludePatterns, i),
+                                    name)) {
+            g_debug("%s: excluding interface %s because it matched pattern %d",
+                    __FUNCTION__, name, i);
+            return TRUE;
+         }
+      }
+   }
+   return FALSE;
+}
 
 /*
  ******************************************************************************
index bc862f2e5cf39b61b675733e6b0ac60df4c74701..f00083226a6646296e480fc210284575210608b7 100644 (file)
@@ -273,6 +273,11 @@ GuestInfoGetNicInfo(NicInfoV3 *nicInfo) // OUT
          GuestNicV3 *nic;
          struct ifaddrs *ip;
          struct sockaddr_ll *sll = (struct sockaddr_ll *)pkt->ifa_addr;
+
+         if (GuestInfo_IfaceIsExcluded(pkt->ifa_name)) {
+            continue;
+         }
+
          if (sll != NULL && sll->sll_family == AF_PACKET) {
             char macAddress[NICINFO_MAC_LEN];
             Str_Sprintf(macAddress, sizeof macAddress,
@@ -383,6 +388,8 @@ GuestInfoGetPrimaryIP(void)
 
       if (!(curr->ifa_flags & IFF_UP) || curr->ifa_flags & IFF_LOOPBACK) {
          continue;
+      } else if (GuestInfo_IfaceIsExcluded(curr->ifa_name)) {
+         continue;
       } else if (currFamily == AF_INET || currFamily == AF_INET6) {
          ipstr = ValidateConvertAddress(curr->ifa_addr);
       } else {
@@ -504,6 +511,11 @@ ReadInterfaceDetails(const struct intf_entry *entry,  // IN: current interface e
       if (entry->intf_link_addr.addr_type == ADDR_TYPE_ETH) {
          Str_Sprintf(macAddress, sizeof macAddress, "%s",
                      addr_ntoa(&entry->intf_link_addr));
+
+         if (GuestInfo_IfaceIsExcluded(entry->intf_name)) {
+            return 0;
+         }
+
          nic = GuestInfoAddNicEntry(nicInfo, macAddress, NULL, NULL);
          if (NULL == nic) {
             /*
@@ -977,6 +989,10 @@ GuestInfoGetIntf(const struct intf_entry *entry,  // IN:
       struct sockaddr_storage ss;
       struct sockaddr *saddr = (struct sockaddr *)&ss;
 
+      if (GuestInfo_IfaceIsExcluded(entry->intf_name)) {
+         return 0;
+      }
+
       memset(&ss, 0, sizeof ss);
       addr_ntos(&entry->intf_addr, saddr);
       *ipstr = ValidateConvertAddress(saddr);
index 36bcff7cccb0f9511cf106397aab9d02f3b229f5..874580703995fb175eea065cb8d7aab2920f2a75 100644 (file)
@@ -621,7 +621,9 @@ VMTools_ConfigGetInteger(GKeyFile *config,
  * @param[in]  section  Section to look for in the config file.
  * @param[in]  defValue Default value if the key is not found or error.
  *
- * @return value of the key if value was read successfully, else defValue.
+ * @return value of the key if value was read successfully, else a copy
+ * of defValue unless defValue is NULL, in which case it's NULL.
+ * The returned string should be freed with g_free() when no longer needed.
  */
 
 gchar *
@@ -646,7 +648,7 @@ VMTools_ConfigGetString(GKeyFile *config,
       }
       g_debug("%s: Returning default value for '[%s] %s'=%s.\n",
               __FUNCTION__, section, key, defValue ? defValue : "(null)");
-      value = defValue;
+      value = g_strdup(defValue);
       g_clear_error(&err);
    }
    return value;
index e0f128a2e4db35e2e22076305c18106d4fde0078..4c473e65dbf12469e0d43b46d6e37efbe3970071 100644 (file)
@@ -85,6 +85,15 @@ VM_EMBED_VERSION(VMTOOLSD_VERSION_STRING);
 
 #define GUESTINFO_DEFAULT_DELIMITER ' '
 
+/**
+ * The default setting for exclude-nics
+ */
+#if defined(_WIN32)
+#define GUESTINFO_DEFAULT_IFACE_EXCLUDES "vEthernet*"
+#else
+#define GUESTINFO_DEFAULT_IFACE_EXCLUDES "docker*,veth*"
+#endif
+
 /*
  * Define what guest info types and nic info versions could be sent
  * to update nic info at VMX. The order defines a sequence of fallback
@@ -309,6 +318,40 @@ GuestInfoCheckIfRunningSlow(ToolsAppCtx *ctx)
 }
 
 
+/*
+ ******************************************************************************
+ * GuestInfoSetNicExcludeList --                                           */ /**
+ *
+ * Gets exclude-nics setting from the config, and sets the list of exclude
+ * patterns.
+ *
+ * @param[in]  ctx     The application context.
+ *
+ ******************************************************************************
+ */
+
+static void
+GuestInfoSetNicExcludeList(ToolsAppCtx *ctx)
+{
+   static gchar *ifaceExcludeStringCached = NULL;
+   gchar *ifaceExcludeString;
+
+   /* Check if we want to exclude interfaces based on the name. */
+   ifaceExcludeString = VMTools_ConfigGetString(ctx->config, CONFGROUPNAME_GUESTINFO,
+                                                CONFNAME_GUESTINFO_EXCLUDENICS,
+                                                GUESTINFO_DEFAULT_IFACE_EXCLUDES);
+   if (g_strcmp0(ifaceExcludeString, ifaceExcludeStringCached) != 0) {
+      gchar **list = NULL;
+      if (ifaceExcludeString != NULL && ifaceExcludeString[0] != '\0') {
+         list = g_strsplit(ifaceExcludeString, ",", 0);
+      }
+      g_free(ifaceExcludeStringCached);
+      ifaceExcludeStringCached = ifaceExcludeString;
+      GuestInfo_SetIfaceExcludeList(list);
+      g_strfreev(list);
+   }
+}
+
 /*
  ******************************************************************************
  * GuestInfoGather --                                                    */ /**
@@ -396,6 +439,9 @@ GuestInfoGather(gpointer data)
    }
 
    /* Get NIC information. */
+
+   GuestInfoSetNicExcludeList(ctx);
+
    if (!GuestInfo_GetNicInfo(&nicInfo)) {
       g_warning("Failed to get nic info.\n");
       /*
@@ -1529,6 +1575,8 @@ GuestInfoServerShutdown(gpointer src,
 {
    GuestInfoClearCache();
 
+   GuestInfo_SetIfaceExcludeList(NULL);
+
    if (gatherInfoTimeoutSource != NULL) {
       g_source_destroy(gatherInfoTimeoutSource);
       gatherInfoTimeoutSource = NULL;