Skip to content

Commit 14f2b67

Browse files
Samuel WilliamsSamuel Williams
authored andcommitted
Added support for appending dependent queries. Useful for returning CNAME and A record pairs.
Added an example showing how to implement SOA records.
1 parent 144fe7f commit 14f2b67

File tree

4 files changed

+108
-4
lines changed

4 files changed

+108
-4
lines changed

lib/rubydns/server.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ def process(name, record_type, *args)
9696
# Match failed against record_type?
9797
case pattern[1]
9898
when String
99-
next if pattern[1] != record_type.upcase
99+
next if pattern[1] != record_type
100100
@logger.debug "Resource type #{record_type} matched"
101101
when Array
102-
next if pattern[1].include?(record_type.upcase)
102+
next if pattern[1].include?(record_type)
103103
@logger.debug "Resource type #{record_type} matched #{pattern[1].inspect}"
104104
end
105105

@@ -154,7 +154,7 @@ def receive_data(data)
154154
transaction = Transaction.new(self, query, question, resource_class, answer)
155155

156156
begin
157-
process(transaction.name, transaction.record_type, transaction)
157+
transaction.process
158158
rescue
159159
@logger.error "Exception thrown while processing #{transaction}!"
160160
@logger.error "#{$!.class}: #{$!.message}"

lib/rubydns/transaction.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,26 @@
1515

1616
module RubyDNS
1717

18+
# Turn a symbol or string name into a resource class. For example,
19+
# convert <tt>:A</tt> into <tt>Resolv::DNS::Resource::IN::A</tt>
20+
def self.lookup_resource_class(klass)
21+
return nil if klass == nil
22+
23+
if Symbol === klass
24+
klass = klass.to_s
25+
end
26+
27+
if String === klass
28+
if Resolv::DNS::Resource.const_defined?(klass)
29+
return Resolv::DNS::Resource.const_get(klass)
30+
elsif Resolv::DNS::Resource::IN.const_defined?(klass)
31+
return Resolv::DNS::Resource::IN.const_get(klass)
32+
end
33+
end
34+
35+
return klass
36+
end
37+
1838
# This class provides all details of a single DNS question and answer. This
1939
# is used by the DSL to provide DNS related functionality.
2040
class Transaction
@@ -56,6 +76,16 @@ def to_s
5676
"#{name} #{record_type}"
5777
end
5878

79+
# Run a new query through the rules with the given name and resource type. The
80+
# results of this query are appended to the current transactions <tt>answer</tt>.
81+
def append_query!(name, resource_type = nil)
82+
Transaction.new(@server, @query, name, RubyDNS.lookup_resource_class(resource_type) || @resource_class, @answer).process
83+
end
84+
85+
def process
86+
@server.process(name, record_type, self)
87+
end
88+
5989
# Use the given resolver to respond to the question. This will <tt>query</tt>
6090
# the resolver and <tt>merge!</tt> the answer if one is received. If recursion is
6191
# not requested, the result is <tt>failure!(:Refused)</tt>. If the resolver does

lib/rubydns/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module RubyDNS
1717
module VERSION #:nodoc:
1818
MAJOR = 0
1919
MINOR = 1
20-
TINY = 6
20+
TINY = 7
2121

2222
STRING = [MAJOR, MINOR, TINY].join('.')
2323
end

test/soa_example1.rb

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env ruby
2+
3+
# Copyright (c) 2009 Samuel Williams. Released under the GNU GPLv3.
4+
#
5+
# This program is free software: you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful,
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
# GNU General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
18+
require 'rubygems'
19+
require 'rubydns'
20+
21+
$R = Resolv::DNS.new
22+
Name = Resolv::DNS::Name
23+
24+
RubyDNS::run_server(:listen => [[:udp, "0.0.0.0", 5300]]) do
25+
# SOA Record
26+
# dig @localhost -p 5300 SOA mydomain.org
27+
match("mydomain.org", :SOA) do |transaction|
28+
#
29+
# For more details about these headers please see:
30+
# http://www.ripe.net/ripe/docs/ripe-203.html
31+
#
32+
33+
transaction.respond!(
34+
Name.create("ns.mydomain.org."), # Master Name
35+
Name.create("admin.mydomain.org."), # Responsible Name
36+
File.mtime(__FILE__).to_i, # Serial Number
37+
1200, # Refresh Time
38+
900, # Retry Time
39+
3600000, # Maximum TTL / Expiry Time
40+
172800 # Minimum TTL
41+
)
42+
end
43+
44+
# Default NS record
45+
# dig @localhost -p 5300 NS
46+
match("", :NS) do |transaction|
47+
transaction.respond!(Name.create("ns.mydomain.org."))
48+
end
49+
50+
# For this exact address record, return an IP address
51+
# dig @localhost -p 5300 CNAME bob.mydomain.org
52+
match(/([^.]+).mydomain.org/, :CNAME) do |match_data, transaction|
53+
transaction.respond!(Name.create("www.mydomain.org"))
54+
transaction.append_query!("www.mydomain.org", :A)
55+
end
56+
57+
match("80.0.0.10.in-addr.arpa", :PTR) do |transaction|
58+
transaction.respond!(Name.create("www.mydomain.org."))
59+
end
60+
61+
match("www.mydomain.org", :A) do |transaction|
62+
transaction.respond!("10.0.0.80", :record_type => :A)
63+
end
64+
65+
match("ns.mydomain.org", :A) do |transaction|
66+
transaction.respond!("10.0.0.10")
67+
end
68+
69+
# Default DNS handler
70+
otherwise do |transaction|
71+
# Non-Existant Domain
72+
transaction.failure!(:NXDomain)
73+
end
74+
end

0 commit comments

Comments
 (0)