|
On Aug 26, 2009, at 3:03 PM, Bert Freudenberg wrote:
>> I thought Bert said that there is a way to enumerate the IP
>> addresses of the interfaces?
>
> I thought it did, but I never had to use it yet ... grmph, I'm sure
> there is a way. Ian?
getaddrinfo gives you a list of addresses that you can use to contact
the given host, filtered by service name, protocol, etc. If the host
is local and you can contact the service on some internal interface,
that interface will show up in the list even though remote machines
will fail to connect to it. The ipv6 prims are based on getaddrinfo
(and getnameinfo, which is even less interesting).
A bit of digging reveals ioctl SIOCGIFCONF is known to be broken, but
getifaddrs() does the same job properly (and with a nicer API).
Here's an updated version of that program which could trivially turn
into a primitive for enumerating interface addresses.
Cheers,
Ian
#include <stdio.h>
#include <ifaddrs.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef s6_addr16
# define s6_addr16 __u6_addr.__u6_addr16
#endif
int main()
{
struct ifaddrs *ifap, *ifaddrs;
if (getifaddrs(&ifaddrs) < 0) {
perror("getifaddrs");
return -1;
}
for (ifap= ifaddrs; ifap; ifap= ifap->ifa_next) {
switch (ifap->ifa_addr->sa_family) {
case AF_INET: {
printf("%s\t%s\n", ifap->ifa_name,
inet_ntoa(((struct sockaddr_in *)ifap->ifa_addr)->sin_addr));
}
case AF_INET6: {
struct sockaddr_in6 *sin6= (struct sockaddr_in6 *)ifap->ifa_addr;
struct in6_addr *in6= &sin6->sin6_addr;
printf("%s\t%x:%x:%x:%x:%x:%x:%x:%x\n", ifap->ifa_name,
in6->s6_addr16[0], in6->s6_addr16[1], in6->s6_addr16[2], in6-
>s6_addr16[3],
in6->s6_addr16[4], in6->s6_addr16[5], in6->s6_addr16[6], in6-
>s6_addr16[7]);
break;
}
default:
break;
}
}
freeifaddrs(ifaddrs);
return 0;
}
|