dnsruby 1.46 → 1.47

Sign up to get free protection for your applications and to get access to all the features.
@@ -65,6 +65,11 @@ module Dnsruby
65
65
  #
66
66
  # Defaults to false
67
67
  attr_accessor :use_tcp
68
+
69
+ # Use UDP only - don't use TCP
70
+ # For test/debug purposes only
71
+ # Defaults to false
72
+ attr_accessor :no_tcp
68
73
 
69
74
  # The TSIG record to sign/verify messages with
70
75
  attr_reader :tsig
@@ -152,6 +157,7 @@ module Dnsruby
152
157
  # * :server
153
158
  # * :port
154
159
  # * :use_tcp
160
+ # * :no_tcp
155
161
  # * :ignore_truncation
156
162
  # * :src_address
157
163
  # * :src_port
@@ -166,6 +172,7 @@ module Dnsruby
166
172
  @udp_size = Resolver::DefaultUDPSize
167
173
  @dnssec = Resolver::DefaultDnssec
168
174
  @use_tcp = false
175
+ @no_tcp = false
169
176
  @tsig = nil
170
177
  @ignore_truncation = false
171
178
  @src_address = '0.0.0.0'
@@ -312,6 +319,13 @@ module Dnsruby
312
319
  end
313
320
  # Otherwise, run the query
314
321
  if (udp_packet_size < query_packet.length)
322
+ if (@no_tcp)
323
+ # Can't send the message - abort!
324
+ err=IOError.new("Can't send message - too big for UDP and no_tcp=true")
325
+ Dnsruby.log.error{"#{err}"}
326
+ st.push_exception_to_select(client_query_id, client_queue, err, nil)
327
+ return
328
+ end
315
329
  Dnsruby.log.debug{"Query packet length exceeds max UDP packet size - using TCP"}
316
330
  use_tcp = true
317
331
  end
@@ -392,10 +406,10 @@ module Dnsruby
392
406
  end
393
407
  socket.send(query_bytes, 0)
394
408
  rescue Exception => e
395
- st.push_exception_to_select(client_query_id, client_queue, err, nil)
396
- socket.close
397
409
  err=IOError.new("Send failed to #{@server}:#{@port} from #{@src_address}:#{src_port}, use_tcp=#{use_tcp}, exception : #{e}")
398
410
  Dnsruby.log.error{"#{err}"}
411
+ st.push_exception_to_select(client_query_id, client_queue, err, nil)
412
+ socket.close
399
413
  return
400
414
  end
401
415
 
@@ -499,12 +513,16 @@ module Dnsruby
499
513
  end
500
514
  end
501
515
  if (response.header.tc && !tcp && !@ignore_truncation)
502
- # Try to resend over tcp
503
- Dnsruby.log.debug{"Truncated - resending over TCP"}
504
- # @TODO@ Are the query options used correctly here? DNSSEC in particular...
505
- # query.send_raw = true # Make sure that the packet is not messed with.
506
- send_async(query, client_queue, client_query_id, true)
507
- return false
516
+ if (@no_tcp)
517
+ Dnsruby.log.debug{"Truncated response - not resending over TCP as no_tcp==true"}
518
+ else
519
+ # Try to resend over tcp
520
+ Dnsruby.log.debug{"Truncated - resending over TCP"}
521
+ # @TODO@ Are the query options used correctly here? DNSSEC in particular...
522
+ # query.send_raw = true # Make sure that the packet is not messed with.
523
+ send_async(query, client_queue, client_query_id, true)
524
+ return false
525
+ end
508
526
  end
509
527
  return true
510
528
  end
@@ -549,12 +567,12 @@ module Dnsruby
549
567
  packet.header.rd=@recurse
550
568
  end
551
569
 
552
- # @TODO@ Only do this if the packet has not been prepared already!
570
+ # Only do this if the packet has not been prepared already!
553
571
  if (@dnssec)
554
572
  prepare_for_dnssec(packet)
555
-
556
573
  elsif ((udp_packet_size > Resolver::DefaultUDPSize) && !use_tcp)
557
574
  # if ((udp_packet_size > Resolver::DefaultUDPSize) && !use_tcp)
575
+ # @TODO@ What if an existing OPT RR is not big enough? Should we replace it?
558
576
  add_opt_rr(packet)
559
577
  end
560
578
  end
@@ -570,7 +588,10 @@ module Dnsruby
570
588
  # RFC 3225
571
589
  optrr = RR::OPT.new(udp_packet_size)
572
590
 
573
- packet.add_additional(optrr)
591
+ # Only one OPT RR allowed per packet - do we already have one?
592
+ if (packet.additional.rrset(packet.question()[0].qname, Types::OPT).rrs.length == 0)
593
+ packet.add_additional(optrr)
594
+ end
574
595
  end
575
596
 
576
597
  def prepare_for_dnssec(packet)
@@ -78,7 +78,12 @@ module Dnsruby
78
78
  attr_reader :port
79
79
 
80
80
  # Should TCP be used as a transport rather than UDP?
81
+ # If use_tcp==true, then ONLY TCP will be used as a transport.
81
82
  attr_reader :use_tcp
83
+
84
+ # If no_tcp==true, then ONLY UDP will be used as a transport.
85
+ # This should not generally be used, but is provided as a debugging aid.
86
+ attr_reader :no_tcp
82
87
 
83
88
 
84
89
  attr_reader :tsig
@@ -288,7 +293,7 @@ module Dnsruby
288
293
  #* msg - the message to send
289
294
  #* client_queue - a Queue to push the response to, when it arrives
290
295
  #* client_query_id - an optional ID to identify the query to the client
291
- #* use_tcp - whether to use TCP (defaults to SingleResolver.use_tcp)
296
+ #* use_tcp - whether to use only TCP (defaults to SingleResolver.use_tcp)
292
297
  #
293
298
  #Returns :
294
299
  #
@@ -417,12 +422,13 @@ module Dnsruby
417
422
  @single_res_mutex.synchronize {
418
423
  # Add the Config nameservers
419
424
  @config.nameserver.each do |ns|
420
- @single_resolvers.push(PacketSender.new({:server=>ns, :dnssec=>@dnssec,
421
- :use_tcp=>@use_tcp, :packet_timeout=>@packet_timeout,
425
+ res = PacketSender.new({:server=>ns, :dnssec=>@dnssec,
426
+ :use_tcp=>@use_tcp, :no_tcp=>@no_tcp, :packet_timeout=>@packet_timeout,
422
427
  :tsig => @tsig, :ignore_truncation=>@ignore_truncation,
423
428
  :src_address=>@src_address, :src_port=>@src_port,
424
429
  :do_caching=>@do_caching,
425
- :recurse=>@recurse, :udp_size=>@udp_size}))
430
+ :recurse=>@recurse, :udp_size=>@udp_size})
431
+ @single_resolvers.push(res) if res
426
432
  end
427
433
  }
428
434
  end
@@ -457,6 +463,7 @@ module Dnsruby
457
463
  @dnssec = DefaultDnssec
458
464
  @do_caching= true
459
465
  @use_tcp = false
466
+ @no_tcp = false
460
467
  @tsig = nil
461
468
  @ignore_truncation = false
462
469
  @config = Config.new()
@@ -472,6 +479,7 @@ module Dnsruby
472
479
  def update #:nodoc: all
473
480
  #Update any resolvers we have with the latest config
474
481
  @single_res_mutex.synchronize {
482
+ @single_resolvers.delete(nil) # Just in case...
475
483
  @single_resolvers.each do |res|
476
484
  update_internal_res(res)
477
485
  end
@@ -488,6 +496,7 @@ module Dnsruby
488
496
  def add_server(server)# :nodoc:
489
497
  @configured = true
490
498
  res = PacketSender.new(server)
499
+ raise ArgumentError.new("Can't create server #{server}") if !res
491
500
  update_internal_res(res)
492
501
  @single_res_mutex.synchronize {
493
502
  @single_resolvers.push(res)
@@ -495,7 +504,7 @@ module Dnsruby
495
504
  end
496
505
 
497
506
  def update_internal_res(res)
498
- [:port, :use_tcp, :tsig, :ignore_truncation, :packet_timeout,
507
+ [:port, :use_tcp, :no_tcp, :tsig, :ignore_truncation, :packet_timeout,
499
508
  :src_address, :src_port, :recurse,
500
509
  :udp_size, :dnssec].each do |param|
501
510
 
@@ -625,6 +634,11 @@ module Dnsruby
625
634
  @use_tcp = on
626
635
  update
627
636
  end
637
+
638
+ def no_tcp=(on)
639
+ @no_tcp=on
640
+ update
641
+ end
628
642
 
629
643
  #Sets the TSIG to sign outgoing messages with.
630
644
  #Pass in either a Dnsruby::RR::TSIG, or a key_name and key (or just a key)
@@ -732,11 +746,10 @@ module Dnsruby
732
746
  if (retry_count>0)
733
747
  retry_delay *= 2
734
748
  end
735
- # servers=[]
736
- # @single_resolvers.each do |r| servers.push(r.server) end
749
+
750
+ @single_resolvers.delete(nil) # Just in case...
737
751
  @single_resolvers.each_index do |i|
738
752
  res= @single_resolvers[i]
739
- next if !res # @TODO@ WHY?1
740
753
  offset = (i*@retry_delay.to_f/@single_resolvers.length)
741
754
  if (retry_count==0)
742
755
  timeouts[base+offset]=[res, retry_count]
@@ -43,6 +43,7 @@ module Dnsruby
43
43
  # * :server
44
44
  # * :port
45
45
  # * :use_tcp
46
+ # * :no_tcp
46
47
  # * :ignore_truncation
47
48
  # * :src_address
48
49
  # * :src_port
@@ -61,6 +62,7 @@ module Dnsruby
61
62
  @udp_size = Resolver::DefaultUDPSize
62
63
  @dnssec = Resolver::DefaultDnssec
63
64
  @use_tcp = false
65
+ @no_tcp = false
64
66
  @tsig = nil
65
67
  @ignore_truncation = false
66
68
  @src_address = nil
@@ -111,7 +113,7 @@ module Dnsruby
111
113
  end
112
114
 
113
115
  isr = PacketSender.new({:server=>@server, :dnssec=>@dnssec,
114
- :use_tcp=>@use_tcp, :packet_timeout=>@packet_timeout,
116
+ :use_tcp=>@use_tcp, :no_tcp=>@no_tcp, :packet_timeout=>@packet_timeout,
115
117
  :tsig => @tsig, :ignore_truncation=>@ignore_truncation,
116
118
  :src_address=>@src_address, :src_port=>@src_port,
117
119
  :do_caching=>@do_caching,
@@ -128,7 +130,7 @@ module Dnsruby
128
130
  end
129
131
  @server = Config.resolve_server(s).to_s
130
132
  isr = PacketSender.new({:server=>@server, :dnssec=>@dnssec,
131
- :use_tcp=>@use_tcp, :packet_timeout=>@packet_timeout,
133
+ :use_tcp=>@use_tcp, :no_tcp=>@no_tcp, :packet_timeout=>@packet_timeout,
132
134
  :tsig => @tsig, :ignore_truncation=>@ignore_truncation,
133
135
  :src_address=>@src_address, :src_port=>@src_port,
134
136
  :do_caching=>@do_caching,
@@ -99,7 +99,10 @@ module Dnsruby
99
99
  if (rr.type == Types::RRSIG)
100
100
  type_ok = (rr.type_covered == type)
101
101
  end
102
- type_ok && (rr.klass == klass) && (rr.name.to_s.downcase == name.to_s.downcase)
102
+ if (!(/\.\z/ =~ name.to_s))
103
+ name = name.to_s + "."
104
+ end
105
+ type_ok && (rr.klass == klass) && (rr.name.to_s(true).downcase == name.to_s().downcase)
103
106
  }
104
107
  rrset = RRSet.new()
105
108
  rrs.each do |rr|
@@ -668,10 +671,7 @@ module Dnsruby
668
671
  attr_accessor :cd
669
672
 
670
673
  #The Authenticated Data flag
671
- attr_accessor :ad
672
-
673
674
  #Relevant in DNSSEC context.
674
- #
675
675
  #(The AD bit is only set on answers where signatures have been
676
676
  #cryptographically verified or the server is authoritative for the data
677
677
  #and is allowed to set the bit by policy.)
@@ -221,8 +221,12 @@ module Dnsruby
221
221
  # p Resolv::Name.create("x.y.z.").to_s #=> "x.y.z"
222
222
  # p Resolv::Name.create("x.y.z").to_s #=> "x.y.z"
223
223
  #
224
- def to_s
225
- return to_str(@labels)
224
+ def to_s(include_absolute=false)
225
+ ret = to_str(@labels)
226
+ if (@absolute && include_absolute)
227
+ ret += "."
228
+ end
229
+ return ret
226
230
  end
227
231
 
228
232
  def to_str(labels) # :nodoc: all
@@ -46,7 +46,7 @@ module Dnsruby
46
46
 
47
47
  def rdata_to_string #:nodoc: all
48
48
  if defined?@subtype
49
- return "#{@subtype} #{@hostname}."
49
+ return "#{@subtype} #{@hostname.to_s(true)}"
50
50
  else
51
51
  return '';
52
52
  end
@@ -105,7 +105,7 @@ module Dnsruby
105
105
  def rdata_to_string #:nodoc: all
106
106
  ret = "#{@pk_algorithm} #{hit_string} #{public_key_string}"
107
107
  @rsvs.each {|rsv|
108
- ret += " #{rsv}"
108
+ ret += " #{rsv.to_s(true)}"
109
109
  }
110
110
  return ret
111
111
  end
@@ -45,7 +45,7 @@ module Dnsruby
45
45
 
46
46
  def rdata_to_string #:nodoc: all
47
47
  if (@preference!=nil)
48
- return "#{@preference} #{@exchange}"
48
+ return "#{@preference} #{@exchange.to_s(true)}"
49
49
  else
50
50
  return ""
51
51
  end
@@ -49,7 +49,7 @@ module Dnsruby
49
49
 
50
50
  def rdata_to_string #:nodoc: all
51
51
  if (@rmailbx!=nil)
52
- return "#{@rmailbx} #{@emailbx}"
52
+ return "#{@rmailbx.to_s(true)} #{@emailbx.to_s(true)}"
53
53
  else
54
54
  return ""
55
55
  end
@@ -45,7 +45,7 @@ module Dnsruby
45
45
 
46
46
  def rdata_to_string #:nodoc: all
47
47
  if (@preference!=nil)
48
- return "#{@preference} #{@exchange}"
48
+ return "#{@preference} #{@exchange.to_s(true)}"
49
49
  else
50
50
  return ""
51
51
  end
@@ -67,7 +67,7 @@ module Dnsruby
67
67
  if (@order!=nil)
68
68
  ret = "#{@order} #{@preference} \"#{@flags}\" \"#{@service}\" \""
69
69
  ret += TXT.display(@regexp)
70
- ret += "\" #{@replacement}"
70
+ ret += "\" #{@replacement.to_s(true)}"
71
71
 
72
72
  return ret
73
73
  else
@@ -274,7 +274,7 @@ module Dnsruby
274
274
  type_strings.push(t.string)
275
275
  end
276
276
  types = type_strings.join(" ")
277
- return "#{@next_domain} ( #{types} )"
277
+ return "#{@next_domain.to_s(true)} ( #{types} )"
278
278
  else
279
279
  return ""
280
280
  end
@@ -47,7 +47,7 @@ module Dnsruby
47
47
 
48
48
  def rdata_to_string #:nodoc: all
49
49
  if (@preference!=nil)
50
- return "#{@preference} #{@map822} #{@mapx400}"
50
+ return "#{@preference} #{@map822.to_s(true)} #{@mapx400.to_s(true)}"
51
51
  else
52
52
  return ""
53
53
  end
@@ -46,7 +46,7 @@ module Dnsruby
46
46
 
47
47
  def rdata_to_string #:nodoc: all
48
48
  if (@mailbox!=nil)
49
- return "#{@mailbox} #{@txtdomain}"
49
+ return "#{@mailbox.to_s(true)} #{@txtdomain.to_s(true)}"
50
50
  else
51
51
  return ""
52
52
  end
@@ -232,7 +232,7 @@ module Dnsruby
232
232
  # @TODO@ Display the expiration and inception as
233
233
  return "#{@type_covered.string} #{@algorithm.string} #{@labels} #{@original_ttl} " +
234
234
  "#{format_time(@expiration)} ( #{format_time(@inception)} " +
235
- "#{@key_tag} #{@signers_name} #{signature} )"
235
+ "#{@key_tag} #{@signers_name.to_s(true)} #{signature} )"
236
236
  else
237
237
  return ""
238
238
  end
@@ -46,7 +46,7 @@ module Dnsruby
46
46
 
47
47
  def rdata_to_string #:nodoc: all
48
48
  if (@preference!=nil)
49
- return "#{@preference} #{@intermediate}"
49
+ return "#{@preference} #{@intermediate.to_s(true)}"
50
50
  else
51
51
  return ""
52
52
  end
@@ -71,7 +71,7 @@ module Dnsruby
71
71
 
72
72
  def rdata_to_string #:nodoc: all
73
73
  if (@mname!=nil)
74
- return "#{@mname} #{@rname} #{@serial} #{@refresh} #{@retry} #{@expire} #{@minimum}"
74
+ return "#{@mname.to_s(true)} #{@rname.to_s(true)} #{@serial} #{@refresh} #{@retry} #{@expire} #{@minimum}"
75
75
  else
76
76
  return ""
77
77
  end
@@ -86,7 +86,7 @@ module Dnsruby
86
86
 
87
87
  def rdata_to_string
88
88
  if (@target!=nil)
89
- return "#{@priority} #{@weight} #{@port} #{@target}"
89
+ return "#{@priority} #{@weight} #{@port} #{@target.to_s(true)}"
90
90
  else
91
91
  return ""
92
92
  end
@@ -131,7 +131,7 @@ module Dnsruby
131
131
  if (@algorithm!=nil)
132
132
  error = @error
133
133
  error = "UNDEFINED" unless error!=nil
134
- rdatastr = "#{@algorithm}. #{error}"
134
+ rdatastr = "#{@algorithm.to_s(true)} #{error}"
135
135
  if (@other_size != nil && @other_size >0 && @other_data!=nil)
136
136
  rdatastr += " #{@other_data}"
137
137
  end
@@ -550,7 +550,7 @@ module Dnsruby
550
550
  if (@algorithm!=nil)
551
551
  error = @error
552
552
  error = "UNDEFINED" unless error!=nil
553
- rdatastr = "#{@original_id} #{@time_signed} #{@algorithm}. #{error}";
553
+ rdatastr = "#{@original_id} #{@time_signed} #{@algorithm.to_s(true)} #{error}";
554
554
  if (@other_size > 0 && @other_data!=nil)
555
555
  rdatastr += " #{@other_data}"
556
556
  end
@@ -39,7 +39,7 @@ module Dnsruby
39
39
  end
40
40
 
41
41
  def rdata_to_string #:nodoc: all
42
- return @domainname.to_s
42
+ return @domainname.to_s(true)
43
43
  end
44
44
 
45
45
  def encode_rdata(msg, canonical=false) #:nodoc: all
@@ -503,7 +503,7 @@ module Dnsruby
503
503
 
504
504
  #Returns a string representation of the RR in zone file format
505
505
  def to_s
506
- return (@name ? @name.to_s():"") + ".\t" +(@ttl ? @ttl.to_s():"") + "\t" + (klass() ? klass.to_s():"") + "\t" + (type() ? type.to_s():"") + "\t" + rdata_to_string
506
+ return (@name ? @name.to_s(true):"") + "\t" +(@ttl ? @ttl.to_s():"") + "\t" + (klass() ? klass.to_s():"") + "\t" + (type() ? type.to_s():"") + "\t" + rdata_to_string
507
507
  end
508
508
 
509
509
  #Get a string representation of the data section of the RR (in zone file format)
@@ -58,6 +58,8 @@ module Dnsruby
58
58
  @@queued_responses=[]
59
59
  @@queued_validation_responses=[]
60
60
  @@wakeup_sockets = get_socket_pair
61
+ # Suppress reverse lookups
62
+ BasicSocket.do_not_reverse_lookup = true
61
63
  # end
62
64
  # Now start the select thread
63
65
  @@select_thread = Thread.new {
@@ -236,9 +238,16 @@ module Dnsruby
236
238
  answerip = msg.answerip.downcase
237
239
  answerfrom = msg.answerfrom.downcase
238
240
  dest_server = query_settings.dest_server
241
+ answeripaddr = IPAddr.new(answerip)
242
+ dest_server = IPAddr.new("0.0.0.0")
243
+ begin
244
+ destserveripaddr = IPAddr.new(dest_server)
245
+ rescue ArgumentError
246
+ # Host name not IP address
247
+ end
239
248
  if (dest_server && (dest_server != '0.0.0.0') &&
240
- (answerip != query_settings.dest_server.downcase) &&
241
- (answerfrom != query_settings.dest_server.downcase))
249
+ (answeripaddr != destserveripaddr) &&
250
+ (answerfrom != dest_server))
242
251
  Dnsruby.log.warn("Unsolicited response received from #{answerip} instead of #{query_settings.dest_server}")
243
252
  else
244
253
  send_response_to_client(msg, bytes, socket)
@@ -516,7 +525,11 @@ module Dnsruby
516
525
  # to send it out from its normal loop.
517
526
  Dnsruby.log.debug{"Pushing response to client queue direct from resolver or validator"}
518
527
  @@mutex.synchronize{
519
- @@queued_responses.push([client_id, client_queue, msg, nil, query, res])
528
+ err = nil
529
+ if (msg.rcode == RCode.NXDOMAIN)
530
+ err = NXDomain.new
531
+ end
532
+ @@queued_responses.push([client_id, client_queue, msg, err, query, res])
520
533
  }
521
534
  # Make sure select loop is running!
522
535
  if (@@select_thread && @@select_thread.alive?)
@@ -21,7 +21,7 @@ module Dnsruby
21
21
  class ValidatorThread # :nodoc: all
22
22
  # include Singleton
23
23
  def initialize(*args)
24
- @client_id, @client_queue, @response, @err, @query, @st, @res = args
24
+ @client_id, @client_queue, @response, @error, @query, @st, @res = args
25
25
  # Create the validation thread, and a queue to receive validation requests
26
26
  # Actually, need to have a thread per validator, as they make recursive calls.
27
27
  # @@mutex = Mutex.new
@@ -59,7 +59,7 @@ module Dnsruby
59
59
  # client_id, client_queue, response, err, query, st, res = item
60
60
  validated_ok = validate(@query, @response, @res)
61
61
 
62
- validated_ok = false if @error
62
+ validated_ok = false if (@error && !(NXDomain === @error))
63
63
 
64
64
  cache_if_valid(@query, @response)
65
65
 
@@ -332,8 +332,9 @@ module Dnsruby
332
332
  if ([Types::MX, Types::NS, Types::AFSDB, Types::NAPTR, Types::RT,
333
333
  Types::SRV, Types::CNAME, Types::MB, Types::MG, Types::MR,
334
334
  Types::PTR].include?type_was)
335
- if (line[line.length-1, 1] != ".")
336
- line = line + "." + @origin.to_s
335
+ # if (line[line.length-1, 1] != ".")
336
+ if (!(/\.\z/ =~ line))
337
+ line = line + "." + @origin.to_s + "."
337
338
  end
338
339
  end
339
340
  # Other RRs have several names. These should be parsed by Dnsruby,
@@ -104,7 +104,7 @@ require 'Dnsruby/TheLog'
104
104
  module Dnsruby
105
105
 
106
106
  # @TODO@ Remember to update version in dnsruby.gemspec!
107
- VERSION = 1.46
107
+ VERSION = 1.47
108
108
  def Dnsruby.version
109
109
  return VERSION
110
110
  end
@@ -22,7 +22,7 @@ require 'dnsruby'
22
22
  include Dnsruby
23
23
  class TestPacket < Test::Unit::TestCase
24
24
  def test_packet
25
- domain = "example.com"
25
+ domain = "example.com."
26
26
  type = "MX"
27
27
  klass = "IN"
28
28
 
@@ -48,43 +48,43 @@ class TestPacket < Test::Unit::TestCase
48
48
  assert(additional.length == 0, 'additional() works when empty'); #9
49
49
 
50
50
  packet.add_answer(RR.create( {
51
- :name => "a1.example.com",
51
+ :name => "a1.example.com.",
52
52
  :type => Types.A,
53
53
  :address => "10.0.0.1"}));
54
54
  assert_equal(1, packet.header.ancount, 'First push into answer section worked'); #10
55
55
 
56
56
 
57
- ret = packet.answer.rrset("example.com", 'NSEC')
57
+ ret = packet.answer.rrset("example.com.", 'NSEC')
58
58
  assert_equal(ret.rrs.length, 0, "#{ret.rrs.length}")
59
59
  ret = packet.answer.rrset("a1.example.com", 'A')
60
60
  assert_equal(ret.rrs.length, 1, "#{ret.rrs.length}")
61
61
  ret = packet.answer.rrsets()
62
62
  assert_equal(ret.length, 1, "#{ret.length}")
63
63
 
64
- packet.add_answer(RR.create({:name => "a2.example.com",
64
+ packet.add_answer(RR.create({:name => "a2.example.com.",
65
65
  :type => "A", :address => "10.0.0.2"}));
66
66
  assert_equal(packet.header.ancount, 2, 'Second push into answer section worked'); #11
67
67
 
68
- packet.add_authority(RR.create({:name => "a3.example.com",
68
+ packet.add_authority(RR.create({:name => "a3.example.com.",
69
69
  :type => "A",
70
70
  :address => "10.0.0.3"}));
71
71
  assert_equal(1, packet.header.nscount, 'First push into authority section worked'); #12
72
72
 
73
73
 
74
74
  packet.add_authority(RR.create( {
75
- :name => "a4.example.com",
75
+ :name => "a4.example.com.",
76
76
  :type => "A",
77
77
  :address => "10.0.0.4"}));
78
78
  assert_equal(2, packet.header.nscount, 'Second push into authority section worked'); #13
79
79
 
80
80
  packet.add_additional(RR.create({
81
- :name => "a5.example.com",
81
+ :name => "a5.example.com.",
82
82
  :type => "A",
83
83
  :address => "10.0.0.5"}));
84
84
  assert_equal(1, packet.header.adcount, 'First push into additional section worked'); #14
85
85
 
86
86
  packet.add_additional(RR.create( {
87
- :name => "a6.example.com",
87
+ :name => "a6.example.com.",
88
88
  :type => Types.A,
89
89
  :address => "10.0.0.6"}));
90
90
  assert_equal(2, packet.header.adcount, 'Second push into additional section worked'); #15
@@ -162,13 +162,13 @@ f4 00 31 04 64 6e 73 31 05 69 63 61 6e 6e 03 6f
162
162
  end
163
163
 
164
164
  def get_test_packet
165
- packet=Message.new("254.9.11.10.in-addr.arpa","PTR","IN")
165
+ packet=Message.new("254.9.11.10.in-addr.arpa.","PTR","IN")
166
166
 
167
- packet.add_answer(RR.create(%q[254.9.11.10.in-addr.arpa 86400 IN PTR host-84-11-9-254.customer.example.com]));
167
+ packet.add_answer(RR.create(%q[254.9.11.10.in-addr.arpa. 86400 IN PTR host-84-11-9-254.customer.example.com.]));
168
168
 
169
- packet.add_authority(RR.create("9.11.10.in-addr.arpa 86400 IN NS autons1.example.com"));
170
- packet.add_authority(RR.create("9.11.10.in-addr.arpa 86400 IN NS autons2.example.com"));
171
- packet.add_authority(RR.create("9.11.10.in-addr.arpa 86400 IN NS autons3.example.com"));
169
+ packet.add_authority(RR.create("9.11.10.in-addr.arpa. 86400 IN NS autons1.example.com."));
170
+ packet.add_authority(RR.create("9.11.10.in-addr.arpa. 86400 IN NS autons2.example.com."));
171
+ packet.add_authority(RR.create("9.11.10.in-addr.arpa. 86400 IN NS autons3.example.com."));
172
172
  return packet
173
173
  end
174
174
 
@@ -121,7 +121,7 @@ class TestResolver < Test::Unit::TestCase
121
121
  id, m, err = q.pop
122
122
  assert(id==1)
123
123
  assert(m.rcode == RCode.NXDOMAIN)
124
- assert(err.kind_of?(NXDomain))
124
+ assert(NXDomain === err)
125
125
  end
126
126
 
127
127
  def test_timeouts
@@ -66,9 +66,9 @@ class TestRrUnknown < Test::Unit::TestCase
66
66
 
67
67
 
68
68
  rr = RR.new_from_string('e.example IN TYPE4555 \# 4 0A0000 01 ')
69
- assert_equal('e.example. 0 IN TYPE4555 \# 4 0a000001', rr.to_s, 'Fully unknown RR parsed correctly')
69
+ assert_equal('e.example 0 IN TYPE4555 \# 4 0a000001', rr.to_s, 'Fully unknown RR parsed correctly')
70
70
 
71
- rr4 = RR.new_from_string('e.example CLASS122 TYPE4555 \# 4 0A0000 01 ')
71
+ rr4 = RR.new_from_string('e.example. CLASS122 TYPE4555 \# 4 0A0000 01 ')
72
72
  assert_equal('e.example. 0 CLASS122 TYPE4555 \# 4 0a000001', rr4.to_s, 'Fully unknown RR in unknown CLASS parsed correctly')
73
73
  end
74
74
 
@@ -14,11 +14,12 @@
14
14
  #limitations under the License.
15
15
  #++
16
16
  begin
17
- require 'rubygems'
17
+ require 'rubygems'
18
18
  rescue LoadError
19
19
  end
20
20
  require 'test/unit'
21
21
  require 'dnsruby'
22
+ require 'socket'
22
23
  class TestTcp < Test::Unit::TestCase
23
24
  def test_TCP
24
25
  res = Dnsruby::Resolver.new()
@@ -27,12 +28,54 @@ class TestTcp < Test::Unit::TestCase
27
28
  assert(ret.is_a?(Dnsruby::Message))
28
29
  end
29
30
  def test_TCP_port
30
- #@TODO@ Need a test server so we can tell what port this message was actually sent on!
31
+ # Need a test server so we can tell what port this message was actually sent on!
32
+ port = 59125
33
+ src_port = 57923
34
+ Dnsruby::PacketSender.clear_caches
35
+ received_port = nil
36
+ server_thread = Thread.new {
37
+ ts = TCPServer.new(port)
38
+ t = ts.accept
39
+ # Check that the source port was src_port
40
+ received_port = t.peeraddr()[1]
41
+ packet = t.recvfrom(2)[0]
42
+
43
+ len = (packet[0]<<8)+packet[1]
44
+ if (RUBY_VERSION >= "1.9")
45
+ len = (packet[0].getbyte(0)<<8)+packet[1].getbyte(0)# Ruby 1.9
46
+ end
47
+ packet = t.recvfrom(len)[0]
48
+ tcpPacket = Dnsruby::Message.decode(packet)
49
+ tcpPacket.header.tc = true
50
+ lenmsg = [tcpPacket.encode.length].pack('n')
51
+ t.send(lenmsg, 0)
52
+ t.write(tcpPacket.encode)
53
+ t.close
54
+ ts.close
55
+ }
56
+ ret = nil
57
+ client_thread = Thread.new {
58
+ res = Dnsruby::SingleResolver.new("127.0.0.1")
59
+ res.port = port
60
+ res.use_tcp = true
61
+ res.src_port=src_port
62
+ ret=res.query("example.com")
63
+ }
64
+ server_thread.join
65
+ client_thread.join
66
+ assert(received_port == src_port)
67
+ assert(ret.is_a?(Dnsruby::Message))
68
+ end
69
+
70
+ def test_no_tcp
71
+ # Try to get a long response (which is truncated) and check that we have
72
+ # tc bit set
31
73
  res = Dnsruby::Resolver.new()
32
- res.use_tcp = true
33
- res.src_port=60123
34
- ret=res.query("example.com")
35
- assert(ret.is_a?(Dnsruby::Message))
74
+ res.udp_size = 512
75
+ res.no_tcp = true
76
+ ret = res.query("overflow.dnsruby.validation-test-servers.nominet.org.uk", Dnsruby::Types.TXT)
77
+ assert(ret.header.tc, "Message should be truncated with no TCP")
36
78
  end
79
+
37
80
  #@TODO@ Check stuff like persistent sockets
38
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dnsruby
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.46"
4
+ version: "1.47"
5
5
  platform: ruby
6
6
  authors:
7
7
  - AlexD
@@ -9,7 +9,7 @@ autorequire: dnsruby
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-04-07 00:00:00 +01:00
12
+ date: 2010-05-19 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15