1 /* $OpenBSD: frontend.c,v 1.60 2021/11/28 12:51:52 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2017 Florian Obser <florian@openbsd.org> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 #include <sys/types.h> 22 #include <sys/ioctl.h> 23 #include <sys/queue.h> 24 #include <sys/socket.h> 25 #include <sys/syslog.h> 26 #include <sys/uio.h> 27 28 #include <net/if.h> 29 #include <net/if_dl.h> 30 #include <net/if_types.h> 31 #include <net/route.h> 32 33 #include <arpa/inet.h> 34 35 #include <netinet/in.h> 36 #include <netinet/if_ether.h> 37 #include <netinet6/nd6.h> 38 #include <netinet6/in6_var.h> 39 #include <netinet/ip6.h> 40 #include <netinet6/ip6_var.h> 41 #include <netinet/icmp6.h> 42 43 #include <errno.h> 44 #include <event.h> 45 #include <ifaddrs.h> 46 #include <imsg.h> 47 #include <pwd.h> 48 #include <signal.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <unistd.h> 53 54 #include "log.h" 55 #include "slaacd.h" 56 #include "frontend.h" 57 #include "control.h" 58 59 #define ROUTE_SOCKET_BUF_SIZE 16384 60 #define ALLROUTER "ff02::2" 61 62 struct icmp6_ev { 63 struct event ev; 64 uint8_t answer[1500]; 65 struct msghdr rcvmhdr; 66 struct iovec rcviov[1]; 67 struct sockaddr_in6 from; 68 int refcnt; 69 }; 70 71 struct iface { 72 LIST_ENTRY(iface) entries; 73 struct icmp6_ev *icmp6ev; 74 struct ether_addr hw_address; 75 uint32_t if_index; 76 int rdomain; 77 int send_solicitation; 78 }; 79 80 __dead void frontend_shutdown(void); 81 void frontend_sig_handler(int, short, void *); 82 void update_iface(uint32_t, char*); 83 void frontend_startup(void); 84 void route_receive(int, short, void *); 85 void handle_route_message(struct rt_msghdr *, struct sockaddr **); 86 void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 87 void icmp6_receive(int, short, void *); 88 int get_flags(char *); 89 int get_xflags(char *); 90 int get_ifrdomain(char *); 91 struct iface *get_iface_by_id(uint32_t); 92 void remove_iface(uint32_t); 93 struct icmp6_ev *get_icmp6ev_by_rdomain(int); 94 void unref_icmp6ev(struct iface *); 95 void set_icmp6sock(int, int); 96 void send_solicitation(uint32_t); 97 #ifndef SMALL 98 void update_autoconf_addresses(uint32_t, char*); 99 const char *flags_to_str(int); 100 #endif /* SMALL */ 101 102 LIST_HEAD(, iface) interfaces; 103 static struct imsgev *iev_main; 104 static struct imsgev *iev_engine; 105 struct event ev_route; 106 struct msghdr sndmhdr; 107 struct iovec sndiov[4]; 108 struct nd_router_solicit rs; 109 struct nd_opt_hdr nd_opt_hdr; 110 struct ether_addr nd_opt_source_link_addr; 111 struct sockaddr_in6 dst; 112 int ioctlsock; 113 114 void 115 frontend_sig_handler(int sig, short event, void *bula) 116 { 117 /* 118 * Normal signal handler rules don't apply because libevent 119 * decouples for us. 120 */ 121 122 switch (sig) { 123 case SIGINT: 124 case SIGTERM: 125 frontend_shutdown(); 126 default: 127 fatalx("unexpected signal"); 128 } 129 } 130 131 void 132 frontend(int debug, int verbose) 133 { 134 struct event ev_sigint, ev_sigterm; 135 struct passwd *pw; 136 struct in6_pktinfo *pi; 137 struct cmsghdr *cm; 138 size_t sndcmsglen; 139 int hoplimit = 255; 140 uint8_t *sndcmsgbuf; 141 142 log_init(debug, LOG_DAEMON); 143 log_setverbose(verbose); 144 145 if ((pw = getpwnam(SLAACD_USER)) == NULL) 146 fatal("getpwnam"); 147 148 if (chdir("/") == -1) 149 fatal("chdir(\"/\")"); 150 151 if (unveil("/", "") == -1) 152 fatal("unveil /"); 153 if (unveil(NULL, NULL) == -1) 154 fatal("unveil"); 155 156 setproctitle("%s", "frontend"); 157 log_procinit("frontend"); 158 159 if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1) 160 fatal("socket"); 161 162 if (setgroups(1, &pw->pw_gid) || 163 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 164 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 165 fatal("can't drop privileges"); 166 167 if (pledge("stdio unix recvfd route", NULL) == -1) 168 fatal("pledge"); 169 170 event_init(); 171 172 /* Setup signal handler. */ 173 signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL); 174 signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL); 175 signal_add(&ev_sigint, NULL); 176 signal_add(&ev_sigterm, NULL); 177 signal(SIGPIPE, SIG_IGN); 178 signal(SIGHUP, SIG_IGN); 179 180 /* Setup pipe and event handler to the parent process. */ 181 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 182 fatal(NULL); 183 imsg_init(&iev_main->ibuf, 3); 184 iev_main->handler = frontend_dispatch_main; 185 iev_main->events = EV_READ; 186 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 187 iev_main->handler, iev_main); 188 event_add(&iev_main->ev, NULL); 189 190 sndcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 191 CMSG_SPACE(sizeof(int)); 192 193 if ((sndcmsgbuf = malloc(sndcmsglen)) == NULL) 194 fatal("malloc"); 195 196 rs.nd_rs_type = ND_ROUTER_SOLICIT; 197 rs.nd_rs_code = 0; 198 rs.nd_rs_cksum = 0; 199 rs.nd_rs_reserved = 0; 200 201 nd_opt_hdr.nd_opt_type = ND_OPT_SOURCE_LINKADDR; 202 nd_opt_hdr.nd_opt_len = 1; 203 204 memset(&dst, 0, sizeof(dst)); 205 dst.sin6_family = AF_INET6; 206 if (inet_pton(AF_INET6, ALLROUTER, &dst.sin6_addr.s6_addr) != 1) 207 fatal("inet_pton"); 208 209 sndmhdr.msg_namelen = sizeof(struct sockaddr_in6); 210 sndmhdr.msg_iov = sndiov; 211 sndmhdr.msg_iovlen = 3; 212 sndmhdr.msg_control = (caddr_t)sndcmsgbuf; 213 sndmhdr.msg_controllen = sndcmsglen; 214 215 sndmhdr.msg_name = (caddr_t)&dst; 216 sndmhdr.msg_iov[0].iov_base = (caddr_t)&rs; 217 sndmhdr.msg_iov[0].iov_len = sizeof(rs); 218 sndmhdr.msg_iov[1].iov_base = (caddr_t)&nd_opt_hdr; 219 sndmhdr.msg_iov[1].iov_len = sizeof(nd_opt_hdr); 220 sndmhdr.msg_iov[2].iov_base = (caddr_t)&nd_opt_source_link_addr; 221 sndmhdr.msg_iov[2].iov_len = sizeof(nd_opt_source_link_addr); 222 223 cm = CMSG_FIRSTHDR(&sndmhdr); 224 225 cm->cmsg_level = IPPROTO_IPV6; 226 cm->cmsg_type = IPV6_PKTINFO; 227 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 228 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 229 memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); 230 pi->ipi6_ifindex = 0; 231 232 cm = CMSG_NXTHDR(&sndmhdr, cm); 233 cm->cmsg_level = IPPROTO_IPV6; 234 cm->cmsg_type = IPV6_HOPLIMIT; 235 cm->cmsg_len = CMSG_LEN(sizeof(int)); 236 memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int)); 237 238 LIST_INIT(&interfaces); 239 240 event_dispatch(); 241 242 frontend_shutdown(); 243 } 244 245 __dead void 246 frontend_shutdown(void) 247 { 248 /* Close pipes. */ 249 msgbuf_write(&iev_engine->ibuf.w); 250 msgbuf_clear(&iev_engine->ibuf.w); 251 close(iev_engine->ibuf.fd); 252 msgbuf_write(&iev_main->ibuf.w); 253 msgbuf_clear(&iev_main->ibuf.w); 254 close(iev_main->ibuf.fd); 255 256 free(iev_engine); 257 free(iev_main); 258 259 log_info("frontend exiting"); 260 exit(0); 261 } 262 263 int 264 frontend_imsg_compose_main(int type, pid_t pid, void *data, 265 uint16_t datalen) 266 { 267 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, 268 datalen)); 269 } 270 271 int 272 frontend_imsg_compose_engine(int type, uint32_t peerid, pid_t pid, 273 void *data, uint16_t datalen) 274 { 275 return (imsg_compose_event(iev_engine, type, peerid, pid, -1, 276 data, datalen)); 277 } 278 279 void 280 frontend_dispatch_main(int fd, short event, void *bula) 281 { 282 struct imsg imsg; 283 struct imsgev *iev = bula; 284 struct imsgbuf *ibuf = &iev->ibuf; 285 ssize_t n; 286 int shut = 0, icmp6sock, rdomain; 287 288 if (event & EV_READ) { 289 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 290 fatal("imsg_read error"); 291 if (n == 0) /* Connection closed. */ 292 shut = 1; 293 } 294 if (event & EV_WRITE) { 295 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 296 fatal("msgbuf_write"); 297 if (n == 0) /* Connection closed. */ 298 shut = 1; 299 } 300 301 for (;;) { 302 if ((n = imsg_get(ibuf, &imsg)) == -1) 303 fatal("%s: imsg_get error", __func__); 304 if (n == 0) /* No more messages. */ 305 break; 306 307 switch (imsg.hdr.type) { 308 case IMSG_SOCKET_IPC: 309 /* 310 * Setup pipe and event handler to the engine 311 * process. 312 */ 313 if (iev_engine) 314 fatalx("%s: received unexpected imsg fd " 315 "to frontend", __func__); 316 317 if ((fd = imsg.fd) == -1) 318 fatalx("%s: expected to receive imsg fd to " 319 "frontend but didn't receive any", 320 __func__); 321 322 iev_engine = malloc(sizeof(struct imsgev)); 323 if (iev_engine == NULL) 324 fatal(NULL); 325 326 imsg_init(&iev_engine->ibuf, fd); 327 iev_engine->handler = frontend_dispatch_engine; 328 iev_engine->events = EV_READ; 329 330 event_set(&iev_engine->ev, iev_engine->ibuf.fd, 331 iev_engine->events, iev_engine->handler, iev_engine); 332 event_add(&iev_engine->ev, NULL); 333 break; 334 case IMSG_ICMP6SOCK: 335 if ((icmp6sock = imsg.fd) == -1) 336 fatalx("%s: expected to receive imsg " 337 "ICMPv6 fd but didn't receive any", 338 __func__); 339 if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain)) 340 fatalx("%s: IMSG_ICMP6SOCK wrong length: " 341 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 342 memcpy(&rdomain, imsg.data, sizeof(rdomain)); 343 set_icmp6sock(icmp6sock, rdomain); 344 break; 345 case IMSG_ROUTESOCK: 346 if ((fd = imsg.fd) == -1) 347 fatalx("%s: expected to receive imsg " 348 "routesocket fd but didn't receive any", 349 __func__); 350 event_set(&ev_route, fd, EV_READ | EV_PERSIST, 351 route_receive, NULL); 352 break; 353 case IMSG_STARTUP: 354 frontend_startup(); 355 break; 356 #ifndef SMALL 357 case IMSG_CONTROLFD: 358 if ((fd = imsg.fd) == -1) 359 fatalx("%s: expected to receive imsg " 360 "control fd but didn't receive any", 361 __func__); 362 /* Listen on control socket. */ 363 control_listen(fd); 364 break; 365 case IMSG_CTL_END: 366 control_imsg_relay(&imsg); 367 break; 368 #endif /* SMALL */ 369 default: 370 log_debug("%s: error handling imsg %d", __func__, 371 imsg.hdr.type); 372 break; 373 } 374 imsg_free(&imsg); 375 } 376 if (!shut) 377 imsg_event_add(iev); 378 else { 379 /* This pipe is dead. Remove its event handler. */ 380 event_del(&iev->ev); 381 event_loopexit(NULL); 382 } 383 } 384 385 void 386 frontend_dispatch_engine(int fd, short event, void *bula) 387 { 388 struct imsgev *iev = bula; 389 struct imsgbuf *ibuf = &iev->ibuf; 390 struct imsg imsg; 391 ssize_t n; 392 int shut = 0; 393 uint32_t if_index; 394 395 if (event & EV_READ) { 396 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 397 fatal("imsg_read error"); 398 if (n == 0) /* Connection closed. */ 399 shut = 1; 400 } 401 if (event & EV_WRITE) { 402 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 403 fatal("msgbuf_write"); 404 if (n == 0) /* Connection closed. */ 405 shut = 1; 406 } 407 408 for (;;) { 409 if ((n = imsg_get(ibuf, &imsg)) == -1) 410 fatal("%s: imsg_get error", __func__); 411 if (n == 0) /* No more messages. */ 412 break; 413 414 switch (imsg.hdr.type) { 415 #ifndef SMALL 416 case IMSG_CTL_END: 417 case IMSG_CTL_SHOW_INTERFACE_INFO: 418 case IMSG_CTL_SHOW_INTERFACE_INFO_RA: 419 case IMSG_CTL_SHOW_INTERFACE_INFO_RA_PREFIX: 420 case IMSG_CTL_SHOW_INTERFACE_INFO_RA_RDNS: 421 case IMSG_CTL_SHOW_INTERFACE_INFO_RA_DNSSL: 422 case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSALS: 423 case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSAL: 424 case IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSALS: 425 case IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSAL: 426 case IMSG_CTL_SHOW_INTERFACE_INFO_RDNS_PROPOSALS: 427 case IMSG_CTL_SHOW_INTERFACE_INFO_RDNS_PROPOSAL: 428 control_imsg_relay(&imsg); 429 break; 430 #endif /* SMALL */ 431 case IMSG_CTL_SEND_SOLICITATION: 432 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 433 fatalx("%s: IMSG_CTL_SEND_SOLICITATION wrong " 434 "length: %lu", __func__, 435 IMSG_DATA_SIZE(imsg)); 436 if_index = *((uint32_t *)imsg.data); 437 send_solicitation(if_index); 438 break; 439 default: 440 log_debug("%s: error handling imsg %d", __func__, 441 imsg.hdr.type); 442 break; 443 } 444 imsg_free(&imsg); 445 } 446 if (!shut) 447 imsg_event_add(iev); 448 else { 449 /* This pipe is dead. Remove its event handler. */ 450 event_del(&iev->ev); 451 event_loopexit(NULL); 452 } 453 } 454 455 int 456 get_flags(char *if_name) 457 { 458 struct ifreq ifr; 459 460 strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 461 if (ioctl(ioctlsock, SIOCGIFFLAGS, (caddr_t)&ifr) == -1) { 462 log_warn("SIOCGIFFLAGS"); 463 return -1; 464 } 465 return ifr.ifr_flags; 466 } 467 468 int 469 get_xflags(char *if_name) 470 { 471 struct ifreq ifr; 472 473 strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 474 if (ioctl(ioctlsock, SIOCGIFXFLAGS, (caddr_t)&ifr) == -1) { 475 log_warn("SIOCGIFXFLAGS"); 476 return -1; 477 } 478 return ifr.ifr_flags; 479 } 480 481 int 482 get_ifrdomain(char *if_name) 483 { 484 struct ifreq ifr; 485 486 strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 487 if (ioctl(ioctlsock, SIOCGIFRDOMAIN, (caddr_t)&ifr) == -1) { 488 log_warn("SIOCGIFRDOMAIN"); 489 return -1; 490 } 491 return ifr.ifr_rdomainid; 492 } 493 494 void 495 update_iface(uint32_t if_index, char* if_name) 496 { 497 struct iface *iface; 498 struct ifaddrs *ifap, *ifa; 499 struct imsg_ifinfo imsg_ifinfo; 500 struct sockaddr_dl *sdl; 501 struct sockaddr_in6 *sin6; 502 int flags, xflags, ifrdomain; 503 504 if ((flags = get_flags(if_name)) == -1 || (xflags = 505 get_xflags(if_name)) == -1) 506 return; 507 508 if (!(xflags & (IFXF_AUTOCONF6 | IFXF_AUTOCONF6TEMP))) 509 return; 510 511 if((ifrdomain = get_ifrdomain(if_name)) == -1) 512 return; 513 514 iface = get_iface_by_id(if_index); 515 516 if (iface != NULL) { 517 if (iface->rdomain != ifrdomain) { 518 unref_icmp6ev(iface); 519 iface->rdomain = ifrdomain; 520 iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain); 521 } 522 } else { 523 if ((iface = calloc(1, sizeof(*iface))) == NULL) 524 fatal("calloc"); 525 iface->if_index = if_index; 526 iface->rdomain = ifrdomain; 527 iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain); 528 529 LIST_INSERT_HEAD(&interfaces, iface, entries); 530 } 531 532 memset(&imsg_ifinfo, 0, sizeof(imsg_ifinfo)); 533 534 imsg_ifinfo.if_index = if_index; 535 imsg_ifinfo.rdomain = ifrdomain; 536 imsg_ifinfo.running = (flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | 537 IFF_RUNNING); 538 imsg_ifinfo.autoconf = (xflags & IFXF_AUTOCONF6); 539 imsg_ifinfo.temporary = (xflags & IFXF_AUTOCONF6TEMP); 540 imsg_ifinfo.soii = !(xflags & IFXF_INET6_NOSOII); 541 542 if (getifaddrs(&ifap) != 0) 543 fatal("getifaddrs"); 544 545 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 546 if (strcmp(if_name, ifa->ifa_name) != 0) 547 continue; 548 if (ifa->ifa_addr == NULL) 549 continue; 550 551 switch(ifa->ifa_addr->sa_family) { 552 case AF_LINK: 553 imsg_ifinfo.link_state = 554 ((struct if_data *)ifa->ifa_data)->ifi_link_state; 555 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 556 if (sdl->sdl_type != IFT_ETHER || 557 sdl->sdl_alen != ETHER_ADDR_LEN) 558 continue; 559 memcpy(iface->hw_address.ether_addr_octet, 560 LLADDR(sdl), ETHER_ADDR_LEN); 561 memcpy(imsg_ifinfo.hw_address.ether_addr_octet, 562 LLADDR(sdl), ETHER_ADDR_LEN); 563 case AF_INET6: 564 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 565 #ifdef __KAME__ 566 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && 567 sin6->sin6_scope_id == 0) { 568 sin6->sin6_scope_id = ntohs(*(u_int16_t *) 569 &sin6->sin6_addr.s6_addr[2]); 570 sin6->sin6_addr.s6_addr[2] = 571 sin6->sin6_addr.s6_addr[3] = 0; 572 } 573 #endif 574 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 575 memcpy(&imsg_ifinfo.ll_address, sin6, 576 sizeof(imsg_ifinfo.ll_address)); 577 break; 578 default: 579 break; 580 } 581 } 582 583 freeifaddrs(ifap); 584 585 frontend_imsg_compose_main(IMSG_UPDATE_IF, 0, &imsg_ifinfo, 586 sizeof(imsg_ifinfo)); 587 } 588 589 #ifndef SMALL 590 void 591 update_autoconf_addresses(uint32_t if_index, char* if_name) 592 { 593 struct in6_ifreq ifr6; 594 struct imsg_addrinfo imsg_addrinfo; 595 struct ifaddrs *ifap, *ifa; 596 struct in6_addrlifetime *lifetime; 597 struct sockaddr_in6 *sin6; 598 time_t t; 599 int xflags; 600 601 if ((xflags = get_xflags(if_name)) == -1) 602 return; 603 604 if (!(xflags & (IFXF_AUTOCONF6 | IFXF_AUTOCONF6TEMP))) 605 return; 606 607 memset(&imsg_addrinfo, 0, sizeof(imsg_addrinfo)); 608 imsg_addrinfo.if_index = if_index; 609 610 if (getifaddrs(&ifap) != 0) 611 fatal("getifaddrs"); 612 613 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 614 if (strcmp(if_name, ifa->ifa_name) != 0) 615 continue; 616 if (ifa->ifa_addr == NULL) 617 continue; 618 619 if (ifa->ifa_addr->sa_family != AF_INET6) 620 continue; 621 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 622 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 623 continue; 624 625 log_debug("%s: IP: %s", __func__, sin6_to_str(sin6)); 626 imsg_addrinfo.addr = *sin6; 627 628 memset(&ifr6, 0, sizeof(ifr6)); 629 strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 630 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 631 632 if (ioctl(ioctlsock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) == -1) { 633 log_warn("SIOCGIFAFLAG_IN6"); 634 continue; 635 } 636 637 if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | 638 IN6_IFF_TEMPORARY))) 639 continue; 640 641 imsg_addrinfo.temporary = ifr6.ifr_ifru.ifru_flags6 & 642 IN6_IFF_TEMPORARY ? 1 : 0; 643 644 memset(&ifr6, 0, sizeof(ifr6)); 645 strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 646 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 647 648 if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) == 649 -1) { 650 log_warn("SIOCGIFNETMASK_IN6"); 651 continue; 652 } 653 654 imsg_addrinfo.mask = ((struct sockaddr_in6 *)&ifr6.ifr_addr) 655 ->sin6_addr; 656 657 memset(&ifr6, 0, sizeof(ifr6)); 658 strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 659 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 660 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 661 662 if (ioctl(ioctlsock, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) == 663 -1) { 664 log_warn("SIOCGIFALIFETIME_IN6"); 665 continue; 666 } 667 668 imsg_addrinfo.vltime = ND6_INFINITE_LIFETIME; 669 imsg_addrinfo.pltime = ND6_INFINITE_LIFETIME; 670 t = time(NULL); 671 672 if (lifetime->ia6t_preferred) 673 imsg_addrinfo.pltime = lifetime->ia6t_preferred < t ? 0 674 : lifetime->ia6t_preferred - t; 675 676 if (lifetime->ia6t_expire) 677 imsg_addrinfo.vltime = lifetime->ia6t_expire < t ? 0 : 678 lifetime->ia6t_expire - t; 679 680 frontend_imsg_compose_main(IMSG_UPDATE_ADDRESS, 0, 681 &imsg_addrinfo, sizeof(imsg_addrinfo)); 682 683 } 684 freeifaddrs(ifap); 685 } 686 687 const char* 688 flags_to_str(int flags) 689 { 690 static char buf[sizeof(" anycast tentative duplicated detached " 691 "deprecated autoconf temporary")]; 692 693 buf[0] = '\0'; 694 if (flags & IN6_IFF_ANYCAST) 695 strlcat(buf, " anycast", sizeof(buf)); 696 if (flags & IN6_IFF_TENTATIVE) 697 strlcat(buf, " tentative", sizeof(buf)); 698 if (flags & IN6_IFF_DUPLICATED) 699 strlcat(buf, " duplicated", sizeof(buf)); 700 if (flags & IN6_IFF_DETACHED) 701 strlcat(buf, " detached", sizeof(buf)); 702 if (flags & IN6_IFF_DEPRECATED) 703 strlcat(buf, " deprecated", sizeof(buf)); 704 if (flags & IN6_IFF_AUTOCONF) 705 strlcat(buf, " autoconf", sizeof(buf)); 706 if (flags & IN6_IFF_TEMPORARY) 707 strlcat(buf, " temporary", sizeof(buf)); 708 709 return (buf); 710 } 711 #endif /* SMALL */ 712 713 void 714 frontend_startup(void) 715 { 716 struct if_nameindex *ifnidxp, *ifnidx; 717 718 if (!event_initialized(&ev_route)) 719 fatalx("%s: did not receive a route socket from the main " 720 "process", __func__); 721 722 event_add(&ev_route, NULL); 723 724 if ((ifnidxp = if_nameindex()) == NULL) 725 fatalx("if_nameindex"); 726 727 for(ifnidx = ifnidxp; ifnidx->if_index !=0 && ifnidx->if_name != NULL; 728 ifnidx++) { 729 update_iface(ifnidx->if_index, ifnidx->if_name); 730 #ifndef SMALL 731 update_autoconf_addresses(ifnidx->if_index, ifnidx->if_name); 732 #endif /* SMALL */ 733 } 734 735 if_freenameindex(ifnidxp); 736 } 737 738 void 739 route_receive(int fd, short events, void *arg) 740 { 741 static uint8_t *buf; 742 743 struct rt_msghdr *rtm; 744 struct sockaddr *sa, *rti_info[RTAX_MAX]; 745 ssize_t n; 746 747 if (buf == NULL) { 748 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 749 if (buf == NULL) 750 fatal("malloc"); 751 } 752 rtm = (struct rt_msghdr *)buf; 753 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 754 if (errno == EAGAIN || errno == EINTR) 755 return; 756 log_warn("dispatch_rtmsg: read error"); 757 return; 758 } 759 760 if (n == 0) 761 fatal("routing socket closed"); 762 763 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 764 log_warnx("partial rtm of %zd in buffer", n); 765 return; 766 } 767 768 if (rtm->rtm_version != RTM_VERSION) 769 return; 770 771 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); 772 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 773 774 handle_route_message(rtm, rti_info); 775 } 776 777 void 778 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) 779 { 780 struct if_msghdr *ifm; 781 struct if_announcemsghdr *ifan; 782 struct imsg_del_addr del_addr; 783 struct imsg_del_route del_route; 784 struct imsg_dup_addr dup_addr; 785 struct sockaddr_rtlabel *rl; 786 struct sockaddr_in6 *sin6; 787 struct in6_ifreq ifr6; 788 struct in6_addr *in6; 789 int xflags, if_index; 790 char ifnamebuf[IFNAMSIZ]; 791 char *if_name; 792 793 switch (rtm->rtm_type) { 794 case RTM_IFINFO: 795 ifm = (struct if_msghdr *)rtm; 796 if_index = ifm->ifm_index; 797 if_name = if_indextoname(if_index, ifnamebuf); 798 if (if_name == NULL) { 799 log_debug("RTM_IFINFO: lost if %d", if_index); 800 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 801 &if_index, sizeof(if_index)); 802 remove_iface(if_index); 803 break; 804 } 805 xflags = get_xflags(if_name); 806 if (xflags == -1 || !(xflags & (IFXF_AUTOCONF6 | 807 IFXF_AUTOCONF6TEMP))) { 808 log_debug("RTM_IFINFO: %s(%d) no(longer) autoconf6", if_name, 809 if_index); 810 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 811 0, &if_index, sizeof(if_index)); 812 remove_iface(if_index); 813 } else { 814 update_iface(if_index, if_name); 815 #ifndef SMALL 816 update_autoconf_addresses(if_index, if_name); 817 #endif /* SMALL */ 818 } 819 break; 820 case RTM_IFANNOUNCE: 821 ifan = (struct if_announcemsghdr *)rtm; 822 if_index = ifan->ifan_index; 823 if (ifan->ifan_what == IFAN_DEPARTURE) { 824 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 825 &if_index, sizeof(if_index)); 826 remove_iface(if_index); 827 } 828 break; 829 case RTM_NEWADDR: 830 ifm = (struct if_msghdr *)rtm; 831 if_index = ifm->ifm_index; 832 if_name = if_indextoname(if_index, ifnamebuf); 833 if (if_name == NULL) { 834 log_debug("RTM_NEWADDR: lost if %d", if_index); 835 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 836 &if_index, sizeof(if_index)); 837 remove_iface(if_index); 838 break; 839 } 840 841 log_debug("RTM_NEWADDR: %s[%u]", if_name, if_index); 842 update_iface(if_index, if_name); 843 break; 844 case RTM_DELADDR: 845 ifm = (struct if_msghdr *)rtm; 846 if_index = ifm->ifm_index; 847 if_name = if_indextoname(if_index, ifnamebuf); 848 if (if_name == NULL) { 849 log_debug("RTM_DELADDR: lost if %d", if_index); 850 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 851 &if_index, sizeof(if_index)); 852 remove_iface(if_index); 853 break; 854 } 855 if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family 856 == AF_INET6) { 857 del_addr.if_index = if_index; 858 memcpy(&del_addr.addr, rti_info[RTAX_IFA], sizeof( 859 del_addr.addr)); 860 frontend_imsg_compose_engine(IMSG_DEL_ADDRESS, 861 0, 0, &del_addr, sizeof(del_addr)); 862 log_debug("RTM_DELADDR: %s[%u]", if_name, if_index); 863 } 864 break; 865 case RTM_CHGADDRATTR: 866 ifm = (struct if_msghdr *)rtm; 867 if_index = ifm->ifm_index; 868 if_name = if_indextoname(if_index, ifnamebuf); 869 if (if_name == NULL) { 870 log_debug("RTM_CHGADDRATTR: lost if %d", if_index); 871 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 872 &if_index, sizeof(if_index)); 873 remove_iface(if_index); 874 break; 875 } 876 if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family 877 == AF_INET6) { 878 sin6 = (struct sockaddr_in6 *) rti_info[RTAX_IFA]; 879 880 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 881 break; 882 883 memset(&ifr6, 0, sizeof(ifr6)); 884 strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 885 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 886 887 if (ioctl(ioctlsock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) 888 == -1) { 889 log_warn("SIOCGIFAFLAG_IN6"); 890 break; 891 } 892 893 #ifndef SMALL 894 log_debug("RTM_CHGADDRATTR: %s - %s", 895 sin6_to_str(sin6), 896 flags_to_str(ifr6.ifr_ifru.ifru_flags6)); 897 #endif /* SMALL */ 898 899 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) { 900 dup_addr.if_index = if_index; 901 dup_addr.addr = *sin6; 902 frontend_imsg_compose_engine(IMSG_DUP_ADDRESS, 903 0, 0, &dup_addr, sizeof(dup_addr)); 904 } 905 906 } 907 break; 908 case RTM_DELETE: 909 ifm = (struct if_msghdr *)rtm; 910 if ((rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY | RTA_LABEL)) != 911 (RTA_DST | RTA_GATEWAY | RTA_LABEL)) 912 break; 913 if (rti_info[RTAX_DST]->sa_family != AF_INET6) 914 break; 915 if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) 916 rti_info[RTAX_DST])->sin6_addr)) 917 break; 918 if (rti_info[RTAX_GATEWAY]->sa_family != AF_INET6) 919 break; 920 if (rti_info[RTAX_LABEL]->sa_len != 921 sizeof(struct sockaddr_rtlabel)) 922 break; 923 924 rl = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL]; 925 if (strcmp(rl->sr_label, SLAACD_RTA_LABEL) != 0) 926 break; 927 if_index = ifm->ifm_index; 928 if_name = if_indextoname(if_index, ifnamebuf); 929 if (if_name == NULL) { 930 log_debug("RTM_DELETE: lost if %d", if_index); 931 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 932 &if_index, sizeof(if_index)); 933 remove_iface(if_index); 934 break; 935 } 936 937 del_route.if_index = if_index; 938 memcpy(&del_route.gw, rti_info[RTAX_GATEWAY], 939 sizeof(del_route.gw)); 940 in6 = &del_route.gw.sin6_addr; 941 #ifdef __KAME__ 942 /* XXX from route(8) p_sockaddr() */ 943 if ((IN6_IS_ADDR_LINKLOCAL(in6) || 944 IN6_IS_ADDR_MC_LINKLOCAL(in6) || 945 IN6_IS_ADDR_MC_INTFACELOCAL(in6)) && 946 del_route.gw.sin6_scope_id == 0) { 947 del_route.gw.sin6_scope_id = 948 (u_int32_t)ntohs(*(u_short *) &in6->s6_addr[2]); 949 *(u_short *)&in6->s6_addr[2] = 0; 950 } 951 #endif 952 frontend_imsg_compose_engine(IMSG_DEL_ROUTE, 953 0, 0, &del_route, sizeof(del_route)); 954 log_debug("RTM_DELETE: %s[%u]", if_name, 955 ifm->ifm_index); 956 957 break; 958 #ifndef SMALL 959 case RTM_PROPOSAL: 960 if (rtm->rtm_priority == RTP_PROPOSAL_SOLICIT) { 961 log_debug("RTP_PROPOSAL_SOLICIT"); 962 frontend_imsg_compose_engine(IMSG_REPROPOSE_RDNS, 963 0, 0, NULL, 0); 964 } 965 break; 966 #endif /* SMALL */ 967 default: 968 log_debug("unexpected RTM: %d", rtm->rtm_type); 969 break; 970 } 971 972 } 973 974 #define ROUNDUP(a) \ 975 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 976 977 void 978 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 979 { 980 int i; 981 982 for (i = 0; i < RTAX_MAX; i++) { 983 if (addrs & (1 << i)) { 984 rti_info[i] = sa; 985 sa = (struct sockaddr *)((char *)(sa) + 986 ROUNDUP(sa->sa_len)); 987 } else 988 rti_info[i] = NULL; 989 } 990 } 991 992 void 993 icmp6_receive(int fd, short events, void *arg) 994 { 995 struct imsg_ra ra; 996 struct icmp6_hdr *icmp6_hdr; 997 struct icmp6_ev *icmp6ev; 998 struct in6_pktinfo *pi = NULL; 999 struct cmsghdr *cm; 1000 ssize_t len; 1001 int if_index = 0, *hlimp = NULL; 1002 char ntopbuf[INET6_ADDRSTRLEN]; 1003 #ifndef SMALL 1004 char ifnamebuf[IFNAMSIZ]; 1005 #endif /* SMALL */ 1006 1007 icmp6ev = arg; 1008 if ((len = recvmsg(fd, &icmp6ev->rcvmhdr, 0)) == -1) { 1009 log_warn("recvmsg"); 1010 return; 1011 } 1012 1013 if ((size_t)len < sizeof(struct icmp6_hdr)) 1014 return; 1015 1016 icmp6_hdr = (struct icmp6_hdr *)icmp6ev->answer; 1017 if (icmp6_hdr->icmp6_type != ND_ROUTER_ADVERT) 1018 return; 1019 1020 /* extract optional information via Advanced API */ 1021 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev->rcvmhdr); cm; 1022 cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev->rcvmhdr, cm)) { 1023 if (cm->cmsg_level == IPPROTO_IPV6 && 1024 cm->cmsg_type == IPV6_PKTINFO && 1025 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 1026 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1027 if_index = pi->ipi6_ifindex; 1028 } 1029 if (cm->cmsg_level == IPPROTO_IPV6 && 1030 cm->cmsg_type == IPV6_HOPLIMIT && 1031 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1032 hlimp = (int *)CMSG_DATA(cm); 1033 } 1034 1035 if (if_index == 0) { 1036 log_warnx("failed to get receiving interface"); 1037 return; 1038 } 1039 1040 if (hlimp == NULL) { 1041 log_warnx("failed to get receiving hop limit"); 1042 return; 1043 } 1044 1045 if (*hlimp != 255) { 1046 log_warnx("invalid RA with hop limit of %d from %s on %s", 1047 *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr, 1048 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 1049 ifnamebuf)); 1050 return; 1051 } 1052 1053 if ((size_t)len > sizeof(ra.packet)) { 1054 log_warnx("invalid RA with size %ld from %s on %s", 1055 len, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr, 1056 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 1057 ifnamebuf)); 1058 return; 1059 } 1060 ra.if_index = if_index; 1061 memcpy(&ra.from, &icmp6ev->from, sizeof(ra.from)); 1062 ra.len = len; 1063 memcpy(ra.packet, icmp6ev->answer, len); 1064 1065 frontend_imsg_compose_engine(IMSG_RA, 0, 0, &ra, sizeof(ra)); 1066 } 1067 1068 void 1069 send_solicitation(uint32_t if_index) 1070 { 1071 struct in6_pktinfo *pi; 1072 struct cmsghdr *cm; 1073 struct iface *iface; 1074 1075 log_debug("%s(%u)", __func__, if_index); 1076 1077 if ((iface = get_iface_by_id(if_index)) == NULL) 1078 return; 1079 1080 if (!event_initialized(&iface->icmp6ev->ev)) { 1081 iface->send_solicitation = 1; 1082 return; 1083 } 1084 1085 dst.sin6_scope_id = if_index; 1086 1087 cm = CMSG_FIRSTHDR(&sndmhdr); 1088 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 1089 pi->ipi6_ifindex = if_index; 1090 1091 memcpy(&nd_opt_source_link_addr, &iface->hw_address, 1092 sizeof(nd_opt_source_link_addr)); 1093 1094 if (sendmsg(EVENT_FD(&iface->icmp6ev->ev), &sndmhdr, 0) != sizeof(rs) + 1095 sizeof(nd_opt_hdr) + sizeof(nd_opt_source_link_addr)) 1096 log_warn("sendmsg"); 1097 } 1098 1099 struct iface* 1100 get_iface_by_id(uint32_t if_index) 1101 { 1102 struct iface *iface; 1103 1104 LIST_FOREACH (iface, &interfaces, entries) { 1105 if (iface->if_index == if_index) 1106 return (iface); 1107 } 1108 1109 return (NULL); 1110 } 1111 1112 void 1113 remove_iface(uint32_t if_index) 1114 { 1115 struct iface *iface; 1116 1117 iface = get_iface_by_id(if_index); 1118 1119 if (iface == NULL) 1120 return; 1121 1122 LIST_REMOVE(iface, entries); 1123 1124 unref_icmp6ev(iface); 1125 free(iface); 1126 } 1127 1128 struct icmp6_ev* 1129 get_icmp6ev_by_rdomain(int rdomain) 1130 { 1131 struct iface *iface; 1132 struct icmp6_ev *icmp6ev = NULL; 1133 1134 LIST_FOREACH (iface, &interfaces, entries) { 1135 if (iface->rdomain == rdomain) { 1136 icmp6ev = iface->icmp6ev; 1137 break; 1138 } 1139 } 1140 1141 if (icmp6ev == NULL) { 1142 if ((icmp6ev = calloc(1, sizeof(*icmp6ev))) == NULL) 1143 fatal("calloc"); 1144 icmp6ev->rcviov[0].iov_base = (caddr_t)icmp6ev->answer; 1145 icmp6ev->rcviov[0].iov_len = sizeof(icmp6ev->answer); 1146 icmp6ev->rcvmhdr.msg_name = (caddr_t)&icmp6ev->from; 1147 icmp6ev->rcvmhdr.msg_namelen = sizeof(icmp6ev->from); 1148 icmp6ev->rcvmhdr.msg_iov = icmp6ev->rcviov; 1149 icmp6ev->rcvmhdr.msg_iovlen = 1; 1150 icmp6ev->rcvmhdr.msg_controllen = 1151 CMSG_SPACE(sizeof(struct in6_pktinfo)) + 1152 CMSG_SPACE(sizeof(int)); 1153 if ((icmp6ev->rcvmhdr.msg_control = malloc(icmp6ev-> 1154 rcvmhdr.msg_controllen)) == NULL) 1155 fatal("malloc"); 1156 frontend_imsg_compose_main(IMSG_OPEN_ICMP6SOCK, 0, 1157 &rdomain, sizeof(rdomain)); 1158 } 1159 icmp6ev->refcnt++; 1160 return (icmp6ev); 1161 } 1162 1163 void 1164 unref_icmp6ev(struct iface *iface) 1165 { 1166 struct icmp6_ev *icmp6ev = iface->icmp6ev; 1167 1168 iface->icmp6ev = NULL; 1169 1170 if (icmp6ev != NULL) { 1171 icmp6ev->refcnt--; 1172 if (icmp6ev->refcnt == 0) { 1173 event_del(&icmp6ev->ev); 1174 close(EVENT_FD(&icmp6ev->ev)); 1175 free(icmp6ev); 1176 } 1177 } 1178 } 1179 1180 void 1181 set_icmp6sock(int icmp6sock, int rdomain) 1182 { 1183 struct iface *iface; 1184 1185 LIST_FOREACH (iface, &interfaces, entries) { 1186 if (!event_initialized(&iface->icmp6ev->ev) && iface->rdomain 1187 == rdomain) { 1188 event_set(&iface->icmp6ev->ev, icmp6sock, EV_READ | 1189 EV_PERSIST, icmp6_receive, iface->icmp6ev); 1190 event_add(&iface->icmp6ev->ev, NULL); 1191 icmp6sock = -1; 1192 break; 1193 } 1194 } 1195 1196 if (icmp6sock != -1) { 1197 /* 1198 * The interface disappeared or changed rdomain while we were 1199 * waiting for the parent process to open the raw socket. 1200 */ 1201 close(icmp6sock); 1202 return; 1203 } 1204 1205 LIST_FOREACH (iface, &interfaces, entries) { 1206 if (event_initialized(&iface->icmp6ev->ev) && 1207 iface->send_solicitation) { 1208 iface->send_solicitation = 0; 1209 send_solicitation(iface->if_index); 1210 } 1211 } 1212 } 1213