xref: /openbsd-src/sbin/unwind/unwind.c (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
1 /*	$OpenBSD: unwind.c,v 1.49 2020/09/12 17:01:03 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.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"
52 
53 __dead void	usage(void);
54 __dead void	main_shutdown(void);
55 
56 void		main_sig_handler(int, short, void *);
57 
58 static pid_t	start_child(int, char *, int, int, int);
59 
60 void		main_dispatch_frontend(int, short, void *);
61 void		main_dispatch_resolver(int, short, void *);
62 
63 static int	main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *);
64 static int	main_imsg_send_config(struct uw_conf *);
65 
66 int		main_reload(void);
67 int		main_sendall(enum imsg_type, void *, uint16_t);
68 void		open_ports(void);
69 void		solicit_dns_proposals(void);
70 void		send_blocklist_fd(void);
71 
72 struct uw_conf	*main_conf;
73 struct imsgev	*iev_frontend;
74 struct imsgev	*iev_resolver;
75 char		*conffile;
76 
77 pid_t		 frontend_pid;
78 pid_t		 resolver_pid;
79 
80 uint32_t	 cmd_opts;
81 
82 int		 routesock;
83 
84 void
85 main_sig_handler(int sig, short event, void *arg)
86 {
87 	/*
88 	 * Normal signal handler rules don't apply because libevent
89 	 * decouples for us.
90 	 */
91 
92 	switch (sig) {
93 	case SIGTERM:
94 	case SIGINT:
95 		main_shutdown();
96 		break;
97 	case SIGHUP:
98 		if (main_reload() == -1)
99 			log_warnx("configuration reload failed");
100 		else
101 			log_debug("configuration reloaded");
102 		break;
103 	default:
104 		fatalx("unexpected signal");
105 	}
106 }
107 
108 __dead void
109 usage(void)
110 {
111 	extern char *__progname;
112 
113 	fprintf(stderr, "usage: %s [-dnv] [-f file] [-s socket]\n",
114 	    __progname);
115 	exit(1);
116 }
117 
118 int
119 main(int argc, char *argv[])
120 {
121 	struct event	 ev_sigint, ev_sigterm, ev_sighup;
122 	int		 ch, debug = 0, resolver_flag = 0, frontend_flag = 0;
123 	int		 frontend_routesock, rtfilter;
124 	int		 pipe_main2frontend[2], pipe_main2resolver[2];
125 	int		 control_fd, ta_fd;
126 	char		*csock, *saved_argv0;
127 
128 	csock = UNWIND_SOCKET;
129 
130 	log_init(1, LOG_DAEMON);	/* Log to stderr until daemonized. */
131 	log_setverbose(1);
132 
133 	saved_argv0 = argv[0];
134 	if (saved_argv0 == NULL)
135 		saved_argv0 = "unwind";
136 
137 	while ((ch = getopt(argc, argv, "dEFf:ns:v")) != -1) {
138 		switch (ch) {
139 		case 'd':
140 			debug = 1;
141 			break;
142 		case 'E':
143 			resolver_flag = 1;
144 			break;
145 		case 'F':
146 			frontend_flag = 1;
147 			break;
148 		case 'f':
149 			conffile = optarg;
150 			break;
151 		case 'n':
152 			cmd_opts |= OPT_NOACTION;
153 			break;
154 		case 's':
155 			csock = optarg;
156 			break;
157 		case 'v':
158 			if (cmd_opts & OPT_VERBOSE2)
159 				cmd_opts |= OPT_VERBOSE3;
160 			if (cmd_opts & OPT_VERBOSE)
161 				cmd_opts |= OPT_VERBOSE2;
162 			cmd_opts |= OPT_VERBOSE;
163 			break;
164 		default:
165 			usage();
166 		}
167 	}
168 
169 	argc -= optind;
170 	argv += optind;
171 	if (argc > 0 || (resolver_flag && frontend_flag))
172 		usage();
173 
174 	if (resolver_flag)
175 		resolver(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 |
176 		    OPT_VERBOSE3));
177 	else if (frontend_flag)
178 		frontend(debug, cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 |
179 		    OPT_VERBOSE3));
180 
181 	if ((main_conf = parse_config(conffile)) == NULL)
182 		exit(1);
183 
184 	if (cmd_opts & OPT_NOACTION) {
185 		if (cmd_opts & OPT_VERBOSE)
186 			print_config(main_conf);
187 		else
188 			fprintf(stderr, "configuration OK\n");
189 		exit(0);
190 	}
191 
192 	/* Check for root privileges. */
193 	if (geteuid())
194 		errx(1, "need root privileges");
195 
196 	/* Check for assigned daemon user */
197 	if (getpwnam(UNWIND_USER) == NULL)
198 		errx(1, "unknown user %s", UNWIND_USER);
199 
200 	log_init(debug, LOG_DAEMON);
201 	log_setverbose(cmd_opts & (OPT_VERBOSE | OPT_VERBOSE2 | OPT_VERBOSE3));
202 
203 	if (!debug)
204 		daemon(1, 0);
205 
206 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
207 	    PF_UNSPEC, pipe_main2frontend) == -1)
208 		fatal("main2frontend socketpair");
209 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
210 	    PF_UNSPEC, pipe_main2resolver) == -1)
211 		fatal("main2resolver socketpair");
212 
213 	/* Start children. */
214 	resolver_pid = start_child(PROC_RESOLVER, saved_argv0,
215 	    pipe_main2resolver[1], debug, cmd_opts & (OPT_VERBOSE |
216 	    OPT_VERBOSE2 | OPT_VERBOSE3));
217 	frontend_pid = start_child(PROC_FRONTEND, saved_argv0,
218 	    pipe_main2frontend[1], debug, cmd_opts & (OPT_VERBOSE |
219 	    OPT_VERBOSE2 | OPT_VERBOSE3));
220 
221 	uw_process = PROC_MAIN;
222 	log_procinit(log_procnames[uw_process]);
223 
224 	event_init();
225 
226 	/* Setup signal handler. */
227 	signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
228 	signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
229 	signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL);
230 	signal_add(&ev_sigint, NULL);
231 	signal_add(&ev_sigterm, NULL);
232 	signal_add(&ev_sighup, NULL);
233 	signal(SIGPIPE, SIG_IGN);
234 
235 	/* Setup pipes to children. */
236 
237 	if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL ||
238 	    (iev_resolver = malloc(sizeof(struct imsgev))) == NULL)
239 		fatal(NULL);
240 	imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]);
241 	iev_frontend->handler = main_dispatch_frontend;
242 	imsg_init(&iev_resolver->ibuf, pipe_main2resolver[0]);
243 	iev_resolver->handler = main_dispatch_resolver;
244 
245 	/* Setup event handlers for pipes. */
246 	iev_frontend->events = EV_READ;
247 	event_set(&iev_frontend->ev, iev_frontend->ibuf.fd,
248 	    iev_frontend->events, iev_frontend->handler, iev_frontend);
249 	event_add(&iev_frontend->ev, NULL);
250 
251 	iev_resolver->events = EV_READ;
252 	event_set(&iev_resolver->ev, iev_resolver->ibuf.fd,
253 	    iev_resolver->events, iev_resolver->handler, iev_resolver);
254 	event_add(&iev_resolver->ev, NULL);
255 
256 	if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf,
257 	    &iev_resolver->ibuf))
258 		fatal("could not establish imsg links");
259 
260 	open_ports();
261 
262 	if ((control_fd = control_init(csock)) == -1)
263 		fatalx("control socket setup failed");
264 
265 	if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC,
266 	    AF_INET)) == -1)
267 		fatal("route socket");
268 
269 	rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_PROPOSAL)
270 	    | ROUTE_FILTER(RTM_IFANNOUNCE);
271 	if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER,
272 	    &rtfilter, sizeof(rtfilter)) == -1)
273 		fatal("setsockopt(ROUTE_MSGFILTER)");
274 
275 	if ((routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC |
276 	    SOCK_NONBLOCK, AF_INET6)) == -1)
277 		fatal("route socket");
278 	shutdown(SHUT_RD, routesock);
279 
280 	if ((ta_fd = open(TRUST_ANCHOR_FILE, O_RDWR | O_CREAT, 0644)) == -1)
281 		log_warn("%s", TRUST_ANCHOR_FILE);
282 
283 	/* receiver handles failed open correctly */
284 	main_imsg_compose_frontend_fd(IMSG_TAFD, 0, ta_fd);
285 
286 	main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd);
287 	main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock);
288 	main_imsg_send_config(main_conf);
289 
290 	if (main_conf->blocklist_file != NULL)
291 		send_blocklist_fd();
292 
293 	if (pledge("stdio rpath sendfd", NULL) == -1)
294 		fatal("pledge");
295 
296 	main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0);
297 	main_imsg_compose_resolver(IMSG_STARTUP, 0, NULL, 0);
298 
299 	event_dispatch();
300 
301 	main_shutdown();
302 	return (0);
303 }
304 
305 __dead void
306 main_shutdown(void)
307 {
308 	pid_t	 pid;
309 	int	 status;
310 
311 	/* Close pipes. */
312 	msgbuf_clear(&iev_frontend->ibuf.w);
313 	close(iev_frontend->ibuf.fd);
314 	msgbuf_clear(&iev_resolver->ibuf.w);
315 	close(iev_resolver->ibuf.fd);
316 
317 	config_clear(main_conf);
318 
319 	log_debug("waiting for children to terminate");
320 	do {
321 		pid = wait(&status);
322 		if (pid == -1) {
323 			if (errno != EINTR && errno != ECHILD)
324 				fatal("wait");
325 		} else if (WIFSIGNALED(status))
326 			log_warnx("%s terminated; signal %d",
327 			    (pid == resolver_pid) ? "resolver" :
328 			    "frontend", WTERMSIG(status));
329 	} while (pid != -1 || (pid == -1 && errno == EINTR));
330 
331 	free(iev_frontend);
332 	free(iev_resolver);
333 
334 	log_info("terminating");
335 	exit(0);
336 }
337 
338 static pid_t
339 start_child(int p, char *argv0, int fd, int debug, int verbose)
340 {
341 	char	*argv[7];
342 	int	 argc = 0;
343 	pid_t	 pid;
344 
345 	switch (pid = fork()) {
346 	case -1:
347 		fatal("cannot fork");
348 	case 0:
349 		break;
350 	default:
351 		close(fd);
352 		return (pid);
353 	}
354 
355 	if (fd != 3) {
356 		if (dup2(fd, 3) == -1)
357 			fatal("cannot setup imsg fd");
358 	} else if (fcntl(fd, F_SETFD, 0) == -1)
359 		fatal("cannot setup imsg fd");
360 
361 	argv[argc++] = argv0;
362 	switch (p) {
363 	case PROC_MAIN:
364 		fatalx("Can not start main process");
365 	case PROC_RESOLVER:
366 		argv[argc++] = "-E";
367 		break;
368 	case PROC_FRONTEND:
369 		argv[argc++] = "-F";
370 		break;
371 	}
372 	if (debug)
373 		argv[argc++] = "-d";
374 	if (verbose & OPT_VERBOSE)
375 		argv[argc++] = "-v";
376 	if (verbose & OPT_VERBOSE2)
377 		argv[argc++] = "-v";
378 	if (verbose & OPT_VERBOSE3)
379 		argv[argc++] = "-v";
380 	argv[argc++] = NULL;
381 
382 	execvp(argv0, argv);
383 	fatal("execvp");
384 }
385 
386 void
387 main_dispatch_frontend(int fd, short event, void *bula)
388 {
389 	struct imsgev	*iev = bula;
390 	struct imsgbuf	*ibuf;
391 	struct imsg	 imsg;
392 	ssize_t		 n;
393 	int		 shut = 0, verbose;
394 
395 	ibuf = &iev->ibuf;
396 
397 	if (event & EV_READ) {
398 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
399 			fatal("imsg_read error");
400 		if (n == 0)	/* Connection closed. */
401 			shut = 1;
402 	}
403 	if (event & EV_WRITE) {
404 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
405 			fatal("msgbuf_write");
406 		if (n == 0)	/* Connection closed. */
407 			shut = 1;
408 	}
409 
410 	for (;;) {
411 		if ((n = imsg_get(ibuf, &imsg)) == -1)
412 			fatal("imsg_get");
413 		if (n == 0)	/* No more messages. */
414 			break;
415 
416 		switch (imsg.hdr.type) {
417 		case IMSG_STARTUP_DONE:
418 			solicit_dns_proposals();
419 			break;
420 		case IMSG_CTL_RELOAD:
421 			if (main_reload() == -1)
422 				log_warnx("configuration reload failed");
423 			else
424 				log_warnx("configuration reloaded");
425 			break;
426 		case IMSG_CTL_LOG_VERBOSE:
427 			if (IMSG_DATA_SIZE(imsg) != sizeof(verbose))
428 				fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
429 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
430 			memcpy(&verbose, imsg.data, sizeof(verbose));
431 			log_setverbose(verbose);
432 			break;
433 		default:
434 			log_debug("%s: error handling imsg %d", __func__,
435 			    imsg.hdr.type);
436 			break;
437 		}
438 		imsg_free(&imsg);
439 	}
440 	if (!shut)
441 		imsg_event_add(iev);
442 	else {
443 		/* This pipe is dead. Remove its event handler */
444 		event_del(&iev->ev);
445 		event_loopexit(NULL);
446 	}
447 }
448 
449 void
450 main_dispatch_resolver(int fd, short event, void *bula)
451 {
452 	struct imsgev		*iev = bula;
453 	struct imsgbuf		*ibuf;
454 	struct imsg		 imsg;
455 	ssize_t			 n;
456 	int			 shut = 0;
457 
458 	ibuf = &iev->ibuf;
459 
460 	if (event & EV_READ) {
461 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
462 			fatal("imsg_read error");
463 		if (n == 0)	/* Connection closed. */
464 			shut = 1;
465 	}
466 	if (event & EV_WRITE) {
467 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
468 			fatal("msgbuf_write");
469 		if (n == 0)	/* Connection closed. */
470 			shut = 1;
471 	}
472 
473 	for (;;) {
474 		if ((n = imsg_get(ibuf, &imsg)) == -1)
475 			fatal("imsg_get");
476 		if (n == 0)	/* No more messages. */
477 			break;
478 
479 		switch (imsg.hdr.type) {
480 		default:
481 			log_debug("%s: error handling imsg %d", __func__,
482 			    imsg.hdr.type);
483 			break;
484 		}
485 		imsg_free(&imsg);
486 	}
487 	if (!shut)
488 		imsg_event_add(iev);
489 	else {
490 		/* This pipe is dead. Remove its event handler. */
491 		event_del(&iev->ev);
492 		event_loopexit(NULL);
493 	}
494 }
495 
496 void
497 main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen)
498 {
499 	if (iev_frontend)
500 		imsg_compose_event(iev_frontend, type, 0, pid, -1, data,
501 		    datalen);
502 }
503 
504 void
505 main_imsg_compose_frontend_fd(int type, pid_t pid, int fd)
506 {
507 	if (iev_frontend)
508 		imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0);
509 }
510 
511 void
512 main_imsg_compose_resolver(int type, pid_t pid, void *data, uint16_t datalen)
513 {
514 	if (iev_resolver)
515 		imsg_compose_event(iev_resolver, type, 0, pid, -1, data,
516 		    datalen);
517 }
518 
519 void
520 imsg_event_add(struct imsgev *iev)
521 {
522 	iev->events = EV_READ;
523 	if (iev->ibuf.w.queued)
524 		iev->events |= EV_WRITE;
525 
526 	event_del(&iev->ev);
527 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
528 	event_add(&iev->ev, NULL);
529 }
530 
531 int
532 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
533     pid_t pid, int fd, void *data, uint16_t datalen)
534 {
535 	int	ret;
536 
537 	if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data,
538 	    datalen)) != -1)
539 		imsg_event_add(iev);
540 
541 	return (ret);
542 }
543 
544 static int
545 main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf,
546     struct imsgbuf *resolver_buf)
547 {
548 	int pipe_frontend2resolver[2];
549 
550 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
551 	    PF_UNSPEC, pipe_frontend2resolver) == -1)
552 		return (-1);
553 
554 	if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC_RESOLVER, 0, 0,
555 	    pipe_frontend2resolver[0], NULL, 0) == -1)
556 		return (-1);
557 	if (imsg_compose(resolver_buf, IMSG_SOCKET_IPC_FRONTEND, 0, 0,
558 	    pipe_frontend2resolver[1], NULL, 0) == -1)
559 		return (-1);
560 
561 	return (0);
562 }
563 
564 int
565 main_reload(void)
566 {
567 	struct uw_conf	*xconf;
568 
569 	if ((xconf = parse_config(conffile)) == NULL)
570 		return (-1);
571 
572 	if (main_imsg_send_config(xconf) == -1)
573 		return (-1);
574 
575 	merge_config(main_conf, xconf);
576 
577 	if (main_conf->blocklist_file != NULL)
578 		send_blocklist_fd();
579 
580 	return (0);
581 }
582 
583 int
584 main_imsg_send_config(struct uw_conf *xconf)
585 {
586 	struct uw_forwarder		*uw_forwarder;
587 	struct force_tree_entry	*force_entry;
588 
589 	/* Send fixed part of config to children. */
590 	if (main_sendall(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
591 		return (-1);
592 
593 	if (xconf->blocklist_file != NULL) {
594 		if (main_sendall(IMSG_RECONF_BLOCKLIST_FILE,
595 		    xconf->blocklist_file, strlen(xconf->blocklist_file) + 1)
596 		    == -1)
597 			return (-1);
598 	}
599 
600 	/* send static forwarders to children */
601 	TAILQ_FOREACH(uw_forwarder, &xconf->uw_forwarder_list, entry) {
602 		if (main_sendall(IMSG_RECONF_FORWARDER, uw_forwarder,
603 		    sizeof(*uw_forwarder)) == -1)
604 			return (-1);
605 	}
606 
607 	/* send static DoT forwarders to children */
608 	TAILQ_FOREACH(uw_forwarder, &xconf->uw_dot_forwarder_list,
609 	    entry) {
610 		if (main_sendall(IMSG_RECONF_DOT_FORWARDER, uw_forwarder,
611 		    sizeof(*uw_forwarder)) == -1)
612 			return (-1);
613 	}
614 	RB_FOREACH(force_entry, force_tree, &xconf->force) {
615 		if (main_sendall(IMSG_RECONF_FORCE, force_entry,
616 		    sizeof(*force_entry)) == -1)
617 			return (-1);
618 	}
619 
620 	/* Tell children the revised config is now complete. */
621 	if (main_sendall(IMSG_RECONF_END, NULL, 0) == -1)
622 		return (-1);
623 
624 	return (0);
625 }
626 
627 int
628 main_sendall(enum imsg_type type, void *buf, uint16_t len)
629 {
630 	if (imsg_compose_event(iev_frontend, type, 0, 0, -1, buf, len) == -1)
631 		return (-1);
632 	if (imsg_compose_event(iev_resolver, type, 0, 0, -1, buf, len) == -1)
633 		return (-1);
634 	return (0);
635 }
636 
637 void
638 merge_config(struct uw_conf *conf, struct uw_conf *xconf)
639 {
640 	struct uw_forwarder		*uw_forwarder;
641 	struct force_tree_entry	*n, *nxt;
642 
643 	/* Remove & discard existing forwarders. */
644 	while ((uw_forwarder = TAILQ_FIRST(&conf->uw_forwarder_list)) !=
645 	    NULL) {
646 		TAILQ_REMOVE(&conf->uw_forwarder_list, uw_forwarder, entry);
647 		free(uw_forwarder);
648 	}
649 	while ((uw_forwarder = TAILQ_FIRST(&conf->uw_dot_forwarder_list)) !=
650 	    NULL) {
651 		TAILQ_REMOVE(&conf->uw_dot_forwarder_list, uw_forwarder, entry);
652 		free(uw_forwarder);
653 	}
654 
655 	/* Remove & discard existing force tree. */
656 	for (n = RB_MIN(force_tree, &conf->force); n != NULL; n = nxt) {
657 		nxt = RB_NEXT(force_tree, &conf->force, n);
658 		RB_REMOVE(force_tree, &conf->force, n);
659 		free(n);
660 	}
661 
662 	memcpy(&conf->res_pref, &xconf->res_pref,
663 	    sizeof(conf->res_pref));
664 
665 	free(conf->blocklist_file);
666 	conf->blocklist_file = xconf->blocklist_file;
667 	conf->blocklist_log = xconf->blocklist_log;
668 
669 	/* Add new forwarders. */
670 	TAILQ_CONCAT(&conf->uw_forwarder_list, &xconf->uw_forwarder_list,
671 	    entry);
672 	TAILQ_CONCAT(&conf->uw_dot_forwarder_list,
673 	    &xconf->uw_dot_forwarder_list, entry);
674 
675 	for (n = RB_MIN(force_tree, &xconf->force); n != NULL; n = nxt) {
676 		nxt = RB_NEXT(force_tree, &xconf->force, n);
677 		RB_REMOVE(force_tree, &xconf->force, n);
678 		RB_INSERT(force_tree, &conf->force, n);
679 	}
680 
681 	free(xconf);
682 }
683 
684 struct uw_conf *
685 config_new_empty(void)
686 {
687 	static enum uw_resolver_type	 default_res_pref[] = {
688 	    UW_RES_DOT,
689 	    UW_RES_ODOT_FORWARDER,
690 	    UW_RES_FORWARDER,
691 	    UW_RES_RECURSOR,
692 	    UW_RES_ODOT_DHCP,
693 	    UW_RES_DHCP,
694 	    UW_RES_ASR};
695 	struct uw_conf			*xconf;
696 
697 	xconf = calloc(1, sizeof(*xconf));
698 	if (xconf == NULL)
699 		fatal(NULL);
700 
701 	memcpy(&xconf->res_pref.types, &default_res_pref,
702 	    sizeof(default_res_pref));
703 	xconf->res_pref.len = nitems(default_res_pref);
704 
705 	TAILQ_INIT(&xconf->uw_forwarder_list);
706 	TAILQ_INIT(&xconf->uw_dot_forwarder_list);
707 
708 	RB_INIT(&xconf->force);
709 
710 	return (xconf);
711 }
712 
713 void
714 config_clear(struct uw_conf *conf)
715 {
716 	struct uw_conf	*xconf;
717 
718 	/* Merge current config with an empty config. */
719 	xconf = config_new_empty();
720 	merge_config(conf, xconf);
721 
722 	free(conf);
723 }
724 
725 void
726 open_ports(void)
727 {
728 	struct addrinfo	 hints, *res0;
729 	int		 udp4sock = -1, udp6sock = -1, error;
730 	int		 opt = 1;
731 
732 	memset(&hints, 0, sizeof(hints));
733 	hints.ai_family = AF_INET;
734 	hints.ai_socktype = SOCK_DGRAM;
735 	hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
736 
737 	error = getaddrinfo("127.0.0.1", "domain", &hints, &res0);
738 	if (!error && res0) {
739 		if ((udp4sock = socket(res0->ai_family, res0->ai_socktype,
740 		    res0->ai_protocol)) != -1) {
741 			if (setsockopt(udp4sock, SOL_SOCKET, SO_REUSEADDR,
742 			    &opt, sizeof(opt)) == -1)
743 				log_warn("setting SO_REUSEADDR on socket");
744 			if (bind(udp4sock, res0->ai_addr, res0->ai_addrlen)
745 			    == -1) {
746 				close(udp4sock);
747 				udp4sock = -1;
748 			}
749 		}
750 	}
751 	if (res0)
752 		freeaddrinfo(res0);
753 
754 	hints.ai_family = AF_INET6;
755 	error = getaddrinfo("::1", "domain", &hints, &res0);
756 	if (!error && res0) {
757 		if ((udp6sock = socket(res0->ai_family, res0->ai_socktype,
758 		    res0->ai_protocol)) != -1) {
759 			if (setsockopt(udp6sock, SOL_SOCKET, SO_REUSEADDR,
760 			    &opt, sizeof(opt)) == -1)
761 				log_warn("setting SO_REUSEADDR on socket");
762 			if (bind(udp6sock, res0->ai_addr, res0->ai_addrlen)
763 			    == -1) {
764 				close(udp6sock);
765 				udp6sock = -1;
766 			}
767 		}
768 	}
769 	if (res0)
770 		freeaddrinfo(res0);
771 
772 	if (udp4sock == -1 && udp6sock == -1)
773 		fatal("could not bind to 127.0.0.1 or ::1 on port 53");
774 
775 	if (udp4sock != -1)
776 		main_imsg_compose_frontend_fd(IMSG_UDP4SOCK, 0, udp4sock);
777 	if (udp6sock != -1)
778 		main_imsg_compose_frontend_fd(IMSG_UDP6SOCK, 0, udp6sock);
779 }
780 
781 void
782 solicit_dns_proposals(void)
783 {
784 	struct rt_msghdr		 rtm;
785 	struct iovec			 iov[1];
786 	int				 iovcnt = 0;
787 
788 	memset(&rtm, 0, sizeof(rtm));
789 
790 	rtm.rtm_version = RTM_VERSION;
791 	rtm.rtm_type = RTM_PROPOSAL;
792 	rtm.rtm_msglen = sizeof(rtm);
793 	rtm.rtm_tableid = 0;
794 	rtm.rtm_index = 0;
795 	rtm.rtm_seq = arc4random();
796 	rtm.rtm_priority = RTP_PROPOSAL_SOLICIT;
797 
798 	iov[iovcnt].iov_base = &rtm;
799 	iov[iovcnt++].iov_len = sizeof(rtm);
800 
801 	if (writev(routesock, iov, iovcnt) == -1)
802 		log_warn("failed to send solicitation");
803 }
804 
805 void
806 send_blocklist_fd(void)
807 {
808 	int	bl_fd;
809 
810 	if ((bl_fd = open(main_conf->blocklist_file, O_RDONLY)) != -1)
811 		main_imsg_compose_frontend_fd(IMSG_BLFD, 0, bl_fd);
812 	else
813 		log_warn("%s", main_conf->blocklist_file);
814 }
815 
816 void
817 imsg_receive_config(struct imsg *imsg, struct uw_conf **xconf)
818 {
819 	struct uw_conf			*nconf;
820 	struct uw_forwarder		*uw_forwarder;
821 	struct force_tree_entry	*force_entry;
822 
823 	nconf = *xconf;
824 
825 	switch (imsg->hdr.type) {
826 	case IMSG_RECONF_CONF:
827 		if (nconf != NULL)
828 			fatalx("%s: IMSG_RECONF_CONF already in "
829 			    "progress", __func__);
830 		if (IMSG_DATA_SIZE(*imsg) != sizeof(struct uw_conf))
831 			fatalx("%s: IMSG_RECONF_CONF wrong length: %lu",
832 			    __func__, IMSG_DATA_SIZE(*imsg));
833 		if ((*xconf = malloc(sizeof(struct uw_conf))) == NULL)
834 			fatal(NULL);
835 		nconf = *xconf;
836 		memcpy(nconf, imsg->data, sizeof(struct uw_conf));
837 		TAILQ_INIT(&nconf->uw_forwarder_list);
838 		TAILQ_INIT(&nconf->uw_dot_forwarder_list);
839 		RB_INIT(&nconf->force);
840 		break;
841 	case IMSG_RECONF_BLOCKLIST_FILE:
842 		/* make sure this is a string */
843 		((char *)imsg->data)[IMSG_DATA_SIZE(*imsg) - 1] = '\0';
844 		if ((nconf->blocklist_file = strdup(imsg->data)) ==
845 		    NULL)
846 			fatal("%s: strdup", __func__);
847 		break;
848 	case IMSG_RECONF_FORWARDER:
849 		if (IMSG_DATA_SIZE(*imsg) != sizeof(struct uw_forwarder))
850 			fatalx("%s: IMSG_RECONF_FORWARDER wrong length:"
851 			    " %lu", __func__, IMSG_DATA_SIZE(*imsg));
852 		if ((uw_forwarder = malloc(sizeof(struct
853 		    uw_forwarder))) == NULL)
854 			fatal(NULL);
855 		memcpy(uw_forwarder, imsg->data, sizeof(struct
856 		    uw_forwarder));
857 		TAILQ_INSERT_TAIL(&nconf->uw_forwarder_list,
858 		    uw_forwarder, entry);
859 		break;
860 	case IMSG_RECONF_DOT_FORWARDER:
861 		if (IMSG_DATA_SIZE(*imsg) != sizeof(struct uw_forwarder))
862 			fatalx("%s: IMSG_RECONF_DOT_FORWARDER wrong "
863 			    "length: %lu", __func__,
864 			    IMSG_DATA_SIZE(*imsg));
865 		if ((uw_forwarder = malloc(sizeof(struct
866 		    uw_forwarder))) == NULL)
867 			fatal(NULL);
868 		memcpy(uw_forwarder, imsg->data, sizeof(struct
869 		    uw_forwarder));
870 		TAILQ_INSERT_TAIL(&nconf->uw_dot_forwarder_list,
871 		    uw_forwarder, entry);
872 		break;
873 	case IMSG_RECONF_FORCE:
874 		if (IMSG_DATA_SIZE(*imsg) != sizeof(struct force_tree_entry))
875 			fatalx("%s: IMSG_RECONF_FORCE wrong "
876 			    "length: %lu", __func__,
877 			    IMSG_DATA_SIZE(*imsg));
878 		if ((force_entry = malloc(sizeof(struct
879 		    force_tree_entry))) == NULL)
880 			fatal(NULL);
881 		memcpy(force_entry, imsg->data, sizeof(struct
882 		    force_tree_entry));
883 		RB_INSERT(force_tree, &nconf->force, force_entry);
884 		break;
885 	default:
886 		log_debug("%s: error handling imsg %d", __func__,
887 		    imsg->hdr.type);
888 		break;
889 	}
890 }
891