faildns 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,93 @@
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 'thread'
21
+ require 'socket'
22
+
23
+ require 'faildns/server/dispatcher/socket'
24
+ require 'faildns/message'
25
+
26
+ module DNS
27
+
28
+ class Server
29
+
30
+ class Dispatcher
31
+
32
+ class ConnectionDispatcher
33
+ attr_reader :server, :dispatcher, :listening
34
+
35
+ def initialize (dispatcher)
36
+ @server = dispatcher.server
37
+ @dispatcher = dispatcher
38
+
39
+ @host = @server.options[:host] || '0.0.0.0'
40
+ @port = @server.options[:port] || 53
41
+
42
+ @sockets = []
43
+ end
44
+
45
+ def start
46
+ @listening = {
47
+ :TCP => TCPServer.new(@host, @port),
48
+ :UDP => UDPSocket.new
49
+ }
50
+
51
+ @listening[:UDP].bind(@host, @port)
52
+ end
53
+
54
+ def read
55
+ reading, = IO::select @sockets.concat([@listening[:UDP], @listening[:TCP]])
56
+
57
+ if !reading
58
+ return
59
+ end
60
+
61
+ reading.each {|socket|
62
+ if socket.is_a? TCPServer
63
+ @sockets.push @listening[:TCP].accept_nonblock
64
+ elsif socket.is_a? TCPSocket
65
+ self.handle socket.recv_nonblock(65535), socket
66
+ @sockets.delete(socket)
67
+ else
68
+ begin
69
+ self.handle *@listening[:UDP].recvfrom_nonblock(512)
70
+ rescue Errno::EAGAIN
71
+ end
72
+ end
73
+ }
74
+ end
75
+
76
+ def handle (string, socket)
77
+ DNS.debug "#{socket.inspect}: #{string.inspect}", { :level => 9 }
78
+
79
+ Thread.new(string) {|input|
80
+ begin
81
+ @dispatcher.dispatch :input, Socket.new(@dispatcher, socket), Message.parse(string)
82
+ rescue Exception => e
83
+ DNS.debug e
84
+ end
85
+ }
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,47 @@
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
+
21
+ module DNS
22
+
23
+ class Server
24
+
25
+ class Dispatcher
26
+
27
+ class Event
28
+ class Callback
29
+ attr_reader :method
30
+ attr_accessor :priority
31
+
32
+ def initialize (method, priority=0)
33
+ @method = method
34
+ @priority = priority
35
+ end
36
+
37
+ def call (*args)
38
+ return @method.call(*args)
39
+ end
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,73 @@
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/server/dispatcher/event'
21
+
22
+ module DNS
23
+
24
+ class Server
25
+
26
+ class Dispatcher
27
+
28
+ class EventDispatcher
29
+ attr_reader :server, :dispatcher
30
+
31
+ def initialize (dispatcher)
32
+ @server = dispatcher.server
33
+ @dispatcher = dispatcher
34
+
35
+ @chains = {
36
+ :input => [],
37
+ :output => [],
38
+
39
+ :custom => {}
40
+ }
41
+ end
42
+
43
+ def dispatch (chain, socket, message)
44
+ @chains[chain].each {|callback|
45
+ callback.call(socket, message)
46
+ }
47
+ end
48
+
49
+ def fire (event, *args)
50
+ (@chain[:custom][event] || []).each {|callback|
51
+ begin
52
+ if callback.call(*args) == false
53
+ return false
54
+ end
55
+ rescue Exception => e
56
+ end
57
+ }
58
+ end
59
+
60
+ def observe (event, callback, priority=0)
61
+ @chains[:custom][event].push((callback.is_a?(Event::Callback)) ? callback : Event::Callback.new(callback, priority))
62
+ end
63
+
64
+ def register (chain, callback, priority=0)
65
+ @chains[chain].push((callback.is_a?(Event::Callback)) ? callback : Event::Callback.new(callback, priority))
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,93 @@
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
+ module DNS
21
+
22
+ class Server
23
+
24
+ class Dispatcher
25
+
26
+ class ConnectionDispatcher
27
+
28
+ class Socket
29
+ attr_reader :ip, :port, :type
30
+
31
+ def initialize (dispatcher, what)
32
+ @dispatcher = dispatcher
33
+
34
+ if what.is_a? TCPSocket
35
+ @type = :TCP
36
+ @ip = what.peeraddr[3]
37
+ @port = what.addr[1]
38
+
39
+ @socket = what
40
+ else
41
+ @type = :UDP
42
+ @ip = what[3]
43
+ @port = what[1]
44
+
45
+ @socket = dispatcher.connection.listening[:UDP]
46
+ end
47
+ end
48
+
49
+ def send (message, close=true)
50
+ @dispatcher.dispatch :output, self, message
51
+
52
+ if @type == :UDP && message.pack.length > 512
53
+ [message.additionals, message.authorities, message.answers, message.questions].each {|rr|
54
+ while (tmp = message.pack).length > 512 && r.pop; end
55
+
56
+ if tmp.length <= 512
57
+ break
58
+ end
59
+ }
60
+
61
+ message.header.questions = message.questions.length
62
+ message.header.answers = message.answers.length
63
+ message.header.authorities = message.authorities.length
64
+ message.header.additionals = message.additionals.length
65
+
66
+ message.header.truncated!
67
+ end
68
+
69
+ if @socket.is_a? TCPSocket
70
+ @socket.send_nonblock(message.pack)
71
+
72
+ if close
73
+ @socket.close
74
+ end
75
+ else
76
+ @socket.send(message.pack, 0, ::Socket.pack_sockaddr_in(@port, @ip))
77
+ end
78
+ end
79
+
80
+ def close
81
+ if @socket.is_a? TCPSocket
82
+ @socket.close
83
+ end
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,186 @@
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
+ module DNS
21
+
22
+ #--
23
+ # TYPE fields are used in resource records. Note that these types are a
24
+ # subset of QTYPEs.
25
+ #
26
+ # TYPE value and meaning
27
+ #
28
+ # A 1 a host address
29
+ #
30
+ # NS 2 an authoritative name server
31
+ #
32
+ # MD 3 a mail destination (Obsolete - use MX)
33
+ #
34
+ # MF 4 a mail forwarder (Obsolete - use MX)
35
+ #
36
+ # CNAME 5 the canonical name for an alias
37
+ #
38
+ # SOA 6 marks the start of a zone of authority
39
+ #
40
+ # MB 7 a mailbox domain name (EXPERIMENTAL)
41
+ #
42
+ # MG 8 a mail group member (EXPERIMENTAL)
43
+ #
44
+ # MR 9 a mail rename domain name (EXPERIMENTAL)
45
+ #
46
+ # NULL 10 a null RR (EXPERIMENTAL)
47
+ #
48
+ # WKS 11 a well known service description
49
+ #
50
+ # PTR 12 a domain name pointer
51
+ #
52
+ # HINFO 13 host information
53
+ #
54
+ # MINFO 14 mailbox or mail list information
55
+ #
56
+ # MX 15 mail exchange
57
+ #
58
+ # TXT 16 text strings
59
+ #++
60
+
61
+ class Type
62
+ Values = {
63
+ 1 => :A,
64
+ 2 => :NS,
65
+ 3 => :MD,
66
+ 4 => :MF,
67
+ 5 => :CNAME,
68
+ 6 => :SOA,
69
+ 7 => :MB,
70
+ 8 => :MG,
71
+ 9 => :MR,
72
+ 10 => :NULL,
73
+ 11 => :WKS,
74
+ 12 => :PTR,
75
+ 13 => :HINFO,
76
+ 14 => :MINFO,
77
+ 15 => :MX,
78
+ 16 => :TXT,
79
+ 17 => :RP,
80
+ 18 => :AFSDB,
81
+ 19 => :X25,
82
+ 20 => :ISDN,
83
+ 21 => :RT,
84
+ 22 => :NSAP,
85
+ 23 => :NSAP_PTR,
86
+ 24 => :SIG,
87
+ 25 => :KEY,
88
+ 26 => :PX,
89
+ 27 => :GPOS,
90
+ 28 => :AAAA,
91
+ 29 => :LOC,
92
+ 30 => :NXT,
93
+ 31 => :EID,
94
+ 32 => :NIMLOC,
95
+ 33 => :SRV,
96
+ 34 => :ATMA,
97
+ 35 => :NAPTR,
98
+ 36 => :KX,
99
+ 37 => :CERT,
100
+ 38 => :A6,
101
+ 39 => :DNAME,
102
+ 40 => :SINK,
103
+ 41 => :OPT,
104
+ 42 => :APL,
105
+ 43 => :DS,
106
+ 44 => :SSHFP,
107
+ 45 => :IPSECKEY,
108
+ 46 => :RRSIG,
109
+ 47 => :NSEC,
110
+ 48 => :DNSKEY,
111
+ 49 => :DHCID,
112
+ 50 => :NSEC3,
113
+ 51 => :NSEC3PARAM,
114
+
115
+ 55 => :HIP,
116
+ 56 => :NINFO,
117
+ 57 => :RKEY,
118
+ 58 => :TALINK,
119
+
120
+ 99 => :SPF,
121
+ 100 => :UINFO,
122
+ 101 => :UID,
123
+ 102 => :GID,
124
+ 103 => :UNSPEC,
125
+
126
+ 249 => :TKEY,
127
+ 250 => :TSIG,
128
+ 251 => :IXFR,
129
+
130
+ 32768 => :TA,
131
+ 32769 => :DLV
132
+ }
133
+
134
+ def self.parse (string)
135
+ string.force_encoding 'BINARY'
136
+
137
+ result = self.new(string.unpack('n').first)
138
+ string[0, self.length] = ''
139
+
140
+ return result
141
+ end
142
+
143
+ def self.length (string=nil)
144
+ 2
145
+ end
146
+
147
+ attr_reader :value
148
+
149
+ def initialize (value)
150
+ if value.is_a? Symbol
151
+ @value = Values.find {|key, val| val == value}.first rescue nil
152
+ elsif value.is_a? Integer
153
+ @value = value
154
+ else
155
+ @value = value.value rescue nil
156
+ end
157
+
158
+ if !self.to_sym
159
+ raise ArgumentError.new('The passed value is not a suitable type.')
160
+ end
161
+ end
162
+
163
+ def pack
164
+ [@value].pack('n')
165
+ end
166
+
167
+ def == (what)
168
+ if what.is_a? Symbol
169
+ self.to_sym == what
170
+ elsif value.is_a? Integer
171
+ @value == what
172
+ else
173
+ @value == what.value rescue false
174
+ end
175
+ end
176
+
177
+ def to_sym
178
+ Values[@value]
179
+ end
180
+
181
+ def to_s
182
+ Values[@value].to_s
183
+ end
184
+ end
185
+
186
+ end