X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fsched%2Fcls_api.c;h=9360fc81e8c7e8099e2cd105d67bbec1511324b6;hb=a9da4f7ed6a702996ac9d1bbaf1a3969a4c092b3;hp=e53773612bc76c39b13949cf76d09266089708d8;hpb=aa767bfea4828936fffb7800204294ba4c8ba283;p=linux-2.6 diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index e53773612b..9360fc81e8 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -31,21 +32,21 @@ /* The list of all installed classifier types */ -static struct tcf_proto_ops *tcf_proto_base; +static struct tcf_proto_ops *tcf_proto_base __read_mostly; /* Protects list of registered TC modules. It is pure SMP lock. */ static DEFINE_RWLOCK(cls_mod_lock); /* Find classifier type by string name */ -static struct tcf_proto_ops *tcf_proto_lookup_ops(struct rtattr *kind) +static struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind) { struct tcf_proto_ops *t = NULL; if (kind) { read_lock(&cls_mod_lock); for (t = tcf_proto_base; t; t = t->next) { - if (rtattr_strcmp(kind, t->kind) == 0) { + if (nla_strcmp(kind, t->kind) == 0) { if (!try_module_get(t->owner)) t = NULL; break; @@ -117,8 +118,8 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp) static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) { - struct net *net = skb->sk->sk_net; - struct rtattr **tca; + struct net *net = sock_net(skb->sk); + struct nlattr *tca[TCA_MAX + 1]; struct tcmsg *t; u32 protocol; u32 prio; @@ -138,7 +139,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) return -EINVAL; replay: - tca = arg; t = NLMSG_DATA(n); protocol = TC_H_MIN(t->tcm_info); prio = TC_H_MAJ(t->tcm_info); @@ -160,6 +160,10 @@ replay: if (dev == NULL) return -ENODEV; + err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL); + if (err < 0) + return err; + /* Find qdisc */ if (!parent) { q = dev->qdisc_sleeping; @@ -202,7 +206,7 @@ replay: if (tp == NULL) { /* Proto-tcf does not exist, create new one */ - if (tca[TCA_KIND-1] == NULL || !protocol) + if (tca[TCA_KIND] == NULL || !protocol) goto errout; err = -ENOENT; @@ -216,15 +220,15 @@ replay: tp = kzalloc(sizeof(*tp), GFP_KERNEL); if (tp == NULL) goto errout; - err = -EINVAL; - tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND-1]); + err = -ENOENT; + tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]); if (tp_ops == NULL) { #ifdef CONFIG_KMOD - struct rtattr *kind = tca[TCA_KIND-1]; + struct nlattr *kind = tca[TCA_KIND]; char name[IFNAMSIZ]; if (kind != NULL && - rtattr_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) { + nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) { rtnl_unlock(); request_module("cls_%s", name); rtnl_lock(); @@ -263,7 +267,7 @@ replay: *back = tp; qdisc_unlock_tree(dev); - } else if (tca[TCA_KIND-1] && rtattr_strcmp(tca[TCA_KIND-1], tp->ops->kind)) + } else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) goto errout; fh = tp->ops->get(tp, t->tcm_handle); @@ -333,18 +337,18 @@ 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); - RTA_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; if (tp->ops->dump && tp->ops->dump(tp, fh, skb, tcm) < 0) - goto rtattr_failure; + goto nla_put_failure; } nlh->nlmsg_len = skb_tail_pointer(skb) - b; return skb->len; nlmsg_failure: -rtattr_failure: +nla_put_failure: nlmsg_trim(skb, b); return -1; } @@ -385,7 +389,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n, static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) { - struct net *net = skb->sk->sk_net; + struct net *net = sock_net(skb->sk); int t; int s_t; struct net_device *dev; @@ -476,38 +480,37 @@ void tcf_exts_destroy(struct tcf_proto *tp, struct tcf_exts *exts) } EXPORT_SYMBOL(tcf_exts_destroy); -int tcf_exts_validate(struct tcf_proto *tp, struct rtattr **tb, - struct rtattr *rate_tlv, struct tcf_exts *exts, - struct tcf_ext_map *map) +int tcf_exts_validate(struct tcf_proto *tp, struct nlattr **tb, + struct nlattr *rate_tlv, struct tcf_exts *exts, + const struct tcf_ext_map *map) { memset(exts, 0, sizeof(*exts)); #ifdef CONFIG_NET_CLS_ACT { - int err; struct tc_action *act; - if (map->police && tb[map->police-1]) { - act = tcf_action_init_1(tb[map->police-1], rate_tlv, + 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-1]) { - act = tcf_action_init(tb[map->action-1], rate_tlv, NULL, - TCA_ACT_NOREPLACE, TCA_ACT_BIND, &err); - if (act == NULL) - return err; + } else if (map->action && tb[map->action]) { + act = tcf_action_init(tb[map->action], rate_tlv, NULL, + TCA_ACT_NOREPLACE, TCA_ACT_BIND); + if (IS_ERR(act)) + return PTR_ERR(act); exts->action = act; } } #else - if ((map->action && tb[map->action-1]) || - (map->police && tb[map->police-1])) + if ((map->action && tb[map->action]) || + (map->police && tb[map->police])) return -EOPNOTSUPP; #endif @@ -532,7 +535,7 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst, EXPORT_SYMBOL(tcf_exts_change); int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts, - struct tcf_ext_map *map) + const struct tcf_ext_map *map) { #ifdef CONFIG_NET_CLS_ACT if (map->action && exts->action) { @@ -541,38 +544,42 @@ 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 rtattr *p_rta = (struct rtattr *)skb_tail_pointer(skb); + struct nlattr *nest; if (exts->action->type != TCA_OLD_COMPAT) { - RTA_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 rtattr_failure; - p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; + goto nla_put_failure; + nla_nest_end(skb, nest); } else if (map->police) { - RTA_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 rtattr_failure; - p_rta->rta_len = skb_tail_pointer(skb) - (u8 *)p_rta; + goto nla_put_failure; + nla_nest_end(skb, nest); } } #endif return 0; -rtattr_failure: __attribute__ ((unused)) +nla_put_failure: __attribute__ ((unused)) return -1; } EXPORT_SYMBOL(tcf_exts_dump); int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts, - struct tcf_ext_map *map) + const struct tcf_ext_map *map) { #ifdef CONFIG_NET_CLS_ACT if (exts->action) if (tcf_action_copy_stats(skb, exts->action, 1) < 0) - goto rtattr_failure; + goto nla_put_failure; #endif return 0; -rtattr_failure: __attribute__ ((unused)) +nla_put_failure: __attribute__ ((unused)) return -1; } EXPORT_SYMBOL(tcf_exts_dump_stats);