[NETFILTER]: Fix fragmentation issues with bridge netfilter
authorPatrick McHardy <kaber@trash.net>
Tue, 4 Apr 2006 20:42:35 +0000 (13:42 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 10 Apr 2006 05:25:23 +0000 (22:25 -0700)
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>
include/net/ip.h
net/bridge/br_netfilter.c
net/ipv4/ip_output.c

index 8fe6156ca9b0807fc3cbb98d2c7aa0faf5741978..3d2e5ca62a5af1c8ba234523d9886380d7d90564 100644 (file)
@@ -95,6 +95,7 @@ extern int            ip_local_deliver(struct sk_buff *skb);
 extern int             ip_mr_input(struct sk_buff *skb);
 extern int             ip_output(struct sk_buff *skb);
 extern int             ip_mc_output(struct sk_buff *skb);
+extern int             ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 extern int             ip_do_nat(struct sk_buff *skb);
 extern void            ip_send_check(struct iphdr *ip);
 extern int             ip_queue_xmit(struct sk_buff *skb, int ipfragok);
index f29450b788be166182999ed6f927a15f6fcb186a..3da9264449f79d6d517fce1391af3f663bdde3a8 100644 (file)
@@ -765,6 +765,15 @@ out:
        return NF_STOLEN;
 }
 
+static int br_nf_dev_queue_xmit(struct sk_buff *skb)
+{
+       if (skb->protocol == htons(ETH_P_IP) &&
+           skb->len > skb->dev->mtu &&
+           !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+               return ip_fragment(skb, br_dev_queue_push_xmit);
+       else
+               return br_dev_queue_push_xmit(skb);
+}
 
 /* PF_BRIDGE/POST_ROUTING ********************************************/
 static 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,
                realoutdev = nf_bridge->netoutdev;
 #endif
        NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
-               br_dev_queue_push_xmit);
+               br_nf_dev_queue_xmit);
 
        return NF_STOLEN;
 
@@ -869,7 +878,7 @@ static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
 
        if ((out->hard_start_xmit == br_dev_xmit &&
             okfn != br_nf_forward_finish &&
-            okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit)
+            okfn != br_nf_local_out_finish && okfn != br_nf_dev_queue_xmit)
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
            || ((out->priv_flags & IFF_802_1Q_VLAN) &&
                VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
index f75ff1d96551d1e03cbfba7153c1bedb9b6e36df..8dcba3887f04eb647df01ae404b3b9bda955408d 100644 (file)
@@ -86,8 +86,6 @@
 
 int sysctl_ip_default_ttl = IPDEFTTL;
 
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*));
-
 /* Generate a checksum for an outgoing IP datagram. */
 __inline__ void ip_send_check(struct iphdr *iph)
 {
@@ -421,7 +419,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
  *     single device frame, and queue such a frame for sending.
  */
 
-static int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
+int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
 {
        struct iphdr *iph;
        int raw = 0;
@@ -673,6 +671,8 @@ fail:
        return err;
 }
 
+EXPORT_SYMBOL(ip_fragment);
+
 int
 ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
 {