Reputation: 451
How can I bind a socket to a particular network interface? I tried using setsockopt
on server side, but the clients can still access the service through both eth0 and lo interfaces.
I can achieve this by setting the particular IP address using serv_addr.sin_addr.s_addr
.
But I suspect that we can bind to an interface using only setsockopt
(without mentioning the IP address).
Upvotes: 31
Views: 67139
Reputation: 6568
You can bind to a specific interface by setting SO_BINDTODEVICE
socket option.
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth0");
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
... error handling ...
}
Warning: You have to be root or have the CAP_NET_RAW
capability in order to use this option.
The second method is that you can resolv IP address tied to an interface with getifaddrs().
Follow the latter link for a comprehensive example.
Upvotes: 46
Reputation: 31
Maybe someone will find it useful, so I am sharing the solution that worked for me (Linux, C++):
uint32_t interfaceIndex = if_nametoindex(interfaceName);
Where "interfaceName" is the name of the interface we want to bind to, e.g. "eth0" (see: https://linux.die.net/man/3/if_nametoindex). Now we can specify this interface in the socket address structure via "sin6_scope_id" (in case we use IPv6):
struct sockaddr_in6 socketAddress;
socketAddress.sin6_scope_id = interfaceIndex;
Now we can bind the socket to the interface via "bind" as usual.
Upvotes: 2
Reputation: 7818
The only way you can do it is as you mention -
by setting the particular IP address using
serv_addr.sin_addr.s_addr
You can't do it without knowing the address to bind to.
You can use ioctl
s to determine the current IP address if you need, though there may be a cleverer way to do this these days - I've not done much in modern Linux distros lately.
Upvotes: 3