diff --git a/include/libtorrent/enum_net.hpp b/include/libtorrent/enum_net.hpp index 033c6dc47..5ac724356 100644 --- a/include/libtorrent/enum_net.hpp +++ b/include/libtorrent/enum_net.hpp @@ -107,13 +107,6 @@ namespace libtorrent { TORRENT_EXTRA_EXPORT boost::optional
get_gateway( ip_interface const& iface, span routes); - TORRENT_EXTRA_EXPORT boost::optional get_default_route(io_service& ios - , string_view device, bool v6, error_code& ec); - - // returns the first default gateway found if device is empty - TORRENT_EXTRA_EXPORT address get_default_gateway(io_service& ios - , string_view device, bool v6, error_code& ec); - // attempt to bind socket to the device with the specified name. For systems // that don't support SO_BINDTODEVICE the socket will be bound to one of the // IP addresses of the specified device. In this case it is necessary to diff --git a/include/libtorrent/natpmp.hpp b/include/libtorrent/natpmp.hpp index deb1d4cbc..63e804bd0 100644 --- a/include/libtorrent/natpmp.hpp +++ b/include/libtorrent/natpmp.hpp @@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/debug.hpp" #include "libtorrent/aux_/portmap.hpp" #include "libtorrent/aux_/vector.hpp" +#include "libtorrent/enum_net.hpp" // for ip_interface namespace libtorrent { @@ -85,7 +86,7 @@ struct TORRENT_EXTRA_EXPORT natpmp { natpmp(io_service& ios, aux::portmap_callback& cb); - void start(address local_address, std::string device); + void start(ip_interface const& ip); // maps the ports, if a port is set to 0 // it will not be mapped diff --git a/src/enum_net.cpp b/src/enum_net.cpp index c5d74034e..7d5d4b996 100644 --- a/src/enum_net.cpp +++ b/src/enum_net.cpp @@ -817,28 +817,6 @@ int _System __libsocket_sysctl(int* mib, u_int namelen, void *oldp, size_t *oldl return {}; } - boost::optional get_default_route(io_service& ios - , string_view const device, bool const v6, error_code& ec) - { - std::vector const ret = enum_routes(ios, ec); - auto const i = std::find_if(ret.begin(), ret.end() - , [device,v6](ip_route const& r) - { - return r.destination.is_unspecified() - && r.destination.is_v6() == v6 - && (device.empty() || r.name == device); - }); - if (i == ret.end()) return boost::none; - return *i; - } - - address get_default_gateway(io_service& ios - , string_view const device, bool const v6, error_code& ec) - { - auto const default_route = get_default_route(ios, device, v6, ec); - return default_route ? default_route->gateway : address(); - } - std::vector enum_routes(io_service& ios, error_code& ec) { std::vector ret; diff --git a/src/natpmp.cpp b/src/natpmp.cpp index 5876683ea..84261edd4 100644 --- a/src/natpmp.cpp +++ b/src/natpmp.cpp @@ -146,28 +146,31 @@ natpmp::natpmp(io_service& ios m_mappings.reserve(10); } -void natpmp::start(address local_address, std::string device) +void natpmp::start(ip_interface const& ip) { TORRENT_ASSERT(is_single_thread()); - error_code ec; - // assume servers support PCP and fall back to NAT-PMP // if necessary m_version = version_pcp; - // we really want a device name to get the right default gateway - // try to find one even if the listen socket isn't bound to a device - if (device.empty()) + address const& local_address = ip.interface_address; + + error_code ec; + auto const routes = enum_routes(get_io_service(m_socket), ec); + if (ec) { - device = device_for_address(local_address, get_io_service(m_socket), ec); - // if this fails fall back to using the first default gateway in the - // routing table - ec.clear(); +#ifndef TORRENT_DISABLE_LOGGING + if (should_log()) + { + log("failed to enumerate routes: %s" + , convert_from_native(ec.message()).c_str()); + } +#endif + disable(ec); } - auto const route = get_default_route(get_io_service(m_socket) - , device, local_address.is_v6(), ec); + auto const route = get_gateway(ip, routes); if (!route) { @@ -175,7 +178,7 @@ void natpmp::start(address local_address, std::string device) if (should_log()) { log("failed to find default route for \"%s\" %s: %s" - , device.c_str(), local_address.to_string().c_str() + , ip.name, local_address.to_string().c_str() , convert_from_native(ec.message()).c_str()); } #endif @@ -183,65 +186,16 @@ void natpmp::start(address local_address, std::string device) return; } - if (device.empty()) device = route->name; - - TORRENT_ASSERT(!device.empty()); - - // PCP requires reporting the source address at the application - // layer so the socket MUST be bound to a specific address - // if the caller didn't specify one then get the first suitable - // address from the OS - if (local_address.is_unspecified()) - { - std::vector const net = enum_net_interfaces( - get_io_service(m_socket), ec); - - auto const it = std::find_if(net.begin(), net.end(), [&](ip_interface const& i) - { - return i.interface_address.is_v4() == local_address.is_v4() - && (i.interface_address.is_v4() || !is_local(i.interface_address)) - && i.name == device; - }); - - if (it != net.end()) - { - local_address = it->interface_address; - } - else - { - // if we can't get a specific address to bind to we'll have - // to fall back to NAT-PMP - // but NAT-PMP doesn't support IPv6 so if that's what is being - // requested we can't do anything - if (local_address.is_v6()) - { - if (!ec) ec = boost::asio::error::address_family_not_supported; -#ifndef TORRENT_DISABLE_LOGGING - if (should_log()) - { - log("cannot map IPv6 without a local address, %s" - , convert_from_native(ec.message()).c_str()); - } -#endif - disable(ec); - return; - } - - m_version = version_natpmp; - ec.clear(); - } - } - m_disabled = false; - udp::endpoint const nat_endpoint(route->gateway, 5351); + udp::endpoint const nat_endpoint(*route, 5351); if (nat_endpoint == m_nat_endpoint) return; m_nat_endpoint = nat_endpoint; #ifndef TORRENT_DISABLE_LOGGING if (should_log()) { - log("found router at: %s" + log("found gateway at: %s" , print_address(m_nat_endpoint.address()).c_str()); } #endif diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 8ae59af11..2d93853c7 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -5464,7 +5464,11 @@ namespace aux { // the natpmp constructor may fail and call the callbacks // into the session_impl. s.natpmp_mapper = std::make_shared(m_io_service, *this); - s.natpmp_mapper->start(s.local_endpoint.address(), s.device); + ip_interface ip; + ip.interface_address = s.local_endpoint.address(); + ip.netmask = s.netmask; + std::strncpy(ip.name, s.device.c_str(), sizeof(ip.name)); + s.natpmp_mapper->start(ip); } } diff --git a/test/enum_if.cpp b/test/enum_if.cpp index 4164ad866..1b3c530a8 100644 --- a/test/enum_if.cpp +++ b/test/enum_if.cpp @@ -42,15 +42,6 @@ int main() io_service ios; error_code ec; - address def_gw = get_default_gateway(ios, "", false, ec); - if (ec) - { - std::printf("%s\n", ec.message().c_str()); - return 1; - } - - std::printf("Default gateway: %s\n", def_gw.to_string(ec).c_str()); - std::printf("=========== Routes ===========\n"); auto const routes = enum_routes(ios, ec); if (ec)