gitlab-net-dns 0.9.1
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 +7 -0
- data/.gitignore +8 -0
- data/.gitlab-ci.yml +20 -0
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_defaults.yml +359 -0
- data/.rubocop_todo.yml +207 -0
- data/.travis.yml +13 -0
- data/CHANGELOG.md +113 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +56 -0
- data/README.md +172 -0
- data/Rakefile +38 -0
- data/THANKS.rdoc +24 -0
- data/bin/console +14 -0
- data/demo/check_soa.rb +104 -0
- data/demo/threads.rb +18 -0
- data/gitlab-net-dns.gemspec +24 -0
- data/lib/net/dns.rb +104 -0
- data/lib/net/dns/header.rb +705 -0
- data/lib/net/dns/names.rb +120 -0
- data/lib/net/dns/packet.rb +560 -0
- data/lib/net/dns/question.rb +185 -0
- data/lib/net/dns/resolver.rb +1214 -0
- data/lib/net/dns/resolver/socks.rb +148 -0
- data/lib/net/dns/resolver/timeouts.rb +70 -0
- data/lib/net/dns/rr.rb +356 -0
- data/lib/net/dns/rr/a.rb +114 -0
- data/lib/net/dns/rr/aaaa.rb +94 -0
- data/lib/net/dns/rr/classes.rb +130 -0
- data/lib/net/dns/rr/cname.rb +74 -0
- data/lib/net/dns/rr/hinfo.rb +96 -0
- data/lib/net/dns/rr/mr.rb +70 -0
- data/lib/net/dns/rr/mx.rb +82 -0
- data/lib/net/dns/rr/ns.rb +70 -0
- data/lib/net/dns/rr/null.rb +50 -0
- data/lib/net/dns/rr/ptr.rb +77 -0
- data/lib/net/dns/rr/soa.rb +75 -0
- data/lib/net/dns/rr/srv.rb +41 -0
- data/lib/net/dns/rr/txt.rb +58 -0
- data/lib/net/dns/rr/types.rb +191 -0
- data/lib/net/dns/version.rb +8 -0
- data/spec/fixtures/resolv.conf +4 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/unit/resolver/dns_timeout_spec.rb +36 -0
- data/spec/unit/resolver/tcp_timeout_spec.rb +46 -0
- data/spec/unit/resolver/udp_timeout_spec.rb +46 -0
- data/test/test_helper.rb +13 -0
- data/test/unit/header_test.rb +164 -0
- data/test/unit/names_test.rb +21 -0
- data/test/unit/packet_test.rb +47 -0
- data/test/unit/question_test.rb +81 -0
- data/test/unit/resolver_test.rb +114 -0
- data/test/unit/rr/a_test.rb +106 -0
- data/test/unit/rr/aaaa_test.rb +102 -0
- data/test/unit/rr/classes_test.rb +83 -0
- data/test/unit/rr/cname_test.rb +90 -0
- data/test/unit/rr/hinfo_test.rb +111 -0
- data/test/unit/rr/mr_test.rb +99 -0
- data/test/unit/rr/mx_test.rb +106 -0
- data/test/unit/rr/ns_test.rb +80 -0
- data/test/unit/rr/types_test.rb +71 -0
- data/test/unit/rr_test.rb +127 -0
- metadata +172 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#
|
5
|
+
# = Mail Rename Record (MR)
|
6
|
+
#
|
7
|
+
# Class for DNS MR resource records.
|
8
|
+
#
|
9
|
+
class MR < RR
|
10
|
+
# Gets the newname value.
|
11
|
+
#
|
12
|
+
# Returns a String.
|
13
|
+
attr_reader :newname
|
14
|
+
|
15
|
+
# Gets the standardized value for this record,
|
16
|
+
# represented by the value of <tt>newname</tt>.
|
17
|
+
#
|
18
|
+
# Returns a String.
|
19
|
+
def value
|
20
|
+
newname.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def subclass_new_from_hash(options)
|
26
|
+
if options.key?(:newname)
|
27
|
+
@newname = check_name(options[:newname])
|
28
|
+
else
|
29
|
+
raise ArgumentError, ":newname field is mandatory"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def subclass_new_from_string(str)
|
34
|
+
@newname = check_name(str)
|
35
|
+
end
|
36
|
+
|
37
|
+
def subclass_new_from_binary(data, offset)
|
38
|
+
@newname = dn_expand(data, offset)
|
39
|
+
offset
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_type
|
43
|
+
@type = Net::DNS::RR::Types.new("MR")
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_inspect
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_name(input)
|
51
|
+
name = input.to_s
|
52
|
+
unless name =~ /(\w\.?)+\s*$/
|
53
|
+
raise ArgumentError, "Invalid Domain Name `#{name}'"
|
54
|
+
end
|
55
|
+
|
56
|
+
name
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_pack
|
60
|
+
@newname_pack = pack_name(@newname)
|
61
|
+
@rdlength = @newname_pack.size
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_data
|
65
|
+
@newname_pack
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#
|
5
|
+
# = Mail Exchange Record (MX)
|
6
|
+
#
|
7
|
+
# Class for DNS MX resource records.
|
8
|
+
#
|
9
|
+
# A MX record specifies the name and relative preference of mail servers
|
10
|
+
# (mail exchangers in the DNS jargon) for the zone.
|
11
|
+
# The MX RR is used by SMTP (Mail) Agents to route mail for the domain.
|
12
|
+
#
|
13
|
+
class MX < RR
|
14
|
+
# Gets the preference value.
|
15
|
+
#
|
16
|
+
# Returns an Integer.
|
17
|
+
attr_reader :preference
|
18
|
+
|
19
|
+
# Gets the exchange value.
|
20
|
+
#
|
21
|
+
# Returns a String.
|
22
|
+
attr_reader :exchange
|
23
|
+
|
24
|
+
# Gets the standardized value for this record,
|
25
|
+
# represented by the value of <tt>preference</tt> and <tt>exchange</tt>.
|
26
|
+
#
|
27
|
+
# Returns a String.
|
28
|
+
def value
|
29
|
+
"#{preference} #{exchange}"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def subclass_new_from_hash(options)
|
35
|
+
if options.key?(:preference) && options.key?(:exchange)
|
36
|
+
@preference = options[:preference].to_i
|
37
|
+
@exchange = options[:exchange]
|
38
|
+
else
|
39
|
+
raise ArgumentError, ":preference and :exchange fields are mandatory"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def subclass_new_from_string(str)
|
44
|
+
@preference, @exchange = check_mx(str)
|
45
|
+
end
|
46
|
+
|
47
|
+
def subclass_new_from_binary(data, offset)
|
48
|
+
@preference = data.unpack("@#{offset} n")[0]
|
49
|
+
offset += 2
|
50
|
+
@exchange, offset = dn_expand(data, offset)
|
51
|
+
offset
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_type
|
55
|
+
@type = Net::DNS::RR::Types.new("MX")
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_inspect
|
59
|
+
value
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_mx(input)
|
63
|
+
str = input.to_s
|
64
|
+
unless str.strip =~ /^(\d+)\s+(\S+)$/
|
65
|
+
raise ArgumentError, "Invalid MX section `#{str}'"
|
66
|
+
end
|
67
|
+
|
68
|
+
[Regexp.last_match(1).to_i, Regexp.last_match(2)]
|
69
|
+
end
|
70
|
+
|
71
|
+
def build_pack
|
72
|
+
@mx_pack = [@preference].pack("n") + pack_name(@exchange)
|
73
|
+
@rdlength = @mx_pack.size
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_data
|
77
|
+
@mx_pack
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#
|
5
|
+
# = Name Server Record (NS)
|
6
|
+
#
|
7
|
+
# Class for DNS NS resource records.
|
8
|
+
#
|
9
|
+
class NS < RR
|
10
|
+
# Gets the name server value.
|
11
|
+
#
|
12
|
+
# Returns a String.
|
13
|
+
attr_reader :nsdname
|
14
|
+
|
15
|
+
# Gets the standardized value for this record,
|
16
|
+
# represented by the value of <tt>nsdname</tt>.
|
17
|
+
#
|
18
|
+
# Returns a String.
|
19
|
+
def value
|
20
|
+
nsdname.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def subclass_new_from_hash(options)
|
26
|
+
if options.key?(:nsdname)
|
27
|
+
@nsdname = check_name(options[:nsdname])
|
28
|
+
else
|
29
|
+
raise ArgumentError, ":nsdname field is mandatory"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def subclass_new_from_string(str)
|
34
|
+
@nsdname = check_name(str)
|
35
|
+
end
|
36
|
+
|
37
|
+
def subclass_new_from_binary(data, offset)
|
38
|
+
@nsdname, offset = dn_expand(data, offset)
|
39
|
+
offset
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_type
|
43
|
+
@type = Net::DNS::RR::Types.new("NS")
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_inspect
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
def check_name(input)
|
51
|
+
name = input.to_s
|
52
|
+
unless name =~ /(\w\.?)+\s*$/ && name =~ /[a-zA-Z]/
|
53
|
+
raise ArgumentError, "Invalid Name Server `#{name}'"
|
54
|
+
end
|
55
|
+
|
56
|
+
name
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_pack
|
60
|
+
@nsdname_pack = pack_name(@nsdname)
|
61
|
+
@rdlength = @nsdname_pack.size
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_data
|
65
|
+
@nsdname_pack
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#------------------------------------------------------------
|
5
|
+
# RR type NULL
|
6
|
+
#------------------------------------------------------------
|
7
|
+
class NULL < RR
|
8
|
+
attr_reader :null
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def build_pack
|
13
|
+
@null_pack = @null
|
14
|
+
@rdlength = @null_pack.size
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_data
|
18
|
+
@null_pack
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_inspect
|
22
|
+
@null.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def subclass_new_from_hash(args)
|
26
|
+
if args.key? :null
|
27
|
+
@null = args[:null]
|
28
|
+
else
|
29
|
+
raise ArgumentError, ":null field is mandatory but missing"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def subclass_new_from_string(str)
|
34
|
+
@null = str.strip
|
35
|
+
end
|
36
|
+
|
37
|
+
def subclass_new_from_binary(data, offset)
|
38
|
+
@null = data[offset..offset + @rdlength]
|
39
|
+
offset + @rdlength
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def set_type
|
45
|
+
@type = Net::DNS::RR::Types.new("NULL")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Net
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#
|
5
|
+
# = Pointer Record (PTR)
|
6
|
+
#
|
7
|
+
# Class for DNS Pointer (PTR) resource records.
|
8
|
+
#
|
9
|
+
# Pointer records are the opposite of A and AAAA RRs
|
10
|
+
# and are used in Reverse Map zone files to map
|
11
|
+
# an IP address (IPv4 or IPv6) to a host name.
|
12
|
+
#
|
13
|
+
class PTR < RR
|
14
|
+
# Gets the PTR value.
|
15
|
+
#
|
16
|
+
# Returns a String.
|
17
|
+
def ptrdname
|
18
|
+
@ptrdname.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
alias ptr ptrdname
|
22
|
+
|
23
|
+
# Gets the standardized value for this record,
|
24
|
+
# represented by the value of <tt>ptrdname</tt>.
|
25
|
+
#
|
26
|
+
# Returns a String.
|
27
|
+
def value
|
28
|
+
ptrdname.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def build_pack
|
34
|
+
@ptrdname_pack = pack_name(@ptrdname)
|
35
|
+
@rdlength = @ptrdname_pack.size
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_data
|
39
|
+
@ptrdname_pack
|
40
|
+
end
|
41
|
+
|
42
|
+
def subclass_new_from_hash(args)
|
43
|
+
if args.key?(:ptrdname) || args.key?(:ptr)
|
44
|
+
@ptrdname = args[:ptrdname]
|
45
|
+
else
|
46
|
+
raise ArgumentError, ":ptrdname or :ptr field is mandatory"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def subclass_new_from_string(str)
|
51
|
+
@ptrdname = check_name(str)
|
52
|
+
end
|
53
|
+
|
54
|
+
def subclass_new_from_binary(data, offset)
|
55
|
+
@ptrdname, offset = dn_expand(data, offset)
|
56
|
+
offset
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def set_type
|
62
|
+
@type = Net::DNS::RR::Types.new("PTR")
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_inspect
|
66
|
+
value
|
67
|
+
end
|
68
|
+
|
69
|
+
def check_name(input)
|
70
|
+
IPAddr.new(str)
|
71
|
+
rescue StandardError
|
72
|
+
raise ArgumentError, "Invalid PTR Section `#{input}'"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#------------------------------------------------------------
|
5
|
+
# RR type SOA
|
6
|
+
#------------------------------------------------------------
|
7
|
+
class SOA < RR
|
8
|
+
attr_reader :mname, :rname, :serial, :refresh, :retry, :expire, :minimum
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def build_pack
|
13
|
+
@soa_pack = pack_name(@mname)
|
14
|
+
@soa_pack += pack_name(@rname)
|
15
|
+
@soa_pack += [@serial, @refresh, @retry, @expire, @minimum].pack("N5")
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_data
|
19
|
+
@soa_pack
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_inspect
|
23
|
+
"#{@mname} #{@rname} #{@serial} #{@refresh} #{@retry} #{@expire} #{@minimum}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def subclass_new_from_hash(args)
|
27
|
+
if args.key? :rdata
|
28
|
+
subclass_new_from_string(args[:rdata])
|
29
|
+
else
|
30
|
+
%i[mname rname serial refresh retry expire minimum].each do |key|
|
31
|
+
raise ArgumentError, "Missing field :#{key}" unless args.key? key
|
32
|
+
end
|
33
|
+
@mname = args[:mname] if valid? args[:mname]
|
34
|
+
@rname = args[:rname] if valid? args[:rname]
|
35
|
+
@serial = args[:serial] if number? args[:serial]
|
36
|
+
@refresh = args[:refresh] if number? args[:refresh]
|
37
|
+
@retry = args[:retry] if number? args[:retry]
|
38
|
+
@expire = args[:expire] if number? args[:expire]
|
39
|
+
@minimum = args[:minimum] if number? args[:minimum]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def number?(num)
|
44
|
+
if num.is_a?(Integer) && (num > 0)
|
45
|
+
true
|
46
|
+
else
|
47
|
+
raise ArgumentError, "Wrong format field: #{num} not a number or less than zero"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def subclass_new_from_string(str)
|
52
|
+
mname, rname, serial, refresh, ret, expire, minimum = str.strip.split(" ")
|
53
|
+
@mname = mname if valid? mname
|
54
|
+
@rname = rname if valid? rname
|
55
|
+
@serial, @refresh, @retry, @expire, @minimum = [serial, refresh, ret, expire, minimum].collect do |i|
|
56
|
+
i.to_i if valid? i.to_i
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def subclass_new_from_binary(data, offset)
|
61
|
+
@mname, offset = dn_expand(data, offset)
|
62
|
+
@rname, offset = dn_expand(data, offset)
|
63
|
+
@serial, @refresh, @retry, @expire, @minimum = data.unpack("@#{offset} N5")
|
64
|
+
offset + 5 * Net::DNS::INT32SZ
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def set_type
|
70
|
+
@type = Net::DNS::RR::Types.new("SOA")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Net # :nodoc:
|
2
|
+
module DNS
|
3
|
+
class RR
|
4
|
+
#------------------------------------------------------------
|
5
|
+
# RR type SRV
|
6
|
+
#------------------------------------------------------------
|
7
|
+
class SRV < RR
|
8
|
+
attr_reader :priority, :weight, :port, :host
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def build_pack
|
13
|
+
str = ""
|
14
|
+
end
|
15
|
+
|
16
|
+
def subclass_new_from_binary(data, offset)
|
17
|
+
off_end = offset + @rdlength
|
18
|
+
@priority, @weight, @port = data.unpack("@#{offset} n n n")
|
19
|
+
offset += 6
|
20
|
+
|
21
|
+
@host = []
|
22
|
+
while offset < off_end
|
23
|
+
len = data.unpack("@#{offset} C")[0]
|
24
|
+
offset += 1
|
25
|
+
str = data[offset..offset + len - 1]
|
26
|
+
offset += len
|
27
|
+
@host << str
|
28
|
+
end
|
29
|
+
@host = @host.join(".")
|
30
|
+
offset
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def set_type
|
36
|
+
@type = Net::DNS::RR::Types.new("SRV")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|