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,55 +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
- module Dnsruby
17
- class RR
18
- #Class for DNS X25 resource records.
19
- #RFC 1183 Section 3.1
20
- class X25 < RR
21
- ClassValue = nil #:nodoc: all
22
- TypeValue = Types::X25 #:nodoc: all
23
-
24
- #The PSDN address
25
- attr_accessor :address
26
-
27
- def from_data(data)
28
- @address = data
29
- end
30
-
31
- def from_string(input)
32
- address = input
33
- address.sub!(/^\"/, "")
34
- @address = address.sub(/\"$/, "")
35
- end
36
-
37
- def rdata_to_string
38
- if (@address!=nil)
39
- return @address
40
- else
41
- return ""
42
- end
43
- end
44
-
45
- def encode_rdata(msg, canonical=false) #:nodoc: all
46
- msg.put_string(@address)
47
- end
48
-
49
- def self.decode_rdata(msg) #:nodoc: all
50
- address = msg.get_string
51
- return self.new(*address)
52
- end
53
- end
54
- end
55
- end
@@ -1,678 +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
- module Dnsruby
17
- ClassHash = {} #:nodoc: all
18
-
19
- # RFC2181, section 5
20
- # "It is however possible for most record types to exist
21
- # with the same label, class and type, but with different data. Such a
22
- # group of records is hereby defined to be a Resource Record Set
23
- # (RRSet)."
24
- # This class also stores the RRSIG records which cover the RRSet
25
- class RRSet
26
- include Comparable
27
- # The number of RRSIGs stored in this RRSet
28
- attr_reader :num_sigs
29
- def initialize(rrs = [])
30
- if (!rrs.instance_of?Array)
31
- rrs = [rrs]
32
- end
33
- @rrs = []
34
- @num_sigs = 0
35
- rrs.each {|rr| add(rr)}
36
- end
37
- def self.new_from_string(string)
38
- rr_strings = string.split("\n")
39
- rrs = rr_strings.map { |s| Dnsruby::RR.new_from_string(s) }
40
-
41
- Dnsruby::RRSet.new(rrs)
42
- end # The RRSIGs stored with this RRSet
43
- def sigs
44
- return @rrs[@rrs.length-@num_sigs, @num_sigs]
45
- end
46
- # The RRs (not RRSIGs) stored in this RRSet
47
- def rrs
48
- return @rrs[0, @rrs.length-@num_sigs]
49
- end
50
- def privateAdd(r) #:nodoc:
51
- if @rrs.include?r
52
- return true
53
- end
54
- new_pos = @rrs.length - @num_sigs
55
- if ((@num_sigs == @rrs.length) && @num_sigs > 0) # if we added RRSIG first
56
- if (((r.type != @rrs.last.type_covered) && (r.type != Types.RRSIG))||
57
- ((r.type == Types.RRSIG) && (r.type_covered != @rrs.last.type_covered)))
58
- return false
59
- end
60
- end
61
- if (r.type == Types::RRSIG)
62
- new_pos = @rrs.length
63
- @num_sigs += 1
64
- end
65
- @rrs.insert(new_pos, r)
66
- return true
67
- end
68
-
69
- #Add the RR to this RRSet
70
- #Takes a copy of the RR by default. To suppress this, pass false
71
- #as the second parameter.
72
- def add(rin, do_clone = true)
73
- if (rin.instance_of?RRSet)
74
- ret = false
75
- [rin.rrs, rin.sigs].each {|rr| ret = add(rr)}
76
- return ret
77
- end
78
- # r = RR.create(r.to_s) # clone the record
79
- r = nil
80
- if do_clone
81
- r = rin.clone
82
- else
83
- r = rin
84
- end
85
- if (@rrs.size() == 0) # && !(r.type == Types.RRSIG))
86
- return privateAdd(r)
87
- end
88
- # Check the type, klass and ttl are correct
89
- first = @rrs[0]
90
- if (!r.sameRRset(first))
91
- return false
92
- # raise ArgumentError.new("record does not match rrset")
93
- end
94
-
95
- if (!(r.type == Types::RRSIG) && (!(first.type == Types::RRSIG)))
96
- if (r.ttl != first.ttl) # RFC2181, section 5.2
97
- if (r.ttl > first.ttl)
98
- r.ttl=(first.ttl)
99
- else
100
- @rrs.each do |rr|
101
- rr.ttl = r.ttl
102
- end
103
- end
104
- end
105
- end
106
-
107
- return privateAdd(r)
108
- # return true
109
- end
110
-
111
- def <=>(other)
112
- # return 1 if ((!other) || !(other.name) || !(other.type))
113
- # return -1 if (!@name)
114
- if (name.canonical == other.name.canonical)
115
- return type.code <=> other.type.code
116
- else
117
- return name <=> other.name
118
- end
119
- end
120
-
121
- def sort_canonical
122
- #Make a list, for all the RRs, where each RR contributes
123
- #the canonical RDATA encoding
124
- canonical_rrs = {}
125
- self.rrs.each do |rr|
126
- data = MessageEncoder.new {|msg|
127
- rr.encode_rdata(msg, true)
128
- }.to_s
129
- canonical_rrs[data] = rr
130
- end
131
-
132
- return_rrs = RRSet.new
133
- canonical_rrs.keys.sort.each { |rdata|
134
- return_rrs.add(canonical_rrs[rdata], false)
135
- }
136
- return return_rrs
137
- end
138
-
139
- def ==(other)
140
- return false unless other.instance_of?RRSet
141
- return false if (other.sigs.length != self.sigs.length)
142
- return false if (other.rrs.length != self.rrs.length)
143
- return false if (other.ttl != self.ttl)
144
- otherrrs = other.rrs
145
- self.rrs.each {|rr|
146
- return false if (!otherrrs.include?rr)
147
- }
148
- othersigs= other.sigs
149
- self.sigs.each {|sig|
150
- return false if (!othersigs.include?sig)
151
- }
152
- return true
153
- end
154
- #Delete the RR from this RRSet
155
- def delete(rr)
156
- @rrs.delete(rr)
157
- end
158
- def each
159
- @rrs.each do |rr|
160
- yield rr
161
- end
162
- end
163
- def [](index)
164
- return @rrs[index]
165
- end
166
- #Return the type of this RRSet
167
- def type
168
- if (@rrs[0])
169
- return @rrs[0].type
170
- end
171
- return nil
172
- end
173
- #Return the klass of this RRSet
174
- def klass
175
- return @rrs[0].klass
176
- end
177
- #Return the ttl of this RRSet
178
- def ttl
179
- return @rrs[0].ttl
180
- end
181
- def ttl=(ttl)
182
- [rrs, sigs].each {|rrs|
183
- rrs.each {|rr|
184
- rr.ttl = ttl
185
- }
186
- }
187
- end
188
- def name
189
- if (@rrs[0])
190
- return @rrs[0].name
191
- else
192
- return nil
193
- end
194
- end
195
- def to_s
196
- ret = ""
197
- each {|rec|
198
- ret += rec.to_s + "\n"
199
- }
200
- return ret
201
- end
202
- def length
203
- return @rrs.length
204
- end
205
- end
206
-
207
- #Superclass for all Dnsruby resource records.
208
- #
209
- #Represents a DNS RR (resource record) [RFC1035, section 3.2]
210
- #
211
- #Use Dnsruby::RR::create(...) to create a new RR record.
212
- #
213
- # mx = Dnsruby::RR.create("example.com. 7200 MX 10 mailhost.example.com.")
214
- #
215
- # rr = Dnsruby::RR.create({:name => "example.com", :type => "MX", :ttl => 7200,
216
- # :preference => 10, :exchange => "mailhost.example.com"})
217
- #
218
- # s = rr.to_s # Get a String representation of the RR (in zone file format)
219
- # rr_again = Dnsruby::RR.create(s)
220
- #
221
- class RR
222
-
223
- include Comparable
224
-
225
- def <=>(other)
226
- # return 1 if ((!other) || !(other.name) || !(other.type))
227
- # return -1 if (!@name)
228
- if (@name.canonical == other.name.canonical)
229
- if (@type.code == other.type.code)
230
- return (@rdata <=> other.rdata)
231
- else
232
- return @type.code <=> other.type.code
233
- end
234
- else
235
- return @name <=> other.name
236
- end
237
- end
238
-
239
- # A regular expression which catches any valid resource record.
240
- @@RR_REGEX = Regexp.new("^\\s*(\\S+)\\s*(\\d+)?\\s*(#{Classes.regexp +
241
- "|CLASS\\d+"})?\\s*(#{Types.regexp + '|TYPE\\d+'})?\\s*([\\s\\S]*)\$") #:nodoc: all
242
-
243
- @@implemented_rr_map = nil
244
-
245
- #The Resource's domain name
246
- attr_reader :name
247
- #The Resource type
248
- attr_reader :type
249
- #The Resource class
250
- attr_reader :klass
251
- #The Resource Time-To-Live
252
- attr_accessor :ttl
253
- #The Resource data section
254
- attr_accessor :rdata
255
-
256
- def rdlength
257
- return rdata.length
258
- end
259
-
260
- def name=(newname)
261
- if (!(newname.kind_of?Name))
262
- @name=Name.create(newname)
263
- else
264
- @name = newname
265
- end
266
- end
267
-
268
- def type=(type)
269
- @type = Types.new(type)
270
- end
271
- alias :rr_type :type
272
-
273
- def klass=(klass)
274
- if (@type != Types::OPT)
275
- @klass= Classes.new(klass)
276
- else
277
- if (klass.class == Classes)
278
- @klass = klass
279
- else
280
- @klass = Classes.new("CLASS#{klass}")
281
- end
282
- end
283
- end
284
-
285
- def clone
286
- MessageDecoder.new(MessageEncoder.new {|msg|
287
- msg.put_rr(self, true)}.to_s) {|msg|
288
- r = msg.get_rr
289
- return r
290
- }
291
-
292
- end
293
-
294
- # Determines if two Records could be part of the same RRset.
295
- # This compares the name, type, and class of the Records; the ttl and
296
- # rdata are not compared.
297
- def sameRRset(rec)
298
- if (@klass != rec.klass || @name.downcase != rec.name.downcase)
299
- return false
300
- end
301
- if (rec.type == Types.RRSIG) && (@type == Types.RRSIG)
302
- return rec.type_covered == self.type_covered
303
- end
304
- [rec, self].each { |rr|
305
- if (rr.type == Types::RRSIG)
306
- return ((@type == rr.type_covered) || (rec.type == rr.type_covered))
307
- end
308
- }
309
- return (@type == rec.type)
310
- end
311
-
312
- def init_defaults
313
- # Default to do nothing
314
- end
315
-
316
- private
317
- def initialize(*args) #:nodoc: all
318
- init_defaults
319
- if (args.length > 0)
320
- if (args[0].class == Hash)
321
- from_hash(args[0])
322
- return
323
- else
324
- @rdata = args[0]
325
- # print "Loading RR from #{args[0]}, class : #{args[0].class}\n"
326
- if (args[0].class == String)
327
- from_string(args[0])
328
- return
329
- else
330
- from_data(args[0])
331
- return
332
- end
333
- end
334
- end
335
- # raise ArgumentError.new("Don't call new! Use Dnsruby::RR::create() instead")
336
- end
337
- public
338
-
339
- def from_hash(hash) #:nodoc: all
340
- hash.keys.each do |param|
341
- send(param.to_s+"=", hash[param])
342
- end
343
- end
344
-
345
- #Create a new RR from the hash. The name is required; all other fields are optional.
346
- #Type defaults to ANY and the Class defaults to IN. The TTL defaults to 0.
347
- #
348
- #If the type is specified, then it is necessary to provide ALL of the resource record fields which
349
- #are specific to that record; i.e. for
350
- #an MX record, you would need to specify the exchange and the preference
351
- #
352
- # require 'Dnsruby'
353
- # rr = Dnsruby::RR.new_from_hash({:name => "example.com"})
354
- # rr = Dnsruby::RR.new_from_hash({:name => "example.com", :type => Types.MX, :ttl => 10, :preference => 5, :exchange => "mx1.example.com"})
355
- def RR.new_from_hash(inhash)
356
- hash = inhash.clone
357
- type = hash[:type] || Types::ANY
358
- klass = hash[:klass] || Classes::IN
359
- ttl = hash[:ttl] || 0
360
- recordclass = get_class(type, klass)
361
- record = recordclass.new
362
- record.name=hash[:name]
363
- if !(record.name.kind_of?Name)
364
- record.name = Name.create(record.name)
365
- end
366
- record.ttl=ttl
367
- record.type = type
368
- record.klass = klass
369
- hash.delete(:name)
370
- hash.delete(:type)
371
- hash.delete(:ttl)
372
- hash.delete(:klass)
373
- record.from_hash(hash)
374
- return record
375
- end
376
-
377
- #Returns a Dnsruby::RR object of the appropriate type and
378
- #initialized from the string passed by the user. The format of the
379
- #string is that used in zone files, and is compatible with the string
380
- #returned by Net::DNS::RR.inspect
381
- #
382
- #The name and RR type are required; all other information is optional.
383
- #If omitted, the TTL defaults to 0 and the RR class defaults to IN.
384
- #
385
- #All names must be fully qualified. The trailing dot (.) is optional.
386
- #
387
- #
388
- # a = Dnsruby::RR.new_from_string("foo.example.com. 86400 A 10.1.2.3")
389
- # mx = Dnsruby::RR.new_from_string("example.com. 7200 MX 10 mailhost.example.com.")
390
- # cname = Dnsruby::RR.new_from_string("www.example.com 300 IN CNAME www1.example.com")
391
- # txt = Dnsruby::RR.new_from_string('baz.example.com 3600 HS TXT "text record"')
392
- #
393
- #
394
- def RR.new_from_string(rrstring)
395
- # strip out comments
396
- # Test for non escaped ";" by means of the look-behind assertion
397
- # (the backslash is escaped)
398
- rrstring = rrstring.gsub(/(\?<!\\);.*/o, "");
399
-
400
- if ((rrstring =~/#{@@RR_REGEX}/xo) == nil)
401
- raise Exception, "#{rrstring} did not match RR pat.\nPlease report this to the author!\n"
402
- end
403
-
404
- name = $1;
405
- ttl = $2.to_i || 0;
406
- rrclass = $3 || '';
407
-
408
-
409
- rrtype = $4 || '';
410
- rdata = $5 || '';
411
-
412
- if rdata
413
- rdata.gsub!(/\s+$/o, "")
414
- end
415
-
416
- # RFC3597 tweaks
417
- # This converts to known class and type if specified as TYPE###
418
- if rrtype =~/^TYPE\d+/o
419
- rrtype = Dnsruby::Types.typesbyval(Dnsruby::Types::typesbyname(rrtype))
420
- end
421
- if rrclass =~/^CLASS\d+/o
422
- rrclass = Dnsruby::Classes.classesbyval(Dnsruby::Classes::classesbyname(rrclass))
423
- end
424
-
425
-
426
- if (rrtype=='' && rrclass && rrclass == 'ANY')
427
- rrtype = 'ANY';
428
- rrclass = 'IN';
429
- elsif (rrclass=='')
430
- rrclass = 'IN';
431
- end
432
-
433
- if (rrtype == '')
434
- rrtype = 'ANY';
435
- end
436
-
437
- if ((rrtype == "NAPTR") || (rrtype == "TXT"))
438
- else
439
- if (rdata)
440
- rdata.gsub!("(", "")
441
- rdata.gsub!(")", "")
442
- end
443
- end
444
-
445
- if (implemented_rrs.include?(rrtype) && rdata !~/^\s*\\#/o )
446
- subclass = _get_subclass(name, rrtype, rrclass, ttl, rdata)
447
- return subclass
448
- elsif (implemented_rrs.include?(rrtype)) # A known RR type starting with \#
449
- rdata =~ /\\\#\s+(\d+)\s+(.*)$/o;
450
-
451
- rdlength = $1.to_i;
452
- hexdump = $2;
453
- hexdump.gsub!(/\s*/, "");
454
-
455
- if hexdump.length() != rdlength*2
456
- raise Exception, "#{rdata} is inconsistent; length does not match content"
457
- end
458
-
459
- rdata = [hexdump].pack('H*');
460
-
461
- return new_from_data(name, rrtype, rrclass, ttl, rdlength, rdata, 0) # rdata.length() - rdlength);
462
- elsif (rdata=~/\s*\\\#\s+\d+\s+/o)
463
- #We are now dealing with the truly unknown.
464
- raise Exception, 'Expected RFC3597 representation of RDATA' unless rdata =~/\\\#\s+(\d+)\s+(.*)$/o;
465
-
466
- rdlength = $1.to_i;
467
- hexdump = $2;
468
- hexdump.gsub!(/\s*/o, "");
469
-
470
- if hexdump.length() != rdlength*2
471
- raise Exception, "#{rdata} is inconsistent; length does not match content" ;
472
- end
473
-
474
- rdata = [hexdump].pack('H*');
475
-
476
- return new_from_data(name,rrtype,rrclass,ttl,rdlength,rdata,0) # rdata.length() - rdlength);
477
- else
478
- #God knows how to handle these...
479
- subclass = _get_subclass(name, rrtype, rrclass, ttl, "")
480
- return subclass
481
- end
482
- end
483
-
484
- def RR.new_from_data(*args) #:nodoc: all
485
- name = args[0]
486
- rrtype = args[1]
487
- rrclass = args[2]
488
- ttl = args[3]
489
- rdlength = args[4]
490
- data = args[5]
491
- offset = args[6]
492
- rdata = []
493
- if (data != nil)
494
- rdata = data[offset, rdlength]
495
- end
496
-
497
- record = nil
498
- MessageDecoder.new(rdata) {|msg|
499
- record = get_class(rrtype, rrclass).decode_rdata(msg)
500
- }
501
- record.name = Name.create(name)
502
- record.ttl = ttl
503
- record.type = rrtype
504
- record.klass = rrclass
505
-
506
- return record
507
- end
508
-
509
- #Return an array of all the currently implemented RR types
510
- def RR.implemented_rrs
511
- if (!@@implemented_rr_map)
512
- @@implemented_rr_map = ClassHash.keys.map {|k| Dnsruby::Types.to_string(k[0])}
513
- end
514
- return @@implemented_rr_map
515
- end
516
-
517
- private
518
- def RR._get_subclass(name, rrtype, rrclass, ttl, rdata) #:nodoc: all
519
- return unless (rrtype!=nil)
520
- record = get_class(rrtype, rrclass).new(rdata)
521
- record.name = Name.create(name)
522
- record.ttl = ttl
523
- record.type = rrtype
524
- record.klass = rrclass
525
- return record
526
- end
527
- public
528
-
529
- #Returns a string representation of the RR in zone file format
530
- def to_s
531
- 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
532
- end
533
-
534
- #Get a string representation of the data section of the RR (in zone file format)
535
- def rdata_to_string
536
- if (@rdata && @rdata.length > 0)
537
- return @rdata
538
- else
539
- return "no rdata"
540
- end
541
- end
542
-
543
- def from_data(data) #:nodoc: all
544
- # to be implemented by subclasses
545
- raise NotImplementedError.new
546
- end
547
-
548
- def from_string(input) #:nodoc: all
549
- # to be implemented by subclasses
550
- # raise NotImplementedError.new
551
- end
552
-
553
- def encode_rdata(msg, canonical=false) #:nodoc: all
554
- # to be implemented by subclasses
555
- raise EncodeError.new("#{self.class} is RR.")
556
- end
557
-
558
- def self.decode_rdata(msg) #:nodoc: all
559
- # to be implemented by subclasses
560
- raise DecodeError.new("#{self.class} is RR.")
561
- end
562
-
563
- def ==(other)
564
- return false unless self.class == other.class
565
- ivars = self.instance_variables
566
- s_ivars = []
567
- ivars.each {|i| s_ivars << i.to_s} # Ruby 1.9
568
- s_ivars.delete "@ttl" # RFC 2136 section 1.1
569
- s_ivars.delete "@rdata"
570
- if (self.type == Types.DS)
571
- s_ivars.delete "@digest"
572
- end
573
- s_ivars.sort!
574
-
575
- ivars = other.instance_variables
576
- o_ivars = []
577
- ivars.each {|i| o_ivars << i.to_s} # Ruby 1.9
578
- o_ivars.delete "@ttl" # RFC 2136 section 1.1
579
- o_ivars.delete "@rdata"
580
- if (other.type == Types.DS)
581
- o_ivars.delete "@digest"
582
- end
583
- o_ivars.sort!
584
-
585
- return s_ivars == o_ivars &&
586
- s_ivars.collect {|name| self.instance_variable_get name} ==
587
- o_ivars.collect {|name| other.instance_variable_get name}
588
- end
589
-
590
- def eql?(other) #:nodoc:
591
- return self == other
592
- end
593
-
594
- def hash # :nodoc:
595
- h = 0
596
- vars = self.instance_variables
597
- vars.delete "@ttl"
598
- vars.each {|name|
599
- h ^= self.instance_variable_get(name).hash
600
- }
601
- return h
602
- end
603
-
604
- def self.find_class(type_value, class_value) # :nodoc: all
605
- klass = nil
606
- if (ret = ClassHash[[type_value, class_value]])
607
- return ret
608
- elsif (val = ClassInsensitiveTypes[type_value])
609
- klass = Class.new(val)
610
- klass.const_set(:TypeValue, type_value)
611
- klass.const_set(:ClassValue, class_value)
612
- return klass
613
- else
614
- return Generic.create(type_value, class_value)
615
- end
616
- end
617
-
618
- #Get an RR of the specified type and class
619
- def self.get_class(type_value, class_value) #:nodoc: all
620
- if (type_value == Types::OPT)
621
- return Class.new(OPT)
622
- end
623
- if (type_value.class == Class)
624
- type_value = type_value.const_get(:TypeValue)
625
- return find_class(type_value, Classes.to_code(class_value))
626
- else
627
- if (type_value.class == Types)
628
- type_value = type_value.code
629
- else
630
- type_value = Types.new(type_value).code
631
- end
632
- if (class_value.class == Classes)
633
- class_value = class_value.code
634
- else
635
- class_value = Classes.new(class_value).code
636
- end
637
- return find_class(type_value, class_value)
638
- end
639
- return ret
640
- end
641
-
642
-
643
- #Create a new RR from the arguments, which can be either a String or a Hash.
644
- #See new_from_string and new_from_hash for details
645
- #
646
- # a = Dnsruby::RR.create("foo.example.com. 86400 A 10.1.2.3")
647
- # mx = Dnsruby::RR.create("example.com. 7200 MX 10 mailhost.example.com.")
648
- # cname = Dnsruby::RR.create("www.example.com 300 IN CNAME www1.example.com")
649
- # txt = Dnsruby::RR.create('baz.example.com 3600 HS TXT "text record"')
650
- #
651
- # rr = Dnsruby::RR.create({:name => "example.com"})
652
- # rr = Dnsruby::RR.create({:name => "example.com", :type => "MX", :ttl => 10,
653
- # :preference => 5, :exchange => "mx1.example.com"})
654
- #
655
- def RR.create(*args)
656
- if (args.length == 1) && (args[0].class == String)
657
- return new_from_string(args[0])
658
- elsif (args.length == 1) && (args[0].class == Hash)
659
- return new_from_hash(args[0])
660
- else
661
- return new_from_data(args)
662
- end
663
- end
664
-
665
- def self.get_num(bytes)
666
- ret = 0
667
- shift = (bytes.length-1) * 8
668
- bytes.each_byte {|byte|
669
- ret += byte.to_i << shift
670
- shift -= 8
671
- }
672
- return ret
673
- end
674
- end
675
- end
676
- require 'Dnsruby/resource/domain_name'
677
- require 'Dnsruby/resource/generic'
678
- require 'Dnsruby/resource/IN'