net/sched: cls_route: make netlink errors meaningful

Use netlink extended ack and parsing policies to return more meaningful
errors instead of the relying solely on errnos.

Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Pedro Tammela 2023-09-11 18:50:16 -03:00 committed by David S. Miller
parent e2f2fb3c35
commit ef765c2587

View File

@ -375,9 +375,9 @@ out:
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 },
[TCA_ROUTE4_TO] = NLA_POLICY_MAX(NLA_U32, 0xFF),
[TCA_ROUTE4_FROM] = NLA_POLICY_MAX(NLA_U32, 0xFF),
[TCA_ROUTE4_IIF] = NLA_POLICY_MAX(NLA_U32, 0x7FFF),
};
static int route4_set_parms(struct net *net, struct tcf_proto *tp,
@ -397,33 +397,37 @@ static int route4_set_parms(struct net *net, struct tcf_proto *tp,
return err;
if (tb[TCA_ROUTE4_TO]) {
if (new && handle & 0x8000)
if (new && handle & 0x8000) {
NL_SET_ERR_MSG(extack, "Invalid handle");
return -EINVAL;
}
to = nla_get_u32(tb[TCA_ROUTE4_TO]);
if (to > 0xFF)
return -EINVAL;
nhandle = to;
}
if (tb[TCA_ROUTE4_FROM] && tb[TCA_ROUTE4_IIF]) {
NL_SET_ERR_MSG_ATTR(extack, tb[TCA_ROUTE4_FROM],
"'from' and 'fromif' are mutually exclusive");
return -EINVAL;
}
if (tb[TCA_ROUTE4_FROM]) {
if (tb[TCA_ROUTE4_IIF])
return -EINVAL;
id = nla_get_u32(tb[TCA_ROUTE4_FROM]);
if (id > 0xFF)
return -EINVAL;
nhandle |= id << 16;
} else if (tb[TCA_ROUTE4_IIF]) {
id = nla_get_u32(tb[TCA_ROUTE4_IIF]);
if (id > 0x7FFF)
return -EINVAL;
nhandle |= (id | 0x8000) << 16;
} else
nhandle |= 0xFFFF << 16;
if (handle && new) {
nhandle |= handle & 0x7F00;
if (nhandle != handle)
if (nhandle != handle) {
NL_SET_ERR_MSG_FMT(extack,
"Handle mismatch constructed: %x (expected: %x)",
handle, nhandle);
return -EINVAL;
}
}
if (!nhandle) {
@ -478,7 +482,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
struct route4_filter __rcu **fp;
struct route4_filter *fold, *f1, *pfp, *f = NULL;
struct route4_bucket *b;
struct nlattr *opt = tca[TCA_OPTIONS];
struct nlattr *tb[TCA_ROUTE4_MAX + 1];
unsigned int h, th;
int err;
@ -489,10 +492,12 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
return -EINVAL;
}
if (opt == NULL)
if (NL_REQ_ATTR_CHECK(extack, NULL, tca, TCA_OPTIONS)) {
NL_SET_ERR_MSG_MOD(extack, "Missing options");
return -EINVAL;
}
err = nla_parse_nested_deprecated(tb, TCA_ROUTE4_MAX, opt,
err = nla_parse_nested_deprecated(tb, TCA_ROUTE4_MAX, tca[TCA_OPTIONS],
route4_policy, NULL);
if (err < 0)
return err;