Forum: Ruby Listing all IP addresses on an multihomed system

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-07-18 17:26
(Received via mailing list)
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
481b8eedcc884289756246e12d1869c1?d=identicon&s=25 Francis Cianfrocca (blackhedd)
on 2007-07-18 17:36
(Received via mailing list)
On 7/18/07, Daniel Berger <djberg96@gmail.com> wrote:
> #include <unistd.h>
>
>       printf("gethostbyname failed\n");
> }
>
> Dan
>
>
>

Since you're obviously using Linux, how about just parsing the output of
ethtool?
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-07-18 19:15
(Received via mailing list)
On 7/18/07, Francis Cianfrocca <garbagecat10@gmail.com> wrote:
> >
> >    char ip[BUF];
> >    if(!h){
> >    return 0;
> > 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
B351db35040dcc3be001dd51ba798a95?d=identicon&s=25 unknown (Guest)
on 2007-07-18 22:19
(Received via mailing list)
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.
481b8eedcc884289756246e12d1869c1?d=identicon&s=25 Francis Cianfrocca (blackhedd)
on 2007-07-18 22:40
(Received via mailing list)
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.
> > >



Sorry, it's the "eth0" and "eth1" that made me think you were doing this
for
Linux.
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-07-19 00:16
(Received via mailing list)
On Jul 18, 2:10 pm, s...@signature.invalid (Douglas Wells) wrote:
> > But, at least one user has reported that he has eth0 configured with a
> 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
B351db35040dcc3be001dd51ba798a95?d=identicon&s=25 unknown (Guest)
on 2007-07-19 02:18
(Received via mailing list)
In article <1184796959.469021.157500@g12g2000prg.googlegroups.com>,
Daniel Berger <djberg96@gmail.com> writes:
> >
> 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
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-07-19 04:43
(Received via mailing list)
Douglas Wells wrote:
>>> Most UNIX and Linux systems provide a mechanism to access this
>>
> 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
This topic is locked and can not be replied to.