diff options
author | bms <bms@FreeBSD.org> | 2007-03-01 13:29:30 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2007-03-01 13:29:30 +0000 |
commit | 3562ed06e76301454bd10cb11f6a608c492ddb50 (patch) | |
tree | bc975727f35d99d6e898ab78eec60ecb51806ecb /sys/netinet/ip_output.c | |
parent | fb0fb9de79f2a61e33488880acd9418ff02fe703 (diff) | |
download | FreeBSD-src-3562ed06e76301454bd10cb11f6a608c492ddb50.zip FreeBSD-src-3562ed06e76301454bd10cb11f6a608c492ddb50.tar.gz |
Fix undirected broadcast sends for the case where SO_DONTROUTE has also
been set at the socket layer, in our somewhat convoluted IPv4 source
selection logic in ip_output().
IP_ONESBCAST is actually a special case of SO_DONTROUTE, as 255.255.255.255
must always be delivered on a local link with a TTL of 1.
If IP_ONESBCAST has been set at the socket layer, also perform destination
interface lookup for point-to-point interfaces based on the destination
address of the link; previously it was not possible to use the option with
such interfaces; also, the destination/broadcast address fields map to the
same field within struct ifnet, which doesn't help matters.
One more valid fix going forward for these issues is to treat 255.255.255.255
as a destination in its own right in the forwarding trie. Other
implementations do this. It fits with the use of multiple paths, though
it then becomes necessary to specify interface preference.
This hack will eventually go away when that comes to pass.
Reviewed by: andre
MFC after: 1 week
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r-- | sys/netinet/ip_output.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 500feff..3314538 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -188,30 +188,33 @@ again: dst->sin_addr = ip->ip_dst; } /* - * If routing to interface only, - * short circuit routing lookup. + * If routing to interface only, short circuit routing lookup. + * The use of an all-ones broadcast address implies this; an + * interface is specified by the broadcast address of an interface, + * or the destination address of a ptp interface. */ - if (flags & IP_ROUTETOIF) { - if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL && - (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) { + if (flags & IP_SENDONES) { + if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst)))) == NULL && + (ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL) { ipstat.ips_noroute++; error = ENETUNREACH; goto bad; } + ip->ip_dst.s_addr = INADDR_BROADCAST; + dst->sin_addr = ip->ip_dst; ifp = ia->ia_ifp; ip->ip_ttl = 1; - isbroadcast = in_broadcast(dst->sin_addr, ifp); - } else if (flags & IP_SENDONES) { - if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst)))) == NULL) { + isbroadcast = 1; + } else if (flags & IP_ROUTETOIF) { + if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL && + (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) { ipstat.ips_noroute++; error = ENETUNREACH; goto bad; } ifp = ia->ia_ifp; - ip->ip_dst.s_addr = INADDR_BROADCAST; - dst->sin_addr = ip->ip_dst; ip->ip_ttl = 1; - isbroadcast = 1; + isbroadcast = in_broadcast(dst->sin_addr, ifp); } else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) && imo != NULL && imo->imo_multicast_ifp != NULL) { /* |