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