netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [NET_SCHED 00/15]: Make use of new netlink API features
@ 2008-01-23 16:36 Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 01/15]: sch_atm: fix format string warning Patrick McHardy
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

Hi Dave,

these patches change the packet schedulers/classifers/actions to make use
of the features of the new netlink API, like typeful attribute dumping and
parsing, automatic basic attribute validation etc. The also fix a bug and
a warning introduced by my last set of patches.

Please apply, thanks.


 include/linux/pkt_sched.h |    2 +
 include/net/act_api.h     |    4 +-
 net/sched/act_api.c       |  197 +++++++++++++++++++++++++--------------------
 net/sched/act_gact.c      |   20 +++--
 net/sched/act_ipt.c       |   33 +++++---
 net/sched/act_mirred.c    |   15 +++-
 net/sched/act_nat.c       |   15 +++-
 net/sched/act_pedit.c     |   15 +++-
 net/sched/act_police.c    |   43 +++++-----
 net/sched/act_simple.c    |   15 +++-
 net/sched/cls_api.c       |   30 ++++---
 net/sched/cls_basic.c     |   33 ++++----
 net/sched/cls_fw.c        |   41 +++++-----
 net/sched/cls_route.c     |   47 +++++------
 net/sched/cls_rsvp.h      |   45 +++++------
 net/sched/cls_tcindex.c   |   70 ++++++++--------
 net/sched/cls_u32.c       |   56 +++++++------
 net/sched/em_meta.c       |   18 +++--
 net/sched/ematch.c        |   31 +++++---
 net/sched/sch_api.c       |    7 +-
 net/sched/sch_atm.c       |   45 ++++++----
 net/sched/sch_cbq.c       |   75 +++++++----------
 net/sched/sch_dsmark.c    |   37 +++++----
 net/sched/sch_gred.c      |   28 +++++--
 net/sched/sch_hfsc.c      |   30 ++++---
 net/sched/sch_htb.c       |   64 ++++++++++-----
 net/sched/sch_ingress.c   |   12 ++--
 net/sched/sch_netem.c     |   73 +++++++---------
 net/sched/sch_prio.c      |    9 ++-
 net/sched/sch_red.c       |   16 +++-
 net/sched/sch_tbf.c       |   29 +++++---
 31 files changed, 650 insertions(+), 505 deletions(-)

Patrick McHardy (15):
      [NET_SCHED]: sch_atm: fix format string warning
      [NET_SCHED]: sch_netem: use nla_parse_nested_compat
      [NET_SCHED]: act_api: fix netlink API conversion bug
      [NET_SCHED]: act_api: use nlmsg_parse
      [NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get
      [NET_SCHED]: Propagate nla_parse return value
      [NET_SCHED]: Use nla_nest_start/nla_nest_end
      [NET_SCHED]: Use NLA_PUT_STRING for string dumping
      [NET_SCHED]: Use typeful attribute construction helpers
      [NET_SCHED]: Use typeful attribute parsing helpers
      [NET_SCHED]: sch_api: introduce constant for rate table size
      [NET_SCHED]: Use nla_policy for attribute validation in packet schedulers
      [NET_SCHED]: Use nla_policy for attribute validation in classifiers
      [NET_SCHED]: Use nla_policy for attribute validation in actions
      [NET_SCHED]: Use nla_policy for attribute validation in ematches

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [NET_SCHED 01/15]: sch_atm: fix format string warning
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 02/15]: sch_netem: use nla_parse_nested_compat Patrick McHardy
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: sch_atm: fix format string warning

Fix format string warning introduces by the netlink API conversion:

net/sched/sch_atm.c:250: warning: format '%lu' expects type 'long unsigned int', but argument 3 has type 'int'.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 3bab4166cf0350552419d7871b4df463c5aed2ea
tree c08015e39f6f1da0255f1325cc21dfda0c738bc2
parent a7f92e3b13a5e3db64383c503f2249dc74b41bd6
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 16:48:28 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 16:48:28 +0100

 net/sched/sch_atm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index eb01aae..e587391 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -246,7 +246,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 		if (!excess)
 			return -ENOENT;
 	}
-	pr_debug("atm_tc_change: type %d, payload %lu, hdr_len %d\n",
+	pr_debug("atm_tc_change: type %d, payload %d, hdr_len %d\n",
 		 opt->nla_type, nla_len(opt), hdr_len);
 	sock = sockfd_lookup(fd, &error);
 	if (!sock)

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 02/15]: sch_netem: use nla_parse_nested_compat
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 01/15]: sch_atm: fix format string warning Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 03/15]: act_api: fix netlink API conversion bug Patrick McHardy
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: sch_netem: use nla_parse_nested_compat

Replace open coded equivalent of nla_parse_nested_compat().

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 1af28b79f4f0a67db344938ef6739ad2af1a72a7
tree 52294414fad2e6cd11aa719113f160a47bbe5bd5
parent 3bab4166cf0350552419d7871b4df463c5aed2ea
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 16:48:46 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 16:48:46 +0100

 net/sched/sch_netem.c |   58 ++++++++++++++++++++++---------------------------
 1 files changed, 26 insertions(+), 32 deletions(-)

diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index a7b58df..1a75579 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -407,13 +407,18 @@ static int get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
 static int netem_change(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
+	struct nlattr *tb[TCA_NETEM_MAX + 1];
 	struct tc_netem_qopt *qopt;
 	int ret;
 
-	if (opt == NULL || nla_len(opt) < sizeof(*qopt))
+	if (opt == NULL)
 		return -EINVAL;
 
-	qopt = nla_data(opt);
+	ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, NULL, qopt,
+				      sizeof(*qopt));
+	if (ret < 0)
+		return ret;
+
 	ret = set_fifo_limit(q->qdisc, qopt->limit);
 	if (ret) {
 		pr_debug("netem: can't set fifo limit\n");
@@ -434,39 +439,28 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
 	if (q->gap)
 		q->reorder = ~0;
 
-	/* Handle nested options after initial queue options.
-	 * Should have put all options in nested format but too late now.
-	 */
-	if (nla_len(opt) > sizeof(*qopt)) {
-		struct nlattr *tb[TCA_NETEM_MAX + 1];
-		if (nla_parse(tb, TCA_NETEM_MAX,
-			      nla_data(opt) + sizeof(*qopt),
-			      nla_len(opt) - sizeof(*qopt), NULL))
-			return -EINVAL;
-
-		if (tb[TCA_NETEM_CORR]) {
-			ret = get_correlation(sch, tb[TCA_NETEM_CORR]);
-			if (ret)
-				return ret;
-		}
+	if (tb[TCA_NETEM_CORR]) {
+		ret = get_correlation(sch, tb[TCA_NETEM_CORR]);
+		if (ret)
+			return ret;
+	}
 
-		if (tb[TCA_NETEM_DELAY_DIST]) {
-			ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
-			if (ret)
-				return ret;
-		}
+	if (tb[TCA_NETEM_DELAY_DIST]) {
+		ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
+		if (ret)
+			return ret;
+	}
 
-		if (tb[TCA_NETEM_REORDER]) {
-			ret = get_reorder(sch, tb[TCA_NETEM_REORDER]);
-			if (ret)
-				return ret;
-		}
+	if (tb[TCA_NETEM_REORDER]) {
+		ret = get_reorder(sch, tb[TCA_NETEM_REORDER]);
+		if (ret)
+			return ret;
+	}
 
-		if (tb[TCA_NETEM_CORRUPT]) {
-			ret = get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
-			if (ret)
-				return ret;
-		}
+	if (tb[TCA_NETEM_CORRUPT]) {
+		ret = get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
+		if (ret)
+			return ret;
 	}
 
 	return 0;

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 03/15]: act_api: fix netlink API conversion bug
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 01/15]: sch_atm: fix format string warning Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 02/15]: sch_netem: use nla_parse_nested_compat Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 04/15]: act_api: use nlmsg_parse Patrick McHardy
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: act_api: fix netlink API conversion bug

Fix two invalid attribute accesses, indices start at 1 with the new
netlink API.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 512b2ab20730e1d24e36fb94eab4a2731e90e315
tree e3583125570ee0c7a57feac7aa6fcabe2541112a
parent 1af28b79f4f0a67db344938ef6739ad2af1a72a7
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:10:00 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:10:00 +0100

 net/sched/act_api.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index ebd21d2..ae077ed 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -997,11 +997,11 @@ find_dump_kind(struct nlmsghdr *n)
 	if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1),
 		      NLMSG_ALIGN(nla_len(tb1)), NULL) < 0)
 		return NULL;
-	if (tb[0] == NULL)
-		return NULL;
 
-	if (nla_parse(tb2, TCA_ACT_MAX, nla_data(tb[0]),
-		      nla_len(tb[0]), NULL) < 0)
+	if (tb[1] == NULL)
+		return NULL;
+	if (nla_parse(tb2, TCA_ACT_MAX, nla_data(tb[1]),
+		      nla_len(tb[1]), NULL) < 0)
 		return NULL;
 	kind = tb2[TCA_ACT_KIND];
 

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 04/15]: act_api: use nlmsg_parse
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (2 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 03/15]: act_api: fix netlink API conversion bug Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 05/15]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get Patrick McHardy
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: act_api: use nlmsg_parse

Convert open-coded nlmsg_parse to use the real function.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit f9f9cbaccb1a58ea02318250192effe1e2e1e715
tree 7ea770493ca465a7aac1a7779b2aa4c593de3a97
parent 512b2ab20730e1d24e36fb94eab4a2731e90e315
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:10:31 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:10:31 +0100

 net/sched/act_api.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index ae077ed..2fe0345 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -984,11 +984,8 @@ find_dump_kind(struct nlmsghdr *n)
 	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
 	struct nlattr *nla[TCAA_MAX + 1];
 	struct nlattr *kind;
-	int min_len = NLMSG_LENGTH(sizeof(struct tcamsg));
-	int attrlen = n->nlmsg_len - NLMSG_ALIGN(min_len);
-	struct nlattr *attr = (void *) n + NLMSG_ALIGN(min_len);
 
-	if (nla_parse(nla, TCAA_MAX, attr, attrlen, NULL) < 0)
+	if (nlmsg_parse(n, sizeof(struct tcamsg), nla, TCAA_MAX, NULL) < 0)
 		return NULL;
 	tb1 = nla[TCA_ACT_TAB];
 	if (tb1 == NULL)

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 05/15]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (3 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 04/15]: act_api: use nlmsg_parse Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 06/15]: Propagate nla_parse return value Patrick McHardy
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 0919ac24aa4bd6978806f35f8daefe32aa997823
tree 95e2c04521d6a09c080eac8735ab0598c3b3ff5b
parent f9f9cbaccb1a58ea02318250192effe1e2e1e715
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:41 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:41 +0100

 include/net/act_api.h |    4 +--
 net/sched/act_api.c   |   71 +++++++++++++++++++++++++++----------------------
 net/sched/cls_api.c   |   14 +++++-----
 3 files changed, 48 insertions(+), 41 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index c5ac61a..565eed8 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -114,8 +114,8 @@ extern int tcf_register_action(struct tc_action_ops *a);
 extern int tcf_unregister_action(struct tc_action_ops *a);
 extern void tcf_action_destroy(struct tc_action *a, int bind);
 extern int tcf_action_exec(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res);
-extern struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind, int *err);
-extern struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind, int *err);
+extern struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind);
+extern struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est, char *n, int ovr, int bind);
 extern int tcf_action_dump(struct sk_buff *skb, struct tc_action *a, int, int);
 extern int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
 extern int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 2fe0345..ea80f82 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -18,6 +18,7 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/kmod.h>
+#include <linux/err.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/sch_generic.h>
@@ -463,15 +464,16 @@ errout:
 }
 
 struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
-				    char *name, int ovr, int bind, int *err)
+				    char *name, int ovr, int bind)
 {
 	struct tc_action *a;
 	struct tc_action_ops *a_o;
 	char act_name[IFNAMSIZ];
 	struct nlattr *tb[TCA_ACT_MAX+1];
 	struct nlattr *kind;
+	int err;
 
-	*err = -EINVAL;
+	err = -EINVAL;
 
 	if (name == NULL) {
 		if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0)
@@ -502,36 +504,35 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
 		 * indicate this using -EAGAIN.
 		 */
 		if (a_o != NULL) {
-			*err = -EAGAIN;
+			err = -EAGAIN;
 			goto err_mod;
 		}
 #endif
-		*err = -ENOENT;
+		err = -ENOENT;
 		goto err_out;
 	}
 
-	*err = -ENOMEM;
+	err = -ENOMEM;
 	a = kzalloc(sizeof(*a), GFP_KERNEL);
 	if (a == NULL)
 		goto err_mod;
 
 	/* backward compatibility for policer */
 	if (name == NULL)
-		*err = a_o->init(tb[TCA_ACT_OPTIONS], est, a, ovr, bind);
+		err = a_o->init(tb[TCA_ACT_OPTIONS], est, a, ovr, bind);
 	else
-		*err = a_o->init(nla, est, a, ovr, bind);
-	if (*err < 0)
+		err = a_o->init(nla, est, a, ovr, bind);
+	if (err < 0)
 		goto err_free;
 
 	/* module count goes up only when brand new policy is created
 	   if it exists and is only bound to in a_o->init() then
 	   ACT_P_CREATED is not returned (a zero is).
 	*/
-	if (*err != ACT_P_CREATED)
+	if (err != ACT_P_CREATED)
 		module_put(a_o->owner);
 	a->ops = a_o;
 
-	*err = 0;
 	return a;
 
 err_free:
@@ -539,24 +540,22 @@ err_free:
 err_mod:
 	module_put(a_o->owner);
 err_out:
-	return NULL;
+	return ERR_PTR(err);
 }
 
 struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est,
-				  char *name, int ovr, int bind, int *err)
+				  char *name, int ovr, int bind)
 {
 	struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
 	struct tc_action *head = NULL, *act, *act_prev = NULL;
 	int i;
 
-	if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0) {
-		*err = -EINVAL;
-		return head;
-	}
+	if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0)
+		return ERR_PTR(-EINVAL);
 
 	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
-		act = tcf_action_init_1(tb[i], est, name, ovr, bind, err);
-		if (act == NULL)
+		act = tcf_action_init_1(tb[i], est, name, ovr, bind);
+		if (IS_ERR(act))
 			goto err;
 		act->order = i;
 
@@ -571,7 +570,7 @@ struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est,
 err:
 	if (head != NULL)
 		tcf_action_destroy(head, bind);
-	return NULL;
+	return act;
 }
 
 int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
@@ -668,44 +667,46 @@ act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event)
 }
 
 static struct tc_action *
-tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int *err)
+tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 {
 	struct nlattr *tb[TCA_ACT_MAX+1];
 	struct tc_action *a;
 	int index;
+	int err;
 
-	*err = -EINVAL;
+	err = -EINVAL;
 	if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0)
-		return NULL;
+		goto err_out;
 
 	if (tb[TCA_ACT_INDEX] == NULL ||
 	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index))
-		return NULL;
+		goto err_out;
 	index = *(int *)nla_data(tb[TCA_ACT_INDEX]);
 
-	*err = -ENOMEM;
+	err = -ENOMEM;
 	a = kzalloc(sizeof(struct tc_action), GFP_KERNEL);
 	if (a == NULL)
-		return NULL;
+		goto err_out;
 
-	*err = -EINVAL;
+	err = -EINVAL;
 	a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
 	if (a->ops == NULL)
 		goto err_free;
 	if (a->ops->lookup == NULL)
 		goto err_mod;
-	*err = -ENOENT;
+	err = -ENOENT;
 	if (a->ops->lookup(a, index) == 0)
 		goto err_mod;
 
 	module_put(a->ops->owner);
-	*err = 0;
 	return a;
+
 err_mod:
 	module_put(a->ops->owner);
 err_free:
 	kfree(a);
-	return NULL;
+err_out:
+	return ERR_PTR(err);
 }
 
 static void cleanup_a(struct tc_action *act)
@@ -816,9 +817,11 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event)
 	}
 
 	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
-		act = tcf_action_get_1(tb[i], n, pid, &ret);
-		if (act == NULL)
+		act = tcf_action_get_1(tb[i], n, pid);
+		if (IS_ERR(act)) {
+			ret = PTR_ERR(act);
 			goto err;
+		}
 		act->order = i;
 
 		if (head == NULL)
@@ -912,9 +915,13 @@ tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr)
 	struct tc_action *a;
 	u32 seq = n->nlmsg_seq;
 
-	act = tcf_action_init(nla, NULL, NULL, ovr, 0, &ret);
+	act = tcf_action_init(nla, NULL, NULL, ovr, 0);
 	if (act == NULL)
 		goto done;
+	if (IS_ERR(act)) {
+		ret = PTR_ERR(act);
+		goto done;
+	}
 
 	/* dump then free all the actions after update; inserted policy
 	 * stays intact
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index d870478..92fa155 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/netlink.h>
+#include <linux/err.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -487,23 +488,22 @@ int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb,
 
 #ifdef CONFIG_NET_CLS_ACT
 	{
-		int err;
 		struct tc_action *act;
 
 		if (map->police && tb[map->police]) {
 			act = tcf_action_init_1(tb[map->police], rate_tlv,
 						"police", TCA_ACT_NOREPLACE,
-						TCA_ACT_BIND, &err);
-			if (act == NULL)
-				return err;
+						TCA_ACT_BIND);
+			if (IS_ERR(act))
+				return PTR_ERR(act);
 
 			act->type = TCA_OLD_COMPAT;
 			exts->action = act;
 		} else if (map->action && tb[map->action]) {
 			act = tcf_action_init(tb[map->action], rate_tlv, NULL,
-				TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err);
-			if (act == NULL)
-				return err;
+					      TCA_ACT_NOREPLACE, TCA_ACT_BIND);
+			if (IS_ERR(act))
+				return PTR_ERR(act);
 
 			exts->action = act;
 		}

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 06/15]: Propagate nla_parse return value
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (4 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 05/15]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 07/15]: Use nla_nest_start/nla_nest_end Patrick McHardy
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Propagate nla_parse return value

nla_parse() returns more detailed errno codes, propagate them back on error.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit f9b5ab497909e836983bc31e5e7ad5065ccba6bc
tree 3b2ca0f7dcf925d113fce3e376cf7f2e995f0b7a
parent 0919ac24aa4bd6978806f35f8daefe32aa997823
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:54 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:54 +0100

 net/sched/act_api.c     |   29 ++++++++++++++++++-----------
 net/sched/act_gact.c    |    7 ++++++-
 net/sched/act_ipt.c     |    6 +++++-
 net/sched/act_mirred.c  |    8 ++++++--
 net/sched/act_nat.c     |    8 ++++++--
 net/sched/act_pedit.c   |    8 ++++++--
 net/sched/act_police.c  |    6 +++++-
 net/sched/act_simple.c  |    8 ++++++--
 net/sched/cls_basic.c   |    7 ++++---
 net/sched/cls_fw.c      |    5 +++--
 net/sched/cls_route.c   |    5 +++--
 net/sched/cls_rsvp.h    |    5 +++--
 net/sched/cls_tcindex.c |    6 ++++--
 net/sched/cls_u32.c     |    5 +++--
 net/sched/em_meta.c     |    6 ++++--
 net/sched/ematch.c      |    6 ++++--
 net/sched/sch_atm.c     |    6 +++++-
 net/sched/sch_cbq.c     |   14 +++++++++++---
 net/sched/sch_dsmark.c  |   14 ++++++++++++--
 net/sched/sch_gred.c    |   16 +++++++++++++---
 net/sched/sch_hfsc.c    |    7 ++++++-
 net/sched/sch_htb.c     |   23 +++++++++++++++++++----
 net/sched/sch_prio.c    |    9 ++++++---
 net/sched/sch_red.c     |    7 ++++++-
 net/sched/sch_tbf.c     |   10 +++++++---
 25 files changed, 171 insertions(+), 60 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index ea80f82..87818d7 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -473,17 +473,18 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
 	struct nlattr *kind;
 	int err;
 
-	err = -EINVAL;
-
 	if (name == NULL) {
-		if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0)
+		err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+		if (err < 0)
 			goto err_out;
+		err = -EINVAL;
 		kind = tb[TCA_ACT_KIND];
 		if (kind == NULL)
 			goto err_out;
 		if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ)
 			goto err_out;
 	} else {
+		err = -EINVAL;
 		if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ)
 			goto err_out;
 	}
@@ -548,10 +549,12 @@ struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est,
 {
 	struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
 	struct tc_action *head = NULL, *act, *act_prev = NULL;
+	int err;
 	int i;
 
-	if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0)
-		return ERR_PTR(-EINVAL);
+	err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
+	if (err < 0)
+		return ERR_PTR(err);
 
 	for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
 		act = tcf_action_init_1(tb[i], est, name, ovr, bind);
@@ -674,10 +677,11 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 	int index;
 	int err;
 
-	err = -EINVAL;
-	if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0)
+	err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+	if (err < 0)
 		goto err_out;
 
+	err = -EINVAL;
 	if (tb[TCA_ACT_INDEX] == NULL ||
 	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index))
 		goto err_out;
@@ -759,9 +763,11 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 
 	b = skb_tail_pointer(skb);
 
-	if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0)
+	err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL);
+	if (err < 0)
 		goto err_out;
 
+	err = -EINVAL;
 	kind = tb[TCA_ACT_KIND];
 	a->ops = tc_lookup_action(kind);
 	if (a->ops == NULL)
@@ -804,12 +810,13 @@ err_out:
 static int
 tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event)
 {
-	int i, ret = 0;
+	int i, ret;
 	struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
 	struct tc_action *head = NULL, *act, *act_prev = NULL;
 
-	if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0)
-		return -EINVAL;
+	ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
+	if (ret < 0)
+		return ret;
 
 	if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
 		if (tb[0] != NULL && tb[1] == NULL)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 5402cf8..df214d4 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -61,10 +61,15 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
 	struct tcf_gact *gact;
 	struct tcf_common *pc;
 	int ret = 0;
+	int err;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_GACT_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_GACT_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_GACT_PARMS] == NULL ||
 	    nla_len(tb[TCA_GACT_PARMS]) < sizeof(*parm))
 		return -EINVAL;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index fee5282..1269334 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -104,9 +104,13 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 	u32 hook = 0;
 	u32 index = 0;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_IPT_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_IPT_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_IPT_HOOK] == NULL ||
 	    nla_len(tb[TCA_IPT_HOOK]) < sizeof(u32))
 		return -EINVAL;
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index db943a8..6cb5e30 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -62,12 +62,16 @@ static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
 	struct tcf_mirred *m;
 	struct tcf_common *pc;
 	struct net_device *dev = NULL;
-	int ret = 0;
+	int ret = 0, err;
 	int ok_push = 0;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_MIRRED_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_MIRRED_PARMS] == NULL ||
 	    nla_len(tb[TCA_MIRRED_PARMS]) < sizeof(*parm))
 		return -EINVAL;
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index be007bb..5a512d4 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -45,13 +45,17 @@ static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
 {
 	struct nlattr *tb[TCA_NAT_MAX + 1];
 	struct tc_nat *parm;
-	int ret = 0;
+	int ret = 0, err;
 	struct tcf_nat *p;
 	struct tcf_common *pc;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_NAT_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_NAT_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_NAT_PARMS] == NULL ||
 	    nla_len(tb[TCA_NAT_PARMS]) < sizeof(*parm))
 		return -EINVAL;
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 88d8a15..1b9ca45 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -38,15 +38,19 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
 {
 	struct nlattr *tb[TCA_PEDIT_MAX + 1];
 	struct tc_pedit *parm;
-	int ret = 0;
+	int ret = 0, err;
 	struct tcf_pedit *p;
 	struct tcf_common *pc;
 	struct tc_pedit_key *keys = NULL;
 	int ksize;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_PEDIT_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_PEDIT_PARMS] == NULL ||
 	    nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm))
 		return -EINVAL;
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 3af5759..c0fce9b 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -129,9 +129,13 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
 	struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
 	int size;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_POLICE_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_POLICE_TBF] == NULL)
 		return -EINVAL;
 	size = nla_len(tb[TCA_POLICE_TBF]);
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index d3226e2..cedaadf 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -93,11 +93,15 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
 	struct tcf_common *pc;
 	void *defdata;
 	u32 datalen = 0;
-	int ret = 0;
+	int ret = 0, err;
 
-	if (nla == NULL || nla_parse_nested(tb, TCA_DEF_MAX, nla, NULL) < 0)
+	if (nla == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_DEF_MAX, nla, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_DEF_PARMS] == NULL ||
 	    nla_len(tb[TCA_DEF_PARMS]) < sizeof(*parm))
 		return -EINVAL;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 3953da3..524b788 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -166,7 +166,7 @@ errout:
 static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 			struct nlattr **tca, unsigned long *arg)
 {
-	int err = -EINVAL;
+	int err;
 	struct basic_head *head = (struct basic_head *) tp->root;
 	struct nlattr *tb[TCA_BASIC_MAX + 1];
 	struct basic_filter *f = (struct basic_filter *) *arg;
@@ -174,8 +174,9 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (tca[TCA_OPTIONS] == NULL)
 		return -EINVAL;
 
-	if (nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS], NULL) < 0)
-		return -EINVAL;
+	err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS], NULL);
+	if (err < 0)
+		return err;
 
 	if (f != NULL) {
 		if (handle && f->handle != handle)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index db6e90a..a1a9f4d 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -246,8 +246,9 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
 	if (!opt)
 		return handle ? -EINVAL : 0;
 
-	if (nla_parse_nested(tb, TCA_FW_MAX, opt, NULL) < 0)
-		return -EINVAL;
+	err = nla_parse_nested(tb, TCA_FW_MAX, opt, NULL);
+	if (err < 0)
+		return err;
 
 	if (f != NULL) {
 		if (f->id != handle && handle)
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index b1aae84..3aa8109 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -440,8 +440,9 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
 	if (opt == NULL)
 		return handle ? -EINVAL : 0;
 
-	if (nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, NULL) < 0)
-		return -EINVAL;
+	err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, NULL);
+	if (err < 0)
+		return err;
 
 	if ((f = (struct route4_filter*)*arg) != NULL) {
 		if (f->handle != handle && handle)
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 2364c79..5747408 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -416,8 +416,9 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 	if (opt == NULL)
 		return handle ? -EINVAL : 0;
 
-	if (nla_parse_nested(tb, TCA_RSVP_MAX, opt, NULL) < 0)
-		return -EINVAL;
+	err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, NULL);
+	if (err < 0)
+		return err;
 
 	err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &rsvp_ext_map);
 	if (err < 0)
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index ed80239..6b84d27 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -350,6 +350,7 @@ tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	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;
 
 	pr_debug("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p,"
 	    "p %p,r %p,*arg 0x%lx\n",
@@ -358,8 +359,9 @@ tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (!opt)
 		return 0;
 
-	if (nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, NULL) < 0)
-		return -EINVAL;
+	err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, NULL);
+	if (err < 0)
+		return err;
 
 	return tcindex_set_parms(tp, base, handle, p, r, tb, tca[TCA_RATE]);
 }
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index aaf5049..3228cc4 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -531,8 +531,9 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (opt == NULL)
 		return handle ? -EINVAL : 0;
 
-	if (nla_parse_nested(tb, TCA_U32_MAX, opt, NULL) < 0)
-		return -EINVAL;
+	err = nla_parse_nested(tb, TCA_U32_MAX, opt, NULL);
+	if (err < 0)
+		return err;
 
 	if ((n = (struct tc_u_knode*)*arg) != NULL) {
 		if (TC_U32_KEY(n->handle) == 0)
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 92b6863..dd57236 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -749,14 +749,16 @@ static inline int meta_is_supported(struct meta_value *val)
 static int em_meta_change(struct tcf_proto *tp, void *data, int len,
 			  struct tcf_ematch *m)
 {
-	int err = -EINVAL;
+	int err;
 	struct nlattr *tb[TCA_EM_META_MAX + 1];
 	struct tcf_meta_hdr *hdr;
 	struct meta_match *meta = NULL;
 
-	if (nla_parse(tb, TCA_EM_META_MAX, data, len, NULL) < 0)
+	err = nla_parse(tb, TCA_EM_META_MAX, data, len, NULL);
+	if (err < 0)
 		goto errout;
 
+	err = -EINVAL;
 	if (tb[TCA_EM_META_HDR] == NULL ||
 	    nla_len(tb[TCA_EM_META_HDR]) < sizeof(*hdr))
 		goto errout;
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 72d9b27..d2b480f 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -301,7 +301,7 @@ errout:
 int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
 			 struct tcf_ematch_tree *tree)
 {
-	int idx, list_len, matches_len, err = -EINVAL;
+	int idx, list_len, matches_len, err;
 	struct nlattr *tb[TCA_EMATCH_TREE_MAX + 1];
 	struct nlattr *rt_match, *rt_hdr, *rt_list;
 	struct tcf_ematch_tree_hdr *tree_hdr;
@@ -312,9 +312,11 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
 		return 0;
 	}
 
-	if (nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, NULL) < 0)
+	err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, NULL);
+	if (err < 0)
 		goto errout;
 
+	err = -EINVAL;
 	rt_hdr = tb[TCA_EMATCH_TREE_HDR];
 	rt_list = tb[TCA_EMATCH_TREE_LIST];
 
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index e587391..aaa32a2 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -223,8 +223,12 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 	 */
 	if (flow)
 		return -EBUSY;
-	if (opt == NULL || nla_parse_nested(tb, TCA_ATM_MAX, opt, NULL))
+	if (opt == NULL)
 		return -EINVAL;
+	error = nla_parse_nested(tb, TCA_ATM_MAX, opt, NULL);
+	if (error < 0)
+		return error;
+
 	if (!tb[TCA_ATM_FD] || nla_len(tb[TCA_ATM_FD]) < sizeof(fd))
 		return -EINVAL;
 	fd = *(int *)nla_data(tb[TCA_ATM_FD]);
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 5c8667e..585f8a6 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1382,9 +1382,13 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_CBQ_MAX + 1];
 	struct tc_ratespec *r;
+	int err;
+
+	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
+	if (err < 0)
+		return err;
 
-	if (nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL) < 0 ||
-	    tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL ||
+	if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL ||
 	    nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
 		return -EINVAL;
 
@@ -1764,9 +1768,13 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 	struct cbq_class *parent;
 	struct qdisc_rate_table *rtab = NULL;
 
-	if (opt==NULL || nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL))
+	if (opt == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_CBQ_OVL_STRATEGY] &&
 	    nla_len(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(struct tc_cbq_ovl))
 		return -EINVAL;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index f183ab7..f1d0a08 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -116,9 +116,14 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
 		goto errout;
 	}
 
-	if (!opt || nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL))
+	if (!opt)
 		goto errout;
 
+	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
+	if (err < 0)
+		return err;
+
+	err = -EINVAL;
 	if (tb[TCA_DSMARK_MASK]) {
 		if (nla_len(tb[TCA_DSMARK_MASK]) < sizeof(u8))
 			goto errout;
@@ -351,9 +356,14 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
 
 	pr_debug("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
 
-	if (!opt || nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL) < 0)
+	if (!opt)
+		goto errout;
+
+	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
+	if (err < 0)
 		goto errout;
 
+	err = -EINVAL;
 	if (nla_len(tb[TCA_DSMARK_INDICES]) < sizeof(u16))
 		goto errout;
 	indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 6b78483..365c7d8 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -430,12 +430,16 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
 	struct gred_sched *table = qdisc_priv(sch);
 	struct tc_gred_qopt *ctl;
 	struct nlattr *tb[TCA_GRED_MAX + 1];
-	int err = -EINVAL, prio = GRED_DEF_PRIO;
+	int err, prio = GRED_DEF_PRIO;
 	u8 *stab;
 
-	if (opt == NULL || nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL))
+	if (opt == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_GRED_PARMS] == NULL && tb[TCA_GRED_STAB] == NULL)
 		return gred_change_table_def(sch, opt);
 
@@ -445,6 +449,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
 	    nla_len(tb[TCA_GRED_STAB]) < 256)
 		return -EINVAL;
 
+	err = -EINVAL;
 	ctl = nla_data(tb[TCA_GRED_PARMS]);
 	stab = nla_data(tb[TCA_GRED_STAB]);
 
@@ -489,10 +494,15 @@ errout:
 static int gred_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct nlattr *tb[TCA_GRED_MAX + 1];
+	int err;
 
-	if (opt == NULL || nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL))
+	if (opt == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_GRED_PARMS] || tb[TCA_GRED_STAB])
 		return -EINVAL;
 
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 4e6a164..fcb4826 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -997,10 +997,15 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 	struct nlattr *tb[TCA_HFSC_MAX + 1];
 	struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
 	u64 cur_time;
+	int err;
 
-	if (opt == NULL || nla_parse_nested(tb, TCA_HFSC_MAX, opt, NULL))
+	if (opt == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_HFSC_RSC]) {
 		if (nla_len(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
 			return -EINVAL;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 3b3ff64..512df9a 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -997,9 +997,17 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 	struct htb_sched *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_HTB_INIT + 1];
 	struct tc_htb_glob *gopt;
+	int err;
 	int i;
-	if (!opt || nla_parse_nested(tb, TCA_HTB_INIT, opt, NULL) ||
-	    tb[TCA_HTB_INIT] == NULL ||
+
+	if (!opt)
+		return -EINVAL;
+
+	err = nla_parse_nested(tb, TCA_HTB_INIT, opt, NULL);
+	if (err < 0)
+		return err;
+
+	if (tb[TCA_HTB_INIT] == NULL ||
 	    nla_len(tb[TCA_HTB_INIT]) < sizeof(*gopt)) {
 		printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
 		return -EINVAL;
@@ -1302,8 +1310,15 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 	struct tc_htb_opt *hopt;
 
 	/* extract all subattrs from opt attr */
-	if (!opt || nla_parse_nested(tb, TCA_HTB_RTAB, opt, NULL) ||
-	    tb[TCA_HTB_PARMS] == NULL ||
+	if (!opt)
+		goto failure;
+
+	err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, NULL);
+	if (err < 0)
+		goto failure;
+
+	err = -EINVAL;
+	if (tb[TCA_HTB_PARMS] == NULL ||
 	    nla_len(tb[TCA_HTB_PARMS]) < sizeof(*hopt))
 		goto failure;
 
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index a4f932d..4aa2b45 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -229,11 +229,14 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
 	struct prio_sched_data *q = qdisc_priv(sch);
 	struct tc_prio_qopt *qopt;
 	struct nlattr *tb[TCA_PRIO_MAX + 1];
+	int err;
 	int i;
 
-	if (nla_parse_nested_compat(tb, TCA_PRIO_MAX, opt, NULL, qopt,
-				    sizeof(*qopt)))
-		return -EINVAL;
+	err = nla_parse_nested_compat(tb, TCA_PRIO_MAX, opt, NULL, qopt,
+				      sizeof(*qopt));
+	if (err < 0)
+		return err;
+
 	q->bands = qopt->bands;
 	/* If we're multiqueue, make sure the number of incoming bands
 	 * matches the number of queues on the device we're associating with.
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 6ce8da5..dcf6afc 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -207,10 +207,15 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
 	struct nlattr *tb[TCA_RED_MAX + 1];
 	struct tc_red_qopt *ctl;
 	struct Qdisc *child = NULL;
+	int err;
 
-	if (opt == NULL || nla_parse_nested(tb, TCA_RED_MAX, opt, NULL))
+	if (opt == NULL)
 		return -EINVAL;
 
+	err = nla_parse_nested(tb, TCA_RED_MAX, opt, NULL);
+	if (err < 0)
+		return err;
+
 	if (tb[TCA_RED_PARMS] == NULL ||
 	    nla_len(tb[TCA_RED_PARMS]) < sizeof(*ctl) ||
 	    tb[TCA_RED_STAB] == NULL ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index 6c4ad7e..f9b1543 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -272,7 +272,7 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
 
 static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
 {
-	int err = -EINVAL;
+	int err;
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	struct nlattr *tb[TCA_TBF_PTAB + 1];
 	struct tc_tbf_qopt *qopt;
@@ -281,8 +281,12 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
 	struct Qdisc *child = NULL;
 	int max_size,n;
 
-	if (nla_parse_nested(tb, TCA_TBF_PTAB, opt, NULL) ||
-	    tb[TCA_TBF_PARMS] == NULL ||
+	err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, NULL);
+	if (err < 0)
+		return err;
+
+	err = -EINVAL;
+	if (tb[TCA_TBF_PARMS] == NULL ||
 	    nla_len(tb[TCA_TBF_PARMS]) < sizeof(*qopt))
 		goto done;
 

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 07/15]: Use nla_nest_start/nla_nest_end
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (5 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 06/15]: Propagate nla_parse return value Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 08/15]: Use NLA_PUT_STRING for string dumping Patrick McHardy
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use nla_nest_start/nla_nest_end

Use nla_nest_start/nla_nest_end for dumping nested attributes.

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit bdd38a3b14cfa340da580f6e825d7f1142925926
tree 36dc82b63837c96b0f5e1b5c508f789abe7414e8
parent f9b5ab497909e836983bc31e5e7ad5065ccba6bc
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:54 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:54 +0100

 net/sched/act_api.c     |   84 ++++++++++++++++++++++++++---------------------
 net/sched/act_police.c  |   13 ++++---
 net/sched/cls_api.c     |   14 +++++---
 net/sched/cls_basic.c   |   12 +++----
 net/sched/cls_fw.c      |    9 +++--
 net/sched/cls_route.c   |    9 +++--
 net/sched/cls_rsvp.h    |   10 +++---
 net/sched/cls_tcindex.c |   13 ++++---
 net/sched/cls_u32.c     |   13 ++++---
 net/sched/ematch.c      |   16 ++++++---
 net/sched/sch_atm.c     |   15 +++++---
 net/sched/sch_cbq.c     |   24 +++++++------
 net/sched/sch_hfsc.c    |   11 +++---
 net/sched/sch_htb.c     |   32 +++++++++++-------
 net/sched/sch_ingress.c |   12 +++----
 net/sched/sch_tbf.c     |   12 +++----
 16 files changed, 166 insertions(+), 133 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 87818d7..3602260 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -69,7 +69,7 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
 {
 	struct tcf_common *p;
 	int err = 0, index = -1,i = 0, s_i = 0, n_i = 0;
-	struct nlattr *r ;
+	struct nlattr *nest;
 
 	read_lock_bh(hinfo->lock);
 
@@ -84,15 +84,17 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
 				continue;
 			a->priv = p;
 			a->order = n_i;
-			r = (struct nlattr *)skb_tail_pointer(skb);
-			NLA_PUT(skb, a->order, 0, NULL);
+
+			nest = nla_nest_start(skb, a->order);
+			if (nest == NULL)
+				goto nla_put_failure;
 			err = tcf_action_dump_1(skb, a, 0, 0);
 			if (err < 0) {
 				index--;
-				nlmsg_trim(skb, r);
+				nlmsg_trim(skb, nest);
 				goto done;
 			}
-			r->nla_len = skb_tail_pointer(skb) - (u8 *)r;
+			nla_nest_end(skb, nest);
 			n_i++;
 			if (n_i >= TCA_ACT_MAX_PRIO)
 				goto done;
@@ -105,7 +107,7 @@ done:
 	return n_i;
 
 nla_put_failure:
-	nlmsg_trim(skb, r);
+	nla_nest_cancel(skb, nest);
 	goto done;
 }
 
@@ -113,11 +115,12 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
 			  struct tcf_hashinfo *hinfo)
 {
 	struct tcf_common *p, *s_p;
-	struct nlattr *r ;
+	struct nlattr *nest;
 	int i= 0, n_i = 0;
 
-	r = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, a->order, 0, NULL);
+	nest = nla_nest_start(skb, a->order);
+	if (nest == NULL)
+		goto nla_put_failure;
 	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
 	for (i = 0; i < (hinfo->hmask + 1); i++) {
 		p = hinfo->htab[tcf_hash(i, hinfo->hmask)];
@@ -131,11 +134,11 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
 		}
 	}
 	NLA_PUT(skb, TCA_FCNT, 4, &n_i);
-	r->nla_len = skb_tail_pointer(skb) - (u8 *)r;
+	nla_nest_end(skb, nest);
 
 	return n_i;
 nla_put_failure:
-	nlmsg_trim(skb, r);
+	nla_nest_cancel(skb, nest);
 	return -EINVAL;
 }
 
@@ -415,7 +418,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
 	int err = -EINVAL;
 	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *r;
+	struct nlattr *nest;
 
 	if (a->ops == NULL || a->ops->dump == NULL)
 		return err;
@@ -423,10 +426,11 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
 	if (tcf_action_copy_stats(skb, a, 0))
 		goto nla_put_failure;
-	r = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 	if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) {
-		r->nla_len = skb_tail_pointer(skb) - (u8 *)r;
+		nla_nest_end(skb, nest);
 		return err;
 	}
 
@@ -441,17 +445,17 @@ tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
 {
 	struct tc_action *a;
 	int err = -EINVAL;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *r ;
+	struct nlattr *nest;
 
 	while ((a = act) != NULL) {
-		r = (struct nlattr *)skb_tail_pointer(skb);
 		act = a->next;
-		NLA_PUT(skb, a->order, 0, NULL);
+		nest = nla_nest_start(skb, a->order);
+		if (nest == NULL)
+			goto nla_put_failure;
 		err = tcf_action_dump_1(skb, a, bind, ref);
 		if (err < 0)
 			goto errout;
-		r->nla_len = skb_tail_pointer(skb) - (u8 *)r;
+		nla_nest_end(skb, nest);
 	}
 
 	return 0;
@@ -459,7 +463,7 @@ tcf_action_dump(struct sk_buff *skb, struct tc_action *act, int bind, int ref)
 nla_put_failure:
 	err = -EINVAL;
 errout:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return err;
 }
 
@@ -627,7 +631,7 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *x;
+	struct nlattr *nest;
 
 	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags);
 
@@ -636,13 +640,14 @@ tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
 	t->tca__pad1 = 0;
 	t->tca__pad2 = 0;
 
-	x = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+	nest = nla_nest_start(skb, TCA_ACT_TAB);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	if (tcf_action_dump(skb, a, bind, ref) < 0)
 		goto nla_put_failure;
 
-	x->nla_len = skb_tail_pointer(skb) - (u8 *)x;
+	nla_nest_end(skb, nest);
 
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	return skb->len;
@@ -743,7 +748,7 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 	struct nlmsghdr *nlh;
 	struct tcamsg *t;
 	struct netlink_callback dcb;
-	struct nlattr *x;
+	struct nlattr *nest;
 	struct nlattr *tb[TCA_ACT_MAX+1];
 	struct nlattr *kind;
 	struct tc_action *a = create_a(0);
@@ -779,14 +784,15 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 	t->tca__pad1 = 0;
 	t->tca__pad2 = 0;
 
-	x = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+	nest = nla_nest_start(skb, TCA_ACT_TAB);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	err = a->ops->walk(skb, &dcb, RTM_DELACTION, a);
 	if (err < 0)
 		goto nla_put_failure;
 
-	x->nla_len = skb_tail_pointer(skb) - (u8 *)x;
+	nla_nest_end(skb, nest);
 
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	nlh->nlmsg_flags |= NLM_F_ROOT;
@@ -875,7 +881,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
 	struct sk_buff *skb;
-	struct nlattr *x;
+	struct nlattr *nest;
 	unsigned char *b;
 	int err = 0;
 
@@ -891,13 +897,14 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
 	t->tca__pad1 = 0;
 	t->tca__pad2 = 0;
 
-	x = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+	nest = nla_nest_start(skb, TCA_ACT_TAB);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	if (tcf_action_dump(skb, a, 0, 0) < 0)
 		goto nla_put_failure;
 
-	x->nla_len = skb_tail_pointer(skb) - (u8 *)x;
+	nla_nest_end(skb, nest);
 
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	NETLINK_CB(skb).dst_group = RTNLGRP_TC;
@@ -1025,7 +1032,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
 	struct net *net = skb->sk->sk_net;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *x;
+	struct nlattr *nest;
 	struct tc_action_ops *a_o;
 	struct tc_action a;
 	int ret = 0;
@@ -1060,18 +1067,19 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
 	t->tca__pad1 = 0;
 	t->tca__pad2 = 0;
 
-	x = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, TCA_ACT_TAB, 0, NULL);
+	nest = nla_nest_start(skb, TCA_ACT_TAB);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	ret = a_o->walk(skb, cb, RTM_GETACTION, &a);
 	if (ret < 0)
 		goto nla_put_failure;
 
 	if (ret > 0) {
-		x->nla_len = skb_tail_pointer(skb) - (u8 *)x;
+		nla_nest_end(skb, nest);
 		ret = skb->len;
 	} else
-		nlmsg_trim(skb, x);
+		nla_nest_cancel(skb, nest);
 
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	if (NETLINK_CB(cb->skb).pid && ret)
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index c0fce9b..ee2f1b6 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -54,7 +54,7 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
 {
 	struct tcf_common *p;
 	int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
-	struct nlattr *r;
+	struct nlattr *nest;
 
 	read_lock_bh(&police_lock);
 
@@ -69,18 +69,19 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
 				continue;
 			a->priv = p;
 			a->order = index;
-			r = (struct nlattr *)skb_tail_pointer(skb);
-			NLA_PUT(skb, a->order, 0, NULL);
+			nest = nla_nest_start(skb, a->order);
+			if (nest == NULL)
+				goto nla_put_failure;
 			if (type == RTM_DELACTION)
 				err = tcf_action_dump_1(skb, a, 0, 1);
 			else
 				err = tcf_action_dump_1(skb, a, 0, 0);
 			if (err < 0) {
 				index--;
-				nlmsg_trim(skb, r);
+				nla_nest_cancel(skb, nest);
 				goto done;
 			}
-			r->nla_len = skb_tail_pointer(skb) - (u8 *)r;
+			nla_nest_end(skb, nest);
 			n_i++;
 		}
 	}
@@ -91,7 +92,7 @@ done:
 	return n_i;
 
 nla_put_failure:
-	nlmsg_trim(skb, r);
+	nla_nest_cancel(skb, nest);
 	goto done;
 }
 
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 92fa155..5584e7c 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -544,18 +544,22 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts,
 		 * to work with both old and new modes of entering
 		 * tc data even if iproute2  was newer - jhs
 		 */
-		struct nlattr *p_rta = (struct nlattr *)skb_tail_pointer(skb);
+		struct nlattr *nest;
 
 		if (exts->action->type != TCA_OLD_COMPAT) {
-			NLA_PUT(skb, map->action, 0, NULL);
+			nest = nla_nest_start(skb, map->action);
+			if (nest == NULL)
+				goto nla_put_failure;
 			if (tcf_action_dump(skb, exts->action, 0, 0) < 0)
 				goto nla_put_failure;
-			p_rta->nla_len = skb_tail_pointer(skb) - (u8 *)p_rta;
+			nla_nest_end(skb, nest);
 		} else if (map->police) {
-			NLA_PUT(skb, map->police, 0, NULL);
+			nest = nla_nest_start(skb, map->police);
+			if (nest == NULL)
+				goto nla_put_failure;
 			if (tcf_action_dump_old(skb, exts->action, 0, 0) < 0)
 				goto nla_put_failure;
-			p_rta->nla_len = skb_tail_pointer(skb) - (u8 *)p_rta;
+			nla_nest_end(skb, nest);
 		}
 	}
 #endif
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 524b788..6d08b42 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -246,16 +246,16 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh,
 		      struct sk_buff *skb, struct tcmsg *t)
 {
 	struct basic_filter *f = (struct basic_filter *) fh;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
 	if (f == NULL)
 		return skb->len;
 
 	t->tcm_handle = f->handle;
 
-	nla = (struct nlattr *) b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	if (f->res.classid)
 		NLA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);
@@ -264,11 +264,11 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh,
 	    tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
 		goto nla_put_failure;
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index a1a9f4d..e3dfbb3 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -334,7 +334,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
 	struct fw_head *head = (struct fw_head *)tp->root;
 	struct fw_filter *f = (struct fw_filter*)fh;
 	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
 	if (f == NULL)
 		return skb->len;
@@ -344,8 +344,9 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
 	if (!f->res.classid && !tcf_exts_is_available(&f->exts))
 		return skb->len;
 
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	if (f->res.classid)
 		NLA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
@@ -359,7 +360,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
 	if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
 		goto nla_put_failure;
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 
 	if (tcf_exts_dump_stats(skb, &f->exts, &fw_ext_map) < 0)
 		goto nla_put_failure;
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 3aa8109..1ce1f36 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -551,7 +551,7 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
 {
 	struct route4_filter *f = (struct route4_filter*)fh;
 	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 	u32 id;
 
 	if (f == NULL)
@@ -559,8 +559,9 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
 
 	t->tcm_handle = f->handle;
 
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	if (!(f->handle&0x8000)) {
 		id = f->id&0xFF;
@@ -579,7 +580,7 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
 	if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0)
 		goto nla_put_failure;
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 
 	if (tcf_exts_dump_stats(skb, &f->exts, &route_ext_map) < 0)
 		goto nla_put_failure;
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 5747408..77097e0 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -595,7 +595,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 	struct rsvp_filter *f = (struct rsvp_filter*)fh;
 	struct rsvp_session *s;
 	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 	struct tc_rsvp_pinfo pinfo;
 
 	if (f == NULL)
@@ -604,9 +604,9 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 
 	t->tcm_handle = f->handle;
 
-
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	NLA_PUT(skb, TCA_RSVP_DST, sizeof(s->dst), &s->dst);
 	pinfo.dpi = s->dpi;
@@ -624,7 +624,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 	if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0)
 		goto nla_put_failure;
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 
 	if (tcf_exts_dump_stats(skb, &f->exts, &rsvp_ext_map) < 0)
 		goto nla_put_failure;
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 6b84d27..cd350d3 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -437,13 +437,16 @@ 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 nlattr *nla;
+	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);
-	nla = (struct nlattr *) b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
+
 	if (!fh) {
 		t->tcm_handle = ~0; /* whatever ... */
 		NLA_PUT(skb, TCA_TCINDEX_HASH, sizeof(p->hash), &p->hash);
@@ -451,7 +454,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
 		NLA_PUT(skb, TCA_TCINDEX_SHIFT, sizeof(p->shift), &p->shift);
 		NLA_PUT(skb, TCA_TCINDEX_FALL_THROUGH, sizeof(p->fall_through),
 		    &p->fall_through);
-		nla->nla_len = skb_tail_pointer(skb) - b;
+		nla_nest_end(skb, nest);
 	} else {
 		if (p->perfect) {
 			t->tcm_handle = r-p->perfect;
@@ -474,7 +477,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
 
 		if (tcf_exts_dump(skb, &r->exts, &tcindex_ext_map) < 0)
 			goto nla_put_failure;
-		nla->nla_len = skb_tail_pointer(skb) - b;
+		nla_nest_end(skb, nest);
 
 		if (tcf_exts_dump_stats(skb, &r->exts, &tcindex_ext_map) < 0)
 			goto nla_put_failure;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 3228cc4..b51c2c3 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -694,16 +694,16 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 		     struct sk_buff *skb, struct tcmsg *t)
 {
 	struct tc_u_knode *n = (struct tc_u_knode*)fh;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
 	if (n == NULL)
 		return skb->len;
 
 	t->tcm_handle = n->handle;
 
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	if (TC_U32_KEY(n->handle) == 0) {
 		struct tc_u_hnode *ht = (struct tc_u_hnode*)fh;
@@ -741,14 +741,15 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 #endif
 	}
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
+
 	if (TC_U32_KEY(n->handle))
 		if (tcf_exts_dump_stats(skb, &n->exts, &u32_ext_map) < 0)
 			goto nla_put_failure;
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index d2b480f..daa9c4e 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -436,14 +436,18 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
 {
 	int i;
 	u8 *tail;
-	struct nlattr *top_start = (struct nlattr *)skb_tail_pointer(skb);
+	struct nlattr *top_start;
 	struct nlattr *list_start;
 
-	NLA_PUT(skb, tlv, 0, NULL);
+	top_start = nla_nest_start(skb, tlv);
+	if (top_start == NULL)
+		goto nla_put_failure;
+
 	NLA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr);
 
-	list_start = (struct nlattr *)skb_tail_pointer(skb);
-	NLA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL);
+	list_start = nla_nest_start(skb, TCA_EMATCH_TREE_LIST);
+	if (list_start == NULL)
+		goto nla_put_failure;
 
 	tail = skb_tail_pointer(skb);
 	for (i = 0; i < tree->hdr.nmatches; i++) {
@@ -470,8 +474,8 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
 		match_start->nla_len = tail - (u8 *)match_start;
 	}
 
-	list_start->nla_len = tail - (u8 *)list_start;
-	top_start->nla_len = tail - (u8 *)top_start;
+	nla_nest_end(skb, list_start);
+	nla_nest_end(skb, top_start);
 
 	return 0;
 
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index aaa32a2..19c0007 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -605,8 +605,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
 {
 	struct atm_qdisc_data *p = qdisc_priv(sch);
 	struct atm_flow_data *flow = (struct atm_flow_data *)cl;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
 	pr_debug("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n",
 		sch, p, flow, skb, tcm);
@@ -614,8 +613,11 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
 		return -EINVAL;
 	tcm->tcm_handle = flow->classid;
 	tcm->tcm_info = flow->q->handle;
-	nla = (struct nlattr *)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
+
 	NLA_PUT(skb, TCA_ATM_HDR, flow->hdr_len, flow->hdr);
 	if (flow->vcc) {
 		struct sockaddr_atmpvc pvc;
@@ -636,11 +638,12 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
 
 		NLA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero);
 	}
-	nla->nla_len = skb_tail_pointer(skb) - b;
+
+	nla_nest_end(skb, nest);
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 static int
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 585f8a6..da0f6c0 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1565,18 +1565,18 @@ static int cbq_dump_attr(struct sk_buff *skb, struct cbq_class *cl)
 static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 	if (cbq_dump_attr(skb, &q->link) < 0)
 		goto nla_put_failure;
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
@@ -1594,8 +1594,7 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
 	       struct sk_buff *skb, struct tcmsg *tcm)
 {
 	struct cbq_class *cl = (struct cbq_class*)arg;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
 	if (cl->tparent)
 		tcm->tcm_parent = cl->tparent->classid;
@@ -1604,15 +1603,16 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg,
 	tcm->tcm_handle = cl->classid;
 	tcm->tcm_info = cl->q->handle;
 
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 	if (cbq_dump_attr(skb, cl) < 0)
 		goto nla_put_failure;
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index fcb4826..54c3e90 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1343,22 +1343,23 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
 		struct tcmsg *tcm)
 {
 	struct hfsc_class *cl = (struct hfsc_class *)arg;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla = (struct nlattr *)b;
+	struct nlattr *nest;
 
 	tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT;
 	tcm->tcm_handle = cl->classid;
 	if (cl->level == 0)
 		tcm->tcm_info = cl->qdisc->handle;
 
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 	if (hfsc_dump_curves(skb, cl) < 0)
 		goto nla_put_failure;
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
 	return skb->len;
 
  nla_put_failure:
-	nlmsg_trim(skb, b);
+ 	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 512df9a..69fac32 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1043,25 +1043,29 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct htb_sched *q = qdisc_priv(sch);
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 	struct tc_htb_glob gopt;
+
 	spin_lock_bh(&sch->dev->queue_lock);
-	gopt.direct_pkts = q->direct_pkts;
 
+	gopt.direct_pkts = q->direct_pkts;
 	gopt.version = HTB_VER;
 	gopt.rate2quantum = q->rate2quantum;
 	gopt.defcls = q->defcls;
 	gopt.debug = 0;
-	nla = (struct nlattr *)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 	NLA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt);
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nla_nest_end(skb, nest);
+
 	spin_unlock_bh(&sch->dev->queue_lock);
 	return skb->len;
+
 nla_put_failure:
 	spin_unlock_bh(&sch->dev->queue_lock);
-	nlmsg_trim(skb, skb_tail_pointer(skb));
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
@@ -1069,8 +1073,7 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
 			  struct sk_buff *skb, struct tcmsg *tcm)
 {
 	struct htb_class *cl = (struct htb_class *)arg;
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 	struct tc_htb_opt opt;
 
 	spin_lock_bh(&sch->dev->queue_lock);
@@ -1079,8 +1082,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
 	if (!cl->level && cl->un.leaf.q)
 		tcm->tcm_info = cl->un.leaf.q->handle;
 
-	nla = (struct nlattr *)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	memset(&opt, 0, sizeof(opt));
 
@@ -1092,12 +1096,14 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
 	opt.prio = cl->un.leaf.prio;
 	opt.level = cl->level;
 	NLA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt);
-	nla->nla_len = skb_tail_pointer(skb) - b;
+
+	nla_nest_end(skb, nest);
 	spin_unlock_bh(&sch->dev->queue_lock);
 	return skb->len;
+
 nla_put_failure:
 	spin_unlock_bh(&sch->dev->queue_lock);
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index f6decbb..3f72d52 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -183,16 +183,16 @@ static void ingress_destroy(struct Qdisc *sch)
 
 static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 
-	nla = (struct nlattr *)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
+	nla_nest_end(skb, nest);
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index f9b1543..b7a185d 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -375,12 +375,12 @@ static void tbf_destroy(struct Qdisc *sch)
 static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla;
+	struct nlattr *nest;
 	struct tc_tbf_qopt opt;
 
-	nla = (struct nlattr*)b;
-	NLA_PUT(skb, TCA_OPTIONS, 0, NULL);
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (nest == NULL)
+		goto nla_put_failure;
 
 	opt.limit = q->limit;
 	opt.rate = q->R_tab->rate;
@@ -391,12 +391,12 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb)
 	opt.mtu = q->mtu;
 	opt.buffer = q->buffer;
 	NLA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt);
-	nla->nla_len = skb_tail_pointer(skb) - b;
 
+	nla_nest_end(skb, nest);
 	return skb->len;
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nla_nest_cancel(skb, nest);
 	return -1;
 }
 

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 08/15]: Use NLA_PUT_STRING for string dumping
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (6 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 07/15]: Use nla_nest_start/nla_nest_end Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 09/15]: Use typeful attribute construction helpers Patrick McHardy
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use NLA_PUT_STRING for string dumping

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit ad688fbdf7dd0ebeb1b2fba0d7d2105bdf3c6de9
tree 68bb3e1dc3484d6ca0e7ddc55ad4e25864aaac84
parent bdd38a3b14cfa340da580f6e825d7f1142925926
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:55 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:55 +0100

 net/sched/act_api.c |    4 ++--
 net/sched/act_ipt.c |    2 +-
 net/sched/cls_api.c |    2 +-
 net/sched/cls_fw.c  |    2 +-
 net/sched/cls_u32.c |    2 +-
 net/sched/sch_api.c |    4 ++--
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 3602260..e33e43a 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -121,7 +121,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
 	nest = nla_nest_start(skb, a->order);
 	if (nest == NULL)
 		goto nla_put_failure;
-	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+	NLA_PUT_STRING(skb, TCA_KIND, a->ops->kind);
 	for (i = 0; i < (hinfo->hmask + 1); i++) {
 		p = hinfo->htab[tcf_hash(i, hinfo->hmask)];
 
@@ -423,7 +423,7 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 	if (a->ops == NULL || a->ops->dump == NULL)
 		return err;
 
-	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind);
+	NLA_PUT_STRING(skb, TCA_KIND, a->ops->kind);
 	if (tcf_action_copy_stats(skb, a, 0))
 		goto nla_put_failure;
 	nest = nla_nest_start(skb, TCA_OPTIONS);
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 1269334..ecda51d 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -257,7 +257,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
 	NLA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index);
 	NLA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook);
 	NLA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
-	NLA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, ipt->tcfi_tname);
+	NLA_PUT_STRING(skb, TCA_IPT_TABLE, ipt->tcfi_tname);
 	tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install);
 	tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse);
 	tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires);
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 5584e7c..3377ca0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -337,7 +337,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,
 	tcm->tcm_ifindex = tp->q->dev->ifindex;
 	tcm->tcm_parent = tp->classid;
 	tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
-	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, tp->ops->kind);
+	NLA_PUT_STRING(skb, TCA_KIND, tp->ops->kind);
 	tcm->tcm_handle = fh;
 	if (RTM_DELTFILTER != event) {
 		tcm->tcm_handle = 0;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index e3dfbb3..3107473 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -352,7 +352,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
 		NLA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
 #ifdef CONFIG_NET_CLS_IND
 	if (strlen(f->indev))
-		NLA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev);
+		NLA_PUT_STRING(skb, TCA_FW_INDEV, f->indev);
 #endif /* CONFIG_NET_CLS_IND */
 	if (head->mask != 0xFFFFFFFF)
 		NLA_PUT(skb, TCA_FW_MASK, 4, &head->mask);
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index b51c2c3..7a15025 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -732,7 +732,7 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 
 #ifdef CONFIG_NET_CLS_IND
 		if(strlen(n->indev))
-			NLA_PUT(skb, TCA_U32_INDEV, IFNAMSIZ, n->indev);
+			NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev);
 #endif
 #ifdef CONFIG_CLS_U32_PERF
 		NLA_PUT(skb, TCA_U32_PCNT,
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 7abb028..8db554d 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -834,7 +834,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
 	tcm->tcm_parent = clid;
 	tcm->tcm_handle = q->handle;
 	tcm->tcm_info = atomic_read(&q->refcnt);
-	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
+	NLA_PUT_STRING(skb, TCA_KIND, q->ops->id);
 	if (q->ops->dump && q->ops->dump(q, skb) < 0)
 		goto nla_put_failure;
 	q->qstats.qlen = q->q.qlen;
@@ -1080,7 +1080,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
 	tcm->tcm_parent = q->handle;
 	tcm->tcm_handle = q->handle;
 	tcm->tcm_info = 0;
-	NLA_PUT(skb, TCA_KIND, IFNAMSIZ, q->ops->id);
+	NLA_PUT_STRING(skb, TCA_KIND, q->ops->id);
 	if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0)
 		goto nla_put_failure;
 

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 09/15]: Use typeful attribute construction helpers
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (7 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 08/15]: Use NLA_PUT_STRING for string dumping Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 10/15]: Use typeful attribute parsing helpers Patrick McHardy
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use typeful attribute construction helpers

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 04d3c2781cba0b4ab75005de0defdb2a58178f21
tree a1b904b7f29ad1ff7cff310128b3fd67e2543278
parent ad688fbdf7dd0ebeb1b2fba0d7d2105bdf3c6de9
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:55 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:55 +0100

 net/sched/act_api.c     |    2 +-
 net/sched/act_ipt.c     |    4 ++--
 net/sched/act_police.c  |    5 ++---
 net/sched/cls_basic.c   |    2 +-
 net/sched/cls_fw.c      |    4 ++--
 net/sched/cls_route.c   |    8 ++++----
 net/sched/cls_rsvp.h    |    2 +-
 net/sched/cls_tcindex.c |   11 +++++------
 net/sched/cls_u32.c     |    8 ++++----
 net/sched/em_meta.c     |    3 +--
 net/sched/sch_atm.c     |    8 +++-----
 11 files changed, 26 insertions(+), 31 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index e33e43a..41fbd49 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -133,7 +133,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
 			p = s_p;
 		}
 	}
-	NLA_PUT(skb, TCA_FCNT, 4, &n_i);
+	NLA_PUT_U32(skb, TCA_FCNT, n_i);
 	nla_nest_end(skb, nest);
 
 	return n_i;
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index ecda51d..5dd701a 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -254,8 +254,8 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
 	strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name);
 
 	NLA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t);
-	NLA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index);
-	NLA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook);
+	NLA_PUT_U32(skb, TCA_IPT_INDEX, ipt->tcf_index);
+	NLA_PUT_U32(skb, TCA_IPT_HOOK, ipt->tcfi_hook);
 	NLA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c);
 	NLA_PUT_STRING(skb, TCA_IPT_TABLE, ipt->tcfi_tname);
 	tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index ee2f1b6..79db6bb 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -339,10 +339,9 @@ tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 		memset(&opt.peakrate, 0, sizeof(opt.peakrate));
 	NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
 	if (police->tcfp_result)
-		NLA_PUT(skb, TCA_POLICE_RESULT, sizeof(int),
-			&police->tcfp_result);
+		NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result);
 	if (police->tcfp_ewma_rate)
-		NLA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate);
+		NLA_PUT_U32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate);
 	return skb->len;
 
 nla_put_failure:
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 6d08b42..58444fe 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -258,7 +258,7 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh,
 		goto nla_put_failure;
 
 	if (f->res.classid)
-		NLA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);
+		NLA_PUT_U32(skb, TCA_BASIC_CLASSID, f->res.classid);
 
 	if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
 	    tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 3107473..61ebe25 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -349,13 +349,13 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
 		goto nla_put_failure;
 
 	if (f->res.classid)
-		NLA_PUT(skb, TCA_FW_CLASSID, 4, &f->res.classid);
+		NLA_PUT_U32(skb, TCA_FW_CLASSID, f->res.classid);
 #ifdef CONFIG_NET_CLS_IND
 	if (strlen(f->indev))
 		NLA_PUT_STRING(skb, TCA_FW_INDEV, f->indev);
 #endif /* CONFIG_NET_CLS_IND */
 	if (head->mask != 0xFFFFFFFF)
-		NLA_PUT(skb, TCA_FW_MASK, 4, &head->mask);
+		NLA_PUT_U32(skb, TCA_FW_MASK, head->mask);
 
 	if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0)
 		goto nla_put_failure;
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 1ce1f36..7752586 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -565,17 +565,17 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
 
 	if (!(f->handle&0x8000)) {
 		id = f->id&0xFF;
-		NLA_PUT(skb, TCA_ROUTE4_TO, sizeof(id), &id);
+		NLA_PUT_U32(skb, TCA_ROUTE4_TO, id);
 	}
 	if (f->handle&0x80000000) {
 		if ((f->handle>>16) != 0xFFFF)
-			NLA_PUT(skb, TCA_ROUTE4_IIF, sizeof(f->iif), &f->iif);
+			NLA_PUT_U32(skb, TCA_ROUTE4_IIF, f->iif);
 	} else {
 		id = f->id>>16;
-		NLA_PUT(skb, TCA_ROUTE4_FROM, sizeof(id), &id);
+		NLA_PUT_U32(skb, TCA_ROUTE4_FROM, id);
 	}
 	if (f->res.classid)
-		NLA_PUT(skb, TCA_ROUTE4_CLASSID, 4, &f->res.classid);
+		NLA_PUT_U32(skb, TCA_ROUTE4_CLASSID, f->res.classid);
 
 	if (tcf_exts_dump(skb, &f->exts, &route_ext_map) < 0)
 		goto nla_put_failure;
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 77097e0..838a3ff 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -617,7 +617,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 	pinfo.pad = 0;
 	NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);
 	if (f->res.classid)
-		NLA_PUT(skb, TCA_RSVP_CLASSID, 4, &f->res.classid);
+		NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid);
 	if (((f->handle>>8)&0xFF) != 16)
 		NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
 
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index cd350d3..7d46df7 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -449,11 +449,10 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
 
 	if (!fh) {
 		t->tcm_handle = ~0; /* whatever ... */
-		NLA_PUT(skb, TCA_TCINDEX_HASH, sizeof(p->hash), &p->hash);
-		NLA_PUT(skb, TCA_TCINDEX_MASK, sizeof(p->mask), &p->mask);
-		NLA_PUT(skb, TCA_TCINDEX_SHIFT, sizeof(p->shift), &p->shift);
-		NLA_PUT(skb, TCA_TCINDEX_FALL_THROUGH, sizeof(p->fall_through),
-		    &p->fall_through);
+		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) {
@@ -473,7 +472,7 @@ static int tcindex_dump(struct tcf_proto *tp, unsigned long fh,
 		}
 		pr_debug("handle = %d\n", t->tcm_handle);
 		if (r->res.class)
-			NLA_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 nla_put_failure;
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 7a15025..326711e 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -708,19 +708,19 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 	if (TC_U32_KEY(n->handle) == 0) {
 		struct tc_u_hnode *ht = (struct tc_u_hnode*)fh;
 		u32 divisor = ht->divisor+1;
-		NLA_PUT(skb, TCA_U32_DIVISOR, 4, &divisor);
+		NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor);
 	} else {
 		NLA_PUT(skb, TCA_U32_SEL,
 			sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
 			&n->sel);
 		if (n->ht_up) {
 			u32 htid = n->handle & 0xFFFFF000;
-			NLA_PUT(skb, TCA_U32_HASH, 4, &htid);
+			NLA_PUT_U32(skb, TCA_U32_HASH, htid);
 		}
 		if (n->res.classid)
-			NLA_PUT(skb, TCA_U32_CLASSID, 4, &n->res.classid);
+			NLA_PUT_U32(skb, TCA_U32_CLASSID, n->res.classid);
 		if (n->ht_down)
-			NLA_PUT(skb, TCA_U32_LINK, 4, &n->ht_down->handle);
+			NLA_PUT_U32(skb, TCA_U32_LINK, n->ht_down->handle);
 
 #ifdef CONFIG_CLS_U32_MARK
 		if (n->mark.val || n->mark.mask)
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index dd57236..63ae6a2 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -623,8 +623,7 @@ static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
 	if (v->len == sizeof(unsigned long))
 		NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
 	else if (v->len == sizeof(u32)) {
-		u32 d = v->val;
-		NLA_PUT(skb, tlv, sizeof(d), &d);
+		NLA_PUT_U32(skb, tlv, v->val);
 	}
 
 	return 0;
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 19c0007..4d87659 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -629,14 +629,12 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
 		pvc.sap_addr.vci = flow->vcc->vci;
 		NLA_PUT(skb, TCA_ATM_ADDR, sizeof(pvc), &pvc);
 		state = ATM_VF2VS(flow->vcc->flags);
-		NLA_PUT(skb, TCA_ATM_STATE, sizeof(state), &state);
+		NLA_PUT_U32(skb, TCA_ATM_STATE, state);
 	}
 	if (flow->excess)
-		NLA_PUT(skb, TCA_ATM_EXCESS, sizeof(u32), &flow->classid);
+		NLA_PUT_U32(skb, TCA_ATM_EXCESS, flow->classid);
 	else {
-		static u32 zero;
-
-		NLA_PUT(skb, TCA_ATM_EXCESS, sizeof(zero), &zero);
+		NLA_PUT_U32(skb, TCA_ATM_EXCESS, 0);
 	}
 
 	nla_nest_end(skb, nest);

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 10/15]: Use typeful attribute parsing helpers
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (8 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 09/15]: Use typeful attribute construction helpers Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 11/15]: sch_api: introduce constant for rate table size Patrick McHardy
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use typeful attribute parsing helpers

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 3e73383f7c353af51e8cc475f1c217a6b81fcecf
tree 53d369ca2ffca26cf46c57d2a9043d53da7474f8
parent 04d3c2781cba0b4ab75005de0defdb2a58178f21
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:56 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:56 +0100

 net/sched/act_api.c     |    2 +-
 net/sched/act_ipt.c     |    4 ++--
 net/sched/act_police.c  |    5 ++---
 net/sched/cls_basic.c   |    2 +-
 net/sched/cls_fw.c      |    6 +++---
 net/sched/cls_route.c   |    8 ++++----
 net/sched/cls_rsvp.h    |    4 ++--
 net/sched/cls_tcindex.c |   11 +++++------
 net/sched/cls_u32.c     |    8 ++++----
 net/sched/em_meta.c     |    2 +-
 net/sched/sch_atm.c     |    4 ++--
 11 files changed, 27 insertions(+), 29 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 41fbd49..0b8eb23 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -690,7 +690,7 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 	if (tb[TCA_ACT_INDEX] == NULL ||
 	    nla_len(tb[TCA_ACT_INDEX]) < sizeof(index))
 		goto err_out;
-	index = *(int *)nla_data(tb[TCA_ACT_INDEX]);
+	index = nla_get_u32(tb[TCA_ACT_INDEX]);
 
 	err = -ENOMEM;
 	a = kzalloc(sizeof(struct tc_action), GFP_KERNEL);
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 5dd701a..7ab2419 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -123,7 +123,7 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 
 	if (tb[TCA_IPT_INDEX] != NULL &&
 	    nla_len(tb[TCA_IPT_INDEX]) >= sizeof(u32))
-		index = *(u32 *)nla_data(tb[TCA_IPT_INDEX]);
+		index = nla_get_u32(tb[TCA_IPT_INDEX]);
 
 	pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
 	if (!pc) {
@@ -140,7 +140,7 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 	}
 	ipt = to_ipt(pc);
 
-	hook = *(u32 *)nla_data(tb[TCA_IPT_HOOK]);
+	hook = nla_get_u32(tb[TCA_IPT_HOOK]);
 
 	err = -ENOMEM;
 	tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 79db6bb..62de806 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -203,7 +203,7 @@ override:
 	}
 
 	if (tb[TCA_POLICE_RESULT])
-		police->tcfp_result = *(u32*)nla_data(tb[TCA_POLICE_RESULT]);
+		police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
 	police->tcfp_toks = police->tcfp_burst = parm->burst;
 	police->tcfp_mtu = parm->mtu;
 	if (police->tcfp_mtu == 0) {
@@ -216,8 +216,7 @@ override:
 	police->tcf_action = parm->action;
 
 	if (tb[TCA_POLICE_AVRATE])
-		police->tcfp_ewma_rate =
-			*(u32*)nla_data(tb[TCA_POLICE_AVRATE]);
+		police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
 	if (est)
 		gen_replace_estimator(&police->tcf_bstats,
 				      &police->tcf_rate_est,
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 58444fe..0c872a7 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -150,7 +150,7 @@ static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
 		goto errout;
 
 	if (tb[TCA_BASIC_CLASSID]) {
-		f->res.classid = *(u32*)nla_data(tb[TCA_BASIC_CLASSID]);
+		f->res.classid = nla_get_u32(tb[TCA_BASIC_CLASSID]);
 		tcf_bind_filter(tp, &f->res, base);
 	}
 
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 61ebe25..b75696d 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -203,7 +203,7 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
 	if (tb[TCA_FW_CLASSID]) {
 		if (nla_len(tb[TCA_FW_CLASSID]) != sizeof(u32))
 			goto errout;
-		f->res.classid = *(u32*)nla_data(tb[TCA_FW_CLASSID]);
+		f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
 		tcf_bind_filter(tp, &f->res, base);
 	}
 
@@ -218,7 +218,7 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
 	if (tb[TCA_FW_MASK]) {
 		if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
 			goto errout;
-		mask = *(u32*)nla_data(tb[TCA_FW_MASK]);
+		mask = nla_get_u32(tb[TCA_FW_MASK]);
 		if (mask != head->mask)
 			goto errout;
 	} else if (head->mask != 0xFFFFFFFF)
@@ -264,7 +264,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
 		if (tb[TCA_FW_MASK]) {
 			if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
 				return -EINVAL;
-			mask = *(u32*)nla_data(tb[TCA_FW_MASK]);
+			mask = nla_get_u32(tb[TCA_FW_MASK]);
 		}
 
 		head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 7752586..ae97238 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -348,7 +348,7 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 			goto errout;
 		if (nla_len(tb[TCA_ROUTE4_TO]) < sizeof(u32))
 			goto errout;
-		to = *(u32*)nla_data(tb[TCA_ROUTE4_TO]);
+		to = nla_get_u32(tb[TCA_ROUTE4_TO]);
 		if (to > 0xFF)
 			goto errout;
 		nhandle = to;
@@ -359,14 +359,14 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 			goto errout;
 		if (nla_len(tb[TCA_ROUTE4_FROM]) < sizeof(u32))
 			goto errout;
-		id = *(u32*)nla_data(tb[TCA_ROUTE4_FROM]);
+		id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
 		if (id > 0xFF)
 			goto errout;
 		nhandle |= id << 16;
 	} else if (tb[TCA_ROUTE4_IIF]) {
 		if (nla_len(tb[TCA_ROUTE4_IIF]) < sizeof(u32))
 			goto errout;
-		id = *(u32*)nla_data(tb[TCA_ROUTE4_IIF]);
+		id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
 		if (id > 0x7FFF)
 			goto errout;
 		nhandle |= (id | 0x8000) << 16;
@@ -411,7 +411,7 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 	tcf_tree_unlock(tp);
 
 	if (tb[TCA_ROUTE4_CLASSID]) {
-		f->res.classid = *(u32*)nla_data(tb[TCA_ROUTE4_CLASSID]);
+		f->res.classid = nla_get_u32(tb[TCA_ROUTE4_CLASSID]);
 		tcf_bind_filter(tp, &f->res, base);
 	}
 
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 838a3ff..61286a0 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -430,7 +430,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 		if (f->handle != handle && handle)
 			goto errout2;
 		if (tb[TCA_RSVP_CLASSID-1]) {
-			f->res.classid = *(u32*)nla_data(tb[TCA_RSVP_CLASSID-1]);
+			f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID-1]);
 			tcf_bind_filter(tp, &f->res, base);
 		}
 
@@ -470,7 +470,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 		err = -EINVAL;
 		if (nla_len(tb[TCA_RSVP_CLASSID-1]) != 4)
 			goto errout;
-		f->res.classid = *(u32*)nla_data(tb[TCA_RSVP_CLASSID-1]);
+		f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID-1]);
 	}
 
 	err = -EINVAL;
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 7d46df7..2809856 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -221,19 +221,19 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (tb[TCA_TCINDEX_HASH]) {
 		if (nla_len(tb[TCA_TCINDEX_HASH]) < sizeof(u32))
 			goto errout;
-		cp.hash = *(u32 *) nla_data(tb[TCA_TCINDEX_HASH]);
+		cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
 	}
 
 	if (tb[TCA_TCINDEX_MASK]) {
 		if (nla_len(tb[TCA_TCINDEX_MASK]) < sizeof(u16))
 			goto errout;
-		cp.mask = *(u16 *) nla_data(tb[TCA_TCINDEX_MASK]);
+		cp.mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
 	}
 
 	if (tb[TCA_TCINDEX_SHIFT]) {
 		if (nla_len(tb[TCA_TCINDEX_SHIFT]) < sizeof(int))
 			goto errout;
-		cp.shift = *(int *) nla_data(tb[TCA_TCINDEX_SHIFT]);
+		cp.shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]);
 	}
 
 	err = -EBUSY;
@@ -251,8 +251,7 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (tb[TCA_TCINDEX_FALL_THROUGH]) {
 		if (nla_len(tb[TCA_TCINDEX_FALL_THROUGH]) < sizeof(u32))
 			goto errout;
-		cp.fall_through =
-			*(u32 *) nla_data(tb[TCA_TCINDEX_FALL_THROUGH]);
+		cp.fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]);
 	}
 
 	if (!cp.hash) {
@@ -305,7 +304,7 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
 	}
 
 	if (tb[TCA_TCINDEX_CLASSID]) {
-		cr.res.classid = *(u32 *) nla_data(tb[TCA_TCINDEX_CLASSID]);
+		cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
 		tcf_bind_filter(tp, &cr.res, base);
 	}
 
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 326711e..a4e72e8 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -474,7 +474,7 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
 
 	err = -EINVAL;
 	if (tb[TCA_U32_LINK]) {
-		u32 handle = *(u32*)nla_data(tb[TCA_U32_LINK]);
+		u32 handle = nla_get_u32(tb[TCA_U32_LINK]);
 		struct tc_u_hnode *ht_down = NULL;
 
 		if (TC_U32_KEY(handle))
@@ -496,7 +496,7 @@ static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
 			ht_down->refcnt--;
 	}
 	if (tb[TCA_U32_CLASSID]) {
-		n->res.classid = *(u32*)nla_data(tb[TCA_U32_CLASSID]);
+		n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
 		tcf_bind_filter(tp, &n->res, base);
 	}
 
@@ -543,7 +543,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	}
 
 	if (tb[TCA_U32_DIVISOR]) {
-		unsigned divisor = *(unsigned*)nla_data(tb[TCA_U32_DIVISOR]);
+		unsigned divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
 
 		if (--divisor > 0x100)
 			return -EINVAL;
@@ -569,7 +569,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	}
 
 	if (tb[TCA_U32_HASH]) {
-		htid = *(unsigned*)nla_data(tb[TCA_U32_HASH]);
+		htid = nla_get_u32(tb[TCA_U32_HASH]);
 		if (TC_U32_HTID(htid) == TC_U32_ROOT) {
 			ht = tp->root;
 			htid = ht->handle;
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 63ae6a2..d9f487d 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -600,7 +600,7 @@ static int meta_int_change(struct meta_value *dst, struct nlattr *nla)
 		dst->val = *(unsigned long *) nla_data(nla);
 		dst->len = sizeof(unsigned long);
 	} else if (nla_len(nla) == sizeof(u32)) {
-		dst->val = *(u32 *) nla_data(nla);
+		dst->val = nla_get_u32(nla);
 		dst->len = sizeof(u32);
 	} else
 		return -EINVAL;
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 4d87659..0c71f2e 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -231,7 +231,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 
 	if (!tb[TCA_ATM_FD] || nla_len(tb[TCA_ATM_FD]) < sizeof(fd))
 		return -EINVAL;
-	fd = *(int *)nla_data(tb[TCA_ATM_FD]);
+	fd = nla_get_u32(tb[TCA_ATM_FD]);
 	pr_debug("atm_tc_change: fd %d\n", fd);
 	if (tb[TCA_ATM_HDR]) {
 		hdr_len = nla_len(tb[TCA_ATM_HDR]);
@@ -246,7 +246,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 		if (nla_len(tb[TCA_ATM_EXCESS]) != sizeof(u32))
 			return -EINVAL;
 		excess = (struct atm_flow_data *)
-			atm_tc_get(sch, *(u32 *)nla_data(tb[TCA_ATM_EXCESS]));
+			atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
 		if (!excess)
 			return -ENOENT;
 	}

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 11/15]: sch_api: introduce constant for rate table size
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (9 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 10/15]: Use typeful attribute parsing helpers Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 12/15]: Use nla_policy for attribute validation in packet schedulers Patrick McHardy
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: sch_api: introduce constant for rate table size

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit b21f31e516f993016f8a1ade331bcaf71576b4e2
tree e59049e1fb3f2711d83c196d2f54b5021dc68330
parent 3e73383f7c353af51e8cc475f1c217a6b81fcecf
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:56 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:56 +0100

 include/linux/pkt_sched.h |    2 ++
 net/sched/sch_api.c       |    3 ++-
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 919af93..3276135 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -83,6 +83,8 @@ struct tc_ratespec
 	__u32		rate;
 };
 
+#define TC_RTAB_SIZE	1024
+
 /* FIFO section */
 
 struct tc_fifo_qopt
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 8db554d..7e3c048 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -244,7 +244,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
 		}
 	}
 
-	if (tab == NULL || r->rate == 0 || r->cell_log == 0 || nla_len(tab) != 1024)
+	if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+	    nla_len(tab) != TC_RTAB_SIZE)
 		return NULL;
 
 	rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 12/15]: Use nla_policy for attribute validation in packet schedulers
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (10 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 11/15]: sch_api: introduce constant for rate table size Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 13/15]: Use nla_policy for attribute validation in classifiers Patrick McHardy
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use nla_policy for attribute validation in packet schedulers

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 76c3c24283fa9f78d8dc30c8eb73e0f11934bf69
tree bcc9baf4eae9086d377efff17fbd37a360ac64b7
parent b21f31e516f993016f8a1ade331bcaf71576b4e2
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:57 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:12:57 +0100

 net/sched/sch_atm.c    |   12 ++++++++----
 net/sched/sch_cbq.c    |   47 +++++++++++++----------------------------------
 net/sched/sch_dsmark.c |   33 +++++++++++++++------------------
 net/sched/sch_gred.c   |   16 ++++++++++------
 net/sched/sch_hfsc.c   |   14 +++++++-------
 net/sched/sch_htb.c    |   17 +++++++++++------
 net/sched/sch_netem.c  |   19 ++++++++-----------
 net/sched/sch_red.c    |   11 +++++++----
 net/sched/sch_tbf.c    |   11 ++++++++---
 9 files changed, 87 insertions(+), 93 deletions(-)

diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 0c71f2e..3352734 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -195,6 +195,11 @@ static const u8 llc_oui_ip[] = {
 	0x08, 0x00
 };				/* Ethertype IP (0800) */
 
+static const struct nla_policy atm_policy[TCA_ATM_MAX + 1] = {
+	[TCA_ATM_FD]		= { .type = NLA_U32 },
+	[TCA_ATM_EXCESS]	= { .type = NLA_U32 },
+};
+
 static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 			 struct nlattr **tca, unsigned long *arg)
 {
@@ -225,11 +230,12 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 		return -EBUSY;
 	if (opt == NULL)
 		return -EINVAL;
-	error = nla_parse_nested(tb, TCA_ATM_MAX, opt, NULL);
+
+	error = nla_parse_nested(tb, TCA_ATM_MAX, opt, atm_policy);
 	if (error < 0)
 		return error;
 
-	if (!tb[TCA_ATM_FD] || nla_len(tb[TCA_ATM_FD]) < sizeof(fd))
+	if (!tb[TCA_ATM_FD])
 		return -EINVAL;
 	fd = nla_get_u32(tb[TCA_ATM_FD]);
 	pr_debug("atm_tc_change: fd %d\n", fd);
@@ -243,8 +249,6 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
 	if (!tb[TCA_ATM_EXCESS])
 		excess = NULL;
 	else {
-		if (nla_len(tb[TCA_ATM_EXCESS]) != sizeof(u32))
-			return -EINVAL;
 		excess = (struct atm_flow_data *)
 			atm_tc_get(sch, nla_get_u32(tb[TCA_ATM_EXCESS]));
 		if (!excess)
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index da0f6c0..09969c1 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1377,6 +1377,16 @@ static int cbq_set_fopt(struct cbq_class *cl, struct tc_cbq_fopt *fopt)
 	return 0;
 }
 
+static const struct nla_policy cbq_policy[TCA_CBQ_MAX + 1] = {
+	[TCA_CBQ_LSSOPT]	= { .len = sizeof(struct tc_cbq_lssopt) },
+	[TCA_CBQ_WRROPT]	= { .len = sizeof(struct tc_cbq_wrropt) },
+	[TCA_CBQ_FOPT]		= { .len = sizeof(struct tc_cbq_fopt) },
+	[TCA_CBQ_OVL_STRATEGY]	= { .len = sizeof(struct tc_cbq_ovl) },
+	[TCA_CBQ_RATE]		= { .len = sizeof(struct tc_ratespec) },
+	[TCA_CBQ_RTAB]		= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+	[TCA_CBQ_POLICE]	= { .len = sizeof(struct tc_cbq_police) },
+};
+
 static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
@@ -1384,16 +1394,11 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
 	struct tc_ratespec *r;
 	int err;
 
-	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL ||
-	    nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
-		return -EINVAL;
-
-	if (tb[TCA_CBQ_LSSOPT] &&
-	    nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
+	if (tb[TCA_CBQ_RTAB] == NULL || tb[TCA_CBQ_RATE] == NULL)
 		return -EINVAL;
 
 	r = nla_data(tb[TCA_CBQ_RATE]);
@@ -1771,36 +1776,10 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 	if (opt == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_CBQ_MAX, opt, cbq_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_CBQ_OVL_STRATEGY] &&
-	    nla_len(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(struct tc_cbq_ovl))
-		return -EINVAL;
-
-	if (tb[TCA_CBQ_FOPT] &&
-	    nla_len(tb[TCA_CBQ_FOPT]) < sizeof(struct tc_cbq_fopt))
-		return -EINVAL;
-
-	if (tb[TCA_CBQ_RATE] &&
-	    nla_len(tb[TCA_CBQ_RATE]) < sizeof(struct tc_ratespec))
-			return -EINVAL;
-
-	if (tb[TCA_CBQ_LSSOPT] &&
-	    nla_len(tb[TCA_CBQ_LSSOPT]) < sizeof(struct tc_cbq_lssopt))
-			return -EINVAL;
-
-	if (tb[TCA_CBQ_WRROPT] &&
-	    nla_len(tb[TCA_CBQ_WRROPT]) < sizeof(struct tc_cbq_wrropt))
-			return -EINVAL;
-
-#ifdef CONFIG_NET_CLS_ACT
-	if (tb[TCA_CBQ_POLICE] &&
-	    nla_len(tb[TCA_CBQ_POLICE]) < sizeof(struct tc_cbq_police))
-			return -EINVAL;
-#endif
-
 	if (cl) {
 		/* Check parent */
 		if (parentid) {
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index f1d0a08..0df911f 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -99,6 +99,14 @@ static void dsmark_put(struct Qdisc *sch, unsigned long cl)
 {
 }
 
+static const struct nla_policy dsmark_policy[TCA_DSMARK_MAX + 1] = {
+	[TCA_DSMARK_INDICES]		= { .type = NLA_U16 },
+	[TCA_DSMARK_DEFAULT_INDEX]	= { .type = NLA_U16 },
+	[TCA_DSMARK_SET_TC_INDEX]	= { .type = NLA_FLAG },
+	[TCA_DSMARK_MASK]		= { .type = NLA_U8 },
+	[TCA_DSMARK_VALUE]		= { .type = NLA_U8 },
+};
+
 static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
 			 struct nlattr **tca, unsigned long *arg)
 {
@@ -119,21 +127,15 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
 	if (!opt)
 		goto errout;
 
-	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
 	if (err < 0)
-		return err;
+		goto errout;
 
-	err = -EINVAL;
-	if (tb[TCA_DSMARK_MASK]) {
-		if (nla_len(tb[TCA_DSMARK_MASK]) < sizeof(u8))
-			goto errout;
+	if (tb[TCA_DSMARK_MASK])
 		mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
-	}
-	if (tb[TCA_DSMARK_VALUE]) {
-		if (nla_len(tb[TCA_DSMARK_VALUE]) < sizeof(u8))
-			goto errout;
+
+	if (tb[TCA_DSMARK_VALUE])
 		p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
-	}
 
 	if (tb[TCA_DSMARK_MASK])
 		p->mask[*arg-1] = mask;
@@ -359,23 +361,18 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
 	if (!opt)
 		goto errout;
 
-	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_DSMARK_MAX, opt, dsmark_policy);
 	if (err < 0)
 		goto errout;
 
 	err = -EINVAL;
-	if (nla_len(tb[TCA_DSMARK_INDICES]) < sizeof(u16))
-		goto errout;
 	indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
 
 	if (hweight32(indices) != 1)
 		goto errout;
 
-	if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
-		if (nla_len(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(u16))
-			goto errout;
+	if (tb[TCA_DSMARK_DEFAULT_INDEX])
 		default_index = nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
-	}
 
 	mask = kmalloc(indices * 2, GFP_KERNEL);
 	if (mask == NULL) {
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 365c7d8..3a9d226 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -356,7 +356,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
 	struct tc_gred_sopt *sopt;
 	int i;
 
-	if (dps == NULL || nla_len(dps) < sizeof(*sopt))
+	if (dps == NULL)
 		return -EINVAL;
 
 	sopt = nla_data(dps);
@@ -425,6 +425,12 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
 	return 0;
 }
 
+static const struct nla_policy gred_policy[TCA_GRED_MAX + 1] = {
+	[TCA_GRED_PARMS]	= { .len = sizeof(struct tc_gred_qopt) },
+	[TCA_GRED_STAB]		= { .len = 256 },
+	[TCA_GRED_DPS]		= { .len = sizeof(struct tc_gred_sopt) },
+};
+
 static int gred_change(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct gred_sched *table = qdisc_priv(sch);
@@ -436,7 +442,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
 	if (opt == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
 	if (err < 0)
 		return err;
 
@@ -444,9 +450,7 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt)
 		return gred_change_table_def(sch, opt);
 
 	if (tb[TCA_GRED_PARMS] == NULL ||
-	    nla_len(tb[TCA_GRED_PARMS]) < sizeof(*ctl) ||
-	    tb[TCA_GRED_STAB] == NULL ||
-	    nla_len(tb[TCA_GRED_STAB]) < 256)
+	    tb[TCA_GRED_STAB] == NULL)
 		return -EINVAL;
 
 	err = -EINVAL;
@@ -499,7 +503,7 @@ static int gred_init(struct Qdisc *sch, struct nlattr *opt)
 	if (opt == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_GRED_MAX, opt, gred_policy);
 	if (err < 0)
 		return err;
 
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 54c3e90..94bf186 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -986,6 +986,12 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc,
 	cl->cl_flags |= HFSC_USC;
 }
 
+static const struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
+	[TCA_HFSC_RSC]	= { .len = sizeof(struct tc_service_curve) },
+	[TCA_HFSC_FSC]	= { .len = sizeof(struct tc_service_curve) },
+	[TCA_HFSC_USC]	= { .len = sizeof(struct tc_service_curve) },
+};
+
 static int
 hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 		  struct nlattr **tca, unsigned long *arg)
@@ -1002,29 +1008,23 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 	if (opt == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_HFSC_MAX, opt, hfsc_policy);
 	if (err < 0)
 		return err;
 
 	if (tb[TCA_HFSC_RSC]) {
-		if (nla_len(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
-			return -EINVAL;
 		rsc = nla_data(tb[TCA_HFSC_RSC]);
 		if (rsc->m1 == 0 && rsc->m2 == 0)
 			rsc = NULL;
 	}
 
 	if (tb[TCA_HFSC_FSC]) {
-		if (nla_len(tb[TCA_HFSC_FSC]) < sizeof(*fsc))
-			return -EINVAL;
 		fsc = nla_data(tb[TCA_HFSC_FSC]);
 		if (fsc->m1 == 0 && fsc->m2 == 0)
 			fsc = NULL;
 	}
 
 	if (tb[TCA_HFSC_USC]) {
-		if (nla_len(tb[TCA_HFSC_USC]) < sizeof(*usc))
-			return -EINVAL;
 		usc = nla_data(tb[TCA_HFSC_USC]);
 		if (usc->m1 == 0 && usc->m2 == 0)
 			usc = NULL;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 69fac32..e1a579e 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -992,6 +992,13 @@ static void htb_reset(struct Qdisc *sch)
 		INIT_LIST_HEAD(q->drops + i);
 }
 
+static const struct nla_policy htb_policy[TCA_HTB_MAX + 1] = {
+	[TCA_HTB_PARMS]	= { .len = sizeof(struct tc_htb_opt) },
+	[TCA_HTB_INIT]	= { .len = sizeof(struct tc_htb_glob) },
+	[TCA_HTB_CTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+	[TCA_HTB_RTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
 static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct htb_sched *q = qdisc_priv(sch);
@@ -1003,12 +1010,11 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 	if (!opt)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_HTB_INIT, opt, NULL);
+	err = nla_parse_nested(tb, TCA_HTB_INIT, opt, htb_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_HTB_INIT] == NULL ||
-	    nla_len(tb[TCA_HTB_INIT]) < sizeof(*gopt)) {
+	if (tb[TCA_HTB_INIT] == NULL) {
 		printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
 		return -EINVAL;
 	}
@@ -1319,13 +1325,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 	if (!opt)
 		goto failure;
 
-	err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, NULL);
+	err = nla_parse_nested(tb, TCA_HTB_RTAB, opt, htb_policy);
 	if (err < 0)
 		goto failure;
 
 	err = -EINVAL;
-	if (tb[TCA_HTB_PARMS] == NULL ||
-	    nla_len(tb[TCA_HTB_PARMS]) < sizeof(*hopt))
+	if (tb[TCA_HTB_PARMS] == NULL)
 		goto failure;
 
 	parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 1a75579..c9c649b 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -368,9 +368,6 @@ static int get_correlation(struct Qdisc *sch, const struct nlattr *attr)
 	struct netem_sched_data *q = qdisc_priv(sch);
 	const struct tc_netem_corr *c = nla_data(attr);
 
-	if (nla_len(attr) != sizeof(*c))
-		return -EINVAL;
-
 	init_crandom(&q->delay_cor, c->delay_corr);
 	init_crandom(&q->loss_cor, c->loss_corr);
 	init_crandom(&q->dup_cor, c->dup_corr);
@@ -382,9 +379,6 @@ static int get_reorder(struct Qdisc *sch, const struct nlattr *attr)
 	struct netem_sched_data *q = qdisc_priv(sch);
 	const struct tc_netem_reorder *r = nla_data(attr);
 
-	if (nla_len(attr) != sizeof(*r))
-		return -EINVAL;
-
 	q->reorder = r->probability;
 	init_crandom(&q->reorder_cor, r->correlation);
 	return 0;
@@ -395,14 +389,17 @@ static int get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
 	struct netem_sched_data *q = qdisc_priv(sch);
 	const struct tc_netem_corrupt *r = nla_data(attr);
 
-	if (nla_len(attr) != sizeof(*r))
-		return -EINVAL;
-
 	q->corrupt = r->probability;
 	init_crandom(&q->corrupt_cor, r->correlation);
 	return 0;
 }
 
+static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
+	[TCA_NETEM_CORR]	= { .len = sizeof(struct tc_netem_corr) },
+	[TCA_NETEM_REORDER]	= { .len = sizeof(struct tc_netem_reorder) },
+	[TCA_NETEM_CORRUPT]	= { .len = sizeof(struct tc_netem_corrupt) },
+};
+
 /* Parse netlink message to set options */
 static int netem_change(struct Qdisc *sch, struct nlattr *opt)
 {
@@ -414,8 +411,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
 	if (opt == NULL)
 		return -EINVAL;
 
-	ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, NULL, qopt,
-				      sizeof(*qopt));
+	ret = nla_parse_nested_compat(tb, TCA_NETEM_MAX, opt, netem_policy,
+				      qopt, sizeof(*qopt));
 	if (ret < 0)
 		return ret;
 
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index dcf6afc..3dcd493 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -201,6 +201,11 @@ static struct Qdisc *red_create_dflt(struct Qdisc *sch, u32 limit)
 	return NULL;
 }
 
+static const struct nla_policy red_policy[TCA_RED_MAX + 1] = {
+	[TCA_RED_PARMS]	= { .len = sizeof(struct tc_red_qopt) },
+	[TCA_RED_STAB]	= { .len = RED_STAB_SIZE },
+};
+
 static int red_change(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
@@ -212,14 +217,12 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
 	if (opt == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_RED_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_RED_MAX, opt, red_policy);
 	if (err < 0)
 		return err;
 
 	if (tb[TCA_RED_PARMS] == NULL ||
-	    nla_len(tb[TCA_RED_PARMS]) < sizeof(*ctl) ||
-	    tb[TCA_RED_STAB] == NULL ||
-	    nla_len(tb[TCA_RED_STAB]) < RED_STAB_SIZE)
+	    tb[TCA_RED_STAB] == NULL)
 		return -EINVAL;
 
 	ctl = nla_data(tb[TCA_RED_PARMS]);
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index b7a185d..0b7d78f 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -270,6 +270,12 @@ static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit)
 	return NULL;
 }
 
+static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
+	[TCA_TBF_PARMS]	= { .len = sizeof(struct tc_tbf_qopt) },
+	[TCA_TBF_RTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+	[TCA_TBF_PTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
+};
+
 static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
 {
 	int err;
@@ -281,13 +287,12 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
 	struct Qdisc *child = NULL;
 	int max_size,n;
 
-	err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, NULL);
+	err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy);
 	if (err < 0)
 		return err;
 
 	err = -EINVAL;
-	if (tb[TCA_TBF_PARMS] == NULL ||
-	    nla_len(tb[TCA_TBF_PARMS]) < sizeof(*qopt))
+	if (tb[TCA_TBF_PARMS] == NULL)
 		goto done;
 
 	qopt = nla_data(tb[TCA_TBF_PARMS]);

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 13/15]: Use nla_policy for attribute validation in classifiers
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (11 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 12/15]: Use nla_policy for attribute validation in packet schedulers Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 14/15]: Use nla_policy for attribute validation in actions Patrick McHardy
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use nla_policy for attribute validation in classifiers

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit d177578bdf08849a388f1bc42a1d0566c6a3aded
tree 2eda0cf1e0479dab464acda9def525df27bd4307
parent 76c3c24283fa9f78d8dc30c8eb73e0f11934bf69
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:14:08 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:14:08 +0100

 net/sched/cls_basic.c   |   12 +++++++-----
 net/sched/cls_fw.c      |   17 ++++++++---------
 net/sched/cls_route.c   |   19 ++++++++-----------
 net/sched/cls_rsvp.h    |   26 +++++++++++---------------
 net/sched/cls_tcindex.c |   31 +++++++++++++------------------
 net/sched/cls_u32.c     |   22 ++++++++++++----------
 6 files changed, 59 insertions(+), 68 deletions(-)

diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 0c872a7..bfb4342 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -129,6 +129,11 @@ static int basic_delete(struct tcf_proto *tp, unsigned long arg)
 	return -ENOENT;
 }
 
+static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
+	[TCA_BASIC_CLASSID]	= { .type = NLA_U32 },
+	[TCA_BASIC_EMATCHES]	= { .type = NLA_NESTED },
+};
+
 static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
 				  unsigned long base, struct nlattr **tb,
 				  struct nlattr *est)
@@ -137,10 +142,6 @@ static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
 	struct tcf_exts e;
 	struct tcf_ematch_tree t;
 
-	if (tb[TCA_BASIC_CLASSID])
-		if (nla_len(tb[TCA_BASIC_CLASSID]) < sizeof(u32))
-			return err;
-
 	err = tcf_exts_validate(tp, tb, est, &e, &basic_ext_map);
 	if (err < 0)
 		return err;
@@ -174,7 +175,8 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (tca[TCA_OPTIONS] == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS], NULL);
+	err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS],
+			       basic_policy);
 	if (err < 0)
 		return err;
 
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index b75696d..436a6e7 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -186,6 +186,12 @@ out:
 	return -EINVAL;
 }
 
+static const struct nla_policy fw_policy[TCA_FW_MAX + 1] = {
+	[TCA_FW_CLASSID]	= { .type = NLA_U32 },
+	[TCA_FW_INDEV]		= { .type = NLA_STRING, .len = IFNAMSIZ },
+	[TCA_FW_MASK]		= { .type = NLA_U32 },
+};
+
 static int
 fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
 	struct nlattr **tb, struct nlattr **tca, unsigned long base)
@@ -201,8 +207,6 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
 
 	err = -EINVAL;
 	if (tb[TCA_FW_CLASSID]) {
-		if (nla_len(tb[TCA_FW_CLASSID]) != sizeof(u32))
-			goto errout;
 		f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
 		tcf_bind_filter(tp, &f->res, base);
 	}
@@ -216,8 +220,6 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f,
 #endif /* CONFIG_NET_CLS_IND */
 
 	if (tb[TCA_FW_MASK]) {
-		if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
-			goto errout;
 		mask = nla_get_u32(tb[TCA_FW_MASK]);
 		if (mask != head->mask)
 			goto errout;
@@ -246,7 +248,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
 	if (!opt)
 		return handle ? -EINVAL : 0;
 
-	err = nla_parse_nested(tb, TCA_FW_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_FW_MAX, opt, fw_policy);
 	if (err < 0)
 		return err;
 
@@ -261,11 +263,8 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
 
 	if (head == NULL) {
 		u32 mask = 0xFFFFFFFF;
-		if (tb[TCA_FW_MASK]) {
-			if (nla_len(tb[TCA_FW_MASK]) != sizeof(u32))
-				return -EINVAL;
+		if (tb[TCA_FW_MASK])
 			mask = nla_get_u32(tb[TCA_FW_MASK]);
-		}
 
 		head = kzalloc(sizeof(struct fw_head), GFP_KERNEL);
 		if (head == NULL)
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index ae97238..f7e7d39 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -323,6 +323,13 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
 	return 0;
 }
 
+static const struct nla_policy route4_policy[TCA_ROUTE4_MAX + 1] = {
+	[TCA_ROUTE4_CLASSID]	= { .type = NLA_U32 },
+	[TCA_ROUTE4_TO]		= { .type = NLA_U32 },
+	[TCA_ROUTE4_FROM]	= { .type = NLA_U32 },
+	[TCA_ROUTE4_IIF]	= { .type = NLA_U32 },
+};
+
 static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 	struct route4_filter *f, u32 handle, struct route4_head *head,
 	struct nlattr **tb, struct nlattr *est, int new)
@@ -339,15 +346,9 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 		return err;
 
 	err = -EINVAL;
-	if (tb[TCA_ROUTE4_CLASSID])
-		if (nla_len(tb[TCA_ROUTE4_CLASSID]) < sizeof(u32))
-			goto errout;
-
 	if (tb[TCA_ROUTE4_TO]) {
 		if (new && handle & 0x8000)
 			goto errout;
-		if (nla_len(tb[TCA_ROUTE4_TO]) < sizeof(u32))
-			goto errout;
 		to = nla_get_u32(tb[TCA_ROUTE4_TO]);
 		if (to > 0xFF)
 			goto errout;
@@ -357,15 +358,11 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 	if (tb[TCA_ROUTE4_FROM]) {
 		if (tb[TCA_ROUTE4_IIF])
 			goto errout;
-		if (nla_len(tb[TCA_ROUTE4_FROM]) < sizeof(u32))
-			goto errout;
 		id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
 		if (id > 0xFF)
 			goto errout;
 		nhandle |= id << 16;
 	} else if (tb[TCA_ROUTE4_IIF]) {
-		if (nla_len(tb[TCA_ROUTE4_IIF]) < sizeof(u32))
-			goto errout;
 		id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
 		if (id > 0x7FFF)
 			goto errout;
@@ -440,7 +437,7 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
 	if (opt == NULL)
 		return handle ? -EINVAL : 0;
 
-	err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_ROUTE4_MAX, opt, route4_policy);
 	if (err < 0)
 		return err;
 
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 61286a0..4f2c3f1 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -397,6 +397,15 @@ static u32 gen_tunnel(struct rsvp_head *data)
 	return 0;
 }
 
+static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = {
+	[TCA_RSVP_CLASSID]	= { .type = NLA_U32 },
+	[TCA_RSVP_DST]		= { .type = NLA_BINARY,
+	 			    .len = RSVP_DST_LEN * sizeof(u32) },
+	[TCA_RSVP_SRC]		= { .type = NLA_BINARY,
+	 			    .len = RSVP_DST_LEN * sizeof(u32) },
+	[TCA_RSVP_PINFO]	= { .len = sizeof(struct tc_rsvp_pinfo) },
+};
+
 static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 		       u32 handle,
 		       struct nlattr **tca,
@@ -416,7 +425,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 	if (opt == NULL)
 		return handle ? -EINVAL : 0;
 
-	err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_RSVP_MAX, opt, rsvp_policy);
 	if (err < 0)
 		return err;
 
@@ -452,30 +461,17 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 
 	h2 = 16;
 	if (tb[TCA_RSVP_SRC-1]) {
-		err = -EINVAL;
-		if (nla_len(tb[TCA_RSVP_SRC-1]) != sizeof(f->src))
-			goto errout;
 		memcpy(f->src, nla_data(tb[TCA_RSVP_SRC-1]), sizeof(f->src));
 		h2 = hash_src(f->src);
 	}
 	if (tb[TCA_RSVP_PINFO-1]) {
-		err = -EINVAL;
-		if (nla_len(tb[TCA_RSVP_PINFO-1]) < sizeof(struct tc_rsvp_pinfo))
-			goto errout;
 		pinfo = nla_data(tb[TCA_RSVP_PINFO-1]);
 		f->spi = pinfo->spi;
 		f->tunnelhdr = pinfo->tunnelhdr;
 	}
-	if (tb[TCA_RSVP_CLASSID-1]) {
-		err = -EINVAL;
-		if (nla_len(tb[TCA_RSVP_CLASSID-1]) != 4)
-			goto errout;
+	if (tb[TCA_RSVP_CLASSID-1])
 		f->res.classid = nla_get_u32(tb[TCA_RSVP_CLASSID-1]);
-	}
 
-	err = -EINVAL;
-	if (nla_len(tb[TCA_RSVP_DST-1]) != sizeof(f->src))
-		goto errout;
 	dst = nla_data(tb[TCA_RSVP_DST-1]);
 	h1 = hash_dst(dst, pinfo ? pinfo->protocol : 0, pinfo ? pinfo->tunnelid : 0);
 
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 2809856..ee60b2d 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -193,6 +193,14 @@ 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,
@@ -217,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]) {
-		if (nla_len(tb[TCA_TCINDEX_HASH]) < sizeof(u32))
-			goto errout;
+	if (tb[TCA_TCINDEX_HASH])
 		cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
-	}
 
-	if (tb[TCA_TCINDEX_MASK]) {
-		if (nla_len(tb[TCA_TCINDEX_MASK]) < sizeof(u16))
-			goto errout;
+	if (tb[TCA_TCINDEX_MASK])
 		cp.mask = nla_get_u16(tb[TCA_TCINDEX_MASK]);
-	}
 
-	if (tb[TCA_TCINDEX_SHIFT]) {
-		if (nla_len(tb[TCA_TCINDEX_SHIFT]) < sizeof(int))
-			goto errout;
+	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
@@ -248,11 +246,8 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
 		goto errout;
 
 	err = -EINVAL;
-	if (tb[TCA_TCINDEX_FALL_THROUGH]) {
-		if (nla_len(tb[TCA_TCINDEX_FALL_THROUGH]) < sizeof(u32))
-			goto errout;
+	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
@@ -358,7 +353,7 @@ tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (!opt)
 		return 0;
 
-	err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_TCINDEX_MAX, opt, tcindex_policy);
 	if (err < 0)
 		return err;
 
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index a4e72e8..e8a7756 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -460,6 +460,16 @@ static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle)
 	return handle|(i>0xFFF ? 0xFFF : i);
 }
 
+static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
+	[TCA_U32_CLASSID]	= { .type = NLA_U32 },
+	[TCA_U32_HASH]		= { .type = NLA_U32 },
+	[TCA_U32_LINK]		= { .type = NLA_U32 },
+	[TCA_U32_DIVISOR]	= { .type = NLA_U32 },
+	[TCA_U32_SEL]		= { .len = sizeof(struct tc_u32_sel) },
+	[TCA_U32_INDEV]		= { .type = NLA_STRING, .len = IFNAMSIZ },
+	[TCA_U32_MARK]		= { .len = sizeof(struct tc_u32_mark) },
+};
+
 static int u32_set_parms(struct tcf_proto *tp, unsigned long base,
 			 struct tc_u_hnode *ht,
 			 struct tc_u_knode *n, struct nlattr **tb,
@@ -531,7 +541,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (opt == NULL)
 		return handle ? -EINVAL : 0;
 
-	err = nla_parse_nested(tb, TCA_U32_MAX, opt, NULL);
+	err = nla_parse_nested(tb, TCA_U32_MAX, opt, u32_policy);
 	if (err < 0)
 		return err;
 
@@ -593,8 +603,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	} else
 		handle = gen_new_kid(ht, htid);
 
-	if (tb[TCA_U32_SEL] == NULL ||
-	    nla_len(tb[TCA_U32_SEL]) < sizeof(struct tc_u32_sel))
+	if (tb[TCA_U32_SEL] == NULL)
 		return -EINVAL;
 
 	s = nla_data(tb[TCA_U32_SEL]);
@@ -620,13 +629,6 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (tb[TCA_U32_MARK]) {
 		struct tc_u32_mark *mark;
 
-		if (nla_len(tb[TCA_U32_MARK]) < sizeof(struct tc_u32_mark)) {
-#ifdef CONFIG_CLS_U32_PERF
-			kfree(n->pf);
-#endif
-			kfree(n);
-			return -EINVAL;
-		}
 		mark = nla_data(tb[TCA_U32_MARK]);
 		memcpy(&n->mark, mark, sizeof(struct tc_u32_mark));
 		n->mark.success = 0;

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 14/15]: Use nla_policy for attribute validation in actions
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (12 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 13/15]: Use nla_policy for attribute validation in classifiers Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-23 16:36 ` [NET_SCHED 15/15]: Use nla_policy for attribute validation in ematches Patrick McHardy
  2008-01-24  4:37 ` [NET_SCHED 00/15]: Make use of new netlink API features David Miller
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use nla_policy for attribute validation in actions

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 99302e1c1ed003305e9a0102aa772e2f2d61114c
tree 05286e8f9d74ad273d6a6e12d7bc794a19c4ea4c
parent d177578bdf08849a388f1bc42a1d0566c6a3aded
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:07 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:07 +0100

 net/sched/act_gact.c   |   15 ++++++++-------
 net/sched/act_ipt.c    |   19 ++++++++++++-------
 net/sched/act_mirred.c |    9 ++++++---
 net/sched/act_nat.c    |    9 ++++++---
 net/sched/act_pedit.c  |    9 ++++++---
 net/sched/act_police.c |   16 ++++++++--------
 net/sched/act_simple.c |    7 +++++--
 7 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index df214d4..422872c 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -53,6 +53,11 @@ typedef int (*g_rand)(struct tcf_gact *gact);
 static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
 #endif /* CONFIG_GACT_PROB */
 
+static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
+	[TCA_GACT_PARMS]	= { .len = sizeof(struct tc_gact) },
+	[TCA_GACT_PROB]		= { .len = sizeof(struct tc_gact_p) },
+};
+
 static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
 			 struct tc_action *a, int ovr, int bind)
 {
@@ -66,20 +71,16 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_GACT_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_GACT_MAX, nla, gact_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_GACT_PARMS] == NULL ||
-	    nla_len(tb[TCA_GACT_PARMS]) < sizeof(*parm))
+	if (tb[TCA_GACT_PARMS] == NULL)
 		return -EINVAL;
 	parm = nla_data(tb[TCA_GACT_PARMS]);
 
+#ifndef CONFIG_GACT_PROB
 	if (tb[TCA_GACT_PROB] != NULL)
-#ifdef CONFIG_GACT_PROB
-		if (nla_len(tb[TCA_GACT_PROB]) < sizeof(struct tc_gact_p))
-			return -EINVAL;
-#else
 		return -EOPNOTSUPP;
 #endif
 
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 7ab2419..da696fd 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -92,6 +92,13 @@ static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
 	return ret;
 }
 
+static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
+	[TCA_IPT_TABLE]	= { .type = NLA_STRING, .len = IFNAMSIZ },
+	[TCA_IPT_HOOK]	= { .type = NLA_U32 },
+	[TCA_IPT_INDEX]	= { .type = NLA_U32 },
+	[TCA_IPT_TARG]	= { .len = sizeof(struct ipt_entry_target) },
+};
+
 static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 			struct tc_action *a, int ovr, int bind)
 {
@@ -107,22 +114,20 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_IPT_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_IPT_MAX, nla, ipt_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_IPT_HOOK] == NULL ||
-	    nla_len(tb[TCA_IPT_HOOK]) < sizeof(u32))
+	if (tb[TCA_IPT_HOOK] == NULL)
 		return -EINVAL;
-	if (tb[TCA_IPT_TARG] == NULL ||
-	    nla_len(tb[TCA_IPT_TARG]) < sizeof(*t))
+	if (tb[TCA_IPT_TARG] == NULL)
 		return -EINVAL;
+
 	td = (struct ipt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
 	if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size)
 		return -EINVAL;
 
-	if (tb[TCA_IPT_INDEX] != NULL &&
-	    nla_len(tb[TCA_IPT_INDEX]) >= sizeof(u32))
+	if (tb[TCA_IPT_INDEX] != NULL)
 		index = nla_get_u32(tb[TCA_IPT_INDEX]);
 
 	pc = tcf_hash_check(index, a, bind, &ipt_hash_info);
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 6cb5e30..1aff005 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -54,6 +54,10 @@ static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
 	return 0;
 }
 
+static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
+	[TCA_MIRRED_PARMS]	= { .len = sizeof(struct tc_mirred) },
+};
+
 static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
 			   struct tc_action *a, int ovr, int bind)
 {
@@ -68,12 +72,11 @@ static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_MIRRED_MAX, nla, mirred_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_MIRRED_PARMS] == NULL ||
-	    nla_len(tb[TCA_MIRRED_PARMS]) < sizeof(*parm))
+	if (tb[TCA_MIRRED_PARMS] == NULL)
 		return -EINVAL;
 	parm = nla_data(tb[TCA_MIRRED_PARMS]);
 
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 5a512d4..0a3c833 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -40,6 +40,10 @@ static struct tcf_hashinfo nat_hash_info = {
 	.lock	=	&nat_lock,
 };
 
+static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
+	[TCA_NAT_PARMS]	= { .len = sizeof(struct tc_nat) },
+};
+
 static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
 			struct tc_action *a, int ovr, int bind)
 {
@@ -52,12 +56,11 @@ static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_NAT_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_NAT_MAX, nla, nat_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_NAT_PARMS] == NULL ||
-	    nla_len(tb[TCA_NAT_PARMS]) < sizeof(*parm))
+	if (tb[TCA_NAT_PARMS] == NULL)
 		return -EINVAL;
 	parm = nla_data(tb[TCA_NAT_PARMS]);
 
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 1b9ca45..3cc4cb9 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -33,6 +33,10 @@ static struct tcf_hashinfo pedit_hash_info = {
 	.lock	=	&pedit_lock,
 };
 
+static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
+	[TCA_PEDIT_PARMS]	= { .len = sizeof(struct tcf_pedit) },
+};
+
 static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
 			  struct tc_action *a, int ovr, int bind)
 {
@@ -47,12 +51,11 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy);
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_PEDIT_PARMS] == NULL ||
-	    nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm))
+	if (tb[TCA_PEDIT_PARMS] == NULL)
 		return -EINVAL;
 	parm = nla_data(tb[TCA_PEDIT_PARMS]);
 	ksize = parm->nkeys * sizeof(struct tc_pedit_key);
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 62de806..0898120 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -119,6 +119,13 @@ static void tcf_police_destroy(struct tcf_police *p)
 	BUG_TRAP(0);
 }
 
+static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
+	[TCA_POLICE_RATE]	= { .len = TC_RTAB_SIZE },
+	[TCA_POLICE_PEAKRATE]	= { .len = TC_RTAB_SIZE },
+	[TCA_POLICE_AVRATE]	= { .type = NLA_U32 },
+	[TCA_POLICE_RESULT]	= { .type = NLA_U32 },
+};
+
 static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
 				 struct tc_action *a, int ovr, int bind)
 {
@@ -133,7 +140,7 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy);
 	if (err < 0)
 		return err;
 
@@ -144,13 +151,6 @@ static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
 		return -EINVAL;
 	parm = nla_data(tb[TCA_POLICE_TBF]);
 
-	if (tb[TCA_POLICE_RESULT] != NULL &&
-	    nla_len(tb[TCA_POLICE_RESULT]) != sizeof(u32))
-		return -EINVAL;
-	if (tb[TCA_POLICE_RESULT] != NULL &&
-	    nla_len(tb[TCA_POLICE_RESULT]) != sizeof(u32))
-		return -EINVAL;
-
 	if (parm->index) {
 		struct tcf_common *pc;
 
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index cedaadf..fbde461 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -84,6 +84,10 @@ static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
 	return alloc_defdata(d, datalen, defdata);
 }
 
+static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
+	[TCA_DEF_PARMS]	= { .len = sizeof(struct tc_defact) },
+};
+
 static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
 			 struct tc_action *a, int ovr, int bind)
 {
@@ -102,8 +106,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_DEF_PARMS] == NULL ||
-	    nla_len(tb[TCA_DEF_PARMS]) < sizeof(*parm))
+	if (tb[TCA_DEF_PARMS] == NULL)
 		return -EINVAL;
 
 	parm = nla_data(tb[TCA_DEF_PARMS]);

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [NET_SCHED 15/15]: Use nla_policy for attribute validation in ematches
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (13 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 14/15]: Use nla_policy for attribute validation in actions Patrick McHardy
@ 2008-01-23 16:36 ` Patrick McHardy
  2008-01-24  4:37 ` [NET_SCHED 00/15]: Make use of new netlink API features David Miller
  15 siblings, 0 replies; 17+ messages in thread
From: Patrick McHardy @ 2008-01-23 16:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, Patrick McHardy

[NET_SCHED]: Use nla_policy for attribute validation in ematches

Signed-off-by: Patrick McHardy <kaber@trash.net>

---
commit 9420f06512465a8a90f3ff0df8b943989bc7e2e7
tree 7556b31b93647c9d2c30eb567b50671d368f8ced
parent 99302e1c1ed003305e9a0102aa772e2f2d61114c
author Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:09 +0100
committer Patrick McHardy <kaber@trash.net> Wed, 23 Jan 2008 17:23:09 +0100

 net/sched/em_meta.c |    9 ++++++---
 net/sched/ematch.c  |   11 ++++++-----
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index d9f487d..a1e5619 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -745,6 +745,10 @@ static inline int meta_is_supported(struct meta_value *val)
 	return (!meta_id(val) || meta_ops(val)->get);
 }
 
+static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = {
+	[TCA_EM_META_HDR]	= { .len = sizeof(struct tcf_meta_hdr) },
+};
+
 static int em_meta_change(struct tcf_proto *tp, void *data, int len,
 			  struct tcf_ematch *m)
 {
@@ -753,13 +757,12 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
 	struct tcf_meta_hdr *hdr;
 	struct meta_match *meta = NULL;
 
-	err = nla_parse(tb, TCA_EM_META_MAX, data, len, NULL);
+	err = nla_parse(tb, TCA_EM_META_MAX, data, len, meta_policy);
 	if (err < 0)
 		goto errout;
 
 	err = -EINVAL;
-	if (tb[TCA_EM_META_HDR] == NULL ||
-	    nla_len(tb[TCA_EM_META_HDR]) < sizeof(*hdr))
+	if (tb[TCA_EM_META_HDR] == NULL)
 		goto errout;
 	hdr = nla_data(tb[TCA_EM_META_HDR]);
 
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index daa9c4e..74ff918 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -282,6 +282,11 @@ errout:
 	return err;
 }
 
+static const struct nla_policy em_policy[TCA_EMATCH_TREE_MAX + 1] = {
+	[TCA_EMATCH_TREE_HDR]	= { .len = sizeof(struct tcf_ematch_tree_hdr) },
+	[TCA_EMATCH_TREE_LIST]	= { .type = NLA_NESTED },
+};
+
 /**
  * tcf_em_tree_validate - validate ematch config TLV and build ematch tree
  *
@@ -312,7 +317,7 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
 		return 0;
 	}
 
-	err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, NULL);
+	err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, em_policy);
 	if (err < 0)
 		goto errout;
 
@@ -323,10 +328,6 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
 	if (rt_hdr == NULL || rt_list == NULL)
 		goto errout;
 
-	if (nla_len(rt_hdr) < sizeof(*tree_hdr) ||
-	    nla_len(rt_list) < sizeof(*rt_match))
-		goto errout;
-
 	tree_hdr = nla_data(rt_hdr);
 	memcpy(&tree->hdr, tree_hdr, sizeof(*tree_hdr));
 

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [NET_SCHED 00/15]: Make use of new netlink API features
  2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
                   ` (14 preceding siblings ...)
  2008-01-23 16:36 ` [NET_SCHED 15/15]: Use nla_policy for attribute validation in ematches Patrick McHardy
@ 2008-01-24  4:37 ` David Miller
  15 siblings, 0 replies; 17+ messages in thread
From: David Miller @ 2008-01-24  4:37 UTC (permalink / raw)
  To: kaber; +Cc: netdev

From: Patrick McHardy <kaber@trash.net>
Date: Wed, 23 Jan 2008 17:36:35 +0100 (MET)

> these patches change the packet schedulers/classifers/actions to make use
> of the features of the new netlink API, like typeful attribute dumping and
> parsing, automatic basic attribute validation etc. The also fix a bug and
> a warning introduced by my last set of patches.
> 
> Please apply, thanks.

All applied, thanks for doing this work Patrick.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2008-01-24  4:36 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-23 16:36 [NET_SCHED 00/15]: Make use of new netlink API features Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 01/15]: sch_atm: fix format string warning Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 02/15]: sch_netem: use nla_parse_nested_compat Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 03/15]: act_api: fix netlink API conversion bug Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 04/15]: act_api: use nlmsg_parse Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 05/15]: act_api: use PTR_ERR in tcf_action_init/tcf_action_get Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 06/15]: Propagate nla_parse return value Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 07/15]: Use nla_nest_start/nla_nest_end Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 08/15]: Use NLA_PUT_STRING for string dumping Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 09/15]: Use typeful attribute construction helpers Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 10/15]: Use typeful attribute parsing helpers Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 11/15]: sch_api: introduce constant for rate table size Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 12/15]: Use nla_policy for attribute validation in packet schedulers Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 13/15]: Use nla_policy for attribute validation in classifiers Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 14/15]: Use nla_policy for attribute validation in actions Patrick McHardy
2008-01-23 16:36 ` [NET_SCHED 15/15]: Use nla_policy for attribute validation in ematches Patrick McHardy
2008-01-24  4:37 ` [NET_SCHED 00/15]: Make use of new netlink API features David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).