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
This is a multi-part message in MIME format. --------------070900070803040605090309 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------070900070803040605090309 Content-Type: text/x-patch; name="ipsendsrcaddr.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ipsendsrcaddr.diff" --- //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) --------------070900070803040605090309--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45EEB086.3050409>