dnsruby 1.55 → 1.56.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +96 -0
  3. data/Rakefile +30 -29
  4. data/demo/axfr.rb +93 -93
  5. data/demo/check_soa.rb +99 -99
  6. data/demo/check_zone.rb +59 -59
  7. data/demo/digdlv.rb +43 -43
  8. data/demo/digroot.rb +34 -34
  9. data/demo/example_recurse.rb +14 -14
  10. data/demo/mresolv.rb +30 -30
  11. data/demo/mx.rb +31 -31
  12. data/demo/rubydig.rb +37 -37
  13. data/demo/to_resolve.txt +3088 -3088
  14. data/demo/trace_dns.rb +46 -46
  15. data/lib/dnsruby.rb +161 -526
  16. data/lib/dnsruby/DNS.rb +305 -0
  17. data/lib/{Dnsruby/Cache.rb → dnsruby/cache.rb} +152 -152
  18. data/lib/{Dnsruby → dnsruby}/code_mapper.rb +48 -52
  19. data/lib/dnsruby/code_mappers.rb +295 -0
  20. data/lib/{Dnsruby/Config.rb → dnsruby/config.rb} +454 -454
  21. data/lib/{Dnsruby → dnsruby}/dnssec.rb +91 -91
  22. data/lib/{Dnsruby/Hosts.rb → dnsruby/hosts.rb} +125 -125
  23. data/lib/{Dnsruby → dnsruby}/ipv4.rb +26 -26
  24. data/lib/{Dnsruby → dnsruby}/ipv6.rb +42 -42
  25. data/lib/{Dnsruby → dnsruby}/key_cache.rb +29 -29
  26. data/lib/dnsruby/message/decoder.rb +164 -0
  27. data/lib/dnsruby/message/encoder.rb +75 -0
  28. data/lib/dnsruby/message/header.rb +249 -0
  29. data/lib/dnsruby/message/message.rb +629 -0
  30. data/lib/dnsruby/message/question.rb +86 -0
  31. data/lib/dnsruby/message/section.rb +96 -0
  32. data/lib/{Dnsruby → dnsruby}/name.rb +141 -141
  33. data/lib/dnsruby/packet_sender.rb +661 -0
  34. data/lib/{Dnsruby/Recursor.rb → dnsruby/recursor.rb} +235 -233
  35. data/lib/dnsruby/resolv.rb +113 -0
  36. data/lib/dnsruby/resolver.rb +1192 -0
  37. data/lib/dnsruby/resource/A.rb +56 -0
  38. data/lib/dnsruby/resource/AAAA.rb +54 -0
  39. data/lib/{Dnsruby → dnsruby}/resource/AFSDB.rb +68 -68
  40. data/lib/{Dnsruby → dnsruby}/resource/CERT.rb +105 -105
  41. data/lib/{Dnsruby → dnsruby}/resource/DHCID.rb +54 -54
  42. data/lib/dnsruby/resource/DLV.rb +27 -0
  43. data/lib/{Dnsruby → dnsruby}/resource/DNSKEY.rb +372 -372
  44. data/lib/{Dnsruby → dnsruby}/resource/DS.rb +255 -255
  45. data/lib/{Dnsruby → dnsruby}/resource/HINFO.rb +71 -71
  46. data/lib/{Dnsruby → dnsruby}/resource/HIP.rb +29 -29
  47. data/lib/{Dnsruby → dnsruby}/resource/IN.rb +30 -30
  48. data/lib/{Dnsruby → dnsruby}/resource/IPSECKEY.rb +31 -31
  49. data/lib/{Dnsruby → dnsruby}/resource/ISDN.rb +62 -62
  50. data/lib/{Dnsruby → dnsruby}/resource/KX.rb +65 -65
  51. data/lib/{Dnsruby → dnsruby}/resource/LOC.rb +263 -263
  52. data/lib/{Dnsruby → dnsruby}/resource/MINFO.rb +69 -69
  53. data/lib/{Dnsruby → dnsruby}/resource/MX.rb +65 -65
  54. data/lib/{Dnsruby → dnsruby}/resource/NAPTR.rb +98 -98
  55. data/lib/{Dnsruby → dnsruby}/resource/NSAP.rb +171 -171
  56. data/lib/dnsruby/resource/NSEC.rb +275 -0
  57. data/lib/dnsruby/resource/NSEC3.rb +332 -0
  58. data/lib/dnsruby/resource/NSEC3PARAM.rb +135 -0
  59. data/lib/dnsruby/resource/OPT.rb +272 -0
  60. data/lib/{Dnsruby → dnsruby}/resource/PX.rb +70 -70
  61. data/lib/{Dnsruby → dnsruby}/resource/RP.rb +75 -75
  62. data/lib/dnsruby/resource/RR.rb +421 -0
  63. data/lib/dnsruby/resource/RRSIG.rb +275 -0
  64. data/lib/dnsruby/resource/RRSet.rb +190 -0
  65. data/lib/{Dnsruby → dnsruby}/resource/RT.rb +67 -67
  66. data/lib/{Dnsruby → dnsruby}/resource/SOA.rb +94 -94
  67. data/lib/dnsruby/resource/SPF.rb +29 -0
  68. data/lib/dnsruby/resource/SRV.rb +112 -0
  69. data/lib/{Dnsruby → dnsruby}/resource/SSHFP.rb +14 -14
  70. data/lib/dnsruby/resource/TKEY.rb +163 -0
  71. data/lib/dnsruby/resource/TSIG.rb +593 -0
  72. data/lib/{Dnsruby → dnsruby}/resource/TXT.rb +191 -191
  73. data/lib/dnsruby/resource/X25.rb +55 -0
  74. data/lib/{Dnsruby → dnsruby}/resource/domain_name.rb +25 -25
  75. data/lib/{Dnsruby → dnsruby}/resource/generic.rb +80 -80
  76. data/lib/dnsruby/resource/resource.rb +25 -0
  77. data/lib/{Dnsruby → dnsruby}/select_thread.rb +148 -148
  78. data/lib/{Dnsruby/SingleResolver.rb → dnsruby/single_resolver.rb} +60 -60
  79. data/lib/{Dnsruby → dnsruby}/single_verifier.rb +344 -344
  80. data/lib/dnsruby/the_log.rb +44 -0
  81. data/lib/dnsruby/update.rb +278 -0
  82. data/lib/dnsruby/validator_thread.rb +124 -0
  83. data/lib/dnsruby/version.rb +3 -0
  84. data/lib/{Dnsruby → dnsruby}/zone_reader.rb +93 -93
  85. data/lib/{Dnsruby → dnsruby}/zone_transfer.rb +377 -377
  86. data/test/spec_helper.rb +16 -0
  87. data/test/tc_axfr.rb +31 -34
  88. data/test/tc_cache.rb +32 -32
  89. data/test/tc_dlv.rb +28 -28
  90. data/test/tc_dns.rb +73 -76
  91. data/test/tc_dnskey.rb +31 -32
  92. data/test/tc_dnsruby.rb +50 -44
  93. data/test/tc_ds.rb +36 -36
  94. data/test/tc_escapedchars.rb +252 -255
  95. data/test/tc_hash.rb +17 -21
  96. data/test/tc_header.rb +48 -57
  97. data/test/tc_hip.rb +19 -22
  98. data/test/tc_ipseckey.rb +18 -21
  99. data/test/tc_keith.rb +300 -0
  100. data/test/tc_message.rb +87 -0
  101. data/test/tc_misc.rb +83 -87
  102. data/test/tc_name.rb +81 -84
  103. data/test/tc_naptr.rb +18 -21
  104. data/test/tc_nsec.rb +55 -55
  105. data/test/tc_nsec3.rb +23 -24
  106. data/test/tc_nsec3param.rb +20 -21
  107. data/test/tc_packet.rb +90 -93
  108. data/test/tc_packet_unique_push.rb +48 -51
  109. data/test/tc_question.rb +30 -33
  110. data/test/tc_queue.rb +16 -17
  111. data/test/tc_recur.rb +16 -17
  112. data/test/tc_res_config.rb +38 -41
  113. data/test/tc_res_env.rb +29 -32
  114. data/test/tc_res_file.rb +26 -29
  115. data/test/tc_res_opt.rb +62 -65
  116. data/test/tc_resolver.rb +287 -242
  117. data/test/tc_rr-opt.rb +70 -63
  118. data/test/tc_rr-txt.rb +68 -71
  119. data/test/tc_rr-unknown.rb +45 -48
  120. data/test/tc_rr.rb +76 -70
  121. data/test/tc_rrset.rb +21 -22
  122. data/test/tc_rrsig.rb +19 -20
  123. data/test/tc_single_resolver.rb +294 -297
  124. data/test/tc_soak.rb +199 -202
  125. data/test/tc_soak_base.rb +29 -34
  126. data/test/tc_sshfp.rb +20 -23
  127. data/test/tc_tcp.rb +32 -35
  128. data/test/tc_tkey.rb +41 -44
  129. data/test/tc_tsig.rb +81 -84
  130. data/test/tc_update.rb +108 -111
  131. data/test/tc_validator.rb +29 -29
  132. data/test/tc_verifier.rb +81 -82
  133. data/test/ts_dnsruby.rb +16 -15
  134. data/test/ts_offline.rb +62 -63
  135. data/test/ts_online.rb +115 -115
  136. metadata +155 -90
  137. data/README +0 -59
  138. data/lib/Dnsruby/DNS.rb +0 -305
  139. data/lib/Dnsruby/PacketSender.rb +0 -656
  140. data/lib/Dnsruby/Resolver.rb +0 -1189
  141. data/lib/Dnsruby/TheLog.rb +0 -44
  142. data/lib/Dnsruby/message.rb +0 -1230
  143. data/lib/Dnsruby/resource/A.rb +0 -56
  144. data/lib/Dnsruby/resource/AAAA.rb +0 -54
  145. data/lib/Dnsruby/resource/DLV.rb +0 -27
  146. data/lib/Dnsruby/resource/NSEC.rb +0 -298
  147. data/lib/Dnsruby/resource/NSEC3.rb +0 -340
  148. data/lib/Dnsruby/resource/NSEC3PARAM.rb +0 -135
  149. data/lib/Dnsruby/resource/OPT.rb +0 -213
  150. data/lib/Dnsruby/resource/RRSIG.rb +0 -275
  151. data/lib/Dnsruby/resource/SPF.rb +0 -29
  152. data/lib/Dnsruby/resource/SRV.rb +0 -112
  153. data/lib/Dnsruby/resource/TKEY.rb +0 -163
  154. data/lib/Dnsruby/resource/TSIG.rb +0 -593
  155. data/lib/Dnsruby/resource/X25.rb +0 -55
  156. data/lib/Dnsruby/resource/resource.rb +0 -678
  157. data/lib/Dnsruby/update.rb +0 -278
  158. data/lib/Dnsruby/validator_thread.rb +0 -124
@@ -1,44 +0,0 @@
1
- #--
2
- #Copyright 2007 Nominet UK
3
- #
4
- #Licensed under the Apache License, Version 2.0 (the "License");
5
- #you may not use this file except in compliance with the License.
6
- #You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- #Unless required by applicable law or agreed to in writing, software
11
- #distributed under the License is distributed on an "AS IS" BASIS,
12
- #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- #See the License for the specific language governing permissions and
14
- #limitations under the License.
15
- #++
16
- require 'logger'
17
- require 'singleton'
18
- require 'thread'
19
- module Dnsruby
20
- #This class exists for backwards compatibility.
21
- #
22
- #It's Logger (which defaults to STDOUT, level FATAL) can be configured, or a new Logger can be supplied.
23
- #
24
- # Dnsruby::TheLog.level=Logger::DEBUG
25
- # Dnsruby::TheLog.debug("Debug message")
26
- #
27
- class TheLog
28
- # Set a new Logger for use by Dnsruby
29
- def set_logger(logger)
30
- Dnsruby.log = logger
31
- end
32
- # Change the Logger level.
33
- def level=(level)
34
- Dnsruby.log.level = level
35
- end
36
- def level
37
- return Dnsruby.log.level
38
- end
39
-
40
- def self.method_missing(symbol, *args) #:nodoc: all
41
- Dnsruby.log.send(symbol, *args)
42
- end
43
- end
44
- end
@@ -1,1230 +0,0 @@
1
- #--
2
- #Copyright 2007 Nominet UK
3
- #
4
- #Licensed under the Apache License, Version 2.0 (the "License");
5
- #you may not use this file except in compliance with the License.
6
- #You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- #Unless required by applicable law or agreed to in writing, software
11
- #distributed under the License is distributed on an "AS IS" BASIS,
12
- #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- #See the License for the specific language governing permissions and
14
- #limitations under the License.
15
- #++
16
- require 'Dnsruby/name'
17
- require 'Dnsruby/resource/resource'
18
- module Dnsruby
19
- #===Defines a DNS packet.
20
- #
21
- #RFC 1035 Section 4.1, RFC 2136 Section 2, RFC 2845
22
- #
23
- #===Sections
24
- #Message objects have five sections:
25
- #
26
- #* The header section, a Dnsruby::Header object.
27
- #
28
- # msg.header=Header.new(...)
29
- # header = msg.header
30
- #
31
- #* The question section, an array of Dnsruby::Question objects.
32
- #
33
- # msg.add_question(Question.new(domain, type, klass))
34
- # msg.each_question do |question| .... end
35
- #
36
- #* The answer section, an array of Dnsruby::RR objects.
37
- #
38
- # msg.add_answer(RR.create({:name => "a2.example.com",
39
- # :type => "A", :address => "10.0.0.2"}))
40
- # msg.each_answer {|answer| ... }
41
- #
42
- #* The authority section, an array of Dnsruby::RR objects.
43
- #
44
- # msg.add_authority(rr)
45
- # msg.each_authority {|rr| ... }
46
- #
47
- #* The additional section, an array of Dnsruby::RR objects.
48
- #
49
- # msg.add_additional(rr)
50
- # msg.each_additional {|rr| ... }
51
- #
52
- #In addition, each_resource iterates the answer, additional
53
- #and authority sections :
54
- #
55
- # msg.each_resource {|rr| ... }
56
- #
57
- #===Packet format encoding
58
- #
59
- # Dnsruby::Message#encode
60
- # Dnsruby::Message::decode(data)
61
- #
62
- #===Additional information
63
- #security_level records the current DNSSEC status of this Message.
64
- #answerfrom records the server which this Message was received from.
65
- #cached records whether this response came from the cache.
66
- #
67
- class Message
68
- # The security level (see RFC 4035 section 4.3)
69
- class SecurityLevel < CodeMapper
70
- INDETERMINATE = -2
71
- BOGUS = -1
72
- UNCHECKED = 0
73
- INSECURE = 1
74
- SECURE = 2
75
- update()
76
- end
77
- # If dnssec is set on, then each message will have the security level set
78
- # To find the precise error (if any), call Dnsruby::Dnssec::validate(msg) -
79
- # the resultant exception will define the error.
80
- attr_accessor :security_level
81
- # If there was a problem verifying this message with DNSSEC, then securiy_error
82
- # will hold a description of the problem. It defaults to ""
83
- attr_accessor :security_error
84
-
85
- # If the Message was returned from the cache, the cached flag will be set
86
- # true. It will be false otherwise.
87
- attr_accessor :cached
88
-
89
-
90
- class Section < Array
91
- def initialize(msg = nil)
92
- @msg = msg
93
- super(0)
94
- end
95
- # Return the rrset of the specified type in this section
96
- def rrset(name, type=Types.A, klass=Classes::IN)
97
- rrs = select{|rr|
98
- type_ok = (rr.type==type)
99
- if (rr.type == Types::RRSIG)
100
- type_ok = (rr.type_covered == type)
101
- end
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)
106
- }
107
- rrset = RRSet.new()
108
- rrs.each do |rr|
109
- rrset.add(rr)
110
- end
111
- return rrset
112
- end
113
-
114
- # Return an array of all the rrsets in the section
115
- def rrsets(type = nil, include_opt = false)
116
- if (type && !(Types === type))
117
- type = Types.new(type)
118
- end
119
- ret = []
120
- each do |rr|
121
- next if (!include_opt && (rr.type == Types::OPT))
122
- # if (type)
123
- # next if ((rr.type == Types.RRSIG) && (type != Types.RRSIG) && (rr.type_covered != type))
124
- # next if (rr.type != type)
125
- # end
126
- if (type)
127
- # if this is an rrsig type, then :
128
- # only include it if the type_covered is the type requested,
129
- # OR if the type requested is an RRSIG
130
- if (rr.type == Types::RRSIG)
131
- if ((rr.type_covered == type) || (type == Types::RRSIG))
132
- else
133
- next
134
- end
135
- # next if ((rr.type_covered != type) || (type != Types.RRSIG))
136
- elsif (rr.type != type)
137
- next
138
- end
139
- end
140
-
141
- found_rrset = false
142
- ret.each do |rrset|
143
- found_rrset = rrset.add(rr)
144
- break if found_rrset
145
- end
146
- if (!found_rrset)
147
- ret.push(RRSet.new(rr))
148
- end
149
- end
150
- return ret
151
- end
152
- def ==(other)
153
- return false unless (other.instance_of?Message::Section)
154
- return false if (other.rrsets(nil, true).length != self.rrsets(nil, true).length)
155
- otherrrsets = other.rrsets(nil, true)
156
- self.rrsets(nil, true).each {|rrset|
157
- return false unless otherrrsets.include?rrset
158
- }
159
- return true
160
- end
161
-
162
- def remove_rrset(name, type)
163
- # Remove all RRs with the name and type from the section.
164
- # Need to worry about header counts here - can we get Message to
165
- # update the counts itself, rather than the section worrying about it?
166
- rrs_to_delete = []
167
- each do |rr|
168
- next if rr.rr_type == Types::OPT
169
- if ((rr.name.to_s.downcase == name.to_s.downcase) &&
170
- ((rr.type == type) ||
171
- ((rr.type == Types::RRSIG) && (rr.type_covered == type)) ))
172
- rrs_to_delete.push(rr)
173
- end
174
- end
175
- rrs_to_delete.each {|rr|
176
- delete(rr)
177
- }
178
- @msg.update_counts if @msg
179
- end
180
- end
181
- #Create a new Message. Takes optional name, type and class
182
- #
183
- #type defaults to A, and klass defaults to IN
184
- #
185
- #* Dnsruby::Message.new("example.com") # defaults to A, IN
186
- #* Dnsruby::Message.new("example.com", 'AAAA')
187
- #* Dnsruby::Message.new("example.com", Dnsruby::Types.PTR, "HS")
188
- #
189
- def initialize(*args)
190
- @header = Header.new()
191
- # @question = Section.new(self)
192
- @question = []
193
- @answer = Section.new(self)
194
- @authority = Section.new(self)
195
- @additional = Section.new(self)
196
- @tsigstate = :Unsigned
197
- @signing = false
198
- @tsigkey = nil
199
- @answerfrom = nil
200
- @answerip = nil
201
- @send_raw = false
202
- @do_validation = true
203
- @do_caching = true
204
- @security_level = SecurityLevel.UNCHECKED
205
- @security_error = nil
206
- @cached = false
207
- type = Types::A
208
- klass = Classes::IN
209
- if (args.length > 0)
210
- name = args[0]
211
- if (args.length > 1)
212
- type = Types.new(args[1])
213
- if (args.length > 2)
214
- klass = Classes.new(args[2])
215
- end
216
- end
217
- add_question(name, type, klass)
218
- end
219
- end
220
-
221
- #The question section, an array of Dnsruby::Question objects.
222
- attr_reader :question
223
-
224
- #The answer section, an array of Dnsruby::RR objects.
225
- attr_reader :answer
226
- #The authority section, an array of Dnsruby::RR objects.
227
- attr_reader :authority
228
- #The additional section, an array of Dnsruby::RR objects.
229
- attr_reader :additional
230
- #The header section, a Dnsruby::Header object.
231
- attr_accessor :header
232
-
233
- #If this Message is a response from a server, then answerfrom contains the address of the server
234
- attr_accessor :answerfrom
235
-
236
- #If this Message is a response from a server, then answerfrom contains the IP address of the server
237
- attr_accessor :answerip
238
-
239
- #If this Message is a response from a server, then answersize contains the size of the response
240
- attr_accessor :answersize
241
-
242
- #If this message has been verified using a TSIG RR then tsigerror contains
243
- #the error code returned by the TSIG verification. The error will be an RCode
244
- attr_accessor :tsigerror
245
-
246
- #Can be
247
- #* :Unsigned - the default state
248
- #* :Signed - the outgoing message has been signed
249
- #* :Verified - the incoming message has been verified by TSIG
250
- #* :Intermediate - the incoming message is an intermediate envelope in a TCP session
251
- #in which only every 100th envelope must be signed
252
- #* :Failed - the incoming response failed verification
253
- attr_accessor :tsigstate
254
-
255
- #--
256
- attr_accessor :tsigstart
257
- #++
258
-
259
- #Set send_raw if you wish to send and receive the response to this Message
260
- #with no additional processing. In other words, if set, then Dnsruby will
261
- #not touch the Header of the outgoing Message. This option does not affect
262
- #caching or dnssec validation
263
- #
264
- #This option should not normally be set.
265
- attr_accessor :send_raw
266
-
267
- #do_validation is set by default. If you do not wish dnsruby to validate
268
- #this message (on a Resolver with @dnssec==true), then set do_validation
269
- #to false. This option does not affect caching, or the header options
270
- attr_accessor :do_validation
271
-
272
- #do_caching is set by default. If you do not wish dnsruby to inspect the
273
- #cache before sending the query, nor cache the result of the query, then
274
- #set do_caching to false.
275
- attr_accessor :do_caching
276
-
277
- def get_exception
278
- exception = nil
279
- if (rcode==RCode.NXDOMAIN)
280
- exception = NXDomain.new
281
- elsif (rcode==RCode.SERVFAIL)
282
- exception = ServFail.new
283
- elsif (rcode==RCode.FORMERR)
284
- exception = FormErr.new
285
- elsif (rcode==RCode.NOTIMP)
286
- exception = NotImp.new
287
- elsif (rcode==RCode.REFUSED)
288
- exception = Refused.new
289
- elsif (rcode==RCode.NOTZONE)
290
- exception = NotZone.new
291
- elsif (rcode==RCode.NOTAUTH)
292
- exception = NotAuth.new
293
- elsif (rcode==RCode.NXRRSET)
294
- exception = NXRRSet.new
295
- elsif (rcode==RCode.YXRRSET)
296
- exception = YXRRSet.new
297
- elsif (rcode==RCode.YXDOMAIN)
298
- exception = YXDomain.new
299
- elsif (rcode >= RCode.BADSIG && rcode <= RCode.BADALG)
300
- return VerifyError.new # @TODO@
301
- end
302
- return exception
303
- end
304
-
305
- def ==(other)
306
- ret = false
307
- if (other.kind_of?Message)
308
- ret = @header == other.header &&
309
- @question[0] == other.question[0] &&
310
- @answer == other.answer &&
311
- @authority == other.authority &&
312
- @additional == other.additional
313
- end
314
- return ret
315
- end
316
-
317
- def remove_additional
318
- @additional = Section.new(self)
319
- @header.arcount = 0
320
- end
321
-
322
- # Return the first rrset of the specified attributes in the message
323
- def rrset(name, type, klass = Classes::IN)
324
- [@answer, @authority, @additional].each do |section|
325
- if ((rrset = section.rrset(name, type, klass)).length > 0)
326
- return rrset
327
- end
328
- end
329
- return RRSet.new
330
- end
331
-
332
- # Return the rrsets of the specified type in the message
333
- def rrsets(type, klass=Classes::IN)
334
- rrsetss = []
335
- [@answer, @authority, @additional].each do |section|
336
- if ((rrsets = section.rrsets(type, klass)).length > 0)
337
- rrsets.each {|rrset|
338
- rrsetss.push(rrset)
339
- }
340
- end
341
- end
342
- return rrsetss
343
- end
344
-
345
- # Return a hash, with the section as key, and the RRSets in that
346
- # section as the data : {section => section_rrs}
347
- def section_rrsets(type = nil, include_opt = false)
348
- ret = {}
349
- ["answer", "authority", "additional"].each do |section|
350
- ret[section] = self.send(section).rrsets(type, include_opt)
351
- end
352
- return ret
353
- end
354
-
355
- #Add a new Question to the Message. Takes either a Question,
356
- #or a name, and an optional type and class.
357
- #
358
- #* msg.add_question(Question.new("example.com", 'MX'))
359
- #* msg.add_question("example.com") # defaults to Types.A, Classes.IN
360
- #* msg.add_question("example.com", Types.LOC)
361
- def add_question(question, type=Types.A, klass=Classes.IN)
362
- if (!question.kind_of?Question)
363
- question = Question.new(question, type, klass)
364
- end
365
- @question << question
366
- update_counts
367
- end
368
-
369
- def each_question
370
- @question.each {|rec|
371
- yield rec
372
- }
373
- end
374
-
375
- def update_counts # :nodoc:all
376
- @header.ancount = @answer.length
377
- @header.arcount = @additional.length
378
- @header.qdcount = @question.length
379
- @header.nscount = @authority.length
380
- end
381
-
382
-
383
- def add_answer(rr) #:nodoc: all
384
- if (!@answer.include?rr)
385
- @answer << rr
386
- update_counts
387
- end
388
- end
389
-
390
- def each_answer
391
- @answer.each {|rec|
392
- yield rec
393
- }
394
- end
395
-
396
- def add_authority(rr) #:nodoc: all
397
- if (!@authority.include?rr)
398
- @authority << rr
399
- update_counts
400
- end
401
- end
402
-
403
- def each_authority
404
- @authority.each {|rec|
405
- yield rec
406
- }
407
- end
408
-
409
- def add_additional(rr) #:nodoc: all
410
- if (!@additional.include?rr)
411
- @additional << rr
412
- update_counts
413
- end
414
- end
415
-
416
- def each_additional
417
- @additional.each {|rec|
418
- yield rec
419
- }
420
- end
421
-
422
- #Yields each section (question, answer, authority, additional)
423
- def each_section
424
- [@answer, @authority, @additional].each {|section| yield section}
425
- end
426
-
427
- #Calls each_answer, each_authority, each_additional
428
- def each_resource
429
- each_answer {|rec| yield rec}
430
- each_authority {|rec| yield rec}
431
- each_additional {|rec| yield rec}
432
- end
433
-
434
- # Returns the TSIG record from the ADDITIONAL section, if one is present.
435
- def tsig
436
- if (@additional.last)
437
- if (@additional.last.rr_type == Types.TSIG)
438
- return @additional.last
439
- end
440
- end
441
- return nil
442
- end
443
-
444
- #Sets the TSIG to sign this message with. Can either be a Dnsruby::RR::TSIG
445
- #object, or it can be a (name, key) tuple, or it can be a hash which takes
446
- #Dnsruby::RR::TSIG attributes (e.g. name, key, fudge, etc.)
447
- def set_tsig(*args)
448
- if (args.length == 1)
449
- if (args[0].instance_of?RR::TSIG)
450
- @tsigkey = args[0]
451
- elsif (args[0].instance_of?Hash)
452
- @tsigkey = RR.create({:type=>'TSIG', :klass=>'ANY'}.merge(args[0]))
453
- else
454
- raise ArgumentError.new("Wrong type of argument to Dnsruby::Message#set_tsig - should be TSIG or Hash")
455
- end
456
- elsif (args.length == 2)
457
- @tsigkey = RR.create({:type=>'TSIG', :klass=>'ANY', :name=>args[0], :key=>args[1]})
458
- else
459
- raise ArgumentError.new("Wrong number of arguments to Dnsruby::Message#set_tsig")
460
- end
461
- end
462
-
463
- #Was this message signed by a TSIG?
464
- def signed?
465
- return (@tsigstate == :Signed ||
466
- @tsigstate == :Verified ||
467
- @tsigstate == :Failed)
468
- end
469
-
470
- #If this message was signed by a TSIG, was the TSIG verified?
471
- def verified?
472
- return (@tsigstate == :Verified)
473
- end
474
-
475
- def get_opt
476
- each_additional do |r|
477
- if (r.type == Types::OPT)
478
- return r
479
- end
480
- end
481
- return nil
482
- end
483
-
484
- def rcode
485
- rcode = @header.get_header_rcode
486
- opt = get_opt
487
- if (opt != nil)
488
- rcode = rcode.code + (opt.xrcode.code << 4)
489
- rcode = RCode.new(rcode)
490
- end
491
- return rcode;
492
- end
493
-
494
- def to_s
495
- retval = "";
496
-
497
- if (@answerfrom != nil && @answerfrom != "")
498
- retval = retval + ";; Answer received from #{@answerfrom} (#{@answersize} bytes)\n;;\n";
499
- end
500
- retval = retval + ";; Security Level : #{@security_level.string}\n"
501
-
502
- retval = retval + ";; HEADER SECTION\n"
503
- # OPT pseudosection? EDNS flags, udpsize
504
- opt = get_opt
505
- if (!opt)
506
- retval = retval + @header.to_s
507
- else
508
- retval = retval + @header.to_s_with_rcode(rcode())
509
- end
510
- retval = retval + "\n"
511
-
512
- if (opt)
513
- retval = retval + opt.to_s
514
- retval = retval + "\n"
515
- end
516
-
517
- section = (@header.opcode == OpCode.UPDATE) ? "ZONE" : "QUESTION";
518
- retval = retval + ";; #{section} SECTION (#{@header.qdcount} record#{@header.qdcount == 1 ? '' : 's'})\n";
519
- each_question { |qr|
520
- retval = retval + ";; #{qr.to_s}\n";
521
- }
522
-
523
- if (@answer.size > 0)
524
- retval = retval + "\n";
525
- section = (@header.opcode == OpCode.UPDATE) ? "PREREQUISITE" : "ANSWER";
526
- retval = retval + ";; #{section} SECTION (#{@header.ancount} record#{@header.ancount == 1 ? '' : 's'})\n";
527
- each_answer { |rr|
528
- retval = retval + rr.to_s + "\n";
529
- }
530
- end
531
-
532
- if (@authority.size > 0)
533
- retval = retval + "\n";
534
- section = (@header.opcode == OpCode.UPDATE) ? "UPDATE" : "AUTHORITY";
535
- retval = retval + ";; #{section} SECTION (#{@header.nscount} record#{@header.nscount == 1 ? '' : 's'})\n";
536
- each_authority { |rr|
537
- retval = retval + rr.to_s + "\n";
538
- }
539
- end
540
-
541
- if ((@additional.size > 0 && !opt) || (@additional.size > 1))
542
- retval = retval + "\n";
543
- retval = retval + ";; ADDITIONAL SECTION (#{@header.arcount} record#{@header.arcount == 1 ? '' : 's'})\n";
544
- each_additional { |rr|
545
- if (rr.type != Types::OPT)
546
- retval = retval + rr.to_s+ "\n"
547
- end
548
- }
549
- end
550
-
551
- return retval;
552
- end
553
-
554
- #Signs the message. If used with no arguments, then the message must have already
555
- #been set (set_tsig). Otherwise, the arguments can either be a Dnsruby::RR::TSIG
556
- #object, or a (name, key) tuple, or a hash which takes
557
- #Dnsruby::RR::TSIG attributes (e.g. name, key, fudge, etc.)
558
- #
559
- #NOTE that this method should only be called by the resolver, rather than the
560
- #client code. To use signing from the client, call Dnsruby::Resolver#tsig=
561
- def sign!(*args) #:nodoc: all
562
- if (args.length > 0)
563
- set_tsig(*args)
564
- sign!
565
- else
566
- if ((@tsigkey) && @tsigstate == :Unsigned)
567
- @tsigkey.apply(self)
568
- end
569
- end
570
- end
571
-
572
- #Return the encoded form of the message
573
- # If there is a TSIG record present and the record has not been signed
574
- # then sign it
575
- def encode
576
- if ((@tsigkey) && @tsigstate == :Unsigned && !@signing)
577
- @signing = true
578
- sign!
579
- @signing = false
580
- end
581
- return MessageEncoder.new {|msg|
582
- header = @header
583
- header.encode(msg)
584
- @question.each {|q|
585
- msg.put_name(q.qname)
586
- msg.put_pack('nn', q.qtype.code, q.qclass.code)
587
- }
588
- [@answer, @authority, @additional].each {|rr|
589
- rr.each { |r|
590
- msg.put_rr(r)
591
- }
592
- }
593
- }.to_s
594
- end
595
-
596
- #Decode the encoded message
597
- def Message.decode(m)
598
- o = Message.new()
599
- begin
600
- MessageDecoder.new(m) {|msg|
601
- o.header = Header.new(msg)
602
- o.header.qdcount.times {
603
- question = msg.get_question
604
- o.question << question
605
- }
606
- o.header.ancount.times {
607
- rr = msg.get_rr
608
- o.answer << rr
609
- }
610
- o.header.nscount.times {
611
- rr = msg.get_rr
612
- o.authority << rr
613
- }
614
- o.header.arcount.times { |count|
615
- start = msg.index
616
- rr = msg.get_rr
617
- if (rr.type == Types::TSIG)
618
- if (count!=o.header.arcount-1)
619
- Dnsruby.log.Error("Incoming message has TSIG record before last record")
620
- raise DecodeError.new("TSIG record present before last record")
621
- end
622
- o.tsigstart = start # needed for TSIG verification
623
- end
624
- o.additional << rr
625
- }
626
- }
627
- rescue DecodeError => e
628
- # So we got a decode error
629
- # However, we might have been able to fill in many parts of the message
630
- # So let's raise the DecodeError, but add the partially completed message
631
- e.partial_message = o
632
- raise e
633
- end
634
- return o
635
- end
636
-
637
- def clone
638
- Message.decode(self.encode)
639
- end
640
-
641
- def ==(msg2)
642
- return self.to_s == msg2.to_s
643
- end
644
-
645
- #In dynamic update packets, the question section is known as zone and
646
- #specifies the zone to be updated.
647
- alias :zone :question
648
- alias :add_zone :add_question
649
- alias :each_zone :each_question
650
- #In dynamic update packets, the answer section is known as pre or
651
- #prerequisite and specifies the RRs or RRsets which must or
652
- #must not preexist.
653
- alias :pre :answer
654
- alias :add_pre :add_answer
655
- alias :each_pre :each_answer
656
- #In dynamic update packets, the answer section is known as pre or
657
- #prerequisite and specifies the RRs or RRsets which must or
658
- #must not preexist.
659
- alias :prerequisite :pre
660
- alias :add_prerequisite :add_pre
661
- alias :each_prerequisite :each_pre
662
- #In dynamic update packets, the authority section is known as update and
663
- #specifies the RRs or RRsets to be added or delted.
664
- alias :update :authority
665
- alias :add_update :add_authority
666
- alias :each_update :each_authority
667
-
668
- end
669
-
670
- #The header portion of a DNS packet
671
- #
672
- #RFC 1035 Section 4.1.1
673
- class Header
674
- MAX_ID = 65535
675
-
676
- # The header ID
677
- attr_accessor :id
678
-
679
- #The query response flag
680
- attr_accessor :qr
681
-
682
- #Authoritative answer flag
683
- attr_accessor :aa
684
-
685
- #Truncated flag
686
- attr_accessor :tc
687
-
688
- #Recursion Desired flag
689
- attr_accessor :rd
690
-
691
- #The Checking Disabled flag
692
- attr_accessor :cd
693
-
694
- #The Authenticated Data flag
695
- #Relevant in DNSSEC context.
696
- #(The AD bit is only set on answers where signatures have been
697
- #cryptographically verified or the server is authoritative for the data
698
- #and is allowed to set the bit by policy.)
699
- attr_accessor :ad
700
-
701
- #The query response flag
702
- attr_accessor :qr
703
-
704
- #Recursion available flag
705
- attr_accessor :ra
706
-
707
- #Query response code
708
- #deprecated - use Message#rcode
709
- # attr_reader :rcode
710
-
711
- # This new get_header_rcode method is intended for use only by the Message class.
712
- # This is because the Message OPT section may contain an extended rcode (see
713
- # RFC 2671 section 4.6). Using the header rcode only ignores this extension, and
714
- # is not recommended.
715
- def get_header_rcode
716
- @rcode
717
- end
718
-
719
- # The header opcode
720
- attr_reader :opcode
721
-
722
- #The number of records in the question section of the message
723
- attr_accessor :qdcount
724
- #The number of records in the authoriy section of the message
725
- attr_accessor :nscount
726
- #The number of records in the answer section of the message
727
- attr_accessor :ancount
728
- #The number of records in the additional record section og the message
729
- attr_accessor :arcount
730
-
731
- def initialize(*args)
732
- if (args.length == 0)
733
- @id = rand(MAX_ID)
734
- @qr = false
735
- @opcode=OpCode.Query
736
- @aa = false
737
- @ad=false
738
- @tc = false
739
- @rd = false # recursion desired
740
- @ra = false # recursion available
741
- @cd=false
742
- @rcode=RCode.NoError
743
- @qdcount = 0
744
- @nscount = 0
745
- @ancount = 0
746
- @arcount = 0
747
- elsif (args.length == 1)
748
- decode(args[0])
749
- end
750
- end
751
-
752
- def opcode=(op)
753
- @opcode = OpCode.new(op)
754
- end
755
-
756
- def rcode=(rcode)
757
- @rcode = RCode.new(rcode)
758
- end
759
-
760
- def Header.new_from_data(data)
761
- header = Header.new
762
- MessageDecoder.new(data) {|msg|
763
- header.decode(msg)}
764
- return header
765
- end
766
-
767
- def data
768
- return MessageEncoder.new {|msg|
769
- self.encode(msg)
770
- }.to_s
771
- end
772
-
773
- def encode(msg)
774
- msg.put_pack('nnnnnn',
775
- @id,
776
- (@qr ? 1:0) << 15 |
777
- (@opcode.code & 15) << 11 |
778
- (@aa ? 1:0) << 10 |
779
- (@tc ? 1:0) << 9 |
780
- (@rd ? 1:0) << 8 |
781
- (@ra ? 1:0) << 7 |
782
- (@ad ? 1:0) << 5 |
783
- (@cd ? 1:0) << 4 |
784
- (@rcode.code & 15),
785
- @qdcount,
786
- @ancount,
787
- @nscount,
788
- @arcount)
789
- end
790
-
791
- def Header.decrement_arcount_encoded(bytes)
792
- header = Header.new
793
- header_end = 0
794
- MessageDecoder.new(bytes) {|msg|
795
- header.decode(msg)
796
- header_end = msg.index
797
- }
798
- header.arcount = header.arcount - 1
799
- bytes[0,header_end]=MessageEncoder.new {|msg|
800
- header.encode(msg)}.to_s
801
- return bytes
802
- end
803
-
804
- def ==(other)
805
- return @qr == other.qr &&
806
- @opcode == other.opcode &&
807
- @aa == other.aa &&
808
- @tc == other.tc &&
809
- @rd == other.rd &&
810
- @ra == other.ra &&
811
- @cd == other.cd &&
812
- @ad == other.ad &&
813
- @rcode == other.get_header_rcode
814
- end
815
-
816
- def to_s
817
- to_s_with_rcode(@rcode)
818
- end
819
-
820
- def to_s_with_rcode(rcode)
821
- retval = ";; id = #{@id}\n";
822
-
823
- if (@opcode == OpCode::Update)
824
- retval += ";; qr = #{@qr} " +\
825
- "opcode = #{@opcode.string} "+\
826
- "rcode = #{@rcode.string}\n";
827
-
828
- retval += ";; zocount = #{@qdcount} "+\
829
- "prcount = #{@ancount} " +\
830
- "upcount = #{@nscount} " +\
831
- "adcount = #{@arcount}\n";
832
- else
833
- retval += ";; qr = #{@qr} " +\
834
- "opcode = #{@opcode.string} " +\
835
- "aa = #{@aa} " +\
836
- "tc = #{@tc} " +\
837
- "rd = #{@rd}\n";
838
-
839
- retval += ";; ra = #{@ra} " +\
840
- "ad = #{@ad} " +\
841
- "cd = #{@cd} " +\
842
- "rcode = #{rcode.string}\n";
843
-
844
- retval += ";; qdcount = #{@qdcount} " +\
845
- "ancount = #{@ancount} " +\
846
- "nscount = #{@nscount} " +\
847
- "arcount = #{@arcount}\n";
848
- end
849
-
850
- return retval;
851
- end
852
-
853
- def decode(msg)
854
- @id, flag, @qdcount, @ancount, @nscount, @arcount =
855
- msg.get_unpack('nnnnnn')
856
- @qr = (((flag >> 15)&1)==1)?true:false
857
- @opcode = OpCode.new((flag >> 11) & 15)
858
- @aa = (((flag >> 10)&1)==1)?true:false
859
- @tc = (((flag >> 9)&1)==1)?true:false
860
- @rd = (((flag >> 8)&1)==1)?true:false
861
- @ra = (((flag >> 7)&1)==1)?true:false
862
- @ad = (((flag >> 5)&1)==1)?true:false
863
- @cd = (((flag >> 4)&1)==1)?true:false
864
- @rcode = RCode.new(flag & 15)
865
- end
866
-
867
- alias zocount qdcount
868
- alias zocount= qdcount=
869
-
870
- alias prcount ancount
871
- alias prcount= ancount=
872
-
873
- alias upcount nscount
874
- alias upcount= nscount=
875
-
876
- alias adcount arcount
877
- alias adcount= arcount=
878
-
879
- end
880
-
881
- class MessageDecoder #:nodoc: all
882
- attr_reader :index
883
- def initialize(data)
884
- @data = data
885
- @index = 0
886
- @limit = data.length
887
- yield self
888
- end
889
-
890
- def has_remaining
891
- return @limit-@index > 0
892
- end
893
-
894
- def get_length16
895
- len, = self.get_unpack('n')
896
- save_limit = @limit
897
- @limit = @index + len
898
- d = yield(len)
899
- if @index < @limit
900
- raise DecodeError.new("junk exists")
901
- elsif @limit < @index
902
- raise DecodeError.new("limit exceeded")
903
- end
904
- @limit = save_limit
905
- return d
906
- end
907
-
908
- def get_bytes(len = @limit - @index)
909
- d = @data[@index, len]
910
- @index += len
911
- return d
912
- end
913
-
914
- def get_unpack(template)
915
- len = 0
916
- littlec = ?c
917
- bigc = ?C
918
- littleh = ?h
919
- bigh = ?H
920
- littlen = ?n
921
- bign = ?N
922
- star = ?*
923
- if (littlec.class != Fixnum)
924
- # We're using Ruby 1.9 - convert the codes
925
- littlec = littlec.getbyte(0)
926
- bigc = bigc.getbyte(0)
927
- littleh = littleh.getbyte(0)
928
- bigh = bigh.getbyte(0)
929
- littlen = littlen.getbyte(0)
930
- bign = bign.getbyte(0)
931
- star = star.getbyte(0)
932
- end
933
- template.each_byte {|byte|
934
- case byte
935
- when littlec, bigc
936
- len += 1
937
- when littleh, bigh
938
- len += 1
939
- when littlen
940
- len += 2
941
- when bign
942
- len += 4
943
- when star
944
- len = @limit-@index
945
- else
946
- raise StandardError.new("unsupported template: '#{byte.chr}' in '#{template}'")
947
- end
948
- }
949
- raise DecodeError.new("limit exceeded") if @limit < @index + len
950
- arr = @data.unpack("@#{@index}#{template}")
951
- @index += len
952
- return arr
953
- end
954
-
955
- def get_string
956
- len = @data[@index]
957
- if (len.class == String)
958
- len = len.getbyte(0)
959
- end
960
- raise DecodeError.new("limit exceeded\nlimit = #{@limit}, index = #{@index}, len = #{len}\n") if @limit < @index + 1 + (len ? len : 0)
961
- d = @data[@index + 1, len]
962
- @index += 1 + len
963
- return d
964
- end
965
-
966
- def get_string_list
967
- strings = []
968
- while @index < @limit
969
- strings << self.get_string
970
- end
971
- strings
972
- end
973
-
974
- def get_name
975
- return Name.new(self.get_labels)
976
- end
977
-
978
- def get_labels(limit=nil)
979
- limit = @index if !limit || @index < limit
980
- d = []
981
- while true
982
- temp = @data[@index]
983
- if (temp.class == String)
984
- temp = (temp.getbyte(0))
985
- end
986
- case temp # @data[@index]
987
- when 0
988
- @index += 1
989
- return d
990
- when 192..255
991
- idx = self.get_unpack('n')[0] & 0x3fff
992
- if limit <= idx
993
- raise DecodeError.new("non-backward name pointer")
994
- end
995
- save_index = @index
996
- @index = idx
997
- d += self.get_labels(limit)
998
- @index = save_index
999
- return d
1000
- else
1001
- d << self.get_label
1002
- end
1003
- end
1004
- return d
1005
- end
1006
-
1007
- def get_label
1008
- begin
1009
- # label = Name::Label.new(Name::decode(self.get_string))
1010
- label = Name::Label.new(self.get_string)
1011
- return label
1012
- # return Name::Label::Str.new(self.get_string)
1013
- rescue ResolvError => e
1014
- raise DecodeError.new(e) # Turn it into something more suitable
1015
- end
1016
- end
1017
-
1018
- def get_question
1019
- name = self.get_name
1020
- type, klass = self.get_unpack("nn")
1021
- q = Question.new(name, type, klass)
1022
- return q
1023
- end
1024
-
1025
- def get_rr
1026
- name = self.get_name
1027
- type, klass, ttl = self.get_unpack('nnN')
1028
- klass = Classes.new(klass)
1029
- typeclass = RR.get_class(type, klass)
1030
- # @TODO@ Trap decode errors here, and somehow mark the record as bad.
1031
- # Need some way to represent raw data only
1032
- rec = self.get_length16 {typeclass.decode_rdata(self)}
1033
- rec.name=name
1034
- rec.ttl=ttl
1035
- rec.type = type
1036
- rec.klass = klass
1037
- return rec
1038
- end
1039
- end
1040
-
1041
- class MessageEncoder #:nodoc: all
1042
- def initialize
1043
- @data = ''
1044
- @names = {}
1045
- yield self
1046
- end
1047
-
1048
- def to_s
1049
- return @data
1050
- end
1051
-
1052
- def put_bytes(d)
1053
- @data << d
1054
- end
1055
-
1056
- def put_pack(template, *d)
1057
- @data << d.pack(template)
1058
- end
1059
-
1060
- def put_length16
1061
- length_index = @data.length
1062
- @data << "\0\0"
1063
- data_start = @data.length
1064
- yield
1065
- data_end = @data.length
1066
- @data[length_index, 2] = [data_end - data_start].pack("n")
1067
- end
1068
-
1069
- def put_string(d)
1070
- self.put_pack("C", d.length)
1071
- @data << d
1072
- end
1073
-
1074
- def put_string_list(ds)
1075
- ds.each {|d|
1076
- self.put_string(d)
1077
- }
1078
- end
1079
-
1080
- def put_rr(rr, canonical=false)
1081
- # RFC4034 Section 6.2
1082
- put_name(rr.name, canonical)
1083
- put_pack("nnN", rr.type.code, rr.klass.code, rr.ttl)
1084
- put_length16 {rr.encode_rdata(self, canonical)}
1085
- end
1086
-
1087
- def put_name(d, canonical=false, downcase = canonical)
1088
- # DNSSEC requires some records (e.g. NSEC, RRSIG) to be canonicalised, but
1089
- # not downcased. YUK!
1090
- if (downcase)
1091
- d = d.downcase
1092
- end
1093
- put_labels(d.to_a, canonical)
1094
- end
1095
-
1096
- def put_labels(d, do_canonical)
1097
- d.each_index {|i|
1098
- domain = d[i..-1].join(".")
1099
- if (!do_canonical && (idx = @names[domain]))
1100
- self.put_pack("n", 0xc000 | idx)
1101
- return
1102
- else
1103
- @names[domain] = @data.length
1104
- self.put_label(d[i])
1105
- end
1106
- }
1107
- @data << "\0"
1108
- end
1109
-
1110
-
1111
- def put_label(d)
1112
- # s, = Name.encode(d)
1113
- s = d
1114
- raise RuntimeError, "length of #{s} is #{s.string.length} (larger than 63 octets)" if s.string.length > 63
1115
- self.put_string(s.string)
1116
- end
1117
- end
1118
-
1119
- #A Dnsruby::Question object represents a record in the
1120
- #question section of a DNS packet.
1121
- #
1122
- #RFC 1035 Section 4.1.2
1123
- class Question
1124
- # The Question name
1125
- attr_reader :qname
1126
- # The Question type
1127
- attr_reader :qtype
1128
- # The Question class
1129
- attr_reader :qclass
1130
-
1131
- #Creates a question object from the domain, type, and class passed
1132
- #as arguments.
1133
- #
1134
- #If a String is passed in, a Name, IPv4 or IPv6 object is created.
1135
- #
1136
- #If an IPv4 or IPv6 object is used then the type is set to PTR.
1137
- def initialize(*args)
1138
- @qtype = Types::A
1139
- @qclass = Classes::IN
1140
- type_given = false
1141
- if (args.length > 0)
1142
- if (args.length > 1)
1143
- @qtype = Types.new(args[1])
1144
- type_given = true
1145
- if (args.length > 2)
1146
- @qclass = Classes.new(args[2])
1147
- end
1148
- end
1149
- else
1150
- raise ArgumentError.new("Must pass at least a name!")
1151
- end
1152
- # If the name looks like an IP address then do an appropriate
1153
- # PTR query, unless the user specified the qtype
1154
- @qname=args[0]
1155
- if (!type_given)
1156
- case @qname.to_s
1157
- when IPv4::Regex
1158
- @qname = IPv4.create(@qname).to_name
1159
- @qtype = Types.PTR
1160
- when IPv6::Regex
1161
- @qname = IPv6.create(@qname).to_name
1162
- @qtype = Types.PTR
1163
- when Name
1164
- when IPv6
1165
- @qtype = Types.PTR
1166
- when IPv4
1167
- @qtype = Types.PTR
1168
- else
1169
- @qname = Name.create(@qname)
1170
- end
1171
- else
1172
- case @qtype
1173
- when Types.PTR
1174
- case @qname.to_s
1175
- when IPv4::Regex
1176
- @qname = IPv4.create(@qname).to_name
1177
- when IPv6::Regex
1178
- @qname = IPv6.create(@qname).to_name
1179
- when IPv6
1180
- when IPv4
1181
- else
1182
- @qname = Name.create(@qname)
1183
- end
1184
- else
1185
- @qname = Name.create(@qname)
1186
- end
1187
- end
1188
- end
1189
-
1190
- def qtype=(qtype)
1191
- @qtype = Types.new(qtype)
1192
- end
1193
-
1194
- def qclass=(qclass)
1195
- @qclass = Classes.new(qclass)
1196
- end
1197
-
1198
- def qname=(qname)
1199
- case qname
1200
- when IPv4::Regex
1201
- @qname = IPv4.create(qname).to_name
1202
- @qtype = Types.PTR
1203
- when IPv6::Regex
1204
- @qname = IPv6.create(qname).to_name
1205
- @qtype = Types.PTR
1206
- when Name
1207
- when IPv6
1208
- @qtype = Types.PTR
1209
- when IPv4
1210
- @qtype = Types.PTR
1211
- else
1212
- @qname = Name.create(qname)
1213
- end
1214
- end
1215
-
1216
- #Returns a string representation of the question record.
1217
- def to_s
1218
- return "#{@qname}.\t#{@qclass.string}\t#{@qtype.string}";
1219
- end
1220
-
1221
- # For Updates, the qname field is redefined to zname (RFC2136, section 2.3)
1222
- alias zname qname
1223
- # For Updates, the qtype field is redefined to ztype (RFC2136, section 2.3)
1224
- alias ztype qtype
1225
- # For Updates, the qclass field is redefined to zclass (RFC2136, section 2.3)
1226
- alias zclass qclass
1227
-
1228
- alias type qtype
1229
- end
1230
- end