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