Class: RubyDNS::Server
- Inherits:
-
Object
- Object
- RubyDNS::Server
- Includes:
- Celluloid::IO
- Defined in:
- lib/rubydns/server.rb
Direct Known Subclasses
Constant Summary collapse
- DEFAULT_INTERFACES =
The default server interfaces
[[:udp, "0.0.0.0", 53], [:tcp, "0.0.0.0", 53]]
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
Instance Method Summary collapse
-
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
-
#initialize(options = {}) ⇒ Server
constructor
Instantiate a server with a block.
-
#process(name, resource_class, transaction) ⇒ Object
Give a name and a record type, try to match a rule and use it for processing the given arguments.
-
#process_query(query, options = {}, &block) ⇒ Object
Process an incoming DNS message.
-
#run ⇒ Object
By default the server runs on port 53, both TCP and UDP, which is usually a priviledged port and requires root access to bind.
- #shutdown ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ Server
Instantiate a server with a block
server = Server.new do match(/server.mydomain.com/, IN::A) do |transaction| transaction.respond!("1.2.3.4") end end
55 56 57 58 59 60 |
# File 'lib/rubydns/server.rb', line 55 def initialize( = {}) @handlers = [] @logger = [:logger] || Celluloid.logger @interfaces = [:listen] || DEFAULT_INTERFACES end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
62 63 64 |
# File 'lib/rubydns/server.rb', line 62 def logger @logger end |
Instance Method Details
#fire(event_name) ⇒ Object
Fire the named event as part of running the server.
65 66 |
# File 'lib/rubydns/server.rb', line 65 def fire(event_name) end |
#process(name, resource_class, transaction) ⇒ Object
Give a name and a record type, try to match a rule and use it for processing the given arguments.
73 74 75 |
# File 'lib/rubydns/server.rb', line 73 def process(name, resource_class, transaction) raise NotImplementedError.new end |
#process_query(query, options = {}, &block) ⇒ Object
Process an incoming DNS message. Returns a serialized message to be sent back to the client.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/rubydns/server.rb', line 78 def process_query(query, = {}, &block) start_time = Time.now # Setup response response = Resolv::DNS::Message::new(query.id) response.qr = 1 # 0 = Query, 1 = Response response.opcode = query.opcode # Type of Query; copy from query response.aa = 1 # Is this an authoritative response: 0 = No, 1 = Yes response.rd = query.rd # Is Recursion Desired, copied from query response.ra = 0 # Does name server support recursion: 0 = No, 1 = Yes response.rcode = 0 # Response code: 0 = No errors transaction = nil begin query.question.each do |question, resource_class| @logger.debug {"<#{query.id}> Processing question #{question} #{resource_class}..."} transaction = Transaction.new(self, query, question, resource_class, response, ) transaction.process end rescue Celluloid::ResumableError raise rescue StandardError => error @logger.error "<#{query.id}> Exception thrown while processing #{transaction}!" RubyDNS.log_exception(@logger, error) response.rcode = Resolv::DNS::RCode::ServFail end end_time = Time.now @logger.debug {"<#{query.id}> Time to process request: #{end_time - start_time}s"} return response end |
#run ⇒ Object
By default the server runs on port 53, both TCP and UDP, which is usually a priviledged port and requires root access to bind. You can change this by specifying options[:listen]
which should contain an array of [protocol, interface address, port]
specifications.
INTERFACES = [[:udp, "0.0.0.0", 5300]] RubyDNS::run_server(:listen => INTERFACES) do ... end
You can specify already connected sockets if need be:
socket = UDPSocket.new; socket.bind("0.0.0.0", 53) Process::Sys.setuid(server_uid) INTERFACES = [socket]
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/rubydns/server.rb', line 129 def run @logger.info "Starting RubyDNS server (v#{RubyDNS::VERSION})..." fire(:setup) # Setup server sockets @interfaces.each do |spec| if spec.is_a?(BasicSocket) spec.do_not_reverse_lookup protocol = spec.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).unpack("i")[0] ip = spec.local_address.ip_address port = spec.local_address.ip_port case protocol when Socket::SOCK_DGRAM @logger.info "<> Attaching to pre-existing UDP socket #{ip}:#{port}" link UDPSocketHandler.new(self, UDPSocketWrapper.new(spec)) when Socket::SOCK_STREAM @logger.info "<> Attaching to pre-existing TCP socket #{ip}:#{port}" link TCPSocketHandler.new(self, TCPServerWrapper.new(spec)) else raise ArgumentError.new("Unknown socket protocol: #{protocol}") end elsif spec[0] == :udp @logger.info "<> Listening on #{spec.join(':')}" link UDPHandler.new(self, spec[1], spec[2]) elsif spec[0] == :tcp @logger.info "<> Listening on #{spec.join(':')}" link TCPHandler.new(self, spec[1], spec[2]) else raise ArgumentError.new("Invalid connection specification: #{spec.inspect}") end end fire(:start) end |
#shutdown ⇒ Object
68 69 70 |
# File 'lib/rubydns/server.rb', line 68 def shutdown fire(:stop) end |