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