diff --git a/include/libtorrent/enum_net.hpp b/include/libtorrent/enum_net.hpp index b97061b0d..b0a41f324 100644 --- a/include/libtorrent/enum_net.hpp +++ b/include/libtorrent/enum_net.hpp @@ -74,6 +74,7 @@ namespace libtorrent { address destination; address netmask; address gateway; + address source_hint; char name[64]{}; int mtu; }; diff --git a/src/enum_net.cpp b/src/enum_net.cpp index 7b9758bc5..5d9cab47a 100644 --- a/src/enum_net.cpp +++ b/src/enum_net.cpp @@ -281,6 +281,9 @@ namespace { case RTA_DST: rt_info->destination = to_address(rt_msg->rtm_family, RTA_DATA(rt_attr)); break; + case RTA_PREFSRC: + rt_info->source_hint = to_address(rt_msg->rtm_family, RTA_DATA(rt_attr)); + break; } } #ifdef __clang__ @@ -396,6 +399,7 @@ int _System __libsocket_sysctl(int* mib, u_int namelen, void *oldp, size_t *oldl rt_info->netmask = sockaddr_to_address(rti_info[RTAX_NETMASK] , rt_info->destination.is_v4() ? AF_INET : AF_INET6); if_indextoname(rtm->rtm_index, rt_info->name); + if (rti_info[RTAX_IFA]) rt_info->source_hint = sockaddr_to_address(rti_info[RTAX_IFA]); return true; } #endif @@ -798,6 +802,10 @@ int _System __libsocket_sysctl(int* mib, u_int namelen, void *oldp, size_t *oldl // interface, but they are addressed by the local network address // space. So this check only works for IPv4. && (!v4 || match_addr_mask(r.gateway, iface.interface_address, iface.netmask)) + // in case there are multiple networks on the same networking + // device, the source hint may be the only thing telling them + // apart + && (r.source_hint.is_unspecified() || r.source_hint == iface.interface_address) && strcmp(r.name, iface.name) == 0; }); if (it != routes.end()) return it->gateway; diff --git a/test/enum_if.cpp b/test/enum_if.cpp index 1b3c530a8..481343045 100644 --- a/test/enum_if.cpp +++ b/test/enum_if.cpp @@ -50,15 +50,16 @@ int main() return 1; } - std::printf("%-18s%-18s%-35s%-7sinterface\n", "destination", "network", "gateway", "mtu"); + std::printf("%-18s%-18s%-35s%-7s%-18sinterface\n", "destination", "network", "gateway", "mtu", "source-hint"); for (auto const& r : routes) { - std::printf("%-18s%-18s%-35s%-7d%s\n" + std::printf("%-18s%-18s%-35s%-7d%-18s%s\n" , r.destination.to_string(ec).c_str() , r.netmask.to_string(ec).c_str() , r.gateway.is_unspecified() ? "-" : r.gateway.to_string(ec).c_str() , r.mtu + , r.source_hint.is_unspecified() ? "-" : r.source_hint.to_string(ec).c_str() , r.name); }