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