1 /* $NetBSD: if_gif.c,v 1.159 2024/09/15 09:46:45 skrll Exp $ */ 2 /* $KAME: if_gif.c,v 1.76 2001/08/20 02:01:02 kjc Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: if_gif.c,v 1.159 2024/09/15 09:46:45 skrll 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/atomic.h> 44 #include <sys/kernel.h> 45 #include <sys/mbuf.h> 46 #include <sys/socket.h> 47 #include <sys/sockio.h> 48 #include <sys/errno.h> 49 #include <sys/ioctl.h> 50 #include <sys/time.h> 51 #include <sys/socketvar.h> 52 #include <sys/syslog.h> 53 #include <sys/proc.h> 54 #include <sys/cpu.h> 55 #include <sys/intr.h> 56 #include <sys/kmem.h> 57 #include <sys/sysctl.h> 58 #include <sys/xcall.h> 59 #include <sys/device.h> 60 #include <sys/module.h> 61 #include <sys/mutex.h> 62 #include <sys/pserialize.h> 63 #include <sys/psref.h> 64 65 #include <net/if.h> 66 #include <net/if_types.h> 67 #include <net/route.h> 68 #include <net/bpf.h> 69 70 #include <netinet/in.h> 71 #include <netinet/in_systm.h> 72 #include <netinet/ip.h> 73 #ifdef INET 74 #include <netinet/in_var.h> 75 #endif /* INET */ 76 #include <netinet/in_gif.h> 77 78 #ifdef INET6 79 #ifndef INET 80 #include <netinet/in.h> 81 #endif 82 #include <netinet6/in6_var.h> 83 #include <netinet/ip6.h> 84 #include <netinet6/ip6_var.h> 85 #include <netinet6/in6_gif.h> 86 #endif /* INET6 */ 87 88 #include <netinet/ip_encap.h> 89 #include <net/if_gif.h> 90 91 #include "ioconf.h" 92 93 #ifdef NET_MPSAFE 94 #define GIF_MPSAFE 1 95 #endif 96 97 /* 98 * gif global variable definitions 99 */ 100 static struct { 101 LIST_HEAD(gif_sclist, gif_softc) list; 102 kmutex_t lock; 103 } gif_softcs __cacheline_aligned; 104 105 struct psref_class *gv_psref_class __read_mostly; 106 107 static pktq_rps_hash_func_t gif_pktq_rps_hash_p; 108 109 static int gifattach0(struct gif_softc *); 110 static int gif_output(struct ifnet *, struct mbuf *, 111 const struct sockaddr *, const struct rtentry *); 112 static void gif_start(struct ifnet *); 113 static int gif_transmit(struct ifnet *, struct mbuf *); 114 static int gif_transmit_direct(struct gif_variant *, struct mbuf *); 115 static int gif_ioctl(struct ifnet *, u_long, void *); 116 static int gif_set_tunnel(struct ifnet *, struct sockaddr *, 117 struct sockaddr *); 118 static void gif_delete_tunnel(struct ifnet *); 119 120 static int gif_clone_create(struct if_clone *, int); 121 static int gif_clone_destroy(struct ifnet *); 122 static int gif_check_nesting(struct ifnet *, struct mbuf *); 123 124 static int gif_encap_attach(struct gif_variant *); 125 static int gif_encap_detach(struct gif_variant *); 126 127 static void gif_update_variant(struct gif_softc *, struct gif_variant *); 128 129 static struct if_clone gif_cloner = 130 IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy); 131 132 #ifndef MAX_GIF_NEST 133 /* 134 * This macro controls the upper limitation on nesting of gif tunnels. 135 * Since, setting a large value to this macro with a careless configuration 136 * may introduce system crash, we don't allow any nestings by default. 137 * If you need to configure nested gif tunnels, you can define this macro 138 * in your kernel configuration file. However, if you do so, please be 139 * careful to configure the tunnels so that it won't make a loop. 140 */ 141 #define MAX_GIF_NEST 1 142 #endif 143 static int max_gif_nesting = MAX_GIF_NEST; 144 145 static struct sysctllog *gif_sysctl; 146 147 #ifdef INET6 148 static int 149 sysctl_gif_pmtu_global(SYSCTLFN_ARGS) 150 { 151 int error, pmtu; 152 struct sysctlnode node = *rnode; 153 154 pmtu = ip6_gif_pmtu; 155 node.sysctl_data = &pmtu; 156 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 157 if (error || newp == NULL) 158 return error; 159 160 switch (pmtu) { 161 case GIF_PMTU_MINMTU: 162 case GIF_PMTU_OUTERMTU: 163 ip6_gif_pmtu = pmtu; 164 break; 165 default: 166 return EINVAL; 167 } 168 169 return 0; 170 } 171 172 static int 173 sysctl_gif_pmtu_perif(SYSCTLFN_ARGS) 174 { 175 int error, pmtu; 176 struct sysctlnode node = *rnode; 177 struct gif_softc *sc = (struct gif_softc *)node.sysctl_data; 178 179 pmtu = sc->gif_pmtu; 180 node.sysctl_data = &pmtu; 181 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 182 if (error || newp == NULL) 183 return error; 184 185 switch (pmtu) { 186 case GIF_PMTU_SYSDEFAULT: 187 case GIF_PMTU_MINMTU: 188 case GIF_PMTU_OUTERMTU: 189 sc->gif_pmtu = pmtu; 190 break; 191 default: 192 return EINVAL; 193 } 194 195 return 0; 196 } 197 #endif 198 199 static void 200 gif_sysctl_setup(void) 201 { 202 const struct sysctlnode *node = NULL; 203 204 gif_sysctl = NULL; 205 206 #ifdef INET 207 /* 208 * Previously create "net.inet.ip" entry to avoid sysctl_createv error. 209 */ 210 sysctl_createv(NULL, 0, NULL, NULL, 211 CTLFLAG_PERMANENT, 212 CTLTYPE_NODE, "inet", 213 SYSCTL_DESCR("PF_INET related settings"), 214 NULL, 0, NULL, 0, 215 CTL_NET, PF_INET, CTL_EOL); 216 sysctl_createv(NULL, 0, NULL, NULL, 217 CTLFLAG_PERMANENT, 218 CTLTYPE_NODE, "ip", 219 SYSCTL_DESCR("IPv4 related settings"), 220 NULL, 0, NULL, 0, 221 CTL_NET, PF_INET, IPPROTO_IP, CTL_EOL); 222 223 sysctl_createv(&gif_sysctl, 0, NULL, NULL, 224 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 225 CTLTYPE_INT, "gifttl", 226 SYSCTL_DESCR("Default TTL for a gif tunnel datagram"), 227 NULL, 0, &ip_gif_ttl, 0, 228 CTL_NET, PF_INET, IPPROTO_IP, 229 IPCTL_GIF_TTL, CTL_EOL); 230 #endif 231 #ifdef INET6 232 /* 233 * Previously create "net.inet6.ip6" entry to avoid sysctl_createv error. 234 */ 235 sysctl_createv(NULL, 0, NULL, NULL, 236 CTLFLAG_PERMANENT, 237 CTLTYPE_NODE, "inet6", 238 SYSCTL_DESCR("PF_INET6 related settings"), 239 NULL, 0, NULL, 0, 240 CTL_NET, PF_INET6, CTL_EOL); 241 sysctl_createv(NULL, 0, NULL, NULL, 242 CTLFLAG_PERMANENT, 243 CTLTYPE_NODE, "ip6", 244 SYSCTL_DESCR("IPv6 related settings"), 245 NULL, 0, NULL, 0, 246 CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_EOL); 247 248 sysctl_createv(&gif_sysctl, 0, NULL, NULL, 249 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 250 CTLTYPE_INT, "gifhlim", 251 SYSCTL_DESCR("Default hop limit for a gif tunnel datagram"), 252 NULL, 0, &ip6_gif_hlim, 0, 253 CTL_NET, PF_INET6, IPPROTO_IPV6, 254 IPV6CTL_GIF_HLIM, CTL_EOL); 255 256 sysctl_createv(&gif_sysctl, 0, NULL, NULL, 257 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 258 CTLTYPE_INT, "gifpmtu", 259 SYSCTL_DESCR("Default Path MTU setting for gif tunnels"), 260 sysctl_gif_pmtu_global, 0, NULL, 0, 261 CTL_NET, PF_INET6, IPPROTO_IPV6, 262 IPV6CTL_GIF_PMTU, CTL_EOL); 263 #endif 264 265 sysctl_createv(&gif_sysctl, 0, NULL, &node, 266 CTLFLAG_PERMANENT, 267 CTLTYPE_NODE, "gif", 268 SYSCTL_DESCR("gif global control"), 269 NULL, 0, NULL, 0, 270 CTL_NET, CTL_CREATE, CTL_EOL); 271 272 sysctl_createv(&gif_sysctl, 0, &node, NULL, 273 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 274 CTLTYPE_STRING, "rps_hash", 275 SYSCTL_DESCR("Interface rps hash function control"), 276 sysctl_pktq_rps_hash_handler, 0, (void *)&gif_pktq_rps_hash_p, 277 PKTQ_RPS_HASH_NAME_LEN, 278 CTL_CREATE, CTL_EOL); 279 } 280 281 static void 282 gif_perif_sysctl_setup(struct sysctllog **clog, struct gif_softc *sc) 283 { 284 #ifdef INET6 285 const struct sysctlnode *cnode, *rnode; 286 struct ifnet *ifp = &sc->gif_if; 287 const char *ifname = ifp->if_xname; 288 int rv; 289 290 /* 291 * Already created in sysctl_sndq_setup(). 292 */ 293 sysctl_createv(clog, 0, NULL, &rnode, 294 CTLFLAG_PERMANENT, 295 CTLTYPE_NODE, "interfaces", 296 SYSCTL_DESCR("Per-interface controls"), 297 NULL, 0, NULL, 0, 298 CTL_NET, CTL_CREATE, CTL_EOL); 299 sysctl_createv(clog, 0, &rnode, &rnode, 300 CTLFLAG_PERMANENT, 301 CTLTYPE_NODE, ifname, 302 SYSCTL_DESCR("Interface controls"), 303 NULL, 0, NULL, 0, 304 CTL_CREATE, CTL_EOL); 305 306 rv = sysctl_createv(clog, 0, &rnode, &cnode, 307 CTLFLAG_PERMANENT, 308 CTLTYPE_INT, "pmtu", 309 SYSCTL_DESCR("Path MTU setting for this gif tunnel"), 310 sysctl_gif_pmtu_perif, 0, (void *)sc, 0, 311 CTL_CREATE, CTL_EOL); 312 if (rv != 0) 313 log(LOG_WARNING, "%s: could not attach sysctl node pmtu\n", ifname); 314 315 sc->gif_pmtu = GIF_PMTU_SYSDEFAULT; 316 #endif 317 } 318 319 /* ARGSUSED */ 320 void 321 gifattach(int count) 322 { 323 /* 324 * Nothing to do here, initialization is handled by the 325 * module initialization code in gifinit() below). 326 */ 327 } 328 329 static void 330 gifinit(void) 331 { 332 333 mutex_init(&gif_softcs.lock, MUTEX_DEFAULT, IPL_NONE); 334 LIST_INIT(&gif_softcs.list); 335 if_clone_attach(&gif_cloner); 336 337 gv_psref_class = psref_class_create("gifvar", IPL_SOFTNET); 338 339 gif_pktq_rps_hash_p = pktq_rps_hash_default; 340 gif_sysctl_setup(); 341 } 342 343 static int 344 gifdetach(void) 345 { 346 347 mutex_enter(&gif_softcs.lock); 348 if (!LIST_EMPTY(&gif_softcs.list)) { 349 mutex_exit(&gif_softcs.lock); 350 return EBUSY; 351 } 352 353 psref_class_destroy(gv_psref_class); 354 355 if_clone_detach(&gif_cloner); 356 sysctl_teardown(&gif_sysctl); 357 mutex_exit(&gif_softcs.lock); 358 mutex_destroy(&gif_softcs.lock); 359 return 0; 360 } 361 362 static int 363 gif_clone_create(struct if_clone *ifc, int unit) 364 { 365 struct gif_softc *sc; 366 struct gif_variant *var; 367 struct ifnet *ifp; 368 int rv; 369 370 sc = kmem_zalloc(sizeof(struct gif_softc), KM_SLEEP); 371 372 if_initname(&sc->gif_if, ifc->ifc_name, unit); 373 374 rv = gifattach0(sc); 375 if (rv != 0) { 376 kmem_free(sc, sizeof(struct gif_softc)); 377 return rv; 378 } 379 380 ifp = &sc->gif_if; 381 gif_perif_sysctl_setup(&ifp->if_sysctl_log, sc); 382 383 var = kmem_zalloc(sizeof(*var), KM_SLEEP); 384 var->gv_softc = sc; 385 psref_target_init(&var->gv_psref, gv_psref_class); 386 387 sc->gif_var = var; 388 mutex_init(&sc->gif_lock, MUTEX_DEFAULT, IPL_NONE); 389 sc->gif_psz = pserialize_create(); 390 391 sc->gif_ro_percpu = if_tunnel_alloc_ro_percpu(); 392 mutex_enter(&gif_softcs.lock); 393 LIST_INSERT_HEAD(&gif_softcs.list, sc, gif_list); 394 mutex_exit(&gif_softcs.lock); 395 return 0; 396 } 397 398 static int 399 gifattach0(struct gif_softc *sc) 400 { 401 402 sc->gif_if.if_addrlen = 0; 403 sc->gif_if.if_mtu = GIF_MTU; 404 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 405 #ifdef GIF_MPSAFE 406 sc->gif_if.if_extflags |= IFEF_MPSAFE; 407 #endif 408 sc->gif_if.if_ioctl = gif_ioctl; 409 sc->gif_if.if_output = gif_output; 410 sc->gif_if.if_start = gif_start; 411 sc->gif_if.if_transmit = gif_transmit; 412 sc->gif_if.if_type = IFT_GIF; 413 sc->gif_if.if_dlt = DLT_NULL; 414 sc->gif_if.if_softc = sc; 415 IFQ_SET_READY(&sc->gif_if.if_snd); 416 if_initialize(&sc->gif_if); 417 418 sc->gif_if.if_link_state = LINK_STATE_DOWN; 419 if_alloc_sadl(&sc->gif_if); 420 bpf_attach(&sc->gif_if, DLT_NULL, sizeof(u_int)); 421 if_register(&sc->gif_if); 422 return 0; 423 } 424 425 static int 426 gif_clone_destroy(struct ifnet *ifp) 427 { 428 struct gif_softc *sc = (void *) ifp; 429 struct gif_variant *var; 430 431 LIST_REMOVE(sc, gif_list); 432 433 gif_delete_tunnel(&sc->gif_if); 434 bpf_detach(ifp); 435 if_detach(ifp); 436 437 if_tunnel_free_ro_percpu(sc->gif_ro_percpu); 438 439 pserialize_destroy(sc->gif_psz); 440 mutex_destroy(&sc->gif_lock); 441 442 var = sc->gif_var; 443 kmem_free(var, sizeof(*var)); 444 kmem_free(sc, sizeof(struct gif_softc)); 445 446 return 0; 447 } 448 449 #ifdef GIF_ENCAPCHECK 450 int 451 gif_encapcheck(struct mbuf *m, int off, int proto, void *arg) 452 { 453 struct ip ip; 454 struct gif_softc *sc; 455 struct gif_variant *var; 456 struct psref psref; 457 int ret = 0; 458 459 sc = arg; 460 if (sc == NULL) 461 return 0; 462 463 if ((sc->gif_if.if_flags & IFF_UP) == 0) 464 return 0; 465 466 var = gif_getref_variant(sc, &psref); 467 /* no physical address */ 468 if (var->gv_psrc == NULL || var->gv_pdst == NULL) 469 goto out; 470 471 switch (proto) { 472 #ifdef INET 473 case IPPROTO_IPV4: 474 break; 475 #endif 476 #ifdef INET6 477 case IPPROTO_IPV6: 478 break; 479 #endif 480 default: 481 goto out; 482 } 483 484 /* Bail on short packets */ 485 KASSERT(m->m_flags & M_PKTHDR); 486 if (m->m_pkthdr.len < sizeof(ip)) 487 goto out; 488 489 m_copydata(m, 0, sizeof(ip), &ip); 490 491 switch (ip.ip_v) { 492 #ifdef INET 493 case 4: 494 if (var->gv_psrc->sa_family != AF_INET || 495 var->gv_pdst->sa_family != AF_INET) 496 goto out; 497 ret = gif_encapcheck4(m, off, proto, var); 498 break; 499 #endif 500 #ifdef INET6 501 case 6: 502 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) 503 goto out; 504 if (var->gv_psrc->sa_family != AF_INET6 || 505 var->gv_pdst->sa_family != AF_INET6) 506 goto out; 507 ret = gif_encapcheck6(m, off, proto, var); 508 break; 509 #endif 510 default: 511 goto out; 512 } 513 514 out: 515 gif_putref_variant(var, &psref); 516 return ret; 517 } 518 #endif 519 520 /* 521 * gif may cause infinite recursion calls when misconfigured. 522 * We'll prevent this by introducing upper limit. 523 */ 524 static int 525 gif_check_nesting(struct ifnet *ifp, struct mbuf *m) 526 { 527 528 return if_tunnel_check_nesting(ifp, m, max_gif_nesting); 529 } 530 531 static int 532 gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 533 const struct rtentry *rt) 534 { 535 struct gif_softc *sc = ifp->if_softc; 536 struct gif_variant *var = NULL; 537 struct psref psref; 538 int error = 0; 539 540 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); 541 542 if ((error = gif_check_nesting(ifp, m)) != 0) { 543 m_freem(m); 544 goto end; 545 } 546 547 if ((ifp->if_flags & IFF_UP) == 0) { 548 m_freem(m); 549 error = ENETDOWN; 550 goto end; 551 } 552 553 var = gif_getref_variant(sc, &psref); 554 if (var->gv_psrc == NULL || var->gv_pdst == NULL) { 555 m_freem(m); 556 error = ENETDOWN; 557 goto end; 558 } 559 /* XXX should we check if our outer source is legal? */ 560 561 m->m_flags &= ~(M_BCAST | M_MCAST); 562 563 /* use DLT_NULL encapsulation here to pass inner af type */ 564 M_PREPEND(m, sizeof(int), M_DONTWAIT); 565 if (!m) { 566 error = ENOBUFS; 567 goto end; 568 } 569 *mtod(m, int *) = dst->sa_family; 570 571 /* Clear checksum-offload flags. */ 572 m->m_pkthdr.csum_flags = 0; 573 m->m_pkthdr.csum_data = 0; 574 575 error = if_transmit_lock(ifp, m); 576 577 end: 578 if (var != NULL) 579 gif_putref_variant(var, &psref); 580 if (error) 581 if_statinc(ifp, if_oerrors); 582 return error; 583 } 584 585 static void 586 gif_start(struct ifnet *ifp) 587 { 588 struct gif_softc *sc; 589 struct gif_variant *var; 590 struct mbuf *m; 591 struct psref psref; 592 int family; 593 int len; 594 int error; 595 596 sc = ifp->if_softc; 597 var = gif_getref_variant(sc, &psref); 598 599 KASSERT(var->gv_output != NULL); 600 601 /* output processing */ 602 while (1) { 603 IFQ_DEQUEUE(&sc->gif_if.if_snd, m); 604 if (m == NULL) 605 break; 606 607 /* grab and chop off inner af type */ 608 if (sizeof(int) > m->m_len) { 609 m = m_pullup(m, sizeof(int)); 610 if (!m) { 611 if_statinc(ifp, if_oerrors); 612 continue; 613 } 614 } 615 family = *mtod(m, int *); 616 bpf_mtap(ifp, m, BPF_D_OUT); 617 m_adj(m, sizeof(int)); 618 619 len = m->m_pkthdr.len; 620 621 error = var->gv_output(var, family, m); 622 if (error) 623 if_statinc(ifp, if_oerrors); 624 else 625 if_statadd2(ifp, if_opackets, 1, if_obytes, len); 626 } 627 628 gif_putref_variant(var, &psref); 629 } 630 631 static int 632 gif_transmit(struct ifnet *ifp, struct mbuf *m) 633 { 634 struct gif_softc *sc; 635 struct gif_variant *var; 636 struct psref psref; 637 int error; 638 639 sc = ifp->if_softc; 640 641 /* output processing */ 642 if (m == NULL) 643 return EINVAL; 644 645 var = gif_getref_variant(sc, &psref); 646 error = gif_transmit_direct(var, m); 647 gif_putref_variant(var, &psref); 648 649 return error; 650 } 651 652 static int 653 gif_transmit_direct(struct gif_variant *var, struct mbuf *m) 654 { 655 struct ifnet *ifp = &var->gv_softc->gif_if; 656 int error; 657 int family; 658 int len; 659 660 KASSERT(gif_heldref_variant(var)); 661 KASSERT(var->gv_output != NULL); 662 663 /* grab and chop off inner af type */ 664 if (sizeof(int) > m->m_len) { 665 m = m_pullup(m, sizeof(int)); 666 if (!m) { 667 if_statinc(ifp, if_oerrors); 668 return ENOBUFS; 669 } 670 } 671 family = *mtod(m, int *); 672 bpf_mtap(ifp, m, BPF_D_OUT); 673 m_adj(m, sizeof(int)); 674 675 len = m->m_pkthdr.len; 676 677 error = var->gv_output(var, family, m); 678 if (error) 679 if_statinc(ifp, if_oerrors); 680 else 681 if_statadd2(ifp, if_opackets, 1, if_obytes, len); 682 683 return error; 684 } 685 686 void 687 gif_input(struct mbuf *m, int af, struct ifnet *ifp) 688 { 689 pktqueue_t *pktq; 690 size_t pktlen; 691 692 if (ifp == NULL) { 693 /* just in case */ 694 m_freem(m); 695 return; 696 } 697 698 m_set_rcvif(m, ifp); 699 pktlen = m->m_pkthdr.len; 700 701 bpf_mtap_af(ifp, af, m, BPF_D_IN); 702 703 /* 704 * Put the packet to the network layer input queue according to the 705 * specified address family. Note: we avoid direct call to the 706 * input function of the network layer in order to avoid recursion. 707 * This may be revisited in the future. 708 */ 709 switch (af) { 710 #ifdef INET 711 case AF_INET: 712 pktq = ip_pktq; 713 break; 714 #endif 715 #ifdef INET6 716 case AF_INET6: 717 pktq = ip6_pktq; 718 break; 719 #endif 720 default: 721 m_freem(m); 722 return; 723 } 724 725 const uint32_t h = pktq_rps_hash(&gif_pktq_rps_hash_p, m); 726 if (__predict_true(pktq_enqueue(pktq, m, h))) { 727 if_statadd2(ifp, if_ibytes, pktlen, if_ipackets, 1); 728 } else { 729 m_freem(m); 730 } 731 } 732 733 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ 734 static int 735 gif_ioctl(struct ifnet *ifp, u_long cmd, void *data) 736 { 737 struct gif_softc *sc = ifp->if_softc; 738 struct ifreq *ifr = (struct ifreq*)data; 739 struct ifaddr *ifa = (struct ifaddr*)data; 740 int error = 0, size, bound; 741 struct sockaddr *dst, *src; 742 struct gif_variant *var; 743 struct psref psref; 744 745 switch (cmd) { 746 case SIOCINITIFADDR: 747 ifp->if_flags |= IFF_UP; 748 ifa->ifa_rtrequest = p2p_rtrequest; 749 break; 750 751 case SIOCADDMULTI: 752 case SIOCDELMULTI: 753 switch (ifr->ifr_addr.sa_family) { 754 #ifdef INET 755 case AF_INET: /* IP supports Multicast */ 756 break; 757 #endif /* INET */ 758 #ifdef INET6 759 case AF_INET6: /* IP6 supports Multicast */ 760 break; 761 #endif /* INET6 */ 762 default: /* Other protocols doesn't support Multicast */ 763 error = EAFNOSUPPORT; 764 break; 765 } 766 break; 767 768 case SIOCSIFMTU: 769 if (ifr->ifr_mtu < GIF_MTU_MIN || ifr->ifr_mtu > GIF_MTU_MAX) 770 return EINVAL; 771 else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) 772 error = 0; 773 break; 774 775 #ifdef INET 776 case SIOCSIFPHYADDR: 777 #endif 778 #ifdef INET6 779 case SIOCSIFPHYADDR_IN6: 780 #endif /* INET6 */ 781 case SIOCSLIFPHYADDR: 782 switch (cmd) { 783 #ifdef INET 784 case SIOCSIFPHYADDR: 785 src = (struct sockaddr *) 786 &(((struct in_aliasreq *)data)->ifra_addr); 787 dst = (struct sockaddr *) 788 &(((struct in_aliasreq *)data)->ifra_dstaddr); 789 break; 790 #endif 791 #ifdef INET6 792 case SIOCSIFPHYADDR_IN6: 793 src = (struct sockaddr *) 794 &(((struct in6_aliasreq *)data)->ifra_addr); 795 dst = (struct sockaddr *) 796 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 797 break; 798 #endif 799 case SIOCSLIFPHYADDR: 800 src = (struct sockaddr *) 801 &(((struct if_laddrreq *)data)->addr); 802 dst = (struct sockaddr *) 803 &(((struct if_laddrreq *)data)->dstaddr); 804 break; 805 default: 806 return EINVAL; 807 } 808 809 /* sa_family must be equal */ 810 if (src->sa_family != dst->sa_family) 811 return EINVAL; 812 813 /* validate sa_len */ 814 switch (src->sa_family) { 815 #ifdef INET 816 case AF_INET: 817 if (src->sa_len != sizeof(struct sockaddr_in)) 818 return EINVAL; 819 break; 820 #endif 821 #ifdef INET6 822 case AF_INET6: 823 if (src->sa_len != sizeof(struct sockaddr_in6)) 824 return EINVAL; 825 break; 826 #endif 827 default: 828 return EAFNOSUPPORT; 829 } 830 switch (dst->sa_family) { 831 #ifdef INET 832 case AF_INET: 833 if (dst->sa_len != sizeof(struct sockaddr_in)) 834 return EINVAL; 835 break; 836 #endif 837 #ifdef INET6 838 case AF_INET6: 839 if (dst->sa_len != sizeof(struct sockaddr_in6)) 840 return EINVAL; 841 break; 842 #endif 843 default: 844 return EAFNOSUPPORT; 845 } 846 847 /* check sa_family looks sane for the cmd */ 848 switch (cmd) { 849 case SIOCSIFPHYADDR: 850 if (src->sa_family == AF_INET) 851 break; 852 return EAFNOSUPPORT; 853 #ifdef INET6 854 case SIOCSIFPHYADDR_IN6: 855 if (src->sa_family == AF_INET6) 856 break; 857 return EAFNOSUPPORT; 858 #endif /* INET6 */ 859 case SIOCSLIFPHYADDR: 860 /* checks done in the above */ 861 break; 862 } 863 864 /* 865 * calls gif_getref_variant() for other softcs to check 866 * address pair duplication 867 */ 868 bound = curlwp_bind(); 869 error = gif_set_tunnel(&sc->gif_if, src, dst); 870 if (error == 0) 871 if_link_state_change(&sc->gif_if, LINK_STATE_UP); 872 curlwp_bindx(bound); 873 874 break; 875 876 #ifdef SIOCDIFPHYADDR 877 case SIOCDIFPHYADDR: 878 bound = curlwp_bind(); 879 gif_delete_tunnel(&sc->gif_if); 880 if_link_state_change(&sc->gif_if, LINK_STATE_DOWN); 881 curlwp_bindx(bound); 882 break; 883 #endif 884 885 case SIOCGIFPSRCADDR: 886 #ifdef INET6 887 case SIOCGIFPSRCADDR_IN6: 888 #endif /* INET6 */ 889 bound = curlwp_bind(); 890 var = gif_getref_variant(sc, &psref); 891 if (var->gv_psrc == NULL) { 892 gif_putref_variant(var, &psref); 893 curlwp_bindx(bound); 894 error = EADDRNOTAVAIL; 895 goto bad; 896 } 897 src = var->gv_psrc; 898 switch (cmd) { 899 #ifdef INET 900 case SIOCGIFPSRCADDR: 901 dst = &ifr->ifr_addr; 902 size = sizeof(ifr->ifr_addr); 903 break; 904 #endif /* INET */ 905 #ifdef INET6 906 case SIOCGIFPSRCADDR_IN6: 907 dst = (struct sockaddr *) 908 &(((struct in6_ifreq *)data)->ifr_addr); 909 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 910 break; 911 #endif /* INET6 */ 912 default: 913 gif_putref_variant(var, &psref); 914 curlwp_bindx(bound); 915 error = EADDRNOTAVAIL; 916 goto bad; 917 } 918 if (src->sa_len > size) { 919 gif_putref_variant(var, &psref); 920 curlwp_bindx(bound); 921 return EINVAL; 922 } 923 memcpy(dst, src, src->sa_len); 924 gif_putref_variant(var, &psref); 925 curlwp_bindx(bound); 926 break; 927 928 case SIOCGIFPDSTADDR: 929 #ifdef INET6 930 case SIOCGIFPDSTADDR_IN6: 931 #endif /* INET6 */ 932 bound = curlwp_bind(); 933 var = gif_getref_variant(sc, &psref); 934 if (var->gv_pdst == NULL) { 935 gif_putref_variant(var, &psref); 936 curlwp_bindx(bound); 937 error = EADDRNOTAVAIL; 938 goto bad; 939 } 940 src = var->gv_pdst; 941 switch (cmd) { 942 #ifdef INET 943 case SIOCGIFPDSTADDR: 944 dst = &ifr->ifr_addr; 945 size = sizeof(ifr->ifr_addr); 946 break; 947 #endif /* INET */ 948 #ifdef INET6 949 case SIOCGIFPDSTADDR_IN6: 950 dst = (struct sockaddr *) 951 &(((struct in6_ifreq *)data)->ifr_addr); 952 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 953 break; 954 #endif /* INET6 */ 955 default: 956 gif_putref_variant(var, &psref); 957 curlwp_bindx(bound); 958 error = EADDRNOTAVAIL; 959 goto bad; 960 } 961 if (src->sa_len > size) { 962 gif_putref_variant(var, &psref); 963 curlwp_bindx(bound); 964 return EINVAL; 965 } 966 memcpy(dst, src, src->sa_len); 967 gif_putref_variant(var, &psref); 968 curlwp_bindx(bound); 969 break; 970 971 case SIOCGLIFPHYADDR: 972 bound = curlwp_bind(); 973 var = gif_getref_variant(sc, &psref); 974 if (var->gv_psrc == NULL || var->gv_pdst == NULL) { 975 gif_putref_variant(var, &psref); 976 curlwp_bindx(bound); 977 error = EADDRNOTAVAIL; 978 goto bad; 979 } 980 981 /* copy src */ 982 src = var->gv_psrc; 983 dst = (struct sockaddr *) 984 &(((struct if_laddrreq *)data)->addr); 985 size = sizeof(((struct if_laddrreq *)data)->addr); 986 if (src->sa_len > size) { 987 gif_putref_variant(var, &psref); 988 curlwp_bindx(bound); 989 return EINVAL; 990 } 991 memcpy(dst, src, src->sa_len); 992 993 /* copy dst */ 994 src = var->gv_pdst; 995 dst = (struct sockaddr *) 996 &(((struct if_laddrreq *)data)->dstaddr); 997 size = sizeof(((struct if_laddrreq *)data)->dstaddr); 998 if (src->sa_len > size) { 999 gif_putref_variant(var, &psref); 1000 curlwp_bindx(bound); 1001 return EINVAL; 1002 } 1003 memcpy(dst, src, src->sa_len); 1004 gif_putref_variant(var, &psref); 1005 curlwp_bindx(bound); 1006 break; 1007 1008 default: 1009 return ifioctl_common(ifp, cmd, data); 1010 } 1011 bad: 1012 return error; 1013 } 1014 1015 static int 1016 gif_encap_attach(struct gif_variant *var) 1017 { 1018 int error; 1019 1020 if (var == NULL || var->gv_psrc == NULL) 1021 return EINVAL; 1022 1023 switch (var->gv_psrc->sa_family) { 1024 #ifdef INET 1025 case AF_INET: 1026 error = in_gif_attach(var); 1027 break; 1028 #endif 1029 #ifdef INET6 1030 case AF_INET6: 1031 error = in6_gif_attach(var); 1032 break; 1033 #endif 1034 default: 1035 error = EINVAL; 1036 break; 1037 } 1038 1039 return error; 1040 } 1041 1042 static int 1043 gif_encap_detach(struct gif_variant *var) 1044 { 1045 int error; 1046 1047 if (var == NULL || var->gv_psrc == NULL) 1048 return EINVAL; 1049 1050 switch (var->gv_psrc->sa_family) { 1051 #ifdef INET 1052 case AF_INET: 1053 error = in_gif_detach(var); 1054 break; 1055 #endif 1056 #ifdef INET6 1057 case AF_INET6: 1058 error = in6_gif_detach(var); 1059 break; 1060 #endif 1061 default: 1062 error = EINVAL; 1063 break; 1064 } 1065 1066 return error; 1067 } 1068 1069 static int 1070 gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) 1071 { 1072 struct gif_softc *sc = ifp->if_softc; 1073 struct gif_softc *sc2; 1074 struct gif_variant *ovar, *nvar; 1075 struct sockaddr *osrc, *odst; 1076 struct sockaddr *nsrc, *ndst; 1077 int error; 1078 #ifndef GIF_MPSAFE 1079 int s; 1080 1081 s = splsoftnet(); 1082 #endif 1083 error = encap_lock_enter(); 1084 if (error) { 1085 #ifndef GIF_MPSAFE 1086 splx(s); 1087 #endif 1088 return error; 1089 } 1090 1091 nsrc = sockaddr_dup(src, M_WAITOK); 1092 ndst = sockaddr_dup(dst, M_WAITOK); 1093 nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP); 1094 1095 mutex_enter(&sc->gif_lock); 1096 1097 ovar = sc->gif_var; 1098 1099 if ((ovar->gv_pdst && sockaddr_cmp(ovar->gv_pdst, dst) == 0) && 1100 (ovar->gv_psrc && sockaddr_cmp(ovar->gv_psrc, src) == 0)) { 1101 /* address and port pair not changed. */ 1102 error = 0; 1103 goto out; 1104 } 1105 1106 mutex_enter(&gif_softcs.lock); 1107 LIST_FOREACH(sc2, &gif_softcs.list, gif_list) { 1108 struct gif_variant *var2; 1109 struct psref psref; 1110 1111 if (sc2 == sc) 1112 continue; 1113 var2 = gif_getref_variant(sc2, &psref); 1114 if (!var2->gv_pdst || !var2->gv_psrc) { 1115 gif_putref_variant(var2, &psref); 1116 continue; 1117 } 1118 /* can't configure same pair of address onto two gifs */ 1119 if (sockaddr_cmp(var2->gv_pdst, dst) == 0 && 1120 sockaddr_cmp(var2->gv_psrc, src) == 0) { 1121 /* continue to use the old configuration. */ 1122 gif_putref_variant(var2, &psref); 1123 mutex_exit(&gif_softcs.lock); 1124 error = EADDRNOTAVAIL; 1125 goto out; 1126 } 1127 gif_putref_variant(var2, &psref); 1128 /* XXX both end must be valid? (I mean, not 0.0.0.0) */ 1129 } 1130 mutex_exit(&gif_softcs.lock); 1131 1132 osrc = ovar->gv_psrc; 1133 odst = ovar->gv_pdst; 1134 1135 *nvar = *ovar; 1136 nvar->gv_psrc = nsrc; 1137 nvar->gv_pdst = ndst; 1138 nvar->gv_encap_cookie4 = NULL; 1139 nvar->gv_encap_cookie6 = NULL; 1140 error = gif_encap_attach(nvar); 1141 if (error) 1142 goto out; 1143 psref_target_init(&nvar->gv_psref, gv_psref_class); 1144 gif_update_variant(sc, nvar); 1145 1146 mutex_exit(&sc->gif_lock); 1147 1148 (void)gif_encap_detach(ovar); 1149 encap_lock_exit(); 1150 1151 if (osrc) 1152 sockaddr_free(osrc); 1153 if (odst) 1154 sockaddr_free(odst); 1155 kmem_free(ovar, sizeof(*ovar)); 1156 1157 #ifndef GIF_MPSAFE 1158 splx(s); 1159 #endif 1160 return 0; 1161 1162 out: 1163 mutex_exit(&sc->gif_lock); 1164 encap_lock_exit(); 1165 1166 sockaddr_free(nsrc); 1167 sockaddr_free(ndst); 1168 kmem_free(nvar, sizeof(*nvar)); 1169 1170 #ifndef GIF_MPSAFE 1171 splx(s); 1172 #endif 1173 return error; 1174 } 1175 1176 static void 1177 gif_delete_tunnel(struct ifnet *ifp) 1178 { 1179 struct gif_softc *sc = ifp->if_softc; 1180 struct gif_variant *ovar, *nvar; 1181 struct sockaddr *osrc, *odst; 1182 int error; 1183 #ifndef GIF_MPSAFE 1184 int s; 1185 1186 s = splsoftnet(); 1187 #endif 1188 error = encap_lock_enter(); 1189 if (error) { 1190 #ifndef GIF_MPSAFE 1191 splx(s); 1192 #endif 1193 return; 1194 } 1195 1196 nvar = kmem_alloc(sizeof(*nvar), KM_SLEEP); 1197 1198 mutex_enter(&sc->gif_lock); 1199 1200 ovar = sc->gif_var; 1201 osrc = ovar->gv_psrc; 1202 odst = ovar->gv_pdst; 1203 if (osrc == NULL || odst == NULL) { 1204 /* address pair not changed. */ 1205 mutex_exit(&sc->gif_lock); 1206 encap_lock_exit(); 1207 kmem_free(nvar, sizeof(*nvar)); 1208 #ifndef GIF_MPSAFE 1209 splx(s); 1210 #endif 1211 return; 1212 } 1213 1214 *nvar = *ovar; 1215 nvar->gv_psrc = NULL; 1216 nvar->gv_pdst = NULL; 1217 nvar->gv_encap_cookie4 = NULL; 1218 nvar->gv_encap_cookie6 = NULL; 1219 nvar->gv_output = NULL; 1220 psref_target_init(&nvar->gv_psref, gv_psref_class); 1221 gif_update_variant(sc, nvar); 1222 1223 mutex_exit(&sc->gif_lock); 1224 1225 gif_encap_detach(ovar); 1226 encap_lock_exit(); 1227 1228 sockaddr_free(osrc); 1229 sockaddr_free(odst); 1230 kmem_free(ovar, sizeof(*ovar)); 1231 1232 #ifndef GIF_MPSAFE 1233 splx(s); 1234 #endif 1235 } 1236 1237 /* 1238 * gif_variant update API. 1239 * 1240 * Assumption: 1241 * reader side dereferences sc->gif_var in reader critical section only, 1242 * that is, all of reader sides do not reader the sc->gif_var after 1243 * pserialize_perform(). 1244 */ 1245 static void 1246 gif_update_variant(struct gif_softc *sc, struct gif_variant *nvar) 1247 { 1248 struct ifnet *ifp = &sc->gif_if; 1249 struct gif_variant *ovar = sc->gif_var; 1250 1251 KASSERT(mutex_owned(&sc->gif_lock)); 1252 1253 atomic_store_release(&sc->gif_var, nvar); 1254 pserialize_perform(sc->gif_psz); 1255 psref_target_destroy(&ovar->gv_psref, gv_psref_class); 1256 1257 if (nvar->gv_psrc != NULL && nvar->gv_pdst != NULL) 1258 ifp->if_flags |= IFF_RUNNING; 1259 else 1260 ifp->if_flags &= ~IFF_RUNNING; 1261 } 1262 1263 /* 1264 * Module infrastructure 1265 */ 1266 #include "if_module.h" 1267 1268 IF_MODULE(MODULE_CLASS_DRIVER, gif, "ip_ecn") 1269