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