Get destination address of a received UDP packet
Upon receiving a UDP packet, I need to respond to the sender with the address he used to send the packet to which I'm replying.
The recvfrom
call lets me get the address of the sender, but how do I get the destination address of the received packet, which should match the address of one of the local host's interfaces?
Solution 1:
I've constructed an example that extracts the source, destination and interface addresses. For brevity, no error checking is provided.
// sock is bound AF_INET socket, usually SOCK_DGRAM
// include struct in_pktinfo in the message "ancilliary" control data
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt));
// the control data is dumped here
char cmbuf[0x100];
// the remote/source sockaddr is put here
struct sockaddr_in peeraddr;
// if you want access to the data you need to init the msg_iovec fields
struct msghdr mh = {
.msg_name = &peeraddr,
.msg_namelen = sizeof(peeraddr),
.msg_control = cmbuf,
.msg_controllen = sizeof(cmbuf),
};
recvmsg(sock, &mh, 0);
for ( // iterate through all the control headers
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&mh, cmsg))
{
// ignore the control headers that don't match what we want
if (cmsg->cmsg_level != IPPROTO_IP ||
cmsg->cmsg_type != IP_PKTINFO)
{
continue;
}
struct in_pktinfo *pi = CMSG_DATA(cmsg);
// at this point, peeraddr is the source sockaddr
// pi->ipi_spec_dst is the destination in_addr
// pi->ipi_addr is the receiving interface in_addr
}
Solution 2:
You set the IP_PKTINFO option using setsockopt and then use recvmsg and get a in_pktinfo structure in the msg_control member of struct msghdr. the in_pktinfo has a field with the destination address of the packet.
See: http://www.linuxquestions.org/questions/programming-9/how-to-get-destination-address-of-udp-packet-600103/ where I found the answer for more details.