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