]> err.no Git - linux-2.6/blobdiff - net/ipv4/netfilter/nf_conntrack_proto_icmp.c
[NETFILTER]: nf_conntrack: Don't track locally generated special ICMP error
[linux-2.6] / net / ipv4 / netfilter / nf_conntrack_proto_icmp.c
index f4fc657c1983068bd5d3f34eb5db9d23f9e9d636..f96573304f5bc12e3de5f6372863988bbc15596f 100644 (file)
 
 static unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ;
 
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 static int icmp_pkt_to_tuple(const struct sk_buff *skb,
                             unsigned int dataoff,
                             struct nf_conntrack_tuple *tuple)
@@ -125,8 +119,8 @@ static int icmp_new(struct nf_conn *conntrack,
        if (conntrack->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
            || !valid_new[conntrack->tuplehash[0].tuple.dst.u.icmp.type]) {
                /* Can't create a new ICMP `conn' with this. */
-               DEBUGP("icmp: can't create new conn with type %u\n",
-                      conntrack->tuplehash[0].tuple.dst.u.icmp.type);
+               pr_debug("icmp: can't create new conn with type %u\n",
+                        conntrack->tuplehash[0].tuple.dst.u.icmp.type);
                NF_CT_DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
                return 0;
        }
@@ -142,72 +136,42 @@ icmp_error_message(struct sk_buff *skb,
                 unsigned int hooknum)
 {
        struct nf_conntrack_tuple innertuple, origtuple;
-       struct {
-               struct icmphdr icmp;
-               struct iphdr ip;
-       } _in, *inside;
        struct nf_conntrack_l4proto *innerproto;
        struct nf_conntrack_tuple_hash *h;
-       int dataoff;
 
        NF_CT_ASSERT(skb->nfct == NULL);
 
-       /* Not enough header? */
-       inside = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_in), &_in);
-       if (inside == NULL)
-               return -NF_ACCEPT;
-
-       /* Ignore ICMP's containing fragments (shouldn't happen) */
-       if (inside->ip.frag_off & htons(IP_OFFSET)) {
-               DEBUGP("icmp_error_message: fragment of proto %u\n",
-                      inside->ip.protocol);
+       /* Are they talking about one of our connections? */
+       if (!nf_ct_get_tuplepr(skb,
+                              skb_network_offset(skb) + ip_hdrlen(skb)
+                                                      + sizeof(struct icmphdr),
+                              PF_INET, &origtuple)) {
+               pr_debug("icmp_error_message: failed to get tuple\n");
                return -NF_ACCEPT;
        }
 
        /* rcu_read_lock()ed by nf_hook_slow */
-       innerproto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
-
-       dataoff = ip_hdrlen(skb) + sizeof(inside->icmp);
-       /* Are they talking about one of our connections? */
-       if (!nf_ct_get_tuple(skb, dataoff, dataoff + inside->ip.ihl*4, PF_INET,
-                            inside->ip.protocol, &origtuple,
-                            &nf_conntrack_l3proto_ipv4, innerproto)) {
-               DEBUGP("icmp_error_message: ! get_tuple p=%u",
-                      inside->ip.protocol);
-               return -NF_ACCEPT;
-       }
+       innerproto = __nf_ct_l4proto_find(PF_INET, origtuple.dst.protonum);
 
        /* Ordinarily, we'd expect the inverted tupleproto, but it's
           been preserved inside the ICMP. */
        if (!nf_ct_invert_tuple(&innertuple, &origtuple,
                                &nf_conntrack_l3proto_ipv4, innerproto)) {
-               DEBUGP("icmp_error_message: no match\n");
+               pr_debug("icmp_error_message: no match\n");
                return -NF_ACCEPT;
        }
 
        *ctinfo = IP_CT_RELATED;
 
-       h = nf_conntrack_find_get(&innertuple, NULL);
+       h = nf_conntrack_find_get(&innertuple);
        if (!h) {
-               /* Locally generated ICMPs will match inverted if they
-                  haven't been SNAT'ed yet */
-               /* FIXME: NAT code has to handle half-done double NAT --RR */
-               if (hooknum == NF_IP_LOCAL_OUT)
-                       h = nf_conntrack_find_get(&origtuple, NULL);
-
-               if (!h) {
-                       DEBUGP("icmp_error_message: no match\n");
-                       return -NF_ACCEPT;
-               }
-
-               /* Reverse direction from that found */
-               if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
-                       *ctinfo += IP_CT_IS_REPLY;
-       } else {
-               if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
-                       *ctinfo += IP_CT_IS_REPLY;
+               pr_debug("icmp_error_message: no match\n");
+               return -NF_ACCEPT;
        }
 
+       if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
+               *ctinfo += IP_CT_IS_REPLY;
+
        /* Update skb to refer to this connection */
        skb->nfct = &nf_ct_tuplehash_to_ctrack(h)->ct_general;
        skb->nfctinfo = *ctinfo;