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