address read_v6_address(InIt&& in) { address_v6::bytes_type bytes; for (auto& b : bytes) b = read_uint8(in); return address_v6(bytes); }
address external_ip::external_address(address const& ip) const { address ext = m_vote_group[ip.is_v6()].external_address(); #if TORRENT_USE_IPV6 if (ip.is_v6() && ext == address_v4()) return address_v6(); #endif return ext; }
address observer::target_addr() const { #if TORRENT_USE_IPV6 if (flags & flag_ipv6_address) return address_v6(m_addr.v6); else #endif return address_v4(m_addr.v4); }
tcp::endpoint peer() const { #if TORRENT_USE_IPV6 if (is_v6_addr) return tcp::endpoint(address_v6(addr.v6), port); else #endif return tcp::endpoint(address_v4(addr.v4), port); }
address read_v6_address(InIt& in) { typedef address_v6::bytes_type bytes_t; bytes_t bytes; for (bytes_t::iterator i = bytes.begin() , end(bytes.end()); i != end; ++i) *i = read_uint8(in); return address_v6(bytes); }
libtorrent::address address() const { #if TORRENT_USE_IPV6 if (v4) return address_v4(addr.v4); else return address_v6(addr.v6); #else return address_v4(addr.v4); #endif }
operator udp::endpoint() const { #if TORRENT_USE_IPV6 if (v4) return udp::endpoint(address_v4(addr.v4), port); else return udp::endpoint(address_v6(addr.v6), port); #else return udp::endpoint(address_v4(addr.v4), port); #endif }
inline address_v6 mproto::endpoint::address() const { address_v6::bytes_type tmp; std::copy(_addr.sin6_addr.s6_addr, _addr.sin6_addr.s6_addr + tmp.size(), tmp.begin()); return address_v6(tmp, _addr.sin6_scope_id); }
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(); } }
static address any() { return address_v6(); }
bool rpc_manager::incoming(msg const& m, node_id* id) { INVARIANT_CHECK; if (m_destructing) return false; // we only deal with replies, not queries TORRENT_ASSERT(m.message.dict_find_string_value("y") == "r"); // if we don't have the transaction id in our // request list, ignore the packet std::string transaction_id = m.message.dict_find_string_value("t"); std::string::const_iterator i = transaction_id.begin(); int tid = transaction_id.size() != 2 ? -1 : io::read_uint16(i); observer_ptr o; for (transactions_t::iterator i = m_transactions.begin() , end(m_transactions.end()); i != end; ++i) { TORRENT_ASSERT(*i); if ((*i)->transaction_id() != tid) continue; if (m.addr.address() != (*i)->target_addr()) continue; o = *i; m_transactions.erase(i); break; } if (!o) { #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(rpc) << "Reply with invalid transaction id size: " << transaction_id.size() << " from " << m.addr; #endif entry e; incoming_error(e, "invalid transaction id"); m_send(m_userdata, e, m.addr, 0); return false; } #ifdef TORRENT_DHT_VERBOSE_LOGGING std::ofstream reply_stats("round_trip_ms.log", std::ios::app); reply_stats << m.addr << "\t" << total_milliseconds(time_now_hires() - o->sent()) << std::endl; #endif lazy_entry const* ret_ent = m.message.dict_find_dict("r"); if (ret_ent == 0) { entry e; incoming_error(e, "missing 'r' key"); m_send(m_userdata, e, m.addr, 0); return false; } lazy_entry const* node_id_ent = ret_ent->dict_find_string("id"); if (node_id_ent == 0 || node_id_ent->string_length() != 20) { entry e; incoming_error(e, "missing 'id' key"); m_send(m_userdata, e, m.addr, 0); return false; } lazy_entry const* ext_ip = ret_ent->dict_find_string("ip"); if (ext_ip && ext_ip->string_length() == 4) { // this node claims we use the wrong node-ID! address_v4::bytes_type b; memcpy(&b[0], ext_ip->string_ptr(), 4); m_ext_ip(address_v4(b), aux::session_impl::source_dht, m.addr.address()); } #if TORRENT_USE_IPV6 else if (ext_ip && ext_ip->string_length() == 16) { // this node claims we use the wrong node-ID! address_v6::bytes_type b; memcpy(&b[0], ext_ip->string_ptr(), 16); m_ext_ip(address_v6(b), aux::session_impl::source_dht, m.addr.address()); } #endif #ifdef TORRENT_DHT_VERBOSE_LOGGING TORRENT_LOG(rpc) << "[" << o->m_algorithm.get() << "] Reply with transaction id: " << tid << " from " << m.addr; #endif o->reply(m); *id = node_id(node_id_ent->string_ptr()); // we found an observer for this reply, hence the node is not spoofing // add it to the routing table return m_table.node_seen(*id, m.addr); }
std::vector<ip_route> enum_routes(io_service& ios, error_code& ec) { std::vector<ip_route> ret; TORRENT_UNUSED(ios); #ifdef TORRENT_BUILD_SIMULATOR TORRENT_UNUSED(ec); std::vector<address> ips = ios.get_ips(); for (int i = 0; i < int(ips.size()); ++i) { ip_route r; if (ips[i].is_v4()) { r.destination = address_v4(); r.netmask = address_v4::from_string("255.255.255.0"); address_v4::bytes_type b = ips[i].to_v4().to_bytes(); b[3] = 1; r.gateway = address_v4(b); } else { r.destination = address_v6(); r.netmask = address_v6::from_string("FFFF:FFFF:FFFF:FFFF::0"); address_v6::bytes_type b = ips[i].to_v6().to_bytes(); b[14] = 1; r.gateway = address_v6(b); } strcpy(r.name, "eth0"); r.mtu = ios.sim().config().path_mtu(ips[i], ips[i]); ret.push_back(r); } #elif TORRENT_USE_SYSCTL /* struct rt_msg { rt_msghdr m_rtm; char buf[512]; }; rt_msg m; int len = sizeof(rt_msg); bzero(&m, len); m.m_rtm.rtm_type = RTM_GET; m.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY; m.m_rtm.rtm_version = RTM_VERSION; m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; m.m_rtm.rtm_seq = 0; m.m_rtm.rtm_msglen = len; int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); if (s == -1) { ec = error_code(errno, boost::asio::error::system_category); return std::vector<ip_route>(); } int n = write(s, &m, len); if (n == -1) { ec = error_code(errno, boost::asio::error::system_category); close(s); return std::vector<ip_route>(); } else if (n != len) { ec = boost::asio::error::operation_not_supported; close(s); return std::vector<ip_route>(); } bzero(&m, len); n = read(s, &m, len); if (n == -1) { ec = error_code(errno, boost::asio::error::system_category); close(s); return std::vector<ip_route>(); } for (rt_msghdr* ptr = &m.m_rtm; (char*)ptr < ((char*)&m.m_rtm) + n; ptr = (rt_msghdr*)(((char*)ptr) + ptr->rtm_msglen)) { std::cout << " rtm_msglen: " << ptr->rtm_msglen << std::endl; std::cout << " rtm_type: " << ptr->rtm_type << std::endl; if (ptr->rtm_errno) { ec = error_code(ptr->rtm_errno, boost::asio::error::system_category); return std::vector<ip_route>(); } if (m.m_rtm.rtm_flags & RTF_UP == 0 || m.m_rtm.rtm_flags & RTF_GATEWAY == 0) { ec = boost::asio::error::operation_not_supported; return address_v4::any(); } if (ptr->rtm_addrs & RTA_DST == 0 || ptr->rtm_addrs & RTA_GATEWAY == 0 || ptr->rtm_addrs & RTA_NETMASK == 0) { ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } if (ptr->rtm_msglen > len - ((char*)ptr - ((char*)&m.m_rtm))) { ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } int min_len = sizeof(rt_msghdr) + 2 * sizeof(sockaddr_in); if (m.m_rtm.rtm_msglen < min_len) { ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } ip_route r; // destination char* p = m.buf; sockaddr_in* sin = (sockaddr_in*)p; r.destination = sockaddr_to_address((sockaddr*)p); // gateway p += sin->sin_len; sin = (sockaddr_in*)p; r.gateway = sockaddr_to_address((sockaddr*)p); // netmask p += sin->sin_len; sin = (sockaddr_in*)p; r.netmask = sockaddr_to_address((sockaddr*)p); ret.push_back(r); } close(s); */ int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0}; size_t needed = 0; #ifdef TORRENT_OS2 if (__libsocket_sysctl(mib, 6, 0, &needed, 0, 0) < 0) #else if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) #endif { ec = error_code(errno, boost::asio::error::system_category); return std::vector<ip_route>(); } if (needed <= 0) { return std::vector<ip_route>(); } boost::scoped_array<char> buf(new (std::nothrow) char[needed]); if (buf.get() == 0) { ec = boost::asio::error::no_memory; return std::vector<ip_route>(); } #ifdef TORRENT_OS2 if (__libsocket_sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0) #else if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0) #endif { ec = error_code(errno, boost::asio::error::system_category); return std::vector<ip_route>(); } char* end = buf.get() + needed; int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { ec = error_code(errno, boost::asio::error::system_category); return std::vector<ip_route>(); } rt_msghdr* rtm; for (char* next = buf.get(); next < end; next += rtm->rtm_msglen) { rtm = reinterpret_cast<rt_msghdr*>(next); if (rtm->rtm_version != RTM_VERSION) continue; ip_route r; if (parse_route(s, rtm, &r)) ret.push_back(r); } close(s); #elif TORRENT_USE_GETIPFORWARDTABLE /* move this to enum_net_interfaces // Load Iphlpapi library HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); if (!iphlp) { ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } // Get GetAdaptersInfo() pointer typedef DWORD (WINAPI *GetAdaptersInfo_t)(PIP_ADAPTER_INFO, PULONG); GetAdaptersInfo_t GetAdaptersInfo = (GetAdaptersInfo_t)GetProcAddress(iphlp, "GetAdaptersInfo"); if (!GetAdaptersInfo) { FreeLibrary(iphlp); ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } PIP_ADAPTER_INFO adapter_info = 0; ULONG out_buf_size = 0; if (GetAdaptersInfo(adapter_info, &out_buf_size) != ERROR_BUFFER_OVERFLOW) { FreeLibrary(iphlp); ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } adapter_info = (IP_ADAPTER_INFO*)malloc(out_buf_size); if (!adapter_info) { FreeLibrary(iphlp); ec = boost::asio::error::no_memory; return std::vector<ip_route>(); } if (GetAdaptersInfo(adapter_info, &out_buf_size) == NO_ERROR) { for (PIP_ADAPTER_INFO adapter = adapter_info; adapter != 0; adapter = adapter->Next) { ip_route r; r.destination = address::from_string(adapter->IpAddressList.IpAddress.String, ec); r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec); r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec); strncpy(r.name, adapter->AdapterName, sizeof(r.name)); if (ec) { ec = error_code(); continue; } ret.push_back(r); } } // Free memory free(adapter_info); FreeLibrary(iphlp); */ // Load Iphlpapi library HMODULE iphlp = LoadLibraryA("Iphlpapi.dll"); if (!iphlp) { ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } typedef DWORD (WINAPI *GetIfEntry_t)(PMIB_IFROW pIfRow); GetIfEntry_t GetIfEntry = (GetIfEntry_t)GetProcAddress(iphlp, "GetIfEntry"); if (!GetIfEntry) { ec = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } #if _WIN32_WINNT >= 0x0600 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; } #endif // 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 = boost::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 = boost::asio::error::operation_not_supported; return std::vector<ip_route>(); } routes = (MIB_IPFORWARDTABLE*)malloc(out_buf_size); if (!routes) { FreeLibrary(iphlp); ec = boost::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 TORRENT_USE_NETLINK enum { BUFSIZE = 8192 }; int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE); if (sock < 0) { ec = error_code(errno, boost::asio::error::system_category); return std::vector<ip_route>(); } int seq = 0; char msg[BUFSIZE]; memset(msg, 0, BUFSIZE); nlmsghdr* nl_msg = (nlmsghdr*)msg; nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg)); nl_msg->nlmsg_type = RTM_GETROUTE; nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nl_msg->nlmsg_seq = seq++; nl_msg->nlmsg_pid = getpid(); if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0) { ec = error_code(errno, boost::asio::error::system_category); close(sock); return std::vector<ip_route>(); } int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid()); if (len < 0) { ec = error_code(errno, boost::asio::error::system_category); close(sock); return std::vector<ip_route>(); } int s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { ec = error_code(errno, boost::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(s, nl_msg, &r)) ret.push_back(r); } close(s); close(sock); #endif return ret; }
/** * @relates address_v6 */ inline address_v6 make_address_v6(const address_v6::bytes_type& bytes, unsigned long scope_id = 0) { return address_v6(bytes, scope_id); }
BOOST_FIXTURE_TEST_CASE(Tcp, ResolverFixture<tcp>) { TcpResolver::asyncResolve("www.named-data.net", "6363", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v4(), 6363), true, false), bind(&ResolverFixture<tcp>::onFailure, this, false)); TcpResolver::asyncResolve("www.named-data.net", "notport", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v4(), 0), false, false), bind(&ResolverFixture<tcp>::onFailure, this, true)); // should fail TcpResolver::asyncResolve("nothost.nothost.nothost.arpa", "6363", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v4(), 6363), false, false), bind(&ResolverFixture<tcp>::onFailure, this, true)); // should fail TcpResolver::asyncResolve("www.google.com", "80", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v4(), 80), true, false), bind(&ResolverFixture<tcp>::onFailure, this, false), resolver::Ipv4Address()); // request IPv4 address TcpResolver::asyncResolve("www.google.com", "80", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v6(), 80), true, false), bind(&ResolverFixture<tcp>::onFailure, this, false), resolver::Ipv6Address()); // request IPv6 address TcpResolver::asyncResolve("ipv6.google.com", "80", // only IPv6 address should be available bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v6(), 80), true, false), bind(&ResolverFixture<tcp>::onFailure, this, false)); TcpResolver::asyncResolve("ipv6.google.com", "80", // only IPv6 address should be available bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v6(), 80), true, false), bind(&ResolverFixture<tcp>::onFailure, this, false), resolver::Ipv6Address()); TcpResolver::asyncResolve("ipv6.google.com", "80", // only IPv6 address should be available bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v6(), 80), false, false), bind(&ResolverFixture<tcp>::onFailure, this, true), // should fail resolver::Ipv4Address()); TcpResolver::asyncResolve("192.0.2.1", "80", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v4::from_string("192.0.2.1"), 80), true, true), bind(&ResolverFixture<tcp>::onFailure, this, false)); TcpResolver::asyncResolve("2001:db8:3f9:0:3025:ccc5:eeeb:86d3", "80", bind(&ResolverFixture<tcp>::onSuccess, this, _1, tcp::endpoint(address_v6:: from_string("2001:db8:3f9:0:3025:ccc5:eeeb:86d3"), 80), true, true), bind(&ResolverFixture<tcp>::onFailure, this, false)); g_io.run(); BOOST_CHECK_EQUAL(m_nFailures, 3); BOOST_CHECK_EQUAL(m_nSuccesses, 7); }
operator address() const { if (v4) return address(address_v4(addr.v4)); else return address(address_v6(addr.v6)); }
std::pair<address,int> ipport_from_string(const std::string&ipPortStr) { std::string ipStr,portStr; const size_t first=ipPortStr.find_first_of(':'); const size_t last=(first==std::string::npos ?std::string::npos : ipPortStr.find_last_of(':',first+1) ); bool v6=false; if (first!=std::string::npos) { const size_t posR=ipPortStr.find_first_of(']'); const size_t posL=ipPortStr.find_first_of('['); if (last!=first ||posR!=std::string::npos ||posL!=std::string::npos )//is ipv6? { if (posR!=std::string::npos&&posL==std::string::npos ||posR==std::string::npos&&posL!=std::string::npos ||posL>posR ) { return std::pair<address,int>(address(),0);//error format } v6=true; if (posR!=std::string::npos)//[ip]:port { BOOST_ASSERT(posL!=std::string::npos&&posR>posL); ipStr=ipPortStr.substr(posL+1,posR-posL-1); if (last>posR&&last!=std::string::npos&&last+1<ipPortStr.size()) portStr=ipPortStr.substr(last+1); } else// only ip { ipStr=ipPortStr; } } else//is ipv4? { ipStr=ipPortStr.substr(0,last); if (last+1<ipPortStr.size()) portStr=ipPortStr.substr(last+1); } } else { const size_t pos=ipPortStr.find_first_of(']'); if (pos!=std::string::npos)//[] { v6=true; if (ipPortStr[0]=='[') ipStr=ipPortStr.substr(1,pos); else return std::pair<address,int>(address(),0);//error format if (pos+1<ipPortStr.size()) portStr=ipPortStr.substr(pos+1); if (boost::iequals(ipStr,"localhost")||boost::iequals(ipStr,"loopback")) { ipStr="::1"; } } else// only ip { ipStr=ipPortStr; } ipStr=ipPortStr; } error_code ec; if (ipStr.empty()) { if (v6) ipStr=address_v6().to_string(ec); else ipStr=address_v4().to_string(ec); } if (boost::iequals(ipStr,"localhost")||boost::iequals(ipStr,"loopback")) { if (v6) ipStr=address_v6::loopback().to_string(ec); else ipStr=address_v4::loopback().to_string(ec); } int port=0; if (!portStr.empty()) port=atoi(portStr.c_str()); if (v6) return std::pair<address,int>(address_v6::from_string(ipStr,ec),port); else return std::pair<address,int>(address_v4::from_string(ipStr,ec),port); }