views:

60

answers:

4

I think there is no way to enumerate each network interface on my system and their assigned IP using just sockets, is this correct?

I mean, in linux this could be:

eth0: 192.168.1.5 wlan0: 192.168.0.5 lo: 127.0.0.1

I dont care interface names, just the IPs assigned.

I recall to have done this in the past in Windows, using winapi (though I don't remember how) But is there a method to do this in a portable way?

Thanks in advance!

A: 

Use gethostname() to retreive the machine's local DNS name, and then pass that name to gethostbyname() to get its local IP addresses.

If the OS supports IPv6, then look at the getaddrinfo() function instead of gethostbyname().

Remy Lebeau - TeamB
here I've manually edited the hostname to resolve to my static LAN IP address (lets say 192.168.0.2) but how exactly this behaves on another systems? I mean.. does the hostname resolve to 127.0.0.1 or to what IP of which interface by default?
conejoroy
Calling `gethostbyname()` with an IP address as the hostname will not work, AFAIK. You could use `gethostbyaddr()` instead, but that will return a `hostent` structure that contains only the IP you originally specified. To enumerate the available IPs, you have to use the machine's actual hostname. Otherwise, you will have to use OS-specific APIs to enumerate the network interfaces directly (on Windows, look at `GetAdapterAddresses()` and related functions).
Remy Lebeau - TeamB
A: 

Take a look at the ioctl() function. If I recall correctly, you can use it to obtain information on any interface, as well as obtaining the available interfaces.

I don't remember the correct invocation though. As with fcntl(), it takes a request argument plus variable parameters that determine its behaviour.

Santiago Lezica
A: 

On Linux, that information is accessed through NETLINK sockets. See the manual pages for libnetlink(3), netlink(7) and rtnetlink(7).

A somewhat more portable way of doing this is via ioctl()'s. SIOCGIFCONF is the one you want. See the manual page for netdevice(7). This one works on some other *nixes.

ninjalj
+3  A: 

Here's a good start:

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <stdio.h>
void
print_sockaddr(struct sockaddr* addr,const char *name)
{
    char addrbuf[128] ;

    addrbuf[0] = 0;
    if(addr->sa_family == AF_UNSPEC)
        return;
    switch(addr->sa_family) {
        case AF_INET:
            inet_ntop(addr->sa_family,&((struct sockaddr_in*)addr)->sin_addr,addrbuf,sizeof(addrbuf));
            break;
        case AF_INET6:
            inet_ntop(addr->sa_family,&((struct sockaddr_in6*)addr)->sin6_addr,addrbuf,sizeof(addrbuf));
            break;
        default:
            sprintf(addrbuf,"Unknown (%d)",(int)addr->sa_family);
            break;

    }
    printf("%-16s %s\n",name,addrbuf);
}

void
print_ifaddr(struct ifaddrs *addr)
{
    char addrbuf[128] ;

    addrbuf[0] = 0;
    printf("%-16s %s\n","Name",addr->ifa_name);
    if(addr->ifa_addr != NULL)
        print_sockaddr(addr->ifa_addr,"Address");
    if(addr->ifa_netmask != NULL)
        print_sockaddr(addr->ifa_netmask,"Netmask");
    if(addr->ifa_broadaddr != NULL)
        print_sockaddr(addr->ifa_broadaddr,"Broadcast addr.");
    if(addr->ifa_dstaddr != NULL)
        print_sockaddr(addr->ifa_dstaddr,"Peer addr.");
    puts("");
}

int main(int argc,char *argv[])
{
    struct ifaddrs *addrs,*tmp;

    if(getifaddrs(&addrs) != 0) {
        perror("getifaddrs");
        return 1;
    }
    for(tmp = addrs; tmp ; tmp = tmp->ifa_next) {
        print_ifaddr(tmp);
    }

    freeifaddrs(addrs);

    return 0;
}
nos
+1. didn't know about getifaddrs()/freeifaddrs()
ninjalj
Excelent answer! +1
Santiago Lezica
this is just what I needed, thanks!! but it only works on linux, am I right? what cuold be the the winapi equivalent?
conejoroy
`GetAdapterAddresses()` and related functions.
Remy Lebeau - TeamB