Skip to content

Commit

Permalink
fix: bind to a specific local IPv6 address during pair verify
Browse files Browse the repository at this point in the history
This will prevent future traffic from picking the "best" address to
communicate with an accessory. Current products tie sessions to the
original IPv6 address and return a CoAP error code 4.04 when a new
address attempts to continue the session.

It is likely that this could explode in fun, new ways: the DHCPv6 server
returning a new address, the host selecting a new random SLAAC address,
etc.
  • Loading branch information
roysjosh committed Dec 20, 2022
1 parent 269c7dd commit 8d7f224
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
14 changes: 13 additions & 1 deletion aiohomekit/controller/coap/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import asyncio
import logging
import random
import socket
import struct
from typing import Any
import uuid
Expand Down Expand Up @@ -244,8 +245,10 @@ def __init__(self, owner, host, port):
self.address = f"[{host}]:{port}"
self.connection_lock = asyncio.Lock()
self.enc_ctx = None
self.host = host
self.owner = owner
self.pair_setup_client = None
self.port = port

async def reconnect_soon(self):
if not self.enc_ctx:
Expand Down Expand Up @@ -322,14 +325,23 @@ async def do_pair_setup_finish(self, pin, salt, srpB):

return pairing

def _get_local_ipv6_addr(self, remote):
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
s.connect(remote)
addr = s.getsockname()[0]
s.close()
return addr

async def do_pair_verify(self, pairing_data):
if self.is_connected:
logger.warning("Connecting to connected device?")
await self.enc_ctx.coap_ctx.shutdown()
self.enc_ctx = None

local_address = self._get_local_ipv6_addr((self.host, self.port))

root = resource.Site()
coap_client = await Context.create_server_context(root, bind=("::", 0))
coap_client = await Context.create_server_context(root, bind=(local_address, 0))
uri = "coap://%s/2" % (self.address)
logger.debug(f"Pair verify uri={uri}")

Expand Down
2 changes: 2 additions & 0 deletions aiohomekit/controller/coap/pairing.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ def _async_endpoint_changed(self) -> None:
self.connection.address = (
f"[{self.description.address}]:{self.description.port}"
)
self.connection.host = self.description.address
self.connection.port = self.description.port
async_create_task(self.connection.reconnect_soon())

@property
Expand Down

0 comments on commit 8d7f224

Please sign in to comment.