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 | } |