summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_bridge.c176
1 files changed, 113 insertions, 63 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index ada2d292a28..9e826016e00 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.86 2002/03/14 01:27:09 millert Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.87 2002/03/18 10:31:25 jasoni Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -64,6 +64,11 @@
#include <net/if_enc.h>
#endif
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#endif
+
#if NPF > 0
#include <net/pfvar.h>
#define BRIDGE_IN PF_IN
@@ -2136,8 +2141,11 @@ bridge_filter(sc, dir, ifp, eh, m)
int hassnap = 0;
struct ip *ip;
int hlen;
+ u_int16_t etype;
+
+ etype = ntohs(eh->ether_type);
- if (eh->ether_type != htons(ETHERTYPE_IP)) {
+ if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) {
if (eh->ether_type > ETHERMTU ||
m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
sizeof(struct ether_header)))
@@ -2151,8 +2159,11 @@ bridge_filter(sc, dir, ifp, eh, m)
llc.llc_control != LLC_UI ||
llc.llc_snap.org_code[0] ||
llc.llc_snap.org_code[1] ||
- llc.llc_snap.org_code[2] ||
- llc.llc_snap.ether_type != htons(ETHERTYPE_IP))
+ llc.llc_snap.org_code[2])
+ return (m);
+
+ etype = ntohs(llc.llc_snap.ether_type);
+ if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6)
return (m);
hassnap = 1;
}
@@ -2161,75 +2172,114 @@ bridge_filter(sc, dir, ifp, eh, m)
if (hassnap)
m_adj(m, LLC_SNAPFRAMELEN);
- if (m->m_pkthdr.len < sizeof(struct ip))
- goto dropit;
-
- /* Copy minimal header, and drop invalids */
- if (m->m_len < sizeof(struct ip) &&
- (m = m_pullup(m, sizeof(struct ip))) == NULL) {
- ipstat.ips_toosmall++;
- return (NULL);
- }
- ip = mtod(m, struct ip *);
+ switch (etype) {
- if (ip->ip_v != IPVERSION) {
- ipstat.ips_badvers++;
- goto dropit;
- }
+ case ETHERTYPE_IP:
+ if (m->m_pkthdr.len < sizeof(struct ip))
+ goto dropit;
- hlen = ip->ip_hl << 2; /* get whole header length */
- if (hlen < sizeof(struct ip)) {
- ipstat.ips_badhlen++;
- goto dropit;
- }
- if (hlen > m->m_len) {
- if ((m = m_pullup(m, hlen)) == NULL) {
- ipstat.ips_badhlen++;
+ /* Copy minimal header, and drop invalids */
+ if (m->m_len < sizeof(struct ip) &&
+ (m = m_pullup(m, sizeof(struct ip))) == NULL) {
+ ipstat.ips_toosmall++;
return (NULL);
}
ip = mtod(m, struct ip *);
- }
-
- if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
- ipstat.ips_badsum++;
- goto dropit;
- }
+
+ if (ip->ip_v != IPVERSION) {
+ ipstat.ips_badvers++;
+ goto dropit;
+ }
+
+ hlen = ip->ip_hl << 2; /* get whole header length */
+ if (hlen < sizeof(struct ip)) {
+ ipstat.ips_badhlen++;
+ goto dropit;
+ }
+ if (hlen > m->m_len) {
+ if ((m = m_pullup(m, hlen)) == NULL) {
+ ipstat.ips_badhlen++;
+ return (NULL);
+ }
+ ip = mtod(m, struct ip *);
+ }
+
+ if ((ip->ip_sum = in_cksum(m, hlen)) != 0) {
+ ipstat.ips_badsum++;
+ goto dropit;
+ }
+
+ NTOHS(ip->ip_len);
+ if (ip->ip_len < hlen)
+ goto dropit;
+ NTOHS(ip->ip_id);
+ NTOHS(ip->ip_off);
+
+ if (m->m_pkthdr.len < ip->ip_len)
+ goto dropit;
+ if (m->m_pkthdr.len > ip->ip_len) {
+ if (m->m_len == m->m_pkthdr.len) {
+ m->m_len = ip->ip_len;
+ m->m_pkthdr.len = ip->ip_len;
+ } else
+ m_adj(m, ip->ip_len - m->m_pkthdr.len);
+ }
+
+ /* Finally, we get to filter the packet! */
+ m->m_pkthdr.rcvif = ifp;
+ if (pf_test(dir, ifp, &m) != PF_PASS)
+ goto dropit;
+ if (m == NULL)
+ goto dropit;
+
+ /* Rebuild the IP header */
+ if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
+ return (NULL);
+ if (m->m_len < sizeof(struct ip))
+ goto dropit;
+ ip = mtod(m, struct ip *);
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_id);
+ HTONS(ip->ip_off);
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(m, hlen);
- NTOHS(ip->ip_len);
- if (ip->ip_len < hlen)
- goto dropit;
- NTOHS(ip->ip_id);
- NTOHS(ip->ip_off);
+ break;
- if (m->m_pkthdr.len < ip->ip_len)
- goto dropit;
- if (m->m_pkthdr.len > ip->ip_len) {
- if (m->m_len == m->m_pkthdr.len) {
- m->m_len = ip->ip_len;
- m->m_pkthdr.len = ip->ip_len;
- } else
- m_adj(m, ip->ip_len - m->m_pkthdr.len);
- }
+#ifdef INET6
+ case ETHERTYPE_IPV6: {
+ struct ip6_hdr *ip6;
- /* Finally, we get to filter the packet! */
- m->m_pkthdr.rcvif = ifp;
- if (pf_test(dir, ifp, &m) != PF_PASS)
- goto dropit;
- if (m == NULL)
- goto dropit;
+ if (m->m_len < sizeof(struct ip6_hdr)) {
+ if ((m = m_pullup(m, sizeof(struct ip6_hdr)))
+ == NULL) {
+ ip6stat.ip6s_toosmall++;
+ return (NULL);
+ }
+ }
+
+ ip6 = mtod(m, struct ip6_hdr *);
+
+ if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
+ ip6stat.ip6s_badvers++;
+ in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
+ goto dropit;
+ }
- /* Rebuild the IP header */
- if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
- return (NULL);
- if (m->m_len < sizeof(struct ip))
+ if (pf_test6(dir, ifp, &m) != PF_PASS)
+ goto dropit;
+ if (m == NULL)
+ return (NULL);
+
+ break;
+ }
+#endif /* INET6 */
+
+ default:
goto dropit;
- ip = mtod(m, struct ip *);
- HTONS(ip->ip_len);
- HTONS(ip->ip_id);
- HTONS(ip->ip_off);
- ip->ip_sum = 0;
- ip->ip_sum = in_cksum(m, hlen);
-
+ break;
+ }
+
/* Reattach SNAP header */
if (hassnap) {
M_PREPEND(m, LLC_SNAPFRAMELEN, M_DONTWAIT);