mirror of
https://github.com/transmission/transmission
synced 2024-12-22 07:42:37 +00:00
fix: misc net.cc and blocklist.cc fixes (#6717)
* fix: `tr_address` should be invalid by default * fix: allow loopback address for LPD and incoming connections * fix: `parseCidrline()` should set address type * code review: keep `memcmp`
This commit is contained in:
parent
9ddf609d50
commit
20aef2f79d
7 changed files with 32 additions and 22 deletions
|
@ -339,7 +339,7 @@ void tr_announcerParseHttpAnnounceResponse(tr_announce_response& response, std::
|
||||||
{
|
{
|
||||||
BasicHandler::EndDict(context);
|
BasicHandler::EndDict(context);
|
||||||
|
|
||||||
if (pex_.is_valid_for_peers())
|
if (pex_.is_valid())
|
||||||
{
|
{
|
||||||
response_.pex.push_back(pex_);
|
response_.pex.push_back(pex_);
|
||||||
pex_ = {};
|
pex_ = {};
|
||||||
|
|
|
@ -204,10 +204,12 @@ std::optional<address_range_t> parseCidrLine(std::string_view line)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const mask = uint32_t{ 0xFFFFFFFF } << (32 - *pflen);
|
auto const mask = ~(~uint32_t{ 0 } >> *pflen);
|
||||||
auto const ip_u = htonl(addrpair.first.addr.addr4.s_addr);
|
auto const ip_u = ntohl(addrpair.first.addr.addr4.s_addr);
|
||||||
addrpair.first.addr.addr4.s_addr = ntohl(ip_u & mask);
|
auto tmp = htonl(ip_u & mask);
|
||||||
addrpair.second.addr.addr4.s_addr = ntohl(ip_u | (~mask));
|
std::tie(addrpair.first, std::ignore) = tr_address::from_compact_ipv4(reinterpret_cast<std::byte*>(&tmp));
|
||||||
|
tmp = htonl(ip_u | (~mask));
|
||||||
|
std::tie(addrpair.second, std::ignore) = tr_address::from_compact_ipv4(reinterpret_cast<std::byte*>(&tmp));
|
||||||
return addrpair;
|
return addrpair;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,7 @@ tr_peer_socket tr_netOpenPeerSocket(tr_session* session, tr_socket_address const
|
||||||
TR_ASSERT(addr.is_valid());
|
TR_ASSERT(addr.is_valid());
|
||||||
TR_ASSERT(!tr_peer_socket::limit_reached(session));
|
TR_ASSERT(!tr_peer_socket::limit_reached(session));
|
||||||
|
|
||||||
if (tr_peer_socket::limit_reached(session) || !session->allowsTCP() || !socket_address.is_valid_for_peers())
|
if (tr_peer_socket::limit_reached(session) || !session->allowsTCP() || !socket_address.is_valid())
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -446,23 +446,29 @@ namespace is_valid_for_peers_helpers
|
||||||
|
|
||||||
/* isMartianAddr was written by Juliusz Chroboczek,
|
/* isMartianAddr was written by Juliusz Chroboczek,
|
||||||
and is covered under the same license as third-party/dht/dht.c. */
|
and is covered under the same license as third-party/dht/dht.c. */
|
||||||
[[nodiscard]] auto is_martian_addr(tr_address const& addr)
|
[[nodiscard]] auto is_martian_addr(tr_address const& addr, tr_peer_from from)
|
||||||
{
|
{
|
||||||
static auto constexpr Zeroes = std::array<unsigned char, 16>{};
|
static auto constexpr Zeroes = std::array<unsigned char, 16>{};
|
||||||
|
auto const loopback_allowed = from == TR_PEER_FROM_INCOMING || from == TR_PEER_FROM_LPD || from == TR_PEER_FROM_RESUME;
|
||||||
|
|
||||||
switch (addr.type)
|
switch (addr.type)
|
||||||
{
|
{
|
||||||
case TR_AF_INET:
|
case TR_AF_INET:
|
||||||
{
|
{
|
||||||
auto const* const address = reinterpret_cast<unsigned char const*>(&addr.addr.addr4);
|
auto const* const address = reinterpret_cast<unsigned char const*>(&addr.addr.addr4);
|
||||||
return address[0] == 0 || address[0] == 127 || (address[0] & 0xE0) == 0xE0;
|
return address[0] == 0 || // 0.x.x.x
|
||||||
|
(!loopback_allowed && address[0] == 127) || // 127.x.x.x
|
||||||
|
(address[0] & 0xE0) == 0xE0; // multicast address
|
||||||
}
|
}
|
||||||
|
|
||||||
case TR_AF_INET6:
|
case TR_AF_INET6:
|
||||||
{
|
{
|
||||||
auto const* const address = reinterpret_cast<unsigned char const*>(&addr.addr.addr6);
|
auto const* const address = reinterpret_cast<unsigned char const*>(&addr.addr.addr6);
|
||||||
return address[0] == 0xFF ||
|
return address[0] == 0xFF || // multicast address
|
||||||
(memcmp(address, std::data(Zeroes), 15) == 0 && (address[15] == 0 || address[15] == 1));
|
(std::memcmp(address, std::data(Zeroes), 15) == 0 &&
|
||||||
|
(address[15] == 0 || // ::
|
||||||
|
(!loopback_allowed && address[15] == 1)) // ::1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -703,12 +709,12 @@ std::string tr_socket_address::display_name(tr_address const& address, tr_port p
|
||||||
return fmt::format("[{:s}]:{:d}", address.display_name(), port.host());
|
return fmt::format("[{:s}]:{:d}", address.display_name(), port.host());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tr_socket_address::is_valid_for_peers() const noexcept
|
bool tr_socket_address::is_valid_for_peers(tr_peer_from from) const noexcept
|
||||||
{
|
{
|
||||||
using namespace is_valid_for_peers_helpers;
|
using namespace is_valid_for_peers_helpers;
|
||||||
|
|
||||||
return is_valid() && !std::empty(port_) && !is_ipv6_link_local_address(address_) && !is_ipv4_mapped_address(address_) &&
|
return is_valid() && !std::empty(port_) && !is_ipv6_link_local_address(address_) && !is_ipv4_mapped_address(address_) &&
|
||||||
!is_martian_addr(address_);
|
!is_martian_addr(address_, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<tr_socket_address> tr_socket_address::from_sockaddr(struct sockaddr const* from)
|
std::optional<tr_socket_address> tr_socket_address::from_sockaddr(struct sockaddr const* from)
|
||||||
|
|
|
@ -60,6 +60,8 @@ using tr_socket_t = int;
|
||||||
#define sockerrno errno
|
#define sockerrno errno
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "libtransmission/transmission.h" // tr_peer_from
|
||||||
|
|
||||||
#include "libtransmission/tr-assert.h"
|
#include "libtransmission/tr-assert.h"
|
||||||
#include "libtransmission/utils.h" // for tr_compare_3way()
|
#include "libtransmission/utils.h" // for tr_compare_3way()
|
||||||
|
|
||||||
|
@ -234,7 +236,7 @@ struct tr_address
|
||||||
|
|
||||||
[[nodiscard]] bool is_global_unicast_address() const noexcept;
|
[[nodiscard]] bool is_global_unicast_address() const noexcept;
|
||||||
|
|
||||||
tr_address_type type;
|
tr_address_type type = NUM_TR_AF_INET_TYPES;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
|
@ -306,7 +308,7 @@ struct tr_socket_address
|
||||||
return address_.is_valid();
|
return address_.is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool is_valid_for_peers() const noexcept;
|
[[nodiscard]] bool is_valid_for_peers(tr_peer_from from) const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] int compare(tr_socket_address const& that) const noexcept
|
[[nodiscard]] int compare(tr_socket_address const& that) const noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,11 +129,6 @@ std::shared_ptr<tr_peerIo> tr_peerIo::new_outgoing(
|
||||||
TR_ASSERT(socket_address.is_valid());
|
TR_ASSERT(socket_address.is_valid());
|
||||||
TR_ASSERT(utp || session->allowsTCP());
|
TR_ASSERT(utp || session->allowsTCP());
|
||||||
|
|
||||||
if (!socket_address.is_valid_for_peers())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto peer_io = tr_peerIo::create(session, parent, &info_hash, false, is_seed);
|
auto peer_io = tr_peerIo::create(session, parent, &info_hash, false, is_seed);
|
||||||
auto const func = small::max_size_map<preferred_key_t, std::function<bool()>, TR_NUM_PREFERRED_TRANSPORT>{
|
auto const func = small::max_size_map<preferred_key_t, std::function<bool()>, TR_NUM_PREFERRED_TRANSPORT>{
|
||||||
{ TR_PREFER_UTP,
|
{ TR_PREFER_UTP,
|
||||||
|
|
|
@ -1439,7 +1439,7 @@ size_t tr_peerMgrAddPex(tr_torrent* tor, tr_peer_from from, tr_pex const* pex, s
|
||||||
for (tr_pex const* const end = pex + n_pex; pex != end; ++pex)
|
for (tr_pex const* const end = pex + n_pex; pex != end; ++pex)
|
||||||
{
|
{
|
||||||
if (tr_isPex(pex) && /* safeguard against corrupt data */
|
if (tr_isPex(pex) && /* safeguard against corrupt data */
|
||||||
!s->manager->blocklists_.contains(pex->socket_address.address()) && pex->is_valid_for_peers() &&
|
!s->manager->blocklists_.contains(pex->socket_address.address()) && pex->is_valid_for_peers(from) &&
|
||||||
from != TR_PEER_FROM_INCOMING && (from != TR_PEER_FROM_PEX || (pex->flags & ADDED_F_CONNECTABLE) != 0))
|
from != TR_PEER_FROM_INCOMING && (from != TR_PEER_FROM_PEX || (pex->flags & ADDED_F_CONNECTABLE) != 0))
|
||||||
{
|
{
|
||||||
// we store this peer since it is supposedly connectable (socket address should be the peer's listening address)
|
// we store this peer since it is supposedly connectable (socket address should be the peer's listening address)
|
||||||
|
|
|
@ -517,9 +517,14 @@ struct tr_pex
|
||||||
return compare(that) < 0;
|
return compare(that) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool is_valid_for_peers() const noexcept
|
[[nodiscard]] bool is_valid() const noexcept
|
||||||
{
|
{
|
||||||
return socket_address.is_valid_for_peers();
|
return socket_address.is_valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool is_valid_for_peers(tr_peer_from from) const noexcept
|
||||||
|
{
|
||||||
|
return socket_address.is_valid_for_peers(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
tr_socket_address socket_address;
|
tr_socket_address socket_address;
|
||||||
|
|
Loading…
Reference in a new issue