Skip to content

Commit 0f5df4b

Browse files
committed
Fix connection between two IPv6-only devices with API v1
Python sockets want the IPv6 addresses without embracing brackets, while grpc needs them. Also, with v1 we didn't actually use IPv6, now we do. This also incorparates linuxmint#241
1 parent d51681b commit 0f5df4b

3 files changed

Lines changed: 24 additions & 10 deletions

File tree

src/remote.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def start_remote_thread(self):
9292
func = self.remote_thread_v2
9393

9494
self.remote_thread = threading.Thread(target=func, name="remote-main-thread-v%s-%s-%s:%d-%s"
95-
% (self.api_version, self.hostname, self.ip_info.ip4_address, self.port, self.ident))
95+
% (self.api_version, self.hostname, self.ip_info, self.port, self.ident))
9696
# logging.debug("remote-thread-%s-%s:%d-%s"
9797
# % (self.hostname, self.ip_info.ip4_address, self.port, self.ident))
9898
self.remote_thread.start()
@@ -102,7 +102,7 @@ def remote_thread_v1(self):
102102

103103
self.emit_machine_info_changed() # Let's make sure the button doesn't have junk in it if we fail to connect.
104104

105-
logging.debug("Remote: Attempting to connect to %s (%s) - api version 1" % (self.display_hostname, self.ip_info.ip4_address))
105+
logging.debug("Remote: Attempting to connect to %s (%s) - api version 1" % (self.display_hostname, self.ip_info))
106106

107107
self.set_remote_status(RemoteStatus.INIT_CONNECTING)
108108

@@ -113,7 +113,9 @@ def run_secure_loop():
113113
cert = auth.get_singleton().get_cached_cert(self.hostname, self.ip_info)
114114
creds = grpc.ssl_channel_credentials(cert)
115115

116-
with grpc.secure_channel("%s:%d" % (self.ip_info.ip4_address, self.port), creds) as channel:
116+
remote_ip, _, ip_version = self.ip_info.get_usable_ip()
117+
remote_ip = remote_ip if ip_version == socket.AF_INET else "[%s]" % (remote_ip,)
118+
with grpc.secure_channel("%s:%d" % (remote_ip, self.port), creds) as channel:
117119
future = grpc.channel_ready_future(channel)
118120

119121
try:

src/remote_registration.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@
1414
import prefs
1515
import config
1616

17+
def get_ipv6_addr_tuple(addr, port):
18+
if '%' in addr:
19+
ip_part, scope_name = addr.split('%', 1)
20+
scope_id = socket.if_nametoindex(scope_name)
21+
else:
22+
ip_part = addr
23+
scope_id = 0
24+
return (ip_part, port, 0, scope_id)
25+
1726
class RegRequest():
1827
def __init__(self, ident, hostname, ip_info, port, auth_port, api_version):
1928
self.api_version = api_version
@@ -142,20 +151,18 @@ def request(self):
142151
remote_ip, _, ip_version = self.ip_info.get_usable_ip()
143152

144153
try:
145-
ip = remote_ip if ip_version == socket.AF_INET else "[%s]" % (remote_ip,)
146154
server_sock = socket.socket(ip_version, socket.SOCK_DGRAM)
147155
server_sock.settimeout(5.0)
148-
server_sock.sendto(REQUEST, (ip, self.port))
156+
server_sock.sendto(REQUEST, (remote_ip, self.port))
149157

150158
reply, addr = server_sock.recvfrom(2000)
151-
152-
if addr == (remote_ip, self.port):
159+
if (addr[0], addr[1]) == (remote_ip, self.port):
153160
return reply
154161
except socket.timeout:
155162
logging.debug("Auth: Cert request failed from remote (%s:%d) - (Is their udp port blocked?"
156163
% (self.ip_info, self.port))
157164
except socket.error as e:
158-
logging.critical("Something wrong with cert request (%s:%s): " % (remote_ip, self.port, e))
165+
logging.critical("Something wrong with cert request (%s:%s): %s" % (remote_ip, self.port, e))
159166

160167
return None
161168

@@ -182,7 +189,10 @@ def serve_cert_thread(self, ip_version):
182189
try:
183190
server_sock = socket.socket(ip_version, socket.SOCK_DGRAM)
184191
server_sock.settimeout(1.0)
185-
server_sock.bind((local_ip, self.port))
192+
if ip_version == socket.AF_INET6:
193+
server_sock.bind(get_ipv6_addr_tuple(local_ip, self.port))
194+
else:
195+
server_sock.bind((local_ip, self.port))
186196
except socket.error as e:
187197
logging.critical("Could not create udp socket for cert requests: %s" % str(e))
188198
return

src/util.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ def as_binary_list(self):
243243
pass
244244
if self.ip6:
245245
try:
246-
blist.append(socket.inet_pton(GLib.SYSDEF_AF_INET6, self.ip6_address))
246+
# Strip scope ID suffix if present (e.g., %eth0)
247+
ip6_clean = self.ip6_address.split('%')[0] if '%' in self.ip6_address else self.ip6_address
248+
blist.append(socket.inet_pton(GLib.SYSDEF_AF_INET6, ip6_clean))
247249
except:
248250
pass
249251

0 commit comments

Comments
 (0)