Re: [PATCH] bridge-nf: Allow IPTables to filter PPPoE traffic
"Michael Milner" <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <[email protected]> |
>> > Op ma, 05-02-2007 te 16:48 -0500, schreef Michael Milner:
>> >> Hi,
>> >>
>> >> I've put together some code to allow IPTables to filter PPPoE traffic
>> in
>> >> the same way that bridge-nf allows iptables to filter VLAN traffic.
Hi,
I've fixed up the return statements as you mentioned. This should now
apply against 2.6.20.1
Mike
--- a/include/linux/sysctl.h 2007-02-20 01:34:32.000000000 -0500
+++ b/include/linux/sysctl.h 2007-03-01 12:01:50.000000000 -0500
@@ -777,6 +777,7 @@
NET_BRIDGE_NF_CALL_IPTABLES = 2,
NET_BRIDGE_NF_CALL_IP6TABLES = 3,
NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4,
+ NET_BRIDGE_NF_FILTER_PPPOE_TAGGED = 5,
};
/* CTL_FS names: */
--- a/include/linux/if_pppox.h 2007-02-20 01:34:32.000000000 -0500
+++ b/include/linux/if_pppox.h 2007-03-01 13:30:38.000000000 -0500
@@ -111,6 +111,9 @@
struct pppoe_tag tag[0];
} __attribute__ ((packed));
+/* Length of entire PPPoE + PPP header */
+#define PPPOE_SES_HLEN 8
+
#ifdef __KERNEL__
struct pppoe_opt {
struct net_device *dev; /* device associated with socket*/
--- a/include/linux/netfilter_bridge.h 2007-02-20 01:34:32.000000000 -0500
+++ b/include/linux/netfilter_bridge.h 2007-03-22 10:41:53.000000000 -0400
@@ -7,6 +7,7 @@
#include <linux/netfilter.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
+#include <linux/if_pppox.h>
/* Bridge Hooks */
/* After promisc drops, checksum checks. */
@@ -58,8 +59,14 @@
* enough room for the encapsulating header (if there is one). */
static inline int nf_bridge_pad(const struct sk_buff *skb)
{
- return (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
- ? VLAN_HLEN : 0;
+ int padding = 0;
+
+ if (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
+ padding = VLAN_HLEN;
+ else if (skb->nf_bridge && skb->protocol == htons(ETH_P_PPP_SES))
+ padding = PPPOE_SES_HLEN;
+
+ return padding;
}
struct bridge_skb_cb {
--- a/net/bridge/br_netfilter.c 2007-02-20 01:34:32.000000000 -0500
+++ b/net/bridge/br_netfilter.c 2007-03-01 13:29:08.000000000 -0500
@@ -12,6 +12,7 @@
* Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
* (bdschuym)
* Sep 01 2004: add IPv6 filtering (bdschuym)
+ * Jan 16 2007: let iptables see bridged PPPoE IP traffic (mdmilner)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -29,6 +30,8 @@
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
+#include <linux/if_pppox.h>
+#include <linux/ppp_defs.h>
#include <linux/netfilter_bridge.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
@@ -57,6 +60,7 @@
static int brnf_call_ip6tables __read_mostly = 1;
static int brnf_call_arptables __read_mostly = 1;
static int brnf_filter_vlan_tagged __read_mostly = 1;
+static int brnf_filter_pppoe_tagged __read_mostly = 1;
#else
#define brnf_filter_vlan_tagged 1
#endif
@@ -81,6 +85,21 @@
vlan_proto(skb) == htons(ETH_P_ARP) && \
brnf_filter_vlan_tagged)
+static __be16 inline pppoe_proto(const struct sk_buff *skb)
+{
+ return *((__be16*)(skb->mac.raw + ETH_HLEN + sizeof(struct pppoe_hdr)));
+}
+
+#define IS_PPPOE_IP(skb) \
+ (skb->protocol == htons(ETH_P_PPP_SES) && \
+ pppoe_proto(skb) == htons(PPP_IP) && \
+ brnf_filter_pppoe_tagged)
+
+#define IS_PPPOE_IPV6(skb) \
+ (skb->protocol == htons(ETH_P_PPP_SES) && \
+ pppoe_proto(skb) == htons(PPP_IPV6) && \
+ brnf_filter_pppoe_tagged)
+
/* We need these fake structures to make netfilter happy --
* lots of places assume that skb->dst != NULL, which isn't
* all that unreasonable.
@@ -128,6 +147,8 @@
if (skb->protocol == htons(ETH_P_8021Q))
header_size += VLAN_HLEN;
+ else if (skb->protocol == htons(ETH_P_PPP_SES))
+ header_size += PPPOE_SES_HLEN;
memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
}
@@ -143,6 +164,8 @@
if (skb->protocol == htons(ETH_P_8021Q))
header_size += VLAN_HLEN;
+ else if (skb->protocol == htons(ETH_P_PPP_SES))
+ header_size += PPPOE_SES_HLEN;
err = skb_cow(skb, header_size);
if (err)
@@ -152,6 +175,8 @@
if (skb->protocol == htons(ETH_P_8021Q))
__skb_push(skb, VLAN_HLEN);
+ else if (skb->protocol == htons(ETH_P_PPP_SES))
+ __skb_push(skb, PPPOE_SES_HLEN);
return 0;
}
@@ -175,6 +200,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_push(skb, VLAN_HLEN);
skb->nh.raw -= VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_push(skb, PPPOE_SES_HLEN);
+ skb->nh.raw -= PPPOE_SES_HLEN;
}
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish, 1);
@@ -256,6 +284,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_pull(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_pull(skb, PPPOE_SES_HLEN);
+ skb->nh.raw += PPPOE_SES_HLEN;
}
skb->dst->output(skb);
}
@@ -326,6 +357,10 @@
htons(ETH_P_8021Q)) {
skb_push(skb, VLAN_HLEN);
skb->nh.raw -= VLAN_HLEN;
+ } else if(skb->protocol ==
+ htons(ETH_P_PPP_SES)) {
+ skb_push(skb, PPPOE_SES_HLEN);
+ skb->nh.raw -= PPPOE_SES_HLEN;
}
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
skb, skb->dev, NULL,
@@ -345,6 +380,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_push(skb, VLAN_HLEN);
skb->nh.raw -= VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_push(skb, PPPOE_SES_HLEN);
+ skb->nh.raw -= PPPOE_SES_HLEN;
}
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish, 1);
@@ -485,7 +523,8 @@
__u32 len;
struct sk_buff *skb = *pskb;
- if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) {
+ if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) ||
+ IS_PPPOE_IPV6(skb)) {
#ifdef CONFIG_SYSCTL
if (!brnf_call_ip6tables)
return NF_ACCEPT;
@@ -496,6 +535,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_pull_rcsum(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_pull_rcsum(skb, PPPOE_SES_HLEN);
+ skb->nh.raw += PPPOE_SES_HLEN;
}
return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
}
@@ -504,7 +546,8 @@
return NF_ACCEPT;
#endif
- if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb))
+ if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb) &&
+ !IS_PPPOE_IP(skb))
return NF_ACCEPT;
if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
@@ -513,6 +556,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_pull_rcsum(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_pull_rcsum(skb, PPPOE_SES_HLEN);
+ skb->nh.raw += PPPOE_SES_HLEN;
}
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
@@ -594,6 +640,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_push(skb, VLAN_HLEN);
skb->nh.raw -= VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_push(skb, PPPOE_SES_HLEN);
+ skb->nh.raw -= PPPOE_SES_HLEN;
}
NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
skb->dev, br_forward_finish, 1);
@@ -622,7 +671,8 @@
if (!parent)
return NF_DROP;
- if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
+ if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb) ||
+ IS_PPPOE_IP(skb))
pf = PF_INET;
else
pf = PF_INET6;
@@ -630,6 +680,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_pull(*pskb, VLAN_HLEN);
(*pskb)->nh.raw += VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_pull(*pskb, PPPOE_SES_HLEN);
+ (*pskb)->nh.raw += PPPOE_SES_HLEN;
}
nf_bridge = skb->nf_bridge;
@@ -722,6 +775,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_push(skb, VLAN_HLEN);
skb->nh.raw -= VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_push(skb, PPPOE_SES_HLEN);
+ skb->nh.raw -= PPPOE_SES_HLEN;
}
NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
@@ -766,7 +822,8 @@
if (!realoutdev)
return NF_DROP;
- if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb))
+ if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb) ||
+ IS_PPPOE_IP(skb))
pf = PF_INET;
else
pf = PF_INET6;
@@ -788,6 +845,9 @@
if (skb->protocol == htons(ETH_P_8021Q)) {
skb_pull(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
+ } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
+ skb_pull(skb, PPPOE_SES_HLEN);
+ skb->nh.raw += PPPOE_SES_HLEN;
}
nf_bridge_save_header(skb);
@@ -925,6 +985,14 @@
.mode = 0644,
.proc_handler = &brnf_sysctl_call_tables,
},
+ {
+ .ctl_name = NET_BRIDGE_NF_FILTER_PPPOE_TAGGED,
+ .procname = "bridge-nf-filter-pppoe-tagged",
+ .data = &brnf_filter_pppoe_tagged,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &brnf_sysctl_call_tables,
+ },
{ .ctl_name = 0 }
};
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV