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