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