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