From: newsham AT lava DOT net (Tim Newsham) Subject: SIOCGIFCONF 27 May 1998 14:47:26 -0700 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit To: cygwin32-developers AT cygnus DOT com Hi, I noticed today that cygwin supports the SIOCGIFCONF ioctl for sockets (get interface list). The code to do this, however, is a bit hacky. It amounts to doing a gethostname, doing a name lookup (DNS/WINS) on the name, and using the resulting IP address as the interface name for "eth0" (also dummys up a loopback interface "lo0"). This is hacky because it depends on an external database (DNS/WINS) to provide the local IP address, and could potentially return erroneous values. It also only provides support for a single interface. In NT4.0, at least, it is possible to grab the tcp/ip parameters from the registry. Attached below are some routines for doing this. I don't know how portable this is across different versions of NT. The code below hasn't been tested on dual homed machines yet, but I have used the same basic algorithm previously on multi homed machines with success. If cygnus wants to use this method, I can write a get_nt_ifconf function for net.cc that uses these routines. One question: Registry access functions are in -ladvapi32. What would be the implication of using these advapi32 routines from within cygwin? Tim N. ---- iflist.c ---- #define TEST #include #include #define MAXIFACENAMELEN 25 int str2ip4(char *str, int *ipaddr) { int ip1, ip2, ip3, ip4, ip; if(sscanf(str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) return -1; ip = (ip1 << 24) | (ip2 << 16) | (ip3 << 8) | ip4; *(ipaddr) = htonl(ip); return 0; } int iface_getaddr(char *iface, int *ipaddrp, int *netmaskp) { char path[MAXIFACENAMELEN + 100], ipaddrbuf[100], netmaskbuf[100]; HKEY hkey; LONG res; DWORD len, type; if(strlen(iface) >= MAXIFACENAMELEN) return -1; sprintf(path, "SYSTEM\\CurrentControlSet\\Services\\%s\\Parameters\\Tcpip", iface); res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey); if(res != ERROR_SUCCESS) return -1; len = sizeof(ipaddrbuf); res = RegQueryValueEx(hkey, "IPAddress", 0, &type, (LPBYTE)&ipaddrbuf, &len); if(res != ERROR_SUCCESS || type != REG_MULTI_SZ) { RegCloseKey(hkey); return -1; } len = sizeof(netmaskbuf); res = RegQueryValueEx(hkey, "SubnetMask", 0, &type, (LPBYTE)&netmaskbuf, &len); if(res != ERROR_SUCCESS || type != REG_MULTI_SZ) { RegCloseKey(hkey); return -1; } RegCloseKey(hkey); if(str2ip4(ipaddrbuf, ipaddrp) == -1) return -1; if(str2ip4(netmaskbuf, netmaskp) == -1) return -1; /* * XXX should we parse out additional values from the MULTI_SZ? * (iface aliases?) */ return 0; } int iface_enumerate(int (*mapfunc)(char *)) { static char device[] = "\\Device\\"; char *path, *p, bindbuf[MAXIFACENAMELEN * 20]; HKEY hkey; LONG res; DWORD len, type; path = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage"; res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ, &hkey); if(res != ERROR_SUCCESS) return -1; len = sizeof(bindbuf); res = RegQueryValueEx(hkey, "Bind", 0, &type, (LPBYTE)&bindbuf, &len); if(res != ERROR_SUCCESS || type != REG_MULTI_SZ) { RegCloseKey(hkey); return -1; } RegCloseKey(hkey); for(p = bindbuf; *p; p += strlen(p)) { /* strip the "\Device\" part off */ if(strncmp(p, device, sizeof device - 1) == 0) p += sizeof device - 1; if(mapfunc(p) == -1) return -1; } return 0; } #ifdef TEST int printif(char *iface) { int ip, mask; if(iface_getaddr(iface, &ip, &mask) == -1) { printf("error getting addr for %s\n", iface); return -1; } printf("%s: %x mask %x\n", iface, ip, mask); return 0; } int main() { iface_enumerate(printif); return 0; } #endif ---- end iflist.c ----