1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * BSD interface driver for dhcpcd 4 * Copyright (c) 2006-2019 Roy Marples <roy@marples.name> 5 * All rights reserved 6 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/ioctl.h> 30 #include <sys/param.h> 31 #include <sys/socket.h> 32 #include <sys/stat.h> 33 #include <sys/sysctl.h> 34 #include <sys/time.h> 35 #include <sys/types.h> 36 #include <sys/uio.h> 37 #include <sys/utsname.h> 38 39 #include "config.h" 40 41 #include <arpa/inet.h> 42 #include <net/bpf.h> 43 #include <net/if.h> 44 #include <net/if_dl.h> 45 #include <net/if_media.h> 46 #include <net/route.h> 47 #include <netinet/if_ether.h> 48 #include <netinet/in.h> 49 #include <netinet/in_var.h> 50 #include <netinet6/in6_var.h> 51 #include <netinet6/nd6.h> 52 #ifdef __NetBSD__ 53 #include <net/if_vlanvar.h> /* Needs netinet/if_ether.h */ 54 #elif defined(__DragonFly__) 55 #include <net/vlan/if_vlan_var.h> 56 #else 57 #include <net/if_vlan_var.h> 58 #endif 59 #ifdef __DragonFly__ 60 # include <netproto/802_11/ieee80211_ioctl.h> 61 #elif __APPLE__ 62 /* FIXME: Add apple includes so we can work out SSID */ 63 #else 64 # include <net80211/ieee80211.h> 65 # include <net80211/ieee80211_ioctl.h> 66 #endif 67 68 #include <assert.h> 69 #include <errno.h> 70 #include <fcntl.h> 71 #include <fnmatch.h> 72 #include <paths.h> 73 #include <stddef.h> 74 #include <stdio.h> 75 #include <stdlib.h> 76 #include <string.h> 77 #include <unistd.h> 78 79 #if defined(OpenBSD) && OpenBSD >= 201411 80 /* OpenBSD dropped the global setting from sysctl but left the #define 81 * which causes a EPERM error when trying to use it. 82 * I think both the error and keeping the define are wrong, so we #undef it. */ 83 #undef IPV6CTL_ACCEPT_RTADV 84 #endif 85 86 #include "common.h" 87 #include "dhcp.h" 88 #include "if.h" 89 #include "if-options.h" 90 #include "ipv4.h" 91 #include "ipv4ll.h" 92 #include "ipv6.h" 93 #include "ipv6nd.h" 94 #include "logerr.h" 95 #include "route.h" 96 #include "sa.h" 97 98 #ifndef RT_ROUNDUP 99 #define RT_ROUNDUP(a) \ 100 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 101 #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len)) 102 #endif 103 104 /* Ignore these interface names which look like ethernet but are virtual. */ 105 static const char * const ifnames_ignore[] = { 106 "bridge", 107 "fwe", /* Firewire */ 108 "tap", 109 NULL 110 }; 111 112 #ifdef INET6 113 static void ifa_setscope(struct sockaddr_in6 *, unsigned int); 114 static unsigned int ifa_getscope(const struct sockaddr_in6 *); 115 #endif 116 117 struct priv { 118 int pf_inet6_fd; 119 }; 120 121 struct rtm 122 { 123 struct rt_msghdr hdr; 124 char buffer[sizeof(struct sockaddr_storage) * RTAX_MAX]; 125 }; 126 127 int 128 if_init(__unused struct interface *iface) 129 { 130 /* BSD promotes secondary address by default */ 131 return 0; 132 } 133 134 int 135 if_conf(__unused struct interface *iface) 136 { 137 /* No extra checks needed on BSD */ 138 return 0; 139 } 140 141 int 142 if_opensockets_os(struct dhcpcd_ctx *ctx) 143 { 144 struct priv *priv; 145 int n; 146 #if defined(RO_MSGFILTER) || defined(ROUTE_MSGFILTER) 147 unsigned char msgfilter[] = { 148 RTM_IFINFO, 149 #ifdef RTM_IFANNOUNCE 150 RTM_IFANNOUNCE, 151 #endif 152 RTM_ADD, RTM_CHANGE, RTM_DELETE, RTM_MISS, 153 #ifdef RTM_CHGADDR 154 RTM_CHGADDR, 155 #endif 156 RTM_NEWADDR, RTM_DELADDR 157 }; 158 #ifdef ROUTE_MSGFILTER 159 unsigned int i, msgfilter_mask; 160 #endif 161 #endif 162 163 if ((priv = malloc(sizeof(*priv))) == NULL) 164 return -1; 165 ctx->priv = priv; 166 167 #ifdef INET6 168 priv->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); 169 /* Don't return an error so we at least work on kernels witout INET6 170 * even though we expect INET6 support. 171 * We will fail noisily elsewhere anyway. */ 172 #else 173 priv->pf_inet6_fd = -1; 174 #endif 175 176 #define SOCK_FLAGS (SOCK_CLOEXEC | SOCK_NONBLOCK) 177 ctx->link_fd = xsocket(PF_ROUTE, SOCK_RAW | SOCK_FLAGS, AF_UNSPEC); 178 #undef SOCK_FLAGS 179 if (ctx->link_fd == -1) 180 return -1; 181 182 /* Ignore our own route(4) messages. 183 * Sadly there is no way of doing this for route(4) messages 184 * generated from addresses we add/delete. */ 185 n = 0; 186 if (setsockopt(ctx->link_fd, SOL_SOCKET, SO_USELOOPBACK, 187 &n, sizeof(n)) == -1) 188 logerr("%s: SO_USELOOPBACK", __func__); 189 190 #if defined(RO_MSGFILTER) 191 if (setsockopt(ctx->link_fd, PF_ROUTE, RO_MSGFILTER, 192 &msgfilter, sizeof(msgfilter)) == -1) 193 logerr(__func__); 194 #elif defined(ROUTE_MSGFILTER) 195 /* Convert the array into a bitmask. */ 196 msgfilter_mask = 0; 197 for (i = 0; i < __arraycount(msgfilter); i++) 198 msgfilter_mask |= ROUTE_FILTER(msgfilter[i]); 199 if (setsockopt(ctx->link_fd, PF_ROUTE, ROUTE_MSGFILTER, 200 &msgfilter_mask, sizeof(msgfilter_mask)) == -1) 201 logerr(__func__); 202 #else 203 #warning kernel does not support route message filtering 204 #endif 205 206 return 0; 207 } 208 209 void 210 if_closesockets_os(struct dhcpcd_ctx *ctx) 211 { 212 struct priv *priv; 213 214 priv = (struct priv *)ctx->priv; 215 if (priv->pf_inet6_fd != -1) 216 close(priv->pf_inet6_fd); 217 } 218 219 static bool 220 if_ignore1(const char *drvname) 221 { 222 const char * const *p; 223 224 for (p = ifnames_ignore; *p; p++) { 225 if (strcmp(*p, drvname) == 0) 226 return true; 227 } 228 return false; 229 } 230 231 bool 232 if_ignore(struct dhcpcd_ctx *ctx, const char *ifname) 233 { 234 struct if_spec spec; 235 236 if (if_nametospec(ifname, &spec) != 0) 237 return false; 238 239 if (if_ignore1(spec.drvname)) 240 return true; 241 242 #ifdef SIOCGIFGROUP 243 struct ifgroupreq ifgr = { .ifgr_len = 0 }; 244 struct ifg_req *ifg; 245 size_t ifg_len; 246 247 /* Sadly it is possible to remove the device name 248 * from the interface groups, but hopefully this 249 * will be very unlikely.... */ 250 251 strlcpy(ifgr.ifgr_name, ifname, sizeof(ifgr.ifgr_name)); 252 if (ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1 || 253 (ifgr.ifgr_groups = malloc(ifgr.ifgr_len)) == NULL || 254 ioctl(ctx->pf_inet_fd, SIOCGIFGROUP, &ifgr) == -1) 255 { 256 logerr(__func__); 257 return false; 258 } 259 260 for (ifg = ifgr.ifgr_groups, ifg_len = ifgr.ifgr_len; 261 ifg && ifg_len >= sizeof(*ifg); 262 ifg++, ifg_len -= sizeof(*ifg)) 263 { 264 if (if_ignore1(ifg->ifgrq_group)) 265 return true; 266 } 267 #else 268 UNUSED(ctx); 269 #endif 270 271 return false; 272 } 273 274 int 275 if_carrier(struct interface *ifp) 276 { 277 struct ifmediareq ifmr = { .ifm_status = 0 }; 278 279 strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name)); 280 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) == -1 || 281 !(ifmr.ifm_status & IFM_AVALID)) 282 return LINK_UNKNOWN; 283 284 return (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN; 285 } 286 287 static void 288 if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp) 289 { 290 291 memset(sdl, 0, sizeof(*sdl)); 292 sdl->sdl_family = AF_LINK; 293 sdl->sdl_len = sizeof(*sdl); 294 sdl->sdl_nlen = sdl->sdl_alen = sdl->sdl_slen = 0; 295 sdl->sdl_index = (unsigned short)ifp->index; 296 } 297 298 #if defined(SIOCG80211NWID) || defined(SIOCGETVLAN) 299 static int if_direct_ioctl(int s, const char *ifname, 300 unsigned long cmd, void *data) 301 { 302 303 strlcpy(data, ifname, IFNAMSIZ); 304 return ioctl(s, cmd, data); 305 } 306 307 static int if_indirect_ioctl(int s, const char *ifname, 308 unsigned long cmd, void *data) 309 { 310 struct ifreq ifr; 311 312 memset(&ifr, 0, sizeof(ifr)); 313 ifr.ifr_data = data; 314 return if_direct_ioctl(s, ifname, cmd, &ifr); 315 } 316 #endif 317 318 static int 319 if_getssid1(int s, const char *ifname, void *ssid) 320 { 321 int retval = -1; 322 #if defined(SIOCG80211NWID) 323 struct ieee80211_nwid nwid; 324 #elif defined(IEEE80211_IOC_SSID) 325 struct ieee80211req ireq; 326 char nwid[IEEE80211_NWID_LEN]; 327 #endif 328 329 #if defined(SIOCG80211NWID) /* NetBSD */ 330 memset(&nwid, 0, sizeof(nwid)); 331 if (if_indirect_ioctl(s, ifname, SIOCG80211NWID, &nwid) == 0) { 332 if (ssid == NULL) 333 retval = nwid.i_len; 334 else if (nwid.i_len > IF_SSIDLEN) 335 errno = ENOBUFS; 336 else { 337 retval = nwid.i_len; 338 memcpy(ssid, nwid.i_nwid, nwid.i_len); 339 } 340 } 341 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */ 342 memset(&ireq, 0, sizeof(ireq)); 343 strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); 344 ireq.i_type = IEEE80211_IOC_SSID; 345 ireq.i_val = -1; 346 memset(nwid, 0, sizeof(nwid)); 347 ireq.i_data = &nwid; 348 if (ioctl(s, SIOCG80211, &ireq) == 0) { 349 if (ssid == NULL) 350 retval = ireq.i_len; 351 else if (ireq.i_len > IF_SSIDLEN) 352 errno = ENOBUFS; 353 else { 354 retval = ireq.i_len; 355 memcpy(ssid, nwid, ireq.i_len); 356 } 357 } 358 #else 359 errno = ENOSYS; 360 #endif 361 362 return retval; 363 } 364 365 int 366 if_getssid(struct interface *ifp) 367 { 368 int r; 369 370 r = if_getssid1(ifp->ctx->pf_inet_fd, ifp->name, ifp->ssid); 371 if (r != -1) 372 ifp->ssid_len = (unsigned int)r; 373 else 374 ifp->ssid_len = 0; 375 ifp->ssid[ifp->ssid_len] = '\0'; 376 return r; 377 } 378 379 /* 380 * FreeBSD allows for Virtual Access Points 381 * We need to check if the interface is a Virtual Interface Master 382 * and if so, don't use it. 383 * This check is made by virtue of being a IEEE80211 device but 384 * returning the SSID gives an error. 385 */ 386 int 387 if_vimaster(const struct dhcpcd_ctx *ctx, const char *ifname) 388 { 389 int r; 390 struct ifmediareq ifmr; 391 392 memset(&ifmr, 0, sizeof(ifmr)); 393 strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 394 r = ioctl(ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr); 395 if (r == -1) 396 return -1; 397 if (ifmr.ifm_status & IFM_AVALID && 398 IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) 399 { 400 if (if_getssid1(ctx->pf_inet_fd, ifname, NULL) == -1) 401 return 1; 402 } 403 return 0; 404 } 405 406 unsigned short 407 if_vlanid(const struct interface *ifp) 408 { 409 #ifdef SIOCGETVLAN 410 struct vlanreq vlr; 411 412 memset(&vlr, 0, sizeof(vlr)); 413 if (if_indirect_ioctl(ifp->ctx->pf_inet_fd, 414 ifp->name, SIOCGETVLAN, &vlr) != 0) 415 return 0; /* 0 means no VLANID */ 416 return vlr.vlr_tag; 417 #elif defined(SIOCGVNETID) 418 struct ifreq ifr; 419 420 memset(&ifr, 0, sizeof(ifr)); 421 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 422 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGVNETID, &ifr) != 0) 423 return 0; /* 0 means no VLANID */ 424 return ifr.ifr_vnetid; 425 #else 426 UNUSED(ifp); 427 return 0; /* 0 means no VLANID */ 428 #endif 429 } 430 431 static int 432 get_addrs(int type, const void *data, size_t data_len, 433 const struct sockaddr **sa) 434 { 435 const char *cp, *ep; 436 int i; 437 438 cp = data; 439 ep = cp + data_len; 440 for (i = 0; i < RTAX_MAX; i++) { 441 if (type & (1 << i)) { 442 if (cp >= ep) { 443 errno = EINVAL; 444 return -1; 445 } 446 sa[i] = (const struct sockaddr *)cp; 447 RT_ADVANCE(cp, sa[i]); 448 } else 449 sa[i] = NULL; 450 } 451 452 return 0; 453 } 454 455 static struct interface * 456 if_findsdl(struct dhcpcd_ctx *ctx, const struct sockaddr_dl *sdl) 457 { 458 459 if (sdl->sdl_index) 460 return if_findindex(ctx->ifaces, sdl->sdl_index); 461 462 if (sdl->sdl_nlen) { 463 char ifname[IF_NAMESIZE]; 464 465 memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen); 466 ifname[sdl->sdl_nlen] = '\0'; 467 return if_find(ctx->ifaces, ifname); 468 } 469 if (sdl->sdl_alen) { 470 struct interface *ifp; 471 472 TAILQ_FOREACH(ifp, ctx->ifaces, next) { 473 if (ifp->hwlen == sdl->sdl_alen && 474 memcmp(ifp->hwaddr, 475 sdl->sdl_data, sdl->sdl_alen) == 0) 476 return ifp; 477 } 478 } 479 480 errno = ENOENT; 481 return NULL; 482 } 483 484 static struct interface * 485 if_findsa(struct dhcpcd_ctx *ctx, const struct sockaddr *sa) 486 { 487 if (sa == NULL) { 488 errno = EINVAL; 489 return NULL; 490 } 491 492 switch (sa->sa_family) { 493 case AF_LINK: 494 { 495 const struct sockaddr_dl *sdl; 496 497 sdl = (const void *)sa; 498 return if_findsdl(ctx, sdl); 499 } 500 #ifdef INET 501 case AF_INET: 502 { 503 const struct sockaddr_in *sin; 504 struct ipv4_addr *ia; 505 506 sin = (const void *)sa; 507 if ((ia = ipv4_findmaskaddr(ctx, &sin->sin_addr))) 508 return ia->iface; 509 break; 510 } 511 #endif 512 #ifdef INET6 513 case AF_INET6: 514 { 515 const struct sockaddr_in6 *sin; 516 unsigned int scope; 517 struct ipv6_addr *ia; 518 519 sin = (const void *)sa; 520 scope = ifa_getscope(sin); 521 if (scope != 0) 522 return if_findindex(ctx->ifaces, scope); 523 if ((ia = ipv6_findmaskaddr(ctx, &sin->sin6_addr))) 524 return ia->iface; 525 break; 526 } 527 #endif 528 default: 529 errno = EAFNOSUPPORT; 530 return NULL; 531 } 532 533 errno = ENOENT; 534 return NULL; 535 } 536 537 static void 538 if_copysa(struct sockaddr *dst, const struct sockaddr *src) 539 { 540 541 assert(dst != NULL); 542 assert(src != NULL); 543 544 memcpy(dst, src, src->sa_len); 545 #if defined(INET6) && defined(__KAME__) 546 if (dst->sa_family == AF_INET6) { 547 struct in6_addr *in6; 548 549 in6 = &satosin6(dst)->sin6_addr; 550 if (IN6_IS_ADDR_LINKLOCAL(in6)) 551 in6->s6_addr[2] = in6->s6_addr[3] = '\0'; 552 } 553 #endif 554 } 555 556 int 557 if_route(unsigned char cmd, const struct rt *rt) 558 { 559 struct dhcpcd_ctx *ctx; 560 struct rtm rtmsg; 561 struct rt_msghdr *rtm = &rtmsg.hdr; 562 char *bp = rtmsg.buffer; 563 struct sockaddr_dl sdl; 564 bool gateway_unspec; 565 566 assert(rt != NULL); 567 assert(rt->rt_ifp != NULL); 568 assert(rt->rt_ifp->ctx != NULL); 569 ctx = rt->rt_ifp->ctx; 570 571 #define ADDSA(sa) do { \ 572 memcpy(bp, (sa), (sa)->sa_len); \ 573 bp += RT_ROUNDUP((sa)->sa_len); \ 574 } while (0 /* CONSTCOND */) 575 576 memset(&rtmsg, 0, sizeof(rtmsg)); 577 rtm->rtm_version = RTM_VERSION; 578 rtm->rtm_type = cmd; 579 #ifdef __OpenBSD__ 580 rtm->rtm_pid = getpid(); 581 #endif 582 rtm->rtm_seq = ++ctx->seq; 583 rtm->rtm_flags = (int)rt->rt_flags; 584 rtm->rtm_addrs = RTA_DST; 585 #ifdef RTF_PINNED 586 if (cmd != RTM_ADD) 587 rtm->rtm_flags |= RTF_PINNED; 588 #endif 589 590 gateway_unspec = sa_is_unspecified(&rt->rt_gateway); 591 592 if (cmd == RTM_ADD || cmd == RTM_CHANGE) { 593 bool netmask_bcast = sa_is_allones(&rt->rt_netmask); 594 595 rtm->rtm_flags |= RTF_UP; 596 rtm->rtm_addrs |= RTA_GATEWAY; 597 if (!(rtm->rtm_flags & RTF_REJECT) && 598 !sa_is_loopback(&rt->rt_gateway)) 599 { 600 rtm->rtm_index = (unsigned short)rt->rt_ifp->index; 601 /* 602 * OpenBSD rejects the message for on-link routes. 603 * FreeBSD-12 kernel apparently panics. 604 * I can't replicate the panic, but better safe than sorry! 605 * https://roy.marples.name/archives/dhcpcd-discuss/0002286.html 606 * 607 * Neither OS currently allows IPv6 address sharing anyway, so let's 608 * try to encourage someone to fix that by logging a waring during compile. 609 */ 610 #if defined(__FreeBSD__) || defined(__OpenBSD__) 611 #warning kernel does not allow IPv6 address sharing 612 if (!gateway_unspec || rt->rt_dest.sa_family!=AF_INET6) 613 #endif 614 rtm->rtm_addrs |= RTA_IFP; 615 if (!sa_is_unspecified(&rt->rt_ifa)) 616 rtm->rtm_addrs |= RTA_IFA; 617 } 618 if (netmask_bcast) 619 rtm->rtm_flags |= RTF_HOST; 620 /* Network routes are cloning or connected if supported. 621 * All other routes are static. */ 622 if (gateway_unspec) { 623 #ifdef RTF_CLONING 624 rtm->rtm_flags |= RTF_CLONING; 625 #endif 626 #ifdef RTF_CONNECTED 627 rtm->rtm_flags |= RTF_CONNECTED; 628 #endif 629 #ifdef RTP_CONNECTED 630 rtm->rtm_priority = RTP_CONNECTED; 631 #endif 632 #ifdef RTF_CLONING 633 if (netmask_bcast) { 634 /* 635 * We add a cloning network route for a single 636 * host. Traffic to the host will generate a 637 * cloned route and the hardware address will 638 * resolve correctly. 639 * It might be more correct to use RTF_HOST 640 * instead of RTF_CLONING, and that does work, 641 * but some OS generate an arp warning 642 * diagnostic which we don't want to do. 643 */ 644 rtm->rtm_flags &= ~RTF_HOST; 645 } 646 #endif 647 } else 648 rtm->rtm_flags |= RTF_GATEWAY; 649 650 /* Emulate the kernel by marking address generated 651 * network routes non-static. */ 652 if (!(rt->rt_dflags & RTDF_IFA_ROUTE)) 653 rtm->rtm_flags |= RTF_STATIC; 654 655 if (rt->rt_mtu != 0) { 656 rtm->rtm_inits |= RTV_MTU; 657 rtm->rtm_rmx.rmx_mtu = rt->rt_mtu; 658 } 659 } 660 661 if (!(rtm->rtm_flags & RTF_HOST)) 662 rtm->rtm_addrs |= RTA_NETMASK; 663 664 if_linkaddr(&sdl, rt->rt_ifp); 665 666 ADDSA(&rt->rt_dest); 667 668 if (rtm->rtm_addrs & RTA_GATEWAY) { 669 if (gateway_unspec) 670 ADDSA((struct sockaddr *)&sdl); 671 else { 672 union sa_ss gateway; 673 674 if_copysa(&gateway.sa, &rt->rt_gateway); 675 #ifdef INET6 676 if (gateway.sa.sa_family == AF_INET6) 677 ifa_setscope(&gateway.sin6, rt->rt_ifp->index); 678 #endif 679 ADDSA(&gateway.sa); 680 } 681 } 682 683 if (rtm->rtm_addrs & RTA_NETMASK) 684 ADDSA(&rt->rt_netmask); 685 686 if (rtm->rtm_addrs & RTA_IFP) 687 ADDSA((struct sockaddr *)&sdl); 688 689 if (rtm->rtm_addrs & RTA_IFA) 690 ADDSA(&rt->rt_ifa); 691 692 #undef ADDSA 693 694 rtm->rtm_msglen = (unsigned short)(bp - (char *)rtm); 695 if (write(ctx->link_fd, rtm, rtm->rtm_msglen) == -1) 696 return -1; 697 return 0; 698 } 699 700 static int 701 if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, const struct rt_msghdr *rtm) 702 { 703 const struct sockaddr *rti_info[RTAX_MAX]; 704 705 if (!(rtm->rtm_addrs & RTA_DST)) { 706 errno = EINVAL; 707 return -1; 708 } 709 if (rtm->rtm_type != RTM_MISS && !(rtm->rtm_addrs & RTA_GATEWAY)) { 710 errno = EINVAL; 711 return -1; 712 } 713 #ifdef RTF_CLONED 714 if (rtm->rtm_flags & RTF_CLONED) { 715 errno = ENOTSUP; 716 return -1; 717 } 718 #endif 719 #ifdef RTF_WASCLONED 720 if (rtm->rtm_flags & RTF_WASCLONED) { 721 errno = ENOTSUP; 722 return -1; 723 } 724 #endif 725 #ifdef RTF_LOCAL 726 if (rtm->rtm_flags & RTF_LOCAL) { 727 errno = ENOTSUP; 728 return -1; 729 } 730 #endif 731 #ifdef RTF_BROADCAST 732 if (rtm->rtm_flags & RTF_BROADCAST) { 733 errno = ENOTSUP; 734 return -1; 735 } 736 #endif 737 738 if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm), 739 rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1) 740 return -1; 741 memset(rt, 0, sizeof(*rt)); 742 743 rt->rt_flags = (unsigned int)rtm->rtm_flags; 744 if_copysa(&rt->rt_dest, rti_info[RTAX_DST]); 745 if (rtm->rtm_addrs & RTA_NETMASK) { 746 if_copysa(&rt->rt_netmask, rti_info[RTAX_NETMASK]); 747 if (rt->rt_netmask.sa_family == 255) /* Why? */ 748 rt->rt_netmask.sa_family = rt->rt_dest.sa_family; 749 } 750 751 /* dhcpcd likes an unspecified gateway to indicate via the link. 752 * However we need to know if gateway was a link with an address. */ 753 if (rtm->rtm_addrs & RTA_GATEWAY) { 754 if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { 755 const struct sockaddr_dl *sdl; 756 757 sdl = (const struct sockaddr_dl*) 758 (const void *)rti_info[RTAX_GATEWAY]; 759 if (sdl->sdl_alen != 0) 760 rt->rt_dflags |= RTDF_GATELINK; 761 } else if (rtm->rtm_flags & RTF_GATEWAY) 762 if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]); 763 } 764 765 if (rtm->rtm_addrs & RTA_IFA) 766 if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]); 767 768 rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu; 769 770 if (rtm->rtm_index) 771 rt->rt_ifp = if_findindex(ctx->ifaces, rtm->rtm_index); 772 else if (rtm->rtm_addrs & RTA_IFP) 773 rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_IFP]); 774 else if (rtm->rtm_addrs & RTA_GATEWAY) 775 rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_GATEWAY]); 776 else 777 rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_DST]); 778 779 if (rt->rt_ifp == NULL && rtm->rtm_type == RTM_MISS) 780 rt->rt_ifp = if_find(ctx->ifaces, "lo0"); 781 782 if (rt->rt_ifp == NULL) { 783 errno = ESRCH; 784 return -1; 785 } 786 return 0; 787 } 788 789 int 790 if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af) 791 { 792 struct rt_msghdr *rtm; 793 int mib[6]; 794 size_t needed; 795 char *buf, *p, *end; 796 struct rt rt, *rtn; 797 798 mib[0] = CTL_NET; 799 mib[1] = PF_ROUTE; 800 mib[2] = 0; 801 mib[3] = af; 802 mib[4] = NET_RT_DUMP; 803 mib[5] = 0; 804 805 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 806 return -1; 807 if (needed == 0) 808 return 0; 809 if ((buf = malloc(needed)) == NULL) 810 return -1; 811 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) { 812 free(buf); 813 return -1; 814 } 815 816 end = buf + needed; 817 for (p = buf; p < end; p += rtm->rtm_msglen) { 818 rtm = (void *)p; 819 if (p + rtm->rtm_msglen >= end) { 820 errno = EINVAL; 821 break; 822 } 823 if (if_copyrt(ctx, &rt, rtm) != 0) 824 continue; 825 if ((rtn = rt_new(rt.rt_ifp)) == NULL) { 826 logerr(__func__); 827 break; 828 } 829 memcpy(rtn, &rt, sizeof(*rtn)); 830 if (rb_tree_insert_node(kroutes, rtn) != rtn) 831 rt_free(rtn); 832 } 833 free(buf); 834 return p == end ? 0 : -1; 835 } 836 837 #ifdef INET 838 int 839 if_address(unsigned char cmd, const struct ipv4_addr *ia) 840 { 841 int r; 842 struct in_aliasreq ifra; 843 844 memset(&ifra, 0, sizeof(ifra)); 845 strlcpy(ifra.ifra_name, ia->iface->name, sizeof(ifra.ifra_name)); 846 847 #define ADDADDR(var, addr) do { \ 848 (var)->sin_family = AF_INET; \ 849 (var)->sin_len = sizeof(*(var)); \ 850 (var)->sin_addr = *(addr); \ 851 } while (/*CONSTCOND*/0) 852 ADDADDR(&ifra.ifra_addr, &ia->addr); 853 ADDADDR(&ifra.ifra_mask, &ia->mask); 854 if (cmd == RTM_NEWADDR && ia->brd.s_addr != INADDR_ANY) 855 ADDADDR(&ifra.ifra_broadaddr, &ia->brd); 856 #undef ADDADDR 857 858 r = ioctl(ia->iface->ctx->pf_inet_fd, 859 cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra); 860 return r; 861 } 862 863 864 865 #if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS)) 866 int 867 if_addrflags(const struct interface *ifp, const struct in_addr *addr, 868 __unused const char *alias) 869 { 870 #ifdef SIOCGIFAFLAG_IN 871 struct ifreq ifr; 872 struct sockaddr_in *sin; 873 874 memset(&ifr, 0, sizeof(ifr)); 875 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 876 sin = (void *)&ifr.ifr_addr; 877 sin->sin_family = AF_INET; 878 sin->sin_addr = *addr; 879 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1) 880 return -1; 881 return ifr.ifr_addrflags; 882 #else 883 UNUSED(ifp); 884 UNUSED(addr); 885 return 0; 886 #endif 887 } 888 #endif 889 #endif /* INET */ 890 891 #ifdef INET6 892 static void 893 ifa_setscope(struct sockaddr_in6 *sin, unsigned int ifindex) 894 { 895 896 #ifdef __KAME__ 897 /* KAME based systems want to store the scope inside the sin6_addr 898 * for link local addresses */ 899 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { 900 uint16_t scope = htons((uint16_t)ifindex); 901 memcpy(&sin->sin6_addr.s6_addr[2], &scope, 902 sizeof(scope)); 903 } 904 sin->sin6_scope_id = 0; 905 #else 906 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) 907 sin->sin6_scope_id = ifindex; 908 else 909 sin->sin6_scope_id = 0; 910 #endif 911 } 912 913 static unsigned int 914 ifa_getscope(const struct sockaddr_in6 *sin) 915 { 916 #ifdef __KAME__ 917 uint16_t scope; 918 #endif 919 920 if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) 921 return 0; 922 #ifdef __KAME__ 923 memcpy(&scope, &sin->sin6_addr.s6_addr[2], sizeof(scope)); 924 return (unsigned int)ntohs(scope); 925 #else 926 return (unsigned int)sin->sin6_scope_id; 927 #endif 928 } 929 930 int 931 if_address6(unsigned char cmd, const struct ipv6_addr *ia) 932 { 933 struct in6_aliasreq ifa; 934 struct in6_addr mask; 935 struct priv *priv; 936 937 priv = (struct priv *)ia->iface->ctx->priv; 938 939 memset(&ifa, 0, sizeof(ifa)); 940 strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name)); 941 /* 942 * We should not set IN6_IFF_TENTATIVE as the kernel should be 943 * able to work out if it's a new address or not. 944 * 945 * We should set IN6_IFF_AUTOCONF, but the kernel won't let us. 946 * This is probably a safety measure, but still it's not entirely right 947 * either. 948 */ 949 #if 0 950 if (ia->autoconf) 951 ifa.ifra_flags |= IN6_IFF_AUTOCONF; 952 #endif 953 #if defined(__FreeBSD__) || defined(__DragonFly__) 954 if (ia->addr_flags & IN6_IFF_TENTATIVE) 955 ifa.ifra_flags |= IN6_IFF_TENTATIVE; 956 #endif 957 #ifdef IPV6_MANGETEMPADDR 958 if (ia->flags & IPV6_AF_TEMPORARY) 959 ifa.ifra_flags |= IN6_IFF_TEMPORARY; 960 #endif 961 962 #define ADDADDR(v, addr) { \ 963 (v)->sin6_family = AF_INET6; \ 964 (v)->sin6_len = sizeof(*v); \ 965 (v)->sin6_addr = *(addr); \ 966 } 967 968 ADDADDR(&ifa.ifra_addr, &ia->addr); 969 ifa_setscope(&ifa.ifra_addr, ia->iface->index); 970 ipv6_mask(&mask, ia->prefix_len); 971 ADDADDR(&ifa.ifra_prefixmask, &mask); 972 973 #undef ADDADDR 974 975 /* 976 * Every BSD kernel wants to add the prefix of the address to it's 977 * list of RA received prefixes. 978 * THIS IS WRONG because there (as the comments in the kernel state) 979 * is no API for managing prefix lifetime and the kernel should not 980 * pretend it's from a RA either. 981 * 982 * The issue is that the very first assigned prefix will inherit the 983 * lifetime of the address, but any subsequent alteration of the 984 * address OR it's lifetime will not affect the prefix lifetime. 985 * As such, we cannot stop the prefix from timing out and then 986 * constantly removing the prefix route dhcpcd is capable of adding 987 * in it's absense. 988 * 989 * What we can do to mitigate the issue is to add the address with 990 * infinite lifetimes, so the prefix route will never time out. 991 * Once done, we can then set lifetimes on the address and all is good. 992 * The downside of this approach is that we need to manually remove 993 * the kernel route because it has no lifetime, but this is OK as 994 * dhcpcd will handle this too. 995 * 996 * This issue is discussed on the NetBSD mailing lists here: 997 * http://mail-index.netbsd.org/tech-net/2016/08/05/msg006044.html 998 * 999 * Fixed in NetBSD-7.99.36 1000 * NOT fixed in FreeBSD - bug 195197 1001 * Fixed in OpenBSD-5.9 1002 */ 1003 1004 #if !((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003600) || \ 1005 (defined(__OpenBSD__) && OpenBSD >= 201605)) 1006 if (cmd == RTM_NEWADDR && !(ia->flags & IPV6_AF_ADDED)) { 1007 ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 1008 ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 1009 (void)ioctl(priv->pf_inet6_fd, SIOCAIFADDR_IN6, &ifa); 1010 } 1011 #endif 1012 1013 #if defined(__OpenBSD__) && OpenBSD <= 201705 1014 /* BUT OpenBSD older than 6.2 does not reset the address lifetime 1015 * for subsequent calls... 1016 * Luckily dhcpcd will remove the lease when it expires so 1017 * just set an infinite lifetime, unless a temporary address. */ 1018 if (ifa.ifra_flags & IN6_IFF_PRIVACY) { 1019 ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime; 1020 ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime; 1021 } else { 1022 ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 1023 ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 1024 } 1025 #else 1026 ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime; 1027 ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime; 1028 #endif 1029 1030 return ioctl(priv->pf_inet6_fd, 1031 cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa); 1032 } 1033 1034 int 1035 if_addrflags6(const struct interface *ifp, const struct in6_addr *addr, 1036 __unused const char *alias) 1037 { 1038 int flags; 1039 struct in6_ifreq ifr6; 1040 struct priv *priv; 1041 1042 memset(&ifr6, 0, sizeof(ifr6)); 1043 strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name)); 1044 ifr6.ifr_addr.sin6_family = AF_INET6; 1045 ifr6.ifr_addr.sin6_addr = *addr; 1046 ifa_setscope(&ifr6.ifr_addr, ifp->index); 1047 priv = (struct priv *)ifp->ctx->priv; 1048 if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1) 1049 flags = ifr6.ifr_ifru.ifru_flags6; 1050 else 1051 flags = -1; 1052 return flags; 1053 } 1054 1055 int 1056 if_getlifetime6(struct ipv6_addr *ia) 1057 { 1058 struct in6_ifreq ifr6; 1059 time_t t; 1060 struct in6_addrlifetime *lifetime; 1061 struct priv *priv; 1062 1063 memset(&ifr6, 0, sizeof(ifr6)); 1064 strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name)); 1065 ifr6.ifr_addr.sin6_family = AF_INET6; 1066 ifr6.ifr_addr.sin6_addr = ia->addr; 1067 ifa_setscope(&ifr6.ifr_addr, ia->iface->index); 1068 priv = (struct priv *)ia->iface->ctx->priv; 1069 if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1) 1070 return -1; 1071 clock_gettime(CLOCK_MONOTONIC, &ia->created); 1072 1073 #if defined(__FreeBSD__) || defined(__DragonFly__) 1074 t = ia->created.tv_sec; 1075 #else 1076 t = time(NULL); 1077 #endif 1078 1079 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 1080 if (lifetime->ia6t_preferred) 1081 ia->prefix_pltime = (uint32_t)(lifetime->ia6t_preferred - 1082 MIN(t, lifetime->ia6t_preferred)); 1083 else 1084 ia->prefix_pltime = ND6_INFINITE_LIFETIME; 1085 if (lifetime->ia6t_expire) { 1086 ia->prefix_vltime = (uint32_t)(lifetime->ia6t_expire - 1087 MIN(t, lifetime->ia6t_expire)); 1088 /* Calculate the created time */ 1089 ia->created.tv_sec -= lifetime->ia6t_vltime - ia->prefix_vltime; 1090 } else 1091 ia->prefix_vltime = ND6_INFINITE_LIFETIME; 1092 return 0; 1093 } 1094 #endif 1095 1096 static int 1097 if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan) 1098 { 1099 1100 if (ifan->ifan_msglen < sizeof(*ifan)) { 1101 errno = EINVAL; 1102 return -1; 1103 } 1104 1105 switch(ifan->ifan_what) { 1106 case IFAN_ARRIVAL: 1107 return dhcpcd_handleinterface(ctx, 1, ifan->ifan_name); 1108 case IFAN_DEPARTURE: 1109 return dhcpcd_handleinterface(ctx, -1, ifan->ifan_name); 1110 } 1111 1112 return 0; 1113 } 1114 1115 static int 1116 if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) 1117 { 1118 struct interface *ifp; 1119 int link_state; 1120 1121 if (ifm->ifm_msglen < sizeof(*ifm)) { 1122 errno = EINVAL; 1123 return -1; 1124 } 1125 1126 if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) 1127 return 0; 1128 1129 switch (ifm->ifm_data.ifi_link_state) { 1130 case LINK_STATE_UNKNOWN: 1131 link_state = LINK_UNKNOWN; 1132 break; 1133 case LINK_STATE_UP: 1134 link_state = LINK_UP; 1135 break; 1136 default: 1137 link_state = LINK_DOWN; 1138 break; 1139 } 1140 1141 dhcpcd_handlecarrier(ctx, link_state, 1142 (unsigned int)ifm->ifm_flags, ifp->name); 1143 return 0; 1144 } 1145 1146 static int 1147 if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) 1148 { 1149 struct rt rt; 1150 1151 if (rtm->rtm_msglen < sizeof(*rtm)) { 1152 errno = EINVAL; 1153 return -1; 1154 } 1155 1156 /* Ignore errors. */ 1157 if (rtm->rtm_errno != 0) 1158 return 0; 1159 1160 if (if_copyrt(ctx, &rt, rtm) == -1) 1161 return errno == ENOTSUP ? 0 : -1; 1162 1163 #ifdef INET6 1164 /* 1165 * BSD announces host routes. 1166 * As such, we should be notified of reachability by its 1167 * existance with a hardware address. 1168 * Ensure we don't call this for a newly incomplete state. 1169 */ 1170 if (rt.rt_dest.sa_family == AF_INET6 && 1171 (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) && 1172 !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) 1173 { 1174 bool reachable; 1175 1176 reachable = (rtm->rtm_type == RTM_ADD || 1177 rtm->rtm_type == RTM_CHANGE) && 1178 rt.rt_dflags & RTDF_GATELINK; 1179 ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable); 1180 } 1181 #endif 1182 1183 if (rtm->rtm_type != RTM_MISS) 1184 rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); 1185 return 0; 1186 } 1187 1188 static int 1189 if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) 1190 { 1191 struct interface *ifp; 1192 const struct sockaddr *rti_info[RTAX_MAX]; 1193 int addrflags; 1194 pid_t pid; 1195 1196 if (ifam->ifam_msglen < sizeof(*ifam)) { 1197 errno = EINVAL; 1198 return -1; 1199 } 1200 if (~ifam->ifam_addrs & RTA_IFA) 1201 return 0; 1202 if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL) 1203 return 0; 1204 1205 if (get_addrs(ifam->ifam_addrs, (const char *)ifam + sizeof(*ifam), 1206 ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1) 1207 return -1; 1208 1209 #ifdef HAVE_IFAM_PID 1210 pid = ifam->ifam_pid; 1211 #else 1212 pid = 0; 1213 #endif 1214 1215 #ifdef HAVE_IFAM_ADDRFLAGS 1216 addrflags = ifam->ifam_addrflags; 1217 #endif 1218 switch (rti_info[RTAX_IFA]->sa_family) { 1219 case AF_LINK: 1220 { 1221 struct sockaddr_dl sdl; 1222 1223 #ifdef RTM_CHGADDR 1224 if (ifam->ifam_type != RTM_CHGADDR) 1225 break; 1226 #else 1227 if (ifam->ifam_type != RTM_NEWADDR) 1228 break; 1229 #endif 1230 memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len); 1231 dhcpcd_handlehwaddr(ctx, ifp->name, CLLADDR(&sdl),sdl.sdl_alen); 1232 break; 1233 } 1234 #ifdef INET 1235 case AF_INET: 1236 case 255: /* FIXME: Why 255? */ 1237 { 1238 const struct sockaddr_in *sin; 1239 struct in_addr addr, mask, bcast; 1240 1241 sin = (const void *)rti_info[RTAX_IFA]; 1242 addr.s_addr = sin != NULL && sin->sin_family == AF_INET ? 1243 sin->sin_addr.s_addr : INADDR_ANY; 1244 sin = (const void *)rti_info[RTAX_NETMASK]; 1245 mask.s_addr = sin != NULL && sin->sin_family == AF_INET ? 1246 sin->sin_addr.s_addr : INADDR_ANY; 1247 sin = (const void *)rti_info[RTAX_BRD]; 1248 bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ? 1249 sin->sin_addr.s_addr : INADDR_ANY; 1250 1251 #if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000 1252 /* 1253 * NetBSD-7 and older send an invalid broadcast address. 1254 * So we need to query the actual address to get 1255 * the right one. 1256 */ 1257 { 1258 #else 1259 /* 1260 * If the address was deleted, lets check if it's 1261 * a late message and it still exists (maybe modified). 1262 * If so, ignore it as deleting an address causes 1263 * dhcpcd to drop any lease to which it belongs. 1264 */ 1265 if (ifam->ifam_type == RTM_DELADDR) { 1266 #endif 1267 #ifdef SIOCGIFALIAS 1268 struct in_aliasreq ifra; 1269 1270 memset(&ifra, 0, sizeof(ifra)); 1271 strlcpy(ifra.ifra_name, ifp->name, 1272 sizeof(ifra.ifra_name)); 1273 ifra.ifra_addr.sin_family = AF_INET; 1274 ifra.ifra_addr.sin_len = sizeof(ifra.ifra_addr); 1275 ifra.ifra_addr.sin_addr = addr; 1276 if (ioctl(ctx->pf_inet_fd, SIOCGIFALIAS, &ifra) == -1) { 1277 if (errno != ENXIO && errno != EADDRNOTAVAIL) 1278 logerr("%s: SIOCGIFALIAS", __func__); 1279 if (ifam->ifam_type != RTM_DELADDR) 1280 break; 1281 } 1282 #if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000 1283 else 1284 bcast = ifra.ifra_broadaddr.sin_addr; 1285 #endif 1286 #else 1287 #warning No SIOCGIFALIAS support 1288 /* 1289 * No SIOCGIFALIAS? That sucks! 1290 * This makes this call very heavy weight, but we 1291 * really need to know if the message is late or not. 1292 */ 1293 const struct sockaddr *sa; 1294 struct ifaddrs *ifaddrs = NULL, *ifa; 1295 1296 sa = rti_info[RTAX_IFA]; 1297 getifaddrs(&ifaddrs); 1298 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 1299 if (ifa->ifa_addr == NULL) 1300 continue; 1301 if (sa_cmp(ifa->ifa_addr, sa) == 0 && 1302 strcmp(ifa->ifa_name, ifp->name) == 0) 1303 break; 1304 } 1305 freeifaddrs(ifaddrs); 1306 if (ifa != NULL) 1307 return 0; 1308 #endif 1309 } 1310 1311 #ifndef HAVE_IFAM_ADDRFLAGS 1312 if (ifam->ifam_type == RTM_DELADDR) 1313 addrflags = 0 ; 1314 else if ((addrflags = if_addrflags(ifp, &addr, NULL)) == -1) { 1315 if (errno != EADDRNOTAVAIL) 1316 logerr("%s: if_addrflags", __func__); 1317 break; 1318 } 1319 #endif 1320 1321 ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name, 1322 &addr, &mask, &bcast, addrflags, pid); 1323 break; 1324 } 1325 #endif 1326 #ifdef INET6 1327 case AF_INET6: 1328 { 1329 struct in6_addr addr6, mask6; 1330 const struct sockaddr_in6 *sin6; 1331 int flags; 1332 1333 sin6 = (const void *)rti_info[RTAX_IFA]; 1334 addr6 = sin6->sin6_addr; 1335 sin6 = (const void *)rti_info[RTAX_NETMASK]; 1336 mask6 = sin6->sin6_addr; 1337 1338 /* 1339 * If the address was deleted, lets check if it's 1340 * a late message and it still exists (maybe modified). 1341 * If so, ignore it as deleting an address causes 1342 * dhcpcd to drop any lease to which it belongs. 1343 */ 1344 if (ifam->ifam_type == RTM_DELADDR) { 1345 flags = if_addrflags6(ifp, &addr6, NULL); 1346 if (flags != -1) 1347 break; 1348 addrflags = 0; 1349 } 1350 #ifndef HAVE_IFAM_ADDRFLAGS 1351 else if ((addrflags = if_addrflags6(ifp, &addr6, NULL)) == -1) { 1352 if (errno != EADDRNOTAVAIL) 1353 logerr("%s: if_addrflags6", __func__); 1354 break; 1355 } 1356 #endif 1357 1358 #ifdef __KAME__ 1359 if (IN6_IS_ADDR_LINKLOCAL(&addr6)) 1360 /* Remove the scope from the address */ 1361 addr6.s6_addr[2] = addr6.s6_addr[3] = '\0'; 1362 #endif 1363 1364 ipv6_handleifa(ctx, ifam->ifam_type, NULL, 1365 ifp->name, &addr6, ipv6_prefixlen(&mask6), addrflags, pid); 1366 break; 1367 } 1368 #endif 1369 } 1370 1371 return 0; 1372 } 1373 1374 static int 1375 if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) 1376 { 1377 1378 if (rtm->rtm_version != RTM_VERSION) 1379 return 0; 1380 1381 switch(rtm->rtm_type) { 1382 #ifdef RTM_IFANNOUNCE 1383 case RTM_IFANNOUNCE: 1384 return if_announce(ctx, (const void *)rtm); 1385 #endif 1386 case RTM_IFINFO: 1387 return if_ifinfo(ctx, (const void *)rtm); 1388 case RTM_ADD: /* FALLTHROUGH */ 1389 case RTM_CHANGE: /* FALLTHROUGH */ 1390 case RTM_DELETE: /* FALLTHROUGH */ 1391 case RTM_MISS: 1392 return if_rtm(ctx, (const void *)rtm); 1393 #ifdef RTM_CHGADDR 1394 case RTM_CHGADDR: /* FALLTHROUGH */ 1395 #endif 1396 case RTM_DELADDR: /* FALLTHROUGH */ 1397 case RTM_NEWADDR: 1398 return if_ifa(ctx, (const void *)rtm); 1399 #ifdef RTM_DESYNC 1400 case RTM_DESYNC: 1401 dhcpcd_linkoverflow(ctx); 1402 #elif !defined(SO_RERROR) 1403 #warning cannot detect route socket overflow within kernel 1404 #endif 1405 } 1406 1407 return 0; 1408 } 1409 1410 __CTASSERT(offsetof(struct rt_msghdr, rtm_msglen) == 0); 1411 int 1412 if_handlelink(struct dhcpcd_ctx *ctx) 1413 { 1414 struct rtm rtm; 1415 ssize_t len; 1416 1417 len = read(ctx->link_fd, &rtm, sizeof(rtm)); 1418 if (len == -1) 1419 return -1; 1420 if (len == 0) 1421 return 0; 1422 if ((size_t)len < sizeof(rtm.hdr.rtm_msglen) || 1423 len != rtm.hdr.rtm_msglen) 1424 { 1425 errno = EINVAL; 1426 return -1; 1427 } 1428 /* 1429 * Coverity thinks that the data could be tainted from here. 1430 * I have no idea how because the length of the data we read 1431 * is guarded by len and checked to match rtm_msglen. 1432 * The issue seems to be related to extracting the addresses 1433 * at the end of the header, but seems to have no issues with the 1434 * equivalent call in if_initrt. 1435 */ 1436 /* coverity[tainted_data] */ 1437 return if_dispatch(ctx, &rtm.hdr); 1438 } 1439 1440 #ifndef SYS_NMLN /* OSX */ 1441 # define SYS_NMLN 256 1442 #endif 1443 #ifndef HW_MACHINE_ARCH 1444 # ifdef HW_MODEL /* OpenBSD */ 1445 # define HW_MACHINE_ARCH HW_MODEL 1446 # endif 1447 #endif 1448 int 1449 if_machinearch(char *str, size_t len) 1450 { 1451 int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 1452 char march[SYS_NMLN]; 1453 size_t marchlen = sizeof(march); 1454 1455 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 1456 march, &marchlen, NULL, 0) != 0) 1457 return -1; 1458 return snprintf(str, len, ":%s", march); 1459 } 1460 1461 #ifdef INET6 1462 #if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)) || \ 1463 defined(IPV6CTL_USETEMPADDR) || defined(IPV6CTL_TEMPVLTIME) || \ 1464 defined(IPV6CTL_FORWARDING) 1465 #define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0) 1466 #define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1) 1467 static int 1468 inet6_sysctl(int code, int val, int action) 1469 { 1470 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 1471 size_t size; 1472 1473 mib[3] = code; 1474 size = sizeof(val); 1475 if (action) { 1476 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), 1477 NULL, 0, &val, size) == -1) 1478 return -1; 1479 return 0; 1480 } 1481 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1) 1482 return -1; 1483 return val; 1484 } 1485 #endif 1486 1487 #ifdef IPV6_MANAGETEMPADDR 1488 #ifndef IPV6CTL_TEMPVLTIME 1489 #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) 1490 #define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1) 1491 static int 1492 inet6_sysctlbyname(const char *name, int val, int action) 1493 { 1494 size_t size; 1495 1496 size = sizeof(val); 1497 if (action) { 1498 if (sysctlbyname(name, NULL, 0, &val, size) == -1) 1499 return -1; 1500 return 0; 1501 } 1502 if (sysctlbyname(name, &val, &size, NULL, 0) == -1) 1503 return -1; 1504 return val; 1505 } 1506 #endif 1507 1508 int 1509 ip6_use_tempaddr(__unused const char *ifname) 1510 { 1511 int val; 1512 1513 #ifdef IPV6CTL_USETEMPADDR 1514 val = get_inet6_sysctl(IPV6CTL_USETEMPADDR); 1515 #else 1516 val = get_inet6_sysctlbyname("net.inet6.ip6.use_tempaddr"); 1517 #endif 1518 return val == -1 ? 0 : val; 1519 } 1520 1521 int 1522 ip6_temp_preferred_lifetime(__unused const char *ifname) 1523 { 1524 int val; 1525 1526 #ifdef IPV6CTL_TEMPPLTIME 1527 val = get_inet6_sysctl(IPV6CTL_TEMPPLTIME); 1528 #else 1529 val = get_inet6_sysctlbyname("net.inet6.ip6.temppltime"); 1530 #endif 1531 return val < 0 ? TEMP_PREFERRED_LIFETIME : val; 1532 } 1533 1534 int 1535 ip6_temp_valid_lifetime(__unused const char *ifname) 1536 { 1537 int val; 1538 1539 #ifdef IPV6CTL_TEMPVLTIME 1540 val = get_inet6_sysctl(IPV6CTL_TEMPVLTIME); 1541 #else 1542 val = get_inet6_sysctlbyname("net.inet6.ip6.tempvltime"); 1543 #endif 1544 return val < 0 ? TEMP_VALID_LIFETIME : val; 1545 } 1546 #endif 1547 1548 int 1549 ip6_forwarding(__unused const char *ifname) 1550 { 1551 int val; 1552 1553 #ifdef IPV6CTL_FORWARDING 1554 val = get_inet6_sysctl(IPV6CTL_FORWARDING); 1555 #else 1556 val = get_inet6_sysctlbyname("net.inet6.ip6.forwarding"); 1557 #endif 1558 return val < 0 ? 0 : val; 1559 } 1560 1561 #ifdef SIOCIFAFATTACH 1562 static int 1563 af_attach(int s, const struct interface *ifp, int af) 1564 { 1565 struct if_afreq ifar; 1566 1567 strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name)); 1568 ifar.ifar_af = af; 1569 return ioctl(s, SIOCIFAFATTACH, (void *)&ifar); 1570 } 1571 #endif 1572 1573 #ifdef SIOCGIFXFLAGS 1574 static int 1575 set_ifxflags(int s, const struct interface *ifp) 1576 { 1577 struct ifreq ifr; 1578 int flags; 1579 1580 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 1581 if (ioctl(s, SIOCGIFXFLAGS, (void *)&ifr) == -1) 1582 return -1; 1583 flags = ifr.ifr_flags; 1584 #ifdef IFXF_NOINET6 1585 flags &= ~IFXF_NOINET6; 1586 #endif 1587 /* 1588 * If not doing autoconf, don't disable the kernel from doing it. 1589 * If we need to, we should have another option actively disable it. 1590 * 1591 * OpenBSD moved from kernel based SLAAC to userland via slaacd(8). 1592 * It has a similar featureset to dhcpcd such as stable private 1593 * addresses, but lacks the ability to handle DNS inside the RA 1594 * which is a serious shortfall in this day and age. 1595 * Appease their user base by working alongside slaacd(8) if 1596 * dhcpcd is instructed not to do auto configuration of addresses. 1597 */ 1598 #if defined(ND6_IFF_ACCEPT_RTADV) 1599 #define BSD_AUTOCONF DHCPCD_IPV6RS 1600 #else 1601 #define BSD_AUTOCONF DHCPCD_IPV6RA_AUTOCONF 1602 #endif 1603 if (ifp->options->options & BSD_AUTOCONF) 1604 flags &= ~IFXF_AUTOCONF6; 1605 if (ifr.ifr_flags == flags) 1606 return 0; 1607 ifr.ifr_flags = flags; 1608 return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr); 1609 } 1610 #endif 1611 1612 /* OpenBSD removed ND6 flags entirely, so we need to check for their 1613 * existance. */ 1614 #if defined(ND6_IFF_AUTO_LINKLOCAL) || \ 1615 defined(ND6_IFF_PERFORMNUD) || \ 1616 defined(ND6_IFF_ACCEPT_RTADV) || \ 1617 defined(ND6_IFF_OVERRIDE_RTADV) || \ 1618 defined(ND6_IFF_IFDISABLED) 1619 #define ND6_NDI_FLAGS 1620 #endif 1621 1622 void 1623 if_setup_inet6(const struct interface *ifp) 1624 { 1625 struct priv *priv; 1626 int s; 1627 #ifdef ND6_NDI_FLAGS 1628 struct in6_ndireq nd; 1629 int flags; 1630 #endif 1631 1632 priv = (struct priv *)ifp->ctx->priv; 1633 s = priv->pf_inet6_fd; 1634 1635 #ifdef ND6_NDI_FLAGS 1636 memset(&nd, 0, sizeof(nd)); 1637 strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname)); 1638 if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1) 1639 logerr("%s: SIOCGIFINFO_FLAGS", ifp->name); 1640 flags = (int)nd.ndi.flags; 1641 #endif 1642 1643 #ifdef ND6_IFF_AUTO_LINKLOCAL 1644 /* Unlike the kernel, 1645 * dhcpcd make make a stable private address. */ 1646 flags &= ~ND6_IFF_AUTO_LINKLOCAL; 1647 #endif 1648 1649 #ifdef ND6_IFF_PERFORMNUD 1650 /* NUD is kind of essential. */ 1651 flags |= ND6_IFF_PERFORMNUD; 1652 #endif 1653 1654 #ifdef ND6_IFF_IFDISABLED 1655 /* Ensure the interface is not disabled. */ 1656 flags &= ~ND6_IFF_IFDISABLED; 1657 #endif 1658 1659 /* 1660 * If not doing autoconf, don't disable the kernel from doing it. 1661 * If we need to, we should have another option actively disable it. 1662 */ 1663 #ifdef ND6_IFF_ACCEPT_RTADV 1664 if (ifp->options->options & DHCPCD_IPV6RS) 1665 flags &= ~ND6_IFF_ACCEPT_RTADV; 1666 #ifdef ND6_IFF_OVERRIDE_RTADV 1667 if (ifp->options->options & DHCPCD_IPV6RS) 1668 flags |= ND6_IFF_OVERRIDE_RTADV; 1669 #endif 1670 #endif 1671 1672 #ifdef ND6_NDI_FLAGS 1673 if (nd.ndi.flags != (uint32_t)flags) { 1674 nd.ndi.flags = (uint32_t)flags; 1675 if (ioctl(s, SIOCSIFINFO_FLAGS, &nd) == -1) 1676 logerr("%s: SIOCSIFINFO_FLAGS", ifp->name); 1677 } 1678 #endif 1679 1680 /* Enabling IPv6 by whatever means must be the 1681 * last action undertaken to ensure kernel RS and 1682 * LLADDR auto configuration are disabled where applicable. */ 1683 #ifdef SIOCIFAFATTACH 1684 if (af_attach(s, ifp, AF_INET6) == -1) 1685 logerr("%s: af_attach", ifp->name); 1686 #endif 1687 1688 #ifdef SIOCGIFXFLAGS 1689 if (set_ifxflags(s, ifp) == -1) 1690 logerr("%s: set_ifxflags", ifp->name); 1691 #endif 1692 1693 #if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV) 1694 /* If we cannot control ra per interface, disable it globally. */ 1695 if (ifp->options->options & DHCPCD_IPV6RS) { 1696 int ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV); 1697 1698 if (ra == -1) { 1699 if (errno != ENOENT) 1700 logerr("IPV6CTL_ACCEPT_RTADV"); 1701 else if (ra != 0) 1702 if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) 1703 logerr("IPV6CTL_ACCEPT_RTADV"); 1704 } 1705 } 1706 #endif 1707 1708 #if defined(IPV6CTL_ACCEPT_RTADV) || defined(ND6_IFF_ACCEPT_RTADV) 1709 /* Flush the kernel knowledge of advertised routers 1710 * and prefixes so the kernel does not expire prefixes 1711 * and default routes we are trying to own. */ 1712 if (ifp->options->options & DHCPCD_IPV6RS) { 1713 struct in6_ifreq ifr; 1714 1715 memset(&ifr, 0, sizeof(ifr)); 1716 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 1717 if (ioctl(s, SIOCSRTRFLUSH_IN6, &ifr) == -1 && 1718 errno != ENOTSUP) 1719 logwarn("SIOCSRTRFLUSH_IN6"); 1720 if (ioctl(s, SIOCSPFXFLUSH_IN6, &ifr) == -1 && 1721 errno != ENOTSUP) 1722 logwarn("SIOCSPFXFLUSH_IN6"); 1723 } 1724 #endif 1725 } 1726 #endif 1727