net-dns 0.8.0 → 0.20.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 +6 -14
- data/.rspec +1 -0
- data/.travis.yml +9 -16
- data/CHANGELOG.md +37 -13
- data/LICENSE.txt +56 -0
- data/README.md +94 -77
- data/demo/check_soa.rb +27 -38
- data/demo/threads.rb +3 -7
- data/lib/net/dns/header.rb +86 -110
- data/lib/net/dns/names.rb +31 -31
- data/lib/net/dns/packet.rb +148 -158
- data/lib/net/dns/question.rb +41 -42
- data/lib/net/dns/resolver/socks.rb +47 -55
- data/lib/net/dns/resolver/timeouts.rb +19 -30
- data/lib/net/dns/resolver.rb +151 -176
- data/lib/net/dns/rr/a.rb +45 -55
- data/lib/net/dns/rr/aaaa.rb +39 -50
- data/lib/net/dns/rr/classes.rb +32 -37
- data/lib/net/dns/rr/cname.rb +31 -41
- data/lib/net/dns/rr/hinfo.rb +40 -56
- data/lib/net/dns/rr/mr.rb +31 -42
- data/lib/net/dns/rr/mx.rb +35 -47
- data/lib/net/dns/rr/ns.rb +31 -41
- data/lib/net/dns/rr/null.rb +10 -15
- data/lib/net/dns/rr/ptr.rb +16 -24
- data/lib/net/dns/rr/soa.rb +36 -35
- data/lib/net/dns/rr/srv.rb +18 -19
- data/lib/net/dns/rr/txt.rb +11 -16
- data/lib/net/dns/rr/types.rb +118 -109
- data/lib/net/dns/rr.rb +107 -117
- data/lib/net/dns/version.rb +5 -13
- data/lib/net/dns.rb +6 -11
- metadata +18 -83
- data/.gitignore +0 -8
- data/Gemfile +0 -4
- data/Rakefile +0 -71
- data/fixtures/resolv.conf +0 -4
- data/lib/net/dns/core_ext.rb +0 -52
- data/net-dns.gemspec +0 -35
- data/test/header_test.rb +0 -167
- data/test/names_test.rb +0 -21
- data/test/packet_test.rb +0 -49
- data/test/question_test.rb +0 -83
- data/test/resolver/timeouts_test.rb +0 -109
- data/test/resolver_test.rb +0 -117
- data/test/rr/a_test.rb +0 -113
- data/test/rr/aaaa_test.rb +0 -109
- data/test/rr/classes_test.rb +0 -85
- data/test/rr/cname_test.rb +0 -97
- data/test/rr/hinfo_test.rb +0 -117
- data/test/rr/mr_test.rb +0 -105
- data/test/rr/mx_test.rb +0 -112
- data/test/rr/ns_test.rb +0 -86
- data/test/rr/types_test.rb +0 -69
- data/test/rr_test.rb +0 -131
- data/test/test_helper.rb +0 -4
data/lib/net/dns/question.rb
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
module Net
|
2
|
-
module DNS
|
3
|
-
|
2
|
+
module DNS
|
4
3
|
#
|
5
4
|
# =Name
|
6
5
|
#
|
7
6
|
# Net::DNS::Question - DNS packet question class
|
8
7
|
#
|
9
8
|
# =Synopsis
|
10
|
-
#
|
9
|
+
#
|
11
10
|
# require 'net/dns/question'
|
12
11
|
#
|
13
12
|
# =Description
|
14
13
|
#
|
15
14
|
# This class represent the Question portion of a DNS packet. The number
|
16
15
|
# of question entries is stored in the +qdCount+ variable of an Header
|
17
|
-
# object.
|
16
|
+
# object.
|
18
17
|
#
|
19
18
|
# A new object can be created passing the name of the query and the type
|
20
19
|
# of answer desired, plus an optional argument containing the class:
|
@@ -26,13 +25,13 @@ module Net
|
|
26
25
|
# packet, as when an answer is received.
|
27
26
|
# To obtain the binary data from a question object you can use
|
28
27
|
# the method Question#data:
|
29
|
-
#
|
28
|
+
#
|
30
29
|
# question.data
|
31
30
|
# #=> "\006google\003com\000\000\001\000\001"
|
32
31
|
#
|
33
32
|
# A lot of methods were written to keep a compatibility layer with
|
34
33
|
# the Perl version of the library, as long as methods name which are
|
35
|
-
# more or less the same.
|
34
|
+
# more or less the same.
|
36
35
|
#
|
37
36
|
class Question
|
38
37
|
include Names
|
@@ -40,18 +39,18 @@ module Net
|
|
40
39
|
# Base error class.
|
41
40
|
class Error < StandardError
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
# An error in the +name+ part of a Question entry
|
45
44
|
class NameInvalid < Error
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
# +name+ part of a Question entry
|
49
|
-
attr_reader :qName
|
48
|
+
attr_reader :qName
|
50
49
|
# +type+ part of a Question entry
|
51
|
-
attr_reader :qType
|
50
|
+
attr_reader :qType
|
52
51
|
# +class+ part of a Question entry
|
53
|
-
attr_reader :qClass
|
54
|
-
|
52
|
+
attr_reader :qClass
|
53
|
+
|
55
54
|
# Creates a new Net::DNS::Question object:
|
56
55
|
#
|
57
56
|
# question = Net::DNS::Question.new("example.com")
|
@@ -60,8 +59,8 @@ module Net
|
|
60
59
|
# #=> "example.com MX IN"
|
61
60
|
# question = Net::DNS::Question.new("example.com", Net::DNS::TXT, Net::DNS::HS)
|
62
61
|
# #=> "example.com TXT HS"
|
63
|
-
|
64
|
-
# If not specified, +type+ and +cls+ arguments defaults
|
62
|
+
|
63
|
+
# If not specified, +type+ and +cls+ arguments defaults
|
65
64
|
# to Net::DNS::A and Net::DNS::IN respectively.
|
66
65
|
#
|
67
66
|
def initialize(name, type = Net::DNS::A, cls = Net::DNS::IN)
|
@@ -83,18 +82,18 @@ module Net
|
|
83
82
|
o.send(:new_from_binary, arg.to_s)
|
84
83
|
o
|
85
84
|
end
|
86
|
-
|
85
|
+
|
87
86
|
# Outputs binary data from a Question object
|
88
87
|
#
|
89
88
|
# question.data
|
90
89
|
# #=> "\006google\003com\000\000\001\000\001"
|
91
90
|
#
|
92
91
|
def data
|
93
|
-
[pack_name(@qName)
|
92
|
+
[pack_name(@qName), @qType.to_i, @qClass.to_i].pack("a*nn")
|
94
93
|
end
|
95
|
-
|
94
|
+
|
96
95
|
# Return the binary data of the objects, plus an offset
|
97
|
-
# and an Hash with references to compressed names. For use in
|
96
|
+
# and an Hash with references to compressed names. For use in
|
98
97
|
# Net::DNS::Packet compressed packet creation.
|
99
98
|
def comp_data
|
100
99
|
arr = @qName.split(".")
|
@@ -103,20 +102,19 @@ module Net
|
|
103
102
|
names = {}
|
104
103
|
offset = Net::DNS::HFIXEDSZ
|
105
104
|
arr.size.times do |i|
|
106
|
-
x = i+1
|
105
|
+
x = i + 1
|
107
106
|
elem = arr[-x]
|
108
107
|
len = elem.size
|
109
|
-
string = (
|
108
|
+
string = (string.reverse + [len, elem].pack("Ca*").reverse).reverse
|
110
109
|
names[string] = offset
|
111
110
|
offset += len
|
112
111
|
end
|
113
112
|
offset += 2 * Net::DNS::INT16SZ
|
114
113
|
str += "\000"
|
115
|
-
[[str
|
114
|
+
[[str, @qType.to_i, @qClass.to_i].pack("a*nn"), offset, names]
|
116
115
|
end
|
117
|
-
|
118
|
-
|
119
|
-
#
|
116
|
+
|
117
|
+
#
|
120
118
|
# call-seq:
|
121
119
|
# question.inspect -> string
|
122
120
|
#
|
@@ -126,15 +124,15 @@ module Net
|
|
126
124
|
# q.inspect # => "google.com. IN A "
|
127
125
|
#
|
128
126
|
def inspect
|
129
|
-
if @qName.size > 29
|
130
|
-
|
127
|
+
len = if @qName.size > 29
|
128
|
+
@qName.size + 1
|
131
129
|
else
|
132
|
-
|
130
|
+
29
|
133
131
|
end
|
134
132
|
[@qName, @qClass.to_s, @qType.to_s].pack("A#{len} A8 A8")
|
135
133
|
end
|
136
|
-
|
137
|
-
#
|
134
|
+
|
135
|
+
#
|
138
136
|
# call-seq:
|
139
137
|
# question.to_s -> string
|
140
138
|
#
|
@@ -145,44 +143,45 @@ module Net
|
|
145
143
|
# q.inspect # => "google.com. IN A "
|
146
144
|
#
|
147
145
|
def to_s
|
148
|
-
|
146
|
+
inspect.to_s
|
149
147
|
end
|
150
|
-
|
151
|
-
|
148
|
+
|
152
149
|
private
|
153
|
-
|
150
|
+
|
154
151
|
def build_qName(str)
|
155
152
|
result = ""
|
156
153
|
offset = 0
|
157
154
|
loop do
|
158
|
-
len = str.
|
155
|
+
len = str.unpack1("@#{offset} C")
|
159
156
|
break if len == 0
|
157
|
+
|
160
158
|
offset += 1
|
161
|
-
result += str[offset..offset+len-1]
|
159
|
+
result += str[offset..offset + len - 1]
|
162
160
|
result += "."
|
163
161
|
offset += len
|
164
162
|
end
|
165
163
|
result
|
166
164
|
end
|
167
|
-
|
165
|
+
|
168
166
|
def check_name(input)
|
169
167
|
name = input.to_s.strip
|
170
|
-
if name =~ /[^\w\.\-_]/
|
168
|
+
if name =~ /[^\w\.\-_\*]/
|
171
169
|
raise NameInvalid, "Invalid Question Name `#{name}'"
|
172
170
|
end
|
171
|
+
|
173
172
|
name
|
174
173
|
end
|
175
|
-
|
174
|
+
|
176
175
|
def new_from_binary(data)
|
177
|
-
|
176
|
+
raise NameInvalid if data.size <= 4
|
177
|
+
|
178
|
+
str, type, cls = data.unpack("a#{data.size - 4}nn")
|
178
179
|
@qName = build_qName(str)
|
179
180
|
@qType = Net::DNS::RR::Types.new type
|
180
181
|
@qClass = Net::DNS::RR::Classes.new cls
|
181
|
-
rescue StandardError
|
182
|
+
rescue StandardError
|
182
183
|
raise ArgumentError, "Invalid data: #{data.inspect}"
|
183
184
|
end
|
184
|
-
|
185
185
|
end
|
186
|
-
|
187
186
|
end
|
188
187
|
end
|
@@ -2,18 +2,16 @@ require 'socket'
|
|
2
2
|
require 'ipaddr'
|
3
3
|
|
4
4
|
class RawSocket # :nodoc:
|
5
|
-
|
6
5
|
@@id_arr = []
|
7
|
-
|
8
|
-
def initialize(src_addr,dest_addr)
|
9
|
-
|
6
|
+
|
7
|
+
def initialize(src_addr, dest_addr)
|
10
8
|
# Define socket
|
11
9
|
begin
|
12
10
|
@socket = Socket.new PF_INET, SOCK_RAW, IPPROTO_RAW
|
13
11
|
rescue SystemCallError => e
|
14
12
|
raise SystemCallError, "You must be root to use raw sockets! #{e}"
|
15
13
|
end
|
16
|
-
|
14
|
+
|
17
15
|
@socket.setsockopt IPPROTO_IP, IP_HDRINCL, 1
|
18
16
|
|
19
17
|
# Checks addresses
|
@@ -26,7 +24,7 @@ class RawSocket # :nodoc:
|
|
26
24
|
|
27
25
|
# Set correct protocol version in the header
|
28
26
|
@version = @dest_addr.ipv4? ? "0100" : "0110"
|
29
|
-
|
27
|
+
|
30
28
|
# Total lenght: must be overridden by subclasses
|
31
29
|
@tot_lenght = 20
|
32
30
|
|
@@ -38,49 +36,48 @@ class RawSocket # :nodoc:
|
|
38
36
|
@id = 1234
|
39
37
|
|
40
38
|
# Generate peer sockaddr
|
41
|
-
@to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
|
39
|
+
@to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
|
42
40
|
end
|
43
41
|
|
44
42
|
def send(payload = '')
|
45
|
-
packet = make_ip_header([
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
43
|
+
packet = make_ip_header([
|
44
|
+
[@version + '0101', 'B8'], # version, hlen
|
45
|
+
[0, 'C'], # tos
|
46
|
+
[@tot_lenght + payload.size, 'n'], # total len
|
47
|
+
[@id, 'n'], # id
|
48
|
+
[0, 'n'], # flags, offset
|
49
|
+
[64, 'C'], # ttl
|
50
|
+
[@protocol, 'C'], # protocol
|
51
|
+
[0, 'n'], # checksum
|
52
|
+
[@src_addr.to_i, 'N'], # source
|
53
|
+
[@dest_addr.to_i, 'N'], # destination
|
54
|
+
])
|
56
55
|
packet << make_transport_header(payload.size)
|
57
56
|
packet << [payload].pack("a*")
|
58
|
-
@socket.send(packet,0
|
59
|
-
end
|
57
|
+
@socket.send(packet, 0, @to)
|
58
|
+
end
|
60
59
|
|
61
60
|
private
|
62
|
-
|
63
|
-
def check_addr
|
61
|
+
|
62
|
+
def check_addr(addr)
|
64
63
|
case addr
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
else
|
70
|
-
raise ArgumentError, "Wrong address format: #{addr}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def check_port port
|
75
|
-
if (1..65535).include? port and port.kind_of? Integer
|
76
|
-
port
|
64
|
+
when String
|
65
|
+
IPAddr.new(addr)
|
66
|
+
when IPAddr
|
67
|
+
addr
|
77
68
|
else
|
78
|
-
raise ArgumentError, "
|
69
|
+
raise ArgumentError, "Wrong address format: #{addr}"
|
79
70
|
end
|
80
71
|
end
|
81
|
-
|
72
|
+
|
73
|
+
def check_port(port)
|
74
|
+
raise ArgumentError, "Port #{port} not valid" unless (1..65_535).cover?(port) && port.is_a?(Integer)
|
75
|
+
|
76
|
+
port
|
77
|
+
end
|
78
|
+
|
82
79
|
def genID
|
83
|
-
while
|
80
|
+
while @@id_arr.include?(q = rand(65_535))
|
84
81
|
end
|
85
82
|
@@id_arr.push(q)
|
86
83
|
q
|
@@ -103,34 +100,31 @@ class RawSocket # :nodoc:
|
|
103
100
|
data[-3] = checksum
|
104
101
|
data.pack(template)
|
105
102
|
end
|
106
|
-
|
103
|
+
|
107
104
|
def make_transport_header
|
108
105
|
""
|
109
106
|
end
|
110
|
-
|
111
107
|
end
|
112
108
|
|
113
109
|
class UdpRawSocket < RawSocket # :nodoc:
|
110
|
+
def initialize(src_addr, src_port, dest_addr, dest_port)
|
111
|
+
super(src_addr, dest_addr)
|
114
112
|
|
115
|
-
def initialize(src_addr,src_port,dest_addr,dest_port)
|
116
|
-
|
117
|
-
super(src_addr,dest_addr)
|
118
|
-
|
119
113
|
# Check ports
|
120
114
|
@src_port = check_port src_port
|
121
115
|
@dest_port = check_port dest_port
|
122
|
-
|
116
|
+
|
123
117
|
# Total lenght: must be overridden by subclasses
|
124
118
|
@tot_lenght = 20 + 8 # 8 bytes => UDP Header
|
125
119
|
|
126
120
|
# Protocol: must be overridden by subclasses
|
127
121
|
@protocol = 17 # UDP protocol
|
128
122
|
|
129
|
-
@to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
|
123
|
+
@to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
|
130
124
|
end
|
131
125
|
|
132
126
|
private
|
133
|
-
|
127
|
+
|
134
128
|
def make_udp_header(parts)
|
135
129
|
template = ''
|
136
130
|
data = []
|
@@ -139,16 +133,14 @@ class UdpRawSocket < RawSocket # :nodoc:
|
|
139
133
|
template << part[-1]
|
140
134
|
end
|
141
135
|
data.pack(template)
|
142
|
-
end
|
143
|
-
|
136
|
+
end
|
137
|
+
|
144
138
|
def make_transport_header(pay_size)
|
145
139
|
make_udp_header([
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
140
|
+
[@src_port, 'n'], # source port
|
141
|
+
[@dest_port, 'n'], # destination port
|
142
|
+
[8 + pay_size, 'n'], # len
|
143
|
+
[0, 'n'], # checksum (mandatory)
|
144
|
+
])
|
151
145
|
end
|
152
|
-
|
153
146
|
end
|
154
|
-
|
@@ -3,28 +3,19 @@ require 'timeout'
|
|
3
3
|
module Net # :nodoc:
|
4
4
|
module DNS
|
5
5
|
class Resolver
|
6
|
-
|
7
6
|
class DnsTimeout
|
8
|
-
|
9
7
|
attr_reader :seconds
|
10
8
|
|
11
|
-
|
12
9
|
def initialize(seconds)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
raise ArgumentError, "Invalid value for tcp timeout"
|
17
|
-
end
|
10
|
+
raise ArgumentError, "Invalid value for tcp timeout" unless seconds.is_a?(Numeric) && seconds >= 0
|
11
|
+
|
12
|
+
@seconds = seconds
|
18
13
|
end
|
19
14
|
|
20
15
|
# Returns a string representation of the timeout corresponding
|
21
16
|
# to the number of <tt>@seconds</tt>.
|
22
17
|
def to_s
|
23
|
-
|
24
|
-
@output.to_s
|
25
|
-
else
|
26
|
-
@seconds.to_s
|
27
|
-
end
|
18
|
+
@seconds == 0 ? @output.to_s : @seconds.to_s
|
28
19
|
end
|
29
20
|
|
30
21
|
def pretty_to_s
|
@@ -37,27 +28,26 @@ module Net # :nodoc:
|
|
37
28
|
# If @seconds is 0 or nil, no timeout is set.
|
38
29
|
def timeout(&block)
|
39
30
|
raise LocalJumpError, "no block given" unless block_given?
|
31
|
+
|
40
32
|
Timeout.timeout(@seconds, &block)
|
41
33
|
end
|
42
34
|
|
43
|
-
|
44
35
|
private
|
45
36
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
end
|
37
|
+
def transform(secs)
|
38
|
+
case secs
|
39
|
+
when 0
|
40
|
+
to_s
|
41
|
+
when 1..59
|
42
|
+
"#{secs} seconds"
|
43
|
+
when 60..3559
|
44
|
+
"#{secs / 60} minutes and #{secs % 60} seconds"
|
45
|
+
else
|
46
|
+
hours = secs / 3600
|
47
|
+
secs -= (hours * 3600)
|
48
|
+
"#{hours} hours, #{secs / 60} minutes and #{secs % 60} seconds"
|
59
49
|
end
|
60
|
-
|
50
|
+
end
|
61
51
|
end
|
62
52
|
|
63
53
|
class TcpTimeout < DnsTimeout
|
@@ -73,7 +63,6 @@ module Net # :nodoc:
|
|
73
63
|
super
|
74
64
|
end
|
75
65
|
end
|
76
|
-
|
77
66
|
end
|
78
67
|
end
|
79
|
-
end
|
68
|
+
end
|