summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/if_bridge.420
-rw-r--r--sys/net/if_bridge.c67
2 files changed, 82 insertions, 5 deletions
diff --git a/share/man/man4/if_bridge.4 b/share/man/man4/if_bridge.4
index 54fa1aa..2e079f5 100644
--- a/share/man/man4/if_bridge.4
+++ b/share/man/man4/if_bridge.4
@@ -81,7 +81,8 @@ Spanning Tree is used to detect and remove loops in a network topology.
.Pp
When filtering is enabled, bridged packets will pass through the filter
inbound on the originating interface, on the bridge interface and outbound on
-the appropriate interfaces. This behaviour can be controlled using
+the appropriate interfaces.
+Either stage can be disabled, this behaviour can be controlled using
.Xr sysctl 8 :
.Bl -tag -width ".Va net.link.bridge.pfil_member"
.It Va net.link.bridge.pfil_member
@@ -98,11 +99,24 @@ to enable enable filtering on the bridge interface, set
to
.Li 0
to disable it.
+.It Va net.link.bridge.ipfw
+Set to
+.Li 1
+to enable enable layer2 filtering with
+.Xr ipfirewall 4
+, set to
+.Li 0
+to disable it.
+When ipfw is enabled pfil_bridge and pfil_member will be disabled so that IPFW
+is not run twice, these can be re-enabled if desired.
.El
.Pp
ARP and REVARP packets are forwarded without being filtered and others
-that are not IP nor IPv6 packets are not forwarded when filtering is
-enabled.
+that are not IP nor IPv6 packets are not forwarded when
+.Xr pfil 9
+filtering is enabled.
+IPFW can filter Ethernet types using 'mac-type' so all packets are passed to
+the filter for processing.
.Pp
Note that packets to and from the bridging host will be seen by the
filter on the interface with the appropriate address configured as well
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index d6825f3..53bd302 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
*/
OpenPOWER on IntegriCloud