net: bridge: netlink: add extack error messages when processing vlans
authorNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Tue, 14 Jan 2020 17:56:08 +0000 (19:56 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 Jan 2020 12:48:17 +0000 (13:48 +0100)
Add extack messages on vlan processing errors. We need to move the flags
missing check after the "last" check since we may have "last" set but
lack a range end flag in the next entry.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_netlink.c
net/bridge/br_private.h

index 14100e8653e65498a14b31fdf3c3967082cd0865..40942cece51a0d67b74e882f6830107d7c4c2eb2 100644 (file)
@@ -568,11 +568,11 @@ static int br_process_vlan_info(struct net_bridge *br,
                                bool *changed,
                                struct netlink_ext_ack *extack)
 {
-       if (!br_vlan_valid_id(vinfo_curr->vid))
+       if (!br_vlan_valid_id(vinfo_curr->vid, extack))
                return -EINVAL;
 
        if (vinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
-               if (!br_vlan_valid_range(vinfo_curr, *vinfo_last))
+               if (!br_vlan_valid_range(vinfo_curr, *vinfo_last, extack))
                        return -EINVAL;
                *vinfo_last = vinfo_curr;
                return 0;
@@ -582,7 +582,7 @@ static int br_process_vlan_info(struct net_bridge *br,
                struct bridge_vlan_info tmp_vinfo;
                int v, err;
 
-               if (!br_vlan_valid_range(vinfo_curr, *vinfo_last))
+               if (!br_vlan_valid_range(vinfo_curr, *vinfo_last, extack))
                        return -EINVAL;
 
                memcpy(&tmp_vinfo, *vinfo_last,
index dbc0089e2c1adf5666f92d67b44175f8a6408e03..a7dddc5d7790b524ef7295eb76ba365e5e4b4aa6 100644 (file)
@@ -507,32 +507,48 @@ static inline bool nbp_state_should_learn(const struct net_bridge_port *p)
        return p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING;
 }
 
-static inline bool br_vlan_valid_id(u16 vid)
+static inline bool br_vlan_valid_id(u16 vid, struct netlink_ext_ack *extack)
 {
-       return vid > 0 && vid < VLAN_VID_MASK;
+       bool ret = vid > 0 && vid < VLAN_VID_MASK;
+
+       if (!ret)
+               NL_SET_ERR_MSG_MOD(extack, "Vlan id is invalid");
+
+       return ret;
 }
 
 static inline bool br_vlan_valid_range(const struct bridge_vlan_info *cur,
-                                      const struct bridge_vlan_info *last)
+                                      const struct bridge_vlan_info *last,
+                                      struct netlink_ext_ack *extack)
 {
        /* pvid flag is not allowed in ranges */
-       if (cur->flags & BRIDGE_VLAN_INFO_PVID)
-               return false;
-
-       /* check for required range flags */
-       if (!(cur->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN |
-                           BRIDGE_VLAN_INFO_RANGE_END)))
+       if (cur->flags & BRIDGE_VLAN_INFO_PVID) {
+               NL_SET_ERR_MSG_MOD(extack, "Pvid isn't allowed in a range");
                return false;
+       }
 
        /* when cur is the range end, check if:
         *  - it has range start flag
         *  - range ids are invalid (end is equal to or before start)
         */
        if (last) {
-               if (cur->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN)
+               if (cur->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+                       NL_SET_ERR_MSG_MOD(extack, "Found a new vlan range start while processing one");
                        return false;
-               else if (cur->vid <= last->vid)
+               } else if (!(cur->flags & BRIDGE_VLAN_INFO_RANGE_END)) {
+                       NL_SET_ERR_MSG_MOD(extack, "Vlan range end flag is missing");
                        return false;
+               } else if (cur->vid <= last->vid) {
+                       NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id");
+                       return false;
+               }
+       }
+
+       /* check for required range flags */
+       if (!(cur->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN |
+                           BRIDGE_VLAN_INFO_RANGE_END))) {
+               NL_SET_ERR_MSG_MOD(extack, "Both vlan range flags are missing");
+               return false;
        }
 
        return true;