【问题标题】:How does Twisted Names build search results for query?Twisted Names 如何为查询构建搜索结果?
【发布时间】:2012-09-16 22:33:12
【问题描述】:

具体来说,在 authority.FileAuthority 类下的 _lookup 调用中会发生什么,它是如何返回结果的?这是未记录的名称领域之一。

【问题讨论】:

    标签: python dns twisted


    【解决方案1】:

    以下是 Twisted Names 11.1 的 authority.py 文件中 FileAuthority._lookup 调用的注释版本。该方法负责同步搜索已从 BIND zonefiles、Python zonefiles 等索引的 DNS 信息。

    def _lookup(self, name, cls, type, timeout = None):
        """Return a list of results.
        name: Queried host name.
        cls: An enum of the query class. See dns.py:
    
            IN, CS, CH, HS = range(1, 5)
    
            QUERY_CLASSES = {
                IN: 'IN',
                CS: 'CS',
                CH: 'CH',
                HS: 'HS',
                ANY: 'ANY'
            }
    
        type: The type of record to search for (or ANY/255 for any and all). 
              See dns.py:
    
            (A, NS, MD, MF, CNAME, SOA, MB, MG, MR, NULL, WKS, PTR, HINFO, MINFO, MX, TXT,
             RP, AFSDB) = range(1, 19)
            AAAA = 28
            SRV = 33
            NAPTR = 35
            A6 = 38
            DNAME = 39
            SPF = 99
    
            QUERY_TYPES = {
                A: 'A',
                NS: 'NS',
                MD: 'MD',
                MF: 'MF',
                CNAME: 'CNAME',
                SOA: 'SOA',
                MB: 'MB',
                MG: 'MG',
                MR: 'MR',
                NULL: 'NULL',
                WKS: 'WKS',
                PTR: 'PTR',
                HINFO: 'HINFO',
                MINFO: 'MINFO',
                MX: 'MX',
                TXT: 'TXT',
                RP: 'RP',
                AFSDB: 'AFSDB',
    
                # 19 through 27?  Eh, I'll get to 'em.
    
                AAAA: 'AAAA',
                SRV: 'SRV',
                NAPTR: 'NAPTR',
                A6: 'A6',
                DNAME: 'DNAME',
                SPF: 'SPF'
            }
    
        timeout: The retention time for this record, in seconds.
        """
        cnames = []
        results = []
        authority = []
        additional = []
        default_ttl = max(self.soa[1].minimum, self.soa[1].expire)
    
        # Do records search. Get a list of classes like Record_A and Record_MX 
        # back. These are defined in dns.py .
        domain_records = self.records.get(name.lower())
    
        # Structure the results so as to present them the way that DNS records 
        # usually come back.
    
        if domain_records:
            # Loop through all of the results.
            for record in domain_records:
                if record.ttl is not None:
                    ttl = record.ttl
                else:
                    ttl = default_ttl
    
                # If we're looking at a [subdomain?] NS record, note it.
                if record.TYPE == dns.NS and name.lower() != self.soa[0].lower():
                    # NS record belong to a child zone: this is a referral.  As
                    # NS records are authoritative in the child zone, ours here
                    # are not.  RFC 2181, section 6.1.
                    authority.append(
                        dns.RRHeader(name, record.TYPE, dns.IN, ttl, record, auth=False)
                    )
    
                # Was the record what was requested, or did we want everything?
                elif record.TYPE == type or type == dns.ALL_RECORDS:
                    results.append(
                        dns.RRHeader(name, record.TYPE, dns.IN, ttl, record, auth=True)
                    )
    
                # If we're looking at a CNAME record, note it.
                if record.TYPE == dns.CNAME:
                    cnames.append(
                        dns.RRHeader(name, record.TYPE, dns.IN, ttl, record, auth=True)
                    )
    
            # If no requested records were found, use the CNAME records (if any).
            if not results:
                results = cnames
    
            # Go through any NS, CNAME, or MX records found, and find the IPs 
            # for those hosts.
            #
            # NOTE: The "additional" list doesn't appear to be populated.
            for record in results + authority:
                section = {dns.NS: additional, dns.CNAME: results, dns.MX: additional}.get(record.type)
                if section is not None:
                    n = str(record.payload.name)
                    for rec in self.records.get(n.lower(), ()):
                        if rec.TYPE == dns.A:
                            section.append(
                                dns.RRHeader(n, dns.A, dns.IN, rec.ttl or default_ttl, rec, auth=True)
                            )
    
            # Not found. Return an SOA record with the name that was requested 
            # (the normal response that you'll see at the console).
            if not results and not authority:
                # Empty response. Include SOA record to allow clients to cache
                # this response.  RFC 1034, sections 3.7 and 4.3.4, and RFC 2181
                # section 7.1.
                authority.append(
                    dns.RRHeader(self.soa[0], dns.SOA, dns.IN, ttl, self.soa[1], auth=True)
                    )
    
            # We return a tuple of individual result lists. Each of the records 
            # is an instance of RRHeader, which wraps the Record_* classes in 
            # dns.py for returning as a result (Resource Record). 
            #
            # The first item in the tuple refers to the "ANSWER SECTION" in the 
            # DiG output, and the third item refers to the "ADDITIONAL 
            # SECTION". As "authority" was an empty list in the example, no 
            # output relates to it. It will have NS records if any are present, 
            # or contain an SOA record for what was requested if nothing was 
            # found.
            # 
            #;; QUESTION SECTION:
            #;example-domain.com.            IN      ANY
            #
            #;; ANSWER SECTION:
            #example-domain.com.     3600    IN      SOA     ns1.example-domain.com. root.example-domain.com. 2003010601 3600 3600 3600 3600
            #example-domain.com.     3600    IN      A       127.9.9.9
            #example-domain.com.     3600    IN      NS      ns1.example-domain.com.
            #example-domain.com.     3600    IN      MX      0 mail.example-domain.com.
            #
            #;; ADDITIONAL SECTION:
            #mail.example-domain.com. 3600   IN      A       123.0.16.43
    
            return defer.succeed((results, authority, additional))
        else:
            if name.lower().endswith(self.soa[0].lower()):
                # We are the authority and we didn't find it.  Goodbye.
                return defer.fail(failure.Failure(dns.AuthoritativeDomainError(name)))
            return defer.fail(failure.Failure(dns.DomainError(name)))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多