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