1 /* $OpenBSD: if_etherip.c,v 1.14 2017/01/29 19:58:47 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 #include "gif.h" 21 22 #include <sys/param.h> 23 #include <sys/systm.h> 24 #include <sys/mbuf.h> 25 #include <sys/socket.h> 26 #include <sys/ioctl.h> 27 #include <sys/device.h> 28 #include <sys/sysctl.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 35 #include <netinet/in.h> 36 #include <netinet/ip.h> 37 #include <netinet/ip_var.h> 38 #include <netinet/if_ether.h> 39 #include <netinet/ip_ether.h> 40 41 #ifdef INET6 42 #include <netinet/ip6.h> 43 #include <netinet6/ip6_var.h> 44 #endif 45 46 #if NBPFILTER > 0 47 #include <net/bpf.h> 48 #endif 49 50 #if NPF > 0 51 #include <net/pfvar.h> 52 #endif 53 54 #include <net/if_etherip.h> 55 56 struct etherip_softc { 57 struct arpcom sc_ac; 58 struct ifmedia sc_media; 59 unsigned int sc_rdomain; 60 struct sockaddr_storage sc_src; 61 struct sockaddr_storage sc_dst; 62 LIST_ENTRY(etherip_softc) sc_entry; 63 }; 64 65 LIST_HEAD(, etherip_softc) etherip_softc_list; 66 67 #if 0 68 /* 69 * TODO: 70 * At this stage, etherip_allow and etheripstat are defined 71 * at netinet/ip_ether.c. When implementation of etherip is 72 * removed from gif(4), there are moved here. 73 */ 74 75 /* 76 * We can control the acceptance of EtherIP packets by altering the sysctl 77 * net.inet.etherip.allow value. Zero means drop them, all else is acceptance. 78 */ 79 int etherip_allow = 0; 80 81 struct etheripstat etheripstat; 82 #endif 83 84 void etheripattach(int); 85 int etherip_clone_create(struct if_clone *, int); 86 int etherip_clone_destroy(struct ifnet *); 87 int etherip_ioctl(struct ifnet *, u_long, caddr_t); 88 void etherip_start(struct ifnet *); 89 int etherip_media_change(struct ifnet *); 90 void etherip_media_status(struct ifnet *, struct ifmediareq *); 91 int etherip_set_tunnel_addr(struct ifnet *, struct sockaddr_storage *, 92 struct sockaddr_storage *); 93 94 struct if_clone etherip_cloner = IF_CLONE_INITIALIZER("etherip", 95 etherip_clone_create, etherip_clone_destroy); 96 97 98 void 99 etheripattach(int count) 100 { 101 if_clone_attach(ðerip_cloner); 102 } 103 104 int 105 etherip_clone_create(struct if_clone *ifc, int unit) 106 { 107 struct ifnet *ifp; 108 struct etherip_softc *sc; 109 110 if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) 111 return ENOMEM; 112 113 ifp = &sc->sc_ac.ac_if; 114 snprintf(ifp->if_xname, sizeof ifp->if_xname, "etherip%d", unit); 115 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 116 ether_fakeaddr(ifp); 117 118 ifp->if_softc = sc; 119 ifp->if_ioctl = etherip_ioctl; 120 ifp->if_start = etherip_start; 121 ifp->if_xflags = IFXF_CLONED; 122 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 123 124 ifp->if_capabilities = IFCAP_VLAN_MTU; 125 126 ifmedia_init(&sc->sc_media, 0, etherip_media_change, 127 etherip_media_status); 128 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 129 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 130 131 if_attach(ifp); 132 ether_ifattach(ifp); 133 134 LIST_INSERT_HEAD(ðerip_softc_list, sc, sc_entry); 135 136 return 0; 137 } 138 139 int 140 etherip_clone_destroy(struct ifnet *ifp) 141 { 142 struct etherip_softc *sc = ifp->if_softc; 143 144 LIST_REMOVE(sc, sc_entry); 145 146 ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY); 147 ether_ifdetach(ifp); 148 if_detach(ifp); 149 free(sc, M_DEVBUF, sizeof(*sc)); 150 151 return 0; 152 } 153 154 int 155 etherip_media_change(struct ifnet *ifp) 156 { 157 return 0; 158 } 159 160 void 161 etherip_media_status(struct ifnet *ifp, struct ifmediareq *imr) 162 { 163 imr->ifm_active = IFM_ETHER | IFM_AUTO; 164 imr->ifm_status = IFM_AVALID | IFM_ACTIVE; 165 } 166 167 void 168 etherip_start(struct ifnet *ifp) 169 { 170 struct etherip_softc *sc = ifp->if_softc; 171 struct mbuf *m; 172 int error; 173 174 for (;;) { 175 IFQ_DEQUEUE(&ifp->if_snd, m); 176 if (m == NULL) 177 break; 178 179 #if NBPFILTER > 0 180 if (ifp->if_bpf) 181 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); 182 #endif 183 if (sc->sc_src.ss_family == AF_UNSPEC || 184 sc->sc_dst.ss_family == AF_UNSPEC) { 185 m_freem(m); 186 continue; 187 } 188 189 switch (sc->sc_src.ss_family) { 190 case AF_INET: 191 error = ip_etherip_output(ifp, m); 192 break; 193 #ifdef INET6 194 case AF_INET6: 195 error = ip6_etherip_output(ifp, m); 196 break; 197 #endif 198 default: 199 unhandled_af(sc->sc_src.ss_family); 200 } 201 202 if (error) 203 ifp->if_oerrors++; 204 } 205 206 } 207 208 209 int 210 etherip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 211 { 212 struct etherip_softc *sc = ifp->if_softc; 213 struct if_laddrreq *lifr = (struct if_laddrreq *)data; 214 struct ifreq *ifr = (struct ifreq *)data; 215 struct sockaddr_storage *src, *dst; 216 struct proc *p = curproc; 217 int error = 0; 218 219 switch (cmd) { 220 case SIOCSIFADDR: 221 ifp->if_flags |= IFF_UP; 222 /* FALLTHROUGH */ 223 224 case SIOCSIFFLAGS: 225 if (ifp->if_flags & IFF_UP) 226 ifp->if_flags |= IFF_RUNNING; 227 else 228 ifp->if_flags &= ~IFF_RUNNING; 229 230 break; 231 232 case SIOCSLIFPHYRTABLE: 233 if ((error = suser(p, 0)) != 0) 234 break; 235 236 if (ifr->ifr_rdomainid < 0 || 237 ifr->ifr_rdomainid > RT_TABLEID_MAX || 238 !rtable_exists(ifr->ifr_rdomainid)) { 239 error = EINVAL; 240 break; 241 } 242 sc->sc_rdomain = ifr->ifr_rdomainid; 243 break; 244 245 case SIOCGLIFPHYRTABLE: 246 ifr->ifr_rdomainid = sc->sc_rdomain; 247 break; 248 249 case SIOCSLIFPHYADDR: 250 if ((error = suser(p, 0)) != 0) 251 break; 252 253 src = &lifr->addr; 254 dst = &lifr->dstaddr; 255 if (src->ss_family == AF_UNSPEC || dst->ss_family == AF_UNSPEC) 256 return EADDRNOTAVAIL; 257 258 switch (src->ss_family) { 259 case AF_INET: 260 if (src->ss_len != sizeof(struct sockaddr_in) || 261 dst->ss_len != sizeof(struct sockaddr_in)) 262 return EINVAL; 263 break; 264 #ifdef INET6 265 case AF_INET6: 266 if (src->ss_len != sizeof(struct sockaddr_in6) || 267 dst->ss_len != sizeof(struct sockaddr_in6)) 268 return EINVAL; 269 break; 270 #endif 271 default: 272 return EAFNOSUPPORT; 273 } 274 275 error = etherip_set_tunnel_addr(ifp, src, dst); 276 break; 277 278 case SIOCDIFPHYADDR: 279 if ((error = suser(p, 0)) != 0) 280 break; 281 282 ifp->if_flags &= ~IFF_RUNNING; 283 memset(&sc->sc_src, 0, sizeof(sc->sc_src)); 284 memset(&sc->sc_dst, 0, sizeof(sc->sc_dst)); 285 break; 286 287 case SIOCGLIFPHYADDR: 288 if (sc->sc_dst.ss_family == AF_UNSPEC) 289 return EADDRNOTAVAIL; 290 291 memset(&lifr->addr, 0, sizeof(lifr->addr)); 292 memset(&lifr->dstaddr, 0, sizeof(lifr->dstaddr)); 293 memcpy(&lifr->addr, &sc->sc_src, sc->sc_src.ss_len); 294 memcpy(&lifr->dstaddr, &sc->sc_dst, sc->sc_dst.ss_len); 295 296 break; 297 298 case SIOCSIFMEDIA: 299 case SIOCGIFMEDIA: 300 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 301 break; 302 303 default: 304 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 305 break; 306 } 307 308 return error; 309 } 310 311 int 312 etherip_set_tunnel_addr(struct ifnet *ifp, struct sockaddr_storage *src, 313 struct sockaddr_storage *dst) 314 { 315 struct etherip_softc *sc, *tsc; 316 int error = 0; 317 318 sc = ifp->if_softc; 319 320 LIST_FOREACH(tsc, ðerip_softc_list, sc_entry) { 321 if (tsc == sc) 322 continue; 323 324 if (tsc->sc_src.ss_family != src->ss_family || 325 tsc->sc_dst.ss_family != dst->ss_family || 326 tsc->sc_src.ss_len != src->ss_len || 327 tsc->sc_dst.ss_len != dst->ss_len) 328 continue; 329 330 if (tsc->sc_rdomain == sc->sc_rdomain && 331 memcmp(&tsc->sc_dst, dst, dst->ss_len) == 0 && 332 memcmp(&tsc->sc_src, src, src->ss_len) == 0) { 333 error = EADDRNOTAVAIL; 334 goto out; 335 } 336 } 337 338 memcpy(&sc->sc_src, src, src->ss_len); 339 memcpy(&sc->sc_dst, dst, dst->ss_len); 340 out: 341 return error; 342 } 343 344 int 345 ip_etherip_output(struct ifnet *ifp, struct mbuf *m) 346 { 347 struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc; 348 struct sockaddr_in *src, *dst; 349 struct etherip_header *eip; 350 struct ip *ip; 351 352 src = (struct sockaddr_in *)&sc->sc_src; 353 dst = (struct sockaddr_in *)&sc->sc_dst; 354 355 if (src == NULL || dst == NULL || 356 src->sin_family != AF_INET || dst->sin_family != AF_INET) { 357 m_freem(m); 358 return EAFNOSUPPORT; 359 } 360 if (dst->sin_addr.s_addr == INADDR_ANY) { 361 m_freem(m); 362 return ENETUNREACH; 363 } 364 365 m->m_flags &= ~(M_BCAST|M_MCAST); 366 367 M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT); 368 if (m == NULL) { 369 etheripstat.etherip_adrops++; 370 return ENOBUFS; 371 } 372 eip = mtod(m, struct etherip_header *); 373 eip->eip_ver = ETHERIP_VERSION; 374 eip->eip_res = 0; 375 eip->eip_pad = 0; 376 377 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); 378 if (m == NULL) { 379 etheripstat.etherip_adrops++; 380 return ENOBUFS; 381 } 382 ip = mtod(m, struct ip *); 383 memset(ip, 0, sizeof(struct ip)); 384 385 ip->ip_v = IPVERSION; 386 ip->ip_hl = sizeof(struct ip) >> 2; 387 ip->ip_id = htons(ip_randomid()); 388 ip->ip_tos = IPTOS_LOWDELAY; 389 ip->ip_p = IPPROTO_ETHERIP; 390 ip->ip_len = htons(m->m_pkthdr.len); 391 ip->ip_ttl = IPDEFTTL; 392 ip->ip_src = src->sin_addr; 393 ip->ip_dst = dst->sin_addr; 394 395 m->m_pkthdr.ph_rtableid = sc->sc_rdomain; 396 397 #if NPF > 0 398 pf_pkt_addr_changed(m); 399 #endif 400 etheripstat.etherip_opackets++; 401 etheripstat.etherip_obytes += (m->m_pkthdr.len - 402 (sizeof(struct ip) + sizeof(struct etherip_header))); 403 404 return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0); 405 } 406 407 int 408 ip_etherip_input(struct mbuf **mp, int *offp, int proto) 409 { 410 struct mbuf *m = *mp; 411 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 412 struct etherip_softc *sc; 413 const struct ip *ip; 414 struct etherip_header *eip; 415 struct sockaddr_in *src, *dst; 416 struct ifnet *ifp = NULL; 417 418 ip = mtod(m, struct ip *); 419 420 if (ip->ip_p != IPPROTO_ETHERIP) { 421 m_freem(m); 422 ipstat_inc(ips_noproto); 423 return IPPROTO_DONE; 424 } 425 426 if (!etherip_allow) { 427 m_freem(m); 428 etheripstat.etherip_pdrops++; 429 return IPPROTO_DONE; 430 } 431 432 LIST_FOREACH(sc, ðerip_softc_list, sc_entry) { 433 if (sc->sc_src.ss_family != AF_INET || 434 sc->sc_dst.ss_family != AF_INET) 435 continue; 436 437 src = (struct sockaddr_in *)&sc->sc_src; 438 dst = (struct sockaddr_in *)&sc->sc_dst; 439 440 if (sc->sc_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid) || 441 src->sin_addr.s_addr != ip->ip_dst.s_addr || 442 dst->sin_addr.s_addr != ip->ip_src.s_addr) 443 continue; 444 445 ifp = &sc->sc_ac.ac_if; 446 break; 447 } 448 449 if (ifp == NULL) { 450 #if NGIF > 0 451 /* 452 * This path is nessesary for gif(4) and etherip(4) coexistence. 453 * This is tricky but the path will be removed soon when 454 * implementation of etherip is removed from gif(4). 455 */ 456 return etherip_input(mp, offp, proto); 457 #else 458 etheripstat.etherip_noifdrops++; 459 m_freem(m); 460 return IPPROTO_DONE; 461 #endif /* NGIF */ 462 } 463 464 m_adj(m, *offp); 465 m = m_pullup(m, sizeof(struct etherip_header)); 466 if (m == NULL) { 467 etheripstat.etherip_adrops++; 468 return IPPROTO_DONE; 469 } 470 471 eip = mtod(m, struct etherip_header *); 472 if (eip->eip_ver != ETHERIP_VERSION || eip->eip_pad) { 473 etheripstat.etherip_adrops++; 474 m_freem(m); 475 return IPPROTO_DONE; 476 } 477 478 etheripstat.etherip_ipackets++; 479 etheripstat.etherip_ibytes += (m->m_pkthdr.len - 480 sizeof(struct etherip_header)); 481 482 m_adj(m, sizeof(struct etherip_header)); 483 m = m_pullup(m, sizeof(struct ether_header)); 484 if (m == NULL) { 485 etheripstat.etherip_adrops++; 486 return IPPROTO_DONE; 487 } 488 m->m_flags &= ~(M_BCAST|M_MCAST); 489 490 #if NPF > 0 491 pf_pkt_addr_changed(m); 492 #endif 493 494 ml_enqueue(&ml, m); 495 if_input(ifp, &ml); 496 return IPPROTO_DONE; 497 } 498 499 #ifdef INET6 500 int 501 ip6_etherip_output(struct ifnet *ifp, struct mbuf *m) 502 { 503 struct etherip_softc *sc = (struct etherip_softc *)ifp->if_softc; 504 struct sockaddr_in6 *src, *dst; 505 struct etherip_header *eip; 506 struct ip6_hdr *ip6; 507 int error; 508 509 src = (struct sockaddr_in6 *)&sc->sc_src; 510 dst = (struct sockaddr_in6 *)&sc->sc_dst; 511 512 if (src == NULL || dst == NULL || 513 src->sin6_family != AF_INET6 || dst->sin6_family != AF_INET6) { 514 error = EAFNOSUPPORT; 515 goto drop; 516 } 517 if (IN6_IS_ADDR_UNSPECIFIED(&dst->sin6_addr)) { 518 error = ENETUNREACH; 519 goto drop; 520 } 521 522 m->m_flags &= ~(M_BCAST|M_MCAST); 523 524 M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT); 525 if (m == NULL) { 526 etheripstat.etherip_adrops++; 527 return ENOBUFS; 528 } 529 eip = mtod(m, struct etherip_header *); 530 eip->eip_ver = ETHERIP_VERSION; 531 eip->eip_res = 0; 532 eip->eip_pad = 0; 533 534 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); 535 if (m == NULL) { 536 etheripstat.etherip_adrops++; 537 return ENOBUFS; 538 } 539 ip6 = mtod(m, struct ip6_hdr *); 540 ip6->ip6_flow = 0; 541 ip6->ip6_vfc &= ~IPV6_VERSION_MASK; 542 ip6->ip6_vfc |= IPV6_VERSION; 543 ip6->ip6_nxt = IPPROTO_ETHERIP; 544 ip6->ip6_hlim = ip6_defhlim; 545 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr)); 546 error = in6_embedscope(&ip6->ip6_src, src, NULL); 547 if (error != 0) 548 goto drop; 549 error = in6_embedscope(&ip6->ip6_dst, dst, NULL); 550 if (error != 0) 551 goto drop; 552 553 m->m_pkthdr.ph_rtableid = sc->sc_rdomain; 554 555 #if NPF > 0 556 pf_pkt_addr_changed(m); 557 #endif 558 etheripstat.etherip_opackets++; 559 etheripstat.etherip_obytes += (m->m_pkthdr.len - 560 (sizeof(struct ip6_hdr) + sizeof(struct etherip_header))); 561 562 return ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL); 563 564 drop: 565 m_freem(m); 566 return (error); 567 } 568 569 int 570 ip6_etherip_input(struct mbuf **mp, int *offp, int proto) 571 { 572 struct mbuf *m = *mp; 573 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 574 struct etherip_softc *sc; 575 const struct ip6_hdr *ip6; 576 struct etherip_header *eip; 577 struct sockaddr_in6 ipsrc, ipdst; 578 struct sockaddr_in6 *src6, *dst6; 579 struct ifnet *ifp = NULL; 580 581 582 if (!etherip_allow) { 583 m_freem(m); 584 etheripstat.etherip_pdrops++; 585 return IPPROTO_NONE; 586 } 587 588 ip6 = mtod(m, const struct ip6_hdr *); 589 in6_recoverscope(&ipsrc, &ip6->ip6_src); 590 in6_recoverscope(&ipdst, &ip6->ip6_dst); 591 592 LIST_FOREACH(sc, ðerip_softc_list, sc_entry) { 593 if (sc->sc_src.ss_family != AF_INET6 || 594 sc->sc_dst.ss_family != AF_INET6) 595 continue; 596 597 src6 = (struct sockaddr_in6 *)&sc->sc_src; 598 dst6 = (struct sockaddr_in6 *)&sc->sc_dst; 599 600 if (IN6_ARE_ADDR_EQUAL(&src6->sin6_addr, &ipdst.sin6_addr) && 601 src6->sin6_scope_id == ipdst.sin6_scope_id && 602 IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr, &ipsrc.sin6_addr) && 603 dst6->sin6_scope_id == ipsrc.sin6_scope_id) { 604 ifp = &sc->sc_ac.ac_if; 605 break; 606 } 607 } 608 609 if (ifp == NULL) { 610 #if NGIF > 0 611 /* 612 * This path is nessesary for gif(4) and etherip(4) coexistence. 613 * This is tricky but the path will be removed soon when 614 * implementation of etherip is removed from gif(4). 615 */ 616 return etherip_input(mp, offp, proto); 617 #else 618 etheripstat.etherip_noifdrops++; 619 m_freem(m); 620 return IPPROTO_DONE; 621 #endif /* NGIF */ 622 } 623 624 m_adj(m, *offp); 625 m = m_pullup(m, sizeof(struct etherip_header)); 626 if (m == NULL) { 627 etheripstat.etherip_adrops++; 628 return IPPROTO_DONE; 629 } 630 631 eip = mtod(m, struct etherip_header *); 632 if ((eip->eip_ver != ETHERIP_VERSION) || eip->eip_pad) { 633 etheripstat.etherip_adrops++; 634 m_freem(m); 635 return IPPROTO_DONE; 636 } 637 etheripstat.etherip_ipackets++; 638 etheripstat.etherip_ibytes += (m->m_pkthdr.len - 639 sizeof(struct etherip_header)); 640 641 m_adj(m, sizeof(struct etherip_header)); 642 m = m_pullup(m, sizeof(struct ether_header)); 643 if (m == NULL) { 644 etheripstat.etherip_adrops++; 645 return IPPROTO_DONE; 646 } 647 648 m->m_flags &= ~(M_BCAST|M_MCAST); 649 650 #if NPF > 0 651 pf_pkt_addr_changed(m); 652 #endif 653 654 ml_enqueue(&ml, m); 655 if_input(ifp, &ml); 656 return IPPROTO_DONE; 657 } 658 #endif /* INET6 */ 659 660 int 661 ip_etherip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, 662 void *newp, size_t newlen) 663 { 664 /* All sysctl names at this level are terminal. */ 665 if (namelen != 1) 666 return ENOTDIR; 667 668 switch (name[0]) { 669 case ETHERIPCTL_ALLOW: 670 return sysctl_int(oldp, oldlenp, newp, newlen, ðerip_allow); 671 case ETHERIPCTL_STATS: 672 if (newp != NULL) 673 return EPERM; 674 return sysctl_struct(oldp, oldlenp, newp, newlen, 675 ðeripstat, sizeof(etheripstat)); 676 default: 677 break; 678 } 679 680 return ENOPROTOOPT; 681 } 682