Obtaining the local IP address of an unbound UDP socket
Sometimes one is finding an interesting problem and is surprised that there is not a multitude of blog post, stackoverflow answers or the like about it.
A (I think) not so uncommon problem when working with datagram sockets is that you may want to know the local IP address that the OS/kernel chooses when sending a packet to a given destination.
In an unbound UDP socket, you basically send and receive packets with
any number of peers from a single socket. When sending a packet to
destination Y, you simply pass the destination address/port into the
sendto()
socket function, and the OS/kernel will figure out which of
its local IP addresses will be used for reaching this particular
destination.
If you're a dumb host with a single default router, then the answer to that question is simple. But in any reasonably non-trivial use case, your host will have a variety of physical and/or virtual network devices with any number of addresses on them.
Why would you want to know that address? Because maybe you need to encode that address as part of a packet payload. In the current use case that we have, it is the OsmoMGW, implementing the IETF MGCP Media Gateway Control Protocol.
So what can you do? You can actually create a new "trial" socket, not
bind it to any specific local address/port, but connect()
it to the
destination of your IP packets. Then you do a getsockname()
, which
will give you the local address/port the kernel has selected for this
socket. And that's exactly the answer to your question. You can now
close the "trial" socket and have learned which local IP address the
kernel would use if you were to send a packet to that destination.
At least on Linux, this works. While getsockname()
is standard BSD
sockets API, I'm not sure how portable it is to use it on a socket that
has not been explicitly bound by a prior call to bind()
.