Commit 30568334 authored by Daniel Machon's avatar Daniel Machon Committed by David S. Miller
Browse files

net: dcb: add new common function for set/del of app/rewr entries



In preparation for DCB rewrite. Add a new function for setting and
deleting both app and rewrite entries. Moving this into a separate
function reduces duplicate code, as both type of entries requires the
same set of checks. The function will now iterate through a configurable
nested attribute (app or rewrite attr), validate each attribute and call
the appropriate set- or delete function.

Note that this function always checks for nla_len(attr_itr) <
sizeof(struct dcb_app), which was only done in dcbnl_ieee_set and not in
dcbnl_ieee_del prior to this patch. This means, that any userspace tool
that used to shove in data < sizeof(struct dcb_app) would now receive
-ERANGE.

Signed-off-by: default avatarDaniel Machon <daniel.machon@microchip.com>
Reviewed-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 34b7074d
Loading
Loading
Loading
Loading
+45 −55
Original line number Diff line number Diff line
@@ -1099,6 +1099,41 @@ static int dcbnl_getapptrust(struct net_device *netdev, struct sk_buff *skb)
	return err;
}

/* Set or delete APP table or rewrite table entries. The APP struct is validated
 * and the appropriate callback function is called.
 */
static int dcbnl_app_table_setdel(struct nlattr *attr,
				  struct net_device *netdev,
				  int (*setdel)(struct net_device *dev,
						struct dcb_app *app))
{
	struct dcb_app *app_data;
	enum ieee_attrs_app type;
	struct nlattr *attr_itr;
	int rem, err;

	nla_for_each_nested(attr_itr, attr, rem) {
		type = nla_type(attr_itr);

		if (!dcbnl_app_attr_type_validate(type))
			continue;

		if (nla_len(attr_itr) < sizeof(struct dcb_app))
			return -ERANGE;

		app_data = nla_data(attr_itr);

		if (!dcbnl_app_selector_validate(type, app_data->selector))
			return -EINVAL;

		err = setdel(netdev, app_data);
		if (err)
			return err;
	}

	return 0;
}

/* Handle IEEE 802.1Qaz/802.1Qau/802.1Qbb GET commands. */
static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
{
@@ -1568,37 +1603,12 @@ static int dcbnl_ieee_set(struct net_device *netdev, struct nlmsghdr *nlh,
	}

	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
		struct nlattr *attr;
		int rem;

		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
			enum ieee_attrs_app type = nla_type(attr);
			struct dcb_app *app_data;

			if (!dcbnl_app_attr_type_validate(type))
				continue;

			if (nla_len(attr) < sizeof(struct dcb_app)) {
				err = -ERANGE;
				goto err;
			}

			app_data = nla_data(attr);

			if (!dcbnl_app_selector_validate(type,
							 app_data->selector)) {
				err = -EINVAL;
				goto err;
			}

			if (ops->ieee_setapp)
				err = ops->ieee_setapp(netdev, app_data);
			else
				err = dcb_ieee_setapp(netdev, app_data);
		err = dcbnl_app_table_setdel(ieee[DCB_ATTR_IEEE_APP_TABLE],
					     netdev, ops->ieee_setapp ?:
					     dcb_ieee_setapp);
		if (err)
			goto err;
	}
	}

	if (ieee[DCB_ATTR_DCB_APP_TRUST_TABLE]) {
		u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1] = {0};
@@ -1684,32 +1694,12 @@ static int dcbnl_ieee_del(struct net_device *netdev, struct nlmsghdr *nlh,
		return err;

	if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
		struct nlattr *attr;
		int rem;

		nla_for_each_nested(attr, ieee[DCB_ATTR_IEEE_APP_TABLE], rem) {
			enum ieee_attrs_app type = nla_type(attr);
			struct dcb_app *app_data;

			if (!dcbnl_app_attr_type_validate(type))
				continue;

			app_data = nla_data(attr);

			if (!dcbnl_app_selector_validate(type,
							 app_data->selector)) {
				err = -EINVAL;
				goto err;
			}

			if (ops->ieee_delapp)
				err = ops->ieee_delapp(netdev, app_data);
			else
				err = dcb_ieee_delapp(netdev, app_data);
		err = dcbnl_app_table_setdel(ieee[DCB_ATTR_IEEE_APP_TABLE],
					     netdev, ops->ieee_delapp ?:
					     dcb_ieee_delapp);
		if (err)
			goto err;
	}
	}

err:
	err = nla_put_u8(skb, DCB_ATTR_IEEE, err);