summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2011-04-10 20:09:22 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2011-04-10 20:09:22 +0000
commitf0073f2271624cccfb3cfbedb96628f22fca97ba (patch)
treef46888ca9bcfb120924c2d726fe00592ede940bd /sys/net
parent5397ce965184bb34e095e92af054d01e9fbf0a43 (diff)
Revert Rev. 1.189. The delayed ip checksum calculation causes problems
with broadcast packets.
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if_bridge.c87
1 files changed, 53 insertions, 34 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 764568b0972..5fc5718e96e 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.190 2011/04/05 18:01:21 henning Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.191 2011/04/10 20:09:21 claudio Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -68,6 +68,7 @@
#ifdef IPSEC
#include <netinet/ip_ipsp.h>
+
#include <net/if_enc.h>
#endif
@@ -147,8 +148,10 @@ int bridge_flushrule(struct bridge_iflist *);
int bridge_brlconf(struct bridge_softc *, struct ifbrlconf *);
u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *,
struct mbuf *);
-struct mbuf *bridge_ip(struct bridge_softc *, int, struct ifnet *,
+#if NPF > 0
+struct mbuf *bridge_filter(struct bridge_softc *, int, struct ifnet *,
struct ether_header *, struct mbuf *m);
+#endif
int bridge_ifenqueue(struct bridge_softc *, struct ifnet *, struct mbuf *);
void bridge_fragment(struct bridge_softc *, struct ifnet *,
struct ether_header *, struct mbuf *);
@@ -999,6 +1002,7 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
struct ifnet *dst_if;
struct ether_addr *dst;
struct bridge_softc *sc;
+ struct arpcom *ac;
int s, error, len;
#ifdef IPSEC
struct m_tag *mtag;
@@ -1063,13 +1067,34 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
#endif /* IPSEC */
/* Catch packets that need TCP/UDP hardware checksumming */
- if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT ||
+ if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT ||
+ m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT ||
m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
m_freem(m);
splx(s);
return (0);
}
+ /* check if packet is for local interface */
+ LIST_FOREACH(p, &sc->sc_iflist, next) {
+ if (p->ifp->if_type != IFT_ETHER)
+ continue;
+ ac = (struct arpcom *)p->ifp;
+ dst_if = p->ifp;
+ if (bcmp(ac->ac_enaddr, eh->ether_dhost,
+ ETHER_ADDR_LEN) == 0
+#if NCARP > 0
+ || (dst_if->if_carp &&
+ carp_ourether(dst_if->if_carp, eh, 0) != NULL)
+#endif
+ ) {
+ bridge_localbroadcast(sc, dst_if, eh, m);
+ m_freem(m);
+ splx(s);
+ return (0);
+ }
+ }
+
bridge_span(sc, NULL, m);
LIST_FOREACH(p, &sc->sc_iflist, next) {
@@ -1133,6 +1158,10 @@ bridge_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
mc = m1;
}
+ /* bounce packets into alternate rdomains */
+ if (ifp->if_rdomain != dst_if->if_rdomain)
+ bridge_localbroadcast(sc, dst_if, eh, m);
+
error = bridge_ifenqueue(sc, dst_if, mc);
if (error)
continue;
@@ -1304,9 +1333,11 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m)
m_freem(m);
return;
}
- m = bridge_ip(sc, BRIDGE_IN, src_if, &eh, m);
+#if NPF > 0
+ m = bridge_filter(sc, BRIDGE_IN, src_if, &eh, m);
if (m == NULL)
return;
+#endif
/*
* If the packet is a multicast or broadcast OR if we don't
* know any better, forward it to all interfaces.
@@ -1344,9 +1375,11 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m)
m_freem(m);
return;
}
- m = bridge_ip(sc, BRIDGE_OUT, dst_if, &eh, m);
+#if NPF > 0
+ m = bridge_filter(sc, BRIDGE_OUT, dst_if, &eh, m);
if (m == NULL)
return;
+#endif
len = m->m_pkthdr.len;
#if NVLAN > 0
@@ -1497,15 +1530,15 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
eh, 0) != NULL)
#endif
) {
- if (srcifl->bif_flags & IFBIF_LEARNING)
- bridge_rtupdate(sc,
- (struct ether_addr *)&eh->ether_shost,
- ifp, 0, IFBAF_DYNAMIC);
if (bridge_filterrule(&srcifl->bif_brlin, eh, m) ==
BRL_ACTION_BLOCK) {
m_freem(m);
return (NULL);
}
+ if (srcifl->bif_flags & IFBIF_LEARNING)
+ bridge_rtupdate(sc,
+ (struct ether_addr *)&eh->ether_shost,
+ ifp, 0, IFBAF_DYNAMIC);
/* Make sure the real incoming interface
* is aware */
@@ -1648,9 +1681,11 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
mc = m1;
}
- mc = bridge_ip(sc, BRIDGE_OUT, dst_if, eh, mc);
+#if NPF > 0
+ mc = bridge_filter(sc, BRIDGE_OUT, dst_if, eh, mc);
if (mc == NULL)
continue;
+#endif
len = mc->m_pkthdr.len;
#if NVLAN > 0
@@ -2496,6 +2531,7 @@ bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp,
}
#endif /* IPSEC */
+#if NPF > 0
/*
* Filter IP packets by peeking into the ethernet frame. This violates
* the ISO model, but allows us to act as a IP filter at the data link
@@ -2503,7 +2539,7 @@ bridge_ipsec(struct bridge_softc *sc, struct ifnet *ifp,
* who've read net/if_ethersubr.c and netinet/ip_input.c
*/
struct mbuf *
-bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
+bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
struct ether_header *eh, struct mbuf *m)
{
struct llc llc;
@@ -2579,20 +2615,9 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
ip = mtod(m, struct ip *);
}
- if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) {
- if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) {
- ipstat.ips_inhwcsum++;
- ipstat.ips_badsum++;
- goto dropit;
- }
-
- if (in_cksum(m, hlen) != 0) {
- ipstat.ips_badsum++;
- goto dropit;
- }
- } else {
- m->m_pkthdr.csum_flags &= ~M_IPV4_CSUM_IN_OK;
- ipstat.ips_inhwcsum++;
+ if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
+ ipstat.ips_badsum++;
+ goto dropit;
}
if (ntohs(ip->ip_len) < hlen)
@@ -2614,13 +2639,12 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
dir, AF_INET, hlen, m))
return (NULL);
#endif /* IPSEC */
-#if NPF > 0
+
/* Finally, we get to filter the packet! */
if (pf_test(dir, ifp, &m, eh) != PF_PASS)
goto dropit;
if (m == NULL)
goto dropit;
-#endif /* NPF > 0 */
/* Rebuild the IP header */
if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
@@ -2629,11 +2653,7 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
goto dropit;
ip = mtod(m, struct ip *);
ip->ip_sum = 0;
- if ((ifp->if_capabilities & IFCAP_CSUM_IPv4)) {
- m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
- ipstat.ips_outhwcsum++;
- } else
- ip->ip_sum = in_cksum(m, hlen);
+ ip->ip_sum = in_cksum(m, hlen);
break;
@@ -2666,12 +2686,10 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
return (NULL);
#endif /* IPSEC */
-#if NPF > 0
if (pf_test6(dir, ifp, &m, eh) != PF_PASS)
goto dropit;
if (m == NULL)
return (NULL);
-#endif /* NPF > 0 */
break;
}
@@ -2703,6 +2721,7 @@ dropit:
m_freem(m);
return (NULL);
}
+#endif /* NPF > 0 */
void
bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,