Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Socket.getifaddrs returns incorrect interface list #2137
With ethernet and wifi interfaces disconnected, I expect to see 5 interfaces from Socket.getifaddrs.
Interfaces listed: 1 each for physcial interfaces eth0, wlan0, and 3 for lo...
As expected only one (lo) has an IPv4 address...
Which can be retrieved...
Running jruby-head, Socket.getifaddrs returns incorrect results:
Incorrect number of interfaces...
Interfaces listed: 4 for lo, none for wlan0 and eth0...
It seems to think 2 interfaces have IPv4 addresses...
One is 127.0.0.1 as expected...
The other isn't actually...
This one is pretty straightforward and may be easy for a new dev (familiar with Java/JDK) to fix.
The logic is in RubySocket.getifaddrs, and basically just uses java.net.NetworkInterfaces. If the count is different, it may not be something we can fix, but the Addrinfos we create can probably be improved.
Ruby's Socket.getifaddrs lists addresses for all interfaces (UP or DOWN), including AF_PACKET (layer 2), AF_INET (layer 3), AF_INET6 (layer 3) addresses (and probably others if present).
java.net.NetworkInterfaces only lists layer 3 addresses and only for interfaces that are UP.
In the absence of a layer 2 interface address, JRuby's Socket.getifaddrs returns 2 Ifaddrs for each
That's close enough as long as all interfaces are UP and have a single IPv4 or IPv6 address. However, when interfaces are DOWN they are not listed, and interfaces with multiple layer 3 addresses (eg; IPv4 and IPv6) create multiple fake layer 2 Ifaddrs.
It seems that perfect emulation of Ruby's Socket.getifaddrs would be quite a bit of work. Even then it would be emulation of an incomplete API: the AF_PACKET Ifaddrs are not terribly useful - there doesn't seem to be a way to get at layer 2 info except by parsing the inspect. But if somebody has the time and inclination :-) .
So, in the meantime, what to do...
My use case is getting all interface IPv4 addresses on a system. My current ugly workaround is to rescue and ignore the exception that occurs when getting an IP address from a fake link layer 2 Ifaddr that still claims to be IPv4 but returns a broken Addrinfo...
@interfaces ||= Socket.getifaddrs.select do |intf| if intf.addr.ipv4? && ! intf.addr.ipv4_loopback? begin intf.addr.ip_address true rescue SocketError false end end end
Options I see for a quick 'fix' are:
These I can do with my rusty Java/JDK skills. Preferences ?
Discovered uses for fake link layer Ifaddr/Addrinfo - going with # 2.
I do not see them in the FFI platform stuff and my attempts to add them there for the build process have failed so far. How do I add them there ? Should I ?