Mail Archives: cygwin-developers/1998/05/27/14:47:26
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 <windows.h>
#include <string.h>
#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 ----
- Raw text -