aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-04-04 16:42:35 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-04-10 01:25:23 -0400
commit2e2f7aefa8a8ba4adb6ecee8cbb43fbe9ca4cc89 (patch)
tree891921c05dbf5ac2436473d77b8dbfda91a1b9bc
parent550e29bc96e6f1ced2bca82dace197b009434367 (diff)
[NETFILTER]: Fix fragmentation issues with bridge netfilter
The conntrack code doesn't do re-fragmentation of defragmented packets anymore but relies on fragmentation in the IP layer. Purely bridged packets don't pass through the IP layer, so the bridge netfilter code needs to take care of fragmentation itself. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ip.h1
-rw-r--r--net/bridge/br_netfilter.c13
-rw-r--r--net/ipv4/ip_output.c6
3 files changed, 15 insertions, 5 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index 8fe6156ca9b0..3d2e5ca62a5a 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_buff *skb);
95extern int ip_mr_input(struct sk_buff *skb); 95extern int ip_mr_input(struct sk_buff *skb);
96extern int ip_output(struct sk_buff *skb); 96extern int ip_output(struct sk_buff *skb);
97extern int ip_mc_output(struct sk_buff *skb); 97extern int ip_mc_output(struct sk_buff *skb);
98extern int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
98extern int ip_do_nat(struct sk_buff *skb); 99extern int ip_do_nat(struct sk_buff *skb);
99extern void ip_send_check(struct iphdr *ip); 100extern void ip_send_check(struct iphdr *ip);
100extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok); 101extern int ip_queue_xmit(struct sk_buff *skb, int ipfragok);
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index f29450b788be..3da9264449f7 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -765,6 +765,15 @@ out:
765 return NF_STOLEN; 765 return NF_STOLEN;
766} 766}
767 767
768static int br_nf_dev_queue_xmit(struct sk_buff *skb)
769{
770 if (skb->protocol == htons(ETH_P_IP) &&
771 skb->len > skb->dev->mtu &&
772 !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
773 return ip_fragment(skb, br_dev_queue_push_xmit);
774 else
775 return br_dev_queue_push_xmit(skb);
776}
768 777
769/* PF_BRIDGE/POST_ROUTING ********************************************/ 778/* PF_BRIDGE/POST_ROUTING ********************************************/
770static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, 779static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
@@ -824,7 +833,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
824 realoutdev = nf_bridge->netoutdev; 833 realoutdev = nf_bridge->netoutdev;
825#endif 834#endif
826 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, 835 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
827 br_dev_queue_push_xmit); 836 br_nf_dev_queue_xmit);
828 837
829 return NF_STOLEN; 838 return NF_STOLEN;
830 839
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
869 878
870 if ((out->hard_start_xmit == br_dev_xmit && 879 if ((out->hard_start_xmit == br_dev_xmit &&
871 okfn != br_nf_forward_finish && 880 okfn != br_nf_forward_finish &&
872 okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit) 881 okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
873#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 882#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
874 || ((out->priv_flags & IFF_802_1Q_VLAN) && 883 || ((out->priv_flags & IFF_802_1Q_VLAN) &&
875 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) 884 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f75ff1d96551..8dcba3887f04 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -86,8 +86,6 @@
86 86
87int sysctl_ip_default_ttl = IPDEFTTL; 87int sysctl_ip_default_ttl = IPDEFTTL;
88 88
89static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
90
91/* Generate a checksum for an outgoing IP datagram. */ 89/* Generate a checksum for an outgoing IP datagram. */
92__inline__ void ip_send_check(struct iphdr *iph) 90__inline__ void ip_send_check(struct iphdr *iph)
93{ 91{
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
421 * single device frame, and queue such a frame for sending. 419 * single device frame, and queue such a frame for sending.
422 */ 420 */
423 421
424static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) 422int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
425{ 423{
426 struct iphdr *iph; 424 struct iphdr *iph;
427 int raw = 0; 425 int raw = 0;
@@ -673,6 +671,8 @@ fail:
673 return err; 671 return err;
674} 672}
675 673
674EXPORT_SYMBOL(ip_fragment);
675
676int 676int
677ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb) 677ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
678{ 678{