xref: /openbsd-src/usr.sbin/rad/frontend.c (revision 3374c67d44f9b75b98444cbf63020f777792342e)
1 /*	$OpenBSD: frontend.c,v 1.42 2022/12/28 21:30:18 jmc 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 
22 /*
23  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
24  * All rights reserved.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions
28  * are met:
29  * 1. Redistributions of source code must retain the above copyright
30  *    notice, this list of conditions and the following disclaimer.
31  * 2. Redistributions in binary form must reproduce the above copyright
32  *    notice, this list of conditions and the following disclaimer in the
33  *    documentation and/or other materials provided with the distribution.
34  * 3. Neither the name of the project nor the names of its contributors
35  *    may be used to endorse or promote products derived from this software
36  *    without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
39  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
42  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  */
50 
51 #include <sys/types.h>
52 #include <sys/ioctl.h>
53 #include <sys/queue.h>
54 #include <sys/socket.h>
55 #include <sys/syslog.h>
56 #include <sys/uio.h>
57 
58 #include <net/if.h>
59 #include <net/if_types.h>
60 #include <net/route.h>
61 
62 #include <arpa/inet.h>
63 
64 #include <netinet/in.h>
65 #include <netinet/if_ether.h>
66 #include <netinet6/nd6.h>
67 #include <netinet6/in6_var.h>
68 #include <netinet/ip6.h>
69 #include <netinet6/ip6_var.h>
70 #include <netinet/icmp6.h>
71 
72 #include <ctype.h>
73 #include <errno.h>
74 #include <event.h>
75 #include <ifaddrs.h>
76 #include <imsg.h>
77 #include <pwd.h>
78 #include <signal.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <unistd.h>
83 
84 #include "log.h"
85 #include "rad.h"
86 #include "frontend.h"
87 #include "control.h"
88 
89 #define	RA_MAX_SIZE		1500
90 #define	ROUTE_SOCKET_BUF_SIZE	16384
91 
92 struct icmp6_ev {
93 	struct event		 ev;
94 	uint8_t			 answer[1500];
95 	struct msghdr		 rcvmhdr;
96 	struct iovec		 rcviov[1];
97 	struct sockaddr_in6	 from;
98 	int			 refcnt;
99 };
100 
101 struct ra_iface {
102 	TAILQ_ENTRY(ra_iface)		 entry;
103 	struct icmp6_ev			*icmp6ev;
104 	struct ra_prefix_conf_head	 prefixes;
105 	char				 name[IF_NAMESIZE];
106 	char				 conf_name[IF_NAMESIZE];
107 	uint32_t			 if_index;
108 	int				 rdomain;
109 	int				 removed;
110 	int				 link_state;
111 	int				 prefix_count;
112 	size_t				 datalen;
113 	uint8_t				 data[RA_MAX_SIZE];
114 };
115 
116 #define ND_OPT_PREF64	38
117 struct nd_opt_pref64 {
118 	u_int8_t	nd_opt_pref64_type;
119 	u_int8_t	nd_opt_pref64_len;
120 	u_int16_t	nd_opt_pref64_sltime_plc;
121 	u_int8_t	nd_opt_pref64[12];
122 };
123 
124 TAILQ_HEAD(, ra_iface)	ra_interfaces;
125 
126 __dead void		 frontend_shutdown(void);
127 void			 frontend_sig_handler(int, short, void *);
128 void			 frontend_startup(void);
129 void			 icmp6_receive(int, short, void *);
130 void			 join_all_routers_mcast_group(struct ra_iface *);
131 void			 leave_all_routers_mcast_group(struct ra_iface *);
132 int			 get_link_state(char *);
133 int			 get_ifrdomain(char *);
134 void			 merge_ra_interface(char *, char *);
135 void			 merge_ra_interfaces(void);
136 struct ra_iface		*find_ra_iface_by_id(uint32_t);
137 struct ra_iface		*find_ra_iface_by_name(char *);
138 struct ra_iface_conf	*find_ra_iface_conf(struct ra_iface_conf_head *,
139 			    char *);
140 struct ra_prefix_conf	*find_ra_prefix_conf(struct ra_prefix_conf_head*,
141 			    struct in6_addr *, int);
142 struct icmp6_ev		*get_icmp6ev_by_rdomain(int);
143 void			 unref_icmp6ev(struct ra_iface *);
144 void			 set_icmp6sock(int, int);
145 void			 add_new_prefix_to_ra_iface(struct ra_iface *r,
146 			    struct in6_addr *, int, struct ra_prefix_conf *);
147 void			 free_ra_iface(struct ra_iface *);
148 int			 in6_mask2prefixlen(struct in6_addr *);
149 void			 get_interface_prefixes(struct ra_iface *,
150 			     struct ra_prefix_conf *);
151 int			 interface_has_linklocal_address(char *);
152 void			 build_packet(struct ra_iface *);
153 void			 build_leaving_packet(struct ra_iface *);
154 void			 ra_output(struct ra_iface *, struct sockaddr_in6 *);
155 void			 get_rtaddrs(int, struct sockaddr *,
156 			     struct sockaddr **);
157 void			 route_receive(int, short, void *);
158 void			 handle_route_message(struct rt_msghdr *,
159 			     struct sockaddr **);
160 
161 struct rad_conf	*frontend_conf;
162 static struct imsgev	*iev_main;
163 static struct imsgev	*iev_engine;
164 struct event		 ev_route;
165 int			 ioctlsock = -1, routesock = -1;
166 struct ipv6_mreq	 all_routers;
167 struct msghdr		 sndmhdr;
168 struct iovec		 sndiov[2];
169 
170 void
171 frontend_sig_handler(int sig, short event, void *bula)
172 {
173 	/*
174 	 * Normal signal handler rules don't apply because libevent
175 	 * decouples for us.
176 	 */
177 
178 	switch (sig) {
179 	case SIGINT:
180 	case SIGTERM:
181 		frontend_shutdown();
182 	default:
183 		fatalx("unexpected signal");
184 	}
185 }
186 
187 void
188 frontend(int debug, int verbose)
189 {
190 	struct event		 ev_sigint, ev_sigterm;
191 	struct passwd		*pw;
192 	size_t			 sndcmsgbuflen;
193 	uint8_t			*sndcmsgbuf = NULL;
194 
195 	frontend_conf = config_new_empty();
196 
197 	log_init(debug, LOG_DAEMON);
198 	log_setverbose(verbose);
199 
200 	if ((pw = getpwnam(RAD_USER)) == NULL)
201 		fatal("getpwnam");
202 
203 	if (chroot(pw->pw_dir) == -1)
204 		fatal("chroot");
205 	if (chdir("/") == -1)
206 		fatal("chdir(\"/\")");
207 
208 	setproctitle("%s", "frontend");
209 	log_procinit("frontend");
210 
211 	if (setgroups(1, &pw->pw_gid) ||
212 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
213 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
214 		fatal("can't drop privileges");
215 
216 	/* XXX pass in from main */
217 	if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1)
218 		fatal("socket");
219 
220 	if (pledge("stdio inet unix recvfd route mcast", NULL) == -1)
221 		fatal("pledge");
222 
223 	event_init();
224 
225 	/* Setup signal handler. */
226 	signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL);
227 	signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL);
228 	signal_add(&ev_sigint, NULL);
229 	signal_add(&ev_sigterm, NULL);
230 	signal(SIGPIPE, SIG_IGN);
231 	signal(SIGHUP, SIG_IGN);
232 
233 	/* Setup pipe and event handler to the parent process. */
234 	if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
235 		fatal(NULL);
236 	imsg_init(&iev_main->ibuf, 3);
237 	iev_main->handler = frontend_dispatch_main;
238 	iev_main->events = EV_READ;
239 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
240 	    iev_main->handler, iev_main);
241 	event_add(&iev_main->ev, NULL);
242 
243 	if (inet_pton(AF_INET6, "ff02::2",
244 	    &all_routers.ipv6mr_multiaddr.s6_addr) == -1)
245 		fatal("inet_pton");
246 
247 	sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
248 	    CMSG_SPACE(sizeof(int));
249 	if ((sndcmsgbuf = malloc(sndcmsgbuflen)) == NULL)
250 		fatal("%s", __func__);
251 
252 	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
253 	sndmhdr.msg_iov = sndiov;
254 	sndmhdr.msg_iovlen = 1;
255 	sndmhdr.msg_control = sndcmsgbuf;
256 	sndmhdr.msg_controllen = sndcmsgbuflen;
257 
258 	TAILQ_INIT(&ra_interfaces);
259 
260 	event_dispatch();
261 
262 	frontend_shutdown();
263 }
264 
265 __dead void
266 frontend_shutdown(void)
267 {
268 	/* Close pipes. */
269 	msgbuf_write(&iev_engine->ibuf.w);
270 	msgbuf_clear(&iev_engine->ibuf.w);
271 	close(iev_engine->ibuf.fd);
272 	msgbuf_write(&iev_main->ibuf.w);
273 	msgbuf_clear(&iev_main->ibuf.w);
274 	close(iev_main->ibuf.fd);
275 
276 	config_clear(frontend_conf);
277 
278 	free(iev_engine);
279 	free(iev_main);
280 
281 	log_info("frontend exiting");
282 	exit(0);
283 }
284 
285 int
286 frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen)
287 {
288 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data,
289 	    datalen));
290 }
291 
292 int
293 frontend_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen)
294 {
295 	return (imsg_compose_event(iev_engine, type, 0, pid, -1, data,
296 	    datalen));
297 }
298 
299 void
300 frontend_dispatch_main(int fd, short event, void *bula)
301 {
302 	static struct rad_conf		*nconf;
303 	static struct ra_iface_conf	*ra_iface_conf;
304 	static struct ra_options_conf	*ra_options;
305 	struct imsg			 imsg;
306 	struct imsgev			*iev = bula;
307 	struct imsgbuf			*ibuf = &iev->ibuf;
308 	struct ra_prefix_conf		*ra_prefix_conf;
309 	struct ra_rdnss_conf		*ra_rdnss_conf;
310 	struct ra_dnssl_conf		*ra_dnssl_conf;
311 	struct ra_pref64_conf		*pref64;
312 	int				 n, shut = 0, icmp6sock, rdomain;
313 
314 	if (event & EV_READ) {
315 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
316 			fatal("imsg_read error");
317 		if (n == 0)	/* Connection closed. */
318 			shut = 1;
319 	}
320 	if (event & EV_WRITE) {
321 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
322 			fatal("msgbuf_write");
323 		if (n == 0)	/* Connection closed. */
324 			shut = 1;
325 	}
326 
327 	for (;;) {
328 		if ((n = imsg_get(ibuf, &imsg)) == -1)
329 			fatal("%s: imsg_get error", __func__);
330 		if (n == 0)	/* No more messages. */
331 			break;
332 
333 		switch (imsg.hdr.type) {
334 		case IMSG_SOCKET_IPC:
335 			/*
336 			 * Setup pipe and event handler to the engine
337 			 * process.
338 			 */
339 			if (iev_engine)
340 				fatalx("%s: received unexpected imsg fd to "
341 				    "frontend", __func__);
342 			if ((fd = imsg.fd) == -1)
343 				fatalx("%s: expected to receive imsg fd to "
344 				   "frontend but didn't receive any",
345 				   __func__);
346 
347 			iev_engine = malloc(sizeof(struct imsgev));
348 			if (iev_engine == NULL)
349 				fatal(NULL);
350 
351 			imsg_init(&iev_engine->ibuf, fd);
352 			iev_engine->handler = frontend_dispatch_engine;
353 			iev_engine->events = EV_READ;
354 
355 			event_set(&iev_engine->ev, iev_engine->ibuf.fd,
356 			iev_engine->events, iev_engine->handler, iev_engine);
357 			event_add(&iev_engine->ev, NULL);
358 			break;
359 		case IMSG_RECONF_CONF:
360 			if (nconf != NULL)
361 				fatalx("%s: IMSG_RECONF_CONF already in "
362 				    "progress", __func__);
363 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct rad_conf))
364 				fatalx("%s: IMSG_RECONF_CONF wrong length: %lu",
365 				    __func__, IMSG_DATA_SIZE(imsg));
366 			if ((nconf = malloc(sizeof(struct rad_conf))) ==
367 			    NULL)
368 				fatal(NULL);
369 			memcpy(nconf, imsg.data, sizeof(struct rad_conf));
370 			SIMPLEQ_INIT(&nconf->ra_iface_list);
371 			SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list);
372 			SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list);
373 			SIMPLEQ_INIT(&nconf->ra_options.ra_pref64_list);
374 			ra_options = &nconf->ra_options;
375 			break;
376 		case IMSG_RECONF_RA_IFACE:
377 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
378 			    ra_iface_conf))
379 				fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: "
380 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
381 			if ((ra_iface_conf = malloc(sizeof(struct
382 			    ra_iface_conf))) == NULL)
383 				fatal(NULL);
384 			memcpy(ra_iface_conf, imsg.data, sizeof(struct
385 			    ra_iface_conf));
386 			ra_iface_conf->autoprefix = NULL;
387 			SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list);
388 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list);
389 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list);
390 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_pref64_list);
391 			SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list,
392 			    ra_iface_conf, entry);
393 			ra_options = &ra_iface_conf->ra_options;
394 			break;
395 		case IMSG_RECONF_RA_AUTOPREFIX:
396 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
397 			    ra_prefix_conf))
398 				fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong "
399 				    "length: %lu", __func__,
400 				    IMSG_DATA_SIZE(imsg));
401 			if ((ra_iface_conf->autoprefix = malloc(sizeof(struct
402 			    ra_prefix_conf))) == NULL)
403 				fatal(NULL);
404 			memcpy(ra_iface_conf->autoprefix, imsg.data,
405 			    sizeof(struct ra_prefix_conf));
406 			break;
407 		case IMSG_RECONF_RA_PREFIX:
408 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
409 			    ra_prefix_conf))
410 				fatalx("%s: IMSG_RECONF_RA_PREFIX wrong "
411 				    "length: %lu", __func__,
412 				    IMSG_DATA_SIZE(imsg));
413 			if ((ra_prefix_conf = malloc(sizeof(struct
414 			    ra_prefix_conf))) == NULL)
415 				fatal(NULL);
416 			memcpy(ra_prefix_conf, imsg.data,
417 			    sizeof(struct ra_prefix_conf));
418 			SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list,
419 			    ra_prefix_conf, entry);
420 			break;
421 		case IMSG_RECONF_RA_RDNSS:
422 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
423 			    ra_rdnss_conf))
424 				fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: "
425 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
426 			if ((ra_rdnss_conf = malloc(sizeof(struct
427 			    ra_rdnss_conf))) == NULL)
428 				fatal(NULL);
429 			memcpy(ra_rdnss_conf, imsg.data, sizeof(struct
430 			    ra_rdnss_conf));
431 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list,
432 			    ra_rdnss_conf, entry);
433 			break;
434 		case IMSG_RECONF_RA_DNSSL:
435 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
436 			    ra_dnssl_conf))
437 				fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: "
438 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
439 			if ((ra_dnssl_conf = malloc(sizeof(struct
440 			    ra_dnssl_conf))) == NULL)
441 				fatal(NULL);
442 			memcpy(ra_dnssl_conf, imsg.data, sizeof(struct
443 			    ra_dnssl_conf));
444 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list,
445 			    ra_dnssl_conf, entry);
446 			break;
447 		case IMSG_RECONF_RA_PREF64:
448 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
449 			    ra_pref64_conf))
450 				fatalx("%s: IMSG_RECONF_RA_PREF64 wrong length: "
451 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
452 			if ((pref64 = malloc(sizeof(struct ra_pref64_conf))) ==
453 			    NULL)
454 				fatal(NULL);
455 			memcpy(pref64, imsg.data, sizeof(struct ra_pref64_conf));
456 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_pref64_list, pref64,
457 			    entry);
458 			break;
459 		case IMSG_RECONF_END:
460 			if (nconf == NULL)
461 				fatalx("%s: IMSG_RECONF_END without "
462 				    "IMSG_RECONF_CONF", __func__);
463 			merge_config(frontend_conf, nconf);
464 			merge_ra_interfaces();
465 			nconf = NULL;
466 			break;
467 		case IMSG_ICMP6SOCK:
468 			if ((icmp6sock = imsg.fd) == -1)
469 				fatalx("%s: expected to receive imsg "
470 				    "ICMPv6 fd but didn't receive any",
471 				    __func__);
472 			if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain))
473 				fatalx("%s: IMSG_ICMP6SOCK wrong length: "
474 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
475 			memcpy(&rdomain, imsg.data, sizeof(rdomain));
476 			set_icmp6sock(icmp6sock, rdomain);
477 			break;
478 		case IMSG_ROUTESOCK:
479 			if (routesock != -1)
480 				fatalx("%s: received unexpected routesock fd",
481 				    __func__);
482 			if ((routesock = imsg.fd) == -1)
483 				fatalx("%s: expected to receive imsg "
484 				    "routesocket fd but didn't receive any",
485 				    __func__);
486 			event_set(&ev_route, routesock, EV_READ | EV_PERSIST,
487 			    route_receive, NULL);
488 			break;
489 		case IMSG_STARTUP:
490 			frontend_startup();
491 			break;
492 		case IMSG_CONTROLFD:
493 			if ((fd = imsg.fd) == -1)
494 				fatalx("%s: expected to receive imsg "
495 				    "control fd but didn't receive any",
496 				    __func__);
497 			/* Listen on control socket. */
498 			control_listen(fd);
499 			break;
500 		default:
501 			log_debug("%s: error handling imsg %d", __func__,
502 			    imsg.hdr.type);
503 			break;
504 		}
505 		imsg_free(&imsg);
506 	}
507 	if (!shut)
508 		imsg_event_add(iev);
509 	else {
510 		/* This pipe is dead. Remove its event handler. */
511 		event_del(&iev->ev);
512 		event_loopexit(NULL);
513 	}
514 }
515 
516 void
517 frontend_dispatch_engine(int fd, short event, void *bula)
518 {
519 	struct imsgev		*iev = bula;
520 	struct imsgbuf		*ibuf = &iev->ibuf;
521 	struct imsg		 imsg;
522 	struct imsg_send_ra	 send_ra;
523 	struct ra_iface		*ra_iface;
524 	uint32_t		 if_index;
525 	int			 n, shut = 0;
526 
527 	if (event & EV_READ) {
528 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
529 			fatal("imsg_read error");
530 		if (n == 0)	/* Connection closed. */
531 			shut = 1;
532 	}
533 	if (event & EV_WRITE) {
534 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
535 			fatal("msgbuf_write");
536 		if (n == 0)	/* Connection closed. */
537 			shut = 1;
538 	}
539 
540 	for (;;) {
541 		if ((n = imsg_get(ibuf, &imsg)) == -1)
542 			fatal("%s: imsg_get error", __func__);
543 		if (n == 0)	/* No more messages. */
544 			break;
545 
546 		switch (imsg.hdr.type) {
547 		case IMSG_SEND_RA:
548 			if (IMSG_DATA_SIZE(imsg) != sizeof(send_ra))
549 				fatalx("%s: IMSG_SEND_RA wrong length: %lu",
550 				    __func__, IMSG_DATA_SIZE(imsg));
551 			memcpy(&send_ra, imsg.data, sizeof(send_ra));
552 			ra_iface = find_ra_iface_by_id(send_ra.if_index);
553 			if (ra_iface)
554 				ra_output(ra_iface, &send_ra.to);
555 			break;
556 		case IMSG_REMOVE_IF:
557 			if (IMSG_DATA_SIZE(imsg) != sizeof(if_index))
558 				fatalx("%s: IMSG_REMOVE_IF wrong length: %lu",
559 				    __func__, IMSG_DATA_SIZE(imsg));
560 			memcpy(&if_index, imsg.data, sizeof(if_index));
561 			ra_iface = find_ra_iface_by_id(if_index);
562 			if (ra_iface) {
563 				TAILQ_REMOVE(&ra_interfaces, ra_iface, entry);
564 				free_ra_iface(ra_iface);
565 			}
566 			break;
567 		default:
568 			log_debug("%s: error handling imsg %d", __func__,
569 			    imsg.hdr.type);
570 			break;
571 		}
572 		imsg_free(&imsg);
573 	}
574 	if (!shut)
575 		imsg_event_add(iev);
576 	else {
577 		/* This pipe is dead. Remove its event handler. */
578 		event_del(&iev->ev);
579 		event_loopexit(NULL);
580 	}
581 }
582 
583 void
584 frontend_startup(void)
585 {
586 	if (!event_initialized(&ev_route))
587 		fatalx("%s: did not receive a route socket from the main "
588 		    "process", __func__);
589 
590 	event_add(&ev_route, NULL);
591 }
592 
593 
594 void
595 icmp6_receive(int fd, short events, void *arg)
596 {
597 	struct icmp6_ev		*icmp6ev;
598 	struct icmp6_hdr	*icmp6_hdr;
599 	struct imsg_ra_rs	 ra_rs;
600 	struct in6_pktinfo	*pi = NULL;
601 	struct cmsghdr		*cm;
602 	ssize_t			 len;
603 	int			 if_index = 0, *hlimp = NULL;
604 	char			 ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
605 
606 	icmp6ev = arg;
607 	if ((len = recvmsg(fd, &icmp6ev->rcvmhdr, 0)) == -1) {
608 		log_warn("recvmsg");
609 		return;
610 	}
611 
612 	if ((size_t)len < sizeof(struct icmp6_hdr))
613 		return;
614 
615 	icmp6_hdr = (struct icmp6_hdr *)icmp6ev->answer;
616 	if (icmp6_hdr->icmp6_type != ND_ROUTER_ADVERT &&
617 	    icmp6_hdr->icmp6_type != ND_ROUTER_SOLICIT)
618 		return;
619 
620 	/* extract optional information via Advanced API */
621 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev->rcvmhdr); cm;
622 	    cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev->rcvmhdr, cm)) {
623 		if (cm->cmsg_level == IPPROTO_IPV6 &&
624 		    cm->cmsg_type == IPV6_PKTINFO &&
625 		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
626 			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
627 			if_index = pi->ipi6_ifindex;
628 		}
629 		if (cm->cmsg_level == IPPROTO_IPV6 &&
630 		    cm->cmsg_type == IPV6_HOPLIMIT &&
631 		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
632 			hlimp = (int *)CMSG_DATA(cm);
633 	}
634 
635 	if (if_index == 0) {
636 		log_warnx("failed to get receiving interface");
637 		return;
638 	}
639 
640 	if (hlimp == NULL) {
641 		log_warnx("failed to get receiving hop limit");
642 		return;
643 	}
644 
645 	if (*hlimp != 255) {
646 		log_warnx("invalid RA or RS with hop limit of %d from %s on %s",
647 		    *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
648 		    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
649 		    ifnamebuf));
650 		return;
651 	}
652 
653 	log_debug("RA or RS with hop limit of %d from %s on %s",
654 	    *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
655 	    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
656 	    ifnamebuf));
657 
658 	if ((size_t)len > sizeof(ra_rs.packet)) {
659 		log_warnx("invalid RA or RS with size %ld from %s on %s",
660 		    len, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
661 		    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
662 		    ifnamebuf));
663 		return;
664 	}
665 
666 	ra_rs.if_index = if_index;
667 	memcpy(&ra_rs.from,  &icmp6ev->from, sizeof(ra_rs.from));
668 	ra_rs.len = len;
669 	memcpy(ra_rs.packet, icmp6ev->answer, len);
670 
671 	frontend_imsg_compose_engine(IMSG_RA_RS, 0, &ra_rs, sizeof(ra_rs));
672 }
673 
674 void
675 join_all_routers_mcast_group(struct ra_iface *ra_iface)
676 {
677 	if (!event_initialized(&ra_iface->icmp6ev->ev))
678 		return;
679 	log_debug("joining multicast group on %s", ra_iface->name);
680 	all_routers.ipv6mr_interface = ra_iface->if_index;
681 	if (setsockopt(EVENT_FD(&ra_iface->icmp6ev->ev), IPPROTO_IPV6,
682 	    IPV6_JOIN_GROUP, &all_routers, sizeof(all_routers)) == -1)
683 		fatal("IPV6_JOIN_GROUP(%s)", ra_iface->name);
684 }
685 
686 void
687 leave_all_routers_mcast_group(struct ra_iface *ra_iface)
688 {
689 	if (!event_initialized(&ra_iface->icmp6ev->ev))
690 		return;
691 	log_debug("leaving multicast group on %s", ra_iface->name);
692 	all_routers.ipv6mr_interface = ra_iface->if_index;
693 	setsockopt(EVENT_FD(&ra_iface->icmp6ev->ev), IPPROTO_IPV6,
694 	    IPV6_LEAVE_GROUP, &all_routers, sizeof(all_routers));
695 }
696 
697 struct ra_iface*
698 find_ra_iface_by_id(uint32_t if_index)
699 {
700 	struct ra_iface	*ra_iface;
701 
702 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
703 		if (ra_iface->if_index == if_index)
704 			return ra_iface;
705 	}
706 	return (NULL);
707 }
708 
709 struct ra_iface*
710 find_ra_iface_by_name(char *if_name)
711 {
712 	struct ra_iface	*ra_iface;
713 
714 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
715 		if (strcmp(ra_iface->name, if_name) == 0)
716 			return ra_iface;
717 	}
718 	return (NULL);
719 }
720 
721 struct ra_iface_conf*
722 find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name)
723 {
724 	struct ra_iface_conf	*ra_iface_conf;
725 
726 	SIMPLEQ_FOREACH(ra_iface_conf, head, entry) {
727 		if (strcmp(ra_iface_conf->name, if_name) == 0)
728 			return ra_iface_conf;
729 	}
730 	return (NULL);
731 }
732 
733 int
734 get_link_state(char *if_name)
735 {
736 	struct ifaddrs	*ifap, *ifa;
737 	int		 ls = LINK_STATE_UNKNOWN;
738 
739 	if (getifaddrs(&ifap) != 0) {
740 		log_warn("getifaddrs");
741 		return LINK_STATE_UNKNOWN;
742 	}
743 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
744 		if (ifa->ifa_addr == NULL ||
745 		    ifa->ifa_addr->sa_family != AF_LINK)
746 			continue;
747 		if (strcmp(if_name, ifa->ifa_name) != 0)
748 			continue;
749 
750 		ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
751 		break;
752 	}
753 	freeifaddrs(ifap);
754 	return ls;
755 }
756 
757 int
758 get_ifrdomain(char *if_name)
759 {
760 	struct ifreq		 ifr;
761 
762 	strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
763 	if (ioctl(ioctlsock, SIOCGIFRDOMAIN, (caddr_t)&ifr) == -1) {
764 		log_warn("SIOCGIFRDOMAIN");
765 		return -1;
766 	}
767 	return ifr.ifr_rdomainid;
768 }
769 
770 void
771 merge_ra_interface(char *name, char *conf_name)
772 {
773 	struct ra_iface		*ra_iface;
774 	uint32_t		 if_index;
775 	int			 link_state, has_linklocal, ifrdomain;
776 
777 	link_state = get_link_state(name);
778 	has_linklocal = interface_has_linklocal_address(name);
779 	ifrdomain = get_ifrdomain(name);
780 
781 	if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
782 		ra_iface->link_state = link_state;
783 		if (!LINK_STATE_IS_UP(link_state)) {
784 			log_debug("%s down, removing", name);
785 			ra_iface->removed = 1;
786 		} else if (!has_linklocal) {
787 			log_debug("%s has no IPv6 link-local address, "
788 			    "removing", name);
789 			ra_iface->removed = 1;
790 		} else if (ifrdomain == -1) {
791 			log_debug("can't get rdomain for %s, removing", name);
792 			ra_iface->removed = 1;
793 		} else if (ra_iface->rdomain != ifrdomain) {
794 			leave_all_routers_mcast_group(ra_iface);
795 			unref_icmp6ev(ra_iface);
796 			ra_iface->rdomain = ifrdomain;
797 			ra_iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain);
798 			join_all_routers_mcast_group(ra_iface);
799 			ra_iface->removed = 0;
800 		} else {
801 			log_debug("keeping interface %s", name);
802 			ra_iface->removed = 0;
803 		}
804 		return;
805 	}
806 
807 	if (!LINK_STATE_IS_UP(link_state)) {
808 		log_debug("%s down, ignoring", name);
809 		return;
810 	}
811 
812 	if (!has_linklocal) {
813 		log_debug("%s has no IPv6 link-local address, ignoring", name);
814 		return;
815 	}
816 
817 	log_debug("new interface %s", name);
818 	if ((if_index = if_nametoindex(name)) == 0)
819 		return;
820 
821 	log_debug("adding interface %s", name);
822 	if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
823 		fatal("%s", __func__);
824 
825 	strlcpy(ra_iface->name, name, sizeof(ra_iface->name));
826 	strlcpy(ra_iface->conf_name, conf_name,
827 	    sizeof(ra_iface->conf_name));
828 
829 	ra_iface->if_index = if_index;
830 	ra_iface->rdomain = ifrdomain;
831 
832 	SIMPLEQ_INIT(&ra_iface->prefixes);
833 
834 	ra_iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain);
835 	join_all_routers_mcast_group(ra_iface);
836 	TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry);
837 }
838 
839 void
840 merge_ra_interfaces(void)
841 {
842 	struct ra_iface_conf	*ra_iface_conf;
843 	struct ra_prefix_conf	*ra_prefix_conf;
844 	struct ra_iface		*ra_iface;
845 	struct ifgroupreq	 ifgr;
846 	struct ifg_req		*ifg;
847 	char			*conf_name;
848 	unsigned int		 len;
849 
850 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry)
851 		ra_iface->removed = 1;
852 
853 	SIMPLEQ_FOREACH(ra_iface_conf, &frontend_conf->ra_iface_list, entry) {
854 		conf_name = ra_iface_conf->name;
855 
856 		/* check if network interface or group */
857 		if (isdigit((unsigned char)conf_name[strlen(conf_name) - 1])) {
858 			merge_ra_interface(conf_name, conf_name);
859 		} else {
860 			log_debug("interface group %s", conf_name);
861 
862 			memset(&ifgr, 0, sizeof(ifgr));
863 			strlcpy(ifgr.ifgr_name, conf_name,
864 			    sizeof(ifgr.ifgr_name));
865 			if (ioctl(ioctlsock, SIOCGIFGMEMB,
866 			    (caddr_t)&ifgr) == -1)
867 				continue;
868 
869 			len = ifgr.ifgr_len;
870 			if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
871 				fatal("%s: calloc", __func__);
872 			if (ioctl(ioctlsock, SIOCGIFGMEMB,
873 			    (caddr_t)&ifgr) == -1) {
874 				log_debug("group %s without members",
875 				    conf_name);
876 				free(ifgr.ifgr_groups);
877 				continue;
878 			}
879 
880 			for (ifg = ifgr.ifgr_groups;
881 			    (ifg != NULL) && (len >= sizeof(struct ifg_req));
882 			    ifg++) {
883 				len -= sizeof(struct ifg_req);
884 				merge_ra_interface(ifg->ifgrq_member,
885 				    conf_name);
886 			}
887 			free(ifgr.ifgr_groups);
888 		}
889 	}
890 
891 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
892 		while ((ra_prefix_conf = SIMPLEQ_FIRST(&ra_iface->prefixes))
893 		    != NULL) {
894 			SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes,
895 			    entry);
896 			free(ra_prefix_conf);
897 		}
898 		ra_iface->prefix_count = 0;
899 
900 		if (ra_iface->removed) {
901 			log_debug("iface removed: %s", ra_iface->name);
902 			build_leaving_packet(ra_iface);
903 			frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0,
904 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
905 			continue;
906 		}
907 
908 		ra_iface_conf = find_ra_iface_conf(
909 		    &frontend_conf->ra_iface_list, ra_iface->conf_name);
910 
911 		log_debug("add static prefixes for %s", ra_iface->name);
912 
913 		SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list,
914 		    entry) {
915 			add_new_prefix_to_ra_iface(ra_iface,
916 			    &ra_prefix_conf->prefix,
917 			    ra_prefix_conf->prefixlen, ra_prefix_conf);
918 		}
919 
920 		if (ra_iface_conf->autoprefix)
921 			get_interface_prefixes(ra_iface,
922 			    ra_iface_conf->autoprefix);
923 
924 		build_packet(ra_iface);
925 	}
926 }
927 
928 void
929 free_ra_iface(struct ra_iface *ra_iface)
930 {
931 	struct ra_prefix_conf	*prefix;
932 
933 	leave_all_routers_mcast_group(ra_iface);
934 
935 	while ((prefix = SIMPLEQ_FIRST(&ra_iface->prefixes)) != NULL) {
936 		SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, entry);
937 		free(prefix);
938 	}
939 
940 	unref_icmp6ev(ra_iface);
941 	free(ra_iface);
942 }
943 
944 /* from kame via ifconfig, where it's called prefix() */
945 int
946 in6_mask2prefixlen(struct in6_addr *in6)
947 {
948 	u_char *nam = (u_char *)in6;
949 	int byte, bit, plen = 0, size = sizeof(struct in6_addr);
950 
951 	for (byte = 0; byte < size; byte++, plen += 8)
952 		if (nam[byte] != 0xff)
953 			break;
954 	if (byte == size)
955 		return (plen);
956 	for (bit = 7; bit != 0; bit--, plen++)
957 		if (!(nam[byte] & (1 << bit)))
958 			break;
959 	for (; bit != 0; bit--)
960 		if (nam[byte] & (1 << bit))
961 			return (0);
962 	byte++;
963 	for (; byte < size; byte++)
964 		if (nam[byte])
965 			return (0);
966 	return (plen);
967 }
968 
969 int
970 interface_has_linklocal_address(char *name)
971 {
972 	struct ifaddrs		*ifap, *ifa;
973 	struct sockaddr_in6	*sin6;
974 	struct in6_ifreq	 ifr6;
975 	int			 ret = 0;
976 
977 	if (getifaddrs(&ifap) != 0)
978 		fatal("getifaddrs");
979 
980 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
981 		if (strcmp(name, ifa->ifa_name) != 0)
982 			continue;
983 		if (ifa->ifa_addr == NULL ||
984 		    ifa->ifa_addr->sa_family != AF_INET6)
985 			continue;
986 
987 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
988 
989 		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
990 			continue;
991 
992 		memset(&ifr6, 0, sizeof(ifr6));
993 		strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
994 		memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr));
995 		if (ioctl(ioctlsock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) == -1) {
996 			log_warn("SIOCGIFAFLAG_IN6");
997 			continue;
998 		}
999 
1000 		if (ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_TENTATIVE |
1001 		    IN6_IFF_DUPLICATED))
1002 			continue;
1003 
1004 		ret = 1;
1005 		break;
1006 	}
1007 	freeifaddrs(ifap);
1008 	return (ret);
1009 }
1010 
1011 void
1012 get_interface_prefixes(struct ra_iface *ra_iface, struct ra_prefix_conf
1013     *autoprefix)
1014 {
1015 	struct in6_ifreq	 ifr6;
1016 	struct ifaddrs		*ifap, *ifa;
1017 	struct sockaddr_in6	*sin6;
1018 	int			 prefixlen;
1019 
1020 	log_debug("%s: %s", __func__, ra_iface->name);
1021 
1022 	if (getifaddrs(&ifap) != 0)
1023 		fatal("getifaddrs");
1024 
1025 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
1026 		if (strcmp(ra_iface->name, ifa->ifa_name) != 0)
1027 			continue;
1028 		if (ifa->ifa_addr == NULL ||
1029 		    ifa->ifa_addr->sa_family != AF_INET6)
1030 			continue;
1031 
1032 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1033 
1034 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
1035 			continue;
1036 
1037 		memset(&ifr6, 0, sizeof(ifr6));
1038 		strlcpy(ifr6.ifr_name, ra_iface->name, sizeof(ifr6.ifr_name));
1039 		memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr));
1040 
1041 		if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) == -1)
1042 			continue; /* addr got deleted while we were looking */
1043 
1044 		prefixlen = in6_mask2prefixlen(&((struct sockaddr_in6 *)
1045 		    &ifr6.ifr_addr)->sin6_addr);
1046 
1047 		if (prefixlen == 128)
1048 			continue;
1049 
1050 		mask_prefix(&sin6->sin6_addr, prefixlen);
1051 
1052 		add_new_prefix_to_ra_iface(ra_iface, &sin6->sin6_addr,
1053 		    prefixlen, autoprefix);
1054 	}
1055 	freeifaddrs(ifap);
1056 }
1057 
1058 struct ra_prefix_conf*
1059 find_ra_prefix_conf(struct ra_prefix_conf_head* head, struct in6_addr *prefix,
1060     int prefixlen)
1061 {
1062 	struct ra_prefix_conf	*ra_prefix_conf;
1063 
1064 	SIMPLEQ_FOREACH(ra_prefix_conf, head, entry) {
1065 		if (ra_prefix_conf->prefixlen == prefixlen &&
1066 		    memcmp(&ra_prefix_conf->prefix, prefix, sizeof(*prefix)) ==
1067 		    0)
1068 			return (ra_prefix_conf);
1069 	}
1070 	return (NULL);
1071 }
1072 
1073 void
1074 add_new_prefix_to_ra_iface(struct ra_iface *ra_iface, struct in6_addr *addr,
1075     int prefixlen, struct ra_prefix_conf *ra_prefix_conf)
1076 {
1077 	struct ra_prefix_conf	*new_ra_prefix_conf;
1078 
1079 	if (find_ra_prefix_conf(&ra_iface->prefixes, addr, prefixlen)) {
1080 		log_debug("ignoring duplicate %s/%d prefix",
1081 		    in6_to_str(addr), prefixlen);
1082 		return;
1083 	}
1084 
1085 	log_debug("adding %s/%d prefix", in6_to_str(addr), prefixlen);
1086 
1087 	if ((new_ra_prefix_conf = calloc(1, sizeof(*ra_prefix_conf))) == NULL)
1088 		fatal("%s", __func__);
1089 	new_ra_prefix_conf->prefix = *addr;
1090 	new_ra_prefix_conf->prefixlen = prefixlen;
1091 	new_ra_prefix_conf->vltime = ra_prefix_conf->vltime;
1092 	new_ra_prefix_conf->pltime = ra_prefix_conf->pltime;
1093 	new_ra_prefix_conf->aflag = ra_prefix_conf->aflag;
1094 	new_ra_prefix_conf->lflag = ra_prefix_conf->lflag;
1095 	SIMPLEQ_INSERT_TAIL(&ra_iface->prefixes, new_ra_prefix_conf, entry);
1096 	ra_iface->prefix_count++;
1097 }
1098 
1099 void
1100 build_packet(struct ra_iface *ra_iface)
1101 {
1102 	struct nd_router_advert		*ra;
1103 	struct nd_opt_mtu		*ndopt_mtu;
1104 	struct nd_opt_prefix_info	*ndopt_pi;
1105 	struct ra_iface_conf		*ra_iface_conf;
1106 	struct ra_options_conf		*ra_options_conf;
1107 	struct ra_prefix_conf		*ra_prefix_conf;
1108 	struct nd_opt_rdnss		*ndopt_rdnss;
1109 	struct nd_opt_dnssl		*ndopt_dnssl;
1110 	struct nd_opt_pref64		*ndopt_pref64;
1111 	struct ra_rdnss_conf		*ra_rdnss;
1112 	struct ra_dnssl_conf		*ra_dnssl;
1113 	struct ra_pref64_conf		*pref64;
1114 	size_t				 len, label_len;
1115 	uint8_t				*p, buf[RA_MAX_SIZE];
1116 	char				*label_start, *label_end;
1117 
1118 	ra_iface_conf = find_ra_iface_conf(&frontend_conf->ra_iface_list,
1119 	    ra_iface->conf_name);
1120 	ra_options_conf = &ra_iface_conf->ra_options;
1121 
1122 	len = sizeof(*ra);
1123 	if (ra_options_conf->mtu > 0)
1124 		len += sizeof(*ndopt_mtu);
1125 	len += sizeof(*ndopt_pi) * ra_iface->prefix_count;
1126 	if (ra_iface_conf->ra_options.rdnss_count > 0)
1127 		len += sizeof(*ndopt_rdnss) +
1128 		    ra_iface_conf->ra_options.rdnss_count *
1129 		    sizeof(struct in6_addr);
1130 
1131 	if (ra_iface_conf->ra_options.dnssl_len > 0)
1132 		/* round up to 8 byte boundary */
1133 		len += sizeof(*ndopt_dnssl) +
1134 		    ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7);
1135 
1136 	SIMPLEQ_FOREACH(pref64, &ra_iface_conf->ra_options.ra_pref64_list,
1137 	    entry)
1138 		len += sizeof(struct nd_opt_pref64);
1139 
1140 	if (len > sizeof(ra_iface->data))
1141 		fatalx("%s: packet too big", __func__); /* XXX send multiple */
1142 
1143 	p = buf;
1144 
1145 	ra = (struct nd_router_advert *)p;
1146 
1147 	memset(ra, 0, sizeof(*ra));
1148 
1149 	ra->nd_ra_type = ND_ROUTER_ADVERT;
1150 	ra->nd_ra_curhoplimit = ra_options_conf->cur_hl;
1151 	if (ra_options_conf->m_flag)
1152 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
1153 	if (ra_options_conf->o_flag)
1154 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
1155 	if (ra_iface->removed)
1156 		/* tell clients that we are no longer a default router */
1157 		ra->nd_ra_router_lifetime = 0;
1158 	else if (ra_options_conf->dfr) {
1159 		ra->nd_ra_router_lifetime =
1160 		    htons(ra_options_conf->router_lifetime);
1161 	}
1162 	ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time);
1163 	ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer);
1164 	p += sizeof(*ra);
1165 
1166 	if (ra_options_conf->mtu > 0) {
1167 		ndopt_mtu = (struct nd_opt_mtu *)p;
1168 		ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
1169 		ndopt_mtu->nd_opt_mtu_len = 1;
1170 		ndopt_mtu->nd_opt_mtu_reserved = 0;
1171 		ndopt_mtu->nd_opt_mtu_mtu = htonl(ra_options_conf->mtu);
1172 		p += sizeof(*ndopt_mtu);
1173 	}
1174 
1175 	SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface->prefixes, entry) {
1176 		ndopt_pi = (struct nd_opt_prefix_info *)p;
1177 		memset(ndopt_pi, 0, sizeof(*ndopt_pi));
1178 		ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
1179 		ndopt_pi->nd_opt_pi_len = 4;
1180 		ndopt_pi->nd_opt_pi_prefix_len = ra_prefix_conf->prefixlen;
1181 		if (ra_prefix_conf->lflag)
1182 			ndopt_pi->nd_opt_pi_flags_reserved |=
1183 			    ND_OPT_PI_FLAG_ONLINK;
1184 		if (ra_prefix_conf->aflag)
1185 			ndopt_pi->nd_opt_pi_flags_reserved |=
1186 			    ND_OPT_PI_FLAG_AUTO;
1187 		ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
1188 		ndopt_pi->nd_opt_pi_preferred_time =
1189 		    htonl(ra_prefix_conf->pltime);
1190 		ndopt_pi->nd_opt_pi_prefix = ra_prefix_conf->prefix;
1191 
1192 		p += sizeof(*ndopt_pi);
1193 	}
1194 
1195 	if (ra_iface_conf->ra_options.rdnss_count > 0) {
1196 		ndopt_rdnss = (struct nd_opt_rdnss *)p;
1197 		ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
1198 		ndopt_rdnss->nd_opt_rdnss_len = 1 +
1199 		    ra_iface_conf->ra_options.rdnss_count * 2;
1200 		ndopt_rdnss->nd_opt_rdnss_reserved = 0;
1201 		ndopt_rdnss->nd_opt_rdnss_lifetime =
1202 		    htonl(ra_iface_conf->ra_options.rdns_lifetime);
1203 		p += sizeof(struct nd_opt_rdnss);
1204 		SIMPLEQ_FOREACH(ra_rdnss,
1205 		    &ra_iface_conf->ra_options.ra_rdnss_list, entry) {
1206 			memcpy(p, &ra_rdnss->rdnss, sizeof(ra_rdnss->rdnss));
1207 			p += sizeof(ra_rdnss->rdnss);
1208 		}
1209 	}
1210 
1211 	if (ra_iface_conf->ra_options.dnssl_len > 0) {
1212 		ndopt_dnssl = (struct nd_opt_dnssl *)p;
1213 		ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
1214 		/* round up to 8 byte boundary */
1215 		ndopt_dnssl->nd_opt_dnssl_len = 1 +
1216 		    ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7) / 8;
1217 		ndopt_dnssl->nd_opt_dnssl_reserved = 0;
1218 		ndopt_dnssl->nd_opt_dnssl_lifetime =
1219 		    htonl(ra_iface_conf->ra_options.rdns_lifetime);
1220 		p += sizeof(struct nd_opt_dnssl);
1221 
1222 		SIMPLEQ_FOREACH(ra_dnssl,
1223 		    &ra_iface_conf->ra_options.ra_dnssl_list, entry) {
1224 			label_start = ra_dnssl->search;
1225 			while ((label_end = strchr(label_start, '.')) != NULL) {
1226 				label_len = label_end - label_start;
1227 				*p++ = label_len;
1228 				memcpy(p, label_start, label_len);
1229 				p += label_len;
1230 				label_start = label_end + 1;
1231 			}
1232 			*p++ = '\0'; /* last dot */
1233 		}
1234 		/* zero pad */
1235 		while (((uintptr_t)p) % 8 != 0)
1236 			*p++ = '\0';
1237 	}
1238 
1239 	SIMPLEQ_FOREACH(pref64, &ra_iface_conf->ra_options.ra_pref64_list,
1240 	    entry) {
1241 		uint16_t	sltime_plc;
1242 
1243 		/* scaled lifetime in units of 8 seconds */
1244 		sltime_plc = pref64->ltime / 8;
1245 		sltime_plc = sltime_plc << 3;
1246 		/* encode prefix length in lower 3 bits */
1247 		switch (pref64->prefixlen) {
1248 		case 96:
1249 			sltime_plc |= 0;
1250 			break;
1251 		case 64:
1252 			sltime_plc |= 1;
1253 			break;
1254 		case 56:
1255 			sltime_plc |= 2;
1256 			break;
1257 		case 48:
1258 			sltime_plc |= 3;
1259 			break;
1260 		case 40:
1261 			sltime_plc |= 4;
1262 			break;
1263 		case 32:
1264 			sltime_plc |= 5;
1265 			break;
1266 		default:
1267 			fatalx("%s: invalid pref64 length: %d", __func__,
1268 			    pref64->prefixlen);
1269 		}
1270 		ndopt_pref64 = (struct nd_opt_pref64 *)p;
1271 		ndopt_pref64->nd_opt_pref64_type = ND_OPT_PREF64;
1272 		ndopt_pref64->nd_opt_pref64_len = 2;
1273 		ndopt_pref64->nd_opt_pref64_sltime_plc = htons(sltime_plc);
1274 		memcpy(ndopt_pref64->nd_opt_pref64, &pref64->prefix,
1275 		    sizeof(ndopt_pref64->nd_opt_pref64));
1276 		p += sizeof(struct nd_opt_pref64);
1277 	}
1278 
1279 	if (len != ra_iface->datalen || memcmp(buf, ra_iface->data, len)
1280 	    != 0) {
1281 		memcpy(ra_iface->data, buf, len);
1282 		ra_iface->datalen = len;
1283 		/* packet changed; tell engine to send new advertisements */
1284 		if (event_initialized(&ra_iface->icmp6ev->ev))
1285 			frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
1286 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
1287 	}
1288 }
1289 
1290 void
1291 build_leaving_packet(struct ra_iface *ra_iface)
1292 {
1293 	struct nd_router_advert		 ra;
1294 
1295 	memset(&ra, 0, sizeof(ra));
1296 
1297 	ra.nd_ra_type = ND_ROUTER_ADVERT;
1298 
1299 	memcpy(ra_iface->data, &ra, sizeof(ra));
1300 	ra_iface->datalen = sizeof(ra);
1301 }
1302 
1303 void
1304 ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to)
1305 {
1306 
1307 	struct cmsghdr		*cm;
1308 	struct in6_pktinfo	*pi;
1309 	ssize_t			 len;
1310 	int			 hoplimit = 255;
1311 
1312 	if (!LINK_STATE_IS_UP(ra_iface->link_state))
1313 		return;
1314 
1315 	sndmhdr.msg_name = to;
1316 	sndmhdr.msg_iov[0].iov_base = ra_iface->data;
1317 	sndmhdr.msg_iov[0].iov_len = ra_iface->datalen;
1318 
1319 	cm = CMSG_FIRSTHDR(&sndmhdr);
1320 	/* specify the outgoing interface */
1321 	cm->cmsg_level = IPPROTO_IPV6;
1322 	cm->cmsg_type = IPV6_PKTINFO;
1323 	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1324 	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
1325 	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));
1326 	pi->ipi6_ifindex = ra_iface->if_index;
1327 
1328 	/* specify the hop limit of the packet */
1329 	cm = CMSG_NXTHDR(&sndmhdr, cm);
1330 	cm->cmsg_level = IPPROTO_IPV6;
1331 	cm->cmsg_type = IPV6_HOPLIMIT;
1332 	cm->cmsg_len = CMSG_LEN(sizeof(int));
1333 	memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
1334 
1335 	log_debug("send RA on %s", ra_iface->name);
1336 
1337 	len = sendmsg(EVENT_FD(&ra_iface->icmp6ev->ev), &sndmhdr, 0);
1338 	if (len == -1)
1339 		log_warn("sendmsg on %s", ra_iface->name);
1340 
1341 }
1342 
1343 #define ROUNDUP(a) \
1344 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1345 
1346 void
1347 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
1348 {
1349 	int	i;
1350 
1351 	for (i = 0; i < RTAX_MAX; i++) {
1352 		if (addrs & (1 << i)) {
1353 			rti_info[i] = sa;
1354 			sa = (struct sockaddr *)((char *)(sa) +
1355 			    ROUNDUP(sa->sa_len));
1356 		} else
1357 			rti_info[i] = NULL;
1358 	}
1359 }
1360 
1361 void
1362 route_receive(int fd, short events, void *arg)
1363 {
1364 	static uint8_t			 *buf;
1365 
1366 	struct rt_msghdr		*rtm;
1367 	struct sockaddr			*sa, *rti_info[RTAX_MAX];
1368 	ssize_t				 n;
1369 
1370 	if (buf == NULL) {
1371 		buf = malloc(ROUTE_SOCKET_BUF_SIZE);
1372 		if (buf == NULL)
1373 			fatal("malloc");
1374 	}
1375 	rtm = (struct rt_msghdr *)buf;
1376 	if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) {
1377 		if (errno == EAGAIN || errno == EINTR)
1378 			return;
1379 		log_warn("dispatch_rtmsg: read error");
1380 		return;
1381 	}
1382 
1383 	if (n == 0)
1384 		fatal("routing socket closed");
1385 
1386 	if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
1387 		log_warnx("partial rtm of %zd in buffer", n);
1388 		return;
1389 	}
1390 
1391 	if (rtm->rtm_version != RTM_VERSION)
1392 		return;
1393 
1394 	sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
1395 	get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1396 
1397 	handle_route_message(rtm, rti_info);
1398 }
1399 
1400 void
1401 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
1402 {
1403 	switch (rtm->rtm_type) {
1404 	case RTM_IFINFO:
1405 	case RTM_NEWADDR:
1406 	case RTM_DELADDR:
1407 	case RTM_CHGADDRATTR:
1408 		/*
1409 		 * do the same thing as after a config reload when interfaces
1410 		 * change or IPv6 addresses show up / disappear
1411 		 */
1412 		merge_ra_interfaces();
1413 		break;
1414 	default:
1415 		log_debug("unexpected RTM: %d", rtm->rtm_type);
1416 		break;
1417 	}
1418 }
1419 
1420 struct icmp6_ev*
1421 get_icmp6ev_by_rdomain(int rdomain)
1422 {
1423 	struct ra_iface	*ra_iface;
1424 	struct icmp6_ev	*icmp6ev = NULL;
1425 
1426 	TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
1427 		if (ra_iface->rdomain == rdomain) {
1428 			icmp6ev = ra_iface->icmp6ev;
1429 			break;
1430 		}
1431 	}
1432 
1433 	if (icmp6ev == NULL) {
1434 		if ((icmp6ev = calloc(1, sizeof(*icmp6ev))) == NULL)
1435 			fatal("calloc");
1436 
1437 		icmp6ev->rcviov[0].iov_base = (caddr_t)icmp6ev->answer;
1438 		icmp6ev->rcviov[0].iov_len = sizeof(icmp6ev->answer);
1439 		icmp6ev->rcvmhdr.msg_name = (caddr_t)&icmp6ev->from;
1440 		icmp6ev->rcvmhdr.msg_namelen = sizeof(icmp6ev->from);
1441 		icmp6ev->rcvmhdr.msg_iov = icmp6ev->rcviov;
1442 		icmp6ev->rcvmhdr.msg_iovlen = 1;
1443 		icmp6ev->rcvmhdr.msg_controllen =
1444 		    CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1445 		    CMSG_SPACE(sizeof(int));
1446 		if ((icmp6ev->rcvmhdr.msg_control = malloc(icmp6ev->
1447 		    rcvmhdr.msg_controllen)) == NULL)
1448 			fatal("malloc");
1449 		frontend_imsg_compose_main(IMSG_OPEN_ICMP6SOCK, 0,
1450 		    &rdomain, sizeof(rdomain));
1451 	}
1452 
1453 	icmp6ev->refcnt++;
1454 	return (icmp6ev);
1455 }
1456 
1457 void
1458 unref_icmp6ev(struct ra_iface *ra_iface)
1459 {
1460 	struct icmp6_ev *icmp6ev = ra_iface->icmp6ev;
1461 
1462 	ra_iface->icmp6ev = NULL;
1463 
1464 	if (icmp6ev != NULL) {
1465 		icmp6ev->refcnt--;
1466 		if (icmp6ev->refcnt == 0) {
1467 			event_del(&icmp6ev->ev);
1468 			close(EVENT_FD(&icmp6ev->ev));
1469 			free(icmp6ev);
1470 		}
1471 	}
1472 }
1473 
1474 void
1475 set_icmp6sock(int icmp6sock, int rdomain)
1476 {
1477 	struct ra_iface	*ra_iface;
1478 
1479 	TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
1480 		if (!event_initialized(&ra_iface->icmp6ev->ev) &&
1481 		    ra_iface->rdomain == rdomain) {
1482 			event_set(&ra_iface->icmp6ev->ev, icmp6sock, EV_READ |
1483 			    EV_PERSIST, icmp6_receive, ra_iface->icmp6ev);
1484 			event_add(&ra_iface->icmp6ev->ev, NULL);
1485 			icmp6sock = -1;
1486 			break;
1487 		}
1488 	}
1489 
1490 	if (icmp6sock != -1) {
1491 		/*
1492 		 * The interface disappeared or changed rdomain while we were
1493 		 * waiting for the parent process to open the raw socket.
1494 		 */
1495 		close(icmp6sock);
1496 		return;
1497 	}
1498 
1499 	TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
1500 		if (ra_iface->rdomain == rdomain) {
1501 			join_all_routers_mcast_group(ra_iface);
1502 			frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
1503 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
1504 		}
1505 	}
1506 }
1507