vlan.c 18.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * INET		802.1Q VLAN
 *		Ethernet-type device handling.
 *
 * Authors:	Ben Greear <greearb@candelatech.com>
P
Patrick McHardy 已提交
6
 *              Please send support related email to: netdev@vger.kernel.org
L
Linus Torvalds 已提交
7
 *              VLAN Home Page: http://www.candelatech.com/~greear/vlan.html
8
 *
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20
 * Fixes:
 *              Fix for packet capture - Nick Eggleston <nick@dccinc.com>;
 *		Add HW acceleration hooks - David S. Miller <davem@redhat.com>;
 *		Correct all the locking - David S. Miller <davem@redhat.com>;
 *		Use hash table for VLAN groups - David S. Miller <davem@redhat.com>
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 */

J
Joe Perches 已提交
21 22
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

23
#include <linux/capability.h>
L
Linus Torvalds 已提交
24 25 26
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
27
#include <linux/slab.h>
L
Linus Torvalds 已提交
28
#include <linux/init.h>
29
#include <linux/rculist.h>
L
Linus Torvalds 已提交
30 31 32 33
#include <net/p8022.h>
#include <net/arp.h>
#include <linux/rtnetlink.h>
#include <linux/notifier.h>
34
#include <net/rtnetlink.h>
35
#include <net/net_namespace.h>
36
#include <net/netns/generic.h>
37
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
38 39 40 41 42 43 44 45 46

#include <linux/if_vlan.h>
#include "vlan.h"
#include "vlanproc.h"

#define DRV_VERSION "1.8"

/* Global VLAN variables */

47
unsigned int vlan_net_id __read_mostly;
48

49 50
const char vlan_fullname[] = "802.1Q VLAN Support";
const char vlan_version[] = DRV_VERSION;
L
Linus Torvalds 已提交
51 52 53

/* End of global variables definitions. */

54 55
static int vlan_group_prealloc_vid(struct vlan_group *vg,
				   __be16 vlan_proto, u16 vlan_id)
56 57
{
	struct net_device **array;
58
	unsigned int pidx, vidx;
59 60 61 62
	unsigned int size;

	ASSERT_RTNL();

63 64 65
	pidx  = vlan_proto_idx(vlan_proto);
	vidx  = vlan_id / VLAN_GROUP_ARRAY_PART_LEN;
	array = vg->vlan_devices_arrays[pidx][vidx];
66 67 68 69 70 71 72 73
	if (array != NULL)
		return 0;

	size = sizeof(struct net_device *) * VLAN_GROUP_ARRAY_PART_LEN;
	array = kzalloc(size, GFP_KERNEL);
	if (array == NULL)
		return -ENOBUFS;

74
	vg->vlan_devices_arrays[pidx][vidx] = array;
75
	return 0;
76 77
}

78
void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
L
Linus Torvalds 已提交
79
{
80
	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
81
	struct net_device *real_dev = vlan->real_dev;
82
	struct vlan_info *vlan_info;
L
Linus Torvalds 已提交
83
	struct vlan_group *grp;
84
	u16 vlan_id = vlan->vlan_id;
L
Linus Torvalds 已提交
85 86

	ASSERT_RTNL();
87

88 89 90 91
	vlan_info = rtnl_dereference(real_dev->vlan_info);
	BUG_ON(!vlan_info);

	grp = &vlan_info->grp;
92

93
	grp->nr_vlan_devs--;
94

95 96
	if (vlan->flags & VLAN_FLAG_MVRP)
		vlan_mvrp_request_leave(dev);
E
Eric Dumazet 已提交
97 98 99
	if (vlan->flags & VLAN_FLAG_GVRP)
		vlan_gvrp_request_leave(dev);

100
	vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, NULL);
101 102

	netdev_upper_dev_unlink(real_dev, dev);
103 104 105 106
	/* Because unregister_netdevice_queue() makes sure at least one rcu
	 * grace period is respected before device freeing,
	 * we dont need to call synchronize_net() here.
	 */
107
	unregister_netdevice_queue(dev, head);
108

109 110
	if (grp->nr_vlan_devs == 0) {
		vlan_mvrp_uninit_applicant(real_dev);
P
Patrick McHardy 已提交
111
		vlan_gvrp_uninit_applicant(real_dev);
112
	}
P
Patrick McHardy 已提交
113

114 115 116 117 118
	/* Take it out of our own structures, but be sure to interlock with
	 * HW accelerating devices or SW vlan input packet processing if
	 * VLAN is not 0 (leave it there for 802.1p).
	 */
	if (vlan_id)
119
		vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id);
120

121 122
	/* Get rid of the vlan's reference to real_dev */
	dev_put(real_dev);
L
Linus Torvalds 已提交
123 124
}

125 126
int vlan_check_real_dev(struct net_device *real_dev,
			__be16 protocol, u16 vlan_id)
L
Linus Torvalds 已提交
127
{
128
	const char *name = real_dev->name;
129

L
Linus Torvalds 已提交
130
	if (real_dev->features & NETIF_F_VLAN_CHALLENGED) {
J
Joe Perches 已提交
131
		pr_info("VLANs not supported on %s\n", name);
P
Patrick McHardy 已提交
132
		return -EOPNOTSUPP;
L
Linus Torvalds 已提交
133 134
	}

135
	if (vlan_find_dev(real_dev, protocol, vlan_id) != NULL)
P
Patrick McHardy 已提交
136
		return -EEXIST;
L
Linus Torvalds 已提交
137

P
Patrick McHardy 已提交
138 139 140
	return 0;
}

P
Patrick McHardy 已提交
141
int register_vlan_dev(struct net_device *dev)
142
{
143
	struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
144
	struct net_device *real_dev = vlan->real_dev;
145
	u16 vlan_id = vlan->vlan_id;
146 147
	struct vlan_info *vlan_info;
	struct vlan_group *grp;
148 149
	int err;

150
	err = vlan_vid_add(real_dev, vlan->vlan_proto, vlan_id);
151 152 153 154 155 156 157 158 159
	if (err)
		return err;

	vlan_info = rtnl_dereference(real_dev->vlan_info);
	/* vlan_info should be there now. vlan_vid_add took care of it */
	BUG_ON(!vlan_info);

	grp = &vlan_info->grp;
	if (grp->nr_vlan_devs == 0) {
P
Patrick McHardy 已提交
160 161
		err = vlan_gvrp_init_applicant(real_dev);
		if (err < 0)
162
			goto out_vid_del;
163 164 165
		err = vlan_mvrp_init_applicant(real_dev);
		if (err < 0)
			goto out_uninit_gvrp;
166 167
	}

168
	err = vlan_group_prealloc_vid(grp, vlan->vlan_proto, vlan_id);
169
	if (err < 0)
170
		goto out_uninit_mvrp;
171

172
	vlan->nest_level = dev_get_nest_level(real_dev) + 1;
173 174
	err = register_netdevice(dev);
	if (err < 0)
175 176 177 178 179
		goto out_uninit_mvrp;

	err = netdev_upper_dev_link(real_dev, dev);
	if (err)
		goto out_unregister_netdev;
180

181
	/* Account for reference in struct vlan_dev_priv */
182 183
	dev_hold(real_dev);

184
	netif_stacked_transfer_operstate(real_dev, dev);
185 186 187 188 189
	linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */

	/* So, got the sucker initialized, now lets place
	 * it into our local structure.
	 */
190
	vlan_group_set_device(grp, vlan->vlan_proto, vlan_id, dev);
191
	grp->nr_vlan_devs++;
192 193 194

	return 0;

195 196
out_unregister_netdev:
	unregister_netdevice(dev);
197 198 199 200
out_uninit_mvrp:
	if (grp->nr_vlan_devs == 0)
		vlan_mvrp_uninit_applicant(real_dev);
out_uninit_gvrp:
201
	if (grp->nr_vlan_devs == 0)
P
Patrick McHardy 已提交
202
		vlan_gvrp_uninit_applicant(real_dev);
203
out_vid_del:
204
	vlan_vid_del(real_dev, vlan->vlan_proto, vlan_id);
205 206 207
	return err;
}

P
Patrick McHardy 已提交
208
/*  Attach a VLAN device to a mac address (ie Ethernet Card).
209
 *  Returns 0 if the device was created or a negative error code otherwise.
P
Patrick McHardy 已提交
210
 */
211
static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
P
Patrick McHardy 已提交
212 213
{
	struct net_device *new_dev;
214
	struct vlan_dev_priv *vlan;
215 216
	struct net *net = dev_net(real_dev);
	struct vlan_net *vn = net_generic(net, vlan_net_id);
P
Patrick McHardy 已提交
217
	char name[IFNAMSIZ];
218
	int err;
P
Patrick McHardy 已提交
219

220
	if (vlan_id >= VLAN_VID_MASK)
221
		return -ERANGE;
P
Patrick McHardy 已提交
222

223
	err = vlan_check_real_dev(real_dev, htons(ETH_P_8021Q), vlan_id);
224 225
	if (err < 0)
		return err;
P
Patrick McHardy 已提交
226

L
Linus Torvalds 已提交
227
	/* Gotta set up the fields for the device. */
228
	switch (vn->name_type) {
L
Linus Torvalds 已提交
229 230
	case VLAN_NAME_TYPE_RAW_PLUS_VID:
		/* name will look like:	 eth1.0005 */
231
		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, vlan_id);
L
Linus Torvalds 已提交
232 233 234 235 236
		break;
	case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
		/* Put our vlan.VID in the name.
		 * Name will look like:	 vlan5
		 */
237
		snprintf(name, IFNAMSIZ, "vlan%i", vlan_id);
L
Linus Torvalds 已提交
238 239 240 241 242
		break;
	case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:
		/* Put our vlan.VID in the name.
		 * Name will look like:	 eth0.5
		 */
243
		snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, vlan_id);
L
Linus Torvalds 已提交
244 245 246 247 248 249
		break;
	case VLAN_NAME_TYPE_PLUS_VID:
		/* Put our vlan.VID in the name.
		 * Name will look like:	 vlan0005
		 */
	default:
250
		snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id);
251
	}
252

253 254
	new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name,
			       NET_NAME_UNKNOWN, vlan_setup);
255

L
Linus Torvalds 已提交
256
	if (new_dev == NULL)
257
		return -ENOBUFS;
L
Linus Torvalds 已提交
258

259
	dev_net_set(new_dev, net);
L
Linus Torvalds 已提交
260 261 262 263 264
	/* need 4 bytes for extra VLAN header info,
	 * hope the underlying device can handle it.
	 */
	new_dev->mtu = real_dev->mtu;

265 266 267 268 269 270
	vlan = vlan_dev_priv(new_dev);
	vlan->vlan_proto = htons(ETH_P_8021Q);
	vlan->vlan_id = vlan_id;
	vlan->real_dev = real_dev;
	vlan->dent = NULL;
	vlan->flags = VLAN_FLAG_REORDER_HDR;
L
Linus Torvalds 已提交
271

P
Patrick McHardy 已提交
272
	new_dev->rtnl_link_ops = &vlan_link_ops;
273 274
	err = register_vlan_dev(new_dev);
	if (err < 0)
275
		goto out_free_newdev;
L
Linus Torvalds 已提交
276

277
	return 0;
L
Linus Torvalds 已提交
278 279

out_free_newdev:
280 281
	if (new_dev->reg_state == NETREG_UNINITIALIZED)
		free_netdev(new_dev);
282
	return err;
L
Linus Torvalds 已提交
283 284
}

285 286 287
static void vlan_sync_address(struct net_device *dev,
			      struct net_device *vlandev)
{
288
	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);
289 290

	/* May be called without an actual change */
291
	if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
292 293
		return;

294 295 296 297
	/* vlan continues to inherit address of lower device */
	if (vlan_dev_inherit_address(vlandev, dev))
		goto out;

298 299
	/* vlan address was different from the old address and is equal to
	 * the new address */
300 301
	if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
	    ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
302
		dev_uc_del(dev, vlandev->dev_addr);
303 304 305

	/* vlan address was equal to the old address and is different from
	 * the new address */
306 307
	if (ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
	    !ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
308
		dev_uc_add(dev, vlandev->dev_addr);
309

310
out:
J
Joe Perches 已提交
311
	ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
312 313
}

314 315 316
static void vlan_transfer_features(struct net_device *dev,
				   struct net_device *vlandev)
{
317 318
	struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev);

319
	vlandev->gso_max_size = dev->gso_max_size;
E
Eric Dumazet 已提交
320
	vlandev->gso_max_segs = dev->gso_max_segs;
321

322
	if (vlan_hw_offload_capable(dev->features, vlan->vlan_proto))
323 324 325 326
		vlandev->hard_header_len = dev->hard_header_len;
	else
		vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;

A
Amerigo Wang 已提交
327
#if IS_ENABLED(CONFIG_FCOE)
328 329
	vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
#endif
330 331

	netdev_update_features(vlandev);
332 333
}

334
static int __vlan_device_event(struct net_device *dev, unsigned long event)
335
{
336 337
	int err = 0;

338 339 340
	switch (event) {
	case NETDEV_CHANGENAME:
		vlan_proc_rem_dev(dev);
341
		err = vlan_proc_add_dev(dev);
342
		break;
343
	case NETDEV_REGISTER:
344
		err = vlan_proc_add_dev(dev);
345 346 347 348
		break;
	case NETDEV_UNREGISTER:
		vlan_proc_rem_dev(dev);
		break;
349
	}
350 351

	return err;
352 353
}

P
Patrick McHardy 已提交
354 355
static int vlan_device_event(struct notifier_block *unused, unsigned long event,
			     void *ptr)
L
Linus Torvalds 已提交
356
{
357
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
358
	struct vlan_group *grp;
359
	struct vlan_info *vlan_info;
L
Linus Torvalds 已提交
360 361
	int i, flgs;
	struct net_device *vlandev;
362
	struct vlan_dev_priv *vlan;
363
	bool last = false;
364
	LIST_HEAD(list);
L
Linus Torvalds 已提交
365

366 367 368 369 370 371
	if (is_vlan_dev(dev)) {
		int err = __vlan_device_event(dev, event);

		if (err)
			return notifier_from_errno(err);
	}
372

373
	if ((event == NETDEV_UP) &&
374
	    (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
J
Joe Perches 已提交
375
		pr_info("adding VLAN 0 to HW filter on device %s\n",
376
			dev->name);
377
		vlan_vid_add(dev, htons(ETH_P_8021Q), 0);
378 379
	}

380 381
	vlan_info = rtnl_dereference(dev->vlan_info);
	if (!vlan_info)
L
Linus Torvalds 已提交
382
		goto out;
383
	grp = &vlan_info->grp;
L
Linus Torvalds 已提交
384 385 386 387 388 389 390 391

	/* It is OK that we do not hold the group lock right now,
	 * as we run under the RTNL lock.
	 */

	switch (event) {
	case NETDEV_CHANGE:
		/* Propagate real device state to vlan devices */
392
		vlan_group_for_each_dev(grp, i, vlandev)
393
			netif_stacked_transfer_operstate(dev, vlandev);
L
Linus Torvalds 已提交
394 395
		break;

396 397
	case NETDEV_CHANGEADDR:
		/* Adjust unicast filters on underlying device */
398
		vlan_group_for_each_dev(grp, i, vlandev) {
399 400 401 402
			flgs = vlandev->flags;
			if (!(flgs & IFF_UP))
				continue;

403 404
			vlan_sync_address(dev, vlandev);
		}
405 406 407
		break;

	case NETDEV_CHANGEMTU:
408
		vlan_group_for_each_dev(grp, i, vlandev) {
409 410 411 412 413
			if (vlandev->mtu <= dev->mtu)
				continue;

			dev_set_mtu(vlandev, dev->mtu);
		}
414 415
		break;

416 417
	case NETDEV_FEAT_CHANGE:
		/* Propagate device features to underlying device */
418
		vlan_group_for_each_dev(grp, i, vlandev)
419 420 421
			vlan_transfer_features(dev, vlandev);
		break;

422 423 424 425
	case NETDEV_DOWN: {
		struct net_device *tmp;
		LIST_HEAD(close_list);

426
		if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
427
			vlan_vid_del(dev, htons(ETH_P_8021Q), 0);
428

L
Linus Torvalds 已提交
429
		/* Put all VLANs for this dev in the down state too.  */
430
		vlan_group_for_each_dev(grp, i, vlandev) {
L
Linus Torvalds 已提交
431 432 433 434
			flgs = vlandev->flags;
			if (!(flgs & IFF_UP))
				continue;

435
			vlan = vlan_dev_priv(vlandev);
436
			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
437 438 439 440 441 442
				list_add(&vlandev->close_list, &close_list);
		}

		dev_close_many(&close_list, false);

		list_for_each_entry_safe(vlandev, tmp, &close_list, close_list) {
443
			netif_stacked_transfer_operstate(dev, vlandev);
444
			list_del_init(&vlandev->close_list);
L
Linus Torvalds 已提交
445
		}
446
		list_del(&close_list);
L
Linus Torvalds 已提交
447
		break;
448
	}
L
Linus Torvalds 已提交
449 450
	case NETDEV_UP:
		/* Put all VLANs for this dev in the up state too.  */
451
		vlan_group_for_each_dev(grp, i, vlandev) {
452
			flgs = dev_get_flags(vlandev);
L
Linus Torvalds 已提交
453 454 455
			if (flgs & IFF_UP)
				continue;

456
			vlan = vlan_dev_priv(vlandev);
457 458
			if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
				dev_change_flags(vlandev, flgs | IFF_UP);
459
			netif_stacked_transfer_operstate(dev, vlandev);
L
Linus Torvalds 已提交
460 461
		}
		break;
462

L
Linus Torvalds 已提交
463
	case NETDEV_UNREGISTER:
464 465 466 467
		/* twiddle thumbs on netns device moves */
		if (dev->reg_state != NETREG_UNREGISTERING)
			break;

468
		vlan_group_for_each_dev(grp, i, vlandev) {
469
			/* removal of last vid destroys vlan_info, abort
470
			 * afterwards */
471
			if (vlan_info->nr_vids == 1)
472
				last = true;
473 474

			unregister_vlan_dev(vlandev, &list);
475 476
			if (last)
				break;
477 478
		}
		unregister_netdevice_many(&list);
L
Linus Torvalds 已提交
479
		break;
480 481 482

	case NETDEV_PRE_TYPE_CHANGE:
		/* Forbid underlaying device to change its type. */
483 484 485
		if (vlan_uses_dev(dev))
			return NOTIFY_BAD;
		break;
486 487

	case NETDEV_NOTIFY_PEERS:
488
	case NETDEV_BONDING_FAILOVER:
489
	case NETDEV_RESEND_IGMP:
490
		/* Propagate to vlan devices */
491
		vlan_group_for_each_dev(grp, i, vlandev)
492
			call_netdevice_notifiers(event, vlandev);
493
		break;
494
	}
L
Linus Torvalds 已提交
495 496 497 498 499

out:
	return NOTIFY_DONE;
}

500 501 502 503
static struct notifier_block vlan_notifier_block __read_mostly = {
	.notifier_call = vlan_device_event,
};

L
Linus Torvalds 已提交
504 505 506 507 508
/*
 *	VLAN IOCTL handler.
 *	o execute requested action or pass command to the device driver
 *   arg is really a struct vlan_ioctl_args __user *.
 */
509
static int vlan_ioctl_handler(struct net *net, void __user *arg)
L
Linus Torvalds 已提交
510
{
511
	int err;
L
Linus Torvalds 已提交
512
	struct vlan_ioctl_args args;
513
	struct net_device *dev = NULL;
L
Linus Torvalds 已提交
514 515 516 517 518

	if (copy_from_user(&args, arg, sizeof(struct vlan_ioctl_args)))
		return -EFAULT;

	/* Null terminate this sucker, just in case. */
519 520
	args.device1[sizeof(args.device1) - 1] = 0;
	args.u.device2[sizeof(args.u.device2) - 1] = 0;
L
Linus Torvalds 已提交
521

522 523
	rtnl_lock();

L
Linus Torvalds 已提交
524 525
	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
526 527 528 529 530 531 532
	case SET_VLAN_EGRESS_PRIORITY_CMD:
	case SET_VLAN_FLAG_CMD:
	case ADD_VLAN_CMD:
	case DEL_VLAN_CMD:
	case GET_VLAN_REALDEV_NAME_CMD:
	case GET_VLAN_VID_CMD:
		err = -ENODEV;
533
		dev = __dev_get_by_name(net, args.device1);
534 535 536 537
		if (!dev)
			goto out;

		err = -EINVAL;
J
Joonwoo Park 已提交
538
		if (args.cmd != ADD_VLAN_CMD && !is_vlan_dev(dev))
539 540 541 542 543 544
			goto out;
	}

	switch (args.cmd) {
	case SET_VLAN_INGRESS_PRIORITY_CMD:
		err = -EPERM;
545
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
546 547 548 549
			break;
		vlan_dev_set_ingress_priority(dev,
					      args.u.skb_priority,
					      args.vlan_qos);
550
		err = 0;
L
Linus Torvalds 已提交
551 552 553
		break;

	case SET_VLAN_EGRESS_PRIORITY_CMD:
554
		err = -EPERM;
555
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
556 557
			break;
		err = vlan_dev_set_egress_priority(dev,
L
Linus Torvalds 已提交
558 559 560 561 562
						   args.u.skb_priority,
						   args.vlan_qos);
		break;

	case SET_VLAN_FLAG_CMD:
563
		err = -EPERM;
564
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
565
			break;
566 567 568
		err = vlan_dev_change_flags(dev,
					    args.vlan_qos ? args.u.flag : 0,
					    args.u.flag);
L
Linus Torvalds 已提交
569 570 571
		break;

	case SET_VLAN_NAME_TYPE_CMD:
572
		err = -EPERM;
573
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
574
			break;
575
		if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) {
576 577 578 579
			struct vlan_net *vn;

			vn = net_generic(net, vlan_net_id);
			vn->name_type = args.u.name_type;
L
Linus Torvalds 已提交
580 581 582 583 584 585 586
			err = 0;
		} else {
			err = -EINVAL;
		}
		break;

	case ADD_VLAN_CMD:
587
		err = -EPERM;
588
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
589
			break;
590
		err = register_vlan_device(dev, args.u.VID);
L
Linus Torvalds 已提交
591 592 593
		break;

	case DEL_VLAN_CMD:
594
		err = -EPERM;
595
		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
596
			break;
597
		unregister_vlan_dev(dev, NULL);
598
		err = 0;
L
Linus Torvalds 已提交
599 600 601
		break;

	case GET_VLAN_REALDEV_NAME_CMD:
602
		err = 0;
603
		vlan_dev_get_realdev_name(dev, args.u.device2);
L
Linus Torvalds 已提交
604
		if (copy_to_user(arg, &args,
P
Patrick McHardy 已提交
605
				 sizeof(struct vlan_ioctl_args)))
L
Linus Torvalds 已提交
606 607 608 609
			err = -EFAULT;
		break;

	case GET_VLAN_VID_CMD:
610
		err = 0;
611
		args.u.VID = vlan_dev_vlan_id(dev);
L
Linus Torvalds 已提交
612
		if (copy_to_user(arg, &args,
P
Patrick McHardy 已提交
613
				 sizeof(struct vlan_ioctl_args)))
614
		      err = -EFAULT;
L
Linus Torvalds 已提交
615 616 617
		break;

	default:
618
		err = -EOPNOTSUPP;
619
		break;
620
	}
621
out:
622
	rtnl_unlock();
L
Linus Torvalds 已提交
623 624 625
	return err;
}

626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666
static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
					 struct sk_buff *skb)
{
	struct sk_buff *p, **pp = NULL;
	struct vlan_hdr *vhdr;
	unsigned int hlen, off_vlan;
	const struct packet_offload *ptype;
	__be16 type;
	int flush = 1;

	off_vlan = skb_gro_offset(skb);
	hlen = off_vlan + sizeof(*vhdr);
	vhdr = skb_gro_header_fast(skb, off_vlan);
	if (skb_gro_header_hard(skb, hlen)) {
		vhdr = skb_gro_header_slow(skb, hlen, off_vlan);
		if (unlikely(!vhdr))
			goto out;
	}

	type = vhdr->h_vlan_encapsulated_proto;

	rcu_read_lock();
	ptype = gro_find_receive_by_type(type);
	if (!ptype)
		goto out_unlock;

	flush = 0;

	for (p = *head; p; p = p->next) {
		struct vlan_hdr *vhdr2;

		if (!NAPI_GRO_CB(p)->same_flow)
			continue;

		vhdr2 = (struct vlan_hdr *)(p->data + off_vlan);
		if (compare_vlan_header(vhdr, vhdr2))
			NAPI_GRO_CB(p)->same_flow = 0;
	}

	skb_gro_pull(skb, sizeof(*vhdr));
	skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
S
Sabrina Dubroca 已提交
667
	pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711

out_unlock:
	rcu_read_unlock();
out:
	NAPI_GRO_CB(skb)->flush |= flush;

	return pp;
}

static int vlan_gro_complete(struct sk_buff *skb, int nhoff)
{
	struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data + nhoff);
	__be16 type = vhdr->h_vlan_encapsulated_proto;
	struct packet_offload *ptype;
	int err = -ENOENT;

	rcu_read_lock();
	ptype = gro_find_complete_by_type(type);
	if (ptype)
		err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(*vhdr));

	rcu_read_unlock();
	return err;
}

static struct packet_offload vlan_packet_offloads[] __read_mostly = {
	{
		.type = cpu_to_be16(ETH_P_8021Q),
		.priority = 10,
		.callbacks = {
			.gro_receive = vlan_gro_receive,
			.gro_complete = vlan_gro_complete,
		},
	},
	{
		.type = cpu_to_be16(ETH_P_8021AD),
		.priority = 10,
		.callbacks = {
			.gro_receive = vlan_gro_receive,
			.gro_complete = vlan_gro_complete,
		},
	},
};

712
static int __net_init vlan_init_net(struct net *net)
713
{
714
	struct vlan_net *vn = net_generic(net, vlan_net_id);
715 716
	int err;

717 718
	vn->name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;

719 720
	err = vlan_proc_init(net);

721 722 723
	return err;
}

724
static void __net_exit vlan_exit_net(struct net *net)
725
{
726
	vlan_proc_cleanup(net);
727 728 729 730 731
}

static struct pernet_operations vlan_net_ops = {
	.init = vlan_init_net,
	.exit = vlan_exit_net,
732 733
	.id   = &vlan_net_id,
	.size = sizeof(struct vlan_net),
734 735
};

736 737 738
static int __init vlan_proto_init(void)
{
	int err;
739
	unsigned int i;
740

741
	pr_info("%s v%s\n", vlan_fullname, vlan_version);
742

743
	err = register_pernet_subsys(&vlan_net_ops);
744 745 746
	if (err < 0)
		goto err0;

747 748 749 750
	err = register_netdevice_notifier(&vlan_notifier_block);
	if (err < 0)
		goto err2;

P
Patrick McHardy 已提交
751
	err = vlan_gvrp_init();
752 753 754
	if (err < 0)
		goto err3;

755
	err = vlan_mvrp_init();
P
Patrick McHardy 已提交
756 757 758
	if (err < 0)
		goto err4;

759 760 761 762
	err = vlan_netlink_init();
	if (err < 0)
		goto err5;

763 764 765
	for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++)
		dev_add_offload(&vlan_packet_offloads[i]);

766 767 768
	vlan_ioctl_set(vlan_ioctl_handler);
	return 0;

769 770
err5:
	vlan_mvrp_uninit();
P
Patrick McHardy 已提交
771 772
err4:
	vlan_gvrp_uninit();
773 774 775
err3:
	unregister_netdevice_notifier(&vlan_notifier_block);
err2:
776
	unregister_pernet_subsys(&vlan_net_ops);
777
err0:
778 779 780 781 782
	return err;
}

static void __exit vlan_cleanup_module(void)
{
783 784
	unsigned int i;

785
	vlan_ioctl_set(NULL);
786 787 788 789

	for (i = 0; i < ARRAY_SIZE(vlan_packet_offloads); i++)
		dev_remove_offload(&vlan_packet_offloads[i]);

790 791 792 793
	vlan_netlink_fini();

	unregister_netdevice_notifier(&vlan_notifier_block);

794
	unregister_pernet_subsys(&vlan_net_ops);
795
	rcu_barrier(); /* Wait for completion of call_rcu()'s */
P
Patrick McHardy 已提交
796

797
	vlan_mvrp_uninit();
P
Patrick McHardy 已提交
798
	vlan_gvrp_uninit();
799 800 801 802 803
}

module_init(vlan_proto_init);
module_exit(vlan_cleanup_module);

L
Linus Torvalds 已提交
804 805
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);