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)
This commit is contained in:
Andrew Thompson 2005-06-07 21:20:18 +00:00
parent bc48d6e6c9
commit 82116c339c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=147111
2 changed files with 82 additions and 5 deletions

View File

@ -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

View File

@ -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
*/