LCOV - code coverage report
Current view: top level - net/8021q - vlan_netlink.c (source / functions) Hit Total Coverage
Test: Real Lines: 2 107 1.9 %
Date: 2020-10-17 15:46:16 Functions: 0 9 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  *      VLAN netlink control interface
       4                 :            :  *
       5                 :            :  *      Copyright (c) 2007 Patrick McHardy <kaber@trash.net>
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <linux/kernel.h>
       9                 :            : #include <linux/netdevice.h>
      10                 :            : #include <linux/if_vlan.h>
      11                 :            : #include <linux/module.h>
      12                 :            : #include <net/net_namespace.h>
      13                 :            : #include <net/netlink.h>
      14                 :            : #include <net/rtnetlink.h>
      15                 :            : #include "vlan.h"
      16                 :            : 
      17                 :            : 
      18                 :            : static const struct nla_policy vlan_policy[IFLA_VLAN_MAX + 1] = {
      19                 :            :         [IFLA_VLAN_ID]          = { .type = NLA_U16 },
      20                 :            :         [IFLA_VLAN_FLAGS]       = { .len = sizeof(struct ifla_vlan_flags) },
      21                 :            :         [IFLA_VLAN_EGRESS_QOS]  = { .type = NLA_NESTED },
      22                 :            :         [IFLA_VLAN_INGRESS_QOS] = { .type = NLA_NESTED },
      23                 :            :         [IFLA_VLAN_PROTOCOL]    = { .type = NLA_U16 },
      24                 :            : };
      25                 :            : 
      26                 :            : static const struct nla_policy vlan_map_policy[IFLA_VLAN_QOS_MAX + 1] = {
      27                 :            :         [IFLA_VLAN_QOS_MAPPING] = { .len = sizeof(struct ifla_vlan_qos_mapping) },
      28                 :            : };
      29                 :            : 
      30                 :            : 
      31                 :          0 : static inline int vlan_validate_qos_map(struct nlattr *attr)
      32                 :            : {
      33                 :          0 :         if (!attr)
      34                 :            :                 return 0;
      35                 :          0 :         return nla_validate_nested_deprecated(attr, IFLA_VLAN_QOS_MAX,
      36                 :            :                                               vlan_map_policy, NULL);
      37                 :            : }
      38                 :            : 
      39                 :          0 : static int vlan_validate(struct nlattr *tb[], struct nlattr *data[],
      40                 :            :                          struct netlink_ext_ack *extack)
      41                 :            : {
      42                 :            :         struct ifla_vlan_flags *flags;
      43                 :            :         u16 id;
      44                 :            :         int err;
      45                 :            : 
      46                 :          0 :         if (tb[IFLA_ADDRESS]) {
      47                 :          0 :                 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) {
      48                 :          0 :                         NL_SET_ERR_MSG_MOD(extack, "Invalid link address");
      49                 :            :                         return -EINVAL;
      50                 :            :                 }
      51                 :          0 :                 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) {
      52                 :          0 :                         NL_SET_ERR_MSG_MOD(extack, "Invalid link address");
      53                 :            :                         return -EADDRNOTAVAIL;
      54                 :            :                 }
      55                 :            :         }
      56                 :            : 
      57                 :          0 :         if (!data) {
      58                 :          0 :                 NL_SET_ERR_MSG_MOD(extack, "VLAN properties not specified");
      59                 :            :                 return -EINVAL;
      60                 :            :         }
      61                 :            : 
      62                 :          0 :         if (data[IFLA_VLAN_PROTOCOL]) {
      63                 :          0 :                 switch (nla_get_be16(data[IFLA_VLAN_PROTOCOL])) {
      64                 :            :                 case htons(ETH_P_8021Q):
      65                 :            :                 case htons(ETH_P_8021AD):
      66                 :            :                         break;
      67                 :            :                 default:
      68                 :          0 :                         NL_SET_ERR_MSG_MOD(extack, "Invalid VLAN protocol");
      69                 :            :                         return -EPROTONOSUPPORT;
      70                 :            :                 }
      71                 :            :         }
      72                 :            : 
      73                 :          0 :         if (data[IFLA_VLAN_ID]) {
      74                 :            :                 id = nla_get_u16(data[IFLA_VLAN_ID]);
      75                 :          0 :                 if (id >= VLAN_VID_MASK) {
      76                 :          0 :                         NL_SET_ERR_MSG_MOD(extack, "Invalid VLAN id");
      77                 :            :                         return -ERANGE;
      78                 :            :                 }
      79                 :            :         }
      80                 :          0 :         if (data[IFLA_VLAN_FLAGS]) {
      81                 :            :                 flags = nla_data(data[IFLA_VLAN_FLAGS]);
      82                 :          0 :                 if ((flags->flags & flags->mask) &
      83                 :            :                     ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
      84                 :            :                       VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP |
      85                 :            :                       VLAN_FLAG_BRIDGE_BINDING)) {
      86                 :          0 :                         NL_SET_ERR_MSG_MOD(extack, "Invalid VLAN flags");
      87                 :            :                         return -EINVAL;
      88                 :            :                 }
      89                 :            :         }
      90                 :            : 
      91                 :          0 :         err = vlan_validate_qos_map(data[IFLA_VLAN_INGRESS_QOS]);
      92                 :          0 :         if (err < 0) {
      93                 :          0 :                 NL_SET_ERR_MSG_MOD(extack, "Invalid ingress QOS map");
      94                 :          0 :                 return err;
      95                 :            :         }
      96                 :          0 :         err = vlan_validate_qos_map(data[IFLA_VLAN_EGRESS_QOS]);
      97                 :          0 :         if (err < 0) {
      98                 :          0 :                 NL_SET_ERR_MSG_MOD(extack, "Invalid egress QOS map");
      99                 :          0 :                 return err;
     100                 :            :         }
     101                 :            :         return 0;
     102                 :            : }
     103                 :            : 
     104                 :          0 : static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
     105                 :            :                            struct nlattr *data[],
     106                 :            :                            struct netlink_ext_ack *extack)
     107                 :            : {
     108                 :            :         struct ifla_vlan_flags *flags;
     109                 :            :         struct ifla_vlan_qos_mapping *m;
     110                 :            :         struct nlattr *attr;
     111                 :            :         int rem, err;
     112                 :            : 
     113                 :          0 :         if (data[IFLA_VLAN_FLAGS]) {
     114                 :            :                 flags = nla_data(data[IFLA_VLAN_FLAGS]);
     115                 :          0 :                 err = vlan_dev_change_flags(dev, flags->flags, flags->mask);
     116                 :          0 :                 if (err)
     117                 :            :                         return err;
     118                 :            :         }
     119                 :          0 :         if (data[IFLA_VLAN_INGRESS_QOS]) {
     120                 :          0 :                 nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
     121                 :            :                         m = nla_data(attr);
     122                 :          0 :                         vlan_dev_set_ingress_priority(dev, m->to, m->from);
     123                 :            :                 }
     124                 :            :         }
     125                 :          0 :         if (data[IFLA_VLAN_EGRESS_QOS]) {
     126                 :          0 :                 nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
     127                 :            :                         m = nla_data(attr);
     128                 :          0 :                         err = vlan_dev_set_egress_priority(dev, m->from, m->to);
     129                 :          0 :                         if (err)
     130                 :          0 :                                 return err;
     131                 :            :                 }
     132                 :            :         }
     133                 :            :         return 0;
     134                 :            : }
     135                 :            : 
     136                 :          0 : static int vlan_newlink(struct net *src_net, struct net_device *dev,
     137                 :            :                         struct nlattr *tb[], struct nlattr *data[],
     138                 :            :                         struct netlink_ext_ack *extack)
     139                 :            : {
     140                 :            :         struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
     141                 :            :         struct net_device *real_dev;
     142                 :            :         unsigned int max_mtu;
     143                 :            :         __be16 proto;
     144                 :            :         int err;
     145                 :            : 
     146                 :          0 :         if (!data[IFLA_VLAN_ID]) {
     147                 :          0 :                 NL_SET_ERR_MSG_MOD(extack, "VLAN id not specified");
     148                 :            :                 return -EINVAL;
     149                 :            :         }
     150                 :            : 
     151                 :          0 :         if (!tb[IFLA_LINK]) {
     152                 :          0 :                 NL_SET_ERR_MSG_MOD(extack, "link not specified");
     153                 :            :                 return -EINVAL;
     154                 :            :         }
     155                 :            : 
     156                 :          0 :         real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
     157                 :          0 :         if (!real_dev) {
     158                 :          0 :                 NL_SET_ERR_MSG_MOD(extack, "link does not exist");
     159                 :            :                 return -ENODEV;
     160                 :            :         }
     161                 :            : 
     162                 :          0 :         if (data[IFLA_VLAN_PROTOCOL])
     163                 :            :                 proto = nla_get_be16(data[IFLA_VLAN_PROTOCOL]);
     164                 :            :         else
     165                 :            :                 proto = htons(ETH_P_8021Q);
     166                 :            : 
     167                 :          0 :         vlan->vlan_proto = proto;
     168                 :          0 :         vlan->vlan_id         = nla_get_u16(data[IFLA_VLAN_ID]);
     169                 :          0 :         vlan->real_dev        = real_dev;
     170                 :          0 :         dev->priv_flags |= (real_dev->priv_flags & IFF_XMIT_DST_RELEASE);
     171                 :          0 :         vlan->flags   = VLAN_FLAG_REORDER_HDR;
     172                 :            : 
     173                 :          0 :         err = vlan_check_real_dev(real_dev, vlan->vlan_proto, vlan->vlan_id,
     174                 :            :                                   extack);
     175                 :          0 :         if (err < 0)
     176                 :            :                 return err;
     177                 :            : 
     178                 :          0 :         max_mtu = netif_reduces_vlan_mtu(real_dev) ? real_dev->mtu - VLAN_HLEN :
     179                 :            :                                                      real_dev->mtu;
     180                 :          0 :         if (!tb[IFLA_MTU])
     181                 :          0 :                 dev->mtu = max_mtu;
     182                 :          0 :         else if (dev->mtu > max_mtu)
     183                 :            :                 return -EINVAL;
     184                 :            : 
     185                 :          0 :         err = vlan_changelink(dev, tb, data, extack);
     186                 :          0 :         if (!err)
     187                 :          0 :                 err = register_vlan_dev(dev, extack);
     188                 :          0 :         if (err)
     189                 :          0 :                 vlan_dev_uninit(dev);
     190                 :          0 :         return err;
     191                 :            : }
     192                 :            : 
     193                 :            : static inline size_t vlan_qos_map_size(unsigned int n)
     194                 :            : {
     195                 :          0 :         if (n == 0)
     196                 :            :                 return 0;
     197                 :            :         /* IFLA_VLAN_{EGRESS,INGRESS}_QOS + n * IFLA_VLAN_QOS_MAPPING */
     198                 :          0 :         return nla_total_size(sizeof(struct nlattr)) +
     199                 :          0 :                nla_total_size(sizeof(struct ifla_vlan_qos_mapping)) * n;
     200                 :            : }
     201                 :            : 
     202                 :          0 : static size_t vlan_get_size(const struct net_device *dev)
     203                 :            : {
     204                 :            :         struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
     205                 :            : 
     206                 :          0 :         return nla_total_size(2) +      /* IFLA_VLAN_PROTOCOL */
     207                 :            :                nla_total_size(2) +      /* IFLA_VLAN_ID */
     208                 :          0 :                nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */
     209                 :          0 :                vlan_qos_map_size(vlan->nr_ingress_mappings) +
     210                 :          0 :                vlan_qos_map_size(vlan->nr_egress_mappings);
     211                 :            : }
     212                 :            : 
     213                 :          0 : static int vlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
     214                 :            : {
     215                 :            :         struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
     216                 :            :         struct vlan_priority_tci_mapping *pm;
     217                 :            :         struct ifla_vlan_flags f;
     218                 :            :         struct ifla_vlan_qos_mapping m;
     219                 :            :         struct nlattr *nest;
     220                 :            :         unsigned int i;
     221                 :            : 
     222                 :          0 :         if (nla_put_be16(skb, IFLA_VLAN_PROTOCOL, vlan->vlan_proto) ||
     223                 :          0 :             nla_put_u16(skb, IFLA_VLAN_ID, vlan->vlan_id))
     224                 :            :                 goto nla_put_failure;
     225                 :          0 :         if (vlan->flags) {
     226                 :          0 :                 f.flags = vlan->flags;
     227                 :          0 :                 f.mask  = ~0;
     228                 :          0 :                 if (nla_put(skb, IFLA_VLAN_FLAGS, sizeof(f), &f))
     229                 :            :                         goto nla_put_failure;
     230                 :            :         }
     231                 :          0 :         if (vlan->nr_ingress_mappings) {
     232                 :            :                 nest = nla_nest_start_noflag(skb, IFLA_VLAN_INGRESS_QOS);
     233                 :          0 :                 if (nest == NULL)
     234                 :            :                         goto nla_put_failure;
     235                 :            : 
     236                 :          0 :                 for (i = 0; i < ARRAY_SIZE(vlan->ingress_priority_map); i++) {
     237                 :          0 :                         if (!vlan->ingress_priority_map[i])
     238                 :          0 :                                 continue;
     239                 :            : 
     240                 :          0 :                         m.from = i;
     241                 :          0 :                         m.to   = vlan->ingress_priority_map[i];
     242                 :          0 :                         if (nla_put(skb, IFLA_VLAN_QOS_MAPPING,
     243                 :            :                                     sizeof(m), &m))
     244                 :            :                                 goto nla_put_failure;
     245                 :            :                 }
     246                 :            :                 nla_nest_end(skb, nest);
     247                 :            :         }
     248                 :            : 
     249                 :          0 :         if (vlan->nr_egress_mappings) {
     250                 :            :                 nest = nla_nest_start_noflag(skb, IFLA_VLAN_EGRESS_QOS);
     251                 :          0 :                 if (nest == NULL)
     252                 :            :                         goto nla_put_failure;
     253                 :            : 
     254                 :          0 :                 for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
     255                 :          0 :                         for (pm = vlan->egress_priority_map[i]; pm;
     256                 :          0 :                              pm = pm->next) {
     257                 :          0 :                                 if (!pm->vlan_qos)
     258                 :          0 :                                         continue;
     259                 :            : 
     260                 :          0 :                                 m.from = pm->priority;
     261                 :          0 :                                 m.to   = (pm->vlan_qos >> 13) & 0x7;
     262                 :          0 :                                 if (nla_put(skb, IFLA_VLAN_QOS_MAPPING,
     263                 :            :                                             sizeof(m), &m))
     264                 :            :                                         goto nla_put_failure;
     265                 :            :                         }
     266                 :            :                 }
     267                 :            :                 nla_nest_end(skb, nest);
     268                 :            :         }
     269                 :            :         return 0;
     270                 :            : 
     271                 :            : nla_put_failure:
     272                 :            :         return -EMSGSIZE;
     273                 :            : }
     274                 :            : 
     275                 :          0 : static struct net *vlan_get_link_net(const struct net_device *dev)
     276                 :            : {
     277                 :          0 :         struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
     278                 :            : 
     279                 :          0 :         return dev_net(real_dev);
     280                 :            : }
     281                 :            : 
     282                 :            : struct rtnl_link_ops vlan_link_ops __read_mostly = {
     283                 :            :         .kind           = "vlan",
     284                 :            :         .maxtype        = IFLA_VLAN_MAX,
     285                 :            :         .policy         = vlan_policy,
     286                 :            :         .priv_size      = sizeof(struct vlan_dev_priv),
     287                 :            :         .setup          = vlan_setup,
     288                 :            :         .validate       = vlan_validate,
     289                 :            :         .newlink        = vlan_newlink,
     290                 :            :         .changelink     = vlan_changelink,
     291                 :            :         .dellink        = unregister_vlan_dev,
     292                 :            :         .get_size       = vlan_get_size,
     293                 :            :         .fill_info      = vlan_fill_info,
     294                 :            :         .get_link_net   = vlan_get_link_net,
     295                 :            : };
     296                 :            : 
     297                 :          3 : int __init vlan_netlink_init(void)
     298                 :            : {
     299                 :          3 :         return rtnl_link_register(&vlan_link_ops);
     300                 :            : }
     301                 :            : 
     302                 :          0 : void __exit vlan_netlink_fini(void)
     303                 :            : {
     304                 :          0 :         rtnl_link_unregister(&vlan_link_ops);
     305                 :          0 : }
     306                 :            : 
     307                 :            : MODULE_ALIAS_RTNL_LINK("vlan");
    

Generated by: LCOV version 1.14