From: Guus Sliepen Date: Sun, 5 Jun 2016 12:47:21 +0000 (+0200) Subject: Preserve IPv6 scope_id in edges. X-Git-Tag: release-1.1pre15~70 X-Git-Url: https://git.tinc-vpn.org/git/browse?a=commitdiff_plain;h=ab13c14a1480561bb9f59ccfbbd6045e0484ce9c;p=tinc Preserve IPv6 scope_id in edges. 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. --- 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;