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