diff options
author | thompsa <thompsa@FreeBSD.org> | 2006-09-22 21:57:52 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2006-09-22 21:57:52 +0000 |
commit | 22a36e67f2dc507b9d579ccc4b1a81de4741c860 (patch) | |
tree | 6b2c542fea6e1147c45e5e744d8c6fa71494a242 /sys/net/if_bridge.c | |
parent | a9f52fafeca473e981ed60c511519e67fa6cc765 (diff) | |
download | FreeBSD-src-22a36e67f2dc507b9d579ccc4b1a81de4741c860.zip FreeBSD-src-22a36e67f2dc507b9d579ccc4b1a81de4741c860.tar.gz |
Revert r1.80 as the ethernet header was inadvertently stripped from ARP
packets. Reimplement this correctly and use a sysctl that defaults to off so
the user doesnt get any suprises if ipfw blocks the ARP packet.
MFC after: 3 days
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r-- | sys/net/if_bridge.c | 50 |
1 files changed, 36 insertions, 14 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index ca4ddf5..e5e88e8 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -321,9 +321,12 @@ static int pfil_onlyip = 1; /* only pass IP[46] packets when pfil is enabled */ 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 */ +static int pfil_ipfw_arp = 0; /* layer2 filter with ipfw */ static int log_stp = 0; /* log STP state changes */ SYSCTL_INT(_net_link_bridge, OID_AUTO, pfil_onlyip, CTLFLAG_RW, &pfil_onlyip, 0, "Only pass IP packets when pfil is enabled"); +SYSCTL_INT(_net_link_bridge, OID_AUTO, ipfw_arp, CTLFLAG_RW, + &pfil_ipfw_arp, 0, "Filter ARP packets through IPFW layer2"); 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, @@ -2736,6 +2739,37 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir) } } + /* + * If we're trying to filter bridge traffic, don't look at anything + * other than IP and ARP traffic. If the filter doesn't understand + * IPv6, don't allow IPv6 through the bridge either. This is lame + * since if we really wanted, say, an AppleTalk filter, we are hosed, + * but of course we don't have an AppleTalk filter to begin with. + * (Note that since pfil doesn't understand ARP it will pass *ALL* + * ARP traffic.) + */ + switch (ether_type) { + case ETHERTYPE_ARP: + case ETHERTYPE_REVARP: + if (pfil_ipfw_arp == 0) + return (0); /* Automatically pass */ + break; + + case ETHERTYPE_IP: +#ifdef INET6 + case ETHERTYPE_IPV6: +#endif /* INET6 */ + break; + default: + /* + * Check to see if the user wants to pass non-ip + * packets, these will not be checked by pfil(9) and + * passed unconditionally so the default is to drop. + */ + if (pfil_onlyip) + goto bad; + } + /* Strip off the Ethernet header and keep a copy. */ m_copydata(*mp, 0, ETHER_HDR_LEN, (caddr_t) &eh2); m_adj(*mp, ETHER_HDR_LEN); @@ -2808,14 +2842,9 @@ ipfwpass: error = 0; /* - * Run the packet through pfil. Note that since pfil doesn't understand - * ARP it will pass all ARP traffic. + * Run the packet through pfil */ switch (ether_type) { - case ETHERTYPE_ARP: - case ETHERTYPE_REVARP: - return (0); /* Automatically pass */ - case ETHERTYPE_IP: /* * before calling the firewall, swap fields the same as @@ -2907,14 +2936,7 @@ ipfwpass: break; #endif default: - /* - * Check to see if the user wants to pass non-ip - * packets. - */ - if (pfil_onlyip) { - error = -1; - goto bad; - } + error = 0; break; } |