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