> Does anyone know how to get the destination address on incoming UDP
> packets?
This is covered in the bible: _UNIX Network Programming_, Volume 1,
by W. Richard Stevens; see Section 20.2 for an example of how to
do this with recvmsg().  Or google for something like "UDP destination
address recvmsg".
-- 
Michael Fuhr
http://www.fuhr.org/~mfuhr/
> mf...@fuhr.org (Michael Fuhr) wrote in message news:<3fb57b91$1...@omega.dimensional.com>...
> > coleman...@aamatrix.com (Coleman Brumley) writes:
> > 
> > > Does anyone know how to get the destination address on incoming UDP
> > > packets?
> > 
> > This is covered in the bible: _UNIX Network Programming_, Volume 1,
> > by W. Richard Stevens; see Section 20.2 for an example of how to
> > do this with recvmsg().  Or google for something like "UDP destination
> > address recvmsg".
>
> I came accross information about using recvmsg with the IP_RECVDSTADDR
> socket option set.
>
> I read that IP_RECVDSTADDR (or IP_RECVIF) isn't supported by Linux.  A
> grep of header files shows this constant doesn't exist.
On Linux I've used the IP_PKTINFO socket option.  I usually write
code that must run on multiple platforms, so I use something like
this:
#if defined IP_RECVDSTADDR 
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
# define dstaddr(x) (CMSG_DATA(x))
#elif defined IP_PKTINFO
# define DSTADDR_SOCKOPT IP_PKTINFO
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
#endif
In the tests I've done, this code correctly returns the destination
IP address, whether unicast or broadcast.
> mf...@fuhr.org (Michael Fuhr) wrote in message news:<3fb66...@omega.dimensional.com>...
>
> > #if defined IP_RECVDSTADDR 
> > # define DSTADDR_SOCKOPT IP_RECVDSTADDR
> > # define dstaddr(x) (CMSG_DATA(x))
> > #elif defined IP_PKTINFO
> > # define DSTADDR_SOCKOPT IP_PKTINFO
> > # define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
> > #endif
[snip]
> Would you be be able to expand upon this code a bit?  Specifically,
> can you give me an example of using your dstaddr macro?  What get's
> passes as x?
Here's a simple example:
for (cmsgptr = CMSG_FIRSTHDR(&msg);
     cmsgptr != NULL;
     cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
    if (cmsgptr->cmsg_level == IPPROTO_IP &&
        cmsgptr->cmsg_type == DSTADDR_SOCKOPT) {
printf("destination: %s\n", inet_ntoa(*dstaddr(cmsgptr)));
> mf...@fuhr.org (Michael Fuhr) wrote in message news:<3fb7be41$1...@omega.dimensional.com>...
>
> > for (cmsgptr = CMSG_FIRSTHDR(&msg);
> >      cmsgptr != NULL;
> >      cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
> > 
> >     if (cmsgptr->cmsg_level == IPPROTO_IP &&
> >         cmsgptr->cmsg_type == DSTADDR_SOCKOPT) {
> > 
> >         printf("destination: %s\n", inet_ntoa(*dstaddr(cmsgptr)));
> >     }
> > }
>
> Ok, after looking at the man pages for cmsg and recvmsg, I can see how
> to get to this information via the msghdr structure.  I'm guessing
> that I can just PEEK at the incoming mesg using recvmsg and then do
> the cmsg/dstaddr thing from above?
You could use MSG_PEEK if you don't want to read the data yet, or
you could read the data and do whatever you want with it.
> Is there anything special I have to do to the socket for this to work?
>  I'm opening the socket using:
> sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> ...
> bind(sock_fd, ...);
>
> I would also guess that I'll need to do setsockopt(DSTADDR_SOCKOPT)?
Yep, with a level of IPPROTO_IP.
> Ok, I'm at a loss.  I did all this, and still nothing.  I'm not sure
> if I'm setting up my socket correctly, though.  Is there something I'm
> doing wrong here?
Below is a complete program that prints the received packet's
destination IP address.  I just wrote it based on some other code
I have and haven't checked it thoroughly for subtle bugs, but in
simple tests it worked on both Linux and FreeBSD.  Hopefully it
will answer any remaining questions you have.
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LISTEN_PORT     12345
#define BUFSIZE         1024
#if defined IP_RECVDSTADDR
# define DSTADDR_SOCKOPT IP_RECVDSTADDR
# define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_addr)))
# define dstaddr(x) (CMSG_DATA(x))
#elif defined IP_PKTINFO
# define DSTADDR_SOCKOPT IP_PKTINFO
# define DSTADDR_DATASIZE (CMSG_SPACE(sizeof(struct in_pktinfo)))
# define dstaddr(x) (&(((struct in_pktinfo *)(CMSG_DATA(x)))->ipi_addr))
#else
# error "can't determine socket option"
#endif
union control_data {
    struct cmsghdr  cmsg;
    u_char          data[DSTADDR_DATASIZE];
};
int
main(void)
{
    int                 sock;
    int                 sockopt;
    struct sockaddr_in  srvaddr;
    struct sockaddr_in  cliaddr;
    struct msghdr       msg;
    union control_data  cmsg;
    struct cmsghdr     *cmsgptr;
    struct iovec        iov[1];
    ssize_t             nbytes;
    char                buf[BUFSIZE];
setbuf(stdout, NULL);
    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    sockopt = 1;
    if (setsockopt(sock, IPPROTO_IP, DSTADDR_SOCKOPT, &sockopt, sizeof sockopt) == -1) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    memset(&srvaddr, 0, sizeof srvaddr);
    srvaddr.sin_family      = AF_INET;
    srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    srvaddr.sin_port        = htons(LISTEN_PORT);
    if (bind(sock, (struct sockaddr *)&srvaddr, sizeof srvaddr) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    iov[0].iov_base = buf;
    iov[0].iov_len  = sizeof buf;
    memset(&msg, 0, sizeof msg);
    msg.msg_name       = &cliaddr;
    msg.msg_namelen    = sizeof cliaddr;
    msg.msg_iov        = iov;
    msg.msg_iovlen     = 1;
    msg.msg_control    = &cmsg;
    msg.msg_controllen = sizeof cmsg;
    for (;;) {
        printf("recvmsg...");
        nbytes = recvmsg(sock, &msg, 0);
        if (nbytes == -1) {
            perror("recvfrom");
            exit(EXIT_FAILURE);
        }
        printf("%ld bytes ", (long)nbytes);
        printf("from %s:%hu ", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
        for (cmsgptr = CMSG_FIRSTHDR(&msg);
             cmsgptr != NULL;
             cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
            if (cmsgptr->cmsg_level == IPPROTO_IP &&
                cmsgptr->cmsg_type == DSTADDR_SOCKOPT) {
                printf("to %s", inet_ntoa(*(struct in_addr *)dstaddr(cmsgptr)));
            }
        }
        putchar('\n');
    }
    /*NOTREACHED*/
    return EXIT_SUCCESS;