Esempio n. 1
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. 2
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();
	}