]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/sched/act_api.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[mirror_ubuntu-artful-kernel.git] / net / sched / act_api.c
index b70aa57319ea3233395dc7ae349b8b7aab5dfd03..257360f773b434e4911c175a17cf80d037264d3f 100644 (file)
@@ -529,20 +529,20 @@ errout:
        return err;
 }
 
-static int nla_memdup_cookie(struct tc_action *a, struct nlattr **tb)
+static struct tc_cookie *nla_memdup_cookie(struct nlattr **tb)
 {
-       a->act_cookie = kzalloc(sizeof(*a->act_cookie), GFP_KERNEL);
-       if (!a->act_cookie)
-               return -ENOMEM;
+       struct tc_cookie *c = kzalloc(sizeof(*c), GFP_KERNEL);
+       if (!c)
+               return NULL;
 
-       a->act_cookie->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
-       if (!a->act_cookie->data) {
-               kfree(a->act_cookie);
-               return -ENOMEM;
+       c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL);
+       if (!c->data) {
+               kfree(c);
+               return NULL;
        }
-       a->act_cookie->len = nla_len(tb[TCA_ACT_COOKIE]);
+       c->len = nla_len(tb[TCA_ACT_COOKIE]);
 
-       return 0;
+       return c;
 }
 
 struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
@@ -551,13 +551,14 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
 {
        struct tc_action *a;
        struct tc_action_ops *a_o;
+       struct tc_cookie *cookie = NULL;
        char act_name[IFNAMSIZ];
        struct nlattr *tb[TCA_ACT_MAX + 1];
        struct nlattr *kind;
        int err;
 
        if (name == NULL) {
-               err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+               err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
                if (err < 0)
                        goto err_out;
                err = -EINVAL;
@@ -566,6 +567,18 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
                        goto err_out;
                if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
                        goto err_out;
+               if (tb[TCA_ACT_COOKIE]) {
+                       int cklen = nla_len(tb[TCA_ACT_COOKIE]);
+
+                       if (cklen > TC_COOKIE_MAX_SIZE)
+                               goto err_out;
+
+                       cookie = nla_memdup_cookie(tb);
+                       if (!cookie) {
+                               err = -ENOMEM;
+                               goto err_out;
+                       }
+               }
        } else {
                err = -EINVAL;
                if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
@@ -604,20 +617,12 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
        if (err < 0)
                goto err_mod;
 
-       if (tb[TCA_ACT_COOKIE]) {
-               int cklen = nla_len(tb[TCA_ACT_COOKIE]);
-
-               if (cklen > TC_COOKIE_MAX_SIZE) {
-                       err = -EINVAL;
-                       tcf_hash_release(a, bind);
-                       goto err_mod;
-               }
-
-               if (nla_memdup_cookie(a, tb) < 0) {
-                       err = -ENOMEM;
-                       tcf_hash_release(a, bind);
-                       goto err_mod;
+       if (name == NULL && tb[TCA_ACT_COOKIE]) {
+               if (a->act_cookie) {
+                       kfree(a->act_cookie->data);
+                       kfree(a->act_cookie);
                }
+               a->act_cookie = cookie;
        }
 
        /* module count goes up only when brand new policy is created
@@ -632,6 +637,10 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
 err_mod:
        module_put(a_o->owner);
 err_out:
+       if (cookie) {
+               kfree(cookie->data);
+               kfree(cookie);
+       }
        return ERR_PTR(err);
 }
 
@@ -654,7 +663,7 @@ int tcf_action_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        int err;
        int i;
 
-       err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
+       err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
        if (err < 0)
                return err;
 
@@ -786,7 +795,7 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
        int index;
        int err;
 
-       err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+       err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
        if (err < 0)
                goto err_out;
 
@@ -835,7 +844,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 
        b = skb_tail_pointer(skb);
 
-       err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+       err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, NULL);
        if (err < 0)
                goto err_out;
 
@@ -921,7 +930,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
        struct tc_action *act;
        LIST_HEAD(actions);
 
-       ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
+       ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, NULL);
        if (ret < 0)
                return ret;
 
@@ -993,7 +1002,8 @@ static int tcf_action_add(struct net *net, struct nlattr *nla,
        return tcf_add_notify(net, n, &actions, portid);
 }
 
-static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n)
+static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n,
+                        struct netlink_ext_ack *extack)
 {
        struct net *net = sock_net(skb->sk);
        struct nlattr *tca[TCA_ACT_MAX + 1];
@@ -1004,7 +1014,8 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n)
            !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
-       ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL);
+       ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL,
+                         extack);
        if (ret < 0)
                return ret;
 
@@ -1051,19 +1062,20 @@ static struct nlattr *find_dump_kind(const struct nlmsghdr *n)
        struct nlattr *nla[TCAA_MAX + 1];
        struct nlattr *kind;
 
-       if (nlmsg_parse(n, sizeof(struct tcamsg), nla, TCAA_MAX, NULL) < 0)
+       if (nlmsg_parse(n, sizeof(struct tcamsg), nla, TCAA_MAX,
+                       NULL, NULL) < 0)
                return NULL;
        tb1 = nla[TCA_ACT_TAB];
        if (tb1 == NULL)
                return NULL;
 
        if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1),
-                     NLMSG_ALIGN(nla_len(tb1)), NULL) < 0)
+                     NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
                return NULL;
 
        if (tb[1] == NULL)
                return NULL;
-       if (nla_parse_nested(tb2, TCA_ACT_MAX, tb[1], NULL) < 0)
+       if (nla_parse_nested(tb2, TCA_ACT_MAX, tb[1], NULL, NULL) < 0)
                return NULL;
        kind = tb2[TCA_ACT_KIND];