summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorandre <andre@FreeBSD.org>2006-09-06 17:12:10 +0000
committerandre <andre@FreeBSD.org>2006-09-06 17:12:10 +0000
commitf044a1949bf52ae215c04b5885db0a0fa58680cf (patch)
tree8e42e2925da63abb07951c584de02d0033376b2f /sys
parent3e9b75279e471e38cf330554242d87ab268a4b01 (diff)
downloadFreeBSD-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.c27
-rw-r--r--sys/net/if_var.h1
-rw-r--r--sys/netinet/ip_output.c13
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;
OpenPOWER on IntegriCloud