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, RTM_MISS, 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)) { 643 errno = EINVAL; 644 return -1; 645 } 646 if (rtm->rtm_type != RTM_MISS && !(rtm->rtm_addrs & RTA_GATEWAY)) { 647 errno = EINVAL; 648 return -1; 649 } 650 #ifdef RTF_CLONED 651 if (rtm->rtm_flags & RTF_CLONED) { 652 errno = ENOTSUP; 653 return -1; 654 } 655 #endif 656 #ifdef RTF_LOCAL 657 if (rtm->rtm_flags & RTF_LOCAL) { 658 errno = ENOTSUP; 659 return -1; 660 } 661 #endif 662 #ifdef RTF_BROADCAST 663 if (rtm->rtm_flags & RTF_BROADCAST) { 664 errno = ENOTSUP; 665 return -1; 666 } 667 #endif 668 669 if (get_addrs(rtm->rtm_addrs, (const char *)rtm + sizeof(*rtm), 670 rtm->rtm_msglen - sizeof(*rtm), rti_info) == -1) 671 return -1; 672 memset(rt, 0, sizeof(*rt)); 673 674 rt->rt_flags = (unsigned int)rtm->rtm_flags; 675 if_copysa(&rt->rt_dest, rti_info[RTAX_DST]); 676 if (rtm->rtm_addrs & RTA_NETMASK) { 677 if_copysa(&rt->rt_netmask, rti_info[RTAX_NETMASK]); 678 if (rt->rt_netmask.sa_family == 255) /* Why? */ 679 rt->rt_netmask.sa_family = rt->rt_dest.sa_family; 680 } 681 682 /* dhcpcd likes an unspecified gateway to indicate via the link. 683 * However we need to know if gateway was a link with an address. */ 684 if (rtm->rtm_addrs & RTA_GATEWAY) { 685 if (rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) { 686 const struct sockaddr_dl *sdl; 687 688 sdl = (const struct sockaddr_dl*) 689 (const void *)rti_info[RTAX_GATEWAY]; 690 if (sdl->sdl_alen != 0) 691 rt->rt_dflags |= RTDF_GATELINK; 692 } else if (rtm->rtm_flags & RTF_GATEWAY) 693 if_copysa(&rt->rt_gateway, rti_info[RTAX_GATEWAY]); 694 } 695 696 if (rtm->rtm_addrs & RTA_IFA) 697 if_copysa(&rt->rt_ifa, rti_info[RTAX_IFA]); 698 699 rt->rt_mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu; 700 701 if (rtm->rtm_index) 702 rt->rt_ifp = if_findindex(ctx->ifaces, rtm->rtm_index); 703 else if (rtm->rtm_addrs & RTA_IFP) 704 rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_IFP]); 705 else if (rtm->rtm_addrs & RTA_GATEWAY) 706 rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_GATEWAY]); 707 else 708 rt->rt_ifp = if_findsa(ctx, rti_info[RTAX_DST]); 709 710 if (rt->rt_ifp == NULL && rtm->rtm_type == RTM_MISS) 711 rt->rt_ifp = if_find(ctx->ifaces, "lo0"); 712 713 if (rt->rt_ifp == NULL) { 714 errno = ESRCH; 715 return -1; 716 } 717 return 0; 718 } 719 720 int 721 if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *kroutes, int af) 722 { 723 struct rt_msghdr *rtm; 724 int mib[6]; 725 size_t needed; 726 char *buf, *p, *end; 727 struct rt rt, *rtn; 728 729 mib[0] = CTL_NET; 730 mib[1] = PF_ROUTE; 731 mib[2] = 0; 732 mib[3] = af; 733 mib[4] = NET_RT_DUMP; 734 mib[5] = 0; 735 736 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 737 return -1; 738 if (needed == 0) 739 return 0; 740 if ((buf = malloc(needed)) == NULL) 741 return -1; 742 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) { 743 free(buf); 744 return -1; 745 } 746 747 end = buf + needed; 748 for (p = buf; p < end; p += rtm->rtm_msglen) { 749 rtm = (void *)p; 750 if (p + rtm->rtm_msglen >= end) { 751 errno = EINVAL; 752 break; 753 } 754 if (if_copyrt(ctx, &rt, rtm) != 0) 755 continue; 756 if ((rtn = rt_new(rt.rt_ifp)) == NULL) { 757 logerr(__func__); 758 break; 759 } 760 memcpy(rtn, &rt, sizeof(*rtn)); 761 if (rb_tree_insert_node(kroutes, rtn) != rtn) 762 rt_free(rtn); 763 } 764 free(buf); 765 return p == end ? 0 : -1; 766 } 767 768 #ifdef INET 769 int 770 if_address(unsigned char cmd, const struct ipv4_addr *ia) 771 { 772 int r; 773 struct in_aliasreq ifra; 774 775 memset(&ifra, 0, sizeof(ifra)); 776 strlcpy(ifra.ifra_name, ia->iface->name, sizeof(ifra.ifra_name)); 777 778 #define ADDADDR(var, addr) do { \ 779 (var)->sin_family = AF_INET; \ 780 (var)->sin_len = sizeof(*(var)); \ 781 (var)->sin_addr = *(addr); \ 782 } while (/*CONSTCOND*/0) 783 ADDADDR(&ifra.ifra_addr, &ia->addr); 784 ADDADDR(&ifra.ifra_mask, &ia->mask); 785 if (cmd == RTM_NEWADDR && ia->brd.s_addr != INADDR_ANY) 786 ADDADDR(&ifra.ifra_broadaddr, &ia->brd); 787 #undef ADDADDR 788 789 r = ioctl(ia->iface->ctx->pf_inet_fd, 790 cmd == RTM_DELADDR ? SIOCDIFADDR : SIOCAIFADDR, &ifra); 791 return r; 792 } 793 794 795 796 #if !(defined(HAVE_IFADDRS_ADDRFLAGS) && defined(HAVE_IFAM_ADDRFLAGS)) 797 int 798 if_addrflags(const struct interface *ifp, const struct in_addr *addr, 799 __unused const char *alias) 800 { 801 #ifdef SIOCGIFAFLAG_IN 802 struct ifreq ifr; 803 struct sockaddr_in *sin; 804 805 memset(&ifr, 0, sizeof(ifr)); 806 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 807 sin = (void *)&ifr.ifr_addr; 808 sin->sin_family = AF_INET; 809 sin->sin_addr = *addr; 810 if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1) 811 return -1; 812 return ifr.ifr_addrflags; 813 #else 814 UNUSED(ifp); 815 UNUSED(addr); 816 return 0; 817 #endif 818 } 819 #endif 820 #endif /* INET */ 821 822 #ifdef INET6 823 static void 824 ifa_setscope(struct sockaddr_in6 *sin, unsigned int ifindex) 825 { 826 827 #ifdef __KAME__ 828 /* KAME based systems want to store the scope inside the sin6_addr 829 * for link local addresses */ 830 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { 831 uint16_t scope = htons((uint16_t)ifindex); 832 memcpy(&sin->sin6_addr.s6_addr[2], &scope, 833 sizeof(scope)); 834 } 835 sin->sin6_scope_id = 0; 836 #else 837 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) 838 sin->sin6_scope_id = ifindex; 839 else 840 sin->sin6_scope_id = 0; 841 #endif 842 } 843 844 static unsigned int 845 ifa_getscope(const struct sockaddr_in6 *sin) 846 { 847 #ifdef __KAME__ 848 uint16_t scope; 849 #endif 850 851 if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) 852 return 0; 853 #ifdef __KAME__ 854 memcpy(&scope, &sin->sin6_addr.s6_addr[2], sizeof(scope)); 855 return (unsigned int)ntohs(scope); 856 #else 857 return (unsigned int)sin->sin6_scope_id; 858 #endif 859 } 860 861 int 862 if_address6(unsigned char cmd, const struct ipv6_addr *ia) 863 { 864 struct in6_aliasreq ifa; 865 struct in6_addr mask; 866 struct priv *priv; 867 868 priv = (struct priv *)ia->iface->ctx->priv; 869 870 memset(&ifa, 0, sizeof(ifa)); 871 strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name)); 872 /* 873 * We should not set IN6_IFF_TENTATIVE as the kernel should be 874 * able to work out if it's a new address or not. 875 * 876 * We should set IN6_IFF_AUTOCONF, but the kernel won't let us. 877 * This is probably a safety measure, but still it's not entirely right 878 * either. 879 */ 880 #if 0 881 if (ia->autoconf) 882 ifa.ifra_flags |= IN6_IFF_AUTOCONF; 883 #endif 884 #if defined(__FreeBSD__) || defined(__DragonFly__) 885 if (ia->addr_flags & IN6_IFF_TENTATIVE) 886 ifa.ifra_flags |= IN6_IFF_TENTATIVE; 887 #endif 888 #ifdef IPV6_MANGETEMPADDR 889 if (ia->flags & IPV6_AF_TEMPORARY) 890 ifa.ifra_flags |= IN6_IFF_TEMPORARY; 891 #endif 892 893 #define ADDADDR(v, addr) { \ 894 (v)->sin6_family = AF_INET6; \ 895 (v)->sin6_len = sizeof(*v); \ 896 (v)->sin6_addr = *(addr); \ 897 } 898 899 ADDADDR(&ifa.ifra_addr, &ia->addr); 900 ifa_setscope(&ifa.ifra_addr, ia->iface->index); 901 ipv6_mask(&mask, ia->prefix_len); 902 ADDADDR(&ifa.ifra_prefixmask, &mask); 903 904 #undef ADDADDR 905 906 /* 907 * Every BSD kernel wants to add the prefix of the address to it's 908 * list of RA received prefixes. 909 * THIS IS WRONG because there (as the comments in the kernel state) 910 * is no API for managing prefix lifetime and the kernel should not 911 * pretend it's from a RA either. 912 * 913 * The issue is that the very first assigned prefix will inherit the 914 * lifetime of the address, but any subsequent alteration of the 915 * address OR it's lifetime will not affect the prefix lifetime. 916 * As such, we cannot stop the prefix from timing out and then 917 * constantly removing the prefix route dhcpcd is capable of adding 918 * in it's absense. 919 * 920 * What we can do to mitigate the issue is to add the address with 921 * infinite lifetimes, so the prefix route will never time out. 922 * Once done, we can then set lifetimes on the address and all is good. 923 * The downside of this approach is that we need to manually remove 924 * the kernel route because it has no lifetime, but this is OK as 925 * dhcpcd will handle this too. 926 * 927 * This issue is discussed on the NetBSD mailing lists here: 928 * http://mail-index.netbsd.org/tech-net/2016/08/05/msg006044.html 929 * 930 * Fixed in NetBSD-7.99.36 931 * NOT fixed in FreeBSD - bug 195197 932 * Fixed in OpenBSD-5.9 933 */ 934 935 #if !((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 799003600) || \ 936 (defined(__OpenBSD__) && OpenBSD >= 201605)) 937 if (cmd == RTM_NEWADDR && !(ia->flags & IPV6_AF_ADDED)) { 938 ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 939 ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 940 (void)ioctl(priv->pf_inet6_fd, SIOCAIFADDR_IN6, &ifa); 941 } 942 #endif 943 944 #if defined(__OpenBSD__) && OpenBSD <= 201705 945 /* BUT OpenBSD older than 6.2 does not reset the address lifetime 946 * for subsequent calls... 947 * Luckily dhcpcd will remove the lease when it expires so 948 * just set an infinite lifetime, unless a temporary address. */ 949 if (ifa.ifra_flags & IN6_IFF_PRIVACY) { 950 ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime; 951 ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime; 952 } else { 953 ifa.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME; 954 ifa.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME; 955 } 956 #else 957 ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime; 958 ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime; 959 #endif 960 961 return ioctl(priv->pf_inet6_fd, 962 cmd == RTM_DELADDR ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa); 963 } 964 965 int 966 if_addrflags6(const struct interface *ifp, const struct in6_addr *addr, 967 __unused const char *alias) 968 { 969 int flags; 970 struct in6_ifreq ifr6; 971 struct priv *priv; 972 973 memset(&ifr6, 0, sizeof(ifr6)); 974 strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name)); 975 ifr6.ifr_addr.sin6_family = AF_INET6; 976 ifr6.ifr_addr.sin6_addr = *addr; 977 ifa_setscope(&ifr6.ifr_addr, ifp->index); 978 priv = (struct priv *)ifp->ctx->priv; 979 if (ioctl(priv->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1) 980 flags = ifr6.ifr_ifru.ifru_flags6; 981 else 982 flags = -1; 983 return flags; 984 } 985 986 int 987 if_getlifetime6(struct ipv6_addr *ia) 988 { 989 struct in6_ifreq ifr6; 990 time_t t; 991 struct in6_addrlifetime *lifetime; 992 struct priv *priv; 993 994 memset(&ifr6, 0, sizeof(ifr6)); 995 strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name)); 996 ifr6.ifr_addr.sin6_family = AF_INET6; 997 ifr6.ifr_addr.sin6_addr = ia->addr; 998 ifa_setscope(&ifr6.ifr_addr, ia->iface->index); 999 priv = (struct priv *)ia->iface->ctx->priv; 1000 if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1) 1001 return -1; 1002 clock_gettime(CLOCK_MONOTONIC, &ia->created); 1003 1004 #if defined(__FreeBSD__) || defined(__DragonFly__) 1005 t = ia->created.tv_sec; 1006 #else 1007 t = time(NULL); 1008 #endif 1009 1010 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 1011 if (lifetime->ia6t_preferred) 1012 ia->prefix_pltime = (uint32_t)(lifetime->ia6t_preferred - 1013 MIN(t, lifetime->ia6t_preferred)); 1014 else 1015 ia->prefix_pltime = ND6_INFINITE_LIFETIME; 1016 if (lifetime->ia6t_expire) { 1017 ia->prefix_vltime = (uint32_t)(lifetime->ia6t_expire - 1018 MIN(t, lifetime->ia6t_expire)); 1019 /* Calculate the created time */ 1020 ia->created.tv_sec -= lifetime->ia6t_vltime - ia->prefix_vltime; 1021 } else 1022 ia->prefix_vltime = ND6_INFINITE_LIFETIME; 1023 return 0; 1024 } 1025 #endif 1026 1027 static int 1028 if_announce(struct dhcpcd_ctx *ctx, const struct if_announcemsghdr *ifan) 1029 { 1030 1031 if (ifan->ifan_msglen < sizeof(*ifan)) { 1032 errno = EINVAL; 1033 return -1; 1034 } 1035 1036 switch(ifan->ifan_what) { 1037 case IFAN_ARRIVAL: 1038 return dhcpcd_handleinterface(ctx, 1, ifan->ifan_name); 1039 case IFAN_DEPARTURE: 1040 return dhcpcd_handleinterface(ctx, -1, ifan->ifan_name); 1041 } 1042 1043 return 0; 1044 } 1045 1046 static int 1047 if_ifinfo(struct dhcpcd_ctx *ctx, const struct if_msghdr *ifm) 1048 { 1049 struct interface *ifp; 1050 int link_state; 1051 1052 if (ifm->ifm_msglen < sizeof(*ifm)) { 1053 errno = EINVAL; 1054 return -1; 1055 } 1056 1057 if ((ifp = if_findindex(ctx->ifaces, ifm->ifm_index)) == NULL) 1058 return 0; 1059 1060 switch (ifm->ifm_data.ifi_link_state) { 1061 case LINK_STATE_UNKNOWN: 1062 link_state = LINK_UNKNOWN; 1063 break; 1064 case LINK_STATE_UP: 1065 link_state = LINK_UP; 1066 break; 1067 default: 1068 link_state = LINK_DOWN; 1069 break; 1070 } 1071 1072 dhcpcd_handlecarrier(ctx, link_state, 1073 (unsigned int)ifm->ifm_flags, ifp->name); 1074 return 0; 1075 } 1076 1077 static int 1078 if_rtm(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) 1079 { 1080 struct rt rt; 1081 1082 if (rtm->rtm_msglen < sizeof(*rtm)) { 1083 errno = EINVAL; 1084 return -1; 1085 } 1086 1087 /* Ignore errors. */ 1088 if (rtm->rtm_errno != 0) 1089 return 0; 1090 1091 if (if_copyrt(ctx, &rt, rtm) == -1) 1092 return errno == ENOTSUP ? 0 : -1; 1093 1094 #ifdef INET6 1095 /* 1096 * BSD announces host routes. 1097 * As such, we should be notified of reachability by its 1098 * existance with a hardware address. 1099 * Ensure we don't call this for a newly incomplete state. 1100 */ 1101 if (rt.rt_dest.sa_family == AF_INET6 && 1102 (rt.rt_flags & RTF_HOST || rtm->rtm_type == RTM_MISS) && 1103 !(rtm->rtm_type == RTM_ADD && !(rt.rt_dflags & RTDF_GATELINK))) 1104 { 1105 bool reachable; 1106 1107 reachable = (rtm->rtm_type == RTM_ADD || 1108 rtm->rtm_type == RTM_CHANGE) && 1109 rt.rt_dflags & RTDF_GATELINK; 1110 ipv6nd_neighbour(ctx, &rt.rt_ss_dest.sin6.sin6_addr, reachable); 1111 } 1112 #endif 1113 1114 if (rtm->rtm_type != RTM_MISS) 1115 rt_recvrt(rtm->rtm_type, &rt, rtm->rtm_pid); 1116 return 0; 1117 } 1118 1119 static int 1120 if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam) 1121 { 1122 struct interface *ifp; 1123 const struct sockaddr *rti_info[RTAX_MAX]; 1124 int addrflags; 1125 pid_t pid; 1126 1127 if (ifam->ifam_msglen < sizeof(*ifam)) { 1128 errno = EINVAL; 1129 return -1; 1130 } 1131 if (~ifam->ifam_addrs & RTA_IFA) 1132 return 0; 1133 if ((ifp = if_findindex(ctx->ifaces, ifam->ifam_index)) == NULL) 1134 return 0; 1135 1136 if (get_addrs(ifam->ifam_addrs, (const char *)ifam + sizeof(*ifam), 1137 ifam->ifam_msglen - sizeof(*ifam), rti_info) == -1) 1138 return -1; 1139 1140 #ifdef HAVE_IFAM_PID 1141 pid = ifam->ifam_pid; 1142 #else 1143 pid = 0; 1144 #endif 1145 1146 #ifdef HAVE_IFAM_ADDRFLAGS 1147 addrflags = ifam->ifam_addrflags; 1148 #endif 1149 switch (rti_info[RTAX_IFA]->sa_family) { 1150 case AF_LINK: 1151 { 1152 struct sockaddr_dl sdl; 1153 1154 #ifdef RTM_CHGADDR 1155 if (ifam->ifam_type != RTM_CHGADDR) 1156 break; 1157 #else 1158 if (ifam->ifam_type != RTM_NEWADDR) 1159 break; 1160 #endif 1161 memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len); 1162 dhcpcd_handlehwaddr(ctx, ifp->name, CLLADDR(&sdl),sdl.sdl_alen); 1163 break; 1164 } 1165 #ifdef INET 1166 case AF_INET: 1167 case 255: /* FIXME: Why 255? */ 1168 { 1169 const struct sockaddr_in *sin; 1170 struct in_addr addr, mask, bcast; 1171 1172 sin = (const void *)rti_info[RTAX_IFA]; 1173 addr.s_addr = sin != NULL && sin->sin_family == AF_INET ? 1174 sin->sin_addr.s_addr : INADDR_ANY; 1175 sin = (const void *)rti_info[RTAX_NETMASK]; 1176 mask.s_addr = sin != NULL && sin->sin_family == AF_INET ? 1177 sin->sin_addr.s_addr : INADDR_ANY; 1178 sin = (const void *)rti_info[RTAX_BRD]; 1179 bcast.s_addr = sin != NULL && sin->sin_family == AF_INET ? 1180 sin->sin_addr.s_addr : INADDR_ANY; 1181 1182 #if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000 1183 /* 1184 * NetBSD-7 and older send an invalid broadcast address. 1185 * So we need to query the actual address to get 1186 * the right one. 1187 */ 1188 { 1189 #else 1190 /* 1191 * If the address was deleted, lets check if it's 1192 * a late message and it still exists (maybe modified). 1193 * If so, ignore it as deleting an address causes 1194 * dhcpcd to drop any lease to which it belongs. 1195 */ 1196 if (ifam->ifam_type == RTM_DELADDR) { 1197 #endif 1198 #ifdef SIOCGIFALIAS 1199 struct in_aliasreq ifra; 1200 1201 memset(&ifra, 0, sizeof(ifra)); 1202 strlcpy(ifra.ifra_name, ifp->name, 1203 sizeof(ifra.ifra_name)); 1204 ifra.ifra_addr.sin_family = AF_INET; 1205 ifra.ifra_addr.sin_len = sizeof(ifra.ifra_addr); 1206 ifra.ifra_addr.sin_addr = addr; 1207 if (ioctl(ctx->pf_inet_fd, SIOCGIFALIAS, &ifra) == -1) { 1208 if (errno != ENXIO && errno != EADDRNOTAVAIL) 1209 logerr("%s: SIOCGIFALIAS", __func__); 1210 if (ifam->ifam_type != RTM_DELADDR) 1211 break; 1212 } 1213 #if defined(__NetBSD_Version__) && __NetBSD_Version__ < 800000000 1214 else 1215 bcast = ifra.ifra_broadaddr.sin_addr; 1216 #endif 1217 #else 1218 #warning No SIOCGIFALIAS support 1219 /* 1220 * No SIOCGIFALIAS? That sucks! 1221 * This makes this call very heavy weight, but we 1222 * really need to know if the message is late or not. 1223 */ 1224 const struct sockaddr *sa; 1225 struct ifaddrs *ifaddrs = NULL, *ifa; 1226 1227 sa = rti_info[RTAX_IFA]; 1228 getifaddrs(&ifaddrs); 1229 for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) { 1230 if (ifa->ifa_addr == NULL) 1231 continue; 1232 if (sa_cmp(ifa->ifa_addr, sa) == 0 && 1233 strcmp(ifa->ifa_name, ifp->name) == 0) 1234 break; 1235 } 1236 freeifaddrs(ifaddrs); 1237 if (ifa != NULL) 1238 return 0; 1239 #endif 1240 } 1241 1242 #ifndef HAVE_IFAM_ADDRFLAGS 1243 if (ifam->ifam_type == RTM_DELADDR) 1244 addrflags = 0 ; 1245 else if ((addrflags = if_addrflags(ifp, &addr, NULL)) == -1) { 1246 if (errno != EADDRNOTAVAIL) 1247 logerr("%s: if_addrflags", __func__); 1248 break; 1249 } 1250 #endif 1251 1252 ipv4_handleifa(ctx, ifam->ifam_type, NULL, ifp->name, 1253 &addr, &mask, &bcast, addrflags, pid); 1254 break; 1255 } 1256 #endif 1257 #ifdef INET6 1258 case AF_INET6: 1259 { 1260 struct in6_addr addr6, mask6; 1261 const struct sockaddr_in6 *sin6; 1262 int flags; 1263 1264 sin6 = (const void *)rti_info[RTAX_IFA]; 1265 addr6 = sin6->sin6_addr; 1266 sin6 = (const void *)rti_info[RTAX_NETMASK]; 1267 mask6 = sin6->sin6_addr; 1268 1269 /* 1270 * If the address was deleted, lets check if it's 1271 * a late message and it still exists (maybe modified). 1272 * If so, ignore it as deleting an address causes 1273 * dhcpcd to drop any lease to which it belongs. 1274 */ 1275 if (ifam->ifam_type == RTM_DELADDR) { 1276 flags = if_addrflags6(ifp, &addr6, NULL); 1277 if (flags != -1) 1278 break; 1279 addrflags = 0; 1280 } 1281 #ifndef HAVE_IFAM_ADDRFLAGS 1282 else if ((addrflags = if_addrflags6(ifp, &addr6, NULL)) == -1) { 1283 if (errno != EADDRNOTAVAIL) 1284 logerr("%s: if_addrflags6", __func__); 1285 break; 1286 } 1287 #endif 1288 1289 #ifdef __KAME__ 1290 if (IN6_IS_ADDR_LINKLOCAL(&addr6)) 1291 /* Remove the scope from the address */ 1292 addr6.s6_addr[2] = addr6.s6_addr[3] = '\0'; 1293 #endif 1294 1295 ipv6_handleifa(ctx, ifam->ifam_type, NULL, 1296 ifp->name, &addr6, ipv6_prefixlen(&mask6), addrflags, pid); 1297 break; 1298 } 1299 #endif 1300 } 1301 1302 return 0; 1303 } 1304 1305 static int 1306 if_dispatch(struct dhcpcd_ctx *ctx, const struct rt_msghdr *rtm) 1307 { 1308 1309 if (rtm->rtm_version != RTM_VERSION) 1310 return 0; 1311 1312 switch(rtm->rtm_type) { 1313 #ifdef RTM_IFANNOUNCE 1314 case RTM_IFANNOUNCE: 1315 return if_announce(ctx, (const void *)rtm); 1316 #endif 1317 case RTM_IFINFO: 1318 return if_ifinfo(ctx, (const void *)rtm); 1319 case RTM_ADD: /* FALLTHROUGH */ 1320 case RTM_CHANGE: /* FALLTHROUGH */ 1321 case RTM_DELETE: /* FALLTHROUGH */ 1322 case RTM_MISS: 1323 return if_rtm(ctx, (const void *)rtm); 1324 #ifdef RTM_CHGADDR 1325 case RTM_CHGADDR: /* FALLTHROUGH */ 1326 #endif 1327 case RTM_DELADDR: /* FALLTHROUGH */ 1328 case RTM_NEWADDR: 1329 return if_ifa(ctx, (const void *)rtm); 1330 #ifdef RTM_DESYNC 1331 case RTM_DESYNC: 1332 dhcpcd_linkoverflow(ctx); 1333 #elif !defined(SO_RERROR) 1334 #warning cannot detect route socket overflow within kernel 1335 #endif 1336 } 1337 1338 return 0; 1339 } 1340 1341 __CTASSERT(offsetof(struct rt_msghdr, rtm_msglen) == 0); 1342 int 1343 if_handlelink(struct dhcpcd_ctx *ctx) 1344 { 1345 struct rtm rtm; 1346 ssize_t len; 1347 1348 len = read(ctx->link_fd, &rtm, sizeof(rtm)); 1349 if (len == -1) 1350 return -1; 1351 if (len == 0) 1352 return 0; 1353 if ((size_t)len < sizeof(rtm.hdr.rtm_msglen) || 1354 len != rtm.hdr.rtm_msglen) 1355 { 1356 errno = EINVAL; 1357 return -1; 1358 } 1359 /* 1360 * Coverity thinks that the data could be tainted from here. 1361 * I have no idea how because the length of the data we read 1362 * is guarded by len and checked to match rtm_msglen. 1363 * The issue seems to be related to extracting the addresses 1364 * at the end of the header, but seems to have no issues with the 1365 * equivalent call in if_initrt. 1366 */ 1367 /* coverity[tainted_data] */ 1368 return if_dispatch(ctx, &rtm.hdr); 1369 } 1370 1371 #ifndef SYS_NMLN /* OSX */ 1372 # define SYS_NMLN 256 1373 #endif 1374 #ifndef HW_MACHINE_ARCH 1375 # ifdef HW_MODEL /* OpenBSD */ 1376 # define HW_MACHINE_ARCH HW_MODEL 1377 # endif 1378 #endif 1379 int 1380 if_machinearch(char *str, size_t len) 1381 { 1382 int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 1383 char march[SYS_NMLN]; 1384 size_t marchlen = sizeof(march); 1385 1386 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 1387 march, &marchlen, NULL, 0) != 0) 1388 return -1; 1389 return snprintf(str, len, ":%s", march); 1390 } 1391 1392 #ifdef INET6 1393 #if (defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV)) || \ 1394 defined(IPV6CTL_USETEMPADDR) || defined(IPV6CTL_TEMPVLTIME) || \ 1395 defined(IPV6CTL_FORWARDING) 1396 #define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0) 1397 #define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1) 1398 static int 1399 inet6_sysctl(int code, int val, int action) 1400 { 1401 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 1402 size_t size; 1403 1404 mib[3] = code; 1405 size = sizeof(val); 1406 if (action) { 1407 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), 1408 NULL, 0, &val, size) == -1) 1409 return -1; 1410 return 0; 1411 } 1412 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1) 1413 return -1; 1414 return val; 1415 } 1416 #endif 1417 1418 #ifdef IPV6_MANAGETEMPADDR 1419 #ifndef IPV6CTL_TEMPVLTIME 1420 #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) 1421 #define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1) 1422 static int 1423 inet6_sysctlbyname(const char *name, int val, int action) 1424 { 1425 size_t size; 1426 1427 size = sizeof(val); 1428 if (action) { 1429 if (sysctlbyname(name, NULL, 0, &val, size) == -1) 1430 return -1; 1431 return 0; 1432 } 1433 if (sysctlbyname(name, &val, &size, NULL, 0) == -1) 1434 return -1; 1435 return val; 1436 } 1437 #endif 1438 1439 int 1440 ip6_use_tempaddr(__unused const char *ifname) 1441 { 1442 int val; 1443 1444 #ifdef IPV6CTL_USETEMPADDR 1445 val = get_inet6_sysctl(IPV6CTL_USETEMPADDR); 1446 #else 1447 val = get_inet6_sysctlbyname("net.inet6.ip6.use_tempaddr"); 1448 #endif 1449 return val == -1 ? 0 : val; 1450 } 1451 1452 int 1453 ip6_temp_preferred_lifetime(__unused const char *ifname) 1454 { 1455 int val; 1456 1457 #ifdef IPV6CTL_TEMPPLTIME 1458 val = get_inet6_sysctl(IPV6CTL_TEMPPLTIME); 1459 #else 1460 val = get_inet6_sysctlbyname("net.inet6.ip6.temppltime"); 1461 #endif 1462 return val < 0 ? TEMP_PREFERRED_LIFETIME : val; 1463 } 1464 1465 int 1466 ip6_temp_valid_lifetime(__unused const char *ifname) 1467 { 1468 int val; 1469 1470 #ifdef IPV6CTL_TEMPVLTIME 1471 val = get_inet6_sysctl(IPV6CTL_TEMPVLTIME); 1472 #else 1473 val = get_inet6_sysctlbyname("net.inet6.ip6.tempvltime"); 1474 #endif 1475 return val < 0 ? TEMP_VALID_LIFETIME : val; 1476 } 1477 #endif 1478 1479 int 1480 ip6_forwarding(__unused const char *ifname) 1481 { 1482 int val; 1483 1484 #ifdef IPV6CTL_FORWARDING 1485 val = get_inet6_sysctl(IPV6CTL_FORWARDING); 1486 #else 1487 val = get_inet6_sysctlbyname("net.inet6.ip6.forwarding"); 1488 #endif 1489 return val < 0 ? 0 : val; 1490 } 1491 1492 #ifdef SIOCIFAFATTACH 1493 static int 1494 af_attach(int s, const struct interface *ifp, int af) 1495 { 1496 struct if_afreq ifar; 1497 1498 strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name)); 1499 ifar.ifar_af = af; 1500 return ioctl(s, SIOCIFAFATTACH, (void *)&ifar); 1501 } 1502 #endif 1503 1504 #ifdef SIOCGIFXFLAGS 1505 static int 1506 set_ifxflags(int s, const struct interface *ifp) 1507 { 1508 struct ifreq ifr; 1509 int flags; 1510 1511 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 1512 if (ioctl(s, SIOCGIFXFLAGS, (void *)&ifr) == -1) 1513 return -1; 1514 flags = ifr.ifr_flags; 1515 #ifdef IFXF_NOINET6 1516 flags &= ~IFXF_NOINET6; 1517 #endif 1518 /* 1519 * If not doing autoconf, don't disable the kernel from doing it. 1520 * If we need to, we should have another option actively disable it. 1521 * 1522 * OpenBSD moved from kernel based SLAAC to userland via slaacd(8). 1523 * It has a similar featureset to dhcpcd such as stable private 1524 * addresses, but lacks the ability to handle DNS inside the RA 1525 * which is a serious shortfall in this day and age. 1526 * Appease their user base by working alongside slaacd(8) if 1527 * dhcpcd is instructed not to do auto configuration of addresses. 1528 */ 1529 #if defined(ND6_IFF_ACCEPT_RTADV) 1530 #define BSD_AUTOCONF DHCPCD_IPV6RS 1531 #else 1532 #define BSD_AUTOCONF DHCPCD_IPV6RA_AUTOCONF 1533 #endif 1534 if (ifp->options->options & BSD_AUTOCONF) 1535 flags &= ~IFXF_AUTOCONF6; 1536 if (ifr.ifr_flags == flags) 1537 return 0; 1538 ifr.ifr_flags = flags; 1539 return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr); 1540 } 1541 #endif 1542 1543 /* OpenBSD removed ND6 flags entirely, so we need to check for their 1544 * existance. */ 1545 #if defined(ND6_IFF_AUTO_LINKLOCAL) || \ 1546 defined(ND6_IFF_PERFORMNUD) || \ 1547 defined(ND6_IFF_ACCEPT_RTADV) || \ 1548 defined(ND6_IFF_OVERRIDE_RTADV) || \ 1549 defined(ND6_IFF_IFDISABLED) 1550 #define ND6_NDI_FLAGS 1551 #endif 1552 1553 void 1554 if_setup_inet6(const struct interface *ifp) 1555 { 1556 struct priv *priv; 1557 int s; 1558 #ifdef ND6_NDI_FLAGS 1559 struct in6_ndireq nd; 1560 int flags; 1561 #endif 1562 1563 priv = (struct priv *)ifp->ctx->priv; 1564 s = priv->pf_inet6_fd; 1565 1566 #ifdef ND6_NDI_FLAGS 1567 memset(&nd, 0, sizeof(nd)); 1568 strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname)); 1569 if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1) 1570 logerr("%s: SIOCGIFINFO_FLAGS", ifp->name); 1571 flags = (int)nd.ndi.flags; 1572 #endif 1573 1574 #ifdef ND6_IFF_AUTO_LINKLOCAL 1575 /* Unlike the kernel, 1576 * dhcpcd make make a stable private address. */ 1577 flags &= ~ND6_IFF_AUTO_LINKLOCAL; 1578 #endif 1579 1580 #ifdef ND6_IFF_PERFORMNUD 1581 /* NUD is kind of essential. */ 1582 flags |= ND6_IFF_PERFORMNUD; 1583 #endif 1584 1585 #ifdef ND6_IFF_IFDISABLED 1586 /* Ensure the interface is not disabled. */ 1587 flags &= ~ND6_IFF_IFDISABLED; 1588 #endif 1589 1590 /* 1591 * If not doing autoconf, don't disable the kernel from doing it. 1592 * If we need to, we should have another option actively disable it. 1593 */ 1594 #ifdef ND6_IFF_ACCEPT_RTADV 1595 if (ifp->options->options & DHCPCD_IPV6RS) 1596 flags &= ~ND6_IFF_ACCEPT_RTADV; 1597 #ifdef ND6_IFF_OVERRIDE_RTADV 1598 if (ifp->options->options & DHCPCD_IPV6RS) 1599 flags |= ND6_IFF_OVERRIDE_RTADV; 1600 #endif 1601 #endif 1602 1603 #ifdef ND6_NDI_FLAGS 1604 if (nd.ndi.flags != (uint32_t)flags) { 1605 nd.ndi.flags = (uint32_t)flags; 1606 if (ioctl(s, SIOCSIFINFO_FLAGS, &nd) == -1) 1607 logerr("%s: SIOCSIFINFO_FLAGS", ifp->name); 1608 } 1609 #endif 1610 1611 /* Enabling IPv6 by whatever means must be the 1612 * last action undertaken to ensure kernel RS and 1613 * LLADDR auto configuration are disabled where applicable. */ 1614 #ifdef SIOCIFAFATTACH 1615 if (af_attach(s, ifp, AF_INET6) == -1) 1616 logerr("%s: af_attach", ifp->name); 1617 #endif 1618 1619 #ifdef SIOCGIFXFLAGS 1620 if (set_ifxflags(s, ifp) == -1) 1621 logerr("%s: set_ifxflags", ifp->name); 1622 #endif 1623 1624 #if defined(IPV6CTL_ACCEPT_RTADV) && !defined(ND6_IFF_ACCEPT_RTADV) 1625 /* If we cannot control ra per interface, disable it globally. */ 1626 if (ifp->options->options & DHCPCD_IPV6RS) { 1627 int ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV); 1628 1629 if (ra == -1) { 1630 if (errno != ENOENT) 1631 logerr("IPV6CTL_ACCEPT_RTADV"); 1632 else if (ra != 0) 1633 if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) 1634 logerr("IPV6CTL_ACCEPT_RTADV"); 1635 } 1636 } 1637 #endif 1638 1639 #if defined(IPV6CTL_ACCEPT_RTADV) || defined(ND6_IFF_ACCEPT_RTADV) 1640 /* Flush the kernel knowledge of advertised routers 1641 * and prefixes so the kernel does not expire prefixes 1642 * and default routes we are trying to own. */ 1643 if (ifp->options->options & DHCPCD_IPV6RS) { 1644 struct in6_ifreq ifr; 1645 1646 memset(&ifr, 0, sizeof(ifr)); 1647 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 1648 if (ioctl(s, SIOCSRTRFLUSH_IN6, &ifr) == -1 && 1649 errno != ENOTSUP) 1650 logwarn("SIOCSRTRFLUSH_IN6"); 1651 if (ioctl(s, SIOCSPFXFLUSH_IN6, &ifr) == -1 && 1652 errno != ENOTSUP) 1653 logwarn("SIOCSPFXFLUSH_IN6"); 1654 } 1655 #endif 1656 } 1657 #endif 1658