Fix servicing IPv6 based TCP connections

When a connection is received via IPv6, the address is a 4-tuple
instead of a 2-tuple for IPv4, so handle this accordingly.

Also handle the end of the TCP connection gracefully instead of
emitting an "Invalid packet" warning every time.

[1] https://docs.python.org/2/library/socket.html

Change-Id: I935bbea1d58af8a5b41b5d29f12de4dcb7cf6301
Closes-Bug: 1734101
(cherry picked from commit 5e45b15419)
This commit is contained in:
Jens Harbott 2017-11-23 16:44:02 +00:00
parent 7c2a3be3e4
commit 16297a3014
1 changed files with 10 additions and 4 deletions

View File

@ -321,6 +321,9 @@ class DNSService(object):
LOG.debug("Handling TCP Request from: %(host)s:%(port)d" %
{'host': addr[0], 'port': addr[1]})
if len(addr) == 4:
LOG.debug("Flow info: %(host)s scope: %(port)d" %
{'host': addr[2], 'port': addr[3]})
# Dispatch a thread to handle the connection
self.tg.add_thread(self._dns_handle_tcp_conn, addr, client)
@ -349,25 +352,28 @@ class DNSService(object):
def _dns_handle_tcp_conn(self, addr, client):
"""
Handle a DNS Query over TCP. Multiple queries can be pipelined
though the same TCP connection but they will be processed
through the same TCP connection but they will be processed
sequentially.
See https://tools.ietf.org/html/draft-ietf-dnsop-5966bis-03
Raises no exception: it's to be run in an eventlet green thread
:param addr: Tuple of the client's (IP addr, Port)
:param addr: Tuple of the client's (IPv4 addr, Port) or
(IPv6 addr, Port, Flow info, Scope ID)
:type addr: tuple
:param client: Client socket
:type client: socket
:raises: None
"""
host, port = addr
host, port = addr[:2]
try:
# The whole loop lives in a try/except block. On exceptions, the
# connection is closed: there would be little chance to save save
# connection is closed: there would be little chance to save
# the connection after a struct error, a socket error.
while True:
# Decode the first 2 bytes containing the query length
expected_length_raw = client.recv(2)
if len(expected_length_raw) == 0:
break
(expected_length, ) = struct.unpack('!H', expected_length_raw)
# Keep receiving data until we've got all the data we expect