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