1 /* $NetBSD: if_gif.c,v 1.125 2017/02/13 04:05:19 ozaki-r 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.125 2017/02/13 04:05:19 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/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 int error; 452 453 sc = ifp->if_softc; 454 455 /* output processing */ 456 while (1) { 457 IFQ_DEQUEUE(&sc->gif_if.if_snd, m); 458 if (m == NULL) 459 break; 460 461 /* grab and chop off inner af type */ 462 if (sizeof(int) > m->m_len) { 463 m = m_pullup(m, sizeof(int)); 464 if (!m) { 465 ifp->if_oerrors++; 466 continue; 467 } 468 } 469 family = *mtod(m, int *); 470 bpf_mtap(ifp, m); 471 m_adj(m, sizeof(int)); 472 473 len = m->m_pkthdr.len; 474 475 /* dispatch to output logic based on outer AF */ 476 switch (sc->gif_psrc->sa_family) { 477 #ifdef INET 478 case AF_INET: 479 /* XXX 480 * To add mutex_enter(softnet_lock) or 481 * KASSERT(mutex_owned(softnet_lock)) here, we shold 482 * coordinate softnet_lock between in6_if_up() and 483 * in6_purgeif(). 484 */ 485 error = in_gif_output(ifp, family, m); 486 break; 487 #endif 488 #ifdef INET6 489 case AF_INET6: 490 /* XXX 491 * the same as in_gif_output() 492 */ 493 error = in6_gif_output(ifp, family, m); 494 break; 495 #endif 496 default: 497 m_freem(m); 498 error = ENETDOWN; 499 break; 500 } 501 502 if (error) 503 ifp->if_oerrors++; 504 else { 505 ifp->if_opackets++; 506 ifp->if_obytes += len; 507 } 508 } 509 } 510 511 static int 512 gif_transmit(struct ifnet *ifp, struct mbuf *m) 513 { 514 struct gif_softc *sc; 515 int family; 516 int len; 517 int error; 518 519 sc = ifp->if_softc; 520 521 /* output processing */ 522 if (m == NULL) 523 return EINVAL; 524 525 /* grab and chop off inner af type */ 526 if (sizeof(int) > m->m_len) { 527 m = m_pullup(m, sizeof(int)); 528 if (!m) { 529 ifp->if_oerrors++; 530 return ENOBUFS; 531 } 532 } 533 family = *mtod(m, int *); 534 bpf_mtap(ifp, m); 535 m_adj(m, sizeof(int)); 536 537 len = m->m_pkthdr.len; 538 539 /* dispatch to output logic based on outer AF */ 540 switch (sc->gif_psrc->sa_family) { 541 #ifdef INET 542 case AF_INET: 543 /* XXX 544 * To add mutex_enter(softnet_lock) or 545 * KASSERT(mutex_owned(softnet_lock)) here, we shold 546 * coordinate softnet_lock between in6_if_up() and 547 * in6_purgeif(). 548 */ 549 error = in_gif_output(ifp, family, m); 550 break; 551 #endif 552 #ifdef INET6 553 case AF_INET6: 554 /* XXX 555 * the same as in_gif_output() 556 */ 557 error = in6_gif_output(ifp, family, m); 558 break; 559 #endif 560 default: 561 m_freem(m); 562 error = ENETDOWN; 563 break; 564 } 565 566 if (error) 567 ifp->if_oerrors++; 568 else { 569 ifp->if_opackets++; 570 ifp->if_obytes += len; 571 } 572 573 return error; 574 } 575 576 void 577 gif_input(struct mbuf *m, int af, struct ifnet *ifp) 578 { 579 pktqueue_t *pktq; 580 size_t pktlen; 581 582 if (ifp == NULL) { 583 /* just in case */ 584 m_freem(m); 585 return; 586 } 587 588 m_set_rcvif(m, ifp); 589 pktlen = m->m_pkthdr.len; 590 591 bpf_mtap_af(ifp, af, m); 592 593 /* 594 * Put the packet to the network layer input queue according to the 595 * specified address family. Note: we avoid direct call to the 596 * input function of the network layer in order to avoid recursion. 597 * This may be revisited in the future. 598 */ 599 switch (af) { 600 #ifdef INET 601 case AF_INET: 602 pktq = ip_pktq; 603 break; 604 #endif 605 #ifdef INET6 606 case AF_INET6: 607 pktq = ip6_pktq; 608 break; 609 #endif 610 default: 611 m_freem(m); 612 return; 613 } 614 615 if (__predict_true(pktq_enqueue(pktq, m, 0))) { 616 ifp->if_ibytes += pktlen; 617 ifp->if_ipackets++; 618 } else { 619 m_freem(m); 620 } 621 } 622 623 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ 624 static int 625 gif_ioctl(struct ifnet *ifp, u_long cmd, void *data) 626 { 627 struct gif_softc *sc = ifp->if_softc; 628 struct ifreq *ifr = (struct ifreq*)data; 629 struct ifaddr *ifa = (struct ifaddr*)data; 630 int error = 0, size; 631 struct sockaddr *dst, *src; 632 633 switch (cmd) { 634 case SIOCINITIFADDR: 635 ifp->if_flags |= IFF_UP; 636 ifa->ifa_rtrequest = p2p_rtrequest; 637 break; 638 639 case SIOCADDMULTI: 640 case SIOCDELMULTI: 641 switch (ifr->ifr_addr.sa_family) { 642 #ifdef INET 643 case AF_INET: /* IP supports Multicast */ 644 break; 645 #endif /* INET */ 646 #ifdef INET6 647 case AF_INET6: /* IP6 supports Multicast */ 648 break; 649 #endif /* INET6 */ 650 default: /* Other protocols doesn't support Multicast */ 651 error = EAFNOSUPPORT; 652 break; 653 } 654 break; 655 656 case SIOCSIFMTU: 657 if (ifr->ifr_mtu < GIF_MTU_MIN || ifr->ifr_mtu > GIF_MTU_MAX) 658 return EINVAL; 659 else if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) 660 error = 0; 661 break; 662 663 #ifdef INET 664 case SIOCSIFPHYADDR: 665 #endif 666 #ifdef INET6 667 case SIOCSIFPHYADDR_IN6: 668 #endif /* INET6 */ 669 case SIOCSLIFPHYADDR: 670 switch (cmd) { 671 #ifdef INET 672 case SIOCSIFPHYADDR: 673 src = (struct sockaddr *) 674 &(((struct in_aliasreq *)data)->ifra_addr); 675 dst = (struct sockaddr *) 676 &(((struct in_aliasreq *)data)->ifra_dstaddr); 677 break; 678 #endif 679 #ifdef INET6 680 case SIOCSIFPHYADDR_IN6: 681 src = (struct sockaddr *) 682 &(((struct in6_aliasreq *)data)->ifra_addr); 683 dst = (struct sockaddr *) 684 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 685 break; 686 #endif 687 case SIOCSLIFPHYADDR: 688 src = (struct sockaddr *) 689 &(((struct if_laddrreq *)data)->addr); 690 dst = (struct sockaddr *) 691 &(((struct if_laddrreq *)data)->dstaddr); 692 break; 693 default: 694 return EINVAL; 695 } 696 697 /* sa_family must be equal */ 698 if (src->sa_family != dst->sa_family) 699 return EINVAL; 700 701 /* validate sa_len */ 702 switch (src->sa_family) { 703 #ifdef INET 704 case AF_INET: 705 if (src->sa_len != sizeof(struct sockaddr_in)) 706 return EINVAL; 707 break; 708 #endif 709 #ifdef INET6 710 case AF_INET6: 711 if (src->sa_len != sizeof(struct sockaddr_in6)) 712 return EINVAL; 713 break; 714 #endif 715 default: 716 return EAFNOSUPPORT; 717 } 718 switch (dst->sa_family) { 719 #ifdef INET 720 case AF_INET: 721 if (dst->sa_len != sizeof(struct sockaddr_in)) 722 return EINVAL; 723 break; 724 #endif 725 #ifdef INET6 726 case AF_INET6: 727 if (dst->sa_len != sizeof(struct sockaddr_in6)) 728 return EINVAL; 729 break; 730 #endif 731 default: 732 return EAFNOSUPPORT; 733 } 734 735 /* check sa_family looks sane for the cmd */ 736 switch (cmd) { 737 case SIOCSIFPHYADDR: 738 if (src->sa_family == AF_INET) 739 break; 740 return EAFNOSUPPORT; 741 #ifdef INET6 742 case SIOCSIFPHYADDR_IN6: 743 if (src->sa_family == AF_INET6) 744 break; 745 return EAFNOSUPPORT; 746 #endif /* INET6 */ 747 case SIOCSLIFPHYADDR: 748 /* checks done in the above */ 749 break; 750 } 751 752 error = gif_set_tunnel(&sc->gif_if, src, dst); 753 break; 754 755 #ifdef SIOCDIFPHYADDR 756 case SIOCDIFPHYADDR: 757 gif_delete_tunnel(&sc->gif_if); 758 break; 759 #endif 760 761 case SIOCGIFPSRCADDR: 762 #ifdef INET6 763 case SIOCGIFPSRCADDR_IN6: 764 #endif /* INET6 */ 765 if (sc->gif_psrc == NULL) { 766 error = EADDRNOTAVAIL; 767 goto bad; 768 } 769 src = sc->gif_psrc; 770 switch (cmd) { 771 #ifdef INET 772 case SIOCGIFPSRCADDR: 773 dst = &ifr->ifr_addr; 774 size = sizeof(ifr->ifr_addr); 775 break; 776 #endif /* INET */ 777 #ifdef INET6 778 case SIOCGIFPSRCADDR_IN6: 779 dst = (struct sockaddr *) 780 &(((struct in6_ifreq *)data)->ifr_addr); 781 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 782 break; 783 #endif /* INET6 */ 784 default: 785 error = EADDRNOTAVAIL; 786 goto bad; 787 } 788 if (src->sa_len > size) 789 return EINVAL; 790 memcpy(dst, src, src->sa_len); 791 break; 792 793 case SIOCGIFPDSTADDR: 794 #ifdef INET6 795 case SIOCGIFPDSTADDR_IN6: 796 #endif /* INET6 */ 797 if (sc->gif_pdst == NULL) { 798 error = EADDRNOTAVAIL; 799 goto bad; 800 } 801 src = sc->gif_pdst; 802 switch (cmd) { 803 #ifdef INET 804 case SIOCGIFPDSTADDR: 805 dst = &ifr->ifr_addr; 806 size = sizeof(ifr->ifr_addr); 807 break; 808 #endif /* INET */ 809 #ifdef INET6 810 case SIOCGIFPDSTADDR_IN6: 811 dst = (struct sockaddr *) 812 &(((struct in6_ifreq *)data)->ifr_addr); 813 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 814 break; 815 #endif /* INET6 */ 816 default: 817 error = EADDRNOTAVAIL; 818 goto bad; 819 } 820 if (src->sa_len > size) 821 return EINVAL; 822 memcpy(dst, src, src->sa_len); 823 break; 824 825 case SIOCGLIFPHYADDR: 826 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 827 error = EADDRNOTAVAIL; 828 goto bad; 829 } 830 831 /* copy src */ 832 src = sc->gif_psrc; 833 dst = (struct sockaddr *) 834 &(((struct if_laddrreq *)data)->addr); 835 size = sizeof(((struct if_laddrreq *)data)->addr); 836 if (src->sa_len > size) 837 return EINVAL; 838 memcpy(dst, src, src->sa_len); 839 840 /* copy dst */ 841 src = sc->gif_pdst; 842 dst = (struct sockaddr *) 843 &(((struct if_laddrreq *)data)->dstaddr); 844 size = sizeof(((struct if_laddrreq *)data)->dstaddr); 845 if (src->sa_len > size) 846 return EINVAL; 847 memcpy(dst, src, src->sa_len); 848 break; 849 850 default: 851 return ifioctl_common(ifp, cmd, data); 852 } 853 bad: 854 return error; 855 } 856 857 static int 858 gif_encap_attach(struct gif_softc *sc) 859 { 860 int error; 861 862 if (sc == NULL || sc->gif_psrc == NULL) 863 return EINVAL; 864 865 switch (sc->gif_psrc->sa_family) { 866 #ifdef INET 867 case AF_INET: 868 error = in_gif_attach(sc); 869 break; 870 #endif 871 #ifdef INET6 872 case AF_INET6: 873 error = in6_gif_attach(sc); 874 break; 875 #endif 876 default: 877 error = EINVAL; 878 break; 879 } 880 881 return error; 882 } 883 884 static int 885 gif_encap_detach(struct gif_softc *sc) 886 { 887 int error; 888 889 if (sc == NULL || sc->gif_psrc == NULL) 890 return EINVAL; 891 892 switch (sc->gif_psrc->sa_family) { 893 #ifdef INET 894 case AF_INET: 895 error = in_gif_detach(sc); 896 break; 897 #endif 898 #ifdef INET6 899 case AF_INET6: 900 error = in6_gif_detach(sc); 901 break; 902 #endif 903 default: 904 error = EINVAL; 905 break; 906 } 907 908 return error; 909 } 910 911 static void 912 gif_encap_pause(struct gif_softc *sc) 913 { 914 struct ifnet *ifp; 915 uint64_t where; 916 917 if (sc == NULL || sc->gif_psrc == NULL) 918 return; 919 920 ifp = &sc->gif_if; 921 if ((ifp->if_flags & IFF_RUNNING) == 0) 922 return; 923 924 switch (sc->gif_psrc->sa_family) { 925 #ifdef INET 926 case AF_INET: 927 (void)in_gif_pause(sc); 928 break; 929 #endif 930 #ifdef INET6 931 case AF_INET6: 932 (void)in6_gif_pause(sc); 933 break; 934 #endif 935 } 936 937 ifp->if_flags &= ~IFF_RUNNING; 938 /* membar_sync() is done in xc_broadcast(). */ 939 940 /* 941 * Wait for softint_execute()(ipintr() or ip6intr()) 942 * completion done by other CPUs which already run over if_flags 943 * check in in_gif_input() or in6_gif_input(). 944 * Furthermore, wait for gif_output() completion too. 945 */ 946 where = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL); 947 xc_wait(where); 948 } 949 950 static int 951 gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) 952 { 953 struct gif_softc *sc = ifp->if_softc; 954 struct gif_softc *sc2; 955 struct sockaddr *osrc, *odst; 956 struct sockaddr *nsrc, *ndst; 957 int error; 958 #ifndef GIF_MPSAFE 959 int s; 960 961 s = splsoftnet(); 962 #endif 963 error = encap_lock_enter(); 964 if (error) { 965 #ifndef GIF_MPSAFE 966 splx(s); 967 #endif 968 return error; 969 } 970 971 LIST_FOREACH(sc2, &gif_softc_list, gif_list) { 972 if (sc2 == sc) 973 continue; 974 if (!sc2->gif_pdst || !sc2->gif_psrc) 975 continue; 976 /* can't configure same pair of address onto two gifs */ 977 if (sockaddr_cmp(sc2->gif_pdst, dst) == 0 && 978 sockaddr_cmp(sc2->gif_psrc, src) == 0) { 979 /* continue to use the old configureation. */ 980 error = EADDRNOTAVAIL; 981 goto out; 982 } 983 984 /* XXX both end must be valid? (I mean, not 0.0.0.0) */ 985 } 986 987 nsrc = sockaddr_dup(src, M_WAITOK); 988 ndst = sockaddr_dup(dst, M_WAITOK); 989 990 gif_encap_pause(sc); 991 992 /* Firstly, clear old configurations. */ 993 /* XXX we can detach from both, but be polite just in case */ 994 if (sc->gif_psrc) 995 (void)gif_encap_detach(sc); 996 997 /* 998 * Secondly, try to set new configurations. 999 * If the setup failed, rollback to old configurations. 1000 */ 1001 do { 1002 osrc = sc->gif_psrc; 1003 odst = sc->gif_pdst; 1004 sc->gif_psrc = nsrc; 1005 sc->gif_pdst = ndst; 1006 1007 error = gif_encap_attach(sc); 1008 if (error) { 1009 /* rollback to the last configuration. */ 1010 nsrc = osrc; 1011 ndst = odst; 1012 osrc = sc->gif_psrc; 1013 odst = sc->gif_pdst; 1014 1015 continue; 1016 } 1017 } while (error != 0 && (nsrc != NULL && ndst != NULL)); 1018 /* Thirdly, even rollback failed, clear configurations. */ 1019 if (error) { 1020 osrc = sc->gif_psrc; 1021 odst = sc->gif_pdst; 1022 sc->gif_psrc = NULL; 1023 sc->gif_pdst = NULL; 1024 } 1025 1026 if (osrc) 1027 sockaddr_free(osrc); 1028 if (odst) 1029 sockaddr_free(odst); 1030 1031 if (sc->gif_psrc && sc->gif_pdst) 1032 ifp->if_flags |= IFF_RUNNING; 1033 else 1034 ifp->if_flags &= ~IFF_RUNNING; 1035 1036 out: 1037 encap_lock_exit(); 1038 #ifndef GIF_MPSAFE 1039 splx(s); 1040 #endif 1041 return error; 1042 } 1043 1044 static void 1045 gif_delete_tunnel(struct ifnet *ifp) 1046 { 1047 struct gif_softc *sc = ifp->if_softc; 1048 int error; 1049 #ifndef GIF_MPSAFE 1050 int s; 1051 1052 s = splsoftnet(); 1053 #endif 1054 error = encap_lock_enter(); 1055 if (error) { 1056 #ifndef GIF_MPSAFE 1057 splx(s); 1058 #endif 1059 return; 1060 } 1061 1062 gif_encap_pause(sc); 1063 if (sc->gif_psrc) { 1064 sockaddr_free(sc->gif_psrc); 1065 sc->gif_psrc = NULL; 1066 } 1067 if (sc->gif_pdst) { 1068 sockaddr_free(sc->gif_pdst); 1069 sc->gif_pdst = NULL; 1070 } 1071 /* it is safe to detach from both */ 1072 #ifdef INET 1073 (void)in_gif_detach(sc); 1074 #endif 1075 #ifdef INET6 1076 (void)in6_gif_detach(sc); 1077 #endif 1078 1079 if (sc->gif_psrc && sc->gif_pdst) 1080 ifp->if_flags |= IFF_RUNNING; 1081 else 1082 ifp->if_flags &= ~IFF_RUNNING; 1083 1084 encap_lock_exit(); 1085 #ifndef GIF_MPSAFE 1086 splx(s); 1087 #endif 1088 } 1089 1090 /* 1091 * Module infrastructure 1092 */ 1093 #include "if_module.h" 1094 1095 IF_MODULE(MODULE_CLASS_DRIVER, gif, "") 1096