Bruce M. Simpson wrote:

Dealing with dhclient is a separate issue -- here, something like IP_SENDIF needs to be introduced, as we are truly in an 'ip unnumbered' situation -- ie the ifnet MAY not yet have been assigned an IPv4 address at all, and IP_SENDSRCADDR implies that you are source routing in the local stack by passing the address of a numbered interface
I have just committed a change in bms_netdev which enforces strict
and better defined semantics for the IP_SENDSRCADDR option in udp_output().

This fits one of the main intended use cases of this option, e.g. a routing
daemon, bound to 0.0.0.0 and a non-ephemeral port, which needs to
explicitly override the hard-coded source selection policy in ip_output()
to send an undirected broadcast on a numbered interface.

It also fits a use case whereby a bound socket may wish to temporarily
ask for default source selection policy by specifying INADDR_ANY, although
this needs to be reviewed and tested further; I believe in_pcbbind_setup()
will detect a collision in this case.

We always obtain the inp_info write lock if IP_SENDSRCADDR was specified,
in case we need to temporarily re-bind laddr.

Pseudo-conditions as follows.

IP_SENDSRCADDR with lport NOT BOUND is NOT OK.
We should never try to persistently bind a socket which is not bound unless
we are bind(2).

IP_SENDSRCADDR with !INADDR_ANY when laddr is NOT BOUND is OK.
It means override the source selection logic and use src.sin_addr instead.

IP_SENDSRCADDR with INADDR_ANY when laddr is BOUND is OK; it
It means override the bound address and use source selection logic instead.

IP_SENDSRCADDR with INADDR_ANY when laddr is BOUND is OK.
It means override the bound address and use source selection logic instead.

IP_SENDSRCADDR with INADDR_ANY when laddr is NOT BOUND is NOT OK.
It means no valid source is specified.


Regards,
BMS
--- //depot/vendor/freebsd/src/sys/netinet/udp_usrreq.c	2007/02/20 10:22:30
+++ //depot/user/bms/netdev/sys/netinet/udp_usrreq.c	2007/03/07 12:28:16
@@ -747,7 +747,8 @@
 		return (EMSGSIZE);
 	}
 
-	src.sin_addr.s_addr = INADDR_ANY;
+	bzero(&src, sizeof(src));
+
 	if (control != NULL) {
 		/*
 		 * XXX: Currently, we assume all the optional information is
@@ -777,12 +778,10 @@
 					error = EINVAL;
 					break;
 				}
-				bzero(&src, sizeof(src));
 				src.sin_family = AF_INET;
 				src.sin_len = sizeof(src);
-				src.sin_port = inp->inp_lport;
 				src.sin_addr = *(struct in_addr *)CMSG_DATA(cm);
 				break;
 			default:
 				error = ENOPROTOOPT;
 				break;
@@ -797,7 +796,7 @@
 		return (error);
 	}
 
-	if (src.sin_addr.s_addr != INADDR_ANY || addr != NULL) {
+	if (src.sin_family == AF_INET || addr != NULL) {
 		INP_INFO_WLOCK(&udbinfo);
 		unlock_udbinfo = 1;
 	} else
@@ -810,11 +809,20 @@
 
 	laddr = inp->inp_laddr;
 	lport = inp->inp_lport;
-	if (src.sin_addr.s_addr != INADDR_ANY) {
-		if (lport == 0) {
+
+	/*
+	 * If the IP_SENDSRCADDR control message was specified, override the
+	 * source address for this datagram. Its use is invalidated if the
+	 * address thus specified is incomplete or clobbers other inpcbs.
+	 */
+	if (src.sin_family == AF_INET) {
+		if ((lport == 0) ||
+		    (laddr.s_addr == INADDR_ANY &&
+		     src.sin_addr.s_addr == INADDR_ANY)) {
 			error = EINVAL;
 			goto release;
 		}
+		src.sin_port = lport;
 		error = in_pcbbind_setup(inp, (struct sockaddr *)&src,
 		    &laddr.s_addr, &lport, td->td_ucred);
 		if (error)
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to