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