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