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