zonefile 1.00 → 1.01
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/zonefile/zonefile.rb +32 -12
- data/tests/test-zone.db +2 -0
- data/tests/zonefile.rb +25 -3
- metadata +19 -7
data/lib/zonefile/zonefile.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# == Description
|
5
5
|
# This class can read, manipulate and create DNS zone files. It supports A, AAAA, MX, NS, SOA,
|
6
|
-
# TXT, CNAME and SRV records. The data can be accessed by the instance method of the same
|
6
|
+
# TXT, CNAME, PTR and SRV records. The data can be accessed by the instance method of the same
|
7
7
|
# name. All except SOA return an array of hashes containing the named data. SOA directly returns the
|
8
8
|
# hash since there can only be one SOA information.
|
9
9
|
#
|
@@ -23,6 +23,8 @@
|
|
23
23
|
# - :name, :ttl, :class, :text
|
24
24
|
# * A4 (AAAA)
|
25
25
|
# - :name, :ttl, :class, :host
|
26
|
+
# * PTR
|
27
|
+
# - :name, :ttl, :class, :host
|
26
28
|
# * SRV
|
27
29
|
# - :name, :ttl, :class, :pri, :weight, :port, :host
|
28
30
|
#
|
@@ -69,10 +71,14 @@
|
|
69
71
|
class Zonefile
|
70
72
|
|
71
73
|
RECORDS = %w{ mx a a4 ns cname txt ptr srv soa }
|
72
|
-
attr :records
|
74
|
+
attr :records
|
73
75
|
attr :soa
|
74
76
|
attr :data
|
75
|
-
|
77
|
+
# global $ORIGIN option
|
78
|
+
attr :origin
|
79
|
+
# global $TTL option
|
80
|
+
attr :ttl
|
81
|
+
|
76
82
|
def method_missing(m)
|
77
83
|
return super unless RECORDS.include?(m.to_s)
|
78
84
|
@records[m]
|
@@ -97,7 +103,7 @@ class Zonefile
|
|
97
103
|
def initialize(zonefile = '', file_name= nil, origin= nil)
|
98
104
|
@data = zonefile
|
99
105
|
@filename = file_name
|
100
|
-
@origin = origin
|
106
|
+
@origin = origin || (file_name ? file_name.split('/').last : '')
|
101
107
|
|
102
108
|
@records = {}
|
103
109
|
@soa = {}
|
@@ -105,6 +111,14 @@ class Zonefile
|
|
105
111
|
parse
|
106
112
|
end
|
107
113
|
|
114
|
+
# True if no records (except sao) is defined in this file
|
115
|
+
def empty?
|
116
|
+
RECORDS.each do |r|
|
117
|
+
return false unless @records[r.intern].empty?
|
118
|
+
end
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
108
122
|
# Create a new object by reading the content of a file
|
109
123
|
def self.from_file(file_name, origin = nil)
|
110
124
|
Zonefile.new(File.read(file_name), file_name.split('/').last, origin)
|
@@ -118,17 +132,17 @@ class Zonefile
|
|
118
132
|
def new_serial
|
119
133
|
base = "%04d%02d%02d" % [Time.now.year, Time.now.month, Time.now.day ]
|
120
134
|
|
121
|
-
if ((
|
122
|
-
ns =
|
123
|
-
|
135
|
+
if ((@soa[:serial].to_i / 100) > base.to_i) then
|
136
|
+
ns = @soa[:serial].to_i + 1
|
137
|
+
@soa[:serial] = ns.to_s
|
124
138
|
return ns.to_s
|
125
139
|
end
|
126
140
|
|
127
141
|
ii = 0
|
128
|
-
while (("#{base}%02d" % ii).to_i <=
|
142
|
+
while (("#{base}%02d" % ii).to_i <= @soa[:serial].to_i) do
|
129
143
|
ii += 1
|
130
144
|
end
|
131
|
-
|
145
|
+
@soa[:serial] = "#{base}%02d" % ii
|
132
146
|
end
|
133
147
|
|
134
148
|
def parse_line(line)
|
@@ -140,7 +154,9 @@ class Zonefile
|
|
140
154
|
ttl_cls = Regexp.new("(?:(#{rr_ttl})\s)?(?:(#{rr_class})\s)?")
|
141
155
|
|
142
156
|
data = {}
|
143
|
-
if line =~
|
157
|
+
if line =~ /^\$ORIGIN\s*(#{valid_name})/ix then
|
158
|
+
@origin = $1
|
159
|
+
elsif line =~ /^(#{valid_name})? \s*
|
144
160
|
#{ttl_cls}
|
145
161
|
(#{rr_type}) \s
|
146
162
|
(#{valid_name})
|
@@ -203,7 +219,7 @@ class Zonefile
|
|
203
219
|
elsif line =~ /(#{valid_name})? \s #{ttl_cls} TXT \s \"([^\"]*)\"/ix
|
204
220
|
add_record('txt', :name => $1, :ttl => $2, :class => $3, :text => $4)
|
205
221
|
elsif line =~ /\$TTL\s+(#{rr_ttl})/i
|
206
|
-
@
|
222
|
+
@ttl = $1
|
207
223
|
end
|
208
224
|
end
|
209
225
|
|
@@ -222,7 +238,8 @@ class Zonefile
|
|
222
238
|
; Database file #{@filename || 'unknown'} for #{@origin || 'unknown'} zone.
|
223
239
|
; Zone version: #{self.soa[:serial]}
|
224
240
|
;
|
225
|
-
#{
|
241
|
+
#{@origin ? "$ORIGIN #{@origin}" : ''}
|
242
|
+
#{@ttl ? "$TTL #{@ttl}" : ''}
|
226
243
|
#{self.soa[:origin]} #{self.soa[:ttl]} IN SOA #{self.soa[:primary]} #{self.soa[:email]} (
|
227
244
|
#{self.soa[:serial]} ; serial number
|
228
245
|
#{self.soa[:refresh]} ; refresh
|
@@ -255,6 +272,9 @@ ENDH
|
|
255
272
|
self.srv.each do |srv|
|
256
273
|
out << "#{srv[:name]} #{srv[:ttl]} #{srv[:class]} SRV #{srv[:pri]} #{srv[:weight]} #{srv[:port]} #{srv[:host]}\n"
|
257
274
|
end
|
275
|
+
self.ptr.each do |ptr|
|
276
|
+
out << "#{ptr[:name]} #{ptr[:ttl]} #{ptr[:class]} PTR #{ptr[:host]}\n"
|
277
|
+
end
|
258
278
|
|
259
279
|
out
|
260
280
|
end
|
data/tests/test-zone.db
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
; Database file dns-zoneparse-test.net.dns for dns-zoneparse-test.net zone.
|
2
2
|
; Zone version: 2000100501
|
3
3
|
$TTL 1H
|
4
|
+
$ORIGIN test-zone.db
|
4
5
|
@ 3600 IN SOA ns0.dns-zoneparse-test.net. support.dns-zoneparse-test.net. (
|
5
6
|
2000100501 ; serial number
|
6
7
|
10800 ; refresh
|
@@ -29,4 +30,5 @@ icarus IN AAAA fe80::0260:83ff:fe7c:3a2a
|
|
29
30
|
soup IN TXT "This is a text message"
|
30
31
|
txta TXT "This is another text message"
|
31
32
|
_sip._tcp.example.com. 86400 IN SRV 0 5 5060 sipserver.example.com.
|
33
|
+
12.23.21.23.in-addr.arpa IN PTR www.myhost.example.com.
|
32
34
|
|
data/tests/zonefile.rb
CHANGED
@@ -17,6 +17,13 @@ class TC_Zonefile < Test::Unit::TestCase
|
|
17
17
|
@zf = Zonefile.new(@zf.output, 'test-origin')
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_empty
|
21
|
+
zf = Zonefile.new
|
22
|
+
zf.soa[:refresh] = 1234
|
23
|
+
assert zf.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
|
20
27
|
def test_soa
|
21
28
|
assert_equal '86400', @zf.soa[:minimumTTL]
|
22
29
|
assert_equal '691200', @zf.soa[:expire]
|
@@ -128,14 +135,29 @@ class TC_Zonefile < Test::Unit::TestCase
|
|
128
135
|
@zf.soa[:serial] = '9999889901'
|
129
136
|
@zf.new_serial
|
130
137
|
assert_equal '9999889902', @zf.soa[:serial]
|
138
|
+
end
|
131
139
|
|
140
|
+
def test_ptr
|
141
|
+
assert_equal '12.23.21.23.in-addr.arpa', @zf.ptr[0][:name]
|
142
|
+
assert_equal 'www.myhost.example.com.', @zf.ptr[0][:host]
|
143
|
+
begin
|
144
|
+
@swap_ptr = true
|
145
|
+
swap
|
146
|
+
test_ptr
|
147
|
+
end unless @swap_ptr
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_origin
|
151
|
+
assert_equal 'test-zone.db', @zf.origin
|
152
|
+
swap
|
153
|
+
assert_equal 'test-zone.db', @zf.origin
|
132
154
|
end
|
133
155
|
|
134
156
|
|
135
157
|
def test_output
|
136
|
-
|
137
|
-
|
138
|
-
|
158
|
+
puts @zf.data
|
159
|
+
puts '==================='
|
160
|
+
puts @zf.output
|
139
161
|
end
|
140
162
|
|
141
163
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zonefile
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 13
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 1
|
9
|
+
version: "1.01"
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Martin Boese
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2011-01-24 00:00:00 +01:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -22,36 +27,43 @@ extensions: []
|
|
22
27
|
extra_rdoc_files: []
|
23
28
|
|
24
29
|
files:
|
25
|
-
- lib/zonefile
|
26
30
|
- lib/zonefile/zonefile.rb
|
27
31
|
- lib/zonefile.rb
|
28
32
|
- tests/test-zone.db
|
29
33
|
- tests/zonefile.rb
|
30
34
|
has_rdoc: true
|
31
35
|
homepage: http://zonefile.rubyforge.org/
|
36
|
+
licenses: []
|
37
|
+
|
32
38
|
post_install_message:
|
33
39
|
rdoc_options: []
|
34
40
|
|
35
41
|
require_paths:
|
36
42
|
- lib
|
37
43
|
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
38
45
|
requirements:
|
39
46
|
- - ">="
|
40
47
|
- !ruby/object:Gem::Version
|
48
|
+
hash: 3
|
49
|
+
segments:
|
50
|
+
- 0
|
41
51
|
version: "0"
|
42
|
-
version:
|
43
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
44
54
|
requirements:
|
45
55
|
- - ">="
|
46
56
|
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
47
60
|
version: "0"
|
48
|
-
version:
|
49
61
|
requirements: []
|
50
62
|
|
51
63
|
rubyforge_project: zonefile
|
52
|
-
rubygems_version: 1.
|
64
|
+
rubygems_version: 1.3.7
|
53
65
|
signing_key:
|
54
|
-
specification_version:
|
66
|
+
specification_version: 3
|
55
67
|
summary: BIND 8/9 Zonefile Reader and Writer
|
56
68
|
test_files: []
|
57
69
|
|