genetlink: optionally validate strictly/dumps
[platform/kernel/linux-rpi.git] / drivers / net / team / team.c
index 6ed96fd..2106045 100644 (file)
  * Helpers
  **********/
 
-#define team_port_exists(dev) (dev->priv_flags & IFF_TEAM_PORT)
-
 static struct team_port *team_port_get_rtnl(const struct net_device *dev)
 {
        struct team_port *port = rtnl_dereference(dev->rx_handler_data);
 
-       return team_port_exists(dev) ? port : NULL;
+       return netif_is_team_port(dev) ? port : NULL;
 }
 
 /*
@@ -1143,7 +1141,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
                return -EINVAL;
        }
 
-       if (team_port_exists(port_dev)) {
+       if (netif_is_team_port(port_dev)) {
                NL_SET_ERR_MSG(extack, "Device is already a port of a team device");
                netdev_err(dev, "Device %s is already a port "
                                "of a team device\n", portname);
@@ -1156,6 +1154,13 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
                return -EINVAL;
        }
 
+       if (netdev_has_upper_dev(dev, port_dev)) {
+               NL_SET_ERR_MSG(extack, "Device is already an upper device of the team interface");
+               netdev_err(dev, "Device %s is already an upper device of the team interface\n",
+                          portname);
+               return -EBUSY;
+       }
+
        if (port_dev->features & NETIF_F_VLAN_CHALLENGED &&
            vlan_uses_dev(dev)) {
                NL_SET_ERR_MSG(extack, "Device is VLAN challenged and team device has VLAN set up");
@@ -1246,6 +1251,23 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
                goto err_option_port_add;
        }
 
+       /* set promiscuity level to new slave */
+       if (dev->flags & IFF_PROMISC) {
+               err = dev_set_promiscuity(port_dev, 1);
+               if (err)
+                       goto err_set_slave_promisc;
+       }
+
+       /* set allmulti level to new slave */
+       if (dev->flags & IFF_ALLMULTI) {
+               err = dev_set_allmulti(port_dev, 1);
+               if (err) {
+                       if (dev->flags & IFF_PROMISC)
+                               dev_set_promiscuity(port_dev, -1);
+                       goto err_set_slave_promisc;
+               }
+       }
+
        netif_addr_lock_bh(dev);
        dev_uc_sync_multiple(port_dev, dev);
        dev_mc_sync_multiple(port_dev, dev);
@@ -1262,6 +1284,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
 
        return 0;
 
+err_set_slave_promisc:
+       __team_option_inst_del_port(team, port);
+
 err_option_port_add:
        team_upper_dev_unlink(team, port);
 
@@ -1307,6 +1332,12 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
 
        team_port_disable(team, port);
        list_del_rcu(&port->list);
+
+       if (dev->flags & IFF_PROMISC)
+               dev_set_promiscuity(port_dev, -1);
+       if (dev->flags & IFF_ALLMULTI)
+               dev_set_allmulti(port_dev, -1);
+
        team_upper_dev_unlink(team, port);
        netdev_rx_handler_unregister(port_dev);
        team_port_disable_netpoll(port);
@@ -1691,8 +1722,7 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb,
-                            struct net_device *sb_dev,
-                            select_queue_fallback_t fallback)
+                            struct net_device *sb_dev)
 {
        /*
         * This helper function exists to help dev_pick_tx get the correct
@@ -2260,7 +2290,7 @@ static int team_nl_fill_one_option_get(struct sk_buff *skb, struct team *team,
        if (err)
                return err;
 
-       option_item = nla_nest_start(skb, TEAM_ATTR_ITEM_OPTION);
+       option_item = nla_nest_start_noflag(skb, TEAM_ATTR_ITEM_OPTION);
        if (!option_item)
                return -EMSGSIZE;
 
@@ -2374,7 +2404,7 @@ start_again:
 
        if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
                goto nla_put_failure;
-       option_list = nla_nest_start(skb, TEAM_ATTR_LIST_OPTION);
+       option_list = nla_nest_start_noflag(skb, TEAM_ATTR_LIST_OPTION);
        if (!option_list)
                goto nla_put_failure;
 
@@ -2480,9 +2510,11 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                        err = -EINVAL;
                        goto team_put;
                }
-               err = nla_parse_nested(opt_attrs, TEAM_ATTR_OPTION_MAX,
-                                      nl_option, team_nl_option_policy,
-                                      info->extack);
+               err = nla_parse_nested_deprecated(opt_attrs,
+                                                 TEAM_ATTR_OPTION_MAX,
+                                                 nl_option,
+                                                 team_nl_option_policy,
+                                                 info->extack);
                if (err)
                        goto team_put;
                if (!opt_attrs[TEAM_ATTR_OPTION_NAME] ||
@@ -2596,7 +2628,7 @@ static int team_nl_fill_one_port_get(struct sk_buff *skb,
 {
        struct nlattr *port_item;
 
-       port_item = nla_nest_start(skb, TEAM_ATTR_ITEM_PORT);
+       port_item = nla_nest_start_noflag(skb, TEAM_ATTR_ITEM_PORT);
        if (!port_item)
                goto nest_cancel;
        if (nla_put_u32(skb, TEAM_ATTR_PORT_IFINDEX, port->dev->ifindex))
@@ -2651,7 +2683,7 @@ start_again:
 
        if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
                goto nla_put_failure;
-       port_list = nla_nest_start(skb, TEAM_ATTR_LIST_PORT);
+       port_list = nla_nest_start_noflag(skb, TEAM_ATTR_LIST_PORT);
        if (!port_list)
                goto nla_put_failure;
 
@@ -2725,25 +2757,25 @@ static int team_nl_cmd_port_list_get(struct sk_buff *skb,
 static const struct genl_ops team_nl_ops[] = {
        {
                .cmd = TEAM_CMD_NOOP,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = team_nl_cmd_noop,
-               .policy = team_nl_policy,
        },
        {
                .cmd = TEAM_CMD_OPTIONS_SET,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = team_nl_cmd_options_set,
-               .policy = team_nl_policy,
                .flags = GENL_ADMIN_PERM,
        },
        {
                .cmd = TEAM_CMD_OPTIONS_GET,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = team_nl_cmd_options_get,
-               .policy = team_nl_policy,
                .flags = GENL_ADMIN_PERM,
        },
        {
                .cmd = TEAM_CMD_PORT_LIST_GET,
+               .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
                .doit = team_nl_cmd_port_list_get,
-               .policy = team_nl_policy,
                .flags = GENL_ADMIN_PERM,
        },
 };
@@ -2756,6 +2788,7 @@ static struct genl_family team_nl_family __ro_after_init = {
        .name           = TEAM_GENL_NAME,
        .version        = TEAM_GENL_VERSION,
        .maxattr        = TEAM_ATTR_MAX,
+       .policy = team_nl_policy,
        .netnsok        = true,
        .module         = THIS_MODULE,
        .ops            = team_nl_ops,