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