1*5ebe2a79Sflorian /* $OpenBSD: unwind.c,v 1.58 2021/01/29 17:46:04 florian Exp $ */ 2018cebfbSflorian 3018cebfbSflorian /* 4018cebfbSflorian * Copyright (c) 2018 Florian Obser <florian@openbsd.org> 5018cebfbSflorian * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6018cebfbSflorian * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7018cebfbSflorian * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8018cebfbSflorian * 9018cebfbSflorian * Permission to use, copy, modify, and distribute this software for any 10018cebfbSflorian * purpose with or without fee is hereby granted, provided that the above 11018cebfbSflorian * copyright notice and this permission notice appear in all copies. 12018cebfbSflorian * 13018cebfbSflorian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14018cebfbSflorian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15018cebfbSflorian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16018cebfbSflorian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17018cebfbSflorian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18018cebfbSflorian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19018cebfbSflorian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20018cebfbSflorian */ 21018cebfbSflorian #include <sys/types.h> 22018cebfbSflorian #include <sys/queue.h> 23018cebfbSflorian #include <sys/socket.h> 24296cf316Sflorian #include <sys/stat.h> 25018cebfbSflorian #include <sys/syslog.h> 26018cebfbSflorian #include <sys/wait.h> 27018cebfbSflorian 28018cebfbSflorian #include <net/if.h> 29018cebfbSflorian #include <net/route.h> 30018cebfbSflorian 31018cebfbSflorian #include <err.h> 32018cebfbSflorian #include <errno.h> 33018cebfbSflorian #include <event.h> 34018cebfbSflorian #include <fcntl.h> 35018cebfbSflorian #include <imsg.h> 36018cebfbSflorian #include <netdb.h> 372f29e846Sflorian #include <asr.h> 38018cebfbSflorian #include <pwd.h> 39018cebfbSflorian #include <stdio.h> 40018cebfbSflorian #include <stdlib.h> 41018cebfbSflorian #include <string.h> 42018cebfbSflorian #include <signal.h> 43018cebfbSflorian #include <unistd.h> 44018cebfbSflorian 4558b5b9b8Sflorian #include "log.h" 46018cebfbSflorian #include "unwind.h" 47018cebfbSflorian #include "frontend.h" 48018cebfbSflorian #include "resolver.h" 49018cebfbSflorian #include "control.h" 50018cebfbSflorian 5190d56d5fSflorian #define TRUST_ANCHOR_FILE "/var/db/unwind.key" 52296cf316Sflorian 53d223f0d9Sflorian enum uw_process { 54d223f0d9Sflorian PROC_MAIN, 55d223f0d9Sflorian PROC_RESOLVER, 56d223f0d9Sflorian PROC_FRONTEND, 57d223f0d9Sflorian }; 58d223f0d9Sflorian 59018cebfbSflorian __dead void usage(void); 60018cebfbSflorian __dead void main_shutdown(void); 61018cebfbSflorian 62018cebfbSflorian void main_sig_handler(int, short, void *); 63018cebfbSflorian 64d223f0d9Sflorian static pid_t start_child(enum uw_process, char *, int, int, int); 65018cebfbSflorian 66018cebfbSflorian void main_dispatch_frontend(int, short, void *); 67018cebfbSflorian void main_dispatch_resolver(int, short, void *); 68018cebfbSflorian 69f3ea9bf1Sflorian static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); 70bb81f7e1Sflorian static int main_imsg_send_config(struct uw_conf *); 71018cebfbSflorian 72018cebfbSflorian int main_reload(void); 73b2501eadSflorian int main_sendall(enum imsg_type, void *, uint16_t); 74d265a5d3Sflorian void open_ports(void); 7528ba4729Sflorian void solicit_dns_proposals(void); 762d988276Sflorian void send_blocklist_fd(void); 77018cebfbSflorian 78bb81f7e1Sflorian struct uw_conf *main_conf; 79d81b02e2Sflorian static struct imsgev *iev_frontend; 80d81b02e2Sflorian static struct imsgev *iev_resolver; 81572e5ac0Skn char *conffile; 82018cebfbSflorian pid_t frontend_pid; 83018cebfbSflorian pid_t resolver_pid; 84018cebfbSflorian uint32_t cmd_opts; 8528ba4729Sflorian int routesock; 8628ba4729Sflorian 87018cebfbSflorian void 88018cebfbSflorian main_sig_handler(int sig, short event, void *arg) 89018cebfbSflorian { 90018cebfbSflorian /* 91018cebfbSflorian * Normal signal handler rules don't apply because libevent 92018cebfbSflorian * decouples for us. 93018cebfbSflorian */ 94018cebfbSflorian 95018cebfbSflorian switch (sig) { 96018cebfbSflorian case SIGTERM: 97018cebfbSflorian case SIGINT: 985472663aSflorian main_shutdown(); 99018cebfbSflorian break; 100018cebfbSflorian case SIGHUP: 101018cebfbSflorian if (main_reload() == -1) 102018cebfbSflorian log_warnx("configuration reload failed"); 103018cebfbSflorian else 104018cebfbSflorian log_debug("configuration reloaded"); 105018cebfbSflorian break; 106018cebfbSflorian default: 107018cebfbSflorian fatalx("unexpected signal"); 108018cebfbSflorian } 109018cebfbSflorian } 110018cebfbSflorian 111018cebfbSflorian __dead void 112018cebfbSflorian usage(void) 113018cebfbSflorian { 114018cebfbSflorian extern char *__progname; 115018cebfbSflorian 116018cebfbSflorian fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n", 117018cebfbSflorian __progname); 118018cebfbSflorian exit(1); 119018cebfbSflorian } 120018cebfbSflorian 121018cebfbSflorian int 122018cebfbSflorian main(int argc, char *argv[]) 123018cebfbSflorian { 124018cebfbSflorian struct event ev_sigint, ev_sigterm, ev_sighup; 125bb81f7e1Sflorian int ch, debug = 0, resolver_flag = 0, frontend_flag = 0; 126f3ea9bf1Sflorian int frontend_routesock, rtfilter; 127bb81f7e1Sflorian int pipe_main2frontend[2], pipe_main2resolver[2]; 128d1b04a40Sflorian int control_fd, ta_fd; 129bb81f7e1Sflorian char *csock, *saved_argv0; 130018cebfbSflorian 131018cebfbSflorian csock = UNWIND_SOCKET; 132018cebfbSflorian 133018cebfbSflorian log_init(1, LOG_DAEMON); /* Log to stderr until daemonized. */ 134018cebfbSflorian log_setverbose(1); 135018cebfbSflorian 136018cebfbSflorian saved_argv0 = argv[0]; 137018cebfbSflorian if (saved_argv0 == NULL) 138018cebfbSflorian saved_argv0 = "unwind"; 139018cebfbSflorian 140f3ea9bf1Sflorian while ((ch = getopt(argc, argv, "dEFf:ns:v")) != -1) { 141018cebfbSflorian switch (ch) { 142018cebfbSflorian case 'd': 143018cebfbSflorian debug = 1; 144018cebfbSflorian break; 145018cebfbSflorian case 'E': 146018cebfbSflorian resolver_flag = 1; 147018cebfbSflorian break; 148018cebfbSflorian case 'F': 149018cebfbSflorian frontend_flag = 1; 150018cebfbSflorian break; 151018cebfbSflorian case 'f': 152018cebfbSflorian conffile = optarg; 153018cebfbSflorian break; 154018cebfbSflorian case 'n': 155018cebfbSflorian cmd_opts |= OPT_NOACTION; 156018cebfbSflorian break; 157018cebfbSflorian case 's': 158018cebfbSflorian csock = optarg; 159018cebfbSflorian break; 160018cebfbSflorian case 'v': 161e5d1a61aSflorian if (cmd_opts & OPT_VERBOSE2) 162e5d1a61aSflorian cmd_opts |= OPT_VERBOSE3; 163018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 164018cebfbSflorian cmd_opts |= OPT_VERBOSE2; 165018cebfbSflorian cmd_opts |= OPT_VERBOSE; 166018cebfbSflorian break; 167018cebfbSflorian default: 168018cebfbSflorian usage(); 169018cebfbSflorian } 170018cebfbSflorian } 171018cebfbSflorian 172018cebfbSflorian argc -= optind; 173018cebfbSflorian argv += optind; 174f3ea9bf1Sflorian if (argc > 0 || (resolver_flag && frontend_flag)) 175018cebfbSflorian usage(); 176018cebfbSflorian 177018cebfbSflorian if (resolver_flag) 178e5d1a61aSflorian resolver(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 | 179e5d1a61aSflorian OPT_VERBOSE3)); 180018cebfbSflorian else if (frontend_flag) 181e5d1a61aSflorian frontend(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 | 182e5d1a61aSflorian OPT_VERBOSE3)); 183018cebfbSflorian 184572e5ac0Skn if ((main_conf = parse_config(conffile)) == NULL) 185018cebfbSflorian exit(1); 186018cebfbSflorian 187018cebfbSflorian if (cmd_opts & OPT_NOACTION) { 188018cebfbSflorian if (cmd_opts & OPT_VERBOSE) 189018cebfbSflorian print_config(main_conf); 190018cebfbSflorian else 191018cebfbSflorian fprintf(stderr, "configuration OK\n"); 192018cebfbSflorian exit(0); 193018cebfbSflorian } 194018cebfbSflorian 195018cebfbSflorian /* Check for root privileges. */ 196018cebfbSflorian if (geteuid()) 197018cebfbSflorian errx(1, "need root privileges"); 198018cebfbSflorian 199018cebfbSflorian /* Check for assigned daemon user */ 200018cebfbSflorian if (getpwnam(UNWIND_USER) == NULL) 201018cebfbSflorian errx(1, "unknown user %s", UNWIND_USER); 202018cebfbSflorian 203018cebfbSflorian log_init(debug, LOG_DAEMON); 204e5d1a61aSflorian log_setverbose(cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 | OPT_VERBOSE3)); 205018cebfbSflorian 206018cebfbSflorian if (!debug) 207018cebfbSflorian daemon(1, 0); 208018cebfbSflorian 209018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 210018cebfbSflorian PF_UNSPEC, pipe_main2frontend) == -1) 211018cebfbSflorian fatal("main2frontend socketpair"); 212018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 213018cebfbSflorian PF_UNSPEC, pipe_main2resolver) == -1) 214018cebfbSflorian fatal("main2resolver socketpair"); 215018cebfbSflorian 216018cebfbSflorian /* Start children. */ 217018cebfbSflorian resolver_pid = start_child(PROC_RESOLVER, saved_argv0, 218018cebfbSflorian pipe_main2resolver[1], debug, cmd_opts & (OPT_VERBOSE | 219e5d1a61aSflorian OPT_VERBOSE2 | OPT_VERBOSE3)); 220018cebfbSflorian frontend_pid = start_child(PROC_FRONTEND, saved_argv0, 221018cebfbSflorian pipe_main2frontend[1], debug, cmd_opts & (OPT_VERBOSE | 222e5d1a61aSflorian OPT_VERBOSE2 | OPT_VERBOSE3)); 223018cebfbSflorian 224d223f0d9Sflorian log_procinit("main"); 225018cebfbSflorian 226018cebfbSflorian event_init(); 227018cebfbSflorian 228018cebfbSflorian /* Setup signal handler. */ 229018cebfbSflorian signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 230018cebfbSflorian signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 231018cebfbSflorian signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 232018cebfbSflorian signal_add(&ev_sigint, NULL); 233018cebfbSflorian signal_add(&ev_sigterm, NULL); 234018cebfbSflorian signal_add(&ev_sighup, NULL); 235018cebfbSflorian signal(SIGPIPE, SIG_IGN); 236018cebfbSflorian 237018cebfbSflorian /* Setup pipes to children. */ 238018cebfbSflorian 239018cebfbSflorian if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL || 240018cebfbSflorian (iev_resolver = malloc(sizeof(struct imsgev))) == NULL) 241018cebfbSflorian fatal(NULL); 242018cebfbSflorian imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); 243018cebfbSflorian iev_frontend->handler = main_dispatch_frontend; 244018cebfbSflorian imsg_init(&iev_resolver->ibuf, pipe_main2resolver[0]); 245018cebfbSflorian iev_resolver->handler = main_dispatch_resolver; 246018cebfbSflorian 247b2501eadSflorian /* Setup event handlers for pipes. */ 248018cebfbSflorian iev_frontend->events = EV_READ; 249018cebfbSflorian event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 250018cebfbSflorian iev_frontend->events, iev_frontend->handler, iev_frontend); 251018cebfbSflorian event_add(&iev_frontend->ev, NULL); 252018cebfbSflorian 253018cebfbSflorian iev_resolver->events = EV_READ; 254bb81f7e1Sflorian event_set(&iev_resolver->ev, iev_resolver->ibuf.fd, 255bb81f7e1Sflorian iev_resolver->events, iev_resolver->handler, iev_resolver); 256018cebfbSflorian event_add(&iev_resolver->ev, NULL); 257018cebfbSflorian 258b2501eadSflorian if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, 259f3ea9bf1Sflorian &iev_resolver->ibuf)) 260018cebfbSflorian fatal("could not establish imsg links"); 261018cebfbSflorian 26249a108abSflorian open_ports(); 26349a108abSflorian 264018cebfbSflorian if ((control_fd = control_init(csock)) == -1) 265018cebfbSflorian fatalx("control socket setup failed"); 266018cebfbSflorian 267*5ebe2a79Sflorian if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | 268*5ebe2a79Sflorian SOCK_NONBLOCK, 0)) == -1) 269018cebfbSflorian fatal("route socket"); 270018cebfbSflorian 27185384332Sflorian rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL) 2725dca88ceSflorian | ROUTE_FILTER(RTM_IFANNOUNCE) | ROUTE_FILTER(RTM_NEWADDR) 2735dca88ceSflorian | ROUTE_FILTER(RTM_DELADDR); 2749e627e00Sflorian if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER, 275df69c215Sderaadt &rtfilter, sizeof(rtfilter)) == -1) 276018cebfbSflorian fatal("setsockopt(ROUTE_MSGFILTER)"); 277018cebfbSflorian 27828ba4729Sflorian if ((routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | 279*5ebe2a79Sflorian SOCK_NONBLOCK, 0)) == -1) 28028ba4729Sflorian fatal("route socket"); 28128ba4729Sflorian shutdown(SHUT_RD, routesock); 28228ba4729Sflorian 283d1b04a40Sflorian if ((ta_fd = open(TRUST_ANCHOR_FILE, O_RDWR | O_CREAT, 0644)) == -1) 284d1b04a40Sflorian log_warn("%s", TRUST_ANCHOR_FILE); 285d1b04a40Sflorian 286d1b04a40Sflorian /* receiver handles failed open correctly */ 287d1b04a40Sflorian main_imsg_compose_frontend_fd(IMSG_TAFD, 0, ta_fd); 288d1b04a40Sflorian 289018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); 290018cebfbSflorian main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); 291018cebfbSflorian main_imsg_send_config(main_conf); 292018cebfbSflorian 2932d988276Sflorian if (main_conf->blocklist_file != NULL) 2942d988276Sflorian send_blocklist_fd(); 2952d988276Sflorian 29649a108abSflorian if (pledge("stdio rpath sendfd", NULL) == -1) 297018cebfbSflorian fatal("pledge"); 298018cebfbSflorian 299018cebfbSflorian main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0); 300296cf316Sflorian main_imsg_compose_resolver(IMSG_STARTUP, 0, NULL, 0); 301018cebfbSflorian 302018cebfbSflorian event_dispatch(); 303018cebfbSflorian 304018cebfbSflorian main_shutdown(); 305018cebfbSflorian return (0); 306018cebfbSflorian } 307018cebfbSflorian 308018cebfbSflorian __dead void 309018cebfbSflorian main_shutdown(void) 310018cebfbSflorian { 311018cebfbSflorian pid_t pid; 312018cebfbSflorian int status; 313018cebfbSflorian 314018cebfbSflorian /* Close pipes. */ 315018cebfbSflorian msgbuf_clear(&iev_frontend->ibuf.w); 316018cebfbSflorian close(iev_frontend->ibuf.fd); 317018cebfbSflorian msgbuf_clear(&iev_resolver->ibuf.w); 318018cebfbSflorian close(iev_resolver->ibuf.fd); 319018cebfbSflorian 320018cebfbSflorian config_clear(main_conf); 321018cebfbSflorian 322018cebfbSflorian log_debug("waiting for children to terminate"); 323018cebfbSflorian do { 324018cebfbSflorian pid = wait(&status); 325018cebfbSflorian if (pid == -1) { 326018cebfbSflorian if (errno != EINTR && errno != ECHILD) 327018cebfbSflorian fatal("wait"); 328018cebfbSflorian } else if (WIFSIGNALED(status)) 329018cebfbSflorian log_warnx("%s terminated; signal %d", 330018cebfbSflorian (pid == resolver_pid) ? "resolver" : 331018cebfbSflorian "frontend", WTERMSIG(status)); 332018cebfbSflorian } while (pid != -1 || (pid == -1 && errno == EINTR)); 333018cebfbSflorian 334018cebfbSflorian free(iev_frontend); 335018cebfbSflorian free(iev_resolver); 336018cebfbSflorian 337018cebfbSflorian log_info("terminating"); 338018cebfbSflorian exit(0); 339018cebfbSflorian } 340018cebfbSflorian 341018cebfbSflorian static pid_t 342d223f0d9Sflorian start_child(enum uw_process p, char *argv0, int fd, int debug, int verbose) 343018cebfbSflorian { 344018cebfbSflorian char *argv[7]; 345018cebfbSflorian int argc = 0; 346018cebfbSflorian pid_t pid; 347018cebfbSflorian 348018cebfbSflorian switch (pid = fork()) { 349018cebfbSflorian case -1: 350018cebfbSflorian fatal("cannot fork"); 351018cebfbSflorian case 0: 352018cebfbSflorian break; 353018cebfbSflorian default: 354018cebfbSflorian close(fd); 355018cebfbSflorian return (pid); 356018cebfbSflorian } 357018cebfbSflorian 358ef4f5895Syasuoka if (fd != 3) { 359018cebfbSflorian if (dup2(fd, 3) == -1) 360018cebfbSflorian fatal("cannot setup imsg fd"); 361ef4f5895Syasuoka } else if (fcntl(fd, F_SETFD, 0) == -1) 362ef4f5895Syasuoka fatal("cannot setup imsg fd"); 363018cebfbSflorian 364018cebfbSflorian argv[argc++] = argv0; 365018cebfbSflorian switch (p) { 366018cebfbSflorian case PROC_MAIN: 367018cebfbSflorian fatalx("Can not start main process"); 368018cebfbSflorian case PROC_RESOLVER: 369018cebfbSflorian argv[argc++] = "-E"; 370018cebfbSflorian break; 371018cebfbSflorian case PROC_FRONTEND: 372018cebfbSflorian argv[argc++] = "-F"; 373018cebfbSflorian break; 374018cebfbSflorian } 375018cebfbSflorian if (debug) 376018cebfbSflorian argv[argc++] = "-d"; 377018cebfbSflorian if (verbose & OPT_VERBOSE) 378018cebfbSflorian argv[argc++] = "-v"; 379018cebfbSflorian if (verbose & OPT_VERBOSE2) 380018cebfbSflorian argv[argc++] = "-v"; 381e5d1a61aSflorian if (verbose & OPT_VERBOSE3) 382e5d1a61aSflorian argv[argc++] = "-v"; 383018cebfbSflorian argv[argc++] = NULL; 384018cebfbSflorian 385018cebfbSflorian execvp(argv0, argv); 386018cebfbSflorian fatal("execvp"); 387018cebfbSflorian } 388018cebfbSflorian 389018cebfbSflorian void 390018cebfbSflorian main_dispatch_frontend(int fd, short event, void *bula) 391018cebfbSflorian { 392018cebfbSflorian struct imsgev *iev = bula; 393018cebfbSflorian struct imsgbuf *ibuf; 394018cebfbSflorian struct imsg imsg; 395018cebfbSflorian ssize_t n; 396018cebfbSflorian int shut = 0, verbose; 397018cebfbSflorian 398018cebfbSflorian ibuf = &iev->ibuf; 399018cebfbSflorian 400018cebfbSflorian if (event & EV_READ) { 401018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 402018cebfbSflorian fatal("imsg_read error"); 403018cebfbSflorian if (n == 0) /* Connection closed. */ 404018cebfbSflorian shut = 1; 405018cebfbSflorian } 406018cebfbSflorian if (event & EV_WRITE) { 407018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 408018cebfbSflorian fatal("msgbuf_write"); 409018cebfbSflorian if (n == 0) /* Connection closed. */ 410018cebfbSflorian shut = 1; 411018cebfbSflorian } 412018cebfbSflorian 413018cebfbSflorian for (;;) { 414018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 415018cebfbSflorian fatal("imsg_get"); 416018cebfbSflorian if (n == 0) /* No more messages. */ 417018cebfbSflorian break; 418018cebfbSflorian 419018cebfbSflorian switch (imsg.hdr.type) { 420018cebfbSflorian case IMSG_STARTUP_DONE: 42128ba4729Sflorian solicit_dns_proposals(); 422018cebfbSflorian break; 423018cebfbSflorian case IMSG_CTL_RELOAD: 424018cebfbSflorian if (main_reload() == -1) 425018cebfbSflorian log_warnx("configuration reload failed"); 426018cebfbSflorian else 427018cebfbSflorian log_warnx("configuration reloaded"); 428018cebfbSflorian break; 429018cebfbSflorian case IMSG_CTL_LOG_VERBOSE: 430a9155f32Sflorian if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 4312b821978Sflorian fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 432a9155f32Sflorian "%lu", __func__, IMSG_DATA_SIZE(imsg)); 433018cebfbSflorian memcpy(&verbose, imsg.data, sizeof(verbose)); 434018cebfbSflorian log_setverbose(verbose); 435018cebfbSflorian break; 436018cebfbSflorian default: 437018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 438018cebfbSflorian imsg.hdr.type); 439018cebfbSflorian break; 440018cebfbSflorian } 441018cebfbSflorian imsg_free(&imsg); 442018cebfbSflorian } 443018cebfbSflorian if (!shut) 444018cebfbSflorian imsg_event_add(iev); 445018cebfbSflorian else { 446018cebfbSflorian /* This pipe is dead. Remove its event handler */ 447018cebfbSflorian event_del(&iev->ev); 448018cebfbSflorian event_loopexit(NULL); 449018cebfbSflorian } 450018cebfbSflorian } 451018cebfbSflorian 452018cebfbSflorian void 453018cebfbSflorian main_dispatch_resolver(int fd, short event, void *bula) 454018cebfbSflorian { 455018cebfbSflorian struct imsgev *iev = bula; 456018cebfbSflorian struct imsgbuf *ibuf; 457018cebfbSflorian struct imsg imsg; 458018cebfbSflorian ssize_t n; 459018cebfbSflorian int shut = 0; 460018cebfbSflorian 461018cebfbSflorian ibuf = &iev->ibuf; 462018cebfbSflorian 463018cebfbSflorian if (event & EV_READ) { 464018cebfbSflorian if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 465018cebfbSflorian fatal("imsg_read error"); 466018cebfbSflorian if (n == 0) /* Connection closed. */ 467018cebfbSflorian shut = 1; 468018cebfbSflorian } 469018cebfbSflorian if (event & EV_WRITE) { 470018cebfbSflorian if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 471018cebfbSflorian fatal("msgbuf_write"); 472018cebfbSflorian if (n == 0) /* Connection closed. */ 473018cebfbSflorian shut = 1; 474018cebfbSflorian } 475018cebfbSflorian 476018cebfbSflorian for (;;) { 477018cebfbSflorian if ((n = imsg_get(ibuf, &imsg)) == -1) 478018cebfbSflorian fatal("imsg_get"); 479018cebfbSflorian if (n == 0) /* No more messages. */ 480018cebfbSflorian break; 481018cebfbSflorian 482018cebfbSflorian switch (imsg.hdr.type) { 483018cebfbSflorian default: 484018cebfbSflorian log_debug("%s: error handling imsg %d", __func__, 485018cebfbSflorian imsg.hdr.type); 486018cebfbSflorian break; 487018cebfbSflorian } 488018cebfbSflorian imsg_free(&imsg); 489018cebfbSflorian } 490018cebfbSflorian if (!shut) 491018cebfbSflorian imsg_event_add(iev); 492018cebfbSflorian else { 493018cebfbSflorian /* This pipe is dead. Remove its event handler. */ 494018cebfbSflorian event_del(&iev->ev); 495018cebfbSflorian event_loopexit(NULL); 496018cebfbSflorian } 497018cebfbSflorian } 498018cebfbSflorian 499018cebfbSflorian void 500018cebfbSflorian main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 501018cebfbSflorian { 502018cebfbSflorian if (iev_frontend) 503018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, -1, data, 504018cebfbSflorian datalen); 505018cebfbSflorian } 506018cebfbSflorian 507018cebfbSflorian void 508018cebfbSflorian main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) 509018cebfbSflorian { 510018cebfbSflorian if (iev_frontend) 511018cebfbSflorian imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0); 512018cebfbSflorian } 513018cebfbSflorian 514018cebfbSflorian void 515018cebfbSflorian main_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen) 516018cebfbSflorian { 517018cebfbSflorian if (iev_resolver) 518018cebfbSflorian imsg_compose_event(iev_resolver, type, 0, pid, -1, data, 519018cebfbSflorian datalen); 520018cebfbSflorian } 521018cebfbSflorian 522018cebfbSflorian void 523018cebfbSflorian imsg_event_add(struct imsgev *iev) 524018cebfbSflorian { 525018cebfbSflorian iev->events = EV_READ; 526018cebfbSflorian if (iev->ibuf.w.queued) 527018cebfbSflorian iev->events |= EV_WRITE; 528018cebfbSflorian 529018cebfbSflorian event_del(&iev->ev); 530018cebfbSflorian event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 531018cebfbSflorian event_add(&iev->ev, NULL); 532018cebfbSflorian } 533018cebfbSflorian 534018cebfbSflorian int 535018cebfbSflorian imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, 536018cebfbSflorian pid_t pid, int fd, void *data, uint16_t datalen) 537018cebfbSflorian { 538018cebfbSflorian int ret; 539018cebfbSflorian 540018cebfbSflorian if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, 541018cebfbSflorian datalen)) != -1) 542018cebfbSflorian imsg_event_add(iev); 543018cebfbSflorian 544018cebfbSflorian return (ret); 545018cebfbSflorian } 546018cebfbSflorian 547018cebfbSflorian static int 548018cebfbSflorian main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, 549f3ea9bf1Sflorian struct imsgbuf *resolver_buf) 550018cebfbSflorian { 551018cebfbSflorian int pipe_frontend2resolver[2]; 552018cebfbSflorian 553018cebfbSflorian if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 554018cebfbSflorian PF_UNSPEC, pipe_frontend2resolver) == -1) 555018cebfbSflorian return (-1); 556018cebfbSflorian 557b2501eadSflorian if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, 558018cebfbSflorian pipe_frontend2resolver[0], NULL, 0) == -1) 559018cebfbSflorian return (-1); 560b2501eadSflorian if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, 561018cebfbSflorian pipe_frontend2resolver[1], NULL, 0) == -1) 562018cebfbSflorian return (-1); 563018cebfbSflorian 564018cebfbSflorian return (0); 565018cebfbSflorian } 566018cebfbSflorian 567018cebfbSflorian int 568018cebfbSflorian main_reload(void) 569018cebfbSflorian { 570bb81f7e1Sflorian struct uw_conf *xconf; 571018cebfbSflorian 572572e5ac0Skn if ((xconf = parse_config(conffile)) == NULL) 573018cebfbSflorian return (-1); 574018cebfbSflorian 575018cebfbSflorian if (main_imsg_send_config(xconf) == -1) 576018cebfbSflorian return (-1); 577018cebfbSflorian 578018cebfbSflorian merge_config(main_conf, xconf); 579018cebfbSflorian 5802d988276Sflorian if (main_conf->blocklist_file != NULL) 5812d988276Sflorian send_blocklist_fd(); 5822d988276Sflorian 583018cebfbSflorian return (0); 584018cebfbSflorian } 585018cebfbSflorian 586018cebfbSflorian int 587bb81f7e1Sflorian main_imsg_send_config(struct uw_conf *xconf) 588018cebfbSflorian { 589bb81f7e1Sflorian struct uw_forwarder *uw_forwarder; 590dd16127bSotto struct force_tree_entry *force_entry; 591018cebfbSflorian 592018cebfbSflorian /* Send fixed part of config to children. */ 593b2501eadSflorian if (main_sendall(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 594018cebfbSflorian return (-1); 595018cebfbSflorian 5962d988276Sflorian if (xconf->blocklist_file != NULL) { 5972d988276Sflorian if (main_sendall(IMSG_RECONF_BLOCKLIST_FILE, 5982d988276Sflorian xconf->blocklist_file, strlen(xconf->blocklist_file) + 1) 5992d988276Sflorian == -1) 6002d988276Sflorian return (-1); 6012d988276Sflorian } 6022d988276Sflorian 6033570995aSflorian /* send static forwarders to children */ 6047d055805Sflorian TAILQ_FOREACH(uw_forwarder, &xconf->uw_forwarder_list, entry) { 605bb81f7e1Sflorian if (main_sendall(IMSG_RECONF_FORWARDER, uw_forwarder, 606bb81f7e1Sflorian sizeof(*uw_forwarder)) == -1) 607018cebfbSflorian return (-1); 608018cebfbSflorian } 609018cebfbSflorian 6103570995aSflorian /* send static DoT forwarders to children */ 6117d055805Sflorian TAILQ_FOREACH(uw_forwarder, &xconf->uw_dot_forwarder_list, 6123570995aSflorian entry) { 613bb81f7e1Sflorian if (main_sendall(IMSG_RECONF_DOT_FORWARDER, uw_forwarder, 614bb81f7e1Sflorian sizeof(*uw_forwarder)) == -1) 6153570995aSflorian return (-1); 6163570995aSflorian } 617dd16127bSotto RB_FOREACH(force_entry, force_tree, &xconf->force) { 618dd16127bSotto if (main_sendall(IMSG_RECONF_FORCE, force_entry, 619dd16127bSotto sizeof(*force_entry)) == -1) 620dd16127bSotto return (-1); 621dd16127bSotto } 6223570995aSflorian 623018cebfbSflorian /* Tell children the revised config is now complete. */ 624b2501eadSflorian if (main_sendall(IMSG_RECONF_END, NULL, 0) == -1) 625018cebfbSflorian return (-1); 626018cebfbSflorian 627018cebfbSflorian return (0); 628018cebfbSflorian } 629018cebfbSflorian 630018cebfbSflorian int 631b2501eadSflorian main_sendall(enum imsg_type type, void *buf, uint16_t len) 632018cebfbSflorian { 633018cebfbSflorian if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) 634018cebfbSflorian return (-1); 635018cebfbSflorian if (imsg_compose_event(iev_resolver, type, 0, 0, -1, buf, len) == -1) 636018cebfbSflorian return (-1); 637018cebfbSflorian return (0); 638018cebfbSflorian } 639018cebfbSflorian 640018cebfbSflorian void 641bb81f7e1Sflorian merge_config(struct uw_conf *conf, struct uw_conf *xconf) 642018cebfbSflorian { 643bb81f7e1Sflorian struct uw_forwarder *uw_forwarder; 644dd16127bSotto struct force_tree_entry *n, *nxt; 645018cebfbSflorian 646018cebfbSflorian /* Remove & discard existing forwarders. */ 6477d055805Sflorian while ((uw_forwarder = TAILQ_FIRST(&conf->uw_forwarder_list)) != 648bb81f7e1Sflorian NULL) { 6497d055805Sflorian TAILQ_REMOVE(&conf->uw_forwarder_list, uw_forwarder, entry); 650bb81f7e1Sflorian free(uw_forwarder); 651018cebfbSflorian } 6527d055805Sflorian while ((uw_forwarder = TAILQ_FIRST(&conf->uw_dot_forwarder_list)) != 653bb81f7e1Sflorian NULL) { 6547d055805Sflorian TAILQ_REMOVE(&conf->uw_dot_forwarder_list, uw_forwarder, entry); 655bb81f7e1Sflorian free(uw_forwarder); 6563570995aSflorian } 657018cebfbSflorian 658dd16127bSotto /* Remove & discard existing force tree. */ 6593bcff273Stb RB_FOREACH_SAFE(n, force_tree, &conf->force, nxt) { 660dd16127bSotto RB_REMOVE(force_tree, &conf->force, n); 661dd16127bSotto free(n); 662dd16127bSotto } 663dd16127bSotto 664fd873f7fSflorian memcpy(&conf->res_pref, &xconf->res_pref, 665fd873f7fSflorian sizeof(conf->res_pref)); 666018cebfbSflorian 6672d988276Sflorian free(conf->blocklist_file); 6682d988276Sflorian conf->blocklist_file = xconf->blocklist_file; 669ac71ec8eSflorian conf->blocklist_log = xconf->blocklist_log; 6702d988276Sflorian 671018cebfbSflorian /* Add new forwarders. */ 6722feeeacaSflorian TAILQ_CONCAT(&conf->uw_forwarder_list, &xconf->uw_forwarder_list, 6737d055805Sflorian entry); 6742feeeacaSflorian TAILQ_CONCAT(&conf->uw_dot_forwarder_list, 6752feeeacaSflorian &xconf->uw_dot_forwarder_list, entry); 676018cebfbSflorian 6773bcff273Stb RB_FOREACH_SAFE(n, force_tree, &xconf->force, nxt) { 678dd16127bSotto RB_REMOVE(force_tree, &xconf->force, n); 679dd16127bSotto RB_INSERT(force_tree, &conf->force, n); 680dd16127bSotto } 681dd16127bSotto 682018cebfbSflorian free(xconf); 683018cebfbSflorian } 684018cebfbSflorian 685bb81f7e1Sflorian struct uw_conf * 686018cebfbSflorian config_new_empty(void) 687018cebfbSflorian { 688fd873f7fSflorian static enum uw_resolver_type default_res_pref[] = { 689fd873f7fSflorian UW_RES_DOT, 69015fe126bSflorian UW_RES_ODOT_FORWARDER, 691fd873f7fSflorian UW_RES_FORWARDER, 692fd873f7fSflorian UW_RES_RECURSOR, 69315fe126bSflorian UW_RES_ODOT_DHCP, 694530f5ecfSflorian UW_RES_DHCP, 695530f5ecfSflorian UW_RES_ASR}; 696bb81f7e1Sflorian struct uw_conf *xconf; 697018cebfbSflorian 698018cebfbSflorian xconf = calloc(1, sizeof(*xconf)); 699018cebfbSflorian if (xconf == NULL) 700018cebfbSflorian fatal(NULL); 701018cebfbSflorian 702d032132bSflorian memcpy(&xconf->res_pref.types, &default_res_pref, 703fd873f7fSflorian sizeof(default_res_pref)); 704d032132bSflorian xconf->res_pref.len = nitems(default_res_pref); 705fd873f7fSflorian 7067d055805Sflorian TAILQ_INIT(&xconf->uw_forwarder_list); 7077d055805Sflorian TAILQ_INIT(&xconf->uw_dot_forwarder_list); 708018cebfbSflorian 709dd16127bSotto RB_INIT(&xconf->force); 710dd16127bSotto 711018cebfbSflorian return (xconf); 712018cebfbSflorian } 713018cebfbSflorian 714018cebfbSflorian void 715bb81f7e1Sflorian config_clear(struct uw_conf *conf) 716018cebfbSflorian { 717bb81f7e1Sflorian struct uw_conf *xconf; 718018cebfbSflorian 719018cebfbSflorian /* Merge current config with an empty config. */ 720018cebfbSflorian xconf = config_new_empty(); 721018cebfbSflorian merge_config(conf, xconf); 722018cebfbSflorian 723018cebfbSflorian free(conf); 724018cebfbSflorian } 725018cebfbSflorian 726018cebfbSflorian void 727d265a5d3Sflorian open_ports(void) 728d265a5d3Sflorian { 729d265a5d3Sflorian struct addrinfo hints, *res0; 73015c83d0cSflorian int udp4sock = -1, udp6sock = -1, error, bsize = 65535; 731297af7e1Sflorian int tcp4sock = -1, tcp6sock = -1; 73215c8ad53Sjca int opt = 1; 733d265a5d3Sflorian 734d265a5d3Sflorian memset(&hints, 0, sizeof(hints)); 735d265a5d3Sflorian hints.ai_family = AF_INET; 736d265a5d3Sflorian hints.ai_socktype = SOCK_DGRAM; 737cc4fd5c4Stedu hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE; 738d265a5d3Sflorian 739d265a5d3Sflorian error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); 740d265a5d3Sflorian if (!error && res0) { 741d265a5d3Sflorian if ((udp4sock = socket(res0->ai_family, res0->ai_socktype, 742d265a5d3Sflorian res0->ai_protocol)) != -1) { 74315c8ad53Sjca if (setsockopt(udp4sock, SOL_SOCKET, SO_REUSEADDR, 74415c8ad53Sjca &opt, sizeof(opt)) == -1) 74515c8ad53Sjca log_warn("setting SO_REUSEADDR on socket"); 74615c83d0cSflorian if (setsockopt(udp4sock, SOL_SOCKET, SO_SNDBUF, &bsize, 74715c83d0cSflorian sizeof(bsize)) == -1) 74815c83d0cSflorian log_warn("setting SO_SNDBUF on socket"); 749d265a5d3Sflorian if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen) 750d265a5d3Sflorian == -1) { 751d265a5d3Sflorian close(udp4sock); 752d265a5d3Sflorian udp4sock = -1; 753d265a5d3Sflorian } 754d265a5d3Sflorian } 755d265a5d3Sflorian } 756296cf316Sflorian if (res0) 757d265a5d3Sflorian freeaddrinfo(res0); 758d265a5d3Sflorian 759d265a5d3Sflorian hints.ai_family = AF_INET6; 760d265a5d3Sflorian error = getaddrinfo("::1", "domain", &hints, &res0); 761d265a5d3Sflorian if (!error && res0) { 762d265a5d3Sflorian if ((udp6sock = socket(res0->ai_family, res0->ai_socktype, 763d265a5d3Sflorian res0->ai_protocol)) != -1) { 76415c8ad53Sjca if (setsockopt(udp6sock, SOL_SOCKET, SO_REUSEADDR, 76515c8ad53Sjca &opt, sizeof(opt)) == -1) 76615c8ad53Sjca log_warn("setting SO_REUSEADDR on socket"); 76715c83d0cSflorian if (setsockopt(udp6sock, SOL_SOCKET, SO_SNDBUF, &bsize, 76815c83d0cSflorian sizeof(bsize)) == -1) 76915c83d0cSflorian log_warn("setting SO_SNDBUF on socket"); 770d265a5d3Sflorian if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen) 771d265a5d3Sflorian == -1) { 772d265a5d3Sflorian close(udp6sock); 773d265a5d3Sflorian udp6sock = -1; 774d265a5d3Sflorian } 775d265a5d3Sflorian } 776d265a5d3Sflorian } 777296cf316Sflorian if (res0) 778d265a5d3Sflorian freeaddrinfo(res0); 779d265a5d3Sflorian 780297af7e1Sflorian hints.ai_family = AF_INET; 781297af7e1Sflorian hints.ai_socktype = SOCK_STREAM; 782297af7e1Sflorian 783297af7e1Sflorian error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); 784297af7e1Sflorian if (!error && res0) { 785297af7e1Sflorian if ((tcp4sock = socket(res0->ai_family, 786297af7e1Sflorian res0->ai_socktype | SOCK_NONBLOCK, 787297af7e1Sflorian res0->ai_protocol)) != -1) { 788297af7e1Sflorian if (setsockopt(tcp4sock, SOL_SOCKET, SO_REUSEADDR, 789297af7e1Sflorian &opt, sizeof(opt)) == -1) 790297af7e1Sflorian log_warn("setting SO_REUSEADDR on socket"); 791297af7e1Sflorian if (setsockopt(tcp4sock, SOL_SOCKET, SO_SNDBUF, &bsize, 792297af7e1Sflorian sizeof(bsize)) == -1) 793297af7e1Sflorian log_warn("setting SO_SNDBUF on socket"); 794297af7e1Sflorian if (bind(tcp4sock, res0->ai_addr, res0->ai_addrlen) 795297af7e1Sflorian == -1) { 796297af7e1Sflorian close(tcp4sock); 797297af7e1Sflorian tcp4sock = -1; 798297af7e1Sflorian } 799297af7e1Sflorian if (listen(tcp4sock, 5) == -1) { 800297af7e1Sflorian close(tcp4sock); 801297af7e1Sflorian tcp4sock = -1; 802297af7e1Sflorian } 803297af7e1Sflorian } 804297af7e1Sflorian } 805297af7e1Sflorian if (res0) 806297af7e1Sflorian freeaddrinfo(res0); 807297af7e1Sflorian 808297af7e1Sflorian hints.ai_family = AF_INET6; 809297af7e1Sflorian error = getaddrinfo("::1", "domain", &hints, &res0); 810297af7e1Sflorian if (!error && res0) { 811297af7e1Sflorian if ((tcp6sock = socket(res0->ai_family, 812297af7e1Sflorian res0->ai_socktype | SOCK_NONBLOCK, 813297af7e1Sflorian res0->ai_protocol)) != -1) { 814297af7e1Sflorian if (setsockopt(tcp6sock, SOL_SOCKET, SO_REUSEADDR, 815297af7e1Sflorian &opt, sizeof(opt)) == -1) 816297af7e1Sflorian log_warn("setting SO_REUSEADDR on socket"); 817297af7e1Sflorian if (setsockopt(tcp6sock, SOL_SOCKET, SO_SNDBUF, &bsize, 818297af7e1Sflorian sizeof(bsize)) == -1) 819297af7e1Sflorian log_warn("setting SO_SNDBUF on socket"); 820297af7e1Sflorian if (bind(tcp6sock, res0->ai_addr, res0->ai_addrlen) 821297af7e1Sflorian == -1) { 822297af7e1Sflorian close(tcp6sock); 823297af7e1Sflorian tcp6sock = -1; 824297af7e1Sflorian } 825297af7e1Sflorian if (listen(tcp6sock, 5) == -1) { 826297af7e1Sflorian close(tcp6sock); 827297af7e1Sflorian tcp6sock = -1; 828297af7e1Sflorian } 829297af7e1Sflorian } 830297af7e1Sflorian } 831297af7e1Sflorian if (res0) 832297af7e1Sflorian freeaddrinfo(res0); 833297af7e1Sflorian 834297af7e1Sflorian if ((udp4sock == -1 || tcp4sock == -1) && (udp6sock == -1 || 835297af7e1Sflorian tcp6sock == -1)) 836afd6e24dSflorian fatalx("could not bind to 127.0.0.1 or ::1 on port 53"); 837d265a5d3Sflorian 838b04dd19dSflorian if (udp4sock != -1) 839d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); 840b04dd19dSflorian if (udp6sock != -1) 841d265a5d3Sflorian main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); 842297af7e1Sflorian if (tcp4sock != -1) 843297af7e1Sflorian main_imsg_compose_frontend_fd(IMSG_TCP4SOCK, 0, tcp4sock); 844297af7e1Sflorian if (tcp6sock != -1) 845297af7e1Sflorian main_imsg_compose_frontend_fd(IMSG_TCP6SOCK, 0, tcp6sock); 846d265a5d3Sflorian } 8472f29e846Sflorian 8482f29e846Sflorian void 84928ba4729Sflorian solicit_dns_proposals(void) 85028ba4729Sflorian { 85128ba4729Sflorian struct rt_msghdr rtm; 85228ba4729Sflorian struct iovec iov[1]; 85328ba4729Sflorian int iovcnt = 0; 85428ba4729Sflorian 85528ba4729Sflorian memset(&rtm, 0, sizeof(rtm)); 85628ba4729Sflorian 85728ba4729Sflorian rtm.rtm_version = RTM_VERSION; 85828ba4729Sflorian rtm.rtm_type = RTM_PROPOSAL; 85928ba4729Sflorian rtm.rtm_msglen = sizeof(rtm); 86028ba4729Sflorian rtm.rtm_tableid = 0; 86128ba4729Sflorian rtm.rtm_index = 0; 86228ba4729Sflorian rtm.rtm_seq = arc4random(); 86328ba4729Sflorian rtm.rtm_priority = RTP_PROPOSAL_SOLICIT; 86428ba4729Sflorian 86528ba4729Sflorian iov[iovcnt].iov_base = &rtm; 86628ba4729Sflorian iov[iovcnt++].iov_len = sizeof(rtm); 86728ba4729Sflorian 86828ba4729Sflorian if (writev(routesock, iov, iovcnt) == -1) 86928ba4729Sflorian log_warn("failed to send solicitation"); 87028ba4729Sflorian } 87128ba4729Sflorian 87228ba4729Sflorian void 8732d988276Sflorian send_blocklist_fd(void) 8742d988276Sflorian { 8752d988276Sflorian int bl_fd; 8762d988276Sflorian 8772d988276Sflorian if ((bl_fd = open(main_conf->blocklist_file, O_RDONLY)) != -1) 8782d988276Sflorian main_imsg_compose_frontend_fd(IMSG_BLFD, 0, bl_fd); 8792d988276Sflorian else 8802d988276Sflorian log_warn("%s", main_conf->blocklist_file); 8812d988276Sflorian } 882679647feSflorian 883679647feSflorian void 884679647feSflorian imsg_receive_config(struct imsg *imsg, struct uw_conf **xconf) 885679647feSflorian { 886679647feSflorian struct uw_conf *nconf; 887679647feSflorian struct uw_forwarder *uw_forwarder; 888dd16127bSotto struct force_tree_entry *force_entry; 889679647feSflorian 890679647feSflorian nconf = *xconf; 891679647feSflorian 892679647feSflorian switch (imsg->hdr.type) { 893679647feSflorian case IMSG_RECONF_CONF: 894679647feSflorian if (nconf != NULL) 895679647feSflorian fatalx("%s: IMSG_RECONF_CONF already in " 896679647feSflorian "progress", __func__); 897679647feSflorian if (IMSG_DATA_SIZE(*imsg) != sizeof(struct uw_conf)) 898679647feSflorian fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", 899679647feSflorian __func__, IMSG_DATA_SIZE(*imsg)); 900679647feSflorian if ((*xconf = malloc(sizeof(struct uw_conf))) == NULL) 901679647feSflorian fatal(NULL); 902679647feSflorian nconf = *xconf; 903679647feSflorian memcpy(nconf, imsg->data, sizeof(struct uw_conf)); 9047d055805Sflorian TAILQ_INIT(&nconf->uw_forwarder_list); 9057d055805Sflorian TAILQ_INIT(&nconf->uw_dot_forwarder_list); 906dd16127bSotto RB_INIT(&nconf->force); 907679647feSflorian break; 908679647feSflorian case IMSG_RECONF_BLOCKLIST_FILE: 909679647feSflorian /* make sure this is a string */ 910679647feSflorian ((char *)imsg->data)[IMSG_DATA_SIZE(*imsg) - 1] = '\0'; 911679647feSflorian if ((nconf->blocklist_file = strdup(imsg->data)) == 912679647feSflorian NULL) 913679647feSflorian fatal("%s: strdup", __func__); 914679647feSflorian break; 915679647feSflorian case IMSG_RECONF_FORWARDER: 916679647feSflorian if (IMSG_DATA_SIZE(*imsg) != sizeof(struct uw_forwarder)) 917679647feSflorian fatalx("%s: IMSG_RECONF_FORWARDER wrong length:" 918679647feSflorian " %lu", __func__, IMSG_DATA_SIZE(*imsg)); 919679647feSflorian if ((uw_forwarder = malloc(sizeof(struct 920679647feSflorian uw_forwarder))) == NULL) 921679647feSflorian fatal(NULL); 922679647feSflorian memcpy(uw_forwarder, imsg->data, sizeof(struct 923679647feSflorian uw_forwarder)); 9247d055805Sflorian TAILQ_INSERT_TAIL(&nconf->uw_forwarder_list, 925679647feSflorian uw_forwarder, entry); 926679647feSflorian break; 927679647feSflorian case IMSG_RECONF_DOT_FORWARDER: 928679647feSflorian if (IMSG_DATA_SIZE(*imsg) != sizeof(struct uw_forwarder)) 929679647feSflorian fatalx("%s: IMSG_RECONF_DOT_FORWARDER wrong " 930679647feSflorian "length: %lu", __func__, 931679647feSflorian IMSG_DATA_SIZE(*imsg)); 932679647feSflorian if ((uw_forwarder = malloc(sizeof(struct 933679647feSflorian uw_forwarder))) == NULL) 934679647feSflorian fatal(NULL); 935679647feSflorian memcpy(uw_forwarder, imsg->data, sizeof(struct 936679647feSflorian uw_forwarder)); 9377d055805Sflorian TAILQ_INSERT_TAIL(&nconf->uw_dot_forwarder_list, 938679647feSflorian uw_forwarder, entry); 939679647feSflorian break; 940dd16127bSotto case IMSG_RECONF_FORCE: 941dd16127bSotto if (IMSG_DATA_SIZE(*imsg) != sizeof(struct force_tree_entry)) 942dd16127bSotto fatalx("%s: IMSG_RECONF_FORCE wrong " 943dd16127bSotto "length: %lu", __func__, 944dd16127bSotto IMSG_DATA_SIZE(*imsg)); 945dd16127bSotto if ((force_entry = malloc(sizeof(struct 946dd16127bSotto force_tree_entry))) == NULL) 947dd16127bSotto fatal(NULL); 948dd16127bSotto memcpy(force_entry, imsg->data, sizeof(struct 949dd16127bSotto force_tree_entry)); 950dbebd753Stb if (RB_INSERT(force_tree, &nconf->force, force_entry) != NULL) { 951dbebd753Stb free(force_entry); 952dbebd753Stb fatalx("%s: IMSG_RECONF_FORCE duplicate entry", 953dbebd753Stb __func__); 954dbebd753Stb } 955dd16127bSotto break; 956679647feSflorian default: 957679647feSflorian log_debug("%s: error handling imsg %d", __func__, 958679647feSflorian imsg->hdr.type); 959679647feSflorian break; 960679647feSflorian } 961679647feSflorian } 962