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; }
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 OsNetworkSocketMulticastAddMembership(THandle aHandle, TIpAddress aInterface, TIpAddress aAddress) { if ( OsNetworkHandle_IsInterrupted(aHandle) ) return -1; struct ip_mreq m = { .imr_multiaddr.s_addr = aAddress, .imr_interface.s_addr = aInterface }; return lwip_setsockopt ( HANDLE_TO_SOCKET(aHandle), IPPROTO_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m) ); } int32_t OsNetworkSocketMulticastDropMembership(THandle aHandle, TIpAddress aInterface, TIpAddress aAddress) { if ( OsNetworkHandle_IsInterrupted(aHandle) ) return -1; struct ip_mreq m = { .imr_multiaddr.s_addr = aAddress, .imr_interface.s_addr = aInterface }; return lwip_setsockopt ( HANDLE_TO_SOCKET(aHandle), IPPROTO_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)); } int32_t OsNetworkListAdapters(OsNetworkAdapter** aAdapters, uint32_t aUseLoopback) { struct netif* n; OsNetworkAdapter* start = NULL; OsNetworkAdapter* end = NULL; for ( n = netif_list ; n != NULL ; n = n->next ) { if ( aUseLoopback ) if ( n->name[0] != 'l' || n->name[1] != 'o' ) continue; if ( !netif_is_up(n) ) continue; OsNetworkAdapter *a = (OsNetworkAdapter*) malloc(sizeof(OsNetworkAdapter)); if ( a == NULL ) { OsNetworkFreeInterfaces(start); return -1; } // Stash lwip interface name (2 chars, no termination) in iReserved char* name_reserved = (char*) &(a->iReserved); name_reserved[0] = n->name[0]; name_reserved[1] = n->name[1]; name_reserved[2] = '\0'; // Copy info a->iAddress = (TIpAddress) n->ip_addr.addr; a->iNetMask = (TIpAddress) n->netmask.addr; a->iName = name_reserved; a->iNext = NULL; // Push on to end of list. We reverse netif_list as loopback is first. if ( start == NULL ) start = end = a; else { end->iNext = a; end = a; } } *aAdapters = start; return 0; } void OsNetworkFreeInterfaces(OsNetworkAdapter* aAdapters) { while ( aAdapters != NULL ) { OsNetworkAdapter* n = aAdapters; aAdapters = aAdapters->iNext; free(n); } } void OsNetworkSetInterfaceChangedObserver(InterfaceListChanged aCallback, void* aArg) { }