Fix IPv6 announce socket binding interface. (#3692)
When Transmission listens on both IPv4 and IPv6 interfaces IPv4 listen address is always passed to CURL's CURLOPT_INTERFACE. In general it stays unnoticed but if user has multiple IPv6 addresses configured on his system random (first?) IPv6 address is used. It happens because passed value to CURLOPT_INTERFACE is not correct -- IPv6 expected but IPv4 is passed.
This commit is contained in:
parent
a0305a3a12
commit
cb17ea4914
|
@ -145,15 +145,23 @@ std::optional<std::string_view> tr_session::WebMediator::userAgent() const
|
||||||
return TR_NAME "/" SHORT_VERSION_STRING;
|
return TR_NAME "/" SHORT_VERSION_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> tr_session::WebMediator::publicAddress() const
|
std::optional<std::string> tr_session::WebMediator::publicAddressV4() const
|
||||||
{
|
{
|
||||||
for (auto const type : { TR_AF_INET, TR_AF_INET6 })
|
auto const [addr, is_default_value] = session_->publicAddress(TR_AF_INET);
|
||||||
|
if (!is_default_value)
|
||||||
{
|
{
|
||||||
auto const [addr, is_default_value] = session_->publicAddress(type);
|
return addr.readable();
|
||||||
if (!is_default_value)
|
}
|
||||||
{
|
|
||||||
return addr.readable();
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> tr_session::WebMediator::publicAddressV6() const
|
||||||
|
{
|
||||||
|
auto const [addr, is_default_value] = session_->publicAddress(TR_AF_INET6);
|
||||||
|
if (!is_default_value)
|
||||||
|
{
|
||||||
|
return addr.readable();
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
@ -825,7 +825,8 @@ private:
|
||||||
~WebMediator() override = default;
|
~WebMediator() override = default;
|
||||||
|
|
||||||
[[nodiscard]] std::optional<std::string> cookieFile() const override;
|
[[nodiscard]] std::optional<std::string> cookieFile() const override;
|
||||||
[[nodiscard]] std::optional<std::string> publicAddress() const override;
|
[[nodiscard]] std::optional<std::string> publicAddressV4() const override;
|
||||||
|
[[nodiscard]] std::optional<std::string> publicAddressV6() const override;
|
||||||
[[nodiscard]] std::optional<std::string_view> userAgent() const override;
|
[[nodiscard]] std::optional<std::string_view> userAgent() const override;
|
||||||
[[nodiscard]] unsigned int clamp(int torrent_id, unsigned int byte_count) const override;
|
[[nodiscard]] unsigned int clamp(int torrent_id, unsigned int byte_count) const override;
|
||||||
void notifyBandwidthConsumed(int torrent_id, size_t byte_count) override;
|
void notifyBandwidthConsumed(int torrent_id, size_t byte_count) override;
|
||||||
|
|
|
@ -249,6 +249,25 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto publicAddress() const
|
||||||
|
{
|
||||||
|
switch (options.ip_proto)
|
||||||
|
{
|
||||||
|
case FetchOptions::IPProtocol::V4:
|
||||||
|
return impl.mediator.publicAddressV4();
|
||||||
|
case FetchOptions::IPProtocol::V6:
|
||||||
|
return impl.mediator.publicAddressV6();
|
||||||
|
default:
|
||||||
|
auto ip = impl.mediator.publicAddressV4();
|
||||||
|
if (ip == std::nullopt)
|
||||||
|
{
|
||||||
|
ip = impl.mediator.publicAddressV6();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void done()
|
void done()
|
||||||
{
|
{
|
||||||
if (options.done_func == nullptr)
|
if (options.done_func == nullptr)
|
||||||
|
@ -394,7 +413,7 @@ public:
|
||||||
(void)curl_easy_setopt(e, CURLOPT_WRITEFUNCTION, onDataReceived);
|
(void)curl_easy_setopt(e, CURLOPT_WRITEFUNCTION, onDataReceived);
|
||||||
(void)curl_easy_setopt(e, CURLOPT_MAXREDIRS, MaxRedirects);
|
(void)curl_easy_setopt(e, CURLOPT_MAXREDIRS, MaxRedirects);
|
||||||
|
|
||||||
if (auto const addrstr = impl->mediator.publicAddress(); addrstr)
|
if (auto const addrstr = task->publicAddress(); addrstr)
|
||||||
{
|
{
|
||||||
(void)curl_easy_setopt(e, CURLOPT_INTERFACE, addrstr->c_str());
|
(void)curl_easy_setopt(e, CURLOPT_INTERFACE, addrstr->c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,8 +119,14 @@ public:
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the preferred user public address string, or nullopt to not use one
|
// Return IPv4 user public address string, or nullopt to not use one
|
||||||
[[nodiscard]] virtual std::optional<std::string> publicAddress() const
|
[[nodiscard]] virtual std::optional<std::string> publicAddressV4() const
|
||||||
|
{
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return IPv6 user public address string, or nullopt to not use one
|
||||||
|
[[nodiscard]] virtual std::optional<std::string> publicAddressV6() const
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue