|
@ -25,6 +25,7 @@ import time |
|
|
import os |
|
|
import os |
|
|
import socket |
|
|
import socket |
|
|
import struct |
|
|
import struct |
|
|
|
|
|
import re |
|
|
import logging |
|
|
import logging |
|
|
import common |
|
|
import common |
|
|
import lru_cache |
|
|
import lru_cache |
|
@ -33,6 +34,8 @@ import eventloop |
|
|
|
|
|
|
|
|
CACHE_SWEEP_INTERVAL = 30 |
|
|
CACHE_SWEEP_INTERVAL = 30 |
|
|
|
|
|
|
|
|
|
|
|
VALID_HOSTNAME = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) |
|
|
|
|
|
|
|
|
common.patch_socket() |
|
|
common.patch_socket() |
|
|
|
|
|
|
|
|
# rfc1035 |
|
|
# rfc1035 |
|
@ -230,11 +233,19 @@ def is_ip(address): |
|
|
try: |
|
|
try: |
|
|
socket.inet_pton(family, address) |
|
|
socket.inet_pton(family, address) |
|
|
return True |
|
|
return True |
|
|
except (OSError, IOError): |
|
|
except (TypeError, OSError, IOError): |
|
|
pass |
|
|
pass |
|
|
return False |
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_valid_hostname(hostname): |
|
|
|
|
|
if len(hostname) > 255: |
|
|
|
|
|
return False |
|
|
|
|
|
if hostname[-1] == ".": |
|
|
|
|
|
hostname = hostname[:-1] |
|
|
|
|
|
return all(VALID_HOSTNAME.match(x) for x in hostname.split(".")) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DNSResponse(object): |
|
|
class DNSResponse(object): |
|
|
def __init__(self): |
|
|
def __init__(self): |
|
|
self.hostname = None |
|
|
self.hostname = None |
|
@ -411,6 +422,9 @@ class DNSResolver(object): |
|
|
ip = self._cache[hostname] |
|
|
ip = self._cache[hostname] |
|
|
callback((hostname, ip), None) |
|
|
callback((hostname, ip), None) |
|
|
else: |
|
|
else: |
|
|
|
|
|
if not is_valid_hostname(hostname): |
|
|
|
|
|
callback(None, Exception('invalid hostname: %s' % hostname)) |
|
|
|
|
|
return |
|
|
arr = self._hostname_to_cb.get(hostname, None) |
|
|
arr = self._hostname_to_cb.get(hostname, None) |
|
|
if not arr: |
|
|
if not arr: |
|
|
self._hostname_status[hostname] = STATUS_IPV4 |
|
|
self._hostname_status[hostname] = STATUS_IPV4 |
|
|