Merge branch 'master' of /repos/git/net-next-2.6
[safe/jmp/linux-2.6] / net / ipv6 / netfilter / nf_conntrack_l3proto_ipv6.c
index a7f4cd6..55ce22e 100644 (file)
@@ -20,6 +20,7 @@
 #include <net/ipv6.h>
 #include <net/inet_frag.h>
 
+#include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv6.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
@@ -27,6 +28,7 @@
 #include <net/netfilter/nf_conntrack_l3proto.h>
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
+#include <net/netfilter/nf_log.h>
 
 static bool ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
                              struct nf_conntrack_tuple *tuple)
@@ -176,13 +178,31 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
        }
 
        ret = helper->help(skb, protoff, ct, ctinfo);
-       if (ret != NF_ACCEPT)
+       if (ret != NF_ACCEPT) {
+               nf_log_packet(NFPROTO_IPV6, hooknum, skb, in, out, NULL,
+                             "nf_ct_%s: dropping packet", helper->name);
                return ret;
+       }
 out:
        /* We've seen it coming out the other side: confirm it */
        return nf_conntrack_confirm(skb);
 }
 
+static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
+                                               struct sk_buff *skb)
+{
+#ifdef CONFIG_BRIDGE_NETFILTER
+       if (skb->nf_bridge &&
+           skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
+               return IP6_DEFRAG_CONNTRACK_BRIDGE_IN;
+#endif
+       if (hooknum == NF_INET_PRE_ROUTING)
+               return IP6_DEFRAG_CONNTRACK_IN;
+       else
+               return IP6_DEFRAG_CONNTRACK_OUT;
+
+}
+
 static unsigned int ipv6_defrag(unsigned int hooknum,
                                struct sk_buff *skb,
                                const struct net_device *in,
@@ -192,11 +212,10 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
        struct sk_buff *reasm;
 
        /* Previously seen (loopback)?  */
-       if (skb->nfct)
+       if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
                return NF_ACCEPT;
 
-       reasm = nf_ct_frag6_gather(skb);
-
+       reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
        /* queued */
        if (reasm == NULL)
                return NF_STOLEN;