delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-developers/1998/05/27/14:47:26

From: newsham AT lava DOT net (Tim Newsham)
Subject: SIOCGIFCONF
27 May 1998 14:47:26 -0700 :
Message-ID: <m0yeneb-001170C.cygnus.cygwin32.developers@malasada.lava.net>
Mime-Version: 1.0
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 <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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019