1 /* $OpenBSD: rad.c,v 1.29 2023/04/19 12:58:16 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2018 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/queue.h> 23 #include <sys/socket.h> 24 #include <sys/syslog.h> 25 #include <sys/uio.h> 26 #include <sys/wait.h> 27 28 #include <netinet/in.h> 29 #include <net/if.h> 30 #include <net/route.h> 31 #include <netinet/if_ether.h> 32 #include <netinet6/in6_var.h> 33 #include <netinet/icmp6.h> 34 35 #include <err.h> 36 #include <errno.h> 37 #include <event.h> 38 #include <fcntl.h> 39 #include <imsg.h> 40 #include <netdb.h> 41 #include <pwd.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <signal.h> 46 #include <unistd.h> 47 48 #include "log.h" 49 #include "rad.h" 50 #include "frontend.h" 51 #include "engine.h" 52 #include "control.h" 53 54 enum rad_process { 55 PROC_MAIN, 56 PROC_ENGINE, 57 PROC_FRONTEND 58 }; 59 60 __dead void usage(void); 61 __dead void main_shutdown(void); 62 63 void main_sig_handler(int, short, void *); 64 65 static pid_t start_child(enum rad_process, char *, int, int, int); 66 67 void main_dispatch_frontend(int, short, void *); 68 void main_dispatch_engine(int, short, void *); 69 void open_icmp6sock(int); 70 71 static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); 72 static int main_imsg_send_config(struct rad_conf *); 73 74 int main_reload(void); 75 int main_sendboth(enum imsg_type, void *, uint16_t); 76 77 void in6_prefixlen2mask(struct in6_addr *, int len); 78 79 struct rad_conf *main_conf; 80 static struct imsgev *iev_frontend; 81 static struct imsgev *iev_engine; 82 char *conffile; 83 pid_t frontend_pid; 84 pid_t engine_pid; 85 uint32_t cmd_opts; 86 87 void 88 main_sig_handler(int sig, short event, void *arg) 89 { 90 /* 91 * Normal signal handler rules don't apply because libevent 92 * decouples for us. 93 */ 94 95 switch (sig) { 96 case SIGTERM: 97 case SIGINT: 98 main_shutdown(); 99 break; 100 case SIGHUP: 101 if (main_reload() == -1) 102 log_warnx("configuration reload failed"); 103 else 104 log_debug("configuration reloaded"); 105 break; 106 default: 107 fatalx("unexpected signal"); 108 } 109 } 110 111 __dead void 112 usage(void) 113 { 114 extern char *__progname; 115 116 fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n", 117 __progname); 118 exit(1); 119 } 120 121 int 122 main(int argc, char *argv[]) 123 { 124 struct event ev_sigint, ev_sigterm, ev_sighup; 125 int ch; 126 int debug = 0, engine_flag = 0, frontend_flag = 0; 127 char *saved_argv0; 128 int pipe_main2frontend[2]; 129 int pipe_main2engine[2]; 130 int frontend_routesock, rtfilter; 131 int rtable_any = RTABLE_ANY; 132 int control_fd; 133 char *csock; 134 135 conffile = _PATH_CONF_FILE; 136 csock = _PATH_RAD_SOCKET; 137 138 log_init(1, LOG_DAEMON); /* Log to stderr until daemonized. */ 139 log_setverbose(1); 140 141 saved_argv0 = argv[0]; 142 if (saved_argv0 == NULL) 143 saved_argv0 = "rad"; 144 145 while ((ch = getopt(argc, argv, "dEFf:ns:v")) != -1) { 146 switch (ch) { 147 case 'd': 148 debug = 1; 149 break; 150 case 'E': 151 engine_flag = 1; 152 break; 153 case 'F': 154 frontend_flag = 1; 155 break; 156 case 'f': 157 conffile = optarg; 158 break; 159 case 'n': 160 cmd_opts |= OPT_NOACTION; 161 break; 162 case 's': 163 csock = optarg; 164 break; 165 case 'v': 166 if (cmd_opts & OPT_VERBOSE) 167 cmd_opts |= OPT_VERBOSE2; 168 cmd_opts |= OPT_VERBOSE; 169 break; 170 default: 171 usage(); 172 } 173 } 174 175 argc -= optind; 176 argv += optind; 177 if (argc > 0 || (engine_flag && frontend_flag)) 178 usage(); 179 180 if (engine_flag) 181 engine(debug, cmd_opts & OPT_VERBOSE); 182 else if (frontend_flag) 183 frontend(debug, cmd_opts & OPT_VERBOSE); 184 185 /* parse config file */ 186 if ((main_conf = parse_config(conffile)) == NULL) { 187 exit(1); 188 } 189 190 if (cmd_opts & OPT_NOACTION) { 191 if (cmd_opts & OPT_VERBOSE) 192 print_config(main_conf); 193 else 194 fprintf(stderr, "configuration OK\n"); 195 exit(0); 196 } 197 198 /* Check for root privileges. */ 199 if (geteuid()) 200 errx(1, "need root privileges"); 201 202 /* Check for assigned daemon user */ 203 if (getpwnam(RAD_USER) == NULL) 204 errx(1, "unknown user %s", RAD_USER); 205 206 log_init(debug, LOG_DAEMON); 207 log_setverbose(cmd_opts & OPT_VERBOSE); 208 209 if (!debug) 210 daemon(1, 0); 211 212 log_info("startup"); 213 214 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 215 PF_UNSPEC, pipe_main2frontend) == -1) 216 fatal("main2frontend socketpair"); 217 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 218 PF_UNSPEC, pipe_main2engine) == -1) 219 fatal("main2engine socketpair"); 220 221 /* Start children. */ 222 engine_pid = start_child(PROC_ENGINE, saved_argv0, pipe_main2engine[1], 223 debug, cmd_opts & OPT_VERBOSE); 224 frontend_pid = start_child(PROC_FRONTEND, saved_argv0, 225 pipe_main2frontend[1], debug, cmd_opts & OPT_VERBOSE); 226 227 log_procinit("main"); 228 229 event_init(); 230 231 /* Setup signal handler. */ 232 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 233 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 234 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 235 signal_add(&ev_sigint, NULL); 236 signal_add(&ev_sigterm, NULL); 237 signal_add(&ev_sighup, NULL); 238 signal(SIGPIPE, SIG_IGN); 239 240 /* Setup pipes to children. */ 241 242 if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 243 (iev_engine = malloc(sizeof(struct imsgev))) == NULL) 244 fatal(NULL); 245 imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 246 iev_frontend->handler = main_dispatch_frontend; 247 imsg_init(&iev_engine->ibuf, pipe_main2engine[0]); 248 iev_engine->handler = main_dispatch_engine; 249 250 /* Setup event handlers for pipes to engine & frontend. */ 251 iev_frontend->events = EV_READ; 252 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 253 iev_frontend->events, iev_frontend->handler, iev_frontend); 254 event_add(&iev_frontend->ev, NULL); 255 256 iev_engine->events = EV_READ; 257 event_set(&iev_engine->ev, iev_engine->ibuf.fd, iev_engine->events, 258 iev_engine->handler, iev_engine); 259 event_add(&iev_engine->ev, NULL); 260 261 if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, &iev_engine->ibuf)) 262 fatal("could not establish imsg links"); 263 264 if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 265 AF_INET6)) == -1) 266 fatal("route socket"); 267 268 rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | 269 ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_CHGADDRATTR); 270 if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, 271 &rtfilter, sizeof(rtfilter)) == -1) 272 fatal("setsockopt(ROUTE_MSGFILTER)"); 273 if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_TABLEFILTER, 274 &rtable_any, sizeof(rtable_any)) == -1) 275 fatal("setsockopt(ROUTE_TABLEFILTER)"); 276 277 if ((control_fd = control_init(csock)) == -1) 278 fatalx("control socket setup failed"); 279 280 main_imsg_compose_frontend(IMSG_ROUTESOCK, frontend_routesock, 281 NULL, 0); 282 main_imsg_compose_frontend(IMSG_CONTROLFD, control_fd, NULL, 0); 283 main_imsg_send_config(main_conf); 284 285 if (pledge("stdio inet rpath sendfd mcast wroute", NULL) == -1) 286 fatal("pledge"); 287 288 main_imsg_compose_frontend(IMSG_STARTUP, -1, NULL, 0); 289 290 event_dispatch(); 291 292 main_shutdown(); 293 return (0); 294 } 295 296 __dead void 297 main_shutdown(void) 298 { 299 pid_t pid; 300 int status; 301 302 /* Close pipes. */ 303 msgbuf_clear(&iev_frontend->ibuf.w); 304 close(iev_frontend->ibuf.fd); 305 msgbuf_clear(&iev_engine->ibuf.w); 306 close(iev_engine->ibuf.fd); 307 308 config_clear(main_conf); 309 310 log_debug("waiting for children to terminate"); 311 do { 312 pid = wait(&status); 313 if (pid == -1) { 314 if (errno != EINTR && errno != ECHILD) 315 fatal("wait"); 316 } else if (WIFSIGNALED(status)) 317 log_warnx("%s terminated; signal %d", 318 (pid == engine_pid) ? "engine" : 319 "frontend", WTERMSIG(status)); 320 } while (pid != -1 || (pid == -1 && errno == EINTR)); 321 322 free(iev_frontend); 323 free(iev_engine); 324 325 log_info("terminating"); 326 exit(0); 327 } 328 329 static pid_t 330 start_child(enum rad_process p, char *argv0, int fd, int debug, int verbose) 331 { 332 char *argv[6]; 333 int argc = 0; 334 pid_t pid; 335 336 switch (pid = fork()) { 337 case -1: 338 fatal("cannot fork"); 339 case 0: 340 break; 341 default: 342 close(fd); 343 return (pid); 344 } 345 346 if (fd != 3) { 347 if (dup2(fd, 3) == -1) 348 fatal("cannot setup imsg fd"); 349 } else if (fcntl(fd, F_SETFD, 0) == -1) 350 fatal("cannot setup imsg fd"); 351 352 argv[argc++] = argv0; 353 switch (p) { 354 case PROC_MAIN: 355 fatalx("Can not start main process"); 356 case PROC_ENGINE: 357 argv[argc++] = "-E"; 358 break; 359 case PROC_FRONTEND: 360 argv[argc++] = "-F"; 361 break; 362 } 363 if (debug) 364 argv[argc++] = "-d"; 365 if (verbose) 366 argv[argc++] = "-v"; 367 argv[argc++] = NULL; 368 369 execvp(argv0, argv); 370 fatal("execvp"); 371 } 372 373 void 374 main_dispatch_frontend(int fd, short event, void *bula) 375 { 376 struct imsgev *iev = bula; 377 struct imsgbuf *ibuf; 378 struct imsg imsg; 379 ssize_t n; 380 int shut = 0, verbose; 381 int rdomain; 382 383 ibuf = &iev->ibuf; 384 385 if (event & EV_READ) { 386 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 387 fatal("imsg_read error"); 388 if (n == 0) /* Connection closed. */ 389 shut = 1; 390 } 391 if (event & EV_WRITE) { 392 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 393 fatal("msgbuf_write"); 394 if (n == 0) /* Connection closed. */ 395 shut = 1; 396 } 397 398 for (;;) { 399 if ((n = imsg_get(ibuf, &imsg)) == -1) 400 fatal("imsg_get"); 401 if (n == 0) /* No more messages. */ 402 break; 403 404 switch (imsg.hdr.type) { 405 case IMSG_OPEN_ICMP6SOCK: 406 log_debug("IMSG_OPEN_ICMP6SOCK"); 407 if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain)) 408 fatalx("%s: IMSG_OPEN_ICMP6SOCK wrong length: " 409 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 410 memcpy(&rdomain, imsg.data, sizeof(rdomain)); 411 open_icmp6sock(rdomain); 412 break; 413 case IMSG_CTL_RELOAD: 414 if (main_reload() == -1) 415 log_warnx("configuration reload failed"); 416 else 417 log_warnx("configuration reloaded"); 418 break; 419 case IMSG_CTL_LOG_VERBOSE: 420 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 421 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 422 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 423 memcpy(&verbose, imsg.data, sizeof(verbose)); 424 log_setverbose(verbose); 425 break; 426 default: 427 log_debug("%s: error handling imsg %d", __func__, 428 imsg.hdr.type); 429 break; 430 } 431 imsg_free(&imsg); 432 } 433 if (!shut) 434 imsg_event_add(iev); 435 else { 436 /* This pipe is dead. Remove its event handler */ 437 event_del(&iev->ev); 438 event_loopexit(NULL); 439 } 440 } 441 442 void 443 main_dispatch_engine(int fd, short event, void *bula) 444 { 445 struct imsgev *iev = bula; 446 struct imsgbuf *ibuf; 447 struct imsg imsg; 448 ssize_t n; 449 int shut = 0; 450 451 ibuf = &iev->ibuf; 452 453 if (event & EV_READ) { 454 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 455 fatal("imsg_read error"); 456 if (n == 0) /* Connection closed. */ 457 shut = 1; 458 } 459 if (event & EV_WRITE) { 460 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 461 fatal("msgbuf_write"); 462 if (n == 0) /* Connection closed. */ 463 shut = 1; 464 } 465 466 for (;;) { 467 if ((n = imsg_get(ibuf, &imsg)) == -1) 468 fatal("imsg_get"); 469 if (n == 0) /* No more messages. */ 470 break; 471 472 switch (imsg.hdr.type) { 473 default: 474 log_debug("%s: error handling imsg %d", __func__, 475 imsg.hdr.type); 476 break; 477 } 478 imsg_free(&imsg); 479 } 480 if (!shut) 481 imsg_event_add(iev); 482 else { 483 /* This pipe is dead. Remove its event handler. */ 484 event_del(&iev->ev); 485 event_loopexit(NULL); 486 } 487 } 488 489 int 490 main_imsg_compose_frontend(int type, int fd, void *data, uint16_t datalen) 491 { 492 if (iev_frontend) 493 return (imsg_compose_event(iev_frontend, type, 0, 0, fd, data, 494 datalen)); 495 else 496 return (-1); 497 } 498 499 void 500 main_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen) 501 { 502 if (iev_engine) 503 imsg_compose_event(iev_engine, type, 0, pid, -1, data, 504 datalen); 505 } 506 507 void 508 imsg_event_add(struct imsgev *iev) 509 { 510 iev->events = EV_READ; 511 if (iev->ibuf.w.queued) 512 iev->events |= EV_WRITE; 513 514 event_del(&iev->ev); 515 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 516 event_add(&iev->ev, NULL); 517 } 518 519 int 520 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 521 pid_t pid, int fd, void *data, uint16_t datalen) 522 { 523 int ret; 524 525 if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 526 datalen)) != -1) 527 imsg_event_add(iev); 528 529 return (ret); 530 } 531 532 static int 533 main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 534 struct imsgbuf *engine_buf) 535 { 536 int pipe_frontend2engine[2]; 537 538 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 539 PF_UNSPEC, pipe_frontend2engine) == -1) 540 return (-1); 541 542 if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC, 0, 0, 543 pipe_frontend2engine[0], NULL, 0) == -1) 544 return (-1); 545 if (imsg_compose(engine_buf, IMSG_SOCKET_IPC, 0, 0, 546 pipe_frontend2engine[1], NULL, 0) == -1) 547 return (-1); 548 549 return (0); 550 } 551 552 int 553 main_reload(void) 554 { 555 struct rad_conf *xconf; 556 557 if ((xconf = parse_config(conffile)) == NULL) 558 return (-1); 559 560 if (main_imsg_send_config(xconf) == -1) 561 return (-1); 562 563 merge_config(main_conf, xconf); 564 565 return (0); 566 } 567 568 int 569 main_imsg_send_config(struct rad_conf *xconf) 570 { 571 struct ra_iface_conf *ra_iface_conf; 572 struct ra_prefix_conf *ra_prefix_conf; 573 struct ra_rdnss_conf *ra_rdnss_conf; 574 struct ra_dnssl_conf *ra_dnssl_conf; 575 struct ra_pref64_conf *pref64; 576 577 /* Send fixed part of config to children. */ 578 if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 579 return (-1); 580 581 /* send global dns options to children */ 582 SIMPLEQ_FOREACH(ra_rdnss_conf, &xconf->ra_options.ra_rdnss_list, 583 entry) { 584 if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf, 585 sizeof(*ra_rdnss_conf)) == -1) 586 return (-1); 587 } 588 SIMPLEQ_FOREACH(ra_dnssl_conf, &xconf->ra_options.ra_dnssl_list, 589 entry) { 590 if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf, 591 sizeof(*ra_dnssl_conf)) == -1) 592 return (-1); 593 } 594 595 /* send global pref64 list to children */ 596 SIMPLEQ_FOREACH(pref64, &xconf->ra_options.ra_pref64_list, 597 entry) { 598 if (main_sendboth(IMSG_RECONF_RA_PREF64, pref64, 599 sizeof(*pref64)) == -1) 600 return (-1); 601 } 602 603 /* Send the interface list to children. */ 604 SIMPLEQ_FOREACH(ra_iface_conf, &xconf->ra_iface_list, entry) { 605 if (main_sendboth(IMSG_RECONF_RA_IFACE, ra_iface_conf, 606 sizeof(*ra_iface_conf)) == -1) 607 return (-1); 608 if (ra_iface_conf->autoprefix) { 609 if (main_sendboth(IMSG_RECONF_RA_AUTOPREFIX, 610 ra_iface_conf->autoprefix, 611 sizeof(*ra_iface_conf->autoprefix)) == -1) 612 return (-1); 613 } 614 SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list, 615 entry) { 616 if (main_sendboth(IMSG_RECONF_RA_PREFIX, 617 ra_prefix_conf, sizeof(*ra_prefix_conf)) == -1) 618 return (-1); 619 } 620 SIMPLEQ_FOREACH(ra_rdnss_conf, 621 &ra_iface_conf->ra_options.ra_rdnss_list, entry) { 622 if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf, 623 sizeof(*ra_rdnss_conf)) == -1) 624 return (-1); 625 } 626 SIMPLEQ_FOREACH(ra_dnssl_conf, 627 &ra_iface_conf->ra_options.ra_dnssl_list, entry) { 628 if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf, 629 sizeof(*ra_dnssl_conf)) == -1) 630 return (-1); 631 } 632 SIMPLEQ_FOREACH(pref64, 633 &ra_iface_conf->ra_options.ra_pref64_list, entry) { 634 if (main_sendboth(IMSG_RECONF_RA_PREF64, pref64, 635 sizeof(*pref64)) == -1) 636 return (-1); 637 } 638 } 639 640 /* Tell children the revised config is now complete. */ 641 if (main_sendboth(IMSG_RECONF_END, NULL, 0) == -1) 642 return (-1); 643 644 return (0); 645 } 646 647 int 648 main_sendboth(enum imsg_type type, void *buf, uint16_t len) 649 { 650 if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) 651 return (-1); 652 if (imsg_compose_event(iev_engine, type, 0, 0, -1, buf, len) == -1) 653 return (-1); 654 return (0); 655 } 656 657 void 658 free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf) 659 { 660 struct ra_prefix_conf *prefix; 661 struct ra_pref64_conf *pref64; 662 663 if (!ra_iface_conf) 664 return; 665 666 free(ra_iface_conf->autoprefix); 667 668 while ((prefix = SIMPLEQ_FIRST(&ra_iface_conf->ra_prefix_list)) != 669 NULL) { 670 SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_prefix_list, entry); 671 free(prefix); 672 } 673 674 free_dns_options(&ra_iface_conf->ra_options); 675 676 while ((pref64 = 677 SIMPLEQ_FIRST(&ra_iface_conf->ra_options.ra_pref64_list)) != NULL) { 678 SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_options.ra_pref64_list, 679 entry); 680 free(pref64); 681 } 682 683 free(ra_iface_conf); 684 } 685 686 void 687 free_dns_options(struct ra_options_conf *ra_options) 688 { 689 struct ra_rdnss_conf *ra_rdnss; 690 struct ra_dnssl_conf *ra_dnssl; 691 692 while ((ra_rdnss = SIMPLEQ_FIRST(&ra_options->ra_rdnss_list)) != NULL) { 693 SIMPLEQ_REMOVE_HEAD(&ra_options->ra_rdnss_list, entry); 694 free(ra_rdnss); 695 } 696 ra_options->rdnss_count = 0; 697 698 while ((ra_dnssl = SIMPLEQ_FIRST(&ra_options->ra_dnssl_list)) != NULL) { 699 SIMPLEQ_REMOVE_HEAD(&ra_options->ra_dnssl_list, entry); 700 free(ra_dnssl); 701 } 702 ra_options->dnssl_len = 0; 703 } 704 705 void 706 merge_config(struct rad_conf *conf, struct rad_conf *xconf) 707 { 708 struct ra_iface_conf *ra_iface_conf; 709 struct ra_pref64_conf *pref64; 710 711 /* Remove & discard existing interfaces. */ 712 while ((ra_iface_conf = SIMPLEQ_FIRST(&conf->ra_iface_list)) != NULL) { 713 SIMPLEQ_REMOVE_HEAD(&conf->ra_iface_list, entry); 714 free_ra_iface_conf(ra_iface_conf); 715 } 716 free_dns_options(&conf->ra_options); 717 718 while ((pref64 = SIMPLEQ_FIRST(&conf->ra_options.ra_pref64_list)) 719 != NULL) { 720 SIMPLEQ_REMOVE_HEAD(&conf->ra_options.ra_pref64_list, entry); 721 free(pref64); 722 } 723 724 conf->ra_options = xconf->ra_options; 725 SIMPLEQ_INIT(&conf->ra_options.ra_rdnss_list); 726 SIMPLEQ_INIT(&conf->ra_options.ra_dnssl_list); 727 SIMPLEQ_INIT(&conf->ra_options.ra_pref64_list); 728 729 /* Add new interfaces. */ 730 SIMPLEQ_CONCAT(&conf->ra_iface_list, &xconf->ra_iface_list); 731 732 /* Add dns options */ 733 SIMPLEQ_CONCAT(&conf->ra_options.ra_rdnss_list, 734 &xconf->ra_options.ra_rdnss_list); 735 SIMPLEQ_CONCAT(&conf->ra_options.ra_dnssl_list, 736 &xconf->ra_options.ra_dnssl_list); 737 SIMPLEQ_CONCAT(&conf->ra_options.ra_pref64_list, 738 &xconf->ra_options.ra_pref64_list); 739 free(xconf); 740 } 741 742 struct rad_conf * 743 config_new_empty(void) 744 { 745 struct rad_conf *xconf; 746 747 xconf = calloc(1, sizeof(*xconf)); 748 if (xconf == NULL) 749 fatal(NULL); 750 751 SIMPLEQ_INIT(&xconf->ra_iface_list); 752 753 xconf->ra_options.dfr = 1; 754 xconf->ra_options.cur_hl = 0; 755 xconf->ra_options.m_flag = 0; 756 xconf->ra_options.o_flag = 0; 757 xconf->ra_options.router_lifetime = ADV_DEFAULT_LIFETIME; 758 xconf->ra_options.reachable_time = 0; 759 xconf->ra_options.retrans_timer = 0; 760 xconf->ra_options.mtu = 0; 761 xconf->ra_options.rdns_lifetime = DEFAULT_RDNS_LIFETIME; 762 SIMPLEQ_INIT(&xconf->ra_options.ra_rdnss_list); 763 SIMPLEQ_INIT(&xconf->ra_options.ra_dnssl_list); 764 SIMPLEQ_INIT(&xconf->ra_options.ra_pref64_list); 765 766 return (xconf); 767 } 768 769 void 770 config_clear(struct rad_conf *conf) 771 { 772 struct rad_conf *xconf; 773 774 /* Merge current config with an empty config. */ 775 xconf = config_new_empty(); 776 merge_config(conf, xconf); 777 778 free(conf); 779 } 780 781 void 782 mask_prefix(struct in6_addr* in6, int len) 783 { 784 uint8_t bitmask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe}; 785 int i, skip; 786 787 if (len < 0 || len > 128) 788 fatalx("invalid prefix length: %d", len); 789 790 skip = len / 8; 791 792 if (skip < 16) 793 in6->s6_addr[skip] &= bitmask[len % 8]; 794 795 for (i = skip + 1; i < 16; i++) 796 in6->s6_addr[i] = 0; 797 } 798 799 const char* 800 sin6_to_str(struct sockaddr_in6 *sin6) 801 { 802 static char hbuf[NI_MAXHOST]; 803 int error; 804 805 error = getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, hbuf, 806 sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); 807 if (error) { 808 log_warnx("%s", gai_strerror(error)); 809 strlcpy(hbuf, "unknown", sizeof(hbuf)); 810 } 811 return hbuf; 812 } 813 814 const char* 815 in6_to_str(struct in6_addr *in6) 816 { 817 818 struct sockaddr_in6 sin6; 819 820 memset(&sin6, 0, sizeof(sin6)); 821 sin6.sin6_len = sizeof(sin6); 822 sin6.sin6_family = AF_INET6; 823 sin6.sin6_addr = *in6; 824 825 return (sin6_to_str(&sin6)); 826 } 827 828 void 829 open_icmp6sock(int rdomain) 830 { 831 int icmp6sock, on = 1, off = 0; 832 833 log_debug("%s: %d", __func__, rdomain); 834 835 if ((icmp6sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, 836 IPPROTO_ICMPV6)) == -1) 837 fatal("ICMPv6 socket"); 838 839 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 840 sizeof(on)) == -1) 841 fatal("IPV6_RECVPKTINFO"); 842 843 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 844 sizeof(on)) == -1) 845 fatal("IPV6_RECVHOPLIMIT"); 846 847 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, 848 sizeof(off)) == -1) 849 fatal("IPV6_RECVHOPLIMIT"); 850 851 if (setsockopt(icmp6sock, SOL_SOCKET, SO_RTABLE, &rdomain, 852 sizeof(rdomain)) == -1) { 853 /* we might race against removal of the rdomain */ 854 log_warn("setsockopt SO_RTABLE"); 855 close(icmp6sock); 856 return; 857 } 858 859 main_imsg_compose_frontend(IMSG_ICMP6SOCK, icmp6sock, &rdomain, 860 sizeof(rdomain)); 861 } 862