Bug #5525
closed
UDPSocket#bind(ip, port) fails under IPv6 => Errno::EAFNOSUPPORT
Added by ibc (Iñaki Baz Castillo) over 12 years ago.
Updated over 12 years ago.
Description
This bug can be reproduced in Ruby 1.8 as well.
The following script shows that UDPSocket#bind fails (Errno::EAFNOSUPPORT) if the given IP is IPv6 (however TCPServer does not fail).
My computer has IPv4 and IPv6 (using Miredo/Teredo). The script:
require "socket"
IPv4 = "192.168.1.12"
IPv6 = "2001:0:53aa:64c:187c:3ecb:2419:d1a6"
PORT = 9999
begin
puts "1) binding in IPv4 TCP..."
s4 = TCPServer.open IPv4, PORT
puts "=> OK"
rescue => e
$stderr.puts "#{e.class}: #{e}"
end
begin
puts "2) binding in IPv6 TCP..."
s4 = TCPServer.open IPv6, PORT
puts "=> OK"
rescue => e
$stderr.puts "#{e.class}: #{e}"
end
begin
puts "3) binding in IPv4 UDP..."
s4 = UDPSocket.new
s4.bind IPv4, PORT
puts "=> OK"
rescue => e
$stderr.puts "#{e.class}: #{e}"
end
begin
puts "4) binding in IPv6 UDP..."
s4 = UDPSocket.new
s4.bind IPv6, PORT
puts "=> OK"
rescue => e
$stderr.puts "#{e.class}: #{e}"
end
Result of the script:
-
binding in IPv4 TCP...
=> OK
-
binding in IPv6 TCP...
=> OK
-
binding in IPv4 UDP...
=> OK
-
binding in IPv6 UDP...
Errno::EAFNOSUPPORT: Address family not supported by protocol - bind(2)
Tested with:
- ruby 1.9.3dev (2011-07-31 revision 32789) [x86_64-linux]
- ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-linux]
- ruby 1.8.7 (2011-06-30 patchlevel 352) [x86_64-linux]
- Category set to lib
- Status changed from Open to Rejected
=begin
You need to create an AF_INET6 UDP socket to bind to a UDP address:
$ ruby -vr 'socket' -e 'u = UDPSocket.new Socket::AF_INET6; u.bind "::1", 9999'
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]
=end
Thanks a lot. But why is it required just for UDP? In TCP I can use "TCPServer.new some_ipv6, port" with no problem. Why UDPSocket requires special handling for IPv6?
- ruby -v changed from ruby 1.9.3dev (2011-07-31 revision 32789) [x86_64-linux] to -
2011/11/1 Iñaki Baz Castillo ibc@aliax.net:
Thanks a lot. But why is it required just for UDP? In TCP I can use "TCPServer.new some_ipv6, port" with no problem. Why UDPSocket requires special handling for IPv6?
The protocol (IPv4/IPv6) is determined at socket creation.
The argument of TCPServer.new(ipv6_address) makes Ruby to find that
the protocol is IPv6.
So TCPServer.new creates a socket for IPv6.
But Ruby cannot find the protocol for UDPSocket.new without arguments.
In that case, UDPScoket.new creates a socket for IPv4.
You meet an error when you use it for IPv6.
Tanaka Akira
Iñaki, perhaps you should open a feature request for new methods, perhaps UDPSocket::bind and UDPSocket::connect which will determine the address family from the address given.
The existing Socket::udp_server_sockets may also help you, but I don't know if it uses bind or connect.
2011/11/2 Eric Hodel drbrain@segment7.net:
Iñaki, perhaps you should open a feature request for new methods, perhaps UDPSocket::bind and UDPSocket::connect which will determine the address family from the address given.
It is possible as follows since Ruby 1.9.2.
Addrinfo.udp("::1", 2000).bind
Addrinfo.udp("127.0.0.1", 2001).bind
Tanaka Akira
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0