faildns 0.0.1

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.
Files changed (37) hide show
  1. data/bin/failnamed +203 -0
  2. data/bin/failresolve +37 -0
  3. data/lib/faildns.rb +20 -0
  4. data/lib/faildns/class.rb +96 -0
  5. data/lib/faildns/client.rb +114 -0
  6. data/lib/faildns/common.rb +52 -0
  7. data/lib/faildns/domainname.rb +223 -0
  8. data/lib/faildns/header.rb +254 -0
  9. data/lib/faildns/header/opcode.rb +95 -0
  10. data/lib/faildns/header/status.rb +123 -0
  11. data/lib/faildns/header/type.rb +72 -0
  12. data/lib/faildns/ip.rb +57 -0
  13. data/lib/faildns/message.rb +100 -0
  14. data/lib/faildns/qclass.rb +51 -0
  15. data/lib/faildns/qtype.rb +60 -0
  16. data/lib/faildns/question.rb +101 -0
  17. data/lib/faildns/resourcerecord.rb +140 -0
  18. data/lib/faildns/resourcerecord/IN.rb +29 -0
  19. data/lib/faildns/resourcerecord/IN/A.rb +75 -0
  20. data/lib/faildns/resourcerecord/IN/AAAA.rb +77 -0
  21. data/lib/faildns/resourcerecord/IN/CNAME.rb +70 -0
  22. data/lib/faildns/resourcerecord/IN/HINFO.rb +79 -0
  23. data/lib/faildns/resourcerecord/IN/MX.rb +75 -0
  24. data/lib/faildns/resourcerecord/IN/NS.rb +77 -0
  25. data/lib/faildns/resourcerecord/IN/NULL.rb +66 -0
  26. data/lib/faildns/resourcerecord/IN/PTR.rb +69 -0
  27. data/lib/faildns/resourcerecord/IN/SOA.rb +128 -0
  28. data/lib/faildns/resourcerecord/IN/TXT.rb +63 -0
  29. data/lib/faildns/resourcerecord/data.rb +41 -0
  30. data/lib/faildns/server.rb +71 -0
  31. data/lib/faildns/server/dispatcher.rb +181 -0
  32. data/lib/faildns/server/dispatcher/connectiondispatcher.rb +93 -0
  33. data/lib/faildns/server/dispatcher/event.rb +47 -0
  34. data/lib/faildns/server/dispatcher/eventdispatcher.rb +73 -0
  35. data/lib/faildns/server/dispatcher/socket.rb +93 -0
  36. data/lib/faildns/type.rb +186 -0
  37. metadata +100 -0
@@ -0,0 +1,51 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
3
+ #
4
+ # This file is part of faildns.
5
+ #
6
+ # faildns is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # faildns is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with faildns. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'faildns/class'
21
+
22
+ module DNS
23
+
24
+ #--
25
+ # QCLASS fields appear in the question section of a query. QCLASS values
26
+ # are a superset of CLASS values; every CLASS is a valid QCLASS. In
27
+ # addition to CLASS values, the following QCLASSes are defined:
28
+ #
29
+ # * 255 any class
30
+ #++
31
+
32
+ class QClass < Class
33
+ Values = {
34
+ 254 => :NONE,
35
+ 255 => :ANY
36
+ }
37
+
38
+ def initialize (value)
39
+ super(value)
40
+ end
41
+
42
+ def to_sym
43
+ Values[@value] || Class::Values[@value]
44
+ end
45
+
46
+ def to_s
47
+ (Values[@value] || Class::Values[@value]).to_s
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,60 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
3
+ #
4
+ # This file is part of faildns.
5
+ #
6
+ # faildns is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # faildns is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with faildns. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'faildns/type'
21
+
22
+ module DNS
23
+
24
+ #--
25
+ # QTYPE fields appear in the question part of a query. QTYPES are a
26
+ # superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the
27
+ # following QTYPEs are defined:
28
+ #
29
+ #
30
+ # AXFR 252 A request for a transfer of an entire zone
31
+ #
32
+ # MAILB 253 A request for mailbox-related records (MB, MG or MR)
33
+ #
34
+ # MAILA 254 A request for mail agent RRs (Obsolete - see MX)
35
+ #
36
+ # * 255 A request for all records
37
+ #++
38
+
39
+ class QType < Type
40
+ Values = {
41
+ 252 => :AXFR,
42
+ 253 => :MAILB,
43
+ 254 => :MAILA,
44
+ 255 => :ANY
45
+ }
46
+
47
+ def initialize (value)
48
+ super(value)
49
+ end
50
+
51
+ def to_sym
52
+ Values[@value] || Type::Values[@value]
53
+ end
54
+
55
+ def to_s
56
+ (Values[@value] || Type::Values[@value]).to_s
57
+ end
58
+ end
59
+
60
+ end
@@ -0,0 +1,101 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
3
+ #
4
+ # This file is part of faildns.
5
+ #
6
+ # faildns is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # faildns is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with faildns. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'faildns/domainname'
21
+ require 'faildns/qtype'
22
+ require 'faildns/qclass'
23
+
24
+ module DNS
25
+
26
+ #--
27
+ # The question section is used to carry the "question" in most queries,
28
+ # i.e., the parameters that define what is being asked. The section
29
+ # contains QDCOUNT (usually 1) entries, each of the following format:
30
+ #
31
+ # 1 1 1 1 1 1
32
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
33
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
34
+ # | |
35
+ # / QNAME /
36
+ # / /
37
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
38
+ # | QTYPE |
39
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
40
+ # | QCLASS |
41
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42
+ #
43
+ # where:
44
+ #
45
+ # QNAME a domain name represented as a sequence of labels, where
46
+ # each label consists of a length octet followed by that
47
+ # number of octets. The domain name terminates with the
48
+ # zero length octet for the null label of the root. Note
49
+ # that this field may be an odd number of octets; no
50
+ # padding is used.
51
+ #
52
+ # QTYPE a two octet code which specifies the type of the query.
53
+ # The values for this field include all codes valid for a
54
+ # TYPE field, together with some more general codes which
55
+ # can match more than one type of RR.
56
+ #
57
+ # QCLASS a two octet code that specifies the class of the query.
58
+ # For example, the QCLASS field is IN for the Internet.
59
+ #++
60
+
61
+ class Question
62
+ def self.parse (string, original)
63
+ Question.new {|q|
64
+ q.name = DomainName.parse(string, original);
65
+ q.type = QType.parse(string);
66
+ q.class = QClass.parse(string);
67
+ }
68
+ end
69
+
70
+ def self.length (string)
71
+ DomainName.length(string) + QType.length + QClass.length
72
+
73
+ return result
74
+ end
75
+
76
+ def initialize (what={})
77
+ if !what.is_a? Hash
78
+ raise ArgumentError.new('You have to pass a Hash.')
79
+ end
80
+
81
+ @data = what
82
+
83
+ if block_given?
84
+ yield self
85
+ end
86
+ end
87
+
88
+ def name; @data[:QNAME] end
89
+ def type; @data[:QTYPE] end
90
+ def class; @data[:QCLASS] end
91
+
92
+ def name= (val); @data[:QNAME] = DomainName.new(val) end
93
+ def type= (val); @data[:QTYPE] = QType.new(val) end
94
+ def class= (val); @data[:QCLASS] = QClass.new(val) end
95
+
96
+ def pack
97
+ self.name.pack + self.type.pack + self.class.pack
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,140 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
3
+ #
4
+ # This file is part of faildns.
5
+ #
6
+ # faildns is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # faildns is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with faildns. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'faildns/resourcerecord/IN'
21
+
22
+ module DNS
23
+
24
+ #--
25
+ # The answer, authority, and additional sections all share the same
26
+ # format: a variable number of resource records, where the number of
27
+ # records is specified in the corresponding count field in the header.
28
+ # Each resource record has the following format:
29
+ # 1 1 1 1 1 1
30
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
31
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
32
+ # | |
33
+ # / /
34
+ # / NAME /
35
+ # | |
36
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
37
+ # | TYPE |
38
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
39
+ # | CLASS |
40
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
41
+ # | TTL |
42
+ # | |
43
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44
+ # | RDLENGTH |
45
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
46
+ # / RDATA /
47
+ # / /
48
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
49
+ #
50
+ # where:
51
+ #
52
+ # NAME a domain name to which this resource record pertains.
53
+ #
54
+ # TYPE two octets containing one of the RR type codes. This
55
+ # field specifies the meaning of the data in the RDATA
56
+ # field.
57
+ #
58
+ # CLASS two octets which specify the class of the data in the
59
+ # RDATA field.
60
+ #
61
+ # TTL a 32 bit unsigned integer that specifies the time
62
+ # interval (in seconds) that the resource record may be
63
+ # cached before it should be discarded. Zero values are
64
+ # interpreted to mean that the RR can only be used for the
65
+ # transaction in progress, and should not be cached.
66
+ #
67
+ # RDLENGTH an unsigned 16 bit integer that specifies the length in
68
+ # octets of the RDATA field.
69
+ #
70
+ # RDATA a variable length string of octets that describes the
71
+ # resource. The format of this information varies
72
+ # according to the TYPE and CLASS of the resource record.
73
+ # For example, the if the TYPE is A and the CLASS is IN,
74
+ # the RDATA field is a 4 octet ARPA Internet address.
75
+ #++
76
+
77
+ class ResourceRecord
78
+ def self.parse (string, original)
79
+ string.force_encoding 'BINARY'
80
+
81
+ ResourceRecord.new {|r|
82
+ r.name = DomainName.parse(string, original)
83
+ r.type = Type.parse(string)
84
+ r.class = Class.parse(string)
85
+
86
+ r.ttl = string.unpack('N').first; string[0, 4] = ''
87
+
88
+ r.length = string.unpack('n').first; string[0, 2] = ''
89
+ r.data = ResourceRecord.const_get(r.class.to_sym).const_get(r.type.to_sym) rescue nil
90
+
91
+ if !r.data
92
+ r.data = ResourceRecord.const_get(r.class.to_sym).const_get(:NULL)
93
+ DNS.debug "ResourceRecord::#{r.class}::#{r.type} not found."
94
+ end
95
+
96
+ DNS.debug r.data.inspect, { :level => 2 }
97
+
98
+ r.data = r.data.parse(string, r.length, original)
99
+ }
100
+ end
101
+
102
+ def self.length (string)
103
+ string.force_encoding 'BINARY'
104
+
105
+ (tmp = DomainName.length(string) + Type.length + Class.length + 4) + string[tmp, 2].unpack('n').first + 2
106
+ end
107
+
108
+ def initialize (what={})
109
+ if !what.is_a? Hash
110
+ raise ArgumentError.new('You have to pass a Hash.')
111
+ end
112
+
113
+ @data = what
114
+
115
+ if block_given?
116
+ yield self
117
+ end
118
+ end
119
+
120
+ def name; @data[:NAME] end
121
+ def type; @data[:TYPE] end
122
+ def class; @data[:CLASS] end
123
+ def ttl; @data[:TTL] end
124
+ def length; @data[:RDLENGTH] end
125
+ def data; @data[:RDATA] end
126
+
127
+ def name= (val); @data[:NAME] = DomainName.new(val) end
128
+ def type= (val); @data[:TYPE] = Type.new(val) end
129
+ def class= (val); @data[:CLASS] = Class.new(val) end
130
+ def ttl= (val); @data[:TTL] = val end
131
+ def length= (val); @data[:RDLENGTH] = val end
132
+ def data= (val); @data[:RDATA] = val end
133
+
134
+ def pack
135
+ self.name.pack + self.type.pack + self.class.pack + [self.ttl].pack('N') +
136
+ [self.length].pack('n') + self.data.pack
137
+ end
138
+ end
139
+
140
+ end
@@ -0,0 +1,29 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
3
+ #
4
+ # This file is part of faildns.
5
+ #
6
+ # faildns is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # faildns is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with faildns. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'faildns/resourcerecord/IN/A'
21
+ require 'faildns/resourcerecord/IN/CNAME'
22
+ require 'faildns/resourcerecord/IN/HINFO'
23
+ require 'faildns/resourcerecord/IN/MX'
24
+ require 'faildns/resourcerecord/IN/NS'
25
+ require 'faildns/resourcerecord/IN/NULL'
26
+ require 'faildns/resourcerecord/IN/PTR'
27
+ require 'faildns/resourcerecord/IN/SOA'
28
+ require 'faildns/resourcerecord/IN/TXT'
29
+ require 'faildns/resourcerecord/IN/AAAA'
@@ -0,0 +1,75 @@
1
+ #--
2
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
3
+ #
4
+ # This file is part of faildns.
5
+ #
6
+ # faildns is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published
8
+ # by the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # faildns is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with faildns. If not, see <http://www.gnu.org/licenses/>.
18
+ #++
19
+
20
+ require 'faildns/resourcerecord/data'
21
+ require 'faildns/ip'
22
+
23
+ module DNS
24
+
25
+ class ResourceRecord
26
+
27
+ module IN
28
+
29
+ #--
30
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
31
+ # | ADDRESS |
32
+ # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
33
+ #
34
+ # where:
35
+ #
36
+ # ADDRESS A 32 bit Internet address.
37
+ #
38
+ # Hosts that have multiple Internet addresses will have multiple A
39
+ # records.
40
+ #
41
+ # A records cause no additional section processing. The RDATA section of
42
+ # an A line in a master file is an Internet address expressed as four
43
+ # decimal numbers separated by dots without any imbedded spaces (e.g.,
44
+ # "10.2.0.52" or "192.0.5.6").
45
+ #++
46
+
47
+ class A < Data
48
+ def self._parse (string, original)
49
+ A.new(IP.parse(string))
50
+ end
51
+
52
+ def self.length
53
+ 4
54
+ end
55
+
56
+ attr_reader :ip
57
+
58
+ def initialize (what)
59
+ @ip = IP.new(what)
60
+ end
61
+
62
+ def pack
63
+ @ip.pack
64
+ end
65
+
66
+ def to_s
67
+ @ip.to_s
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end