Listing all IP addresses on an multihomed system

D

Daniel Berger

Hi all,

I'm wondering if there's a way to list all IP addresses on a
multihomed system using Ruby's Socket API. I actually want this for
the sys-host library (at http://www.rubyforge.org/projects/sysutils).
It's C, but I figure I can reverse engineer the Ruby code back to C.

Here's the equivalent of what I'm currently doing (in C):

#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <arpa/inet.h>

#define BUF 256

int main(){
struct hostent* h;
char hostname[BUF];
char ip[BUF];

if(gethostname(hostname, BUF) != 0){
printf("gethostbyname failed\n");
return -1;
}

printf("Hostname: %s\n", hostname);

h = gethostbyname(hostname);

if(!h){
printf("gethostbyname failed\n");
return -1;
}

while(*h->h_addr_list){
printf("Addr: %s\n", inet_ntop(h->h_addrtype, *h->h_addr_list,
ip, BUF));
*h->h_addr_list++;
}

return 0;
}

But, at least one user has reported that he has eth0 configured with a
LAN IP and eth1 that has 5 attached IP addresses. The above code
doesn't pick them up.

Is there a pure Ruby solution? Is it just a matter of
Socket.getaddrinfo(Socket.gethostname, 80)? Or, does anyone happen to
know the C solution?

Thanks,

Dan
 
D

Daniel Berger

Hi all,

I'm wondering if there's a way to list all IP addresses on a
multihomed system using Ruby's Socket API. I actually want this for
the sys-host library (at http://www.rubyforge.org/projects/sysutils).
It's C, but I figure I can reverse engineer the Ruby code back to C.

Here's the equivalent of what I'm currently doing (in C):

#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <arpa/inet.h>

#define BUF 256

int main(){
struct hostent* h;
char hostname[BUF];
char ip[BUF];

if(gethostname(hostname, BUF) != 0){
printf("gethostbyname failed\n");
return -1;
}

printf("Hostname: %s\n", hostname);

h = gethostbyname(hostname);

if(!h){
printf("gethostbyname failed\n");
return -1;
}

while(*h->h_addr_list){
printf("Addr: %s\n", inet_ntop(h->h_addrtype, *h->h_addr_list,
ip, BUF));
*h->h_addr_list++;
}

return 0;
}

But, at least one user has reported that he has eth0 configured with a
LAN IP and eth1 that has 5 attached IP addresses. The above code
doesn't pick them up.

Is there a pure Ruby solution? Is it just a matter of
Socket.getaddrinfo(Socket.gethostname, 80)? Or, does anyone happen to
know the C solution?

Thanks,

Dan

Since you're obviously using Linux, how about just parsing the output of
ethtool?

Eh? No, the C code above works just fine on Solaris (with -lsocket and
-lnsl added). Besides, I need the code to be as cross platform as
possible (for Unix flavors, that is - I use a different approach on MS
Windows). So, parsing system calls is out of the question.

Regards,

Dan
 
D

Douglas Wells

Daniel Berger said:
I'm wondering if there's a way to list all IP addresses on a
multihomed system using Ruby's Socket API. I actually want this for
the sys-host library (at http://www.rubyforge.org/projects/sysutils).
It's C, but I figure I can reverse engineer the Ruby code back to C.

[ extraneous program based on gethostbyname elided]

But, at least one user has reported that he has eth0 configured with a
LAN IP and eth1 that has 5 attached IP addresses. The above code
doesn't pick them up.

As your user has reported, your C-based program does not do what
you desire. gethostbyname (and its friends) can only deal with
DNS-based information. Information about multi-hosting is not
stored in the DNS. In fact, it is actually system dependent and is
only stored in the local kernel's network tables.

Most UNIX and Linux systems provide a mechanism to access this
information via some variant of the ioctl(2) call with command
SIOCGIFCONF. BSDi and FreeBSD have a set of subroutines (originally
based on the ioctl) called getifaddrs. MS Windows WinSock2 uses
the command SIO_GET_INTERFACE_LIST with the WSAIoctl procedure.
You will need to look in the documentation for your system (and
probably do a net search for programming examples) to see how it
works.
Is there a pure Ruby solution? Is it just a matter of
Socket.getaddrinfo(Socket.gethostname, 80)? Or, does anyone happen to
know the C solution?

I'm fairly certain that this could be done in ruby via IO.ioctl
and pack/unpack on UNIX/Linux, but I'm also fairly certain that
this would be a real PITA. I don't have any familiarity with the
Win32-specific solutions.

Good luck, - dmw

Notes:
- DNS = Domain Name System
- The ioctl commands evolve over time and over various systems.
The ones I note there may well be deprecated, obsolete, and/or
non-existent on your system.
 
D

Daniel Berger

Daniel Berger said:
I'm wondering if there's a way to list all IP addresses on a
multihomed system using Ruby's Socket API. I actually want this for
the sys-host library (athttp://www.rubyforge.org/projects/sysutils).
It's C, but I figure I can reverse engineer the Ruby code back to C.
[ extraneous program based on gethostbyname elided]
But, at least one user has reported that he has eth0 configured with a
LAN IP and eth1 that has 5 attached IP addresses. The above code
doesn't pick them up.

As your user has reported, your C-based program does not do what
you desire. gethostbyname (and its friends) can only deal with
DNS-based information. Information about multi-hosting is not
stored in the DNS. In fact, it is actually system dependent and is
only stored in the local kernel's network tables.

Most UNIX and Linux systems provide a mechanism to access this
information via some variant of the ioctl(2) call with command
SIOCGIFCONF. BSDi and FreeBSD have a set of subroutines (originally
based on the ioctl) called getifaddrs. MS Windows WinSock2 uses
the command SIO_GET_INTERFACE_LIST with the WSAIoctl procedure.
You will need to look in the documentation for your system (and
probably do a net search for programming examples) to see how it
works.

<snip>

Indeed, there's an example in Stevens' "Unix Network Programming, Vol.
1" staring at me now. :) Many thanks for the lead. I should be ok from
here (I hope).

I'll see if I can come up with a pure Ruby solution and post it here
eventually.

Regards,

Dan
 
D

Douglas Wells

Indeed, there's an example in Stevens' "Unix Network Programming, Vol.
1" staring at me now. :) Many thanks for the lead. I should be ok from
here (I hope).

I'll see if I can come up with a pure Ruby solution and post it here
eventually.

Dan

Please let us know if you do. I managed to find time to take a
slightly deeper look, and the problem that I found is that SIOCGIFCONF
requires that you place an actual virtual address in the additional
argument to ioctl. I doubt that there is a "pure Ruby" way of
doing that. You'll can probably do ok getting the addresses
associated with an interface name, however.

- dmw
 
D

Daniel Berger

Douglas said:
Please let us know if you do. I managed to find time to take a
slightly deeper look, and the problem that I found is that SIOCGIFCONF
requires that you place an actual virtual address in the additional
argument to ioctl. I doubt that there is a "pure Ruby" way of
doing that. You'll can probably do ok getting the addresses
associated with an interface name, however.

It also appears that you can use sysctl() + NET_RT_IFLIST. It's easier,
but less portable. I'll probably just suck it up and use the more
portable version.

Regards,

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top