diff options
Diffstat (limited to 'project2/proj2_s4498062/dns/resolver.py')
-rw-r--r-- | project2/proj2_s4498062/dns/resolver.py | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/project2/proj2_s4498062/dns/resolver.py b/project2/proj2_s4498062/dns/resolver.py index ffb7c16..fe46492 100644 --- a/project2/proj2_s4498062/dns/resolver.py +++ b/project2/proj2_s4498062/dns/resolver.py @@ -13,7 +13,7 @@ import socket from dns.classes import Class from dns.types import Type -import dns.cache +from dns.cache import RecordCache from dns.message import Message, Question, Header import dns.rcodes @@ -48,8 +48,16 @@ class Resolver(object): self.ttl = ttl self.timeout = timeout - def do_query(self, hint, hostname, type_, class_=Class.IN): + if self.caching: + self.cache = RecordCache() + + def do_query(self, hint, hostname, type_, class_=Class.IN, caching=True): """Do a query to a hint""" + if self.caching and caching: + records = self.cache.lookup(hostname, type_, class_) + if records != []: + return records + ident = randint(0, 65535) header = Header(ident, 0, 1, 0, 0, 0) header.qr = 0 @@ -65,19 +73,22 @@ class Resolver(object): data = sock.recv(512) resp = Message.from_bytes(data) if resp.header.ident == ident: - return resp + if self.caching and caching: + self.cache.add_records_from(resp) + return resp.answers + resp.authorities + resp.additionals except socket.timeout: pass - return None + return [] - def do_query_to_multiple(self, hints, hostname, type_, class_=Class.IN): + def do_query_to_multiple( + self, hints, hostname, type_, class_=Class.IN, caching=True): """Do a query to multiple hints, return the remaining hints""" while hints != []: hint = hints.pop() - response = self.do_query(hint, hostname, type_, class_) + response = self.do_query(hint, hostname, type_, class_, caching) if response is not None: return hints, response - return [], None + return [], [] def gethostbyname(self, hostname): """ Translate a host name to IPv4 address. @@ -101,11 +112,7 @@ class Resolver(object): domain = domains.pop(-1) aliases = [] while hints != []: - hints, resp = self.do_query_to_multiple(hints, domain, Type.A) - if resp == None: - continue - - info = resp.answers + resp.authorities + resp.additionals + hints, info = self.do_query_to_multiple(hints, domain, Type.A) aliases += [ r.rdata.data for r in info @@ -117,7 +124,8 @@ class Resolver(object): if r.match(type_=Type.A, class_=Class.IN, name=domain)] if ips != []: return hostname, aliases, ips - # Case 2: name servers + + # Case 2: name servers for this domain auths = [ r.rdata.data for r in info if r.match(type_=Type.NS, class_=Class.IN, name=domain)] @@ -135,21 +143,23 @@ class Resolver(object): if domain != hostname: domain = domains.pop(-1) + '.' + domain continue - # Case 3: delegation to other name servers + + # Case 3: name servers for the same domain parent = '.'.join(domain.split('.')[1:]) - refs = [ + 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 refs for add in info + 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 refs != []: - refs = [h for r in refs for h in self.gethostbyname(r)[2]] - hints += refs + if auths != []: + auths = [h for r in auths for h in self.gethostbyname(r)[2]] + hints += auths continue + # Case 4: aliases for alias in aliases: _, extra_aliases, alias_addresses = self.gethostbyname(alias) |