1 /* $FreeBSD$ */ 2 /* $KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 itojun 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 "opt_inet.h" 34 #include "opt_inet6.h" 35 #include "opt_mac.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/malloc.h> 41 #include <sys/mbuf.h> 42 #include <sys/module.h> 43 #include <sys/socket.h> 44 #include <sys/sockio.h> 45 #include <sys/errno.h> 46 #include <sys/time.h> 47 #include <sys/sysctl.h> 48 #include <sys/syslog.h> 49 #include <sys/proc.h> 50 #include <sys/protosw.h> 51 #include <sys/conf.h> 52 #include <sys/vimage.h> 53 #include <machine/cpu.h> 54 55 #include <net/if.h> 56 #include <net/if_clone.h> 57 #include <net/if_types.h> 58 #include <net/netisr.h> 59 #include <net/route.h> 60 #include <net/bpf.h> 61 62 #include <netinet/in.h> 63 #include <netinet/in_systm.h> 64 #include <netinet/ip.h> 65 #ifdef INET 66 #include <netinet/in_var.h> 67 #include <netinet/in_gif.h> 68 #include <netinet/ip_var.h> 69 #endif /* INET */ 70 71 #ifdef INET6 72 #ifndef INET 73 #include <netinet/in.h> 74 #endif 75 #include <netinet6/in6_var.h> 76 #include <netinet/ip6.h> 77 #include <netinet6/ip6_var.h> 78 #include <netinet6/scope6_var.h> 79 #include <netinet6/in6_gif.h> 80 #include <netinet6/ip6protosw.h> 81 #endif /* INET6 */ 82 83 #include <netinet/ip_encap.h> 84 #include <net/ethernet.h> 85 #include <net/if_bridgevar.h> 86 #include <net/if_gif.h> 87 88 #include <security/mac/mac_framework.h> 89 90 #define GIFNAME "gif" 91 92 /* 93 * gif_mtx protects the global gif_softc_list. 94 */ 95 static struct mtx gif_mtx; 96 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); 97 static LIST_HEAD(, gif_softc) gif_softc_list; 98 99 void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af); 100 void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af); 101 void (*ng_gif_attach_p)(struct ifnet *ifp); 102 void (*ng_gif_detach_p)(struct ifnet *ifp); 103 104 static void gif_start(struct ifnet *); 105 static int gif_clone_create(struct if_clone *, int, caddr_t); 106 static void gif_clone_destroy(struct ifnet *); 107 108 IFC_SIMPLE_DECLARE(gif, 0); 109 110 static int gifmodevent(module_t, int, void *); 111 112 SYSCTL_DECL(_net_link); 113 SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0, 114 "Generic Tunnel Interface"); 115 #ifndef MAX_GIF_NEST 116 /* 117 * This macro controls the default upper limitation on nesting of gif tunnels. 118 * Since, setting a large value to this macro with a careless configuration 119 * may introduce system crash, we don't allow any nestings by default. 120 * If you need to configure nested gif tunnels, you can define this macro 121 * in your kernel configuration file. However, if you do so, please be 122 * careful to configure the tunnels so that it won't make a loop. 123 */ 124 #define MAX_GIF_NEST 1 125 #endif 126 static int max_gif_nesting = MAX_GIF_NEST; 127 SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, 128 &max_gif_nesting, 0, "Max nested tunnels"); 129 130 /* 131 * By default, we disallow creation of multiple tunnels between the same 132 * pair of addresses. Some applications require this functionality so 133 * we allow control over this check here. 134 */ 135 #ifdef XBONEHACK 136 static int parallel_tunnels = 1; 137 #else 138 static int parallel_tunnels = 0; 139 #endif 140 SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, 141 ¶llel_tunnels, 0, "Allow parallel tunnels?"); 142 143 /* copy from src/sys/net/if_ethersubr.c */ 144 static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = 145 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 146 #ifndef ETHER_IS_BROADCAST 147 #define ETHER_IS_BROADCAST(addr) \ 148 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0) 149 #endif 150 151 static int 152 gif_clone_create(ifc, unit, params) 153 struct if_clone *ifc; 154 int unit; 155 caddr_t params; 156 { 157 struct gif_softc *sc; 158 159 sc = malloc(sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO); 160 sc->gif_fibnum = curthread->td_proc->p_fibnum; 161 GIF2IFP(sc) = if_alloc(IFT_GIF); 162 if (GIF2IFP(sc) == NULL) { 163 free(sc, M_GIF); 164 return (ENOSPC); 165 } 166 167 GIF_LOCK_INIT(sc); 168 169 GIF2IFP(sc)->if_softc = sc; 170 if_initname(GIF2IFP(sc), ifc->ifc_name, unit); 171 172 sc->encap_cookie4 = sc->encap_cookie6 = NULL; 173 174 GIF2IFP(sc)->if_addrlen = 0; 175 GIF2IFP(sc)->if_mtu = GIF_MTU; 176 GIF2IFP(sc)->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 177 #if 0 178 /* turn off ingress filter */ 179 GIF2IFP(sc)->if_flags |= IFF_LINK2; 180 #endif 181 GIF2IFP(sc)->if_ioctl = gif_ioctl; 182 GIF2IFP(sc)->if_start = gif_start; 183 GIF2IFP(sc)->if_output = gif_output; 184 GIF2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN; 185 if_attach(GIF2IFP(sc)); 186 bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t)); 187 if (ng_gif_attach_p != NULL) 188 (*ng_gif_attach_p)(GIF2IFP(sc)); 189 190 mtx_lock(&gif_mtx); 191 LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list); 192 mtx_unlock(&gif_mtx); 193 194 return (0); 195 } 196 197 static void 198 gif_clone_destroy(ifp) 199 struct ifnet *ifp; 200 { 201 int err; 202 struct gif_softc *sc = ifp->if_softc; 203 204 mtx_lock(&gif_mtx); 205 LIST_REMOVE(sc, gif_list); 206 mtx_unlock(&gif_mtx); 207 208 gif_delete_tunnel(ifp); 209 #ifdef INET6 210 if (sc->encap_cookie6 != NULL) { 211 err = encap_detach(sc->encap_cookie6); 212 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6")); 213 } 214 #endif 215 #ifdef INET 216 if (sc->encap_cookie4 != NULL) { 217 err = encap_detach(sc->encap_cookie4); 218 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4")); 219 } 220 #endif 221 222 if (ng_gif_detach_p != NULL) 223 (*ng_gif_detach_p)(ifp); 224 bpfdetach(ifp); 225 if_detach(ifp); 226 if_free(ifp); 227 228 GIF_LOCK_DESTROY(sc); 229 230 free(sc, M_GIF); 231 } 232 233 static int 234 gifmodevent(mod, type, data) 235 module_t mod; 236 int type; 237 void *data; 238 { 239 240 switch (type) { 241 case MOD_LOAD: 242 mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF); 243 LIST_INIT(&V_gif_softc_list); 244 if_clone_attach(&gif_cloner); 245 246 #ifdef INET6 247 V_ip6_gif_hlim = GIF_HLIM; 248 #endif 249 250 break; 251 case MOD_UNLOAD: 252 if_clone_detach(&gif_cloner); 253 mtx_destroy(&gif_mtx); 254 #ifdef INET6 255 V_ip6_gif_hlim = 0; 256 #endif 257 break; 258 default: 259 return EOPNOTSUPP; 260 } 261 return 0; 262 } 263 264 static moduledata_t gif_mod = { 265 "if_gif", 266 gifmodevent, 267 0 268 }; 269 270 DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 271 MODULE_VERSION(if_gif, 1); 272 273 int 274 gif_encapcheck(m, off, proto, arg) 275 const struct mbuf *m; 276 int off; 277 int proto; 278 void *arg; 279 { 280 struct ip ip; 281 struct gif_softc *sc; 282 283 sc = (struct gif_softc *)arg; 284 if (sc == NULL) 285 return 0; 286 287 if ((GIF2IFP(sc)->if_flags & IFF_UP) == 0) 288 return 0; 289 290 /* no physical address */ 291 if (!sc->gif_psrc || !sc->gif_pdst) 292 return 0; 293 294 switch (proto) { 295 #ifdef INET 296 case IPPROTO_IPV4: 297 break; 298 #endif 299 #ifdef INET6 300 case IPPROTO_IPV6: 301 break; 302 #endif 303 case IPPROTO_ETHERIP: 304 break; 305 306 default: 307 return 0; 308 } 309 310 /* Bail on short packets */ 311 if (m->m_pkthdr.len < sizeof(ip)) 312 return 0; 313 314 m_copydata(m, 0, sizeof(ip), (caddr_t)&ip); 315 316 switch (ip.ip_v) { 317 #ifdef INET 318 case 4: 319 if (sc->gif_psrc->sa_family != AF_INET || 320 sc->gif_pdst->sa_family != AF_INET) 321 return 0; 322 return gif_encapcheck4(m, off, proto, arg); 323 #endif 324 #ifdef INET6 325 case 6: 326 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) 327 return 0; 328 if (sc->gif_psrc->sa_family != AF_INET6 || 329 sc->gif_pdst->sa_family != AF_INET6) 330 return 0; 331 return gif_encapcheck6(m, off, proto, arg); 332 #endif 333 default: 334 return 0; 335 } 336 } 337 338 static void 339 gif_start(struct ifnet *ifp) 340 { 341 struct gif_softc *sc; 342 struct mbuf *m; 343 344 sc = ifp->if_softc; 345 346 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 347 for (;;) { 348 IFQ_DEQUEUE(&ifp->if_snd, m); 349 if (m == 0) 350 break; 351 352 gif_output(ifp, m, sc->gif_pdst, NULL); 353 354 } 355 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 356 357 return; 358 } 359 360 int 361 gif_output(ifp, m, dst, rt) 362 struct ifnet *ifp; 363 struct mbuf *m; 364 struct sockaddr *dst; 365 struct rtentry *rt; /* added in net2 */ 366 { 367 struct gif_softc *sc = ifp->if_softc; 368 struct m_tag *mtag; 369 int error = 0; 370 int gif_called; 371 u_int32_t af; 372 373 #ifdef MAC 374 error = mac_ifnet_check_transmit(ifp, m); 375 if (error) { 376 m_freem(m); 377 goto end; 378 } 379 #endif 380 381 /* 382 * gif may cause infinite recursion calls when misconfigured. 383 * We'll prevent this by detecting loops. 384 * 385 * High nesting level may cause stack exhaustion. 386 * We'll prevent this by introducing upper limit. 387 */ 388 gif_called = 1; 389 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL); 390 while (mtag != NULL) { 391 if (*(struct ifnet **)(mtag + 1) == ifp) { 392 log(LOG_NOTICE, 393 "gif_output: loop detected on %s\n", 394 (*(struct ifnet **)(mtag + 1))->if_xname); 395 m_freem(m); 396 error = EIO; /* is there better errno? */ 397 goto end; 398 } 399 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag); 400 gif_called++; 401 } 402 if (gif_called > V_max_gif_nesting) { 403 log(LOG_NOTICE, 404 "gif_output: recursively called too many times(%d)\n", 405 gif_called); 406 m_freem(m); 407 error = EIO; /* is there better errno? */ 408 goto end; 409 } 410 mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *), 411 M_NOWAIT); 412 if (mtag == NULL) { 413 m_freem(m); 414 error = ENOMEM; 415 goto end; 416 } 417 *(struct ifnet **)(mtag + 1) = ifp; 418 m_tag_prepend(m, mtag); 419 420 m->m_flags &= ~(M_BCAST|M_MCAST); 421 422 GIF_LOCK(sc); 423 424 if (!(ifp->if_flags & IFF_UP) || 425 sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 426 GIF_UNLOCK(sc); 427 m_freem(m); 428 error = ENETDOWN; 429 goto end; 430 } 431 432 /* BPF writes need to be handled specially. */ 433 if (dst->sa_family == AF_UNSPEC) { 434 bcopy(dst->sa_data, &af, sizeof(af)); 435 dst->sa_family = af; 436 } 437 438 af = dst->sa_family; 439 BPF_MTAP2(ifp, &af, sizeof(af), m); 440 ifp->if_opackets++; 441 ifp->if_obytes += m->m_pkthdr.len; 442 443 /* override to IPPROTO_ETHERIP for bridged traffic */ 444 if (ifp->if_bridge) 445 af = AF_LINK; 446 447 M_SETFIB(m, sc->gif_fibnum); 448 /* inner AF-specific encapsulation */ 449 450 /* XXX should we check if our outer source is legal? */ 451 452 /* dispatch to output logic based on outer AF */ 453 switch (sc->gif_psrc->sa_family) { 454 #ifdef INET 455 case AF_INET: 456 error = in_gif_output(ifp, af, m); 457 break; 458 #endif 459 #ifdef INET6 460 case AF_INET6: 461 error = in6_gif_output(ifp, af, m); 462 break; 463 #endif 464 default: 465 m_freem(m); 466 error = ENETDOWN; 467 } 468 469 GIF_UNLOCK(sc); 470 end: 471 if (error) 472 ifp->if_oerrors++; 473 return (error); 474 } 475 476 void 477 gif_input(m, af, ifp) 478 struct mbuf *m; 479 int af; 480 struct ifnet *ifp; 481 { 482 int isr, n; 483 struct etherip_header *eip; 484 struct ether_header *eh; 485 struct ifnet *oldifp; 486 487 if (ifp == NULL) { 488 /* just in case */ 489 m_freem(m); 490 return; 491 } 492 493 m->m_pkthdr.rcvif = ifp; 494 495 #ifdef MAC 496 mac_ifnet_create_mbuf(ifp, m); 497 #endif 498 499 if (bpf_peers_present(ifp->if_bpf)) { 500 u_int32_t af1 = af; 501 bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); 502 } 503 504 if (ng_gif_input_p != NULL) { 505 (*ng_gif_input_p)(ifp, &m, af); 506 if (m == NULL) 507 return; 508 } 509 510 /* 511 * Put the packet to the network layer input queue according to the 512 * specified address family. 513 * Note: older versions of gif_input directly called network layer 514 * input functions, e.g. ip6_input, here. We changed the policy to 515 * prevent too many recursive calls of such input functions, which 516 * might cause kernel panic. But the change may introduce another 517 * problem; if the input queue is full, packets are discarded. 518 * The kernel stack overflow really happened, and we believed 519 * queue-full rarely occurs, so we changed the policy. 520 */ 521 switch (af) { 522 #ifdef INET 523 case AF_INET: 524 isr = NETISR_IP; 525 break; 526 #endif 527 #ifdef INET6 528 case AF_INET6: 529 isr = NETISR_IPV6; 530 break; 531 #endif 532 case AF_LINK: 533 n = sizeof(struct etherip_header) + sizeof(struct ether_header); 534 if (n > m->m_len) { 535 m = m_pullup(m, n); 536 if (m == NULL) { 537 ifp->if_ierrors++; 538 return; 539 } 540 } 541 542 eip = mtod(m, struct etherip_header *); 543 if (eip->eip_ver != 544 (ETHERIP_VERSION & ETHERIP_VER_VERS_MASK)) { 545 /* discard unknown versions */ 546 m_freem(m); 547 return; 548 } 549 m_adj(m, sizeof(struct etherip_header)); 550 551 m->m_flags &= ~(M_BCAST|M_MCAST); 552 m->m_pkthdr.rcvif = ifp; 553 554 if (ifp->if_bridge) { 555 oldifp = ifp; 556 eh = mtod(m, struct ether_header *); 557 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 558 if (ETHER_IS_BROADCAST(eh->ether_dhost)) 559 m->m_flags |= M_BCAST; 560 else 561 m->m_flags |= M_MCAST; 562 ifp->if_imcasts++; 563 } 564 BRIDGE_INPUT(ifp, m); 565 566 if (m != NULL && ifp != oldifp) { 567 /* 568 * The bridge gave us back itself or one of the 569 * members for which the frame is addressed. 570 */ 571 ether_demux(ifp, m); 572 return; 573 } 574 } 575 if (m != NULL) 576 m_freem(m); 577 return; 578 579 default: 580 if (ng_gif_input_orphan_p != NULL) 581 (*ng_gif_input_orphan_p)(ifp, m, af); 582 else 583 m_freem(m); 584 return; 585 } 586 587 ifp->if_ipackets++; 588 ifp->if_ibytes += m->m_pkthdr.len; 589 netisr_dispatch(isr, m); 590 } 591 592 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ 593 int 594 gif_ioctl(ifp, cmd, data) 595 struct ifnet *ifp; 596 u_long cmd; 597 caddr_t data; 598 { 599 struct gif_softc *sc = ifp->if_softc; 600 struct ifreq *ifr = (struct ifreq*)data; 601 int error = 0, size; 602 struct sockaddr *dst, *src; 603 #ifdef SIOCSIFMTU /* xxx */ 604 u_long mtu; 605 #endif 606 607 switch (cmd) { 608 case SIOCSIFADDR: 609 ifp->if_flags |= IFF_UP; 610 break; 611 612 case SIOCSIFDSTADDR: 613 break; 614 615 case SIOCADDMULTI: 616 case SIOCDELMULTI: 617 break; 618 619 #ifdef SIOCSIFMTU /* xxx */ 620 case SIOCGIFMTU: 621 break; 622 623 case SIOCSIFMTU: 624 mtu = ifr->ifr_mtu; 625 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) 626 return (EINVAL); 627 ifp->if_mtu = mtu; 628 break; 629 #endif /* SIOCSIFMTU */ 630 631 #ifdef INET 632 case SIOCSIFPHYADDR: 633 #endif 634 #ifdef INET6 635 case SIOCSIFPHYADDR_IN6: 636 #endif /* INET6 */ 637 case SIOCSLIFPHYADDR: 638 switch (cmd) { 639 #ifdef INET 640 case SIOCSIFPHYADDR: 641 src = (struct sockaddr *) 642 &(((struct in_aliasreq *)data)->ifra_addr); 643 dst = (struct sockaddr *) 644 &(((struct in_aliasreq *)data)->ifra_dstaddr); 645 break; 646 #endif 647 #ifdef INET6 648 case SIOCSIFPHYADDR_IN6: 649 src = (struct sockaddr *) 650 &(((struct in6_aliasreq *)data)->ifra_addr); 651 dst = (struct sockaddr *) 652 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 653 break; 654 #endif 655 case SIOCSLIFPHYADDR: 656 src = (struct sockaddr *) 657 &(((struct if_laddrreq *)data)->addr); 658 dst = (struct sockaddr *) 659 &(((struct if_laddrreq *)data)->dstaddr); 660 break; 661 default: 662 return EINVAL; 663 } 664 665 /* sa_family must be equal */ 666 if (src->sa_family != dst->sa_family) 667 return EINVAL; 668 669 /* validate sa_len */ 670 switch (src->sa_family) { 671 #ifdef INET 672 case AF_INET: 673 if (src->sa_len != sizeof(struct sockaddr_in)) 674 return EINVAL; 675 break; 676 #endif 677 #ifdef INET6 678 case AF_INET6: 679 if (src->sa_len != sizeof(struct sockaddr_in6)) 680 return EINVAL; 681 break; 682 #endif 683 default: 684 return EAFNOSUPPORT; 685 } 686 switch (dst->sa_family) { 687 #ifdef INET 688 case AF_INET: 689 if (dst->sa_len != sizeof(struct sockaddr_in)) 690 return EINVAL; 691 break; 692 #endif 693 #ifdef INET6 694 case AF_INET6: 695 if (dst->sa_len != sizeof(struct sockaddr_in6)) 696 return EINVAL; 697 break; 698 #endif 699 default: 700 return EAFNOSUPPORT; 701 } 702 703 /* check sa_family looks sane for the cmd */ 704 switch (cmd) { 705 case SIOCSIFPHYADDR: 706 if (src->sa_family == AF_INET) 707 break; 708 return EAFNOSUPPORT; 709 #ifdef INET6 710 case SIOCSIFPHYADDR_IN6: 711 if (src->sa_family == AF_INET6) 712 break; 713 return EAFNOSUPPORT; 714 #endif /* INET6 */ 715 case SIOCSLIFPHYADDR: 716 /* checks done in the above */ 717 break; 718 } 719 720 error = gif_set_tunnel(GIF2IFP(sc), src, dst); 721 break; 722 723 #ifdef SIOCDIFPHYADDR 724 case SIOCDIFPHYADDR: 725 gif_delete_tunnel(GIF2IFP(sc)); 726 break; 727 #endif 728 729 case SIOCGIFPSRCADDR: 730 #ifdef INET6 731 case SIOCGIFPSRCADDR_IN6: 732 #endif /* INET6 */ 733 if (sc->gif_psrc == NULL) { 734 error = EADDRNOTAVAIL; 735 goto bad; 736 } 737 src = sc->gif_psrc; 738 switch (cmd) { 739 #ifdef INET 740 case SIOCGIFPSRCADDR: 741 dst = &ifr->ifr_addr; 742 size = sizeof(ifr->ifr_addr); 743 break; 744 #endif /* INET */ 745 #ifdef INET6 746 case SIOCGIFPSRCADDR_IN6: 747 dst = (struct sockaddr *) 748 &(((struct in6_ifreq *)data)->ifr_addr); 749 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 750 break; 751 #endif /* INET6 */ 752 default: 753 error = EADDRNOTAVAIL; 754 goto bad; 755 } 756 if (src->sa_len > size) 757 return EINVAL; 758 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 759 #ifdef INET6 760 if (dst->sa_family == AF_INET6) { 761 error = sa6_recoverscope((struct sockaddr_in6 *)dst); 762 if (error != 0) 763 return (error); 764 } 765 #endif 766 break; 767 768 case SIOCGIFPDSTADDR: 769 #ifdef INET6 770 case SIOCGIFPDSTADDR_IN6: 771 #endif /* INET6 */ 772 if (sc->gif_pdst == NULL) { 773 error = EADDRNOTAVAIL; 774 goto bad; 775 } 776 src = sc->gif_pdst; 777 switch (cmd) { 778 #ifdef INET 779 case SIOCGIFPDSTADDR: 780 dst = &ifr->ifr_addr; 781 size = sizeof(ifr->ifr_addr); 782 break; 783 #endif /* INET */ 784 #ifdef INET6 785 case SIOCGIFPDSTADDR_IN6: 786 dst = (struct sockaddr *) 787 &(((struct in6_ifreq *)data)->ifr_addr); 788 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 789 break; 790 #endif /* INET6 */ 791 default: 792 error = EADDRNOTAVAIL; 793 goto bad; 794 } 795 if (src->sa_len > size) 796 return EINVAL; 797 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 798 #ifdef INET6 799 if (dst->sa_family == AF_INET6) { 800 error = sa6_recoverscope((struct sockaddr_in6 *)dst); 801 if (error != 0) 802 return (error); 803 } 804 #endif 805 break; 806 807 case SIOCGLIFPHYADDR: 808 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 809 error = EADDRNOTAVAIL; 810 goto bad; 811 } 812 813 /* copy src */ 814 src = sc->gif_psrc; 815 dst = (struct sockaddr *) 816 &(((struct if_laddrreq *)data)->addr); 817 size = sizeof(((struct if_laddrreq *)data)->addr); 818 if (src->sa_len > size) 819 return EINVAL; 820 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 821 822 /* copy dst */ 823 src = sc->gif_pdst; 824 dst = (struct sockaddr *) 825 &(((struct if_laddrreq *)data)->dstaddr); 826 size = sizeof(((struct if_laddrreq *)data)->dstaddr); 827 if (src->sa_len > size) 828 return EINVAL; 829 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 830 break; 831 832 case SIOCSIFFLAGS: 833 /* if_ioctl() takes care of it */ 834 break; 835 836 default: 837 error = EINVAL; 838 break; 839 } 840 bad: 841 return error; 842 } 843 844 /* 845 * XXXRW: There's a general event-ordering issue here: the code to check 846 * if a given tunnel is already present happens before we perform a 847 * potentially blocking setup of the tunnel. This code needs to be 848 * re-ordered so that the check and replacement can be atomic using 849 * a mutex. 850 */ 851 int 852 gif_set_tunnel(ifp, src, dst) 853 struct ifnet *ifp; 854 struct sockaddr *src; 855 struct sockaddr *dst; 856 { 857 struct gif_softc *sc = ifp->if_softc; 858 struct gif_softc *sc2; 859 struct sockaddr *osrc, *odst, *sa; 860 int error = 0; 861 862 mtx_lock(&gif_mtx); 863 LIST_FOREACH(sc2, &V_gif_softc_list, gif_list) { 864 if (sc2 == sc) 865 continue; 866 if (!sc2->gif_pdst || !sc2->gif_psrc) 867 continue; 868 if (sc2->gif_pdst->sa_family != dst->sa_family || 869 sc2->gif_pdst->sa_len != dst->sa_len || 870 sc2->gif_psrc->sa_family != src->sa_family || 871 sc2->gif_psrc->sa_len != src->sa_len) 872 continue; 873 874 /* 875 * Disallow parallel tunnels unless instructed 876 * otherwise. 877 */ 878 if (!V_parallel_tunnels && 879 bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && 880 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { 881 error = EADDRNOTAVAIL; 882 mtx_unlock(&gif_mtx); 883 goto bad; 884 } 885 886 /* XXX both end must be valid? (I mean, not 0.0.0.0) */ 887 } 888 mtx_unlock(&gif_mtx); 889 890 /* XXX we can detach from both, but be polite just in case */ 891 if (sc->gif_psrc) 892 switch (sc->gif_psrc->sa_family) { 893 #ifdef INET 894 case AF_INET: 895 (void)in_gif_detach(sc); 896 break; 897 #endif 898 #ifdef INET6 899 case AF_INET6: 900 (void)in6_gif_detach(sc); 901 break; 902 #endif 903 } 904 905 osrc = sc->gif_psrc; 906 sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK); 907 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len); 908 sc->gif_psrc = sa; 909 910 odst = sc->gif_pdst; 911 sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK); 912 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len); 913 sc->gif_pdst = sa; 914 915 switch (sc->gif_psrc->sa_family) { 916 #ifdef INET 917 case AF_INET: 918 error = in_gif_attach(sc); 919 break; 920 #endif 921 #ifdef INET6 922 case AF_INET6: 923 /* 924 * Check validity of the scope zone ID of the addresses, and 925 * convert it into the kernel internal form if necessary. 926 */ 927 error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_psrc, 0); 928 if (error != 0) 929 break; 930 error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_pdst, 0); 931 if (error != 0) 932 break; 933 error = in6_gif_attach(sc); 934 break; 935 #endif 936 } 937 if (error) { 938 /* rollback */ 939 free((caddr_t)sc->gif_psrc, M_IFADDR); 940 free((caddr_t)sc->gif_pdst, M_IFADDR); 941 sc->gif_psrc = osrc; 942 sc->gif_pdst = odst; 943 goto bad; 944 } 945 946 if (osrc) 947 free((caddr_t)osrc, M_IFADDR); 948 if (odst) 949 free((caddr_t)odst, M_IFADDR); 950 951 bad: 952 if (sc->gif_psrc && sc->gif_pdst) 953 ifp->if_drv_flags |= IFF_DRV_RUNNING; 954 else 955 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 956 957 return error; 958 } 959 960 void 961 gif_delete_tunnel(ifp) 962 struct ifnet *ifp; 963 { 964 struct gif_softc *sc = ifp->if_softc; 965 966 if (sc->gif_psrc) { 967 free((caddr_t)sc->gif_psrc, M_IFADDR); 968 sc->gif_psrc = NULL; 969 } 970 if (sc->gif_pdst) { 971 free((caddr_t)sc->gif_pdst, M_IFADDR); 972 sc->gif_pdst = NULL; 973 } 974 /* it is safe to detach from both */ 975 #ifdef INET 976 (void)in_gif_detach(sc); 977 #endif 978 #ifdef INET6 979 (void)in6_gif_detach(sc); 980 #endif 981 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 982 } 983