void get_available_address_v4(io_service& ios,std::set<address>& addrs) { addrs.clear(); error_code ec; std::vector<ip_interface> interfaces=enum_net_interfaces(ios,ec); address realBindAddr; for(std::size_t i=0;i<interfaces.size();++i) { if(is_loopback(interfaces[i].interface_address) ||is_any(interfaces[i].interface_address) ||interfaces[i].interface_address.is_v6() ) { continue; } //test can we bind this port endpoint edp(interfaces[i].interface_address,0); boost::asio::ip::tcp::socket tcpSocket(ios); tcpSocket.open(boost::asio::ip::tcp::v4(),ec); tcpSocket.bind(edp,ec); if (!ec&&!is_any(realBindAddr=tcpSocket.local_endpoint(ec).address())) { addrs.insert(realBindAddr); } else { addrs.erase(realBindAddr); } tcpSocket.close(ec); } }
// returns the device name whose local address is ``addr``. If // no such device is found, an empty string is returned. std::string device_for_address(address addr, io_service& ios, error_code& ec) { std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec); if (ec) return std::string(); for (int i = 0; i < int(ifs.size()); ++i) if (ifs[i].interface_address == addr) return ifs[i].name; return std::string(); }
// returns true if the given device exists bool has_interface(char const* name, io_service& ios, error_code& ec) { std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec); if (ec) return false; for (int i = 0; i < int(ifs.size()); ++i) if (ifs[i].name == name) return true; return false; }
tcp::endpoint utp_socket_manager::local_endpoint(address const& remote, error_code& ec) const { tcp::endpoint socket_ep = m_sock.local_endpoint(ec); // first enumerate the routes in the routing table if (time_now() - m_last_route_update > seconds(60)) { m_last_route_update = time_now(); error_code ec; m_routes = enum_routes(m_sock.get_io_service(), ec); if (ec) return socket_ep; } if (m_routes.empty()) return socket_ep; // then find the best match ip_route* best = &m_routes[0]; for (std::vector<ip_route>::iterator i = m_routes.begin() , end(m_routes.end()); i != end; ++i) { if (is_any(i->destination) && i->destination.is_v4() == remote.is_v4()) { best = &*i; continue; } if (match_addr_mask(remote, i->destination, i->netmask)) { best = &*i; continue; } } // best now tells us which interface we would send over // for this target. Now figure out what the local address // is for that interface if (time_now() - m_last_if_update > seconds(60)) { m_last_if_update = time_now(); error_code ec; m_interfaces = enum_net_interfaces(m_sock.get_io_service(), ec); if (ec) return socket_ep; } for (std::vector<ip_interface>::iterator i = m_interfaces.begin() , end(m_interfaces.end()); i != end; ++i) { if (i->interface_address.is_v4() != remote.is_v4()) continue; if (strcmp(best->name, i->name) == 0) return tcp::endpoint(i->interface_address, socket_ep.port()); } return socket_ep; }
address bind_to_device(io_service& ios, Socket& sock , bool ipv4, char const* device_name, int port, error_code& ec) { boost::asio::ip::tcp::endpoint bind_ep(address_v4::any(), port); address ip = address::from_string(device_name, ec); if (!ec) { bind_ep.address(ip); // it appears to be an IP. Just bind to that address sock.bind(bind_ep, ec); return bind_ep.address(); } ec.clear(); #ifdef SO_BINDTODEVICE // try to use SO_BINDTODEVICE here, if that exists. If it fails, // fall back to the mechanism we have below sock.set_option(bind_to_device_opt(device_name), ec); if (ec) #endif { ec.clear(); // TODO: 2 this could be done more efficiently by just looking up // the interface with the given name, maybe even with if_nametoindex() std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec); if (ec) return bind_ep.address(); bool found = false; for (int i = 0; i < int(ifs.size()); ++i) { // we're looking for a specific interface, and its address // (which must be of the same family as the address we're // connecting to) if (strcmp(ifs[i].name, device_name) != 0) continue; if (ifs[i].interface_address.is_v4() != ipv4) continue; bind_ep.address(ifs[i].interface_address); found = true; break; } if (!found) { ec = error_code(boost::system::errc::no_such_device, generic_category()); return bind_ep.address(); } } sock.bind(bind_ep, ec); return bind_ep.address(); }
bool in_local_network(io_service& ios, address const& addr, error_code& ec) { std::vector<ip_interface> net = enum_net_interfaces(ios, ec); if (ec) return false; for (std::vector<ip_interface>::iterator i = net.begin() , end(net.end()); i != end; ++i) { if (in_subnet(addr, *i)) return true; } return false; }
address bind_socket_to_device(io_service& ios, Socket& sock , boost::asio::ip::tcp const& protocol , char const* device_name, int port, error_code& ec) { tcp::endpoint bind_ep(address_v4::any(), std::uint16_t(port)); address ip = make_address(device_name, ec); if (!ec) { #if TORRENT_USE_IPV6 // this is to cover the case where "0.0.0.0" is considered any IPv4 or // IPv6 address. If we're asking to be bound to an IPv6 address and // providing 0.0.0.0 as the device, turn it into "::" if (ip == address_v4::any() && protocol == boost::asio::ip::tcp::v6()) ip = address_v6::any(); #endif bind_ep.address(ip); // it appears to be an IP. Just bind to that address sock.bind(bind_ep, ec); return bind_ep.address(); } ec.clear(); #if TORRENT_HAS_BINDTODEVICE // try to use SO_BINDTODEVICE here, if that exists. If it fails, // fall back to the mechanism we have below sock.set_option(aux::bind_to_device(device_name), ec); if (ec) #endif { ec.clear(); // TODO: 2 this could be done more efficiently by just looking up // the interface with the given name, maybe even with if_nametoindex() std::vector<ip_interface> ifs = enum_net_interfaces(ios, ec); if (ec) return bind_ep.address(); bool found = false; for (auto const& iface : ifs) { // we're looking for a specific interface, and its address // (which must be of the same family as the address we're // connecting to) if (std::strcmp(iface.name, device_name) != 0) continue; if (iface.interface_address.is_v4() != (protocol == boost::asio::ip::tcp::v4())) continue; bind_ep.address(iface.interface_address); found = true; break; } if (!found) { ec = error_code(boost::system::errc::no_such_device, generic_category()); return bind_ep.address(); } } sock.bind(bind_ep, ec); return bind_ep.address(); }