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."