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