net-dns 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +6 -14
  2. data/.gitignore +1 -1
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +3 -0
  5. data/.rubocop_defaults.yml +364 -0
  6. data/.rubocop_todo.yml +207 -0
  7. data/.travis.yml +9 -16
  8. data/CHANGELOG.md +12 -1
  9. data/Gemfile +6 -2
  10. data/LICENSE.txt +56 -0
  11. data/README.md +94 -77
  12. data/Rakefile +23 -56
  13. data/bin/console +14 -0
  14. data/demo/check_soa.rb +27 -38
  15. data/demo/threads.rb +3 -7
  16. data/lib/net/dns.rb +4 -11
  17. data/lib/net/dns/core_ext.rb +8 -15
  18. data/lib/net/dns/header.rb +58 -66
  19. data/lib/net/dns/names.rb +25 -23
  20. data/lib/net/dns/packet.rb +136 -139
  21. data/lib/net/dns/question.rb +36 -39
  22. data/lib/net/dns/resolver.rb +103 -113
  23. data/lib/net/dns/resolver/socks.rb +45 -51
  24. data/lib/net/dns/resolver/timeouts.rb +17 -26
  25. data/lib/net/dns/rr.rb +107 -117
  26. data/lib/net/dns/rr/a.rb +46 -55
  27. data/lib/net/dns/rr/aaaa.rb +40 -49
  28. data/lib/net/dns/rr/classes.rb +26 -29
  29. data/lib/net/dns/rr/cname.rb +33 -41
  30. data/lib/net/dns/rr/hinfo.rb +44 -56
  31. data/lib/net/dns/rr/mr.rb +33 -42
  32. data/lib/net/dns/rr/mx.rb +37 -47
  33. data/lib/net/dns/rr/ns.rb +33 -41
  34. data/lib/net/dns/rr/null.rb +8 -11
  35. data/lib/net/dns/rr/ptr.rb +14 -20
  36. data/lib/net/dns/rr/soa.rb +27 -30
  37. data/lib/net/dns/rr/srv.rb +13 -17
  38. data/lib/net/dns/rr/txt.rb +8 -11
  39. data/lib/net/dns/rr/types.rb +97 -99
  40. data/lib/net/dns/version.rb +5 -13
  41. data/net-dns.gemspec +17 -29
  42. data/{fixtures → spec/fixtures}/resolv.conf +0 -0
  43. data/spec/spec_helper.rb +14 -0
  44. data/spec/unit/resolver/dns_timeout_spec.rb +36 -0
  45. data/spec/unit/resolver/tcp_timeout_spec.rb +46 -0
  46. data/spec/unit/resolver/udp_timeout_spec.rb +46 -0
  47. data/test/test_helper.rb +12 -3
  48. data/test/{header_test.rb → unit/header_test.rb} +43 -46
  49. data/test/{names_test.rb → unit/names_test.rb} +1 -1
  50. data/test/{packet_test.rb → unit/packet_test.rb} +3 -5
  51. data/test/{question_test.rb → unit/question_test.rb} +3 -5
  52. data/test/{resolver_test.rb → unit/resolver_test.rb} +10 -13
  53. data/test/{rr → unit/rr}/a_test.rb +10 -17
  54. data/test/{rr → unit/rr}/aaaa_test.rb +7 -14
  55. data/test/{rr → unit/rr}/classes_test.rb +14 -16
  56. data/test/{rr → unit/rr}/cname_test.rb +7 -14
  57. data/test/{rr → unit/rr}/hinfo_test.rb +16 -22
  58. data/test/{rr → unit/rr}/mr_test.rb +12 -18
  59. data/test/{rr → unit/rr}/mx_test.rb +18 -24
  60. data/test/{rr → unit/rr}/ns_test.rb +10 -16
  61. data/test/{rr → unit/rr}/types_test.rb +10 -8
  62. data/test/{rr_test.rb → unit/rr_test.rb} +33 -37
  63. metadata +77 -49
  64. data/test/resolver/timeouts_test.rb +0 -109
@@ -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,50 @@ 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([[ @version+'0101', 'B8' ], # version, hlen
46
- [ 0, 'C' ], # tos
47
- [ @tot_lenght + payload.size, 'n' ], # total len
48
- [ @id, 'n' ], # id
49
- [ 0, 'n' ], # flags, offset
50
- [ 64, 'C' ], # ttl
51
- [ @protocol, 'C' ], # protocol
52
- [ 0, 'n' ], # checksum
53
- [ @src_addr.to_i, 'N' ], # source
54
- [ @dest_addr.to_i, 'N' ], # destination
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,@to)
59
- end
57
+ @socket.send(packet, 0, @to)
58
+ end
60
59
 
61
60
  private
62
-
63
- def check_addr addr
61
+
62
+ def check_addr(addr)
64
63
  case addr
65
- when String
66
- IPAddr.new(addr)
67
- when IPAddr
68
- addr
69
- else
70
- raise ArgumentError, "Wrong address format: #{addr}"
64
+ when String
65
+ IPAddr.new(addr)
66
+ when IPAddr
67
+ addr
68
+ else
69
+ raise ArgumentError, "Wrong address format: #{addr}"
71
70
  end
72
71
  end
73
-
74
- def check_port port
75
- if (1..65535).include? port and port.kind_of? Integer
72
+
73
+ def check_port(port)
74
+ if (1..65_535).cover?(port) && port.is_a?(Integer)
76
75
  port
77
76
  else
78
77
  raise ArgumentError, "Port #{port} not valid"
79
78
  end
80
79
  end
81
-
80
+
82
81
  def genID
83
- while (@@id_arr.include?(q = rand(65535)))
82
+ while @@id_arr.include?(q = rand(65_535))
84
83
  end
85
84
  @@id_arr.push(q)
86
85
  q
@@ -103,34 +102,31 @@ class RawSocket # :nodoc:
103
102
  data[-3] = checksum
104
103
  data.pack(template)
105
104
  end
106
-
105
+
107
106
  def make_transport_header
108
107
  ""
109
108
  end
110
-
111
109
  end
112
110
 
113
111
  class UdpRawSocket < RawSocket # :nodoc:
112
+ def initialize(src_addr, src_port, dest_addr, dest_port)
113
+ super(src_addr, dest_addr)
114
114
 
115
- def initialize(src_addr,src_port,dest_addr,dest_port)
116
-
117
- super(src_addr,dest_addr)
118
-
119
115
  # Check ports
120
116
  @src_port = check_port src_port
121
117
  @dest_port = check_port dest_port
122
-
118
+
123
119
  # Total lenght: must be overridden by subclasses
124
120
  @tot_lenght = 20 + 8 # 8 bytes => UDP Header
125
121
 
126
122
  # Protocol: must be overridden by subclasses
127
123
  @protocol = 17 # UDP protocol
128
124
 
129
- @to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
125
+ @to = Socket.pack_sockaddr_in @dest_port, @dest_addr.to_s
130
126
  end
131
127
 
132
128
  private
133
-
129
+
134
130
  def make_udp_header(parts)
135
131
  template = ''
136
132
  data = []
@@ -139,16 +135,14 @@ class UdpRawSocket < RawSocket # :nodoc:
139
135
  template << part[-1]
140
136
  end
141
137
  data.pack(template)
142
- end
143
-
138
+ end
139
+
144
140
  def make_transport_header(pay_size)
145
141
  make_udp_header([
146
- [ @src_port, 'n'], # source port
147
- [ @dest_port, 'n' ], # destination port
148
- [ 8 + pay_size, 'n' ], # len
149
- [ 0, 'n' ] # checksum (mandatory)
150
- ])
142
+ [@src_port, 'n'], # source port
143
+ [@dest_port, 'n'], # destination port
144
+ [8 + pay_size, 'n'], # len
145
+ [0, 'n'] # checksum (mandatory)
146
+ ])
151
147
  end
152
-
153
148
  end
154
-
@@ -3,14 +3,11 @@ 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
- if seconds.is_a? Numeric and seconds >= 0
10
+ if seconds.is_a?(Numeric) && seconds >= 0
14
11
  @seconds = seconds
15
12
  else
16
13
  raise ArgumentError, "Invalid value for tcp timeout"
@@ -20,11 +17,7 @@ module Net # :nodoc:
20
17
  # Returns a string representation of the timeout corresponding
21
18
  # to the number of <tt>@seconds</tt>.
22
19
  def to_s
23
- if @seconds == 0
24
- @output.to_s
25
- else
26
- @seconds.to_s
27
- end
20
+ @seconds == 0 ? @output.to_s : @seconds.to_s
28
21
  end
29
22
 
30
23
  def pretty_to_s
@@ -37,27 +30,26 @@ module Net # :nodoc:
37
30
  # If @seconds is 0 or nil, no timeout is set.
38
31
  def timeout(&block)
39
32
  raise LocalJumpError, "no block given" unless block_given?
33
+
40
34
  Timeout.timeout(@seconds, &block)
41
35
  end
42
36
 
43
-
44
37
  private
45
38
 
46
- def transform(secs)
47
- case secs
48
- when 0
49
- to_s
50
- when 1..59
51
- "#{secs} seconds"
52
- when 60..3559
53
- "#{secs / 60} minutes and #{secs % 60} seconds"
54
- else
55
- hours = secs / 3600
56
- secs -= (hours * 3600)
57
- "#{hours} hours, #{secs / 60} minutes and #{secs % 60} seconds"
58
- end
39
+ def transform(secs)
40
+ case secs
41
+ when 0
42
+ to_s
43
+ when 1..59
44
+ "#{secs} seconds"
45
+ when 60..3559
46
+ "#{secs / 60} minutes and #{secs % 60} seconds"
47
+ else
48
+ hours = secs / 3600
49
+ secs -= (hours * 3600)
50
+ "#{hours} hours, #{secs / 60} minutes and #{secs % 60} seconds"
59
51
  end
60
-
52
+ end
61
53
  end
62
54
 
63
55
  class TcpTimeout < DnsTimeout
@@ -73,7 +65,6 @@ module Net # :nodoc:
73
65
  super
74
66
  end
75
67
  end
76
-
77
68
  end
78
69
  end
79
- end
70
+ end
@@ -1,15 +1,14 @@
1
1
  require 'ipaddr'
2
- require 'net/dns/names'
3
- require 'net/dns/rr/types'
4
- require 'net/dns/rr/classes'
2
+ require_relative 'names'
3
+ require_relative 'rr/types'
4
+ require_relative 'rr/classes'
5
5
 
6
- %w(a aaaa cname hinfo mr mx ns ptr soa srv txt).each do |file|
7
- require "net/dns/rr/#{file}"
6
+ %w[a aaaa cname hinfo mr mx ns ptr soa srv txt].each do |file|
7
+ require_relative "rr/#{file}"
8
8
  end
9
9
 
10
10
  module Net
11
11
  module DNS
12
-
13
12
  #
14
13
  # = Net::DNS::RR - DNS Resource Record class
15
14
  #
@@ -42,7 +41,6 @@ module Net
42
41
  class RR
43
42
  include Names
44
43
 
45
-
46
44
  # Base error class.
47
45
  class Error < StandardError
48
46
  end
@@ -51,7 +49,6 @@ module Net
51
49
  class DataError < Error
52
50
  end
53
51
 
54
-
55
52
  # Regexp matching an RR string
56
53
  RR_REGEXP = Regexp.new("^\\s*(\\S+)\\s*(\\d+)?\\s+(" +
57
54
  Net::DNS::RR::Classes.regexp +
@@ -63,7 +60,6 @@ module Net
63
60
  # RR portion of the packet, in bytes
64
61
  RRFIXEDSZ = 10
65
62
 
66
-
67
63
  # Create a new instance of Net::DNS::RR class, or an instance of
68
64
  # any of the subclass of the appropriate type.
69
65
  #
@@ -108,12 +104,12 @@ module Net
108
104
  #
109
105
  def initialize(arg)
110
106
  instance = case arg
111
- when String
112
- new_from_string(arg)
113
- when Hash
114
- new_from_hash(arg)
115
- else
116
- raise ArgumentError, "Invalid argument, must be a RR string or an hash of values"
107
+ when String
108
+ new_from_string(arg)
109
+ when Hash
110
+ new_from_hash(arg)
111
+ else
112
+ raise ArgumentError, "Invalid argument, must be a RR string or an hash of values"
117
113
  end
118
114
 
119
115
  if @type.to_s == "ANY"
@@ -133,7 +129,7 @@ module Net
133
129
  # This method is used when parsing a binary packet by the Packet
134
130
  # class.
135
131
  #
136
- def RR.parse(data)
132
+ def self.parse(data)
137
133
  o = allocate
138
134
  obj, offset = o.send(:new_from_binary, data, 0)
139
135
  obj
@@ -146,18 +142,14 @@ module Net
146
142
  # Return an instance of appropriate class and the offset
147
143
  # pointing at the end of the data parsed.
148
144
  #
149
- def RR.parse_packet(data, offset)
145
+ def self.parse_packet(data, offset)
150
146
  o = allocate
151
147
  o.send(:new_from_binary, data, offset)
152
148
  end
153
149
 
154
- def name
155
- @name
156
- end
150
+ attr_reader :name
157
151
 
158
- def ttl
159
- @ttl
160
- end
152
+ attr_reader :ttl
161
153
 
162
154
  # Type accessor
163
155
  def type
@@ -169,16 +161,13 @@ module Net
169
161
  @cls.to_s
170
162
  end
171
163
 
172
-
173
164
  def value
174
165
  get_inspect
175
166
  end
176
167
 
177
168
  # Data belonging to that appropriate class,
178
169
  # not to be used (use real accessors instead)
179
- def rdata
180
- @rdata
181
- end
170
+ attr_reader :rdata
182
171
 
183
172
  # Return the RR object in binary data format, suitable
184
173
  # for using in network streams.
@@ -201,14 +190,13 @@ module Net
201
190
  #
202
191
  # TO FIX in one of the future releases
203
192
  #
204
- def comp_data(offset,compnames)
193
+ def comp_data(offset, compnames)
205
194
  str, offset, names = dn_comp(@name, offset, compnames)
206
195
  str += [@type.to_i, @cls.to_i, ttl, @rdlength].pack("n2 N n")
207
196
  offset += Net::DNS::RRFIXEDSZ
208
197
  [str, offset, names]
209
198
  end
210
199
 
211
-
212
200
  # Returns a human readable representation of this record.
213
201
  # The value is always a String.
214
202
  #
@@ -226,7 +214,7 @@ module Net
226
214
  # #=> "example.com. 7200 IN MX 10 mailhost.example.com."
227
215
  #
228
216
  def to_s
229
- items = to_a.map { |e| e.to_s }
217
+ items = to_a.map(&:to_s)
230
218
  if @name.size < 24
231
219
  items.pack("A24 A8 A8 A8 A*")
232
220
  else
@@ -244,123 +232,125 @@ module Net
244
232
  [name, ttl, cls.to_s, type.to_s, value]
245
233
  end
246
234
 
247
-
248
235
  private
249
236
 
250
- def new_from_string(rrstring)
251
- unless rrstring =~ RR_REGEXP
252
- raise ArgumentError,
253
- "Format error for RR string (maybe CLASS and TYPE not valid?)"
254
- end
237
+ def new_from_string(rrstring)
238
+ unless rrstring =~ RR_REGEXP
239
+ raise ArgumentError,
240
+ "Format error for RR string (maybe CLASS and TYPE not valid?)"
241
+ end
255
242
 
256
- # Name of RR - mandatory
257
- begin
258
- @name = $1.downcase
259
- rescue NoMethodError
260
- raise ArgumentError, "Missing name field in RR string #{rrstring}"
261
- end
243
+ # Name of RR - mandatory
244
+ begin
245
+ @name = Regexp.last_match(1).downcase
246
+ rescue NoMethodError
247
+ raise ArgumentError, "Missing name field in RR string #{rrstring}"
248
+ end
262
249
 
263
- # Time to live for RR, default 3 hours
264
- @ttl = $2 ? $2.to_i : 10800
250
+ # Time to live for RR, default 3 hours
251
+ @ttl = Regexp.last_match(2) ? Regexp.last_match(2).to_i : 10_800
265
252
 
266
- # RR class, default to IN
267
- @cls = Net::DNS::RR::Classes.new $3
253
+ # RR class, default to IN
254
+ @cls = Net::DNS::RR::Classes.new Regexp.last_match(3)
268
255
 
269
- # RR type, default to A
270
- @type = Net::DNS::RR::Types.new $4
256
+ # RR type, default to A
257
+ @type = Net::DNS::RR::Types.new Regexp.last_match(4)
271
258
 
272
- # All the rest is data
273
- @rdata = $5 ? $5.strip : ""
259
+ # All the rest is data
260
+ @rdata = Regexp.last_match(5) ? Regexp.last_match(5).strip : ""
274
261
 
275
- if self.class == Net::DNS::RR
276
- Net::DNS::RR.const_get(@type.to_s).new(rrstring)
277
- else
278
- subclass_new_from_string(@rdata)
279
- self.class
280
- end
262
+ if self.class == Net::DNS::RR
263
+ Net::DNS::RR.const_get(@type.to_s).new(rrstring)
264
+ else
265
+ subclass_new_from_string(@rdata)
266
+ self.class
281
267
  end
268
+ end
282
269
 
283
- def new_from_hash(args)
284
- # Name field is mandatory
285
- unless args.has_key? :name
286
- raise ArgumentError, ":name field is mandatory"
287
- end
270
+ def new_from_hash(args)
271
+ # Name field is mandatory
272
+ unless args.key? :name
273
+ raise ArgumentError, ":name field is mandatory"
274
+ end
288
275
 
289
- @name = args[:name].downcase
290
- @ttl = args[:ttl] ? args[:ttl].to_i : 10800 # Default 3 hours
291
- @type = Net::DNS::RR::Types.new args[:type]
292
- @cls = Net::DNS::RR::Classes.new args[:cls]
276
+ @name = args[:name].downcase
277
+ @ttl = args[:ttl] ? args[:ttl].to_i : 10_800 # Default 3 hours
278
+ @type = Net::DNS::RR::Types.new args[:type]
279
+ @cls = Net::DNS::RR::Classes.new args[:cls]
293
280
 
294
- @rdata = args[:rdata] ? args[:rdata].strip : ""
295
- @rdlength = args[:rdlength] || @rdata.size
281
+ @rdata = args[:rdata] ? args[:rdata].strip : ""
282
+ @rdlength = args[:rdlength] || @rdata.size
296
283
 
297
- if self.class == Net::DNS::RR
298
- Net::DNS::RR.const_get(@type.to_s).new(args)
284
+ if self.class == Net::DNS::RR
285
+ Net::DNS::RR.const_get(@type.to_s).new(args)
286
+ else
287
+ hash = args - %i[name ttl type cls]
288
+ if hash.key? :rdata
289
+ subclass_new_from_string(hash[:rdata])
299
290
  else
300
- hash = args - [:name, :ttl, :type, :cls]
301
- if hash.has_key? :rdata
302
- subclass_new_from_string(hash[:rdata])
303
- else
304
- subclass_new_from_hash(hash)
305
- end
306
- self.class
291
+ subclass_new_from_hash(hash)
307
292
  end
293
+ self.class
308
294
  end
295
+ end
309
296
 
310
- def new_from_binary(data,offset)
311
- if self.class == Net::DNS::RR
312
- temp = dn_expand(data,offset)[1]
313
- type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0]
314
- (eval "Net::DNS::RR::#{type}").parse_packet(data,offset)
315
- else
316
- @name,offset = dn_expand(data,offset)
317
- rrtype,cls,@ttl,@rdlength = data.unpack("@#{offset} n2 N n")
318
- @type = Net::DNS::RR::Types.new rrtype
319
- @cls = Net::DNS::RR::Classes.new cls
320
- offset += RRFIXEDSZ
321
- offset = subclass_new_from_binary(data,offset)
322
- build_pack
323
- set_type
324
- [self, offset]
325
- end
297
+ def new_from_binary(data, offset)
298
+ if self.class == Net::DNS::RR
299
+ temp = dn_expand(data, offset)[1]
300
+ type = Net::DNS::RR::Types.new data.unpack("@#{temp} n")[0]
301
+ (eval "Net::DNS::RR::#{type}").parse_packet(data, offset)
302
+ else
303
+ @name, offset = dn_expand(data, offset)
304
+ rrtype, cls, @ttl, @rdlength = data.unpack("@#{offset} n2 N n")
305
+ @type = Net::DNS::RR::Types.new rrtype
306
+ @cls = Net::DNS::RR::Classes.new cls
307
+ offset += RRFIXEDSZ
308
+ offset = subclass_new_from_binary(data, offset)
309
+ build_pack
310
+ set_type
311
+ [self, offset]
326
312
  end
313
+ end
327
314
 
328
- # Methods to be overridden by subclasses
329
- def subclass_new_from_array(arr)
330
- end
331
- def subclass_new_from_string(str)
332
- end
333
- def subclass_new_from_hash(hash)
334
- end
335
- def subclass_new_from_binary(data, offset)
336
- end
337
- def build_pack
338
- end
339
- def get_inspect
340
- @rdata
341
- end
342
- def get_data
343
- @rdata
344
- end
315
+ # Methods to be overridden by subclasses
316
+ def subclass_new_from_array(arr)
317
+ end
345
318
 
346
- def set_type
347
- # TODO: Here we should probably
348
- # raise NotImplementedError
349
- # if we want the method to be implemented in any subclass.
350
- end
319
+ def subclass_new_from_string(str)
320
+ end
351
321
 
322
+ def subclass_new_from_hash(hash)
323
+ end
324
+
325
+ def subclass_new_from_binary(data, offset)
326
+ end
327
+
328
+ def build_pack
329
+ end
330
+
331
+ def get_inspect
332
+ @rdata
333
+ end
334
+
335
+ def get_data
336
+ @rdata
337
+ end
338
+
339
+ def set_type
340
+ # TODO: Here we should probably
341
+ # raise NotImplementedError
342
+ # if we want the method to be implemented in any subclass.
343
+ end
352
344
 
353
345
  def self.new(*args)
354
346
  o = allocate
355
- obj = o.send(:initialize,*args)
347
+ obj = o.send(:initialize, *args)
356
348
  if self == Net::DNS::RR
357
349
  obj
358
350
  else
359
351
  o
360
352
  end
361
353
  end
362
-
363
354
  end
364
-
365
355
  end
366
356
  end