/**
 * Enumerates the adapters for this host by first trying to enumerate
 * MSFT_NetAdapter and if this fails (root\standardcimv2 namespace does
 * not exist prior to Win8/2012) then tries to enumerate Win32_NetworkAdapter
 * where NetConnectionStatus=2 (to exclude tunnels, ras, wan miniports etc).
 * Uses the information to populate the sp->adaptorList structure.
 * Optionally gets the IP address (v4 and/or v6) from the approriate associated
 * objects (MSFT_NetIpAddress or Win32_NetworkAdapterConfiguration). 
 * This is only required when trying to identify the IP addresses that could be 
 * used as the agent address.
 * MSFT_NetAdapter is preferred, since the interface description is used for
 * the interface counter instance name, and this description does not
 * change when teaming is enabled, whereas Win32_NetworkAdapter.Name does
 * change when teaming is enabled.
 */
 void readInterfaces(HSP *sp, BOOL getIPAddr)
 {
	if (sp->adaptorList == NULL) {
		sp->adaptorList = adaptorListNew();
	}
	adaptorListMarkAll(sp->adaptorList);
	if (!readInterfacesMsft(sp->adaptorList, getIPAddr)) {
		readInterfacesWin32(sp->adaptorList, getIPAddr);
	}
	adaptorListFreeMarked(sp->adaptorList, freeAdaptorInfo);
 }
Esempio n. 2
0
int readInterfaces(HSP *sp)
{
  if(sp->adaptorList == NULL) sp->adaptorList = adaptorListNew();
  else adaptorListMarkAll(sp->adaptorList);

  // Walk the interfaces and collect the non-loopback interfaces so that we
  // have a list of MAC addresses for each interface (usually only 1).
  //
  // May need to come back and run a variation of this where we supply
  // a domain and collect the virtual interfaces for that domain in a
  // similar way.  It looks like we do that by just parsing the numbers
  // out of the interface name.
  
  int fd = socket (PF_INET, SOCK_DGRAM, 0);
  if (fd < 0) {
    fprintf (stderr, "error opening socket: %d (%s)\n", errno, strerror(errno));
    return 0;
  }

  FILE *procFile = fopen("/proc/net/dev", "r");
  if(procFile) {
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    char line[MAX_PROC_LINE_CHARS];
    while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) {
      if(debug) myLog(LOG_INFO, "/proc/net/dev line: %s", line);
      // the device name is always the token before the ":"
      char *devName = strtok(line, ":");
      if(devName) {
	devName = trimWhitespace(devName);
	if(devName && strlen(devName) < IFNAMSIZ) {
	  // we set the ifr_name field to make our queries
	  strcpy(ifr.ifr_name, devName);

	  if(debug > 1) {
	    myLog(LOG_INFO, "reading interface %s", devName);
	  }

	  // Get the flags for this interface
	  if(ioctl(fd,SIOCGIFFLAGS, &ifr) != 0) {
	    myLog(LOG_ERR, "device %s Get SIOCGIFFLAGS failed : %s",
		  devName,
		  strerror(errno));
	  }
	  else {
	    int up = (ifr.ifr_flags & IFF_UP) ? YES : NO;
	    int loopback = (ifr.ifr_flags & IFF_LOOPBACK) ? YES : NO;
	    int promisc =  (ifr.ifr_flags & IFF_PROMISC) ? YES : NO;
	    int bond_master = (ifr.ifr_flags & IFF_MASTER) ? YES : NO;
	    //int hasBroadcast = (ifr.ifr_flags & IFF_BROADCAST);
	    //int pointToPoint = (ifr.ifr_flags & IFF_POINTOPOINT);

	    // used to igore loopback interfaces here, but now those
	    // are filtered at the point where we roll together the
	    // counters.
	    if(up) {
	      
	       // Get the MAC Address for this interface
	      if(ioctl(fd,SIOCGIFHWADDR, &ifr) != 0) {
		myLog(LOG_ERR, "device %s Get SIOCGIFHWADDR failed : %s",
		      devName,
		      strerror(errno));
	      }

	      // for now just assume that each interface has only one MAC.  It's not clear how we can
	      // learn multiple MACs this way anyhow.  It seems like there is just one per ifr record.
	      // find or create a new "adaptor" entry
	      SFLAdaptor *adaptor = adaptorListAdd(sp->adaptorList, devName, (u_char *)&ifr.ifr_hwaddr.sa_data, sizeof(HSPAdaptorNIO));

	      // clear the mark so we don't free it below
	      adaptor->marked = NO;

	      // this flag might belong in the adaptorNIO struct
	      adaptor->promiscuous = promisc;

	      // remember some useful flags in the userData structure
	      HSPAdaptorNIO *adaptorNIO = (HSPAdaptorNIO *)adaptor->userData;
	      adaptorNIO->loopback = loopback;
	      adaptorNIO->bond_master = bond_master;
	      adaptorNIO->vlan = HSP_VLAN_ALL; // may be modified below

	      // Try and get the ifIndex for this interface
	      if(ioctl(fd,SIOCGIFINDEX, &ifr) != 0) {
		// only complain about this if we are debugging
		if(debug) {
		  myLog(LOG_ERR, "device %s Get SIOCGIFINDEX failed : %s",
			devName,
			strerror(errno));
		}
	      }
	      else {
		adaptor->ifIndex = ifr.ifr_ifindex;
	      }
	      
	      // Try to get the IP address for this interface
	      if(ioctl(fd,SIOCGIFADDR, &ifr) != 0) {
		// only complain about this if we are debugging
		if(debug) {
		  myLog(LOG_ERR, "device %s Get SIOCGIFADDR failed : %s",
			devName,
			strerror(errno));
		}
	      }
	      else {
		if (ifr.ifr_addr.sa_family == AF_INET) {
		  struct sockaddr_in *s = (struct sockaddr_in *)&ifr.ifr_addr;
		  // IP addr is now s->sin_addr
		  adaptorNIO->ipAddr.type = SFLADDRESSTYPE_IP_V4;
		  adaptorNIO->ipAddr.address.ip_v4.addr = s->sin_addr.s_addr;
		}
		//else if (ifr.ifr_addr.sa_family == AF_INET6) {
		// not sure this ever happens - on a linux system IPv6 addresses
		// are picked up from /proc/net/if_inet6
		// struct sockaddr_in6 *s = (struct sockaddr_in6 *)&ifr.ifr_addr;
		// IP6 addr is now s->sin6_addr;
		//}
	      }
	      
	      // Try to get the ethtool info for this interface so we can infer the
	      // ifDirection and ifSpeed. Learned from openvswitch (http://www.openvswitch.org).
	      struct ethtool_cmd ecmd = { 0 };
	      ecmd.cmd = ETHTOOL_GSET;
	      ifr.ifr_data = (char *)&ecmd;
	      if(ioctl(fd, SIOCETHTOOL, &ifr) == 0) {
		adaptor->ifDirection = ecmd.duplex ? 1 : 2;
		uint64_t ifSpeed_mb = ecmd.speed;
		// ethtool_cmd_speed(&ecmd) is available in newer systems and uses the
		// speed_hi field too,  but we would need to run autoconf-style
		// tests to see if it was there and we are trying to avoid that.
		if(ifSpeed_mb == (uint16_t)-1 ||
		   ifSpeed_mb == (uint32_t)-1) {
		  // unknown
		  adaptor->ifSpeed = 0;
		}
		else {
		  adaptor->ifSpeed = ifSpeed_mb * 1000000;
		}
	      }
	    }
	  }
	}
      }
    }
    fclose(procFile);
  }
  
  close (fd);

  // now remove and free any that are still marked
  adaptorListFreeMarked(sp->adaptorList);

  // check in case any of the survivors are specific
  // to a particular VLAN
  readVLANs(sp);

  // now that we have the evidence gathered together, we can
  // set the L3 address priorities (used for auto-selecting
  // the sFlow-agent-address if requrired to by the config.
  setAddressPriorities(sp);

  // now we can read IPv6 addresses too - they come from a
  // different place. Depending on the address priorities this
  // may cause the adaptor's best-choice ipAddress to be
  // overwritten.
  readIPv6Addresses(sp);

  return sp->adaptorList->num_adaptors;
}
Esempio n. 3
0
/**
 * Updates the switch port list with the information in pSwitchConfig
 * obtained from the filter.
 */
void updateSwitchPorts(HSP *sp, PAllSwitchesConfig config)
{
	if (config->revision <= sp->portInfoRevision) {
		return;
	}
	if (sp->vAdaptorList == NULL) {
		sp->vAdaptorList = adaptorListNew();
	} else {
		adaptorListMarkAll(sp->vAdaptorList);
	}
	PSwitchConfig switchConfig;
	for (uint32_t switchNum = 0; switchNum < config->numSwitches; switchNum++) {
		if (switchNum == 0) {
			switchConfig = GET_FIRST_SWITCH_CONFIG(config);
		} else {
			switchConfig = GET_NEXT_SWITCH_CONFIG(switchConfig);
		}
		wchar_t *switchName = ndiswcsdup(&switchConfig->switchName);
		uint64_t switchId = switchConfig->switchID;
		for (uint32_t portNum = 0; portNum < switchConfig->numPorts; portNum++) {
			PPortEntry portEntry = GET_PORT_ENTRY_AT(switchConfig, portNum);
			uint32_t portId = portEntry->portID;
			wchar_t *portName = ndiswcsdup(&portEntry->portName);
			char portGuid[FORMATTED_GUID_LEN+1];
			guidToString(portName, (UCHAR *)portGuid, FORMATTED_GUID_LEN);
			SFLAdaptor *switchPort = adaptorListGet(sp->vAdaptorList, portGuid);
			if (switchPort == NULL) {
				//new port so add to the vadaptor list
				//convert GUID to uuid format to look up ifIndex/dsIndex
				char uuid[16];
				hexToBinary((UCHAR *)portGuid, (UCHAR *)uuid, 33);
				uint32_t ifIndex = assign_dsIndex(&sp->portStore, uuid, &sp->maxIfIndex, &sp->portStoreInvalid);
				switchPort = addVAdaptor(sp->vAdaptorList, portGuid, ifIndex);
				HVSVPortInfo *portInfo = (HVSVPortInfo *)switchPort->userData;
				portInfo->filterEnabled = TRUE;
				portInfo->portId = portId;
				portInfo->revision = portEntry->revision;
				switchPort->marked = FALSE;
				updatePortSwitchName(switchPort, switchName);
				portInfo->switchId = switchConfig->switchID;
				myLog(LOG_INFO, "updateSwitchPorts: Added new portId=%u ifIndex=%u deviceName=%s switchId=%llu switchName=%S",
					portInfo->portId, switchPort->ifIndex, switchPort->deviceName, portInfo->switchId, portInfo->switchName);
				addPoller(sp, switchPort);
			} else {
				//we already know about this port, so make sure we have a poller
				//and the current info
				SFLDataSource_instance dsi;
				SFL_DS_SET(dsi, 0, switchPort->ifIndex, 0);
				SFLPoller *poller = sfl_agent_getPoller(sp->sFlow->agent, &dsi);
				if (poller == NULL) {
					poller = addPoller(sp, switchPort);
				}
				HVSVPortInfo *portInfo = (HVSVPortInfo *)switchPort->userData;
				if (portEntry->revision > portInfo->revision) {
					updatePortSwitchName(switchPort, switchName);
					portInfo->revision = portEntry->revision;
					if (poller != NULL) {
						sfl_poller_resetCountersSeqNo(poller);
					}
					myLog(LOG_INFO, "updateSwitchPorts: revision changed: portId=%u ifIndex=%u deviceName=%s switchId=%llu switchName=%S", 
						  portInfo->portId, switchPort->ifIndex, switchPort->deviceName, portInfo->switchId, portInfo->switchName);
				}
				portInfo->filterEnabled = TRUE;
				switchPort->marked = FALSE;
			}
			my_free(portName);
		}
		my_free(switchName);
	}
	//now sweep
	//remove the pollers for non-sampling ports
	for (uint32_t i = 0; i < sp->vAdaptorList->num_adaptors; i++) {
		SFLAdaptor *vAdaptor = sp->vAdaptorList->adaptors[i];
		if (vAdaptor->marked) {
			HVSVPortInfo *portInfo = (HVSVPortInfo *)vAdaptor->userData;
			if (portInfo->filterEnabled) {
				//filter (ie sampling) has been disabled in the switch with this port
				((HVSVPortInfo *)vAdaptor->userData)->portId = 0;
				removePoller(sp, vAdaptor);
				portInfo->filterEnabled = FALSE;
				//Clear the mark so this port will not be deleted, the VM and adaptor may still exist.
				//If the adaptor does not exist, it will be removed when we next refresh the VMs.
				vAdaptor->marked = FALSE;
			} else {
				//this was a port added for a vm on a switch with the filter disabled, so
				//just clear the mark so that it will not be deleted.
				vAdaptor->marked = FALSE;
			}	
		}
	}
	//Now remove the marked adaptors and their port info from the list
	adaptorListFreeMarked(sp->vAdaptorList, freePortInfo);
	//TODO ageout the persistent ifIndex->GUID mapping and remove from vAdaptor list.
	sp->portInfoRevision = config->revision;
	readWMISwitchPorts(sp); //update the ifSpeed, MAC, VM name
	sp->refreshVms = TRUE;
}
  int readInterfaces(HSP *sp, uint32_t *p_added, uint32_t *p_removed, uint32_t *p_cameup, uint32_t *p_wentdown, uint32_t *p_changed)
{
  uint32_t ad_added=0, ad_removed=0, ad_cameup=0, ad_wentdown=0, ad_changed=0;
  if(sp->adaptorList == NULL) sp->adaptorList = adaptorListNew();
  else adaptorListMarkAll(sp->adaptorList);

  // Walk the interfaces and collect the non-loopback interfaces so that we
  // have a list of MAC addresses for each interface (usually only 1).
  //
  // May need to come back and run a variation of this where we supply
  // a domain and collect the virtual interfaces for that domain in a
  // similar way.  It looks like we do that by just parsing the numbers
  // out of the interface name.
  
  int fd = socket (PF_INET, SOCK_DGRAM, 0);
  if (fd < 0) {
    fprintf (stderr, "error opening socket: %d (%s)\n", errno, strerror(errno));
    return 0;
  }

  FILE *procFile = fopen("/proc/net/dev", "r");
  if(procFile) {
    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    char line[MAX_PROC_LINE_CHARS];
    int lineNo = 0;
    while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) {
      if(lineNo++ < 2) continue; // skip headers
      // the device name is always the first token before the ":"
      char buf[MAX_PROC_LINE_CHARS];
      char *p = line;
      char *devName = parseNextTok(&p, " \t:", NO, '\0', NO, buf, MAX_PROC_LINE_CHARS);
      if(devName && my_strlen(devName) < IFNAMSIZ) {
	devName = trimWhitespace(devName);
	if(devName && strlen(devName) < IFNAMSIZ) {
	  // we set the ifr_name field to make our queries
	  strncpy(ifr.ifr_name, devName, sizeof(ifr.ifr_name));

	  if(debug > 1) {
	    myLog(LOG_INFO, "reading interface %s", devName);
	  }

	  // Get the flags for this interface
	  if(ioctl(fd,SIOCGIFFLAGS, &ifr) < 0) {
	    myLog(LOG_ERR, "device %s Get SIOCGIFFLAGS failed : %s",
		  devName,
		  strerror(errno));
	  }
	  else {
	    int up = (ifr.ifr_flags & IFF_UP) ? YES : NO;
	    int loopback = (ifr.ifr_flags & IFF_LOOPBACK) ? YES : NO;
	    int promisc =  (ifr.ifr_flags & IFF_PROMISC) ? YES : NO;
	    int bond_master = (ifr.ifr_flags & IFF_MASTER) ? YES : NO;
	    int bond_slave = (ifr.ifr_flags & IFF_SLAVE) ? YES : NO;
	    //int hasBroadcast = (ifr.ifr_flags & IFF_BROADCAST);
	    //int pointToPoint = (ifr.ifr_flags & IFF_POINTOPOINT);

	    // used to ignore loopback interfaces here, and interfaces
	    // that are currently marked down, but now those are
	    // filtered at the point where we roll together the
	    // counters, or build the list for export
	      
	    // Get the MAC Address for this interface
	    if(ioctl(fd,SIOCGIFHWADDR, &ifr) < 0) {
	      myLog(LOG_ERR, "device %s Get SIOCGIFHWADDR failed : %s",
		    devName,
		    strerror(errno));
	    }
	    
	    // for now just assume that each interface has only one MAC.  It's not clear how we can
	    // learn multiple MACs this way anyhow.  It seems like there is just one per ifr record.
	    // find or create a new "adaptor" entry
	    SFLAdaptor *adaptor = adaptorListGet(sp->adaptorList, devName);
	    if(adaptor == NULL) {
	      ad_added++;
	      adaptor = adaptorListAdd(sp->adaptorList, devName, (u_char *)&ifr.ifr_hwaddr.sa_data, sizeof(HSPAdaptorNIO));
	    }
	    
	    // clear the mark so we don't free it below
	    adaptor->marked = NO;
	    
	    // this flag might belong in the adaptorNIO struct
	    adaptor->promiscuous = promisc;
	    
	    // remember some useful flags in the userData structure
	    HSPAdaptorNIO *adaptorNIO = (HSPAdaptorNIO *)adaptor->userData;
	    if(adaptorNIO->up != up) {
	      if(up) ad_cameup++;
	      else ad_wentdown++;
	      if(debug) {
		myLog(LOG_INFO, "adaptor %s %s",
		      adaptor->deviceName,
		      up ? "came up" : "went down");
	      }
	    }
	    adaptorNIO->up = up;
	    adaptorNIO->loopback = loopback;
	    adaptorNIO->bond_master = bond_master;
	    adaptorNIO->bond_slave = bond_slave;
	    adaptorNIO->vlan = HSP_VLAN_ALL; // may be modified below
#ifdef HSP_SWITCHPORT_REGEX
	    if(regexec(&sp->swp_regex, devName, 0, NULL, 0) == 0) {
	      adaptorNIO->switchPort = YES;
	    }
#endif
	    // Try and get the ifIndex for this interface
	    if(ioctl(fd,SIOCGIFINDEX, &ifr) < 0) {
	      // only complain about this if we are debugging
	      if(debug) {
		myLog(LOG_ERR, "device %s Get SIOCGIFINDEX failed : %s",
		      devName,
		      strerror(errno));
	      }
	    }
	    else {
	      adaptor->ifIndex = ifr.ifr_ifindex;
	    }
	    
	    // Try to get the IP address for this interface
	    if(ioctl(fd,SIOCGIFADDR, &ifr) < 0) {
	      // only complain about this if we are debugging
	      if(debug) {
		myLog(LOG_ERR, "device %s Get SIOCGIFADDR failed : %s",
		      devName,
		      strerror(errno));
	      }
	    }
	    else {
	      if (ifr.ifr_addr.sa_family == AF_INET) {
		struct sockaddr_in *s = (struct sockaddr_in *)&ifr.ifr_addr;
		// IP addr is now s->sin_addr
		adaptorNIO->ipAddr.type = SFLADDRESSTYPE_IP_V4;
		adaptorNIO->ipAddr.address.ip_v4.addr = s->sin_addr.s_addr;
	      }
	      //else if (ifr.ifr_addr.sa_family == AF_INET6) {
	      // not sure this ever happens - on a linux system IPv6 addresses
	      // are picked up from /proc/net/if_inet6
	      // struct sockaddr_in6 *s = (struct sockaddr_in6 *)&ifr.ifr_addr;
	      // IP6 addr is now s->sin6_addr;
	      //}
	    }

	    // use ethtool to get info about direction/speed and more
	    if(read_ethtool_info(&ifr, fd, adaptor) == YES) {
	      ad_changed++;
	    }
	  }
	}
      }
    }
    fclose(procFile);
  }
  
  close (fd);

  // now remove and free any that are still marked
  ad_removed = adaptorListFreeMarked(sp->adaptorList);

  // check in case any of the survivors are specific
  // to a particular VLAN
  readVLANs(sp);

  // now that we have the evidence gathered together, we can
  // set the L3 address priorities (used for auto-selecting
  // the sFlow-agent-address if requrired to by the config.
  setAddressPriorities(sp);

  // now we can read IPv6 addresses too - they come from a
  // different place. Depending on the address priorities this
  // may cause the adaptor's best-choice ipAddress to be
  // overwritten.
  readIPv6Addresses(sp);

  if(p_added) *p_added = ad_added;
  if(p_removed) *p_removed = ad_removed;
  if(p_cameup) *p_cameup = ad_cameup;
  if(p_wentdown) *p_wentdown = ad_wentdown;
  if(p_changed) *p_changed = ad_changed;

  return sp->adaptorList->num_adaptors;
}
Esempio n. 5
0
/**
 * Enumerates the adapters for this host from WMI Win32_NetworkAdapter
 * where NetConnectionStatus=2 (to exclude tunnels, ras, wan miniports etc).
 * Uses the information to populate the sp->adaptorList structure.
 * adapter->deviceName = Win32_NetworkAdapter.GUID (converted to 
 * lowercase char with enclosing {} removed)
 * adapter->ifIndex = Win32_NetworkAdapter.InterfaceIndex
 * this is the interface index used in the route table (rather than Index
 * which is the index for the interface in the registry).
 * adapter->userData->countersInstance = Win32_NetworkAdapter.Name 
 * (with reserved chars replaced) 
 * adapter->userData->isVirtual = (Win32_NetworkAdapter.ServiceName == "VMSMP")
 * Optionally gets the IP address (v4 and/or v6) from the associated
 * Win32_NetworkAdapterConfiguration. This is only required when trying
 * to identify the IP addresses that could be used as the agent address.
 */
void readInterfaces(HSP *sp, BOOL getIpAddr)
{
	if (sp->adaptorList == NULL) {
		sp->adaptorList = adaptorListNew();
	}
	adaptorListMarkAll(sp->adaptorList);

	BSTR path = SysAllocString(WMI_CIMV2_NS);
	HRESULT hr = S_FALSE;
	IWbemServices *pNamespace = NULL;
	
	hr = connectToWMI(path, &pNamespace);
	SysFreeString(path);
	if (WBEM_S_NO_ERROR != hr) {
		myLog(LOG_ERR,"readInterfaces: connectToWMI failed for namespace %S", path);
		return;
	}
	BSTR queryLang = SysAllocString(L"WQL");
	BSTR query = SysAllocString(L"SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionStatus=2");
	IEnumWbemClassObject *adapterEnum = NULL;
	hr = pNamespace->ExecQuery(queryLang, query, WBEM_FLAG_FORWARD_ONLY, NULL, &adapterEnum);
	SysFreeString(queryLang);
	if (!SUCCEEDED(hr)) {
		myLog(LOG_ERR,"readInterfaces: ExecQuery() failed for query %S error=0x%x", query, hr);
		SysFreeString(query);
		pNamespace->Release();
		CoUninitialize();
		return;
	}
	SysFreeString(query);
	IWbemClassObject *adapterObj = NULL;
	VARIANT ifIndexVal;
	hr = WBEM_S_NO_ERROR;
	while (WBEM_S_NO_ERROR == hr) {
		ULONG adapterCount = 1;
		hr = adapterEnum->Next(WBEM_INFINITE, 1, &adapterObj, &adapterCount);
		if (0 == adapterCount) {
			break;
		}
		wchar_t *guidString = stringFromWMIProperty(adapterObj, PROP_GUID);
		wchar_t *macString = stringFromWMIProperty(adapterObj, PROP_MAC);
		if (guidString != NULL && macString != NULL) {
			u_char deviceName[FORMATTED_GUID_LEN+1];
			guidToString(guidString, deviceName, FORMATTED_GUID_LEN);
			u_char mac[13];
			wchexToBinary(macString, mac, 13);
			SFLAdaptor *adaptor = adaptorListAdd(sp->adaptorList, 
												(char *)deviceName, mac, 
												sizeof(HSPAdaptorNIO));
			// clear the mark so we don't free it below
			adaptor->marked = FALSE;
			if (WBEM_S_NO_ERROR == adapterObj->Get(PROP_IFINDEX, 0, &ifIndexVal, 0, 0) &&
				(V_VT(&ifIndexVal) == VT_I4 || V_VT(&ifIndexVal) == VT_UI4)) {
				adaptor->ifIndex = ifIndexVal.ulVal;
			}
			HSPAdaptorNIO *userData = (HSPAdaptorNIO *)adaptor->userData;
			if (userData->countersInstance != NULL) {
				my_free(userData->countersInstance);
			}
			wchar_t *counterName = stringFromWMIProperty(adapterObj, PROP_NAME);
			if (counterName != NULL) {
				cleanCounterName(counterName, UTNETWORK_INTERFACE);
				userData->countersInstance = counterName;
			}
			wchar_t *svcName = stringFromWMIProperty(adapterObj, PROP_SVC_NAME);
			if (svcName != NULL) {
				userData->isVirtual = (_wcsicmp(VMSMP, svcName) == 0);
				my_free(svcName);
			}
			if (getIpAddr) {
				userData->ipPriority = IPSP_NONE;
				readIpAddresses(pNamespace, adapterObj, adaptor);
			}
			myLog(LOG_INFO,"ReadInterfaces:\n\tAdapterName:\t%s\n\tifIndex:\t%lu\n\tCounterName:\t%S\n\tisVirtual\t%u",
				adaptor->deviceName, adaptor->ifIndex, userData->countersInstance, userData->isVirtual);
		}
		if (guidString != NULL) {
			my_free(guidString);
		}
		if (macString != NULL) {
			my_free(macString);
		}
		adapterObj->Release();
		VariantClear(&ifIndexVal);
	}
	adapterEnum->Release();
	pNamespace->Release();
	CoUninitialize();
	adaptorListFreeMarked(sp->adaptorList, freeAdaptorInfo);
}