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