diff --git a/libtransmission/announcer-http.cc b/libtransmission/announcer-http.cc index c730e79bf..47a08eeef 100644 --- a/libtransmission/announcer-http.cc +++ b/libtransmission/announcer-http.cc @@ -107,7 +107,7 @@ static std::string announce_url_new(tr_session const* session, tr_announce_reque announce twice. At any rate, we're already computing our IPv6 address (for the LTEP handshake), so this comes for free. */ - unsigned char const* const ipv6 = tr_globalIPv6(); + unsigned char const* const ipv6 = tr_globalIPv6(session); if (ipv6 != nullptr) { char ipv6_readable[INET6_ADDRSTRLEN]; diff --git a/libtransmission/net.cc b/libtransmission/net.cc index da4b8912a..09b64de34 100644 --- a/libtransmission/net.cc +++ b/libtransmission/net.cc @@ -638,12 +638,14 @@ static int tr_globalAddress(int af, void* addr, int* addr_len) } /* Return our global IPv6 address, with caching. */ -unsigned char const* tr_globalIPv6(void) +unsigned char const* tr_globalIPv6(tr_session const* session) { static unsigned char ipv6[16]; static time_t last_time = 0; static bool have_ipv6 = false; time_t const now = tr_time(); + bool is_default; + tr_address const* ipv6_bindaddr; /* Re-check every half hour */ if (last_time < now - 1800) @@ -654,7 +656,23 @@ unsigned char const* tr_globalIPv6(void) last_time = now; } - return have_ipv6 ? ipv6 : nullptr; + if (!have_ipv6) + return nullptr; /* No IPv6 address at all. */ + + /* Return the default address. This is useful for checking + for connectivity in general. */ + if (session == nullptr) + return ipv6; + + /* We have some sort of address, now make sure that we return + our bound address if non-default. */ + + ipv6_bindaddr = tr_sessionGetPublicAddress(session, TR_AF_INET6, &is_default); + if (ipv6_bindaddr != nullptr && !is_default) + /* Explicitly bound. Return that address. */ + memcpy(ipv6, ipv6_bindaddr->addr.addr6.s6_addr, 16); + + return ipv6; } /*** diff --git a/libtransmission/net.h b/libtransmission/net.h index 906025e53..025d580fe 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -135,4 +135,4 @@ bool tr_net_hasIPv6(tr_port); */ char* tr_net_strerror(char* buf, size_t buflen, int err); -unsigned char const* tr_globalIPv6(void); +unsigned char const* tr_globalIPv6(tr_session const* session); diff --git a/libtransmission/peer-msgs.cc b/libtransmission/peer-msgs.cc index 99ea07935..e99a4d5c5 100644 --- a/libtransmission/peer-msgs.cc +++ b/libtransmission/peer-msgs.cc @@ -255,7 +255,7 @@ public: /* Only send PORT over IPv6 when the IPv6 DHT is running (BEP-32). */ struct tr_address const* addr = tr_peerIoGetAddress(io, nullptr); - if (addr->type == TR_AF_INET || tr_globalIPv6() != nullptr) + if (addr->type == TR_AF_INET || tr_globalIPv6(nullptr) != nullptr) { protocolSendPort(this, tr_dhtPort(torrent->session)); } @@ -1007,7 +1007,7 @@ static bool requestIsValid(tr_peerMsgsImpl const* msgs, struct peer_request cons static void sendLtepHandshake(tr_peerMsgsImpl* msgs) { evbuffer* const out = msgs->outMessages; - unsigned char const* ipv6 = tr_globalIPv6(); + unsigned char const* ipv6 = tr_globalIPv6(msgs->io->session); static tr_quark version_quark = 0; if (msgs->clientSentLtepHandshake) diff --git a/libtransmission/tr-udp.cc b/libtransmission/tr-udp.cc index e16c7315a..aa79678b5 100644 --- a/libtransmission/tr-udp.cc +++ b/libtransmission/tr-udp.cc @@ -133,7 +133,7 @@ static void rebind_ipv6(tr_session* ss, bool force) bool is_default = false; tr_address const* public_addr = nullptr; struct sockaddr_in6 sin6; - unsigned char const* ipv6 = tr_globalIPv6(); + unsigned char const* ipv6 = tr_globalIPv6(ss); tr_socket_t s = TR_BAD_SOCKET; int rc = -1; int one = 1; @@ -178,12 +178,6 @@ static void rebind_ipv6(tr_session* ss, bool force) } sin6.sin6_port = htons(ss->udp_port); - public_addr = tr_sessionGetPublicAddress(ss, TR_AF_INET6, &is_default); - - if (public_addr != nullptr && !is_default) - { - sin6.sin6_addr = public_addr->addr.addr6; - } rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6)); @@ -343,7 +337,7 @@ void tr_udpInit(tr_session* ss) // IPV6 - if (tr_globalIPv6() != nullptr) + if (tr_globalIPv6(nullptr) != nullptr) { rebind_ipv6(ss, true); }