dnsruby 1.39 → 1.40
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.
- 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
|