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