net-dns 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.gitignore +8 -6
  2. data/.travis.yml +14 -0
  3. data/CHANGELOG.md +79 -0
  4. data/Gemfile +4 -0
  5. data/Rakefile +56 -66
  6. data/demo/check_soa.rb +1 -1
  7. data/demo/threads.rb +1 -1
  8. data/lib/net/dns.rb +24 -22
  9. data/lib/net/dns/header.rb +77 -103
  10. data/lib/net/dns/{names/names.rb → names.rb} +19 -20
  11. data/lib/net/dns/packet.rb +231 -256
  12. data/lib/net/dns/question.rb +11 -40
  13. data/lib/net/dns/resolver.rb +248 -250
  14. data/lib/net/dns/resolver/socks.rb +6 -6
  15. data/lib/net/dns/resolver/timeouts.rb +1 -1
  16. data/lib/net/dns/rr.rb +112 -117
  17. data/lib/net/dns/rr/a.rb +98 -89
  18. data/lib/net/dns/rr/aaaa.rb +84 -68
  19. data/lib/net/dns/rr/classes.rb +91 -106
  20. data/lib/net/dns/rr/cname.rb +64 -45
  21. data/lib/net/dns/rr/hinfo.rb +90 -50
  22. data/lib/net/dns/rr/mr.rb +61 -44
  23. data/lib/net/dns/rr/mx.rb +73 -48
  24. data/lib/net/dns/rr/ns.rb +60 -46
  25. data/lib/net/dns/rr/null.rb +11 -12
  26. data/lib/net/dns/rr/ptr.rb +47 -34
  27. data/lib/net/dns/rr/soa.rb +5 -6
  28. data/lib/net/dns/rr/srv.rb +1 -4
  29. data/lib/net/dns/rr/txt.rb +14 -14
  30. data/lib/net/dns/rr/types.rb +13 -13
  31. data/lib/net/dns/version.rb +8 -14
  32. data/net-dns.gemspec +35 -0
  33. data/setup.rb +3 -2
  34. data/test/header_test.rb +18 -18
  35. data/test/names_test.rb +21 -0
  36. data/test/packet_test.rb +38 -31
  37. data/test/question_test.rb +23 -24
  38. data/test/resolver/timeouts_test.rb +13 -13
  39. data/test/resolver_test.rb +28 -20
  40. data/test/rr/a_test.rb +70 -23
  41. data/test/rr/aaaa_test.rb +109 -0
  42. data/test/rr/classes_test.rb +61 -49
  43. data/test/rr/cname_test.rb +97 -0
  44. data/test/rr/hinfo_test.rb +117 -0
  45. data/test/rr/mr_test.rb +105 -0
  46. data/test/rr/mx_test.rb +112 -0
  47. data/test/rr/ns_test.rb +34 -12
  48. data/test/rr/types_test.rb +4 -4
  49. data/test/rr_test.rb +1 -1
  50. metadata +77 -52
  51. data/AUTHORS.rdoc +0 -7
  52. data/CHANGELOG.rdoc +0 -46
  53. data/VERSION.yml +0 -5
@@ -1,23 +1,19 @@
1
- module Net
2
- module DNS
3
-
1
+ module Net # :nodoc:
2
+ module DNS
3
+
4
4
  module Names
5
-
6
- # Argument Error for class Net::DNS::Names.
7
- class ArgumentError < ArgumentError
8
- end
9
-
5
+
10
6
  # Base error class.
11
7
  class Error < StandardError
12
8
  end
13
-
9
+
14
10
  # Generic Names Error.
15
11
  class ExpandError < Error
16
12
  end
17
-
18
-
13
+
14
+
19
15
  INT16SZ = 2
20
-
16
+
21
17
  # Expand a compressed name in a DNS Packet object. Please
22
18
  # see RFC1025 for an explanation of how the compression
23
19
  # in DNS packets works, how may it be useful and how should
@@ -33,7 +29,7 @@ module Net
33
29
  while true
34
30
  raise ExpandError, "Offset is greater than packet lenght!" if packetlen < (offset+1)
35
31
  len = packet.unpack("@#{offset} C")[0]
36
-
32
+
37
33
  if len == 0
38
34
  offset += 1
39
35
  break
@@ -54,16 +50,19 @@ module Net
54
50
  offset += len
55
51
  end
56
52
  end
57
- return [name,offset] # name.chomp(".") if trailing dot has to be omitted
53
+ [name, offset] # name.chomp(".") if trailing dot has to be omitted
58
54
  end
59
-
55
+
60
56
  def pack_name(name)
61
- if name.size > 63
62
- raise ArgumentError, "Label data cannot exceed 63 chars"
57
+ if name.size > 255
58
+ raise ArgumentError, "Name may not exceed 255 chars"
63
59
  end
64
60
  arr = name.split(".")
65
61
  str = ""
66
62
  arr.each do |elem|
63
+ if elem.size > 63
64
+ raise ArgumentError, "Label may not exceed 63 chars"
65
+ end
67
66
  str += [elem.size,elem].pack("Ca*")
68
67
  end
69
68
  str += [0].pack("C")
@@ -105,7 +104,7 @@ module Net
105
104
  end
106
105
  return str,offset,names
107
106
  end
108
-
107
+
109
108
  def valid?(name)
110
109
  if name =~ /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/i
111
110
  return name
@@ -113,7 +112,7 @@ module Net
113
112
  raise ArgumentError, "Invalid FQDN: #{name}"
114
113
  end
115
114
  end
116
-
115
+
117
116
  end
118
117
  end
119
- end
118
+ end
@@ -1,36 +1,28 @@
1
1
  require 'logger'
2
- require 'net/dns/names/names'
3
- require 'net/dns'
2
+ require 'net/dns/names'
4
3
  require 'net/dns/header'
5
4
  require 'net/dns/question'
6
5
  require 'net/dns/rr'
7
6
 
8
- module Net # :nodoc:
9
- module DNS
10
-
11
- # =Name
12
- #
13
- # Net::DNS::Packet - DNS packet object class
7
+ module Net
8
+ module DNS
9
+
14
10
  #
15
- # =Synopsis
16
- #
17
- # require 'net/dns/packet'
11
+ # = Net::DNS::Packet
18
12
  #
19
- # =Description
20
- #
21
13
  # The Net::DNS::Packet class represents an entire DNS packet,
22
- # divided in his main section:
23
- #
14
+ # divided in his main section:
15
+ #
24
16
  # * Header (instance of Net::DNS::Header)
25
17
  # * Question (array of Net::DNS::Question objects)
26
- # * Answer, Authority, Additional (each formed by an array of Net::DNS::RR
18
+ # * Answer, Authority, Additional (each formed by an array of Net::DNS::RR
27
19
  # objects)
28
20
  #
29
21
  # You can use this class whenever you need to create a DNS packet, whether
30
22
  # in an user application, in a resolver instance (have a look, for instance,
31
- # at the Net::DNS::Resolver#send method) or for a nameserver.
23
+ # at the <tt>Net::DNS::Resolver#send</tt> method) or for a nameserver.
32
24
  #
33
- # Some example:
25
+ # For example:
34
26
  #
35
27
  # # Create a packet
36
28
  # packet = Net::DNS::Packet.new("www.example.com")
@@ -39,7 +31,7 @@ module Net # :nodoc:
39
31
  # # Getting packet binary data, suitable for network transmission
40
32
  # data = packet.data
41
33
  #
42
- # A packet object can be created from binary data too, like an
34
+ # A packet object can be created from binary data too, like an
43
35
  # answer packet just received from a network stream:
44
36
  #
45
37
  # packet = Net::DNS::Packet::parse(data)
@@ -48,13 +40,13 @@ module Net # :nodoc:
48
40
  #
49
41
  # header = packet.header # Instance of Net::DNS::Header class
50
42
  # question = packet.question # Instance of Net::DNS::Question class
51
- #
43
+ #
52
44
  # # Iterate over additional RRs
53
45
  # packet.additional.each do |rr|
54
46
  # puts "Got an #{rr.type} record"
55
47
  # end
56
48
  #
57
- # Some iterators have been written to easy the access of those RRs,
49
+ # Some iterators have been written to easy the access of those RRs,
58
50
  # which are often the most important. So instead of doing:
59
51
  #
60
52
  # packet.answer.each do |rr|
@@ -71,10 +63,10 @@ module Net # :nodoc:
71
63
  #
72
64
  # Be sure you don't miss all the iterators in the class documentation.
73
65
  #
74
- # =Logging facility
75
- #
66
+ # == Logging facility
67
+ #
76
68
  # As Net::DNS::Resolver class, Net::DNS::Packet class has its own logging
77
- # facility too. It work in the same way the other one do, so you can
69
+ # facility too. It work in the same way the other one do, so you can
78
70
  # maybe want to override it or change the file descriptor.
79
71
  #
80
72
  # packet = Net::DNS::Packet.new("www.example.com")
@@ -83,49 +75,29 @@ module Net # :nodoc:
83
75
  # # or even
84
76
  # packet.logger = Logger.new("/tmp/packet.log")
85
77
  #
86
- # If the Net::DNS::Packet class is directly instantiated by the Net::DNS::Resolver
78
+ # If the <tt>Net::DNS::Packet</tt> class is directly instantiated by the <tt>Net::DNS::Resolver</tt>
87
79
  # class, like the great majority of the time, it will use the same logger facility.
88
80
  #
89
- # Logger level will be set to Logger::Debug if $DEBUG variable is set.
90
- #
91
- # =Error classes
92
- #
93
- # Some error classes has been defined for the Net::DNS::Packet class,
94
- # which are listed here to keep a light and browsable main documentation.
95
- # We have:
96
- #
97
- # ArgumentError:: Argument Error for class Net::DNS::Packet
98
- # PacketError:: Generic Packet Error
99
- #
100
- # =Copyright
101
- #
102
- # Copyright (c) 2006 Marco Ceresa
103
- #
104
- # All rights reserved. This program is free software; you may redistribute
105
- # it and/or modify it under the same terms as Ruby itself.
81
+ # Logger level will be set to <tt>Logger::Debug</tt> if <tt>$DEBUG</tt> variable is set.
106
82
  #
107
83
  class Packet
108
84
  include Names
109
-
110
- # Argument Error for class Net::DNS::Packet.
111
- class ArgumentError < ArgumentError
112
- end
113
-
85
+
114
86
  # Base error class.
115
87
  class Error < StandardError
116
88
  end
117
-
89
+
118
90
  # Generic Packet Error.
119
91
  class PacketError < Error
120
92
  end
121
-
122
-
93
+
94
+
123
95
  attr_reader :header, :question, :answer, :authority, :additional
124
96
  attr_reader :answerfrom, :answersize
125
-
126
- # Create a new instance of Net::DNS::Packet class. Arguments are the
127
- # canonical name of the resourse, an optional type field and an optional
128
- # class field. The record type and class can be omitted; they default
97
+
98
+ # Creates a new instance of <tt>Net::DNS::Packet</tt> class. Arguments are the
99
+ # canonical name of the resource, an optional type field and an optional
100
+ # class field. The record type and class can be omitted; they default
129
101
  # to +A+ and +IN+.
130
102
  #
131
103
  # packet = Net::DNS::Packet.new("www.example.com")
@@ -133,8 +105,7 @@ module Net # :nodoc:
133
105
  # packet = Net::DNS::Packet.new("example.com", Net::DNS::TXT, Net::DNS::CH)
134
106
  #
135
107
  # This class no longer instantiate object from binary data coming from
136
- # network streams. Please use Net::DNS::Packet.new_from_data instead.
137
- #
108
+ # network streams. Please use <tt>Net::DNS::Packet.parse</tt> instead.
138
109
  def initialize(name, type = Net::DNS::A, cls = Net::DNS::IN)
139
110
  @header = Net::DNS::Header.new(:qdCount => 1)
140
111
  @question = [Net::DNS::Question.new(name, type, cls)]
@@ -145,33 +116,13 @@ module Net # :nodoc:
145
116
  @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
146
117
  end
147
118
 
148
- # Create a new instance of Net::DNS::Packet class from binary data, taken
149
- # out by a network stream. For example:
150
- #
151
- # # udp_socket is an UDPSocket waiting for a response
152
- # ans = udp_socket.recvfrom(1500)
153
- # packet = Net::DNS::Packet::parse(ans)
154
- #
155
- # An optional +from+ argument can be used to specify the information
156
- # of the sender. If data is passed as is from a Socket#recvfrom call,
157
- # the method will accept it.
158
- #
159
- # Be sure that your network data is clean from any UDP/TCP header,
160
- # expecially when using RAW sockets.
161
- #
162
- def Packet.parse(*args)
163
- o = allocate
164
- o.send(:new_from_data, *args)
165
- o
166
- end
167
-
168
119
 
169
120
  # Checks if the packet is a QUERY packet
170
121
  def query?
171
122
  @header.opCode == Net::DNS::Header::QUERY
172
123
  end
173
124
 
174
- # Return the packet object in binary data, suitable
125
+ # Returns the packet object in binary data, suitable
175
126
  # for sending across a network stream.
176
127
  #
177
128
  # packet_data = packet.data
@@ -181,7 +132,7 @@ module Net # :nodoc:
181
132
  qdcount=ancount=nscount=arcount=0
182
133
  data = @header.data
183
134
  headerlength = data.length
184
-
135
+
185
136
  @question.each do |question|
186
137
  data += question.data
187
138
  qdcount += 1
@@ -198,7 +149,7 @@ module Net # :nodoc:
198
149
  data += rr.data#(data.length)
199
150
  arcount += 1
200
151
  end
201
-
152
+
202
153
  @header.qdCount = qdcount
203
154
  @header.anCount = ancount
204
155
  @header.nsCount = nscount
@@ -207,13 +158,13 @@ module Net # :nodoc:
207
158
  @header.data + data[Net::DNS::HFIXEDSZ..data.size]
208
159
  end
209
160
 
210
- # Same as Net::DNS::Packet#data, but implements name compression
161
+ # Same as <tt>Net::DNS::Packet#data</tt>, but implements name compression
211
162
  # (see RFC1025) for a considerable save of bytes.
212
163
  #
213
164
  # packet = Net::DNS::Packet.new("www.example.com")
214
165
  # puts "Size normal is #{packet.data.size} bytes"
215
166
  # puts "Size compressed is #{packet.data_comp.size} bytes"
216
- #
167
+ #
217
168
  def data_comp
218
169
  offset = 0
219
170
  compnames = {}
@@ -227,46 +178,47 @@ module Net # :nodoc:
227
178
  compnames.update(names)
228
179
  qdcount += 1
229
180
  end
230
-
181
+
231
182
  @answer.each do |rr|
232
183
  str,offset,names = rr.data(offset,compnames)
233
184
  data += str
234
185
  compnames.update(names)
235
186
  ancount += 1
236
187
  end
237
-
188
+
238
189
  @authority.each do |rr|
239
190
  str,offset,names = rr.data(offset,compnames)
240
191
  data += str
241
192
  compnames.update(names)
242
193
  nscount += 1
243
194
  end
244
-
195
+
245
196
  @additional.each do |rr|
246
197
  str,offset,names = rr.data(offset,compnames)
247
198
  data += str
248
199
  compnames.update(names)
249
200
  arcount += 1
250
201
  end
251
-
202
+
252
203
  @header.qdCount = qdcount
253
204
  @header.anCount = ancount
254
205
  @header.nsCount = nscount
255
206
  @header.arCount = arcount
256
-
207
+
257
208
  @header.data + data[Net::DNS::HFIXEDSZ..data.size]
258
209
  end
259
-
260
- # Inspect method
210
+
211
+ # Returns a string containing a human-readable representation
212
+ # of this <tt>Net::DNS::Packet</tt> instance.
261
213
  def inspect
262
214
  retval = ""
263
215
  if @answerfrom != "0.0.0.0:0" and @answerfrom
264
216
  retval += ";; Answer received from #@answerfrom (#{@answersize} bytes)\n;;\n"
265
217
  end
266
-
218
+
267
219
  retval += ";; HEADER SECTION\n"
268
220
  retval += @header.inspect
269
-
221
+
270
222
  retval += "\n"
271
223
  section = (@header.opCode == "UPDATE") ? "ZONE" : "QUESTION"
272
224
  retval += ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '' : 's'}):\n"
@@ -291,7 +243,7 @@ module Net # :nodoc:
291
243
  retval += rr.inspect + "\n"
292
244
  end
293
245
  end
294
-
246
+
295
247
  unless @additional.size == 0
296
248
  retval += "\n"
297
249
  retval += ";; ADDITIONAL SECTION (#{@header.arCount} record#{@header.arCount == 1 ? '' : 's'}):\n"
@@ -299,20 +251,18 @@ module Net # :nodoc:
299
251
  retval += rr.inspect + "\n"
300
252
  end
301
253
  end
302
-
254
+
303
255
  retval
304
256
  end
305
- alias_method :to_s, :inspect
306
-
307
- # Wrapper to Header#truncated?
308
- #
257
+ alias_method :to_s, :inspect
258
+
259
+ # Delegates to <tt>Net::DNS::Header#truncated?</tt>.
309
260
  def truncated?
310
261
  @header.truncated?
311
262
  end
312
-
313
- # Assing a Net::DNS::Header object to a Net::DNS::Packet
314
- # instance.
315
- #
263
+
264
+ # Assigns a <tt>Net::DNS::Header</tt> <tt>object</tt>
265
+ # to this <tt>Net::DNS::Packet</tt> instance.
316
266
  def header=(object)
317
267
  if object.kind_of? Net::DNS::Header
318
268
  @header = object
@@ -320,10 +270,9 @@ module Net # :nodoc:
320
270
  raise ArgumentError, "Argument must be a Net::DNS::Header object"
321
271
  end
322
272
  end
323
-
324
- # Assign a Net::DNS::Question object, or an array of
325
- # Questions objects, to a Net::DNS::Packet instance.
326
- #
273
+
274
+ # Assigns a <tt>Net::DNS::Question</tt> <tt>object</tt>
275
+ # to this <tt>Net::DNS::Packet</tt> instance.
327
276
  def question=(object)
328
277
  case object
329
278
  when Array
@@ -339,250 +288,276 @@ module Net # :nodoc:
339
288
  end
340
289
  end
341
290
 
342
- # Assign a Net::DNS::RR object, or an array of
343
- # RR objects, to a Net::DNS::Packet instance answer
344
- # section.
345
- #
291
+ # Assigns one or an array of <tt>Net::DNS::RR</tt> <tt>object</tt>s
292
+ # to the answer section of this <tt>Net::DNS::Packet</tt> instance.
346
293
  def answer=(object)
347
294
  case object
348
- when Array
349
- if object.all? {|x| x.kind_of? Net::DNS::RR}
350
- @answer = object
295
+ when Array
296
+ if object.all? {|x| x.kind_of? Net::DNS::RR}
297
+ @answer = object
298
+ else
299
+ raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
300
+ end
301
+ when Net::DNS::RR
302
+ @answer = [object]
351
303
  else
352
- raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
353
- end
354
- when Net::DNS::RR
355
- @answer = [object]
356
- else
357
- raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
304
+ raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
358
305
  end
359
306
  end
360
307
 
361
- # Assign a Net::DNS::RR object, or an array of
362
- # RR objects, to a Net::DNS::Packet instance additional
363
- # section.
364
- #
308
+ # Assigns one or an array of <tt>Net::DNS::RR</tt> <tt>object</tt>s
309
+ # to the additional section of this <tt>Net::DNS::Packet</tt> instance.
365
310
  def additional=(object)
366
311
  case object
367
- when Array
368
- if object.all? {|x| x.kind_of? Net::DNS::RR}
369
- @additional = object
312
+ when Array
313
+ if object.all? {|x| x.kind_of? Net::DNS::RR}
314
+ @additional = object
315
+ else
316
+ raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
317
+ end
318
+ when Net::DNS::RR
319
+ @additional = [object]
370
320
  else
371
- raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
372
- end
373
- when Net::DNS::RR
374
- @additional = [object]
375
- else
376
- raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
321
+ raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
377
322
  end
378
323
  end
379
324
 
380
- # Assign a Net::DNS::RR object, or an array of
381
- # RR objects, to a Net::DNS::Packet instance authority
382
- # section.
383
- #
325
+ # Assigns one or an array of <tt>Net::DNS::RR</tt> <tt>object</tt>s
326
+ # to the authority section of this <tt>Net::DNS::Packet</tt> instance.
384
327
  def authority=(object)
385
328
  case object
386
- when Array
387
- if object.all? {|x| x.kind_of? Net::DNS::RR}
388
- @authority = object
329
+ when Array
330
+ if object.all? {|x| x.kind_of? Net::DNS::RR}
331
+ @authority = object
332
+ else
333
+ raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
334
+ end
335
+ when Net::DNS::RR
336
+ @authority = [object]
389
337
  else
390
- raise ArgumentError, "Some of the elements is not an Net::DNS::RR object"
391
- end
392
- when Net::DNS::RR
393
- @authority = [object]
394
- else
395
- raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
338
+ raise ArgumentError, "Invalid argument, not a RR object nor an array of objects"
396
339
  end
397
340
  end
398
-
399
- # Iterate for every address in the +answer+ section of a
400
- # Net::DNS::Packet object.
341
+
342
+ # Iterates every address in the +answer+ section
343
+ # of this <tt>Net::DNS::Packet</tt> instance.
401
344
  #
402
345
  # packet.each_address do |ip|
403
346
  # ping ip.to_s
404
347
  # end
405
348
  #
406
- # As you can see in the documentation for Net::DNS::RR::A class,
407
- # the address returned is an instance of IPAddr class.
408
- #
409
- def each_address
349
+ # As you can see in the documentation for the <tt>Net::DNS::RR::A</tt> class,
350
+ # the address returned is an instance of <tt>IPAddr</tt> class.
351
+ def each_address(&block)
410
352
  @answer.each do |elem|
411
353
  next unless elem.class == Net::DNS::RR::A
412
354
  yield elem.address
413
355
  end
414
356
  end
415
-
416
- # Iterate for every nameserver in the +answer+ section of a
417
- # Net::DNS::Packet object.
357
+
358
+ # Iterates every nameserver in the +answer+ section
359
+ # of this <tt>Net::DNS::Packet</tt> instance.
418
360
  #
419
361
  # packet.each_nameserver do |ns|
420
362
  # puts "Nameserver found: #{ns}"
421
363
  # end
422
364
  #
423
- def each_nameserver
365
+ def each_nameserver(&block)
424
366
  @answer.each do |elem|
425
367
  next unless elem.class == Net::DNS::RR::NS
426
368
  yield elem.nsdname
427
369
  end
428
370
  end
429
-
430
- # Iterate for every exchange record in the +answer+ section
431
- # of a Net::DNS::Packet object.
371
+
372
+ # Iterates every exchange record in the +answer+ section
373
+ # of this <tt>Net::DNS::Packet</tt> instance.
432
374
  #
433
375
  # packet.each_mx do |pref,name|
434
376
  # puts "Mail exchange #{name} has preference #{pref}"
435
377
  # end
436
378
  #
437
- def each_mx
379
+ def each_mx(&block)
438
380
  @answer.each do |elem|
439
381
  next unless elem.class == Net::DNS::RR::MX
440
- yield elem.preference,elem.exchange
382
+ yield elem.preference, elem.exchange
441
383
  end
442
384
  end
443
-
444
- # Iterate for every canonical name in the +answer+ section
445
- # of a Net::DNS::Packet object.
385
+
386
+ # Iterates every canonical name in the +answer+ section
387
+ # of this <tt>Net::DNS::Packet</tt> instance.
446
388
  #
447
389
  # packet.each_cname do |cname|
448
390
  # puts "Canonical name: #{cname}"
449
391
  # end
450
392
  #
451
- def each_cname
393
+ def each_cname(&block)
452
394
  @answer.each do |elem|
453
395
  next unless elem.class == Net::DNS::RR::CNAME
454
396
  yield elem.cname
455
397
  end
456
398
  end
457
-
458
- # Iterate for every pointer in the +answer+ section of a
459
- # Net::DNS::Packet object.
399
+
400
+ # Iterates every pointer in the +answer+ section
401
+ # of this <tt>Net::DNS::Packet</tt> instance.
460
402
  #
461
403
  # packet.each_ptr do |ptr|
462
404
  # puts "Pointer for resource: #{ptr}"
463
405
  # end
464
406
  #
465
- def each_ptr
407
+ def each_ptr(&block)
466
408
  @answer.each do |elem|
467
409
  next unless elem.class == Net::DNS::RR::PTR
468
410
  yield elem.ptrdname
469
411
  end
470
412
  end
471
413
 
472
- # Returns the packet size in bytes
414
+ # Returns the packet size in bytes.
473
415
  #
474
- # Resolver("www.google.com") do |packet|
416
+ # Resolver("www.google.com") do |packet|
475
417
  # puts packet.size + " bytes"}
476
418
  # end
477
- # #=> 484 bytes
419
+ # # => 484 bytes
478
420
  #
479
421
  def size
480
422
  data.size
481
423
  end
482
424
 
483
- # Checks whether a query has returned a NXDOMAIN error,
484
- # meaning the domain name queried doesn't exists.
425
+ # Checks whether the query returned a NXDOMAIN error,
426
+ # meaning the queried domain name doesn't exist.
485
427
  #
486
428
  # %w[a.com google.com ibm.com d.com].each do |domain|
487
429
  # response = Net::DNS::Resolver.new.send(domain)
488
430
  # puts "#{domain} doesn't exist" if response.nxdomain?
489
431
  # end
490
- # #=> a.com doesn't exist
491
- # #=> d.com doesn't exist
432
+ # # => a.com doesn't exist
433
+ # # => d.com doesn't exist
492
434
  #
493
435
  def nxdomain?
494
436
  header.rCode.code == Net::DNS::Header::RCode::NAME
495
437
  end
496
-
438
+
439
+
440
+ # Creates a new instance of <tt>Net::DNS::Packet</tt> class from binary data,
441
+ # taken out from a network stream. For example:
442
+ #
443
+ # # udp_socket is an UDPSocket waiting for a response
444
+ # ans = udp_socket.recvfrom(1500)
445
+ # packet = Net::DNS::Packet::parse(ans)
446
+ #
447
+ # An optional +from+ argument can be used to specify the information
448
+ # of the sender. If data is passed as is from a Socket#recvfrom call,
449
+ # the method will accept it.
450
+ #
451
+ # Be sure that your network data is clean from any UDP/TCP header,
452
+ # especially when using RAW sockets.
453
+ #
454
+ def self.parse(*args)
455
+ o = allocate
456
+ o.send(:new_from_data, *args)
457
+ o
458
+ end
459
+
497
460
  private
498
461
 
499
- # New packet from binary data
500
- def new_from_data(data, from = nil)
501
- unless from
502
- if data.kind_of? Array
503
- data,from = data
504
- else
505
- from = [0,0,"0.0.0.0","unknown"]
462
+ # New packet from binary data
463
+ def new_from_data(data, from = nil)
464
+ unless from
465
+ if data.kind_of? Array
466
+ data, from = data
467
+ else
468
+ from = [0, 0, "0.0.0.0", "unknown"]
469
+ end
506
470
  end
507
- end
508
-
509
- @answerfrom = from[2] + ":" + from[1].to_s
510
- @answersize = data.size
511
- @logger = Logger.new $stdout
512
- @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
513
-
514
- #------------------------------------------------------------
515
- # Header section
516
- #------------------------------------------------------------
517
- offset = Net::DNS::HFIXEDSZ
518
- @header = Net::DNS::Header.parse(data[0..offset-1])
519
-
520
- @logger.debug ";; HEADER SECTION"
521
- @logger.debug @header.inspect
522
-
523
- #------------------------------------------------------------
524
- # Question section
525
- #------------------------------------------------------------
526
- section = @header.opCode == "UPDATE" ? "ZONE" : "QUESTION"
527
- @logger.debug ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '': 's'})"
528
-
529
- @question = []
530
- @header.qdCount.times do
531
- qobj,offset = parse_question(data,offset)
532
- @question << qobj
533
- @logger.debug ";; #{qobj.inspect}"
534
- end
535
471
 
536
- #------------------------------------------------------------
537
- # Answer/prerequisite section
538
- #------------------------------------------------------------
539
- section = @header.opCode == "UPDATE" ? "PREREQUISITE" : "ANSWER"
540
- @logger.debug ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '': 's'})"
541
-
542
- @answer = []
543
- @header.anCount.times do
544
- rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
545
- @answer << rrobj
546
- @logger.debug rrobj.inspect
547
- end
472
+ @answerfrom = from[2] + ":" + from[1].to_s
473
+ @answersize = data.size
474
+ @logger = Logger.new $stdout
475
+ @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
476
+
477
+ #------------------------------------------------------------
478
+ # Header section
479
+ #------------------------------------------------------------
480
+ offset = Net::DNS::HFIXEDSZ
481
+ @header = Net::DNS::Header.parse(data[0..offset-1])
482
+
483
+ @logger.debug ";; HEADER SECTION"
484
+ @logger.debug @header.inspect
485
+
486
+ #------------------------------------------------------------
487
+ # Question section
488
+ #------------------------------------------------------------
489
+ section = @header.opCode == "UPDATE" ? "ZONE" : "QUESTION"
490
+ @logger.debug ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '': 's'})"
491
+
492
+ @question = []
493
+ @header.qdCount.times do
494
+ qobj,offset = parse_question(data,offset)
495
+ @question << qobj
496
+ @logger.debug ";; #{qobj.inspect}"
497
+ end
498
+
499
+ #------------------------------------------------------------
500
+ # Answer/prerequisite section
501
+ #------------------------------------------------------------
502
+ section = @header.opCode == "UPDATE" ? "PREREQUISITE" : "ANSWER"
503
+ @logger.debug ";; #{section} SECTION (#{@header.qdCount} record#{@header.qdCount == 1 ? '': 's'})"
504
+
505
+ @answer = []
506
+ @header.anCount.times do
507
+ begin
508
+ rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
509
+ @answer << rrobj
510
+ @logger.debug rrobj.inspect
511
+ rescue NameError => e
512
+ warn "Net::DNS unsupported record type: #{e.message}"
513
+ end
514
+ end
515
+
516
+ #------------------------------------------------------------
517
+ # Authority/update section
518
+ #------------------------------------------------------------
519
+ section = @header.opCode == "UPDATE" ? "UPDATE" : "AUTHORITY"
520
+ @logger.debug ";; #{section} SECTION (#{@header.nsCount} record#{@header.nsCount == 1 ? '': 's'})"
521
+
522
+ @authority = []
523
+ @header.nsCount.times do
524
+ begin
525
+ rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
526
+ @authority << rrobj
527
+ @logger.debug rrobj.inspect
528
+ rescue NameError => e
529
+ warn "Net::DNS unsupported record type: #{e.message}"
530
+ end
531
+ end
532
+
533
+ #------------------------------------------------------------
534
+ # Additional section
535
+ #------------------------------------------------------------
536
+ @logger.debug ";; ADDITIONAL SECTION (#{@header.arCount} record#{@header.arCount == 1 ? '': 's'})"
537
+
538
+ @additional = []
539
+ @header.arCount.times do
540
+ begin
541
+ rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
542
+ @additional << rrobj
543
+ @logger.debug rrobj.inspect
544
+ rescue NameError => e
545
+ warn "Net::DNS supported record type: #{e.message}"
546
+ end
547
+ end
548
548
 
549
- #------------------------------------------------------------
550
- # Authority/update section
551
- #------------------------------------------------------------
552
- section = @header.opCode == "UPDATE" ? "UPDATE" : "AUTHORITY"
553
- @logger.debug ";; #{section} SECTION (#{@header.nsCount} record#{@header.nsCount == 1 ? '': 's'})"
554
-
555
- @authority = []
556
- @header.nsCount.times do
557
- rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
558
- @authority << rrobj
559
- @logger.debug rrobj.inspect
560
549
  end
561
-
562
- #------------------------------------------------------------
563
- # Additional section
564
- #------------------------------------------------------------
565
- @logger.debug ";; ADDITIONAL SECTION (#{@header.arCount} record#{@header.arCount == 1 ? '': 's'})"
566
-
567
- @additional = []
568
- @header.arCount.times do
569
- rrobj,offset = Net::DNS::RR.parse_packet(data,offset)
570
- @additional << rrobj
571
- @logger.debug rrobj.inspect
550
+
551
+
552
+ # Parse question section
553
+ def parse_question(data,offset)
554
+ size = (dn_expand(data, offset)[1] - offset) + (2 * Net::DNS::INT16SZ)
555
+ return [Net::DNS::Question.parse(data[offset, size]), offset + size]
556
+ rescue StandardError => e
557
+ raise PacketError, "Caught exception, maybe packet malformed => #{e.message}"
572
558
  end
573
-
574
- end # new_from_data
575
-
576
-
577
- # Parse question section
578
- def parse_question(data,offset)
579
- size = (dn_expand(data,offset)[1]-offset) + 2*Net::DNS::INT16SZ
580
- return [Net::DNS::Question.parse(data[offset,size]), offset+size]
581
- rescue StandardError => e
582
- raise PacketError, "Caught exception, maybe packet malformed => #{e.message}"
583
- end
584
559
 
585
560
  end
586
-
561
+
587
562
  end
588
563
  end