redns 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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