Listing all IP addresses on an multihomed system

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?

···

On 7/18/07, Daniel Berger <djberg96@gmail.com> wrote:

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

In article <1184772029.010310.165980@j4g2000prf.googlegroups.com>,
  Daniel Berger <djberg96@gmail.com> writes:

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.

Dan

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.

···

--
. Douglas Wells . Connection Technologies .
. Internet: -sp9804- -at - contek.com- .

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

···

On 7/18/07, Francis Cianfrocca <garbagecat10@gmail.com> wrote:

On 7/18/07, Daniel Berger <djberg96@gmail.com> wrote:
>
> 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?

<snip>

Indeed, there's an example in Stevens' "Unix Network Programming, Vol.
1" staring at me now. :slight_smile: 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

···

On Jul 18, 2:10 pm, s...@signature.invalid (Douglas Wells) wrote:

In article <1184772029.010310.165...@j4g2000prf.googlegroups.com>,
  Daniel Berger <djber...@gmail.com> writes:

> 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.

Sorry, it's the "eth0" and "eth1" that made me think you were doing this for
Linux.

···

On 7/18/07, Daniel Berger <djberg96@gmail.com> wrote:

> > 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.
> >

In article <1184796959.469021.157500@g12g2000prg.googlegroups.com>, Daniel Berger <djberg96@gmail.com> writes:

> In article <1184772029.010310.165...@j4g2000prf.googlegroups.com>,
> Daniel Berger <djber...@gmail.com> writes:
>
> > 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.
>
> 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.

Indeed, there's an example in Stevens' "Unix Network Programming, Vol.
1" staring at me now. :slight_smile: 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

···

On Jul 18, 2:10 pm, s...@signature.invalid (Douglas Wells) wrote:

--
. Douglas Wells . Connection Technologies .
. Internet: -sp9804- -at - contek.com- .

Douglas Wells wrote:

In article <1184796959.469021.157500@g12g2000prg.googlegroups.com>, Daniel Berger <djberg96@gmail.com> writes:

In article <1184772029.010310.165...@j4g2000prf.googlegroups.com>,
  Daniel Berger <djber...@gmail.com> writes:

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.

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.

Indeed, there's an example in Stevens' "Unix Network Programming, Vol.
1" staring at me now. :slight_smile: 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.

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

···

On Jul 18, 2:10 pm, s...@signature.invalid (Douglas Wells) wrote: