From 61c1214dce59fd19e86bd9362207fb5e658d9a88 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Mon, 30 May 2016 15:21:17 +0200 Subject: Fixes for resolver & server; tests for resolver; cloogle zonefile --- project2/proj2_s4498062/dns/cache.py | 7 +++--- project2/proj2_s4498062/dns/resolver.py | 42 +++++++-------------------------- project2/proj2_s4498062/dns/resource.py | 4 ++-- project2/proj2_s4498062/dns/server.py | 18 ++++++++++---- 4 files changed, 29 insertions(+), 42 deletions(-) (limited to 'project2/proj2_s4498062/dns') diff --git a/project2/proj2_s4498062/dns/cache.py b/project2/proj2_s4498062/dns/cache.py index 9cde66f..a8b62be 100644 --- a/project2/proj2_s4498062/dns/cache.py +++ b/project2/proj2_s4498062/dns/cache.py @@ -53,7 +53,7 @@ class RecordCache(object): FILE = '.dns.cache' - def __init__(self): + def __init__(self, ttl): """ Initialize the RecordCache Args: @@ -61,15 +61,16 @@ class RecordCache(object): """ self.records = [] self.read_cache_file() + self.ttl = ttl def __del__(self): self.write_cache_file() def remove_old(self): """Remove entries for which the TTL has expired""" - now = int(time.clock()) + now = int(time.time()) for record in reversed(self.records): - if record.ttl + record.timestamp < now: + if min(self.ttl, record.ttl) + record.timestamp < now: self.records.remove(record) def lookup(self, dname, type_, class_): diff --git a/project2/proj2_s4498062/dns/resolver.py b/project2/proj2_s4498062/dns/resolver.py index 2c22adb..4c09681 100644 --- a/project2/proj2_s4498062/dns/resolver.py +++ b/project2/proj2_s4498062/dns/resolver.py @@ -48,7 +48,7 @@ class Resolver(object): self.timeout = timeout if self.caching: - self.cache = RecordCache() + self.cache = RecordCache(ttl) def do_query(self, hint, hostname, type_, class_=Class.IN, caching=True): """Do a query to a hint""" @@ -98,9 +98,6 @@ class Resolver(object): Returns: (str, [str], [str]): (hostname, aliaslist, ipaddrlist) """ - domains = hostname.split('.') - hints = self.ROOT_SERVERS - if self.caching: addrs = self.cache.lookup(hostname, Type.A, Class.IN) cnames = self.cache.lookup(hostname, Type.CNAME, Class.IN) @@ -109,66 +106,45 @@ class Resolver(object): [r.rdata.data for r in cnames], \ [r.rdata.data for r in addrs] for cname in cnames: - print 'trying', cname.rdata.data cname, aliases, addrs = self.gethostbyname(cname.rdata.data) if addrs != []: return str(cname), aliases, addrs - if domains == []: + if hostname == '': return hostname, [], [] - domain = domains.pop(-1) + hints = self.ROOT_SERVERS[:] aliases = [] while hints != []: - hints, info = self.do_query_to_multiple(hints, domain, Type.A) + hints, info = self.do_query_to_multiple(hints, hostname, Type.A) aliases += [ r.rdata.data for r in info - if r.match(type_=Type.CNAME, class_=Class.IN, name=domain)] + if r.match(type_=Type.CNAME, class_=Class.IN, name=hostname)] # Case 1: answer ips = [ r.rdata.data for r in info - if r.match(type_=Type.A, class_=Class.IN, name=domain)] + if r.match(type_=Type.A, class_=Class.IN, name=hostname)] if ips != []: return hostname, aliases, ips - # Case 2: name servers for this domain + # Case 2: name servers auths = [ r.rdata.data for r in info - if r.match(type_=Type.NS, class_=Class.IN, name=domain)] + if r.match(type_=Type.NS, class_=Class.IN)] ips = [ add.rdata.data for ns in auths for add in info if add.match(name=ns, type_=Type.A)] if ips != []: hints += ips - if domain != hostname: - domain = domains.pop(-1) + '.' + domain continue if auths != []: auths = [h for a in auths for h in self.gethostbyname(a)[2]] hints += auths - if domain != hostname: - domain = domains.pop(-1) + '.' + domain - continue - - # Case 3: name servers for the same domain - parent = '.'.join(domain.split('.')[1:]) - auths = [ - r.rdata.data for r in info - if r.match(type_=Type.NS, class_=Class.IN, name=parent)] - ips = [ - add.rdata.data for ns in auths for add in info - if add.match(name=ns, type_=Type.A)] - if ips != []: - hints += ips - continue - if auths != []: - auths = [h for r in auths for h in self.gethostbyname(r)[2]] - hints += auths continue - # Case 4: aliases + # Case 3: aliases for alias in aliases: _, extra_aliases, alias_addresses = self.gethostbyname(alias) if alias_addresses != []: diff --git a/project2/proj2_s4498062/dns/resource.py b/project2/proj2_s4498062/dns/resource.py index b1c8ae4..e552c22 100644 --- a/project2/proj2_s4498062/dns/resource.py +++ b/project2/proj2_s4498062/dns/resource.py @@ -14,7 +14,7 @@ from dns.types import Type class ResourceRecord(object): """ DNS resource record """ - def __init__(self, name, type_, class_, ttl, rdata, timestamp=time.time()): + def __init__(self, name, type_, class_, ttl, rdata, timestamp=None): """ Create a new resource record Args: @@ -28,7 +28,7 @@ class ResourceRecord(object): self.class_ = class_ self.ttl = ttl self.rdata = rdata - self.timestamp = timestamp + self.timestamp = int(timestamp or time.time()) def match(self, name=None, type_=None, class_=None, ttl=None): """Check if the record matches properties""" diff --git a/project2/proj2_s4498062/dns/server.py b/project2/proj2_s4498062/dns/server.py index f830651..10cad8b 100644 --- a/project2/proj2_s4498062/dns/server.py +++ b/project2/proj2_s4498062/dns/server.py @@ -12,7 +12,8 @@ from dns.classes import Class from dns.types import Type from dns.message import Header, Message from dns.resolver import Resolver -from dns.resource import ResourceRecord, ARecordData, CNAMERecordData +from dns.resource import \ + ResourceRecord, ARecordData, NSRecordData, CNAMERecordData class RequestHandler(Thread): @@ -112,12 +113,21 @@ class Server(object): ttl, class_ = 3600000, Class.IN for match in re.finditer(rgx.ZONE_LINE_DOMAIN, zone, re.MULTILINE): match = match.groups() - name = match[0] - ttl = int(match[1] or match[4] or ttl) + name = match[0][:-1] + ttl = int(match[1] or match[4] or ttl * 1000) / 1000 class_ = Class.from_string( match[2] or match[3] or Class.to_string(class_)) type_ = Type.from_string(match[5]) data = match[6] - record = ResourceRecord(name, type_, class_, ttl, data) + if type_ == Type.A: + cls = ARecordData + elif type_ == Type.NS: + cls = NSRecordData + elif type_ == Type.CNAME: + cls = CNAMERecordData + else: + continue + + record = ResourceRecord(name, type_, class_, ttl, cls(data)) self.zone.append(record) -- cgit v1.2.3