def build_message(self,id, rd, aa, rcode, questions, answers, authorities, additionals): header = Header(id, 0, len(questions), len(answers), len(authorities), len(additionals)) header.qr = 1 header.opcode = 0 header.rd = rd header.ra = 1 header.aa = aa header.rcode = rcode return Message(header, questions=questions, answers=answers, authorities=authorities, additionals=additionals)
def send_response(self, records, authoritative, error=0): """Send a response to some message.""" if not error and len(records) == 0: error = 3 # NXDOMAIN (Domain Name not found) if error != 0: header = Header(self.message.header.ident, 0, 0, 0, 0, 0) header.rcode = error else: header = Header(self.message.header.ident, 0, 0, len(records), 0, 0) header.aa = authoritative # Authoritative Answer header.qr = 1 # Message is Response header.rd = self.message.header.rd # Recursion desired header.ra = 1 # Recursion Available response = Message(header, answers=records) self.sock.sendto(response.to_bytes(), self.address)
def test_flags_aa(self): header = Header(0, 0, 0, 0, 0, 0) header.aa = 1 self.assertEqual(header.flags, 1 << 10)
def test_aa(self): header = Header(0, 0, 0, 0, 0, 0) header.aa = 1 self.assertEqual(header.aa, 1)
def handle_request(self): """ Attempts to answer the received query """ #Check this next to the given algorithm #print("Catalog:",self.catalog.zones) #for zone in self.catalog.zones: # print("Records:",self.catalog.zones[zone].records) if self.message.header.opcode != 0: #Send a not implemented error, we don't need to support those kinds of queries print("[-] - Received a nonstandard query. This is unsupported.") header = Header(ident, 0, 1, 0, 0, 0) header.qr = 1 header.rd = self.message.header.rd header.ra = 1 header.rcode = 4 self.sendResponse(Message(header, self.message.questions, [])) return #print("[*] - Handling request.") if len(self.message.questions) != 1: #Send a format error response print("[-] - Invalid request.") header = Header(ident, 0, 1, 0, 0, 0) header.qr = 1 header.rd = self.message.header.rd header.ra = 1 header.rcode = 1 self.sendResponse(Message(header, self.message.questions, [])) return #print("MSG:",self.message) #print("RECEIVED QUESTION",self.message.questions[0]) hname = str(self.message.questions[0].qname) #print("Solving",hname,type(hname)) ident = self.message.header.ident #print("Checking zone") answer, authority, found = self.check_zone(hname) #print("Wat we in de zone hebben gevonden") #print("ANS:",answer,"AUTH:",authority,"FOUND:",found) #found = False if found: print("Found in zone") header = Header(ident, 0, 1, len(answer), len(authority), 0) header.qr = 1 header.aa = 1 header.rd = self.message.header.rd header.ra = 1 self.sendResponse( Message(header, self.message.questions, answer, authority)) elif self.message.header.rd == 1: h, al, ad = self.resolver.gethostbyname(hname) #Make and send th appropriate response header = Header(ident, 0, 1, len(al) + len(ad), 0, 0) header.qr = 1 header.rd = self.message.header.rd header.ra = 1 aliases = [ ResourceRecord(Name(h), Type.CNAME, Class.IN, self.ttl, RecordData.create(Type.CNAME, Name(alias))) for alias in al ] addresses = [ ResourceRecord(Name(h), Type.A, Class.IN, self.ttl, RecordData.create(Type.A, address)) for address in ad ] self.sendResponse( Message(header, self.message.questions, aliases + addresses)) else: #Send an empty response header = Header(ident, 0, 1, 0, 0, 0) header.qr = 1 header.rd = self.message.header.rd header.ra = 1 header.rcode = 0 self.sendResponse(Message(header, self.message.questions, []))
def run(self): """ Run the handler thread""" msg = Message.from_bytes(self.data) header = msg.header recursion = header.rd != 0 questions = msg.questions answers = [] authorative = [] additional = [] for question in questions: qname = question.qname qtype = question.qtype if question.qclass != Class.IN: pass domains = self.getdomains(str(qname)) for domain in domains: if not self.zone.records.get(domain, False): continue for rr in self.zone.records[domain]: if (rr.type_ == Type.A or rr.type_ == Type.CNAME) and domain == str(qname): answers.append(rr) if rr.type_ == Type.NS: authorative.append(rr) for rec in self.zone.records[str(rr.rdata.nsdname)]: if rec not in additional: if rec.qtype == Type.A: additional.append(rec) if authorative or answers: header_response = Header(9001, 0, 1, len(answers), len(authorative), len(additionals)) header_response.qr = True header_response.opcode(1) header_response.aa(False) header_respones.tc(False) header_response.rd(False) header_response.ra(True) header_response.z(False) header_respones.rcode(False) respons = Message(header_response, [question], answers, authorities, additionals) self.sock.sendto(respons.to_bytes(), self.addr) break if recursion and (qtype == Type.A or qtype == Type.CNAME): answers = [] resolver = Resolver(100, False, 0, True) (hostname, aliaslist, ipaddrlist) = resolver.gethostbyname(question.qname) header_response = Header(9001, 0, 1, len(aliaslist) + len(ipaddrlist), 0, 0) header_response.qr = 1 header_response.opcode = 1 header_response.aa = 0 header_response.tc = 0 header_response.rd = 0 header_response.ra = 1 header_response.rcode = 0 for addr in ipaddrlist: answers.append( ResourceRecord.from_dict({ "name": str(hostname), "type": str(Type.A), "class": str(Class.IN), "ttl": 0, "rdata": { "address": str(addr) } })) for alias in aliaslist: answers.append( ResourceRecord.from_dict({ "name": str(hostname), "type": str(Type.CNAME), "class": str(Class.IN), "ttl": 0, "rdata": { "cname": str(alias) } })) response = Message(header_response, questions, answers) self.sock.sendto(response.to_bytes(), self.addr) break