1 /* $OpenBSD: slaacd.c,v 1.55 2021/01/19 16:48:20 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/sysctl.h> 27 #include <sys/uio.h> 28 #include <sys/wait.h> 29 30 #include <net/if.h> 31 #include <net/route.h> 32 #include <netinet/in.h> 33 #include <netinet/if_ether.h> 34 #include <netinet6/in6_var.h> 35 #include <netinet/icmp6.h> 36 37 #include <err.h> 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <event.h> 41 #include <imsg.h> 42 #include <netdb.h> 43 #include <pwd.h> 44 #include <stddef.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <signal.h> 49 #include <unistd.h> 50 51 #include "log.h" 52 #include "slaacd.h" 53 #include "frontend.h" 54 #include "engine.h" 55 #include "control.h" 56 57 enum slaacd_process { 58 PROC_MAIN, 59 PROC_ENGINE, 60 PROC_FRONTEND 61 }; 62 63 __dead void usage(void); 64 __dead void main_shutdown(void); 65 66 void main_sig_handler(int, short, void *); 67 68 static pid_t start_child(enum slaacd_process, char *, int, int, int); 69 70 void main_dispatch_frontend(int, short, void *); 71 void main_dispatch_engine(int, short, void *); 72 void open_icmp6sock(int); 73 void configure_interface(struct imsg_configure_address *); 74 void delete_address(struct imsg_configure_address *); 75 void configure_gateway(struct imsg_configure_dfr *, uint8_t); 76 void add_gateway(struct imsg_configure_dfr *); 77 void delete_gateway(struct imsg_configure_dfr *); 78 #ifndef SMALL 79 void send_rdns_proposal(struct imsg_propose_rdns *); 80 #endif /* SMALL */ 81 int get_soiikey(uint8_t *); 82 83 static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); 84 int main_imsg_compose_frontend(int, int, void *, uint16_t); 85 int main_imsg_compose_engine(int, pid_t, void *, uint16_t); 86 87 struct imsgev *iev_frontend; 88 struct imsgev *iev_engine; 89 90 pid_t frontend_pid; 91 pid_t engine_pid; 92 93 int routesock, ioctl_sock, rtm_seq = 0; 94 95 void 96 main_sig_handler(int sig, short event, void *arg) 97 { 98 /* 99 * Normal signal handler rules don't apply because libevent 100 * decouples for us. 101 */ 102 103 switch (sig) { 104 case SIGTERM: 105 case SIGINT: 106 main_shutdown(); 107 default: 108 fatalx("unexpected signal"); 109 } 110 } 111 112 __dead void 113 usage(void) 114 { 115 extern char *__progname; 116 117 fprintf(stderr, "usage: %s [-dv] [-s socket]\n", 118 __progname); 119 exit(1); 120 } 121 122 int 123 main(int argc, char *argv[]) 124 { 125 struct event ev_sigint, ev_sigterm; 126 int ch; 127 int debug = 0, engine_flag = 0, frontend_flag = 0; 128 int verbose = 0; 129 char *saved_argv0; 130 int pipe_main2frontend[2]; 131 int pipe_main2engine[2]; 132 int frontend_routesock, rtfilter; 133 int rtable_any = RTABLE_ANY; 134 char *csock = SLAACD_SOCKET; 135 #ifndef SMALL 136 struct imsg_propose_rdns rdns; 137 int control_fd; 138 #endif /* SMALL */ 139 140 log_init(1, LOG_DAEMON); /* Log to stderr until daemonized. */ 141 log_setverbose(1); 142 143 saved_argv0 = argv[0]; 144 if (saved_argv0 == NULL) 145 saved_argv0 = "slaacd"; 146 147 while ((ch = getopt(argc, argv, "dEFs:v")) != -1) { 148 switch (ch) { 149 case 'd': 150 debug = 1; 151 break; 152 case 'E': 153 engine_flag = 1; 154 break; 155 case 'F': 156 frontend_flag = 1; 157 break; 158 case 's': 159 csock = optarg; 160 break; 161 case 'v': 162 verbose++; 163 break; 164 default: 165 usage(); 166 } 167 } 168 169 argc -= optind; 170 argv += optind; 171 if (argc > 0 || (engine_flag && frontend_flag)) 172 usage(); 173 174 if (engine_flag) 175 engine(debug, verbose); 176 else if (frontend_flag) 177 frontend(debug, verbose); 178 179 /* Check for root privileges. */ 180 if (geteuid()) 181 errx(1, "need root privileges"); 182 183 /* Check for assigned daemon user */ 184 if (getpwnam(SLAACD_USER) == NULL) 185 errx(1, "unknown user %s", SLAACD_USER); 186 187 log_init(debug, LOG_DAEMON); 188 log_setverbose(verbose); 189 190 if (!debug) 191 daemon(0, 0); 192 193 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 194 PF_UNSPEC, pipe_main2frontend) == -1) 195 fatal("main2frontend socketpair"); 196 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 197 PF_UNSPEC, pipe_main2engine) == -1) 198 fatal("main2engine socketpair"); 199 200 /* Start children. */ 201 engine_pid = start_child(PROC_ENGINE, saved_argv0, pipe_main2engine[1], 202 debug, verbose); 203 frontend_pid = start_child(PROC_FRONTEND, saved_argv0, 204 pipe_main2frontend[1], debug, verbose); 205 206 log_procinit("main"); 207 208 if ((routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | 209 SOCK_NONBLOCK, AF_INET6)) == -1) 210 fatal("route socket"); 211 shutdown(SHUT_RD, routesock); 212 213 event_init(); 214 215 /* Setup signal handler. */ 216 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 217 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 218 signal_add(&ev_sigint, NULL); 219 signal_add(&ev_sigterm, NULL); 220 signal(SIGPIPE, SIG_IGN); 221 signal(SIGHUP, SIG_IGN); 222 223 /* Setup pipes to children. */ 224 225 if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 226 (iev_engine = malloc(sizeof(struct imsgev))) == NULL) 227 fatal(NULL); 228 imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 229 iev_frontend->handler = main_dispatch_frontend; 230 imsg_init(&iev_engine->ibuf, pipe_main2engine[0]); 231 iev_engine->handler = main_dispatch_engine; 232 233 /* Setup event handlers for pipes to engine & frontend. */ 234 iev_frontend->events = EV_READ; 235 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 236 iev_frontend->events, iev_frontend->handler, iev_frontend); 237 event_add(&iev_frontend->ev, NULL); 238 239 iev_engine->events = EV_READ; 240 event_set(&iev_engine->ev, iev_engine->ibuf.fd, iev_engine->events, 241 iev_engine->handler, iev_engine); 242 event_add(&iev_engine->ev, NULL); 243 244 if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, &iev_engine->ibuf)) 245 fatal("could not establish imsg links"); 246 247 if ((ioctl_sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1) 248 fatal("socket"); 249 250 if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 251 AF_INET6)) == -1) 252 fatal("route socket"); 253 254 rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | 255 ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_DELETE) | 256 ROUTE_FILTER(RTM_CHGADDRATTR) | ROUTE_FILTER(RTM_PROPOSAL); 257 if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, 258 &rtfilter, sizeof(rtfilter)) == -1) 259 fatal("setsockopt(ROUTE_MSGFILTER)"); 260 if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_TABLEFILTER, 261 &rtable_any, sizeof(rtable_any)) == -1) 262 fatal("setsockopt(ROUTE_TABLEFILTER)"); 263 264 #ifndef SMALL 265 if ((control_fd = control_init(csock)) == -1) 266 fatalx("control socket setup failed"); 267 #endif /* SMALL */ 268 269 if (pledge("stdio inet sendfd wroute", NULL) == -1) 270 fatal("pledge"); 271 272 main_imsg_compose_frontend(IMSG_ROUTESOCK, frontend_routesock, NULL, 0); 273 274 #ifndef SMALL 275 main_imsg_compose_frontend(IMSG_CONTROLFD, control_fd, NULL, 0); 276 #endif /* SMALL */ 277 278 main_imsg_compose_frontend(IMSG_STARTUP, -1, NULL, 0); 279 280 #ifndef SMALL 281 /* we are taking over, clear all previos slaac proposals */ 282 memset(&rdns, 0, sizeof(rdns)); 283 rdns.if_index = 0; 284 rdns.rdns_count = 0; 285 send_rdns_proposal(&rdns); 286 #endif /* SMALL */ 287 288 event_dispatch(); 289 290 main_shutdown(); 291 return (0); 292 } 293 294 __dead void 295 main_shutdown(void) 296 { 297 pid_t pid; 298 int status; 299 300 /* Close pipes. */ 301 msgbuf_clear(&iev_frontend->ibuf.w); 302 close(iev_frontend->ibuf.fd); 303 msgbuf_clear(&iev_engine->ibuf.w); 304 close(iev_engine->ibuf.fd); 305 306 log_debug("waiting for children to terminate"); 307 do { 308 pid = wait(&status); 309 if (pid == -1) { 310 if (errno != EINTR && errno != ECHILD) 311 fatal("wait"); 312 } else if (WIFSIGNALED(status)) 313 log_warnx("%s terminated; signal %d", 314 (pid == engine_pid) ? "engine" : 315 "frontend", WTERMSIG(status)); 316 } while (pid != -1 || (pid == -1 && errno == EINTR)); 317 318 free(iev_frontend); 319 free(iev_engine); 320 321 log_info("terminating"); 322 exit(0); 323 } 324 325 static pid_t 326 start_child(enum slaacd_process p, char *argv0, int fd, int debug, int verbose) 327 { 328 char *argv[7]; 329 int argc = 0; 330 pid_t pid; 331 332 switch (pid = fork()) { 333 case -1: 334 fatal("cannot fork"); 335 case 0: 336 break; 337 default: 338 close(fd); 339 return (pid); 340 } 341 342 if (fd != 3) { 343 if (dup2(fd, 3) == -1) 344 fatal("cannot setup imsg fd"); 345 } else if (fcntl(fd, F_SETFD, 0) == -1) 346 fatal("cannot setup imsg fd"); 347 348 argv[argc++] = argv0; 349 switch (p) { 350 case PROC_MAIN: 351 fatalx("Can not start main process"); 352 case PROC_ENGINE: 353 argv[argc++] = "-E"; 354 break; 355 case PROC_FRONTEND: 356 argv[argc++] = "-F"; 357 break; 358 } 359 if (debug) 360 argv[argc++] = "-d"; 361 if (verbose) 362 argv[argc++] = "-v"; 363 if (verbose > 1) 364 argv[argc++] = "-v"; 365 argv[argc++] = NULL; 366 367 execvp(argv0, argv); 368 fatal("execvp"); 369 } 370 371 void 372 main_dispatch_frontend(int fd, short event, void *bula) 373 { 374 struct imsgev *iev = bula; 375 struct imsgbuf *ibuf; 376 struct imsg imsg; 377 struct imsg_ifinfo imsg_ifinfo; 378 ssize_t n; 379 int shut = 0; 380 int rdomain; 381 #ifndef SMALL 382 struct imsg_addrinfo imsg_addrinfo; 383 struct imsg_link_state imsg_link_state; 384 int verbose; 385 #endif /* SMALL */ 386 387 ibuf = &iev->ibuf; 388 389 if (event & EV_READ) { 390 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 391 fatal("imsg_read error"); 392 if (n == 0) /* Connection closed. */ 393 shut = 1; 394 } 395 if (event & EV_WRITE) { 396 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 397 fatal("msgbuf_write"); 398 if (n == 0) /* Connection closed. */ 399 shut = 1; 400 } 401 402 for (;;) { 403 if ((n = imsg_get(ibuf, &imsg)) == -1) 404 fatal("imsg_get"); 405 if (n == 0) /* No more messages. */ 406 break; 407 408 switch (imsg.hdr.type) { 409 case IMSG_OPEN_ICMP6SOCK: 410 log_debug("IMSG_OPEN_ICMP6SOCK"); 411 if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain)) 412 fatalx("%s: IMSG_OPEN_ICMP6SOCK wrong length: " 413 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 414 memcpy(&rdomain, imsg.data, sizeof(rdomain)); 415 open_icmp6sock(rdomain); 416 break; 417 #ifndef SMALL 418 case IMSG_CTL_LOG_VERBOSE: 419 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 420 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 421 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 422 memcpy(&verbose, imsg.data, sizeof(verbose)); 423 log_setverbose(verbose); 424 break; 425 case IMSG_UPDATE_ADDRESS: 426 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_addrinfo)) 427 fatalx("%s: IMSG_UPDATE_ADDRESS wrong length: " 428 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 429 memcpy(&imsg_addrinfo, imsg.data, 430 sizeof(imsg_addrinfo)); 431 main_imsg_compose_engine(IMSG_UPDATE_ADDRESS, 0, 432 &imsg_addrinfo, sizeof(imsg_addrinfo)); 433 break; 434 case IMSG_UPDATE_LINK_STATE: 435 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_link_state)) 436 fatalx("%s: IMSG_UPDATE_LINK_STATE wrong " 437 "length: %lu", __func__, 438 IMSG_DATA_SIZE(imsg)); 439 memcpy(&imsg_link_state, imsg.data, 440 sizeof(imsg_link_state)); 441 main_imsg_compose_engine(IMSG_UPDATE_LINK_STATE, 0, 442 &imsg_link_state, sizeof(imsg_link_state)); 443 break; 444 #endif /* SMALL */ 445 case IMSG_UPDATE_IF: 446 if (IMSG_DATA_SIZE(imsg) != sizeof(imsg_ifinfo)) 447 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 448 __func__, IMSG_DATA_SIZE(imsg)); 449 memcpy(&imsg_ifinfo, imsg.data, sizeof(imsg_ifinfo)); 450 if (get_soiikey(imsg_ifinfo.soiikey) == -1) 451 log_warn("get_soiikey"); 452 else 453 main_imsg_compose_engine(IMSG_UPDATE_IF, 0, 454 &imsg_ifinfo, sizeof(imsg_ifinfo)); 455 break; 456 default: 457 log_debug("%s: error handling imsg %d", __func__, 458 imsg.hdr.type); 459 break; 460 } 461 imsg_free(&imsg); 462 } 463 if (!shut) 464 imsg_event_add(iev); 465 else { 466 /* This pipe is dead. Remove its event handler */ 467 event_del(&iev->ev); 468 event_loopexit(NULL); 469 } 470 } 471 472 void 473 main_dispatch_engine(int fd, short event, void *bula) 474 { 475 struct imsgev *iev = bula; 476 struct imsgbuf *ibuf; 477 struct imsg imsg; 478 struct imsg_configure_address address; 479 struct imsg_configure_dfr dfr; 480 #ifndef SMALL 481 struct imsg_propose_rdns rdns; 482 #endif /* SMALL */ 483 ssize_t n; 484 int shut = 0; 485 486 ibuf = &iev->ibuf; 487 488 if (event & EV_READ) { 489 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 490 fatal("imsg_read error"); 491 if (n == 0) /* Connection closed. */ 492 shut = 1; 493 } 494 if (event & EV_WRITE) { 495 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 496 fatal("msgbuf_write"); 497 if (n == 0) /* Connection closed. */ 498 shut = 1; 499 } 500 501 for (;;) { 502 if ((n = imsg_get(ibuf, &imsg)) == -1) 503 fatal("imsg_get"); 504 if (n == 0) /* No more messages. */ 505 break; 506 507 switch (imsg.hdr.type) { 508 case IMSG_CONFIGURE_ADDRESS: 509 if (IMSG_DATA_SIZE(imsg) != sizeof(address)) 510 fatalx("%s: IMSG_CONFIGURE_ADDRESS wrong " 511 "length: %lu", __func__, 512 IMSG_DATA_SIZE(imsg)); 513 memcpy(&address, imsg.data, sizeof(address)); 514 configure_interface(&address); 515 break; 516 case IMSG_WITHDRAW_ADDRESS: 517 if (IMSG_DATA_SIZE(imsg) != sizeof(address)) 518 fatalx("%s: IMSG_WITHDRAW_ADDRESS wrong " 519 "length: %lu", __func__, 520 IMSG_DATA_SIZE(imsg)); 521 memcpy(&address, imsg.data, sizeof(address)); 522 delete_address(&address); 523 break; 524 case IMSG_CONFIGURE_DFR: 525 if (IMSG_DATA_SIZE(imsg) != sizeof(dfr)) 526 fatalx("%s: IMSG_CONFIGURE_DFR wrong " 527 "length: %lu", __func__, 528 IMSG_DATA_SIZE(imsg)); 529 memcpy(&dfr, imsg.data, sizeof(dfr)); 530 add_gateway(&dfr); 531 break; 532 case IMSG_WITHDRAW_DFR: 533 if (IMSG_DATA_SIZE(imsg) != sizeof(dfr)) 534 fatalx("%s: IMSG_WITHDRAW_DFR wrong " 535 "length: %lu", __func__, 536 IMSG_DATA_SIZE(imsg)); 537 memcpy(&dfr, imsg.data, sizeof(dfr)); 538 delete_gateway(&dfr); 539 break; 540 #ifndef SMALL 541 case IMSG_PROPOSE_RDNS: 542 if (IMSG_DATA_SIZE(imsg) != sizeof(rdns)) 543 fatalx("%s: IMSG_PROPOSE_RDNS wrong " 544 "length: %lu", __func__, 545 IMSG_DATA_SIZE(imsg)); 546 memcpy(&rdns, imsg.data, sizeof(rdns)); 547 if ((2 + rdns.rdns_count * sizeof(struct in6_addr)) > 548 sizeof(struct sockaddr_rtdns)) 549 fatalx("%s: rdns_count too big: %d", __func__, 550 rdns.rdns_count); 551 send_rdns_proposal(&rdns); 552 break; 553 #endif /* SMALL */ 554 default: 555 log_debug("%s: error handling imsg %d", __func__, 556 imsg.hdr.type); 557 break; 558 } 559 imsg_free(&imsg); 560 } 561 if (!shut) 562 imsg_event_add(iev); 563 else { 564 /* This pipe is dead. Remove its event handler. */ 565 event_del(&iev->ev); 566 event_loopexit(NULL); 567 } 568 } 569 570 int 571 main_imsg_compose_frontend(int type, int fd, void *data, uint16_t datalen) 572 { 573 if (iev_frontend) 574 return (imsg_compose_event(iev_frontend, type, 0, 0, fd, data, 575 datalen)); 576 else 577 return (-1); 578 } 579 580 int 581 main_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen) 582 { 583 if (iev_engine) 584 return(imsg_compose_event(iev_engine, type, 0, pid, -1, data, 585 datalen)); 586 else 587 return (-1); 588 } 589 590 void 591 imsg_event_add(struct imsgev *iev) 592 { 593 iev->events = EV_READ; 594 if (iev->ibuf.w.queued) 595 iev->events |= EV_WRITE; 596 597 event_del(&iev->ev); 598 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 599 event_add(&iev->ev, NULL); 600 } 601 602 int 603 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 604 pid_t pid, int fd, void *data, uint16_t datalen) 605 { 606 int ret; 607 608 if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 609 datalen)) != -1) 610 imsg_event_add(iev); 611 612 return (ret); 613 } 614 615 static int 616 main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 617 struct imsgbuf *engine_buf) 618 { 619 int pipe_frontend2engine[2]; 620 621 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 622 PF_UNSPEC, pipe_frontend2engine) == -1) 623 return (-1); 624 625 if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC, 0, 0, 626 pipe_frontend2engine[0], NULL, 0) == -1) 627 return (-1); 628 imsg_flush(frontend_buf); 629 if (imsg_compose(engine_buf, IMSG_SOCKET_IPC, 0, 0, 630 pipe_frontend2engine[1], NULL, 0) == -1) 631 return (-1); 632 imsg_flush(engine_buf); 633 return (0); 634 } 635 636 void 637 configure_interface(struct imsg_configure_address *address) 638 { 639 640 struct in6_aliasreq in6_addreq; 641 time_t t; 642 char *if_name; 643 644 memset(&in6_addreq, 0, sizeof(in6_addreq)); 645 646 if_name = if_indextoname(address->if_index, in6_addreq.ifra_name); 647 if (if_name == NULL) { 648 log_warnx("%s: cannot find interface %d", __func__, 649 address->if_index); 650 return; 651 } 652 653 memcpy(&in6_addreq.ifra_addr, &address->addr, 654 sizeof(in6_addreq.ifra_addr)); 655 memcpy(&in6_addreq.ifra_prefixmask.sin6_addr, &address->mask, 656 sizeof(in6_addreq.ifra_prefixmask.sin6_addr)); 657 in6_addreq.ifra_prefixmask.sin6_family = AF_INET6; 658 in6_addreq.ifra_prefixmask.sin6_len = 659 sizeof(in6_addreq.ifra_prefixmask); 660 661 t = time(NULL); 662 663 in6_addreq.ifra_lifetime.ia6t_expire = t + address->vltime; 664 in6_addreq.ifra_lifetime.ia6t_vltime = address->vltime; 665 666 in6_addreq.ifra_lifetime.ia6t_preferred = t + address->pltime; 667 in6_addreq.ifra_lifetime.ia6t_pltime = address->pltime; 668 669 in6_addreq.ifra_flags |= IN6_IFF_AUTOCONF; 670 671 if (address->privacy) 672 in6_addreq.ifra_flags |= IN6_IFF_TEMPORARY; 673 674 log_debug("%s: %s", __func__, if_name); 675 676 if (ioctl(ioctl_sock, SIOCAIFADDR_IN6, &in6_addreq) == -1) 677 fatal("SIOCAIFADDR_IN6"); 678 679 if (address->mtu) { 680 struct ifreq ifr; 681 682 strlcpy(ifr.ifr_name, in6_addreq.ifra_name, 683 sizeof(ifr.ifr_name)); 684 ifr.ifr_mtu = address->mtu; 685 log_debug("Setting MTU to %d", ifr.ifr_mtu); 686 687 if (ioctl(ioctl_sock, SIOCSIFMTU, &ifr) == -1) 688 log_warn("failed to set MTU"); 689 } 690 } 691 692 void 693 delete_address(struct imsg_configure_address *address) 694 { 695 696 struct in6_ifreq in6_ridreq; 697 char *if_name; 698 699 memset(&in6_ridreq, 0, sizeof(in6_ridreq)); 700 701 if_name = if_indextoname(address->if_index, in6_ridreq.ifr_name); 702 if (if_name == NULL) { 703 log_warnx("%s: cannot find interface %d", __func__, 704 address->if_index); 705 return; 706 } 707 708 memcpy(&in6_ridreq.ifr_addr, &address->addr, 709 sizeof(in6_ridreq.ifr_addr)); 710 711 log_debug("%s: %s", __func__, if_name); 712 713 if (ioctl(ioctl_sock, SIOCDIFADDR_IN6, &in6_ridreq) == -1) 714 log_warn("%s: cannot remove address", __func__); 715 716 } 717 718 #define ROUNDUP(a) \ 719 (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) 720 721 void 722 configure_gateway(struct imsg_configure_dfr *dfr, uint8_t rtm_type) 723 { 724 struct rt_msghdr rtm; 725 struct sockaddr_rtlabel rl; 726 struct sockaddr_in6 dst, gw, mask; 727 struct iovec iov[10]; 728 long pad = 0; 729 int iovcnt = 0, padlen; 730 731 memset(&rtm, 0, sizeof(rtm)); 732 733 rtm.rtm_version = RTM_VERSION; 734 rtm.rtm_type = rtm_type; 735 rtm.rtm_msglen = sizeof(rtm); 736 rtm.rtm_tableid = dfr->rdomain; 737 rtm.rtm_index = dfr->if_index; 738 rtm.rtm_seq = ++rtm_seq; 739 rtm.rtm_priority = RTP_NONE; 740 rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_LABEL; 741 rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC | RTF_MPATH; 742 743 iov[iovcnt].iov_base = &rtm; 744 iov[iovcnt++].iov_len = sizeof(rtm); 745 746 memset(&dst, 0, sizeof(mask)); 747 dst.sin6_family = AF_INET6; 748 dst.sin6_len = sizeof(struct sockaddr_in6); 749 750 iov[iovcnt].iov_base = &dst; 751 iov[iovcnt++].iov_len = sizeof(dst); 752 rtm.rtm_msglen += sizeof(dst); 753 padlen = ROUNDUP(sizeof(dst)) - sizeof(dst); 754 if (padlen > 0) { 755 iov[iovcnt].iov_base = &pad; 756 iov[iovcnt++].iov_len = padlen; 757 rtm.rtm_msglen += padlen; 758 } 759 760 memcpy(&gw, &dfr->addr, sizeof(gw)); 761 #ifdef __KAME__ 762 /* from route(8) getaddr()*/ 763 *(u_int16_t *)& gw.sin6_addr.s6_addr[2] = htons(gw.sin6_scope_id); 764 gw.sin6_scope_id = 0; 765 #endif 766 iov[iovcnt].iov_base = &gw; 767 iov[iovcnt++].iov_len = sizeof(gw); 768 rtm.rtm_msglen += sizeof(gw); 769 padlen = ROUNDUP(sizeof(gw)) - sizeof(gw); 770 if (padlen > 0) { 771 iov[iovcnt].iov_base = &pad; 772 iov[iovcnt++].iov_len = padlen; 773 rtm.rtm_msglen += padlen; 774 } 775 776 memset(&mask, 0, sizeof(mask)); 777 mask.sin6_family = AF_INET6; 778 mask.sin6_len = sizeof(struct sockaddr_in6); 779 iov[iovcnt].iov_base = &mask; 780 iov[iovcnt++].iov_len = sizeof(mask); 781 rtm.rtm_msglen += sizeof(mask); 782 padlen = ROUNDUP(sizeof(mask)) - sizeof(mask); 783 if (padlen > 0) { 784 iov[iovcnt].iov_base = &pad; 785 iov[iovcnt++].iov_len = padlen; 786 rtm.rtm_msglen += padlen; 787 } 788 789 memset(&rl, 0, sizeof(rl)); 790 rl.sr_len = sizeof(rl); 791 rl.sr_family = AF_UNSPEC; 792 (void)snprintf(rl.sr_label, sizeof(rl.sr_label), "%s", 793 SLAACD_RTA_LABEL); 794 iov[iovcnt].iov_base = &rl; 795 iov[iovcnt++].iov_len = sizeof(rl); 796 rtm.rtm_msglen += sizeof(rl); 797 padlen = ROUNDUP(sizeof(rl)) - sizeof(rl); 798 if (padlen > 0) { 799 iov[iovcnt].iov_base = &pad; 800 iov[iovcnt++].iov_len = padlen; 801 rtm.rtm_msglen += padlen; 802 } 803 804 if (writev(routesock, iov, iovcnt) == -1) 805 log_warn("failed to send route message"); 806 } 807 808 void 809 add_gateway(struct imsg_configure_dfr *dfr) 810 { 811 configure_gateway(dfr, RTM_ADD); 812 } 813 814 void 815 delete_gateway(struct imsg_configure_dfr *dfr) 816 { 817 configure_gateway(dfr, RTM_DELETE); 818 } 819 820 #ifndef SMALL 821 void 822 send_rdns_proposal(struct imsg_propose_rdns *rdns) 823 { 824 struct rt_msghdr rtm; 825 struct sockaddr_rtdns rtdns; 826 struct iovec iov[3]; 827 long pad = 0; 828 int iovcnt = 0, padlen; 829 830 memset(&rtm, 0, sizeof(rtm)); 831 832 rtm.rtm_version = RTM_VERSION; 833 rtm.rtm_type = RTM_PROPOSAL; 834 rtm.rtm_msglen = sizeof(rtm); 835 rtm.rtm_tableid = rdns->rdomain; 836 rtm.rtm_index = rdns->if_index; 837 rtm.rtm_seq = ++rtm_seq; 838 rtm.rtm_priority = RTP_PROPOSAL_SLAAC; 839 rtm.rtm_addrs = RTA_DNS; 840 rtm.rtm_flags = RTF_UP; 841 842 iov[iovcnt].iov_base = &rtm; 843 iov[iovcnt++].iov_len = sizeof(rtm); 844 845 memset(&rtdns, 0, sizeof(rtdns)); 846 rtdns.sr_family = AF_INET6; 847 rtdns.sr_len = 2 + rdns->rdns_count * sizeof(struct in6_addr); 848 memcpy(rtdns.sr_dns, rdns->rdns, sizeof(rtdns.sr_dns)); 849 850 iov[iovcnt].iov_base = &rtdns; 851 iov[iovcnt++].iov_len = sizeof(rtdns); 852 rtm.rtm_msglen += sizeof(rtdns); 853 padlen = ROUNDUP(sizeof(rtdns)) - sizeof(rtdns); 854 if (padlen > 0) { 855 iov[iovcnt].iov_base = &pad; 856 iov[iovcnt++].iov_len = padlen; 857 rtm.rtm_msglen += padlen; 858 } 859 860 if (writev(routesock, iov, iovcnt) == -1) 861 log_warn("failed to send route message"); 862 } 863 864 const char* 865 sin6_to_str(struct sockaddr_in6 *sin6) 866 { 867 static char hbuf[NI_MAXHOST]; 868 int error; 869 870 error = getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, hbuf, 871 sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); 872 if (error) { 873 log_warnx("%s", gai_strerror(error)); 874 strlcpy(hbuf, "unknown", sizeof(hbuf)); 875 } 876 return hbuf; 877 } 878 #endif /* SMALL */ 879 880 int 881 get_soiikey(uint8_t *key) 882 { 883 int mib[4] = {CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_SOIIKEY}; 884 size_t size = SLAACD_SOIIKEY_LEN; 885 886 return sysctl(mib, sizeof(mib) / sizeof(mib[0]), key, &size, NULL, 0); 887 } 888 889 void 890 open_icmp6sock(int rdomain) 891 { 892 int icmp6sock, on = 1; 893 894 log_debug("%s: %d", __func__, rdomain); 895 896 if ((icmp6sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, 897 IPPROTO_ICMPV6)) == -1) 898 fatal("ICMPv6 socket"); 899 900 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 901 sizeof(on)) == -1) 902 fatal("IPV6_RECVPKTINFO"); 903 904 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 905 sizeof(on)) == -1) 906 fatal("IPV6_RECVHOPLIMIT"); 907 908 if (setsockopt(icmp6sock, SOL_SOCKET, SO_RTABLE, &rdomain, 909 sizeof(rdomain)) == -1) { 910 /* we might race against removal of the rdomain */ 911 log_warn("setsockopt SO_RTABLE"); 912 close(icmp6sock); 913 return; 914 } 915 916 main_imsg_compose_frontend(IMSG_ICMP6SOCK, icmp6sock, &rdomain, 917 sizeof(rdomain)); 918 } 919