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
On 7/18/07, Daniel B. [email protected] wrote:
#include <unistd.h>
printf("gethostbyname failed\n");
}
Dan
Since you’re obviously using Linux, how about just parsing the output of
ethtool?
On 7/18/07, Francis C. [email protected] 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
In article [email protected],
Daniel B. [email protected] 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.
On 7/18/07, Daniel B. [email protected] 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.
On Jul 18, 2:10 pm, [email protected] (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.
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
In article [email protected],
Daniel B. [email protected] 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.