1 /* $OpenBSD: rad.c,v 1.16 2018/09/16 08:53:02 bluhm 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/in.h> 32 #include <netinet/if_ether.h> 33 #include <netinet6/in6_var.h> 34 #include <netinet/icmp6.h> 35 36 #include <err.h> 37 #include <errno.h> 38 #include <event.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 __dead void usage(void); 55 __dead void main_shutdown(void); 56 57 void main_sig_handler(int, short, void *); 58 59 static pid_t start_child(int, char *, int, int, int); 60 61 void main_dispatch_frontend(int, short, void *); 62 void main_dispatch_engine(int, short, void *); 63 64 static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); 65 static int main_imsg_send_config(struct rad_conf *); 66 67 int main_reload(void); 68 int main_sendboth(enum imsg_type, void *, uint16_t); 69 70 void in6_prefixlen2mask(struct in6_addr *, int len); 71 72 struct rad_conf *main_conf; 73 struct imsgev *iev_frontend; 74 struct imsgev *iev_engine; 75 char *conffile; 76 77 pid_t frontend_pid; 78 pid_t engine_pid; 79 80 uint32_t cmd_opts; 81 82 void 83 main_sig_handler(int sig, short event, void *arg) 84 { 85 struct rad_conf empty_conf; 86 87 /* 88 * Normal signal handler rules don't apply because libevent 89 * decouples for us. 90 */ 91 92 switch (sig) { 93 case SIGTERM: 94 case SIGINT: 95 memset(&empty_conf, 0, sizeof(empty_conf)); 96 (void)main_imsg_send_config(&empty_conf); 97 (void)main_imsg_compose_frontend(IMSG_SHUTDOWN, 0, NULL, 0); 98 break; 99 case SIGHUP: 100 if (main_reload() == -1) 101 log_warnx("configuration reload failed"); 102 else 103 log_debug("configuration reloaded"); 104 break; 105 default: 106 fatalx("unexpected signal"); 107 } 108 } 109 110 __dead void 111 usage(void) 112 { 113 extern char *__progname; 114 115 fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n", 116 __progname); 117 exit(1); 118 } 119 120 int 121 main(int argc, char *argv[]) 122 { 123 struct event ev_sigint, ev_sigterm, ev_sighup; 124 struct icmp6_filter filt; 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 icmp6sock, on = 1, off = 0; 131 int frontend_routesock, rtfilter; 132 int control_fd; 133 char *csock; 134 135 conffile = CONF_FILE; 136 csock = 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 rad_process = PROC_MAIN; 228 log_procinit(log_procnames[rad_process]); 229 230 event_init(); 231 232 /* Setup signal handler. */ 233 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 234 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 235 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 236 signal_add(&ev_sigint, NULL); 237 signal_add(&ev_sigterm, NULL); 238 signal_add(&ev_sighup, NULL); 239 signal(SIGPIPE, SIG_IGN); 240 241 /* Setup pipes to children. */ 242 243 if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 244 (iev_engine = malloc(sizeof(struct imsgev))) == NULL) 245 fatal(NULL); 246 imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 247 iev_frontend->handler = main_dispatch_frontend; 248 imsg_init(&iev_engine->ibuf, pipe_main2engine[0]); 249 iev_engine->handler = main_dispatch_engine; 250 251 /* Setup event handlers for pipes to engine & frontend. */ 252 iev_frontend->events = EV_READ; 253 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 254 iev_frontend->events, iev_frontend->handler, iev_frontend); 255 event_add(&iev_frontend->ev, NULL); 256 257 iev_engine->events = EV_READ; 258 event_set(&iev_engine->ev, iev_engine->ibuf.fd, iev_engine->events, 259 iev_engine->handler, iev_engine); 260 event_add(&iev_engine->ev, NULL); 261 262 if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, &iev_engine->ibuf)) 263 fatal("could not establish imsg links"); 264 265 if ((icmp6sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC, 266 IPPROTO_ICMPV6)) < 0) 267 fatal("ICMPv6 socket"); 268 269 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, 270 sizeof(on)) < 0) 271 fatal("IPV6_RECVPKTINFO"); 272 273 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, 274 sizeof(on)) < 0) 275 fatal("IPV6_RECVHOPLIMIT"); 276 277 if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, 278 sizeof(off)) < 0) 279 fatal("IPV6_RECVHOPLIMIT"); 280 281 /* only router advertisements and solicitations */ 282 ICMP6_FILTER_SETBLOCKALL(&filt); 283 ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt); 284 ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt); 285 if (setsockopt(icmp6sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, 286 sizeof(filt)) == -1) 287 fatal("ICMP6_FILTER"); 288 289 if ((frontend_routesock = socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, 290 AF_INET6)) < 0) 291 fatal("route socket"); 292 293 rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | 294 ROUTE_FILTER(RTM_DELADDR); 295 if (setsockopt(frontend_routesock, PF_ROUTE, ROUTE_MSGFILTER, 296 &rtfilter, sizeof(rtfilter)) < 0) 297 fatal("setsockopt(ROUTE_MSGFILTER)"); 298 299 if ((control_fd = control_init(csock)) == -1) 300 fatalx("control socket setup failed"); 301 302 main_imsg_compose_frontend_fd(IMSG_ICMP6SOCK, 0, icmp6sock); 303 main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); 304 main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); 305 main_imsg_send_config(main_conf); 306 307 if (pledge("stdio rpath sendfd", NULL) == -1) 308 fatal("pledge"); 309 310 main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); 311 312 event_dispatch(); 313 314 main_shutdown(); 315 return (0); 316 } 317 318 __dead void 319 main_shutdown(void) 320 { 321 pid_t pid; 322 int status; 323 324 /* Close pipes. */ 325 msgbuf_clear(&iev_frontend->ibuf.w); 326 close(iev_frontend->ibuf.fd); 327 msgbuf_clear(&iev_engine->ibuf.w); 328 close(iev_engine->ibuf.fd); 329 330 config_clear(main_conf); 331 332 log_debug("waiting for children to terminate"); 333 do { 334 pid = wait(&status); 335 if (pid == -1) { 336 if (errno != EINTR && errno != ECHILD) 337 fatal("wait"); 338 } else if (WIFSIGNALED(status)) 339 log_warnx("%s terminated; signal %d", 340 (pid == engine_pid) ? "engine" : 341 "frontend", WTERMSIG(status)); 342 } while (pid != -1 || (pid == -1 && errno == EINTR)); 343 344 free(iev_frontend); 345 free(iev_engine); 346 347 log_info("terminating"); 348 exit(0); 349 } 350 351 static pid_t 352 start_child(int p, char *argv0, int fd, int debug, int verbose) 353 { 354 char *argv[6]; 355 int argc = 0; 356 pid_t pid; 357 358 switch (pid = fork()) { 359 case -1: 360 fatal("cannot fork"); 361 case 0: 362 break; 363 default: 364 close(fd); 365 return (pid); 366 } 367 368 if (dup2(fd, 3) == -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 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 ssize_t n; 399 int shut = 0, verbose; 400 401 ibuf = &iev->ibuf; 402 403 if (event & EV_READ) { 404 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 405 fatal("imsg_read error"); 406 if (n == 0) /* Connection closed. */ 407 shut = 1; 408 } 409 if (event & EV_WRITE) { 410 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 411 fatal("msgbuf_write"); 412 if (n == 0) /* Connection closed. */ 413 shut = 1; 414 } 415 416 for (;;) { 417 if ((n = imsg_get(ibuf, &imsg)) == -1) 418 fatal("imsg_get"); 419 if (n == 0) /* No more messages. */ 420 break; 421 422 switch (imsg.hdr.type) { 423 case IMSG_STARTUP_DONE: 424 if (pledge("stdio rpath", NULL) == -1) 425 fatal("pledge"); 426 break; 427 case IMSG_CTL_RELOAD: 428 if (main_reload() == -1) 429 log_warnx("configuration reload failed"); 430 else 431 log_warnx("configuration reloaded"); 432 break; 433 case IMSG_CTL_LOG_VERBOSE: 434 /* Already checked by frontend. */ 435 memcpy(&verbose, imsg.data, sizeof(verbose)); 436 log_setverbose(verbose); 437 break; 438 case IMSG_SHUTDOWN: 439 shut = 1; 440 break; 441 default: 442 log_debug("%s: error handling imsg %d", __func__, 443 imsg.hdr.type); 444 break; 445 } 446 imsg_free(&imsg); 447 } 448 if (!shut) 449 imsg_event_add(iev); 450 else { 451 /* This pipe is dead. Remove its event handler */ 452 event_del(&iev->ev); 453 event_loopexit(NULL); 454 } 455 } 456 457 void 458 main_dispatch_engine(int fd, short event, void *bula) 459 { 460 struct imsgev *iev = bula; 461 struct imsgbuf *ibuf; 462 struct imsg imsg; 463 ssize_t n; 464 int shut = 0; 465 466 ibuf = &iev->ibuf; 467 468 if (event & EV_READ) { 469 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 470 fatal("imsg_read error"); 471 if (n == 0) /* Connection closed. */ 472 shut = 1; 473 } 474 if (event & EV_WRITE) { 475 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 476 fatal("msgbuf_write"); 477 if (n == 0) /* Connection closed. */ 478 shut = 1; 479 } 480 481 for (;;) { 482 if ((n = imsg_get(ibuf, &imsg)) == -1) 483 fatal("imsg_get"); 484 if (n == 0) /* No more messages. */ 485 break; 486 487 switch (imsg.hdr.type) { 488 default: 489 log_debug("%s: error handling imsg %d", __func__, 490 imsg.hdr.type); 491 break; 492 } 493 imsg_free(&imsg); 494 } 495 if (!shut) 496 imsg_event_add(iev); 497 else { 498 /* This pipe is dead. Remove its event handler. */ 499 event_del(&iev->ev); 500 event_loopexit(NULL); 501 } 502 } 503 504 void 505 main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 506 { 507 if (iev_frontend) 508 imsg_compose_event(iev_frontend, type, 0, pid, -1, data, 509 datalen); 510 } 511 512 void 513 main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) 514 { 515 if (iev_frontend) 516 imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0); 517 } 518 519 520 void 521 main_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen) 522 { 523 if (iev_engine) 524 imsg_compose_event(iev_engine, type, 0, pid, -1, data, 525 datalen); 526 } 527 528 void 529 imsg_event_add(struct imsgev *iev) 530 { 531 iev->events = EV_READ; 532 if (iev->ibuf.w.queued) 533 iev->events |= EV_WRITE; 534 535 event_del(&iev->ev); 536 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 537 event_add(&iev->ev, NULL); 538 } 539 540 int 541 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 542 pid_t pid, int fd, void *data, uint16_t datalen) 543 { 544 int ret; 545 546 if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 547 datalen)) != -1) 548 imsg_event_add(iev); 549 550 return (ret); 551 } 552 553 static int 554 main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 555 struct imsgbuf *engine_buf) 556 { 557 int pipe_frontend2engine[2]; 558 559 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 560 PF_UNSPEC, pipe_frontend2engine) == -1) 561 return (-1); 562 563 if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC, 0, 0, 564 pipe_frontend2engine[0], NULL, 0) == -1) 565 return (-1); 566 if (imsg_compose(engine_buf, IMSG_SOCKET_IPC, 0, 0, 567 pipe_frontend2engine[1], NULL, 0) == -1) 568 return (-1); 569 570 return (0); 571 } 572 573 int 574 main_reload(void) 575 { 576 struct rad_conf *xconf; 577 578 if ((xconf = parse_config(conffile)) == NULL) 579 return (-1); 580 581 if (main_imsg_send_config(xconf) == -1) 582 return (-1); 583 584 merge_config(main_conf, xconf); 585 586 return (0); 587 } 588 589 int 590 main_imsg_send_config(struct rad_conf *xconf) 591 { 592 struct ra_iface_conf *ra_iface_conf; 593 struct ra_prefix_conf *ra_prefix_conf; 594 struct ra_rdnss_conf *ra_rdnss_conf; 595 struct ra_dnssl_conf *ra_dnssl_conf; 596 597 /* Send fixed part of config to children. */ 598 if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 599 return (-1); 600 601 /* send global dns options to children */ 602 SIMPLEQ_FOREACH(ra_rdnss_conf, &xconf->ra_options.ra_rdnss_list, 603 entry) { 604 if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf, 605 sizeof(*ra_rdnss_conf)) == -1) 606 return (-1); 607 } 608 SIMPLEQ_FOREACH(ra_dnssl_conf, &xconf->ra_options.ra_dnssl_list, 609 entry) { 610 if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf, 611 sizeof(*ra_dnssl_conf)) == -1) 612 return (-1); 613 } 614 615 /* Send the interface list to children. */ 616 SIMPLEQ_FOREACH(ra_iface_conf, &xconf->ra_iface_list, entry) { 617 if (main_sendboth(IMSG_RECONF_RA_IFACE, ra_iface_conf, 618 sizeof(*ra_iface_conf)) == -1) 619 return (-1); 620 if (ra_iface_conf->autoprefix) { 621 if (main_sendboth(IMSG_RECONF_RA_AUTOPREFIX, 622 ra_iface_conf->autoprefix, 623 sizeof(*ra_iface_conf->autoprefix)) == -1) 624 return (-1); 625 } 626 SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list, 627 entry) { 628 if (main_sendboth(IMSG_RECONF_RA_PREFIX, 629 ra_prefix_conf, sizeof(*ra_prefix_conf)) == -1) 630 return (-1); 631 } 632 SIMPLEQ_FOREACH(ra_rdnss_conf, 633 &ra_iface_conf->ra_options.ra_rdnss_list, entry) { 634 if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf, 635 sizeof(*ra_rdnss_conf)) == -1) 636 return (-1); 637 } 638 SIMPLEQ_FOREACH(ra_dnssl_conf, 639 &ra_iface_conf->ra_options.ra_dnssl_list, entry) { 640 if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf, 641 sizeof(*ra_dnssl_conf)) == -1) 642 return (-1); 643 } 644 } 645 646 /* Tell children the revised config is now complete. */ 647 if (main_sendboth(IMSG_RECONF_END, NULL, 0) == -1) 648 return (-1); 649 650 return (0); 651 } 652 653 int 654 main_sendboth(enum imsg_type type, void *buf, uint16_t len) 655 { 656 if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) 657 return (-1); 658 if (imsg_compose_event(iev_engine, type, 0, 0, -1, buf, len) == -1) 659 return (-1); 660 return (0); 661 } 662 663 void 664 free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf) 665 { 666 struct ra_prefix_conf *prefix; 667 668 if (!ra_iface_conf) 669 return; 670 671 free(ra_iface_conf->autoprefix); 672 673 while ((prefix = SIMPLEQ_FIRST(&ra_iface_conf->ra_prefix_list)) != 674 NULL) { 675 SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_prefix_list, entry); 676 free(prefix); 677 } 678 679 free_dns_options(&ra_iface_conf->ra_options); 680 681 free(ra_iface_conf); 682 } 683 684 void 685 free_dns_options(struct ra_options_conf *ra_options) 686 { 687 struct ra_rdnss_conf *ra_rdnss; 688 struct ra_dnssl_conf *ra_dnssl; 689 690 while ((ra_rdnss = SIMPLEQ_FIRST(&ra_options->ra_rdnss_list)) != NULL) { 691 SIMPLEQ_REMOVE_HEAD(&ra_options->ra_rdnss_list, entry); 692 free(ra_rdnss); 693 } 694 ra_options->rdnss_count = 0; 695 696 while ((ra_dnssl = SIMPLEQ_FIRST(&ra_options->ra_dnssl_list)) != NULL) { 697 SIMPLEQ_REMOVE_HEAD(&ra_options->ra_dnssl_list, entry); 698 free(ra_dnssl); 699 } 700 ra_options->dnssl_len = 0; 701 } 702 703 void 704 merge_config(struct rad_conf *conf, struct rad_conf *xconf) 705 { 706 struct ra_iface_conf *ra_iface_conf; 707 struct ra_rdnss_conf *ra_rdnss; 708 struct ra_dnssl_conf *ra_dnssl; 709 710 /* Remove & discard existing interfaces. */ 711 while ((ra_iface_conf = SIMPLEQ_FIRST(&conf->ra_iface_list)) != NULL) { 712 SIMPLEQ_REMOVE_HEAD(&conf->ra_iface_list, entry); 713 free_ra_iface_conf(ra_iface_conf); 714 } 715 free_dns_options(&conf->ra_options); 716 717 conf->ra_options = xconf->ra_options; 718 SIMPLEQ_INIT(&conf->ra_options.ra_rdnss_list); 719 SIMPLEQ_INIT(&conf->ra_options.ra_dnssl_list); 720 721 /* Add new interfaces. */ 722 while ((ra_iface_conf = SIMPLEQ_FIRST(&xconf->ra_iface_list)) != NULL) { 723 SIMPLEQ_REMOVE_HEAD(&xconf->ra_iface_list, entry); 724 SIMPLEQ_INSERT_TAIL(&conf->ra_iface_list, ra_iface_conf, entry); 725 } 726 727 /* Add dns options */ 728 while ((ra_rdnss = SIMPLEQ_FIRST(&xconf->ra_options.ra_rdnss_list)) 729 != NULL) { 730 SIMPLEQ_REMOVE_HEAD(&xconf->ra_options.ra_rdnss_list, entry); 731 SIMPLEQ_INSERT_TAIL(&conf->ra_options.ra_rdnss_list, ra_rdnss, 732 entry); 733 } 734 while ((ra_dnssl = SIMPLEQ_FIRST(&xconf->ra_options.ra_dnssl_list)) 735 != NULL) { 736 SIMPLEQ_REMOVE_HEAD(&xconf->ra_options.ra_dnssl_list, entry); 737 SIMPLEQ_INSERT_TAIL(&conf->ra_options.ra_dnssl_list, ra_dnssl, 738 entry); 739 } 740 free(xconf); 741 } 742 743 struct rad_conf * 744 config_new_empty(void) 745 { 746 struct rad_conf *xconf; 747 748 xconf = calloc(1, sizeof(*xconf)); 749 if (xconf == NULL) 750 fatal(NULL); 751 752 SIMPLEQ_INIT(&xconf->ra_iface_list); 753 754 xconf->ra_options.dfr = 1; 755 xconf->ra_options.cur_hl = 0; 756 xconf->ra_options.m_flag = 0; 757 xconf->ra_options.o_flag = 0; 758 xconf->ra_options.router_lifetime = 1800; 759 xconf->ra_options.reachable_time = 0; 760 xconf->ra_options.retrans_timer = 0; 761 xconf->ra_options.mtu = 0; 762 xconf->ra_options.rdns_lifetime = DEFAULT_RDNS_LIFETIME; 763 SIMPLEQ_INIT(&xconf->ra_options.ra_rdnss_list); 764 SIMPLEQ_INIT(&xconf->ra_options.ra_dnssl_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