Esempio n. 1
0
	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);
		}
	}
Esempio n. 2
0
	// 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();
	}
Esempio n. 3
0
	// 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;
	}
Esempio n. 4
0
	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;
	}
Esempio n. 5
0
	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();
	}
Esempio n. 6
0
	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;
	}
Esempio n. 7
0
	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();
	}