if_gif.c revision 276068
1/* $FreeBSD: stable/10/sys/net/if_gif.c 276068 2014-12-22 17:54:26Z ae $ */ 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 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/jail.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/priv.h> 50#include <sys/proc.h> 51#include <sys/protosw.h> 52#include <sys/conf.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#include <net/vnet.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/scope6_var.h> 80#include <netinet6/in6_gif.h> 81#include <netinet6/ip6protosw.h> 82#endif /* INET6 */ 83 84#include <netinet/ip_encap.h> 85#include <net/ethernet.h> 86#include <net/if_bridgevar.h> 87#include <net/if_gif.h> 88 89#include <security/mac/mac_framework.h> 90 91static const char gifname[] = "gif"; 92 93/* 94 * gif_mtx protects a per-vnet gif_softc_list. 95 */ 96static VNET_DEFINE(struct mtx, gif_mtx); 97#define V_gif_mtx VNET(gif_mtx) 98static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); 99static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list); 100#define V_gif_softc_list VNET(gif_softc_list) 101 102#define GIF_LIST_LOCK_INIT(x) mtx_init(&V_gif_mtx, "gif_mtx", \ 103 NULL, MTX_DEF) 104#define GIF_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gif_mtx) 105#define GIF_LIST_LOCK(x) mtx_lock(&V_gif_mtx) 106#define GIF_LIST_UNLOCK(x) mtx_unlock(&V_gif_mtx) 107 108void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af); 109void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af); 110void (*ng_gif_attach_p)(struct ifnet *ifp); 111void (*ng_gif_detach_p)(struct ifnet *ifp); 112 113static void gif_start(struct ifnet *); 114static int gif_clone_create(struct if_clone *, int, caddr_t); 115static void gif_clone_destroy(struct ifnet *); 116static VNET_DEFINE(struct if_clone *, gif_cloner); 117#define V_gif_cloner VNET(gif_cloner) 118 119static int gifmodevent(module_t, int, void *); 120 121SYSCTL_DECL(_net_link); 122static SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0, 123 "Generic Tunnel Interface"); 124#ifndef MAX_GIF_NEST 125/* 126 * This macro controls the default upper limitation on nesting of gif tunnels. 127 * Since, setting a large value to this macro with a careless configuration 128 * may introduce system crash, we don't allow any nestings by default. 129 * If you need to configure nested gif tunnels, you can define this macro 130 * in your kernel configuration file. However, if you do so, please be 131 * careful to configure the tunnels so that it won't make a loop. 132 */ 133#define MAX_GIF_NEST 1 134#endif 135static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST; 136#define V_max_gif_nesting VNET(max_gif_nesting) 137SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, 138 &VNET_NAME(max_gif_nesting), 0, "Max nested tunnels"); 139 140/* 141 * By default, we disallow creation of multiple tunnels between the same 142 * pair of addresses. Some applications require this functionality so 143 * we allow control over this check here. 144 */ 145#ifdef XBONEHACK 146static VNET_DEFINE(int, parallel_tunnels) = 1; 147#else 148static VNET_DEFINE(int, parallel_tunnels) = 0; 149#endif 150#define V_parallel_tunnels VNET(parallel_tunnels) 151SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, 152 &VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?"); 153 154/* copy from src/sys/net/if_ethersubr.c */ 155static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = 156 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 157#ifndef ETHER_IS_BROADCAST 158#define ETHER_IS_BROADCAST(addr) \ 159 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0) 160#endif 161 162static int 163gif_clone_create(struct if_clone *ifc, int unit, caddr_t params) 164{ 165 struct gif_softc *sc; 166 167 sc = malloc(sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO); 168 sc->gif_fibnum = curthread->td_proc->p_fibnum; 169 GIF2IFP(sc) = if_alloc(IFT_GIF); 170 if (GIF2IFP(sc) == NULL) { 171 free(sc, M_GIF); 172 return (ENOSPC); 173 } 174 175 GIF_LOCK_INIT(sc); 176 177 GIF2IFP(sc)->if_softc = sc; 178 if_initname(GIF2IFP(sc), gifname, unit); 179 180 sc->encap_cookie4 = sc->encap_cookie6 = NULL; 181 sc->gif_options = 0; 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 = ifqmaxlen; 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 GIF_LIST_LOCK(); 200 LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list); 201 GIF_LIST_UNLOCK(); 202 203 return (0); 204} 205 206static void 207gif_clone_destroy(struct ifnet *ifp) 208{ 209#if defined(INET) || defined(INET6) 210 int err; 211#endif 212 struct gif_softc *sc = ifp->if_softc; 213 214 GIF_LIST_LOCK(); 215 LIST_REMOVE(sc, gif_list); 216 GIF_LIST_UNLOCK(); 217 218 gif_delete_tunnel(ifp); 219#ifdef INET6 220 if (sc->encap_cookie6 != NULL) { 221 err = encap_detach(sc->encap_cookie6); 222 KASSERT(err == 0, ("Unexpected error detaching encap_cookie6")); 223 } 224#endif 225#ifdef INET 226 if (sc->encap_cookie4 != NULL) { 227 err = encap_detach(sc->encap_cookie4); 228 KASSERT(err == 0, ("Unexpected error detaching encap_cookie4")); 229 } 230#endif 231 232 if (ng_gif_detach_p != NULL) 233 (*ng_gif_detach_p)(ifp); 234 bpfdetach(ifp); 235 if_detach(ifp); 236 if_free(ifp); 237 238 GIF_LOCK_DESTROY(sc); 239 240 free(sc, M_GIF); 241} 242 243static void 244vnet_gif_init(const void *unused __unused) 245{ 246 247 LIST_INIT(&V_gif_softc_list); 248 GIF_LIST_LOCK_INIT(); 249 V_gif_cloner = if_clone_simple(gifname, gif_clone_create, 250 gif_clone_destroy, 0); 251} 252VNET_SYSINIT(vnet_gif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, 253 vnet_gif_init, NULL); 254 255static void 256vnet_gif_uninit(const void *unused __unused) 257{ 258 259 if_clone_detach(V_gif_cloner); 260 GIF_LIST_LOCK_DESTROY(); 261} 262VNET_SYSUNINIT(vnet_gif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, 263 vnet_gif_uninit, NULL); 264 265static int 266gifmodevent(module_t mod, int type, void *data) 267{ 268 269 switch (type) { 270 case MOD_LOAD: 271 case MOD_UNLOAD: 272 break; 273 default: 274 return (EOPNOTSUPP); 275 } 276 return (0); 277} 278 279static moduledata_t gif_mod = { 280 "if_gif", 281 gifmodevent, 282 0 283}; 284 285DECLARE_MODULE(if_gif, gif_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); 286MODULE_VERSION(if_gif, 1); 287 288int 289gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg) 290{ 291 struct ip ip; 292 struct gif_softc *sc; 293 294 sc = (struct gif_softc *)arg; 295 if (sc == NULL) 296 return 0; 297 298 if ((GIF2IFP(sc)->if_flags & IFF_UP) == 0) 299 return 0; 300 301 /* no physical address */ 302 if (!sc->gif_psrc || !sc->gif_pdst) 303 return 0; 304 305 switch (proto) { 306#ifdef INET 307 case IPPROTO_IPV4: 308 break; 309#endif 310#ifdef INET6 311 case IPPROTO_IPV6: 312 break; 313#endif 314 case IPPROTO_ETHERIP: 315 break; 316 317 default: 318 return 0; 319 } 320 321 /* Bail on short packets */ 322 if (m->m_pkthdr.len < sizeof(ip)) 323 return 0; 324 325 m_copydata(m, 0, sizeof(ip), (caddr_t)&ip); 326 327 switch (ip.ip_v) { 328#ifdef INET 329 case 4: 330 if (sc->gif_psrc->sa_family != AF_INET || 331 sc->gif_pdst->sa_family != AF_INET) 332 return 0; 333 return gif_encapcheck4(m, off, proto, arg); 334#endif 335#ifdef INET6 336 case 6: 337 if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) 338 return 0; 339 if (sc->gif_psrc->sa_family != AF_INET6 || 340 sc->gif_pdst->sa_family != AF_INET6) 341 return 0; 342 return gif_encapcheck6(m, off, proto, arg); 343#endif 344 default: 345 return 0; 346 } 347} 348#ifdef INET 349#define GIF_HDR_LEN (ETHER_HDR_LEN + sizeof (struct ip)) 350#endif 351#ifdef INET6 352#define GIF_HDR_LEN6 (ETHER_HDR_LEN + sizeof (struct ip6_hdr)) 353#endif 354 355static void 356gif_start(struct ifnet *ifp) 357{ 358 struct gif_softc *sc; 359 struct mbuf *m; 360 uint32_t af; 361 int error = 0; 362 363 sc = ifp->if_softc; 364 GIF_LOCK(sc); 365 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 366 while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 367 368 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 369 if (m == 0) 370 break; 371 372#ifdef ALTQ 373 /* Take out those altq bytes we add in gif_output */ 374#ifdef INET 375 if (sc->gif_psrc->sa_family == AF_INET) 376 m->m_pkthdr.len -= GIF_HDR_LEN; 377#endif 378#ifdef INET6 379 if (sc->gif_psrc->sa_family == AF_INET6) 380 m->m_pkthdr.len -= GIF_HDR_LEN6; 381#endif 382#endif 383 /* 384 * Now pull back the af that we 385 * stashed in the csum_data. 386 */ 387 af = m->m_pkthdr.csum_data; 388 389 /* override to IPPROTO_ETHERIP for bridged traffic */ 390 if (ifp->if_bridge) 391 af = AF_LINK; 392 393 BPF_MTAP2(ifp, &af, sizeof(af), m); 394 ifp->if_opackets++; 395 396/* Done by IFQ_HANDOFF */ 397/* ifp->if_obytes += m->m_pkthdr.len;*/ 398 399 M_SETFIB(m, sc->gif_fibnum); 400 /* inner AF-specific encapsulation */ 401 /* XXX should we check if our outer source is legal? */ 402 /* dispatch to output logic based on outer AF */ 403 switch (sc->gif_psrc->sa_family) { 404#ifdef INET 405 case AF_INET: 406 error = in_gif_output(ifp, af, m); 407 break; 408#endif 409#ifdef INET6 410 case AF_INET6: 411 error = in6_gif_output(ifp, af, m); 412 break; 413#endif 414 default: 415 m_freem(m); 416 error = ENETDOWN; 417 } 418 if (error) 419 ifp->if_oerrors++; 420 421 } 422 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 423 GIF_UNLOCK(sc); 424 return; 425} 426 427int 428gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 429 struct route *ro) 430{ 431 struct gif_softc *sc = ifp->if_softc; 432 struct m_tag *mtag; 433 int error = 0; 434 int gif_called; 435 uint32_t af; 436#ifdef MAC 437 error = mac_ifnet_check_transmit(ifp, m); 438 if (error) { 439 m_freem(m); 440 goto end; 441 } 442#endif 443 if ((ifp->if_flags & IFF_MONITOR) != 0) { 444 error = ENETDOWN; 445 m_freem(m); 446 goto end; 447 } 448 449 /* 450 * gif may cause infinite recursion calls when misconfigured. 451 * We'll prevent this by detecting loops. 452 * 453 * High nesting level may cause stack exhaustion. 454 * We'll prevent this by introducing upper limit. 455 */ 456 gif_called = 1; 457 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, NULL); 458 while (mtag != NULL) { 459 if (*(struct ifnet **)(mtag + 1) == ifp) { 460 log(LOG_NOTICE, 461 "gif_output: loop detected on %s\n", 462 (*(struct ifnet **)(mtag + 1))->if_xname); 463 m_freem(m); 464 error = EIO; /* is there better errno? */ 465 goto end; 466 } 467 mtag = m_tag_locate(m, MTAG_GIF, MTAG_GIF_CALLED, mtag); 468 gif_called++; 469 } 470 if (gif_called > V_max_gif_nesting) { 471 log(LOG_NOTICE, 472 "gif_output: recursively called too many times(%d)\n", 473 gif_called); 474 m_freem(m); 475 error = EIO; /* is there better errno? */ 476 goto end; 477 } 478 mtag = m_tag_alloc(MTAG_GIF, MTAG_GIF_CALLED, sizeof(struct ifnet *), 479 M_NOWAIT); 480 if (mtag == NULL) { 481 m_freem(m); 482 error = ENOMEM; 483 goto end; 484 } 485 *(struct ifnet **)(mtag + 1) = ifp; 486 m_tag_prepend(m, mtag); 487 488 m->m_flags &= ~(M_BCAST|M_MCAST); 489 /* BPF writes need to be handled specially. */ 490 if (dst->sa_family == AF_UNSPEC) 491 bcopy(dst->sa_data, &af, sizeof(af)); 492 else 493 af = dst->sa_family; 494 /* 495 * Now save the af in the inbound pkt csum 496 * data, this is a cheat since we are using 497 * the inbound csum_data field to carry the 498 * af over to the gif_start() routine, avoiding 499 * using yet another mtag. 500 */ 501 m->m_pkthdr.csum_data = af; 502 if (!(ifp->if_flags & IFF_UP) || 503 sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 504 m_freem(m); 505 error = ENETDOWN; 506 goto end; 507 } 508#ifdef ALTQ 509 /* 510 * Make altq aware of the bytes we will add 511 * when we actually send it. 512 */ 513#ifdef INET 514 if (sc->gif_psrc->sa_family == AF_INET) 515 m->m_pkthdr.len += GIF_HDR_LEN; 516#endif 517#ifdef INET6 518 if (sc->gif_psrc->sa_family == AF_INET6) 519 m->m_pkthdr.len += GIF_HDR_LEN6; 520#endif 521#endif 522 /* 523 * Queue message on interface, update output statistics if 524 * successful, and start output if interface not yet active. 525 */ 526 IFQ_HANDOFF(ifp, m, error); 527 end: 528 if (error) 529 ifp->if_oerrors++; 530 return (error); 531} 532 533void 534gif_input(struct mbuf *m, int af, struct ifnet *ifp) 535{ 536 int isr, n; 537 struct gif_softc *sc; 538 struct etherip_header *eip; 539 struct ether_header *eh; 540 struct ifnet *oldifp; 541 542 if (ifp == NULL) { 543 /* just in case */ 544 m_freem(m); 545 return; 546 } 547 sc = ifp->if_softc; 548 m->m_pkthdr.rcvif = ifp; 549 m_clrprotoflags(m); 550 551#ifdef MAC 552 mac_ifnet_create_mbuf(ifp, m); 553#endif 554 555 if (bpf_peers_present(ifp->if_bpf)) { 556 u_int32_t af1 = af; 557 bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); 558 } 559 560 if ((ifp->if_flags & IFF_MONITOR) != 0) { 561 ifp->if_ipackets++; 562 ifp->if_ibytes += m->m_pkthdr.len; 563 m_freem(m); 564 return; 565 } 566 567 if (ng_gif_input_p != NULL) { 568 (*ng_gif_input_p)(ifp, &m, af); 569 if (m == NULL) 570 return; 571 } 572 573 /* 574 * Put the packet to the network layer input queue according to the 575 * specified address family. 576 * Note: older versions of gif_input directly called network layer 577 * input functions, e.g. ip6_input, here. We changed the policy to 578 * prevent too many recursive calls of such input functions, which 579 * might cause kernel panic. But the change may introduce another 580 * problem; if the input queue is full, packets are discarded. 581 * The kernel stack overflow really happened, and we believed 582 * queue-full rarely occurs, so we changed the policy. 583 */ 584 switch (af) { 585#ifdef INET 586 case AF_INET: 587 isr = NETISR_IP; 588 break; 589#endif 590#ifdef INET6 591 case AF_INET6: 592 isr = NETISR_IPV6; 593 break; 594#endif 595 case AF_LINK: 596 n = sizeof(struct etherip_header) + sizeof(struct ether_header); 597 if (n > m->m_len) { 598 m = m_pullup(m, n); 599 if (m == NULL) { 600 ifp->if_ierrors++; 601 return; 602 } 603 } 604 605 eip = mtod(m, struct etherip_header *); 606 /* 607 * GIF_ACCEPT_REVETHIP (enabled by default) intentionally 608 * accepts an EtherIP packet with revered version field in 609 * the header. This is a knob for backward compatibility 610 * with FreeBSD 7.2R or prior. 611 */ 612 if (sc->gif_options & GIF_ACCEPT_REVETHIP) { 613 if (eip->eip_resvl != ETHERIP_VERSION 614 && eip->eip_ver != ETHERIP_VERSION) { 615 /* discard unknown versions */ 616 m_freem(m); 617 return; 618 } 619 } else { 620 if (eip->eip_ver != ETHERIP_VERSION) { 621 /* discard unknown versions */ 622 m_freem(m); 623 return; 624 } 625 } 626 m_adj(m, sizeof(struct etherip_header)); 627 628 m->m_flags &= ~(M_BCAST|M_MCAST); 629 m->m_pkthdr.rcvif = ifp; 630 631 if (ifp->if_bridge) { 632 oldifp = ifp; 633 eh = mtod(m, struct ether_header *); 634 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 635 if (ETHER_IS_BROADCAST(eh->ether_dhost)) 636 m->m_flags |= M_BCAST; 637 else 638 m->m_flags |= M_MCAST; 639 ifp->if_imcasts++; 640 } 641 BRIDGE_INPUT(ifp, m); 642 643 if (m != NULL && ifp != oldifp) { 644 /* 645 * The bridge gave us back itself or one of the 646 * members for which the frame is addressed. 647 */ 648 ether_demux(ifp, m); 649 return; 650 } 651 } 652 if (m != NULL) 653 m_freem(m); 654 return; 655 656 default: 657 if (ng_gif_input_orphan_p != NULL) 658 (*ng_gif_input_orphan_p)(ifp, m, af); 659 else 660 m_freem(m); 661 return; 662 } 663 664 ifp->if_ipackets++; 665 ifp->if_ibytes += m->m_pkthdr.len; 666 M_SETFIB(m, ifp->if_fib); 667 netisr_dispatch(isr, m); 668} 669 670/* XXX how should we handle IPv6 scope on SIOC[GS]IFPHYADDR? */ 671int 672gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 673{ 674 struct gif_softc *sc = ifp->if_softc; 675 struct ifreq *ifr = (struct ifreq*)data; 676 int error = 0, size; 677 u_int options; 678 struct sockaddr *dst, *src; 679#ifdef SIOCSIFMTU /* xxx */ 680 u_long mtu; 681#endif 682 683 switch (cmd) { 684 case SIOCSIFADDR: 685 ifp->if_flags |= IFF_UP; 686 break; 687 688 case SIOCADDMULTI: 689 case SIOCDELMULTI: 690 break; 691 692#ifdef SIOCSIFMTU /* xxx */ 693 case SIOCGIFMTU: 694 break; 695 696 case SIOCSIFMTU: 697 mtu = ifr->ifr_mtu; 698 if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) 699 return (EINVAL); 700 ifp->if_mtu = mtu; 701 break; 702#endif /* SIOCSIFMTU */ 703 704#ifdef INET 705 case SIOCSIFPHYADDR: 706#endif 707#ifdef INET6 708 case SIOCSIFPHYADDR_IN6: 709#endif /* INET6 */ 710 case SIOCSLIFPHYADDR: 711 switch (cmd) { 712#ifdef INET 713 case SIOCSIFPHYADDR: 714 src = (struct sockaddr *) 715 &(((struct in_aliasreq *)data)->ifra_addr); 716 dst = (struct sockaddr *) 717 &(((struct in_aliasreq *)data)->ifra_dstaddr); 718 break; 719#endif 720#ifdef INET6 721 case SIOCSIFPHYADDR_IN6: 722 src = (struct sockaddr *) 723 &(((struct in6_aliasreq *)data)->ifra_addr); 724 dst = (struct sockaddr *) 725 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 726 break; 727#endif 728 case SIOCSLIFPHYADDR: 729 src = (struct sockaddr *) 730 &(((struct if_laddrreq *)data)->addr); 731 dst = (struct sockaddr *) 732 &(((struct if_laddrreq *)data)->dstaddr); 733 break; 734 default: 735 return EINVAL; 736 } 737 738 /* sa_family must be equal */ 739 if (src->sa_family != dst->sa_family) 740 return EINVAL; 741 742 /* validate sa_len */ 743 switch (src->sa_family) { 744#ifdef INET 745 case AF_INET: 746 if (src->sa_len != sizeof(struct sockaddr_in)) 747 return EINVAL; 748 break; 749#endif 750#ifdef INET6 751 case AF_INET6: 752 if (src->sa_len != sizeof(struct sockaddr_in6)) 753 return EINVAL; 754 break; 755#endif 756 default: 757 return EAFNOSUPPORT; 758 } 759 switch (dst->sa_family) { 760#ifdef INET 761 case AF_INET: 762 if (dst->sa_len != sizeof(struct sockaddr_in)) 763 return EINVAL; 764 break; 765#endif 766#ifdef INET6 767 case AF_INET6: 768 if (dst->sa_len != sizeof(struct sockaddr_in6)) 769 return EINVAL; 770 break; 771#endif 772 default: 773 return EAFNOSUPPORT; 774 } 775 776 /* check sa_family looks sane for the cmd */ 777 switch (cmd) { 778 case SIOCSIFPHYADDR: 779 if (src->sa_family == AF_INET) 780 break; 781 return EAFNOSUPPORT; 782#ifdef INET6 783 case SIOCSIFPHYADDR_IN6: 784 if (src->sa_family == AF_INET6) 785 break; 786 return EAFNOSUPPORT; 787#endif /* INET6 */ 788 case SIOCSLIFPHYADDR: 789 /* checks done in the above */ 790 break; 791 } 792 793 error = gif_set_tunnel(GIF2IFP(sc), src, dst); 794 break; 795 796#ifdef SIOCDIFPHYADDR 797 case SIOCDIFPHYADDR: 798 gif_delete_tunnel(GIF2IFP(sc)); 799 break; 800#endif 801 802 case SIOCGIFPSRCADDR: 803#ifdef INET6 804 case SIOCGIFPSRCADDR_IN6: 805#endif /* INET6 */ 806 if (sc->gif_psrc == NULL) { 807 error = EADDRNOTAVAIL; 808 goto bad; 809 } 810 src = sc->gif_psrc; 811 switch (cmd) { 812#ifdef INET 813 case SIOCGIFPSRCADDR: 814 dst = &ifr->ifr_addr; 815 size = sizeof(ifr->ifr_addr); 816 break; 817#endif /* INET */ 818#ifdef INET6 819 case SIOCGIFPSRCADDR_IN6: 820 dst = (struct sockaddr *) 821 &(((struct in6_ifreq *)data)->ifr_addr); 822 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 823 break; 824#endif /* INET6 */ 825 default: 826 error = EADDRNOTAVAIL; 827 goto bad; 828 } 829 if (src->sa_len > size) 830 return EINVAL; 831 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 832#ifdef INET6 833 if (dst->sa_family == AF_INET6) { 834 error = sa6_recoverscope((struct sockaddr_in6 *)dst); 835 if (error != 0) 836 return (error); 837 } 838#endif 839 break; 840 841 case SIOCGIFPDSTADDR: 842#ifdef INET6 843 case SIOCGIFPDSTADDR_IN6: 844#endif /* INET6 */ 845 if (sc->gif_pdst == NULL) { 846 error = EADDRNOTAVAIL; 847 goto bad; 848 } 849 src = sc->gif_pdst; 850 switch (cmd) { 851#ifdef INET 852 case SIOCGIFPDSTADDR: 853 dst = &ifr->ifr_addr; 854 size = sizeof(ifr->ifr_addr); 855 break; 856#endif /* INET */ 857#ifdef INET6 858 case SIOCGIFPDSTADDR_IN6: 859 dst = (struct sockaddr *) 860 &(((struct in6_ifreq *)data)->ifr_addr); 861 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 862 break; 863#endif /* INET6 */ 864 default: 865 error = EADDRNOTAVAIL; 866 goto bad; 867 } 868 if (src->sa_len > size) 869 return EINVAL; 870 error = prison_if(curthread->td_ucred, src); 871 if (error != 0) 872 return (error); 873 error = prison_if(curthread->td_ucred, dst); 874 if (error != 0) 875 return (error); 876 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 877#ifdef INET6 878 if (dst->sa_family == AF_INET6) { 879 error = sa6_recoverscope((struct sockaddr_in6 *)dst); 880 if (error != 0) 881 return (error); 882 } 883#endif 884 break; 885 886 case SIOCGLIFPHYADDR: 887 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 888 error = EADDRNOTAVAIL; 889 goto bad; 890 } 891 892 /* copy src */ 893 src = sc->gif_psrc; 894 dst = (struct sockaddr *) 895 &(((struct if_laddrreq *)data)->addr); 896 size = sizeof(((struct if_laddrreq *)data)->addr); 897 if (src->sa_len > size) 898 return EINVAL; 899 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 900 901 /* copy dst */ 902 src = sc->gif_pdst; 903 dst = (struct sockaddr *) 904 &(((struct if_laddrreq *)data)->dstaddr); 905 size = sizeof(((struct if_laddrreq *)data)->dstaddr); 906 if (src->sa_len > size) 907 return EINVAL; 908 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 909 break; 910 911 case SIOCSIFFLAGS: 912 /* if_ioctl() takes care of it */ 913 break; 914 915 case GIFGOPTS: 916 options = sc->gif_options; 917 error = copyout(&options, ifr->ifr_data, 918 sizeof(options)); 919 break; 920 921 case GIFSOPTS: 922 if ((error = priv_check(curthread, PRIV_NET_GIF)) != 0) 923 break; 924 error = copyin(ifr->ifr_data, &options, sizeof(options)); 925 if (error) 926 break; 927 if (options & ~GIF_OPTMASK) 928 error = EINVAL; 929 else 930 sc->gif_options = options; 931 break; 932 933 default: 934 error = EINVAL; 935 break; 936 } 937 bad: 938 return error; 939} 940 941/* 942 * XXXRW: There's a general event-ordering issue here: the code to check 943 * if a given tunnel is already present happens before we perform a 944 * potentially blocking setup of the tunnel. This code needs to be 945 * re-ordered so that the check and replacement can be atomic using 946 * a mutex. 947 */ 948int 949gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst) 950{ 951 struct gif_softc *sc = ifp->if_softc; 952 struct gif_softc *sc2; 953 struct sockaddr *osrc, *odst, *sa; 954 int error = 0; 955 956 GIF_LIST_LOCK(); 957 LIST_FOREACH(sc2, &V_gif_softc_list, gif_list) { 958 if (sc2 == sc) 959 continue; 960 if (!sc2->gif_pdst || !sc2->gif_psrc) 961 continue; 962 if (sc2->gif_pdst->sa_family != dst->sa_family || 963 sc2->gif_pdst->sa_len != dst->sa_len || 964 sc2->gif_psrc->sa_family != src->sa_family || 965 sc2->gif_psrc->sa_len != src->sa_len) 966 continue; 967 968 /* 969 * Disallow parallel tunnels unless instructed 970 * otherwise. 971 */ 972 if (!V_parallel_tunnels && 973 bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && 974 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { 975 error = EADDRNOTAVAIL; 976 GIF_LIST_UNLOCK(); 977 goto bad; 978 } 979 980 /* XXX both end must be valid? (I mean, not 0.0.0.0) */ 981 } 982 GIF_LIST_UNLOCK(); 983 984 /* XXX we can detach from both, but be polite just in case */ 985 if (sc->gif_psrc) 986 switch (sc->gif_psrc->sa_family) { 987#ifdef INET 988 case AF_INET: 989 (void)in_gif_detach(sc); 990 break; 991#endif 992#ifdef INET6 993 case AF_INET6: 994 (void)in6_gif_detach(sc); 995 break; 996#endif 997 } 998 999 osrc = sc->gif_psrc; 1000 sa = (struct sockaddr *)malloc(src->sa_len, M_IFADDR, M_WAITOK); 1001 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len); 1002 sc->gif_psrc = sa; 1003 1004 odst = sc->gif_pdst; 1005 sa = (struct sockaddr *)malloc(dst->sa_len, M_IFADDR, M_WAITOK); 1006 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len); 1007 sc->gif_pdst = sa; 1008 1009 switch (sc->gif_psrc->sa_family) { 1010#ifdef INET 1011 case AF_INET: 1012 error = in_gif_attach(sc); 1013 break; 1014#endif 1015#ifdef INET6 1016 case AF_INET6: 1017 /* 1018 * Check validity of the scope zone ID of the addresses, and 1019 * convert it into the kernel internal form if necessary. 1020 */ 1021 error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_psrc, 0); 1022 if (error != 0) 1023 break; 1024 error = sa6_embedscope((struct sockaddr_in6 *)sc->gif_pdst, 0); 1025 if (error != 0) 1026 break; 1027 error = in6_gif_attach(sc); 1028 break; 1029#endif 1030 } 1031 if (error) { 1032 /* rollback */ 1033 free((caddr_t)sc->gif_psrc, M_IFADDR); 1034 free((caddr_t)sc->gif_pdst, M_IFADDR); 1035 sc->gif_psrc = osrc; 1036 sc->gif_pdst = odst; 1037 goto bad; 1038 } 1039 1040 if (osrc) 1041 free((caddr_t)osrc, M_IFADDR); 1042 if (odst) 1043 free((caddr_t)odst, M_IFADDR); 1044 1045 bad: 1046 if (sc->gif_psrc && sc->gif_pdst) 1047 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1048 else 1049 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1050 1051 return error; 1052} 1053 1054void 1055gif_delete_tunnel(struct ifnet *ifp) 1056{ 1057 struct gif_softc *sc = ifp->if_softc; 1058 1059 if (sc->gif_psrc) { 1060 free((caddr_t)sc->gif_psrc, M_IFADDR); 1061 sc->gif_psrc = NULL; 1062 } 1063 if (sc->gif_pdst) { 1064 free((caddr_t)sc->gif_pdst, M_IFADDR); 1065 sc->gif_pdst = NULL; 1066 } 1067 /* it is safe to detach from both */ 1068#ifdef INET 1069 (void)in_gif_detach(sc); 1070#endif 1071#ifdef INET6 1072 (void)in6_gif_detach(sc); 1073#endif 1074 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1075} 1076