xref: /openbsd-src/sys/net/if_vlan.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*	$OpenBSD: if_vlan.c,v 1.165 2016/05/18 03:46:03 dlg Exp $	*/
2 
3 /*
4  * Copyright 1998 Massachusetts Institute of Technology
5  *
6  * Permission to use, copy, modify, and distribute this software and
7  * its documentation for any purpose and without fee is hereby
8  * granted, provided that both the above copyright notice and this
9  * permission notice appear in all copies, that both the above
10  * copyright notice and this permission notice appear in all
11  * supporting documentation, and that the name of M.I.T. not be used
12  * in advertising or publicity pertaining to distribution of the
13  * software without specific, written prior permission.  M.I.T. makes
14  * no representations about the suitability of this software for any
15  * purpose.  It is provided "as is" without express or implied
16  * warranty.
17  *
18  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
19  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
22  * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/net/if_vlan.c,v 1.16 2000/03/26 15:21:40 charnier Exp $
32  */
33 
34 /*
35  * if_vlan.c - pseudo-device driver for IEEE 802.1Q virtual LANs.
36  * This is sort of sneaky in the implementation, since
37  * we need to pretend to be enough of an Ethernet implementation
38  * to make arp work.  The way we do this is by telling everyone
39  * that we are an Ethernet, and then catch the packets that
40  * ether_output() left on our output queue when it calls
41  * if_start(), rewrite them for use by the real outgoing interface,
42  * and ask it to send them.
43  *
44  * Some devices support 802.1Q tag insertion in firmware.  The
45  * vlan interface behavior changes when the IFCAP_VLAN_HWTAGGING
46  * capability is set on the parent.  In this case, vlan_start()
47  * will not modify the ethernet header.
48  */
49 
50 #include "mpw.h"
51 
52 #include <sys/param.h>
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 #include <sys/mbuf.h>
56 #include <sys/queue.h>
57 #include <sys/socket.h>
58 #include <sys/sockio.h>
59 #include <sys/systm.h>
60 #include <sys/rwlock.h>
61 
62 #include <net/if.h>
63 #include <net/if_dl.h>
64 #include <net/if_types.h>
65 
66 #include <netinet/in.h>
67 #include <netinet/if_ether.h>
68 
69 #include <net/if_vlan_var.h>
70 
71 #include "bpfilter.h"
72 #if NBPFILTER > 0
73 #include <net/bpf.h>
74 #endif
75 
76 #define TAG_HASH_BITS		5
77 #define TAG_HASH_SIZE		(1 << TAG_HASH_BITS)
78 #define TAG_HASH_MASK		(TAG_HASH_SIZE - 1)
79 #define TAG_HASH(tag)		(tag & TAG_HASH_MASK)
80 SRPL_HEAD(, ifvlan) *vlan_tagh, *svlan_tagh;
81 struct rwlock vlan_tagh_lk = RWLOCK_INITIALIZER("vlantag");
82 
83 void	vlanattach(int count);
84 int	vlan_clone_create(struct if_clone *, int);
85 int	vlan_clone_destroy(struct ifnet *);
86 
87 int	vlan_input(struct ifnet *, struct mbuf *, void *);
88 void	vlan_start(struct ifnet *ifp);
89 int	vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
90 
91 int	vlan_up(struct ifvlan *);
92 int	vlan_parent_up(struct ifvlan *, struct ifnet *);
93 int	vlan_down(struct ifvlan *);
94 
95 void	vlan_ifdetach(void *);
96 void	vlan_link_hook(void *);
97 void	vlan_link_state(struct ifvlan *, u_char, u_int64_t);
98 
99 int	vlan_set_vnetid(struct ifvlan *, uint16_t);
100 int	vlan_inuse(uint16_t, unsigned int, uint16_t);
101 int	vlan_inuse_locked(uint16_t, unsigned int, uint16_t);
102 
103 int	vlan_multi_add(struct ifvlan *, struct ifreq *);
104 int	vlan_multi_del(struct ifvlan *, struct ifreq *);
105 void	vlan_multi_apply(struct ifvlan *, struct ifnet *, u_long);
106 void	vlan_multi_free(struct ifvlan *);
107 
108 int	vlan_iff(struct ifvlan *);
109 int	vlan_setlladdr(struct ifvlan *, struct ifreq *);
110 
111 int	vlan_set_compat(struct ifnet *, struct ifreq *);
112 int	vlan_get_compat(struct ifnet *, struct ifreq *);
113 
114 struct if_clone vlan_cloner =
115     IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
116 struct if_clone svlan_cloner =
117     IF_CLONE_INITIALIZER("svlan", vlan_clone_create, vlan_clone_destroy);
118 
119 void vlan_ref(void *, void *);
120 void vlan_unref(void *, void *);
121 
122 struct srpl_rc vlan_tagh_rc = SRPL_RC_INITIALIZER(vlan_ref, vlan_unref, NULL);
123 
124 void
125 vlanattach(int count)
126 {
127 	u_int i;
128 
129 	/* Normal VLAN */
130 	vlan_tagh = mallocarray(TAG_HASH_SIZE, sizeof(*vlan_tagh),
131 	    M_DEVBUF, M_NOWAIT);
132 	if (vlan_tagh == NULL)
133 		panic("vlanattach: hashinit");
134 
135 	/* Service-VLAN for QinQ/802.1ad provider bridges */
136 	svlan_tagh = mallocarray(TAG_HASH_SIZE, sizeof(*svlan_tagh),
137 	    M_DEVBUF, M_NOWAIT);
138 	if (svlan_tagh == NULL)
139 		panic("vlanattach: hashinit");
140 
141 	for (i = 0; i < TAG_HASH_SIZE; i++) {
142 		SRPL_INIT(&vlan_tagh[i]);
143 		SRPL_INIT(&svlan_tagh[i]);
144 	}
145 
146 	if_clone_attach(&vlan_cloner);
147 	if_clone_attach(&svlan_cloner);
148 }
149 
150 int
151 vlan_clone_create(struct if_clone *ifc, int unit)
152 {
153 	struct ifvlan	*ifv;
154 	struct ifnet	*ifp;
155 
156 	ifv = malloc(sizeof(*ifv), M_DEVBUF, M_NOWAIT|M_ZERO);
157 	if (ifv == NULL)
158 		return (ENOMEM);
159 
160 	LIST_INIT(&ifv->vlan_mc_listhead);
161 	ifp = &ifv->ifv_if;
162 	ifp->if_softc = ifv;
163 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
164 	    unit);
165 	/* NB: flags are not set here */
166 	/* NB: mtu is not set here */
167 
168 	/* Special handling for the IEEE 802.1ad QinQ variant */
169 	if (strcmp("svlan", ifc->ifc_name) == 0)
170 		ifv->ifv_type = ETHERTYPE_QINQ;
171 	else
172 		ifv->ifv_type = ETHERTYPE_VLAN;
173 
174 	refcnt_init(&ifv->ifv_refcnt);
175 
176 	ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
177 	ifp->if_xflags = IFXF_MPSAFE;
178 	ifp->if_start = vlan_start;
179 	ifp->if_ioctl = vlan_ioctl;
180 	ifp->if_hardmtu = 0xffff;
181 	ifp->if_link_state = LINK_STATE_DOWN;
182 	if_attach(ifp);
183 	ether_ifattach(ifp);
184 	ifp->if_hdrlen = EVL_ENCAPLEN;
185 
186 	return (0);
187 }
188 
189 void
190 vlan_ref(void *null, void *v)
191 {
192 	struct ifvlan *ifv = v;
193 
194 	refcnt_take(&ifv->ifv_refcnt);
195 }
196 
197 void
198 vlan_unref(void *null, void *v)
199 {
200 	struct ifvlan *ifv = v;
201 
202 	refcnt_rele_wake(&ifv->ifv_refcnt);
203 }
204 
205 int
206 vlan_clone_destroy(struct ifnet *ifp)
207 {
208 	struct ifvlan	*ifv = ifp->if_softc;
209 
210 	if (ISSET(ifp->if_flags, IFF_RUNNING))
211 		vlan_down(ifv);
212 
213 	ether_ifdetach(ifp);
214 	if_detach(ifp);
215 	refcnt_finalize(&ifv->ifv_refcnt, "vlanrefs");
216 	vlan_multi_free(ifv);
217 	free(ifv, M_DEVBUF, sizeof(*ifv));
218 
219 	return (0);
220 }
221 
222 static inline int
223 vlan_mplstunnel(int ifidx)
224 {
225 #if NMPW > 0
226 	struct ifnet *ifp;
227 	int rv = 0;
228 
229 	ifp = if_get(ifidx);
230 	if (ifp != NULL) {
231 		rv = ifp->if_type == IFT_MPLSTUNNEL;
232 		if_put(ifp);
233 	}
234 	return (rv);
235 #else
236 	return (0);
237 #endif
238 }
239 
240 void
241 vlan_start(struct ifnet *ifp)
242 {
243 	struct ifvlan   *ifv;
244 	struct ifnet	*ifp0;
245 	struct mbuf	*m;
246 	uint8_t		 prio;
247 
248 	ifv = ifp->if_softc;
249 	ifp0 = if_get(ifv->ifv_ifp0);
250 	if (ifp0 == NULL || (ifp0->if_flags & (IFF_UP|IFF_RUNNING)) !=
251 	    (IFF_UP|IFF_RUNNING)) {
252 		ifq_purge(&ifp->if_snd);
253 		goto leave;
254 	}
255 
256 	for (;;) {
257 		IFQ_DEQUEUE(&ifp->if_snd, m);
258 		if (m == NULL)
259 			break;
260 
261 #if NBPFILTER > 0
262 		if (ifp->if_bpf)
263 			bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
264 #endif /* NBPFILTER > 0 */
265 
266 
267 		/* IEEE 802.1p has prio 0 and 1 swapped */
268 		prio = m->m_pkthdr.pf.prio;
269 		if (prio <= 1)
270 			prio = !prio;
271 
272 		/*
273 		 * If this packet came from a pseudowire it means it already
274 		 * has all tags it needs, so just output it.
275 		 */
276 		if (vlan_mplstunnel(m->m_pkthdr.ph_ifidx)) {
277 			/* NOTHING */
278 
279 		/*
280 		 * If the underlying interface cannot do VLAN tag insertion
281 		 * itself, create an encapsulation header.
282 		 */
283 		} else if ((ifp0->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
284 		    (ifv->ifv_type == ETHERTYPE_VLAN)) {
285 			m->m_pkthdr.ether_vtag = ifv->ifv_tag +
286 			    (prio << EVL_PRIO_BITS);
287 			m->m_flags |= M_VLANTAG;
288 		} else {
289 			m = vlan_inject(m, ifv->ifv_type, ifv->ifv_tag |
290 			    (prio << EVL_PRIO_BITS));
291 			if (m == NULL) {
292 				ifp->if_oerrors++;
293 				continue;
294 			}
295 		}
296 
297 		if (if_enqueue(ifp0, m)) {
298 			ifp->if_oerrors++;
299 			continue;
300 		}
301 		ifp->if_opackets++;
302 	}
303 
304 leave:
305 	if_put(ifp0);
306 }
307 
308 struct mbuf *
309 vlan_inject(struct mbuf *m, uint16_t type, uint16_t tag)
310 {
311 	struct ether_vlan_header evh;
312 
313 	m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
314 	evh.evl_proto = evh.evl_encap_proto;
315 	evh.evl_encap_proto = htons(type);
316 	evh.evl_tag = htons(tag);
317 	m_adj(m, ETHER_HDR_LEN);
318 	M_PREPEND(m, sizeof(evh), M_DONTWAIT);
319 	if (m == NULL)
320 		return (NULL);
321 
322 	m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
323 	CLR(m->m_flags, M_VLANTAG);
324 
325 	return (m);
326  }
327 
328 /*
329  * vlan_input() returns 1 if it has consumed the packet, 0 otherwise.
330  */
331 int
332 vlan_input(struct ifnet *ifp0, struct mbuf *m, void *cookie)
333 {
334 	struct ifvlan			*ifv;
335 	struct ether_vlan_header	*evl;
336 	struct ether_header		*eh;
337 	SRPL_HEAD(, ifvlan)		*tagh, *list;
338 	struct srp_ref			 sr;
339 	u_int				 tag;
340 	struct mbuf_list		 ml = MBUF_LIST_INITIALIZER();
341 	u_int16_t			 etype;
342 
343 	eh = mtod(m, struct ether_header *);
344 	etype = ntohs(eh->ether_type);
345 
346 	if (m->m_flags & M_VLANTAG) {
347 		etype = ETHERTYPE_VLAN;
348 		tagh = vlan_tagh;
349 	} else if ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ)) {
350 		if (m->m_len < sizeof(*evl) &&
351 		    (m = m_pullup(m, sizeof(*evl))) == NULL) {
352 			ifp0->if_ierrors++;
353 			return (1);
354 		}
355 
356 		evl = mtod(m, struct ether_vlan_header *);
357 		m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag);
358 		tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
359 	} else {
360 		/* Skip non-VLAN packets. */
361 		return (0);
362 	}
363 
364 	/* From now on ether_vtag is fine */
365 	tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
366 	m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
367 
368 	/* IEEE 802.1p has prio 0 and 1 swapped */
369 	if (m->m_pkthdr.pf.prio <= 1)
370 		m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio;
371 
372 	list = &tagh[TAG_HASH(tag)];
373 	SRPL_FOREACH(ifv, &sr, list, ifv_list) {
374 		if (ifp0->if_index == ifv->ifv_ifp0 && tag == ifv->ifv_tag &&
375 		    etype == ifv->ifv_type)
376 			break;
377 	}
378 
379 	if (ifv == NULL) {
380 		ifp0->if_noproto++;
381 		goto drop;
382 	}
383 
384 	if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
385 	    (IFF_UP|IFF_RUNNING))
386 		goto drop;
387 
388 	/*
389 	 * Having found a valid vlan interface corresponding to
390 	 * the given source interface and vlan tag, remove the
391 	 * encapsulation.
392 	 */
393 	if (m->m_flags & M_VLANTAG) {
394 		m->m_flags &= ~M_VLANTAG;
395 	} else {
396 		eh->ether_type = evl->evl_proto;
397 		memmove((char *)eh + EVL_ENCAPLEN, eh, sizeof(*eh));
398 		m_adj(m, EVL_ENCAPLEN);
399 	}
400 
401 	ml_enqueue(&ml, m);
402 	if_input(&ifv->ifv_if, &ml);
403 	SRPL_LEAVE(&sr);
404 	return (1);
405 
406 drop:
407 	SRPL_LEAVE(&sr);
408 	m_freem(m);
409 	return (1);
410 }
411 
412 int
413 vlan_parent_up(struct ifvlan *ifv, struct ifnet *ifp0)
414 {
415 	int error;
416 
417 	if (ISSET(ifv->ifv_flags, IFVF_PROMISC)) {
418 		error = ifpromisc(ifp0, 1);
419 		if (error != 0)
420 			return (error);
421 	}
422 
423 	/* Register callback for physical link state changes */
424 	ifv->lh_cookie = hook_establish(ifp0->if_linkstatehooks, 1,
425 	    vlan_link_hook, ifv);
426 
427 	/* Register callback if parent wants to unregister */
428 	ifv->dh_cookie = hook_establish(ifp0->if_detachhooks, 0,
429 	    vlan_ifdetach, ifv);
430 
431 	vlan_multi_apply(ifv, ifp0, SIOCADDMULTI);
432 
433 	if_ih_insert(ifp0, vlan_input, NULL);
434 
435 	return (0);
436 }
437 
438 int
439 vlan_up(struct ifvlan *ifv)
440 {
441 	SRPL_HEAD(, ifvlan) *tagh, *list;
442 	struct ifnet *ifp = &ifv->ifv_if;
443 	struct ifnet *ifp0;
444 	int error = 0;
445 	u_int hardmtu;
446 
447 	KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING));
448 
449 	tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
450 	list = &tagh[TAG_HASH(ifv->ifv_tag)];
451 
452 	ifp0 = if_get(ifv->ifv_ifp0);
453 	if (ifp0 == NULL)
454 		return (ENXIO);
455 
456 	/* check vlan will work on top of the parent */
457 	if (ifp0->if_type != IFT_ETHER) {
458 		error = EPROTONOSUPPORT;
459 		goto put;
460 	}
461 
462 	hardmtu = ifp0->if_hardmtu;
463 	if (!ISSET(ifp0->if_capabilities, IFCAP_VLAN_MTU))
464 		hardmtu -= EVL_ENCAPLEN;
465 
466 	if (ifp->if_mtu > hardmtu) {
467 		error = ENOBUFS;
468 		goto put;
469 	}
470 
471 	/* parent is fine, let's prepare the ifv to handle packets */
472 	ifp->if_hardmtu = hardmtu;
473 	SET(ifp->if_flags, ifp0->if_flags & IFF_SIMPLEX);
474 	if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
475 		if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
476 
477 	if (ifv->ifv_type != ETHERTYPE_VLAN) {
478 		/*
479 		 * Hardware offload only works with the default VLAN
480 		 * ethernet type (0x8100).
481 		 */
482 		ifp->if_capabilities = 0;
483 	} else if (ISSET(ifp0->if_capabilities, IFCAP_VLAN_HWTAGGING)) {
484 		/*
485 		 * If the parent interface can do hardware-assisted
486 		 * VLAN encapsulation, then propagate its hardware-
487 		 * assisted checksumming flags.
488 		 *
489 		 * If the card cannot handle hardware tagging, it cannot
490 		 * possibly compute the correct checksums for tagged packets.
491 		 */
492 		ifp->if_capabilities = ifp0->if_capabilities & IFCAP_CSUM_MASK;
493 	}
494 
495 	/* commit the ifv */
496 	error = rw_enter(&vlan_tagh_lk, RW_WRITE | RW_INTR);
497 	if (error != 0)
498 		goto scrub;
499 
500 	error = vlan_inuse_locked(ifv->ifv_type, ifv->ifv_ifp0, ifv->ifv_tag);
501 	if (error != 0)
502 		goto leave;
503 
504 	SRPL_INSERT_HEAD_LOCKED(&vlan_tagh_rc, list, ifv, ifv_list);
505 	rw_exit(&vlan_tagh_lk);
506 
507 	/* configure the parent to handle packets for this vlan */
508 	error = vlan_parent_up(ifv, ifp0);
509 	if (error != 0)
510 		goto remove;
511 
512 	/* we're running now */
513 	SET(ifp->if_flags, IFF_RUNNING);
514 	vlan_link_state(ifv, ifp0->if_link_state, ifp0->if_baudrate);
515 
516 	if_put(ifp0);
517 
518 	return (0);
519 
520 remove:
521 	rw_enter(&vlan_tagh_lk, RW_WRITE);
522 	SRPL_REMOVE_LOCKED(&vlan_tagh_rc, list, ifv, ifvlan, ifv_list);
523 leave:
524 	rw_exit(&vlan_tagh_lk);
525 scrub:
526 	ifp->if_capabilities = 0;
527 	if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
528 		if_setlladdr(ifp, etheranyaddr);
529 	CLR(ifp->if_flags, IFF_SIMPLEX);
530 	ifp->if_hardmtu = 0xffff;
531 put:
532 	if_put(ifp0);
533 
534 	return (error);
535 }
536 
537 int
538 vlan_down(struct ifvlan *ifv)
539 {
540 	SRPL_HEAD(, ifvlan) *tagh, *list;
541 	struct ifnet *ifp = &ifv->ifv_if;
542 	struct ifnet *ifp0;
543 
544 	tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
545 	list = &tagh[TAG_HASH(ifv->ifv_tag)];
546 
547 	KASSERT(ISSET(ifp->if_flags, IFF_RUNNING));
548 
549 	vlan_link_state(ifv, LINK_STATE_DOWN, 0);
550 	CLR(ifp->if_flags, IFF_RUNNING);
551 
552 	ifq_barrier(&ifp->if_snd);
553 
554 	ifp0 = if_get(ifv->ifv_ifp0);
555 	if (ifp0 != NULL) {
556 		if_ih_remove(ifp0, vlan_input, NULL);
557 		if (ISSET(ifv->ifv_flags, IFVF_PROMISC))
558 			ifpromisc(ifp0, 0);
559 		vlan_multi_apply(ifv, ifp0, SIOCDELMULTI);
560 		hook_disestablish(ifp0->if_detachhooks, ifv->dh_cookie);
561 		hook_disestablish(ifp0->if_linkstatehooks, ifv->lh_cookie);
562 	}
563 	if_put(ifp0);
564 
565 	rw_enter_write(&vlan_tagh_lk);
566 	SRPL_REMOVE_LOCKED(&vlan_tagh_rc, list, ifv, ifvlan, ifv_list);
567 	rw_exit_write(&vlan_tagh_lk);
568 
569 	ifp->if_capabilities = 0;
570 	if (!ISSET(ifv->ifv_flags, IFVF_LLADDR))
571 		if_setlladdr(ifp, etheranyaddr);
572 	CLR(ifp->if_flags, IFF_SIMPLEX);
573 	ifp->if_hardmtu = 0xffff;
574 
575 	return (0);
576 }
577 
578 void
579 vlan_ifdetach(void *v)
580 {
581 	struct ifvlan *ifv = v;
582 	struct ifnet *ifp = &ifv->ifv_if;
583 
584 	if (ISSET(ifp->if_flags, IFF_RUNNING)) {
585 		vlan_down(ifv);
586 		CLR(ifp->if_flags, IFF_UP);
587 	}
588 
589 	ifv->ifv_ifp0 = 0;
590 }
591 
592 void
593 vlan_link_hook(void *v)
594 {
595 	struct ifvlan *ifv = v;
596 	struct ifnet *ifp0;
597 
598 	u_char link = LINK_STATE_DOWN;
599 	uint64_t baud = 0;
600 
601 	ifp0 = if_get(ifv->ifv_ifp0);
602 	if (ifp0 != NULL) {
603 		link = ifp0->if_link_state;
604 		baud = ifp0->if_baudrate;
605 	}
606 	if_put(ifp0);
607 
608 	vlan_link_state(ifv, link, baud);
609 }
610 
611 void
612 vlan_link_state(struct ifvlan *ifv, u_char link, uint64_t baud)
613 {
614 	if (ifv->ifv_if.if_link_state == link)
615 		return;
616 
617 	ifv->ifv_if.if_link_state = link;
618 	ifv->ifv_if.if_baudrate = baud;
619 
620 	if_link_state_change(&ifv->ifv_if);
621 }
622 
623 int
624 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
625 {
626 	struct ifvlan *ifv = ifp->if_softc;
627 	struct ifreq *ifr = (struct ifreq *)data;
628 	struct if_parent *parent = (struct if_parent *)data;
629 	struct ifnet *ifp0;
630 	uint16_t tag;
631 	int error = 0;
632 
633 	switch (cmd) {
634 	case SIOCSIFADDR:
635 		ifp->if_flags |= IFF_UP;
636 		/* FALLTHROUGH */
637 
638 	case SIOCSIFFLAGS:
639 		if (ISSET(ifp->if_flags, IFF_UP)) {
640 			if (!ISSET(ifp->if_flags, IFF_RUNNING))
641 				error = vlan_up(ifv);
642 			else
643 				error = ENETRESET;
644 		} else {
645 			if (ISSET(ifp->if_flags, IFF_RUNNING))
646 				error = vlan_down(ifv);
647 		}
648 		break;
649 
650 	case SIOCSVNETID:
651 		tag = ifr->ifr_vnetid;
652 		if (tag == ifv->ifv_tag)
653 			break;
654 
655 		if (tag < EVL_VLID_MIN || tag > EVL_VLID_MAX) {
656 			error = EINVAL;
657 			break;
658 		}
659 
660 		error = vlan_set_vnetid(ifv, tag);
661 		break;
662 
663 	case SIOCGVNETID:
664 		if (ifv->ifv_tag == EVL_VLID_NULL)
665 			error = EADDRNOTAVAIL;
666 		else
667 			ifr->ifr_vnetid = (uint32_t)ifv->ifv_tag;
668 		break;
669 
670 	case SIOCDVNETID:
671 		error = vlan_set_vnetid(ifv, 0);
672 		break;
673 
674 	case SIOCSIFPARENT:
675 		if (ISSET(ifp->if_flags, IFF_RUNNING)) {
676 			error = EBUSY;
677 			break;
678 		}
679 
680 		ifp0 = ifunit(parent->ifp_parent);
681 		if (ifp0 == NULL) {
682 			error = EINVAL;
683 			break;
684 		}
685 
686 		if (ifv->ifv_ifp0 == ifp0->if_index) {
687 			/* nop */
688 			break;
689 		}
690 
691 		if (ifp0->if_type != IFT_ETHER) {
692 			error = EPROTONOSUPPORT;
693 			break;
694 		}
695 
696 		error = vlan_inuse(ifv->ifv_type, ifp0->if_index, ifv->ifv_tag);
697 		if (error != 0)
698 			break;
699 
700 		ifv->ifv_ifp0 = ifp0->if_index;
701 		break;
702 
703 	case SIOCGIFPARENT:
704 		ifp0 = if_get(ifv->ifv_ifp0);
705 		if (ifp0 == NULL)
706 			error = EADDRNOTAVAIL;
707 		else {
708 			memcpy(parent->ifp_parent, ifp0->if_xname,
709 			    sizeof(parent->ifp_parent));
710 		}
711 		if_put(ifp0);
712 		break;
713 
714 	case SIOCDIFPARENT:
715 		if (ISSET(ifp->if_flags, IFF_RUNNING)) {
716 			error = EBUSY;
717 			break;
718 		}
719 
720 		ifv->ifv_ifp0 = 0;
721 		break;
722 
723 	case SIOCADDMULTI:
724 		error = vlan_multi_add(ifv, ifr);
725 		break;
726 	case SIOCDELMULTI:
727 		error = vlan_multi_del(ifv, ifr);
728 		break;
729 
730 	case SIOCSIFLLADDR:
731 		error = vlan_setlladdr(ifv, ifr);
732 		break;
733 
734 	case SIOCSETVLAN:
735 		error = vlan_set_compat(ifp, ifr);
736 		break;
737 	case SIOCGETVLAN:
738 		error = vlan_get_compat(ifp, ifr);
739 		break;
740 
741 	default:
742 		error = ether_ioctl(ifp, &ifv->ifv_ac, cmd, data);
743 		break;
744 	}
745 
746 	if (error == ENETRESET) {
747 		vlan_iff(ifv);
748 		error = 0;
749 	}
750 
751 	return error;
752 }
753 
754 int
755 vlan_iff(struct ifvlan *ifv)
756 {
757 	struct ifnet *ifp0;
758 	int promisc = 0;
759 	int error = 0;
760 
761 	if (ISSET(ifv->ifv_if.if_flags, IFF_PROMISC) ||
762 	    ISSET(ifv->ifv_flags, IFVF_LLADDR))
763 		promisc = IFVF_PROMISC;
764 
765 	if (ISSET(ifv->ifv_flags, IFVF_PROMISC) == promisc)
766 		return (0);
767 
768 	if (ISSET(ifv->ifv_if.if_flags, IFF_RUNNING)) {
769 		ifp0 = if_get(ifv->ifv_ifp0);
770 		if (ifp0 != NULL)
771 			error = ifpromisc(ifp0, promisc);
772 		if_put(ifp0);
773 	}
774 
775 	if (error == 0) {
776 		CLR(ifv->ifv_flags, IFVF_PROMISC);
777 		SET(ifv->ifv_flags, promisc);
778 	}
779 
780 	return (error);
781 }
782 
783 int
784 vlan_setlladdr(struct ifvlan *ifv, struct ifreq *ifr)
785 {
786 	struct ifnet *ifp = &ifv->ifv_if;;
787 	struct ifnet *ifp0;
788 	int flag = IFVF_LLADDR;
789 
790 	/* setting the mac addr to 00:00:00:00:00:00 means reset lladdr */
791 	if (memcmp(ifr->ifr_addr.sa_data, etheranyaddr, ETHER_ADDR_LEN) == 0)
792 		flag = 0;
793 
794 	if (ISSET(ifv->ifv_flags, IFVF_LLADDR) == flag)
795 		return (0);
796 
797 	/* if we're up and the mac is reset, inherit the parents mac */
798 	if (ISSET(ifp->if_flags, IFF_RUNNING) && flag == 0) {
799 		ifp0 = if_get(ifv->ifv_ifp0);
800 		if (ifp0 != NULL)
801 			if_setlladdr(ifp, LLADDR(ifp0->if_sadl));
802 		if_put(ifp0);
803 	}
804 
805 	CLR(ifv->ifv_flags, IFVF_LLADDR);
806 	SET(ifv->ifv_flags, flag);
807 
808 	return (ENETRESET);
809 }
810 
811 int
812 vlan_set_vnetid(struct ifvlan *ifv, uint16_t tag)
813 {
814 	struct ifnet *ifp = &ifv->ifv_if;
815 	SRPL_HEAD(, ifvlan) *tagh, *list;
816 	u_char link = ifp->if_link_state;
817 	uint64_t baud = ifp->if_baudrate;
818 	int error;
819 
820 	tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
821 
822 	if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link))
823 		vlan_link_state(ifv, LINK_STATE_DOWN, 0);
824 
825 	error = rw_enter(&vlan_tagh_lk, RW_WRITE);
826 	if (error != 0)
827 		return (error);
828 
829 	error = vlan_inuse_locked(ifv->ifv_type, ifv->ifv_ifp0, tag);
830 	if (error != 0)
831 		goto unlock;
832 
833 	if (ISSET(ifp->if_flags, IFF_RUNNING)) {
834 		list = &tagh[TAG_HASH(ifv->ifv_tag)];
835 		SRPL_REMOVE_LOCKED(&vlan_tagh_rc, list, ifv, ifvlan, ifv_list);
836 
837 		ifv->ifv_tag = tag;
838 
839 		list = &tagh[TAG_HASH(ifv->ifv_tag)];
840 		SRPL_INSERT_HEAD_LOCKED(&vlan_tagh_rc, list, ifv, ifv_list);
841 	} else
842 		ifv->ifv_tag = tag;
843 
844 unlock:
845 	rw_exit(&vlan_tagh_lk);
846 
847 	if (ISSET(ifp->if_flags, IFF_RUNNING) && LINK_STATE_IS_UP(link))
848 		vlan_link_state(ifv, link, baud);
849 
850 	return (error);
851 }
852 
853 int
854 vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr)
855 {
856 	struct vlanreq vlr;
857 	struct ifreq req;
858 	struct if_parent parent;
859 
860 	int error;
861 
862 	error = suser(curproc, 0);
863 	if (error != 0)
864 		return (error);
865 
866 	error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
867 	if (error != 0)
868 		return (error);
869 
870 	if (vlr.vlr_parent[0] == '\0')
871 		return (vlan_ioctl(ifp, SIOCDIFPARENT, (caddr_t)ifr));
872 
873 	memset(&req, 0, sizeof(req));
874 	memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name));
875 	req.ifr_vnetid = vlr.vlr_tag;
876 
877 	error = vlan_ioctl(ifp, SIOCSVNETID, (caddr_t)&req);
878 	if (error != 0)
879 		return (error);
880 
881 	memset(&parent, 0, sizeof(parent));
882 	memcpy(parent.ifp_name, ifp->if_xname, sizeof(parent.ifp_name));
883 	memcpy(parent.ifp_parent, vlr.vlr_parent, sizeof(parent.ifp_parent));
884 	error = vlan_ioctl(ifp, SIOCSIFPARENT, (caddr_t)&parent);
885 	if (error != 0)
886 		return (error);
887 
888 	memset(&req, 0, sizeof(req));
889 	memcpy(req.ifr_name, ifp->if_xname, sizeof(req.ifr_name));
890 	SET(ifp->if_flags, IFF_UP);
891 	return (vlan_ioctl(ifp, SIOCSIFFLAGS, (caddr_t)&req));
892 }
893 
894 int
895 vlan_get_compat(struct ifnet *ifp, struct ifreq *ifr)
896 {
897 	struct ifvlan *ifv = ifp->if_softc;
898 	struct vlanreq vlr;
899 	struct ifnet *p;
900 
901 	memset(&vlr, 0, sizeof(vlr));
902 	p = if_get(ifv->ifv_ifp0);
903 	if (p != NULL)
904 		memcpy(vlr.vlr_parent, p->if_xname, sizeof(vlr.vlr_parent));
905 	if_put(p);
906 
907 	vlr.vlr_tag = ifv->ifv_tag;
908 
909 	return (copyout(&vlr, ifr->ifr_data, sizeof(vlr)));
910 }
911 
912 /*
913  * do a quick check of up and running vlans for existing configurations.
914  *
915  * NOTE: this does allow the same config on down vlans, but vlan_up()
916  * will catch them.
917  */
918 int
919 vlan_inuse(uint16_t type, unsigned int ifidx, uint16_t tag)
920 {
921 	int error = 0;
922 
923 	error = rw_enter(&vlan_tagh_lk, RW_READ | RW_INTR);
924 	if (error != 0)
925 		return (error);
926 
927 	error = vlan_inuse_locked(type, ifidx, tag);
928 
929 	rw_exit(&vlan_tagh_lk);
930 
931 	return (error);
932 }
933 
934 int
935 vlan_inuse_locked(uint16_t type, unsigned int ifidx, uint16_t tag)
936 {
937 	SRPL_HEAD(, ifvlan) *tagh, *list;
938 	struct ifvlan *ifv;
939 
940 	tagh = type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
941 	list = &tagh[TAG_HASH(tag)];
942 
943 	SRPL_FOREACH_LOCKED(ifv, list, ifv_list) {
944 		if (ifv->ifv_tag == tag &&
945 		    ifv->ifv_type == type && /* wat */
946 		    ifv->ifv_ifp0 == ifidx)
947 			return (EADDRINUSE);
948 	}
949 
950 	return (0);
951 }
952 
953 int
954 vlan_multi_add(struct ifvlan *ifv, struct ifreq *ifr)
955 {
956 	struct ifnet		*ifp0;
957 	struct vlan_mc_entry	*mc;
958 	u_int8_t		 addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
959 	int			 error;
960 
961 	error = ether_addmulti(ifr, &ifv->ifv_ac);
962 	if (error != ENETRESET)
963 		return (error);
964 
965 	/*
966 	 * This is new multicast address.  We have to tell parent
967 	 * about it.  Also, remember this multicast address so that
968 	 * we can delete them on unconfigure.
969 	 */
970 	if ((mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT)) == NULL) {
971 		error = ENOMEM;
972 		goto alloc_failed;
973 	}
974 
975 	/*
976 	 * As ether_addmulti() returns ENETRESET, following two
977 	 * statement shouldn't fail.
978 	 */
979 	(void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
980 	ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, mc->mc_enm);
981 	memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
982 	LIST_INSERT_HEAD(&ifv->vlan_mc_listhead, mc, mc_entries);
983 
984 	ifp0 = if_get(ifv->ifv_ifp0);
985 	error = (ifp0 == NULL) ? 0 :
986 	    (*ifp0->if_ioctl)(ifp0, SIOCADDMULTI, (caddr_t)ifr);
987 	if_put(ifp0);
988 
989 	if (error != 0)
990 		goto ioctl_failed;
991 
992 	return (error);
993 
994  ioctl_failed:
995 	LIST_REMOVE(mc, mc_entries);
996 	free(mc, M_DEVBUF, sizeof(*mc));
997  alloc_failed:
998 	(void)ether_delmulti(ifr, &ifv->ifv_ac);
999 
1000 	return (error);
1001 }
1002 
1003 int
1004 vlan_multi_del(struct ifvlan *ifv, struct ifreq *ifr)
1005 {
1006 	struct ifnet		*ifp0;
1007 	struct ether_multi	*enm;
1008 	struct vlan_mc_entry	*mc;
1009 	u_int8_t		 addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
1010 	int			 error;
1011 
1012 	/*
1013 	 * Find a key to lookup vlan_mc_entry.  We have to do this
1014 	 * before calling ether_delmulti for obvious reason.
1015 	 */
1016 	if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0)
1017 		return (error);
1018 	ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, enm);
1019 	if (enm == NULL)
1020 		return (EINVAL);
1021 
1022 	LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries) {
1023 		if (mc->mc_enm == enm)
1024 			break;
1025 	}
1026 
1027 	/* We won't delete entries we didn't add */
1028 	if (mc == NULL)
1029 		return (EINVAL);
1030 
1031 	error = ether_delmulti(ifr, &ifv->ifv_ac);
1032 	if (error != ENETRESET)
1033 		return (error);
1034 
1035 	if (!ISSET(ifv->ifv_if.if_flags, IFF_RUNNING))
1036 		goto forget;
1037 
1038 	ifp0 = if_get(ifv->ifv_ifp0);
1039 	error = (ifp0 == NULL) ? 0 :
1040 	    (*ifp0->if_ioctl)(ifp0, SIOCDELMULTI, (caddr_t)ifr);
1041 	if_put(ifp0);
1042 
1043 	if (error != 0) {
1044 		(void)ether_addmulti(ifr, &ifv->ifv_ac);
1045 		return (error);
1046 	}
1047 
1048 forget:
1049 	/* forget about this address */
1050 	LIST_REMOVE(mc, mc_entries);
1051 	free(mc, M_DEVBUF, sizeof(*mc));
1052 
1053 	return (0);
1054 }
1055 
1056 void
1057 vlan_multi_apply(struct ifvlan *ifv, struct ifnet *ifp0, u_long cmd)
1058 {
1059 	struct vlan_mc_entry	*mc;
1060 	union {
1061 		struct ifreq ifreq;
1062 		struct {
1063 			char			ifr_name[IFNAMSIZ];
1064 			struct sockaddr_storage	ifr_ss;
1065 		} ifreq_storage;
1066 	} ifreq;
1067 	struct ifreq	*ifr = &ifreq.ifreq;
1068 
1069 	memcpy(ifr->ifr_name, ifp0->if_xname, IFNAMSIZ);
1070 	LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries) {
1071 		memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
1072 
1073 		(void)(*ifp0->if_ioctl)(ifp0, cmd, (caddr_t)ifr);
1074 	}
1075 }
1076 
1077 void
1078 vlan_multi_free(struct ifvlan *ifv)
1079 {
1080 	struct vlan_mc_entry	*mc;
1081 
1082 	while ((mc = LIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
1083 		LIST_REMOVE(mc, mc_entries);
1084 		free(mc, M_DEVBUF, sizeof(*mc));
1085 	}
1086 }
1087