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.
- checksums.yaml +4 -4
- data/README.md +96 -0
- data/Rakefile +30 -29
- data/demo/axfr.rb +93 -93
- data/demo/check_soa.rb +99 -99
- data/demo/check_zone.rb +59 -59
- data/demo/digdlv.rb +43 -43
- data/demo/digroot.rb +34 -34
- data/demo/example_recurse.rb +14 -14
- data/demo/mresolv.rb +30 -30
- data/demo/mx.rb +31 -31
- data/demo/rubydig.rb +37 -37
- data/demo/to_resolve.txt +3088 -3088
- data/demo/trace_dns.rb +46 -46
- data/lib/dnsruby.rb +161 -526
- data/lib/dnsruby/DNS.rb +305 -0
- data/lib/{Dnsruby/Cache.rb → dnsruby/cache.rb} +152 -152
- data/lib/{Dnsruby → dnsruby}/code_mapper.rb +48 -52
- data/lib/dnsruby/code_mappers.rb +295 -0
- data/lib/{Dnsruby/Config.rb → dnsruby/config.rb} +454 -454
- data/lib/{Dnsruby → dnsruby}/dnssec.rb +91 -91
- data/lib/{Dnsruby/Hosts.rb → dnsruby/hosts.rb} +125 -125
- data/lib/{Dnsruby → dnsruby}/ipv4.rb +26 -26
- data/lib/{Dnsruby → dnsruby}/ipv6.rb +42 -42
- data/lib/{Dnsruby → dnsruby}/key_cache.rb +29 -29
- data/lib/dnsruby/message/decoder.rb +164 -0
- data/lib/dnsruby/message/encoder.rb +75 -0
- data/lib/dnsruby/message/header.rb +249 -0
- data/lib/dnsruby/message/message.rb +629 -0
- data/lib/dnsruby/message/question.rb +86 -0
- data/lib/dnsruby/message/section.rb +96 -0
- data/lib/{Dnsruby → dnsruby}/name.rb +141 -141
- data/lib/dnsruby/packet_sender.rb +661 -0
- data/lib/{Dnsruby/Recursor.rb → dnsruby/recursor.rb} +235 -233
- data/lib/dnsruby/resolv.rb +113 -0
- data/lib/dnsruby/resolver.rb +1192 -0
- data/lib/dnsruby/resource/A.rb +56 -0
- data/lib/dnsruby/resource/AAAA.rb +54 -0
- data/lib/{Dnsruby → dnsruby}/resource/AFSDB.rb +68 -68
- data/lib/{Dnsruby → dnsruby}/resource/CERT.rb +105 -105
- data/lib/{Dnsruby → dnsruby}/resource/DHCID.rb +54 -54
- data/lib/dnsruby/resource/DLV.rb +27 -0
- data/lib/{Dnsruby → dnsruby}/resource/DNSKEY.rb +372 -372
- data/lib/{Dnsruby → dnsruby}/resource/DS.rb +255 -255
- data/lib/{Dnsruby → dnsruby}/resource/HINFO.rb +71 -71
- data/lib/{Dnsruby → dnsruby}/resource/HIP.rb +29 -29
- data/lib/{Dnsruby → dnsruby}/resource/IN.rb +30 -30
- data/lib/{Dnsruby → dnsruby}/resource/IPSECKEY.rb +31 -31
- data/lib/{Dnsruby → dnsruby}/resource/ISDN.rb +62 -62
- data/lib/{Dnsruby → dnsruby}/resource/KX.rb +65 -65
- data/lib/{Dnsruby → dnsruby}/resource/LOC.rb +263 -263
- data/lib/{Dnsruby → dnsruby}/resource/MINFO.rb +69 -69
- data/lib/{Dnsruby → dnsruby}/resource/MX.rb +65 -65
- data/lib/{Dnsruby → dnsruby}/resource/NAPTR.rb +98 -98
- data/lib/{Dnsruby → dnsruby}/resource/NSAP.rb +171 -171
- data/lib/dnsruby/resource/NSEC.rb +275 -0
- data/lib/dnsruby/resource/NSEC3.rb +332 -0
- data/lib/dnsruby/resource/NSEC3PARAM.rb +135 -0
- data/lib/dnsruby/resource/OPT.rb +272 -0
- data/lib/{Dnsruby → dnsruby}/resource/PX.rb +70 -70
- data/lib/{Dnsruby → dnsruby}/resource/RP.rb +75 -75
- data/lib/dnsruby/resource/RR.rb +421 -0
- data/lib/dnsruby/resource/RRSIG.rb +275 -0
- data/lib/dnsruby/resource/RRSet.rb +190 -0
- data/lib/{Dnsruby → dnsruby}/resource/RT.rb +67 -67
- data/lib/{Dnsruby → dnsruby}/resource/SOA.rb +94 -94
- data/lib/dnsruby/resource/SPF.rb +29 -0
- data/lib/dnsruby/resource/SRV.rb +112 -0
- data/lib/{Dnsruby → dnsruby}/resource/SSHFP.rb +14 -14
- data/lib/dnsruby/resource/TKEY.rb +163 -0
- data/lib/dnsruby/resource/TSIG.rb +593 -0
- data/lib/{Dnsruby → dnsruby}/resource/TXT.rb +191 -191
- data/lib/dnsruby/resource/X25.rb +55 -0
- data/lib/{Dnsruby → dnsruby}/resource/domain_name.rb +25 -25
- data/lib/{Dnsruby → dnsruby}/resource/generic.rb +80 -80
- data/lib/dnsruby/resource/resource.rb +25 -0
- data/lib/{Dnsruby → dnsruby}/select_thread.rb +148 -148
- data/lib/{Dnsruby/SingleResolver.rb → dnsruby/single_resolver.rb} +60 -60
- data/lib/{Dnsruby → dnsruby}/single_verifier.rb +344 -344
- data/lib/dnsruby/the_log.rb +44 -0
- data/lib/dnsruby/update.rb +278 -0
- data/lib/dnsruby/validator_thread.rb +124 -0
- data/lib/dnsruby/version.rb +3 -0
- data/lib/{Dnsruby → dnsruby}/zone_reader.rb +93 -93
- data/lib/{Dnsruby → dnsruby}/zone_transfer.rb +377 -377
- data/test/spec_helper.rb +16 -0
- data/test/tc_axfr.rb +31 -34
- data/test/tc_cache.rb +32 -32
- data/test/tc_dlv.rb +28 -28
- data/test/tc_dns.rb +73 -76
- data/test/tc_dnskey.rb +31 -32
- data/test/tc_dnsruby.rb +50 -44
- data/test/tc_ds.rb +36 -36
- data/test/tc_escapedchars.rb +252 -255
- data/test/tc_hash.rb +17 -21
- data/test/tc_header.rb +48 -57
- data/test/tc_hip.rb +19 -22
- data/test/tc_ipseckey.rb +18 -21
- data/test/tc_keith.rb +300 -0
- data/test/tc_message.rb +87 -0
- data/test/tc_misc.rb +83 -87
- data/test/tc_name.rb +81 -84
- data/test/tc_naptr.rb +18 -21
- data/test/tc_nsec.rb +55 -55
- data/test/tc_nsec3.rb +23 -24
- data/test/tc_nsec3param.rb +20 -21
- data/test/tc_packet.rb +90 -93
- data/test/tc_packet_unique_push.rb +48 -51
- data/test/tc_question.rb +30 -33
- data/test/tc_queue.rb +16 -17
- data/test/tc_recur.rb +16 -17
- data/test/tc_res_config.rb +38 -41
- data/test/tc_res_env.rb +29 -32
- data/test/tc_res_file.rb +26 -29
- data/test/tc_res_opt.rb +62 -65
- data/test/tc_resolver.rb +287 -242
- data/test/tc_rr-opt.rb +70 -63
- data/test/tc_rr-txt.rb +68 -71
- data/test/tc_rr-unknown.rb +45 -48
- data/test/tc_rr.rb +76 -70
- data/test/tc_rrset.rb +21 -22
- data/test/tc_rrsig.rb +19 -20
- data/test/tc_single_resolver.rb +294 -297
- data/test/tc_soak.rb +199 -202
- data/test/tc_soak_base.rb +29 -34
- data/test/tc_sshfp.rb +20 -23
- data/test/tc_tcp.rb +32 -35
- data/test/tc_tkey.rb +41 -44
- data/test/tc_tsig.rb +81 -84
- data/test/tc_update.rb +108 -111
- data/test/tc_validator.rb +29 -29
- data/test/tc_verifier.rb +81 -82
- data/test/ts_dnsruby.rb +16 -15
- data/test/ts_offline.rb +62 -63
- data/test/ts_online.rb +115 -115
- metadata +155 -90
- data/README +0 -59
- data/lib/Dnsruby/DNS.rb +0 -305
- data/lib/Dnsruby/PacketSender.rb +0 -656
- data/lib/Dnsruby/Resolver.rb +0 -1189
- data/lib/Dnsruby/TheLog.rb +0 -44
- data/lib/Dnsruby/message.rb +0 -1230
- data/lib/Dnsruby/resource/A.rb +0 -56
- data/lib/Dnsruby/resource/AAAA.rb +0 -54
- data/lib/Dnsruby/resource/DLV.rb +0 -27
- data/lib/Dnsruby/resource/NSEC.rb +0 -298
- data/lib/Dnsruby/resource/NSEC3.rb +0 -340
- data/lib/Dnsruby/resource/NSEC3PARAM.rb +0 -135
- data/lib/Dnsruby/resource/OPT.rb +0 -213
- data/lib/Dnsruby/resource/RRSIG.rb +0 -275
- data/lib/Dnsruby/resource/SPF.rb +0 -29
- data/lib/Dnsruby/resource/SRV.rb +0 -112
- data/lib/Dnsruby/resource/TKEY.rb +0 -163
- data/lib/Dnsruby/resource/TSIG.rb +0 -593
- data/lib/Dnsruby/resource/X25.rb +0 -55
- data/lib/Dnsruby/resource/resource.rb +0 -678
- data/lib/Dnsruby/update.rb +0 -278
- data/lib/Dnsruby/validator_thread.rb +0 -124
data/lib/Dnsruby/resource/X25.rb
DELETED
|
@@ -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'
|