summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--lib/resolv.rb92
2 files changed, 82 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f1c3d0caf..69ca81ffd8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+Thu Feb 11 09:49:31 2010 Tanaka Akira <akr@fsij.org>
+
+ * lib/resolv.rb: fix [ruby-core:28144].
+ (Resolv::DNS#make_requester): pass nameserver_port to
+ UnconnectedUDP.new.
+ (Resolv::DNS.bind_random_port): change the is_ipv6 argument to
+ bind_host.
+ (Resolv::DNS::Requester#initialize): change instance variable to
+ store multiple sockets.
+ (Resolv::DNS::Requester#request): pass readable sockets to
+ recv_reply.
+ (Resolv::DNS::Requester#close): close all sockets.
+ (Resolv::DNS::Requester::UnconnectedUDP#initialize): allocate
+ a socket for each address family of name servers.
+ (Resolv::DNS::Requester::UnconnectedUDP#recv_reply): read from the
+ passwd readable socket.
+ (Resolv::DNS::Requester::UnconnectedUDP#sender): use appropriate
+ socket for the target nameserver.
+ (Resolv::DNS::Requester::ConnectedUDP): follow the instance variable
+ change.
+ (Resolv::DNS::Requester::TCP#sender): ditto.
+ (Resolv::DNS::Config#nameserver_port): new method.
+
Thu Feb 11 01:45:04 2010 Yusuke Endoh <mame@tsg.ne.jp>
* vm.c (vm_exec): temporarily revert r26628, which causes SEGV when
diff --git a/lib/resolv.rb b/lib/resolv.rb
index b9bb536c2e..ffced98052 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -520,10 +520,11 @@ class Resolv
end
def make_requester # :nodoc:
- if nameserver_port = @config.single?
- Requester::ConnectedUDP.new(*nameserver_port)
+ nameserver_port = @config.nameserver_port
+ if nameserver_port.length == 1
+ Requester::ConnectedUDP.new(*nameserver_port[0])
else
- Requester::UnconnectedUDP.new
+ Requester::UnconnectedUDP.new(*nameserver_port)
end
end
@@ -609,10 +610,10 @@ class Resolv
}
end
- def self.bind_random_port(udpsock, is_ipv6=false) # :nodoc:
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
begin
port = rangerand(1024..65535)
- udpsock.bind(is_ipv6 ? "::" : "", port)
+ udpsock.bind(bind_host, port)
rescue Errno::EADDRINUSE
retry
end
@@ -621,7 +622,7 @@ class Resolv
class Requester # :nodoc:
def initialize
@senders = {}
- @sock = nil
+ @socks = nil
end
def request(sender, tout)
@@ -629,10 +630,11 @@ class Resolv
sender.send
while (now = Time.now) < timelimit
timeout = timelimit - now
- if !IO.select([@sock], nil, nil, timeout)
+ select_result = IO.select(@socks, nil, nil, timeout)
+ if !select_result
raise ResolvTimeout
end
- reply, from = recv_reply
+ reply, from = recv_reply(select_result[0])
begin
msg = Message.decode(reply)
rescue DecodeError
@@ -648,9 +650,11 @@ class Resolv
end
def close
- sock = @sock
- @sock = nil
- sock.close if sock
+ socks = @socks
+ @socks = nil
+ if socks
+ socks.each {|sock| sock.close }
+ end
end
class Sender # :nodoc:
@@ -662,16 +666,31 @@ class Resolv
end
class UnconnectedUDP < Requester # :nodoc:
- def initialize
+ def initialize(*nameserver_port)
super()
- @sock = UDPSocket.new
- @sock.do_not_reverse_lookup = true
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
- DNS.bind_random_port(@sock)
+ @nameserver_port = nameserver_port
+ @socks_hash = {}
+ @socks = []
+ nameserver_port.each {|host, port|
+ if host.index(':')
+ bind_host = "::"
+ af = Socket::AF_INET6
+ else
+ bind_host = "0.0.0.0"
+ af = Socket::AF_INET
+ end
+ next if @socks_hash[bind_host]
+ sock = UDPSocket.new(af)
+ sock.do_not_reverse_lookup = true
+ sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+ DNS.bind_random_port(sock, bind_host)
+ @socks << sock
+ @socks_hash[bind_host] = sock
+ }
end
- def recv_reply
- reply, from = @sock.recvfrom(UDPSize)
+ def recv_reply(readable_socks)
+ reply, from = readable_socks[0].recvfrom(UDPSize)
return reply, [from[3],from[1]]
end
@@ -680,8 +699,9 @@ class Resolv
id = DNS.allocate_request_id(host, port)
request = msg.encode
request[0,2] = [id].pack('n')
+ sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
return @senders[[service, id]] =
- Sender.new(request, data, @sock, host, port)
+ Sender.new(request, data, sock, host, port)
end
def close
@@ -711,15 +731,16 @@ class Resolv
@host = host
@port = port
is_ipv6 = host.index(':')
- @sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
- @sock.do_not_reverse_lookup = true
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
- DNS.bind_random_port(@sock, is_ipv6)
- @sock.connect(host, port)
+ sock = UDPSocket.new(is_ipv6 ? Socket::AF_INET6 : Socket::AF_INET)
+ @socks = [sock]
+ sock.do_not_reverse_lookup = true
+ sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+ DNS.bind_random_port(sock, is_ipv6 ? "::" : "0.0.0.0")
+ sock.connect(host, port)
end
- def recv_reply
- reply = @sock.recv(UDPSize)
+ def recv_reply(readable_socks)
+ reply = readable_socks[0].recv(UDPSize)
return reply, nil
end
@@ -730,7 +751,7 @@ class Resolv
id = DNS.allocate_request_id(@host, @port)
request = msg.encode
request[0,2] = [id].pack('n')
- return @senders[[nil,id]] = Sender.new(request, data, @sock)
+ return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
end
def close
@@ -753,14 +774,15 @@ class Resolv
super()
@host = host
@port = port
- @sock = TCPSocket.new(@host, @port)
- @sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
+ sock = TCPSocket.new(@host, @port)
+ @socks = [sock]
+ sock.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) if defined? Fcntl::F_SETFD
@senders = {}
end
- def recv_reply
- len = @sock.read(2).unpack('n')[0]
- reply = @sock.read(len)
+ def recv_reply(readable_socks)
+ len = readable_socks[0].read(2).unpack('n')[0]
+ reply = @socks[0].read(len)
return reply, nil
end
@@ -771,7 +793,7 @@ class Resolv
id = DNS.allocate_request_id(@host, @port)
request = msg.encode
request[0,2] = [request.length, id].pack('nn')
- return @senders[[nil,id]] = Sender.new(request, data, @sock)
+ return @senders[[nil,id]] = Sender.new(request, data, @socks[0])
end
class Sender < Requester::Sender # :nodoc:
@@ -932,6 +954,10 @@ class Resolv
end
end
+ def nameserver_port
+ @nameserver_port
+ end
+
def generate_candidates(name)
candidates = nil
name = Name.create(name)