netfilter: ctnetlink: add CTA_HELP_INFO attribute
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 7 Jun 2012 12:19:42 +0000 (14:19 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 16 Jun 2012 13:09:15 +0000 (15:09 +0200)
This attribute can be used to modify and to dump the internal
protocol information.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter/nfnetlink_conntrack.h
include/net/netfilter/nf_conntrack_helper.h
net/netfilter/nf_conntrack_netlink.c

index e58e4b93c10813c4959c59e81349b2432c0d722e..7688833700804c25ce758e9af3cddc7221b42108 100644 (file)
@@ -191,6 +191,7 @@ enum ctattr_expect_nat {
 enum ctattr_help {
        CTA_HELP_UNSPEC,
        CTA_HELP_NAME,
+       CTA_HELP_INFO,
        __CTA_HELP_MAX
 };
 #define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
index 061352f71a84d004f8cd3ddde84c97cdcbe361a1..84b24c3a3834ee3701e1066314ef297ff2820aef 100644 (file)
@@ -39,6 +39,7 @@ struct nf_conntrack_helper {
 
        void (*destroy)(struct nf_conn *ct);
 
+       int (*from_nlattr)(struct nlattr *attr, struct nf_conn *ct);
        int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
        unsigned int expect_class_max;
 };
index 8be0ab9b47586ef6c0937f7fb096f6e3dd0bd7af..ae156dff4887da2931d8746063baf7bf5f584a61 100644 (file)
@@ -902,7 +902,8 @@ static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
 };
 
 static inline int
-ctnetlink_parse_help(const struct nlattr *attr, char **helper_name)
+ctnetlink_parse_help(const struct nlattr *attr, char **helper_name,
+                    struct nlattr **helpinfo)
 {
        struct nlattr *tb[CTA_HELP_MAX+1];
 
@@ -913,6 +914,9 @@ ctnetlink_parse_help(const struct nlattr *attr, char **helper_name)
 
        *helper_name = nla_data(tb[CTA_HELP_NAME]);
 
+       if (tb[CTA_HELP_INFO])
+               *helpinfo = tb[CTA_HELP_INFO];
+
        return 0;
 }
 
@@ -1173,13 +1177,14 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
        struct nf_conntrack_helper *helper;
        struct nf_conn_help *help = nfct_help(ct);
        char *helpname = NULL;
+       struct nlattr *helpinfo = NULL;
        int err;
 
        /* don't change helper of sibling connections */
        if (ct->master)
                return -EBUSY;
 
-       err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
+       err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
        if (err < 0)
                return err;
 
@@ -1214,8 +1219,12 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
        }
 
        if (help) {
-               if (help->helper == helper)
+               if (help->helper == helper) {
+                       /* update private helper data if allowed. */
+                       if (helper->from_nlattr && helpinfo)
+                               helper->from_nlattr(helpinfo, ct);
                        return 0;
+               }
                if (help->helper)
                        return -EBUSY;
                /* need to zero data of old helper */
@@ -1411,8 +1420,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
        rcu_read_lock();
        if (cda[CTA_HELP]) {
                char *helpname = NULL;
-               err = ctnetlink_parse_help(cda[CTA_HELP], &helpname);
+               struct nlattr *helpinfo = NULL;
+
+               err = ctnetlink_parse_help(cda[CTA_HELP], &helpname, &helpinfo);
                if (err < 0)
                        goto err2;
 
@@ -1446,6 +1456,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
                                err = -ENOMEM;
                                goto err2;
                        }
+                       /* set private helper data if allowed. */
+                       if (helper->from_nlattr && helpinfo)
+                               helper->from_nlattr(helpinfo, ct);
 
                        /* not in hash table yet so not strictly necessary */
                        RCU_INIT_POINTER(help->helper, helper);