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