Obter endereço de destino de um pacote UDP recebido

Ao receber um pacote UDP, preciso responder ao remetente com o endereço que ele usou para enviar o pacote ao qual estou respondendo.

A chamada de recvfrom me permite obter o endereço do remetente, mas como obtenho o endereço de destino do pacote recebido, que deve corresponder ao endereço de uma das interfaces do host local?

Você configura a opção IP_PKTINFO usando setsockopt e, em seguida, usa recvmsg e obtém uma estrutura in_pktinfo no membro msg_control de struct msghdr. o in_pktinfo tem um campo com o endereço de destino do pacote.

Veja: http://www.linuxquestions.org/questions/programming-9/how-to-get-destination-address-of-udp-packet-600103/ onde encontrei a resposta para mais detalhes.

Eu construí um exemplo que extrai os endereços de origem, destino e interface. Por uma questão de brevidade, nenhuma verificação de erros é fornecida.

 // 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 }