diff options
author | bms <bms@FreeBSD.org> | 2007-03-08 15:26:54 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2007-03-08 15:26:54 +0000 |
commit | 428a375b20f0af97722089874e08b6e7ef2142f8 (patch) | |
tree | 08e778f16008a77f0b796a0639cc7d0ee603fd3c /sys/netinet/udp_usrreq.c | |
parent | 0d80e5c2726cfb0eeb56d19ab729583febe6d46f (diff) | |
download | FreeBSD-src-428a375b20f0af97722089874e08b6e7ef2142f8.zip FreeBSD-src-428a375b20f0af97722089874e08b6e7ef2142f8.tar.gz |
Fix IP_SENDSRCADDR semantics.
* To use this option with a UDP socket, it must be bound to a local port,
and INADDR_ANY, to disallow possible collisions with existing udp inpcbs
bound to the same port on other interfaces at send time.
* If the socket is bound to INADDR_ANY, specifying IP_SENDSRCADDR with
INADDR_ANY will be rejected as it is ambiguous.
* If the socket is bound to an address other than INADDR_ANY, specifying
IP_SENDSRCADDR with INADDR_ANY will be disallowed by in_pcbbind_setup().
Reviewed by: silence on -net
Tested with: src/tools/regression/netinet/ipbroadcast
MFC after: 4 days
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r-- | sys/netinet/udp_usrreq.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 2743cf7..0966f2e 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -747,7 +747,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, return (EMSGSIZE); } - src.sin_addr.s_addr = INADDR_ANY; + src.sin_family = 0; if (control != NULL) { /* * XXX: Currently, we assume all the optional information is @@ -797,7 +797,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, 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 @@ -808,10 +808,17 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, mac_create_mbuf_from_inpcb(inp, m); #endif + /* + * 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. + */ laddr = inp->inp_laddr; lport = inp->inp_lport; - if (src.sin_addr.s_addr != INADDR_ANY) { - if (lport == 0) { + 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; } |