aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorAndrew Thompson <thompsa@FreeBSD.org>2005-06-07 21:20:18 +0000
committerAndrew Thompson <thompsa@FreeBSD.org>2005-06-07 21:20:18 +0000
commit82116c339c553fcc2c07c2e6c9679ded51b19d64 (patch)
tree8809398320aa340f89cd0896986b9b82138326de /sys/net/if_bridge.c
parentbc48d6e6c9739bd039ef96b4a23a62e3a0fbc22f (diff)
downloadsrc-82116c339c553fcc2c07c2e6c9679ded51b19d64.tar.gz
src-82116c339c553fcc2c07c2e6c9679ded51b19d64.zip
Bring in IPFW layer2 filtering from bridge.c, this allows Ethernet filtering
using the layer2, mac and mac-type keywords. This is one of the last features that bridge.c has over if_bridge and gets us very close to a full functional replacement. Approved by: mlaier (mentor)
Notes
Notes: svn path=/head/; revision=147111
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index d6825f3b3892..53bd302549f4 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -253,6 +253,7 @@ SYSCTL_NODE(_net_link, IFT_BRIDGE, bridge, CTLFLAG_RW, 0, "Bridge");
static int pfil_bridge = 1; /* run pfil hooks on the bridge interface */
static int pfil_member = 1; /* run pfil hooks on the member interface */
+static int pfil_ipfw = 0; /* layer2 filter with ipfw */
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_bridge, CTLFLAG_RW,
&pfil_bridge, 0, "Packet filter on the bridge interface");
SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_member, CTLFLAG_RW,
@@ -376,6 +377,35 @@ static moduledata_t bridge_mod = {
DECLARE_MODULE(if_bridge, bridge_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+/*
+ * handler for net.link.bridge.pfil_ipfw
+ */
+static int
+sysctl_pfil_ipfw(SYSCTL_HANDLER_ARGS)
+{
+ int enable = pfil_ipfw;
+ int error;
+
+ error = sysctl_handle_int(oidp, &enable, 0, req);
+ enable = (enable) ? 1 : 0;
+
+ if (enable != pfil_ipfw) {
+ pfil_ipfw = enable;
+
+ /*
+ * Disable pfil so that ipfw doesnt run twice, if the user really wants
+ * both then they can re-enable pfil_bridge and/or pfil_member.
+ */
+ if (pfil_ipfw) {
+ pfil_bridge = 0;
+ pfil_member = 0;
+ }
+ }
+
+ return error;
+}
+SYSCTL_PROC(_net_link_bridge, OID_AUTO, ipfw, CTLTYPE_INT|CTLFLAG_RW,
+ &pfil_ipfw, 0, &sysctl_pfil_ipfw, "I", "Layer2 filter with IPFW");
/*
* bridge_clone_create:
@@ -2109,14 +2139,25 @@ bridge_rtnode_destroy(struct bridge_softc *sc, struct bridge_rtnode *brt)
static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
struct ifnet *ifp, int dir)
{
- int snap, error;
+ int snap, error, i;
struct ether_header *eh1, eh2;
+ struct ip_fw_args args;
struct ip *ip;
struct llc llc;
u_int16_t ether_type;
snap = 0;
error = -1; /* Default error if not error == 0 */
+
+ i = min((*mp)->m_pkthdr.len, max_protohdr);
+ if ((*mp)->m_len < i) {
+ *mp = m_pullup(*mp, i);
+ if (*mp == NULL) {
+ printf("%s: m_pullup failed\n", __func__);
+ return -1;
+ }
+ }
+
eh1 = mtod(*mp, struct ether_header *);
ether_type = ntohs(eh1->ether_type);
@@ -2154,7 +2195,13 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
# endif /* INET6 */
break;
default:
- goto bad;
+ /*
+ * ipfw allows layer2 protocol filtering using
+ * 'mac-type' so we will let the packet past, if
+ * ipfw is disabled then drop it.
+ */
+ if (!IPFW_LOADED || pfil_ipfw == 0)
+ goto bad;
}
/* Strip off the Ethernet header and keep a copy. */
@@ -2244,6 +2291,22 @@ static int bridge_pfil(struct mbuf **mp, struct ifnet *bifp,
error = -1;
+ if (IPFW_LOADED && pfil_ipfw != 0) {
+ args.m = *mp;
+ args.oif = NULL;
+ args.next_hop = NULL;
+ args.rule = NULL;
+ args.eh = &eh2;
+ i = ip_fw_chk_ptr(&args);
+ *mp = args.m;
+
+ if (*mp == NULL)
+ return error;
+
+ if (i == IP_FW_DENY) /* drop */
+ goto bad;
+ }
+
/*
* Finally, put everything back the way it was and return
*/