/** * Parses addrString into an IPv4 or IPv6 address, then determines * whether the priority of the address is higher than the existing * adaptor IP address (according to EnumIPSelectionPriority). * If it is, then the new address is assigned as the adaptor IP address * and used to populate adapter->userData->ipAddr. * If two addresses have the same highest priority, then the first one seen * is chosen. */ static void stringToAdaptorIp(PCWSTR addrString, SFLAdaptor *adaptor) { HSPAdaptorNIO *nioState = (HSPAdaptorNIO *)adaptor->userData; IN_ADDR in_addr = {0}; LPCWSTR terminator; LONG result = RtlIpv4StringToAddressW(addrString, TRUE, &terminator, &in_addr); if (NO_ERROR == result) { SFLAddress addrv4; addrv4.type = SFLADDRESSTYPE_IP_V4; addrv4.address.ip_v4.addr = in_addr.S_un.S_addr; EnumIPSelectionPriority ipPriority = agentAddressPriority(&addrv4); if (ipPriority > nioState->ipPriority) { nioState->ipPriority = ipPriority; nioState->ipAddr = addrv4; } } else { IN6_ADDR in6_addr = {0}; result = RtlIpv6StringToAddressW(addrString, &terminator, &in6_addr); if (NO_ERROR == result) { SFLAddress addrv6; addrv6.type = SFLADDRESSTYPE_IP_V6; memcpy(addrv6.address.ip_v6.addr, in_addr6.u.Byte, sizeof(in6_addr.u.Byte)); EnumIPSelectionPriority ipPriority = agentAddressPriority(&addrv6); if (ipPriority > nioState->ipPriority) { nioState->ipPriority = ipPriority; nioState->ipAddr = addrv6; } } } }
/*________________---------------------------__________________ ________________ setAddressPriorities __________________ ----------------___________________________------------------ Ideally we would do this as we go along, but since the vlan info is spliced in separately we have to wait for that and then set the priorities for the whole list. */ void setAddressPriorities(HSP *sp) { for(uint32_t i = 0; i < sp->adaptorList->num_adaptors; i++) { SFLAdaptor *adaptor = sp->adaptorList->adaptors[i]; if(adaptor && adaptor->userData) { HSPAdaptorNIO *adaptorNIO = (HSPAdaptorNIO *)adaptor->userData; adaptorNIO->ipPriority = agentAddressPriority(&adaptorNIO->ipAddr, adaptorNIO->vlan, adaptorNIO->loopback); } } }
void readIPv6Addresses(HSP *sp) { FILE *procFile = fopen("/proc/net/if_inet6", "r"); if(procFile) { char line[MAX_PROC_LINE_CHARS]; int lineNo = 0; while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) { // expect lines of the form "<address> <netlink_no> <prefix_len(HEX)> <scope(HEX)> <flags(HEX)> <deviceName> // (with a header line on the first row) char devName[MAX_PROC_LINE_CHARS]; u_char addr[MAX_PROC_LINE_CHARS]; u_int devNo, maskBits, scope, flags; ++lineNo; if(sscanf(line, "%s %x %x %x %x %s", addr, &devNo, &maskBits, &scope, &flags, devName) == 6) { if(debug) { myLog(LOG_INFO, "adaptor %s has v6 address %s with scope 0x%x", devName, addr, scope); } SFLAdaptor *adaptor = adaptorListGet(sp->adaptorList, trimWhitespace(devName)); if(adaptor && adaptor->userData) { HSPAdaptorNIO *niostate = (HSPAdaptorNIO *)adaptor->userData; SFLAddress v6addr; v6addr.type = SFLADDRESSTYPE_IP_V6; if(hexToBinary(addr, v6addr.address.ip_v6.addr, 16) == 16) { // we interpret the scope from the address now // scope = remap_proc_net_if_inet6_scope(scope); EnumIPSelectionPriority ipPriority = agentAddressPriority(sp, &v6addr, niostate->vlan, niostate->loopback); if(ipPriority > niostate->ipPriority) { // write this in as the preferred sflow-agent-address for this adaptor niostate->ipAddr = v6addr; niostate->ipPriority = ipPriority; } } } } } fclose(procFile); } }
int readInterfaces_getifaddrs(HSP *sp) { struct ifaddrs *ifap = NULL; int interfaces_found = 0; if(getifaddrs(&ifap) != 0) { myLog(LOG_ERR, "getifaddrs() failed : %s", strerror(errno)); return 0; } for(struct ifaddrs *ifa = ifap; ifa; ifa = ifa->ifa_next) { int up = (ifa->ifa_flags & IFF_UP) ? 1 : 0; int loopback = (ifa->ifa_flags & IFF_LOOPBACK) ? 1: 0; int promisc = (ifa->ifa_flags & IFF_PROMISC) ? 1 : 0; int bond_master = 0; // (ifa->ifa_flags & IFF_MASTER) ? 1 : 0; if(debug) myLog(LOG_INFO, "ifa_name=%s up=%d loopback=%d", ifa->ifa_name, up, loopback); if(up == 0) continue; interfaces_found++; // try to get the MAC u_char *macptr = NULL; u_char macAddr[6]; if(readMacAddress(ifa->ifa_name, macAddr, 6)) { macptr = macAddr; } // find or create the "adaptor" entry for this dev SFLAdaptor *adaptor = adaptorListAdd(sp->adaptorList, ifa->ifa_name, macptr, sizeof(HSPAdaptorNIO)); // 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 // we don't expect to read counters from this device - it's // really just there to learn the IP address/MAC addresses adaptorNIO->forCounters = NO; SFLAddress addr = { 0 }; if (AF_INET == ifa->ifa_addr->sa_family) { struct sockaddr_in *s = (struct sockaddr_in *)ifa->ifa_addr; addr.type = SFLADDRESSTYPE_IP_V4; addr.address.ip_v4.addr = s->sin_addr.s_addr; } else if(AF_INET6 == ifa->ifa_addr->sa_family) { struct sockaddr_in6 *s = (struct sockaddr_in6 *)ifa->ifa_addr; addr.type = SFLADDRESSTYPE_IP_V6; memcpy(&addr.address.ip_v6.addr, &s->sin6_addr, 16); } EnumIPSelectionPriority ipPriority = agentAddressPriority(sp, &addr, adaptorNIO->vlan, adaptorNIO->loopback); if(adaptor->marked || ipPriority > adaptorNIO->ipPriority) { adaptorNIO->ipAddr = addr; adaptorNIO->ipPriority = ipPriority; if(debug) { char buf[51]; myLog(LOG_INFO, "interface: %s family: %d IP: %s priority: %d", ifa->ifa_name, ifa->ifa_addr->sa_family, inet_ntop(ifa->ifa_addr->sa_family, &adaptorNIO->ipAddr.address, buf, 50), ipPriority); } } // clear the mark so we don't free it below adaptor->marked = NO; } // clean up freeifaddrs(ifap); if(debug) myLog(LOG_INFO, "found (and unmarked) %d interfaces via getifaddrs", interfaces_found); return interfaces_found; }
/** * Finds the associated Win32_NetworkAdapterConfiguration for Win32_NetworkAdapter adapterObj. * Iterates through the IP addresses associated with the adapter and chooses the highest * priority IP address (according to EnumIPSelectionPriority) as the adapter address * which is used to populate adapter->userData->ipAddr. * If two addresses have the same highest priority, then the first one seen is chosen. */ void readIpAddresses(IWbemServices *pNamespace, IWbemClassObject *adapterObj, SFLAdaptor *adaptor) { IEnumWbemClassObject *configEnum; HRESULT hr = associatorsOf(pNamespace, adapterObj, L"Win32_NetworkAdapterSetting", L"Win32_NetworkAdapterConfiguration", L"Setting", &configEnum); if (SUCCEEDED(hr)) { IWbemClassObject *configObj; ULONG configCount; hr = configEnum->Next(WBEM_INFINITE, 1, &configObj, &configCount); if (SUCCEEDED(hr) && configCount == 1) { VARIANT addresses; hr = configObj->Get(L"IPAddress", 0, &addresses, 0, 0); if (WBEM_S_NO_ERROR == hr && addresses.vt == (VT_ARRAY |VT_BSTR)) { SAFEARRAY *sa = V_ARRAY(&addresses); LONG lstart, lend; hr = SafeArrayGetLBound(sa, 1, &lstart); hr = SafeArrayGetUBound(sa, 1, &lend); BSTR *pbstr; hr = SafeArrayAccessData(sa, (void HUGEP **)&pbstr); if (SUCCEEDED(hr)) { HSPAdaptorNIO *nioState = (HSPAdaptorNIO *)adaptor->userData; for (LONG idx=lstart; idx <= lend; idx++) { PCWSTR addrStr = pbstr[idx]; IN_ADDR in_addr = {0}; LPCWSTR terminator; LONG result = RtlIpv4StringToAddressW(addrStr, TRUE, &terminator, &in_addr); if (NO_ERROR == result) { SFLAddress addrv4; addrv4.type = SFLADDRESSTYPE_IP_V4; addrv4.address.ip_v4.addr = in_addr.S_un.S_addr; EnumIPSelectionPriority ipPriority = agentAddressPriority(&addrv4); if (ipPriority > nioState->ipPriority) { nioState->ipPriority = ipPriority; nioState->ipAddr = addrv4; } } else { IN6_ADDR in6_addr = {0}; result = RtlIpv6StringToAddressW(addrStr, &terminator, &in6_addr); if (NO_ERROR == result) { SFLAddress addrv6; addrv6.type = SFLADDRESSTYPE_IP_V6; memcpy(addrv6.address.ip_v6.addr, in_addr6.u.Byte, sizeof(in6_addr.u.Byte)); EnumIPSelectionPriority ipPriority = agentAddressPriority(&addrv6); if (ipPriority > nioState->ipPriority) { nioState->ipPriority = ipPriority; nioState->ipAddr = addrv6; } } } } SafeArrayUnaccessData(sa); } } VariantClear(&addresses); configObj->Release(); } configEnum->Release(); } }