dnsruby 1.39 → 1.40
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/Dnsruby/Recursor.rb +1 -1
- data/lib/Dnsruby/code_mapper.rb +5 -14
- data/lib/Dnsruby/name.rb +7 -5
- data/lib/Dnsruby/resource/AFSDB.rb +1 -1
- data/lib/Dnsruby/resource/CERT.rb +21 -8
- data/lib/Dnsruby/resource/DHCID.rb +55 -0
- data/lib/Dnsruby/resource/HINFO.rb +5 -1
- data/lib/Dnsruby/resource/HIP.rb +138 -0
- data/lib/Dnsruby/resource/IN.rb +2 -2
- data/lib/Dnsruby/resource/IPSECKEY.rb +143 -0
- data/lib/Dnsruby/resource/ISDN.rb +9 -1
- data/lib/Dnsruby/resource/KX.rb +66 -0
- data/lib/Dnsruby/resource/LOC.rb +10 -4
- data/lib/Dnsruby/resource/X25.rb +3 -1
- data/lib/Dnsruby/resource/generic.rb +5 -1
- data/lib/Dnsruby/resource/resource.rb +8 -2
- data/lib/Dnsruby/single_verifier.rb +3 -0
- data/lib/Dnsruby/zone_reader.rb +381 -0
- data/lib/dnsruby.rb +3 -0
- data/test/tc_hip.rb +70 -0
- data/test/tc_ipseckey.rb +70 -0
- data/test/tc_rr.rb +37 -1
- data/test/tc_verifier.rb +0 -46
- data/test/ts_offline.rb +2 -1
- metadata +10 -3
@@ -32,7 +32,15 @@ module Dnsruby
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def from_string(input) #:nodoc: all
|
35
|
-
|
35
|
+
address, subaddress = input.split(" ")
|
36
|
+
address.sub!(/^\"/, "")
|
37
|
+
@address = address.sub(/\"$/, "")
|
38
|
+
if (subaddress)
|
39
|
+
subaddress.sub!(/^\"/, "")
|
40
|
+
@subaddress = subaddress.sub(/\"$/, "")
|
41
|
+
else
|
42
|
+
@subaddress = nil
|
43
|
+
end
|
36
44
|
end
|
37
45
|
|
38
46
|
def rdata_to_string #:nodoc: all
|
@@ -0,0 +1,66 @@
|
|
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 Key Exchange (KX) resource records.
|
19
|
+
#RFC 2230
|
20
|
+
class KX < RR
|
21
|
+
ClassValue = nil #:nodoc: all
|
22
|
+
TypeValue= Types::KX #:nodoc: all
|
23
|
+
|
24
|
+
#The preference for this mail exchange.
|
25
|
+
attr_accessor :preference
|
26
|
+
#The name of this mail exchange.
|
27
|
+
attr_accessor :exchange
|
28
|
+
|
29
|
+
def from_hash(hash) #:nodoc: all
|
30
|
+
@preference = hash[:preference]
|
31
|
+
@exchange = Name.create(hash[:exchange])
|
32
|
+
end
|
33
|
+
|
34
|
+
def from_data(data) #:nodoc: all
|
35
|
+
@preference, @exchange = data
|
36
|
+
end
|
37
|
+
|
38
|
+
def from_string(input) #:nodoc: all
|
39
|
+
if (input.length > 0)
|
40
|
+
names = input.split(" ")
|
41
|
+
@preference = names[0].to_i
|
42
|
+
@exchange = Name.create(names[1])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def rdata_to_string #:nodoc: all
|
47
|
+
if (@preference!=nil)
|
48
|
+
return "#{@preference} #{@exchange}"
|
49
|
+
else
|
50
|
+
return ""
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def encode_rdata(msg, canonical=false) #:nodoc: all
|
55
|
+
msg.put_pack('n', @preference)
|
56
|
+
msg.put_name(@exchange, true)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.decode_rdata(msg) #:nodoc: all
|
60
|
+
preference, = msg.get_unpack('n')
|
61
|
+
exchange = msg.get_name
|
62
|
+
return self.new([preference, exchange])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/Dnsruby/resource/LOC.rb
CHANGED
@@ -143,9 +143,17 @@ module Dnsruby
|
|
143
143
|
# What to do for other versions?
|
144
144
|
version = 0;
|
145
145
|
|
146
|
+
horiz_pre = DEFAULT_HORIZ_PRE
|
147
|
+
vert_pre = DEFAULT_VERT_PRE
|
146
148
|
latdeg, latmin, latsec, lathem = $1.to_i, $3.to_i, $5.to_i, $6;
|
147
149
|
londeg, lonmin, lonsec, lonhem = $7.to_i, $9.to_i, $11.to_i, $12
|
148
|
-
alt, size
|
150
|
+
alt, size = $13.to_i, $15.to_i
|
151
|
+
if ($17)
|
152
|
+
horiz_pre = $17.to_i
|
153
|
+
end
|
154
|
+
if ($19)
|
155
|
+
vert_pre = $19.to_i
|
156
|
+
end
|
149
157
|
|
150
158
|
latmin = DEFAULT_MIN unless latmin;
|
151
159
|
latsec = DEFAULT_SEC unless latsec;
|
@@ -156,9 +164,7 @@ module Dnsruby
|
|
156
164
|
lonhem = lonhem.upcase
|
157
165
|
|
158
166
|
size = DEFAULT_SIZE unless size;
|
159
|
-
|
160
|
-
vert_pre = DEFAULT_VERT_PRE unless vert_pre;
|
161
|
-
|
167
|
+
|
162
168
|
@version = version;
|
163
169
|
@size = size * 100;
|
164
170
|
@horiz_pre = horiz_pre * 100;
|
data/lib/Dnsruby/resource/X25.rb
CHANGED
@@ -150,4 +150,8 @@ require 'Dnsruby/resource/DS'
|
|
150
150
|
require 'Dnsruby/resource/NSEC3'
|
151
151
|
require 'Dnsruby/resource/NSEC3PARAM'
|
152
152
|
require 'Dnsruby/resource/DLV'
|
153
|
-
require 'Dnsruby/resource/SSHFP'
|
153
|
+
require 'Dnsruby/resource/SSHFP'
|
154
|
+
require 'Dnsruby/resource/IPSECKEY'
|
155
|
+
require 'Dnsruby/resource/HIP'
|
156
|
+
require 'Dnsruby/resource/KX'
|
157
|
+
require 'Dnsruby/resource/DHCID'
|
@@ -534,16 +534,22 @@ module Dnsruby
|
|
534
534
|
ivars = self.instance_variables
|
535
535
|
s_ivars = []
|
536
536
|
ivars.each {|i| s_ivars << i.to_s} # Ruby 1.9
|
537
|
-
s_ivars.sort!
|
538
537
|
s_ivars.delete "@ttl" # RFC 2136 section 1.1
|
539
538
|
s_ivars.delete "@rdata"
|
539
|
+
if (self.type == Types.DS)
|
540
|
+
s_ivars.delete "@digest"
|
541
|
+
end
|
542
|
+
s_ivars.sort!
|
540
543
|
|
541
544
|
ivars = other.instance_variables
|
542
545
|
o_ivars = []
|
543
546
|
ivars.each {|i| o_ivars << i.to_s} # Ruby 1.9
|
544
|
-
o_ivars.sort!
|
545
547
|
o_ivars.delete "@ttl" # RFC 2136 section 1.1
|
546
548
|
o_ivars.delete "@rdata"
|
549
|
+
if (other.type == Types.DS)
|
550
|
+
o_ivars.delete "@digest"
|
551
|
+
end
|
552
|
+
o_ivars.sort!
|
547
553
|
|
548
554
|
return s_ivars == o_ivars &&
|
549
555
|
s_ivars.collect {|name| self.instance_variable_get name} ==
|
@@ -437,6 +437,7 @@ module Dnsruby
|
|
437
437
|
end
|
438
438
|
|
439
439
|
def check_no_wildcard_expansion(msg) # :nodoc:
|
440
|
+
# @TODO@ Do this for NSEC3 records!!!
|
440
441
|
proven_no_wildcards = false
|
441
442
|
name = msg.question()[0].qname
|
442
443
|
[msg.authority.rrsets('NSEC'), msg.authority.rrsets('NSEC3')].each {|nsec_rrsets|
|
@@ -475,6 +476,7 @@ module Dnsruby
|
|
475
476
|
def check_name_in_nsecs(msg, qtype=nil, expected_qtype = false) # :nodoc:
|
476
477
|
# Check these NSECs to make sure that this name cannot be in the zone
|
477
478
|
# and that no RRSets could match through wildcard expansion
|
479
|
+
# @TODO@ Get this right for NSEC3 too!
|
478
480
|
name = msg.question()[0].qname
|
479
481
|
proven_name_in_nsecs = false
|
480
482
|
type_covered_checked = false
|
@@ -516,6 +518,7 @@ module Dnsruby
|
|
516
518
|
end
|
517
519
|
|
518
520
|
def check_name_not_in_wildcard_nsecs(msg) # :nodoc:
|
521
|
+
# @TODO@ Do this for NSEC3 records too!
|
519
522
|
name = msg.question()[0].qname
|
520
523
|
qtype = msg.question()[0].qtype
|
521
524
|
done= false
|
@@ -0,0 +1,381 @@
|
|
1
|
+
#--
|
2
|
+
#Copyright 2009 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
|
+
|
17
|
+
# This class provides the facility to load a zone file.
|
18
|
+
# It can either process one line at a time, or return an entire zone as a list of
|
19
|
+
# records.
|
20
|
+
module Dnsruby
|
21
|
+
class ZoneReader
|
22
|
+
class ParseException < Exception
|
23
|
+
|
24
|
+
end
|
25
|
+
# Create a new ZoneReader. The zone origin is required. If the desired SOA minimum
|
26
|
+
# and TTL are passed in, then they are used as default values.
|
27
|
+
def initialize(origin, soa_minimum = nil, soa_ttl = nil)
|
28
|
+
@origin = origin
|
29
|
+
|
30
|
+
if (!Name.create(@origin).absolute?)
|
31
|
+
@origin = @origin + "."
|
32
|
+
end
|
33
|
+
@soa_ttl = soa_ttl
|
34
|
+
if (soa_minimum && !@last_explicit_ttl)
|
35
|
+
@last_explicit_ttl = soa_minimum
|
36
|
+
else
|
37
|
+
@last_explicit_ttl = 0
|
38
|
+
end
|
39
|
+
@last_explicit_class = Classes.new("IN")
|
40
|
+
@last_name = nil
|
41
|
+
@continued_line = nil
|
42
|
+
@in_quoted_section = false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Takes a filename string and attempts to load a zone. Returns a list
|
46
|
+
# of RRs if successful, nil otherwise.
|
47
|
+
def process_file(file)
|
48
|
+
line_num = 0
|
49
|
+
zone = nil
|
50
|
+
IO.foreach(file) { |line|
|
51
|
+
begin
|
52
|
+
ret = process_line(line)
|
53
|
+
if (ret)
|
54
|
+
rr = RR.create(ret)
|
55
|
+
if (!zone)
|
56
|
+
zone = []
|
57
|
+
end
|
58
|
+
zone.push(rr)
|
59
|
+
end
|
60
|
+
rescue Exception => e
|
61
|
+
raise ParseException.new("Error reading line #{line_num} of #{file} : [#{line}]")
|
62
|
+
end
|
63
|
+
}
|
64
|
+
return zone
|
65
|
+
end
|
66
|
+
|
67
|
+
# Process the next line of the file
|
68
|
+
# Returns a string representing the normalised line.
|
69
|
+
def process_line(line, do_prefix_hack = false)
|
70
|
+
return nil if (line.index(';') == 0)
|
71
|
+
return nil if (line.strip.length == 0)
|
72
|
+
return nil if (!line || (line.length == 0))
|
73
|
+
@in_quoted_section = false if !@continued_line
|
74
|
+
|
75
|
+
line = strip_comments(line)
|
76
|
+
|
77
|
+
if (line.index("$ORIGIN") == 0)
|
78
|
+
@origin = line.split()[1].strip # $ORIGIN <domain-name> [<comment>]
|
79
|
+
# print "Setting $ORIGIN to #{@origin}\n"
|
80
|
+
return nil
|
81
|
+
end
|
82
|
+
if (line.index("$TTL") == 0)
|
83
|
+
@last_explicit_ttl = get_ttl(line.split()[1].strip) # $TTL <ttl>
|
84
|
+
# print "Setting $TTL to #{ttl}\n"
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
if (@continued_line)
|
88
|
+
# Add the next line until we see a ")"
|
89
|
+
# REMEMBER TO STRIP OFF COMMENTS!!!
|
90
|
+
@continued_line = strip_comments(@continued_line)
|
91
|
+
line = @continued_line.strip.chomp + " " + line
|
92
|
+
if (line.index(")"))
|
93
|
+
# OK
|
94
|
+
@continued_line = false
|
95
|
+
end
|
96
|
+
end
|
97
|
+
open_bracket = line.index("(")
|
98
|
+
if (open_bracket)
|
99
|
+
# Keep going until we see ")"
|
100
|
+
index = line.index(")")
|
101
|
+
if (index && (index > open_bracket))
|
102
|
+
# OK
|
103
|
+
@continued_line = false
|
104
|
+
else
|
105
|
+
@continued_line = line
|
106
|
+
end
|
107
|
+
end
|
108
|
+
return nil if @continued_line
|
109
|
+
|
110
|
+
line = strip_comments(line) + "\n"
|
111
|
+
|
112
|
+
# If SOA, then replace "3h" etc. with expanded seconds
|
113
|
+
# begin
|
114
|
+
return normalise_line(line, do_prefix_hack)
|
115
|
+
# rescue Exception => e
|
116
|
+
# print "ERROR parsing line #{@line_num} : #{line}\n"
|
117
|
+
# return "\n", Types::ANY
|
118
|
+
# end
|
119
|
+
end
|
120
|
+
|
121
|
+
def strip_comments(line)
|
122
|
+
last_index = 0
|
123
|
+
# Are we currently in a quoted section?
|
124
|
+
# Does a quoted section begin or end in this line?
|
125
|
+
# Are there any semi-colons?
|
126
|
+
# Ary any of the semi-colons inside a quoted section?
|
127
|
+
while (next_index = line.index(";", last_index + 1))
|
128
|
+
# Have there been any quotes since we last looked?
|
129
|
+
process_quotes(line[last_index, next_index - last_index])
|
130
|
+
|
131
|
+
# Now use @in_quoted_section to work out if the ';' terminates the line
|
132
|
+
if (!@in_quoted_section)
|
133
|
+
return line[0,next_index]
|
134
|
+
end
|
135
|
+
|
136
|
+
last_index = next_index
|
137
|
+
end
|
138
|
+
# Check out the quote situation to the end of the line
|
139
|
+
process_quotes(line[last_index, line.length-1])
|
140
|
+
|
141
|
+
return line
|
142
|
+
end
|
143
|
+
|
144
|
+
def process_quotes(section)
|
145
|
+
# Look through the section of text and set the @in_quoted_section
|
146
|
+
# as it should be at the end of the given section
|
147
|
+
last_index = 0
|
148
|
+
while (next_index = section.index("\"", last_index + 1))
|
149
|
+
@in_quoted_section = !@in_quoted_section
|
150
|
+
last_index = next_index
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Take a line from the input zone file, and return the normalised form
|
155
|
+
# do_prefix_hack should always be false
|
156
|
+
def normalise_line(line, do_prefix_hack = false)
|
157
|
+
# Note that a freestanding "@" is used to denote the current origin - we can simply replace that straight away
|
158
|
+
# Remove the ( and )
|
159
|
+
# Note that no domain name may be specified in the RR - in that case, last_name should be used. How do we tell? Tab or space at start of line.
|
160
|
+
if ((line[0,1] == " ") || (line[0,1] == "\t"))
|
161
|
+
line = @last_name + " " + line
|
162
|
+
end
|
163
|
+
line.chomp!
|
164
|
+
line.sub!("(", "")
|
165
|
+
line.sub!(")", "")
|
166
|
+
line.sub!("@ ", "#{@origin} ")
|
167
|
+
line.sub!("@\t", "#{@origin} ")
|
168
|
+
line.strip!
|
169
|
+
|
170
|
+
|
171
|
+
# o We need to identify the domain name in the record, and then
|
172
|
+
split = line.split(' ') # split on whitespace
|
173
|
+
name = split[0].strip
|
174
|
+
# o add $ORIGIN to it if it is not absolute
|
175
|
+
if !(/\.\z/ =~ name)
|
176
|
+
new_name = name + "." + @origin
|
177
|
+
line.sub!(name, new_name)
|
178
|
+
name = new_name
|
179
|
+
split = line.split
|
180
|
+
end
|
181
|
+
|
182
|
+
# If the second field is not a number, then we should add the TTL to the line
|
183
|
+
# Remember we can get "m" "w" "y" here! So need to check for appropriate regexp...
|
184
|
+
found_ttl_regexp = (split[1]=~/^[0-9]+[smhdwSMHDW]/)
|
185
|
+
if (found_ttl_regexp == 0)
|
186
|
+
# Replace the formatted ttl with an actual number
|
187
|
+
ttl = get_ttl(split[1])
|
188
|
+
line = name + " #{ttl} "
|
189
|
+
@last_explicit_ttl = ttl
|
190
|
+
(split.length - 2).times {|i| line += "#{split[i+2]} "}
|
191
|
+
line += "\n"
|
192
|
+
split = line.split
|
193
|
+
elsif (((split[1]).to_i == 0) && (split[1] != "0"))
|
194
|
+
# Add the TTL
|
195
|
+
if (!@last_explicit_ttl)
|
196
|
+
# If this is the SOA record, and no @last_explicit_ttl is defined,
|
197
|
+
# then we need to try the SOA TTL element from the config. Otherwise,
|
198
|
+
# find the SOA Minimum field, and use that.
|
199
|
+
# We should also generate a warning to that effect
|
200
|
+
# How do we know if it is an SOA record at this stage? It must be, or
|
201
|
+
# else @last_explicit_ttl should be defined
|
202
|
+
# We could put a marker in the RR for now - and replace it once we know
|
203
|
+
# the actual type. If the type is not SOA then, then we can raise an error
|
204
|
+
line = name + " %MISSING_TTL% "
|
205
|
+
else
|
206
|
+
line = name + " #{@last_explicit_ttl} "
|
207
|
+
end
|
208
|
+
(split.length - 1).times {|i| line += "#{split[i+1]} "}
|
209
|
+
line += "\n"
|
210
|
+
split = line.split
|
211
|
+
else
|
212
|
+
@last_explicit_ttl = split[1].to_i
|
213
|
+
end
|
214
|
+
|
215
|
+
# Now see if the clas is included. If not, then we should default to the last class used.
|
216
|
+
begin
|
217
|
+
klass = Classes.new(split[2])
|
218
|
+
@last_explicit_class = klass
|
219
|
+
rescue ArgumentError
|
220
|
+
# Wasn't a CLASS
|
221
|
+
# So add the last explicit class in
|
222
|
+
line = ""
|
223
|
+
(2).times {|i| line += "#{split[i]} "}
|
224
|
+
line += " #{@last_explicit_class} "
|
225
|
+
(split.length - 2).times {|i| line += "#{split[i+2]} "}
|
226
|
+
line += "\n"
|
227
|
+
split = line.split
|
228
|
+
rescue Error => e
|
229
|
+
end
|
230
|
+
|
231
|
+
# Add the type so we can load the zone one RRSet at a time.
|
232
|
+
type = Types.new(split[3].strip)
|
233
|
+
is_soa = (type == Types::SOA)
|
234
|
+
type_was = type
|
235
|
+
if (type == Types.RRSIG)
|
236
|
+
# If this is an RRSIG record, then add the TYPE COVERED rather than the type - this allows us to load a complete RRSet at a time
|
237
|
+
type = Types.new(split[4].strip)
|
238
|
+
end
|
239
|
+
|
240
|
+
type_string=prefix_for_rrset_order(type, type_was)
|
241
|
+
@last_name = name
|
242
|
+
|
243
|
+
if (is_soa)
|
244
|
+
if (@soa_ttl)
|
245
|
+
# Replace the %MISSING_TTL% text with the SOA TTL from the config
|
246
|
+
line.sub!(" %MISSING_TTL% ", " #{@soa_ttl} ")
|
247
|
+
else
|
248
|
+
# Can we try the @last_explicit_ttl?
|
249
|
+
if (@last_explicit_ttl)
|
250
|
+
line.sub!(" %MISSING_TTL% ", " #{@last_explicit_ttl} ")
|
251
|
+
end
|
252
|
+
end
|
253
|
+
line = replace_soa_ttl_fields(line)
|
254
|
+
if (!@last_explicit_ttl)
|
255
|
+
soa_rr = Dnsruby::RR.create(line)
|
256
|
+
@last_explicit_ttl = soa_rr.minimum
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
line = line.split.join(' ').strip
|
261
|
+
# We need to fix up any non-absolute names in the RR
|
262
|
+
# Some RRs have a single name, at the end of the string -
|
263
|
+
# to do these, we can just check the last character for "." and add the
|
264
|
+
# "." + origin string if necessary
|
265
|
+
if ([Types::MX, Types::NS, Types::AFSDB, Types::NAPTR, Types::RT,
|
266
|
+
Types::SRV, Types::CNAME, Types::MB, Types::MG, Types::MR,
|
267
|
+
Types::PTR].include?type_was)
|
268
|
+
if (line[line.length-1, 1] != ".")
|
269
|
+
line = line + "." + @origin.to_s
|
270
|
+
end
|
271
|
+
end
|
272
|
+
# Other RRs have several names. These should be parsed by Dnsruby,
|
273
|
+
# and the names adjusted there.
|
274
|
+
if ([Types::MINFO, Types::PX, Types::RP].include?type_was)
|
275
|
+
parsed_rr = Dnsruby::RR.create(line)
|
276
|
+
case parsed_rr.type
|
277
|
+
when Types::MINFO
|
278
|
+
if (!parsed_rr.rmailbx.absolute?)
|
279
|
+
parsed_rr.rmailbx = parsed_rr.rmailbx.to_s + "." + @origin.to_s
|
280
|
+
end
|
281
|
+
if (!parsed_rr.emailbx.absolute?)
|
282
|
+
parsed_rr.emailbx = parsed_rr.emailbx.to_s + "." + @origin.to_s
|
283
|
+
end
|
284
|
+
when Types::PX
|
285
|
+
if (!parsed_rr.map822.absolute?)
|
286
|
+
parsed_rr.map822 = parsed_rr.map822.to_s + "." + @origin.to_s
|
287
|
+
end
|
288
|
+
if (!parsed_rr.mapx400.absolute?)
|
289
|
+
parsed_rr.mapx400 = parsed_rr.mapx400.to_s + "." + @origin.to_s
|
290
|
+
end
|
291
|
+
when Types::RP
|
292
|
+
if (!parsed_rr.mailbox.absolute?)
|
293
|
+
parsed_rr.mailbox = parsed_rr.mailbox.to_s + "." + @origin.to_s
|
294
|
+
if (!parsed_rr.txtdomain.absolute?)
|
295
|
+
parsed_rr.txtdomain = parsed_rr.txtdomain.to_s + "." + @origin.to_s
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
line = parsed_rr.to_s
|
300
|
+
end
|
301
|
+
|
302
|
+
if (do_prefix_hack)
|
303
|
+
return line + "\n", type_string, @last_name
|
304
|
+
end
|
305
|
+
return line+"\n"
|
306
|
+
end
|
307
|
+
|
308
|
+
# Get the TTL in seconds from the m, h, d, w format
|
309
|
+
def get_ttl(ttl_text_in)
|
310
|
+
# If no letter afterwards, then in seconds already
|
311
|
+
# Could be e.g. "3d4h12m" - unclear if "4h5w" is legal - best assume it is
|
312
|
+
# So, search out each letter in the string, and get the number before it.
|
313
|
+
ttl_text = ttl_text_in.downcase
|
314
|
+
index = ttl_text.index(/[whdms]/)
|
315
|
+
if (!index)
|
316
|
+
return ttl_text.to_i
|
317
|
+
end
|
318
|
+
last_index = -1
|
319
|
+
total = 0
|
320
|
+
while (index)
|
321
|
+
letter = ttl_text[index]
|
322
|
+
number = ttl_text[last_index + 1, index-last_index-1].to_i
|
323
|
+
new_number = 0
|
324
|
+
case letter
|
325
|
+
when 115 then # "s"
|
326
|
+
new_number = number
|
327
|
+
when 109 then # "m"
|
328
|
+
new_number = number * 60
|
329
|
+
when 104 then # "h"
|
330
|
+
new_number = number * 3600
|
331
|
+
when 100 then # "d"
|
332
|
+
new_number = number * 86400
|
333
|
+
when 119 then # "w"
|
334
|
+
new_number = number * 604800
|
335
|
+
end
|
336
|
+
total += new_number
|
337
|
+
|
338
|
+
last_index = index
|
339
|
+
index = ttl_text.index(/[whdms]/, last_index + 1)
|
340
|
+
end
|
341
|
+
return total
|
342
|
+
end
|
343
|
+
|
344
|
+
def replace_soa_ttl_fields(line)
|
345
|
+
# Replace any fields which evaluate to 0
|
346
|
+
split = line.split
|
347
|
+
4.times {|i|
|
348
|
+
x = i + 7
|
349
|
+
split[x].strip!
|
350
|
+
split[x] = get_ttl(split[x]).to_s
|
351
|
+
}
|
352
|
+
return split.join(" ") + "\n"
|
353
|
+
end
|
354
|
+
|
355
|
+
# This method is included only for OpenDNSSEC support. It should not be
|
356
|
+
# used otherwise.
|
357
|
+
# Frig the RR type so that NSEC records appear last in the RRSets.
|
358
|
+
# Also make sure that DNSKEYs come first (so we have a key to verify
|
359
|
+
# the RRSet with!).
|
360
|
+
def prefix_for_rrset_order(type, type_was) # :nodoc: all
|
361
|
+
# Now make sure that NSEC(3) RRs go to the back of the list
|
362
|
+
if ['NSEC', 'NSEC3'].include?type.string
|
363
|
+
if (type_was == Types::RRSIG)
|
364
|
+
# Get the RRSIG first
|
365
|
+
type_string = "ZZ" + type.string
|
366
|
+
else
|
367
|
+
type_string = "ZZZ" + type.string
|
368
|
+
end
|
369
|
+
elsif type == Types::DNSKEY
|
370
|
+
type_string = "0" + type.string
|
371
|
+
elsif type == Types::NS
|
372
|
+
# Make sure that we see the NS records first so we know the delegation status
|
373
|
+
type_string = "1" + type.string
|
374
|
+
else
|
375
|
+
type_string = type.string
|
376
|
+
end
|
377
|
+
return type_string
|
378
|
+
end
|
379
|
+
|
380
|
+
end
|
381
|
+
end
|