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