summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2021-03-20 13:18:32 +0900
committernagachika <nagachika@ruby-lang.org>2021-03-20 13:18:32 +0900
commit70c3a195f39763dccdf9367d0c9b7e815431a41a (patch)
tree37117c01623a51581de61dde314be9dcc683a802
parent9994860dcb56697fad1799128d1493adc06b23c7 (diff)
merge revision(s) 9682db065158da5fa4ec8a3bc267da45b429b92c: [Backport #12838] [Backport #17658]
Remove sender/message_id pair after response received in resolv Once a response for a given DNS request has been received (which requires a matching message id), the [sender, message_id] pair should be removed from the list of valid senders. This makes it so duplicate responses from the same sender are ignored. Fixes [Bug #12838] --- lib/resolv.rb | 2 +- test/resolv/test_dns.rb | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-)
-rw-r--r--lib/resolv.rb2
-rw-r--r--test/resolv/test_dns.rb113
-rw-r--r--version.h2
3 files changed, 115 insertions, 2 deletions
diff --git a/lib/resolv.rb b/lib/resolv.rb
index e7b45e785a..fd5e475aa2 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -706,7 +706,7 @@ class Resolv
end
def sender_for(addr, msg)
- @senders[[addr,msg.id]]
+ @senders.delete([addr,msg.id])
end
def close
diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb
index 70d5067750..617babf829 100644
--- a/test/resolv/test_dns.rb
+++ b/test/resolv/test_dns.rb
@@ -128,6 +128,119 @@ class TestResolvDNS < Test::Unit::TestCase
}
end
+ def test_query_ipv4_duplicate_responses
+ begin
+ OpenSSL
+ rescue LoadError
+ skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ end if defined?(OpenSSL)
+
+ with_udp('127.0.0.1', 0) {|u|
+ _, server_port, _, server_address = u.addr
+ begin
+ client_thread = Thread.new {
+ Resolv::DNS.open(:nameserver_port => [[server_address, server_port]], :search => ['bad1.com', 'bad2.com', 'good.com'], ndots: 5) {|dns|
+ dns.getaddress("example")
+ }
+ }
+ server_thread = Thread.new {
+ 3.times do
+ msg, (_, client_port, _, client_address) = Timeout.timeout(5) {u.recvfrom(4096)}
+ id, flags, qdcount, ancount, nscount, arcount = msg.unpack("nnnnnn")
+
+ qr = (flags & 0x8000) >> 15
+ opcode = (flags & 0x7800) >> 11
+ aa = (flags & 0x0400) >> 10
+ tc = (flags & 0x0200) >> 9
+ rd = (flags & 0x0100) >> 8
+ ra = (flags & 0x0080) >> 7
+ z = (flags & 0x0070) >> 4
+ rcode = flags & 0x000f
+ rest = msg[12..-1]
+
+ questions = msg.bytes[12..-1]
+ labels = []
+ idx = 0
+ while idx < questions.length-5
+ size = questions[idx]
+ labels << questions[idx+1..idx+size].pack('c*')
+ idx += size+1
+ end
+ hostname = labels.join('.')
+
+ if hostname == "example.good.com"
+ id = id
+ qr = 1
+ opcode = opcode
+ aa = 0
+ tc = 0
+ rd = rd
+ ra = 1
+ z = 0
+ rcode = 0
+ qdcount = 1
+ ancount = 1
+ nscount = 0
+ arcount = 0
+ word2 = (qr << 15) |
+ (opcode << 11) |
+ (aa << 10) |
+ (tc << 9) |
+ (rd << 8) |
+ (ra << 7) |
+ (z << 4) |
+ rcode
+ msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn")
+ msg << questions.pack('c*')
+ type = 1
+ klass = 1
+ ttl = 3600
+ rdlength = 4
+ rdata = [52,0,2,1].pack("CCCC")
+ rr = [0xc00c, type, klass, ttl, rdlength, rdata].pack("nnnNna*")
+ msg << rr
+ rdata = [52,0,2,2].pack("CCCC")
+ rr = [0xc00c, type, klass, ttl, rdlength, rdata].pack("nnnNna*")
+ msg << rr
+
+ u.send(msg, 0, client_address, client_port)
+ else
+ id = id
+ qr = 1
+ opcode = opcode
+ aa = 0
+ tc = 0
+ rd = rd
+ ra = 1
+ z = 0
+ rcode = 3
+ qdcount = 1
+ ancount = 0
+ nscount = 0
+ arcount = 0
+ word2 = (qr << 15) |
+ (opcode << 11) |
+ (aa << 10) |
+ (tc << 9) |
+ (rd << 8) |
+ (ra << 7) |
+ (z << 4) |
+ rcode
+ msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn")
+ msg << questions.pack('c*')
+
+ u.send(msg, 0, client_address, client_port)
+ u.send(msg, 0, client_address, client_port)
+ end
+ end
+ }
+ result, _ = assert_join_threads([client_thread, server_thread])
+ assert_instance_of(Resolv::IPv4, result)
+ assert_equal("52.0.2.1", result.to_s)
+ end
+ }
+ end
+
def test_query_ipv4_address_timeout
with_udp('127.0.0.1', 0) {|u|
_, port , _, host = u.addr
diff --git a/version.h b/version.h
index ef9fcd0e5c..a5bd5b5a0b 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 3
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 163
+#define RUBY_PATCHLEVEL 164
#define RUBY_RELEASE_YEAR 2021
#define RUBY_RELEASE_MONTH 3