Reputation: 63
My application has opened an UDP socket that is bound to INADDR_ANY to listen to packets on all the interfaces my server has. I'm sending out replies through the same socket.
However, while sending a reply from the server, default IP is chosen by the IP layer of linux depending upon which interface is chosen for packet to going out. The IP associated with this interface may not be the destination address with which this UDP server got a query from a client. Thus source IP of the reply from server becomes different from the destination IP with which the query came. The client may be uncomfortable with such a reply.
Following link gives the behavior of INADDR_ANY with UDP: http://www.cs.cmu.edu/~srini/15-441/F01.full/www/assignments/P2/htmlsim_split/node18.html
How can I change this default behavior and use a particular interface IP in the source address? That is more control on the application code to decide what will be the source address. Also it make sense that source address in the reply be same as the destination address with which the query came.
Upvotes: 2
Views: 4025
Reputation: 2953
Once a socket is bound to an address you can not bind it again to another address or you will get error EINVAL
. But there is another technique described in this post Setting the source IP for a UDP socket
Upvotes: 0
Reputation: 5535
Assuming you have multiple interfaces (one of which has the correct ip) of course you can bind to an interface for outgoing response. Take a look at SO_BINDTODEVICE socket option.
int bind_sock2inf(int sock, char *interface_name)
{
int status = -1;
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), interface_name);
if ( (status = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
(void *)&ifr, sizeof(ifr))) < 0) {
log_debug(4, "Failed binding to interface named %s", inf_name);
}
else log_debug(3, "Binding to interface %s", inf_name);
return status;
}
Now your outgoing request should automatically use the ip address attached to this interface. The only down side is that you stop receiving messages on any other interface for this socket.
Possible work arounds are:
Use a separate socket for listening which is not bound to any interface and another one for sending and bind to whatever interface you need before sending.
Bind to interface before sending a message and bind to "" again which clears the previous bind immediately after sending. However, you might loose any packets received during this time frame which your socket was bound to interface say eth0 and packets arrived at eth1.
Also you can simply use bind() for associating a source ip for an outgoing packet.
Upvotes: 1