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