Fwd: Finding ip address for eth0?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Fwd: Finding ip address for eth0?

Ian Piumarta
 
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;
}