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