xref: /netbsd-src/sys/net/if_l2tp.c (revision 87d689fb734c654d2486f87f7be32f1b53ecdbec)
1 /*	$NetBSD: if_l2tp.c,v 1.17 2017/12/19 03:32:35 ozaki-r Exp $	*/
2 
3 /*
4  * Copyright (c) 2017 Internet Initiative Japan Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * L2TPv3 kernel interface
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: if_l2tp.c,v 1.17 2017/12/19 03:32:35 ozaki-r Exp $");
35 
36 #ifdef _KERNEL_OPT
37 #include "opt_inet.h"
38 #include "opt_net_mpsafe.h"
39 #endif
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/mbuf.h>
45 #include <sys/socket.h>
46 #include <sys/sockio.h>
47 #include <sys/errno.h>
48 #include <sys/ioctl.h>
49 #include <sys/time.h>
50 #include <sys/syslog.h>
51 #include <sys/proc.h>
52 #include <sys/conf.h>
53 #include <sys/kauth.h>
54 #include <sys/cpu.h>
55 #include <sys/cprng.h>
56 #include <sys/intr.h>
57 #include <sys/kmem.h>
58 #include <sys/mutex.h>
59 #include <sys/atomic.h>
60 #include <sys/pserialize.h>
61 #include <sys/device.h>
62 #include <sys/module.h>
63 
64 #include <net/if.h>
65 #include <net/if_dl.h>
66 #include <net/if_ether.h>
67 #include <net/if_types.h>
68 #include <net/netisr.h>
69 #include <net/route.h>
70 #include <net/bpf.h>
71 #include <net/if_vlanvar.h>
72 
73 #include <netinet/in.h>
74 #include <netinet/in_systm.h>
75 #include <netinet/ip.h>
76 #include <netinet/ip_encap.h>
77 #ifdef	INET
78 #include <netinet/in_var.h>
79 #include <netinet/in_l2tp.h>
80 #endif	/* INET */
81 #ifdef INET6
82 #include <netinet6/in6_l2tp.h>
83 #endif
84 
85 #include <net/if_l2tp.h>
86 
87 #include <net/if_vlanvar.h>
88 
89 /* TODO: IP_TCPMSS support */
90 #undef IP_TCPMSS
91 #ifdef IP_TCPMSS
92 #include <netinet/ip_tcpmss.h>
93 #endif
94 
95 #include <net/bpf.h>
96 #include <net/net_osdep.h>
97 
98 /*
99  * l2tp global variable definitions
100  */
101 LIST_HEAD(l2tp_sclist, l2tp_softc);
102 static struct {
103 	struct l2tp_sclist list;
104 	kmutex_t lock;
105 } l2tp_softcs __cacheline_aligned;
106 
107 
108 #if !defined(L2TP_ID_HASH_SIZE)
109 #define L2TP_ID_HASH_SIZE 64
110 #endif
111 static struct {
112 	kmutex_t lock;
113 	struct pslist_head *lists;
114 	u_long mask;
115 } l2tp_hash __cacheline_aligned = {
116 	.lists = NULL,
117 };
118 
119 pserialize_t l2tp_psz __read_mostly;
120 struct psref_class *lv_psref_class __read_mostly;
121 
122 static void	l2tp_ro_init_pc(void *, void *, struct cpu_info *);
123 static void	l2tp_ro_fini_pc(void *, void *, struct cpu_info *);
124 
125 static int	l2tp_clone_create(struct if_clone *, int);
126 static int	l2tp_clone_destroy(struct ifnet *);
127 
128 struct if_clone l2tp_cloner =
129     IF_CLONE_INITIALIZER("l2tp", l2tp_clone_create, l2tp_clone_destroy);
130 
131 static int	l2tp_output(struct ifnet *, struct mbuf *,
132 		    const struct sockaddr *, const struct rtentry *);
133 static void	l2tpintr(struct l2tp_variant *);
134 
135 static void	l2tp_hash_init(void);
136 static int	l2tp_hash_fini(void);
137 
138 static void	l2tp_start(struct ifnet *);
139 static int	l2tp_transmit(struct ifnet *, struct mbuf *);
140 
141 static int	l2tp_set_tunnel(struct ifnet *, struct sockaddr *,
142 		    struct sockaddr *);
143 static void	l2tp_delete_tunnel(struct ifnet *);
144 
145 static int	id_hash_func(uint32_t, u_long);
146 
147 static void	l2tp_variant_update(struct l2tp_softc *, struct l2tp_variant *);
148 static int	l2tp_set_session(struct l2tp_softc *, uint32_t, uint32_t);
149 static int	l2tp_clear_session(struct l2tp_softc *);
150 static int	l2tp_set_cookie(struct l2tp_softc *, uint64_t, u_int, uint64_t, u_int);
151 static void	l2tp_clear_cookie(struct l2tp_softc *);
152 static void	l2tp_set_state(struct l2tp_softc *, int);
153 static int	l2tp_encap_attach(struct l2tp_variant *);
154 static int	l2tp_encap_detach(struct l2tp_variant *);
155 
156 #ifndef MAX_L2TP_NEST
157 /*
158  * This macro controls the upper limitation on nesting of l2tp tunnels.
159  * Since, setting a large value to this macro with a careless configuration
160  * may introduce system crash, we don't allow any nestings by default.
161  * If you need to configure nested l2tp tunnels, you can define this macro
162  * in your kernel configuration file.  However, if you do so, please be
163  * careful to configure the tunnels so that it won't make a loop.
164  */
165 /*
166  * XXX
167  * Currently, if in_l2tp_output recursively calls, it causes locking against
168  * myself of struct l2tp_ro->lr_lock. So, nested l2tp tunnels is prohibited.
169  */
170 #define MAX_L2TP_NEST 0
171 #endif
172 
173 static int max_l2tp_nesting = MAX_L2TP_NEST;
174 
175 /* ARGSUSED */
176 void
177 l2tpattach(int count)
178 {
179 	/*
180 	 * Nothing to do here, initialization is handled by the
181 	 * module initialization code in l2tpinit() below).
182 	 */
183 }
184 
185 static void
186 l2tpinit(void)
187 {
188 
189 	mutex_init(&l2tp_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
190 	LIST_INIT(&l2tp_softcs.list);
191 
192 	mutex_init(&l2tp_hash.lock, MUTEX_DEFAULT, IPL_NONE);
193 	l2tp_psz = pserialize_create();
194 	lv_psref_class = psref_class_create("l2tpvar", IPL_SOFTNET);
195 	if_clone_attach(&l2tp_cloner);
196 
197 	l2tp_hash_init();
198 }
199 
200 static int
201 l2tpdetach(void)
202 {
203 	int error;
204 
205 	mutex_enter(&l2tp_softcs.lock);
206 	if (!LIST_EMPTY(&l2tp_softcs.list)) {
207 		mutex_exit(&l2tp_softcs.lock);
208 		return EBUSY;
209 	}
210 	mutex_exit(&l2tp_softcs.lock);
211 
212 	error = l2tp_hash_fini();
213 	if (error)
214 		return error;
215 
216 	if_clone_detach(&l2tp_cloner);
217 	psref_class_destroy(lv_psref_class);
218 	pserialize_destroy(l2tp_psz);
219 	mutex_destroy(&l2tp_hash.lock);
220 
221 	mutex_destroy(&l2tp_softcs.lock);
222 
223 	return error;
224 }
225 
226 static int
227 l2tp_clone_create(struct if_clone *ifc, int unit)
228 {
229 	struct l2tp_softc *sc;
230 	struct l2tp_variant *var;
231 	int rv;
232 
233 	sc = kmem_zalloc(sizeof(struct l2tp_softc), KM_SLEEP);
234 	if_initname(&sc->l2tp_ec.ec_if, ifc->ifc_name, unit);
235 	rv = l2tpattach0(sc);
236 	if (rv != 0) {
237 		kmem_free(sc, sizeof(struct l2tp_softc));
238 		return rv;
239 	}
240 
241 	var = kmem_zalloc(sizeof(struct l2tp_variant), KM_SLEEP);
242 	var->lv_softc = sc;
243 	var->lv_state = L2TP_STATE_DOWN;
244 	var->lv_use_cookie = L2TP_COOKIE_OFF;
245 	psref_target_init(&var->lv_psref, lv_psref_class);
246 
247 	sc->l2tp_var = var;
248 	mutex_init(&sc->l2tp_lock, MUTEX_DEFAULT, IPL_NONE);
249 	PSLIST_ENTRY_INIT(sc, l2tp_hash);
250 
251 	sc->l2tp_ro_percpu = percpu_alloc(sizeof(struct l2tp_ro));
252 	percpu_foreach(sc->l2tp_ro_percpu, l2tp_ro_init_pc, NULL);
253 
254 	mutex_enter(&l2tp_softcs.lock);
255 	LIST_INSERT_HEAD(&l2tp_softcs.list, sc, l2tp_list);
256 	mutex_exit(&l2tp_softcs.lock);
257 
258 	return (0);
259 }
260 
261 int
262 l2tpattach0(struct l2tp_softc *sc)
263 {
264 	int rv;
265 
266 	sc->l2tp_ec.ec_if.if_addrlen = 0;
267 	sc->l2tp_ec.ec_if.if_mtu    = L2TP_MTU;
268 	sc->l2tp_ec.ec_if.if_flags  = IFF_POINTOPOINT|IFF_MULTICAST|IFF_SIMPLEX;
269 	sc->l2tp_ec.ec_if.if_extflags = IFEF_NO_LINK_STATE_CHANGE;
270 #ifdef NET_MPSAFE
271 	sc->l2tp_ec.ec_if.if_extflags |= IFEF_MPSAFE;
272 #endif
273 	sc->l2tp_ec.ec_if.if_ioctl  = l2tp_ioctl;
274 	sc->l2tp_ec.ec_if.if_output = l2tp_output;
275 	sc->l2tp_ec.ec_if.if_type   = IFT_L2TP;
276 	sc->l2tp_ec.ec_if.if_dlt    = DLT_NULL;
277 	sc->l2tp_ec.ec_if.if_start  = l2tp_start;
278 	sc->l2tp_ec.ec_if.if_transmit = l2tp_transmit;
279 	sc->l2tp_ec.ec_if._if_input = ether_input;
280 	IFQ_SET_READY(&sc->l2tp_ec.ec_if.if_snd);
281 	/* XXX
282 	 * It may improve performance to use if_initialize()/if_register()
283 	 * so that l2tp_input() calls if_input() instead of
284 	 * if_percpuq_enqueue(). However, that causes recursive softnet_lock
285 	 * when NET_MPSAFE is not set.
286 	 */
287 	rv = if_attach(&sc->l2tp_ec.ec_if);
288 	if (rv != 0)
289 		return rv;
290 	if_alloc_sadl(&sc->l2tp_ec.ec_if);
291 	bpf_attach(&sc->l2tp_ec.ec_if, DLT_EN10MB, sizeof(struct ether_header));
292 
293 	return 0;
294 }
295 
296 void
297 l2tp_ro_init_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
298 {
299 	struct l2tp_ro *lro = p;
300 
301 	mutex_init(&lro->lr_lock, MUTEX_DEFAULT, IPL_NONE);
302 }
303 
304 void
305 l2tp_ro_fini_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
306 {
307 	struct l2tp_ro *lro = p;
308 
309 	rtcache_free(&lro->lr_ro);
310 
311 	mutex_destroy(&lro->lr_lock);
312 }
313 
314 static int
315 l2tp_clone_destroy(struct ifnet *ifp)
316 {
317 	struct l2tp_variant *var;
318 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
319 	    l2tp_ec.ec_if);
320 
321 	l2tp_clear_session(sc);
322 	l2tp_delete_tunnel(&sc->l2tp_ec.ec_if);
323 	/*
324 	 * To avoid for l2tp_transmit() to access sc->l2tp_var after free it.
325 	 */
326 	mutex_enter(&sc->l2tp_lock);
327 	var = sc->l2tp_var;
328 	l2tp_variant_update(sc, NULL);
329 	mutex_exit(&sc->l2tp_lock);
330 
331 	mutex_enter(&l2tp_softcs.lock);
332 	LIST_REMOVE(sc, l2tp_list);
333 	mutex_exit(&l2tp_softcs.lock);
334 
335 	bpf_detach(ifp);
336 
337 	if_detach(ifp);
338 
339 	percpu_foreach(sc->l2tp_ro_percpu, l2tp_ro_fini_pc, NULL);
340 	percpu_free(sc->l2tp_ro_percpu, sizeof(struct l2tp_ro));
341 
342 	kmem_free(var, sizeof(struct l2tp_variant));
343 	mutex_destroy(&sc->l2tp_lock);
344 	kmem_free(sc, sizeof(struct l2tp_softc));
345 
346 	return 0;
347 }
348 
349 static int
350 l2tp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
351     const struct rtentry *rt)
352 {
353 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
354 	    l2tp_ec.ec_if);
355 	struct l2tp_variant *var;
356 	struct psref psref;
357 	int error = 0;
358 
359 	var = l2tp_getref_variant(sc, &psref);
360 	if (var == NULL) {
361 		m_freem(m);
362 		return ENETDOWN;
363 	}
364 
365 	IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
366 
367 	m->m_flags &= ~(M_BCAST|M_MCAST);
368 
369 	if ((ifp->if_flags & IFF_UP) == 0) {
370 		m_freem(m);
371 		error = ENETDOWN;
372 		goto end;
373 	}
374 
375 	if (var->lv_psrc == NULL || var->lv_pdst == NULL) {
376 		m_freem(m);
377 		error = ENETDOWN;
378 		goto end;
379 	}
380 
381 	/* XXX should we check if our outer source is legal? */
382 
383 	/* use DLT_NULL encapsulation here to pass inner af type */
384 	M_PREPEND(m, sizeof(int), M_DONTWAIT);
385 	if (!m) {
386 		error = ENOBUFS;
387 		goto end;
388 	}
389 	*mtod(m, int *) = dst->sa_family;
390 
391 	IFQ_ENQUEUE(&ifp->if_snd, m, error);
392 	if (error)
393 		goto end;
394 
395 	/*
396 	 * direct call to avoid infinite loop at l2tpintr()
397 	 */
398 	l2tpintr(var);
399 
400 	error = 0;
401 
402 end:
403 	l2tp_putref_variant(var, &psref);
404 	if (error)
405 		ifp->if_oerrors++;
406 
407 	return error;
408 }
409 
410 static void
411 l2tpintr(struct l2tp_variant *var)
412 {
413 	struct l2tp_softc *sc;
414 	struct ifnet *ifp;
415 	struct mbuf *m;
416 	int error;
417 
418 	KASSERT(psref_held(&var->lv_psref, lv_psref_class));
419 
420 	sc = var->lv_softc;
421 	ifp = &sc->l2tp_ec.ec_if;
422 
423 	/* output processing */
424 	if (var->lv_my_sess_id == 0 || var->lv_peer_sess_id == 0) {
425 		IFQ_PURGE(&ifp->if_snd);
426 		return;
427 	}
428 
429 	for (;;) {
430 		IFQ_DEQUEUE(&ifp->if_snd, m);
431 		if (m == NULL)
432 			break;
433 		m->m_flags &= ~(M_BCAST|M_MCAST);
434 		bpf_mtap(ifp, m);
435 		switch (var->lv_psrc->sa_family) {
436 #ifdef INET
437 		case AF_INET:
438 			error = in_l2tp_output(var, m);
439 			break;
440 #endif
441 #ifdef INET6
442 		case AF_INET6:
443 			error = in6_l2tp_output(var, m);
444 			break;
445 #endif
446 		default:
447 			m_freem(m);
448 			error = ENETDOWN;
449 			break;
450 		}
451 
452 		if (error)
453 			ifp->if_oerrors++;
454 		else {
455 			ifp->if_opackets++;
456 			/*
457 			 * obytes is incremented at ether_output() or
458 			 * bridge_enqueue().
459 			 */
460 		}
461 	}
462 
463 }
464 
465 void
466 l2tp_input(struct mbuf *m, struct ifnet *ifp)
467 {
468 
469 	KASSERT(ifp != NULL);
470 
471 	if (0 == (mtod(m, u_long) & 0x03)) {
472 		/* copy and align head of payload */
473 		struct mbuf *m_head;
474 		int copy_length;
475 
476 #define L2TP_COPY_LENGTH		60
477 #define L2TP_LINK_HDR_ROOM	(MHLEN - L2TP_COPY_LENGTH - 4/*round4(2)*/)
478 
479 		if (m->m_pkthdr.len < L2TP_COPY_LENGTH) {
480 			copy_length = m->m_pkthdr.len;
481 		} else {
482 			copy_length = L2TP_COPY_LENGTH;
483 		}
484 
485 		if (m->m_len < copy_length) {
486 			m = m_pullup(m, copy_length);
487 			if (m == NULL)
488 				return;
489 		}
490 
491 		MGETHDR(m_head, M_DONTWAIT, MT_HEADER);
492 		if (m_head == NULL) {
493 			m_freem(m);
494 			return;
495 		}
496 		M_COPY_PKTHDR(m_head, m);
497 
498 		m_head->m_data += 2 /* align */ + L2TP_LINK_HDR_ROOM;
499 		memcpy(m_head->m_data, m->m_data, copy_length);
500 		m_head->m_len = copy_length;
501 		m->m_data += copy_length;
502 		m->m_len -= copy_length;
503 
504 		/* construct chain */
505 		if (m->m_len == 0) {
506 			m_head->m_next = m_free(m); /* not m_freem */
507 		} else {
508 			/*
509 			 * copyed mtag in previous call M_COPY_PKTHDR
510 			 * but don't delete mtag in case cutt of M_PKTHDR flag
511 			 */
512 			m_tag_delete_chain(m, NULL);
513 			m->m_flags &= ~M_PKTHDR;
514 			m_head->m_next = m;
515 		}
516 
517 		/* override m */
518 		m = m_head;
519 	}
520 
521 	m_set_rcvif(m, ifp);
522 
523 	/*
524 	 * bpf_mtap() and ifp->if_ipackets++ is done in if_input()
525 	 *
526 	 * obytes is incremented at ether_output() or bridge_enqueue().
527 	 */
528 	if_percpuq_enqueue(ifp->if_percpuq, m);
529 }
530 
531 void
532 l2tp_start(struct ifnet *ifp)
533 {
534 	struct psref psref;
535 	struct l2tp_variant *var;
536 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
537 	    l2tp_ec.ec_if);
538 
539 	var = l2tp_getref_variant(sc, &psref);
540 	if (var == NULL)
541 		return;
542 
543 	if (var->lv_psrc == NULL || var->lv_pdst == NULL)
544 		return;
545 
546 	l2tpintr(var);
547 	l2tp_putref_variant(var, &psref);
548 }
549 
550 int
551 l2tp_transmit(struct ifnet *ifp, struct mbuf *m)
552 {
553 	int error;
554 	struct psref psref;
555 	struct l2tp_variant *var;
556 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
557 	    l2tp_ec.ec_if);
558 
559 	var = l2tp_getref_variant(sc, &psref);
560 	if (var == NULL) {
561 		m_freem(m);
562 		return ENETDOWN;
563 	}
564 
565 	if (var->lv_psrc == NULL || var->lv_pdst == NULL) {
566 		m_freem(m);
567 		error = ENETDOWN;
568 		goto out;
569 	}
570 
571 	m->m_flags &= ~(M_BCAST|M_MCAST);
572 	bpf_mtap(ifp, m);
573 	switch (var->lv_psrc->sa_family) {
574 #ifdef INET
575 	case AF_INET:
576 		error = in_l2tp_output(var, m);
577 		break;
578 #endif
579 #ifdef INET6
580 	case AF_INET6:
581 		error = in6_l2tp_output(var, m);
582 		break;
583 #endif
584 	default:
585 		m_freem(m);
586 		error = ENETDOWN;
587 		break;
588 	}
589 
590 	if (error)
591 		ifp->if_oerrors++;
592 	else {
593 		ifp->if_opackets++;
594 		/*
595 		 * obytes is incremented at ether_output() or bridge_enqueue().
596 		 */
597 	}
598 
599 out:
600 	l2tp_putref_variant(var, &psref);
601 	return error;
602 }
603 
604 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */
605 int
606 l2tp_ioctl(struct ifnet *ifp, u_long cmd, void *data)
607 {
608 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
609 	    l2tp_ec.ec_if);
610 	struct l2tp_variant *var, *var_tmp;
611 	struct ifreq     *ifr = data;
612 	int error = 0, size;
613 	struct sockaddr *dst, *src;
614 	struct l2tp_req l2tpr;
615 	u_long mtu;
616 	int bound;
617 	struct psref psref;
618 
619 	switch (cmd) {
620 	case SIOCSIFADDR:
621 		ifp->if_flags |= IFF_UP;
622 		break;
623 
624 	case SIOCSIFDSTADDR:
625 		break;
626 
627 	case SIOCADDMULTI:
628 	case SIOCDELMULTI:
629 		switch (ifr->ifr_addr.sa_family) {
630 #ifdef INET
631 		case AF_INET:	/* IP supports Multicast */
632 			break;
633 #endif /* INET */
634 #ifdef INET6
635 		case AF_INET6:	/* IP6 supports Multicast */
636 			break;
637 #endif /* INET6 */
638 		default:  /* Other protocols doesn't support Multicast */
639 			error = EAFNOSUPPORT;
640 			break;
641 		}
642 		break;
643 
644 	case SIOCSIFMTU:
645 		mtu = ifr->ifr_mtu;
646 		if (mtu < L2TP_MTU_MIN || mtu > L2TP_MTU_MAX)
647 			return (EINVAL);
648 		ifp->if_mtu = mtu;
649 		break;
650 
651 #ifdef INET
652 	case SIOCSIFPHYADDR:
653 		src = (struct sockaddr *)
654 			&(((struct in_aliasreq *)data)->ifra_addr);
655 		dst = (struct sockaddr *)
656 			&(((struct in_aliasreq *)data)->ifra_dstaddr);
657 		if (src->sa_family != AF_INET || dst->sa_family != AF_INET)
658 			return EAFNOSUPPORT;
659 		else if (src->sa_len != sizeof(struct sockaddr_in)
660 		    || dst->sa_len != sizeof(struct sockaddr_in))
661 			return EINVAL;
662 
663 		error = l2tp_set_tunnel(&sc->l2tp_ec.ec_if, src, dst);
664 		break;
665 
666 #endif /* INET */
667 #ifdef INET6
668 	case SIOCSIFPHYADDR_IN6:
669 		src = (struct sockaddr *)
670 			&(((struct in6_aliasreq *)data)->ifra_addr);
671 		dst = (struct sockaddr *)
672 			&(((struct in6_aliasreq *)data)->ifra_dstaddr);
673 		if (src->sa_family != AF_INET6 || dst->sa_family != AF_INET6)
674 			return EAFNOSUPPORT;
675 		else if (src->sa_len != sizeof(struct sockaddr_in6)
676 		    || dst->sa_len != sizeof(struct sockaddr_in6))
677 			return EINVAL;
678 
679 		error = l2tp_set_tunnel(&sc->l2tp_ec.ec_if, src, dst);
680 		break;
681 
682 #endif /* INET6 */
683 	case SIOCSLIFPHYADDR:
684 		src = (struct sockaddr *)
685 			&(((struct if_laddrreq *)data)->addr);
686 		dst = (struct sockaddr *)
687 			&(((struct if_laddrreq *)data)->dstaddr);
688 		if (src->sa_family != dst->sa_family)
689 			return EINVAL;
690 		else if (src->sa_family == AF_INET
691 		    && src->sa_len != sizeof(struct sockaddr_in))
692 			return EINVAL;
693 		else if (src->sa_family == AF_INET6
694 		    && src->sa_len != sizeof(struct sockaddr_in6))
695 			return EINVAL;
696 		else if (dst->sa_family == AF_INET
697 		    && dst->sa_len != sizeof(struct sockaddr_in))
698 			return EINVAL;
699 		else if (dst->sa_family == AF_INET6
700 		    && dst->sa_len != sizeof(struct sockaddr_in6))
701 			return EINVAL;
702 
703 		error = l2tp_set_tunnel(&sc->l2tp_ec.ec_if, src, dst);
704 		break;
705 
706 	case SIOCDIFPHYADDR:
707 		l2tp_delete_tunnel(&sc->l2tp_ec.ec_if);
708 		break;
709 
710 	case SIOCGIFPSRCADDR:
711 #ifdef INET6
712 	case SIOCGIFPSRCADDR_IN6:
713 #endif /* INET6 */
714 		bound = curlwp_bind();
715 		var = l2tp_getref_variant(sc, &psref);
716 		if (var == NULL) {
717 			curlwp_bindx(bound);
718 			error = EADDRNOTAVAIL;
719 			goto bad;
720 		}
721 		if (var->lv_psrc == NULL) {
722 			l2tp_putref_variant(var, &psref);
723 			curlwp_bindx(bound);
724 			error = EADDRNOTAVAIL;
725 			goto bad;
726 		}
727 		src = var->lv_psrc;
728 		switch (cmd) {
729 #ifdef INET
730 		case SIOCGIFPSRCADDR:
731 			dst = &ifr->ifr_addr;
732 			size = sizeof(ifr->ifr_addr);
733 			break;
734 #endif /* INET */
735 #ifdef INET6
736 		case SIOCGIFPSRCADDR_IN6:
737 			dst = (struct sockaddr *)
738 				&(((struct in6_ifreq *)data)->ifr_addr);
739 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
740 			break;
741 #endif /* INET6 */
742 		default:
743 			l2tp_putref_variant(var, &psref);
744 			curlwp_bindx(bound);
745 			error = EADDRNOTAVAIL;
746 			goto bad;
747 		}
748 		if (src->sa_len > size) {
749 			l2tp_putref_variant(var, &psref);
750 			curlwp_bindx(bound);
751 			return EINVAL;
752 		}
753 		sockaddr_copy(dst, src->sa_len, src);
754 		l2tp_putref_variant(var, &psref);
755 		curlwp_bindx(bound);
756 		break;
757 
758 	case SIOCGIFPDSTADDR:
759 #ifdef INET6
760 	case SIOCGIFPDSTADDR_IN6:
761 #endif /* INET6 */
762 		bound = curlwp_bind();
763 		var = l2tp_getref_variant(sc, &psref);
764 		if (var == NULL) {
765 			curlwp_bindx(bound);
766 			error = EADDRNOTAVAIL;
767 			goto bad;
768 		}
769 		if (var->lv_pdst == NULL) {
770 			l2tp_putref_variant(var, &psref);
771 			curlwp_bindx(bound);
772 			error = EADDRNOTAVAIL;
773 			goto bad;
774 		}
775 		src = var->lv_pdst;
776 		switch (cmd) {
777 #ifdef INET
778 		case SIOCGIFPDSTADDR:
779 			dst = &ifr->ifr_addr;
780 			size = sizeof(ifr->ifr_addr);
781 			break;
782 #endif /* INET */
783 #ifdef INET6
784 		case SIOCGIFPDSTADDR_IN6:
785 			dst = (struct sockaddr *)
786 				&(((struct in6_ifreq *)data)->ifr_addr);
787 			size = sizeof(((struct in6_ifreq *)data)->ifr_addr);
788 			break;
789 #endif /* INET6 */
790 		default:
791 			l2tp_putref_variant(var, &psref);
792 			curlwp_bindx(bound);
793 			error = EADDRNOTAVAIL;
794 			goto bad;
795 		}
796 		if (src->sa_len > size) {
797 			l2tp_putref_variant(var, &psref);
798 			curlwp_bindx(bound);
799 			return EINVAL;
800 		}
801 		sockaddr_copy(dst, src->sa_len, src);
802 		l2tp_putref_variant(var, &psref);
803 		curlwp_bindx(bound);
804 		break;
805 
806 	case SIOCGLIFPHYADDR:
807 		bound = curlwp_bind();
808 		var = l2tp_getref_variant(sc, &psref);
809 		if (var == NULL) {
810 			curlwp_bindx(bound);
811 			error = EADDRNOTAVAIL;
812 			goto bad;
813 		}
814 		if (var->lv_psrc == NULL || var->lv_pdst == NULL) {
815 			l2tp_putref_variant(var, &psref);
816 			curlwp_bindx(bound);
817 			error = EADDRNOTAVAIL;
818 			goto bad;
819 		}
820 
821 		/* copy src */
822 		src = var->lv_psrc;
823 		dst = (struct sockaddr *)
824 			&(((struct if_laddrreq *)data)->addr);
825 		size = sizeof(((struct if_laddrreq *)data)->addr);
826 		if (src->sa_len > size) {
827 			l2tp_putref_variant(var, &psref);
828 			curlwp_bindx(bound);
829 			return EINVAL;
830                 }
831 		sockaddr_copy(dst, src->sa_len, src);
832 
833 		/* copy dst */
834 		src = var->lv_pdst;
835 		dst = (struct sockaddr *)
836 			&(((struct if_laddrreq *)data)->dstaddr);
837 		size = sizeof(((struct if_laddrreq *)data)->dstaddr);
838 		if (src->sa_len > size) {
839 			l2tp_putref_variant(var, &psref);
840 			curlwp_bindx(bound);
841 			return EINVAL;
842                 }
843 		sockaddr_copy(dst, src->sa_len, src);
844 		l2tp_putref_variant(var, &psref);
845 		curlwp_bindx(bound);
846 		break;
847 
848 	case SIOCSL2TPSESSION:
849 		if ((error = copyin(ifr->ifr_data, &l2tpr, sizeof(l2tpr))) != 0)
850 			break;
851 
852 		/* session id must not zero */
853 		if (l2tpr.my_sess_id == 0 || l2tpr.peer_sess_id == 0)
854 			return EINVAL;
855 
856 		bound = curlwp_bind();
857 		var_tmp = l2tp_lookup_session_ref(l2tpr.my_sess_id, &psref);
858 		if (var_tmp != NULL) {
859 			/* duplicate session id */
860 			log(LOG_WARNING, "%s: duplicate session id %" PRIu32 " of %s\n",
861 				sc->l2tp_ec.ec_if.if_xname, l2tpr.my_sess_id,
862 				var_tmp->lv_softc->l2tp_ec.ec_if.if_xname);
863 			psref_release(&psref, &var_tmp->lv_psref,
864 			    lv_psref_class);
865 			curlwp_bindx(bound);
866 			return EINVAL;
867 		}
868 		curlwp_bindx(bound);
869 
870 		error = l2tp_set_session(sc, l2tpr.my_sess_id, l2tpr.peer_sess_id);
871 		break;
872 	case SIOCDL2TPSESSION:
873 		l2tp_clear_session(sc);
874 		break;
875 	case SIOCSL2TPCOOKIE:
876 		if ((error = copyin(ifr->ifr_data, &l2tpr, sizeof(l2tpr))) != 0)
877 			break;
878 
879 		error = l2tp_set_cookie(sc, l2tpr.my_cookie, l2tpr.my_cookie_len,
880 		    l2tpr.peer_cookie, l2tpr.peer_cookie_len);
881 		break;
882 	case SIOCDL2TPCOOKIE:
883 		l2tp_clear_cookie(sc);
884 		break;
885 	case SIOCSL2TPSTATE:
886 		if ((error = copyin(ifr->ifr_data, &l2tpr, sizeof(l2tpr))) != 0)
887 			break;
888 
889 		l2tp_set_state(sc, l2tpr.state);
890 		break;
891 	case SIOCGL2TP:
892 		/* get L2TPV3 session info */
893 		memset(&l2tpr, 0, sizeof(l2tpr));
894 
895 		bound = curlwp_bind();
896 		var = l2tp_getref_variant(sc, &psref);
897 		if (var == NULL) {
898 			curlwp_bindx(bound);
899 			error = EADDRNOTAVAIL;
900 			goto bad;
901 		}
902 
903 		l2tpr.state = var->lv_state;
904 		l2tpr.my_sess_id = var->lv_my_sess_id;
905 		l2tpr.peer_sess_id = var->lv_peer_sess_id;
906 		l2tpr.my_cookie = var->lv_my_cookie;
907 		l2tpr.my_cookie_len = var->lv_my_cookie_len;
908 		l2tpr.peer_cookie = var->lv_peer_cookie;
909 		l2tpr.peer_cookie_len = var->lv_peer_cookie_len;
910 		l2tp_putref_variant(var, &psref);
911 		curlwp_bindx(bound);
912 
913 		error = copyout(&l2tpr, ifr->ifr_data, sizeof(l2tpr));
914 		break;
915 
916 	default:
917 		error =	ifioctl_common(ifp, cmd, data);
918 		break;
919 	}
920  bad:
921 	return error;
922 }
923 
924 static int
925 l2tp_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
926 {
927 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
928 	    l2tp_ec.ec_if);
929 	struct sockaddr *osrc, *odst;
930 	struct sockaddr *nsrc, *ndst;
931 	struct l2tp_variant *ovar, *nvar;
932 	int error;
933 
934 	nsrc = sockaddr_dup(src, M_WAITOK);
935 	ndst = sockaddr_dup(dst, M_WAITOK);
936 
937 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
938 
939 	error = encap_lock_enter();
940 	if (error)
941 		goto error;
942 
943 	mutex_enter(&sc->l2tp_lock);
944 
945 	ovar = sc->l2tp_var;
946 	osrc = ovar->lv_psrc;
947 	odst = ovar->lv_pdst;
948 	*nvar = *ovar;
949 	psref_target_init(&nvar->lv_psref, lv_psref_class);
950 	nvar->lv_psrc = nsrc;
951 	nvar->lv_pdst = ndst;
952 	error = l2tp_encap_attach(nvar);
953 	if (error) {
954 		mutex_exit(&sc->l2tp_lock);
955 		encap_lock_exit();
956 		goto error;
957 	}
958 	membar_producer();
959 	l2tp_variant_update(sc, nvar);
960 
961 	mutex_exit(&sc->l2tp_lock);
962 
963 	(void)l2tp_encap_detach(ovar);
964 	encap_lock_exit();
965 
966 	if (osrc)
967 		sockaddr_free(osrc);
968 	if (odst)
969 		sockaddr_free(odst);
970 	kmem_free(ovar, sizeof(*ovar));
971 
972 	return 0;
973 
974 error:
975 	sockaddr_free(nsrc);
976 	sockaddr_free(ndst);
977 	kmem_free(nvar, sizeof(*nvar));
978 
979 	return error;
980 }
981 
982 static void
983 l2tp_delete_tunnel(struct ifnet *ifp)
984 {
985 	struct l2tp_softc *sc = container_of(ifp, struct l2tp_softc,
986 	    l2tp_ec.ec_if);
987 	struct sockaddr *osrc, *odst;
988 	struct l2tp_variant *ovar, *nvar;
989 	int error;
990 
991 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
992 
993 	error = encap_lock_enter();
994 	if (error) {
995 		kmem_free(nvar, sizeof(*nvar));
996 		return;
997 	}
998 	mutex_enter(&sc->l2tp_lock);
999 
1000 	ovar = sc->l2tp_var;
1001 	osrc = ovar->lv_psrc;
1002 	odst = ovar->lv_pdst;
1003 	*nvar = *ovar;
1004 	psref_target_init(&nvar->lv_psref, lv_psref_class);
1005 	nvar->lv_psrc = NULL;
1006 	nvar->lv_pdst = NULL;
1007 	membar_producer();
1008 	l2tp_variant_update(sc, nvar);
1009 
1010 	mutex_exit(&sc->l2tp_lock);
1011 
1012 	(void)l2tp_encap_detach(ovar);
1013 	encap_lock_exit();
1014 
1015 	if (osrc)
1016 		sockaddr_free(osrc);
1017 	if (odst)
1018 		sockaddr_free(odst);
1019 	kmem_free(ovar, sizeof(*ovar));
1020 }
1021 
1022 static int
1023 id_hash_func(uint32_t id, u_long mask)
1024 {
1025 	uint32_t hash;
1026 
1027 	hash = (id >> 16) ^ id;
1028 	hash = (hash >> 4) ^ hash;
1029 
1030 	return hash & mask;
1031 }
1032 
1033 static void
1034 l2tp_hash_init(void)
1035 {
1036 
1037 	l2tp_hash.lists = hashinit(L2TP_ID_HASH_SIZE, HASH_PSLIST, true,
1038 	    &l2tp_hash.mask);
1039 }
1040 
1041 static int
1042 l2tp_hash_fini(void)
1043 {
1044 	int i;
1045 
1046 	mutex_enter(&l2tp_hash.lock);
1047 
1048 	for (i = 0; i < l2tp_hash.mask + 1; i++) {
1049 		if (PSLIST_WRITER_FIRST(&l2tp_hash.lists[i], struct l2tp_softc,
1050 			l2tp_hash) != NULL) {
1051 			mutex_exit(&l2tp_hash.lock);
1052 			return EBUSY;
1053 		}
1054 	}
1055 	for (i = 0; i < l2tp_hash.mask + 1; i++)
1056 		PSLIST_DESTROY(&l2tp_hash.lists[i]);
1057 
1058 	mutex_exit(&l2tp_hash.lock);
1059 
1060 	hashdone(l2tp_hash.lists, HASH_PSLIST, l2tp_hash.mask);
1061 
1062 	return 0;
1063 }
1064 
1065 static int
1066 l2tp_set_session(struct l2tp_softc *sc, uint32_t my_sess_id,
1067     uint32_t peer_sess_id)
1068 {
1069 	uint32_t idx;
1070 	struct l2tp_variant *nvar;
1071 	struct l2tp_variant *ovar;
1072 	struct ifnet *ifp = &sc->l2tp_ec.ec_if;
1073 
1074 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
1075 
1076 	mutex_enter(&sc->l2tp_lock);
1077 	ovar = sc->l2tp_var;
1078 	*nvar = *ovar;
1079 	psref_target_init(&nvar->lv_psref, lv_psref_class);
1080 	nvar->lv_my_sess_id = my_sess_id;
1081 	nvar->lv_peer_sess_id = peer_sess_id;
1082 	membar_producer();
1083 
1084 	mutex_enter(&l2tp_hash.lock);
1085 	if (ovar->lv_my_sess_id > 0 && ovar->lv_peer_sess_id > 0) {
1086 		PSLIST_WRITER_REMOVE(sc, l2tp_hash);
1087 		pserialize_perform(l2tp_psz);
1088 	}
1089 	mutex_exit(&l2tp_hash.lock);
1090 	PSLIST_ENTRY_DESTROY(sc, l2tp_hash);
1091 
1092 	l2tp_variant_update(sc, nvar);
1093 	mutex_exit(&sc->l2tp_lock);
1094 
1095 	idx = id_hash_func(nvar->lv_my_sess_id, l2tp_hash.mask);
1096 	if ((ifp->if_flags & IFF_DEBUG) != 0)
1097 		log(LOG_DEBUG, "%s: add hash entry: sess_id=%" PRIu32 ", idx=%" PRIu32 "\n",
1098 		    sc->l2tp_ec.ec_if.if_xname, nvar->lv_my_sess_id, idx);
1099 
1100 	PSLIST_ENTRY_INIT(sc, l2tp_hash);
1101 	mutex_enter(&l2tp_hash.lock);
1102 	PSLIST_WRITER_INSERT_HEAD(&l2tp_hash.lists[idx], sc, l2tp_hash);
1103 	mutex_exit(&l2tp_hash.lock);
1104 
1105 	kmem_free(ovar, sizeof(*ovar));
1106 	return 0;
1107 }
1108 
1109 static int
1110 l2tp_clear_session(struct l2tp_softc *sc)
1111 {
1112 	struct l2tp_variant *nvar;
1113 	struct l2tp_variant *ovar;
1114 
1115 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
1116 
1117 	mutex_enter(&sc->l2tp_lock);
1118 	ovar = sc->l2tp_var;
1119 	*nvar = *ovar;
1120 	psref_target_init(&nvar->lv_psref, lv_psref_class);
1121 	nvar->lv_my_sess_id = 0;
1122 	nvar->lv_peer_sess_id = 0;
1123 	membar_producer();
1124 
1125 	mutex_enter(&l2tp_hash.lock);
1126 	if (ovar->lv_my_sess_id > 0 && ovar->lv_peer_sess_id > 0) {
1127 		PSLIST_WRITER_REMOVE(sc, l2tp_hash);
1128 		pserialize_perform(l2tp_psz);
1129 	}
1130 	mutex_exit(&l2tp_hash.lock);
1131 
1132 	l2tp_variant_update(sc, nvar);
1133 	mutex_exit(&sc->l2tp_lock);
1134 	kmem_free(ovar, sizeof(*ovar));
1135 	return 0;
1136 }
1137 
1138 struct l2tp_variant *
1139 l2tp_lookup_session_ref(uint32_t id, struct psref *psref)
1140 {
1141 	int idx;
1142 	int s;
1143 	struct l2tp_softc *sc;
1144 
1145 	idx = id_hash_func(id, l2tp_hash.mask);
1146 
1147 	s = pserialize_read_enter();
1148 	PSLIST_READER_FOREACH(sc, &l2tp_hash.lists[idx], struct l2tp_softc,
1149 	    l2tp_hash) {
1150 		struct l2tp_variant *var = sc->l2tp_var;
1151 		if (var == NULL)
1152 			continue;
1153 		if (var->lv_my_sess_id != id)
1154 			continue;
1155 		psref_acquire(psref, &var->lv_psref, lv_psref_class);
1156 		pserialize_read_exit(s);
1157 		return var;
1158 	}
1159 	pserialize_read_exit(s);
1160 	return NULL;
1161 }
1162 
1163 /*
1164  * l2tp_variant update API.
1165  *
1166  * Assumption:
1167  * reader side dereferences sc->l2tp_var in reader critical section only,
1168  * that is, all of reader sides do not reader the sc->l2tp_var after
1169  * pserialize_perform().
1170  */
1171 static void
1172 l2tp_variant_update(struct l2tp_softc *sc, struct l2tp_variant *nvar)
1173 {
1174 	struct ifnet *ifp = &sc->l2tp_ec.ec_if;
1175 	struct l2tp_variant *ovar = sc->l2tp_var;
1176 
1177 	KASSERT(mutex_owned(&sc->l2tp_lock));
1178 
1179 	sc->l2tp_var = nvar;
1180 	pserialize_perform(l2tp_psz);
1181 	psref_target_destroy(&ovar->lv_psref, lv_psref_class);
1182 
1183 	/*
1184 	 * In the manual of atomic_swap_ptr(3), there is no mention if 2nd
1185 	 * argument is rewrite or not. So, use sc->l2tp_var instead of nvar.
1186 	 */
1187 	if (sc->l2tp_var != NULL) {
1188 		if (sc->l2tp_var->lv_psrc != NULL
1189 		    && sc->l2tp_var->lv_pdst != NULL)
1190 			ifp->if_flags |= IFF_RUNNING;
1191 		else
1192 			ifp->if_flags &= ~IFF_RUNNING;
1193 	}
1194 }
1195 
1196 static int
1197 l2tp_set_cookie(struct l2tp_softc *sc, uint64_t my_cookie, u_int my_cookie_len,
1198     uint64_t peer_cookie, u_int peer_cookie_len)
1199 {
1200 	struct l2tp_variant *nvar;
1201 
1202 	if (my_cookie == 0 || peer_cookie == 0)
1203 		return EINVAL;
1204 
1205 	if (my_cookie_len != 4 && my_cookie_len != 8
1206 	    && peer_cookie_len != 4 && peer_cookie_len != 8)
1207 		return EINVAL;
1208 
1209 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
1210 
1211 	mutex_enter(&sc->l2tp_lock);
1212 
1213 	*nvar = *sc->l2tp_var;
1214 	psref_target_init(&nvar->lv_psref, lv_psref_class);
1215 	nvar->lv_my_cookie = my_cookie;
1216 	nvar->lv_my_cookie_len = my_cookie_len;
1217 	nvar->lv_peer_cookie = peer_cookie;
1218 	nvar->lv_peer_cookie_len = peer_cookie_len;
1219 	nvar->lv_use_cookie = L2TP_COOKIE_ON;
1220 	membar_producer();
1221 	l2tp_variant_update(sc, nvar);
1222 
1223 	mutex_exit(&sc->l2tp_lock);
1224 
1225 	struct ifnet *ifp = &sc->l2tp_ec.ec_if;
1226 	if ((ifp->if_flags & IFF_DEBUG) != 0) {
1227 		log(LOG_DEBUG,
1228 		    "%s: set cookie: "
1229 		    "local cookie_len=%u local cookie=%" PRIu64 ", "
1230 		    "remote cookie_len=%u remote cookie=%" PRIu64 "\n",
1231 		    ifp->if_xname, my_cookie_len, my_cookie,
1232 		    peer_cookie_len, peer_cookie);
1233 	}
1234 
1235 	return 0;
1236 }
1237 
1238 static void
1239 l2tp_clear_cookie(struct l2tp_softc *sc)
1240 {
1241 	struct l2tp_variant *nvar;
1242 
1243 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
1244 
1245 	mutex_enter(&sc->l2tp_lock);
1246 
1247 	*nvar = *sc->l2tp_var;
1248 	psref_target_init(&nvar->lv_psref, lv_psref_class);
1249 	nvar->lv_my_cookie = 0;
1250 	nvar->lv_my_cookie_len = 0;
1251 	nvar->lv_peer_cookie = 0;
1252 	nvar->lv_peer_cookie_len = 0;
1253 	nvar->lv_use_cookie = L2TP_COOKIE_OFF;
1254 	membar_producer();
1255 	l2tp_variant_update(sc, nvar);
1256 
1257 	mutex_exit(&sc->l2tp_lock);
1258 }
1259 
1260 static void
1261 l2tp_set_state(struct l2tp_softc *sc, int state)
1262 {
1263 	struct ifnet *ifp = &sc->l2tp_ec.ec_if;
1264 	struct l2tp_variant *nvar;
1265 
1266 	nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP);
1267 
1268 	mutex_enter(&sc->l2tp_lock);
1269 
1270 	*nvar = *sc->l2tp_var;
1271 	psref_target_init(&nvar->lv_psref, lv_psref_class);
1272 	nvar->lv_state = state;
1273 	membar_producer();
1274 	l2tp_variant_update(sc, nvar);
1275 
1276 	if (nvar->lv_state == L2TP_STATE_UP) {
1277 		ifp->if_link_state = LINK_STATE_UP;
1278 	} else {
1279 		ifp->if_link_state = LINK_STATE_DOWN;
1280 	}
1281 
1282 	mutex_exit(&sc->l2tp_lock);
1283 
1284 #ifdef NOTYET
1285 	vlan_linkstate_notify(ifp, ifp->if_link_state);
1286 #endif
1287 }
1288 
1289 static int
1290 l2tp_encap_attach(struct l2tp_variant *var)
1291 {
1292 	int error;
1293 
1294 	if (var == NULL || var->lv_psrc == NULL)
1295 		return EINVAL;
1296 
1297 	switch (var->lv_psrc->sa_family) {
1298 #ifdef INET
1299 	case AF_INET:
1300 		error = in_l2tp_attach(var);
1301 		break;
1302 #endif
1303 #ifdef INET6
1304 	case AF_INET6:
1305 		error = in6_l2tp_attach(var);
1306 		break;
1307 #endif
1308 	default:
1309 		error = EINVAL;
1310 		break;
1311 	}
1312 
1313 	return error;
1314 }
1315 
1316 static int
1317 l2tp_encap_detach(struct l2tp_variant *var)
1318 {
1319 	int error;
1320 
1321 	if (var == NULL || var->lv_psrc == NULL)
1322 		return EINVAL;
1323 
1324 	switch (var->lv_psrc->sa_family) {
1325 #ifdef INET
1326 	case AF_INET:
1327 		error = in_l2tp_detach(var);
1328 		break;
1329 #endif
1330 #ifdef INET6
1331 	case AF_INET6:
1332 		error = in6_l2tp_detach(var);
1333 		break;
1334 #endif
1335 	default:
1336 		error = EINVAL;
1337 		break;
1338 	}
1339 
1340 	return error;
1341 }
1342 
1343 int
1344 l2tp_check_nesting(struct ifnet *ifp, struct mbuf *m)
1345 {
1346 
1347 	return if_tunnel_check_nesting(ifp, m, max_l2tp_nesting);
1348 }
1349 
1350 /*
1351  * Module infrastructure
1352  */
1353 #include "if_module.h"
1354 
1355 IF_MODULE(MODULE_CLASS_DRIVER, l2tp, "")
1356 
1357 
1358 /* TODO: IP_TCPMSS support */
1359 #ifdef IP_TCPMSS
1360 static int l2tp_need_tcpmss_clamp(struct ifnet *);
1361 #ifdef INET
1362 static struct mbuf *l2tp_tcpmss4_clamp(struct ifnet *, struct mbuf *);
1363 #endif
1364 #ifdef INET6
1365 static struct mbuf *l2tp_tcpmss6_clamp(struct ifnet *, struct mbuf *);
1366 #endif
1367 
1368 struct mbuf *
1369 l2tp_tcpmss_clamp(struct ifnet *ifp, struct mbuf	*m)
1370 {
1371 
1372 	if (l2tp_need_tcpmss_clamp(ifp)) {
1373 		struct ether_header *eh;
1374 		struct ether_vlan_header evh;
1375 
1376 		/* save ether header */
1377 		m_copydata(m, 0, sizeof(evh), (void *)&evh);
1378 		eh = (struct ether_header *)&evh;
1379 
1380 		switch (ntohs(eh->ether_type)) {
1381 		case ETHERTYPE_VLAN: /* Ether + VLAN */
1382 			if (m->m_pkthdr.len <= sizeof(struct ether_vlan_header))
1383 				break;
1384 			m_adj(m, sizeof(struct ether_vlan_header));
1385 			switch (ntohs(evh.evl_proto)) {
1386 #ifdef INET
1387 			case ETHERTYPE_IP: /* Ether + VLAN + IPv4 */
1388 				m = l2tp_tcpmss4_clamp(ifp, m);
1389 				if (m == NULL)
1390 					return NULL;
1391 				break;
1392 #endif /* INET */
1393 #ifdef INET6
1394 			case ETHERTYPE_IPV6: /* Ether + VLAN + IPv6 */
1395 				m = l2tp_tcpmss6_clamp(ifp, m);
1396 				if (m == NULL)
1397 					return NULL;
1398 				break;
1399 #endif /* INET6 */
1400 			default:
1401 				break;
1402 			}
1403 			/* restore ether header */
1404 			M_PREPEND(m, sizeof(struct ether_vlan_header),
1405 			    M_DONTWAIT);
1406 			if (m == NULL)
1407 				return NULL;
1408 			*mtod(m, struct ether_vlan_header *) = evh;
1409 			break;
1410 #ifdef INET
1411 		case ETHERTYPE_IP: /* Ether + IPv4 */
1412 			if (m->m_pkthdr.len <= sizeof(struct ether_header))
1413 				break;
1414 			m_adj(m, sizeof(struct ether_header));
1415 			m = l2tp_tcpmss4_clamp(ifp, m);
1416 			if (m == NULL)
1417 				return NULL;
1418 			/* restore ether header */
1419 			M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
1420 			if (m == NULL)
1421 				return NULL;
1422 			*mtod(m, struct ether_header *) = *eh;
1423 			break;
1424 #endif /* INET */
1425 #ifdef INET6
1426 		case ETHERTYPE_IPV6: /* Ether + IPv6 */
1427 			if (m->m_pkthdr.len <= sizeof(struct ether_header))
1428 				break;
1429 			m_adj(m, sizeof(struct ether_header));
1430 			m = l2tp_tcpmss6_clamp(ifp, m);
1431 			if (m == NULL)
1432 				return NULL;
1433 			/* restore ether header */
1434 			M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
1435 			if (m == NULL)
1436 				return NULL;
1437 			*mtod(m, struct ether_header *) = *eh;
1438 			break;
1439 #endif /* INET6 */
1440 		default:
1441 			break;
1442 		}
1443 	}
1444 
1445 	return m;
1446 }
1447 
1448 static int
1449 l2tp_need_tcpmss_clamp(struct ifnet *ifp)
1450 {
1451 	int ret = 0;
1452 
1453 #ifdef INET
1454 	if (ifp->if_tcpmss != 0)
1455 		ret = 1;
1456 #endif /* INET */
1457 
1458 #ifdef INET6
1459 	if (ifp->if_tcpmss6 != 0)
1460 		ret = 1;
1461 #endif /* INET6 */
1462 
1463 	return ret;
1464 }
1465 
1466 #ifdef INET
1467 static struct mbuf *
1468 l2tp_tcpmss4_clamp(struct ifnet *ifp, struct mbuf *m)
1469 {
1470 
1471 	if (ifp->if_tcpmss != 0) {
1472 		return ip_tcpmss(m, (ifp->if_tcpmss < 0) ?
1473 			ifp->if_mtu - IP_TCPMSS_EXTLEN :
1474 			ifp->if_tcpmss);
1475 	}
1476 	return m;
1477 }
1478 #endif /* INET */
1479 
1480 #ifdef INET6
1481 static struct mbuf *
1482 l2tp_tcpmss6_clamp(struct ifnet *ifp, struct mbuf *m)
1483 {
1484 	int ip6hdrlen;
1485 
1486 	if (ifp->if_tcpmss6 != 0 &&
1487 	    ip6_tcpmss_applicable(m, &ip6hdrlen)) {
1488 		return ip6_tcpmss(m, ip6hdrlen,
1489 			(ifp->if_tcpmss6 < 0) ?
1490 			ifp->if_mtu - IP6_TCPMSS_EXTLEN :
1491 			ifp->if_tcpmss6);
1492 	}
1493 	return m;
1494 }
1495 #endif /* INET6 */
1496 
1497 #endif /* IP_TCPMSS */
1498