Support IPV6 DNS servers.

Closes #28.
This commit is contained in:
Brian May 2015-11-24 12:23:17 +11:00
parent 71d46d77bf
commit c0748c2388

View File

@ -120,55 +120,62 @@ class Hostwatch:
class DnsProxy(Handler): class DnsProxy(Handler):
def __init__(self, mux, chan, request): def __init__(self, mux, chan, request):
# FIXME! IPv4 specific Handler.__init__(self, [])
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Handler.__init__(self, [sock])
self.timeout = time.time() + 30 self.timeout = time.time() + 30
self.mux = mux self.mux = mux
self.chan = chan self.chan = chan
self.tries = 0 self.tries = 0
self.peer = None
self.request = request self.request = request
self.sock = sock self.peers = {}
# FIXME! IPv4 specific
self.sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
self.try_send() self.try_send()
def try_send(self): def try_send(self):
if self.tries >= 3: if self.tries >= 3:
return return
self.tries += 1 self.tries += 1
# FIXME! Support IPv6 nameservers
self.peer = resolvconf_random_nameserver()[1] family, peer = resolvconf_random_nameserver()
self.sock.connect((self.peer, 53))
debug2('DNS: sending to %r\n' % self.peer) sock = socket.socket(family, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
sock.connect((peer, 53))
self.peers[sock] = peer
debug2('DNS: sending to %r (try %d)\n' % (peer, self.tries))
try: try:
self.sock.send(self.request) sock.send(self.request)
self.socks.append(sock)
except socket.error as e: except socket.error as e:
if e.args[0] in ssnet.NET_ERRS: if e.args[0] in ssnet.NET_ERRS:
# might have been spurious; try again. # might have been spurious; try again.
# Note: these errors sometimes are reported by recv(), # Note: these errors sometimes are reported by recv(),
# and sometimes by send(). We have to catch both. # and sometimes by send(). We have to catch both.
debug2('DNS send to %r: %s\n' % (self.peer, e)) debug2('DNS send to %r: %s\n' % (peer, e))
self.try_send() self.try_send()
return return
else: else:
log('DNS send to %r: %s\n' % (self.peer, e)) log('DNS send to %r: %s\n' % (peer, e))
return return
def callback(self, sock): def callback(self, sock):
peer = self.peers[sock]
try: try:
data = sock.recv(4096) data = sock.recv(4096)
except socket.error as e: except socket.error as e:
self.socks.remove(sock)
del self.peers[sock]
if e.args[0] in ssnet.NET_ERRS: if e.args[0] in ssnet.NET_ERRS:
# might have been spurious; try again. # might have been spurious; try again.
# Note: these errors sometimes are reported by recv(), # Note: these errors sometimes are reported by recv(),
# and sometimes by send(). We have to catch both. # and sometimes by send(). We have to catch both.
debug2('DNS recv from %r: %s\n' % (self.peer, e)) debug2('DNS recv from %r: %s\n' % (peer, e))
self.try_send() self.try_send()
return return
else: else:
log('DNS recv from %r: %s\n' % (self.peer, e)) log('DNS recv from %r: %s\n' % (peer, e))
return return
debug2('DNS response: %d bytes\n' % len(data)) debug2('DNS response: %d bytes\n' % len(data))
self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data) self.mux.send(self.chan, ssnet.CMD_DNS_RESPONSE, data)