xref: /openbsd-src/usr.sbin/rad/rad.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: rad.c,v 1.24 2020/12/01 17:31:37 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/syslog.h>
25 #include <sys/uio.h>
26 #include <sys/wait.h>
27 
28 #include <netinet/in.h>
29 #include <net/if.h>
30 #include <net/route.h>
31 #include <netinet/in.h>
32 #include <netinet/if_ether.h>
33 #include <netinet6/in6_var.h>
34 #include <netinet/icmp6.h>
35 
36 #include <err.h>
37 #include <errno.h>
38 #include <event.h>
39 #include <fcntl.h>
40 #include <imsg.h>
41 #include <netdb.h>
42 #include <pwd.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <signal.h>
47 #include <unistd.h>
48 
49 #include "log.h"
50 #include "rad.h"
51 #include "frontend.h"
52 #include "engine.h"
53 #include "control.h"
54 
55 __dead void	usage(void);
56 __dead void	main_shutdown(void);
57 
58 void	main_sig_handler(int, short, void *);
59 
60 static pid_t	start_child(int, char *, int, int, int);
61 
62 void	main_dispatch_frontend(int, short, void *);
63 void	main_dispatch_engine(int, short, void *);
64 void	open_icmp6sock(int);
65 
66 static int	main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *);
67 static int	main_imsg_send_config(struct rad_conf *);
68 
69 int	main_reload(void);
70 int	main_sendboth(enum imsg_type, void *, uint16_t);
71 
72 void	in6_prefixlen2mask(struct in6_addr *, int len);
73 
74 struct rad_conf	*main_conf;
75 struct imsgev		*iev_frontend;
76 struct imsgev		*iev_engine;
77 char			*conffile;
78 
79 pid_t	 frontend_pid;
80 pid_t	 engine_pid;
81 
82 uint32_t cmd_opts;
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;
123 	int			 debug = 0, engine_flag = 0, frontend_flag = 0;
124 	char			*saved_argv0;
125 	int			 pipe_main2frontend[2];
126 	int			 pipe_main2engine[2];
127 	int			 frontend_routesock, rtfilter;
128 	int			 rtable_any = RTABLE_ANY;
129 	int			 control_fd;
130 	char			*csock;
131 
132 	conffile = CONF_FILE;
133 	csock = RAD_SOCKET;
134 
135 	log_init(1, LOG_DAEMON);	/* Log to stderr until daemonized. */
136 	log_setverbose(1);
137 
138 	saved_argv0 = argv[0];
139 	if (saved_argv0 == NULL)
140 		saved_argv0 = "rad";
141 
142 	while ((ch = getopt(argc, argv, "dEFf:ns:v")) != -1) {
143 		switch (ch) {
144 		case 'd':
145 			debug = 1;
146 			break;
147 		case 'E':
148 			engine_flag = 1;
149 			break;
150 		case 'F':
151 			frontend_flag = 1;
152 			break;
153 		case 'f':
154 			conffile = optarg;
155 			break;
156 		case 'n':
157 			cmd_opts |= OPT_NOACTION;
158 			break;
159 		case 's':
160 			csock = optarg;
161 			break;
162 		case 'v':
163 			if (cmd_opts & OPT_VERBOSE)
164 				cmd_opts |= OPT_VERBOSE2;
165 			cmd_opts |= OPT_VERBOSE;
166 			break;
167 		default:
168 			usage();
169 		}
170 	}
171 
172 	argc -= optind;
173 	argv += optind;
174 	if (argc > 0 || (engine_flag && frontend_flag))
175 		usage();
176 
177 	if (engine_flag)
178 		engine(debug, cmd_opts & OPT_VERBOSE);
179 	else if (frontend_flag)
180 		frontend(debug, cmd_opts & OPT_VERBOSE);
181 
182 	/* parse config file */
183 	if ((main_conf = parse_config(conffile)) == NULL) {
184 		exit(1);
185 	}
186 
187 	if (cmd_opts & OPT_NOACTION) {
188 		if (cmd_opts & OPT_VERBOSE)
189 			print_config(main_conf);
190 		else
191 			fprintf(stderr, "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(RAD_USER) == NULL)
201 		errx(1, "unknown user %s", RAD_USER);
202 
203 	log_init(debug, LOG_DAEMON);
204 	log_setverbose(cmd_opts & OPT_VERBOSE);
205 
206 	if (!debug)
207 		daemon(1, 0);
208 
209 	log_info("startup");
210 
211 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
212 	    PF_UNSPEC, pipe_main2frontend) == -1)
213 		fatal("main2frontend socketpair");
214 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
215 	    PF_UNSPEC, pipe_main2engine) == -1)
216 		fatal("main2engine socketpair");
217 
218 	/* Start children. */
219 	engine_pid = start_child(PROC_ENGINE, saved_argv0, pipe_main2engine[1],
220 	    debug, cmd_opts & OPT_VERBOSE);
221 	frontend_pid = start_child(PROC_FRONTEND, saved_argv0,
222 	    pipe_main2frontend[1], debug, cmd_opts & OPT_VERBOSE);
223 
224 	rad_process = PROC_MAIN;
225 	log_procinit(log_procnames[rad_process]);
226 
227 	event_init();
228 
229 	/* Setup signal handler. */
230 	signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
231 	signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
232 	signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL);
233 	signal_add(&ev_sigint, NULL);
234 	signal_add(&ev_sigterm, NULL);
235 	signal_add(&ev_sighup, NULL);
236 	signal(SIGPIPE, SIG_IGN);
237 
238 	/* Setup pipes to children. */
239 
240 	if ((iev_frontend = malloc(sizeof(struct imsgev))) == NULL ||
241 	    (iev_engine = malloc(sizeof(struct imsgev))) == NULL)
242 		fatal(NULL);
243 	imsg_init(&iev_frontend->ibuf, pipe_main2frontend[0]);
244 	iev_frontend->handler = main_dispatch_frontend;
245 	imsg_init(&iev_engine->ibuf, pipe_main2engine[0]);
246 	iev_engine->handler = main_dispatch_engine;
247 
248 	/* Setup event handlers for pipes to engine & frontend. */
249 	iev_frontend->events = EV_READ;
250 	event_set(&iev_frontend->ev, iev_frontend->ibuf.fd,
251 	    iev_frontend->events, iev_frontend->handler, iev_frontend);
252 	event_add(&iev_frontend->ev, NULL);
253 
254 	iev_engine->events = EV_READ;
255 	event_set(&iev_engine->ev, iev_engine->ibuf.fd, iev_engine->events,
256 	    iev_engine->handler, iev_engine);
257 	event_add(&iev_engine->ev, NULL);
258 
259 	if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, &iev_engine->ibuf))
260 		fatal("could not establish imsg links");
261 
262 	if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC,
263 	    AF_INET6)) == -1)
264 		fatal("route socket");
265 
266 	rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) |
267 	    ROUTE_FILTER(RTM_DELADDR) | ROUTE_FILTER(RTM_CHGADDRATTR);
268 	if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_MSGFILTER,
269 	    &rtfilter, sizeof(rtfilter)) == -1)
270 		fatal("setsockopt(ROUTE_MSGFILTER)");
271 	if (setsockopt(frontend_routesock, AF_ROUTE, ROUTE_TABLEFILTER,
272 	    &rtable_any, sizeof(rtable_any)) == -1)
273 		fatal("setsockopt(ROUTE_TABLEFILTER)");
274 
275 	if ((control_fd = control_init(csock)) == -1)
276 		fatalx("control socket setup failed");
277 
278 	main_imsg_compose_frontend(IMSG_ROUTESOCK, frontend_routesock,
279 	    NULL, 0);
280 	main_imsg_compose_frontend(IMSG_CONTROLFD, control_fd, NULL, 0);
281 	main_imsg_send_config(main_conf);
282 
283 	if (pledge("stdio inet rpath sendfd mcast wroute", NULL) == -1)
284 		fatal("pledge");
285 
286 	main_imsg_compose_frontend(IMSG_STARTUP, -1, NULL, 0);
287 
288 	event_dispatch();
289 
290 	main_shutdown();
291 	return (0);
292 }
293 
294 __dead void
295 main_shutdown(void)
296 {
297 	pid_t	 pid;
298 	int	 status;
299 
300 	/* Close pipes. */
301 	msgbuf_clear(&iev_frontend->ibuf.w);
302 	close(iev_frontend->ibuf.fd);
303 	msgbuf_clear(&iev_engine->ibuf.w);
304 	close(iev_engine->ibuf.fd);
305 
306 	config_clear(main_conf);
307 
308 	log_debug("waiting for children to terminate");
309 	do {
310 		pid = wait(&status);
311 		if (pid == -1) {
312 			if (errno != EINTR && errno != ECHILD)
313 				fatal("wait");
314 		} else if (WIFSIGNALED(status))
315 			log_warnx("%s terminated; signal %d",
316 			    (pid == engine_pid) ? "engine" :
317 			    "frontend", WTERMSIG(status));
318 	} while (pid != -1 || (pid == -1 && errno == EINTR));
319 
320 	free(iev_frontend);
321 	free(iev_engine);
322 
323 	log_info("terminating");
324 	exit(0);
325 }
326 
327 static pid_t
328 start_child(int p, char *argv0, int fd, int debug, int verbose)
329 {
330 	char	*argv[6];
331 	int	 argc = 0;
332 	pid_t	 pid;
333 
334 	switch (pid = fork()) {
335 	case -1:
336 		fatal("cannot fork");
337 	case 0:
338 		break;
339 	default:
340 		close(fd);
341 		return (pid);
342 	}
343 
344 	if (fd != 3) {
345 		if (dup2(fd, 3) == -1)
346 			fatal("cannot setup imsg fd");
347 	} else if (fcntl(fd, F_SETFD, 0) == -1)
348 		fatal("cannot setup imsg fd");
349 
350 	argv[argc++] = argv0;
351 	switch (p) {
352 	case PROC_MAIN:
353 		fatalx("Can not start main process");
354 	case PROC_ENGINE:
355 		argv[argc++] = "-E";
356 		break;
357 	case PROC_FRONTEND:
358 		argv[argc++] = "-F";
359 		break;
360 	}
361 	if (debug)
362 		argv[argc++] = "-d";
363 	if (verbose)
364 		argv[argc++] = "-v";
365 	argv[argc++] = NULL;
366 
367 	execvp(argv0, argv);
368 	fatal("execvp");
369 }
370 
371 void
372 main_dispatch_frontend(int fd, short event, void *bula)
373 {
374 	struct imsgev		*iev = bula;
375 	struct imsgbuf		*ibuf;
376 	struct imsg		 imsg;
377 	ssize_t			 n;
378 	int			 shut = 0, verbose;
379 	int			 rdomain;
380 
381 	ibuf = &iev->ibuf;
382 
383 	if (event & EV_READ) {
384 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
385 			fatal("imsg_read error");
386 		if (n == 0)	/* Connection closed. */
387 			shut = 1;
388 	}
389 	if (event & EV_WRITE) {
390 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
391 			fatal("msgbuf_write");
392 		if (n == 0)	/* Connection closed. */
393 			shut = 1;
394 	}
395 
396 	for (;;) {
397 		if ((n = imsg_get(ibuf, &imsg)) == -1)
398 			fatal("imsg_get");
399 		if (n == 0)	/* No more messages. */
400 			break;
401 
402 		switch (imsg.hdr.type) {
403 		case IMSG_OPEN_ICMP6SOCK:
404 			log_debug("IMSG_OPEN_ICMP6SOCK");
405 			if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain))
406 				fatalx("%s: IMSG_OPEN_ICMP6SOCK wrong length: "
407 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
408 			memcpy(&rdomain, imsg.data, sizeof(rdomain));
409 			open_icmp6sock(rdomain);
410 			break;
411 		case IMSG_CTL_RELOAD:
412 			if (main_reload() == -1)
413 				log_warnx("configuration reload failed");
414 			else
415 				log_warnx("configuration reloaded");
416 			break;
417 		case IMSG_CTL_LOG_VERBOSE:
418 			if (IMSG_DATA_SIZE(imsg) != sizeof(verbose))
419 				fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: "
420 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
421 			memcpy(&verbose, imsg.data, sizeof(verbose));
422 			log_setverbose(verbose);
423 			break;
424 		default:
425 			log_debug("%s: error handling imsg %d", __func__,
426 			    imsg.hdr.type);
427 			break;
428 		}
429 		imsg_free(&imsg);
430 	}
431 	if (!shut)
432 		imsg_event_add(iev);
433 	else {
434 		/* This pipe is dead. Remove its event handler */
435 		event_del(&iev->ev);
436 		event_loopexit(NULL);
437 	}
438 }
439 
440 void
441 main_dispatch_engine(int fd, short event, void *bula)
442 {
443 	struct imsgev	*iev = bula;
444 	struct imsgbuf  *ibuf;
445 	struct imsg	 imsg;
446 	ssize_t		 n;
447 	int		 shut = 0;
448 
449 	ibuf = &iev->ibuf;
450 
451 	if (event & EV_READ) {
452 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
453 			fatal("imsg_read error");
454 		if (n == 0)	/* Connection closed. */
455 			shut = 1;
456 	}
457 	if (event & EV_WRITE) {
458 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
459 			fatal("msgbuf_write");
460 		if (n == 0)	/* Connection closed. */
461 			shut = 1;
462 	}
463 
464 	for (;;) {
465 		if ((n = imsg_get(ibuf, &imsg)) == -1)
466 			fatal("imsg_get");
467 		if (n == 0)	/* No more messages. */
468 			break;
469 
470 		switch (imsg.hdr.type) {
471 		default:
472 			log_debug("%s: error handling imsg %d", __func__,
473 			    imsg.hdr.type);
474 			break;
475 		}
476 		imsg_free(&imsg);
477 	}
478 	if (!shut)
479 		imsg_event_add(iev);
480 	else {
481 		/* This pipe is dead. Remove its event handler. */
482 		event_del(&iev->ev);
483 		event_loopexit(NULL);
484 	}
485 }
486 
487 int
488 main_imsg_compose_frontend(int type, int fd, void *data, uint16_t datalen)
489 {
490 	if (iev_frontend)
491 		return (imsg_compose_event(iev_frontend, type, 0, 0, fd, data,
492 		    datalen));
493 	else
494 		return (-1);
495 }
496 
497 void
498 main_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen)
499 {
500 	if (iev_engine)
501 		imsg_compose_event(iev_engine, type, 0, pid, -1, data,
502 		    datalen);
503 }
504 
505 void
506 imsg_event_add(struct imsgev *iev)
507 {
508 	iev->events = EV_READ;
509 	if (iev->ibuf.w.queued)
510 		iev->events |= EV_WRITE;
511 
512 	event_del(&iev->ev);
513 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
514 	event_add(&iev->ev, NULL);
515 }
516 
517 int
518 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
519     pid_t pid, int fd, void *data, uint16_t datalen)
520 {
521 	int	ret;
522 
523 	if ((ret = imsg_compose(&iev->ibuf, type, peerid, pid, fd, data,
524 	    datalen)) != -1)
525 		imsg_event_add(iev);
526 
527 	return (ret);
528 }
529 
530 static int
531 main_imsg_send_ipc_sockets(struct imsgbuf *frontend_buf,
532     struct imsgbuf *engine_buf)
533 {
534 	int pipe_frontend2engine[2];
535 
536 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
537 	    PF_UNSPEC, pipe_frontend2engine) == -1)
538 		return (-1);
539 
540 	if (imsg_compose(frontend_buf, IMSG_SOCKET_IPC, 0, 0,
541 	    pipe_frontend2engine[0], NULL, 0) == -1)
542 		return (-1);
543 	if (imsg_compose(engine_buf, IMSG_SOCKET_IPC, 0, 0,
544 	    pipe_frontend2engine[1], NULL, 0) == -1)
545 		return (-1);
546 
547 	return (0);
548 }
549 
550 int
551 main_reload(void)
552 {
553 	struct rad_conf *xconf;
554 
555 	if ((xconf = parse_config(conffile)) == NULL)
556 		return (-1);
557 
558 	if (main_imsg_send_config(xconf) == -1)
559 		return (-1);
560 
561 	merge_config(main_conf, xconf);
562 
563 	return (0);
564 }
565 
566 int
567 main_imsg_send_config(struct rad_conf *xconf)
568 {
569 	struct ra_iface_conf	*ra_iface_conf;
570 	struct ra_prefix_conf	*ra_prefix_conf;
571 	struct ra_rdnss_conf	*ra_rdnss_conf;
572 	struct ra_dnssl_conf	*ra_dnssl_conf;
573 
574 	/* Send fixed part of config to children. */
575 	if (main_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
576 		return (-1);
577 
578 	/* send global dns options to children */
579 	SIMPLEQ_FOREACH(ra_rdnss_conf, &xconf->ra_options.ra_rdnss_list,
580 	    entry) {
581 		if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf,
582 		    sizeof(*ra_rdnss_conf)) == -1)
583 			return (-1);
584 	}
585 	SIMPLEQ_FOREACH(ra_dnssl_conf, &xconf->ra_options.ra_dnssl_list,
586 	    entry) {
587 		if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf,
588 		    sizeof(*ra_dnssl_conf)) == -1)
589 			return (-1);
590 	}
591 
592 	/* Send the interface list to children. */
593 	SIMPLEQ_FOREACH(ra_iface_conf, &xconf->ra_iface_list, entry) {
594 		if (main_sendboth(IMSG_RECONF_RA_IFACE, ra_iface_conf,
595 		    sizeof(*ra_iface_conf)) == -1)
596 			return (-1);
597 		if (ra_iface_conf->autoprefix) {
598 			if (main_sendboth(IMSG_RECONF_RA_AUTOPREFIX,
599 			    ra_iface_conf->autoprefix,
600 			    sizeof(*ra_iface_conf->autoprefix)) == -1)
601 				return (-1);
602 		}
603 		SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list,
604 		    entry) {
605 			if (main_sendboth(IMSG_RECONF_RA_PREFIX,
606 			    ra_prefix_conf, sizeof(*ra_prefix_conf)) == -1)
607 				return (-1);
608 		}
609 		SIMPLEQ_FOREACH(ra_rdnss_conf,
610 		    &ra_iface_conf->ra_options.ra_rdnss_list, entry) {
611 			if (main_sendboth(IMSG_RECONF_RA_RDNSS, ra_rdnss_conf,
612 			    sizeof(*ra_rdnss_conf)) == -1)
613 				return (-1);
614 		}
615 		SIMPLEQ_FOREACH(ra_dnssl_conf,
616 		    &ra_iface_conf->ra_options.ra_dnssl_list, entry) {
617 			if (main_sendboth(IMSG_RECONF_RA_DNSSL, ra_dnssl_conf,
618 			    sizeof(*ra_dnssl_conf)) == -1)
619 				return (-1);
620 		}
621 	}
622 
623 	/* Tell children the revised config is now complete. */
624 	if (main_sendboth(IMSG_RECONF_END, NULL, 0) == -1)
625 		return (-1);
626 
627 	return (0);
628 }
629 
630 int
631 main_sendboth(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_engine, type, 0, 0, -1, buf, len) == -1)
636 		return (-1);
637 	return (0);
638 }
639 
640 void
641 free_ra_iface_conf(struct ra_iface_conf *ra_iface_conf)
642 {
643 	struct ra_prefix_conf	*prefix;
644 
645 	if (!ra_iface_conf)
646 		return;
647 
648 	free(ra_iface_conf->autoprefix);
649 
650 	while ((prefix = SIMPLEQ_FIRST(&ra_iface_conf->ra_prefix_list)) !=
651 	    NULL) {
652 		SIMPLEQ_REMOVE_HEAD(&ra_iface_conf->ra_prefix_list, entry);
653 		free(prefix);
654 	}
655 
656 	free_dns_options(&ra_iface_conf->ra_options);
657 
658 	free(ra_iface_conf);
659 }
660 
661 void
662 free_dns_options(struct ra_options_conf *ra_options)
663 {
664 	struct ra_rdnss_conf	*ra_rdnss;
665 	struct ra_dnssl_conf	*ra_dnssl;
666 
667 	while ((ra_rdnss = SIMPLEQ_FIRST(&ra_options->ra_rdnss_list)) != NULL) {
668 		SIMPLEQ_REMOVE_HEAD(&ra_options->ra_rdnss_list, entry);
669 		free(ra_rdnss);
670 	}
671 	ra_options->rdnss_count = 0;
672 
673 	while ((ra_dnssl = SIMPLEQ_FIRST(&ra_options->ra_dnssl_list)) != NULL) {
674 		SIMPLEQ_REMOVE_HEAD(&ra_options->ra_dnssl_list, entry);
675 		free(ra_dnssl);
676 	}
677 	ra_options->dnssl_len = 0;
678 }
679 
680 void
681 merge_config(struct rad_conf *conf, struct rad_conf *xconf)
682 {
683 	struct ra_iface_conf	*ra_iface_conf;
684 
685 	/* Remove & discard existing interfaces. */
686 	while ((ra_iface_conf = SIMPLEQ_FIRST(&conf->ra_iface_list)) != NULL) {
687 		SIMPLEQ_REMOVE_HEAD(&conf->ra_iface_list, entry);
688 		free_ra_iface_conf(ra_iface_conf);
689 	}
690 	free_dns_options(&conf->ra_options);
691 
692 	conf->ra_options = xconf->ra_options;
693 	SIMPLEQ_INIT(&conf->ra_options.ra_rdnss_list);
694 	SIMPLEQ_INIT(&conf->ra_options.ra_dnssl_list);
695 
696 	/* Add new interfaces. */
697 	SIMPLEQ_CONCAT(&conf->ra_iface_list, &xconf->ra_iface_list);
698 
699 	/* Add dns options */
700 	SIMPLEQ_CONCAT(&conf->ra_options.ra_rdnss_list,
701 	    &xconf->ra_options.ra_rdnss_list);
702 	SIMPLEQ_CONCAT(&conf->ra_options.ra_dnssl_list,
703 	    &xconf->ra_options.ra_dnssl_list);
704 	free(xconf);
705 }
706 
707 struct rad_conf *
708 config_new_empty(void)
709 {
710 	struct rad_conf	*xconf;
711 
712 	xconf = calloc(1, sizeof(*xconf));
713 	if (xconf == NULL)
714 		fatal(NULL);
715 
716 	SIMPLEQ_INIT(&xconf->ra_iface_list);
717 
718 	xconf->ra_options.dfr = 1;
719 	xconf->ra_options.cur_hl = 0;
720 	xconf->ra_options.m_flag = 0;
721 	xconf->ra_options.o_flag = 0;
722 	xconf->ra_options.router_lifetime = ADV_DEFAULT_LIFETIME;
723 	xconf->ra_options.reachable_time = 0;
724 	xconf->ra_options.retrans_timer = 0;
725 	xconf->ra_options.mtu = 0;
726 	xconf->ra_options.rdns_lifetime = DEFAULT_RDNS_LIFETIME;
727 	SIMPLEQ_INIT(&xconf->ra_options.ra_rdnss_list);
728 	SIMPLEQ_INIT(&xconf->ra_options.ra_dnssl_list);
729 
730 	return (xconf);
731 }
732 
733 void
734 config_clear(struct rad_conf *conf)
735 {
736 	struct rad_conf	*xconf;
737 
738 	/* Merge current config with an empty config. */
739 	xconf = config_new_empty();
740 	merge_config(conf, xconf);
741 
742 	free(conf);
743 }
744 
745 void
746 mask_prefix(struct in6_addr* in6, int len)
747 {
748 	uint8_t	bitmask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
749 	int	i, skip;
750 
751 	if (len < 0 || len > 128)
752 		fatalx("invalid prefix length: %d", len);
753 
754 	skip = len / 8;
755 
756 	if (skip < 16)
757 		in6->s6_addr[skip] &= bitmask[len % 8];
758 
759 	for (i = skip + 1; i < 16; i++)
760 		in6->s6_addr[i] = 0;
761 }
762 
763 const char*
764 sin6_to_str(struct sockaddr_in6 *sin6)
765 {
766 	static char hbuf[NI_MAXHOST];
767 	int error;
768 
769 	error = getnameinfo((struct sockaddr *)sin6, sin6->sin6_len, hbuf,
770 	    sizeof(hbuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
771 	if (error) {
772 		log_warnx("%s", gai_strerror(error));
773 		strlcpy(hbuf, "unknown", sizeof(hbuf));
774 	}
775 	return hbuf;
776 }
777 
778 const char*
779 in6_to_str(struct in6_addr *in6)
780 {
781 
782 	struct sockaddr_in6	sin6;
783 
784 	memset(&sin6, 0, sizeof(sin6));
785 	sin6.sin6_len = sizeof(sin6);
786 	sin6.sin6_family = AF_INET6;
787 	sin6.sin6_addr = *in6;
788 
789 	return (sin6_to_str(&sin6));
790 }
791 
792 void
793 open_icmp6sock(int rdomain)
794 {
795 	int			 icmp6sock, on = 1, off = 0;
796 
797 	log_debug("%s: %d", __func__, rdomain);
798 
799 	if ((icmp6sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC,
800 	    IPPROTO_ICMPV6)) == -1)
801 		fatal("ICMPv6 socket");
802 
803 	if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
804 	    sizeof(on)) == -1)
805 		fatal("IPV6_RECVPKTINFO");
806 
807 	if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
808 	    sizeof(on)) == -1)
809 		fatal("IPV6_RECVHOPLIMIT");
810 
811 	if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off,
812 	    sizeof(off)) == -1)
813 		fatal("IPV6_RECVHOPLIMIT");
814 
815 	if (setsockopt(icmp6sock, SOL_SOCKET, SO_RTABLE, &rdomain,
816 	    sizeof(rdomain)) == -1) {
817 		/* we might race against removal of the rdomain */
818 		log_warn("setsockopt SO_RTABLE");
819 		close(icmp6sock);
820 		return;
821 	}
822 
823 	main_imsg_compose_frontend(IMSG_ICMP6SOCK, icmp6sock, &rdomain,
824 	    sizeof(rdomain));
825 }
826