Commit 2ac95dfe authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller
Browse files

net: bridge: mdb: use extack in br_mdb_parse()



We can drop the pr_info() calls and just use extack to return a
meaningful error to user-space when br_mdb_parse() fails.

Signed-off-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 35c52c5c
Loading
Loading
Loading
Loading
+39 −21
Original line number Diff line number Diff line
@@ -629,33 +629,50 @@ void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
	rtnl_set_sk_err(net, RTNLGRP_MDB, err);
}

static bool is_valid_mdb_entry(struct br_mdb_entry *entry)
static bool is_valid_mdb_entry(struct br_mdb_entry *entry,
			       struct netlink_ext_ack *extack)
{
	if (entry->ifindex == 0)
	if (entry->ifindex == 0) {
		NL_SET_ERR_MSG_MOD(extack, "Zero entry ifindex is not allowed");
		return false;
	}

	if (entry->addr.proto == htons(ETH_P_IP)) {
		if (!ipv4_is_multicast(entry->addr.u.ip4))
		if (!ipv4_is_multicast(entry->addr.u.ip4)) {
			NL_SET_ERR_MSG_MOD(extack, "IPv4 entry group address is not multicast");
			return false;
		if (ipv4_is_local_multicast(entry->addr.u.ip4))
		}
		if (ipv4_is_local_multicast(entry->addr.u.ip4)) {
			NL_SET_ERR_MSG_MOD(extack, "IPv4 entry group address is local multicast");
			return false;
		}
#if IS_ENABLED(CONFIG_IPV6)
	} else if (entry->addr.proto == htons(ETH_P_IPV6)) {
		if (ipv6_addr_is_ll_all_nodes(&entry->addr.u.ip6))
		if (ipv6_addr_is_ll_all_nodes(&entry->addr.u.ip6)) {
			NL_SET_ERR_MSG_MOD(extack, "IPv6 entry group address is link-local all nodes");
			return false;
		}
#endif
	} else
	} else {
		NL_SET_ERR_MSG_MOD(extack, "Unknown entry protocol");
		return false;
	if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY)
	}

	if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) {
		NL_SET_ERR_MSG_MOD(extack, "Unknown entry state");
		return false;
	if (entry->vid >= VLAN_VID_MASK)
	}
	if (entry->vid >= VLAN_VID_MASK) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid entry VLAN id");
		return false;
	}

	return true;
}

static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct net_device **pdev, struct br_mdb_entry **pentry)
			struct net_device **pdev, struct br_mdb_entry **pentry,
			struct netlink_ext_ack *extack)
{
	struct net *net = sock_net(skb->sk);
	struct br_mdb_entry *entry;
@@ -671,36 +688,37 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,

	bpm = nlmsg_data(nlh);
	if (bpm->ifindex == 0) {
		pr_info("PF_BRIDGE: br_mdb_parse() with invalid ifindex\n");
		NL_SET_ERR_MSG_MOD(extack, "Invalid bridge ifindex");
		return -EINVAL;
	}

	dev = __dev_get_by_index(net, bpm->ifindex);
	if (dev == NULL) {
		pr_info("PF_BRIDGE: br_mdb_parse() with unknown ifindex\n");
		NL_SET_ERR_MSG_MOD(extack, "Bridge device doesn't exist");
		return -ENODEV;
	}

	if (!(dev->priv_flags & IFF_EBRIDGE)) {
		pr_info("PF_BRIDGE: br_mdb_parse() with non-bridge\n");
		NL_SET_ERR_MSG_MOD(extack, "Device is not a bridge");
		return -EOPNOTSUPP;
	}

	*pdev = dev;

	if (!tb[MDBA_SET_ENTRY] ||
	    nla_len(tb[MDBA_SET_ENTRY]) != sizeof(struct br_mdb_entry)) {
		pr_info("PF_BRIDGE: br_mdb_parse() with invalid attr\n");
	if (!tb[MDBA_SET_ENTRY]) {
		NL_SET_ERR_MSG_MOD(extack, "Missing MDBA_SET_ENTRY attribute");
		return -EINVAL;
	}

	entry = nla_data(tb[MDBA_SET_ENTRY]);
	if (!is_valid_mdb_entry(entry)) {
		pr_info("PF_BRIDGE: br_mdb_parse() with invalid entry\n");
	if (nla_len(tb[MDBA_SET_ENTRY]) != sizeof(struct br_mdb_entry)) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid MDBA_SET_ENTRY attribute length");
		return -EINVAL;
	}

	entry = nla_data(tb[MDBA_SET_ENTRY]);
	if (!is_valid_mdb_entry(entry, extack))
		return -EINVAL;
	*pentry = entry;

	return 0;
}

@@ -797,7 +815,7 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh,
	struct net_bridge *br;
	int err;

	err = br_mdb_parse(skb, nlh, &dev, &entry);
	err = br_mdb_parse(skb, nlh, &dev, &entry, extack);
	if (err < 0)
		return err;

@@ -892,7 +910,7 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
	struct net_bridge *br;
	int err;

	err = br_mdb_parse(skb, nlh, &dev, &entry);
	err = br_mdb_parse(skb, nlh, &dev, &entry, extack);
	if (err < 0)
		return err;