redns 0.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.
@@ -0,0 +1,65 @@
1
+ class ReDNS::Record::SOA < ReDNS::Fragment
2
+ # == Attributes ===========================================================
3
+
4
+ attribute :mname, :default => lambda { ReDNS::Name.new }, :class => ReDNS::Name
5
+ attribute :rname, :default => lambda { ReDNS::Name.new }, :class => ReDNS::Name
6
+
7
+ attribute :serial, :default => 0, :convert => :to_i
8
+ attribute :refresh, :default => 0, :convert => :to_i
9
+ attribute :retry, :default => 0, :convert => :to_i
10
+ attribute :expire, :default => 0, :convert => :to_i
11
+ attribute :minimum, :default => 0, :convert => :to_i
12
+
13
+ # == Class Methods ========================================================
14
+
15
+ # == Instance Methods =====================================================
16
+
17
+ def to_s
18
+ to_a.join(' ')
19
+ end
20
+
21
+ def to_a
22
+ [
23
+ self.mname,
24
+ self.rname,
25
+ self.serial,
26
+ self.refresh,
27
+ self.retry,
28
+ self.expire,
29
+ self.minimum
30
+ ]
31
+ end
32
+
33
+ def serialize(buffer = ReDNS::Buffer.new)
34
+ self.mname.serialize(buffer)
35
+ self.rname.serialize(buffer)
36
+
37
+ buffer.pack(
38
+ [
39
+ self.serial,
40
+ self.refresh,
41
+ self.retry,
42
+ self.expire,
43
+ self.minimum
44
+ ],
45
+ 'NNNNN'
46
+ )
47
+
48
+ buffer
49
+ end
50
+
51
+ def deserialize(buffer)
52
+ self.mname = ReDNS::Name.new(buffer)
53
+ self.rname = ReDNS::Name.new(buffer)
54
+
55
+ data = buffer.unpack('NNNNN')
56
+
57
+ self.serial = data.shift
58
+ self.refresh = data.shift
59
+ self.retry = data.shift
60
+ self.expire = data.shift
61
+ self.minimum = data.shift
62
+
63
+ self
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ class ReDNS::Record < ReDNS::Fragment
2
+ # == Submodules ===========================================================
3
+
4
+ autoload(:MX, 'redns/record/mx')
5
+ autoload(:Null, 'redns/record/null')
6
+ autoload(:SOA, 'redns/record/soa')
7
+ end
@@ -0,0 +1,86 @@
1
+ class ReDNS::Resource < ReDNS::Fragment
2
+ # == Constants ============================================================
3
+
4
+ # == Attributes ===========================================================
5
+
6
+ attribute :name, :convert => ReDNS::Name, :default => lambda { ReDNS::Name.new }
7
+ attribute :rclass, :default => :in
8
+ attribute :rtype, :default => :a
9
+ attribute :rdata
10
+ attribute :ttl, :default => 0, :convert => :to_i
11
+ attribute :additional, :default => lambda { [ ] }
12
+
13
+ # == Class Methods ========================================================
14
+
15
+ # == Instance Methods =====================================================
16
+
17
+ def empty?
18
+ self.name.empty?
19
+ end
20
+
21
+ def to_s
22
+ "#{name} #{ttl} #{rclass.to_s.upcase} #{rtype.to_s.upcase} #{rdata}"
23
+ end
24
+
25
+ def to_a
26
+ [ name, ttl, rclass, rtype, rdata.to_a ].flatten
27
+ end
28
+
29
+ def serialize(buffer = ReDNS::Buffer.new)
30
+ self.name.serialize(buffer)
31
+
32
+ data_buffer = nil
33
+
34
+ if (self.rdata)
35
+ data_buffer = ReDNS::Buffer.new
36
+ self.rdata.serialize(data_buffer)
37
+ end
38
+
39
+ buffer.pack(
40
+ [
41
+ ReDNS::RR_TYPE[self.rtype],
42
+ ReDNS::RR_CLASS[self.rclass],
43
+ self.ttl,
44
+ data_buffer ? data_buffer.length : 0
45
+ ],
46
+ 'nnNn'
47
+ )
48
+
49
+ if (data_buffer)
50
+ buffer.append(data_buffer)
51
+ end
52
+
53
+ buffer
54
+ end
55
+
56
+ def deserialize(buffer)
57
+ self.name = ReDNS::Name.new(buffer)
58
+
59
+ raw = buffer.unpack("nnNn")
60
+
61
+ self.rtype = ReDNS::RR_TYPE_LABEL[raw.shift]
62
+ self.rclass = ReDNS::RR_CLASS_LABEL[raw.shift]
63
+ self.ttl = raw.shift
64
+
65
+ rdata_length = raw.shift
66
+
67
+ self.rdata =
68
+ case (self.rtype)
69
+ when :a, :aaaa
70
+ self.rdata = ReDNS::Address.new(buffer)
71
+ when :cname, :ptr, :ns
72
+ self.rdata = ReDNS::Name.new(buffer)
73
+ when :soa
74
+ self.rdata = ReDNS::Record::SOA.new(buffer)
75
+ when :txt, :null
76
+ self.rdata = ReDNS::Record::Null.new(buffer.read(rdata_length))
77
+ when :mx
78
+ self.rdata = ReDNS::Record::MX.new(buffer)
79
+ else
80
+ # FUTURE: Throw exception here when trying to decode invalid type
81
+ nil
82
+ end
83
+
84
+ self
85
+ end
86
+ end
@@ -0,0 +1,19 @@
1
+ module ReDNS::Support
2
+ def addr_to_arpa(ip)
3
+ ip and (ip.split(/\./).reverse.join('.') + '.in-addr.arpa.')
4
+ end
5
+
6
+ def inet_ntoa(addr)
7
+ addr.unpack("C4")[0, 4].collect do |v|
8
+ v or 0
9
+ end.join('.')
10
+ end
11
+
12
+ def inet_aton(s)
13
+ s.split(/\./).map do |c|
14
+ c.to_i
15
+ end.pack("C*")
16
+ end
17
+
18
+ extend(self)
19
+ end
data/lib/redns.rb ADDED
@@ -0,0 +1,84 @@
1
+ module ReDNS
2
+ # == Constants ============================================================
3
+
4
+ # RFC1035 Resource Record Type Constants
5
+
6
+ RR_TYPE = {
7
+ :a => 1,
8
+ :ns => 2,
9
+ :md => 3,
10
+ :mf => 4,
11
+ :cname => 5,
12
+ :soa => 6,
13
+ :mb => 7,
14
+ :mg => 8,
15
+ :mr => 9,
16
+ :null => 10,
17
+ :wks => 11,
18
+ :ptr => 12,
19
+ :hinfo => 13,
20
+ :minfo => 14,
21
+ :mx => 15,
22
+ :txt => 16,
23
+ :axfr => 252,
24
+ :mailb => 253,
25
+ :maila => 254,
26
+ :any => 255
27
+ }.freeze
28
+
29
+ RR_TYPE_LABEL = RR_TYPE.invert.freeze
30
+
31
+ # RFC1035 Network Class Constants
32
+
33
+ # NOTE: Other classes are defined but are irrelevant in a contemporary
34
+ # context. This library is entirely IN(internet)-bound.
35
+
36
+ RR_CLASS = {
37
+ :in => 1
38
+ }.freeze
39
+
40
+ RR_CLASS_LABEL = RR_CLASS.invert.freeze
41
+
42
+ OPCODE = {
43
+ :query => 0,
44
+ :iquery => 1,
45
+ :status => 2,
46
+ :unknown => 15
47
+ }.freeze
48
+
49
+ OPCODE_LABEL = OPCODE.invert.freeze
50
+
51
+ RCODE = {
52
+ :noerror => 0,
53
+ :format_error => 1,
54
+ :server_failure => 2,
55
+ :name_error => 3,
56
+ :not_implemented => 4,
57
+ :refused => 5,
58
+ :unknown => 15
59
+ }.freeze
60
+
61
+ RCODE_LABEL = RCODE.invert.freeze
62
+
63
+ # == Submodules ===========================================================
64
+
65
+ autoload(:Address, 'redns/address')
66
+ autoload(:Buffer, 'redns/buffer')
67
+ autoload(:Fragment, 'redns/fragment')
68
+ autoload(:Message, 'redns/message')
69
+ autoload(:Name, 'redns/name')
70
+ autoload(:Question, 'redns/question')
71
+ autoload(:Record, 'redns/record')
72
+ autoload(:Resource, 'redns/resource')
73
+ autoload(:Support, 'redns/support')
74
+
75
+ # == Exceptions ===========================================================
76
+
77
+ class Exception < ::Exception
78
+ class BufferUnderrun < Exception
79
+ end
80
+
81
+ class InvalidPacket < Exception
82
+ end
83
+ end
84
+ end
data/redns.gemspec ADDED
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{redns}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["tadman"]
12
+ s.date = %q{2010-08-13}
13
+ s.description = %q{ReDNS is a pure Ruby DNS library with drivers for reactor-model engines such as EventMachine}
14
+ s.email = %q{github@tadman.ca}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ ".gitignore",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "lib/redns.rb",
25
+ "lib/redns/address.rb",
26
+ "lib/redns/buffer.rb",
27
+ "lib/redns/fragment.rb",
28
+ "lib/redns/message.rb",
29
+ "lib/redns/name.rb",
30
+ "lib/redns/question.rb",
31
+ "lib/redns/record.rb",
32
+ "lib/redns/record/mx.rb",
33
+ "lib/redns/record/null.rb",
34
+ "lib/redns/record/soa.rb",
35
+ "lib/redns/resource.rb",
36
+ "lib/redns/support.rb",
37
+ "redns.gemspec",
38
+ "test/helper.rb",
39
+ "test/test_redns.rb",
40
+ "test/test_redns_address.rb",
41
+ "test/test_redns_buffer.rb",
42
+ "test/test_redns_fragment.rb",
43
+ "test/test_redns_message.rb",
44
+ "test/test_redns_name.rb",
45
+ "test/test_redns_question.rb",
46
+ "test/test_redns_resource.rb",
47
+ "test/test_redns_support.rb"
48
+ ]
49
+ s.homepage = %q{http://github.com/tadman/redns}
50
+ s.rdoc_options = ["--charset=UTF-8"]
51
+ s.require_paths = ["lib"]
52
+ s.rubygems_version = %q{1.3.7}
53
+ s.summary = %q{Ruby Reactor-Ready DNS Library}
54
+ s.test_files = [
55
+ "test/helper.rb",
56
+ "test/test_redns.rb",
57
+ "test/test_redns_address.rb",
58
+ "test/test_redns_buffer.rb",
59
+ "test/test_redns_fragment.rb",
60
+ "test/test_redns_message.rb",
61
+ "test/test_redns_name.rb",
62
+ "test/test_redns_question.rb",
63
+ "test/test_redns_resource.rb",
64
+ "test/test_redns_support.rb"
65
+ ]
66
+
67
+ if s.respond_to? :specification_version then
68
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
69
+ s.specification_version = 3
70
+
71
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
72
+ else
73
+ end
74
+ else
75
+ end
76
+ end
77
+
data/test/helper.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ [ %w[ .. lib ], %w[ . ] ].each do |path|
5
+ $LOAD_PATH.unshift(
6
+ File.expand_path(File.join(*path), File.dirname(__FILE__))
7
+ )
8
+ end
9
+
10
+ require 'redns'
11
+
12
+ class Test::Unit::TestCase
13
+ end
@@ -0,0 +1,4 @@
1
+ require 'helper'
2
+
3
+ class TestRedns < Test::Unit::TestCase
4
+ end
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+
3
+ class TestReDNSAddress < Test::Unit::TestCase
4
+ def test_defaults
5
+ address = ReDNS::Address.new
6
+
7
+ assert_equal '0.0.0.0', address.to_s
8
+ assert address.empty?
9
+ end
10
+
11
+ def test_serialization
12
+ address = ReDNS::Address.new('127.0.0.1')
13
+
14
+ assert_equal '127.0.0.1', address.to_s
15
+ assert !address.empty?
16
+
17
+ buffer = ReDNS::Buffer.new(address)
18
+
19
+ assert_equal 4, buffer.size
20
+
21
+ assert_equal '127.0.0.1', ReDNS::Address.new(buffer).to_s
22
+ end
23
+ end
@@ -0,0 +1,180 @@
1
+ require 'helper'
2
+
3
+ class TestReDNSBuffer < Test::Unit::TestCase
4
+ def test_default_state
5
+ buffer = ReDNS::Buffer.new
6
+
7
+ assert_equal 0, buffer.offset
8
+ assert_equal 0, buffer.length
9
+ assert_equal '', buffer.to_s
10
+
11
+ assert buffer.empty?
12
+ assert !buffer.inspect.empty?
13
+
14
+ rescued = nil
15
+
16
+ begin
17
+ assert '', buffer.read
18
+ rescue Object => rescued
19
+ end
20
+
21
+ assert_equal ReDNS::Exception::BufferUnderrun, rescued.class
22
+ end
23
+
24
+ def test_simple_duplicate
25
+ buffer = ReDNS::Buffer.new('example'.freeze, 1, 3)
26
+
27
+ buffer_copy = buffer.dup
28
+
29
+ assert_equal 1, buffer_copy.offset
30
+ assert_equal 3, buffer_copy.length
31
+ assert_equal 'xam', buffer_copy.to_s
32
+
33
+ assert !buffer_copy.inspect.empty?
34
+ end
35
+
36
+ def test_simple_slice
37
+ data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".freeze
38
+
39
+ buffer = ReDNS::Buffer.new(data)
40
+
41
+ assert_equal 0, buffer.offset
42
+ assert_equal 26, buffer.length
43
+ assert_equal data, buffer.to_s
44
+
45
+ buffer = ReDNS::Buffer.new(data, 5, 10)
46
+
47
+ assert_equal 5, buffer.offset
48
+ assert_equal 10, buffer.length
49
+ assert_equal data[5, 10], buffer.to_s
50
+
51
+ buffer = ReDNS::Buffer.new(data, 20, 10)
52
+
53
+ assert_equal 20, buffer.offset
54
+ assert_equal 6, buffer.length
55
+ assert_equal data[20, 6], buffer.to_s
56
+ end
57
+
58
+ def test_read_and_rewind
59
+ data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".freeze
60
+
61
+ buffer = ReDNS::Buffer.new(data)
62
+
63
+ assert_equal 0, buffer.offset
64
+ assert_equal 26, buffer.length
65
+ assert_equal data, buffer.to_s
66
+
67
+ assert_equal 'ABCDE', buffer.read(5)
68
+ assert_equal 21, buffer.length
69
+
70
+ assert_equal 'F', buffer.read
71
+ assert_equal 20, buffer.length
72
+
73
+ assert_equal 'GHI', buffer.read(3)
74
+ assert_equal 17, buffer.length
75
+
76
+ buffer.rewind(4)
77
+ assert_equal 21, buffer.length
78
+
79
+ assert_equal 'FGHIJ', buffer.read(5)
80
+ assert_equal 16, buffer.length
81
+
82
+ buffer.rewind
83
+ assert_equal 26, buffer.length
84
+
85
+ assert_equal 'ABCDE', buffer.read(5)
86
+ assert_equal 21, buffer.length
87
+
88
+ buffer.advance(-1)
89
+ assert_equal 22, buffer.length
90
+
91
+ assert_equal 'EFGHI', buffer.read(5)
92
+ assert_equal 17, buffer.length
93
+
94
+ buffer.rewind(-1)
95
+ assert_equal 16, buffer.length
96
+
97
+ assert_equal 'KLM', buffer.read(3)
98
+ assert_equal 13, buffer.length
99
+
100
+ buffer.rewind(99)
101
+ assert_equal 26, buffer.length
102
+
103
+ buffer.rewind(-99)
104
+ assert_equal 0, buffer.length
105
+
106
+ buffer.rewind(99)
107
+ assert_equal 26, buffer.length
108
+ end
109
+
110
+ def test_write_and_append
111
+ data = 'ABCDEF'.freeze
112
+
113
+ buffer = ReDNS::Buffer.new(data)
114
+
115
+ buffer.write('XY')
116
+ buffer.write('Z')
117
+
118
+ assert_equal 'ABCDEF', buffer.to_s
119
+
120
+ buffer.advance(2)
121
+ buffer.write('QRST', 1)
122
+
123
+ buffer.rewind
124
+ assert_equal 'XYZABQCDEF', buffer.to_s
125
+
126
+ buffer.advance(2)
127
+ assert_equal 'ZABQCDEF', buffer.to_s
128
+
129
+ buffer.append('RST')
130
+ assert_equal 'ZABQCDEFRST', buffer.to_s
131
+ end
132
+
133
+ def test_unpack
134
+ buffer = ReDNS::Buffer.new([ 127, 0, 0, 255 ].pack('CCCC'))
135
+
136
+ assert_equal [ 127, 0, 0, 255 ], buffer.unpack('CCCC')
137
+
138
+ assert_equal 4, buffer.offset
139
+ assert_equal 0, buffer.length
140
+
141
+ buffer.rewind
142
+
143
+ assert_equal [ (127 << 24 | 255) ], buffer.unpack('N')
144
+ end
145
+
146
+ def test_pack
147
+ buffer = ReDNS::Buffer.new
148
+
149
+ buffer.pack([ 127, 0, 0, 255 ], 'CCCC')
150
+ buffer.pack([ 1, 2, 3, 4 ], 'CCCC')
151
+
152
+ assert_equal 0, buffer.offset
153
+ assert_equal 8, buffer.length
154
+
155
+ assert_equal [ 127, 0, 0, 255 ], buffer.unpack('CCCC')
156
+
157
+ assert_equal 4, buffer.offset
158
+ assert_equal 4, buffer.length
159
+
160
+ assert_equal [ 1, 2, 3, 4 ], buffer.unpack('CCCC')
161
+
162
+ assert_equal 8, buffer.offset
163
+ assert_equal 0, buffer.length
164
+
165
+ assert_equal [ ], buffer.unpack('N')
166
+
167
+ buffer.rewind(4)
168
+
169
+ assert_equal [ (1 << 24 | 2 << 16 | 3 << 8 | 4) ], buffer.unpack('N')
170
+
171
+ buffer.rewind(8)
172
+
173
+ assert_equal [ (127 << 24 | 255) ], buffer.unpack('N')
174
+
175
+ assert_equal [ 1 ], buffer.unpack('C')
176
+ assert_equal [ 2 ], buffer.unpack('C')
177
+ assert_equal [ 3 ], buffer.unpack('C')
178
+ assert_equal [ 4 ], buffer.unpack('C')
179
+ end
180
+ end
@@ -0,0 +1,55 @@
1
+ require 'helper'
2
+
3
+ class ExampleFragment < ReDNS::Fragment
4
+ attribute :sample
5
+ attribute :sample_int, :convert => :to_i, :default => 0
6
+ attribute :sample_proc, :convert => lambda { |v| v.to_i * 2 }
7
+ attribute :sample_class, :convert => ReDNS::Buffer
8
+ attribute :sample_default, :default => lambda { 5 }
9
+ attribute :sample_boolean, :boolean => true
10
+ end
11
+
12
+ class TestReDNSFragment < Test::Unit::TestCase
13
+ def test_base_class
14
+ fragment = ReDNS::Fragment.new
15
+
16
+ empty_state = { }
17
+
18
+ assert_equal empty_state, fragment.attributes
19
+ end
20
+
21
+ def test_example_class
22
+ fragment = ExampleFragment.new
23
+
24
+ assert_equal nil, fragment.sample
25
+ assert_equal 0, fragment.sample_int
26
+ assert_equal ReDNS::Buffer, fragment.sample_class.class
27
+ assert_equal false, fragment.sample_boolean
28
+
29
+ fragment.sample = 'foo'
30
+ assert_equal 'foo', fragment.sample
31
+
32
+ fragment.sample_int = '290'
33
+ assert_equal 290, fragment.sample_int
34
+
35
+ fragment.sample_proc = '100'
36
+ assert_equal 200, fragment.sample_proc
37
+
38
+ fragment.sample_class = 'EXAMPLE'
39
+ assert_equal 'EXAMPLE', fragment.sample_class
40
+ assert_equal ReDNS::Buffer, fragment.sample_class.class
41
+
42
+ assert_equal 5, fragment.sample_default
43
+
44
+ fragment.sample_boolean = 0
45
+ assert_equal true, fragment.sample_boolean
46
+ end
47
+
48
+ def test_initialize_with_block
49
+ fragment = ExampleFragment.new do |fragment|
50
+ fragment.sample = "Example"
51
+ end
52
+
53
+ assert_equal "Example", fragment.sample
54
+ end
55
+ end
@@ -0,0 +1,35 @@
1
+ require 'helper'
2
+
3
+ class TestReDNSMessage < Test::Unit::TestCase
4
+ def test_empty_message
5
+ message = ReDNS::Message.new
6
+
7
+ assert_equal true, message.query?
8
+
9
+ assert_equal 1, message.id
10
+ assert_equal 0, message.questions_count
11
+ assert_equal 0, message.answers_count
12
+ assert_equal 0, message.nameservers_count
13
+ assert_equal 0, message.additional_records_count
14
+
15
+ assert_equal [ ], message.questions
16
+ assert_equal [ ], message.answers
17
+ assert_equal [ ], message.nameservers
18
+ assert_equal [ ], message.additional_records
19
+
20
+ assert_equal ";; HEADER:\n;; opcode: QUERY status: NOERROR id: 1 \n;; flags: ; QUERY: 0, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0\n;; QUESTION SECTION:\n\n;; ANSWER SECTION:\n\n;; NAMESERVER SECTION:\n\n;; ADDITIONAL SECTION:\n\n", message.to_s
21
+ end
22
+
23
+ def test_simple_query
24
+ message = ReDNS::Message.new
25
+
26
+ question = ReDNS::Question.new do |question|
27
+ question.name = 'example.com'
28
+ question.qtype = :a
29
+ end
30
+
31
+ message.questions << question
32
+
33
+ assert_equal 1, message.questions.length
34
+ end
35
+ end