xref: /openbsd-src/sys/net/if_vlan.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: if_vlan.c,v 1.91 2011/11/27 00:46:07 haesbaert 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 "vlan.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/proc.h>
61 
62 #include "bpfilter.h"
63 #if NBPFILTER > 0
64 #include <net/bpf.h>
65 #endif
66 
67 #include <net/if.h>
68 #include <net/if_dl.h>
69 #include <net/if_types.h>
70 
71 #ifdef INET
72 #include <netinet/in.h>
73 #include <netinet/if_ether.h>
74 #endif
75 
76 #include <net/if_vlan_var.h>
77 
78 extern struct	ifaddr	**ifnet_addrs;
79 u_long vlan_tagmask, svlan_tagmask;
80 
81 #define TAG_HASH_SIZE		32
82 #define TAG_HASH(tag)		(tag & vlan_tagmask)
83 LIST_HEAD(vlan_taghash, ifvlan)	*vlan_tagh, *svlan_tagh;
84 
85 void	vlan_start(struct ifnet *ifp);
86 int	vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
87 int	vlan_unconfig(struct ifnet *ifp, struct ifnet *newp);
88 int	vlan_config(struct ifvlan *, struct ifnet *, u_int16_t);
89 void	vlan_vlandev_state(void *);
90 void	vlanattach(int count);
91 int	vlan_set_promisc(struct ifnet *ifp);
92 int	vlan_ether_addmulti(struct ifvlan *, struct ifreq *);
93 int	vlan_ether_delmulti(struct ifvlan *, struct ifreq *);
94 void	vlan_ether_purgemulti(struct ifvlan *);
95 void	vlan_ether_resetmulti(struct ifvlan *, struct ifnet *);
96 int	vlan_clone_create(struct if_clone *, int);
97 int	vlan_clone_destroy(struct ifnet *);
98 void	vlan_ifdetach(void *);
99 
100 struct if_clone vlan_cloner =
101     IF_CLONE_INITIALIZER("vlan", vlan_clone_create, vlan_clone_destroy);
102 struct if_clone svlan_cloner =
103     IF_CLONE_INITIALIZER("svlan", vlan_clone_create, vlan_clone_destroy);
104 
105 /* ARGSUSED */
106 void
107 vlanattach(int count)
108 {
109 	/* Normal VLAN */
110 	vlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT,
111 	    &vlan_tagmask);
112 	if (vlan_tagh == NULL)
113 		panic("vlanattach: hashinit");
114 	if_clone_attach(&vlan_cloner);
115 
116 	/* Service-VLAN for QinQ/802.1ad provider bridges */
117 	svlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT,
118 	    &svlan_tagmask);
119 	if (svlan_tagh == NULL)
120 		panic("vlanattach: hashinit");
121 	if_clone_attach(&svlan_cloner);
122 }
123 
124 int
125 vlan_clone_create(struct if_clone *ifc, int unit)
126 {
127 	struct ifvlan *ifv;
128 	struct ifnet *ifp;
129 
130 	ifv = malloc(sizeof(*ifv), M_DEVBUF, M_NOWAIT|M_ZERO);
131 	if (!ifv)
132 		return (ENOMEM);
133 
134 	LIST_INIT(&ifv->vlan_mc_listhead);
135 	ifp = &ifv->ifv_if;
136 	ifp->if_softc = ifv;
137 	snprintf(ifp->if_xname, sizeof ifp->if_xname, "%s%d", ifc->ifc_name,
138 	    unit);
139 	/* NB: flags are not set here */
140 	/* NB: mtu is not set here */
141 
142 	/* Special handling for the IEEE 802.1ad QinQ variant */
143 	if (strcmp("svlan", ifc->ifc_name) == 0)
144 		ifv->ifv_type = ETHERTYPE_QINQ;
145 	else
146 		ifv->ifv_type = ETHERTYPE_VLAN;
147 
148 	ifp->if_start = vlan_start;
149 	ifp->if_ioctl = vlan_ioctl;
150 	IFQ_SET_MAXLEN(&ifp->if_snd, 1);
151 	IFQ_SET_READY(&ifp->if_snd);
152 	if_attach(ifp);
153 	ether_ifattach(ifp);
154 	/* Now undo some of the damage... */
155 	ifp->if_type = IFT_L2VLAN;
156 	ifp->if_hdrlen = EVL_ENCAPLEN;
157 
158 	return (0);
159 }
160 
161 int
162 vlan_clone_destroy(struct ifnet *ifp)
163 {
164 	struct ifvlan *ifv = ifp->if_softc;
165 
166 	vlan_unconfig(ifp, NULL);
167 	ether_ifdetach(ifp);
168 	if_detach(ifp);
169 
170 	free(ifv, M_DEVBUF);
171 	return (0);
172 }
173 
174 void
175 vlan_ifdetach(void *ptr)
176 {
177 	struct ifvlan *ifv = (struct ifvlan *)ptr;
178 	/*
179 	 * Destroy the vlan interface because the parent has been
180 	 * detached. Set the dh_cookie to NULL because we're running
181 	 * inside of dohooks which is told to disestablish the hook
182 	 * for us (otherwise we would kill the TAILQ element...).
183 	 */
184 	ifv->dh_cookie = NULL;
185 	vlan_clone_destroy(&ifv->ifv_if);
186 }
187 
188 void
189 vlan_start(struct ifnet *ifp)
190 {
191 	struct ifvlan *ifv;
192 	struct ifnet *p;
193 	struct mbuf *m;
194 	int error;
195 
196 	ifv = ifp->if_softc;
197 	p = ifv->ifv_p;
198 
199 	ifp->if_flags |= IFF_OACTIVE;
200 	for (;;) {
201 		IFQ_DEQUEUE(&ifp->if_snd, m);
202 		if (m == NULL)
203 			break;
204 
205 		if ((p->if_flags & (IFF_UP|IFF_RUNNING)) !=
206 		    (IFF_UP|IFF_RUNNING)) {
207 			IF_DROP(&p->if_snd);
208 				/* XXX stats */
209 			ifp->if_oerrors++;
210 			m_freem(m);
211 			continue;
212 		}
213 
214 #if NBPFILTER > 0
215 		if (ifp->if_bpf)
216 			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
217 #endif
218 
219 		/*
220 		 * If the IFCAP_VLAN_HWTAGGING capability is set on the parent,
221 		 * it can do VLAN tag insertion itself and doesn't require us
222 	 	 * to create a special header for it. In this case, we just pass
223 		 * the packet along.
224 		 */
225 		if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
226 		    (ifv->ifv_type == ETHERTYPE_VLAN)) {
227 			m->m_pkthdr.ether_vtag = ifv->ifv_tag +
228 			    (m->m_pkthdr.pf.prio << EVL_PRIO_BITS);
229 			m->m_flags |= M_VLANTAG;
230 		} else {
231 			struct ether_vlan_header evh;
232 
233 			m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
234 			evh.evl_proto = evh.evl_encap_proto;
235 			evh.evl_encap_proto = htons(ifv->ifv_type);
236 			evh.evl_tag = htons(ifv->ifv_tag +
237 			    (m->m_pkthdr.pf.prio << EVL_PRIO_BITS));
238 
239 			m_adj(m, ETHER_HDR_LEN);
240 			M_PREPEND(m, sizeof(evh), M_DONTWAIT);
241 			if (m == NULL) {
242 				ifp->if_oerrors++;
243 				continue;
244 			}
245 
246 			m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
247 		}
248 
249 		/*
250 		 * Send it, precisely as ether_output() would have.
251 		 * We are already running at splnet.
252 		 */
253 		IFQ_ENQUEUE(&p->if_snd, m, NULL, error);
254 		if (error) {
255 			/* mbuf is already freed */
256 			ifp->if_oerrors++;
257 			continue;
258 		}
259 		p->if_obytes += m->m_pkthdr.len;
260 		if (m->m_flags & M_MCAST)
261 			p->if_omcasts++;
262 
263 		ifp->if_opackets++;
264 		if_start(p);
265 	}
266 	ifp->if_flags &= ~IFF_OACTIVE;
267 
268 	return;
269 }
270 
271 /*
272  * vlan_input() returns 0 if it has consumed the packet, 1 otherwise.
273  */
274 int
275 vlan_input(struct ether_header *eh, struct mbuf *m)
276 {
277 	struct ifvlan *ifv;
278 	struct ifnet *ifp = m->m_pkthdr.rcvif;
279 	struct vlan_taghash *tagh;
280 	u_int tag;
281 	u_int16_t etype;
282 
283 	if (m->m_flags & M_VLANTAG) {
284 		etype = ETHERTYPE_VLAN;
285 		tagh = vlan_tagh;
286 	} else {
287 		if (m->m_len < EVL_ENCAPLEN &&
288 		    (m = m_pullup(m, EVL_ENCAPLEN)) == NULL) {
289 			ifp->if_ierrors++;
290 			return (0);
291 		}
292 
293 		etype = ntohs(eh->ether_type);
294 		tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
295 		m->m_pkthdr.ether_vtag = ntohs(*mtod(m, u_int16_t *));
296 	}
297 	/* From now on ether_vtag is fine */
298 	tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
299 	m->m_pkthdr.pf.prio = EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
300 
301 	LIST_FOREACH(ifv, &tagh[TAG_HASH(tag)], ifv_list) {
302 		if (m->m_pkthdr.rcvif == ifv->ifv_p && tag == ifv->ifv_tag &&
303 		    etype == ifv->ifv_type)
304 			break;
305 	}
306 	if (ifv == NULL)
307 		return (1);
308 
309 	if ((ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
310 	    (IFF_UP|IFF_RUNNING)) {
311 		m_freem(m);
312 		return (0);
313 	}
314 
315 	/*
316 	 * Having found a valid vlan interface corresponding to
317 	 * the given source interface and vlan tag, remove the
318 	 * encapsulation, and run the real packet through
319 	 * ether_input() a second time (it had better be
320 	 * reentrant!).
321 	 */
322 	m->m_pkthdr.rcvif = &ifv->ifv_if;
323 	if (m->m_flags & M_VLANTAG) {
324 		m->m_flags &= ~M_VLANTAG;
325 	} else {
326 		eh->ether_type = mtod(m, u_int16_t *)[1];
327 		m->m_len -= EVL_ENCAPLEN;
328 		m->m_data += EVL_ENCAPLEN;
329 		m->m_pkthdr.len -= EVL_ENCAPLEN;
330 	}
331 
332 #if NBPFILTER > 0
333 	if (ifv->ifv_if.if_bpf)
334 		bpf_mtap_hdr(ifv->ifv_if.if_bpf, (char *)eh, ETHER_HDR_LEN,
335 		    m, BPF_DIRECTION_IN);
336 #endif
337 
338 	/*
339 	 * Drop promiscuously received packets if we are not in
340 	 * promiscuous mode.
341 	 */
342 	if ((m->m_flags & (M_BCAST|M_MCAST)) == 0 &&
343 	    (ifp->if_flags & IFF_PROMISC) &&
344 	    (ifv->ifv_if.if_flags & IFF_PROMISC) == 0) {
345 		struct arpcom *ac = &ifv->ifv_ac;
346 		if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) {
347 			m_freem(m);
348 			return (0);
349 		}
350 	}
351 
352 	ifv->ifv_if.if_ipackets++;
353 	ether_input(&ifv->ifv_if, eh, m);
354 
355 	return (0);
356 }
357 
358 int
359 vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
360 {
361 	struct ifaddr *ifa1, *ifa2;
362 	struct sockaddr_dl *sdl1, *sdl2;
363 	struct vlan_taghash *tagh;
364 	u_int flags;
365 	int s;
366 
367 	if (p->if_type != IFT_ETHER)
368 		return EPROTONOSUPPORT;
369 	if (ifv->ifv_p == p && ifv->ifv_tag == tag) /* noop */
370 		return (0);
371 
372 	/* Remember existing interface flags and reset the interface */
373 	flags = ifv->ifv_flags;
374 	vlan_unconfig(&ifv->ifv_if, p);
375 
376 	ifv->ifv_p = p;
377 
378 	if (p->if_capabilities & IFCAP_VLAN_MTU)
379 		ifv->ifv_if.if_mtu = p->if_mtu;
380 	else {
381 		/*
382 		 * This will be incompatible with strict
383 		 * 802.1Q implementations
384 		 */
385 		ifv->ifv_if.if_mtu = p->if_mtu - EVL_ENCAPLEN;
386 #ifdef DIAGNOSTIC
387 		printf("%s: initialized with non-standard mtu %u (parent %s)\n",
388 		    ifv->ifv_if.if_xname, ifv->ifv_if.if_mtu,
389 		    ifv->ifv_p->if_xname);
390 #endif
391 	}
392 
393 	ifv->ifv_if.if_flags = p->if_flags &
394 	    (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
395 
396 	/* Reset promisc mode on the interface and its parent */
397 	if (flags & IFVF_PROMISC) {
398 		ifv->ifv_if.if_flags |= IFF_PROMISC;
399 		vlan_set_promisc(&ifv->ifv_if);
400 	}
401 
402 	/*
403 	 * Inherit the if_type from the parent.  This allows us to
404 	 * participate in bridges of that type.
405 	 */
406 	ifv->ifv_if.if_type = p->if_type;
407 
408 	/*
409 	 * Inherit baudrate from the parent.  An SNMP agent would use this
410 	 * information.
411 	 */
412 	ifv->ifv_if.if_baudrate = p->if_baudrate;
413 
414 	/*
415 	 * If the parent interface can do hardware-assisted
416 	 * VLAN encapsulation, then propagate its hardware-
417 	 * assisted checksumming flags.
418 	 *
419 	 * If the card cannot handle hardware tagging, it cannot
420 	 * possibly compute the correct checksums for tagged packets.
421 	 *
422 	 * This brings up another possibility, do cards exist which
423 	 * have all of these capabilities but cannot utilize them together?
424 	 */
425 	if (p->if_capabilities & IFCAP_VLAN_HWTAGGING)
426 		ifv->ifv_if.if_capabilities = p->if_capabilities &
427 		    (IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4|
428 		    IFCAP_CSUM_UDPv4);
429 		/* (IFCAP_CSUM_TCPv6|IFCAP_CSUM_UDPv6); */
430 
431 	/*
432 	 * Hardware VLAN tagging only works with the default VLAN
433 	 * ethernet type (0x8100).
434 	 */
435 	if (ifv->ifv_type != ETHERTYPE_VLAN)
436 		ifv->ifv_if.if_capabilities &= ~IFCAP_VLAN_HWTAGGING;
437 
438 	/*
439 	 * Set up our ``Ethernet address'' to reflect the underlying
440 	 * physical interface's.
441 	 */
442 	ifa1 = ifnet_addrs[ifv->ifv_if.if_index];
443 	ifa2 = ifnet_addrs[p->if_index];
444 	sdl1 = (struct sockaddr_dl *)ifa1->ifa_addr;
445 	sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr;
446 	sdl1->sdl_type = IFT_ETHER;
447 	sdl1->sdl_alen = ETHER_ADDR_LEN;
448 	bcopy(LLADDR(sdl2), LLADDR(sdl1), ETHER_ADDR_LEN);
449 	bcopy(LLADDR(sdl2), ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
450 
451 	ifv->ifv_tag = tag;
452 	s = splnet();
453 	tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
454 	LIST_INSERT_HEAD(&tagh[TAG_HASH(tag)], ifv, ifv_list);
455 
456 	/* Register callback for physical link state changes */
457 	ifv->lh_cookie = hook_establish(p->if_linkstatehooks, 1,
458 	    vlan_vlandev_state, ifv);
459 
460 	/* Register callback if parent wants to unregister */
461 	ifv->dh_cookie = hook_establish(p->if_detachhooks, 1,
462 	    vlan_ifdetach, ifv);
463 
464 	vlan_vlandev_state(ifv);
465 	splx(s);
466 
467 	return 0;
468 }
469 
470 int
471 vlan_unconfig(struct ifnet *ifp, struct ifnet *newp)
472 {
473 	struct ifaddr *ifa;
474 	struct sockaddr_dl *sdl;
475 	struct ifvlan *ifv;
476 	struct ifnet *p;
477 	int s;
478 
479 	ifv = ifp->if_softc;
480 	p = ifv->ifv_p;
481 	if (p == NULL)
482 		return 0;
483 
484 	/* Unset promisc mode on the interface and its parent */
485 	if (ifv->ifv_flags & IFVF_PROMISC) {
486 		ifp->if_flags &= ~IFF_PROMISC;
487 		vlan_set_promisc(ifp);
488 	}
489 
490 	s = splnet();
491 	LIST_REMOVE(ifv, ifv_list);
492 	if (ifv->lh_cookie != NULL)
493 		hook_disestablish(p->if_linkstatehooks, ifv->lh_cookie);
494 	/* The cookie is NULL if disestablished externally */
495 	if (ifv->dh_cookie != NULL)
496 		hook_disestablish(p->if_detachhooks, ifv->dh_cookie);
497 	/* Reset link state */
498 	if (newp != NULL) {
499 		ifp->if_link_state = LINK_STATE_INVALID;
500 		if_link_state_change(ifp);
501 	}
502 	splx(s);
503 
504 	/*
505  	 * Since the interface is being unconfigured, we need to
506 	 * empty the list of multicast groups that we may have joined
507 	 * while we were alive and remove them from the parent's list
508 	 * as well.
509 	 */
510 	vlan_ether_resetmulti(ifv, newp);
511 
512 	/* Disconnect from parent. */
513 	ifv->ifv_p = NULL;
514 	ifv->ifv_if.if_mtu = ETHERMTU;
515 	ifv->ifv_flags = 0;
516 
517 	/* Clear our MAC address. */
518 	ifa = ifnet_addrs[ifv->ifv_if.if_index];
519 	sdl = (struct sockaddr_dl *)ifa->ifa_addr;
520 	sdl->sdl_type = IFT_ETHER;
521 	sdl->sdl_alen = ETHER_ADDR_LEN;
522 	bzero(LLADDR(sdl), ETHER_ADDR_LEN);
523 	bzero(ifv->ifv_ac.ac_enaddr, ETHER_ADDR_LEN);
524 
525 	return 0;
526 }
527 
528 void
529 vlan_vlandev_state(void *v)
530 {
531 	struct ifvlan *ifv = v;
532 
533 	if (ifv->ifv_if.if_link_state == ifv->ifv_p->if_link_state)
534 		return;
535 
536 	ifv->ifv_if.if_link_state = ifv->ifv_p->if_link_state;
537 	ifv->ifv_if.if_baudrate = ifv->ifv_p->if_baudrate;
538 	if_link_state_change(&ifv->ifv_if);
539 }
540 
541 int
542 vlan_set_promisc(struct ifnet *ifp)
543 {
544 	struct ifvlan *ifv = ifp->if_softc;
545 	int error = 0;
546 
547 	if ((ifp->if_flags & IFF_PROMISC) != 0) {
548 		if ((ifv->ifv_flags & IFVF_PROMISC) == 0) {
549 			error = ifpromisc(ifv->ifv_p, 1);
550 			if (error == 0)
551 				ifv->ifv_flags |= IFVF_PROMISC;
552 		}
553 	} else {
554 		if ((ifv->ifv_flags & IFVF_PROMISC) != 0) {
555 			error = ifpromisc(ifv->ifv_p, 0);
556 			if (error == 0)
557 				ifv->ifv_flags &= ~IFVF_PROMISC;
558 		}
559 	}
560 
561 	return (0);
562 }
563 
564 int
565 vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
566 {
567 	struct proc *p = curproc;	/* XXX */
568 	struct ifaddr *ifa;
569 	struct ifnet *pr;
570 	struct ifreq *ifr;
571 	struct ifvlan *ifv;
572 	struct vlanreq vlr;
573 	int error = 0, p_mtu = 0, s;
574 
575 	ifr = (struct ifreq *)data;
576 	ifa = (struct ifaddr *)data;
577 	ifv = ifp->if_softc;
578 
579 	switch (cmd) {
580 	case SIOCSIFADDR:
581 		if (ifv->ifv_p != NULL) {
582 			ifp->if_flags |= IFF_UP;
583 
584 			switch (ifa->ifa_addr->sa_family) {
585 #ifdef INET
586 			case AF_INET:
587 				arp_ifinit(&ifv->ifv_ac, ifa);
588 				break;
589 #endif
590 			default:
591 				break;
592 			}
593 		} else {
594 			error = EINVAL;
595 		}
596 		break;
597 
598 	case SIOCGIFADDR:
599 		{
600 			struct sockaddr *sa;
601 
602 			sa = (struct sockaddr *) &ifr->ifr_data;
603 			bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
604 			    (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
605 		}
606 		break;
607 
608 	case SIOCSIFMTU:
609 		if (ifv->ifv_p != NULL) {
610 			if (ifv->ifv_p->if_capabilities & IFCAP_VLAN_MTU)
611 				p_mtu = ifv->ifv_p->if_mtu;
612 			else
613 				p_mtu = ifv->ifv_p->if_mtu - EVL_ENCAPLEN;
614 
615 			if (ifr->ifr_mtu > p_mtu || ifr->ifr_mtu < ETHERMIN)
616 				error = EINVAL;
617 			else
618 				ifp->if_mtu = ifr->ifr_mtu;
619 		} else
620 			error = EINVAL;
621 
622 		break;
623 
624 	case SIOCSETVLAN:
625 		if ((error = suser(p, 0)) != 0)
626 			break;
627 		if ((error = copyin(ifr->ifr_data, &vlr, sizeof vlr)))
628 			break;
629 		if (vlr.vlr_parent[0] == '\0') {
630 			s = splnet();
631 			vlan_unconfig(ifp, NULL);
632 			if (ifp->if_flags & IFF_UP)
633 				if_down(ifp);
634 			ifp->if_flags &= ~IFF_RUNNING;
635 			splx(s);
636 			break;
637 		}
638 		pr = ifunit(vlr.vlr_parent);
639 		if (pr == NULL) {
640 			error = ENOENT;
641 			break;
642 		}
643 		/*
644 		 * Don't let the caller set up a VLAN tag with
645 		 * anything except VLID bits.
646 		 */
647 		if (vlr.vlr_tag & ~EVL_VLID_MASK) {
648 			error = EINVAL;
649 			break;
650 		}
651 		error = vlan_config(ifv, pr, vlr.vlr_tag);
652 		if (error)
653 			break;
654 		ifp->if_flags |= IFF_RUNNING;
655 
656 		/* Update promiscuous mode, if necessary. */
657 		vlan_set_promisc(ifp);
658 		break;
659 
660 	case SIOCGETVLAN:
661 		bzero(&vlr, sizeof vlr);
662 		if (ifv->ifv_p) {
663 			snprintf(vlr.vlr_parent, sizeof(vlr.vlr_parent),
664 			    "%s", ifv->ifv_p->if_xname);
665 			vlr.vlr_tag = ifv->ifv_tag;
666 		}
667 		error = copyout(&vlr, ifr->ifr_data, sizeof vlr);
668 		break;
669 	case SIOCSIFFLAGS:
670 		/*
671 		 * For promiscuous mode, we enable promiscuous mode on
672 		 * the parent if we need promiscuous on the VLAN interface.
673 		 */
674 		if (ifv->ifv_p != NULL)
675 			error = vlan_set_promisc(ifp);
676 		break;
677 
678 	case SIOCADDMULTI:
679 		error = (ifv->ifv_p != NULL) ?
680 		    vlan_ether_addmulti(ifv, ifr) : EINVAL;
681 		break;
682 
683 	case SIOCDELMULTI:
684 		error = (ifv->ifv_p != NULL) ?
685 		    vlan_ether_delmulti(ifv, ifr) : EINVAL;
686 		break;
687 	default:
688 		error = ENOTTY;
689 	}
690 	return error;
691 }
692 
693 
694 int
695 vlan_ether_addmulti(struct ifvlan *ifv, struct ifreq *ifr)
696 {
697 	struct ifnet *ifp = ifv->ifv_p;		/* Parent. */
698 	struct vlan_mc_entry *mc;
699 	u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
700 	int error;
701 
702 	/* XXX: sa_len is too small for such comparison
703 	if (ifr->ifr_addr.sa_len > sizeof(struct sockaddr_storage))
704 		return (EINVAL);
705 	*/
706 
707 	error = ether_addmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
708 	if (error != ENETRESET)
709 		return (error);
710 
711 	/*
712 	 * This is new multicast address.  We have to tell parent
713 	 * about it.  Also, remember this multicast address so that
714 	 * we can delete them on unconfigure.
715 	 */
716 	mc = malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT);
717 	if (mc == NULL) {
718 		error = ENOMEM;
719 		goto alloc_failed;
720 	}
721 
722 	/*
723 	 * As ether_addmulti() returns ENETRESET, following two
724 	 * statement shouldn't fail.
725 	 */
726 	(void)ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi);
727 	ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, mc->mc_enm);
728 	memcpy(&mc->mc_addr, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
729 	LIST_INSERT_HEAD(&ifv->vlan_mc_listhead, mc, mc_entries);
730 
731 	error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)ifr);
732 	if (error != 0)
733 		goto ioctl_failed;
734 
735 	return (error);
736 
737  ioctl_failed:
738 	LIST_REMOVE(mc, mc_entries);
739 	free(mc, M_DEVBUF);
740  alloc_failed:
741 	(void)ether_delmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
742 
743 	return (error);
744 }
745 
746 int
747 vlan_ether_delmulti(struct ifvlan *ifv, struct ifreq *ifr)
748 {
749 	struct ifnet *ifp = ifv->ifv_p;		/* Parent. */
750 	struct ether_multi *enm;
751 	struct vlan_mc_entry *mc;
752 	u_int8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN];
753 	int error;
754 
755 	/*
756 	 * Find a key to lookup vlan_mc_entry.  We have to do this
757 	 * before calling ether_delmulti for obvious reason.
758 	 */
759 	if ((error = ether_multiaddr(&ifr->ifr_addr, addrlo, addrhi)) != 0)
760 		return (error);
761 	ETHER_LOOKUP_MULTI(addrlo, addrhi, &ifv->ifv_ac, enm);
762 	if (enm == NULL)
763 		return (EINVAL);
764 
765 	LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries)
766 		if (mc->mc_enm == enm)
767 			break;
768 
769 	/* We won't delete entries we didn't add */
770 	if (mc == NULL)
771 		return (EINVAL);
772 
773 	error = ether_delmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
774 	if (error != ENETRESET)
775 		return (error);
776 
777 	/* We no longer use this multicast address.  Tell parent so. */
778 	error = (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
779 	if (error == 0) {
780 		/* And forget about this address. */
781 		LIST_REMOVE(mc, mc_entries);
782 		free(mc, M_DEVBUF);
783 	} else
784 		(void)ether_addmulti(ifr, (struct arpcom *)&ifv->ifv_ac);
785 	return (error);
786 }
787 
788 /*
789  * Delete any multicast address we have asked to add from parent
790  * interface.  Called when the vlan is being unconfigured.
791  */
792 void
793 vlan_ether_purgemulti(struct ifvlan *ifv)
794 {
795 	struct ifnet *ifp = ifv->ifv_p;		/* Parent. */
796 	struct vlan_mc_entry *mc;
797 	union {
798 		struct ifreq ifreq;
799 		struct {
800 			char ifr_name[IFNAMSIZ];
801 			struct sockaddr_storage ifr_ss;
802 		} ifreq_storage;
803 	} ifreq;
804 	struct ifreq *ifr = &ifreq.ifreq;
805 
806 	memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
807 	while ((mc = LIST_FIRST(&ifv->vlan_mc_listhead)) != NULL) {
808 		memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
809 		(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
810 		LIST_REMOVE(mc, mc_entries);
811 		free(mc, M_DEVBUF);
812 	}
813 }
814 
815 void
816 vlan_ether_resetmulti(struct ifvlan *ifv, struct ifnet *p)
817 {
818 	struct ifnet *ifp = ifv->ifv_p;		/* Parent. */
819 	struct vlan_mc_entry *mc;
820 	union {
821 		struct ifreq ifreq;
822 		struct {
823 			char ifr_name[IFNAMSIZ];
824 			struct sockaddr_storage ifr_ss;
825 		} ifreq_storage;
826 	} ifreq;
827 	struct ifreq *ifr = &ifreq.ifreq;
828 
829 	if (p == NULL) {
830 		vlan_ether_purgemulti(ifv);
831 		return;
832 	} else if (ifp == p)
833 		return;
834 
835 	LIST_FOREACH(mc, &ifv->vlan_mc_listhead, mc_entries) {
836 		memcpy(&ifr->ifr_addr, &mc->mc_addr, mc->mc_addr.ss_len);
837 
838 		/* Remove from the old parent */
839 		memcpy(ifr->ifr_name, ifp->if_xname, IFNAMSIZ);
840 		(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)ifr);
841 
842 		/* Try to add to the new parent */
843 		memcpy(ifr->ifr_name, p->if_xname, IFNAMSIZ);
844 		(void)(*p->if_ioctl)(p, SIOCADDMULTI, (caddr_t)ifr);
845 	}
846 }
847