OSDN Git Service

[NET_SCHED]: Use nla_policy for attribute validation in classifiers
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / net / sched / cls_tcindex.c
index 47ac0c5..ee60b2d 100644 (file)
@@ -9,12 +9,9 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <net/ip.h>
 #include <net/act_api.h>
 #include <net/netlink.h>
 #include <net/pkt_cls.h>
-#include <net/route.h>
 
 
 /*
 #define DEFAULT_HASH_SIZE      64      /* optimized for diffserv */
 
 
-#if 1 /* control */
-#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define DPRINTK(format,args...)
-#endif
-
-#if 0 /* data */
-#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args)
-#else
-#define D2PRINTK(format,args...)
-#endif
-
-
 #define        PRIV(tp)        ((struct tcindex_data *) (tp)->root)
 
 
@@ -107,7 +91,8 @@ static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
        struct tcindex_filter_result *f;
        int key = (skb->tc_index & p->mask) >> p->shift;
 
-       D2PRINTK("tcindex_classify(skb %p,tp %p,res %p),p %p\n",skb,tp,res,p);
+       pr_debug("tcindex_classify(skb %p,tp %p,res %p),p %p\n",
+                skb, tp, res, p);
 
        f = tcindex_lookup(p, key);
        if (!f) {
@@ -115,11 +100,11 @@ static int tcindex_classify(struct sk_buff *skb, struct tcf_proto *tp,
                        return -1;
                res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key);
                res->class = 0;
-               D2PRINTK("alg 0x%x\n",res->classid);
+               pr_debug("alg 0x%x\n", res->classid);
                return 0;
        }
        *res = f->res;
-       D2PRINTK("map 0x%x\n",res->classid);
+       pr_debug("map 0x%x\n", res->classid);
 
        return tcf_exts_exec(skb, &f->exts, res);
 }
@@ -130,7 +115,7 @@ static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
        struct tcindex_data *p = PRIV(tp);
        struct tcindex_filter_result *r;
 
-       DPRINTK("tcindex_get(tp %p,handle 0x%08x)\n",tp,handle);
+       pr_debug("tcindex_get(tp %p,handle 0x%08x)\n", tp, handle);
        if (p->perfect && handle >= p->alloc_hash)
                return 0;
        r = tcindex_lookup(p, handle);
@@ -140,7 +125,7 @@ static unsigned long tcindex_get(struct tcf_proto *tp, u32 handle)
 
 static void tcindex_put(struct tcf_proto *tp, unsigned long f)
 {
-       DPRINTK("tcindex_put(tp %p,f 0x%lx)\n",tp,f);
+       pr_debug("tcindex_put(tp %p,f 0x%lx)\n", tp, f);
 }
 
 
@@ -148,8 +133,8 @@ static int tcindex_init(struct tcf_proto *tp)
 {
        struct tcindex_data *p;
 
-       DPRINTK("tcindex_init(tp %p)\n",tp);
-       p = kzalloc(sizeof(struct tcindex_data),GFP_KERNEL);
+       pr_debug("tcindex_init(tp %p)\n", tp);
+       p = kzalloc(sizeof(struct tcindex_data), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
 
@@ -169,7 +154,7 @@ __tcindex_delete(struct tcf_proto *tp, unsigned long arg, int lock)
        struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg;
        struct tcindex_filter *f = NULL;
 
-       DPRINTK("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n",tp,arg,p,f);
+       pr_debug("tcindex_delete(tp %p,arg 0x%lx),p %p,f %p\n", tp, arg, p, f);
        if (p->perfect) {
                if (!r->res.class)
                        return -ENOENT;
@@ -208,10 +193,18 @@ valid_perfect_hash(struct tcindex_data *p)
        return  p->hash > (p->mask >> p->shift);
 }
 
+static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = {
+       [TCA_TCINDEX_HASH]              = { .type = NLA_U32 },
+       [TCA_TCINDEX_MASK]              = { .type = NLA_U16 },
+       [TCA_TCINDEX_SHIFT]             = { .type = NLA_U32 },
+       [TCA_TCINDEX_FALL_THROUGH]      = { .type = NLA_U32 },
+       [TCA_TCINDEX_CLASSID]           = { .type = NLA_U32 },
+};
+
 static int
 tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
                  struct tcindex_data *p, struct tcindex_filter_result *r,
-                 struct rtattr **tb, struct rtattr *est)
+                 struct nlattr **tb, struct nlattr *est)
 {
        int err, balloc = 0;
        struct tcindex_filter_result new_filter_result, *old_r = r;
@@ -232,24 +225,14 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
        else
                memset(&cr, 0, sizeof(cr));
 
-       err = -EINVAL;
-       if (tb[TCA_TCINDEX_HASH-1]) {
-               if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH-1]) < sizeof(u32))
-                       goto errout;
-               cp.hash = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_HASH-1]);
-       }
+       if (tb[TCA_TCINDEX_HASH])
+               cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
 
-       if (tb[TCA_TCINDEX_MASK-1]) {
-               if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK-1]) < sizeof(u16))
-                       goto errout;
-               cp.mask = *(u16 *) RTA_DATA(tb[TCA_TCINDEX_MASK-1]);
-       }
+       if (tb[TCA_TCINDEX_MASK])
+               cp.mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
 
-       if (tb[TCA_TCINDEX_SHIFT-1]) {
-               if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT-1]) < sizeof(int))
-                       goto errout;
-               cp.shift = *(int *) RTA_DATA(tb[TCA_TCINDEX_SHIFT-1]);
-       }
+       if (tb[TCA_TCINDEX_SHIFT])
+               cp.shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]);
 
        err = -EBUSY;
        /* Hash already allocated, make sure that we still meet the
@@ -263,12 +246,8 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
                goto errout;
 
        err = -EINVAL;
-       if (tb[TCA_TCINDEX_FALL_THROUGH-1]) {
-               if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH-1]) < sizeof(u32))
-                       goto errout;
-               cp.fall_through =
-                       *(u32 *) RTA_DATA(tb[TCA_TCINDEX_FALL_THROUGH-1]);
-       }
+       if (tb[TCA_TCINDEX_FALL_THROUGH])
+               cp.fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]);
 
        if (!cp.hash) {
                /* Hash not specified, use perfect hash if the upper limit
@@ -319,8 +298,8 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
                        goto errout_alloc;
        }
 
-       if (tb[TCA_TCINDEX_CLASSID-1]) {
-               cr.res.classid = *(u32 *) RTA_DATA(tb[TCA_TCINDEX_CLASSID-1]);
+       if (tb[TCA_TCINDEX_CLASSID]) {
+               cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
                tcf_bind_filter(tp, &cr.res, base);
        }
 
@@ -359,34 +338,36 @@ errout:
 
 static int
 tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
-              struct rtattr **tca, unsigned long *arg)
+              struct nlattr **tca, unsigned long *arg)
 {
-       struct rtattr *opt = tca[TCA_OPTIONS-1];
-       struct rtattr *tb[TCA_TCINDEX_MAX];
+       struct nlattr *opt = tca[TCA_OPTIONS];
+       struct nlattr *tb[TCA_TCINDEX_MAX + 1];
        struct tcindex_data *p = PRIV(tp);
        struct tcindex_filter_result *r = (struct tcindex_filter_result *) *arg;
+       int err;
 
-       DPRINTK("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
+       pr_debug("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
            "p %p,r %p,*arg 0x%lx\n",
            tp, handle, tca, arg, opt, p, r, arg ? *arg : 0L);
 
        if (!opt)
                return 0;
 
-       if (rtattr_parse_nested(tb, TCA_TCINDEX_MAX, opt) < 0)
-               return -EINVAL;
+       err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, tcindex_policy);
+       if (err < 0)
+               return err;
 
-       return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE-1]);
+       return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE]);
 }
 
 
 static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
 {
        struct tcindex_data *p = PRIV(tp);
-       struct tcindex_filter *f,*next;
+       struct tcindex_filter *f, *next;
        int i;
 
-       DPRINTK("tcindex_walk(tp %p,walker %p),p %p\n",tp,walker,p);
+       pr_debug("tcindex_walk(tp %p,walker %p),p %p\n", tp, walker, p);
        if (p->perfect) {
                for (i = 0; i < p->hash; i++) {
                        if (!p->perfect[i].res.class)
@@ -408,7 +389,7 @@ static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker)
                for (f = p->h[i]; f; f = next) {
                        next = f->next;
                        if (walker->count >= walker->skip) {
-                               if (walker->fn(tp,(unsigned long) &f->result,
+                               if (walker->fn(tp, (unsigned long) &f->result,
                                    walker) < 0) {
                                        walker->stop = 1;
                                        return;
@@ -432,11 +413,11 @@ static void tcindex_destroy(struct tcf_proto *tp)
        struct tcindex_data *p = PRIV(tp);
        struct tcf_walker walker;
 
-       DPRINTK("tcindex_destroy(tp %p),p %p\n",tp,p);
+       pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
        walker.count = 0;
        walker.skip = 0;
        walker.fn = &tcindex_destroy_element;
-       tcindex_walk(tp,&walker);
+       tcindex_walk(tp, &walker);
        kfree(p->perfect);
        kfree(p->h);
        kfree(p);
@@ -450,21 +431,23 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
        struct tcindex_data *p = PRIV(tp);
        struct tcindex_filter_result *r = (struct tcindex_filter_result *) fh;
        unsigned char *b = skb_tail_pointer(skb);
-       struct rtattr *rta;
+       struct nlattr *nest;
+
+       pr_debug("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
+                tp, fh, skb, t, p, r, b);
+       pr_debug("p->perfect %p p->h %p\n", p->perfect, p->h);
+
+       nest = nla_nest_start(skb, TCA_OPTIONS);
+       if (nest == NULL)
+               goto nla_put_failure;
 
-       DPRINTK("tcindex_dump(tp %p,fh 0x%lx,skb %p,t %p),p %p,r %p,b %p\n",
-           tp,fh,skb,t,p,r,b);
-       DPRINTK("p->perfect %p p->h %p\n",p->perfect,p->h);
-       rta = (struct rtattr *) b;
-       RTA_PUT(skb,TCA_OPTIONS,0,NULL);
        if (!fh) {
                t->tcm_handle = ~0; /* whatever ... */
-               RTA_PUT(skb,TCA_TCINDEX_HASH,sizeof(p->hash),&p->hash);
-               RTA_PUT(skb,TCA_TCINDEX_MASK,sizeof(p->mask),&p->mask);
-               RTA_PUT(skb,TCA_TCINDEX_SHIFT,sizeof(p->shift),&p->shift);
-               RTA_PUT(skb,TCA_TCINDEX_FALL_THROUGH,sizeof(p->fall_through),
-                   &p->fall_through);
-               rta->rta_len = skb_tail_pointer(skb) - b;
+               NLA_PUT_U32(skb, TCA_TCINDEX_HASH, p->hash);
+               NLA_PUT_U16(skb, TCA_TCINDEX_MASK, p->mask);
+               NLA_PUT_U32(skb, TCA_TCINDEX_SHIFT, p->shift);
+               NLA_PUT_U32(skb, TCA_TCINDEX_FALL_THROUGH, p->fall_through);
+               nla_nest_end(skb, nest);
        } else {
                if (p->perfect) {
                        t->tcm_handle = r-p->perfect;
@@ -481,27 +464,26 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
                                }
                        }
                }
-               DPRINTK("handle = %d\n",t->tcm_handle);
+               pr_debug("handle = %d\n", t->tcm_handle);
                if (r->res.class)
-                       RTA_PUT(skb, TCA_TCINDEX_CLASSID, 4, &r->res.classid);
+                       NLA_PUT_U32(skb, TCA_TCINDEX_CLASSID, r->res.classid);
 
                if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0)
-                       goto rtattr_failure;
-               rta->rta_len = skb_tail_pointer(skb) - b;
+                       goto nla_put_failure;
+               nla_nest_end(skb, nest);
 
                if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0)
-                       goto rtattr_failure;
+                       goto nla_put_failure;
        }
 
        return skb->len;
 
-rtattr_failure:
+nla_put_failure:
        nlmsg_trim(skb, b);
        return -1;
 }
 
-static struct tcf_proto_ops cls_tcindex_ops = {
-       .next           =       NULL,
+static struct tcf_proto_ops cls_tcindex_ops __read_mostly = {
        .kind           =       "tcindex",
        .classify       =       tcindex_classify,
        .init           =       tcindex_init,