[NETFILTER]: Introduce NF_INET_ hook values
[deliverable/linux.git] / net / netfilter / nf_conntrack_netlink.c
index ce3581266b87beb63ca5e3f12b6b463b7ba75e9f..a15971e9923bb48c8f8ba1e1b0039a3785fe8265 100644 (file)
@@ -4,7 +4,7 @@
  * (C) 2001 by Jay Schulist <jschlst@samba.org>
  * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
  *
  * Initial connection tracking via netlink development funded and
  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
@@ -257,7 +257,7 @@ nla_put_failure:
 static inline int
 ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
 {
-       __be32 id = htonl(ct->id);
+       __be32 id = htonl((unsigned long)ct);
        NLA_PUT(skb, CTA_ID, sizeof(u_int32_t), &id);
        return 0;
 
@@ -723,7 +723,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
 
        if (cda[CTA_ID]) {
                u_int32_t id = ntohl(*(__be32 *)nla_data(cda[CTA_ID]));
-               if (ct->id != id) {
+               if (id != (u32)(unsigned long)ct) {
                        nf_ct_put(ct);
                        return -ENOENT;
                }
@@ -829,18 +829,18 @@ ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
                                                &range) < 0)
                                return -EINVAL;
                        if (nf_nat_initialized(ct,
-                                              HOOK2MANIP(NF_IP_PRE_ROUTING)))
+                                              HOOK2MANIP(NF_INET_PRE_ROUTING)))
                                return -EEXIST;
-                       nf_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+                       nf_nat_setup_info(ct, &range, NF_INET_PRE_ROUTING);
                }
                if (cda[CTA_NAT_SRC]) {
                        if (nfnetlink_parse_nat(cda[CTA_NAT_SRC], ct,
                                                &range) < 0)
                                return -EINVAL;
                        if (nf_nat_initialized(ct,
-                                              HOOK2MANIP(NF_IP_POST_ROUTING)))
+                                              HOOK2MANIP(NF_INET_POST_ROUTING)))
                                return -EEXIST;
-                       nf_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+                       nf_nat_setup_info(ct, &range, NF_INET_POST_ROUTING);
                }
 #endif
        }
@@ -975,7 +975,8 @@ ctnetlink_change_conntrack(struct nf_conn *ct, struct nlattr *cda[])
 static int
 ctnetlink_create_conntrack(struct nlattr *cda[],
                           struct nf_conntrack_tuple *otuple,
-                          struct nf_conntrack_tuple *rtuple)
+                          struct nf_conntrack_tuple *rtuple,
+                          struct nf_conn *master_ct)
 {
        struct nf_conn *ct;
        int err = -EINVAL;
@@ -1022,6 +1023,12 @@ ctnetlink_create_conntrack(struct nlattr *cda[],
                rcu_assign_pointer(help->helper, helper);
        }
 
+       /* setup master conntrack: this is a confirmed expectation */
+       if (master_ct) {
+               __set_bit(IPS_EXPECTED_BIT, &ct->status);
+               ct->master = master_ct;
+       }
+
        add_timer(&ct->timeout);
        nf_conntrack_hash_insert(ct);
 
@@ -1064,10 +1071,37 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
                h = __nf_conntrack_find(&rtuple, NULL);
 
        if (h == NULL) {
+               struct nf_conntrack_tuple master;
+               struct nf_conntrack_tuple_hash *master_h = NULL;
+               struct nf_conn *master_ct = NULL;
+
+               if (cda[CTA_TUPLE_MASTER]) {
+                       err = ctnetlink_parse_tuple(cda,
+                                                   &master,
+                                                   CTA_TUPLE_MASTER,
+                                                   u3);
+                       if (err < 0)
+                               return err;
+
+                       master_h = __nf_conntrack_find(&master, NULL);
+                       if (master_h == NULL) {
+                               err = -ENOENT;
+                               goto out_unlock;
+                       }
+                       master_ct = nf_ct_tuplehash_to_ctrack(master_h);
+                       atomic_inc(&master_ct->ct_general.use);
+               }
+
                write_unlock_bh(&nf_conntrack_lock);
                err = -ENOENT;
                if (nlh->nlmsg_flags & NLM_F_CREATE)
-                       err = ctnetlink_create_conntrack(cda, &otuple, &rtuple);
+                       err = ctnetlink_create_conntrack(cda,
+                                                        &otuple,
+                                                        &rtuple,
+                                                        master_ct);
+               if (err < 0 && master_ct)
+                       nf_ct_put(master_ct);
+
                return err;
        }
        /* implicit 'else' */
@@ -1081,6 +1115,11 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
                        err = -EINVAL;
                        goto out_unlock;
                }
+               /* can't link an existing conntrack to a master */
+               if (cda[CTA_TUPLE_MASTER]) {
+                       err = -EINVAL;
+                       goto out_unlock;
+               }
                err = ctnetlink_change_conntrack(nf_ct_tuplehash_to_ctrack(h),
                                                 cda);
        }
@@ -1160,7 +1199,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
 {
        struct nf_conn *master = exp->master;
        __be32 timeout = htonl((exp->timeout.expires - jiffies) / HZ);
-       __be32 id = htonl(exp->id);
+       __be32 id = htonl((unsigned long)exp);
 
        if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
                goto nla_put_failure;
@@ -1346,7 +1385,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
 
        if (cda[CTA_EXPECT_ID]) {
                __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
-               if (exp->id != ntohl(id)) {
+               if (ntohl(id) != (u32)(unsigned long)exp) {
                        nf_ct_expect_put(exp);
                        return -ENOENT;
                }
@@ -1400,7 +1439,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
 
                if (cda[CTA_EXPECT_ID]) {
                        __be32 id = *(__be32 *)nla_data(cda[CTA_EXPECT_ID]);
-                       if (exp->id != ntohl(id)) {
+                       if (ntohl(id) != (u32)(unsigned long)exp) {
                                nf_ct_expect_put(exp);
                                return -ENOENT;
                        }
This page took 0.034207 seconds and 5 git commands to generate.