1 /* $OpenBSD: if_etherip.c,v 1.55 2024/02/13 12:22:09 bluhm Exp $ */ 2 /* 3 * Copyright (c) 2015 Kazuya GODA <goda@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "bpfilter.h" 19 #include "pf.h" 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/mbuf.h> 24 #include <sys/socket.h> 25 #include <sys/ioctl.h> 26 #include <sys/device.h> 27 #include <sys/sysctl.h> 28 #include <sys/tree.h> 29 30 #include <net/if.h> 31 #include <net/if_var.h> 32 #include <net/if_dl.h> 33 #include <net/if_media.h> 34 #include <net/route.h> 35 #include <net/rtable.h> 36 37 #include <netinet/in.h> 38 #include <netinet/ip.h> 39 #include <netinet/ip_var.h> 40 #include <netinet/if_ether.h> 41 #include <netinet/ip_ether.h> 42 43 #ifdef INET6 44 #include <netinet/ip6.h> 45 #include <netinet6/ip6_var.h> 46 #endif 47 48 #if NBPFILTER > 0 49 #include <net/bpf.h> 50 #endif 51 52 #if NPF > 0 53 #include <net/pfvar.h> 54 #endif 55 56 #include <net/if_etherip.h> 57 58 union etherip_addr { 59 struct in_addr in4; 60 struct in6_addr in6; 61 }; 62 63 struct etherip_tunnel { 64 union etherip_addr 65 _t_src; 66 #define t_src4 _t_src.in4 67 #define t_src6 _t_src.in6 68 union etherip_addr 69 _t_dst; 70 #define t_dst4 _t_dst.in4 71 #define t_dst6 _t_dst.in6 72 73 unsigned int t_rtableid; 74 sa_family_t t_af; 75 uint8_t t_tos; 76 77 TAILQ_ENTRY(etherip_tunnel) 78 t_entry; 79 }; 80 81 TAILQ_HEAD(etherip_list, etherip_tunnel); 82 83 static inline int etherip_cmp(const struct etherip_tunnel *, 84 const struct etherip_tunnel *); 85 86 struct etherip_softc { 87 struct etherip_tunnel sc_tunnel; /* must be first */ 88 struct arpcom sc_ac; 89 struct ifmedia sc_media; 90 int sc_txhprio; 91 int sc_rxhprio; 92 uint16_t sc_df; 93 uint8_t sc_ttl; 94 }; 95 96 /* 97 * We can control the acceptance of EtherIP packets by altering the sysctl 98 * net.inet.etherip.allow value. Zero means drop them, all else is acceptance. 99 */ 100 int etherip_allow = 0; 101 102 struct cpumem *etheripcounters; 103 104 void etheripattach(int); 105 int etherip_clone_create(struct if_clone *, int); 106 int etherip_clone_destroy(struct ifnet *); 107 int etherip_ioctl(struct ifnet *, u_long, caddr_t); 108 int etherip_output(struct ifnet *, struct mbuf *, struct sockaddr *, 109 struct rtentry *); 110 void etherip_start(struct ifnet *); 111 int etherip_media_change(struct ifnet *); 112 void etherip_media_status(struct ifnet *, struct ifmediareq *); 113 int etherip_set_tunnel(struct etherip_softc *, struct if_laddrreq *); 114 int etherip_get_tunnel(struct etherip_softc *, struct if_laddrreq *); 115 int etherip_del_tunnel(struct etherip_softc *); 116 int etherip_up(struct etherip_softc *); 117 int etherip_down(struct etherip_softc *); 118 struct etherip_softc *etherip_find(const struct etherip_tunnel *); 119 int etherip_input(struct etherip_tunnel *, struct mbuf *, uint8_t, int); 120 121 struct if_clone etherip_cloner = IF_CLONE_INITIALIZER("etherip", 122 etherip_clone_create, etherip_clone_destroy); 123 124 struct etherip_list etherip_list = TAILQ_HEAD_INITIALIZER(etherip_list); 125 126 void 127 etheripattach(int count) 128 { 129 if_clone_attach(ðerip_cloner); 130 etheripcounters = counters_alloc(etherips_ncounters); 131 } 132 133 int 134 etherip_clone_create(struct if_clone *ifc, int unit) 135 { 136 struct ifnet *ifp; 137 struct etherip_softc *sc; 138 139 sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); 140 ifp = &sc->sc_ac.ac_if; 141 142 snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", 143 ifc->ifc_name, unit); 144 145 sc->sc_ttl = ip_defttl; 146 sc->sc_txhprio = IFQ_TOS2PRIO(IPTOS_PREC_ROUTINE); /* 0 */ 147 sc->sc_rxhprio = IF_HDRPRIO_PACKET; 148 sc->sc_df = htons(0); 149 150 ifp->if_softc = sc; 151 ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN; 152 ifp->if_ioctl = etherip_ioctl; 153 ifp->if_output = etherip_output; 154 ifp->if_start = etherip_start; 155 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 156 ifp->if_xflags = IFXF_CLONED; 157 ifp->if_capabilities = IFCAP_VLAN_MTU; 158 ether_fakeaddr(ifp); 159 160 ifmedia_init(&sc->sc_media, 0, etherip_media_change, 161 etherip_media_status); 162 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 163 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 164 165 if_counters_alloc(ifp); 166 if_attach(ifp); 167 ether_ifattach(ifp); 168 169 NET_LOCK(); 170 TAILQ_INSERT_TAIL(ðerip_list, &sc->sc_tunnel, t_entry); 171 NET_UNLOCK(); 172 173 return (0); 174 } 175 176 int 177 etherip_clone_destroy(struct ifnet *ifp) 178 { 179 struct etherip_softc *sc = ifp->if_softc; 180 181 NET_LOCK(); 182 if (ISSET(ifp->if_flags, IFF_RUNNING)) 183 etherip_down(sc); 184 185 TAILQ_REMOVE(ðerip_list, &sc->sc_tunnel, t_entry); 186 NET_UNLOCK(); 187 188 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 189 ether_ifdetach(ifp); 190 if_detach(ifp); 191 192 free(sc, M_DEVBUF, sizeof(*sc)); 193 194 return (0); 195 } 196 197 int 198 etherip_media_change(struct ifnet *ifp) 199 { 200 return 0; 201 } 202 203 void 204 etherip_media_status(struct ifnet *ifp, struct ifmediareq *imr) 205 { 206 imr->ifm_active = IFM_ETHER | IFM_AUTO; 207 imr->ifm_status = IFM_AVALID | IFM_ACTIVE; 208 } 209 210 int 211 etherip_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 212 struct rtentry *rt) 213 { 214 struct m_tag *mtag; 215 216 mtag = NULL; 217 while ((mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) != NULL) { 218 if (*(int *)(mtag + 1) == ifp->if_index) { 219 m_freem(m); 220 return (EIO); 221 } 222 } 223 224 return (ether_output(ifp, m, dst, rt)); 225 } 226 227 void 228 etherip_start(struct ifnet *ifp) 229 { 230 struct etherip_softc *sc = ifp->if_softc; 231 struct mbuf *m; 232 int error; 233 #if NBPFILTER > 0 234 caddr_t if_bpf; 235 #endif 236 237 while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) { 238 #if NBPFILTER > 0 239 if_bpf = ifp->if_bpf; 240 if (if_bpf) 241 bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_OUT); 242 #endif 243 244 switch (sc->sc_tunnel.t_af) { 245 case AF_INET: 246 error = ip_etherip_output(ifp, m); 247 break; 248 #ifdef INET6 249 case AF_INET6: 250 error = ip6_etherip_output(ifp, m); 251 break; 252 #endif 253 default: 254 /* unhandled_af(sc->sc_tunnel.t_af); */ 255 m_freem(m); 256 continue; 257 } 258 259 if (error) 260 ifp->if_oerrors++; 261 } 262 } 263 264 int 265 etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 266 { 267 struct etherip_softc *sc = ifp->if_softc; 268 struct ifreq *ifr = (struct ifreq *)data; 269 int error = 0; 270 271 switch (cmd) { 272 case SIOCSIFADDR: 273 ifp->if_flags |= IFF_UP; 274 /* FALLTHROUGH */ 275 276 case SIOCSIFFLAGS: 277 if (ISSET(ifp->if_flags, IFF_UP)) { 278 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 279 error = etherip_up(sc); 280 else 281 error = 0; 282 } else { 283 if (ISSET(ifp->if_flags, IFF_RUNNING)) 284 error = etherip_down(sc); 285 } 286 break; 287 288 case SIOCSLIFPHYRTABLE: 289 if (ifr->ifr_rdomainid < 0 || 290 ifr->ifr_rdomainid > RT_TABLEID_MAX || 291 !rtable_exists(ifr->ifr_rdomainid)) { 292 error = EINVAL; 293 break; 294 } 295 sc->sc_tunnel.t_rtableid = ifr->ifr_rdomainid; 296 break; 297 298 case SIOCGLIFPHYRTABLE: 299 ifr->ifr_rdomainid = sc->sc_tunnel.t_rtableid; 300 break; 301 302 case SIOCSLIFPHYADDR: 303 error = etherip_set_tunnel(sc, (struct if_laddrreq *)data); 304 break; 305 case SIOCGLIFPHYADDR: 306 error = etherip_get_tunnel(sc, (struct if_laddrreq *)data); 307 break; 308 case SIOCDIFPHYADDR: 309 error = etherip_del_tunnel(sc); 310 break; 311 312 case SIOCSTXHPRIO: 313 error = if_txhprio_l2_check(ifr->ifr_hdrprio); 314 if (error != 0) 315 break; 316 317 sc->sc_txhprio = ifr->ifr_hdrprio; 318 break; 319 case SIOCGTXHPRIO: 320 ifr->ifr_hdrprio = sc->sc_txhprio; 321 break; 322 323 case SIOCSRXHPRIO: 324 error = if_rxhprio_l2_check(ifr->ifr_hdrprio); 325 if (error != 0) 326 break; 327 328 sc->sc_rxhprio = ifr->ifr_hdrprio; 329 break; 330 case SIOCGRXHPRIO: 331 ifr->ifr_hdrprio = sc->sc_rxhprio; 332 break; 333 334 case SIOCSLIFPHYTTL: 335 if (ifr->ifr_ttl < 1 || ifr->ifr_ttl > 0xff) { 336 error = EINVAL; 337 break; 338 } 339 340 /* commit */ 341 sc->sc_ttl = (uint8_t)ifr->ifr_ttl; 342 break; 343 case SIOCGLIFPHYTTL: 344 ifr->ifr_ttl = (int)sc->sc_ttl; 345 break; 346 347 case SIOCSLIFPHYDF: 348 /* commit */ 349 sc->sc_df = ifr->ifr_df ? htons(IP_DF) : htons(0); 350 break; 351 case SIOCGLIFPHYDF: 352 ifr->ifr_df = sc->sc_df ? 1 : 0; 353 break; 354 355 case SIOCSIFMEDIA: 356 case SIOCGIFMEDIA: 357 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 358 break; 359 360 case SIOCADDMULTI: 361 case SIOCDELMULTI: 362 break; 363 364 default: 365 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 366 break; 367 } 368 369 if (error == ENETRESET) { 370 /* no hardware to program */ 371 error = 0; 372 } 373 374 return (error); 375 } 376 377 int 378 etherip_set_tunnel(struct etherip_softc *sc, struct if_laddrreq *req) 379 { 380 struct sockaddr *src = (struct sockaddr *)&req->addr; 381 struct sockaddr *dst = (struct sockaddr *)&req->dstaddr; 382 struct sockaddr_in *src4, *dst4; 383 #ifdef INET6 384 struct sockaddr_in6 *src6, *dst6; 385 int error; 386 #endif 387 388 /* sa_family and sa_len must be equal */ 389 if (src->sa_family != dst->sa_family || src->sa_len != dst->sa_len) 390 return (EINVAL); 391 392 /* validate */ 393 switch (dst->sa_family) { 394 case AF_INET: 395 if (dst->sa_len != sizeof(*dst4)) 396 return (EINVAL); 397 398 src4 = (struct sockaddr_in *)src; 399 if (in_nullhost(src4->sin_addr) || 400 IN_MULTICAST(src4->sin_addr.s_addr)) 401 return (EINVAL); 402 403 dst4 = (struct sockaddr_in *)dst; 404 if (in_nullhost(dst4->sin_addr) || 405 IN_MULTICAST(dst4->sin_addr.s_addr)) 406 return (EINVAL); 407 408 sc->sc_tunnel.t_src4 = src4->sin_addr; 409 sc->sc_tunnel.t_dst4 = dst4->sin_addr; 410 break; 411 #ifdef INET6 412 case AF_INET6: 413 if (dst->sa_len != sizeof(*dst6)) 414 return (EINVAL); 415 416 src6 = (struct sockaddr_in6 *)src; 417 if (IN6_IS_ADDR_UNSPECIFIED(&src6->sin6_addr) || 418 IN6_IS_ADDR_MULTICAST(&src6->sin6_addr)) 419 return (EINVAL); 420 421 dst6 = (struct sockaddr_in6 *)dst; 422 if (IN6_IS_ADDR_UNSPECIFIED(&dst6->sin6_addr) || 423 IN6_IS_ADDR_MULTICAST(&dst6->sin6_addr)) 424 return (EINVAL); 425 426 error = in6_embedscope(&sc->sc_tunnel.t_src6, src6, NULL, NULL); 427 if (error != 0) 428 return (error); 429 430 error = in6_embedscope(&sc->sc_tunnel.t_dst6, dst6, NULL, NULL); 431 if (error != 0) 432 return (error); 433 434 break; 435 #endif 436 default: 437 return (EAFNOSUPPORT); 438 } 439 440 /* commit */ 441 sc->sc_tunnel.t_af = dst->sa_family; 442 443 return (0); 444 } 445 446 int 447 etherip_get_tunnel(struct etherip_softc *sc, struct if_laddrreq *req) 448 { 449 struct sockaddr *src = (struct sockaddr *)&req->addr; 450 struct sockaddr *dst = (struct sockaddr *)&req->dstaddr; 451 struct sockaddr_in *sin; 452 #ifdef INET6 /* ifconfig already embeds the scopeid */ 453 struct sockaddr_in6 *sin6; 454 #endif 455 456 switch (sc->sc_tunnel.t_af) { 457 case AF_UNSPEC: 458 return (EADDRNOTAVAIL); 459 case AF_INET: 460 sin = (struct sockaddr_in *)src; 461 memset(sin, 0, sizeof(*sin)); 462 sin->sin_family = AF_INET; 463 sin->sin_len = sizeof(*sin); 464 sin->sin_addr = sc->sc_tunnel.t_src4; 465 466 sin = (struct sockaddr_in *)dst; 467 memset(sin, 0, sizeof(*sin)); 468 sin->sin_family = AF_INET; 469 sin->sin_len = sizeof(*sin); 470 sin->sin_addr = sc->sc_tunnel.t_dst4; 471 472 break; 473 #ifdef INET6 474 case AF_INET6: 475 sin6 = (struct sockaddr_in6 *)src; 476 memset(sin6, 0, sizeof(*sin6)); 477 sin6->sin6_family = AF_INET6; 478 sin6->sin6_len = sizeof(*sin6); 479 in6_recoverscope(sin6, &sc->sc_tunnel.t_src6); 480 481 sin6 = (struct sockaddr_in6 *)dst; 482 memset(sin6, 0, sizeof(*sin6)); 483 sin6->sin6_family = AF_INET6; 484 sin6->sin6_len = sizeof(*sin6); 485 in6_recoverscope(sin6, &sc->sc_tunnel.t_dst6); 486 487 break; 488 #endif 489 default: 490 return (EAFNOSUPPORT); 491 } 492 493 return (0); 494 } 495 496 int 497 etherip_del_tunnel(struct etherip_softc *sc) 498 { 499 /* commit */ 500 sc->sc_tunnel.t_af = AF_UNSPEC; 501 502 return (0); 503 } 504 505 int 506 etherip_up(struct etherip_softc *sc) 507 { 508 struct ifnet *ifp = &sc->sc_ac.ac_if; 509 510 NET_ASSERT_LOCKED(); 511 512 SET(ifp->if_flags, IFF_RUNNING); 513 514 return (0); 515 } 516 517 int 518 etherip_down(struct etherip_softc *sc) 519 { 520 struct ifnet *ifp = &sc->sc_ac.ac_if; 521 522 NET_ASSERT_LOCKED(); 523 524 CLR(ifp->if_flags, IFF_RUNNING); 525 526 return (0); 527 } 528 529 int 530 ip_etherip_output(struct ifnet *ifp, struct mbuf *m) 531 { 532 struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc; 533 struct m_tag *mtag; 534 struct etherip_header *eip; 535 struct ip *ip; 536 537 M_PREPEND(m, sizeof(*ip) + sizeof(*eip), M_DONTWAIT); 538 if (m == NULL) { 539 etheripstat_inc(etherips_adrops); 540 return ENOBUFS; 541 } 542 543 ip = mtod(m, struct ip *); 544 memset(ip, 0, sizeof(struct ip)); 545 546 ip->ip_v = IPVERSION; 547 ip->ip_hl = sizeof(*ip) >> 2; 548 ip->ip_tos = IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? 549 m->m_pkthdr.pf.prio : sc->sc_txhprio); 550 ip->ip_len = htons(m->m_pkthdr.len); 551 ip->ip_id = htons(ip_randomid()); 552 ip->ip_off = sc->sc_df; 553 ip->ip_ttl = sc->sc_ttl; 554 ip->ip_p = IPPROTO_ETHERIP; 555 ip->ip_src = sc->sc_tunnel.t_src4; 556 ip->ip_dst = sc->sc_tunnel.t_dst4; 557 558 eip = (struct etherip_header *)(ip + 1); 559 eip->eip_ver = ETHERIP_VERSION; 560 eip->eip_res = 0; 561 eip->eip_pad = 0; 562 563 mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); 564 if (mtag == NULL) { 565 m_freem(m); 566 return (ENOMEM); 567 } 568 569 *(int *)(mtag + 1) = ifp->if_index; 570 m_tag_prepend(m, mtag); 571 572 m->m_flags &= ~(M_BCAST|M_MCAST); 573 m->m_pkthdr.ph_rtableid = sc->sc_tunnel.t_rtableid; 574 575 #if NPF > 0 576 pf_pkt_addr_changed(m); 577 #endif 578 etheripstat_pkt(etherips_opackets, etherips_obytes, m->m_pkthdr.len - 579 (sizeof(struct ip) + sizeof(struct etherip_header))); 580 581 ip_send(m); 582 583 return (0); 584 } 585 586 int 587 ip_etherip_input(struct mbuf **mp, int *offp, int type, int af) 588 { 589 struct mbuf *m = *mp; 590 struct etherip_tunnel key; 591 struct ip *ip; 592 593 ip = mtod(m, struct ip *); 594 595 key.t_af = AF_INET; 596 key.t_src4 = ip->ip_dst; 597 key.t_dst4 = ip->ip_src; 598 599 return (etherip_input(&key, m, ip->ip_tos, *offp)); 600 } 601 602 struct etherip_softc * 603 etherip_find(const struct etherip_tunnel *key) 604 { 605 struct etherip_tunnel *t; 606 struct etherip_softc *sc; 607 608 TAILQ_FOREACH(t, ðerip_list, t_entry) { 609 if (etherip_cmp(key, t) != 0) 610 continue; 611 612 sc = (struct etherip_softc *)t; 613 if (!ISSET(sc->sc_ac.ac_if.if_flags, IFF_RUNNING)) 614 continue; 615 616 return (sc); 617 } 618 619 return (NULL); 620 } 621 622 int 623 etherip_input(struct etherip_tunnel *key, struct mbuf *m, uint8_t tos, 624 int hlen) 625 { 626 struct etherip_softc *sc; 627 struct ifnet *ifp; 628 struct etherip_header *eip; 629 int rxprio; 630 631 if (!etherip_allow && (m->m_flags & (M_AUTH|M_CONF)) == 0) { 632 etheripstat_inc(etherips_pdrops); 633 goto drop; 634 } 635 636 key->t_rtableid = m->m_pkthdr.ph_rtableid; 637 638 NET_ASSERT_LOCKED(); 639 sc = etherip_find(key); 640 if (sc == NULL) { 641 etheripstat_inc(etherips_noifdrops); 642 goto drop; 643 } 644 645 m_adj(m, hlen); 646 m = m_pullup(m, sizeof(*eip)); 647 if (m == NULL) { 648 etheripstat_inc(etherips_adrops); 649 return IPPROTO_DONE; 650 } 651 652 eip = mtod(m, struct etherip_header *); 653 if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) { 654 etheripstat_inc(etherips_adrops); 655 goto drop; 656 } 657 658 m_adj(m, sizeof(struct etherip_header)); 659 660 etheripstat_pkt(etherips_ipackets, etherips_ibytes, m->m_pkthdr.len); 661 662 m = m_pullup(m, sizeof(struct ether_header)); 663 if (m == NULL) { 664 etheripstat_inc(etherips_adrops); 665 return IPPROTO_DONE; 666 } 667 668 rxprio = sc->sc_rxhprio; 669 switch (rxprio) { 670 case IF_HDRPRIO_PACKET: 671 break; 672 case IF_HDRPRIO_OUTER: 673 m->m_pkthdr.pf.prio = IFQ_TOS2PRIO(tos); 674 break; 675 default: 676 m->m_pkthdr.pf.prio = rxprio; 677 break; 678 } 679 680 ifp = &sc->sc_ac.ac_if; 681 682 m->m_flags &= ~(M_BCAST|M_MCAST); 683 m->m_pkthdr.ph_ifidx = ifp->if_index; 684 m->m_pkthdr.ph_rtableid = ifp->if_rdomain; 685 686 #if NPF > 0 687 pf_pkt_addr_changed(m); 688 #endif 689 690 if_vinput(ifp, m); 691 return IPPROTO_DONE; 692 693 drop: 694 m_freem(m); 695 return (IPPROTO_DONE); 696 } 697 698 #ifdef INET6 699 int 700 ip6_etherip_output(struct ifnet *ifp, struct mbuf *m) 701 { 702 struct etherip_softc *sc = ifp->if_softc; 703 struct m_tag *mtag; 704 struct ip6_hdr *ip6; 705 struct etherip_header *eip; 706 uint16_t len; 707 uint32_t flow; 708 709 if (IN6_IS_ADDR_UNSPECIFIED(&sc->sc_tunnel.t_dst6)) { 710 m_freem(m); 711 return (ENETUNREACH); 712 } 713 714 len = m->m_pkthdr.len; 715 716 M_PREPEND(m, sizeof(*ip6) + sizeof(*eip), M_DONTWAIT); 717 if (m == NULL) { 718 etheripstat_inc(etherips_adrops); 719 return ENOBUFS; 720 } 721 722 flow = IPV6_VERSION << 24; 723 flow |= IFQ_PRIO2TOS(sc->sc_txhprio == IF_HDRPRIO_PACKET ? 724 m->m_pkthdr.pf.prio : sc->sc_txhprio) << 20; 725 726 ip6 = mtod(m, struct ip6_hdr *); 727 htobem32(&ip6->ip6_flow, flow); 728 ip6->ip6_nxt = IPPROTO_ETHERIP; 729 ip6->ip6_hlim = sc->sc_ttl; 730 ip6->ip6_plen = htons(len); 731 memcpy(&ip6->ip6_src, &sc->sc_tunnel.t_src6, sizeof(ip6->ip6_src)); 732 memcpy(&ip6->ip6_dst, &sc->sc_tunnel.t_dst6, sizeof(ip6->ip6_dst)); 733 734 eip = (struct etherip_header *)(ip6 + 1); 735 eip->eip_ver = ETHERIP_VERSION; 736 eip->eip_res = 0; 737 eip->eip_pad = 0; 738 739 mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); 740 if (mtag == NULL) { 741 m_freem(m); 742 return (ENOMEM); 743 } 744 745 *(int *)(mtag + 1) = ifp->if_index; 746 m_tag_prepend(m, mtag); 747 748 if (sc->sc_df) 749 SET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT); 750 751 m->m_flags &= ~(M_BCAST|M_MCAST); 752 m->m_pkthdr.ph_rtableid = sc->sc_tunnel.t_rtableid; 753 754 #if NPF > 0 755 pf_pkt_addr_changed(m); 756 #endif 757 758 etheripstat_pkt(etherips_opackets, etherips_obytes, len); 759 760 ip6_send(m); 761 return (0); 762 } 763 764 int 765 ip6_etherip_input(struct mbuf **mp, int *offp, int proto, int af) 766 { 767 struct mbuf *m = *mp; 768 struct etherip_tunnel key; 769 const struct ip6_hdr *ip6; 770 uint32_t flow; 771 772 ip6 = mtod(m, const struct ip6_hdr *); 773 774 key.t_af = AF_INET6; 775 key.t_src6 = ip6->ip6_dst; 776 key.t_dst6 = ip6->ip6_src; 777 778 flow = bemtoh32(&ip6->ip6_flow); 779 780 return (etherip_input(&key, m, flow >> 20, *offp)); 781 } 782 #endif /* INET6 */ 783 784 int 785 etherip_sysctl_etheripstat(void *oldp, size_t *oldlenp, void *newp) 786 { 787 struct etheripstat etheripstat; 788 789 CTASSERT(sizeof(etheripstat) == (etherips_ncounters * 790 sizeof(uint64_t))); 791 memset(ðeripstat, 0, sizeof etheripstat); 792 counters_read(etheripcounters, (uint64_t *)ðeripstat, 793 etherips_ncounters, NULL); 794 return (sysctl_rdstruct(oldp, oldlenp, newp, ðeripstat, 795 sizeof(etheripstat))); 796 } 797 798 int 799 etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 800 void *newp, size_t newlen) 801 { 802 int error; 803 804 /* All sysctl names at this level are terminal. */ 805 if (namelen != 1) 806 return ENOTDIR; 807 808 switch (name[0]) { 809 case ETHERIPCTL_ALLOW: 810 NET_LOCK(); 811 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen, 812 ðerip_allow, 0, 1); 813 NET_UNLOCK(); 814 return (error); 815 case ETHERIPCTL_STATS: 816 return (etherip_sysctl_etheripstat(oldp, oldlenp, newp)); 817 default: 818 break; 819 } 820 821 return ENOPROTOOPT; 822 } 823 824 static inline int 825 etherip_ip_cmp(int af, const union etherip_addr *a, const union etherip_addr *b) 826 { 827 switch (af) { 828 #ifdef INET6 829 case AF_INET6: 830 return (memcmp(&a->in6, &b->in6, sizeof(a->in6))); 831 /* FALLTHROUGH */ 832 #endif /* INET6 */ 833 case AF_INET: 834 return (memcmp(&a->in4, &b->in4, sizeof(a->in4))); 835 break; 836 default: 837 panic("%s: unsupported af %d", __func__, af); 838 } 839 840 return (0); 841 } 842 843 static inline int 844 etherip_cmp(const struct etherip_tunnel *a, const struct etherip_tunnel *b) 845 { 846 int rv; 847 848 if (a->t_rtableid > b->t_rtableid) 849 return (1); 850 if (a->t_rtableid < b->t_rtableid) 851 return (-1); 852 853 /* sort by address */ 854 if (a->t_af > b->t_af) 855 return (1); 856 if (a->t_af < b->t_af) 857 return (-1); 858 859 rv = etherip_ip_cmp(a->t_af, &a->_t_dst, &b->_t_dst); 860 if (rv != 0) 861 return (rv); 862 863 rv = etherip_ip_cmp(a->t_af, &a->_t_src, &b->_t_src); 864 if (rv != 0) 865 return (rv); 866 867 return (0); 868 } 869