gitlab-net-dns 0.12.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +1 -1
- data/README.md +3 -3
- data/lib/net/dns/resolver.rb +81 -95
- data/lib/net/dns/version.rb +1 -1
- data/spec/unit/resolver_spec.rb +47 -0
- data/test/unit/dns_resolver_test.rb +80 -0
- data/test/unit/resolver_test.rb +70 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74ee6c4e55aca3a4b262ef65ed15aa7eb4faefba46e236581313e600f488d4fb
|
4
|
+
data.tar.gz: c0737bd705ee060cb3e0cabd8f16985e24cbc9c32435ab7287435075a70c4532
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88cc517f05b54349d8cc62a597415e395888398e9d4557b1f9c8176b7dc1b98ab6b4683a82ca50909c37054c1e9bee076648eb637242db69d2ab94899577ea71
|
7
|
+
data.tar.gz: 9e4bfdd6c46a3e1e48449aa384561cd158c4e7580e01593d24f860900ffc708d789fbdfbc5f6b39ba35fdeccc2d5d3971e4f482e158792e16d56509d2d5b200d
|
data/.rubocop_todo.yml
CHANGED
data/README.md
CHANGED
@@ -17,16 +17,16 @@ Ruby >= 2.1
|
|
17
17
|
|
18
18
|
## Installation
|
19
19
|
|
20
|
-
The best way to install this library is via [RubyGems](https://rubygems.org/).
|
20
|
+
The best way to install this library is via [RubyGems](https://rubygems.org/gems/gitlab-net-dns/).
|
21
21
|
|
22
22
|
```
|
23
|
-
gem install net-dns
|
23
|
+
gem install gitlab-net-dns
|
24
24
|
```
|
25
25
|
|
26
26
|
|
27
27
|
## API Documentation
|
28
28
|
|
29
|
-
Visit the page http://rdoc.info/gems/net-dns
|
29
|
+
Visit the page http://rdoc.info/gems/gitlab-net-dns
|
30
30
|
|
31
31
|
|
32
32
|
## Trivial resolver
|
data/lib/net/dns/resolver.rb
CHANGED
@@ -92,7 +92,10 @@ module Net
|
|
92
92
|
class NoResponseError < Error
|
93
93
|
end
|
94
94
|
|
95
|
-
|
95
|
+
class ResolverPermissionError < Error
|
96
|
+
end
|
97
|
+
|
98
|
+
# A hash with the default values of almost all the
|
96
99
|
# configuration parameters of a resolver object. See
|
97
100
|
# the description for each parameter to have an
|
98
101
|
# explanation of its usage.
|
@@ -315,7 +318,16 @@ module Net
|
|
315
318
|
# #=> ["192.168.0.1","192.168.0.2"]
|
316
319
|
#
|
317
320
|
def nameservers
|
318
|
-
@config[:nameservers].map
|
321
|
+
@config[:nameservers].map do |entry|
|
322
|
+
case entry
|
323
|
+
in IPAddr
|
324
|
+
entry.to_s
|
325
|
+
in [IPAddr]
|
326
|
+
[entry[0].to_s]
|
327
|
+
in [IPAddr, Integer]
|
328
|
+
[entry[0].to_s, entry[1]]
|
329
|
+
end
|
330
|
+
end
|
319
331
|
end
|
320
332
|
|
321
333
|
alias nameserver nameservers
|
@@ -326,48 +338,38 @@ module Net
|
|
326
338
|
# res.nameservers = "192.168.0.1"
|
327
339
|
# res.nameservers = ["192.168.0.1","192.168.0.2"]
|
328
340
|
#
|
329
|
-
# If you want you can specify the addresses as IPAddr instances.
|
341
|
+
# If you want, you can specify the addresses as IPAddr instances.
|
330
342
|
#
|
331
|
-
#
|
332
|
-
# res.nameservers << ip
|
333
|
-
# #=> ["192.168.0.1","192.168.0.2","192.168.0.3"]
|
343
|
+
# res.nameservers = IPAddr.new("192.168.0.3")
|
334
344
|
#
|
335
345
|
# The default is 127.0.0.1 (localhost)
|
336
346
|
#
|
337
347
|
def nameservers=(arg)
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
end
|
346
|
-
when IPAddr
|
347
|
-
@config[:nameservers] = [arg]
|
348
|
-
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
349
|
-
when Array
|
350
|
-
@config[:nameservers] = []
|
351
|
-
arg.each do |x|
|
352
|
-
val = case x
|
353
|
-
when String
|
354
|
-
begin
|
355
|
-
IPAddr.new(x)
|
356
|
-
rescue ArgumentError
|
357
|
-
nameservers_from_name(arg)
|
358
|
-
return
|
359
|
-
end
|
360
|
-
when IPAddr
|
361
|
-
x
|
362
|
-
else
|
363
|
-
raise ArgumentError, "Wrong argument format"
|
348
|
+
@config[:nameservers] = Array(arg).flat_map do |entry|
|
349
|
+
case entry
|
350
|
+
in String
|
351
|
+
begin
|
352
|
+
IPAddr.new(entry)
|
353
|
+
rescue ArgumentError
|
354
|
+
nameservers_from_name(entry)
|
364
355
|
end
|
365
|
-
|
356
|
+
in IPAddr
|
357
|
+
entry
|
358
|
+
in [String]
|
359
|
+
[[IPAddr.new(entry[0])]]
|
360
|
+
in [IPAddr]
|
361
|
+
[[entry[0]]]
|
362
|
+
in [String, Integer]
|
363
|
+
validate_port!(entry[1])
|
364
|
+
[[IPAddr.new(entry[0]), entry[1]]]
|
365
|
+
in [IPAddr, Integer]
|
366
|
+
validate_port!(entry[1])
|
367
|
+
[[entry[0], entry[1]]]
|
368
|
+
else
|
369
|
+
raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
|
366
370
|
end
|
367
|
-
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
368
|
-
else
|
369
|
-
raise ArgumentError, "Wrong argument format, neither String, Array nor IPAddr"
|
370
371
|
end
|
372
|
+
@logger.info "Nameservers list changed to value #{@config[:nameservers].inspect}"
|
371
373
|
end
|
372
374
|
alias_method("nameserver=", "nameservers=")
|
373
375
|
|
@@ -402,8 +404,7 @@ module Net
|
|
402
404
|
# The default is port 53.
|
403
405
|
#
|
404
406
|
def port=(num)
|
405
|
-
(
|
406
|
-
raise(ArgumentError, "Wrong port number #{num}")
|
407
|
+
validate_port!(num)
|
407
408
|
|
408
409
|
@config[:port] = num
|
409
410
|
@logger.info "Port number changed to #{num}"
|
@@ -422,7 +423,7 @@ module Net
|
|
422
423
|
#
|
423
424
|
# res.source_port = 40000
|
424
425
|
#
|
425
|
-
# Note that if you want to set a port you need root
|
426
|
+
# Note that if you want to set a port, you need root privileges, as
|
426
427
|
# raw sockets will be used to generate packets. The class will then
|
427
428
|
# generate the exception ResolverPermissionError if you're not root.
|
428
429
|
#
|
@@ -430,10 +431,8 @@ module Net
|
|
430
431
|
# underlaying layers.
|
431
432
|
#
|
432
433
|
def source_port=(num)
|
433
|
-
root?
|
434
|
-
|
435
|
-
(0..65_535).cover?(num) or
|
436
|
-
raise(ArgumentError, "Wrong port number #{num}")
|
434
|
+
raise(ResolverPermissionError, "Are you root?") unless root?
|
435
|
+
validate_port!(num)
|
437
436
|
|
438
437
|
@config[:source_port] = num
|
439
438
|
end
|
@@ -871,43 +870,6 @@ module Net
|
|
871
870
|
query(name + ".", type, cls)
|
872
871
|
end
|
873
872
|
|
874
|
-
# Performs a DNS query for the given name; the search list
|
875
|
-
# is not applied. If the name doesn't contain any dots and
|
876
|
-
# +defname+ is true then the default domain will be appended.
|
877
|
-
#
|
878
|
-
# The record type and class can be omitted; they default to +A+
|
879
|
-
# and +IN+. If the name looks like an IP address (IPv4 or IPv6),
|
880
|
-
# then an appropriate PTR query will be performed.
|
881
|
-
#
|
882
|
-
# packet = res.query('mailhost')
|
883
|
-
# packet = res.query('mailhost.example.com')
|
884
|
-
# packet = res.query('example.com', Net::DNS::MX)
|
885
|
-
# packet = res.query('user.passwd.example.com', Net::DNS::TXT, Net::DNS::HS)
|
886
|
-
#
|
887
|
-
# If the name is an IP address (Ipv4 or IPv6), in the form of a string
|
888
|
-
# or a +IPAddr+ object, then an appropriate PTR query will be performed:
|
889
|
-
#
|
890
|
-
# ip = IPAddr.new("172.16.100.2")
|
891
|
-
# packet = res.query(ip)
|
892
|
-
# packet = res.query("192.168.10.254")
|
893
|
-
#
|
894
|
-
# Returns a Net::DNS::Packet object. If you need to examine the response
|
895
|
-
# packet whether it contains any answers or not, use the Resolver#query
|
896
|
-
# method instead.
|
897
|
-
#
|
898
|
-
def query(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
899
|
-
return send(name, type, cls) if name.class == IPAddr
|
900
|
-
|
901
|
-
# If the name doesn't contain any dots then append the default domain.
|
902
|
-
if name !~ /\./ && name !~ /:/ && @config[:defname]
|
903
|
-
name += "." + @config[:domain]
|
904
|
-
end
|
905
|
-
|
906
|
-
@logger.debug "Query(#{name},#{Net::DNS::RR::Types.new(type)},#{Net::DNS::RR::Classes.new(cls)})"
|
907
|
-
|
908
|
-
send(name, type, cls)
|
909
|
-
end
|
910
|
-
|
911
873
|
# Performs a DNS query for the given name. Neither the
|
912
874
|
# searchlist nor the default domain will be appended.
|
913
875
|
#
|
@@ -1293,11 +1255,9 @@ module Net
|
|
1293
1255
|
# res.nameservers = "192.168.0.1"
|
1294
1256
|
# res.nameservers = ["192.168.0.1","192.168.0.2"]
|
1295
1257
|
#
|
1296
|
-
# If you want you can specify the addresses as IPAddr instances.
|
1258
|
+
# If you want, you can specify the addresses as IPAddr instances.
|
1297
1259
|
#
|
1298
|
-
#
|
1299
|
-
# res.nameservers << ip
|
1300
|
-
# #=> ["192.168.0.1","192.168.0.2","192.168.0.3"]
|
1260
|
+
# res.nameservers = IPAddr.new("192.168.0.3")
|
1301
1261
|
#
|
1302
1262
|
# The default is 127.0.0.1 (localhost)
|
1303
1263
|
#
|
@@ -1639,7 +1599,7 @@ module Net
|
|
1639
1599
|
arr << ip
|
1640
1600
|
end
|
1641
1601
|
end
|
1642
|
-
|
1602
|
+
arr
|
1643
1603
|
end
|
1644
1604
|
|
1645
1605
|
def make_query_packet(string, type, cls)
|
@@ -1675,20 +1635,21 @@ module Net
|
|
1675
1635
|
ans = nil
|
1676
1636
|
length = [packet_data.size].pack("n")
|
1677
1637
|
|
1678
|
-
|
1638
|
+
nameserver_port_pairs.each do |(ns, ns_port)|
|
1679
1639
|
begin
|
1680
1640
|
buffer = ""
|
1681
1641
|
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
1682
1642
|
socket.bind(Socket.pack_sockaddr_in(@config[:source_port], @config[:source_address].to_s))
|
1683
1643
|
|
1684
|
-
sockaddr = Socket.pack_sockaddr_in(
|
1644
|
+
sockaddr = Socket.pack_sockaddr_in(ns_port, ns.to_s)
|
1645
|
+
success = false
|
1685
1646
|
|
1686
1647
|
@config[:tcp_timeout].timeout do
|
1687
1648
|
socket.connect(sockaddr)
|
1688
|
-
@logger.info "Contacting nameserver #{ns} port #{
|
1649
|
+
@logger.info "Contacting nameserver #{ns} port #{ns_port}"
|
1689
1650
|
socket.write(length + packet_data)
|
1690
1651
|
ans = socket.recv(Net::DNS::INT16SZ)
|
1691
|
-
len = ans.unpack("n")[0]
|
1652
|
+
len = ans.unpack("n")[0].to_i
|
1692
1653
|
|
1693
1654
|
@logger.info "Receiving #{len} bytes..."
|
1694
1655
|
|
@@ -1707,8 +1668,16 @@ module Net
|
|
1707
1668
|
@logger.warn "Malformed packet from nameserver #{ns}, trying next."
|
1708
1669
|
next
|
1709
1670
|
end
|
1671
|
+
|
1672
|
+
success = true
|
1710
1673
|
end
|
1711
|
-
|
1674
|
+
|
1675
|
+
# Return buffer and the socket "from" data:
|
1676
|
+
# from[0] - Address family as a string (e.g., "AF_INET" or "AF_INET6")
|
1677
|
+
# from[1] - Port number as an integer
|
1678
|
+
# from[2] - IP address as a string (e.g., "192.168.1.1" or "::1")
|
1679
|
+
# from[3] - IP address as a string (same as from[2])
|
1680
|
+
return [buffer, ["", ns_port, ns.to_s, ns.to_s]] if success
|
1712
1681
|
rescue Timeout::Error
|
1713
1682
|
@logger.warn "Nameserver #{ns} not responding within TCP timeout, trying next one"
|
1714
1683
|
next
|
@@ -1716,7 +1685,8 @@ module Net
|
|
1716
1685
|
socket.close
|
1717
1686
|
end
|
1718
1687
|
end
|
1719
|
-
|
1688
|
+
|
1689
|
+
nil
|
1720
1690
|
end
|
1721
1691
|
|
1722
1692
|
def query_udp(packet, packet_data)
|
@@ -1727,15 +1697,15 @@ module Net
|
|
1727
1697
|
|
1728
1698
|
ans = nil
|
1729
1699
|
response = ""
|
1730
|
-
|
1700
|
+
nameserver_port_pairs.each do |(ns, ns_port)|
|
1731
1701
|
begin
|
1732
1702
|
@config[:udp_timeout].timeout do
|
1733
|
-
@logger.info "Contacting nameserver #{ns} port #{
|
1703
|
+
@logger.info "Contacting nameserver #{ns} port #{ns_port}"
|
1734
1704
|
ans = if ns.ipv6?
|
1735
|
-
socket6.send(packet_data, 0, ns.to_s,
|
1705
|
+
socket6.send(packet_data, 0, ns.to_s, ns_port)
|
1736
1706
|
socket6.recvfrom(@config[:packet_size])
|
1737
1707
|
else
|
1738
|
-
socket4.send(packet_data, 0, ns.to_s,
|
1708
|
+
socket4.send(packet_data, 0, ns.to_s, ns_port)
|
1739
1709
|
socket4.recvfrom(@config[:packet_size])
|
1740
1710
|
end
|
1741
1711
|
end
|
@@ -1748,6 +1718,22 @@ module Net
|
|
1748
1718
|
ans
|
1749
1719
|
end
|
1750
1720
|
|
1721
|
+
def nameserver_port_pairs
|
1722
|
+
@config[:nameservers].map { |entry| Array(entry) }.map { |ns, ns_port| [ns, ns_port || port] }
|
1723
|
+
end
|
1724
|
+
|
1725
|
+
def validate_port!(port)
|
1726
|
+
raise(ArgumentError, "Wrong port number #{port}") unless valid_port?(port)
|
1727
|
+
end
|
1728
|
+
|
1729
|
+
def valid_port?(port)
|
1730
|
+
(0..65_535).cover?(port)
|
1731
|
+
end
|
1732
|
+
|
1733
|
+
def root?
|
1734
|
+
Process.euid == 0
|
1735
|
+
end
|
1736
|
+
|
1751
1737
|
# FIXME: a ? method should never raise.
|
1752
1738
|
def valid?(name)
|
1753
1739
|
name !~ /[^-\w\.]/ or
|
data/lib/net/dns/version.rb
CHANGED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'net/dns/resolver/timeouts'
|
3
|
+
|
4
|
+
describe Net::DNS::Resolver do
|
5
|
+
it 'executes UDP query' do
|
6
|
+
ipv4_sock = instance_double(UDPSocket, bind: 0, send: 0)
|
7
|
+
ipv6_sock = instance_double(UDPSocket, bind: 0)
|
8
|
+
|
9
|
+
google_com_a_record_response = [
|
10
|
+
"A\x06\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x06google\x03com\x00\x00\x01\x00\x01\xC0\f\x00\x01\x00\x01\x00\x00\x00I\x00\x04\x8E\xFA\xBA\xCE",
|
11
|
+
['AF_INET', 53, '8.8.8.8', '8.8.8.8']
|
12
|
+
]
|
13
|
+
allow(ipv4_sock).to receive(:recvfrom).and_return(google_com_a_record_response)
|
14
|
+
|
15
|
+
allow(UDPSocket).to receive(:new).and_return(ipv4_sock)
|
16
|
+
allow(UDPSocket).to receive(:new).with(Socket::AF_INET6).and_return(ipv6_sock)
|
17
|
+
|
18
|
+
resolver = Net::DNS::Resolver.new(nameservers: %w[8.8.8.8])
|
19
|
+
response = resolver.query('google.com')
|
20
|
+
|
21
|
+
expect(response.answer[0].address.to_s).to eq('142.250.186.206')
|
22
|
+
expect(ipv4_sock).to have_received(:bind).with(instance_of(String), instance_of(Integer))
|
23
|
+
expect(ipv4_sock).to have_received(:send).with(instance_of(String), 0, '8.8.8.8', 53)
|
24
|
+
expect(ipv4_sock).to have_received(:recvfrom).with(instance_of(Integer))
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'executes TCP query' do
|
28
|
+
sock = instance_double(Socket, bind: 0, connect: 0, write: 0, close: nil)
|
29
|
+
|
30
|
+
allow(sock).to receive(:recv).and_return("\x00,")
|
31
|
+
google_com_a_record_response = "%\xF9\x81\x80\x00\x01\x00\x01\x00\x00\x00\x00\x06google\x03com\x00\x00\x01\x00\x01\xC0\f\x00\x01\x00\x01\x00\x00\x00\xB3\x00\x04\x8E\xFA\xBA\xCE"
|
32
|
+
allow(sock).to receive(:recvfrom).and_return(google_com_a_record_response)
|
33
|
+
|
34
|
+
allow(Socket).to receive(:new).and_return(sock)
|
35
|
+
|
36
|
+
resolver = Net::DNS::Resolver.new(nameservers: %w[8.8.8.8], use_tcp: true)
|
37
|
+
response = resolver.query('google.com')
|
38
|
+
|
39
|
+
expect(response.answer[0].address.to_s).to eq('142.250.186.206')
|
40
|
+
expect(sock).to have_received(:bind).with(instance_of(String))
|
41
|
+
expect(sock).to have_received(:connect).with(Socket.pack_sockaddr_in(53, '8.8.8.8'))
|
42
|
+
expect(sock).to have_received(:write).with(instance_of(String))
|
43
|
+
expect(sock).to have_received(:recv)
|
44
|
+
expect(sock).to have_received(:recvfrom).with(instance_of(Integer))
|
45
|
+
expect(sock).to have_received(:close)
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'net/dns/resolver'
|
3
|
+
|
4
|
+
class TestDNSResolver < Minitest::Test
|
5
|
+
def setup
|
6
|
+
@resolver = Net::DNS::Resolver.new(
|
7
|
+
nameservers: ['8.8.8.8'],
|
8
|
+
port: 53,
|
9
|
+
source_address: IPAddr.new('0.0.0.0'),
|
10
|
+
tcp_timeout: 5,
|
11
|
+
udp_timeout: 5
|
12
|
+
)
|
13
|
+
|
14
|
+
# Sample DNS packet data
|
15
|
+
@packet_data = "\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01"
|
16
|
+
end
|
17
|
+
|
18
|
+
# Tests for query_tcp
|
19
|
+
def test_query_tcp_successful_response
|
20
|
+
mock_socket = Minitest::Mock.new
|
21
|
+
|
22
|
+
Socket.stub(:new, mock_socket) do
|
23
|
+
mock_socket.expect(:bind, nil, [String])
|
24
|
+
mock_socket.expect(:connect, nil, [String])
|
25
|
+
mock_socket.expect(:write, @packet_data.size + 2, [String])
|
26
|
+
mock_socket.expect(:recv, "\x00\x20", [2]) # Length = 32 bytes
|
27
|
+
mock_socket.expect(:recvfrom, ["A" * 32, nil], [32])
|
28
|
+
mock_socket.expect(:close, nil)
|
29
|
+
|
30
|
+
Socket.stub(:pack_sockaddr_in, "mock_sockaddr") do
|
31
|
+
result = @resolver.send(:query_tcp, @packet, @packet_data)
|
32
|
+
|
33
|
+
refute_nil result
|
34
|
+
assert_equal 2, result.size
|
35
|
+
assert_equal "A" * 32, result[0] # Response data
|
36
|
+
assert_equal ["", 53, "8.8.8.8", "8.8.8.8"], result[1] # From info
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
mock_socket.verify
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_query_tcp_zero_length_response
|
44
|
+
mock_socket = Minitest::Mock.new
|
45
|
+
|
46
|
+
Socket.stub(:new, mock_socket) do
|
47
|
+
mock_socket.expect(:bind, nil, [String])
|
48
|
+
mock_socket.expect(:connect, nil, [String])
|
49
|
+
mock_socket.expect(:write, @packet_data.size + 2, [String])
|
50
|
+
mock_socket.expect(:recv, "\x00\x00", [2]) # Length = 0 bytes
|
51
|
+
mock_socket.expect(:close, nil)
|
52
|
+
|
53
|
+
Socket.stub(:pack_sockaddr_in, "mock_sockaddr") do
|
54
|
+
result = @resolver.send(:query_tcp, @packet, @packet_data)
|
55
|
+
assert_nil result # Should return nil for zero-length response
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
mock_socket.verify
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_query_tcp_bogus_response
|
63
|
+
mock_socket = Minitest::Mock.new
|
64
|
+
|
65
|
+
Socket.stub(:new, mock_socket) do
|
66
|
+
mock_socket.expect(:bind, nil, [String])
|
67
|
+
mock_socket.expect(:connect, nil, [String])
|
68
|
+
mock_socket.expect(:write, @packet_data.size + 2, [String])
|
69
|
+
mock_socket.expect(:recv, "0", [2]) # Length = 0 bytes
|
70
|
+
mock_socket.expect(:close, nil)
|
71
|
+
|
72
|
+
Socket.stub(:pack_sockaddr_in, "mock_sockaddr") do
|
73
|
+
result = @resolver.send(:query_tcp, @packet, @packet_data)
|
74
|
+
assert_nil result # Should return nil for zero-length response
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
mock_socket.verify
|
79
|
+
end
|
80
|
+
end
|
data/test/unit/resolver_test.rb
CHANGED
@@ -25,6 +25,69 @@ class ResolverTest < Minitest::Test
|
|
25
25
|
assert_raises(ArgumentError) { Net::DNS::Resolver.new(:foo) }
|
26
26
|
end
|
27
27
|
|
28
|
+
def test_set_port
|
29
|
+
resolver = Net::DNS::Resolver.new
|
30
|
+
assert_equal 53, resolver.port
|
31
|
+
|
32
|
+
assert_raises(ArgumentError) { resolver.port = 100_000 }
|
33
|
+
assert_equal 53, resolver.port
|
34
|
+
|
35
|
+
resolver.port = 10_053
|
36
|
+
assert_equal 10_053, resolver.port
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_set_source_port
|
40
|
+
resolver = Net::DNS::Resolver.new
|
41
|
+
assert_equal 0, resolver.source_port
|
42
|
+
|
43
|
+
resolver.stub :root?, false do
|
44
|
+
assert_raises(Net::DNS::Resolver::ResolverPermissionError) { resolver.source_port = 1 }
|
45
|
+
assert_equal 0, resolver.source_port
|
46
|
+
end
|
47
|
+
|
48
|
+
resolver.stub :root?, true do
|
49
|
+
assert_raises(ArgumentError) { resolver.source_port = 100_000 }
|
50
|
+
assert_equal 0, resolver.source_port
|
51
|
+
|
52
|
+
resolver.source_port = 1
|
53
|
+
assert_equal 1, resolver.source_port
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_set_nameservers
|
58
|
+
resolver = Net::DNS::Resolver.new nameservers: '127.0.0.1'
|
59
|
+
assert_equal ['127.0.0.1'], resolver.nameservers
|
60
|
+
|
61
|
+
assert_raises(ArgumentError) { resolver.nameservers = 1 }
|
62
|
+
assert_equal ['127.0.0.1'], resolver.nameservers
|
63
|
+
|
64
|
+
assert_raises(ArgumentError) { resolver.nameservers = ['192.168.1.1', 1] }
|
65
|
+
assert_equal ['127.0.0.1'], resolver.nameservers
|
66
|
+
|
67
|
+
resolver.stub :nameservers_from_name, [IPAddr.new('192.168.1.1')] do
|
68
|
+
assert_raises(ArgumentError) { resolver.nameservers = ['test.com', 1] }
|
69
|
+
assert_equal ['127.0.0.1'], resolver.nameservers
|
70
|
+
|
71
|
+
resolver.nameservers = 'test.com'
|
72
|
+
assert_equal ['192.168.1.1'], resolver.nameservers
|
73
|
+
|
74
|
+
resolver.nameservers = ['test.com']
|
75
|
+
assert_equal ['192.168.1.1'], resolver.nameservers
|
76
|
+
|
77
|
+
resolver.nameservers = ['192.168.1.2', 'test.com', IPAddr.new('192.168.1.3')]
|
78
|
+
assert_equal ['192.168.1.2', '192.168.1.1', '192.168.1.3'], resolver.nameservers
|
79
|
+
end
|
80
|
+
|
81
|
+
resolver.nameservers = [['192.168.1.1', 30053], ['192.168.1.2'], '192.168.1.3']
|
82
|
+
assert_equal [['192.168.1.1', 30053], ['192.168.1.2'], '192.168.1.3'], resolver.nameservers
|
83
|
+
|
84
|
+
resolver.nameservers = [[IPAddr.new('192.168.1.1'), 30053], [IPAddr.new('192.168.1.2')], IPAddr.new('192.168.1.3')]
|
85
|
+
assert_equal [['192.168.1.1', 30053], ['192.168.1.2'], '192.168.1.3'], resolver.nameservers
|
86
|
+
|
87
|
+
assert_raises(ArgumentError) { resolver.nameservers = [['192.168.1.1', 100_000]] }
|
88
|
+
assert_raises(ArgumentError) { resolver.nameservers = [[IPAddr.new('192.168.1.2'), 100_000]] }
|
89
|
+
end
|
90
|
+
|
28
91
|
def test_query_with_no_nameservers_should_raise_resolvererror
|
29
92
|
assert_raises(Net::DNS::Resolver::Error) { Net::DNS::Resolver.new(nameservers: []).query("example.com") }
|
30
93
|
end
|
@@ -75,6 +138,13 @@ class ResolverTest < Minitest::Test
|
|
75
138
|
assert_equal Net::DNS::IN.to_i, packet.question.first.qClass.to_i
|
76
139
|
end
|
77
140
|
|
141
|
+
def test_nameserver_port_pairs
|
142
|
+
resolver = Net::DNS::Resolver.new(nameservers: [['172.16.1.1', 30_053], ['172.16.1.2'], '172.16.1.3'])
|
143
|
+
nameserver_port_pairs = resolver.send(:nameserver_port_pairs)
|
144
|
+
assert_equal ['172.16.1.1', '172.16.1.2', '172.16.1.3'], nameserver_port_pairs.map(&:first).map(&:to_s)
|
145
|
+
assert_equal [30_053, 53, 53], nameserver_port_pairs.map(&:last)
|
146
|
+
end
|
147
|
+
|
78
148
|
def test_should_return_state_without_exception
|
79
149
|
res = Net::DNS::Resolver.new
|
80
150
|
assert_nothing_raised { res.state }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gitlab-net-dns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marco Ceresa
|
8
8
|
- Simone Carletti
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logger
|
@@ -122,7 +122,9 @@ files:
|
|
122
122
|
- spec/unit/resolver/dns_timeout_spec.rb
|
123
123
|
- spec/unit/resolver/tcp_timeout_spec.rb
|
124
124
|
- spec/unit/resolver/udp_timeout_spec.rb
|
125
|
+
- spec/unit/resolver_spec.rb
|
125
126
|
- test/test_helper.rb
|
127
|
+
- test/unit/dns_resolver_test.rb
|
126
128
|
- test/unit/header_test.rb
|
127
129
|
- test/unit/names_test.rb
|
128
130
|
- test/unit/packet_test.rb
|
@@ -165,7 +167,9 @@ test_files:
|
|
165
167
|
- spec/unit/resolver/dns_timeout_spec.rb
|
166
168
|
- spec/unit/resolver/tcp_timeout_spec.rb
|
167
169
|
- spec/unit/resolver/udp_timeout_spec.rb
|
170
|
+
- spec/unit/resolver_spec.rb
|
168
171
|
- test/test_helper.rb
|
172
|
+
- test/unit/dns_resolver_test.rb
|
169
173
|
- test/unit/header_test.rb
|
170
174
|
- test/unit/names_test.rb
|
171
175
|
- test/unit/packet_test.rb
|