Пример #1
0
    def read_cache_file(self, cache_file=Consts.CACHE_FILE):
        """ Read the cache file from disk """
        #Empty current cache
        self.records = []

        #Load from file
        try:
            with open(cache_file + ".timestamp") as infile:
                self.lastCleanup = int(infile.readline())

            with open(cache_file, "r") as infile:
                curTime = int(time.time())
                dcts = json.load(infile)
                self.records = [ResourceRecord.from_dict(dct) for dct in dcts]
                #Don't add the entries whose TTL is expired and update the ttls
                self.cleanup()

        except (ValueError, IOError, FileNotFoundError) as e:
            print("An error has occured while loading cache from disk: " +
                  str(e))

            with open(cache_file, 'w') as outfile:
                json.dump([], outfile, indent=2)

            with open(cache_file + ".timestamp", 'w') as outfile:
                outfile.write(str(self.lastCleanup))

            if isinstance(e, FileNotFoundError):
                print("Missing files were created")
            self.records = []
Пример #2
0
 def read_cache_file(self):
     """Read the cache file from disk"""
     dcts = []
     try:
         with open("cache", "r") as file_:
             dcts = json.load(file_)
     except:
         print("could not read cache")
     self.records = [ResourceRecord.from_dict(dct) for dct in dcts]
Пример #3
0
    def read_master_file(self, filename):
        """Read the zone from a master file

        See section 5 of RFC 1035.

        Args:
            filename (str): the filename of the master file
        """
        typeData = {"NS": "nsdname", "A": "address", "CNAME": "cname"}
        try:
            with open(filename, "r") as file_:
                for l in file_:
                    rr = l.split(";")[0]
                    if not rr:
                        continue
                    entries = re.split("[\\n]?[\ +]*[\\t+]*", rr)[:-1]
                    name = entries[0]
                    ttl = int(entries[1])
                    type_ = entries[2]
                    address = entries[3]

                    if type_ not in typeData:
                        continue

                    rr = {
                        "type": type_,
                        "name": name,
                        "class": "IN",
                        "ttl": ttl,
                        "rdata": {
                            typeData[type_]: address
                        }
                    }
                    if name not in self.records:
                        self.records[name] = [ResourceRecord.from_dict(rr)]
                    else:
                        self.records[name].append(ResourceRecord.from_dict(rr))
        except:
            print("could not read zone file")
        return self
Пример #4
0
    def lookup(self, dname, type_, class_):
        """Lookup resource records in cache

        Lookup for the resource records for a domain name with a specific type
        and class.

        Args:
            dname (str): domain name
            type_ (Type): type
            class_ (Class): class
        """
        dname = Name(dname)
        rrs = [
            ResourceRecord.from_dict(r) for r in self.records
            if (time.time() - r["timestamp"]) < r["ttl"]
        ]
        rs = [
            r for r in rrs
            if r.name == dname and r.class_ == class_ and r.type_ == type_
        ]
        return rs
Пример #5
0
    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