dnsruby 1.55 → 1.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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'