I have a UDP socket that is bound to INADDR_ANY to listen to packets on all the IPs my server has. I’m sending out replies through the same socket.
Right now the server chooses automatically which IP is used as the source IP when packets are sent out, but I would like to be able to set the outgoing source IP myself.
Is there any way to do that without having to create a separate socket for each IP ?
Nikolai, using a separate socket and bind(2) for each address or messing with routing tables is often not a feasible option e.g. with dynamic addresses. A single
IP_ADDRANY-bound UDP server should be able to appear to respond on the same dynamically-assigned IP address a packet is received on.Luckily, there is another way. Depending on your system’s support you can make use of the
IP_PKTINFOsocket options to set or receive ancillary data about a message. Ancillary data (viacmsg(3)) is covered in many places online though comp.os.linux.development.system had a full code sample specific toIP_PKTINFO.The code in the link uses
IP_PKTINFO(orIP_RECVDSTADDRdepending on the platform) to get the destination address of a UDP message from the ancillarycmsg(3)data. Paraphrased here:Gene, your question asked how to set the source address on outgoing packets. With
IP_PKTINFOit is possible to set theipi_spec_dstfield of thestruct in_pktinfoin the ancillary data passed tosendmsg(2). See the post referenced above,cmsg(3), andsendmsg(2)for guidelines on how to create and manipulate the ancillary data in astruct msghdr. An example (no guarantee here) might be:Note this is different in IPv6: use
struct in6_pktinfo::ipi6_addrin both the recvmsg and sendmsg cases.Note also that Windows does not support an equivalent to ipi_spec_dst in the in_pktinfo struct, so you cannot use this method to set the source address on an outgoing winsock2 packet.
(man pages referenced – getting around 1 hyperlink limit)