diff options
author | andre <andre@FreeBSD.org> | 2006-09-06 17:12:10 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2006-09-06 17:12:10 +0000 |
commit | f044a1949bf52ae215c04b5885db0a0fa58680cf (patch) | |
tree | 8e42e2925da63abb07951c584de02d0033376b2f /sys | |
parent | 3e9b75279e471e38cf330554242d87ab268a4b01 (diff) | |
download | FreeBSD-src-f044a1949bf52ae215c04b5885db0a0fa58680cf.zip FreeBSD-src-f044a1949bf52ae215c04b5885db0a0fa58680cf.tar.gz |
Fix the socket option IP_ONESBCAST by giving it its own case in ip_output()
and skip over the normal IP processing.
Add a supporting function ifa_ifwithbroadaddr() to verify and validate the
supplied subnet broadcast address.
PR: kern/99558
Tested by: Andrey V. Elsukov <bu7cher-at-yandex.ru>
Sponsored by: TCP/IP Optimization Fundraise 2005
MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if.c | 27 | ||||
-rw-r--r-- | sys/net/if_var.h | 1 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 13 |
3 files changed, 39 insertions, 2 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 33e26cd..278b4a8 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1006,6 +1006,33 @@ done: } /* + * Locate an interface based on the broadcast address. + */ +/* ARGSUSED */ +struct ifaddr * +ifa_ifwithbroadaddr(struct sockaddr *addr) +{ + struct ifnet *ifp; + struct ifaddr *ifa; + + IFNET_RLOCK(); + TAILQ_FOREACH(ifp, &ifnet, if_link) + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family != addr->sa_family) + continue; + if ((ifp->if_flags & IFF_BROADCAST) && + ifa->ifa_broadaddr && + ifa->ifa_broadaddr->sa_len != 0 && + sa_equal(ifa->ifa_broadaddr, addr)) + goto done; + } + ifa = NULL; +done: + IFNET_RUNLOCK(); + return (ifa); +} + +/* * Locate the point to point interface with a given destination address. */ /*ARGSUSED*/ diff --git a/sys/net/if_var.h b/sys/net/if_var.h index a73d781..6d7601c 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -683,6 +683,7 @@ int ifpromisc(struct ifnet *, int); struct ifnet *ifunit(const char *); struct ifaddr *ifa_ifwithaddr(struct sockaddr *); +struct ifaddr *ifa_ifwithbroadaddr(struct sockaddr *); struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); struct ifaddr *ifa_ifwithnet(struct sockaddr *); struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *); diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 8efc288..79d3806 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -198,6 +198,17 @@ again: 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) { + 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; } else if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) && imo != NULL && imo->imo_multicast_ifp != NULL) { /* @@ -381,8 +392,6 @@ again: error = EMSGSIZE; goto bad; } - if (flags & IP_SENDONES) - ip->ip_dst.s_addr = INADDR_BROADCAST; m->m_flags |= M_BCAST; } else { m->m_flags &= ~M_BCAST; |