1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2015 Roy Marples <roy (at) 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 <arpa/inet.h> 39 #include <net/bpf.h> 40 #include <net/if.h> 41 #include <net/if_dl.h> 42 #ifdef __FreeBSD__ /* Needed so that including netinet6/in6_var.h works */ 43 # include <net/if_var.h> 44 #endif 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 __DragonFly__ 53 # include <netproto/802_11/ieee80211_ioctl.h> 54 #elif __APPLE__ 55 /* FIXME: Add apple includes so we can work out SSID */ 56 #else 57 # include <net80211/ieee80211.h> 58 # include <net80211/ieee80211_ioctl.h> 59 #endif 60 61 #include <errno.h> 62 #include <fcntl.h> 63 #include <fnmatch.h> 64 #include <paths.h> 65 #include <stddef.h> 66 #include <stdio.h> 67 #include <stdlib.h> 68 #include <string.h> 69 #include <unistd.h> 70 71 #if defined(OpenBSD) && OpenBSD >= 201411 72 /* OpenBSD dropped the global setting from sysctl but left the #define 73 * which causes a EPERM error when trying to use it. 74 * I think both the error and keeping the define are wrong, so we #undef it. */ 75 #undef IPV6CTL_ACCEPT_RTADV 76 #endif 77 78 #include "config.h" 79 #include "common.h" 80 #include "dhcp.h" 81 #include "if.h" 82 #include "if-options.h" 83 #include "ipv4.h" 84 #include "ipv6.h" 85 #include "ipv6nd.h" 86 87 #include "bpf-filter.h" 88 89 #ifndef RT_ROUNDUP 90 #define RT_ROUNDUP(a) \ 91 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 92 #define RT_ADVANCE(x, n) (x += RT_ROUNDUP((n)->sa_len)) 93 #endif 94 95 #define COPYOUT(sin, sa) do { \ 96 if ((sa) && ((sa)->sa_family == AF_INET || (sa)->sa_family == 255)) \ 97 (sin) = ((struct sockaddr_in*)(void *)(sa))->sin_addr; \ 98 } while (0) 99 100 #define COPYOUT6(sin, sa) do { \ 101 if ((sa) && ((sa)->sa_family == AF_INET6 || (sa)->sa_family == 255)) \ 102 (sin) = ((struct sockaddr_in6*)(void *)(sa))->sin6_addr; \ 103 } while (0) 104 105 #ifndef CLLADDR 106 # define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen)) 107 #endif 108 109 int 110 if_init(__unused struct interface *iface) 111 { 112 /* BSD promotes secondary address by default */ 113 return 0; 114 } 115 116 int 117 if_conf(__unused struct interface *iface) 118 { 119 /* No extra checks needed on BSD */ 120 return 0; 121 } 122 123 int 124 if_openlinksocket(void) 125 { 126 127 #ifdef SOCK_CLOEXEC 128 return socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); 129 #else 130 int s, flags; 131 132 if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 133 return -1; 134 if ((flags = fcntl(s, F_GETFD, 0)) == -1 || 135 fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1) 136 { 137 close(s); 138 return -1; 139 } 140 if ((flags = fcntl(s, F_GETFL, 0)) == -1 || 141 fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) 142 { 143 close(s); 144 return -1; 145 } 146 return s; 147 #endif 148 } 149 150 #if defined(INET) || defined(INET6) 151 static void 152 if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp) 153 { 154 155 memset(sdl, 0, sizeof(*sdl)); 156 sdl->sdl_family = AF_LINK; 157 sdl->sdl_len = sizeof(*sdl); 158 sdl->sdl_nlen = sdl->sdl_alen = sdl->sdl_slen = 0; 159 sdl->sdl_index = (unsigned short)ifp->index; 160 } 161 #endif 162 163 static int 164 if_getssid1(const char *ifname, uint8_t *ssid) 165 { 166 int s, retval = -1; 167 #if defined(SIOCG80211NWID) 168 struct ifreq ifr; 169 struct ieee80211_nwid nwid; 170 #elif defined(IEEE80211_IOC_SSID) 171 struct ieee80211req ireq; 172 char nwid[IEEE80211_NWID_LEN + 1]; 173 #endif 174 175 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 176 return -1; 177 178 #if defined(SIOCG80211NWID) /* NetBSD */ 179 memset(&ifr, 0, sizeof(ifr)); 180 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 181 memset(&nwid, 0, sizeof(nwid)); 182 ifr.ifr_data = (void *)&nwid; 183 if (ioctl(s, SIOCG80211NWID, &ifr) == 0) { 184 if (ssid == NULL) 185 retval = nwid.i_len; 186 else if (nwid.i_len > IF_SSIDSIZE) { 187 errno = ENOBUFS; 188 retval = -1; 189 } else { 190 retval = nwid.i_len; 191 memcpy(ssid, nwid.i_nwid, nwid.i_len); 192 ssid[nwid.i_len] = '\0'; 193 } 194 } 195 #elif defined(IEEE80211_IOC_SSID) /* FreeBSD */ 196 memset(&ireq, 0, sizeof(ireq)); 197 strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); 198 ireq.i_type = IEEE80211_IOC_SSID; 199 ireq.i_val = -1; 200 memset(nwid, 0, sizeof(nwid)); 201 ireq.i_data = &nwid; 202 if (ioctl(s, SIOCG80211, &ireq) == 0) { 203 if (ssid == NULL) 204 retval = ireq.i_len; 205 else if (ireq.i_len > IF_SSIDSIZE) { 206 errno = ENOBUFS; 207 retval = -1; 208 } else { 209 retval = ireq.i_len; 210 memcpy(ssid, nwid, ireq.i_len); 211 ssid[ireq.i_len] = '\0'; 212 } 213 } 214 #endif 215 216 close(s); 217 return retval; 218 } 219 220 int 221 if_getssid(struct interface *ifp) 222 { 223 int r; 224 225 r = if_getssid1(ifp->name, ifp->ssid); 226 if (r != -1) 227 ifp->ssid_len = (unsigned int)r; 228 return r; 229 } 230 231 /* 232 * FreeBSD allows for Virtual Access Points 233 * We need to check if the interface is a Virtual Interface Master 234 * and if so, don't use it. 235 * This check is made by virtue of being a IEEE80211 device but 236 * returning the SSID gives an error. 237 */ 238 int 239 if_vimaster(const char *ifname) 240 { 241 int s, r; 242 struct ifmediareq ifmr; 243 244 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 245 return -1; 246 memset(&ifmr, 0, sizeof(ifmr)); 247 strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 248 r = ioctl(s, SIOCGIFMEDIA, &ifmr); 249 close(s); 250 if (r == -1) 251 return -1; 252 if (ifmr.ifm_status & IFM_AVALID && 253 IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211) 254 { 255 if (if_getssid1(ifname, NULL) == -1) 256 return 1; 257 } 258 return 0; 259 } 260 261 static void 262 get_addrs(int type, char *cp, struct sockaddr **sa) 263 { 264 int i; 265 266 for (i = 0; i < RTAX_MAX; i++) { 267 if (type & (1 << i)) { 268 sa[i] = (struct sockaddr *)cp; 269 RT_ADVANCE(cp, sa[i]); 270 } else 271 sa[i] = NULL; 272 } 273 } 274 275 #if defined(INET) || defined(INET6) 276 static struct interface * 277 if_findsdl(struct dhcpcd_ctx *ctx, struct sockaddr_dl *sdl) 278 { 279 280 if (sdl->sdl_nlen) { 281 char ifname[IF_NAMESIZE]; 282 memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen); 283 ifname[sdl->sdl_nlen] = '\0'; 284 return if_find(ctx->ifaces, ifname); 285 } 286 return NULL; 287 } 288 #endif 289 290 #ifdef INET 291 const char *if_pfname = "Berkley Packet Filter"; 292 293 int 294 if_openrawsocket(struct interface *ifp, uint16_t protocol) 295 { 296 struct dhcp_state *state; 297 int fd = -1; 298 struct ifreq ifr; 299 int ibuf_len = 0; 300 size_t buf_len; 301 struct bpf_version pv; 302 struct bpf_program pf; 303 #ifdef BIOCIMMEDIATE 304 int flags; 305 #endif 306 #ifdef _PATH_BPF 307 fd = open(_PATH_BPF, O_RDWR | O_CLOEXEC | O_NONBLOCK); 308 #else 309 char device[32]; 310 int n = 0; 311 312 do { 313 snprintf(device, sizeof(device), "/dev/bpf%d", n++); 314 fd = open(device, O_RDWR | O_CLOEXEC | O_NONBLOCK); 315 } while (fd == -1 && errno == EBUSY); 316 #endif 317 318 if (fd == -1) 319 return -1; 320 321 state = D_STATE(ifp); 322 323 memset(&pv, 0, sizeof(pv)); 324 if (ioctl(fd, BIOCVERSION, &pv) == -1) 325 goto eexit; 326 if (pv.bv_major != BPF_MAJOR_VERSION || 327 pv.bv_minor < BPF_MINOR_VERSION) { 328 logger(ifp->ctx, LOG_ERR, "BPF version mismatch - recompile"); 329 goto eexit; 330 } 331 332 memset(&ifr, 0, sizeof(ifr)); 333 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 334 if (ioctl(fd, BIOCSETIF, &ifr) == -1) 335 goto eexit; 336 337 /* Get the required BPF buffer length from the kernel. */ 338 if (ioctl(fd, BIOCGBLEN, &ibuf_len) == -1) 339 goto eexit; 340 buf_len = (size_t)ibuf_len; 341 if (state->buffer_size != buf_len) { 342 free(state->buffer); 343 state->buffer = malloc(buf_len); 344 if (state->buffer == NULL) 345 goto eexit; 346 state->buffer_size = buf_len; 347 state->buffer_len = state->buffer_pos = 0; 348 } 349 350 #ifdef BIOCIMMEDIATE 351 flags = 1; 352 if (ioctl(fd, BIOCIMMEDIATE, &flags) == -1) 353 goto eexit; 354 #endif 355 356 /* Install the DHCP filter */ 357 memset(&pf, 0, sizeof(pf)); 358 if (protocol == ETHERTYPE_ARP) { 359 pf.bf_insns = UNCONST(arp_bpf_filter); 360 pf.bf_len = arp_bpf_filter_len; 361 } else { 362 pf.bf_insns = UNCONST(dhcp_bpf_filter); 363 pf.bf_len = dhcp_bpf_filter_len; 364 } 365 if (ioctl(fd, BIOCSETF, &pf) == -1) 366 goto eexit; 367 368 return fd; 369 370 eexit: 371 free(state->buffer); 372 state->buffer = NULL; 373 close(fd); 374 return -1; 375 } 376 377 ssize_t 378 if_sendrawpacket(const struct interface *ifp, uint16_t protocol, 379 const void *data, size_t len, const uint8_t *dest_hw_addr) 380 { 381 struct iovec iov[2]; 382 struct ether_header hw; 383 int fd; 384 const struct dhcp_state *state; 385 386 memset(&hw, 0, ETHER_HDR_LEN); 387 if (dest_hw_addr) 388 memcpy(&hw.ether_dhost, dest_hw_addr, ETHER_ADDR_LEN); 389 else 390 memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN); 391 hw.ether_type = htons(protocol); 392 iov[0].iov_base = &hw; 393 iov[0].iov_len = ETHER_HDR_LEN; 394 iov[1].iov_base = UNCONST(data); 395 iov[1].iov_len = len; 396 state = D_CSTATE(ifp); 397 if (protocol == ETHERTYPE_ARP) 398 fd = state->arp_fd; 399 else 400 fd = state->raw_fd; 401 return writev(fd, iov, 2); 402 } 403 404 /* BPF requires that we read the entire buffer. 405 * So we pass the buffer in the API so we can loop on >1 packet. */ 406 ssize_t 407 if_readrawpacket(struct interface *ifp, uint16_t protocol, 408 void *data, size_t len, int *flags) 409 { 410 int fd; 411 struct bpf_hdr packet; 412 ssize_t bytes; 413 const unsigned char *payload; 414 struct dhcp_state *state; 415 416 state = D_STATE(ifp); 417 if (protocol == ETHERTYPE_ARP) 418 fd = state->arp_fd; 419 else 420 fd = state->raw_fd; 421 422 *flags = 0; 423 for (;;) { 424 if (state->buffer_len == 0) { 425 bytes = read(fd, state->buffer, state->buffer_size); 426 if (bytes == -1 || bytes == 0) 427 return bytes; 428 state->buffer_len = (size_t)bytes; 429 state->buffer_pos = 0; 430 } 431 bytes = -1; 432 memcpy(&packet, state->buffer + state->buffer_pos, 433 sizeof(packet)); 434 if (packet.bh_caplen != packet.bh_datalen) 435 goto next; /* Incomplete packet, drop. */ 436 if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen > 437 state->buffer_len) 438 goto next; /* Packet beyond buffer, drop. */ 439 payload = state->buffer + state->buffer_pos + 440 packet.bh_hdrlen + ETHER_HDR_LEN; 441 bytes = (ssize_t)packet.bh_caplen - ETHER_HDR_LEN; 442 if ((size_t)bytes > len) 443 bytes = (ssize_t)len; 444 memcpy(data, payload, (size_t)bytes); 445 next: 446 state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen + 447 packet.bh_caplen); 448 if (state->buffer_pos >= state->buffer_len) { 449 state->buffer_len = state->buffer_pos = 0; 450 *flags |= RAW_EOF; 451 } 452 if (bytes != -1) 453 return bytes; 454 } 455 } 456 457 int 458 if_address(const struct interface *ifp, const struct in_addr *address, 459 const struct in_addr *netmask, const struct in_addr *broadcast, 460 int action) 461 { 462 int s, r; 463 struct in_aliasreq ifra; 464 465 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 466 return -1; 467 468 memset(&ifra, 0, sizeof(ifra)); 469 strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name)); 470 471 #define ADDADDR(var, addr) do { \ 472 (var)->sin_family = AF_INET; \ 473 (var)->sin_len = sizeof(*(var)); \ 474 (var)->sin_addr = *(addr); \ 475 } while (/*CONSTCOND*/0) 476 ADDADDR(&ifra.ifra_addr, address); 477 ADDADDR(&ifra.ifra_mask, netmask); 478 if (action >= 0 && broadcast) 479 ADDADDR(&ifra.ifra_broadaddr, broadcast); 480 #undef ADDADDR 481 482 r = ioctl(s, 483 action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra); 484 close(s); 485 return r; 486 } 487 488 static int 489 if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm) 490 { 491 char *cp; 492 struct sockaddr *sa, *rti_info[RTAX_MAX]; 493 494 cp = (char *)(void *)(rtm + 1); 495 sa = (struct sockaddr *)(void *)cp; 496 if (sa->sa_family != AF_INET) 497 return -1; 498 if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) 499 return -1; 500 #ifdef RTF_CLONED 501 if (rtm->rtm_flags & RTF_CLONED) 502 return -1; 503 #endif 504 #ifdef RTF_LOCAL 505 if (rtm->rtm_flags & RTF_LOCAL) 506 return -1; 507 #endif 508 #ifdef RTF_BROADCAST 509 if (rtm->rtm_flags & RTF_BROADCAST) 510 return -1; 511 #endif 512 513 get_addrs(rtm->rtm_addrs, cp, rti_info); 514 memset(rt, 0, sizeof(*rt)); 515 COPYOUT(rt->dest, rti_info[RTAX_DST]); 516 if (rtm->rtm_addrs & RTA_NETMASK) 517 COPYOUT(rt->net, rti_info[RTAX_NETMASK]); 518 else 519 rt->net.s_addr = INADDR_BROADCAST; 520 COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]); 521 522 if (rtm->rtm_index) 523 rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index); 524 else if (rtm->rtm_addrs & RTA_IFP) { 525 struct sockaddr_dl *sdl; 526 527 sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP]; 528 rt->iface = if_findsdl(ctx, sdl); 529 } 530 /* If we don't have an interface and it's a host route, it maybe 531 * to a local ip via the loopback interface. */ 532 if (rt->iface == NULL && 533 !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY))) 534 { 535 struct ipv4_addr *ia; 536 537 if ((ia = ipv4_findaddr(ctx, &rt->dest))) 538 rt->iface = ia->iface; 539 } 540 541 return 0; 542 } 543 544 int 545 if_route(unsigned char cmd, const struct rt *rt) 546 { 547 const struct dhcp_state *state; 548 union sockunion { 549 struct sockaddr sa; 550 struct sockaddr_in sin; 551 struct sockaddr_dl sdl; 552 } su; 553 struct rtm 554 { 555 struct rt_msghdr hdr; 556 char buffer[sizeof(su) * RTAX_MAX]; 557 } rtm; 558 char *bp = rtm.buffer; 559 size_t l; 560 int s, retval; 561 562 if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 563 return -1; 564 565 #define ADDSU { \ 566 l = RT_ROUNDUP(su.sa.sa_len); \ 567 memcpy(bp, &su, l); \ 568 bp += l; \ 569 } 570 #define ADDADDR(addr) { \ 571 memset(&su, 0, sizeof(su)); \ 572 su.sin.sin_family = AF_INET; \ 573 su.sin.sin_len = sizeof(su.sin); \ 574 (&su.sin)->sin_addr = *addr; \ 575 ADDSU; \ 576 } 577 578 if (cmd != RTM_DELETE) 579 state = D_CSTATE(rt->iface); 580 else /* appease GCC */ 581 state = NULL; 582 memset(&rtm, 0, sizeof(rtm)); 583 rtm.hdr.rtm_version = RTM_VERSION; 584 rtm.hdr.rtm_seq = 1; 585 rtm.hdr.rtm_type = cmd; 586 rtm.hdr.rtm_addrs = RTA_DST; 587 if (cmd == RTM_ADD || cmd == RTM_CHANGE) 588 rtm.hdr.rtm_addrs |= RTA_GATEWAY; 589 rtm.hdr.rtm_flags = RTF_UP; 590 #ifdef RTF_PINNED 591 if (cmd != RTM_ADD) 592 rtm.hdr.rtm_flags |= RTF_PINNED; 593 #endif 594 595 if (cmd != RTM_DELETE) { 596 rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP; 597 /* None interface subnet routes are static. */ 598 if (rt->gate.s_addr != INADDR_ANY || 599 rt->net.s_addr != state->net.s_addr || 600 rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr)) 601 rtm.hdr.rtm_flags |= RTF_STATIC; 602 else { 603 #ifdef RTF_CLONING 604 rtm.hdr.rtm_flags |= RTF_CLONING; 605 #endif 606 #ifdef RTP_CONNECTED 607 rtm.hdr.rtm_priority = RTP_CONNECTED; 608 #endif 609 } 610 } 611 if (rt->net.s_addr == htonl(INADDR_BROADCAST) && 612 rt->gate.s_addr == htonl(INADDR_ANY)) 613 { 614 #ifdef RTF_CLONING 615 /* We add a cloning network route for a single host. 616 * Traffic to the host will generate a cloned route and the 617 * hardware address will resolve correctly. 618 * It might be more correct to use RTF_HOST instead of 619 * RTF_CLONING, and that does work, but some OS generate 620 * an arp warning diagnostic which we don't want to do. */ 621 rtm.hdr.rtm_flags |= RTF_CLONING; 622 rtm.hdr.rtm_addrs |= RTA_NETMASK; 623 #else 624 rtm.hdr.rtm_flags |= RTF_HOST; 625 #endif 626 } else if (rt->gate.s_addr == htonl(INADDR_LOOPBACK) && 627 rt->net.s_addr == htonl(INADDR_BROADCAST)) 628 { 629 rtm.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY; 630 /* Going via lo0 so remove the interface flags */ 631 if (cmd == RTM_ADD) 632 rtm.hdr.rtm_addrs &= ~(RTA_IFA | RTA_IFP); 633 } else { 634 rtm.hdr.rtm_addrs |= RTA_NETMASK; 635 if (rtm.hdr.rtm_flags & RTF_STATIC) 636 rtm.hdr.rtm_flags |= RTF_GATEWAY; 637 } 638 if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 639 !(rtm.hdr.rtm_flags & RTF_GATEWAY)) 640 rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP; 641 642 ADDADDR(&rt->dest); 643 if (rtm.hdr.rtm_addrs & RTA_GATEWAY) { 644 #ifdef RTF_CLONING 645 if ((rtm.hdr.rtm_flags & (RTF_HOST | RTF_CLONING) && 646 #else 647 if ((rtm.hdr.rtm_flags & RTF_HOST && 648 #endif 649 rt->gate.s_addr != htonl(INADDR_LOOPBACK)) || 650 !(rtm.hdr.rtm_flags & RTF_STATIC)) 651 { 652 if_linkaddr(&su.sdl, rt->iface); 653 ADDSU; 654 } else 655 ADDADDR(&rt->gate); 656 } 657 658 if (rtm.hdr.rtm_addrs & RTA_NETMASK) 659 ADDADDR(&rt->net); 660 661 if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 662 (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA))) 663 { 664 rtm.hdr.rtm_index = (unsigned short)rt->iface->index; 665 if (rtm.hdr.rtm_addrs & RTA_IFP) { 666 if_linkaddr(&su.sdl, rt->iface); 667 ADDSU; 668 } 669 670 if (rtm.hdr.rtm_addrs & RTA_IFA) 671 ADDADDR(&state->addr); 672 } 673 674 #undef ADDADDR 675 #undef ADDSU 676 677 rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm); 678 retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0; 679 close(s); 680 return retval; 681 } 682 683 int 684 if_initrt(struct interface *ifp) 685 { 686 struct rt_msghdr *rtm; 687 int mib[6]; 688 size_t needed; 689 char *buf, *p, *end; 690 struct rt rt; 691 692 ipv4_freerts(ifp->ctx->ipv4_kroutes); 693 694 mib[0] = CTL_NET; 695 mib[1] = PF_ROUTE; 696 mib[2] = 0; 697 mib[3] = AF_INET; 698 mib[4] = NET_RT_DUMP; 699 mib[5] = 0; 700 701 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 702 return -1; 703 if (needed == 0) 704 return 0; 705 if ((buf = malloc(needed)) == NULL) 706 return -1; 707 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 708 return -1; 709 710 end = buf + needed; 711 for (p = buf; p < end; p += rtm->rtm_msglen) { 712 rtm = (struct rt_msghdr *)(void *)p; 713 if (if_copyrt(ifp->ctx, &rt, rtm) == 0) 714 ipv4_handlert(ifp->ctx, RTM_ADD, &rt); 715 } 716 free(buf); 717 return 0; 718 } 719 720 #ifdef SIOCGIFAFLAG_IN 721 int 722 if_addrflags(const struct in_addr *addr, const struct interface *ifp) 723 { 724 int s, flags; 725 struct ifreq ifr; 726 struct sockaddr_in *sin; 727 728 s = socket(PF_INET, SOCK_DGRAM, 0); 729 flags = -1; 730 if (s != -1) { 731 memset(&ifr, 0, sizeof(ifr)); 732 strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name)); 733 sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr; 734 sin->sin_family = AF_INET; 735 sin->sin_addr = *addr; 736 if (ioctl(s, SIOCGIFAFLAG_IN, &ifr) != -1) 737 flags = ifr.ifr_addrflags; 738 close(s); 739 } 740 return flags; 741 } 742 #else 743 int 744 if_addrflags(__unused const struct in_addr *addr, 745 __unused const struct interface *ifp) 746 { 747 748 errno = ENOTSUP; 749 return 0; 750 } 751 #endif 752 #endif /* INET */ 753 754 #ifdef INET6 755 static void 756 ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex) 757 { 758 759 #ifdef __KAME__ 760 /* KAME based systems want to store the scope inside the sin6_addr 761 * for link local addreses */ 762 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { 763 uint16_t scope = htons((uint16_t)ifindex); 764 memcpy(&sin->sin6_addr.s6_addr[2], &scope, 765 sizeof(scope)); 766 } 767 sin->sin6_scope_id = 0; 768 #else 769 if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) 770 sin->sin6_scope_id = ifindex; 771 else 772 sin->sin6_scope_id = 0; 773 #endif 774 } 775 776 #ifdef __KAME__ 777 #define DESCOPE(ia6) do { \ 778 if (IN6_IS_ADDR_LINKLOCAL((ia6))) \ 779 (ia6)->s6_addr[2] = (ia6)->s6_addr[3] = '\0'; \ 780 } while (/*CONSTCOND */0) 781 #else 782 #define DESCOPE(ia6) 783 #endif 784 785 int 786 if_address6(const struct ipv6_addr *a, int action) 787 { 788 int s, r; 789 struct in6_aliasreq ifa; 790 struct in6_addr mask; 791 792 if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) 793 return -1; 794 795 memset(&ifa, 0, sizeof(ifa)); 796 strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name)); 797 /* 798 * We should not set IN6_IFF_TENTATIVE as the kernel should be 799 * able to work out if it's a new address or not. 800 * 801 * We should set IN6_IFF_AUTOCONF, but the kernel won't let us. 802 * This is probably a safety measure, but still it's not entirely right 803 * either. 804 */ 805 #if 0 806 if (a->autoconf) 807 ifa.ifra_flags |= IN6_IFF_AUTOCONF; 808 #endif 809 #ifdef IPV6_MANGETEMPADDR 810 if (a->flags & IPV6_AF_TEMPORARY) 811 ifa.ifra_flags |= IN6_IFF_TEMPORARY; 812 #endif 813 814 #define ADDADDR(v, addr) { \ 815 (v)->sin6_family = AF_INET6; \ 816 (v)->sin6_len = sizeof(*v); \ 817 (v)->sin6_addr = *addr; \ 818 } 819 820 ADDADDR(&ifa.ifra_addr, &a->addr); 821 ifa_scope(&ifa.ifra_addr, a->iface->index); 822 ipv6_mask(&mask, a->prefix_len); 823 ADDADDR(&ifa.ifra_prefixmask, &mask); 824 ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime; 825 ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime; 826 #undef ADDADDR 827 828 r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa); 829 close(s); 830 return r; 831 } 832 833 834 static int 835 if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm) 836 { 837 char *cp; 838 struct sockaddr *sa, *rti_info[RTAX_MAX]; 839 840 cp = (char *)(void *)(rtm + 1); 841 sa = (struct sockaddr *)(void *)cp; 842 if (sa->sa_family != AF_INET6) 843 return -1; 844 if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) 845 return -1; 846 #ifdef RTF_CLONED 847 if (rtm->rtm_flags & (RTF_CLONED | RTF_HOST)) 848 return -1; 849 #else 850 if (rtm->rtm_flags & RTF_HOST) 851 return -1; 852 #endif 853 #ifdef RTF_LOCAL 854 if (rtm->rtm_flags & RTF_LOCAL) 855 return -1; 856 #endif 857 858 get_addrs(rtm->rtm_addrs, cp, rti_info); 859 memset(rt, 0, sizeof(*rt)); 860 rt->flags = (unsigned int)rtm->rtm_flags; 861 COPYOUT6(rt->dest, rti_info[RTAX_DST]); 862 if (rtm->rtm_addrs & RTA_NETMASK) { 863 /* 864 * We need to zero out the struct beyond sin6_len and 865 * ensure it's valid. 866 * I have no idea what the invalid data is for, could be 867 * a kernel bug or actually used for something. 868 * Either way it needs to be zeroed out. 869 */ 870 struct sockaddr_in6 *sin6; 871 size_t e, i, len = 0, final = 0; 872 873 sin6 = (struct sockaddr_in6 *)(void *)rti_info[RTAX_NETMASK]; 874 rt->net = sin6->sin6_addr; 875 e = sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr); 876 if (e > sizeof(struct in6_addr)) 877 e = sizeof(struct in6_addr); 878 for (i = 0; i < e; i++) { 879 switch (rt->net.s6_addr[i] & 0xff) { 880 case 0xff: 881 /* We don't really want the length, 882 * just that it's valid */ 883 len++; 884 break; 885 case 0xfe: 886 case 0xfc: 887 case 0xf8: 888 case 0xf0: 889 case 0xe0: 890 case 0xc0: 891 case 0x80: 892 len++; 893 final = 1; 894 break; 895 default: 896 rt->net.s6_addr[i] = 0x00; 897 final = 1; 898 break; 899 } 900 if (final) 901 break; 902 } 903 if (len == 0) 904 i = 0; 905 while (i < sizeof(rt->net.s6_addr)) 906 rt->net.s6_addr[i++] = 0x00; 907 } else 908 ipv6_mask(&rt->net, 128); 909 COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]); 910 911 if (rtm->rtm_index) 912 rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index); 913 else if (rtm->rtm_addrs & RTA_IFP) { 914 struct sockaddr_dl *sdl; 915 916 sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP]; 917 rt->iface = if_findsdl(ctx, sdl); 918 } 919 /* If we don't have an interface and it's a host route, it maybe 920 * to a local ip via the loopback interface. */ 921 if (rt->iface == NULL && 922 !(~rtm->rtm_flags & (RTF_HOST | RTF_GATEWAY))) 923 { 924 struct ipv6_addr *ia; 925 926 if ((ia = ipv6_findaddr(ctx, &rt->dest, 0))) 927 rt->iface = ia->iface; 928 } 929 930 return 0; 931 } 932 933 int 934 if_route6(unsigned char cmd, const struct rt6 *rt) 935 { 936 union sockunion { 937 struct sockaddr sa; 938 struct sockaddr_in6 sin; 939 struct sockaddr_dl sdl; 940 } su; 941 struct rtm 942 { 943 struct rt_msghdr hdr; 944 char buffer[sizeof(su) * RTAX_MAX]; 945 } rtm; 946 char *bp = rtm.buffer; 947 size_t l; 948 int s, retval; 949 950 if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) 951 return -1; 952 953 #define ADDSU { \ 954 l = RT_ROUNDUP(su.sa.sa_len); \ 955 memcpy(bp, &su, l); \ 956 bp += l; \ 957 } 958 #define ADDADDRS(addr, scope) { \ 959 memset(&su, 0, sizeof(su)); \ 960 su.sin.sin6_family = AF_INET6; \ 961 su.sin.sin6_len = sizeof(su.sin); \ 962 (&su.sin)->sin6_addr = *addr; \ 963 if (scope) \ 964 ifa_scope(&su.sin, scope); \ 965 ADDSU; \ 966 } 967 #define ADDADDR(addr) ADDADDRS(addr, 0) 968 969 memset(&rtm, 0, sizeof(rtm)); 970 rtm.hdr.rtm_version = RTM_VERSION; 971 rtm.hdr.rtm_seq = 1; 972 rtm.hdr.rtm_type = cmd; 973 rtm.hdr.rtm_flags = RTF_UP | (int)rt->flags; 974 #ifdef RTF_PINNED 975 if (rtm.hdr.rtm_type != RTM_ADD) 976 rtm.hdr.rtm_flags |= RTF_PINNED; 977 #endif 978 rtm.hdr.rtm_addrs = RTA_DST | RTA_NETMASK; 979 /* None interface subnet routes are static. */ 980 if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) { 981 #ifdef RTF_CLONING 982 rtm.hdr.rtm_flags |= RTF_CLONING; 983 #endif 984 #ifdef RTP_CONNECTED 985 rtm.hdr.rtm_priority = RTP_CONNECTED; 986 #endif 987 } else 988 rtm.hdr.rtm_flags |= RTF_GATEWAY | RTF_STATIC; 989 990 if (cmd == RTM_ADD) 991 rtm.hdr.rtm_addrs |= RTA_GATEWAY; 992 if (cmd == RTM_ADD && !(rtm.hdr.rtm_flags & RTF_REJECT)) 993 rtm.hdr.rtm_addrs |= RTA_IFP | RTA_IFA; 994 995 ADDADDR(&rt->dest); 996 if (rtm.hdr.rtm_addrs & RTA_GATEWAY) { 997 if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) { 998 if_linkaddr(&su.sdl, rt->iface); 999 ADDSU; 1000 } else { 1001 ADDADDRS(&rt->gate, rt->iface->index); 1002 } 1003 } 1004 1005 if (rtm.hdr.rtm_addrs & RTA_NETMASK) 1006 ADDADDR(&rt->net); 1007 1008 if ((cmd == RTM_ADD || cmd == RTM_CHANGE) && 1009 (rtm.hdr.rtm_addrs & (RTA_IFP | RTA_IFA))) 1010 { 1011 rtm.hdr.rtm_index = (unsigned short)rt->iface->index; 1012 if (rtm.hdr.rtm_addrs & RTA_IFP) { 1013 if_linkaddr(&su.sdl, rt->iface); 1014 ADDSU; 1015 } 1016 1017 if (rtm.hdr.rtm_addrs & RTA_IFA) { 1018 const struct ipv6_addr *lla; 1019 1020 lla = ipv6_linklocal(rt->iface); 1021 if (lla == NULL) /* unlikely */ 1022 return -1; 1023 ADDADDRS(&lla->addr, rt->iface->index); 1024 } 1025 1026 if (rt->mtu) { 1027 rtm.hdr.rtm_inits |= RTV_MTU; 1028 rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu; 1029 } 1030 } 1031 1032 #undef ADDADDR 1033 #undef ADDSU 1034 1035 rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm); 1036 retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0; 1037 close(s); 1038 return retval; 1039 } 1040 1041 int 1042 if_initrt6(struct interface *ifp) 1043 { 1044 struct rt_msghdr *rtm; 1045 int mib[6]; 1046 size_t needed; 1047 char *buf, *p, *end; 1048 struct rt6 rt; 1049 1050 ipv6_freerts(&ifp->ctx->ipv6->kroutes); 1051 1052 mib[0] = CTL_NET; 1053 mib[1] = PF_ROUTE; 1054 mib[2] = 0; 1055 mib[3] = AF_INET6; 1056 mib[4] = NET_RT_DUMP; 1057 mib[5] = 0; 1058 1059 if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) 1060 return -1; 1061 if (needed == 0) 1062 return 0; 1063 if ((buf = malloc(needed)) == NULL) 1064 return -1; 1065 if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) 1066 return -1; 1067 1068 end = buf + needed; 1069 for (p = buf; p < end; p += rtm->rtm_msglen) { 1070 rtm = (struct rt_msghdr *)(void *)p; 1071 if (if_copyrt6(ifp->ctx, &rt, rtm) == 0) 1072 ipv6_handlert(ifp->ctx, RTM_ADD, &rt); 1073 } 1074 free(buf); 1075 return 0; 1076 } 1077 1078 int 1079 if_addrflags6(const struct in6_addr *addr, const struct interface *ifp) 1080 { 1081 int s, flags; 1082 struct in6_ifreq ifr6; 1083 1084 s = socket(PF_INET6, SOCK_DGRAM, 0); 1085 flags = -1; 1086 if (s != -1) { 1087 memset(&ifr6, 0, sizeof(ifr6)); 1088 strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name)); 1089 ifr6.ifr_addr.sin6_family = AF_INET6; 1090 ifr6.ifr_addr.sin6_addr = *addr; 1091 ifa_scope(&ifr6.ifr_addr, ifp->index); 1092 if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1) 1093 flags = ifr6.ifr_ifru.ifru_flags6; 1094 close(s); 1095 } 1096 return flags; 1097 } 1098 1099 int 1100 if_getlifetime6(struct ipv6_addr *ia) 1101 { 1102 int s, r; 1103 struct in6_ifreq ifr6; 1104 1105 s = socket(PF_INET6, SOCK_DGRAM, 0); 1106 r = -1; 1107 if (s != -1) { 1108 memset(&ifr6, 0, sizeof(ifr6)); 1109 strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name)); 1110 ifr6.ifr_addr.sin6_family = AF_INET6; 1111 ifr6.ifr_addr.sin6_addr = ia->addr; 1112 ifa_scope(&ifr6.ifr_addr, ia->iface->index); 1113 if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) != -1) { 1114 time_t t; 1115 struct in6_addrlifetime *lifetime; 1116 1117 t = time(NULL); 1118 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 1119 1120 if (lifetime->ia6t_preferred) 1121 ia->prefix_pltime = 1122 (uint32_t)(lifetime->ia6t_preferred - 1123 MIN(t, lifetime->ia6t_preferred)); 1124 else 1125 ia->prefix_pltime = ND6_INFINITE_LIFETIME; 1126 if (lifetime->ia6t_expire) { 1127 ia->prefix_vltime = 1128 (uint32_t)(lifetime->ia6t_expire - 1129 MIN(t, lifetime->ia6t_expire)); 1130 /* Calculate the created time */ 1131 get_monotonic(&ia->created); 1132 ia->created.tv_sec -= 1133 lifetime->ia6t_vltime - ia->prefix_vltime; 1134 } else 1135 ia->prefix_vltime = ND6_INFINITE_LIFETIME; 1136 1137 r = 0; 1138 } 1139 close(s); 1140 } 1141 return r; 1142 } 1143 #endif 1144 1145 int 1146 if_managelink(struct dhcpcd_ctx *ctx) 1147 { 1148 /* route and ifwatchd like a msg buf size of 2048 */ 1149 char msg[2048], *p, *e, *cp; 1150 ssize_t bytes; 1151 struct rt_msghdr *rtm; 1152 struct if_announcemsghdr *ifan; 1153 struct if_msghdr *ifm; 1154 struct ifa_msghdr *ifam; 1155 struct sockaddr *sa, *rti_info[RTAX_MAX]; 1156 int len; 1157 struct sockaddr_dl sdl; 1158 struct interface *ifp; 1159 #ifdef INET 1160 struct rt rt; 1161 #endif 1162 #ifdef INET6 1163 struct rt6 rt6; 1164 struct in6_addr ia6, net6; 1165 struct sockaddr_in6 *sin6; 1166 #endif 1167 #if (defined(INET) && defined(IN_IFF_TENTATIVE)) || defined(INET6) 1168 int ifa_flags; 1169 #endif 1170 1171 if ((bytes = read(ctx->link_fd, msg, sizeof(msg))) == -1) 1172 return -1; 1173 e = msg + bytes; 1174 for (p = msg; p < e; p += rtm->rtm_msglen) { 1175 rtm = (struct rt_msghdr *)(void *)p; 1176 // Ignore messages generated by us 1177 if (rtm->rtm_pid == getpid()) 1178 break; 1179 switch(rtm->rtm_type) { 1180 #ifdef RTM_IFANNOUNCE 1181 case RTM_IFANNOUNCE: 1182 ifan = (struct if_announcemsghdr *)(void *)p; 1183 switch(ifan->ifan_what) { 1184 case IFAN_ARRIVAL: 1185 dhcpcd_handleinterface(ctx, 1, 1186 ifan->ifan_name); 1187 break; 1188 case IFAN_DEPARTURE: 1189 dhcpcd_handleinterface(ctx, -1, 1190 ifan->ifan_name); 1191 break; 1192 } 1193 break; 1194 #endif 1195 case RTM_IFINFO: 1196 ifm = (struct if_msghdr *)(void *)p; 1197 ifp = if_findindex(ctx->ifaces, ifm->ifm_index); 1198 if (ifp == NULL) 1199 break; 1200 switch (ifm->ifm_data.ifi_link_state) { 1201 case LINK_STATE_DOWN: 1202 len = LINK_DOWN; 1203 break; 1204 case LINK_STATE_UP: 1205 len = LINK_UP; 1206 break; 1207 default: 1208 /* handle_carrier will re-load 1209 * the interface flags and check for 1210 * IFF_RUNNING as some drivers that 1211 * don't handle link state also don't 1212 * set IFF_RUNNING when this routing 1213 * message is generated. 1214 * As such, it is a race ...*/ 1215 len = LINK_UNKNOWN; 1216 break; 1217 } 1218 dhcpcd_handlecarrier(ctx, len, 1219 (unsigned int)ifm->ifm_flags, ifp->name); 1220 break; 1221 case RTM_ADD: 1222 case RTM_CHANGE: 1223 case RTM_DELETE: 1224 cp = (char *)(void *)(rtm + 1); 1225 sa = (struct sockaddr *)(void *)cp; 1226 switch (sa->sa_family) { 1227 #ifdef INET 1228 case AF_INET: 1229 if (if_copyrt(ctx, &rt, rtm) == 0) 1230 ipv4_handlert(ctx, rtm->rtm_type, &rt); 1231 break; 1232 #endif 1233 #ifdef INET6 1234 case AF_INET6: 1235 if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY)) 1236 break; 1237 /* 1238 * BSD caches host routes in the 1239 * routing table. 1240 * As such, we should be notified of 1241 * reachability by its existance 1242 * with a hardware address 1243 */ 1244 if (rtm->rtm_flags & (RTF_HOST)) { 1245 get_addrs(rtm->rtm_addrs, cp, rti_info); 1246 COPYOUT6(ia6, rti_info[RTAX_DST]); 1247 DESCOPE(&ia6); 1248 if (rti_info[RTAX_GATEWAY]->sa_family 1249 == AF_LINK) 1250 memcpy(&sdl, 1251 rti_info[RTAX_GATEWAY], 1252 sizeof(sdl)); 1253 else 1254 sdl.sdl_alen = 0; 1255 ipv6nd_neighbour(ctx, &ia6, 1256 rtm->rtm_type != RTM_DELETE && 1257 sdl.sdl_alen ? 1258 IPV6ND_REACHABLE : 0); 1259 break; 1260 } 1261 1262 if (if_copyrt6(ctx, &rt6, rtm) == 0) 1263 ipv6_handlert(ctx, rtm->rtm_type, &rt6); 1264 break; 1265 #endif 1266 } 1267 break; 1268 #ifdef RTM_CHGADDR 1269 case RTM_CHGADDR: /* FALLTHROUGH */ 1270 #endif 1271 case RTM_DELADDR: /* FALLTHROUGH */ 1272 case RTM_NEWADDR: 1273 ifam = (struct ifa_msghdr *)(void *)p; 1274 ifp = if_findindex(ctx->ifaces, ifam->ifam_index); 1275 if (ifp == NULL) 1276 break; 1277 cp = (char *)(void *)(ifam + 1); 1278 get_addrs(ifam->ifam_addrs, cp, rti_info); 1279 if (rti_info[RTAX_IFA] == NULL) 1280 break; 1281 switch (rti_info[RTAX_IFA]->sa_family) { 1282 case AF_LINK: 1283 #ifdef RTM_CHGADDR 1284 if (rtm->rtm_type != RTM_CHGADDR) 1285 break; 1286 #else 1287 if (rtm->rtm_type != RTM_NEWADDR) 1288 break; 1289 #endif 1290 memcpy(&sdl, rti_info[RTAX_IFA], 1291 rti_info[RTAX_IFA]->sa_len); 1292 dhcpcd_handlehwaddr(ctx, ifp->name, 1293 (const unsigned char*)CLLADDR(&sdl), 1294 sdl.sdl_alen); 1295 break; 1296 #ifdef INET 1297 case AF_INET: 1298 case 255: /* FIXME: Why 255? */ 1299 COPYOUT(rt.dest, rti_info[RTAX_IFA]); 1300 COPYOUT(rt.net, rti_info[RTAX_NETMASK]); 1301 COPYOUT(rt.gate, rti_info[RTAX_BRD]); 1302 if (rtm->rtm_type == RTM_NEWADDR) { 1303 ifa_flags = if_addrflags(&rt.dest, ifp); 1304 if (ifa_flags == -1) 1305 break; 1306 } else 1307 ifa_flags = 0; 1308 ipv4_handleifa(ctx, rtm->rtm_type, 1309 NULL, ifp->name, 1310 &rt.dest, &rt.net, &rt.gate, ifa_flags); 1311 break; 1312 #endif 1313 #ifdef INET6 1314 case AF_INET6: 1315 sin6 = (struct sockaddr_in6*)(void *) 1316 rti_info[RTAX_IFA]; 1317 ia6 = sin6->sin6_addr; 1318 DESCOPE(&ia6); 1319 sin6 = (struct sockaddr_in6*)(void *) 1320 rti_info[RTAX_NETMASK]; 1321 net6 = sin6->sin6_addr; 1322 DESCOPE(&net6); 1323 if (rtm->rtm_type == RTM_NEWADDR) { 1324 ifa_flags = if_addrflags6(&ia6, ifp); 1325 if (ifa_flags == -1) 1326 break; 1327 } else 1328 ifa_flags = 0; 1329 ipv6_handleifa(ctx, rtm->rtm_type, NULL, 1330 ifp->name, &ia6, ipv6_prefixlen(&net6), 1331 ifa_flags); 1332 break; 1333 #endif 1334 } 1335 break; 1336 } 1337 } 1338 return 0; 1339 } 1340 1341 #ifndef SYS_NMLN /* OSX */ 1342 # define SYS_NMLN 256 1343 #endif 1344 #ifndef HW_MACHINE_ARCH 1345 # ifdef HW_MODEL /* OpenBSD */ 1346 # define HW_MACHINE_ARCH HW_MODEL 1347 # endif 1348 #endif 1349 int 1350 if_machinearch(char *str, size_t len) 1351 { 1352 int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 1353 char march[SYS_NMLN]; 1354 size_t marchlen = sizeof(march); 1355 1356 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), 1357 march, &marchlen, NULL, 0) != 0) 1358 return -1; 1359 return snprintf(str, len, ":%s", march); 1360 } 1361 1362 #ifdef INET6 1363 #ifdef IPV6CTL_ACCEPT_RTADV 1364 #define get_inet6_sysctl(code) inet6_sysctl(code, 0, 0) 1365 #define set_inet6_sysctl(code, val) inet6_sysctl(code, val, 1) 1366 static int 1367 inet6_sysctl(int code, int val, int action) 1368 { 1369 int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 }; 1370 size_t size; 1371 1372 mib[3] = code; 1373 size = sizeof(val); 1374 if (action) { 1375 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), 1376 NULL, 0, &val, size) == -1) 1377 return -1; 1378 return 0; 1379 } 1380 if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &val, &size, NULL, 0) == -1) 1381 return -1; 1382 return val; 1383 } 1384 #endif 1385 1386 #ifdef IPV6_MANAGETEMPADDR 1387 #ifndef IPV6CTL_TEMPVLTIME 1388 #define get_inet6_sysctlbyname(code) inet6_sysctlbyname(code, 0, 0) 1389 #define set_inet6_sysctlbyname(code, val) inet6_sysctlbyname(code, val, 1) 1390 static int 1391 inet6_sysctlbyname(const char *name, int val, int action) 1392 { 1393 size_t size; 1394 1395 size = sizeof(val); 1396 if (action) { 1397 if (sysctlbyname(name, NULL, 0, &val, size) == -1) 1398 return -1; 1399 return 0; 1400 } 1401 if (sysctlbyname(name, &val, &size, NULL, 0) == -1) 1402 return -1; 1403 return val; 1404 } 1405 #endif 1406 1407 int 1408 ip6_use_tempaddr(__unused const char *ifname) 1409 { 1410 int val; 1411 1412 #ifdef IPV6CTL_USETEMPADDR 1413 val = get_inet6_sysctl(IPV6CTL_USETEMPADDR); 1414 #else 1415 val = get_inet6_sysctlbyname("net.inet6.ip6.use_tempaddr"); 1416 #endif 1417 return val == -1 ? 0 : val; 1418 } 1419 1420 int 1421 ip6_temp_preferred_lifetime(__unused const char *ifname) 1422 { 1423 int val; 1424 1425 #ifdef IPV6CTL_TEMPPLTIME 1426 val = get_inet6_sysctl(IPV6CTL_TEMPPLTIME); 1427 #else 1428 val = get_inet6_sysctlbyname("net.inet6.ip6.temppltime"); 1429 #endif 1430 return val < 0 ? TEMP_PREFERRED_LIFETIME : val; 1431 } 1432 1433 int 1434 ip6_temp_valid_lifetime(__unused const char *ifname) 1435 { 1436 int val; 1437 1438 #ifdef IPV6CTL_TEMPVLTIME 1439 val = get_inet6_sysctl(IPV6CTL_TEMPVLTIME); 1440 #else 1441 val = get_inet6_sysctlbyname("net.inet6.ip6.tempvltime"); 1442 #endif 1443 return val < 0 ? TEMP_VALID_LIFETIME : val; 1444 } 1445 #endif 1446 1447 #define del_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), -1) 1448 #define get_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), 0) 1449 #define set_if_nd6_flag(s, ifname, flag) if_nd6_flag((s), (ifp), (flag), 1) 1450 static int 1451 if_nd6_flag(int s, const struct interface *ifp, unsigned int flag, int set) 1452 { 1453 struct in6_ndireq nd; 1454 unsigned int oflags; 1455 1456 memset(&nd, 0, sizeof(nd)); 1457 strlcpy(nd.ifname, ifp->name, sizeof(nd.ifname)); 1458 if (ioctl(s, SIOCGIFINFO_IN6, &nd) == -1) 1459 return -1; 1460 if (set == 0) 1461 return nd.ndi.flags & flag ? 1 : 0; 1462 1463 oflags = nd.ndi.flags; 1464 if (set == -1) 1465 nd.ndi.flags &= ~flag; 1466 else 1467 nd.ndi.flags |= flag; 1468 if (oflags == nd.ndi.flags) 1469 return 0; 1470 return ioctl(s, SIOCSIFINFO_FLAGS, &nd); 1471 } 1472 1473 static int 1474 if_raflush(int s) 1475 { 1476 char dummy[IFNAMSIZ + 8]; 1477 1478 strlcpy(dummy, "lo0", sizeof(dummy)); 1479 if (ioctl(s, SIOCSRTRFLUSH_IN6, (void *)&dummy) == -1 || 1480 ioctl(s, SIOCSPFXFLUSH_IN6, (void *)&dummy) == -1) 1481 return -1; 1482 return 0; 1483 } 1484 1485 #ifdef SIOCIFAFATTACH 1486 static int 1487 af_attach(int s, const struct interface *ifp, int af) 1488 { 1489 struct if_afreq ifar; 1490 1491 strlcpy(ifar.ifar_name, ifp->name, sizeof(ifar.ifar_name)); 1492 ifar.ifar_af = af; 1493 return ioctl(s, SIOCIFAFATTACH, (void *)&ifar); 1494 } 1495 #endif 1496 1497 #ifdef SIOCGIFXFLAGS 1498 static int 1499 set_ifxflags(int s, const struct interface *ifp, int own) 1500 { 1501 struct ifreq ifr; 1502 int flags; 1503 1504 #ifndef IFXF_NOINET6 1505 /* No point in removing the no inet6 flag if it doesn't 1506 * exist and we're not owning inet6. */ 1507 if (! own) 1508 return 0; 1509 #endif 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 if (own) 1519 flags &= ~IFXF_AUTOCONF6; 1520 if (ifr.ifr_flags == flags) 1521 return 0; 1522 ifr.ifr_flags = flags; 1523 return ioctl(s, SIOCSIFXFLAGS, (void *)&ifr); 1524 } 1525 #endif 1526 1527 static int 1528 _if_checkipv6(int s, struct dhcpcd_ctx *ctx, 1529 const struct interface *ifp, int own) 1530 { 1531 int ra; 1532 1533 if (ifp) { 1534 #ifdef ND6_IFF_OVERRIDE_RTADV 1535 int override; 1536 #endif 1537 1538 #ifdef ND6_IFF_IFDISABLED 1539 if (del_if_nd6_flag(s, ifp, ND6_IFF_IFDISABLED) == -1) { 1540 logger(ifp->ctx, LOG_ERR, 1541 "%s: del_if_nd6_flag: ND6_IFF_IFDISABLED: %m", 1542 ifp->name); 1543 return -1; 1544 } 1545 #endif 1546 1547 #ifdef ND6_IFF_PERFORMNUD 1548 if (set_if_nd6_flag(s, ifp, ND6_IFF_PERFORMNUD) == -1) { 1549 logger(ifp->ctx, LOG_ERR, 1550 "%s: set_if_nd6_flag: ND6_IFF_PERFORMNUD: %m", 1551 ifp->name); 1552 return -1; 1553 } 1554 #endif 1555 1556 #ifdef ND6_IFF_AUTO_LINKLOCAL 1557 if (own) { 1558 int all; 1559 1560 all = get_if_nd6_flag(s, ifp, ND6_IFF_AUTO_LINKLOCAL); 1561 if (all == -1) 1562 logger(ifp->ctx, LOG_ERR, 1563 "%s: get_if_nd6_flag: " 1564 "ND6_IFF_AUTO_LINKLOCAL: %m", 1565 ifp->name); 1566 else if (all != 0) { 1567 logger(ifp->ctx, LOG_DEBUG, 1568 "%s: disabling Kernel IPv6 " 1569 "auto link-local support", 1570 ifp->name); 1571 if (del_if_nd6_flag(s, ifp, 1572 ND6_IFF_AUTO_LINKLOCAL) == -1) 1573 { 1574 logger(ifp->ctx, LOG_ERR, 1575 "%s: del_if_nd6_flag: " 1576 "ND6_IFF_AUTO_LINKLOCAL: %m", 1577 ifp->name); 1578 return -1; 1579 } 1580 } 1581 } 1582 #endif 1583 1584 #ifdef SIOCIFAFATTACH 1585 if (af_attach(s, ifp, AF_INET6) == -1) { 1586 logger(ifp->ctx, LOG_ERR, 1587 "%s: af_attach: %m", ifp->name); 1588 return 1; 1589 } 1590 #endif 1591 1592 #ifdef SIOCGIFXFLAGS 1593 if (set_ifxflags(s, ifp, own) == -1) { 1594 logger(ifp->ctx, LOG_ERR, 1595 "%s: set_ifxflags: %m", ifp->name); 1596 return -1; 1597 } 1598 #endif 1599 1600 #ifdef ND6_IFF_OVERRIDE_RTADV 1601 override = get_if_nd6_flag(s, ifp, ND6_IFF_OVERRIDE_RTADV); 1602 if (override == -1) 1603 logger(ifp->ctx, LOG_ERR, 1604 "%s: get_if_nd6_flag: ND6_IFF_OVERRIDE_RTADV: %m", 1605 ifp->name); 1606 else if (override == 0 && own) { 1607 if (set_if_nd6_flag(s, ifp, ND6_IFF_OVERRIDE_RTADV) 1608 == -1) 1609 logger(ifp->ctx, LOG_ERR, 1610 "%s: set_if_nd6_flag: " 1611 "ND6_IFF_OVERRIDE_RTADV: %m", 1612 ifp->name); 1613 else 1614 override = 1; 1615 } 1616 #endif 1617 1618 #ifdef ND6_IFF_ACCEPT_RTADV 1619 ra = get_if_nd6_flag(s, ifp, ND6_IFF_ACCEPT_RTADV); 1620 if (ra == -1) 1621 logger(ifp->ctx, LOG_ERR, 1622 "%s: get_if_nd6_flag: ND6_IFF_ACCEPT_RTADV: %m", 1623 ifp->name); 1624 else if (ra != 0 && own) { 1625 logger(ifp->ctx, LOG_DEBUG, 1626 "%s: disabling Kernel IPv6 RA support", 1627 ifp->name); 1628 if (del_if_nd6_flag(s, ifp, ND6_IFF_ACCEPT_RTADV) 1629 == -1) 1630 logger(ifp->ctx, LOG_ERR, 1631 "%s: del_if_nd6_flag: " 1632 "ND6_IFF_ACCEPT_RTADV: %m", 1633 ifp->name); 1634 else 1635 ra = 0; 1636 } else if (ra == 0 && !own) 1637 logger(ifp->ctx, LOG_WARNING, 1638 "%s: IPv6 kernel autoconf disabled", ifp->name); 1639 #ifdef ND6_IFF_OVERRIDE_RTADV 1640 if (override == 0 && ra) 1641 return ctx->ra_global; 1642 #endif 1643 return ra; 1644 #else 1645 return ctx->ra_global; 1646 #endif 1647 } 1648 1649 #ifdef IPV6CTL_ACCEPT_RTADV 1650 ra = get_inet6_sysctl(IPV6CTL_ACCEPT_RTADV); 1651 if (ra == -1) 1652 /* The sysctl probably doesn't exist, but this isn't an 1653 * error as such so just log it and continue */ 1654 logger(ifp->ctx, errno == ENOENT ? LOG_DEBUG : LOG_WARNING, 1655 "IPV6CTL_ACCEPT_RTADV: %m"); 1656 else if (ra != 0 && own) { 1657 logger(ifp->ctx, LOG_DEBUG, "disabling Kernel IPv6 RA support"); 1658 if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 0) == -1) { 1659 logger(ifp->ctx, LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m"); 1660 return ra; 1661 } 1662 ra = 0; 1663 #else 1664 ra = 0; 1665 if (own) { 1666 #endif 1667 /* Flush the kernel knowledge of advertised routers 1668 * and prefixes so the kernel does not expire prefixes 1669 * and default routes we are trying to own. */ 1670 if (if_raflush(s) == -1) 1671 logger(ctx, LOG_WARNING, "if_raflush: %m"); 1672 } 1673 1674 ctx->ra_global = ra; 1675 return ra; 1676 } 1677 1678 int 1679 if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own) 1680 { 1681 int s, r; 1682 1683 if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1) 1684 return -1; 1685 r = _if_checkipv6(s, ctx, ifp, own); 1686 close(s); 1687 return r; 1688 } 1689 #endif 1690