Project

General

Profile

Actions

Feature #8368

closed

Socket.getifaddrs

Added by akr (Akira Tanaka) over 9 years ago. Updated over 9 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
[ruby-core:54777]

Description

I'd like to add a method: Socket.getifaddrs.

This method is a wrapper to getifaddrs() function.
The result is an array of instances of Socket::Ifaddr class as follows.

% ./ruby -rpp -rsocket -e 'pp Socket.getifaddrs'
[#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 [PACKET protocol:0 lo hatype:772 HOST hwaddr:00:00:00:00:00:00]>,
#<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 [PACKET protocol:0 eth0 hatype:1 HOST hwaddr:00:16:3e:95:88:bb] broadcast:[PACKET protocol:0 eth0 hatype:1 HOST hwaddr:ff:ff:ff:ff:ff:ff]>,
#<Socket::Ifaddr sit0 NOARP [PACKET protocol:0 sit0 hatype:776 HOST hwaddr:00:00:00:00]>,
#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 [127.0.0.1] netmask:[255.0.0.0]>,
#<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 [221.186.184.67] netmask:[255.255.255.240] broadcast:[221.186.184.79]>,
#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 [::1] netmask:[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]>,
#<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 [fe80::216:3eff:fe95:88bb%eth0] netmask:[ffff:ffff:ffff:ffff::]>]

This method can be used to choose multicast-enabled interfaces.
Multicast applications needs to identify a such interface to sending a multicast datagram.

% ./ruby -rpp -rsocket -e '
pp Socket.getifaddrs.reject {|ifaddr|
!ifaddr.addr.ip? || (ifaddr.flags & Socket::IFF_MULTICAST == 0)
}.map {|ifaddr| [ifaddr.name, ifaddr.ifindex, ifaddr.addr] }'
[["eth0", 2, #<Addrinfo: 221.186.184.67>],
["eth0", 2, #<Addrinfo: fe80::216:3eff:fe95:88bb%eth0>]]

This method can be used to obtain broadcast addresses to send a broadcast
messages. (use case: [ruby-talk:329921])

Also, the broadcast addresses can be used to receive broadcast messages.
(Programming UNIX Sockets in C: 4.12. How can I write a multi-homed server?
http://www.faqs.org/faqs/unix-faq/socket/ )

getifaddrs() is not standardized but many platforms have.
BSDI, FreeBSD, NetBSD, OpenBSD, DragonFly, MirOS, GNU/Linux, MacOS X, SunOS 5.11 (OpenIndiana), Cygwin 1.7.15

From Gnulib document, getifaddrs() is not exist on
AIX 5.1, HP-UX 11, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x, mingw, MSVC 9, Interix 3.5, BeOS.
http://www.gnu.org/software/gnulib/manual/html_node/getifaddrs.html

I implemented new Socket::Ifaddr class for return value of Socket.getifaddrs,
instead of constructing the result from currentn data structures such as Array.
This choice make us possible to implement Socket::Ifaddr#inspect to show flags as its names (UP,...).
Also, struct getifaddrs contains Address-specific data, ifa_data which may be extended by platforms.
When we find a way to extract some data from ifa_data, we can add a method for that.

Socket::Ifaddr is different from Socket::Interface by
http://bugs.ruby-lang.org/issues/8075 .
They have no one-to-one mapping.
For example, Socket.getifaddrs returns two or more elements for one interface.


Files

getifaddrs.patch (31.6 KB) getifaddrs.patch akr (Akira Tanaka), 05/04/2013 04:57 PM
getifaddrs2.patch (32.7 KB) getifaddrs2.patch akr (Akira Tanaka), 05/06/2013 08:33 PM

Updated by naruse (Yui NARUSE) over 9 years ago

  • Target version set to 2.1.0

I'm for this method.

Updated by judofyr (Magnus Holm) over 9 years ago

Shouldn't this be moved to CommonRuby?

Updated by naruse (Yui NARUSE) over 9 years ago

judofyr (Magnus Holm) wrote:

Shouldn't this be moved to CommonRuby?

There's no such consensus yet, especially bundled libraries.

Updated by akr (Akira Tanaka) over 9 years ago

I updated the patch to fix compile error on environments which has no getifaddrs().
Also I refined the result of Socket::Ifaddrs#inspect.

% ./ruby -rsocket -rpp -e 'pp Socket.getifaddrs'
[#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 PACKET[protocol=0 lo hatype=772 HOST hwaddr=00:00:00:00:00:00]>,
#<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=00:16:3e:95:88:bb] broadcast=PACKET[protocol=0 eth0 hatype=1 HOST hwaddr=ff:ff:ff:ff:ff:ff]>,
#<Socket::Ifaddr sit0 NOARP PACKET[protocol=0 sit0 hatype=776 HOST hwaddr=00:00:00:00]>,
#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 127.0.0.1 netmask=255.0.0.0>,
#<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 221.186.184.67 netmask=255.255.255.240 broadcast=221.186.184.79>,
#<Socket::Ifaddr lo UP,LOOPBACK,RUNNING,0x10000 ::1 netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>,
#<Socket::Ifaddr eth0 UP,BROADCAST,RUNNING,MULTICAST,0x10000 fe80::216:3eff:fe95:88bb%eth0 netmask=ffff:ffff:ffff:ffff::>]

Actions #5

Updated by akr (Akira Tanaka) over 9 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r40639.
Akira, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


Updated by akr (Akira Tanaka) over 9 years ago

It seems no one against for this method and naruse-san (the release manager of Ruby 2.1.0) supported.
I added Socket.getifaddrs.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0