net: bridge: mdb: use extack in br_mdb_parse()
authorNikolay Aleksandrov <nikolay@nvidia.com>
Tue, 22 Sep 2020 07:30:12 +0000 (10:30 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 23 Sep 2020 20:24:34 +0000 (13:24 -0700)
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: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_mdb.c

index 00f1651..d4031f5 100644 (file)
@@ -629,33 +629,50 @@ errout:
        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;