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