--- /dev/null
+From kaber@trash.net Thu Apr 6 09:54:12 2006
+Message-ID: <4435471A.5010604@trash.net>
+Date: Thu, 06 Apr 2006 18:51:38 +0200
+From: Patrick McHardy <kaber@trash.net>
+To: Greg KH <greg@kroah.com>
+CC: stable@kernel.org, davem@davemloft.net
+Subject: NETFILTER: Fix fragmentation issues with bridge netfilter
+
+[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: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/net/ip.h | 1 +
+ net/bridge/br_netfilter.c | 13 +++++++++++--
+ net/ipv4/ip_output.c | 6 +++---
+ 3 files changed, 15 insertions(+), 5 deletions(-)
+
+--- linux-2.6.16.1.orig/include/net/ip.h
++++ linux-2.6.16.1/include/net/ip.h
+@@ -95,6 +95,7 @@ extern int ip_local_deliver(struct sk_b
+ 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);
+--- linux-2.6.16.1.orig/net/bridge/br_netfilter.c
++++ linux-2.6.16.1/net/bridge/br_netfilter.c
+@@ -739,6 +739,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,
+@@ -798,7 +807,7 @@ static unsigned int br_nf_post_routing(u
+ 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;
+
+@@ -843,7 +852,7 @@ static unsigned int ip_sabotage_out(unsi
+ 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_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)
+--- linux-2.6.16.1.orig/net/ipv4/ip_output.c
++++ linux-2.6.16.1/net/ipv4/ip_output.c
+@@ -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_b
+ * 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)
+ {