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