netfilter: xtables: add struct xt_mtchk_param::net
[safe/jmp/linux-2.6] / net / ipv4 / netfilter / nf_conntrack_proto_icmp.c
index 2a8bee2..7afd39b 100644 (file)
@@ -54,8 +54,8 @@ static const u_int8_t invmap[] = {
 static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
                              const struct nf_conntrack_tuple *orig)
 {
-       if (orig->dst.u.icmp.type >= sizeof(invmap)
-           || !invmap[orig->dst.u.icmp.type])
+       if (orig->dst.u.icmp.type >= sizeof(invmap) ||
+           !invmap[orig->dst.u.icmp.type])
                return false;
 
        tuple->src.u.icmp.id = orig->src.u.icmp.id;
@@ -82,18 +82,10 @@ static int icmp_packet(struct nf_conn *ct,
                       u_int8_t pf,
                       unsigned int hooknum)
 {
-       /* Try to delete connection immediately after all replies:
-          won't actually vanish as we still have skb, and del_timer
-          means this will only run once even if count hits zero twice
-          (theoretically possible with SMP) */
-       if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) {
-               if (atomic_dec_and_test(&ct->proto.icmp.count))
-                       nf_ct_kill_acct(ct, ctinfo, skb);
-       } else {
-               atomic_inc(&ct->proto.icmp.count);
-               nf_conntrack_event_cache(IPCT_PROTOINFO_VOLATILE, ct);
-               nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
-       }
+       /* Do not immediately delete the connection after the first
+          successful reply to avoid excessive conntrackd traffic
+          and also to handle correctly ICMP echo reply duplicates. */
+       nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout);
 
        return NF_ACCEPT;
 }
@@ -109,15 +101,14 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
                [ICMP_ADDRESS] = 1
        };
 
-       if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new)
-           || !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) {
+       if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) ||
+           !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) {
                /* Can't create a new ICMP `conn' with this. */
                pr_debug("icmp: can't create new conn with type %u\n",
                         ct->tuplehash[0].tuple.dst.u.icmp.type);
                nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple);
                return false;
        }
-       atomic_set(&ct->proto.icmp.count, 0);
        return true;
 }
 
@@ -210,11 +201,11 @@ icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
        }
 
        /* Need to track icmp error message? */
-       if (icmph->type != ICMP_DEST_UNREACH
-           && icmph->type != ICMP_SOURCE_QUENCH
-           && icmph->type != ICMP_TIME_EXCEEDED
-           && icmph->type != ICMP_PARAMETERPROB
-           && icmph->type != ICMP_REDIRECT)
+       if (icmph->type != ICMP_DEST_UNREACH &&
+           icmph->type != ICMP_SOURCE_QUENCH &&
+           icmph->type != ICMP_TIME_EXCEEDED &&
+           icmph->type != ICMP_PARAMETERPROB &&
+           icmph->type != ICMP_REDIRECT)
                return NF_ACCEPT;
 
        return icmp_error_message(net, skb, ctinfo, hooknum);
@@ -247,21 +238,26 @@ static const struct nla_policy icmp_nla_policy[CTA_PROTO_MAX+1] = {
 static int icmp_nlattr_to_tuple(struct nlattr *tb[],
                                struct nf_conntrack_tuple *tuple)
 {
-       if (!tb[CTA_PROTO_ICMP_TYPE]
-           || !tb[CTA_PROTO_ICMP_CODE]
-           || !tb[CTA_PROTO_ICMP_ID])
+       if (!tb[CTA_PROTO_ICMP_TYPE] ||
+           !tb[CTA_PROTO_ICMP_CODE] ||
+           !tb[CTA_PROTO_ICMP_ID])
                return -EINVAL;
 
        tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]);
        tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]);
        tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMP_ID]);
 
-       if (tuple->dst.u.icmp.type >= sizeof(invmap)
-           || !invmap[tuple->dst.u.icmp.type])
+       if (tuple->dst.u.icmp.type >= sizeof(invmap) ||
+           !invmap[tuple->dst.u.icmp.type])
                return -EINVAL;
 
        return 0;
 }
+
+static int icmp_nlattr_tuple_size(void)
+{
+       return nla_policy_len(icmp_nla_policy, CTA_PROTO_MAX + 1);
+}
 #endif
 
 #ifdef CONFIG_SYSCTL
@@ -274,9 +270,7 @@ static struct ctl_table icmp_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       {
-               .ctl_name = 0
-       }
+       { }
 };
 #ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
 static struct ctl_table icmp_compat_sysctl_table[] = {
@@ -287,9 +281,7 @@ static struct ctl_table icmp_compat_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       {
-               .ctl_name = 0
-       }
+       { }
 };
 #endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
 #endif /* CONFIG_SYSCTL */
@@ -309,6 +301,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
        .me                     = NULL,
 #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
        .tuple_to_nlattr        = icmp_tuple_to_nlattr,
+       .nlattr_tuple_size      = icmp_nlattr_tuple_size,
        .nlattr_to_tuple        = icmp_nlattr_to_tuple,
        .nla_policy             = icmp_nla_policy,
 #endif