1 /* $OpenBSD: if_gif.c,v 1.64 2013/10/19 14:46:30 mpi Exp $ */ 2 /* $KAME: if_gif.c,v 1.43 2001/02/20 08:51:07 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 <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/mbuf.h> 37 #include <sys/socket.h> 38 #include <sys/sockio.h> 39 #include <sys/syslog.h> 40 41 #include <net/if.h> 42 #include <net/if_types.h> 43 #include <net/route.h> 44 #include <net/bpf.h> 45 46 #ifdef INET 47 #include <netinet/in.h> 48 #include <netinet/in_systm.h> 49 #include <netinet/in_var.h> 50 #include <netinet/in_gif.h> 51 #include <netinet/ip.h> 52 #include <netinet/ip_ether.h> 53 #include <netinet/ip_var.h> 54 #endif /* INET */ 55 56 #ifdef INET6 57 #ifndef INET 58 #include <netinet/in.h> 59 #endif 60 #include <netinet6/in6_var.h> 61 #include <netinet/ip6.h> 62 #include <netinet6/ip6_var.h> 63 #include <netinet6/in6_gif.h> 64 #endif /* INET6 */ 65 66 #include <net/if_gif.h> 67 68 #include "bpfilter.h" 69 #include "bridge.h" 70 71 void gifattach(int); 72 int gif_clone_create(struct if_clone *, int); 73 int gif_clone_destroy(struct ifnet *); 74 int gif_checkloop(struct ifnet *, struct mbuf *); 75 76 /* 77 * gif global variable definitions 78 */ 79 struct gif_softc_head gif_softc_list; 80 struct if_clone gif_cloner = 81 IF_CLONE_INITIALIZER("gif", gif_clone_create, gif_clone_destroy); 82 83 /* ARGSUSED */ 84 void 85 gifattach(int count) 86 { 87 LIST_INIT(&gif_softc_list); 88 if_clone_attach(&gif_cloner); 89 } 90 91 int 92 gif_clone_create(struct if_clone *ifc, int unit) 93 { 94 struct gif_softc *sc; 95 int s; 96 97 sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO); 98 if (!sc) 99 return (ENOMEM); 100 101 snprintf(sc->gif_if.if_xname, sizeof sc->gif_if.if_xname, 102 "%s%d", ifc->ifc_name, unit); 103 sc->gif_if.if_mtu = GIF_MTU; 104 sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; 105 sc->gif_if.if_ioctl = gif_ioctl; 106 sc->gif_if.if_start = gif_start; 107 sc->gif_if.if_output = gif_output; 108 sc->gif_if.if_type = IFT_GIF; 109 IFQ_SET_MAXLEN(&sc->gif_if.if_snd, IFQ_MAXLEN); 110 IFQ_SET_READY(&sc->gif_if.if_snd); 111 sc->gif_if.if_softc = sc; 112 if_attach(&sc->gif_if); 113 if_alloc_sadl(&sc->gif_if); 114 115 #if NBPFILTER > 0 116 bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_LOOP, sizeof(u_int32_t)); 117 #endif 118 s = splnet(); 119 LIST_INSERT_HEAD(&gif_softc_list, sc, gif_list); 120 splx(s); 121 122 return (0); 123 } 124 125 int 126 gif_clone_destroy(struct ifnet *ifp) 127 { 128 struct gif_softc *sc = ifp->if_softc; 129 int s; 130 131 s = splnet(); 132 LIST_REMOVE(sc, gif_list); 133 splx(s); 134 135 if_detach(ifp); 136 137 if (sc->gif_psrc) 138 free((caddr_t)sc->gif_psrc, M_IFADDR); 139 sc->gif_psrc = NULL; 140 if (sc->gif_pdst) 141 free((caddr_t)sc->gif_pdst, M_IFADDR); 142 sc->gif_pdst = NULL; 143 free(sc, M_DEVBUF); 144 return (0); 145 } 146 147 void 148 gif_start(struct ifnet *ifp) 149 { 150 struct gif_softc *sc = (struct gif_softc*)ifp; 151 struct mbuf *m; 152 int s; 153 154 while (1) { 155 s = splnet(); 156 IFQ_DEQUEUE(&ifp->if_snd, m); 157 splx(s); 158 159 if (m == NULL) 160 break; 161 162 /* is interface up and usable? */ 163 if ((ifp->if_flags & (IFF_OACTIVE | IFF_UP)) != IFF_UP || 164 sc->gif_psrc == NULL || sc->gif_pdst == NULL || 165 sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) { 166 m_freem(m); 167 continue; 168 } 169 170 /* 171 * Check if the packet is coming via bridge and needs 172 * etherip encapsulation or not. bridge(4) directly calls 173 * the start function and bypasses the if_output function 174 * so we need to do the encap here. 175 */ 176 if (ifp->if_bridgeport && (m->m_flags & M_PROTO1)) { 177 int error = 0; 178 /* 179 * Remove multicast and broadcast flags or encapsulated 180 * packet ends up as multicast or broadcast packet. 181 */ 182 m->m_flags &= ~(M_BCAST|M_MCAST); 183 switch (sc->gif_psrc->sa_family) { 184 #ifdef INET 185 case AF_INET: 186 error = in_gif_output(ifp, AF_LINK, &m); 187 break; 188 #endif 189 #ifdef INET6 190 case AF_INET6: 191 error = in6_gif_output(ifp, AF_LINK, &m); 192 break; 193 #endif 194 default: 195 error = EAFNOSUPPORT; 196 m_freem(m); 197 break; 198 } 199 if (error) 200 continue; 201 if (gif_checkloop(ifp, m)) 202 continue; 203 } 204 205 #if NBPFILTER > 0 206 if (ifp->if_bpf) { 207 int offset; 208 sa_family_t family; 209 u_int8_t proto; 210 211 /* must decapsulate outer header for bpf */ 212 switch (sc->gif_psrc->sa_family) { 213 #ifdef INET 214 case AF_INET: 215 offset = sizeof(struct ip); 216 proto = mtod(m, struct ip *)->ip_p; 217 break; 218 #endif 219 #ifdef INET6 220 case AF_INET6: 221 offset = sizeof(struct ip6_hdr); 222 proto = mtod(m, struct ip6_hdr *)->ip6_nxt; 223 break; 224 #endif 225 default: 226 proto = 0; 227 break; 228 } 229 switch (proto) { 230 case IPPROTO_IPV4: 231 family = AF_INET; 232 break; 233 case IPPROTO_IPV6: 234 family = AF_INET6; 235 break; 236 case IPPROTO_ETHERIP: 237 family = AF_LINK; 238 offset += sizeof(struct etherip_header); 239 break; 240 case IPPROTO_MPLS: 241 family = AF_MPLS; 242 break; 243 default: 244 offset = 0; 245 family = sc->gif_psrc->sa_family; 246 break; 247 } 248 m->m_data += offset; 249 m->m_len -= offset; 250 m->m_pkthdr.len -= offset; 251 bpf_mtap_af(ifp->if_bpf, family, m, BPF_DIRECTION_OUT); 252 m->m_data -= offset; 253 m->m_len += offset; 254 m->m_pkthdr.len += offset; 255 } 256 #endif 257 ifp->if_opackets++; 258 259 /* XXX we should cache the outgoing route */ 260 261 switch (sc->gif_psrc->sa_family) { 262 #ifdef INET 263 case AF_INET: 264 ip_output(m, (void *)NULL, (void *)NULL, 0, 265 (void *)NULL, (void *)NULL); 266 break; 267 #endif 268 #ifdef INET6 269 case AF_INET6: 270 /* 271 * force fragmentation to minimum MTU, to avoid path 272 * MTU discovery. It is too painful to ask for resend 273 * of inner packet, to achieve path MTU discovery for 274 * encapsulated packets. 275 */ 276 ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL, 277 NULL); 278 break; 279 #endif 280 default: 281 m_freem(m); 282 break; 283 } 284 } 285 } 286 287 int 288 gif_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 289 struct rtentry *rt) 290 { 291 struct gif_softc *sc = (struct gif_softc*)ifp; 292 int error = 0; 293 int s; 294 295 if (!(ifp->if_flags & IFF_UP) || 296 sc->gif_psrc == NULL || sc->gif_pdst == NULL || 297 sc->gif_psrc->sa_family != sc->gif_pdst->sa_family) { 298 m_freem(m); 299 error = ENETDOWN; 300 goto end; 301 } 302 303 /* 304 * Remove multicast and broadcast flags or encapsulated packet 305 * ends up as multicast or broadcast packet. 306 */ 307 m->m_flags &= ~(M_BCAST|M_MCAST); 308 309 /* 310 * Encapsulate packet. Add IP or IP6 header depending on tunnel AF. 311 */ 312 switch (sc->gif_psrc->sa_family) { 313 #ifdef INET 314 case AF_INET: 315 error = in_gif_output(ifp, dst->sa_family, &m); 316 break; 317 #endif 318 #ifdef INET6 319 case AF_INET6: 320 error = in6_gif_output(ifp, dst->sa_family, &m); 321 break; 322 #endif 323 default: 324 m_freem(m); 325 error = EAFNOSUPPORT; 326 break; 327 } 328 329 if (error) 330 goto end; 331 332 if ((error = gif_checkloop(ifp, m))) 333 goto end; 334 335 /* 336 * Queue message on interface, and start output. 337 */ 338 s = splnet(); 339 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 340 if (error) { 341 /* mbuf is already freed */ 342 splx(s); 343 goto end; 344 } 345 ifp->if_obytes += m->m_pkthdr.len; 346 if_start(ifp); 347 splx(s); 348 349 end: 350 if (error) 351 ifp->if_oerrors++; 352 return (error); 353 } 354 355 int 356 gif_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 357 { 358 struct gif_softc *sc = (struct gif_softc*)ifp; 359 struct ifreq *ifr = (struct ifreq*)data; 360 int error = 0, size; 361 struct sockaddr *dst, *src; 362 struct sockaddr *sa; 363 int s; 364 struct gif_softc *sc2; 365 366 switch (cmd) { 367 case SIOCSIFADDR: 368 break; 369 370 case SIOCSIFDSTADDR: 371 break; 372 373 case SIOCADDMULTI: 374 case SIOCDELMULTI: 375 break; 376 377 case SIOCSIFPHYADDR: 378 #ifdef INET6 379 case SIOCSIFPHYADDR_IN6: 380 #endif /* INET6 */ 381 case SIOCSLIFPHYADDR: 382 switch (cmd) { 383 #ifdef INET 384 case SIOCSIFPHYADDR: 385 src = (struct sockaddr *) 386 &(((struct in_aliasreq *)data)->ifra_addr); 387 dst = (struct sockaddr *) 388 &(((struct in_aliasreq *)data)->ifra_dstaddr); 389 break; 390 #endif 391 #ifdef INET6 392 case SIOCSIFPHYADDR_IN6: 393 src = (struct sockaddr *) 394 &(((struct in6_aliasreq *)data)->ifra_addr); 395 dst = (struct sockaddr *) 396 &(((struct in6_aliasreq *)data)->ifra_dstaddr); 397 break; 398 #endif 399 case SIOCSLIFPHYADDR: 400 src = (struct sockaddr *) 401 &(((struct if_laddrreq *)data)->addr); 402 dst = (struct sockaddr *) 403 &(((struct if_laddrreq *)data)->dstaddr); 404 break; 405 default: 406 return (EINVAL); 407 } 408 409 /* sa_family must be equal */ 410 if (src->sa_family != dst->sa_family) 411 return (EINVAL); 412 413 /* validate sa_len */ 414 switch (src->sa_family) { 415 #ifdef INET 416 case AF_INET: 417 if (src->sa_len != sizeof(struct sockaddr_in)) 418 return (EINVAL); 419 break; 420 #endif 421 #ifdef INET6 422 case AF_INET6: 423 if (src->sa_len != sizeof(struct sockaddr_in6)) 424 return (EINVAL); 425 break; 426 #endif 427 default: 428 return (EAFNOSUPPORT); 429 } 430 switch (dst->sa_family) { 431 #ifdef INET 432 case AF_INET: 433 if (dst->sa_len != sizeof(struct sockaddr_in)) 434 return (EINVAL); 435 break; 436 #endif 437 #ifdef INET6 438 case AF_INET6: 439 if (dst->sa_len != sizeof(struct sockaddr_in6)) 440 return (EINVAL); 441 break; 442 #endif 443 default: 444 return (EAFNOSUPPORT); 445 } 446 447 /* check sa_family looks sane for the cmd */ 448 switch (cmd) { 449 case SIOCSIFPHYADDR: 450 if (src->sa_family == AF_INET) 451 break; 452 return (EAFNOSUPPORT); 453 #ifdef INET6 454 case SIOCSIFPHYADDR_IN6: 455 if (src->sa_family == AF_INET6) 456 break; 457 return (EAFNOSUPPORT); 458 #endif /* INET6 */ 459 case SIOCSLIFPHYADDR: 460 /* checks done in the above */ 461 break; 462 } 463 464 LIST_FOREACH(sc2, &gif_softc_list, gif_list) { 465 if (sc2 == sc) 466 continue; 467 if (!sc2->gif_pdst || !sc2->gif_psrc) 468 continue; 469 if (sc2->gif_pdst->sa_family != dst->sa_family || 470 sc2->gif_pdst->sa_len != dst->sa_len || 471 sc2->gif_psrc->sa_family != src->sa_family || 472 sc2->gif_psrc->sa_len != src->sa_len) 473 continue; 474 /* can't configure same pair of address onto two gifs */ 475 if (bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && 476 bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { 477 error = EADDRNOTAVAIL; 478 goto bad; 479 } 480 481 /* can't configure multiple multi-dest interfaces */ 482 #define multidest(x) \ 483 (((struct sockaddr_in *)(x))->sin_addr.s_addr == INADDR_ANY) 484 #ifdef INET6 485 #define multidest6(x) \ 486 (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)(x))->sin6_addr)) 487 #endif 488 if (dst->sa_family == AF_INET && 489 multidest(dst) && multidest(sc2->gif_pdst)) { 490 error = EADDRNOTAVAIL; 491 goto bad; 492 } 493 #ifdef INET6 494 if (dst->sa_family == AF_INET6 && 495 multidest6(dst) && multidest6(sc2->gif_pdst)) { 496 error = EADDRNOTAVAIL; 497 goto bad; 498 } 499 #endif 500 } 501 502 if (sc->gif_psrc) 503 free((caddr_t)sc->gif_psrc, M_IFADDR); 504 sa = malloc(src->sa_len, M_IFADDR, M_WAITOK); 505 bcopy((caddr_t)src, (caddr_t)sa, src->sa_len); 506 sc->gif_psrc = sa; 507 508 if (sc->gif_pdst) 509 free((caddr_t)sc->gif_pdst, M_IFADDR); 510 sa = malloc(dst->sa_len, M_IFADDR, M_WAITOK); 511 bcopy((caddr_t)dst, (caddr_t)sa, dst->sa_len); 512 sc->gif_pdst = sa; 513 514 s = splnet(); 515 ifp->if_flags |= IFF_RUNNING; 516 if_up(ifp); /* send up RTM_IFINFO */ 517 splx(s); 518 519 error = 0; 520 break; 521 522 #ifdef SIOCDIFPHYADDR 523 case SIOCDIFPHYADDR: 524 if (sc->gif_psrc) { 525 free((caddr_t)sc->gif_psrc, M_IFADDR); 526 sc->gif_psrc = NULL; 527 } 528 if (sc->gif_pdst) { 529 free((caddr_t)sc->gif_pdst, M_IFADDR); 530 sc->gif_pdst = NULL; 531 } 532 /* change the IFF_{UP, RUNNING} flag as well? */ 533 break; 534 #endif 535 536 case SIOCGIFPSRCADDR: 537 #ifdef INET6 538 case SIOCGIFPSRCADDR_IN6: 539 #endif /* INET6 */ 540 if (sc->gif_psrc == NULL) { 541 error = EADDRNOTAVAIL; 542 goto bad; 543 } 544 src = sc->gif_psrc; 545 switch (cmd) { 546 #ifdef INET 547 case SIOCGIFPSRCADDR: 548 dst = &ifr->ifr_addr; 549 size = sizeof(ifr->ifr_addr); 550 break; 551 #endif /* INET */ 552 #ifdef INET6 553 case SIOCGIFPSRCADDR_IN6: 554 dst = (struct sockaddr *) 555 &(((struct in6_ifreq *)data)->ifr_addr); 556 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 557 break; 558 #endif /* INET6 */ 559 default: 560 error = EADDRNOTAVAIL; 561 goto bad; 562 } 563 if (src->sa_len > size) 564 return (EINVAL); 565 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 566 break; 567 568 case SIOCGIFPDSTADDR: 569 #ifdef INET6 570 case SIOCGIFPDSTADDR_IN6: 571 #endif /* INET6 */ 572 if (sc->gif_pdst == NULL) { 573 error = EADDRNOTAVAIL; 574 goto bad; 575 } 576 src = sc->gif_pdst; 577 switch (cmd) { 578 #ifdef INET 579 case SIOCGIFPDSTADDR: 580 dst = &ifr->ifr_addr; 581 size = sizeof(ifr->ifr_addr); 582 break; 583 #endif /* INET */ 584 #ifdef INET6 585 case SIOCGIFPDSTADDR_IN6: 586 dst = (struct sockaddr *) 587 &(((struct in6_ifreq *)data)->ifr_addr); 588 size = sizeof(((struct in6_ifreq *)data)->ifr_addr); 589 break; 590 #endif /* INET6 */ 591 default: 592 error = EADDRNOTAVAIL; 593 goto bad; 594 } 595 if (src->sa_len > size) 596 return (EINVAL); 597 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 598 break; 599 600 case SIOCGLIFPHYADDR: 601 if (sc->gif_psrc == NULL || sc->gif_pdst == NULL) { 602 error = EADDRNOTAVAIL; 603 goto bad; 604 } 605 606 /* copy src */ 607 src = sc->gif_psrc; 608 dst = (struct sockaddr *) 609 &(((struct if_laddrreq *)data)->addr); 610 size = sizeof(((struct if_laddrreq *)data)->addr); 611 if (src->sa_len > size) 612 return (EINVAL); 613 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 614 615 /* copy dst */ 616 src = sc->gif_pdst; 617 dst = (struct sockaddr *) 618 &(((struct if_laddrreq *)data)->dstaddr); 619 size = sizeof(((struct if_laddrreq *)data)->dstaddr); 620 if (src->sa_len > size) 621 return (EINVAL); 622 bcopy((caddr_t)src, (caddr_t)dst, src->sa_len); 623 break; 624 625 case SIOCSIFFLAGS: 626 /* if_ioctl() takes care of it */ 627 break; 628 629 case SIOCSIFMTU: 630 if (ifr->ifr_mtu < GIF_MTU_MIN || ifr->ifr_mtu > GIF_MTU_MAX) 631 error = EINVAL; 632 else 633 ifp->if_mtu = ifr->ifr_mtu; 634 break; 635 636 case SIOCSLIFPHYRTABLE: 637 if (ifr->ifr_rdomainid < 0 || 638 ifr->ifr_rdomainid > RT_TABLEID_MAX || 639 !rtable_exists(ifr->ifr_rdomainid)) { 640 error = EINVAL; 641 break; 642 } 643 sc->gif_rtableid = ifr->ifr_rdomainid; 644 break; 645 case SIOCGLIFPHYRTABLE: 646 ifr->ifr_rdomainid = sc->gif_rtableid; 647 break; 648 default: 649 error = ENOTTY; 650 break; 651 } 652 bad: 653 return (error); 654 } 655 656 int 657 gif_checkloop(struct ifnet *ifp, struct mbuf *m) 658 { 659 struct m_tag *mtag; 660 661 /* 662 * gif may cause infinite recursion calls when misconfigured. 663 * We'll prevent this by detecting loops. 664 */ 665 for (mtag = m_tag_find(m, PACKET_TAG_GIF, NULL); mtag; 666 mtag = m_tag_find(m, PACKET_TAG_GIF, mtag)) { 667 if (*(struct ifnet **)(mtag + 1) == ifp) { 668 log(LOG_NOTICE, "gif_output: " 669 "recursively called too many times\n"); 670 m_freem(m); 671 return ENETUNREACH; 672 } 673 } 674 675 mtag = m_tag_get(PACKET_TAG_GIF, sizeof(struct ifnet *), M_NOWAIT); 676 if (mtag == NULL) { 677 m_freem(m); 678 return ENOMEM; 679 } 680 *(struct ifnet **)(mtag + 1) = ifp; 681 m_tag_prepend(m, mtag); 682 return 0; 683 } 684