| File: | src/sbin/unwind/unwind.c |
| Warning: | line 173, column 2 Value stored to 'argv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: unwind.c,v 1.67 2021/12/18 10:34:19 florian 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/stat.h> |
| 25 | #include <sys/syslog.h> |
| 26 | #include <sys/wait.h> |
| 27 | |
| 28 | #include <net/if.h> |
| 29 | #include <net/route.h> |
| 30 | |
| 31 | #include <err.h> |
| 32 | #include <errno(*__errno()).h> |
| 33 | #include <event.h> |
| 34 | #include <fcntl.h> |
| 35 | #include <imsg.h> |
| 36 | #include <netdb.h> |
| 37 | #include <asr.h> |
| 38 | #include <pwd.h> |
| 39 | #include <stdio.h> |
| 40 | #include <stdlib.h> |
| 41 | #include <string.h> |
| 42 | #include <signal.h> |
| 43 | #include <unistd.h> |
| 44 | |
| 45 | #include "log.h" |
| 46 | #include "unwind.h" |
| 47 | #include "frontend.h" |
| 48 | #include "resolver.h" |
| 49 | #include "control.h" |
| 50 | |
| 51 | #define TRUST_ANCHOR_FILE"/var/db/unwind.key" "/var/db/unwind.key" |
| 52 | |
| 53 | enum uw_process { |
| 54 | PROC_MAIN, |
| 55 | PROC_RESOLVER, |
| 56 | PROC_FRONTEND, |
| 57 | }; |
| 58 | |
| 59 | __dead__attribute__((__noreturn__)) void usage(void); |
| 60 | __dead__attribute__((__noreturn__)) void main_shutdown(void); |
| 61 | |
| 62 | void main_sig_handler(int, short, void *); |
| 63 | |
| 64 | static pid_t start_child(enum uw_process, char *, int, int, int); |
| 65 | |
| 66 | void main_dispatch_frontend(int, short, void *); |
| 67 | void main_dispatch_resolver(int, short, void *); |
| 68 | |
| 69 | static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *); |
| 70 | static int main_imsg_send_config(struct uw_conf *); |
| 71 | |
| 72 | int main_reload(void); |
| 73 | int main_sendall(enum imsg_type, void *, uint16_t); |
| 74 | void open_ports(void); |
| 75 | void solicit_dns_proposals(void); |
| 76 | void send_blocklist_fd(void); |
| 77 | |
| 78 | struct uw_conf *main_conf; |
| 79 | static struct imsgev *iev_frontend; |
| 80 | static struct imsgev *iev_resolver; |
| 81 | char *conffile; |
| 82 | pid_t frontend_pid; |
| 83 | pid_t resolver_pid; |
| 84 | uint32_t cmd_opts; |
| 85 | int routesock; |
| 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 SIGTERM15: |
| 97 | case SIGINT2: |
| 98 | main_shutdown(); |
| 99 | break; |
| 100 | case SIGHUP1: |
| 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__attribute__((__noreturn__)) void |
| 112 | usage(void) |
| 113 | { |
| 114 | extern char *__progname; |
| 115 | |
| 116 | fprintf(stderr(&__sF[2]), "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, debug = 0, resolver_flag = 0, frontend_flag = 0; |
| 126 | int frontend_routesock, rtfilter; |
| 127 | int pipe_main2frontend[2], pipe_main2resolver[2]; |
| 128 | int control_fd, ta_fd; |
| 129 | char *csock, *saved_argv0; |
| 130 | |
| 131 | csock = _PATH_UNWIND_SOCKET"/dev/unwind.sock"; |
| 132 | |
| 133 | log_init(1, LOG_DAEMON)uw_log_init(1, (3<<3)); /* Log to stderr until daemonized. */ |
| 134 | log_setverbose(1); |
| 135 | |
| 136 | saved_argv0 = argv[0]; |
| 137 | if (saved_argv0 == NULL((void *)0)) |
| 138 | saved_argv0 = "unwind"; |
| 139 | |
| 140 | while ((ch = getopt(argc, argv, "dEFf:ns:v")) != -1) { |
| 141 | switch (ch) { |
| 142 | case 'd': |
| 143 | debug = 1; |
| 144 | break; |
| 145 | case 'E': |
| 146 | resolver_flag = 1; |
| 147 | break; |
| 148 | case 'F': |
| 149 | frontend_flag = 1; |
| 150 | break; |
| 151 | case 'f': |
| 152 | conffile = optarg; |
| 153 | break; |
| 154 | case 'n': |
| 155 | cmd_opts |= OPT_NOACTION0x00000008; |
| 156 | break; |
| 157 | case 's': |
| 158 | csock = optarg; |
| 159 | break; |
| 160 | case 'v': |
| 161 | if (cmd_opts & OPT_VERBOSE20x00000002) |
| 162 | cmd_opts |= OPT_VERBOSE30x00000004; |
| 163 | if (cmd_opts & OPT_VERBOSE0x00000001) |
| 164 | cmd_opts |= OPT_VERBOSE20x00000002; |
| 165 | cmd_opts |= OPT_VERBOSE0x00000001; |
| 166 | break; |
| 167 | default: |
| 168 | usage(); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | argc -= optind; |
| 173 | argv += optind; |
Value stored to 'argv' is never read | |
| 174 | if (argc > 0 || (resolver_flag && frontend_flag)) |
| 175 | usage(); |
| 176 | |
| 177 | if (resolver_flag) |
| 178 | resolver(debug, cmd_opts & (OPT_VERBOSE0x00000001 | OPT_VERBOSE20x00000002 | |
| 179 | OPT_VERBOSE30x00000004)); |
| 180 | else if (frontend_flag) |
| 181 | frontend(debug, cmd_opts & (OPT_VERBOSE0x00000001 | OPT_VERBOSE20x00000002 | |
| 182 | OPT_VERBOSE30x00000004)); |
| 183 | |
| 184 | if ((main_conf = parse_config(conffile)) == NULL((void *)0)) |
| 185 | exit(1); |
| 186 | |
| 187 | if (cmd_opts & OPT_NOACTION0x00000008) { |
| 188 | if (cmd_opts & OPT_VERBOSE0x00000001) |
| 189 | print_config(main_conf); |
| 190 | else |
| 191 | fprintf(stderr(&__sF[2]), "configuration OK\n"); |
| 192 | exit(0); |
| 193 | } |
| 194 | |
| 195 | /* Check for root privileges. */ |
| 196 | if (geteuid()) |
| 197 | errx(1, "need root privileges"); |
| 198 | |
| 199 | /* Check for assigned daemon user */ |
| 200 | if (getpwnam(UNWIND_USER"_unwind") == NULL((void *)0)) |
| 201 | errx(1, "unknown user %s", UNWIND_USER"_unwind"); |
| 202 | |
| 203 | log_init(debug, LOG_DAEMON)uw_log_init(debug, (3<<3)); |
| 204 | log_setverbose(cmd_opts & (OPT_VERBOSE0x00000001 | OPT_VERBOSE20x00000002 | OPT_VERBOSE30x00000004)); |
| 205 | |
| 206 | if (!debug) |
| 207 | daemon(1, 0); |
| 208 | |
| 209 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, |
| 210 | PF_UNSPEC0, pipe_main2frontend) == -1) |
| 211 | fatal("main2frontend socketpair"); |
| 212 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, |
| 213 | PF_UNSPEC0, pipe_main2resolver) == -1) |
| 214 | fatal("main2resolver socketpair"); |
| 215 | |
| 216 | /* Start children. */ |
| 217 | resolver_pid = start_child(PROC_RESOLVER, saved_argv0, |
| 218 | pipe_main2resolver[1], debug, cmd_opts & (OPT_VERBOSE0x00000001 | |
| 219 | OPT_VERBOSE20x00000002 | OPT_VERBOSE30x00000004)); |
| 220 | frontend_pid = start_child(PROC_FRONTEND, saved_argv0, |
| 221 | pipe_main2frontend[1], debug, cmd_opts & (OPT_VERBOSE0x00000001 | |
| 222 | OPT_VERBOSE20x00000002 | OPT_VERBOSE30x00000004)); |
| 223 | |
| 224 | log_procinit("main"); |
| 225 | |
| 226 | event_init(); |
| 227 | |
| 228 | /* Setup signal handler. */ |
| 229 | signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, main_sig_handler, ((void *)0)); |
| 230 | signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, main_sig_handler, ( (void *)0)); |
| 231 | signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, main_sig_handler, ((void *)0)); |
| 232 | signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0)); |
| 233 | signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0)); |
| 234 | signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void *)0)); |
| 235 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); |
| 236 | |
| 237 | /* Setup pipes to children. */ |
| 238 | |
| 239 | if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL((void *)0) || |
| 240 | (iev_resolver = malloc(sizeof(struct imsgev))) == NULL((void *)0)) |
| 241 | fatal(NULL((void *)0)); |
| 242 | imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]); |
| 243 | iev_frontend->handler = main_dispatch_frontend; |
| 244 | imsg_init(&iev_resolver->ibuf, pipe_main2resolver[0]); |
| 245 | iev_resolver->handler = main_dispatch_resolver; |
| 246 | |
| 247 | /* Setup event handlers for pipes. */ |
| 248 | iev_frontend->events = EV_READ0x02; |
| 249 | event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, |
| 250 | iev_frontend->events, iev_frontend->handler, iev_frontend); |
| 251 | event_add(&iev_frontend->ev, NULL((void *)0)); |
| 252 | |
| 253 | iev_resolver->events = EV_READ0x02; |
| 254 | event_set(&iev_resolver->ev, iev_resolver->ibuf.fd, |
| 255 | iev_resolver->events, iev_resolver->handler, iev_resolver); |
| 256 | event_add(&iev_resolver->ev, NULL((void *)0)); |
| 257 | |
| 258 | if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, |
| 259 | &iev_resolver->ibuf)) |
| 260 | fatal("could not establish imsg links"); |
| 261 | |
| 262 | open_ports(); |
| 263 | |
| 264 | if ((control_fd = control_init(csock)) == -1) |
| 265 | fatalx("control socket setup failed"); |
| 266 | |
| 267 | if ((frontend_routesock = socket(AF_ROUTE17, SOCK_RAW3 | SOCK_CLOEXEC0x8000 | |
| 268 | SOCK_NONBLOCK0x4000, 0)) == -1) |
| 269 | fatal("route socket"); |
| 270 | |
| 271 | rtfilter = ROUTE_FILTER(RTM_IFINFO)(1 << (0xe)) | ROUTE_FILTER(RTM_PROPOSAL)(1 << (0x13)) |
| 272 | | ROUTE_FILTER(RTM_IFANNOUNCE)(1 << (0xf)) | ROUTE_FILTER(RTM_NEWADDR)(1 << (0xc)) |
| 273 | | ROUTE_FILTER(RTM_DELADDR)(1 << (0xd)); |
| 274 | if (setsockopt(frontend_routesock, AF_ROUTE17, ROUTE_MSGFILTER1, |
| 275 | &rtfilter, sizeof(rtfilter)) == -1) |
| 276 | fatal("setsockopt(ROUTE_MSGFILTER)"); |
| 277 | |
| 278 | if ((routesock = socket(AF_ROUTE17, SOCK_RAW3 | SOCK_CLOEXEC0x8000 | |
| 279 | SOCK_NONBLOCK0x4000, 0)) == -1) |
| 280 | fatal("route socket"); |
| 281 | shutdown(SHUT_RD0, routesock); |
| 282 | |
| 283 | if ((ta_fd = open(TRUST_ANCHOR_FILE"/var/db/unwind.key", O_RDWR0x0002 | O_CREAT0x0200, 0644)) == -1) |
| 284 | log_warn("%s", TRUST_ANCHOR_FILE)uw_log_warn("%s", "/var/db/unwind.key"); |
| 285 | |
| 286 | /* receiver handles failed open correctly */ |
| 287 | main_imsg_compose_frontend_fd(IMSG_TAFD, 0, ta_fd); |
| 288 | |
| 289 | main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd); |
| 290 | main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); |
| 291 | main_imsg_send_config(main_conf); |
| 292 | |
| 293 | if (main_conf->blocklist_file != NULL((void *)0)) |
| 294 | send_blocklist_fd(); |
| 295 | |
| 296 | if (pledge("stdio rpath sendfd", NULL((void *)0)) == -1) |
| 297 | fatal("pledge"); |
| 298 | |
| 299 | main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL((void *)0), 0); |
| 300 | main_imsg_compose_resolver(IMSG_STARTUP, 0, NULL((void *)0), 0); |
| 301 | |
| 302 | event_dispatch(); |
| 303 | |
| 304 | main_shutdown(); |
| 305 | return (0); |
| 306 | } |
| 307 | |
| 308 | __dead__attribute__((__noreturn__)) void |
| 309 | main_shutdown(void) |
| 310 | { |
| 311 | pid_t pid; |
| 312 | int status; |
| 313 | |
| 314 | /* Close pipes. */ |
| 315 | msgbuf_clear(&iev_frontend->ibuf.w); |
| 316 | close(iev_frontend->ibuf.fd); |
| 317 | msgbuf_clear(&iev_resolver->ibuf.w); |
| 318 | close(iev_resolver->ibuf.fd); |
| 319 | |
| 320 | config_clear(main_conf); |
| 321 | |
| 322 | log_debug("waiting for children to terminate"); |
| 323 | do { |
| 324 | pid = wait(&status); |
| 325 | if (pid == -1) { |
| 326 | if (errno(*__errno()) != EINTR4 && errno(*__errno()) != ECHILD10) |
| 327 | fatal("wait"); |
| 328 | } else if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177 ) != 0)) |
| 329 | log_warnx("%s terminated; signal %d", |
| 330 | (pid == resolver_pid) ? "resolver" : |
| 331 | "frontend", WTERMSIG(status)(((status) & 0177))); |
| 332 | } while (pid != -1 || (pid == -1 && errno(*__errno()) == EINTR4)); |
| 333 | |
| 334 | free(iev_frontend); |
| 335 | free(iev_resolver); |
| 336 | |
| 337 | log_info("terminating")uw_log_info("terminating"); |
| 338 | exit(0); |
| 339 | } |
| 340 | |
| 341 | static pid_t |
| 342 | start_child(enum uw_process p, char *argv0, int fd, int debug, int verbose) |
| 343 | { |
| 344 | char *argv[7]; |
| 345 | int argc = 0; |
| 346 | pid_t pid; |
| 347 | |
| 348 | switch (pid = fork()) { |
| 349 | case -1: |
| 350 | fatal("cannot fork"); |
| 351 | case 0: |
| 352 | break; |
| 353 | default: |
| 354 | close(fd); |
| 355 | return (pid); |
| 356 | } |
| 357 | |
| 358 | if (fd != 3) { |
| 359 | if (dup2(fd, 3) == -1) |
| 360 | fatal("cannot setup imsg fd"); |
| 361 | } else if (fcntl(fd, F_SETFD2, 0) == -1) |
| 362 | fatal("cannot setup imsg fd"); |
| 363 | |
| 364 | argv[argc++] = argv0; |
| 365 | switch (p) { |
| 366 | case PROC_MAIN: |
| 367 | fatalx("Can not start main process"); |
| 368 | case PROC_RESOLVER: |
| 369 | argv[argc++] = "-E"; |
| 370 | break; |
| 371 | case PROC_FRONTEND: |
| 372 | argv[argc++] = "-F"; |
| 373 | break; |
| 374 | } |
| 375 | if (debug) |
| 376 | argv[argc++] = "-d"; |
| 377 | if (verbose & OPT_VERBOSE0x00000001) |
| 378 | argv[argc++] = "-v"; |
| 379 | if (verbose & OPT_VERBOSE20x00000002) |
| 380 | argv[argc++] = "-v"; |
| 381 | if (verbose & OPT_VERBOSE30x00000004) |
| 382 | argv[argc++] = "-v"; |
| 383 | argv[argc++] = NULL((void *)0); |
| 384 | |
| 385 | execvp(argv0, argv); |
| 386 | fatal("execvp"); |
| 387 | } |
| 388 | |
| 389 | void |
| 390 | main_dispatch_frontend(int fd, short event, void *bula) |
| 391 | { |
| 392 | struct imsgev *iev = bula; |
| 393 | struct imsgbuf *ibuf; |
| 394 | struct imsg imsg; |
| 395 | ssize_t n; |
| 396 | int shut = 0, verbose; |
| 397 | |
| 398 | ibuf = &iev->ibuf; |
| 399 | |
| 400 | if (event & EV_READ0x02) { |
| 401 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) |
| 402 | fatal("imsg_read error"); |
| 403 | if (n == 0) /* Connection closed. */ |
| 404 | shut = 1; |
| 405 | } |
| 406 | if (event & EV_WRITE0x04) { |
| 407 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) |
| 408 | fatal("msgbuf_write"); |
| 409 | if (n == 0) /* Connection closed. */ |
| 410 | shut = 1; |
| 411 | } |
| 412 | |
| 413 | for (;;) { |
| 414 | if ((n = imsg_get(ibuf, &imsg)) == -1) |
| 415 | fatal("imsg_get"); |
| 416 | if (n == 0) /* No more messages. */ |
| 417 | break; |
| 418 | |
| 419 | switch (imsg.hdr.type) { |
| 420 | case IMSG_STARTUP_DONE: |
| 421 | solicit_dns_proposals(); |
| 422 | break; |
| 423 | case IMSG_CTL_RELOAD: |
| 424 | if (main_reload() == -1) |
| 425 | log_warnx("configuration reload failed"); |
| 426 | else |
| 427 | log_warnx("configuration reloaded"); |
| 428 | break; |
| 429 | case IMSG_CTL_LOG_VERBOSE: |
| 430 | if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(verbose)) |
| 431 | fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " |
| 432 | "%lu", __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr))); |
| 433 | memcpy(&verbose, imsg.data, sizeof(verbose)); |
| 434 | log_setverbose(verbose); |
| 435 | break; |
| 436 | default: |
| 437 | log_debug("%s: error handling imsg %d", __func__, |
| 438 | imsg.hdr.type); |
| 439 | break; |
| 440 | } |
| 441 | imsg_free(&imsg); |
| 442 | } |
| 443 | if (!shut) |
| 444 | imsg_event_add(iev); |
| 445 | else { |
| 446 | /* This pipe is dead. Remove its event handler */ |
| 447 | event_del(&iev->ev); |
| 448 | event_loopexit(NULL((void *)0)); |
| 449 | } |
| 450 | } |
| 451 | |
| 452 | void |
| 453 | main_dispatch_resolver(int fd, short event, void *bula) |
| 454 | { |
| 455 | struct imsgev *iev = bula; |
| 456 | struct imsgbuf *ibuf; |
| 457 | struct imsg imsg; |
| 458 | ssize_t n; |
| 459 | int shut = 0; |
| 460 | |
| 461 | ibuf = &iev->ibuf; |
| 462 | |
| 463 | if (event & EV_READ0x02) { |
| 464 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) |
| 465 | fatal("imsg_read error"); |
| 466 | if (n == 0) /* Connection closed. */ |
| 467 | shut = 1; |
| 468 | } |
| 469 | if (event & EV_WRITE0x04) { |
| 470 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) |
| 471 | fatal("msgbuf_write"); |
| 472 | if (n == 0) /* Connection closed. */ |
| 473 | shut = 1; |
| 474 | } |
| 475 | |
| 476 | for (;;) { |
| 477 | if ((n = imsg_get(ibuf, &imsg)) == -1) |
| 478 | fatal("imsg_get"); |
| 479 | if (n == 0) /* No more messages. */ |
| 480 | break; |
| 481 | |
| 482 | switch (imsg.hdr.type) { |
| 483 | default: |
| 484 | log_debug("%s: error handling imsg %d", __func__, |
| 485 | imsg.hdr.type); |
| 486 | break; |
| 487 | } |
| 488 | imsg_free(&imsg); |
| 489 | } |
| 490 | if (!shut) |
| 491 | imsg_event_add(iev); |
| 492 | else { |
| 493 | /* This pipe is dead. Remove its event handler. */ |
| 494 | event_del(&iev->ev); |
| 495 | event_loopexit(NULL((void *)0)); |
| 496 | } |
| 497 | } |
| 498 | |
| 499 | void |
| 500 | main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) |
| 501 | { |
| 502 | if (iev_frontend) |
| 503 | imsg_compose_event(iev_frontend, type, 0, pid, -1, data, |
| 504 | datalen); |
| 505 | } |
| 506 | |
| 507 | void |
| 508 | main_imsg_compose_frontend_fd(int type, pid_t pid, int fd) |
| 509 | { |
| 510 | if (iev_frontend) |
| 511 | imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL((void *)0), 0); |
| 512 | } |
| 513 | |
| 514 | void |
| 515 | main_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen) |
| 516 | { |
| 517 | if (iev_resolver) |
| 518 | imsg_compose_event(iev_resolver, type, 0, pid, -1, data, |
| 519 | datalen); |
| 520 | } |
| 521 | |
| 522 | void |
| 523 | imsg_event_add(struct imsgev *iev) |
| 524 | { |
| 525 | iev->events = EV_READ0x02; |
| 526 | if (iev->ibuf.w.queued) |
| 527 | iev->events |= EV_WRITE0x04; |
| 528 | |
| 529 | event_del(&iev->ev); |
| 530 | event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); |
| 531 | event_add(&iev->ev, NULL((void *)0)); |
| 532 | } |
| 533 | |
| 534 | int |
| 535 | imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, |
| 536 | pid_t pid, int fd, void *data, uint16_t datalen) |
| 537 | { |
| 538 | int ret; |
| 539 | |
| 540 | if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data, |
| 541 | datalen)) != -1) |
| 542 | imsg_event_add(iev); |
| 543 | |
| 544 | return (ret); |
| 545 | } |
| 546 | |
| 547 | static int |
| 548 | main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf, |
| 549 | struct imsgbuf *resolver_buf) |
| 550 | { |
| 551 | int pipe_frontend2resolver[2]; |
| 552 | |
| 553 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, |
| 554 | PF_UNSPEC0, pipe_frontend2resolver) == -1) |
| 555 | return (-1); |
| 556 | |
| 557 | if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0, |
| 558 | pipe_frontend2resolver[0], NULL((void *)0), 0) == -1) |
| 559 | return (-1); |
| 560 | if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0, |
| 561 | pipe_frontend2resolver[1], NULL((void *)0), 0) == -1) |
| 562 | return (-1); |
| 563 | |
| 564 | return (0); |
| 565 | } |
| 566 | |
| 567 | int |
| 568 | main_reload(void) |
| 569 | { |
| 570 | struct uw_conf *xconf; |
| 571 | |
| 572 | if ((xconf = parse_config(conffile)) == NULL((void *)0)) |
| 573 | return (-1); |
| 574 | |
| 575 | if (main_imsg_send_config(xconf) == -1) |
| 576 | return (-1); |
| 577 | |
| 578 | merge_config(main_conf, xconf); |
| 579 | |
| 580 | if (main_conf->blocklist_file != NULL((void *)0)) |
| 581 | send_blocklist_fd(); |
| 582 | |
| 583 | return (0); |
| 584 | } |
| 585 | |
| 586 | int |
| 587 | main_imsg_send_config(struct uw_conf *xconf) |
| 588 | { |
| 589 | struct uw_forwarder *uw_forwarder; |
| 590 | struct force_tree_entry *force_entry; |
| 591 | |
| 592 | /* Send fixed part of config to children. */ |
| 593 | if (main_sendall(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) |
| 594 | return (-1); |
| 595 | |
| 596 | if (xconf->blocklist_file != NULL((void *)0)) { |
| 597 | if (main_sendall(IMSG_RECONF_BLOCKLIST_FILE, |
| 598 | xconf->blocklist_file, strlen(xconf->blocklist_file) + 1) |
| 599 | == -1) |
| 600 | return (-1); |
| 601 | } |
| 602 | |
| 603 | /* send static forwarders to children */ |
| 604 | TAILQ_FOREACH(uw_forwarder, &xconf->uw_forwarder_list, entry)for((uw_forwarder) = ((&xconf->uw_forwarder_list)-> tqh_first); (uw_forwarder) != ((void *)0); (uw_forwarder) = ( (uw_forwarder)->entry.tqe_next)) { |
| 605 | if (main_sendall(IMSG_RECONF_FORWARDER, uw_forwarder, |
| 606 | sizeof(*uw_forwarder)) == -1) |
| 607 | return (-1); |
| 608 | } |
| 609 | |
| 610 | /* send static DoT forwarders to children */ |
| 611 | TAILQ_FOREACH(uw_forwarder, &xconf->uw_dot_forwarder_list,for((uw_forwarder) = ((&xconf->uw_dot_forwarder_list)-> tqh_first); (uw_forwarder) != ((void *)0); (uw_forwarder) = ( (uw_forwarder)->entry.tqe_next)) |
| 612 | entry)for((uw_forwarder) = ((&xconf->uw_dot_forwarder_list)-> tqh_first); (uw_forwarder) != ((void *)0); (uw_forwarder) = ( (uw_forwarder)->entry.tqe_next)) { |
| 613 | if (main_sendall(IMSG_RECONF_DOT_FORWARDER, uw_forwarder, |
| 614 | sizeof(*uw_forwarder)) == -1) |
| 615 | return (-1); |
| 616 | } |
| 617 | RB_FOREACH(force_entry, force_tree, &xconf->force)for ((force_entry) = force_tree_RB_MINMAX(&xconf->force , -1); (force_entry) != ((void *)0); (force_entry) = force_tree_RB_NEXT (force_entry)) { |
| 618 | if (main_sendall(IMSG_RECONF_FORCE, force_entry, |
| 619 | sizeof(*force_entry)) == -1) |
| 620 | return (-1); |
| 621 | } |
| 622 | |
| 623 | /* Tell children the revised config is now complete. */ |
| 624 | if (main_sendall(IMSG_RECONF_END, NULL((void *)0), 0) == -1) |
| 625 | return (-1); |
| 626 | |
| 627 | return (0); |
| 628 | } |
| 629 | |
| 630 | int |
| 631 | main_sendall(enum imsg_type type, void *buf, uint16_t len) |
| 632 | { |
| 633 | if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1) |
| 634 | return (-1); |
| 635 | if (imsg_compose_event(iev_resolver, type, 0, 0, -1, buf, len) == -1) |
| 636 | return (-1); |
| 637 | return (0); |
| 638 | } |
| 639 | |
| 640 | void |
| 641 | merge_config(struct uw_conf *conf, struct uw_conf *xconf) |
| 642 | { |
| 643 | struct uw_forwarder *uw_forwarder; |
| 644 | struct force_tree_entry *n, *nxt; |
| 645 | |
| 646 | /* Remove & discard existing forwarders. */ |
| 647 | while ((uw_forwarder = TAILQ_FIRST(&conf->uw_forwarder_list)((&conf->uw_forwarder_list)->tqh_first)) != |
| 648 | NULL((void *)0)) { |
| 649 | TAILQ_REMOVE(&conf->uw_forwarder_list, uw_forwarder, entry)do { if (((uw_forwarder)->entry.tqe_next) != ((void *)0)) ( uw_forwarder)->entry.tqe_next->entry.tqe_prev = (uw_forwarder )->entry.tqe_prev; else (&conf->uw_forwarder_list)-> tqh_last = (uw_forwarder)->entry.tqe_prev; *(uw_forwarder) ->entry.tqe_prev = (uw_forwarder)->entry.tqe_next; ; ; } while (0); |
| 650 | free(uw_forwarder); |
| 651 | } |
| 652 | while ((uw_forwarder = TAILQ_FIRST(&conf->uw_dot_forwarder_list)((&conf->uw_dot_forwarder_list)->tqh_first)) != |
| 653 | NULL((void *)0)) { |
| 654 | TAILQ_REMOVE(&conf->uw_dot_forwarder_list, uw_forwarder, entry)do { if (((uw_forwarder)->entry.tqe_next) != ((void *)0)) ( uw_forwarder)->entry.tqe_next->entry.tqe_prev = (uw_forwarder )->entry.tqe_prev; else (&conf->uw_dot_forwarder_list )->tqh_last = (uw_forwarder)->entry.tqe_prev; *(uw_forwarder )->entry.tqe_prev = (uw_forwarder)->entry.tqe_next; ; ; } while (0); |
| 655 | free(uw_forwarder); |
| 656 | } |
| 657 | |
| 658 | /* Remove & discard existing force tree. */ |
| 659 | RB_FOREACH_SAFE(n, force_tree, &conf->force, nxt)for ((n) = force_tree_RB_MINMAX(&conf->force, -1); ((n ) != ((void *)0)) && ((nxt) = force_tree_RB_NEXT(n), 1 ); (n) = (nxt)) { |
| 660 | RB_REMOVE(force_tree, &conf->force, n)force_tree_RB_REMOVE(&conf->force, n); |
| 661 | free(n); |
| 662 | } |
| 663 | |
| 664 | memcpy(&conf->enabled_resolvers, &xconf->enabled_resolvers, |
| 665 | sizeof(conf->enabled_resolvers)); |
| 666 | |
| 667 | memcpy(&conf->res_pref, &xconf->res_pref, |
| 668 | sizeof(conf->res_pref)); |
| 669 | |
| 670 | free(conf->blocklist_file); |
| 671 | conf->blocklist_file = xconf->blocklist_file; |
| 672 | conf->blocklist_log = xconf->blocklist_log; |
| 673 | |
| 674 | /* Add new forwarders. */ |
| 675 | TAILQ_CONCAT(&conf->uw_forwarder_list, &xconf->uw_forwarder_list,do { if (!(((&xconf->uw_forwarder_list)->tqh_first) == ((void *)0))) { *(&conf->uw_forwarder_list)->tqh_last = (&xconf->uw_forwarder_list)->tqh_first; (&xconf ->uw_forwarder_list)->tqh_first->entry.tqe_prev = (& conf->uw_forwarder_list)->tqh_last; (&conf->uw_forwarder_list )->tqh_last = (&xconf->uw_forwarder_list)->tqh_last ; do { ((&xconf->uw_forwarder_list))->tqh_first = ( (void *)0); ((&xconf->uw_forwarder_list))->tqh_last = &((&xconf->uw_forwarder_list))->tqh_first; } while (0); } } while (0) |
| 676 | entry)do { if (!(((&xconf->uw_forwarder_list)->tqh_first) == ((void *)0))) { *(&conf->uw_forwarder_list)->tqh_last = (&xconf->uw_forwarder_list)->tqh_first; (&xconf ->uw_forwarder_list)->tqh_first->entry.tqe_prev = (& conf->uw_forwarder_list)->tqh_last; (&conf->uw_forwarder_list )->tqh_last = (&xconf->uw_forwarder_list)->tqh_last ; do { ((&xconf->uw_forwarder_list))->tqh_first = ( (void *)0); ((&xconf->uw_forwarder_list))->tqh_last = &((&xconf->uw_forwarder_list))->tqh_first; } while (0); } } while (0); |
| 677 | TAILQ_CONCAT(&conf->uw_dot_forwarder_list,do { if (!(((&xconf->uw_dot_forwarder_list)->tqh_first ) == ((void *)0))) { *(&conf->uw_dot_forwarder_list)-> tqh_last = (&xconf->uw_dot_forwarder_list)->tqh_first ; (&xconf->uw_dot_forwarder_list)->tqh_first->entry .tqe_prev = (&conf->uw_dot_forwarder_list)->tqh_last ; (&conf->uw_dot_forwarder_list)->tqh_last = (& xconf->uw_dot_forwarder_list)->tqh_last; do { ((&xconf ->uw_dot_forwarder_list))->tqh_first = ((void *)0); ((& xconf->uw_dot_forwarder_list))->tqh_last = &((& xconf->uw_dot_forwarder_list))->tqh_first; } while (0); } } while (0) |
| 678 | &xconf->uw_dot_forwarder_list, entry)do { if (!(((&xconf->uw_dot_forwarder_list)->tqh_first ) == ((void *)0))) { *(&conf->uw_dot_forwarder_list)-> tqh_last = (&xconf->uw_dot_forwarder_list)->tqh_first ; (&xconf->uw_dot_forwarder_list)->tqh_first->entry .tqe_prev = (&conf->uw_dot_forwarder_list)->tqh_last ; (&conf->uw_dot_forwarder_list)->tqh_last = (& xconf->uw_dot_forwarder_list)->tqh_last; do { ((&xconf ->uw_dot_forwarder_list))->tqh_first = ((void *)0); ((& xconf->uw_dot_forwarder_list))->tqh_last = &((& xconf->uw_dot_forwarder_list))->tqh_first; } while (0); } } while (0); |
| 679 | |
| 680 | RB_FOREACH_SAFE(n, force_tree, &xconf->force, nxt)for ((n) = force_tree_RB_MINMAX(&xconf->force, -1); (( n) != ((void *)0)) && ((nxt) = force_tree_RB_NEXT(n), 1); (n) = (nxt)) { |
| 681 | RB_REMOVE(force_tree, &xconf->force, n)force_tree_RB_REMOVE(&xconf->force, n); |
| 682 | RB_INSERT(force_tree, &conf->force, n)force_tree_RB_INSERT(&conf->force, n); |
| 683 | } |
| 684 | |
| 685 | free(xconf); |
| 686 | } |
| 687 | |
| 688 | struct uw_conf * |
| 689 | config_new_empty(void) |
| 690 | { |
| 691 | struct uw_conf *xconf; |
| 692 | |
| 693 | xconf = calloc(1, sizeof(*xconf)); |
| 694 | if (xconf == NULL((void *)0)) |
| 695 | fatal(NULL((void *)0)); |
| 696 | |
| 697 | TAILQ_INIT(&xconf->uw_forwarder_list)do { (&xconf->uw_forwarder_list)->tqh_first = ((void *)0); (&xconf->uw_forwarder_list)->tqh_last = & (&xconf->uw_forwarder_list)->tqh_first; } while (0); |
| 698 | TAILQ_INIT(&xconf->uw_dot_forwarder_list)do { (&xconf->uw_dot_forwarder_list)->tqh_first = ( (void *)0); (&xconf->uw_dot_forwarder_list)->tqh_last = &(&xconf->uw_dot_forwarder_list)->tqh_first; } while (0); |
| 699 | |
| 700 | RB_INIT(&xconf->force)do { (&xconf->force)->rbh_root = ((void *)0); } while (0); |
| 701 | |
| 702 | return (xconf); |
| 703 | } |
| 704 | |
| 705 | void |
| 706 | config_clear(struct uw_conf *conf) |
| 707 | { |
| 708 | struct uw_conf *xconf; |
| 709 | |
| 710 | /* Merge current config with an empty config. */ |
| 711 | xconf = config_new_empty(); |
| 712 | merge_config(conf, xconf); |
| 713 | |
| 714 | free(conf); |
| 715 | } |
| 716 | |
| 717 | void |
| 718 | open_ports(void) |
| 719 | { |
| 720 | struct addrinfo hints, *res0; |
| 721 | int udp4sock = -1, udp6sock = -1, error, bsize = 65535; |
| 722 | int tcp4sock = -1, tcp6sock = -1; |
| 723 | int opt = 1; |
| 724 | |
| 725 | memset(&hints, 0, sizeof(hints)); |
| 726 | hints.ai_family = AF_INET2; |
| 727 | hints.ai_socktype = SOCK_DGRAM2; |
| 728 | hints.ai_flags = AI_NUMERICHOST4 | AI_PASSIVE1; |
| 729 | |
| 730 | error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); |
| 731 | if (!error && res0) { |
| 732 | if ((udp4sock = socket(res0->ai_family, res0->ai_socktype, |
| 733 | res0->ai_protocol)) != -1) { |
| 734 | if (setsockopt(udp4sock, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, |
| 735 | &opt, sizeof(opt)) == -1) |
| 736 | log_warn("setting SO_REUSEADDR on socket")uw_log_warn("setting SO_REUSEADDR on socket"); |
| 737 | if (setsockopt(udp4sock, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize, |
| 738 | sizeof(bsize)) == -1) |
| 739 | log_warn("setting SO_SNDBUF on socket")uw_log_warn("setting SO_SNDBUF on socket"); |
| 740 | if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen) |
| 741 | == -1) { |
| 742 | close(udp4sock); |
| 743 | udp4sock = -1; |
| 744 | } |
| 745 | } |
| 746 | } |
| 747 | if (res0) |
| 748 | freeaddrinfo(res0); |
| 749 | |
| 750 | hints.ai_family = AF_INET624; |
| 751 | error = getaddrinfo("::1", "domain", &hints, &res0); |
| 752 | if (!error && res0) { |
| 753 | if ((udp6sock = socket(res0->ai_family, res0->ai_socktype, |
| 754 | res0->ai_protocol)) != -1) { |
| 755 | if (setsockopt(udp6sock, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, |
| 756 | &opt, sizeof(opt)) == -1) |
| 757 | log_warn("setting SO_REUSEADDR on socket")uw_log_warn("setting SO_REUSEADDR on socket"); |
| 758 | if (setsockopt(udp6sock, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize, |
| 759 | sizeof(bsize)) == -1) |
| 760 | log_warn("setting SO_SNDBUF on socket")uw_log_warn("setting SO_SNDBUF on socket"); |
| 761 | if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen) |
| 762 | == -1) { |
| 763 | close(udp6sock); |
| 764 | udp6sock = -1; |
| 765 | } |
| 766 | } |
| 767 | } |
| 768 | if (res0) |
| 769 | freeaddrinfo(res0); |
| 770 | |
| 771 | hints.ai_family = AF_INET2; |
| 772 | hints.ai_socktype = SOCK_STREAM1; |
| 773 | |
| 774 | error = getaddrinfo("127.0.0.1", "domain", &hints, &res0); |
| 775 | if (!error && res0) { |
| 776 | if ((tcp4sock = socket(res0->ai_family, |
| 777 | res0->ai_socktype | SOCK_NONBLOCK0x4000, |
| 778 | res0->ai_protocol)) != -1) { |
| 779 | if (setsockopt(tcp4sock, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, |
| 780 | &opt, sizeof(opt)) == -1) |
| 781 | log_warn("setting SO_REUSEADDR on socket")uw_log_warn("setting SO_REUSEADDR on socket"); |
| 782 | if (setsockopt(tcp4sock, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize, |
| 783 | sizeof(bsize)) == -1) |
| 784 | log_warn("setting SO_SNDBUF on socket")uw_log_warn("setting SO_SNDBUF on socket"); |
| 785 | if (bind(tcp4sock, res0->ai_addr, res0->ai_addrlen) |
| 786 | == -1) { |
| 787 | close(tcp4sock); |
| 788 | tcp4sock = -1; |
| 789 | } |
| 790 | if (listen(tcp4sock, 5) == -1) { |
| 791 | close(tcp4sock); |
| 792 | tcp4sock = -1; |
| 793 | } |
| 794 | } |
| 795 | } |
| 796 | if (res0) |
| 797 | freeaddrinfo(res0); |
| 798 | |
| 799 | hints.ai_family = AF_INET624; |
| 800 | error = getaddrinfo("::1", "domain", &hints, &res0); |
| 801 | if (!error && res0) { |
| 802 | if ((tcp6sock = socket(res0->ai_family, |
| 803 | res0->ai_socktype | SOCK_NONBLOCK0x4000, |
| 804 | res0->ai_protocol)) != -1) { |
| 805 | if (setsockopt(tcp6sock, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, |
| 806 | &opt, sizeof(opt)) == -1) |
| 807 | log_warn("setting SO_REUSEADDR on socket")uw_log_warn("setting SO_REUSEADDR on socket"); |
| 808 | if (setsockopt(tcp6sock, SOL_SOCKET0xffff, SO_SNDBUF0x1001, &bsize, |
| 809 | sizeof(bsize)) == -1) |
| 810 | log_warn("setting SO_SNDBUF on socket")uw_log_warn("setting SO_SNDBUF on socket"); |
| 811 | if (bind(tcp6sock, res0->ai_addr, res0->ai_addrlen) |
| 812 | == -1) { |
| 813 | close(tcp6sock); |
| 814 | tcp6sock = -1; |
| 815 | } |
| 816 | if (listen(tcp6sock, 5) == -1) { |
| 817 | close(tcp6sock); |
| 818 | tcp6sock = -1; |
| 819 | } |
| 820 | } |
| 821 | } |
| 822 | if (res0) |
| 823 | freeaddrinfo(res0); |
| 824 | |
| 825 | if ((udp4sock == -1 || tcp4sock == -1) && (udp6sock == -1 || |
| 826 | tcp6sock == -1)) |
| 827 | fatalx("could not bind to 127.0.0.1 or ::1 on port 53"); |
| 828 | |
| 829 | if (udp4sock != -1) |
| 830 | main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock); |
| 831 | if (udp6sock != -1) |
| 832 | main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock); |
| 833 | if (tcp4sock != -1) |
| 834 | main_imsg_compose_frontend_fd(IMSG_TCP4SOCK, 0, tcp4sock); |
| 835 | if (tcp6sock != -1) |
| 836 | main_imsg_compose_frontend_fd(IMSG_TCP6SOCK, 0, tcp6sock); |
| 837 | } |
| 838 | |
| 839 | void |
| 840 | solicit_dns_proposals(void) |
| 841 | { |
| 842 | struct rt_msghdr rtm; |
| 843 | struct iovec iov[1]; |
| 844 | int iovcnt = 0; |
| 845 | |
| 846 | memset(&rtm, 0, sizeof(rtm)); |
| 847 | |
| 848 | rtm.rtm_version = RTM_VERSION5; |
| 849 | rtm.rtm_type = RTM_PROPOSAL0x13; |
| 850 | rtm.rtm_msglen = sizeof(rtm); |
| 851 | rtm.rtm_tableid = 0; |
| 852 | rtm.rtm_index = 0; |
| 853 | rtm.rtm_seq = arc4random(); |
| 854 | rtm.rtm_priority = RTP_PROPOSAL_SOLICIT62; |
| 855 | |
| 856 | iov[iovcnt].iov_base = &rtm; |
| 857 | iov[iovcnt++].iov_len = sizeof(rtm); |
| 858 | |
| 859 | if (writev(routesock, iov, iovcnt) == -1) |
| 860 | log_warn("failed to send solicitation")uw_log_warn("failed to send solicitation"); |
| 861 | } |
| 862 | |
| 863 | void |
| 864 | send_blocklist_fd(void) |
| 865 | { |
| 866 | int bl_fd; |
| 867 | |
| 868 | if ((bl_fd = open(main_conf->blocklist_file, O_RDONLY0x0000)) != -1) |
| 869 | main_imsg_compose_frontend_fd(IMSG_BLFD, 0, bl_fd); |
| 870 | else |
| 871 | log_warn("%s", main_conf->blocklist_file)uw_log_warn("%s", main_conf->blocklist_file); |
| 872 | } |
| 873 | |
| 874 | void |
| 875 | imsg_receive_config(struct imsg *imsg, struct uw_conf **xconf) |
| 876 | { |
| 877 | struct uw_conf *nconf; |
| 878 | struct uw_forwarder *uw_forwarder; |
| 879 | struct force_tree_entry *force_entry; |
| 880 | |
| 881 | nconf = *xconf; |
| 882 | |
| 883 | switch (imsg->hdr.type) { |
| 884 | case IMSG_RECONF_CONF: |
| 885 | if (nconf != NULL((void *)0)) |
| 886 | fatalx("%s: IMSG_RECONF_CONF already in " |
| 887 | "progress", __func__); |
| 888 | if (IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(struct uw_conf)) |
| 889 | fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", |
| 890 | __func__, IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr))); |
| 891 | if ((*xconf = malloc(sizeof(struct uw_conf))) == NULL((void *)0)) |
| 892 | fatal(NULL((void *)0)); |
| 893 | nconf = *xconf; |
| 894 | memcpy(nconf, imsg->data, sizeof(struct uw_conf)); |
| 895 | TAILQ_INIT(&nconf->uw_forwarder_list)do { (&nconf->uw_forwarder_list)->tqh_first = ((void *)0); (&nconf->uw_forwarder_list)->tqh_last = & (&nconf->uw_forwarder_list)->tqh_first; } while (0); |
| 896 | TAILQ_INIT(&nconf->uw_dot_forwarder_list)do { (&nconf->uw_dot_forwarder_list)->tqh_first = ( (void *)0); (&nconf->uw_dot_forwarder_list)->tqh_last = &(&nconf->uw_dot_forwarder_list)->tqh_first; } while (0); |
| 897 | RB_INIT(&nconf->force)do { (&nconf->force)->rbh_root = ((void *)0); } while (0); |
| 898 | break; |
| 899 | case IMSG_RECONF_BLOCKLIST_FILE: |
| 900 | if (((char *)imsg->data)[IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr)) - 1] != '\0') |
| 901 | fatalx("Invalid blocklist file"); |
| 902 | if ((nconf->blocklist_file = strdup(imsg->data)) == |
| 903 | NULL((void *)0)) |
| 904 | fatal("%s: strdup", __func__); |
| 905 | break; |
| 906 | case IMSG_RECONF_FORWARDER: |
| 907 | if (IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(struct uw_forwarder)) |
| 908 | fatalx("%s: IMSG_RECONF_FORWARDER wrong length:" |
| 909 | " %lu", __func__, IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr))); |
| 910 | if ((uw_forwarder = malloc(sizeof(struct |
| 911 | uw_forwarder))) == NULL((void *)0)) |
| 912 | fatal(NULL((void *)0)); |
| 913 | memcpy(uw_forwarder, imsg->data, sizeof(struct |
| 914 | uw_forwarder)); |
| 915 | TAILQ_INSERT_TAIL(&nconf->uw_forwarder_list,do { (uw_forwarder)->entry.tqe_next = ((void *)0); (uw_forwarder )->entry.tqe_prev = (&nconf->uw_forwarder_list)-> tqh_last; *(&nconf->uw_forwarder_list)->tqh_last = ( uw_forwarder); (&nconf->uw_forwarder_list)->tqh_last = &(uw_forwarder)->entry.tqe_next; } while (0) |
| 916 | uw_forwarder, entry)do { (uw_forwarder)->entry.tqe_next = ((void *)0); (uw_forwarder )->entry.tqe_prev = (&nconf->uw_forwarder_list)-> tqh_last; *(&nconf->uw_forwarder_list)->tqh_last = ( uw_forwarder); (&nconf->uw_forwarder_list)->tqh_last = &(uw_forwarder)->entry.tqe_next; } while (0); |
| 917 | break; |
| 918 | case IMSG_RECONF_DOT_FORWARDER: |
| 919 | if (IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(struct uw_forwarder)) |
| 920 | fatalx("%s: IMSG_RECONF_DOT_FORWARDER wrong " |
| 921 | "length: %lu", __func__, |
| 922 | IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr))); |
| 923 | if ((uw_forwarder = malloc(sizeof(struct |
| 924 | uw_forwarder))) == NULL((void *)0)) |
| 925 | fatal(NULL((void *)0)); |
| 926 | memcpy(uw_forwarder, imsg->data, sizeof(struct |
| 927 | uw_forwarder)); |
| 928 | TAILQ_INSERT_TAIL(&nconf->uw_dot_forwarder_list,do { (uw_forwarder)->entry.tqe_next = ((void *)0); (uw_forwarder )->entry.tqe_prev = (&nconf->uw_dot_forwarder_list) ->tqh_last; *(&nconf->uw_dot_forwarder_list)->tqh_last = (uw_forwarder); (&nconf->uw_dot_forwarder_list)-> tqh_last = &(uw_forwarder)->entry.tqe_next; } while (0 ) |
| 929 | uw_forwarder, entry)do { (uw_forwarder)->entry.tqe_next = ((void *)0); (uw_forwarder )->entry.tqe_prev = (&nconf->uw_dot_forwarder_list) ->tqh_last; *(&nconf->uw_dot_forwarder_list)->tqh_last = (uw_forwarder); (&nconf->uw_dot_forwarder_list)-> tqh_last = &(uw_forwarder)->entry.tqe_next; } while (0 ); |
| 930 | break; |
| 931 | case IMSG_RECONF_FORCE: |
| 932 | if (IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(struct force_tree_entry)) |
| 933 | fatalx("%s: IMSG_RECONF_FORCE wrong " |
| 934 | "length: %lu", __func__, |
| 935 | IMSG_DATA_SIZE(*imsg)((*imsg).hdr.len - sizeof(struct imsg_hdr))); |
| 936 | if ((force_entry = malloc(sizeof(struct |
| 937 | force_tree_entry))) == NULL((void *)0)) |
| 938 | fatal(NULL((void *)0)); |
| 939 | memcpy(force_entry, imsg->data, sizeof(struct |
| 940 | force_tree_entry)); |
| 941 | if (RB_INSERT(force_tree, &nconf->force, force_entry)force_tree_RB_INSERT(&nconf->force, force_entry) != NULL((void *)0)) { |
| 942 | free(force_entry); |
| 943 | fatalx("%s: IMSG_RECONF_FORCE duplicate entry", |
| 944 | __func__); |
| 945 | } |
| 946 | break; |
| 947 | default: |
| 948 | log_debug("%s: error handling imsg %d", __func__, |
| 949 | imsg->hdr.type); |
| 950 | break; |
| 951 | } |
| 952 | } |