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