Use getaddrinfo to obtain a correct sockaddr

While with AF_INET sockaddr is a 2-tuple composed by (address, port),
with AF_INET6 it is a 4-tuple with (address, port, flow info, scope id).

We were always passing a 2-tuple to socket.connect which would fail whenever
the address was, for instance, a link-local IPv6 address that needs a scope id.

With this change we now use getaddrinfo to correctly compute the full tuple.

Fixes #156.
This commit is contained in:
vieira 2017-10-15 01:03:58 +00:00 committed by Brian May
parent 2fa0cd06fb
commit 4c50be0bc7

View File

@ -172,27 +172,30 @@ class DnsProxy(Handler):
self.to_nameserver = None self.to_nameserver = None
else: else:
peer, port = to_nameserver.split("@") peer, port = to_nameserver.split("@")
port = int(port) self.to_nameserver = self._addrinfo(peer, port)
if port == 0:
port = 53
family = socket.AF_INET6 if ":" in peer else socket.AF_INET
self.to_nameserver = family, peer, port
self.try_send() self.try_send()
def _addrinfo(self, peer, port):
if int(port) == 0:
port = 53
family, _, _, _, sockaddr = socket.getaddrinfo(peer, port)[0]
return (family, sockaddr)
def try_send(self): def try_send(self):
if self.tries >= 3: if self.tries >= 3:
return return
self.tries += 1 self.tries += 1
if self.to_nameserver is None: if self.to_nameserver is None:
family, peer = resolvconf_random_nameserver() _, peer = resolvconf_random_nameserver()
port = 53 port = 53
family, sockaddr = self._addrinfo(peer, port)
else: else:
family, peer, port = self.to_nameserver family, sockaddr = self.to_nameserver
sock = socket.socket(family, socket.SOCK_DGRAM) sock = socket.socket(family, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42) sock.setsockopt(socket.SOL_IP, socket.IP_TTL, 42)
sock.connect((peer, port)) sock.connect(sockaddr)
self.peers[sock] = peer self.peers[sock] = peer