Project

General

Profile

Bug #5525

UDPSocket#bind(ip, port) fails under IPv6 => Errno::EAFNOSUPPORT

Added by ibc (Iñaki Baz Castillo) over 7 years ago. Updated over 7 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
-
Backport:
[ruby-core:40562]

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:


1) binding in IPv4 TCP...
=> OK

2) binding in IPv6 TCP...
=> OK

3) binding in IPv4 UDP...
=> OK

4) 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]

History

Updated by drbrain (Eric Hodel) over 7 years ago

  • 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

Updated by ibc (Iñaki Baz Castillo) over 7 years ago

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?

Updated by akr (Akira Tanaka) over 7 years ago

  • 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

Updated by drbrain (Eric Hodel) over 7 years ago

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.

Updated by akr (Akira Tanaka) over 7 years ago

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