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