Search code examples
c++socketsboostboost-asio

boost::asio - is it possible to bind to a local device (equivalent of SO_BINDTODEVICE) rather than local address?


I would like to bind to a local interface, eg "eth0", using boost::asio.

The equivalent code using the low level socket interface would be:

const std::string ifc = "eth0";

struct ifreq ifr;
bzero(&ifr, sizeof(ifr));
memcpy(ifr.ifr_name, ifc.c_str(), ifc.length());
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, static_cast<void*>(&ifr), sizeof(ifr)) < 0)
{
    throw std::runtime_error("bind to local interface failed");
}

However, when I attempt to pass a local interface to the boost::asio::ip::tcp::resolver, it can't resolve it:

using tcp = boost::asio::ip::tcp;

const std::string ifc = "eth0";

auto ctx = socket.get_executor();
tcp::resolver resolver(ctx);
tcp::resolver::results_type results = resolver.resolve(ifc, "");

This throws an exception, with description "Host not found (authoritative)"

By the content of the error message it does sound like it's attempting to resolve the interface as a host address.

Is it possible to do the equivalent of SO_BINDTODEVICE using boost::asio?


Solution

  • Is it possible to do the equivalent of SO_BINDTODEVICE using boost::asio?

    No, but you can use the option like you're used to.

    if (setsockopt(socket.native_handle(), SOL_SOCKET, SO_BINDTODEVICE, static_cast<void*>(&ifr), sizeof(ifr)) < 0)
    

    You could also define your own custom option to make it "prettier", but I would probably only do this if this is somehow oft-repeating code.