Enumerating each IP address assigned to network interfaces
I think there is no way to enumerate each network interface on my system and their assigned IP address 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 don't care about interface names, just the IP addresses assigned.
I recall to have done this in the past in Windows, using Win32 (though I don't remember how). But is there a method to do this in a portable way?
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;
}
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()
.
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.
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.
精彩评论