/* Enumerates the IP addresses in the system using SIOCGIFCONF, returning * the count to you in *pcAddresses. It also returns to you the struct ifconf * used by the call to ioctl, so that you may process the addresses further. * Free ifc->ifc_buf using HeapFree. * Returns NO_ERROR on success, something else on failure. */ static DWORD enumIPAddresses(PDWORD pcAddresses, struct ifconf *ifc) { DWORD ret; int fd; fd = socket(PF_INET, SOCK_DGRAM, 0); if (fd != -1) { int ioctlRet = 0; DWORD guessedNumAddresses = 0, numAddresses = 0; caddr_t ifPtr; int lastlen; ret = NO_ERROR; ifc->ifc_len = 0; ifc->ifc_buf = NULL; /* there is no way to know the interface count beforehand, so we need to loop again and again upping our max each time until returned is constant across 2 calls */ do { lastlen = ifc->ifc_len; HeapFree(GetProcessHeap(), 0, ifc->ifc_buf); if (guessedNumAddresses == 0) guessedNumAddresses = INITIAL_INTERFACES_ASSUMED; else guessedNumAddresses *= 2; ifc->ifc_len = sizeof(struct ifreq) * guessedNumAddresses; ifc->ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc->ifc_len); ioctlRet = ioctl(fd, SIOCGIFCONF, ifc); } while ((ioctlRet == 0) && (ifc->ifc_len != lastlen)); if (ioctlRet == 0) { ifPtr = ifc->ifc_buf; while (ifPtr && ifPtr < ifc->ifc_buf + ifc->ifc_len) { struct ifreq *ifr = (struct ifreq *)ifPtr; if (ifr->ifr_addr.sa_family == AF_INET) numAddresses++; ifPtr += ifreq_len((struct ifreq *)ifPtr); } } else ret = ERROR_INVALID_PARAMETER; /* FIXME: map from errno to Win32 */ if (!ret) *pcAddresses = numAddresses; else { HeapFree(GetProcessHeap(), 0, ifc->ifc_buf); ifc->ifc_buf = NULL; } close(fd); } else ret = ERROR_NO_SYSTEM_RESOURCES; return ret; }
DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags) { DWORD ret; if (!ppIpAddrTable) ret = ERROR_INVALID_PARAMETER; else { DWORD numAddresses = 0; struct ifconf ifc; ret = enumIPAddresses(&numAddresses, &ifc); if (!ret) { DWORD size = sizeof(MIB_IPADDRTABLE); if (numAddresses > 1) size += (numAddresses - 1) * sizeof(MIB_IPADDRROW); *ppIpAddrTable = HeapAlloc(heap, flags, size); if (*ppIpAddrTable) { DWORD i = 0, bcast; caddr_t ifPtr; ret = NO_ERROR; (*ppIpAddrTable)->dwNumEntries = numAddresses; ifPtr = ifc.ifc_buf; while (!ret && ifPtr && ifPtr < ifc.ifc_buf + ifc.ifc_len) { struct ifreq *ifr = (struct ifreq *)ifPtr; ifPtr += ifreq_len(ifr); if (ifr->ifr_addr.sa_family != AF_INET) continue; ret = getInterfaceIndexByName(ifr->ifr_name, &(*ppIpAddrTable)->table[i].dwIndex); memcpy(&(*ppIpAddrTable)->table[i].dwAddr, ifr->ifr_addr.sa_data + 2, sizeof(DWORD)); (*ppIpAddrTable)->table[i].dwMask = getInterfaceMaskByName(ifr->ifr_name); /* the dwBCastAddr member isn't the broadcast address, it indicates * whether the interface uses the 1's broadcast address (1) or the * 0's broadcast address (0). */ bcast = getInterfaceBCastAddrByName(ifr->ifr_name); (*ppIpAddrTable)->table[i].dwBCastAddr = (bcast & (*ppIpAddrTable)->table[i].dwMask) ? 1 : 0; /* FIXME: hardcoded reasm size, not sure where to get it */ (*ppIpAddrTable)->table[i].dwReasmSize = 65535; (*ppIpAddrTable)->table[i].unused1 = 0; (*ppIpAddrTable)->table[i].wType = 0; i++; } } else ret = ERROR_OUTOFMEMORY; HeapFree(GetProcessHeap(), 0, ifc.ifc_buf); } } return ret; }
static UCHAR NETBIOS_Enum(PNCB ncb) { #ifdef HAVE_NET_IF_H int sd; struct ifconf ifc; int i; int lastlen, numAddresses = 2; int ioctlRet = 0; caddr_t ifPtr; #endif LANA_ENUM *lanas = NULL; if (ncb) { lanas = (PLANA_ENUM) ncb->ncb_buffer; lanas->length = 0; } TRACE("NCBENUM\n"); #ifdef HAVE_NET_IF_H /* BSD 4.4 defines the size of an ifreq to be * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len * However, under earlier systems, sa_len isn't present, so * the size is just sizeof(struct ifreq) */ sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (sd < 0) return NRC_OPENERROR; ifc.ifc_len = 0; ifc.ifc_buf = NULL; do { lastlen = ifc.ifc_len; HeapFree (GetProcessHeap (), 0, ifc.ifc_buf); numAddresses *= 2; ifc.ifc_len = sizeof (struct ifreq) * numAddresses; ifc.ifc_buf = HeapAlloc (GetProcessHeap (), 0, ifc.ifc_len); if (!ifc.ifc_buf) { close (sd); return NRC_OPENERROR; } ioctlRet = ioctl (sd, SIOCGIFCONF, (char *)&ifc); } while ((ioctlRet == 0) && (ifc.ifc_len != lastlen)); if (ioctlRet) { HeapFree (GetProcessHeap (), 0, ifc.ifc_buf); close (sd); return NRC_OPENERROR; } /* loop through the interfaces, looking for a valid one */ /* n = ifc.ifc_len; */ ifPtr = ifc.ifc_buf; i = 0; while (ifPtr && (ifPtr < (ifc.ifc_buf + ifc.ifc_len))) { unsigned char *a = NETBIOS_Adapter[i].address; struct ifreq ifr, *ifrp; ifrp = (struct ifreq *)ifPtr; ifPtr += ifreq_len ((struct ifreq *)ifPtr); i++; if (ifrp->ifr_addr.sa_family != AF_INET) continue; strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* try to get the address for this interface */ if(get_hw_address(sd, &ifr, a)==0) { /* make sure it's not blank */ /* if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) continue; */ TRACE("Found valid adapter %d at %02x:%02x:%02x:%02x:%02x:%02x\n", i, a[0],a[1],a[2],a[3],a[4],a[5]); if (a[0] || a[1] || a[2] || a[3] || a[4] || a[5]) NETBIOS_Adapter[i - 1].valid = TRUE; if (lanas) { lanas->lana[lanas->length] = i - 1; lanas->length++; } } } close(sd); HeapFree (GetProcessHeap (), 0, ifc.ifc_buf); #endif /* HAVE_NET_IF_H */ EnumDone = TRUE; return NRC_GOODRET; }