merged uTP branch into trunk (yay)
This commit is contained in:
368
src/enum_net.cpp
368
src/enum_net.cpp
@@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libtorrent/config.hpp"
|
||||
#include <boost/bind.hpp>
|
||||
#include <vector>
|
||||
#include <stdlib.h> // for wcstombscstombs
|
||||
#include "libtorrent/enum_net.hpp"
|
||||
#include "libtorrent/broadcast_socket.hpp"
|
||||
#include "libtorrent/error_code.hpp"
|
||||
@@ -84,31 +85,44 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
namespace libtorrent { namespace
|
||||
{
|
||||
|
||||
address inaddr_to_address(in_addr const* ina)
|
||||
address inaddr_to_address(in_addr const* ina, int len = 4)
|
||||
{
|
||||
typedef asio::ip::address_v4::bytes_type bytes_t;
|
||||
bytes_t b;
|
||||
std::memcpy(&b[0], ina, b.size());
|
||||
std::memset(&b[0], 0, b.size());
|
||||
if (len > 0) std::memcpy(&b[0], ina, (std::min)(len, int(b.size())));
|
||||
return address_v4(b);
|
||||
}
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
address inaddr6_to_address(in6_addr const* ina6)
|
||||
address inaddr6_to_address(in6_addr const* ina6, int len = 16)
|
||||
{
|
||||
typedef asio::ip::address_v6::bytes_type bytes_t;
|
||||
bytes_t b;
|
||||
std::memcpy(&b[0], ina6, b.size());
|
||||
std::memset(&b[0], 0, b.size());
|
||||
if (len > 0) std::memcpy(&b[0], ina6, (std::min)(len, int(b.size())));
|
||||
return address_v6(b);
|
||||
}
|
||||
#endif
|
||||
|
||||
address sockaddr_to_address(sockaddr const* sin)
|
||||
int sockaddr_len(sockaddr const* sin)
|
||||
{
|
||||
if (sin->sa_family == AF_INET)
|
||||
return inaddr_to_address(&((sockaddr_in const*)sin)->sin_addr);
|
||||
#if defined TORRENT_WINDOWS || TORRENT_MINGW || defined TORRENT_LINUX
|
||||
return sin->sa_family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
|
||||
#else
|
||||
return sin->sa_len;
|
||||
#endif
|
||||
}
|
||||
|
||||
address sockaddr_to_address(sockaddr const* sin, int assume_family = -1)
|
||||
{
|
||||
if (sin->sa_family == AF_INET || assume_family == AF_INET)
|
||||
return inaddr_to_address(&((sockaddr_in const*)sin)->sin_addr
|
||||
, sockaddr_len(sin) - offsetof(sockaddr, sa_data));
|
||||
#if TORRENT_USE_IPV6
|
||||
else if (sin->sa_family == AF_INET6)
|
||||
return inaddr6_to_address(&((sockaddr_in6 const*)sin)->sin6_addr);
|
||||
else if (sin->sa_family == AF_INET6 || assume_family == AF_INET6)
|
||||
return inaddr6_to_address(&((sockaddr_in6 const*)sin)->sin6_addr
|
||||
, sockaddr_len(sin) - offsetof(sockaddr, sa_data));
|
||||
#endif
|
||||
return address();
|
||||
}
|
||||
@@ -142,13 +156,15 @@ namespace libtorrent { namespace
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
bool parse_route(nlmsghdr* nl_hdr, ip_route* rt_info)
|
||||
bool parse_route(int s, nlmsghdr* nl_hdr, ip_route* rt_info)
|
||||
{
|
||||
rtmsg* rt_msg = (rtmsg*)NLMSG_DATA(nl_hdr);
|
||||
|
||||
if((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN))
|
||||
if((rt_msg->rtm_family != AF_INET && rt_msg->rtm_family != AF_INET6) || (rt_msg->rtm_table != RT_TABLE_MAIN
|
||||
&& rt_msg->rtm_table != RT_TABLE_LOCAL))
|
||||
return false;
|
||||
|
||||
int if_index = 0;
|
||||
int rt_len = RTM_PAYLOAD(nl_hdr);
|
||||
for (rtattr* rt_attr = (rtattr*)RTM_RTA(rt_msg);
|
||||
RTA_OK(rt_attr,rt_len); rt_attr = RTA_NEXT(rt_attr,rt_len))
|
||||
@@ -156,23 +172,52 @@ namespace libtorrent { namespace
|
||||
switch(rt_attr->rta_type)
|
||||
{
|
||||
case RTA_OIF:
|
||||
if_indextoname(*(int*)RTA_DATA(rt_attr), rt_info->name);
|
||||
if_index = *(int*)RTA_DATA(rt_attr);
|
||||
break;
|
||||
case RTA_GATEWAY:
|
||||
rt_info->gateway = address_v4(ntohl(*(u_int*)RTA_DATA(rt_attr)));
|
||||
#if TORRENT_USE_IPV6
|
||||
if (rt_msg->rtm_family == AF_INET6)
|
||||
{
|
||||
rt_info->gateway = inaddr6_to_address((in6_addr*)RTA_DATA(rt_attr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rt_info->gateway = inaddr_to_address((in_addr*)RTA_DATA(rt_attr));
|
||||
}
|
||||
break;
|
||||
case RTA_DST:
|
||||
rt_info->destination = address_v4(ntohl(*(u_int*)RTA_DATA(rt_attr)));
|
||||
#if TORRENT_USE_IPV6
|
||||
if (rt_msg->rtm_family == AF_INET6)
|
||||
{
|
||||
rt_info->destination = inaddr6_to_address((in6_addr*)RTA_DATA(rt_attr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rt_info->destination = inaddr_to_address((in_addr*)RTA_DATA(rt_attr));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if_indextoname(if_index, rt_info->name);
|
||||
ifreq req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
if_indextoname(if_index, req.ifr_name);
|
||||
ioctl(s, SIOCGIFMTU, &req);
|
||||
rt_info->mtu = req.ifr_mtu;
|
||||
// obviously this doesn't work correctly. How do you get the netmask for a route?
|
||||
// if (ioctl(s, SIOCGIFNETMASK, &req) == 0) {
|
||||
// rt_info->netmask = sockaddr_to_address(&req.ifr_addr, req.ifr_addr.sa_family);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_BSD
|
||||
|
||||
bool parse_route(rt_msghdr* rtm, ip_route* rt_info)
|
||||
bool parse_route(int s, rt_msghdr* rtm, ip_route* rt_info)
|
||||
{
|
||||
sockaddr* rti_info[RTAX_MAX];
|
||||
sockaddr* sa = (sockaddr*)(rtm + 1);
|
||||
@@ -205,9 +250,17 @@ namespace libtorrent { namespace
|
||||
return false;
|
||||
|
||||
rt_info->gateway = sockaddr_to_address(rti_info[RTAX_GATEWAY]);
|
||||
rt_info->netmask = sockaddr_to_address(rti_info[RTAX_NETMASK]);
|
||||
rt_info->destination = sockaddr_to_address(rti_info[RTAX_DST]);
|
||||
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);
|
||||
|
||||
ifreq req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
if_indextoname(rtm->rtm_index, req.ifr_name);
|
||||
if (ioctl(s, SIOCGIFMTU, &req) < 0) return false;
|
||||
rt_info->mtu = req.ifr_mtu;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -231,17 +284,29 @@ namespace libtorrent { namespace
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
bool in_subnet(address const& addr, ip_interface const& iface)
|
||||
// return (a1 & mask) == (a2 & mask)
|
||||
bool match_addr_mask(address const& a1, address const& a2, address const& mask)
|
||||
{
|
||||
if (addr.is_v4() != iface.interface_address.is_v4()) return false;
|
||||
// since netmasks seems unreliable for IPv6 interfaces
|
||||
// (MacOS X returns AF_INET addresses as bitmasks) assume
|
||||
// that any IPv6 address belongs to the subnet of any
|
||||
// interface with an IPv6 address
|
||||
if (addr.is_v6()) return true;
|
||||
// all 3 addresses needs to belong to the same family
|
||||
if (a1.is_v4() != a2.is_v4()) return false;
|
||||
if (a1.is_v4() != mask.is_v4()) return false;
|
||||
|
||||
return (addr.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong())
|
||||
== (iface.interface_address.to_v4().to_ulong() & iface.netmask.to_v4().to_ulong());
|
||||
#if TORRENT_USE_IPV6
|
||||
if (a1.is_v6())
|
||||
{
|
||||
address_v6::bytes_type b1;
|
||||
address_v6::bytes_type b2;
|
||||
address_v6::bytes_type m;
|
||||
b1 = a1.to_v6().to_bytes();
|
||||
b2 = a2.to_v6().to_bytes();
|
||||
m = mask.to_v6().to_bytes();
|
||||
for (int i = 0; i < b1.size(); ++i)
|
||||
b1[i] &= m[i];
|
||||
return memcmp(&b1[0], &b2[0], b1.size());
|
||||
}
|
||||
#endif
|
||||
return (a1.to_v4().to_ulong() & mask.to_v4().to_ulong())
|
||||
== (a2.to_v4().to_ulong() & mask.to_v4().to_ulong());
|
||||
}
|
||||
|
||||
bool in_local_network(io_service& ios, address const& addr, error_code& ec)
|
||||
@@ -251,10 +316,56 @@ namespace libtorrent
|
||||
for (std::vector<ip_interface>::iterator i = net.begin()
|
||||
, end(net.end()); i != end; ++i)
|
||||
{
|
||||
if (in_subnet(addr, *i)) return true;
|
||||
if (match_addr_mask(addr, i->interface_address, i->netmask)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined TORRENT_WINDOWS || defined TORRENT_MINGW
|
||||
address build_netmask(int bits, int family)
|
||||
{
|
||||
if (family == AF_INET)
|
||||
{
|
||||
typedef asio::ip::address_v4::bytes_type bytes_t;
|
||||
bytes_t b;
|
||||
std::memset(&b[0], 0xff, b.size());
|
||||
for (int i = sizeof(bytes_t)/8-1; i > 0; --i)
|
||||
{
|
||||
if (bits < 8)
|
||||
{
|
||||
b[i] <<= bits;
|
||||
break;
|
||||
}
|
||||
b[i] = 0;
|
||||
bits -= 8;
|
||||
}
|
||||
return address_v4(b);
|
||||
}
|
||||
#if TORRENT_USE_IPV6
|
||||
else if (family == AF_INET6)
|
||||
{
|
||||
typedef asio::ip::address_v6::bytes_type bytes_t;
|
||||
bytes_t b;
|
||||
std::memset(&b[0], 0xff, b.size());
|
||||
for (int i = sizeof(bytes_t)/8-1; i > 0; --i)
|
||||
{
|
||||
if (bits < 8)
|
||||
{
|
||||
b[i] <<= bits;
|
||||
break;
|
||||
}
|
||||
b[i] = 0;
|
||||
bits -= 8;
|
||||
}
|
||||
return address_v6(b);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return address();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<ip_interface> enum_net_interfaces(io_service& ios, error_code& ec)
|
||||
{
|
||||
@@ -295,8 +406,20 @@ namespace libtorrent
|
||||
iface.interface_address = sockaddr_to_address(&item.ifr_addr);
|
||||
strcpy(iface.name, item.ifr_name);
|
||||
|
||||
ifreq netmask = item;
|
||||
if (ioctl(s, SIOCGIFNETMASK, &netmask) < 0)
|
||||
ifreq req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
strncpy(req.ifr_name, item.ifr_name, IF_NAMESIZE);
|
||||
if (ioctl(s, SIOCGIFMTU, &req) < 0)
|
||||
{
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
close(s);
|
||||
return ret;
|
||||
}
|
||||
iface.mtu = req.ifr_mtu;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
strncpy(req.ifr_name, item.ifr_name, IF_NAMESIZE);
|
||||
if (ioctl(s, SIOCGIFNETMASK, &req) < 0)
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
if (iface.interface_address.is_v6())
|
||||
@@ -314,7 +437,7 @@ namespace libtorrent
|
||||
}
|
||||
else
|
||||
{
|
||||
iface.netmask = sockaddr_to_address(&netmask.ifr_addr);
|
||||
iface.netmask = sockaddr_to_address(&req.ifr_addr, item.ifr_addr.sa_family);
|
||||
}
|
||||
ret.push_back(iface);
|
||||
}
|
||||
@@ -331,6 +454,65 @@ namespace libtorrent
|
||||
|
||||
#elif defined TORRENT_WINDOWS || defined TORRENT_MINGW
|
||||
|
||||
// Load Iphlpapi library
|
||||
HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
|
||||
if (iphlp)
|
||||
{
|
||||
// Get GetAdaptersAddresses() pointer
|
||||
typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG);
|
||||
GetAdaptersAddresses_t GetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(
|
||||
iphlp, "GetAdaptersAddresses");
|
||||
|
||||
if (GetAdaptersAddresses)
|
||||
{
|
||||
PIP_ADAPTER_ADDRESSES adapter_addresses = 0;
|
||||
ULONG out_buf_size = 0;
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER
|
||||
| GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &out_buf_size) != ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
FreeLibrary(iphlp);
|
||||
ec = asio::error::operation_not_supported;
|
||||
return std::vector<ip_interface>();
|
||||
}
|
||||
|
||||
adapter_addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_size);
|
||||
if (!adapter_addresses)
|
||||
{
|
||||
FreeLibrary(iphlp);
|
||||
ec = asio::error::no_memory;
|
||||
return std::vector<ip_interface>();
|
||||
}
|
||||
|
||||
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER
|
||||
| GAA_FLAG_SKIP_ANYCAST, NULL, adapter_addresses, &out_buf_size) == NO_ERROR)
|
||||
{
|
||||
for (PIP_ADAPTER_ADDRESSES adapter = adapter_addresses;
|
||||
adapter != 0; adapter = adapter->Next)
|
||||
{
|
||||
ip_interface r;
|
||||
strncpy(r.name, adapter->AdapterName, sizeof(r.name));
|
||||
r.name[sizeof(r.name)-1] = 0;
|
||||
r.mtu = adapter->Mtu;
|
||||
IP_ADAPTER_UNICAST_ADDRESS* unicast = adapter->FirstUnicastAddress;
|
||||
while (unicast)
|
||||
{
|
||||
r.interface_address = sockaddr_to_address(unicast->Address.lpSockaddr);
|
||||
|
||||
ret.push_back(r);
|
||||
|
||||
unicast = unicast->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free memory
|
||||
free(adapter_addresses);
|
||||
FreeLibrary(iphlp);
|
||||
return ret;
|
||||
}
|
||||
FreeLibrary(iphlp);
|
||||
}
|
||||
|
||||
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s == SOCKET_ERROR)
|
||||
{
|
||||
@@ -356,9 +538,11 @@ namespace libtorrent
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
iface.interface_address = sockaddr_to_address(&buffer[i].iiAddress.Address);
|
||||
iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address);
|
||||
iface.name[0] = 0;
|
||||
if (iface.interface_address == address_v4::any()) continue;
|
||||
iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address
|
||||
, iface.interface_address.is_v4() ? AF_INET : AF_INET6);
|
||||
iface.name[0] = 0;
|
||||
iface.mtu = 1500; // how to get the MTU?
|
||||
ret.push_back(iface);
|
||||
}
|
||||
|
||||
@@ -372,6 +556,7 @@ namespace libtorrent
|
||||
for (;i != udp::resolver_iterator(); ++i)
|
||||
{
|
||||
iface.interface_address = i->endpoint().address();
|
||||
iface.mtu = 1500;
|
||||
if (iface.interface_address.is_v4())
|
||||
iface.netmask = address_v4::netmask(iface.interface_address.to_v4());
|
||||
ret.push_back(iface);
|
||||
@@ -528,6 +713,12 @@ namespace libtorrent
|
||||
|
||||
char* end = buf.get() + needed;
|
||||
|
||||
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
{
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
rt_msghdr* rtm;
|
||||
for (char* next = buf.get(); next < end; next += rtm->rtm_msglen)
|
||||
{
|
||||
@@ -536,11 +727,13 @@ namespace libtorrent
|
||||
continue;
|
||||
|
||||
ip_route r;
|
||||
if (parse_route(rtm, &r)) ret.push_back(r);
|
||||
if (parse_route(s, rtm, &r)) ret.push_back(r);
|
||||
}
|
||||
close(s);
|
||||
|
||||
#elif defined TORRENT_WINDOWS || defined TORRENT_MINGW
|
||||
|
||||
/*
|
||||
move this to enum_net_interfaces
|
||||
// Load Iphlpapi library
|
||||
HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
|
||||
if (!iphlp)
|
||||
@@ -596,11 +789,109 @@ namespace libtorrent
|
||||
ret.push_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Free memory
|
||||
free(adapter_info);
|
||||
FreeLibrary(iphlp);
|
||||
*/
|
||||
|
||||
// Load Iphlpapi library
|
||||
HMODULE iphlp = LoadLibraryA("Iphlpapi.dll");
|
||||
if (!iphlp)
|
||||
{
|
||||
ec = asio::error::operation_not_supported;
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
typedef DWORD (WINAPI *GetIpForwardTable2_t)(
|
||||
ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2*);
|
||||
typedef void (WINAPI *FreeMibTable_t)(PVOID Memory);
|
||||
|
||||
GetIpForwardTable2_t GetIpForwardTable2 = (GetIpForwardTable2_t)GetProcAddress(
|
||||
iphlp, "GetIpForwardTable2");
|
||||
FreeMibTable_t FreeMibTable = (FreeMibTable_t)GetProcAddress(
|
||||
iphlp, "FreeMibTable");
|
||||
if (GetIpForwardTable2 && FreeMibTable)
|
||||
{
|
||||
MIB_IPFORWARD_TABLE2* routes = NULL;
|
||||
int res = GetIpForwardTable2(AF_UNSPEC, &routes);
|
||||
if (res == NO_ERROR)
|
||||
{
|
||||
for (int i = 0; i < routes->NumEntries; ++i)
|
||||
{
|
||||
ip_route r;
|
||||
r.gateway = sockaddr_to_address((const sockaddr*)&routes->Table[i].NextHop);
|
||||
r.destination = sockaddr_to_address(
|
||||
(const sockaddr*)&routes->Table[i].DestinationPrefix.Prefix);
|
||||
r.netmask = build_netmask(routes->Table[i].SitePrefixLength
|
||||
, routes->Table[i].DestinationPrefix.Prefix.si_family);
|
||||
MIB_IFROW ifentry;
|
||||
ifentry.dwIndex = routes->Table[i].InterfaceIndex;
|
||||
if (GetIfEntry(&ifentry) == NO_ERROR)
|
||||
{
|
||||
wcstombs(r.name, ifentry.wszName, sizeof(r.name));
|
||||
r.mtu = ifentry.dwMtu;
|
||||
ret.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (routes) FreeMibTable(routes);
|
||||
FreeLibrary(iphlp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get GetIpForwardTable() pointer
|
||||
typedef DWORD (WINAPI *GetIpForwardTable_t)(PMIB_IPFORWARDTABLE pIpForwardTable,PULONG pdwSize,BOOL bOrder);
|
||||
|
||||
GetIpForwardTable_t GetIpForwardTable = (GetIpForwardTable_t)GetProcAddress(
|
||||
iphlp, "GetIpForwardTable");
|
||||
if (!GetIpForwardTable)
|
||||
{
|
||||
FreeLibrary(iphlp);
|
||||
ec = asio::error::operation_not_supported;
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
MIB_IPFORWARDTABLE* routes = NULL;
|
||||
ULONG out_buf_size = 0;
|
||||
if (GetIpForwardTable(routes, &out_buf_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
FreeLibrary(iphlp);
|
||||
ec = asio::error::operation_not_supported;
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
routes = (MIB_IPFORWARDTABLE*)malloc(out_buf_size);
|
||||
if (!routes)
|
||||
{
|
||||
FreeLibrary(iphlp);
|
||||
ec = asio::error::no_memory;
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
if (GetIpForwardTable(routes, &out_buf_size, FALSE) == NO_ERROR)
|
||||
{
|
||||
for (int i = 0; i < routes->dwNumEntries; ++i)
|
||||
{
|
||||
ip_route r;
|
||||
r.destination = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardDest);
|
||||
r.netmask = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardMask);
|
||||
r.gateway = inaddr_to_address((in_addr const*)&routes->table[i].dwForwardNextHop);
|
||||
MIB_IFROW ifentry;
|
||||
ifentry.dwIndex = routes->table[i].dwForwardIfIndex;
|
||||
if (GetIfEntry(&ifentry) == NO_ERROR)
|
||||
{
|
||||
wcstombs(r.name, ifentry.wszName, sizeof(r.name));
|
||||
r.name[sizeof(r.name)-1] = 0;
|
||||
r.mtu = ifentry.dwMtu;
|
||||
ret.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free memory
|
||||
free(routes);
|
||||
FreeLibrary(iphlp);
|
||||
#elif defined TORRENT_LINUX
|
||||
|
||||
enum { BUFSIZE = 8192 };
|
||||
@@ -639,11 +930,18 @@ namespace libtorrent
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
|
||||
int s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
{
|
||||
ec = error_code(errno, asio::error::system_category);
|
||||
return std::vector<ip_route>();
|
||||
}
|
||||
for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len))
|
||||
{
|
||||
ip_route r;
|
||||
if (parse_route(nl_msg, &r)) ret.push_back(r);
|
||||
if (parse_route(s, nl_msg, &r)) ret.push_back(r);
|
||||
}
|
||||
close(s);
|
||||
close(sock);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user