X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fsched%2Fact_api.c;h=d308c19aa3f9be6d6087aecfa27dcc55dead6eed;hb=f8e79ddd31c3615ddca26b9a469c44a7adbd4e13;hp=ae077ed208af79306e3a4d6a4e74ba8cf2caf2e9;hpb=6d834e04e596d6803cf1074a07fd67e7b5662f1b;p=linux-2.6 diff --git a/net/sched/act_api.c b/net/sched/act_api.c index ae077ed208..d308c19aa3 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,7 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) return; } } - BUG_TRAP(0); + WARN_ON(1); } EXPORT_SYMBOL(tcf_hash_destroy); @@ -68,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); @@ -83,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; @@ -104,7 +107,7 @@ done: return n_i; nla_put_failure: - nlmsg_trim(skb, r); + nla_nest_cancel(skb, nest); goto done; } @@ -112,12 +115,13 @@ 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); - NLA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); + nest = nla_nest_start(skb, a->order); + if (nest == NULL) + goto nla_put_failure; + 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)]; @@ -129,12 +133,12 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, p = s_p; } } - NLA_PUT(skb, TCA_FCNT, 4, &n_i); - r->nla_len = skb_tail_pointer(skb) - (u8 *)r; + NLA_PUT_U32(skb, TCA_FCNT, n_i); + nla_nest_end(skb, nest); return n_i; nla_put_failure: - nlmsg_trim(skb, r); + nla_nest_cancel(skb, nest); return -EINVAL; } @@ -414,18 +418,19 @@ 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; - 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; - 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; } @@ -440,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; @@ -458,30 +463,32 @@ 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; } 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; - - *err = -EINVAL; + int err; 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; } @@ -502,36 +509,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 +545,24 @@ 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 err; int i; - if (nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL) < 0) { - *err = -EINVAL; - return head; - } + 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, 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 +577,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, @@ -625,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); @@ -634,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; @@ -668,44 +675,47 @@ 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; - if (nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL) < 0) - return NULL; + 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)) - return NULL; - index = *(int *)nla_data(tb[TCA_ACT_INDEX]); + goto err_out; + index = nla_get_u32(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) @@ -738,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); @@ -758,9 +768,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) @@ -772,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; @@ -803,12 +816,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) @@ -816,9 +830,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) @@ -865,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; @@ -881,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; @@ -912,9 +929,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 @@ -930,7 +951,7 @@ done: static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) { - struct net *net = skb->sk->sk_net; + struct net *net = sock_net(skb->sk); struct nlattr *tca[TCA_ACT_MAX + 1]; u32 pid = skb ? NETLINK_CB(skb).pid : 0; int ret = 0, ovr = 0; @@ -984,11 +1005,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) @@ -1011,10 +1029,10 @@ find_dump_kind(struct nlmsghdr *n) static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = skb->sk->sk_net; + struct net *net = sock_net(skb->sk); 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; @@ -1049,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)