diff options
Diffstat (limited to 'net/sched/act_pedit.c')
| -rw-r--r-- | net/sched/act_pedit.c | 31 | 
1 files changed, 23 insertions, 8 deletions
| diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index a80373878df7..d790c02b9c6c 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -23,6 +23,7 @@  #include <linux/tc_act/tc_pedit.h>  #include <net/tc_act/tc_pedit.h>  #include <uapi/linux/tc_act/tc_pedit.h> +#include <net/pkt_cls.h>  static unsigned int pedit_net_id;  static struct tc_action_ops act_pedit_ops; @@ -69,8 +70,9 @@ static struct tcf_pedit_key_ex *tcf_pedit_keys_ex_parse(struct nlattr *nla,  			goto err_out;  		} -		err = nla_parse_nested(tb, TCA_PEDIT_KEY_EX_MAX, ka, -				       pedit_key_ex_policy, NULL); +		err = nla_parse_nested_deprecated(tb, TCA_PEDIT_KEY_EX_MAX, +						  ka, pedit_key_ex_policy, +						  NULL);  		if (err)  			goto err_out; @@ -107,14 +109,15 @@ err_out:  static int tcf_pedit_key_ex_dump(struct sk_buff *skb,  				 struct tcf_pedit_key_ex *keys_ex, int n)  { -	struct nlattr *keys_start = nla_nest_start(skb, TCA_PEDIT_KEYS_EX); +	struct nlattr *keys_start = nla_nest_start_noflag(skb, +							  TCA_PEDIT_KEYS_EX);  	if (!keys_start)  		goto nla_failure;  	for (; n > 0; n--) {  		struct nlattr *key_start; -		key_start = nla_nest_start(skb, TCA_PEDIT_KEY_EX); +		key_start = nla_nest_start_noflag(skb, TCA_PEDIT_KEY_EX);  		if (!key_start)  			goto nla_failure; @@ -138,10 +141,11 @@ nla_failure:  static int tcf_pedit_init(struct net *net, struct nlattr *nla,  			  struct nlattr *est, struct tc_action **a,  			  int ovr, int bind, bool rtnl_held, -			  struct netlink_ext_ack *extack) +			  struct tcf_proto *tp, struct netlink_ext_ack *extack)  {  	struct tc_action_net *tn = net_generic(net, pedit_net_id);  	struct nlattr *tb[TCA_PEDIT_MAX + 1]; +	struct tcf_chain *goto_ch = NULL;  	struct tc_pedit_key *keys = NULL;  	struct tcf_pedit_key_ex *keys_ex;  	struct tc_pedit *parm; @@ -155,7 +159,8 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,  		return -EINVAL;  	} -	err = nla_parse_nested(tb, TCA_PEDIT_MAX, nla, pedit_policy, NULL); +	err = nla_parse_nested_deprecated(tb, TCA_PEDIT_MAX, nla, +					  pedit_policy, NULL);  	if (err < 0)  		return err; @@ -205,6 +210,11 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,  		goto out_free;  	} +	err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack); +	if (err < 0) { +		ret = err; +		goto out_release; +	}  	p = to_pedit(*a);  	spin_lock_bh(&p->tcf_lock); @@ -214,7 +224,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,  		if (!keys) {  			spin_unlock_bh(&p->tcf_lock);  			ret = -ENOMEM; -			goto out_release; +			goto put_chain;  		}  		kfree(p->tcfp_keys);  		p->tcfp_keys = keys; @@ -223,16 +233,21 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,  	memcpy(p->tcfp_keys, parm->keys, ksize);  	p->tcfp_flags = parm->flags; -	p->tcf_action = parm->action; +	goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);  	kfree(p->tcfp_keys_ex);  	p->tcfp_keys_ex = keys_ex;  	spin_unlock_bh(&p->tcf_lock); +	if (goto_ch) +		tcf_chain_put_by_act(goto_ch);  	if (ret == ACT_P_CREATED)  		tcf_idr_insert(tn, *a);  	return ret; +put_chain: +	if (goto_ch) +		tcf_chain_put_by_act(goto_ch);  out_release:  	tcf_idr_release(*a, bind);  out_free: |