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
This commit is contained in:
Andre Oppermann 2006-09-06 17:12:10 +00:00
parent e5bec77751
commit 773725a255
3 changed files with 39 additions and 2 deletions

View File

@ -1005,6 +1005,33 @@ ifa_ifwithaddr(struct sockaddr *addr)
return (ifa);
}
/*
* 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.
*/

View File

@ -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 *);

View File

@ -198,6 +198,17 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
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;