onedns/onedns/resolver.py

111 lines
3.3 KiB
Python
Raw Permalink Normal View History

import time
import threading
import dnslib
from dnslib import server
from wrapt import synchronized
from onedns import zone
2016-08-12 18:12:11 +03:00
from onedns import utils
from onedns import exception
from onedns.logger import log
2016-08-12 18:12:11 +03:00
class DynamicResolver(server.BaseResolver):
"""
Dynamic In-Memory DNS Resolver
"""
_lock = threading.RLock()
def __init__(self, domain):
"""
Initialise resolver from zone list
Stores RRs as a list of (label, type, rr) tuples
"""
self.domain = domain
self.zone = zone.Zone(domain)
self._tcp_server = None
self._udp_server = None
@synchronized(_lock)
def resolve(self, request, handler):
"""
Respond to DNS request - parameters are request packet & handler.
Method is expected to return DNS response
"""
reply = request.reply()
qname = request.q.qname
qtype = request.q.qtype
try:
if qtype == dnslib.QTYPE.A:
forward = self.zone.get_forward(qname)
reply.add_answer(forward)
elif qtype == dnslib.QTYPE.AAAA:
reply.header.rcode = 0
elif qtype == dnslib.QTYPE.PTR:
reverse = self.zone.get_reverse(
utils.reverse_to_ip(qname.idna()))
reply.add_answer(reverse)
forward = self.zone.get_forward(str(reverse.rdata))
if forward:
reply.add_ar(forward)
except exception.RecordDoesNotExist:
reply.header.rcode = dnslib.RCODE.NXDOMAIN
return reply
@synchronized(_lock)
def clear(self):
self.zone.clear()
@synchronized(_lock)
def load(self, zone):
self.zone = zone
@synchronized(_lock)
def add_host(self, name, ip, zone=None):
z = zone or self.zone
z.add_host(name, ip)
@synchronized(_lock)
def remove_host(self, name, ip, zone=None):
z = zone or self.zone
z.remove_host(name, ip)
def start(self, dns_address='0.0.0.0', dns_port=53,
api_address='127.0.0.1', api_port=8000, tcp=True, udplen=0,
log_components="request,reply,truncated,error",
log_prefix=False):
logger = server.DNSLogger(log_components, log_prefix)
log.info("Starting OneDNS (%s:%d) [%s]" %
(dns_address or "*", dns_port, "UDP/TCP" if tcp else "UDP"))
server.DNSHandler.udplen = udplen
self._udp_server = server.DNSServer(self, port=dns_port,
address=dns_address, logger=logger)
self._udp_server.start_thread()
if tcp:
self._tcp_server = server.DNSServer(self, port=dns_port,
address=dns_address, tcp=True,
logger=logger)
self._tcp_server.start_thread()
def close(self):
for srv in [self._tcp_server, self._udp_server]:
if srv:
srv.stop()
srv.server.socket.close()
def daemon(self, *args, **kwargs):
test = kwargs.pop('test', False)
if self._udp_server is None or not self._udp_server.isAlive():
self.start(*args, **kwargs)
while self._udp_server.isAlive():
time.sleep(1)
if test:
break