dns-zonefile 0.0.1 → 1.0.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.
- 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
|