dns-zonefile 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +30 -0
- data/LICENCE +13 -0
- data/README +26 -2
- data/Rakefile +11 -13
- data/TODO +2 -6
- data/dns-zonefile.gemspec +30 -0
- data/doc/example.com.zone +60 -0
- data/doc/zonefile.treetop +193 -53
- data/lib/dns/zonefile.rb +301 -9
- data/lib/dns/zonefile/parser.rb +3435 -0
- data/lib/dns/zonefile/version.rb +5 -0
- data/spec/dns/zonefile_spec.rb +241 -41
- data/spec/spec_helper.rb +2 -2
- metadata +79 -50
- data/lib/dns/zonefile_parser.rb +0 -1895
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
dns-zonefile (1.0.0)
|
5
|
+
polyglot
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
polyglot (0.3.2)
|
12
|
+
rspec (2.6.0)
|
13
|
+
rspec-core (~> 2.6.0)
|
14
|
+
rspec-expectations (~> 2.6.0)
|
15
|
+
rspec-mocks (~> 2.6.0)
|
16
|
+
rspec-core (2.6.4)
|
17
|
+
rspec-expectations (2.6.0)
|
18
|
+
diff-lcs (~> 1.1.2)
|
19
|
+
rspec-mocks (2.6.0)
|
20
|
+
treetop (1.4.10)
|
21
|
+
polyglot
|
22
|
+
polyglot (>= 0.3.1)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
|
27
|
+
DEPENDENCIES
|
28
|
+
dns-zonefile!
|
29
|
+
rspec (= 2.6)
|
30
|
+
treetop
|
data/LICENCE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
2
|
+
Version 2, December 2004
|
3
|
+
|
4
|
+
Copyright (C) 2010 Craig R Webster <craig@barkingiguana.com>
|
5
|
+
|
6
|
+
Everyone is permitted to copy and distribute verbatim or modified
|
7
|
+
copies of this license document, and changing it is allowed as long
|
8
|
+
as the name is changed.
|
9
|
+
|
10
|
+
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
11
|
+
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
12
|
+
|
13
|
+
0. You just DO WHAT THE FUCK YOU WANT TO.
|
data/README
CHANGED
@@ -25,24 +25,48 @@ that I've hacked together.
|
|
25
25
|
|
26
26
|
Okay, you're ready to move onto the examples now.
|
27
27
|
|
28
|
+
The above steps should not be necessary if you install the gem via rubygems.
|
29
|
+
|
28
30
|
|
29
31
|
Examples
|
30
32
|
--------
|
31
33
|
|
34
|
+
Using raw data from the parser. Note that "@" isn't translated in this mode.
|
35
|
+
Nor are inherited TTLs interpreted.
|
36
|
+
|
32
37
|
zonefile = "/path/to/file.zone"
|
33
38
|
zone_string = File.read(zonefile)
|
34
39
|
zone = DNS::Zonefile.parse(zone_string)
|
35
40
|
|
41
|
+
puts zone.soa.origin.to_s
|
42
|
+
puts zone.soa.ns.to_s
|
43
|
+
puts zone.rr[0].to_s
|
44
|
+
|
45
|
+
Using more structure data. @, TTLs, and empty hostname inheritance are all
|
46
|
+
handled in this mode.
|
47
|
+
|
48
|
+
zonefile = "/path/to/file.zone"
|
49
|
+
zone_string = File.read(zonefile)
|
50
|
+
zone = DNS::Zonefile.load(zone_string)
|
51
|
+
# or, if no $origin is in the zone file
|
52
|
+
zone = DNS::Zonefile.load(zone_string, 'example.com.')
|
53
|
+
|
36
54
|
puts zone.soa.origin
|
37
|
-
puts zone.soa.
|
38
|
-
puts zone.
|
55
|
+
puts zone.soa.nameserver
|
56
|
+
puts zone.records[1]
|
57
|
+
# get all MX records
|
58
|
+
puts zone.records_of(DNS::MX)
|
39
59
|
|
40
60
|
|
41
61
|
Authors
|
42
62
|
-------
|
43
63
|
|
64
|
+
Original code and concept:
|
44
65
|
Craig R Webster <http://barkingiguana.com/>
|
45
66
|
|
67
|
+
Additions:
|
68
|
+
t.e.morgan <http://zerigo.com/>
|
69
|
+
|
46
70
|
|
47
71
|
Contributing
|
48
72
|
------------
|
data/Rakefile
CHANGED
@@ -1,32 +1,30 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
1
3
|
require 'rake'
|
2
|
-
require '
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
3
6
|
|
4
|
-
desc "Run the tests"
|
5
|
-
Spec::Rake::SpecTask.new('spec') do |t|
|
6
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
7
|
-
t.ruby_opts = [ '-rubygems' ]
|
8
|
-
t.spec_opts = [ '--format specdoc' ]
|
9
|
-
t.libs << 'lib'
|
10
|
-
t.libs << 'spec'
|
11
|
-
end
|
12
7
|
task :default => [ :generate_grammar, :spec ]
|
13
8
|
|
14
9
|
desc "Regenerate the grammar definition"
|
15
10
|
task :generate_grammar do
|
16
|
-
parser_file = 'lib/dns/
|
11
|
+
parser_file = 'lib/dns/zonefile/parser.rb'
|
17
12
|
File.unlink(parser_file) if File.exists?(parser_file)
|
18
13
|
puts %x[tt doc/zonefile -o #{parser_file}]
|
19
14
|
source = "require 'treetop'\n\n"
|
20
15
|
source += "module DNS\n"
|
16
|
+
source += " module Zonefile\n"
|
21
17
|
parser_source = File.open(parser_file, 'r').read
|
22
18
|
parser_source.gsub!(/(\s+)Zonefile$/, '\1ZonefileGrammar # :nodoc:')
|
23
|
-
|
19
|
+
parser_source.gsub!(/(\s+)ZonefileParser/, '\1Parser')
|
20
|
+
source += parser_source.split(/\n/).map { |l| " #{l}".rstrip }.join("\n")
|
21
|
+
source += "\n end"
|
24
22
|
source += "\nend"
|
25
23
|
File.open(parser_file, 'w') do |f|
|
26
24
|
f.write(source)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
30
|
-
task :
|
28
|
+
task :build => [ :generate_grammar, :spec ] do
|
31
29
|
puts %x[gem build dns-zonefile.gemspec]
|
32
|
-
end
|
30
|
+
end
|
data/TODO
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
* Allow empty host strings which expand to the zone origin eg:
|
2
|
-
[spaces] MX 100 mail4
|
3
|
-
-> example.com. MX 100 mail4.example.com.
|
4
1
|
* Support more record types: http://www.dns.net/dnsrd/rr.html
|
5
2
|
* Output the zone object-graph as a zone string.
|
6
|
-
*
|
7
|
-
|
8
|
-
* Allow comparison of resource records and zones for checking equality.
|
3
|
+
* Allow comparison of resource records and zones for checking equality.
|
4
|
+
* Allow unqualified ns and rp in SOA
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "dns/zonefile/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "dns-zonefile"
|
7
|
+
s.version = DNS::Zonefile::VERSION
|
8
|
+
s.authors = ["Craig R Webster"]
|
9
|
+
s.email = ["craig@barkingiguana.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Work with zonefiles (RFC 1035 section 5 and RFC 1034 section 3.6.1)}
|
12
|
+
s.description = %q{The format of a DNS Zonefile is defined in RFC 1035 section 5 and RFC
|
13
|
+
1034 section 3.6.1. To anyone who's using BIND they'll look very
|
14
|
+
familiar.
|
15
|
+
|
16
|
+
This is an attempt to use Ruby parse them into an object graph which can
|
17
|
+
be investigated programatically, manipulated, validated or printed into
|
18
|
+
some canonical form.}
|
19
|
+
|
20
|
+
s.rubyforge_project = "dns-zonefile"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
|
27
|
+
s.add_development_dependency "rspec", "= 2.6"
|
28
|
+
s.add_development_dependency "treetop"
|
29
|
+
s.add_runtime_dependency "polyglot"
|
30
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
; Hi! I'm an example zonefile.
|
2
|
+
$ORIGIN example.com.
|
3
|
+
$TTL 86400; expire in 1 day.
|
4
|
+
@ IN SOA ns.example.com. hostmaster.example.com. (
|
5
|
+
2007120710 ; serial number of this zone file
|
6
|
+
1d ; slave refresh (1 day)
|
7
|
+
1d ; slave retry time in case of a problem (1 day)
|
8
|
+
4W ; slave expiration time (4 weeks)
|
9
|
+
3600 ; minimum caching time in case of failed lookups (1 hour)
|
10
|
+
)
|
11
|
+
; That's the SOA part done.
|
12
|
+
|
13
|
+
; Next comment line has nothing after the semi-colon.
|
14
|
+
;
|
15
|
+
|
16
|
+
; Let's start the resource records.
|
17
|
+
example.com. NS ns ; ns.example.com is the nameserver for example.com
|
18
|
+
example.com. NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.com
|
19
|
+
example.com. A 10.0.0.1 ; ip address for "example.com"
|
20
|
+
@ A 10.0.0.11 ; secondary ip for "example.com"
|
21
|
+
A 10.0.0.12 ; tertiary ip for "example.com"
|
22
|
+
ns A 10.0.0.2 ; ip address for "ns.example.com"
|
23
|
+
A 10.0.0.21 ; secondary ip for "ns.example.com"
|
24
|
+
* A 10.0.0.100 ; wildcard
|
25
|
+
*.sub A 10.0.0.101 ; subdomain wildcard
|
26
|
+
with-class IN A 10.0.0.3 ; record that includes the class type of IN
|
27
|
+
with-ttl 60 A 10.0.0.5 ; with a specified TTL
|
28
|
+
ttl-class 60 IN A 10.0.0.6 ; with TTL and class type
|
29
|
+
www CNAME ns ; "www.example.com" is an alias for "ns.example.com"
|
30
|
+
wwwtest CNAME www ; "wwwtest.example.com" is another alias for "www.example.com"
|
31
|
+
www2 CNAME ns.example.com. ; yet another alias, with FQDN target
|
32
|
+
|
33
|
+
; Email... that'll be fun then
|
34
|
+
example.com. MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
|
35
|
+
@ MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
|
36
|
+
@ MX 50 mail3 ; Similar to above line, but using a host within this domain
|
37
|
+
|
38
|
+
@ AAAA 2001:db8:a::1 ; IPv6, lowercase
|
39
|
+
ns AAAA 2001:DB8:B::1 ; IPv6, uppercase
|
40
|
+
mail AAAA 2001:db8:c::10.0.0.4 ; IPv6, with trailing IPv4-type address
|
41
|
+
|
42
|
+
sip NAPTR 100 10 "U" "E2U+sip" "!^.*$!sip:cs@example.com!i" . ; NAPTR record
|
43
|
+
sip2 NAPTR 100 10 "" "" "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i" . ; another one
|
44
|
+
|
45
|
+
_xmpp-server._tcp SRV 5 0 5269 xmpp-server.l.google.com. ; SRV record
|
46
|
+
|
47
|
+
; TXT record, with embedded semicolons
|
48
|
+
_domainkey TXT "v=DKIM1\;g=*\;k=rsa\; p=4tkw1bbkfa0ahfjgnbewr2ttkvahvfmfizowl9s4g0h28io76ndow25snl9iumpcv0jwxr2k"
|
49
|
+
|
50
|
+
@ TXT "some other \"message\" goes here" ; embedded quotes
|
51
|
+
long TXT "a multi-segment TXT record" "usually used for really long TXT records" "since each segment can only span 255 chars"
|
52
|
+
@ SPF "v=spf1 a a:other.domain.com ~all"
|
53
|
+
|
54
|
+
45 IN PTR @
|
55
|
+
|
56
|
+
$ORIGIN test.example.com.
|
57
|
+
$TTL 3600; expire in 1 day.
|
58
|
+
@ A 10.1.0.1 ; Test with alternate origin
|
59
|
+
MX 10 mail.example.com.
|
60
|
+
www A 10.1.0.2 ; www.test.example.com.
|
data/doc/zonefile.treetop
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
grammar Zonefile
|
2
2
|
rule zone
|
3
|
-
(variable /
|
3
|
+
(variable / space_or_break / comment)* soa (resource_record / variable / comment / space / linebreak)* {
|
4
4
|
def variables
|
5
5
|
@variables ||= begin
|
6
6
|
raw = elements[0].elements.select { |e| e.to_s =~ /^\$/ }
|
@@ -21,7 +21,13 @@ grammar Zonefile
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def rr
|
24
|
-
elements[-1].elements.select { |e| e.to_s !~ /\A\s*(
|
24
|
+
elements[-1].elements.select { |e| e.to_s !~ /\A\s*([;$].*)?\z|\A\z/; }
|
25
|
+
end
|
26
|
+
|
27
|
+
def entries
|
28
|
+
elements[0].elements.select { |e| e.to_s !~ /\A\s*(;.*)?\z|\A\z/; } +
|
29
|
+
[soa] +
|
30
|
+
elements[-1].elements.select { |e| e.to_s !~ /\A\s*(;.*)?\z|\A\z/; }
|
25
31
|
end
|
26
32
|
}
|
27
33
|
end
|
@@ -31,25 +37,41 @@ grammar Zonefile
|
|
31
37
|
def to_s
|
32
38
|
"$#{name.text_value.to_s} #{value.text_value.to_s}"
|
33
39
|
end
|
40
|
+
|
41
|
+
def parse_type ; :variable ; end
|
34
42
|
}
|
35
43
|
end
|
36
44
|
|
37
45
|
rule soa
|
38
|
-
origin space
|
46
|
+
origin space ttl klass "SOA" space ns space rp space "("? space_or_break* serial space_or_break refresh space_or_break reretry space_or_break expiry space_or_break nxttl space_or_break* ")"? {
|
39
47
|
def to_s
|
40
|
-
|
48
|
+
"#{origin} #{ttl} #{klass} SOA #{ns} #{rp} (#{serial} #{refresh} #{reretry} #{expiry} #{nxttl})"
|
41
49
|
end
|
50
|
+
|
51
|
+
def parse_type ; :soa ; end
|
42
52
|
}
|
43
53
|
end
|
44
54
|
|
45
55
|
rule resource_record
|
46
|
-
|
56
|
+
record:(a_record / aaaa_record / cname_record / mx_record / naptr_record / ns_record / ptr_record / srv_record / spf_record / txt_record / soa_record) space* comment? linebreak {
|
57
|
+
def zone
|
58
|
+
p = parent
|
59
|
+
while p.respond_to?(:parent) && p.parent
|
60
|
+
p = p.parent
|
61
|
+
end
|
62
|
+
p
|
63
|
+
end
|
64
|
+
|
47
65
|
def to_s
|
48
66
|
text_value
|
49
67
|
end
|
50
68
|
|
51
69
|
def record_type
|
52
|
-
record.elements[
|
70
|
+
record.elements[4].text_value
|
71
|
+
end
|
72
|
+
|
73
|
+
def ttl
|
74
|
+
record.ttl || zone.variables['TTL'].to_i
|
53
75
|
end
|
54
76
|
|
55
77
|
def method_missing(method_name, *args)
|
@@ -61,13 +83,15 @@ grammar Zonefile
|
|
61
83
|
def respond_to?(method_name)
|
62
84
|
super || record.respond_to?(method_name)
|
63
85
|
end
|
86
|
+
|
87
|
+
def parse_type ; :record ; end
|
64
88
|
}
|
65
89
|
end
|
66
90
|
|
67
91
|
rule a_record
|
68
|
-
host space "A" space ip_address {
|
92
|
+
host space ttl klass "A" space ip_address {
|
69
93
|
def to_s
|
70
|
-
|
94
|
+
"#{host} #{ttl} #{klass} A #{ip_address}"
|
71
95
|
end
|
72
96
|
}
|
73
97
|
end
|
@@ -79,27 +103,91 @@ grammar Zonefile
|
|
79
103
|
end
|
80
104
|
}
|
81
105
|
end
|
106
|
+
|
107
|
+
rule aaaa_record
|
108
|
+
host space ttl klass "AAAA" space ip_address:ip6_address {
|
109
|
+
def to_s
|
110
|
+
"#{host} #{ttl} #{klass} AAAA #{ip_address}"
|
111
|
+
end
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
rule ip6_address
|
116
|
+
[\da-fA-F:.] 2..39 {
|
117
|
+
def to_s
|
118
|
+
text_value.downcase
|
119
|
+
end
|
120
|
+
}
|
121
|
+
end
|
82
122
|
|
83
123
|
rule cname_record
|
84
|
-
|
124
|
+
host space ttl klass "CNAME" space target:host {
|
85
125
|
def to_s
|
86
|
-
|
126
|
+
"#{host} #{ttl} #{klass} CNAME #{target}"
|
87
127
|
end
|
88
128
|
}
|
89
129
|
end
|
90
130
|
|
91
131
|
rule mx_record
|
92
|
-
host space "MX" space priority:integer space exchanger:host {
|
132
|
+
host space ttl klass "MX" space priority:integer space exchanger:host {
|
93
133
|
def to_s
|
94
|
-
|
134
|
+
"#{host} #{ttl} #{klass} MX #{priority} #{exchanger}"
|
135
|
+
end
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
rule naptr_record
|
140
|
+
host space ttl klass "NAPTR" space data {
|
141
|
+
def to_s
|
142
|
+
"#{host} #{ttl} #{klass} NAPTR #{data}"
|
95
143
|
end
|
96
144
|
}
|
97
145
|
end
|
98
146
|
|
99
147
|
rule ns_record
|
100
|
-
host space "NS" space nameserver:host {
|
148
|
+
host space ttl klass "NS" space nameserver:host {
|
101
149
|
def to_s
|
102
|
-
|
150
|
+
"#{host} #{ttl} #{klass} NS #{nameserver}"
|
151
|
+
end
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
rule ptr_record
|
156
|
+
host space ttl klass "PTR" space target:host {
|
157
|
+
def to_s
|
158
|
+
"#{host} #{ttl} #{klass} PTR #{target}"
|
159
|
+
end
|
160
|
+
}
|
161
|
+
end
|
162
|
+
|
163
|
+
rule soa_record
|
164
|
+
origin space ttl klass "SOA" space ns space rp space data {
|
165
|
+
def to_s
|
166
|
+
"#{origin} #{ttl} #{klass} SOA #{ns} #{rp} (#{space})"
|
167
|
+
end
|
168
|
+
}
|
169
|
+
end
|
170
|
+
|
171
|
+
rule srv_record
|
172
|
+
host space ttl klass "SRV" space priority:integer space weight:integer space port:integer space target:host {
|
173
|
+
def to_s
|
174
|
+
"#{host} #{ttl} #{klass} SRV #{priority} #{weight} #{port} #{target}"
|
175
|
+
end
|
176
|
+
}
|
177
|
+
end
|
178
|
+
|
179
|
+
rule spf_record
|
180
|
+
host space ttl klass "SPF" space data:txt_data {
|
181
|
+
def to_s
|
182
|
+
"#{host} #{ttl} #{klass} SPF #{data}"
|
183
|
+
end
|
184
|
+
}
|
185
|
+
end
|
186
|
+
|
187
|
+
rule txt_record
|
188
|
+
host space ttl klass "TXT" space data:txt_data {
|
189
|
+
def to_s
|
190
|
+
"#{host} #{ttl} #{klass} TXT #{data}"
|
103
191
|
end
|
104
192
|
}
|
105
193
|
end
|
@@ -107,31 +195,47 @@ grammar Zonefile
|
|
107
195
|
rule origin
|
108
196
|
host comment* {
|
109
197
|
def to_s
|
110
|
-
|
198
|
+
"#{host}"
|
111
199
|
end
|
112
200
|
}
|
113
201
|
end
|
114
202
|
|
115
203
|
rule space
|
116
|
-
[\
|
204
|
+
[ \t]+ {
|
117
205
|
def to_s
|
118
206
|
text_value
|
119
207
|
end
|
120
208
|
}
|
121
209
|
end
|
122
|
-
|
123
|
-
rule
|
124
|
-
|
210
|
+
|
211
|
+
rule linebreak
|
212
|
+
[\n\r]+ {
|
213
|
+
def to_s
|
214
|
+
''
|
215
|
+
end
|
216
|
+
}
|
217
|
+
end
|
218
|
+
|
219
|
+
rule space_or_break
|
220
|
+
[\s]+ {
|
125
221
|
def to_s
|
126
222
|
text_value
|
127
223
|
end
|
128
224
|
}
|
129
225
|
end
|
130
226
|
|
227
|
+
rule klass
|
228
|
+
(("IN" space) / '') {
|
229
|
+
def to_s
|
230
|
+
text_value.strip
|
231
|
+
end
|
232
|
+
}
|
233
|
+
end
|
234
|
+
|
131
235
|
rule comment
|
132
|
-
space* ";" [^\n]
|
236
|
+
space* ";" [^\n\r]* {
|
133
237
|
def to_s
|
134
|
-
text_value
|
238
|
+
text_value.strip
|
135
239
|
end
|
136
240
|
}
|
137
241
|
end
|
@@ -139,11 +243,12 @@ grammar Zonefile
|
|
139
243
|
rule ns
|
140
244
|
host comment* {
|
141
245
|
def to_s
|
142
|
-
|
246
|
+
"#{host}"
|
143
247
|
end
|
144
248
|
}
|
145
249
|
end
|
146
250
|
|
251
|
+
# fixme: same as host, except also allow \. -- eg: firstname\.lastname.domain.com
|
147
252
|
rule rp
|
148
253
|
([a-zA-Z0-9\-]+ ".")+ {
|
149
254
|
def to_s
|
@@ -157,6 +262,9 @@ grammar Zonefile
|
|
157
262
|
def to_i
|
158
263
|
integer.to_i
|
159
264
|
end
|
265
|
+
def to_s
|
266
|
+
"#{to_i}"
|
267
|
+
end
|
160
268
|
}
|
161
269
|
end
|
162
270
|
|
@@ -167,15 +275,7 @@ grammar Zonefile
|
|
167
275
|
end
|
168
276
|
|
169
277
|
def to_i
|
170
|
-
|
171
|
-
"" => 1,
|
172
|
-
"h" => 60 * 60,
|
173
|
-
"d" => 60 * 60 * 24,
|
174
|
-
"w" => 60 * 60 * 24 * 7,
|
175
|
-
"m" => 60 * 60 * 24 * 7 * 4,
|
176
|
-
"y" => 60 * 60 * 24 * 7 * 4 * 52
|
177
|
-
}
|
178
|
-
multipliers[time_multiplier.to_s] * integer.to_i
|
278
|
+
time_multiplier.to_i * integer.to_i
|
179
279
|
end
|
180
280
|
}
|
181
281
|
end
|
@@ -185,6 +285,9 @@ grammar Zonefile
|
|
185
285
|
def to_i
|
186
286
|
time_interval.to_i
|
187
287
|
end
|
288
|
+
def to_s
|
289
|
+
time_interval.to_s
|
290
|
+
end
|
188
291
|
}
|
189
292
|
end
|
190
293
|
|
@@ -193,22 +296,38 @@ grammar Zonefile
|
|
193
296
|
def to_i
|
194
297
|
text_value.to_i
|
195
298
|
end
|
299
|
+
def to_s
|
300
|
+
"#{to_i}"
|
301
|
+
end
|
196
302
|
}
|
197
303
|
end
|
198
304
|
|
199
305
|
rule time_multiplier
|
200
|
-
(
|
306
|
+
( 's' / 'S' / 'm' / 'M' / 'h' / 'H' / 'd' / 'D' / 'w' / 'W' / '' ) {
|
201
307
|
def to_s
|
202
308
|
text_value
|
203
309
|
end
|
310
|
+
def to_i
|
311
|
+
case text_value.downcase
|
312
|
+
when 'm' then 60
|
313
|
+
when 'h' then 60 * 60
|
314
|
+
when 'd' then 60 * 60 * 24
|
315
|
+
when 'w' then 60 * 60 * 24 * 7
|
316
|
+
else
|
317
|
+
1
|
318
|
+
end
|
319
|
+
end
|
204
320
|
}
|
205
321
|
end
|
206
322
|
|
207
|
-
rule
|
323
|
+
rule reretry
|
208
324
|
time_interval comment* {
|
209
325
|
def to_i
|
210
326
|
time_interval.to_i
|
211
327
|
end
|
328
|
+
def to_s
|
329
|
+
time_interval.to_s
|
330
|
+
end
|
212
331
|
}
|
213
332
|
end
|
214
333
|
|
@@ -217,41 +336,62 @@ grammar Zonefile
|
|
217
336
|
def to_i
|
218
337
|
time_interval.to_i
|
219
338
|
end
|
339
|
+
def to_s
|
340
|
+
time_interval.to_s
|
341
|
+
end
|
220
342
|
}
|
221
343
|
end
|
222
344
|
|
223
|
-
rule
|
345
|
+
rule nxttl
|
224
346
|
time_interval comment* {
|
225
347
|
def to_i
|
226
348
|
time_interval.to_i
|
227
349
|
end
|
350
|
+
def to_s
|
351
|
+
time_interval.to_s
|
352
|
+
end
|
228
353
|
}
|
229
354
|
end
|
230
|
-
|
231
|
-
rule
|
232
|
-
((
|
233
|
-
def
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
p
|
355
|
+
|
356
|
+
rule ttl
|
357
|
+
((time_interval space) / '') {
|
358
|
+
def to_i
|
359
|
+
respond_to?(:time_interval) ? time_interval.to_i : nil
|
360
|
+
end
|
361
|
+
def to_s
|
362
|
+
respond_to?(:time_interval) ? time_interval.to_s : ''
|
239
363
|
end
|
364
|
+
}
|
365
|
+
end
|
240
366
|
|
367
|
+
rule host
|
368
|
+
( ([*a-zA-Z0-9\-\._]+) / "@" / ' ' / "\t" ) {
|
241
369
|
def to_s
|
242
|
-
case
|
243
|
-
when
|
370
|
+
case text_value
|
371
|
+
when /\.$/
|
372
|
+
text_value
|
373
|
+
when "@", /\s/
|
244
374
|
text_value
|
245
|
-
when text_value == "@" || text_value == ""
|
246
|
-
if parent == zone.soa.origin
|
247
|
-
zone.variables['ORIGIN']
|
248
|
-
else
|
249
|
-
zone.origin.to_s
|
250
|
-
end
|
251
375
|
else
|
252
|
-
text_value + '
|
376
|
+
text_value + '.@'
|
253
377
|
end
|
254
378
|
end
|
255
379
|
}
|
256
380
|
end
|
257
|
-
|
381
|
+
|
382
|
+
rule data
|
383
|
+
[^;\n\r]+ {
|
384
|
+
def to_s
|
385
|
+
text_value.strip
|
386
|
+
end
|
387
|
+
}
|
388
|
+
end
|
389
|
+
|
390
|
+
rule txt_data
|
391
|
+
'"'? ('\\"' / !'"' [^\n\r])* '"'? (space '"' ('\\"' / !'"' [^\n\r])* '"')* {
|
392
|
+
def to_s
|
393
|
+
text_value
|
394
|
+
end
|
395
|
+
}
|
396
|
+
end
|
397
|
+
end
|