aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Milner <milner@blissisland.ca>2007-04-13 01:14:23 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:28:57 -0400
commit516299d2f5b6f9703b9b388faf91898dc636a678 (patch)
tree909b7003188f0f100e0782c9620515e39cba1603
parent91d73c15cb165195bc8c3d6a35e30df454b1485b (diff)
[NETFILTER]: bridge-nf: filter bridged IPv4/IPv6 encapsulated in pppoe traffic
The attached patch by Michael Milner adds support for using iptables and ip6tables on bridged traffic encapsulated in ppoe frames, similar to what's already supported for vlan. Signed-off-by: Michael Milner <milner@blissisland.ca> Signed-off-by: Bart De Schuymer <bdschuym@pandora.be> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/ip-sysctl.txt7
-rw-r--r--include/linux/if_pppox.h3
-rw-r--r--include/linux/netfilter_bridge.h11
-rw-r--r--include/linux/sysctl.h1
-rw-r--r--net/bridge/br_netfilter.c77
5 files changed, 92 insertions, 7 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 054c515bd726..af6a63ab9026 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1015,7 +1015,12 @@ bridge-nf-call-ip6tables - BOOLEAN
1015 Default: 1 1015 Default: 1
1016 1016
1017bridge-nf-filter-vlan-tagged - BOOLEAN 1017bridge-nf-filter-vlan-tagged - BOOLEAN
1018 1 : pass bridged vlan-tagged ARP/IP traffic to arptables/iptables. 1018 1 : pass bridged vlan-tagged ARP/IP/IPv6 traffic to {arp,ip,ip6}tables.
1019 0 : disable this.
1020 Default: 1
1021
1022bridge-nf-filter-pppoe-tagged - BOOLEAN
1023 1 : pass bridged pppoe-tagged IP/IPv6 traffic to {ip,ip6}tables.
1019 0 : disable this. 1024 0 : disable this.
1020 Default: 1 1025 Default: 1
1021 1026
diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h
index 29d6579ff1a0..6f987be60fe2 100644
--- a/include/linux/if_pppox.h
+++ b/include/linux/if_pppox.h
@@ -111,6 +111,9 @@ struct pppoe_hdr {
111 struct pppoe_tag tag[0]; 111 struct pppoe_tag tag[0];
112} __attribute__ ((packed)); 112} __attribute__ ((packed));
113 113
114/* Length of entire PPPoE + PPP header */
115#define PPPOE_SES_HLEN 8
116
114#ifdef __KERNEL__ 117#ifdef __KERNEL__
115#include <linux/skbuff.h> 118#include <linux/skbuff.h>
116 119
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 55689f39f77a..19060030bac9 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -7,6 +7,7 @@
7#include <linux/netfilter.h> 7#include <linux/netfilter.h>
8#include <linux/if_ether.h> 8#include <linux/if_ether.h>
9#include <linux/if_vlan.h> 9#include <linux/if_vlan.h>
10#include <linux/if_pppox.h>
10 11
11/* Bridge Hooks */ 12/* Bridge Hooks */
12/* After promisc drops, checksum checks. */ 13/* After promisc drops, checksum checks. */
@@ -58,8 +59,14 @@ static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
58 * enough room for the encapsulating header (if there is one). */ 59 * enough room for the encapsulating header (if there is one). */
59static inline int nf_bridge_pad(const struct sk_buff *skb) 60static inline int nf_bridge_pad(const struct sk_buff *skb)
60{ 61{
61 return (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q)) 62 int padding = 0;
62 ? VLAN_HLEN : 0; 63
64 if (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q))
65 padding = VLAN_HLEN;
66 else if (skb->nf_bridge && skb->protocol == htons(ETH_P_PPP_SES))
67 padding = PPPOE_SES_HLEN;
68
69 return padding;
63} 70}
64 71
65struct bridge_skb_cb { 72struct bridge_skb_cb {
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index df2d9ed20a4e..47f1c53332ce 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -792,6 +792,7 @@ enum {
792 NET_BRIDGE_NF_CALL_IPTABLES = 2, 792 NET_BRIDGE_NF_CALL_IPTABLES = 2,
793 NET_BRIDGE_NF_CALL_IP6TABLES = 3, 793 NET_BRIDGE_NF_CALL_IP6TABLES = 3,
794 NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4, 794 NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4,
795 NET_BRIDGE_NF_FILTER_PPPOE_TAGGED = 5,
795}; 796};
796 797
797/* CTL_FS names: */ 798/* CTL_FS names: */
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index fd70d041e51f..9b2986b182ba 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -29,6 +29,8 @@
29#include <linux/if_arp.h> 29#include <linux/if_arp.h>
30#include <linux/if_ether.h> 30#include <linux/if_ether.h>
31#include <linux/if_vlan.h> 31#include <linux/if_vlan.h>
32#include <linux/if_pppox.h>
33#include <linux/ppp_defs.h>
32#include <linux/netfilter_bridge.h> 34#include <linux/netfilter_bridge.h>
33#include <linux/netfilter_ipv4.h> 35#include <linux/netfilter_ipv4.h>
34#include <linux/netfilter_ipv6.h> 36#include <linux/netfilter_ipv6.h>
@@ -57,8 +59,10 @@ static int brnf_call_iptables __read_mostly = 1;
57static int brnf_call_ip6tables __read_mostly = 1; 59static int brnf_call_ip6tables __read_mostly = 1;
58static int brnf_call_arptables __read_mostly = 1; 60static int brnf_call_arptables __read_mostly = 1;
59static int brnf_filter_vlan_tagged __read_mostly = 1; 61static int brnf_filter_vlan_tagged __read_mostly = 1;
62static int brnf_filter_pppoe_tagged __read_mostly = 1;
60#else 63#else
61#define brnf_filter_vlan_tagged 1 64#define brnf_filter_vlan_tagged 1
65#define brnf_filter_pppoe_tagged 1
62#endif 66#endif
63 67
64static inline __be16 vlan_proto(const struct sk_buff *skb) 68static inline __be16 vlan_proto(const struct sk_buff *skb)
@@ -81,6 +85,22 @@ static inline __be16 vlan_proto(const struct sk_buff *skb)
81 vlan_proto(skb) == htons(ETH_P_ARP) && \ 85 vlan_proto(skb) == htons(ETH_P_ARP) && \
82 brnf_filter_vlan_tagged) 86 brnf_filter_vlan_tagged)
83 87
88static inline __be16 pppoe_proto(const struct sk_buff *skb)
89{
90 return *((__be16 *)(skb_mac_header(skb) + ETH_HLEN +
91 sizeof(struct pppoe_hdr)));
92}
93
94#define IS_PPPOE_IP(skb) \
95 (skb->protocol == htons(ETH_P_PPP_SES) && \
96 pppoe_proto(skb) == htons(PPP_IP) && \
97 brnf_filter_pppoe_tagged)
98
99#define IS_PPPOE_IPV6(skb) \
100 (skb->protocol == htons(ETH_P_PPP_SES) && \
101 pppoe_proto(skb) == htons(PPP_IPV6) && \
102 brnf_filter_pppoe_tagged)
103
84/* We need these fake structures to make netfilter happy -- 104/* We need these fake structures to make netfilter happy --
85 * lots of places assume that skb->dst != NULL, which isn't 105 * lots of places assume that skb->dst != NULL, which isn't
86 * all that unreasonable. 106 * all that unreasonable.
@@ -128,6 +148,8 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
128 148
129 if (skb->protocol == htons(ETH_P_8021Q)) 149 if (skb->protocol == htons(ETH_P_8021Q))
130 header_size += VLAN_HLEN; 150 header_size += VLAN_HLEN;
151 else if (skb->protocol == htons(ETH_P_PPP_SES))
152 header_size += PPPOE_SES_HLEN;
131 153
132 skb_copy_from_linear_data_offset(skb, -header_size, 154 skb_copy_from_linear_data_offset(skb, -header_size,
133 skb->nf_bridge->data, header_size); 155 skb->nf_bridge->data, header_size);
@@ -144,6 +166,8 @@ int nf_bridge_copy_header(struct sk_buff *skb)
144 166
145 if (skb->protocol == htons(ETH_P_8021Q)) 167 if (skb->protocol == htons(ETH_P_8021Q))
146 header_size += VLAN_HLEN; 168 header_size += VLAN_HLEN;
169 else if (skb->protocol == htons(ETH_P_PPP_SES))
170 header_size += PPPOE_SES_HLEN;
147 171
148 err = skb_cow(skb, header_size); 172 err = skb_cow(skb, header_size);
149 if (err) 173 if (err)
@@ -154,6 +178,8 @@ int nf_bridge_copy_header(struct sk_buff *skb)
154 178
155 if (skb->protocol == htons(ETH_P_8021Q)) 179 if (skb->protocol == htons(ETH_P_8021Q))
156 __skb_push(skb, VLAN_HLEN); 180 __skb_push(skb, VLAN_HLEN);
181 else if (skb->protocol == htons(ETH_P_PPP_SES))
182 __skb_push(skb, PPPOE_SES_HLEN);
157 return 0; 183 return 0;
158} 184}
159 185
@@ -177,6 +203,9 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
177 if (skb->protocol == htons(ETH_P_8021Q)) { 203 if (skb->protocol == htons(ETH_P_8021Q)) {
178 skb_push(skb, VLAN_HLEN); 204 skb_push(skb, VLAN_HLEN);
179 skb->network_header -= VLAN_HLEN; 205 skb->network_header -= VLAN_HLEN;
206 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
207 skb_push(skb, PPPOE_SES_HLEN);
208 skb->network_header -= PPPOE_SES_HLEN;
180 } 209 }
181 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, 210 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
182 br_handle_frame_finish, 1); 211 br_handle_frame_finish, 1);
@@ -258,6 +287,9 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
258 if (skb->protocol == htons(ETH_P_8021Q)) { 287 if (skb->protocol == htons(ETH_P_8021Q)) {
259 skb_pull(skb, VLAN_HLEN); 288 skb_pull(skb, VLAN_HLEN);
260 skb->network_header += VLAN_HLEN; 289 skb->network_header += VLAN_HLEN;
290 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
291 skb_pull(skb, PPPOE_SES_HLEN);
292 skb->network_header += PPPOE_SES_HLEN;
261 } 293 }
262 skb->dst->output(skb); 294 skb->dst->output(skb);
263 } 295 }
@@ -328,6 +360,10 @@ bridged_dnat:
328 htons(ETH_P_8021Q)) { 360 htons(ETH_P_8021Q)) {
329 skb_push(skb, VLAN_HLEN); 361 skb_push(skb, VLAN_HLEN);
330 skb->network_header -= VLAN_HLEN; 362 skb->network_header -= VLAN_HLEN;
363 } else if(skb->protocol ==
364 htons(ETH_P_PPP_SES)) {
365 skb_push(skb, PPPOE_SES_HLEN);
366 skb->network_header -= PPPOE_SES_HLEN;
331 } 367 }
332 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, 368 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
333 skb, skb->dev, NULL, 369 skb, skb->dev, NULL,
@@ -347,6 +383,9 @@ bridged_dnat:
347 if (skb->protocol == htons(ETH_P_8021Q)) { 383 if (skb->protocol == htons(ETH_P_8021Q)) {
348 skb_push(skb, VLAN_HLEN); 384 skb_push(skb, VLAN_HLEN);
349 skb->network_header -= VLAN_HLEN; 385 skb->network_header -= VLAN_HLEN;
386 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
387 skb_push(skb, PPPOE_SES_HLEN);
388 skb->network_header -= PPPOE_SES_HLEN;
350 } 389 }
351 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, 390 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
352 br_handle_frame_finish, 1); 391 br_handle_frame_finish, 1);
@@ -489,7 +528,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
489 __u32 len; 528 __u32 len;
490 struct sk_buff *skb = *pskb; 529 struct sk_buff *skb = *pskb;
491 530
492 if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) { 531 if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) ||
532 IS_PPPOE_IPV6(skb)) {
493#ifdef CONFIG_SYSCTL 533#ifdef CONFIG_SYSCTL
494 if (!brnf_call_ip6tables) 534 if (!brnf_call_ip6tables)
495 return NF_ACCEPT; 535 return NF_ACCEPT;
@@ -500,6 +540,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
500 if (skb->protocol == htons(ETH_P_8021Q)) { 540 if (skb->protocol == htons(ETH_P_8021Q)) {
501 skb_pull_rcsum(skb, VLAN_HLEN); 541 skb_pull_rcsum(skb, VLAN_HLEN);
502 skb->network_header += VLAN_HLEN; 542 skb->network_header += VLAN_HLEN;
543 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
544 skb_pull_rcsum(skb, PPPOE_SES_HLEN);
545 skb->network_header += PPPOE_SES_HLEN;
503 } 546 }
504 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); 547 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
505 } 548 }
@@ -508,7 +551,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
508 return NF_ACCEPT; 551 return NF_ACCEPT;
509#endif 552#endif
510 553
511 if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb)) 554 if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb) &&
555 !IS_PPPOE_IP(skb))
512 return NF_ACCEPT; 556 return NF_ACCEPT;
513 557
514 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) 558 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
@@ -517,6 +561,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
517 if (skb->protocol == htons(ETH_P_8021Q)) { 561 if (skb->protocol == htons(ETH_P_8021Q)) {
518 skb_pull_rcsum(skb, VLAN_HLEN); 562 skb_pull_rcsum(skb, VLAN_HLEN);
519 skb->network_header += VLAN_HLEN; 563 skb->network_header += VLAN_HLEN;
564 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
565 skb_pull_rcsum(skb, PPPOE_SES_HLEN);
566 skb->network_header += PPPOE_SES_HLEN;
520 } 567 }
521 568
522 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 569 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
@@ -598,6 +645,9 @@ static int br_nf_forward_finish(struct sk_buff *skb)
598 if (skb->protocol == htons(ETH_P_8021Q)) { 645 if (skb->protocol == htons(ETH_P_8021Q)) {
599 skb_push(skb, VLAN_HLEN); 646 skb_push(skb, VLAN_HLEN);
600 skb->network_header -= VLAN_HLEN; 647 skb->network_header -= VLAN_HLEN;
648 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
649 skb_push(skb, PPPOE_SES_HLEN);
650 skb->network_header -= PPPOE_SES_HLEN;
601 } 651 }
602 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, 652 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
603 skb->dev, br_forward_finish, 1); 653 skb->dev, br_forward_finish, 1);
@@ -626,7 +676,8 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
626 if (!parent) 676 if (!parent)
627 return NF_DROP; 677 return NF_DROP;
628 678
629 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) 679 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb) ||
680 IS_PPPOE_IP(skb))
630 pf = PF_INET; 681 pf = PF_INET;
631 else 682 else
632 pf = PF_INET6; 683 pf = PF_INET6;
@@ -634,6 +685,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
634 if (skb->protocol == htons(ETH_P_8021Q)) { 685 if (skb->protocol == htons(ETH_P_8021Q)) {
635 skb_pull(*pskb, VLAN_HLEN); 686 skb_pull(*pskb, VLAN_HLEN);
636 (*pskb)->network_header += VLAN_HLEN; 687 (*pskb)->network_header += VLAN_HLEN;
688 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
689 skb_pull(*pskb, PPPOE_SES_HLEN);
690 (*pskb)->network_header += PPPOE_SES_HLEN;
637 } 691 }
638 692
639 nf_bridge = skb->nf_bridge; 693 nf_bridge = skb->nf_bridge;
@@ -726,6 +780,9 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
726 if (skb->protocol == htons(ETH_P_8021Q)) { 780 if (skb->protocol == htons(ETH_P_8021Q)) {
727 skb_push(skb, VLAN_HLEN); 781 skb_push(skb, VLAN_HLEN);
728 skb->network_header -= VLAN_HLEN; 782 skb->network_header -= VLAN_HLEN;
783 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
784 skb_push(skb, PPPOE_SES_HLEN);
785 skb->network_header -= PPPOE_SES_HLEN;
729 } 786 }
730 787
731 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev, 788 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev,
@@ -771,7 +828,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
771 if (!realoutdev) 828 if (!realoutdev)
772 return NF_DROP; 829 return NF_DROP;
773 830
774 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) 831 if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb) ||
832 IS_PPPOE_IP(skb))
775 pf = PF_INET; 833 pf = PF_INET;
776 else 834 else
777 pf = PF_INET6; 835 pf = PF_INET6;
@@ -793,6 +851,9 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
793 if (skb->protocol == htons(ETH_P_8021Q)) { 851 if (skb->protocol == htons(ETH_P_8021Q)) {
794 skb_pull(skb, VLAN_HLEN); 852 skb_pull(skb, VLAN_HLEN);
795 skb->network_header += VLAN_HLEN; 853 skb->network_header += VLAN_HLEN;
854 } else if (skb->protocol == htons(ETH_P_PPP_SES)) {
855 skb_pull(skb, PPPOE_SES_HLEN);
856 skb->network_header += PPPOE_SES_HLEN;
796 } 857 }
797 858
798 nf_bridge_save_header(skb); 859 nf_bridge_save_header(skb);
@@ -930,6 +991,14 @@ static ctl_table brnf_table[] = {
930 .mode = 0644, 991 .mode = 0644,
931 .proc_handler = &brnf_sysctl_call_tables, 992 .proc_handler = &brnf_sysctl_call_tables,
932 }, 993 },
994 {
995 .ctl_name = NET_BRIDGE_NF_FILTER_PPPOE_TAGGED,
996 .procname = "bridge-nf-filter-pppoe-tagged",
997 .data = &brnf_filter_pppoe_tagged,
998 .maxlen = sizeof(int),
999 .mode = 0644,
1000 .proc_handler = &brnf_sysctl_call_tables,
1001 },
933 { .ctl_name = 0 } 1002 { .ctl_name = 0 }
934}; 1003};
935 1004