Commit ef765c25 authored by Pedro Tammela's avatar Pedro Tammela Committed by David S. Miller
Browse files

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: default avatarVictor Nogueira <victor@mojatatu.com>
Signed-off-by: default avatarPedro Tammela <pctammela@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e2f2fb3c
Loading
Loading
Loading
Loading
+21 −16
Original line number Diff line number Diff line
@@ -375,9 +375,9 @@ static int route4_delete(struct tcf_proto *tp, void *arg, bool *last,

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,34 +397,38 @@ 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]) {
		if (tb[TCA_ROUTE4_IIF])
	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]) {
		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) {
		NL_SET_ERR_MSG(extack, "Replacing with handle of 0 is invalid");
@@ -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;