diff options
author | Patrick McHardy <kaber@trash.net> | 2007-05-03 06:36:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-05-03 06:36:16 -0400 |
commit | fc38582db98533066f4ba64f948720483fbfe7b2 (patch) | |
tree | 350d7e725e4dedfbf41b3ee54d585ed2d609b607 | |
parent | cfd6c38096d75c8b86782683c5f45c415a505b78 (diff) |
[NETFILTER]: bridge netfilter: consolidate header pushing/pulling code
Consolidate the common push/pull sequences into a few helper functions.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netfilter_bridge.h | 25 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 138 |
2 files changed, 56 insertions, 107 deletions
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h index 19060030bac9..533ee351a273 100644 --- a/include/linux/netfilter_bridge.h +++ b/include/linux/netfilter_bridge.h | |||
@@ -55,18 +55,25 @@ static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) | |||
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb) | ||
59 | { | ||
60 | switch (skb->protocol) { | ||
61 | case __constant_htons(ETH_P_8021Q): | ||
62 | return VLAN_HLEN; | ||
63 | case __constant_htons(ETH_P_PPP_SES): | ||
64 | return PPPOE_SES_HLEN; | ||
65 | default: | ||
66 | return 0; | ||
67 | } | ||
68 | } | ||
69 | |||
58 | /* This is called by the IP fragmenting code and it ensures there is | 70 | /* This is called by the IP fragmenting code and it ensures there is |
59 | * enough room for the encapsulating header (if there is one). */ | 71 | * enough room for the encapsulating header (if there is one). */ |
60 | static inline int nf_bridge_pad(const struct sk_buff *skb) | 72 | static inline unsigned int nf_bridge_pad(const struct sk_buff *skb) |
61 | { | 73 | { |
62 | int padding = 0; | 74 | if (skb->nf_bridge) |
63 | 75 | return nf_bridge_encap_header_len(skb); | |
64 | if (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q)) | 76 | return 0; |
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; | ||
70 | } | 77 | } |
71 | 78 | ||
72 | struct bridge_skb_cb { | 79 | struct bridge_skb_cb { |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 9b2986b182ba..fa779874b9dd 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -142,14 +142,33 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) | |||
142 | return skb->nf_bridge; | 142 | return skb->nf_bridge; |
143 | } | 143 | } |
144 | 144 | ||
145 | static inline void nf_bridge_save_header(struct sk_buff *skb) | 145 | static inline void nf_bridge_push_encap_header(struct sk_buff *skb) |
146 | { | ||
147 | unsigned int len = nf_bridge_encap_header_len(skb); | ||
148 | |||
149 | skb_push(skb, len); | ||
150 | skb->network_header -= len; | ||
151 | } | ||
152 | |||
153 | static inline void nf_bridge_pull_encap_header(struct sk_buff *skb) | ||
146 | { | 154 | { |
147 | int header_size = ETH_HLEN; | 155 | unsigned int len = nf_bridge_encap_header_len(skb); |
156 | |||
157 | skb_pull(skb, len); | ||
158 | skb->network_header += len; | ||
159 | } | ||
148 | 160 | ||
149 | if (skb->protocol == htons(ETH_P_8021Q)) | 161 | static inline void nf_bridge_pull_encap_header_rcsum(struct sk_buff *skb) |
150 | header_size += VLAN_HLEN; | 162 | { |
151 | else if (skb->protocol == htons(ETH_P_PPP_SES)) | 163 | unsigned int len = nf_bridge_encap_header_len(skb); |
152 | header_size += PPPOE_SES_HLEN; | 164 | |
165 | skb_pull_rcsum(skb, len); | ||
166 | skb->network_header += len; | ||
167 | } | ||
168 | |||
169 | static inline void nf_bridge_save_header(struct sk_buff *skb) | ||
170 | { | ||
171 | int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); | ||
153 | 172 | ||
154 | skb_copy_from_linear_data_offset(skb, -header_size, | 173 | skb_copy_from_linear_data_offset(skb, -header_size, |
155 | skb->nf_bridge->data, header_size); | 174 | skb->nf_bridge->data, header_size); |
@@ -162,12 +181,7 @@ static inline void nf_bridge_save_header(struct sk_buff *skb) | |||
162 | int nf_bridge_copy_header(struct sk_buff *skb) | 181 | int nf_bridge_copy_header(struct sk_buff *skb) |
163 | { | 182 | { |
164 | int err; | 183 | int err; |
165 | int header_size = ETH_HLEN; | 184 | int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); |
166 | |||
167 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
168 | header_size += VLAN_HLEN; | ||
169 | else if (skb->protocol == htons(ETH_P_PPP_SES)) | ||
170 | header_size += PPPOE_SES_HLEN; | ||
171 | 185 | ||
172 | err = skb_cow(skb, header_size); | 186 | err = skb_cow(skb, header_size); |
173 | if (err) | 187 | if (err) |
@@ -175,11 +189,7 @@ int nf_bridge_copy_header(struct sk_buff *skb) | |||
175 | 189 | ||
176 | skb_copy_to_linear_data_offset(skb, -header_size, | 190 | skb_copy_to_linear_data_offset(skb, -header_size, |
177 | skb->nf_bridge->data, header_size); | 191 | skb->nf_bridge->data, header_size); |
178 | 192 | __skb_push(skb, nf_bridge_encap_header_len(skb)); | |
179 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
180 | __skb_push(skb, VLAN_HLEN); | ||
181 | else if (skb->protocol == htons(ETH_P_PPP_SES)) | ||
182 | __skb_push(skb, PPPOE_SES_HLEN); | ||
183 | return 0; | 193 | return 0; |
184 | } | 194 | } |
185 | 195 | ||
@@ -200,13 +210,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
200 | dst_hold(skb->dst); | 210 | dst_hold(skb->dst); |
201 | 211 | ||
202 | skb->dev = nf_bridge->physindev; | 212 | skb->dev = nf_bridge->physindev; |
203 | if (skb->protocol == htons(ETH_P_8021Q)) { | 213 | nf_bridge_push_encap_header(skb); |
204 | skb_push(skb, 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; | ||
209 | } | ||
210 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 214 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
211 | br_handle_frame_finish, 1); | 215 | br_handle_frame_finish, 1); |
212 | 216 | ||
@@ -284,13 +288,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | |||
284 | if (!skb->dev) | 288 | if (!skb->dev) |
285 | kfree_skb(skb); | 289 | kfree_skb(skb); |
286 | else { | 290 | else { |
287 | if (skb->protocol == htons(ETH_P_8021Q)) { | 291 | nf_bridge_pull_encap_header(skb); |
288 | skb_pull(skb, 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; | ||
293 | } | ||
294 | skb->dst->output(skb); | 292 | skb->dst->output(skb); |
295 | } | 293 | } |
296 | return 0; | 294 | return 0; |
@@ -356,15 +354,7 @@ bridged_dnat: | |||
356 | * bridged frame */ | 354 | * bridged frame */ |
357 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | 355 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; |
358 | skb->dev = nf_bridge->physindev; | 356 | skb->dev = nf_bridge->physindev; |
359 | if (skb->protocol == | 357 | nf_bridge_push_encap_header(skb); |
360 | htons(ETH_P_8021Q)) { | ||
361 | skb_push(skb, 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; | ||
367 | } | ||
368 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, | 358 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, |
369 | skb, skb->dev, NULL, | 359 | skb, skb->dev, NULL, |
370 | br_nf_pre_routing_finish_bridge, | 360 | br_nf_pre_routing_finish_bridge, |
@@ -380,13 +370,7 @@ bridged_dnat: | |||
380 | } | 370 | } |
381 | 371 | ||
382 | skb->dev = nf_bridge->physindev; | 372 | skb->dev = nf_bridge->physindev; |
383 | if (skb->protocol == htons(ETH_P_8021Q)) { | 373 | nf_bridge_push_encap_header(skb); |
384 | skb_push(skb, 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; | ||
389 | } | ||
390 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 374 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
391 | br_handle_frame_finish, 1); | 375 | br_handle_frame_finish, 1); |
392 | 376 | ||
@@ -536,14 +520,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
536 | #endif | 520 | #endif |
537 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) | 521 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) |
538 | goto out; | 522 | goto out; |
539 | 523 | nf_bridge_pull_encap_header_rcsum(skb); | |
540 | if (skb->protocol == htons(ETH_P_8021Q)) { | ||
541 | skb_pull_rcsum(skb, 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; | ||
546 | } | ||
547 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); | 524 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); |
548 | } | 525 | } |
549 | #ifdef CONFIG_SYSCTL | 526 | #ifdef CONFIG_SYSCTL |
@@ -557,14 +534,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
557 | 534 | ||
558 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) | 535 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) |
559 | goto out; | 536 | goto out; |
560 | 537 | nf_bridge_pull_encap_header_rcsum(skb); | |
561 | if (skb->protocol == htons(ETH_P_8021Q)) { | ||
562 | skb_pull_rcsum(skb, 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; | ||
567 | } | ||
568 | 538 | ||
569 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 539 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
570 | goto inhdr_error; | 540 | goto inhdr_error; |
@@ -642,13 +612,7 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
642 | } else { | 612 | } else { |
643 | in = *((struct net_device **)(skb->cb)); | 613 | in = *((struct net_device **)(skb->cb)); |
644 | } | 614 | } |
645 | if (skb->protocol == htons(ETH_P_8021Q)) { | 615 | nf_bridge_push_encap_header(skb); |
646 | skb_push(skb, 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; | ||
651 | } | ||
652 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, | 616 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, |
653 | skb->dev, br_forward_finish, 1); | 617 | skb->dev, br_forward_finish, 1); |
654 | return 0; | 618 | return 0; |
@@ -682,13 +646,7 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
682 | else | 646 | else |
683 | pf = PF_INET6; | 647 | pf = PF_INET6; |
684 | 648 | ||
685 | if (skb->protocol == htons(ETH_P_8021Q)) { | 649 | nf_bridge_pull_encap_header(*pskb); |
686 | skb_pull(*pskb, 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; | ||
691 | } | ||
692 | 650 | ||
693 | nf_bridge = skb->nf_bridge; | 651 | nf_bridge = skb->nf_bridge; |
694 | if (skb->pkt_type == PACKET_OTHERHOST) { | 652 | if (skb->pkt_type == PACKET_OTHERHOST) { |
@@ -722,15 +680,12 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
722 | if (skb->protocol != htons(ETH_P_ARP)) { | 680 | if (skb->protocol != htons(ETH_P_ARP)) { |
723 | if (!IS_VLAN_ARP(skb)) | 681 | if (!IS_VLAN_ARP(skb)) |
724 | return NF_ACCEPT; | 682 | return NF_ACCEPT; |
725 | skb_pull(*pskb, VLAN_HLEN); | 683 | nf_bridge_pull_encap_header(*pskb); |
726 | (*pskb)->network_header += VLAN_HLEN; | ||
727 | } | 684 | } |
728 | 685 | ||
729 | if (arp_hdr(skb)->ar_pln != 4) { | 686 | if (arp_hdr(skb)->ar_pln != 4) { |
730 | if (IS_VLAN_ARP(skb)) { | 687 | if (IS_VLAN_ARP(skb)) |
731 | skb_push(*pskb, VLAN_HLEN); | 688 | nf_bridge_push_encap_header(*pskb); |
732 | (*pskb)->network_header -= VLAN_HLEN; | ||
733 | } | ||
734 | return NF_ACCEPT; | 689 | return NF_ACCEPT; |
735 | } | 690 | } |
736 | *d = (struct net_device *)in; | 691 | *d = (struct net_device *)in; |
@@ -777,13 +732,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | |||
777 | skb->pkt_type = PACKET_OTHERHOST; | 732 | skb->pkt_type = PACKET_OTHERHOST; |
778 | nf_bridge->mask ^= BRNF_PKT_TYPE; | 733 | nf_bridge->mask ^= BRNF_PKT_TYPE; |
779 | } | 734 | } |
780 | if (skb->protocol == htons(ETH_P_8021Q)) { | 735 | nf_bridge_push_encap_header(skb); |
781 | skb_push(skb, 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; | ||
786 | } | ||
787 | 736 | ||
788 | NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev, | 737 | NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev, skb->dev, |
789 | br_forward_finish); | 738 | br_forward_finish); |
@@ -848,14 +797,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | |||
848 | nf_bridge->mask |= BRNF_PKT_TYPE; | 797 | nf_bridge->mask |= BRNF_PKT_TYPE; |
849 | } | 798 | } |
850 | 799 | ||
851 | if (skb->protocol == htons(ETH_P_8021Q)) { | 800 | nf_bridge_pull_encap_header(skb); |
852 | skb_pull(skb, 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; | ||
857 | } | ||
858 | |||
859 | nf_bridge_save_header(skb); | 801 | nf_bridge_save_header(skb); |
860 | 802 | ||
861 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 803 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |