int32_t OsNetworkListAdapters(OsContext* aContext, OsNetworkAdapter** aAdapters, uint32_t aUseLoopback) { #ifdef DEFINE_BIG_ENDIAN #define MakeIpAddress(aByte1, aByte2, aByte3, aByte4) \ (aByte4 | (aByte3<<8) | (aByte2<<16) | (aByte1<<24)) #elif defined(DEFINE_LITTLE_ENDIAN) #define MakeIpAddress(aByte1, aByte2, aByte3, aByte4) \ (aByte1 | (aByte2<<8) | (aByte3<<16) | (aByte4<<24)) #else #error "Endianness must be defined." #endif int32_t ret = -1; struct ifaddrs* networkIf; struct ifaddrs* iter; int32_t includeLoopback = 1; #ifdef PLATFORM_MACOSX_GNU aUseLoopback = 0; #endif *aAdapters = NULL; if (TEMP_FAILURE_RETRY(getifaddrs(&networkIf)) == -1) { return -1; } TIpAddress loopbackAddr = MakeIpAddress(127, 0, 0, 1); /* first check whether we have any suitable interfaces other than loopback */ if (aUseLoopback == 0) { iter = networkIf; while (iter != NULL) { if (iter->ifa_addr != NULL && iter->ifa_addr->sa_family == AF_INET && (iter->ifa_flags & IFF_RUNNING) != 0 && ((struct sockaddr_in*)iter->ifa_addr)->sin_addr.s_addr != loopbackAddr) { includeLoopback = 0; break; } iter = iter->ifa_next; } } /* ...then allocate/populate the list */ iter = networkIf; OsNetworkAdapter* head = NULL; OsNetworkAdapter* tail = NULL; while (iter != NULL) { if (iter->ifa_addr == NULL || iter->ifa_addr->sa_family != AF_INET || (iter->ifa_flags & IFF_RUNNING) == 0 || (includeLoopback == 0 && ((struct sockaddr_in*)iter->ifa_addr)->sin_addr.s_addr == loopbackAddr) || (aUseLoopback == 1 && ((struct sockaddr_in*)iter->ifa_addr)->sin_addr.s_addr != loopbackAddr)) { iter = iter->ifa_next; continue; } OsNetworkAdapter* iface = (OsNetworkAdapter*)calloc(1, sizeof(*iface)); if (iface == NULL) { OsNetworkFreeInterfaces(head); goto exit; } if (head == NULL) { head = iface; } iface->iName = (char*)malloc(strlen(iter->ifa_name) + 1); if (iface->iName == NULL) { OsNetworkFreeInterfaces(head); goto exit; } (void)strcpy(iface->iName, iter->ifa_name); iface->iAddress = ((struct sockaddr_in*)iter->ifa_addr)->sin_addr.s_addr; iface->iNetMask = ((struct sockaddr_in*)iter->ifa_netmask)->sin_addr.s_addr; if (tail != NULL) { tail->iNext = iface; } tail = iface; iter = iter->ifa_next; } ret = 0; *aAdapters = head; exit: freeifaddrs(networkIf); return ret; }
int32_t OsNetworkListAdapters(OsContext* aContext, OsNetworkAdapter** aInterfaces, uint32_t aUseLoopback) { #define MakeIpAddress(aByte1, aByte2, aByte3, aByte4) \ (aByte1 | (aByte2<<8) | (aByte3<<16) | (aByte4<<24)) MIB_IFTABLE* ifTable = NULL; MIB_IPADDRTABLE* addrTable = NULL; ULONG bytes = 0; OsNetworkAdapter* head = NULL; int32_t index = 0; const TIpAddress loopbackAddr = MakeIpAddress(127, 0, 0, 1); int32_t includeLoopback = 1; uint32_t i; if (ERROR_INSUFFICIENT_BUFFER != GetIpAddrTable(NULL, &bytes, FALSE)) { return -1; } addrTable = (MIB_IPADDRTABLE*)malloc(bytes); if (NO_ERROR != GetIpAddrTable(addrTable, &bytes, FALSE)) { goto failure; } bytes = 0; if (ERROR_INSUFFICIENT_BUFFER != GetIfTable(NULL, &bytes, FALSE)) { goto failure; } ifTable = (MIB_IFTABLE*)malloc(bytes); if (NO_ERROR != GetIfTable(ifTable, &bytes, FALSE)) { goto failure; } if (aUseLoopback == LOOPBACK_EXCLUDE) { // Only include loopback if there are no non-loopback adapters for (i=0; i<addrTable->dwNumEntries; i++) { MIB_IPADDRROW* addrRow = &(addrTable->table[i]); if (addrRow->dwAddr != loopbackAddr) { includeLoopback = 0; break; } } } for (i=0; i<addrTable->dwNumEntries; i++) { MIB_IPADDRROW* addrRow = &(addrTable->table[i]); MIB_IFROW* ifRow = NULL; OsNetworkAdapter* nif; size_t len; DWORD j = 0; for (; j< ifTable->dwNumEntries; j++) { MIB_IFROW* tmp = &ifTable->table[j]; if (tmp->dwIndex == addrRow->dwIndex) { ifRow = tmp; break; } } if (ifRow == NULL) { fprintf(stderr, "Unable to match ifRow to addrRow\n"); continue; } if ((addrRow->dwAddr == loopbackAddr && includeLoopback == 0) || (addrRow->dwAddr != loopbackAddr && aUseLoopback == LOOPBACK_USE)) { continue; } if (-1 != aContext->iTestInterfaceIndex && index++ != aContext->iTestInterfaceIndex) { continue; } if (addrRow->dwAddr == 0 || addrRow->dwMask == 0) { continue; } nif = (OsNetworkAdapter*)calloc(1, sizeof(*nif)); if (nif == NULL) { goto failure; } nif->iReserved = ifRow->dwType; nif->iAddress = addrRow->dwAddr; nif->iNetMask = addrRow->dwMask; len = ifRow->dwDescrLen; nif->iName = (char*)malloc(len+1); if (NULL == nif->iName) { free(nif); goto failure; } for (j=0; j<len; j++) { nif->iName[j] = (char)ifRow->bDescr[j]; } nif->iName[len] = '\0'; if (head == NULL) { head = nif; } else { TIpAddress subnet = (nif->iAddress & nif->iNetMask); OsNetworkAdapter* p1 = head; OsNetworkAdapter* prev = NULL; while (NULL != p1) { if ((p1->iAddress & p1->iNetMask) == subnet) { while (NULL != p1 && IF_TYPE_ETHERNET_CSMACD == p1->iReserved) { prev = p1; p1 = p1->iNext; } break; } prev = p1; p1 = p1->iNext; } if (NULL == prev) { nif->iNext = head; head = nif; } else { nif->iNext = prev->iNext; prev->iNext = nif; } } } free(addrTable); free(ifTable); *aInterfaces = head; return 0; failure: free(addrTable); free(ifTable); OsNetworkFreeInterfaces(head); return -1; }