xref: /openbsd-src/usr.sbin/rad/frontend.c (revision 8e0c768258d4632c51876b4397034bc3152bf8db)
1 /*	$OpenBSD: frontend.c,v 1.31 2019/09/07 18:57:47 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 
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 } icmp6ev;
99 
100 struct ra_iface {
101 	TAILQ_ENTRY(ra_iface)		entry;
102 	struct ra_prefix_conf_head	prefixes;
103 	char				name[IF_NAMESIZE];
104 	char				conf_name[IF_NAMESIZE];
105 	uint32_t			if_index;
106 	int				removed;
107 	int				link_state;
108 	int				prefix_count;
109 	size_t				datalen;
110 	uint8_t				data[RA_MAX_SIZE];
111 };
112 
113 TAILQ_HEAD(, ra_iface)	ra_interfaces;
114 
115 __dead void		 frontend_shutdown(void);
116 void			 frontend_sig_handler(int, short, void *);
117 void			 frontend_startup(void);
118 void			 icmp6_receive(int, short, void *);
119 void			 join_all_routers_mcast_group(struct ra_iface *);
120 void			 leave_all_routers_mcast_group(struct ra_iface *);
121 int			 get_link_state(char *);
122 void			 merge_ra_interface(char *, char *);
123 void			 merge_ra_interfaces(void);
124 struct ra_iface		*find_ra_iface_by_id(uint32_t);
125 struct ra_iface		*find_ra_iface_by_name(char *);
126 struct ra_iface_conf	*find_ra_iface_conf(struct ra_iface_conf_head *,
127 			    char *);
128 struct ra_prefix_conf	*find_ra_prefix_conf(struct ra_prefix_conf_head*,
129 			    struct in6_addr *, int);
130 void			 add_new_prefix_to_ra_iface(struct ra_iface *r,
131 			    struct in6_addr *, int, struct ra_prefix_conf *);
132 void			 free_ra_iface(struct ra_iface *);
133 int			 in6_mask2prefixlen(struct in6_addr *);
134 void			 get_interface_prefixes(struct ra_iface *,
135 			     struct ra_prefix_conf *);
136 void			 build_packet(struct ra_iface *);
137 void			 build_leaving_packet(struct ra_iface *);
138 void			 ra_output(struct ra_iface *, struct sockaddr_in6 *);
139 void			 get_rtaddrs(int, struct sockaddr *,
140 			     struct sockaddr **);
141 void			 route_receive(int, short, void *);
142 void			 handle_route_message(struct rt_msghdr *,
143 			     struct sockaddr **);
144 
145 struct rad_conf	*frontend_conf;
146 struct imsgev		*iev_main;
147 struct imsgev		*iev_engine;
148 struct event		 ev_route;
149 int			 icmp6sock = -1, ioctlsock = -1, routesock = -1;
150 struct ipv6_mreq	 all_routers;
151 struct sockaddr_in6	 all_nodes;
152 struct msghdr		 sndmhdr;
153 struct iovec		 sndiov[2];
154 
155 void
156 frontend_sig_handler(int sig, short event, void *bula)
157 {
158 	/*
159 	 * Normal signal handler rules don't apply because libevent
160 	 * decouples for us.
161 	 */
162 
163 	switch (sig) {
164 	case SIGINT:
165 	case SIGTERM:
166 		frontend_shutdown();
167 	default:
168 		fatalx("unexpected signal");
169 	}
170 }
171 
172 void
173 frontend(int debug, int verbose)
174 {
175 	struct event		 ev_sigint, ev_sigterm;
176 	struct passwd		*pw;
177 	size_t			 rcvcmsglen, sndcmsgbuflen;
178 	uint8_t			*rcvcmsgbuf;
179 	uint8_t			*sndcmsgbuf = NULL;
180 
181 	frontend_conf = config_new_empty();
182 	control_state.fd = -1;
183 
184 	log_init(debug, LOG_DAEMON);
185 	log_setverbose(verbose);
186 
187 	if ((pw = getpwnam(RAD_USER)) == NULL)
188 		fatal("getpwnam");
189 
190 	if (chroot(pw->pw_dir) == -1)
191 		fatal("chroot");
192 	if (chdir("/") == -1)
193 		fatal("chdir(\"/\")");
194 
195 	rad_process = PROC_FRONTEND;
196 	setproctitle("%s", log_procnames[rad_process]);
197 	log_procinit(log_procnames[rad_process]);
198 
199 	if (setgroups(1, &pw->pw_gid) ||
200 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
201 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
202 		fatal("can't drop privileges");
203 
204 	/* XXX pass in from main */
205 	if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1)
206 		fatal("socket");
207 
208 	if (pledge("stdio inet unix recvfd route mcast", NULL) == -1)
209 		fatal("pledge");
210 
211 	event_init();
212 
213 	/* Setup signal handler. */
214 	signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL);
215 	signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL);
216 	signal_add(&ev_sigint, NULL);
217 	signal_add(&ev_sigterm, NULL);
218 	signal(SIGPIPE, SIG_IGN);
219 	signal(SIGHUP, SIG_IGN);
220 
221 	/* Setup pipe and event handler to the parent process. */
222 	if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
223 		fatal(NULL);
224 	imsg_init(&iev_main->ibuf, 3);
225 	iev_main->handler = frontend_dispatch_main;
226 	iev_main->events = EV_READ;
227 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
228 	    iev_main->handler, iev_main);
229 	event_add(&iev_main->ev, NULL);
230 
231 	rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
232 	    CMSG_SPACE(sizeof(int));
233 	if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL)
234 		fatal("malloc");
235 
236 	icmp6ev.rcviov[0].iov_base = (caddr_t)icmp6ev.answer;
237 	icmp6ev.rcviov[0].iov_len = sizeof(icmp6ev.answer);
238 	icmp6ev.rcvmhdr.msg_name = (caddr_t)&icmp6ev.from;
239 	icmp6ev.rcvmhdr.msg_namelen = sizeof(icmp6ev.from);
240 	icmp6ev.rcvmhdr.msg_iov = icmp6ev.rcviov;
241 	icmp6ev.rcvmhdr.msg_iovlen = 1;
242 	icmp6ev.rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
243 	icmp6ev.rcvmhdr.msg_controllen = rcvcmsglen;
244 
245 	if (inet_pton(AF_INET6, "ff02::2",
246 	    &all_routers.ipv6mr_multiaddr.s6_addr) == -1)
247 		fatal("inet_pton");
248 
249 	all_nodes.sin6_len = sizeof(all_nodes);
250 	all_nodes.sin6_family = AF_INET6;
251 	if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1)
252 		fatal("inet_pton");
253 
254 	sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
255 	    CMSG_SPACE(sizeof(int));
256 	if ((sndcmsgbuf = malloc(sndcmsgbuflen)) == NULL)
257 		fatal("%s", __func__);
258 
259 	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
260 	sndmhdr.msg_iov = sndiov;
261 	sndmhdr.msg_iovlen = 1;
262 	sndmhdr.msg_control = sndcmsgbuf;
263 	sndmhdr.msg_controllen = sndcmsgbuflen;
264 
265 	TAILQ_INIT(&ra_interfaces);
266 
267 	event_dispatch();
268 
269 	frontend_shutdown();
270 }
271 
272 __dead void
273 frontend_shutdown(void)
274 {
275 	/* Close pipes. */
276 	msgbuf_write(&iev_engine->ibuf.w);
277 	msgbuf_clear(&iev_engine->ibuf.w);
278 	close(iev_engine->ibuf.fd);
279 	msgbuf_write(&iev_main->ibuf.w);
280 	msgbuf_clear(&iev_main->ibuf.w);
281 	close(iev_main->ibuf.fd);
282 
283 	config_clear(frontend_conf);
284 
285 	free(iev_engine);
286 	free(iev_main);
287 
288 	log_info("frontend exiting");
289 	exit(0);
290 }
291 
292 int
293 frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen)
294 {
295 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data,
296 	    datalen));
297 }
298 
299 int
300 frontend_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen)
301 {
302 	return (imsg_compose_event(iev_engine, type, 0, pid, -1, data,
303 	    datalen));
304 }
305 
306 void
307 frontend_dispatch_main(int fd, short event, void *bula)
308 {
309 	static struct rad_conf		*nconf;
310 	static struct ra_iface_conf	*ra_iface_conf;
311 	static struct ra_options_conf	*ra_options;
312 	struct imsg			 imsg;
313 	struct imsgev			*iev = bula;
314 	struct imsgbuf			*ibuf = &iev->ibuf;
315 	struct ra_prefix_conf		*ra_prefix_conf;
316 	struct ra_rdnss_conf		*ra_rdnss_conf;
317 	struct ra_dnssl_conf		*ra_dnssl_conf;
318 	int				 n, shut = 0;
319 
320 	if (event & EV_READ) {
321 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
322 			fatal("imsg_read error");
323 		if (n == 0)	/* Connection closed. */
324 			shut = 1;
325 	}
326 	if (event & EV_WRITE) {
327 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
328 			fatal("msgbuf_write");
329 		if (n == 0)	/* Connection closed. */
330 			shut = 1;
331 	}
332 
333 	for (;;) {
334 		if ((n = imsg_get(ibuf, &imsg)) == -1)
335 			fatal("%s: imsg_get error", __func__);
336 		if (n == 0)	/* No more messages. */
337 			break;
338 
339 		switch (imsg.hdr.type) {
340 		case IMSG_SOCKET_IPC:
341 			/*
342 			 * Setup pipe and event handler to the engine
343 			 * process.
344 			 */
345 			if (iev_engine)
346 				fatalx("%s: received unexpected imsg fd to "
347 				    "frontend", __func__);
348 			if ((fd = imsg.fd) == -1)
349 				fatalx("%s: expected to receive imsg fd to "
350 				   "frontend but didn't receive any",
351 				   __func__);
352 
353 			iev_engine = malloc(sizeof(struct imsgev));
354 			if (iev_engine == NULL)
355 				fatal(NULL);
356 
357 			imsg_init(&iev_engine->ibuf, fd);
358 			iev_engine->handler = frontend_dispatch_engine;
359 			iev_engine->events = EV_READ;
360 
361 			event_set(&iev_engine->ev, iev_engine->ibuf.fd,
362 			iev_engine->events, iev_engine->handler, iev_engine);
363 			event_add(&iev_engine->ev, NULL);
364 			break;
365 		case IMSG_RECONF_CONF:
366 			if (nconf != NULL)
367 				fatalx("%s: IMSG_RECONF_CONF already in "
368 				    "progress", __func__);
369 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct rad_conf))
370 				fatalx("%s: IMSG_RECONF_CONF wrong length: %lu",
371 				    __func__, IMSG_DATA_SIZE(imsg));
372 			if ((nconf = malloc(sizeof(struct rad_conf))) ==
373 			    NULL)
374 				fatal(NULL);
375 			memcpy(nconf, imsg.data, sizeof(struct rad_conf));
376 			SIMPLEQ_INIT(&nconf->ra_iface_list);
377 			SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list);
378 			SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list);
379 			ra_options = &nconf->ra_options;
380 			break;
381 		case IMSG_RECONF_RA_IFACE:
382 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
383 			    ra_iface_conf))
384 				fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: "
385 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
386 			if ((ra_iface_conf = malloc(sizeof(struct
387 			    ra_iface_conf))) == NULL)
388 				fatal(NULL);
389 			memcpy(ra_iface_conf, imsg.data, sizeof(struct
390 			    ra_iface_conf));
391 			ra_iface_conf->autoprefix = NULL;
392 			SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list);
393 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list);
394 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list);
395 			SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list,
396 			    ra_iface_conf, entry);
397 			ra_options = &ra_iface_conf->ra_options;
398 			break;
399 		case IMSG_RECONF_RA_AUTOPREFIX:
400 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
401 			    ra_prefix_conf))
402 				fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong "
403 				    "length: %lu", __func__,
404 				    IMSG_DATA_SIZE(imsg));
405 			if ((ra_iface_conf->autoprefix = malloc(sizeof(struct
406 			    ra_prefix_conf))) == NULL)
407 				fatal(NULL);
408 			memcpy(ra_iface_conf->autoprefix, imsg.data,
409 			    sizeof(struct ra_prefix_conf));
410 			break;
411 		case IMSG_RECONF_RA_PREFIX:
412 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
413 			    ra_prefix_conf))
414 				fatalx("%s: IMSG_RECONF_RA_PREFIX wrong "
415 				    "length: %lu", __func__,
416 				    IMSG_DATA_SIZE(imsg));
417 			if ((ra_prefix_conf = malloc(sizeof(struct
418 			    ra_prefix_conf))) == NULL)
419 				fatal(NULL);
420 			memcpy(ra_prefix_conf, imsg.data,
421 			    sizeof(struct ra_prefix_conf));
422 			SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list,
423 			    ra_prefix_conf, entry);
424 			break;
425 		case IMSG_RECONF_RA_RDNSS:
426 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
427 			    ra_rdnss_conf))
428 				fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: "
429 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
430 			if ((ra_rdnss_conf = malloc(sizeof(struct
431 			    ra_rdnss_conf))) == NULL)
432 				fatal(NULL);
433 			memcpy(ra_rdnss_conf, imsg.data, sizeof(struct
434 			    ra_rdnss_conf));
435 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list,
436 			    ra_rdnss_conf, entry);
437 			break;
438 		case IMSG_RECONF_RA_DNSSL:
439 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
440 			    ra_dnssl_conf))
441 				fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: "
442 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
443 			if ((ra_dnssl_conf = malloc(sizeof(struct
444 			    ra_dnssl_conf))) == NULL)
445 				fatal(NULL);
446 			memcpy(ra_dnssl_conf, imsg.data, sizeof(struct
447 			    ra_dnssl_conf));
448 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list,
449 			    ra_dnssl_conf, entry);
450 			break;
451 		case IMSG_RECONF_END:
452 			if (nconf == NULL)
453 				fatalx("%s: IMSG_RECONF_END without "
454 				    "IMSG_RECONF_CONF", __func__);
455 			merge_config(frontend_conf, nconf);
456 			merge_ra_interfaces();
457 			nconf = NULL;
458 			break;
459 		case IMSG_ICMP6SOCK:
460 			if (icmp6sock != -1)
461 				fatalx("%s: received unexpected icmp6 fd",
462 				    __func__);
463 			if ((icmp6sock = imsg.fd) == -1)
464 				fatalx("%s: expected to receive imsg "
465 				    "ICMPv6 fd but didn't receive any",
466 				    __func__);
467 			event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST,
468 			    icmp6_receive, NULL);
469 			break;
470 		case IMSG_ROUTESOCK:
471 			if (routesock != -1)
472 				fatalx("%s: received unexpected routesock fd",
473 				    __func__);
474 			if ((routesock = imsg.fd) == -1)
475 				fatalx("%s: expected to receive imsg "
476 				    "routesocket fd but didn't receive any",
477 				    __func__);
478 			event_set(&ev_route, routesock, EV_READ | EV_PERSIST,
479 			    route_receive, NULL);
480 			break;
481 		case IMSG_STARTUP:
482 			if (pledge("stdio inet unix route mcast", NULL) == -1)
483 				fatal("pledge");
484 			frontend_startup();
485 			break;
486 		case IMSG_CONTROLFD:
487 			if (control_state.fd != -1)
488 				fatalx("%s: received unexpected controlsock",
489 				    __func__);
490 			if ((fd = imsg.fd) == -1)
491 				fatalx("%s: expected to receive imsg "
492 				    "control fd but didn't receive any",
493 				    __func__);
494 			control_state.fd = fd;
495 			/* Listen on control socket. */
496 			TAILQ_INIT(&ctl_conns);
497 			control_listen();
498 			break;
499 		default:
500 			log_debug("%s: error handling imsg %d", __func__,
501 			    imsg.hdr.type);
502 			break;
503 		}
504 		imsg_free(&imsg);
505 	}
506 	if (!shut)
507 		imsg_event_add(iev);
508 	else {
509 		/* This pipe is dead. Remove its event handler. */
510 		event_del(&iev->ev);
511 		event_loopexit(NULL);
512 	}
513 }
514 
515 void
516 frontend_dispatch_engine(int fd, short event, void *bula)
517 {
518 	struct imsgev		*iev = bula;
519 	struct imsgbuf		*ibuf = &iev->ibuf;
520 	struct imsg		 imsg;
521 	struct imsg_send_ra	 send_ra;
522 	struct ra_iface		*ra_iface;
523 	uint32_t		 if_index;
524 	int			 n, shut = 0;
525 
526 	if (event & EV_READ) {
527 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
528 			fatal("imsg_read error");
529 		if (n == 0)	/* Connection closed. */
530 			shut = 1;
531 	}
532 	if (event & EV_WRITE) {
533 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
534 			fatal("msgbuf_write");
535 		if (n == 0)	/* Connection closed. */
536 			shut = 1;
537 	}
538 
539 	for (;;) {
540 		if ((n = imsg_get(ibuf, &imsg)) == -1)
541 			fatal("%s: imsg_get error", __func__);
542 		if (n == 0)	/* No more messages. */
543 			break;
544 
545 		switch (imsg.hdr.type) {
546 		case IMSG_SEND_RA:
547 			if (IMSG_DATA_SIZE(imsg) != sizeof(send_ra))
548 				fatalx("%s: IMSG_SEND_RA wrong length: %lu",
549 				    __func__, IMSG_DATA_SIZE(imsg));
550 			memcpy(&send_ra, imsg.data, sizeof(send_ra));
551 			ra_iface = find_ra_iface_by_id(send_ra.if_index);
552 			if (ra_iface)
553 				ra_output(ra_iface, &send_ra.to);
554 			break;
555 		case IMSG_REMOVE_IF:
556 			if (IMSG_DATA_SIZE(imsg) != sizeof(if_index))
557 				fatalx("%s: IMSG_REMOVE_IF wrong length: %lu",
558 				    __func__, IMSG_DATA_SIZE(imsg));
559 			memcpy(&if_index, imsg.data, sizeof(if_index));
560 			ra_iface = find_ra_iface_by_id(if_index);
561 			if (ra_iface) {
562 				TAILQ_REMOVE(&ra_interfaces, ra_iface, entry);
563 				free_ra_iface(ra_iface);
564 			}
565 			break;
566 		default:
567 			log_debug("%s: error handling imsg %d", __func__,
568 			    imsg.hdr.type);
569 			break;
570 		}
571 		imsg_free(&imsg);
572 	}
573 	if (!shut)
574 		imsg_event_add(iev);
575 	else {
576 		/* This pipe is dead. Remove its event handler. */
577 		event_del(&iev->ev);
578 		event_loopexit(NULL);
579 	}
580 }
581 
582 void
583 frontend_startup(void)
584 {
585 	if (!event_initialized(&ev_route))
586 		fatalx("%s: did not receive a route socket from the main "
587 		    "process", __func__);
588 
589 	event_add(&ev_route, NULL);
590 
591 	if (!event_initialized(&icmp6ev.ev))
592 		fatalx("%s: did not receive a icmp6 socket fd from the main "
593 		    "process", __func__);
594 
595 	event_add(&icmp6ev.ev, NULL);
596 
597 	frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0);
598 }
599 
600 
601 void
602 icmp6_receive(int fd, short events, void *arg)
603 {
604 	struct imsg_ra_rs	 ra_rs;
605 	struct in6_pktinfo	*pi = NULL;
606 	struct cmsghdr		*cm;
607 	ssize_t			 len;
608 	int			 if_index = 0, *hlimp = NULL;
609 	char			 ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
610 
611 	if ((len = recvmsg(fd, &icmp6ev.rcvmhdr, 0)) == -1) {
612 		log_warn("recvmsg");
613 		return;
614 	}
615 
616 	/* extract optional information via Advanced API */
617 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev.rcvmhdr); cm;
618 	    cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev.rcvmhdr, cm)) {
619 		if (cm->cmsg_level == IPPROTO_IPV6 &&
620 		    cm->cmsg_type == IPV6_PKTINFO &&
621 		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
622 			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
623 			if_index = pi->ipi6_ifindex;
624 		}
625 		if (cm->cmsg_level == IPPROTO_IPV6 &&
626 		    cm->cmsg_type == IPV6_HOPLIMIT &&
627 		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
628 			hlimp = (int *)CMSG_DATA(cm);
629 	}
630 
631 	if (if_index == 0) {
632 		log_warnx("failed to get receiving interface");
633 		return;
634 	}
635 
636 	if (hlimp == NULL) {
637 		log_warnx("failed to get receiving hop limit");
638 		return;
639 	}
640 
641 	if (*hlimp != 255) {
642 		log_warnx("invalid RA or RS with hop limit of %d from %s on %s",
643 		    *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr,
644 		    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
645 		    ifnamebuf));
646 		return;
647 	}
648 
649 	log_debug("RA or RS with hop limit of %d from %s on %s",
650 	    *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr,
651 	    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
652 	    ifnamebuf));
653 
654 	if ((size_t)len > sizeof(ra_rs.packet)) {
655 		log_warnx("invalid RA or RS with size %ld from %s on %s",
656 		    len, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr,
657 		    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
658 		    ifnamebuf));
659 		return;
660 	}
661 
662 	ra_rs.if_index = if_index;
663 	memcpy(&ra_rs.from,  &icmp6ev.from, sizeof(ra_rs.from));
664 	ra_rs.len = len;
665 	memcpy(ra_rs.packet, icmp6ev.answer, len);
666 
667 	frontend_imsg_compose_engine(IMSG_RA_RS, 0, &ra_rs, sizeof(ra_rs));
668 }
669 
670 void
671 join_all_routers_mcast_group(struct ra_iface *ra_iface)
672 {
673 	log_debug("joining multicast group on %s", ra_iface->name);
674 	all_routers.ipv6mr_interface = ra_iface->if_index;
675 	if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
676 	    &all_routers, sizeof(all_routers)) == -1)
677 		fatal("IPV6_JOIN_GROUP(%s)", ra_iface->name);
678 }
679 
680 void
681 leave_all_routers_mcast_group(struct ra_iface *ra_iface)
682 {
683 	log_debug("leaving multicast group on %s", ra_iface->name);
684 	all_routers.ipv6mr_interface = ra_iface->if_index;
685 	setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
686 	    &all_routers, sizeof(all_routers));
687 }
688 
689 struct ra_iface*
690 find_ra_iface_by_id(uint32_t if_index)
691 {
692 	struct ra_iface	*ra_iface;
693 
694 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
695 		if (ra_iface->if_index == if_index)
696 			return ra_iface;
697 	}
698 	return (NULL);
699 }
700 
701 struct ra_iface*
702 find_ra_iface_by_name(char *if_name)
703 {
704 	struct ra_iface	*ra_iface;
705 
706 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
707 		if (strcmp(ra_iface->name, if_name) == 0)
708 			return ra_iface;
709 	}
710 	return (NULL);
711 }
712 
713 struct ra_iface_conf*
714 find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name)
715 {
716 	struct ra_iface_conf	*ra_iface_conf;
717 
718 	SIMPLEQ_FOREACH(ra_iface_conf, head, entry) {
719 		if (strcmp(ra_iface_conf->name, if_name) == 0)
720 			return ra_iface_conf;
721 	}
722 	return (NULL);
723 }
724 
725 int
726 get_link_state(char *if_name)
727 {
728 	struct ifaddrs	*ifap, *ifa;
729 	int		 ls = LINK_STATE_UNKNOWN;
730 
731 	if (getifaddrs(&ifap) != 0) {
732 		log_warn("getifaddrs");
733 		return LINK_STATE_UNKNOWN;
734 	}
735 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
736 		if (ifa->ifa_addr->sa_family != AF_LINK)
737 			continue;
738 		if (strcmp(if_name, ifa->ifa_name) != 0)
739 			continue;
740 
741 		ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
742 		break;
743 	}
744 	freeifaddrs(ifap);
745 	return ls;
746 }
747 
748 void
749 merge_ra_interface(char *name, char *conf_name)
750 {
751 	struct ra_iface		*ra_iface;
752 	uint32_t		 if_index;
753 	int			 link_state;
754 
755 	link_state = get_link_state(name);
756 
757 	if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
758 		ra_iface->link_state = link_state;
759 		if (!LINK_STATE_IS_UP(link_state)) {
760 			log_debug("%s down, ignoring", name);
761 			ra_iface->removed = 1;
762 		} else {
763 			log_debug("keeping interface %s", name);
764 			ra_iface->removed = 0;
765 		}
766 		return;
767 	}
768 
769 	if (!LINK_STATE_IS_UP(link_state)) {
770 		log_debug("%s down, ignoring", name);
771 		return;
772 	}
773 
774 	log_debug("new interface %s", name);
775 	if ((if_index = if_nametoindex(name)) == 0)
776 		return;
777 
778 	log_debug("adding interface %s", name);
779 	if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
780 		fatal("%s", __func__);
781 
782 	strlcpy(ra_iface->name, name, sizeof(ra_iface->name));
783 	strlcpy(ra_iface->conf_name, conf_name,
784 	    sizeof(ra_iface->conf_name));
785 
786 	ra_iface->if_index = if_index;
787 	SIMPLEQ_INIT(&ra_iface->prefixes);
788 	TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry);
789 	join_all_routers_mcast_group(ra_iface);
790 }
791 
792 void
793 merge_ra_interfaces(void)
794 {
795 	struct ra_iface_conf	*ra_iface_conf;
796 	struct ra_prefix_conf	*ra_prefix_conf;
797 	struct ra_iface		*ra_iface;
798 	struct ifgroupreq	 ifgr;
799 	struct ifg_req		*ifg;
800 	char			*conf_name;
801 	unsigned int		 len;
802 
803 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry)
804 		ra_iface->removed = 1;
805 
806 	SIMPLEQ_FOREACH(ra_iface_conf, &frontend_conf->ra_iface_list, entry) {
807 		conf_name = ra_iface_conf->name;
808 
809 		/* check if network interface or group */
810 		if (isdigit((unsigned char)conf_name[strlen(conf_name) - 1])) {
811 			merge_ra_interface(conf_name, conf_name);
812 		} else {
813 			log_debug("interface group %s", conf_name);
814 
815 			memset(&ifgr, 0, sizeof(ifgr));
816 			strlcpy(ifgr.ifgr_name, conf_name,
817 			    sizeof(ifgr.ifgr_name));
818 			if (ioctl(ioctlsock, SIOCGIFGMEMB,
819 			    (caddr_t)&ifgr) == -1)
820 				continue;
821 
822 			len = ifgr.ifgr_len;
823 			if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
824 				fatal("%s: calloc", __func__);
825 			if (ioctl(ioctlsock, SIOCGIFGMEMB,
826 			    (caddr_t)&ifgr) == -1) {
827 				log_debug("group %s without members",
828 				    conf_name);
829 				free(ifgr.ifgr_groups);
830 				continue;
831 			}
832 
833 			for (ifg = ifgr.ifgr_groups;
834 			    (ifg != NULL) && (len >= sizeof(struct ifg_req));
835 			    ifg++) {
836 				len -= sizeof(struct ifg_req);
837 				merge_ra_interface(ifg->ifgrq_member,
838 				    conf_name);
839 			}
840 			free(ifgr.ifgr_groups);
841 		}
842 	}
843 
844 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
845 		while ((ra_prefix_conf = SIMPLEQ_FIRST(&ra_iface->prefixes))
846 		    != NULL) {
847 			SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes,
848 			    entry);
849 			free(ra_prefix_conf);
850 		}
851 		ra_iface->prefix_count = 0;
852 
853 		if (ra_iface->removed) {
854 			log_debug("iface removed: %s", ra_iface->name);
855 			build_leaving_packet(ra_iface);
856 			frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0,
857 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
858 			continue;
859 		}
860 
861 		ra_iface_conf = find_ra_iface_conf(
862 		    &frontend_conf->ra_iface_list, ra_iface->conf_name);
863 
864 		log_debug("add static prefixes for %s", ra_iface->name);
865 
866 		SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list,
867 		    entry) {
868 			add_new_prefix_to_ra_iface(ra_iface,
869 			    &ra_prefix_conf->prefix,
870 			    ra_prefix_conf->prefixlen, ra_prefix_conf);
871 		}
872 
873 		if (ra_iface_conf->autoprefix)
874 			get_interface_prefixes(ra_iface,
875 			    ra_iface_conf->autoprefix);
876 
877 		build_packet(ra_iface);
878 	}
879 }
880 
881 void
882 free_ra_iface(struct ra_iface *ra_iface)
883 {
884 	struct ra_prefix_conf	*prefix;
885 
886 	leave_all_routers_mcast_group(ra_iface);
887 
888 	while ((prefix = SIMPLEQ_FIRST(&ra_iface->prefixes)) != NULL) {
889 		SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, entry);
890 		free(prefix);
891 	}
892 
893 	free(ra_iface);
894 }
895 
896 /* from kame via ifconfig, where it's called prefix() */
897 int
898 in6_mask2prefixlen(struct in6_addr *in6)
899 {
900 	u_char *nam = (u_char *)in6;
901 	int byte, bit, plen = 0, size = sizeof(struct in6_addr);
902 
903 	for (byte = 0; byte < size; byte++, plen += 8)
904 		if (nam[byte] != 0xff)
905 			break;
906 	if (byte == size)
907 		return (plen);
908 	for (bit = 7; bit != 0; bit--, plen++)
909 		if (!(nam[byte] & (1 << bit)))
910 			break;
911 	for (; bit != 0; bit--)
912 		if (nam[byte] & (1 << bit))
913 			return (0);
914 	byte++;
915 	for (; byte < size; byte++)
916 		if (nam[byte])
917 			return (0);
918 	return (plen);
919 }
920 
921 void
922 get_interface_prefixes(struct ra_iface *ra_iface, struct ra_prefix_conf
923     *autoprefix)
924 {
925 	struct in6_ifreq	 ifr6;
926 	struct ifaddrs		*ifap, *ifa;
927 	struct sockaddr_in6	*sin6;
928 	int			 prefixlen;
929 
930 	log_debug("%s: %s", __func__, ra_iface->name);
931 
932 	if (getifaddrs(&ifap) != 0)
933 		fatal("getifaddrs");
934 
935 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
936 		if (strcmp(ra_iface->name, ifa->ifa_name) != 0)
937 			continue;
938 		if (ifa->ifa_addr->sa_family != AF_INET6)
939 			continue;
940 
941 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
942 
943 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
944 			continue;
945 
946 		memset(&ifr6, 0, sizeof(ifr6));
947 		(void) strlcpy(ifr6.ifr_name, ra_iface->name,
948 		    sizeof(ifr6.ifr_name));
949 		memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr));
950 
951 		if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) == -1)
952 			continue; /* addr got deleted while we were looking */
953 
954 		prefixlen = in6_mask2prefixlen(&((struct sockaddr_in6 *)
955 		    &ifr6.ifr_addr)->sin6_addr);
956 
957 		if (prefixlen == 128)
958 			continue;
959 
960 		mask_prefix(&sin6->sin6_addr, prefixlen);
961 
962 		add_new_prefix_to_ra_iface(ra_iface, &sin6->sin6_addr,
963 		    prefixlen, autoprefix);
964 	}
965 	freeifaddrs(ifap);
966 }
967 
968 struct ra_prefix_conf*
969 find_ra_prefix_conf(struct ra_prefix_conf_head* head, struct in6_addr *prefix,
970     int prefixlen)
971 {
972 	struct ra_prefix_conf	*ra_prefix_conf;
973 
974 	SIMPLEQ_FOREACH(ra_prefix_conf, head, entry) {
975 		if (ra_prefix_conf->prefixlen == prefixlen &&
976 		    memcmp(&ra_prefix_conf->prefix, prefix, sizeof(*prefix)) ==
977 		    0)
978 			return (ra_prefix_conf);
979 	}
980 	return (NULL);
981 }
982 
983 void
984 add_new_prefix_to_ra_iface(struct ra_iface *ra_iface, struct in6_addr *addr,
985     int prefixlen, struct ra_prefix_conf *ra_prefix_conf)
986 {
987 	struct ra_prefix_conf	*new_ra_prefix_conf;
988 
989 	if (find_ra_prefix_conf(&ra_iface->prefixes, addr, prefixlen)) {
990 		log_debug("ignoring duplicate %s/%d prefix",
991 		    in6_to_str(addr), prefixlen);
992 		return;
993 	}
994 
995 	log_debug("adding %s/%d prefix", in6_to_str(addr), prefixlen);
996 
997 	if ((new_ra_prefix_conf = calloc(1, sizeof(*ra_prefix_conf))) == NULL)
998 		fatal("%s", __func__);
999 	new_ra_prefix_conf->prefix = *addr;
1000 	new_ra_prefix_conf->prefixlen = prefixlen;
1001 	new_ra_prefix_conf->vltime = ra_prefix_conf->vltime;
1002 	new_ra_prefix_conf->pltime = ra_prefix_conf->pltime;
1003 	new_ra_prefix_conf->aflag = ra_prefix_conf->aflag;
1004 	new_ra_prefix_conf->lflag = ra_prefix_conf->lflag;
1005 	SIMPLEQ_INSERT_TAIL(&ra_iface->prefixes, new_ra_prefix_conf, entry);
1006 	ra_iface->prefix_count++;
1007 }
1008 
1009 void
1010 build_packet(struct ra_iface *ra_iface)
1011 {
1012 	struct nd_router_advert		*ra;
1013 	struct nd_opt_mtu		*ndopt_mtu;
1014 	struct nd_opt_prefix_info	*ndopt_pi;
1015 	struct ra_iface_conf		*ra_iface_conf;
1016 	struct ra_options_conf		*ra_options_conf;
1017 	struct ra_prefix_conf		*ra_prefix_conf;
1018 	struct nd_opt_rdnss		*ndopt_rdnss;
1019 	struct nd_opt_dnssl		*ndopt_dnssl;
1020 	struct ra_rdnss_conf		*ra_rdnss;
1021 	struct ra_dnssl_conf		*ra_dnssl;
1022 	size_t				 len, label_len;
1023 	uint8_t				*p, buf[RA_MAX_SIZE];
1024 	char				*label_start, *label_end;
1025 
1026 	ra_iface_conf = find_ra_iface_conf(&frontend_conf->ra_iface_list,
1027 	    ra_iface->conf_name);
1028 	ra_options_conf = &ra_iface_conf->ra_options;
1029 
1030 	len = sizeof(*ra);
1031 	if (ra_options_conf->mtu > 0)
1032 		len += sizeof(*ndopt_mtu);
1033 	len += sizeof(*ndopt_pi) * ra_iface->prefix_count;
1034 	if (ra_iface_conf->ra_options.rdnss_count > 0)
1035 		len += sizeof(*ndopt_rdnss) +
1036 		    ra_iface_conf->ra_options.rdnss_count *
1037 		    sizeof(struct in6_addr);
1038 
1039 	if (ra_iface_conf->ra_options.dnssl_len > 0)
1040 		/* round up to 8 byte boundary */
1041 		len += sizeof(*ndopt_dnssl) +
1042 		    ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7);
1043 
1044 	if (len > sizeof(ra_iface->data))
1045 		fatalx("%s: packet too big", __func__); /* XXX send multiple */
1046 
1047 	p = buf;
1048 
1049 	ra = (struct nd_router_advert *)p;
1050 
1051 	memset(ra, 0, sizeof(*ra));
1052 
1053 	ra->nd_ra_type = ND_ROUTER_ADVERT;
1054 	ra->nd_ra_curhoplimit = ra_options_conf->cur_hl;
1055 	if (ra_options_conf->m_flag)
1056 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
1057 	if (ra_options_conf->o_flag)
1058 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
1059 	if (ra_iface->removed)
1060 		/* tell clients that we are no longer a default router */
1061 		ra->nd_ra_router_lifetime = 0;
1062 	else if (ra_options_conf->dfr) {
1063 		ra->nd_ra_router_lifetime =
1064 		    htons(ra_options_conf->router_lifetime);
1065 	}
1066 	ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time);
1067 	ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer);
1068 	p += sizeof(*ra);
1069 
1070 	if (ra_options_conf->mtu > 0) {
1071 		ndopt_mtu = (struct nd_opt_mtu *)p;
1072 		ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
1073 		ndopt_mtu->nd_opt_mtu_len = 1;
1074 		ndopt_mtu->nd_opt_mtu_reserved = 0;
1075 		ndopt_mtu->nd_opt_mtu_mtu = htonl(ra_options_conf->mtu);
1076 		p += sizeof(*ndopt_mtu);
1077 	}
1078 
1079 	SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface->prefixes, entry) {
1080 		ndopt_pi = (struct nd_opt_prefix_info *)p;
1081 		memset(ndopt_pi, 0, sizeof(*ndopt_pi));
1082 		ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
1083 		ndopt_pi->nd_opt_pi_len = 4;
1084 		ndopt_pi->nd_opt_pi_prefix_len = ra_prefix_conf->prefixlen;
1085 		if (ra_prefix_conf->lflag)
1086 			ndopt_pi->nd_opt_pi_flags_reserved |=
1087 			    ND_OPT_PI_FLAG_ONLINK;
1088 		if (ra_prefix_conf->aflag)
1089 			ndopt_pi->nd_opt_pi_flags_reserved |=
1090 			    ND_OPT_PI_FLAG_AUTO;
1091 		ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
1092 		ndopt_pi->nd_opt_pi_preferred_time =
1093 		    htonl(ra_prefix_conf->pltime);
1094 		ndopt_pi->nd_opt_pi_prefix = ra_prefix_conf->prefix;
1095 
1096 		p += sizeof(*ndopt_pi);
1097 	}
1098 
1099 	if (ra_iface_conf->ra_options.rdnss_count > 0) {
1100 		ndopt_rdnss = (struct nd_opt_rdnss *)p;
1101 		ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
1102 		ndopt_rdnss->nd_opt_rdnss_len = 1 +
1103 		    ra_iface_conf->ra_options.rdnss_count * 2;
1104 		ndopt_rdnss->nd_opt_rdnss_reserved = 0;
1105 		ndopt_rdnss->nd_opt_rdnss_lifetime =
1106 		    htonl(ra_iface_conf->ra_options.rdns_lifetime);
1107 		p += sizeof(struct nd_opt_rdnss);
1108 		SIMPLEQ_FOREACH(ra_rdnss,
1109 		    &ra_iface_conf->ra_options.ra_rdnss_list, entry) {
1110 			memcpy(p, &ra_rdnss->rdnss, sizeof(ra_rdnss->rdnss));
1111 			p += sizeof(ra_rdnss->rdnss);
1112 		}
1113 	}
1114 
1115 	if (ra_iface_conf->ra_options.dnssl_len > 0) {
1116 		ndopt_dnssl = (struct nd_opt_dnssl *)p;
1117 		ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
1118 		/* round up to 8 byte boundary */
1119 		ndopt_dnssl->nd_opt_dnssl_len = 1 +
1120 		    ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7) / 8;
1121 		ndopt_dnssl->nd_opt_dnssl_reserved = 0;
1122 		ndopt_dnssl->nd_opt_dnssl_lifetime =
1123 		    htonl(ra_iface_conf->ra_options.rdns_lifetime);
1124 		p += sizeof(struct nd_opt_dnssl);
1125 
1126 		SIMPLEQ_FOREACH(ra_dnssl,
1127 		    &ra_iface_conf->ra_options.ra_dnssl_list, entry) {
1128 			label_start = ra_dnssl->search;
1129 			while ((label_end = strchr(label_start, '.')) != NULL) {
1130 				label_len = label_end - label_start;
1131 				*p++ = label_len;
1132 				memcpy(p, label_start, label_len);
1133 				p += label_len;
1134 				label_start = label_end + 1;
1135 			}
1136 			*p++ = '\0'; /* last dot */
1137 		}
1138 		/* zero pad */
1139 		while (((uintptr_t)p) % 8 != 0)
1140 			*p++ = '\0';
1141 	}
1142 
1143 	if (len != ra_iface->datalen || memcmp(buf, ra_iface->data, len)
1144 	    != 0) {
1145 		memcpy(ra_iface->data, buf, len);
1146 		ra_iface->datalen = len;
1147 		/* packet changed; tell engine to send new advertisments */
1148 		frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
1149 		    &ra_iface->if_index, sizeof(ra_iface->if_index));
1150 	}
1151 }
1152 
1153 void
1154 build_leaving_packet(struct ra_iface *ra_iface)
1155 {
1156 	struct nd_router_advert		 ra;
1157 	size_t				 len;
1158 
1159 	len = sizeof(ra);
1160 
1161 	memset(&ra, 0, sizeof(ra));
1162 
1163 	ra.nd_ra_type = ND_ROUTER_ADVERT;
1164 
1165 	memcpy(ra_iface->data, &ra, sizeof(ra));
1166 	ra_iface->datalen = sizeof(ra);
1167 }
1168 
1169 void
1170 ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to)
1171 {
1172 
1173 	struct cmsghdr		*cm;
1174 	struct in6_pktinfo	*pi;
1175 	ssize_t			 len;
1176 	int			 hoplimit = 255;
1177 
1178 	if (!LINK_STATE_IS_UP(ra_iface->link_state))
1179 		return;
1180 
1181 	sndmhdr.msg_name = to;
1182 	sndmhdr.msg_iov[0].iov_base = ra_iface->data;
1183 	sndmhdr.msg_iov[0].iov_len = ra_iface->datalen;
1184 
1185 	cm = CMSG_FIRSTHDR(&sndmhdr);
1186 	/* specify the outgoing interface */
1187 	cm->cmsg_level = IPPROTO_IPV6;
1188 	cm->cmsg_type = IPV6_PKTINFO;
1189 	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1190 	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
1191 	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));
1192 	pi->ipi6_ifindex = ra_iface->if_index;
1193 
1194 	/* specify the hop limit of the packet */
1195 	cm = CMSG_NXTHDR(&sndmhdr, cm);
1196 	cm->cmsg_level = IPPROTO_IPV6;
1197 	cm->cmsg_type = IPV6_HOPLIMIT;
1198 	cm->cmsg_len = CMSG_LEN(sizeof(int));
1199 	memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
1200 
1201 	log_debug("send RA on %s", ra_iface->name);
1202 
1203 	len = sendmsg(icmp6sock, &sndmhdr, 0);
1204 	if (len == -1)
1205 		log_warn("sendmsg on %s", ra_iface->name);
1206 
1207 }
1208 
1209 #define ROUNDUP(a) \
1210 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1211 
1212 void
1213 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
1214 {
1215 	int	i;
1216 
1217 	for (i = 0; i < RTAX_MAX; i++) {
1218 		if (addrs & (1 << i)) {
1219 			rti_info[i] = sa;
1220 			sa = (struct sockaddr *)((char *)(sa) +
1221 			    ROUNDUP(sa->sa_len));
1222 		} else
1223 			rti_info[i] = NULL;
1224 	}
1225 }
1226 
1227 void
1228 route_receive(int fd, short events, void *arg)
1229 {
1230 	static uint8_t			 *buf;
1231 
1232 	struct rt_msghdr		*rtm;
1233 	struct sockaddr			*sa, *rti_info[RTAX_MAX];
1234 	ssize_t				 n;
1235 
1236 	if (buf == NULL) {
1237 		buf = malloc(ROUTE_SOCKET_BUF_SIZE);
1238 		if (buf == NULL)
1239 			fatal("malloc");
1240 	}
1241 	rtm = (struct rt_msghdr *)buf;
1242 	if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) {
1243 		if (errno == EAGAIN || errno == EINTR)
1244 			return;
1245 		log_warn("dispatch_rtmsg: read error");
1246 		return;
1247 	}
1248 
1249 	if (n == 0)
1250 		fatal("routing socket closed");
1251 
1252 	if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
1253 		log_warnx("partial rtm of %zd in buffer", n);
1254 		return;
1255 	}
1256 
1257 	if (rtm->rtm_version != RTM_VERSION)
1258 		return;
1259 
1260 	sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
1261 	get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1262 
1263 	handle_route_message(rtm, rti_info);
1264 }
1265 
1266 void
1267 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
1268 {
1269 	switch (rtm->rtm_type) {
1270 	case RTM_IFINFO:
1271 	case RTM_NEWADDR:
1272 	case RTM_DELADDR:
1273 		/*
1274 		 * do the same thing as after a config reload when interfaces
1275 		 * change or IPv6 addresses show up / disappear
1276 		 */
1277 		merge_ra_interfaces();
1278 		break;
1279 	default:
1280 		log_debug("unexpected RTM: %d", rtm->rtm_type);
1281 		break;
1282 	}
1283 }
1284