def lookup_domain(self, domain, nameserver=None, log_prefix=''):
        """Most basic DNS primitive that looks up a domain, waits for a
        second response, then returns all of the results

        :param domain: the domain to lookup
        :param nameserver: the nameserver to use
        :param log_prefix:
        :return:

        Note: if you want to lookup multiple domains you *should not* use
        this function, you should use lookup_domains because this does
        blocking IO to wait for the second response

        """
        if domain not in self.results:
            self.results[domain] = []
        # get the resolver to use
        if nameserver is None:
            logging.debug("Nameserver not specified, using %s" % self.nameservers[0])
            nameserver = self.nameservers[0]
        results = {'domain': domain, 'nameserver': nameserver}
        # construct the socket to use
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(self.timeout)
        # set port number and increment index:
        interrupt = False
        with self.port_lock:
            counter = 1
            while True:
                if counter > 100:
                    logging.warning("Stop trying to get an available port")
                    interrupt = True
                    break
                try:
                    sock.bind(('', self.port))
                    break
                except socket.error:
                    logging.debug("Port {} already in use, try next one".format(self.port))
                    self.port += 1
                    counter += 1
            self.port += 1

        if interrupt:
            sock.close()
            results['error'] = 'Failed to run DNS test'
            self.results[domain].append(results)
            return results

        logging.debug("%sQuerying DNS enteries for "
                      "%s (nameserver: %s)." % (log_prefix, domain, nameserver))

        # construct and send the request
        request = dns.message.make_query(domain,
                                         dns.rdatatype.from_text(self.rtype))
        results['request'] = b64encode(request.to_wire())
        sock.sendto(request.to_wire(), (nameserver, 53))

        # read the first response from the socket
        try:
            response = sock.recvfrom(4096)[0]
            results['response1'] = b64encode(response)
            resp = dns.message.from_wire(response)
            results['response1-ips'] = parse_out_ips(resp)

            # first domain name in response should be the same with query
            # domain name
            for entry in resp.answer:
                if domain.lower() != entry.name.to_text().lower()[:-1]:
                    logging.debug("%sWrong domain name %s for %s!"
                                  % (log_prefix, entry.name.to_text().lower()[:-1], domain))
                    results['response1-domain'] = entry.name.to_text().lower()[:-1]
                break
        except socket.timeout:
            # if we didn't get anything, then set the results to nothing
            logging.debug("%sQuerying DNS enteries for "
                          "%s (nameserver: %s) timed out!" % (log_prefix, domain, nameserver))
            sock.close()
            results['response1'] = None
            self.results[domain].append(results)
            return results

        # if we have made it this far, then wait for the next response
        try:
            response2 = sock.recvfrom(4096)[0]
            results['response2'] = b64encode(response2)
            resp2 = dns.message.from_wire(response2)
            results['response2-ips'] = parse_out_ips(resp2)

            # first domain name in response should be the same with query
            # domain name
            for entry in resp2.answer:
                if domain.lower != entry.name.to_text().lower()[:-1]:
                    logging.debug("%sWrong domain name %s for %s!"
                                  % (log_prefix, entry.name.to_text().lower()[:-1], domain))
                    results['response2-domain'] = entry.name.to_text().lower()[:-1]
                break
        except socket.timeout:
            # no second response
            results['response2'] = None

        sock.close()
        self.results[domain].append(results)
        return results
def lookup_domain ( self , domain , nameserver = None , log_prefix = '' ) : if domain not in self . results : self . results [ domain ] = [ ] if nameserver is None : logging . debug ( "Nameserver not specified, using %s" % self . nameservers [ 0 ] ) nameserver = self . nameservers [ 0 ] results = { 'domain' : domain , 'nameserver' : nameserver } sock = socket . socket ( socket . AF_INET , socket . SOCK_DGRAM ) sock . settimeout ( self . timeout ) interrupt = False with self . port_lock : counter = 1 while True : if counter > 100 : logging . warning ( "Stop trying to get an available port" ) interrupt = True break try : sock . bind ( ( '' , self . port ) ) break except socket . error : logging . debug ( "Port {} already in use, try next one" . format ( self . port ) ) self . port += 1 counter += 1 self . port += 1 if interrupt : sock . close ( ) results [ 'error' ] = 'Failed to run DNS test' self . results [ domain ] . append ( results ) return results logging . debug ( "%sQuerying DNS enteries for " "%s (nameserver: %s)." % ( log_prefix , domain , nameserver ) ) request = dns . message . make_query ( domain , dns . rdatatype . from_text ( self . rtype ) ) results [ 'request' ] = b64encode ( request . to_wire ( ) ) sock . sendto ( request . to_wire ( ) , ( nameserver , 53 ) ) try : response = sock . recvfrom ( 4096 ) [ 0 ] results [ 'response1' ] = b64encode ( response ) resp = dns . message . from_wire ( response ) results [ 'response1-ips' ] = parse_out_ips ( resp ) for entry in resp . answer : if domain . lower ( ) != entry . name . to_text ( ) . lower ( ) [ : - 1 ] : logging . debug ( "%sWrong domain name %s for %s!" % ( log_prefix , entry . name . to_text ( ) . lower ( ) [ : - 1 ] , domain ) ) results [ 'response1-domain' ] = entry . name . to_text ( ) . lower ( ) [ : - 1 ] break except socket . timeout : logging . debug ( "%sQuerying DNS enteries for " "%s (nameserver: %s) timed out!" % ( log_prefix , domain , nameserver ) ) sock . close ( ) results [ 'response1' ] = None self . results [ domain ] . append ( results ) return results try : response2 = sock . recvfrom ( 4096 ) [ 0 ] results [ 'response2' ] = b64encode ( response2 ) resp2 = dns . message . from_wire ( response2 ) results [ 'response2-ips' ] = parse_out_ips ( resp2 ) for entry in resp2 . answer : if domain . lower != entry . name . to_text ( ) . lower ( ) [ : - 1 ] : logging . debug ( "%sWrong domain name %s for %s!" % ( log_prefix , entry . name . to_text ( ) . lower ( ) [ : - 1 ] , domain ) ) results [ 'response2-domain' ] = entry . name . to_text ( ) . lower ( ) [ : - 1 ] break except socket . timeout : results [ 'response2' ] = None sock . close ( ) self . results [ domain ] . append ( results ) return results
Most basic DNS primitive that looks up a domain, waits for a
        second response, then returns all of the results

        :param domain: the domain to lookup
        :param nameserver: the nameserver to use
        :param log_prefix:
        :return:

        Note: if you want to lookup multiple domains you *should not* use
        this function, you should use lookup_domains because this does
        blocking IO to wait for the second response