xref: /freebsd/sys/net/if_vlan.c (revision c98323078dede7579020518ec84cdcb478e5c142)
1 /*
2  * Copyright 1998 Massachusetts Institute of Technology
3  *
4  * Permission to use, copy, modify, and distribute this software and
5  * its documentation for any purpose and without fee is hereby
6  * granted, provided that both the above copyright notice and this
7  * permission notice appear in all copies, that both the above
8  * copyright notice and this permission notice appear in all
9  * supporting documentation, and that the name of M.I.T. not be used
10  * in advertising or publicity pertaining to distribution of the
11  * software without specific, written prior permission.  M.I.T. makes
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied
14  * warranty.
15  *
16  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
17  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31 
32 /*
33  * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
34  * Might be extended some day to also handle IEEE 802.1p priority
35  * tagging.  This is sort of sneaky in the implementation, since
36  * we need to pretend to be enough of an Ethernet implementation
37  * to make arp work.  The way we do this is by telling everyone
38  * that we are an Ethernet, and then catch the packets that
39  * ether_output() left on our output queue when it calls
40  * if_start(), rewrite them for use by the real outgoing interface,
41  * and ask it to send them.
42  */
43 
44 #include "opt_inet.h"
45 
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/mbuf.h>
50 #include <sys/module.h>
51 #include <sys/queue.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54 #include <sys/sysctl.h>
55 #include <sys/systm.h>
56 
57 #include <net/bpf.h>
58 #include <net/ethernet.h>
59 #include <net/if.h>
60 #include <net/if_clone.h>
61 #include <net/if_arp.h>
62 #include <net/if_dl.h>
63 #include <net/if_types.h>
64 #include <net/if_vlan_var.h>
65 #include <net/route.h>
66 
67 #ifdef INET
68 #include <netinet/in.h>
69 #include <netinet/if_ether.h>
70 #endif
71 
72 #define VLANNAME	"vlan"
73 
74 struct vlan_mc_entry {
75 	struct ether_addr		mc_addr;
76 	SLIST_ENTRY(vlan_mc_entry)	mc_entries;
77 };
78 
79 struct	ifvlan {
80 	struct	arpcom ifv_ac;	/* make this an interface */
81 	struct	ifnet *ifv_p;	/* parent inteface of this vlan */
82 	struct	ifv_linkmib {
83 		int	ifvm_parent;
84 		int	ifvm_encaplen;	/* encapsulation length */
85 		int	ifvm_mtufudge;	/* MTU fudged by this much */
86 		int	ifvm_mintu;	/* min transmission unit */
87 		u_int16_t ifvm_proto; /* encapsulation ethertype */
88 		u_int16_t ifvm_tag; /* tag to apply on packets leaving if */
89 	}	ifv_mib;
90 	SLIST_HEAD(__vlan_mchead, vlan_mc_entry)	vlan_mc_listhead;
91 	LIST_ENTRY(ifvlan) ifv_list;
92 	int	ifv_flags;
93 };
94 #define	ifv_if	ifv_ac.ac_if
95 #define	ifv_tag	ifv_mib.ifvm_tag
96 #define	ifv_encaplen	ifv_mib.ifvm_encaplen
97 #define	ifv_mtufudge	ifv_mib.ifvm_mtufudge
98 #define	ifv_mintu	ifv_mib.ifvm_mintu
99 
100 #define	IFVF_PROMISC	0x01		/* promiscuous mode enabled */
101 
102 SYSCTL_DECL(_net_link);
103 SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN");
104 SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency");
105 
106 static MALLOC_DEFINE(M_VLAN, VLANNAME, "802.1Q Virtual LAN Interface");
107 static LIST_HEAD(, ifvlan) ifv_list;
108 
109 /*
110  * Locking: one lock is used to guard both the ifv_list and modification
111  * to vlan data structures.  We are rather conservative here; probably
112  * more than necessary.
113  */
114 static struct mtx ifv_mtx;
115 #define	VLAN_LOCK_INIT()	mtx_init(&ifv_mtx, VLANNAME, NULL, MTX_DEF)
116 #define	VLAN_LOCK_DESTROY()	mtx_destroy(&ifv_mtx)
117 #define	VLAN_LOCK_ASSERT()	mtx_assert(&ifv_mtx, MA_OWNED)
118 #define	VLAN_LOCK()	mtx_lock(&ifv_mtx)
119 #define	VLAN_UNLOCK()	mtx_unlock(&ifv_mtx)
120 
121 static	void vlan_start(struct ifnet *ifp);
122 static	void vlan_ifinit(void *foo);
123 static	void vlan_input(struct ifnet *ifp, struct mbuf *m);
124 static	int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
125 static	int vlan_setmulti(struct ifnet *ifp);
126 static	int vlan_unconfig(struct ifnet *ifp);
127 static	int vlan_config(struct ifvlan *ifv, struct ifnet *p);
128 static	void vlan_link_state(struct ifnet *ifp, int link);
129 static	int vlan_set_promisc(struct ifnet *ifp);
130 
131 static	struct ifnet *vlan_clone_match_ethertag(struct if_clone *,
132     const char *, int *);
133 static	int vlan_clone_match(struct if_clone *, const char *);
134 static	int vlan_clone_create(struct if_clone *, char *, size_t);
135 static	int vlan_clone_destroy(struct if_clone *, struct ifnet *);
136 
137 struct if_clone vlan_cloner = IFC_CLONE_INITIALIZER(VLANNAME, NULL, IF_MAXUNIT,
138     NULL, vlan_clone_match, vlan_clone_create, vlan_clone_destroy);
139 
140 /*
141  * Program our multicast filter. What we're actually doing is
142  * programming the multicast filter of the parent. This has the
143  * side effect of causing the parent interface to receive multicast
144  * traffic that it doesn't really want, which ends up being discarded
145  * later by the upper protocol layers. Unfortunately, there's no way
146  * to avoid this: there really is only one physical interface.
147  *
148  * XXX: There is a possible race here if more than one thread is
149  *      modifying the multicast state of the vlan interface at the same time.
150  */
151 static int
152 vlan_setmulti(struct ifnet *ifp)
153 {
154 	struct ifnet		*ifp_p;
155 	struct ifmultiaddr	*ifma, *rifma = NULL;
156 	struct ifvlan		*sc;
157 	struct vlan_mc_entry	*mc = NULL;
158 	struct sockaddr_dl	sdl;
159 	int			error;
160 
161 	/*VLAN_LOCK_ASSERT();*/
162 
163 	/* Find the parent. */
164 	sc = ifp->if_softc;
165 	ifp_p = sc->ifv_p;
166 
167 	/*
168 	 * If we don't have a parent, just remember the membership for
169 	 * when we do.
170 	 */
171 	if (ifp_p == NULL)
172 		return (0);
173 
174 	bzero((char *)&sdl, sizeof(sdl));
175 	sdl.sdl_len = sizeof(sdl);
176 	sdl.sdl_family = AF_LINK;
177 	sdl.sdl_index = ifp_p->if_index;
178 	sdl.sdl_type = IFT_ETHER;
179 	sdl.sdl_alen = ETHER_ADDR_LEN;
180 
181 	/* First, remove any existing filter entries. */
182 	while (SLIST_FIRST(&sc->vlan_mc_listhead) != NULL) {
183 		mc = SLIST_FIRST(&sc->vlan_mc_listhead);
184 		bcopy((char *)&mc->mc_addr, LLADDR(&sdl), ETHER_ADDR_LEN);
185 		error = if_delmulti(ifp_p, (struct sockaddr *)&sdl);
186 		if (error)
187 			return (error);
188 		SLIST_REMOVE_HEAD(&sc->vlan_mc_listhead, mc_entries);
189 		free(mc, M_VLAN);
190 	}
191 
192 	/* Now program new ones. */
193 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
194 		if (ifma->ifma_addr->sa_family != AF_LINK)
195 			continue;
196 		mc = malloc(sizeof(struct vlan_mc_entry), M_VLAN, M_NOWAIT);
197 		if (mc == NULL)
198 			return (ENOMEM);
199 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
200 		    (char *)&mc->mc_addr, ETHER_ADDR_LEN);
201 		SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries);
202 		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
203 		    LLADDR(&sdl), ETHER_ADDR_LEN);
204 		error = if_addmulti(ifp_p, (struct sockaddr *)&sdl, &rifma);
205 		if (error)
206 			return (error);
207 	}
208 
209 	return (0);
210 }
211 
212 /*
213  * VLAN support can be loaded as a module.  The only place in the
214  * system that's intimately aware of this is ether_input.  We hook
215  * into this code through vlan_input_p which is defined there and
216  * set here.  Noone else in the system should be aware of this so
217  * we use an explicit reference here.
218  *
219  * NB: Noone should ever need to check if vlan_input_p is null or
220  *     not.  This is because interfaces have a count of the number
221  *     of active vlans (if_nvlans) and this should never be bumped
222  *     except by vlan_config--which is in this module so therefore
223  *     the module must be loaded and vlan_input_p must be non-NULL.
224  */
225 extern	void (*vlan_input_p)(struct ifnet *, struct mbuf *);
226 
227 /* For MII eyes only... */
228 extern	void (*vlan_link_state_p)(struct ifnet *, int);
229 
230 static int
231 vlan_modevent(module_t mod, int type, void *data)
232 {
233 
234 	switch (type) {
235 	case MOD_LOAD:
236 		LIST_INIT(&ifv_list);
237 		VLAN_LOCK_INIT();
238 		vlan_input_p = vlan_input;
239 		vlan_link_state_p = vlan_link_state;
240 		if_clone_attach(&vlan_cloner);
241 		break;
242 	case MOD_UNLOAD:
243 		if_clone_detach(&vlan_cloner);
244 		vlan_input_p = NULL;
245 		vlan_link_state_p = NULL;
246 		while (!LIST_EMPTY(&ifv_list))
247 			vlan_clone_destroy(&vlan_cloner,
248 			    &LIST_FIRST(&ifv_list)->ifv_if);
249 		VLAN_LOCK_DESTROY();
250 		break;
251 	default:
252 		return (EOPNOTSUPP);
253 	}
254 	return (0);
255 }
256 
257 static moduledata_t vlan_mod = {
258 	"if_vlan",
259 	vlan_modevent,
260 	0
261 };
262 
263 DECLARE_MODULE(if_vlan, vlan_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
264 MODULE_DEPEND(if_vlan, miibus, 1, 1, 1);
265 
266 static struct ifnet *
267 vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag)
268 {
269 	const char *cp;
270 	struct ifnet *ifp;
271 	int t = 0;
272 
273 	/* Check for <etherif>.<vlan> style interface names. */
274 	IFNET_RLOCK();
275 	TAILQ_FOREACH(ifp, &ifnet, if_link) {
276 		if (ifp->if_type != IFT_ETHER)
277 			continue;
278 		if (strncmp(ifp->if_xname, name, strlen(ifp->if_xname)) != 0)
279 			continue;
280 		cp = name + strlen(ifp->if_xname);
281 		if (*cp != '.')
282 			continue;
283 		for(; *cp != '\0'; cp++) {
284 			if (*cp < '0' || *cp > '9')
285 				continue;
286 			t = (t * 10) + (*cp - '0');
287 		}
288 		if (tag != NULL)
289 			*tag = t;
290 		break;
291 	}
292 	IFNET_RUNLOCK();
293 
294 	return (ifp);
295 }
296 
297 static int
298 vlan_clone_match(struct if_clone *ifc, const char *name)
299 {
300 	const char *cp;
301 
302 	if (vlan_clone_match_ethertag(ifc, name, NULL) != NULL)
303 		return (1);
304 
305 	if (strncmp(VLANNAME, name, strlen(VLANNAME)) != 0)
306 		return (0);
307 	for (cp = name + 4; *cp != '\0'; cp++) {
308 		if (*cp < '0' || *cp > '9')
309 			return (0);
310 	}
311 
312 	return (1);
313 }
314 
315 static int
316 vlan_clone_create(struct if_clone *ifc, char *name, size_t len)
317 {
318 	char *dp;
319 	int wildcard;
320 	int unit;
321 	int error;
322 	int tag;
323 	int ethertag;
324 	struct ifvlan *ifv;
325 	struct ifnet *ifp;
326 	struct ifnet *p;
327 
328 	if ((p = vlan_clone_match_ethertag(ifc, name, &tag)) != NULL) {
329 		ethertag = 1;
330 		unit = -1;
331 		wildcard = 0;
332 
333 		/*
334 		 * Don't let the caller set up a VLAN tag with
335 		 * anything except VLID bits.
336 		 */
337 		if (tag & ~EVL_VLID_MASK)
338 			return (EINVAL);
339 	} else {
340 		ethertag = 0;
341 
342 		error = ifc_name2unit(name, &unit);
343 		if (error != 0)
344 			return (error);
345 
346 		wildcard = (unit < 0);
347 	}
348 
349 	error = ifc_alloc_unit(ifc, &unit);
350 	if (error != 0)
351 		return (error);
352 
353 	/* In the wildcard case, we need to update the name. */
354 	if (wildcard) {
355 		for (dp = name; *dp != '\0'; dp++);
356 		if (snprintf(dp, len - (dp-name), "%d", unit) >
357 		    len - (dp-name) - 1) {
358 			panic("%s: interface name too long", __func__);
359 		}
360 	}
361 
362 	ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO);
363 	ifp = &ifv->ifv_if;
364 	SLIST_INIT(&ifv->vlan_mc_listhead);
365 
366 	ifp->if_softc = ifv;
367 	/*
368 	 * Set the name manually rather then using if_initname because
369 	 * we don't conform to the default naming convention for interfaces.
370 	 */
371 	strlcpy(ifp->if_xname, name, IFNAMSIZ);
372 	ifp->if_dname = ifc->ifc_name;
373 	ifp->if_dunit = unit;
374 	/* NB: flags are not set here */
375 	ifp->if_linkmib = &ifv->ifv_mib;
376 	ifp->if_linkmiblen = sizeof(ifv->ifv_mib);
377 	/* NB: mtu is not set here */
378 
379 	ifp->if_init = vlan_ifinit;
380 	ifp->if_start = vlan_start;
381 	ifp->if_ioctl = vlan_ioctl;
382 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
383 	ether_ifattach(ifp, ifv->ifv_ac.ac_enaddr);
384 	/* Now undo some of the damage... */
385 	ifp->if_baudrate = 0;
386 	ifp->if_type = IFT_L2VLAN;
387 	ifp->if_hdrlen = ETHER_VLAN_ENCAP_LEN;
388 
389 	VLAN_LOCK();
390 	LIST_INSERT_HEAD(&ifv_list, ifv, ifv_list);
391 	VLAN_UNLOCK();
392 
393 	if (ethertag) {
394 		VLAN_LOCK();
395 		error = vlan_config(ifv, p);
396 		if (error != 0) {
397 			/*
398 			 * Since we've partialy failed, we need to back
399 			 * out all the way, otherwise userland could get
400 			 * confused.  Thus, we destroy the interface.
401 			 */
402 			LIST_REMOVE(ifv, ifv_list);
403 			vlan_unconfig(ifp);
404 			VLAN_UNLOCK();
405 			ether_ifdetach(ifp);
406 			free(ifv, M_VLAN);
407 
408 			return (error);
409 		}
410 		ifv->ifv_tag = tag;
411 		ifp->if_flags |= IFF_RUNNING;
412 		VLAN_UNLOCK();
413 
414 		/* Update promiscuous mode, if necessary. */
415 		vlan_set_promisc(ifp);
416 	}
417 
418 	return (0);
419 }
420 
421 static int
422 vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
423 {
424 	struct ifvlan *ifv = ifp->if_softc;
425 
426 	VLAN_LOCK();
427 	LIST_REMOVE(ifv, ifv_list);
428 	vlan_unconfig(ifp);
429 	VLAN_UNLOCK();
430 
431 	ether_ifdetach(ifp);
432 
433 	free(ifv, M_VLAN);
434 
435 	return (0);
436 }
437 
438 /*
439  * The ifp->if_init entry point for vlan(4) is a no-op.
440  */
441 static void
442 vlan_ifinit(void *foo)
443 {
444 
445 }
446 
447 static void
448 vlan_start(struct ifnet *ifp)
449 {
450 	struct ifvlan *ifv;
451 	struct ifnet *p;
452 	struct ether_vlan_header *evl;
453 	struct mbuf *m;
454 	int error;
455 
456 	ifv = ifp->if_softc;
457 	p = ifv->ifv_p;
458 
459 	ifp->if_flags |= IFF_OACTIVE;
460 	for (;;) {
461 		IF_DEQUEUE(&ifp->if_snd, m);
462 		if (m == 0)
463 			break;
464 		BPF_MTAP(ifp, m);
465 
466 		/*
467 		 * Do not run parent's if_start() if the parent is not up,
468 		 * or parent's driver will cause a system crash.
469 		 */
470 		if ((p->if_flags & (IFF_UP | IFF_RUNNING)) !=
471 					(IFF_UP | IFF_RUNNING)) {
472 			m_freem(m);
473 			ifp->if_collisions++;
474 			continue;
475 		}
476 
477 		/*
478 		 * If underlying interface can do VLAN tag insertion itself,
479 		 * just pass the packet along. However, we need some way to
480 		 * tell the interface where the packet came from so that it
481 		 * knows how to find the VLAN tag to use, so we attach a
482 		 * packet tag that holds it.
483 		 */
484 		if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
485 			struct m_tag *mtag = m_tag_alloc(MTAG_VLAN,
486 							 MTAG_VLAN_TAG,
487 							 sizeof(u_int),
488 							 M_NOWAIT);
489 			if (mtag == NULL) {
490 				ifp->if_oerrors++;
491 				m_freem(m);
492 				continue;
493 			}
494 			*(u_int*)(mtag + 1) = ifv->ifv_tag;
495 			m_tag_prepend(m, mtag);
496 		} else {
497 			M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT);
498 			if (m == NULL) {
499 				if_printf(ifp,
500 				    "unable to prepend VLAN header\n");
501 				ifp->if_oerrors++;
502 				continue;
503 			}
504 			/* M_PREPEND takes care of m_len, m_pkthdr.len for us */
505 
506 			if (m->m_len < sizeof(*evl)) {
507 				m = m_pullup(m, sizeof(*evl));
508 				if (m == NULL) {
509 					if_printf(ifp,
510 					    "cannot pullup VLAN header\n");
511 					ifp->if_oerrors++;
512 					continue;
513 				}
514 			}
515 
516 			/*
517 			 * Transform the Ethernet header into an Ethernet header
518 			 * with 802.1Q encapsulation.
519 			 */
520 			bcopy(mtod(m, char *) + ifv->ifv_encaplen,
521 			      mtod(m, char *), ETHER_HDR_LEN);
522 			evl = mtod(m, struct ether_vlan_header *);
523 			evl->evl_proto = evl->evl_encap_proto;
524 			evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
525 			evl->evl_tag = htons(ifv->ifv_tag);
526 #ifdef DEBUG
527 			printf("vlan_start: %*D\n", (int)sizeof(*evl),
528 			    (unsigned char *)evl, ":");
529 #endif
530 		}
531 
532 		/*
533 		 * Send it, precisely as ether_output() would have.
534 		 * We are already running at splimp.
535 		 */
536 		IFQ_HANDOFF(p, m, error);
537 		if (!error)
538 			ifp->if_opackets++;
539 		else
540 			ifp->if_oerrors++;
541 	}
542 	ifp->if_flags &= ~IFF_OACTIVE;
543 }
544 
545 static void
546 vlan_input(struct ifnet *ifp, struct mbuf *m)
547 {
548 	struct ether_vlan_header *evl;
549 	struct ifvlan *ifv;
550 	struct m_tag *mtag;
551 	u_int tag;
552 
553 	mtag = m_tag_locate(m, MTAG_VLAN, MTAG_VLAN_TAG, NULL);
554 	if (mtag != NULL) {
555 		/*
556 		 * Packet is tagged, m contains a normal
557 		 * Ethernet frame; the tag is stored out-of-band.
558 		 */
559 		tag = EVL_VLANOFTAG(VLAN_TAG_VALUE(mtag));
560 		m_tag_delete(m, mtag);
561 	} else {
562 		switch (ifp->if_type) {
563 		case IFT_ETHER:
564 			if (m->m_len < sizeof(*evl) &&
565 			    (m = m_pullup(m, sizeof(*evl))) == NULL) {
566 				if_printf(ifp, "cannot pullup VLAN header\n");
567 				return;
568 			}
569 			evl = mtod(m, struct ether_vlan_header *);
570 			KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN,
571 				("vlan_input: bad encapsulated protocols (%u)",
572 				 ntohs(evl->evl_encap_proto)));
573 
574 			tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
575 
576 			/*
577 			 * Restore the original ethertype.  We'll remove
578 			 * the encapsulation after we've found the vlan
579 			 * interface corresponding to the tag.
580 			 */
581 			evl->evl_encap_proto = evl->evl_proto;
582 			break;
583 		default:
584 			tag = (u_int) -1;
585 #ifdef DIAGNOSTIC
586 			panic("vlan_input: unsupported if type %u",
587 			    ifp->if_type);
588 #endif
589 			break;
590 		}
591 	}
592 
593 	VLAN_LOCK();
594 	LIST_FOREACH(ifv, &ifv_list, ifv_list)
595 		if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
596 			break;
597 
598 	if (ifv == NULL || (ifv->ifv_if.if_flags & IFF_UP) == 0) {
599 		VLAN_UNLOCK();
600 		m_freem(m);
601 		ifp->if_noproto++;
602 #ifdef DEBUG
603 		printf("vlan_input: tag %d, no interface\n", tag);
604 #endif
605 		return;
606 	}
607 	VLAN_UNLOCK();		/* XXX extend below? */
608 #ifdef DEBUG
609 	printf("vlan_input: tag %d, parent %s\n", tag, ifv->ifv_p->if_xname);
610 #endif
611 
612 	if (mtag == NULL) {
613 		/*
614 		 * Packet had an in-line encapsulation header;
615 		 * remove it.  The original header has already
616 		 * been fixed up above.
617 		 */
618 		bcopy(mtod(m, caddr_t),
619 		      mtod(m, caddr_t) + ETHER_VLAN_ENCAP_LEN,
620 		      ETHER_HDR_LEN);
621 		m_adj(m, ETHER_VLAN_ENCAP_LEN);
622 	}
623 
624 	m->m_pkthdr.rcvif = &ifv->ifv_if;
625 	ifv->ifv_if.if_ipackets++;
626 
627 	/* Pass it back through the parent's input routine. */
628 	(*ifp->if_input)(&ifv->ifv_if, m);
629 }
630 
631 static int
632 vlan_config(struct ifvlan *ifv, struct ifnet *p)
633 {
634 	struct ifaddr *ifa1, *ifa2;
635 	struct sockaddr_dl *sdl1, *sdl2;
636 
637 	VLAN_LOCK_ASSERT();
638 
639 	if (p->if_data.ifi_type != IFT_ETHER)
640 		return (EPROTONOSUPPORT);
641 	if (ifv->ifv_p)
642 		return (EBUSY);
643 
644 	ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN;
645 	ifv->ifv_mintu = ETHERMIN;
646 	ifv->ifv_flags = 0;
647 
648 	/*
649 	 * If the parent supports the VLAN_MTU capability,
650 	 * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames,
651 	 * use it.
652 	 * First of all, enable Tx/Rx of such extended frames on the
653 	 * parent if it's disabled and we're the first to attach.
654 	 */
655 	p->if_nvlans++;
656 	if (p->if_nvlans == 1 &&
657 	    (p->if_capabilities & IFCAP_VLAN_MTU) &&
658 	    (p->if_capenable & IFCAP_VLAN_MTU) == 0) {
659 		struct ifreq ifr;
660 		int error;
661 
662 		ifr.ifr_reqcap = p->if_capenable | IFCAP_VLAN_MTU;
663 		error = (*p->if_ioctl)(p, SIOCSIFCAP, (caddr_t) &ifr);
664 		if (error) {
665 			p->if_nvlans--;
666 			return (error);
667 		}
668 	}
669 	if (p->if_capenable & IFCAP_VLAN_MTU) {
670 		/*
671 		 * No need to fudge the MTU since the parent can
672 		 * handle extended frames.
673 		 */
674 		ifv->ifv_mtufudge = 0;
675 	} else {
676 		/*
677 		 * Fudge the MTU by the encapsulation size.  This
678 		 * makes us incompatible with strictly compliant
679 		 * 802.1Q implementations, but allows us to use
680 		 * the feature with other NetBSD implementations,
681 		 * which might still be useful.
682 		 */
683 		ifv->ifv_mtufudge = ifv->ifv_encaplen;
684 	}
685 
686 	ifv->ifv_p = p;
687 	ifv->ifv_if.if_mtu = p->if_mtu - ifv->ifv_mtufudge;
688 	/*
689 	 * Copy only a selected subset of flags from the parent.
690 	 * Other flags are none of our business.
691 	 */
692 	ifv->ifv_if.if_flags = (p->if_flags &
693 	    (IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX | IFF_POINTOPOINT));
694 	ifv->ifv_if.if_link_state = p->if_link_state;
695 
696 #if 0
697 	/*
698 	 * Not ready yet.  We need notification from the parent
699 	 * when hw checksumming flags in its if_capenable change.
700 	 * Flags set in if_capabilities only are useless.
701 	 */
702 	/*
703 	 * If the parent interface can do hardware-assisted
704 	 * VLAN encapsulation, then propagate its hardware-
705 	 * assisted checksumming flags.
706 	 */
707 	if (p->if_capabilities & IFCAP_VLAN_HWTAGGING)
708 		ifv->ifv_if.if_capabilities |= p->if_capabilities & IFCAP_HWCSUM;
709 #endif
710 
711 	/*
712 	 * Set up our ``Ethernet address'' to reflect the underlying
713 	 * physical interface's.
714 	 */
715 	ifa1 = ifaddr_byindex(ifv->ifv_if.if_index);
716 	ifa2 = ifaddr_byindex(p->if_index);
717 	sdl1 = (struct sockaddr_dl *)ifa1->ifa_addr;
718 	sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr;
719 	sdl1->sdl_type = IFT_ETHER;
720 	sdl1->sdl_alen = ETHER_ADDR_LEN;
721 	bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN);
722 	bcopy(LLADDR(sdl2), ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
723 
724 	/*
725 	 * Configure multicast addresses that may already be
726 	 * joined on the vlan device.
727 	 */
728 	(void)vlan_setmulti(&ifv->ifv_if); /* XXX: VLAN lock held */
729 
730 	return (0);
731 }
732 
733 static int
734 vlan_unconfig(struct ifnet *ifp)
735 {
736 	struct ifaddr *ifa;
737 	struct sockaddr_dl *sdl;
738 	struct vlan_mc_entry *mc;
739 	struct ifvlan *ifv;
740 	struct ifnet *p;
741 	int error;
742 
743 	VLAN_LOCK_ASSERT();
744 
745 	ifv = ifp->if_softc;
746 	p = ifv->ifv_p;
747 
748 	if (p) {
749 		struct sockaddr_dl sdl;
750 
751 		/*
752 		 * Since the interface is being unconfigured, we need to
753 		 * empty the list of multicast groups that we may have joined
754 		 * while we were alive from the parent's list.
755 		 */
756 		bzero((char *)&sdl, sizeof(sdl));
757 		sdl.sdl_len = sizeof(sdl);
758 		sdl.sdl_family = AF_LINK;
759 		sdl.sdl_index = p->if_index;
760 		sdl.sdl_type = IFT_ETHER;
761 		sdl.sdl_alen = ETHER_ADDR_LEN;
762 
763 		while(SLIST_FIRST(&ifv->vlan_mc_listhead) != NULL) {
764 			mc = SLIST_FIRST(&ifv->vlan_mc_listhead);
765 			bcopy((char *)&mc->mc_addr, LLADDR(&sdl),
766 			    ETHER_ADDR_LEN);
767 			error = if_delmulti(p, (struct sockaddr *)&sdl);
768 			if (error)
769 				return (error);
770 			SLIST_REMOVE_HEAD(&ifv->vlan_mc_listhead, mc_entries);
771 			free(mc, M_VLAN);
772 		}
773 
774 		p->if_nvlans--;
775 		if (p->if_nvlans == 0) {
776 			struct ifreq ifr;
777 
778 			/*
779 			 * Try to disable Tx/Rx of VLAN-sized frames.
780 			 * This may have no effect for some interfaces,
781 			 * but only the parent driver knows that.
782 			 */
783 			ifr.ifr_reqcap = p->if_capenable & ~IFCAP_VLAN_MTU;
784 			(*p->if_ioctl)(p, SIOCSIFCAP, (caddr_t) &ifr);
785 		}
786 	}
787 
788 	/* Disconnect from parent. */
789 	ifv->ifv_p = NULL;
790 	ifv->ifv_if.if_mtu = ETHERMTU;		/* XXX why not 0? */
791 	ifv->ifv_flags = 0;
792 	ifv->ifv_if.if_link_state = LINK_STATE_UNKNOWN;
793 
794 	/* Clear our MAC address. */
795 	ifa = ifaddr_byindex(ifv->ifv_if.if_index);
796 	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
797 	sdl->sdl_type = IFT_ETHER;
798 	sdl->sdl_alen = ETHER_ADDR_LEN;
799 	bzero(LLADDR(sdl), ETHER_ADDR_LEN);
800 	bzero(ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
801 
802 	return (0);
803 }
804 
805 static int
806 vlan_set_promisc(struct ifnet *ifp)
807 {
808 	struct ifvlan *ifv = ifp->if_softc;
809 	int error = 0;
810 
811 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
812 		if ((ifv->ifv_flags & IFVF_PROMISC) == 0) {
813 			error = ifpromisc(ifv->ifv_p, 1);
814 			if (error == 0)
815 				ifv->ifv_flags |= IFVF_PROMISC;
816 		}
817 	} else {
818 		if ((ifv->ifv_flags & IFVF_PROMISC) != 0) {
819 			error = ifpromisc(ifv->ifv_p, 0);
820 			if (error == 0)
821 				ifv->ifv_flags &= ~IFVF_PROMISC;
822 		}
823 	}
824 
825 	return (error);
826 }
827 
828 /* Inform all vlans that their parent has changed link state */
829 static void
830 vlan_link_state(struct ifnet *ifp, int link)
831 {
832 	struct ifvlan *ifv;
833 
834 	VLAN_LOCK();
835 	LIST_FOREACH(ifv, &ifv_list, ifv_list) {
836 		if (ifv->ifv_p == ifp) {
837 			ifv->ifv_if.if_link_state = ifv->ifv_p->if_link_state;
838 			rt_ifmsg(&(ifv->ifv_if));
839 			KNOTE(&ifp->if_klist, link);
840 		}
841 	}
842 	VLAN_UNLOCK();
843 }
844 
845 static int
846 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
847 {
848 	struct ifaddr *ifa;
849 	struct ifnet *p;
850 	struct ifreq *ifr;
851 	struct ifvlan *ifv;
852 	struct vlanreq vlr;
853 	int error = 0;
854 
855 	ifr = (struct ifreq *)data;
856 	ifa = (struct ifaddr *)data;
857 	ifv = ifp->if_softc;
858 
859 	switch (cmd) {
860 	case SIOCSIFADDR:
861 		ifp->if_flags |= IFF_UP;
862 
863 		switch (ifa->ifa_addr->sa_family) {
864 #ifdef INET
865 		case AF_INET:
866 			arp_ifinit(&ifv->ifv_if, ifa);
867 			break;
868 #endif
869 		default:
870 			break;
871 		}
872 		break;
873 
874 	case SIOCGIFADDR:
875 		{
876 			struct sockaddr *sa;
877 
878 			sa = (struct sockaddr *) &ifr->ifr_data;
879 			bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t)sa->sa_data,
880 			    ETHER_ADDR_LEN);
881 		}
882 		break;
883 
884 	case SIOCGIFMEDIA:
885 		VLAN_LOCK();
886 		if (ifv->ifv_p != NULL) {
887 			error = (*ifv->ifv_p->if_ioctl)(ifv->ifv_p,
888 					SIOCGIFMEDIA, data);
889 			VLAN_UNLOCK();
890 			/* Limit the result to the parent's current config. */
891 			if (error == 0) {
892 				struct ifmediareq *ifmr;
893 
894 				ifmr = (struct ifmediareq *)data;
895 				if (ifmr->ifm_count >= 1 && ifmr->ifm_ulist) {
896 					ifmr->ifm_count = 1;
897 					error = copyout(&ifmr->ifm_current,
898 						ifmr->ifm_ulist,
899 						sizeof(int));
900 				}
901 			}
902 		} else {
903 			VLAN_UNLOCK();
904 			error = EINVAL;
905 		}
906 		break;
907 
908 	case SIOCSIFMEDIA:
909 		error = EINVAL;
910 		break;
911 
912 	case SIOCSIFMTU:
913 		/*
914 		 * Set the interface MTU.
915 		 */
916 		VLAN_LOCK();
917 		if (ifv->ifv_p != NULL) {
918 			if (ifr->ifr_mtu >
919 			     (ifv->ifv_p->if_mtu - ifv->ifv_mtufudge) ||
920 			    ifr->ifr_mtu <
921 			     (ifv->ifv_mintu - ifv->ifv_mtufudge))
922 				error = EINVAL;
923 			else
924 				ifp->if_mtu = ifr->ifr_mtu;
925 		} else
926 			error = EINVAL;
927 		VLAN_UNLOCK();
928 		break;
929 
930 	case SIOCSETVLAN:
931 		error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
932 		if (error)
933 			break;
934 		if (vlr.vlr_parent[0] == '\0') {
935 			VLAN_LOCK();
936 			vlan_unconfig(ifp);
937 			if (ifp->if_flags & IFF_UP)
938 				if_down(ifp);
939 			ifp->if_flags &= ~IFF_RUNNING;
940 			VLAN_UNLOCK();
941 			break;
942 		}
943 		p = ifunit(vlr.vlr_parent);
944 		if (p == 0) {
945 			error = ENOENT;
946 			break;
947 		}
948 		/*
949 		 * Don't let the caller set up a VLAN tag with
950 		 * anything except VLID bits.
951 		 */
952 		if (vlr.vlr_tag & ~EVL_VLID_MASK) {
953 			error = EINVAL;
954 			break;
955 		}
956 		VLAN_LOCK();
957 		error = vlan_config(ifv, p);
958 		if (error) {
959 			VLAN_UNLOCK();
960 			break;
961 		}
962 		ifv->ifv_tag = vlr.vlr_tag;
963 		ifp->if_flags |= IFF_RUNNING;
964 		VLAN_UNLOCK();
965 
966 		/* Update promiscuous mode, if necessary. */
967 		vlan_set_promisc(ifp);
968 		break;
969 
970 	case SIOCGETVLAN:
971 		bzero(&vlr, sizeof(vlr));
972 		VLAN_LOCK();
973 		if (ifv->ifv_p) {
974 			strlcpy(vlr.vlr_parent, ifv->ifv_p->if_xname,
975 			    sizeof(vlr.vlr_parent));
976 			vlr.vlr_tag = ifv->ifv_tag;
977 		}
978 		VLAN_UNLOCK();
979 		error = copyout(&vlr, ifr->ifr_data, sizeof(vlr));
980 		break;
981 
982 	case SIOCSIFFLAGS:
983 		/*
984 		 * For promiscuous mode, we enable promiscuous mode on
985 		 * the parent if we need promiscuous on the VLAN interface.
986 		 */
987 		if (ifv->ifv_p != NULL)
988 			error = vlan_set_promisc(ifp);
989 		break;
990 
991 	case SIOCADDMULTI:
992 	case SIOCDELMULTI:
993 		/*VLAN_LOCK();*/
994 		error = vlan_setmulti(ifp);
995 		/*VLAN_UNLOCK();*/
996 		break;
997 	default:
998 		error = EINVAL;
999 	}
1000 
1001 	return (error);
1002 }
1003