1 /* 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: src/sys/net/if_gif.c,v 1.4.2.15 2002/11/08 16:57:13 ume Exp $ 30 * $KAME: if_gif.c,v 1.87 2001/10/19 08:50:27 itojun Exp $ 31 */ 32 33 #include "opt_inet.h" 34 #include "opt_inet6.h" 35 #include "opt_xbonehack.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/bus.h> 41 #include <sys/malloc.h> 42 #include <sys/mbuf.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/protosw.h> 50 #include <sys/conf.h> 51 #include <sys/thread2.h> 52 53 #include <machine/cpu.h> 54 55 #include <net/if.h> 56 #include <net/if_types.h> 57 #include <net/ifq_var.h> 58 #include <net/netisr2.h> 59 #include <net/route.h> 60 #include <net/bpf.h> 61 #include <net/if_clone.h> 62 63 #include <netinet/in.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/ip.h> 66 #ifdef INET 67 #include <netinet/in_var.h> 68 #include <netinet/in_gif.h> 69 #include <netinet/ip_var.h> 70 #endif /* INET */ 71 72 #ifdef INET6 73 #ifndef INET 74 #include <netinet/in.h> 75 #endif 76 #include <netinet6/in6_var.h> 77 #include <netinet/ip6.h> 78 #include <netinet6/ip6_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 "if_gif.h" 85 86 #include <net/net_osdep.h> 87 88 #define GIFNAME "gif" 89 90 #define MTAG_GIF 1709048582 /* mtag cookie for nesting check */ 91 92 static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); 93 LIST_HEAD(, gif_softc) gif_softc_list; 94 95 int gif_clone_create(struct if_clone *, int, caddr_t, caddr_t); 96 int gif_clone_destroy(struct ifnet *); 97 98 struct if_clone gif_cloner = IF_CLONE_INITIALIZER("gif", gif_clone_create, 99 gif_clone_destroy, 0, IF_MAXUNIT); 100 101 static int gifmodevent(module_t, int, void *); 102 static void gif_clear_cache(struct gif_softc *sc); 103 104 SYSCTL_DECL(_net_link); 105 SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0, 106 "Generic Tunnel Interface"); 107 108 #ifndef MAX_GIF_NEST 109 /* 110 * This macro controls the default upper limitation on nesting of gif tunnels. 111 * Since, setting a large value to this macro with a careless configuration 112 * may introduce system crash, we don't allow any nestings by default. 113 * If you need to configure nested gif tunnels, you can define this macro 114 * in your kernel configuration file. However, if you do so, please be 115 * careful to configure the tunnels so that it won't make a loop. 116 */ 117 #define MAX_GIF_NEST 1 118 #endif 119 static int max_gif_nesting = MAX_GIF_NEST; 120 SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, 121 &max_gif_nesting, 0, "Max nested tunnels"); 122 123 /* 124 * By default, we disallow creation of multiple tunnels between the same 125 * pair of addresses. Some applications require this functionality so 126 * we allow control over this check here. 127 */ 128 #ifdef XBONEHACK 129 static int parallel_tunnels = 1; 130 #else 131 static int parallel_tunnels = 0; 132 #endif 133 SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, 134 ¶llel_tunnels, 0, "Allow parallel tunnels?"); 135 136 137 int 138 gif_clone_create(struct if_clone *ifc, int unit, 139 caddr_t params __unused, caddr_t data __unused) 140 { 141 struct gif_softc *sc; 142 143 sc = kmalloc (sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO); 144 145 sc->gif_if.if_softc = sc; 146 if_initname(&(sc->gif_if), GIFNAME, unit); 147 148 gifattach0(sc); 149 150 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list); 151 return (0); 152 } 153 154 void 155 gifattach0(struct gif_softc *sc) 156 { 157 158 sc->encap_cookie4 = sc->encap_cookie6 = NULL; 159 160 sc->gif_if.if_addrlen = 0; 161 sc->gif_if.if_mtu = GIF_MTU; 162 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 163 #if 0 164 /* turn off ingress filter */ 165 sc->gif_if.if_flags |= IFF_LINK2; 166 #endif 167 sc->gif_if.if_ioctl = gif_ioctl; 168 sc->gif_if.if_output = gif_output; 169 sc->gif_if.if_type = IFT_GIF; 170 ifq_set_maxlen(&sc->gif_if.if_snd, IFQ_MAXLEN); 171 if_attach(&sc->gif_if, NULL); 172 bpfattach(&sc->gif_if, DLT_NULL, sizeof(uint32_t)); 173 } 174 175 int 176 gif_clone_destroy(struct ifnet *ifp) 177 { 178 struct gif_softc *sc = ifp->if_softc; 179 int err; 180 181 gif_delete_tunnel(&sc->gif_if); 182 LIST_REMOVE(sc, gif_list); 183 #ifdef INET6 184 if (sc->encap_cookie6 != NULL) { 185 err = encap_detach(sc->encap_cookie6); 186 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6")); 187 } 188 #endif 189 #ifdef INET 190 if (sc->encap_cookie4 != NULL) { 191 err = encap_detach(sc->encap_cookie4); 192 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4")); 193 } 194 #endif 195 gif_clear_cache(sc); 196 197 bpfdetach(ifp); 198 if_detach(ifp); 199 200 kfree(sc, M_GIF); 201 202 return 0; 203 } 204 205 static void 206 gif_clear_cache(struct gif_softc *sc) 207 { 208 struct rtentry *rt; 209 int n; 210 211 for (n = 0; n < netisr_ncpus; ++n) { 212 rt = sc->gif_ro[n].ro_rt; 213 if (rt != NULL) { 214 KASSERT(rt->rt_cpuid == n, 215 ("inet rt for cpu%d installed on cpu%d slot", 216 rt->rt_cpuid, n)); 217 rtfree_async(rt); 218 sc->gif_ro[n].ro_rt = NULL; 219 } 220 #ifdef INET6 221 rt = sc->gif_ro6[n].ro_rt; 222 if (rt != NULL) { 223 KASSERT(rt->rt_cpuid == n, 224 ("inet6 rt for cpu%d installed on cpu%d slot", 225 rt->rt_cpuid, n)); 226 rtfree_async(rt); 227 sc->gif_ro6[n].ro_rt = NULL; 228 } 229 #endif 230 } 231 } 232 233 static int 234 gifmodevent(module_t mod, int type, void *data) 235 { 236 237 switch (type) { 238 case MOD_LOAD: 239 LIST_INIT(&gif_softc_list); 240 if_clone_attach(&gif_cloner); 241 242 #ifdef INET6 243 ip6_gif_hlim = GIF_HLIM; 244 #endif 245 246 break; 247 case MOD_UNLOAD: 248 if_clone_detach(&gif_cloner); 249 250 while (!LIST_EMPTY(&gif_softc_list)) 251 gif_clone_destroy(&LIST_FIRST(&gif_softc_list)->gif_if); 252 253 #ifdef INET6 254 ip6_gif_hlim = 0; 255 #endif 256 break; 257 } 258 return 0; 259 } 260 261 static moduledata_t gif_mod = { 262 "if_gif", 263 gifmodevent, 264 0 265 }; 266 267 DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 268 269 int 270 gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg) 271 { 272 struct ip ip; 273 struct gif_softc *sc; 274 275 sc = (struct gif_softc *)arg; 276 if (sc == NULL) 277 return 0; 278 279 if ((sc->gif_if.if_flags & IFF_UP) == 0) 280 return 0; 281 282 /* no physical address */ 283 if (!sc->gif_psrc || !sc->gif_pdst) 284 return 0; 285 286 switch (proto) { 287 #ifdef INET 288 case IPPROTO_IPV4: 289 break; 290 #endif 291 #ifdef INET6 292 case IPPROTO_IPV6: 293 break; 294 #endif 295 default: 296 return 0; 297 } 298 299 /* Bail on short packets */ 300 if (m->m_pkthdr.len < sizeof(ip)) 301 return 0; 302 303 m_copydata(m, 0, sizeof(ip), &ip); 304 305 switch (ip.ip_v) { 306 #ifdef INET 307 case 4: 308 if (sc->gif_psrc->sa_family != AF_INET || 309 sc->gif_pdst->sa_family != AF_INET) 310 return 0; 311 return gif_encapcheck4(m, off, proto, arg); 312 #endif 313 #ifdef INET6 314 case 6: 315 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) 316 return 0; 317 if (sc->gif_psrc->sa_family != AF_INET6 || 318 sc->gif_pdst->sa_family != AF_INET6) 319 return 0; 320 return gif_encapcheck6(m, off, proto, arg); 321 #endif 322 default: 323 return 0; 324 } 325 } 326 327 /* 328 * Parameters: 329 * rt: added in net2 330 */ 331 static int 332 gif_output_serialized(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 333 struct rtentry *rt) 334 { 335 struct gif_softc *sc = (struct gif_softc *)ifp; 336 int error = 0; 337 338 error = if_tunnel_check_nesting(ifp, m, MTAG_GIF, max_gif_nesting); 339 if (error != 0) { 340 m_freem(m); 341 goto end; 342 } 343 344 m->m_flags &= ~(M_BCAST|M_MCAST); 345 if (!(ifp->if_flags & IFF_UP) || 346 sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 347 m_freem(m); 348 error = ENETDOWN; 349 goto end; 350 } 351 352 if (ifp->if_bpf) { 353 bpf_gettoken(); 354 if (ifp->if_bpf) { 355 /* 356 * We need to prepend the address family as 357 * a four byte field. 358 */ 359 uint32_t af = dst->sa_family; 360 361 bpf_ptap(ifp->if_bpf, m, &af, sizeof(af)); 362 } 363 bpf_reltoken(); 364 } 365 IFNET_STAT_INC(ifp, opackets, 1); 366 IFNET_STAT_INC(ifp, obytes, m->m_pkthdr.len); 367 368 /* inner AF-specific encapsulation */ 369 370 /* XXX should we check if our outer source is legal? */ 371 372 /* dispatch to output logic based on outer AF */ 373 switch (sc->gif_psrc->sa_family) { 374 #ifdef INET 375 case AF_INET: 376 error = in_gif_output(ifp, dst->sa_family, m); 377 break; 378 #endif 379 #ifdef INET6 380 case AF_INET6: 381 error = in6_gif_output(ifp, dst->sa_family, m); 382 break; 383 #endif 384 default: 385 m_freem(m); 386 error = ENETDOWN; 387 goto end; 388 } 389 390 end: 391 if (error) 392 IFNET_STAT_INC(ifp, oerrors, 1); 393 return error; 394 } 395 396 int 397 gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 398 struct rtentry *rt) 399 { 400 struct ifaltq_subque *ifsq = ifq_get_subq_default(&ifp->if_snd); 401 int error; 402 403 ASSERT_NETISR_NCPUS(mycpuid); 404 405 ifsq_serialize_hw(ifsq); 406 error = gif_output_serialized(ifp, m, dst, rt); 407 ifsq_deserialize_hw(ifsq); 408 return error; 409 } 410 411 void 412 gif_input(struct mbuf *m, int af, struct ifnet *ifp) 413 { 414 int isr; 415 416 if (ifp == NULL) { 417 /* just in case */ 418 m_freem(m); 419 return; 420 } 421 422 m->m_pkthdr.rcvif = ifp; 423 424 if (ifp->if_bpf) { 425 bpf_gettoken(); 426 if (ifp->if_bpf) { 427 /* 428 * We need to prepend the address family as 429 * a four byte field. 430 */ 431 uint32_t af1 = af; 432 433 bpf_ptap(ifp->if_bpf, m, &af1, sizeof(af1)); 434 } 435 bpf_reltoken(); 436 } 437 438 /* 439 * Put the packet to the network layer input queue according to the 440 * specified address family. 441 * Note: older versions of gif_input directly called network layer 442 * input functions, e.g. ip6_input, here. We changed the policy to 443 * prevent too many recursive calls of such input functions, which 444 * might cause kernel panic. But the change may introduce another 445 * problem; if the input queue is full, packets are discarded. 446 * The kernel stack overflow really happened, and we believed 447 * queue-full rarely occurs, so we changed the policy. 448 */ 449 switch (af) { 450 #ifdef INET 451 case AF_INET: 452 isr = NETISR_IP; 453 break; 454 #endif 455 #ifdef INET6 456 case AF_INET6: 457 isr = NETISR_IPV6; 458 break; 459 #endif 460 default: 461 m_freem(m); 462 return; 463 } 464 465 IFNET_STAT_INC(ifp, ipackets, 1); 466 IFNET_STAT_INC(ifp, ibytes, m->m_pkthdr.len); 467 m->m_flags &= ~M_HASH; 468 netisr_queue(isr, m); 469 470 return; 471 } 472 473 /* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ 474 int 475 gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 476 { 477 struct gif_softc *sc = (struct gif_softc*)ifp; 478 struct ifreq *ifr = (struct ifreq*)data; 479 int error = 0, size; 480 struct sockaddr *dst, *src; 481 #ifdef SIOCSIFMTU /* xxx */ 482 u_long mtu; 483 #endif 484 485 switch (cmd) { 486 case SIOCSIFADDR: 487 ifp->if_flags |= IFF_UP; 488 break; 489 490 case SIOCSIFDSTADDR: 491 break; 492 493 case SIOCADDMULTI: 494 case SIOCDELMULTI: 495 break; 496 497 #ifdef SIOCSIFMTU /* xxx */ 498 case SIOCGIFMTU: 499 break; 500 501 case SIOCSIFMTU: 502 mtu = ifr->ifr_mtu; 503 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) 504 return (EINVAL); 505 ifp->if_mtu = mtu; 506 break; 507 #endif /* SIOCSIFMTU */ 508 509 #ifdef INET 510 case SIOCSIFPHYADDR: 511 #endif 512 #ifdef INET6 513 case SIOCSIFPHYADDR_IN6: 514 #endif /* INET6 */ 515 case SIOCSLIFPHYADDR: 516 switch (cmd) { 517 #ifdef INET 518 case SIOCSIFPHYADDR: 519 src = (struct sockaddr *) 520 &(((struct in_aliasreq *)data)->ifra_addr); 521 dst = (struct sockaddr *) 522 &(((struct in_aliasreq *)data)->ifra_dstaddr); 523 break; 524 #endif 525 #ifdef INET6 526 case SIOCSIFPHYADDR_IN6: 527 src = (struct sockaddr *) 528 &(((struct in6_aliasreq *)data)->ifra_addr); 529 dst = (struct sockaddr *) 530 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 531 break; 532 #endif 533 case SIOCSLIFPHYADDR: 534 src = (struct sockaddr *) 535 &(((struct if_laddrreq *)data)->addr); 536 dst = (struct sockaddr *) 537 &(((struct if_laddrreq *)data)->dstaddr); 538 break; 539 default: 540 return EINVAL; 541 } 542 543 /* sa_family must be equal */ 544 if (src->sa_family != dst->sa_family) 545 return EINVAL; 546 547 /* validate sa_len */ 548 switch (src->sa_family) { 549 #ifdef INET 550 case AF_INET: 551 if (src->sa_len != sizeof(struct sockaddr_in)) 552 return EINVAL; 553 break; 554 #endif 555 #ifdef INET6 556 case AF_INET6: 557 if (src->sa_len != sizeof(struct sockaddr_in6)) 558 return EINVAL; 559 break; 560 #endif 561 default: 562 return EAFNOSUPPORT; 563 } 564 switch (dst->sa_family) { 565 #ifdef INET 566 case AF_INET: 567 if (dst->sa_len != sizeof(struct sockaddr_in)) 568 return EINVAL; 569 break; 570 #endif 571 #ifdef INET6 572 case AF_INET6: 573 if (dst->sa_len != sizeof(struct sockaddr_in6)) 574 return EINVAL; 575 break; 576 #endif 577 default: 578 return EAFNOSUPPORT; 579 } 580 581 /* check sa_family looks sane for the cmd */ 582 switch (cmd) { 583 case SIOCSIFPHYADDR: 584 if (src->sa_family == AF_INET) 585 break; 586 return EAFNOSUPPORT; 587 #ifdef INET6 588 case SIOCSIFPHYADDR_IN6: 589 if (src->sa_family == AF_INET6) 590 break; 591 return EAFNOSUPPORT; 592 #endif /* INET6 */ 593 case SIOCSLIFPHYADDR: 594 /* checks done in the above */ 595 break; 596 } 597 598 error = gif_set_tunnel(&sc->gif_if, src, dst); 599 break; 600 601 #ifdef SIOCDIFPHYADDR 602 case SIOCDIFPHYADDR: 603 gif_delete_tunnel(&sc->gif_if); 604 break; 605 #endif 606 607 case SIOCGIFPSRCADDR: 608 #ifdef INET6 609 case SIOCGIFPSRCADDR_IN6: 610 #endif /* INET6 */ 611 if (sc->gif_psrc == NULL) { 612 error = EADDRNOTAVAIL; 613 goto bad; 614 } 615 src = sc->gif_psrc; 616 switch (cmd) { 617 #ifdef INET 618 case SIOCGIFPSRCADDR: 619 dst = &ifr->ifr_addr; 620 size = sizeof(ifr->ifr_addr); 621 break; 622 #endif /* INET */ 623 #ifdef INET6 624 case SIOCGIFPSRCADDR_IN6: 625 dst = (struct sockaddr *) 626 &(((struct in6_ifreq *)data)->ifr_addr); 627 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 628 break; 629 #endif /* INET6 */ 630 default: 631 error = EADDRNOTAVAIL; 632 goto bad; 633 } 634 if (src->sa_len > size) 635 return EINVAL; 636 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 637 break; 638 639 case SIOCGIFPDSTADDR: 640 #ifdef INET6 641 case SIOCGIFPDSTADDR_IN6: 642 #endif /* INET6 */ 643 if (sc->gif_pdst == NULL) { 644 error = EADDRNOTAVAIL; 645 goto bad; 646 } 647 src = sc->gif_pdst; 648 switch (cmd) { 649 #ifdef INET 650 case SIOCGIFPDSTADDR: 651 dst = &ifr->ifr_addr; 652 size = sizeof(ifr->ifr_addr); 653 break; 654 #endif /* INET */ 655 #ifdef INET6 656 case SIOCGIFPDSTADDR_IN6: 657 dst = (struct sockaddr *) 658 &(((struct in6_ifreq *)data)->ifr_addr); 659 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 660 break; 661 #endif /* INET6 */ 662 default: 663 error = EADDRNOTAVAIL; 664 goto bad; 665 } 666 if (src->sa_len > size) 667 return EINVAL; 668 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 669 break; 670 671 case SIOCGLIFPHYADDR: 672 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 673 error = EADDRNOTAVAIL; 674 goto bad; 675 } 676 677 /* copy src */ 678 src = sc->gif_psrc; 679 dst = (struct sockaddr *) 680 &(((struct if_laddrreq *)data)->addr); 681 size = sizeof(((struct if_laddrreq *)data)->addr); 682 if (src->sa_len > size) 683 return EINVAL; 684 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 685 686 /* copy dst */ 687 src = sc->gif_pdst; 688 dst = (struct sockaddr *) 689 &(((struct if_laddrreq *)data)->dstaddr); 690 size = sizeof(((struct if_laddrreq *)data)->dstaddr); 691 if (src->sa_len > size) 692 return EINVAL; 693 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 694 break; 695 696 case SIOCSIFFLAGS: 697 /* if_ioctl() takes care of it */ 698 break; 699 700 default: 701 error = EINVAL; 702 break; 703 } 704 bad: 705 return error; 706 } 707 708 int 709 gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) 710 { 711 struct gif_softc *sc = (struct gif_softc *)ifp; 712 struct gif_softc *sc2; 713 struct sockaddr *osrc, *odst, *sa; 714 int error = 0; 715 716 crit_enter(); 717 718 LIST_FOREACH(sc2, &gif_softc_list, gif_list) { 719 if (sc2 == sc) 720 continue; 721 if (!sc2->gif_pdst || !sc2->gif_psrc) 722 continue; 723 if (sc2->gif_pdst->sa_family != dst->sa_family || 724 sc2->gif_pdst->sa_len != dst->sa_len || 725 sc2->gif_psrc->sa_family != src->sa_family || 726 sc2->gif_psrc->sa_len != src->sa_len) 727 continue; 728 729 /* 730 * Disallow parallel tunnels unless instructed 731 * otherwise. 732 */ 733 if (!parallel_tunnels && 734 bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && 735 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { 736 error = EADDRNOTAVAIL; 737 goto bad; 738 } 739 740 /* XXX both end must be valid? (I mean, not 0.0.0.0) */ 741 } 742 743 /* XXX we can detach from both, but be polite just in case */ 744 if (sc->gif_psrc) { 745 switch (sc->gif_psrc->sa_family) { 746 #ifdef INET 747 case AF_INET: 748 in_gif_detach(sc); 749 break; 750 #endif 751 #ifdef INET6 752 case AF_INET6: 753 in6_gif_detach(sc); 754 break; 755 #endif 756 } 757 gif_clear_cache(sc); 758 } 759 760 osrc = sc->gif_psrc; 761 sa = (struct sockaddr *)kmalloc(src->sa_len, M_IFADDR, M_WAITOK); 762 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len); 763 sc->gif_psrc = sa; 764 765 odst = sc->gif_pdst; 766 sa = (struct sockaddr *)kmalloc(dst->sa_len, M_IFADDR, M_WAITOK); 767 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len); 768 sc->gif_pdst = sa; 769 770 switch (sc->gif_psrc->sa_family) { 771 #ifdef INET 772 case AF_INET: 773 error = in_gif_attach(sc); 774 break; 775 #endif 776 #ifdef INET6 777 case AF_INET6: 778 error = in6_gif_attach(sc); 779 break; 780 #endif 781 } 782 if (error) { 783 /* rollback */ 784 kfree((caddr_t)sc->gif_psrc, M_IFADDR); 785 kfree((caddr_t)sc->gif_pdst, M_IFADDR); 786 sc->gif_psrc = osrc; 787 sc->gif_pdst = odst; 788 goto bad; 789 } 790 791 if (osrc) 792 kfree((caddr_t)osrc, M_IFADDR); 793 if (odst) 794 kfree((caddr_t)odst, M_IFADDR); 795 796 if (sc->gif_psrc && sc->gif_pdst) 797 ifp->if_flags |= IFF_RUNNING; 798 else 799 ifp->if_flags &= ~IFF_RUNNING; 800 crit_exit(); 801 802 return 0; 803 804 bad: 805 if (sc->gif_psrc && sc->gif_pdst) 806 ifp->if_flags |= IFF_RUNNING; 807 else 808 ifp->if_flags &= ~IFF_RUNNING; 809 crit_exit(); 810 811 return error; 812 } 813 814 void 815 gif_delete_tunnel(struct ifnet *ifp) 816 { 817 struct gif_softc *sc = (struct gif_softc *)ifp; 818 819 crit_enter(); 820 821 if (sc->gif_psrc) { 822 kfree((caddr_t)sc->gif_psrc, M_IFADDR); 823 sc->gif_psrc = NULL; 824 } 825 if (sc->gif_pdst) { 826 kfree((caddr_t)sc->gif_pdst, M_IFADDR); 827 sc->gif_pdst = NULL; 828 } 829 /* it is safe to detach from both */ 830 #ifdef INET 831 in_gif_detach(sc); 832 #endif 833 #ifdef INET6 834 in6_gif_detach(sc); 835 #endif 836 gif_clear_cache(sc); 837 838 if (sc->gif_psrc && sc->gif_pdst) 839 ifp->if_flags |= IFF_RUNNING; 840 else 841 ifp->if_flags &= ~IFF_RUNNING; 842 crit_exit(); 843 } 844