From ab13c14a1480561bb9f59ccfbbd6045e0484ce9c Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 5 Jun 2016 14:47:21 +0200 Subject: [PATCH] Preserve IPv6 scope_id in edges. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit When creating an edge after authenticating a peer, we copy the address used for the TCP connection, but change the port to that used for UDP. But the way we did it discarded the scope_id for IPv6 addresses. This prevented UDP communication from working correctly when connecting to a peer on the same LAN using an IPv6 link-local address. Thanks to Rafał Leśniak for pointing out this issue. --- src/netutl.c | 19 +++++++++++++++++++ src/netutl.h | 1 + src/protocol_auth.c | 13 +++---------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/netutl.c b/src/netutl.c index 2eebb644..a9ad17ce 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -234,3 +234,22 @@ void sockaddrunmap(sockaddr_t *sa) { sa->in.sin_family = AF_INET; } } + +void sockaddr_setport(sockaddr_t *sa, const char *port) { + uint16_t portnum = htons(atoi(port)); + if(!portnum) + return; + switch(sa->sa.sa_family) { + case AF_INET: + sa->in.sin_port = portnum; + break; + case AF_INET6: + sa->in6.sin6_port = portnum; + break; + case AF_UNKNOWN: + free(sa->unknown.port); + sa->unknown.port = xstrdup(port); + default: + return; + } +} diff --git a/src/netutl.h b/src/netutl.h index 471cae7f..2e2f2936 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -34,5 +34,6 @@ extern int sockaddrcmp_noport(const sockaddr_t *, const sockaddr_t *); extern void sockaddrunmap(sockaddr_t *); extern void sockaddrfree(sockaddr_t *); extern void sockaddrcpy(sockaddr_t *, const sockaddr_t *); +extern void sockaddr_setport(sockaddr_t *, const char *); #endif /* __TINC_NETUTL_H__ */ diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 0a7ad1ca..65c5e89e 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -790,7 +790,6 @@ bool ack_h(connection_t *c, const char *request) { return upgrade_h(c, request); char hisport[MAX_STRING_SIZE]; - char *hisaddress; int weight, mtu; uint32_t options; node_t *n; @@ -867,19 +866,13 @@ bool ack_h(connection_t *c, const char *request) { c->edge = new_edge(); c->edge->from = myself; c->edge->to = n; - sockaddr2str(&c->address, &hisaddress, NULL); - c->edge->address = str2sockaddr(hisaddress, hisport); - free(hisaddress); + sockaddr_setport(&c->address, hisport); sockaddr_t local_sa; socklen_t local_salen = sizeof local_sa; if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0) logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name); - else { - char *local_address; - sockaddr2str(&local_sa, &local_address, NULL); - c->edge->local_address = str2sockaddr(local_address, myport); - free(local_address); - } + else + sockaddr_setport(&local_sa, myport); c->edge->weight = (weight + c->estimated_weight) / 2; c->edge->connection = c; c->edge->options = c->options; -- 2.20.1