Subject: Re: Flag to exclude an interface from INADDR_ANY?
To: Michael Richardson <mcr@sandelman.ottawa.on.ca>
From: Andrew Brown <atatat@atatdot.net>
List: tech-net
Date: 01/03/2002 14:11:13
> Darren> Also, it would be nice if you could ask the kernel what address an
> Darren> incoming UDP packet had "connected" with.
>
> You can.
>
> You have to set a socket option and then use recvmsg(2). You get an
>additional sockaddr in the control structure. I can never remember the name
>of the option, or I'd point you right at it. I wish they were all documented
>on udp(4) or something. I can never find socket stuff with man :-(
that's IP_RECVDSTADDR. i usually just replace recvfrom() in my
programs with this piece of code.
ssize_t
recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from,
int *fromlen)
{
size_t rc;
struct msghdr msg;
u_char address[MYBUF];
struct iovec iov;
struct cmsghdr *cmsg;
void *cdata;
struct in_addr *i;
iov.iov_base = buf;
iov.iov_len = len;
msg.msg_name = (caddr_t)from;
msg.msg_namelen = (uint)*fromlen;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = address;
msg.msg_controllen = sizeof(address);
msg.msg_flags = 0;
if ((rc = recvmsg(s, &msg, flags)) != -1) {
/* "copy" this back to the caller */
*fromlen = msg.msg_namelen;
/* and arrange for IP_RECVDSTADDR to be available */
if (msg.msg_controllen > 0)
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
cdata = CMSG_DATA(cmsg);
if (cmsg->cmsg_type == IP_RECVDSTADDR) {
i = cdata;
to = *i;
}
}
}
return rc;
}
--
|-----< "CODE WARRIOR" >-----|
codewarrior@daemon.org * "ah! i see you have the internet
twofsonet@graffiti.com (Andrew Brown) that goes *ping*!"
andrew@crossbar.com * "information is power -- share the wealth."