1 /* $OpenBSD: frontend.c,v 1.26 2019/03/15 16:45:33 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 __dead void frontend_shutdown(void); 63 void frontend_sig_handler(int, short, void *); 64 void update_iface(uint32_t, char*); 65 void frontend_startup(void); 66 void route_receive(int, short, void *); 67 void handle_route_message(struct rt_msghdr *, struct sockaddr **); 68 void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); 69 void icmp6_receive(int, short, void *); 70 int get_flags(char *); 71 int get_xflags(char *); 72 void get_lladdr(char *, struct ether_addr *, struct sockaddr_in6 *); 73 void send_solicitation(uint32_t); 74 #ifndef SMALL 75 void update_autoconf_addresses(uint32_t, char*); 76 const char *flags_to_str(int); 77 #endif /* SMALL */ 78 79 struct imsgev *iev_main; 80 struct imsgev *iev_engine; 81 struct event ev_route; 82 struct msghdr sndmhdr; 83 struct iovec sndiov[4]; 84 struct nd_router_solicit rs; 85 struct nd_opt_hdr nd_opt_hdr; 86 struct ether_addr nd_opt_source_link_addr; 87 struct sockaddr_in6 dst; 88 int icmp6sock = -1, ioctlsock; 89 90 struct icmp6_ev { 91 struct event ev; 92 uint8_t answer[1500]; 93 struct msghdr rcvmhdr; 94 struct iovec rcviov[1]; 95 struct sockaddr_in6 from; 96 } icmp6ev; 97 98 void 99 frontend_sig_handler(int sig, short event, void *bula) 100 { 101 /* 102 * Normal signal handler rules don't apply because libevent 103 * decouples for us. 104 */ 105 106 switch (sig) { 107 case SIGINT: 108 case SIGTERM: 109 frontend_shutdown(); 110 default: 111 fatalx("unexpected signal"); 112 } 113 } 114 115 void 116 frontend(int debug, int verbose) 117 { 118 struct event ev_sigint, ev_sigterm; 119 struct passwd *pw; 120 struct in6_pktinfo *pi; 121 struct cmsghdr *cm; 122 size_t rcvcmsglen, sndcmsglen; 123 int hoplimit = 255; 124 uint8_t *rcvcmsgbuf, *sndcmsgbuf; 125 126 log_init(debug, LOG_DAEMON); 127 log_setverbose(verbose); 128 129 #ifndef SMALL 130 control_state.fd = -1; 131 #endif /* SMALL */ 132 133 if ((pw = getpwnam(SLAACD_USER)) == NULL) 134 fatal("getpwnam"); 135 136 if (chroot(pw->pw_dir) == -1) 137 fatal("chroot"); 138 if (chdir("/") == -1) 139 fatal("chdir(\"/\")"); 140 141 slaacd_process = PROC_FRONTEND; 142 setproctitle("%s", log_procnames[slaacd_process]); 143 log_procinit(log_procnames[slaacd_process]); 144 145 if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0) 146 fatal("socket"); 147 148 if (setgroups(1, &pw->pw_gid) || 149 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 150 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 151 fatal("can't drop privileges"); 152 153 if (pledge("stdio unix recvfd route", NULL) == -1) 154 fatal("pledge"); 155 156 event_init(); 157 158 /* Setup signal handler. */ 159 signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL); 160 signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL); 161 signal_add(&ev_sigint, NULL); 162 signal_add(&ev_sigterm, NULL); 163 signal(SIGPIPE, SIG_IGN); 164 signal(SIGHUP, SIG_IGN); 165 166 /* Setup pipe and event handler to the parent process. */ 167 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 168 fatal(NULL); 169 imsg_init(&iev_main->ibuf, 3); 170 iev_main->handler = frontend_dispatch_main; 171 iev_main->events = EV_READ; 172 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 173 iev_main->handler, iev_main); 174 event_add(&iev_main->ev, NULL); 175 176 rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 177 CMSG_SPACE(sizeof(int)); 178 if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) 179 fatal("malloc"); 180 181 icmp6ev.rcviov[0].iov_base = (caddr_t)icmp6ev.answer; 182 icmp6ev.rcviov[0].iov_len = sizeof(icmp6ev.answer); 183 icmp6ev.rcvmhdr.msg_name = (caddr_t)&icmp6ev.from; 184 icmp6ev.rcvmhdr.msg_namelen = sizeof(icmp6ev.from); 185 icmp6ev.rcvmhdr.msg_iov = icmp6ev.rcviov; 186 icmp6ev.rcvmhdr.msg_iovlen = 1; 187 icmp6ev.rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf; 188 icmp6ev.rcvmhdr.msg_controllen = rcvcmsglen; 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 event_dispatch(); 239 240 frontend_shutdown(); 241 } 242 243 __dead void 244 frontend_shutdown(void) 245 { 246 /* Close pipes. */ 247 msgbuf_write(&iev_engine->ibuf.w); 248 msgbuf_clear(&iev_engine->ibuf.w); 249 close(iev_engine->ibuf.fd); 250 msgbuf_write(&iev_main->ibuf.w); 251 msgbuf_clear(&iev_main->ibuf.w); 252 close(iev_main->ibuf.fd); 253 254 free(iev_engine); 255 free(iev_main); 256 257 log_info("frontend exiting"); 258 exit(0); 259 } 260 261 int 262 frontend_imsg_compose_main(int type, pid_t pid, void *data, 263 uint16_t datalen) 264 { 265 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, 266 datalen)); 267 } 268 269 int 270 frontend_imsg_compose_engine(int type, uint32_t peerid, pid_t pid, 271 void *data, uint16_t datalen) 272 { 273 return (imsg_compose_event(iev_engine, type, peerid, pid, -1, 274 data, datalen)); 275 } 276 277 void 278 frontend_dispatch_main(int fd, short event, void *bula) 279 { 280 struct imsg imsg; 281 struct imsgev *iev = bula; 282 struct imsgbuf *ibuf = &iev->ibuf; 283 ssize_t n; 284 int shut = 0; 285 286 if (event & EV_READ) { 287 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 288 fatal("imsg_read error"); 289 if (n == 0) /* Connection closed. */ 290 shut = 1; 291 } 292 if (event & EV_WRITE) { 293 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 294 fatal("msgbuf_write"); 295 if (n == 0) /* Connection closed. */ 296 shut = 1; 297 } 298 299 for (;;) { 300 if ((n = imsg_get(ibuf, &imsg)) == -1) 301 fatal("%s: imsg_get error", __func__); 302 if (n == 0) /* No more messages. */ 303 break; 304 305 switch (imsg.hdr.type) { 306 case IMSG_SOCKET_IPC: 307 /* 308 * Setup pipe and event handler to the engine 309 * process. 310 */ 311 if (iev_engine) 312 fatalx("%s: received unexpected imsg fd " 313 "to frontend", __func__); 314 315 if ((fd = imsg.fd) == -1) 316 fatalx("%s: expected to receive imsg fd to " 317 "frontend but didn't receive any", 318 __func__); 319 320 iev_engine = malloc(sizeof(struct imsgev)); 321 if (iev_engine == NULL) 322 fatal(NULL); 323 324 imsg_init(&iev_engine->ibuf, fd); 325 iev_engine->handler = frontend_dispatch_engine; 326 iev_engine->events = EV_READ; 327 328 event_set(&iev_engine->ev, iev_engine->ibuf.fd, 329 iev_engine->events, iev_engine->handler, iev_engine); 330 event_add(&iev_engine->ev, NULL); 331 break; 332 case IMSG_ICMP6SOCK: 333 if ((icmp6sock = imsg.fd) == -1) 334 fatalx("%s: expected to receive imsg " 335 "ICMPv6 fd but didn't receive any", 336 __func__); 337 event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST, 338 icmp6_receive, NULL); 339 break; 340 case IMSG_ROUTESOCK: 341 if ((fd = imsg.fd) == -1) 342 fatalx("%s: expected to receive imsg " 343 "routesocket fd but didn't receive any", 344 __func__); 345 event_set(&ev_route, fd, EV_READ | EV_PERSIST, 346 route_receive, NULL); 347 break; 348 case IMSG_STARTUP: 349 if (pledge("stdio unix route", NULL) == -1) 350 fatal("pledge"); 351 frontend_startup(); 352 break; 353 #ifndef SMALL 354 case IMSG_CONTROLFD: 355 if (control_state.fd != -1) 356 fatalx("%s: received unexpected controlsock", 357 __func__); 358 if ((fd = imsg.fd) == -1) 359 fatalx("%s: expected to receive imsg " 360 "control fd but didn't receive any", 361 __func__); 362 control_state.fd = fd; 363 /* Listen on control socket. */ 364 TAILQ_INIT(&ctl_conns); 365 control_listen(); 366 break; 367 case IMSG_CTL_END: 368 control_imsg_relay(&imsg); 369 break; 370 #endif /* SMALL */ 371 default: 372 log_debug("%s: error handling imsg %d", __func__, 373 imsg.hdr.type); 374 break; 375 } 376 imsg_free(&imsg); 377 } 378 if (!shut) 379 imsg_event_add(iev); 380 else { 381 /* This pipe is dead. Remove its event handler. */ 382 event_del(&iev->ev); 383 event_loopexit(NULL); 384 } 385 } 386 387 void 388 frontend_dispatch_engine(int fd, short event, void *bula) 389 { 390 struct imsgev *iev = bula; 391 struct imsgbuf *ibuf = &iev->ibuf; 392 struct imsg imsg; 393 ssize_t n; 394 int shut = 0; 395 uint32_t if_index; 396 397 if (event & EV_READ) { 398 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 399 fatal("imsg_read error"); 400 if (n == 0) /* Connection closed. */ 401 shut = 1; 402 } 403 if (event & EV_WRITE) { 404 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 405 fatal("msgbuf_write"); 406 if (n == 0) /* Connection closed. */ 407 shut = 1; 408 } 409 410 for (;;) { 411 if ((n = imsg_get(ibuf, &imsg)) == -1) 412 fatal("%s: imsg_get error", __func__); 413 if (n == 0) /* No more messages. */ 414 break; 415 416 switch (imsg.hdr.type) { 417 #ifndef SMALL 418 case IMSG_CTL_END: 419 case IMSG_CTL_SHOW_INTERFACE_INFO: 420 case IMSG_CTL_SHOW_INTERFACE_INFO_RA: 421 case IMSG_CTL_SHOW_INTERFACE_INFO_RA_PREFIX: 422 case IMSG_CTL_SHOW_INTERFACE_INFO_RA_RDNS: 423 case IMSG_CTL_SHOW_INTERFACE_INFO_RA_DNSSL: 424 case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSALS: 425 case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSAL: 426 case IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSALS: 427 case IMSG_CTL_SHOW_INTERFACE_INFO_DFR_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 case IMSG_FAKE_ACK: 440 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 441 imsg_proposal_ack)) 442 fatalx("%s: IMSG_FAKE_ACK wrong length: %lu", 443 __func__, IMSG_DATA_SIZE(imsg)); 444 frontend_imsg_compose_engine(IMSG_PROPOSAL_ACK, 445 0, 0, imsg.data, sizeof(struct imsg_proposal_ack)); 446 break; 447 default: 448 log_debug("%s: error handling imsg %d", __func__, 449 imsg.hdr.type); 450 break; 451 } 452 imsg_free(&imsg); 453 } 454 if (!shut) 455 imsg_event_add(iev); 456 else { 457 /* This pipe is dead. Remove its event handler. */ 458 event_del(&iev->ev); 459 event_loopexit(NULL); 460 } 461 } 462 463 int 464 get_flags(char *if_name) 465 { 466 struct ifreq ifr; 467 468 (void) strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 469 if (ioctl(ioctlsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) 470 fatal("SIOCGIFFLAGS"); 471 return ifr.ifr_flags; 472 } 473 474 int 475 get_xflags(char *if_name) 476 { 477 struct ifreq ifr; 478 479 (void) strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)); 480 if (ioctl(ioctlsock, SIOCGIFXFLAGS, (caddr_t)&ifr) < 0) 481 fatal("SIOCGIFXFLAGS"); 482 return ifr.ifr_flags; 483 } 484 485 void 486 update_iface(uint32_t if_index, char* if_name) 487 { 488 struct imsg_ifinfo imsg_ifinfo; 489 int flags, xflags; 490 491 flags = get_flags(if_name); 492 xflags = get_xflags(if_name); 493 494 if (!(xflags & IFXF_AUTOCONF6)) 495 return; 496 497 memset(&imsg_ifinfo, 0, sizeof(imsg_ifinfo)); 498 499 imsg_ifinfo.if_index = if_index; 500 imsg_ifinfo.running = (flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | 501 IFF_RUNNING); 502 imsg_ifinfo.autoconfprivacy = !(xflags & IFXF_INET6_NOPRIVACY); 503 imsg_ifinfo.soii = !(xflags & IFXF_INET6_NOSOII); 504 get_lladdr(if_name, &imsg_ifinfo.hw_address, &imsg_ifinfo.ll_address); 505 506 memcpy(&nd_opt_source_link_addr, &imsg_ifinfo.hw_address, 507 sizeof(nd_opt_source_link_addr)); 508 509 frontend_imsg_compose_main(IMSG_UPDATE_IF, 0, &imsg_ifinfo, 510 sizeof(imsg_ifinfo)); 511 } 512 513 #ifndef SMALL 514 void 515 update_autoconf_addresses(uint32_t if_index, char* if_name) 516 { 517 struct in6_ifreq ifr6; 518 struct imsg_addrinfo imsg_addrinfo; 519 struct ifaddrs *ifap, *ifa; 520 struct in6_addrlifetime *lifetime; 521 struct sockaddr_in6 *sin6; 522 struct imsg_link_state imsg_link_state; 523 time_t t; 524 int xflags; 525 526 xflags = get_xflags(if_name); 527 528 if (!(xflags & IFXF_AUTOCONF6)) 529 return; 530 531 memset(&imsg_addrinfo, 0, sizeof(imsg_addrinfo)); 532 imsg_addrinfo.if_index = if_index; 533 get_lladdr(if_name, &imsg_addrinfo.hw_address, 534 &imsg_addrinfo.ll_address); 535 536 memset(&imsg_link_state, 0, sizeof(imsg_link_state)); 537 imsg_link_state.if_index = if_index; 538 539 if (getifaddrs(&ifap) != 0) 540 fatal("getifaddrs"); 541 542 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 543 if (strcmp(if_name, ifa->ifa_name) != 0) 544 continue; 545 546 if (ifa->ifa_addr->sa_family == AF_LINK) 547 imsg_link_state.link_state = 548 ((struct if_data *)ifa->ifa_data)->ifi_link_state; 549 550 if (ifa->ifa_addr->sa_family != AF_INET6) 551 continue; 552 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 553 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 554 continue; 555 556 log_debug("%s: IP: %s", __func__, sin6_to_str(sin6)); 557 imsg_addrinfo.addr = *sin6; 558 559 memset(&ifr6, 0, sizeof(ifr6)); 560 (void) strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 561 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 562 563 if (ioctl(ioctlsock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) < 0) { 564 log_warn("SIOCGIFAFLAG_IN6"); 565 continue; 566 } 567 568 if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | 569 IN6_IFF_PRIVACY))) 570 continue; 571 572 imsg_addrinfo.privacy = ifr6.ifr_ifru.ifru_flags6 & 573 IN6_IFF_PRIVACY ? 1 : 0; 574 575 memset(&ifr6, 0, sizeof(ifr6)); 576 (void) strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 577 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 578 579 if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) { 580 log_warn("SIOCGIFNETMASK_IN6"); 581 continue; 582 } 583 584 imsg_addrinfo.mask = ((struct sockaddr_in6 *)&ifr6.ifr_addr) 585 ->sin6_addr; 586 587 memset(&ifr6, 0, sizeof(ifr6)); 588 (void) strlcpy(ifr6.ifr_name, if_name, sizeof(ifr6.ifr_name)); 589 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 590 lifetime = &ifr6.ifr_ifru.ifru_lifetime; 591 592 if (ioctl(ioctlsock, SIOCGIFALIFETIME_IN6, (caddr_t)&ifr6) < 593 0) { 594 log_warn("SIOCGIFALIFETIME_IN6"); 595 continue; 596 } 597 598 imsg_addrinfo.vltime = ND6_INFINITE_LIFETIME; 599 imsg_addrinfo.pltime = ND6_INFINITE_LIFETIME; 600 t = time(NULL); 601 602 if (lifetime->ia6t_preferred) 603 imsg_addrinfo.pltime = lifetime->ia6t_preferred < t ? 0 604 : lifetime->ia6t_preferred - t; 605 606 if (lifetime->ia6t_expire) 607 imsg_addrinfo.vltime = lifetime->ia6t_expire < t ? 0 : 608 lifetime->ia6t_expire - t; 609 610 frontend_imsg_compose_main(IMSG_UPDATE_ADDRESS, 0, 611 &imsg_addrinfo, sizeof(imsg_addrinfo)); 612 613 } 614 freeifaddrs(ifap); 615 616 log_debug("%s: %s link state down? %s", __func__, if_name, 617 imsg_link_state.link_state == LINK_STATE_DOWN ? "yes" : "no"); 618 619 frontend_imsg_compose_main(IMSG_UPDATE_LINK_STATE, 0, 620 &imsg_link_state, sizeof(imsg_link_state)); 621 } 622 623 const char* 624 flags_to_str(int flags) 625 { 626 static char buf[sizeof(" anycast tentative duplicated detached " 627 "deprecated autoconf autoconfprivacy")]; 628 629 buf[0] = '\0'; 630 if (flags & IN6_IFF_ANYCAST) 631 (void)strlcat(buf, " anycast", sizeof(buf)); 632 if (flags & IN6_IFF_TENTATIVE) 633 (void)strlcat(buf, " tentative", sizeof(buf)); 634 if (flags & IN6_IFF_DUPLICATED) 635 (void)strlcat(buf, " duplicated", sizeof(buf)); 636 if (flags & IN6_IFF_DETACHED) 637 (void)strlcat(buf, " detached", sizeof(buf)); 638 if (flags & IN6_IFF_DEPRECATED) 639 (void)strlcat(buf, " deprecated", sizeof(buf)); 640 if (flags & IN6_IFF_AUTOCONF) 641 (void)strlcat(buf, " autoconf", sizeof(buf)); 642 if (flags & IN6_IFF_PRIVACY) 643 (void)strlcat(buf, " autoconfprivacy", sizeof(buf)); 644 645 return (buf); 646 } 647 #endif /* SMALL */ 648 649 void 650 frontend_startup(void) 651 { 652 struct if_nameindex *ifnidxp, *ifnidx; 653 654 if (!event_initialized(&ev_route)) 655 fatalx("%s: did not receive a route socket from the main " 656 "process", __func__); 657 658 event_add(&ev_route, NULL); 659 660 if (!event_initialized(&icmp6ev.ev)) 661 fatalx("%s: did not receive a icmp6 socket fd from the main " 662 "process", __func__); 663 664 event_add(&icmp6ev.ev, NULL); 665 666 if ((ifnidxp = if_nameindex()) == NULL) 667 fatalx("if_nameindex"); 668 669 frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0); 670 671 for(ifnidx = ifnidxp; ifnidx->if_index !=0 && ifnidx->if_name != NULL; 672 ifnidx++) { 673 update_iface(ifnidx->if_index, ifnidx->if_name); 674 #ifndef SMALL 675 update_autoconf_addresses(ifnidx->if_index, ifnidx->if_name); 676 #endif /* SMALL */ 677 } 678 679 if_freenameindex(ifnidxp); 680 } 681 682 void 683 route_receive(int fd, short events, void *arg) 684 { 685 static uint8_t *buf; 686 687 struct rt_msghdr *rtm; 688 struct sockaddr *sa, *rti_info[RTAX_MAX]; 689 ssize_t n; 690 691 if (buf == NULL) { 692 buf = malloc(ROUTE_SOCKET_BUF_SIZE); 693 if (buf == NULL) 694 fatal("malloc"); 695 } 696 rtm = (struct rt_msghdr *)buf; 697 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { 698 if (errno == EAGAIN || errno == EINTR) 699 return; 700 log_warn("dispatch_rtmsg: read error"); 701 return; 702 } 703 704 if (n == 0) 705 fatal("routing socket closed"); 706 707 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { 708 log_warnx("partial rtm of %zd in buffer", n); 709 return; 710 } 711 712 if (rtm->rtm_version != RTM_VERSION) 713 return; 714 715 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); 716 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 717 718 handle_route_message(rtm, rti_info); 719 } 720 721 void 722 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) 723 { 724 struct if_msghdr *ifm; 725 struct imsg_proposal_ack proposal_ack; 726 struct imsg_del_addr del_addr; 727 struct imsg_del_route del_route; 728 struct imsg_dup_addr dup_addr; 729 struct sockaddr_rtlabel *rl; 730 struct sockaddr_in6 *sin6; 731 struct in6_ifreq ifr6; 732 struct in6_addr *in6; 733 int64_t id, pid; 734 int xflags, if_index; 735 char ifnamebuf[IFNAMSIZ]; 736 char *if_name; 737 char **ap, *argv[4], *p; 738 const char *errstr; 739 740 switch (rtm->rtm_type) { 741 case RTM_IFINFO: 742 ifm = (struct if_msghdr *)rtm; 743 if_name = if_indextoname(ifm->ifm_index, ifnamebuf); 744 if (if_name == NULL) { 745 log_debug("RTM_IFINFO: lost if %d", ifm->ifm_index); 746 if_index = ifm->ifm_index; 747 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0, 748 &if_index, sizeof(if_index)); 749 } else { 750 xflags = get_xflags(if_name); 751 if (!(xflags & IFXF_AUTOCONF6)) { 752 log_debug("RTM_IFINFO: %s(%d) no(longer) " 753 "autoconf6", if_name, ifm->ifm_index); 754 if_index = ifm->ifm_index; 755 frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 756 0, &if_index, sizeof(if_index)); 757 } else { 758 update_iface(ifm->ifm_index, if_name); 759 #ifndef SMALL 760 update_autoconf_addresses(ifm->ifm_index, 761 if_name); 762 #endif /* SMALL */ 763 } 764 } 765 break; 766 case RTM_NEWADDR: 767 ifm = (struct if_msghdr *)rtm; 768 if_name = if_indextoname(ifm->ifm_index, ifnamebuf); 769 log_debug("RTM_NEWADDR: %s[%u]", if_name, ifm->ifm_index); 770 update_iface(ifm->ifm_index, if_name); 771 break; 772 case RTM_DELADDR: 773 ifm = (struct if_msghdr *)rtm; 774 if_name = if_indextoname(ifm->ifm_index, ifnamebuf); 775 if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family 776 == AF_INET6) { 777 del_addr.if_index = ifm->ifm_index; 778 memcpy(&del_addr.addr, rti_info[RTAX_IFA], sizeof( 779 del_addr.addr)); 780 frontend_imsg_compose_engine(IMSG_DEL_ADDRESS, 781 0, 0, &del_addr, sizeof(del_addr)); 782 log_debug("RTM_DELADDR: %s[%u]", if_name, 783 ifm->ifm_index); 784 } 785 break; 786 case RTM_CHGADDRATTR: 787 ifm = (struct if_msghdr *)rtm; 788 if_name = if_indextoname(ifm->ifm_index, ifnamebuf); 789 if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family 790 == AF_INET6) { 791 sin6 = (struct sockaddr_in6 *) rti_info[RTAX_IFA]; 792 793 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 794 break; 795 796 memset(&ifr6, 0, sizeof(ifr6)); 797 (void) strlcpy(ifr6.ifr_name, if_name, 798 sizeof(ifr6.ifr_name)); 799 memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr)); 800 801 if (ioctl(ioctlsock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) 802 < 0) { 803 log_warn("SIOCGIFAFLAG_IN6"); 804 break; 805 } 806 807 #ifndef SMALL 808 log_debug("RTM_CHGADDRATTR: %s -%s", 809 sin6_to_str(sin6), 810 flags_to_str(ifr6.ifr_ifru.ifru_flags6)); 811 #endif /* SMALL */ 812 813 if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) { 814 dup_addr.if_index = ifm->ifm_index; 815 dup_addr.addr = *sin6; 816 frontend_imsg_compose_engine(IMSG_DUP_ADDRESS, 817 0, 0, &dup_addr, sizeof(dup_addr)); 818 } 819 820 } 821 break; 822 case RTM_DELETE: 823 ifm = (struct if_msghdr *)rtm; 824 if ((rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY | RTA_LABEL)) != 825 (RTA_DST | RTA_GATEWAY | RTA_LABEL)) 826 break; 827 if (rti_info[RTAX_DST]->sa_family != AF_INET6) 828 break; 829 if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) 830 rti_info[RTAX_DST])->sin6_addr)) 831 break; 832 if (rti_info[RTAX_GATEWAY]->sa_family != AF_INET6) 833 break; 834 if (rti_info[RTAX_LABEL]->sa_len != 835 sizeof(struct sockaddr_rtlabel)) 836 break; 837 838 rl = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL]; 839 if (strcmp(rl->sr_label, SLAACD_RTA_LABEL) != 0) 840 break; 841 842 if_name = if_indextoname(ifm->ifm_index, ifnamebuf); 843 844 del_route.if_index = ifm->ifm_index; 845 memcpy(&del_route.gw, rti_info[RTAX_GATEWAY], 846 sizeof(del_route.gw)); 847 in6 = &del_route.gw.sin6_addr; 848 /* XXX from route(8) p_sockaddr() */ 849 if (IN6_IS_ADDR_LINKLOCAL(in6) || 850 IN6_IS_ADDR_MC_LINKLOCAL(in6) || 851 IN6_IS_ADDR_MC_INTFACELOCAL(in6)) { 852 del_route.gw.sin6_scope_id = 853 (u_int32_t)ntohs(*(u_short *) &in6->s6_addr[2]); 854 *(u_short *)&in6->s6_addr[2] = 0; 855 } 856 frontend_imsg_compose_engine(IMSG_DEL_ROUTE, 857 0, 0, &del_route, sizeof(del_route)); 858 log_debug("RTM_DELETE: %s[%u]", if_name, 859 ifm->ifm_index); 860 861 break; 862 case RTM_PROPOSAL: 863 ifm = (struct if_msghdr *)rtm; 864 if_name = if_indextoname(ifm->ifm_index, ifnamebuf); 865 866 if ((rtm->rtm_flags & (RTF_DONE | RTF_PROTO1)) == 867 (RTF_DONE | RTF_PROTO1) && rtm->rtm_addrs == RTA_LABEL) { 868 rl = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL]; 869 /* XXX validate rl */ 870 871 p = rl->sr_label; 872 873 for (ap = argv; ap < &argv[3] && (*ap = 874 strsep(&p, " ")) != NULL;) { 875 if (**ap != '\0') 876 ap++; 877 } 878 *ap = NULL; 879 880 if (argv[0] != NULL && strncmp(argv[0], 881 SLAACD_RTA_LABEL":", strlen(SLAACD_RTA_LABEL":")) 882 == 0 && argv[1] != NULL && argv[2] != NULL && 883 argv[3] == NULL) { 884 id = strtonum(argv[1], 0, INT64_MAX, &errstr); 885 if (errstr != NULL) { 886 log_warnx("%s: proposal seq is %s: %s", 887 __func__, errstr, argv[1]); 888 break; 889 } 890 pid = strtonum(argv[2], 0, INT32_MAX, &errstr); 891 if (errstr != NULL) { 892 log_warnx("%s: pid is %s: %s", 893 __func__, errstr, argv[2]); 894 break; 895 } 896 proposal_ack.id = id; 897 proposal_ack.pid = pid; 898 proposal_ack.if_index = ifm->ifm_index; 899 900 frontend_imsg_compose_engine(IMSG_PROPOSAL_ACK, 901 0, 0, &proposal_ack, sizeof(proposal_ack)); 902 } else { 903 log_debug("cannot parse: %s", rl->sr_label); 904 } 905 } else { 906 #if 0 907 log_debug("%s: got flags %x, expcted %x", __func__, 908 rtm->rtm_flags, (RTF_DONE | RTF_PROTO1)); 909 #endif 910 } 911 912 break; 913 default: 914 log_debug("unexpected RTM: %d", rtm->rtm_type); 915 break; 916 } 917 918 } 919 920 #define ROUNDUP(a) \ 921 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 922 923 void 924 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) 925 { 926 int i; 927 928 for (i = 0; i < RTAX_MAX; i++) { 929 if (addrs & (1 << i)) { 930 rti_info[i] = sa; 931 sa = (struct sockaddr *)((char *)(sa) + 932 ROUNDUP(sa->sa_len)); 933 } else 934 rti_info[i] = NULL; 935 } 936 } 937 938 void 939 get_lladdr(char *if_name, struct ether_addr *mac, struct sockaddr_in6 *ll) 940 { 941 struct ifaddrs *ifap, *ifa; 942 struct sockaddr_dl *sdl; 943 struct sockaddr_in6 *sin6; 944 945 if (getifaddrs(&ifap) != 0) 946 fatal("getifaddrs"); 947 948 memset(mac, 0, sizeof(*mac)); 949 memset(ll, 0, sizeof(*ll)); 950 951 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 952 if (strcmp(if_name, ifa->ifa_name) != 0) 953 continue; 954 955 switch(ifa->ifa_addr->sa_family) { 956 case AF_LINK: 957 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 958 if (sdl->sdl_type != IFT_ETHER || 959 sdl->sdl_alen != ETHER_ADDR_LEN) 960 continue; 961 962 memcpy(mac->ether_addr_octet, LLADDR(sdl), 963 ETHER_ADDR_LEN); 964 break; 965 case AF_INET6: 966 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 967 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 968 sin6->sin6_scope_id = ntohs(*(u_int16_t *) 969 &sin6->sin6_addr.s6_addr[2]); 970 sin6->sin6_addr.s6_addr[2] = 971 sin6->sin6_addr.s6_addr[3] = 0; 972 memcpy(ll, sin6, sizeof(*ll)); 973 } 974 break; 975 default: 976 break; 977 } 978 } 979 freeifaddrs(ifap); 980 } 981 982 void 983 icmp6_receive(int fd, short events, void *arg) 984 { 985 struct imsg_ra ra; 986 987 struct in6_pktinfo *pi = NULL; 988 struct cmsghdr *cm; 989 ssize_t len; 990 int if_index = 0, *hlimp = NULL; 991 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 992 993 if ((len = recvmsg(fd, &icmp6ev.rcvmhdr, 0)) < 0) { 994 log_warn("recvmsg"); 995 return; 996 } 997 998 /* extract optional information via Advanced API */ 999 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev.rcvmhdr); cm; 1000 cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev.rcvmhdr, cm)) { 1001 if (cm->cmsg_level == IPPROTO_IPV6 && 1002 cm->cmsg_type == IPV6_PKTINFO && 1003 cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { 1004 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 1005 if_index = pi->ipi6_ifindex; 1006 } 1007 if (cm->cmsg_level == IPPROTO_IPV6 && 1008 cm->cmsg_type == IPV6_HOPLIMIT && 1009 cm->cmsg_len == CMSG_LEN(sizeof(int))) 1010 hlimp = (int *)CMSG_DATA(cm); 1011 } 1012 1013 if (if_index == 0) { 1014 log_warnx("failed to get receiving interface"); 1015 return; 1016 } 1017 1018 if (hlimp == NULL) { 1019 log_warnx("failed to get receiving hop limit"); 1020 return; 1021 } 1022 1023 if (*hlimp != 255) { 1024 log_warnx("invalid RA with hop limit of %d from %s on %s", 1025 *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 1026 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 1027 ifnamebuf)); 1028 return; 1029 } 1030 1031 if ((size_t)len > sizeof(ra.packet)) { 1032 log_warnx("invalid RA with size %ld from %s on %s", 1033 len, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr, 1034 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index, 1035 ifnamebuf)); 1036 return; 1037 } 1038 1039 ra.if_index = if_index; 1040 memcpy(&ra.from, &icmp6ev.from, sizeof(ra.from)); 1041 ra.len = len; 1042 memcpy(ra.packet, icmp6ev.answer, len); 1043 1044 frontend_imsg_compose_engine(IMSG_RA, 0, 0, &ra, sizeof(ra)); 1045 } 1046 1047 void 1048 send_solicitation(uint32_t if_index) 1049 { 1050 struct in6_pktinfo *pi; 1051 struct cmsghdr *cm; 1052 1053 log_debug("%s(%u)", __func__, if_index); 1054 1055 dst.sin6_scope_id = if_index; 1056 1057 cm = CMSG_FIRSTHDR(&sndmhdr); 1058 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 1059 pi->ipi6_ifindex = if_index; 1060 1061 if (sendmsg(icmp6sock, &sndmhdr, 0) != sizeof(rs) + 1062 sizeof(nd_opt_hdr) + sizeof(nd_opt_source_link_addr)) 1063 log_warn("sendmsg"); 1064 } 1065