Date: Wed, 07 Mar 2007 12:31:02 +0000 From: "Bruce M. Simpson" <bms@FreeBSD.org> To: "Bruce M. Simpson" <bms@FreeBSD.org> Cc: Andre Oppermann <andre@freebsd.org>, net@FreeBSD.org Subject: Re: Inconsistencies with IP_ONESBCAST and/or IP_SENDSRCADDR Message-ID: <45EEB086.3050409@FreeBSD.org> In-Reply-To: <45E6D70C.10104@FreeBSD.org> References: <45C0CA5D.5090903@incunabulum.net> <45E6BEE0.2050307@FreeBSD.org> <45E6C22D.7060200@freebsd.org> <45E6D70C.10104@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
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
[-- Attachment #2 --]
--- //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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45EEB086.3050409>
