xref: /openbsd-src/usr.sbin/rad/frontend.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: frontend.c,v 1.35 2020/12/29 19:47:16 benno Exp $	*/
2 
3 /*
4  * Copyright (c) 2018 Florian Obser <florian@openbsd.org>
5  * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6  * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
24  * All rights reserved.
25  *
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions
28  * are met:
29  * 1. Redistributions of source code must retain the above copyright
30  *    notice, this list of conditions and the following disclaimer.
31  * 2. Redistributions in binary form must reproduce the above copyright
32  *    notice, this list of conditions and the following disclaimer in the
33  *    documentation and/or other materials provided with the distribution.
34  * 3. Neither the name of the project nor the names of its contributors
35  *    may be used to endorse or promote products derived from this software
36  *    without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
39  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
42  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  */
50 
51 #include <sys/types.h>
52 #include <sys/ioctl.h>
53 #include <sys/queue.h>
54 #include <sys/socket.h>
55 #include <sys/syslog.h>
56 #include <sys/uio.h>
57 
58 #include <net/if.h>
59 #include <net/if_types.h>
60 #include <net/route.h>
61 
62 #include <arpa/inet.h>
63 
64 #include <netinet/in.h>
65 #include <netinet/if_ether.h>
66 #include <netinet6/nd6.h>
67 #include <netinet6/in6_var.h>
68 #include <netinet/ip6.h>
69 #include <netinet6/ip6_var.h>
70 #include <netinet/icmp6.h>
71 
72 #include <ctype.h>
73 #include <errno.h>
74 #include <event.h>
75 #include <ifaddrs.h>
76 #include <imsg.h>
77 #include <pwd.h>
78 #include <signal.h>
79 #include <stdio.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <unistd.h>
83 
84 #include "log.h"
85 #include "rad.h"
86 #include "frontend.h"
87 #include "control.h"
88 
89 #define	RA_MAX_SIZE		1500
90 #define	ROUTE_SOCKET_BUF_SIZE	16384
91 
92 struct icmp6_ev {
93 	struct event		 ev;
94 	uint8_t			 answer[1500];
95 	struct msghdr		 rcvmhdr;
96 	struct iovec		 rcviov[1];
97 	struct sockaddr_in6	 from;
98 	int			 refcnt;
99 };
100 
101 struct ra_iface {
102 	TAILQ_ENTRY(ra_iface)		 entry;
103 	struct icmp6_ev			*icmp6ev;
104 	struct ra_prefix_conf_head	 prefixes;
105 	char				 name[IF_NAMESIZE];
106 	char				 conf_name[IF_NAMESIZE];
107 	uint32_t			 if_index;
108 	int				 rdomain;
109 	int				 removed;
110 	int				 link_state;
111 	int				 prefix_count;
112 	size_t				 datalen;
113 	uint8_t				 data[RA_MAX_SIZE];
114 };
115 
116 TAILQ_HEAD(, ra_iface)	ra_interfaces;
117 
118 __dead void		 frontend_shutdown(void);
119 void			 frontend_sig_handler(int, short, void *);
120 void			 frontend_startup(void);
121 void			 icmp6_receive(int, short, void *);
122 void			 join_all_routers_mcast_group(struct ra_iface *);
123 void			 leave_all_routers_mcast_group(struct ra_iface *);
124 int			 get_link_state(char *);
125 int			 get_ifrdomain(char *);
126 void			 merge_ra_interface(char *, char *);
127 void			 merge_ra_interfaces(void);
128 struct ra_iface		*find_ra_iface_by_id(uint32_t);
129 struct ra_iface		*find_ra_iface_by_name(char *);
130 struct ra_iface_conf	*find_ra_iface_conf(struct ra_iface_conf_head *,
131 			    char *);
132 struct ra_prefix_conf	*find_ra_prefix_conf(struct ra_prefix_conf_head*,
133 			    struct in6_addr *, int);
134 struct icmp6_ev		*get_icmp6ev_by_rdomain(int);
135 void			 unref_icmp6ev(struct ra_iface *);
136 void			 set_icmp6sock(int, int);
137 void			 add_new_prefix_to_ra_iface(struct ra_iface *r,
138 			    struct in6_addr *, int, struct ra_prefix_conf *);
139 void			 free_ra_iface(struct ra_iface *);
140 int			 in6_mask2prefixlen(struct in6_addr *);
141 void			 get_interface_prefixes(struct ra_iface *,
142 			     struct ra_prefix_conf *);
143 int			 interface_has_linklocal_address(char *);
144 void			 build_packet(struct ra_iface *);
145 void			 build_leaving_packet(struct ra_iface *);
146 void			 ra_output(struct ra_iface *, struct sockaddr_in6 *);
147 void			 get_rtaddrs(int, struct sockaddr *,
148 			     struct sockaddr **);
149 void			 route_receive(int, short, void *);
150 void			 handle_route_message(struct rt_msghdr *,
151 			     struct sockaddr **);
152 
153 struct rad_conf	*frontend_conf;
154 struct imsgev		*iev_main;
155 struct imsgev		*iev_engine;
156 struct event		 ev_route;
157 int			 ioctlsock = -1, routesock = -1;
158 struct ipv6_mreq	 all_routers;
159 struct sockaddr_in6	 all_nodes;
160 struct msghdr		 sndmhdr;
161 struct iovec		 sndiov[2];
162 
163 void
164 frontend_sig_handler(int sig, short event, void *bula)
165 {
166 	/*
167 	 * Normal signal handler rules don't apply because libevent
168 	 * decouples for us.
169 	 */
170 
171 	switch (sig) {
172 	case SIGINT:
173 	case SIGTERM:
174 		frontend_shutdown();
175 	default:
176 		fatalx("unexpected signal");
177 	}
178 }
179 
180 void
181 frontend(int debug, int verbose)
182 {
183 	struct event		 ev_sigint, ev_sigterm;
184 	struct passwd		*pw;
185 	size_t			 sndcmsgbuflen;
186 	uint8_t			*sndcmsgbuf = NULL;
187 
188 	frontend_conf = config_new_empty();
189 	control_state.fd = -1;
190 
191 	log_init(debug, LOG_DAEMON);
192 	log_setverbose(verbose);
193 
194 	if ((pw = getpwnam(RAD_USER)) == NULL)
195 		fatal("getpwnam");
196 
197 	if (chroot(pw->pw_dir) == -1)
198 		fatal("chroot");
199 	if (chdir("/") == -1)
200 		fatal("chdir(\"/\")");
201 
202 	rad_process = PROC_FRONTEND;
203 	setproctitle("%s", log_procnames[rad_process]);
204 	log_procinit(log_procnames[rad_process]);
205 
206 	if (setgroups(1, &pw->pw_gid) ||
207 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
208 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
209 		fatal("can't drop privileges");
210 
211 	/* XXX pass in from main */
212 	if ((ioctlsock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1)
213 		fatal("socket");
214 
215 	if (pledge("stdio inet unix recvfd route mcast", NULL) == -1)
216 		fatal("pledge");
217 
218 	event_init();
219 
220 	/* Setup signal handler. */
221 	signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL);
222 	signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL);
223 	signal_add(&ev_sigint, NULL);
224 	signal_add(&ev_sigterm, NULL);
225 	signal(SIGPIPE, SIG_IGN);
226 	signal(SIGHUP, SIG_IGN);
227 
228 	/* Setup pipe and event handler to the parent process. */
229 	if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
230 		fatal(NULL);
231 	imsg_init(&iev_main->ibuf, 3);
232 	iev_main->handler = frontend_dispatch_main;
233 	iev_main->events = EV_READ;
234 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
235 	    iev_main->handler, iev_main);
236 	event_add(&iev_main->ev, NULL);
237 
238 	if (inet_pton(AF_INET6, "ff02::2",
239 	    &all_routers.ipv6mr_multiaddr.s6_addr) == -1)
240 		fatal("inet_pton");
241 
242 	all_nodes.sin6_len = sizeof(all_nodes);
243 	all_nodes.sin6_family = AF_INET6;
244 	if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1)
245 		fatal("inet_pton");
246 
247 	sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
248 	    CMSG_SPACE(sizeof(int));
249 	if ((sndcmsgbuf = malloc(sndcmsgbuflen)) == NULL)
250 		fatal("%s", __func__);
251 
252 	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
253 	sndmhdr.msg_iov = sndiov;
254 	sndmhdr.msg_iovlen = 1;
255 	sndmhdr.msg_control = sndcmsgbuf;
256 	sndmhdr.msg_controllen = sndcmsgbuflen;
257 
258 	TAILQ_INIT(&ra_interfaces);
259 
260 	event_dispatch();
261 
262 	frontend_shutdown();
263 }
264 
265 __dead void
266 frontend_shutdown(void)
267 {
268 	/* Close pipes. */
269 	msgbuf_write(&iev_engine->ibuf.w);
270 	msgbuf_clear(&iev_engine->ibuf.w);
271 	close(iev_engine->ibuf.fd);
272 	msgbuf_write(&iev_main->ibuf.w);
273 	msgbuf_clear(&iev_main->ibuf.w);
274 	close(iev_main->ibuf.fd);
275 
276 	config_clear(frontend_conf);
277 
278 	free(iev_engine);
279 	free(iev_main);
280 
281 	log_info("frontend exiting");
282 	exit(0);
283 }
284 
285 int
286 frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen)
287 {
288 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data,
289 	    datalen));
290 }
291 
292 int
293 frontend_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen)
294 {
295 	return (imsg_compose_event(iev_engine, type, 0, pid, -1, data,
296 	    datalen));
297 }
298 
299 void
300 frontend_dispatch_main(int fd, short event, void *bula)
301 {
302 	static struct rad_conf		*nconf;
303 	static struct ra_iface_conf	*ra_iface_conf;
304 	static struct ra_options_conf	*ra_options;
305 	struct imsg			 imsg;
306 	struct imsgev			*iev = bula;
307 	struct imsgbuf			*ibuf = &iev->ibuf;
308 	struct ra_prefix_conf		*ra_prefix_conf;
309 	struct ra_rdnss_conf		*ra_rdnss_conf;
310 	struct ra_dnssl_conf		*ra_dnssl_conf;
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.fd) == -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 			ra_options = &nconf->ra_options;
373 			break;
374 		case IMSG_RECONF_RA_IFACE:
375 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
376 			    ra_iface_conf))
377 				fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: "
378 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
379 			if ((ra_iface_conf = malloc(sizeof(struct
380 			    ra_iface_conf))) == NULL)
381 				fatal(NULL);
382 			memcpy(ra_iface_conf, imsg.data, sizeof(struct
383 			    ra_iface_conf));
384 			ra_iface_conf->autoprefix = NULL;
385 			SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list);
386 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list);
387 			SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list);
388 			SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list,
389 			    ra_iface_conf, entry);
390 			ra_options = &ra_iface_conf->ra_options;
391 			break;
392 		case IMSG_RECONF_RA_AUTOPREFIX:
393 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
394 			    ra_prefix_conf))
395 				fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong "
396 				    "length: %lu", __func__,
397 				    IMSG_DATA_SIZE(imsg));
398 			if ((ra_iface_conf->autoprefix = malloc(sizeof(struct
399 			    ra_prefix_conf))) == NULL)
400 				fatal(NULL);
401 			memcpy(ra_iface_conf->autoprefix, imsg.data,
402 			    sizeof(struct ra_prefix_conf));
403 			break;
404 		case IMSG_RECONF_RA_PREFIX:
405 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
406 			    ra_prefix_conf))
407 				fatalx("%s: IMSG_RECONF_RA_PREFIX wrong "
408 				    "length: %lu", __func__,
409 				    IMSG_DATA_SIZE(imsg));
410 			if ((ra_prefix_conf = malloc(sizeof(struct
411 			    ra_prefix_conf))) == NULL)
412 				fatal(NULL);
413 			memcpy(ra_prefix_conf, imsg.data,
414 			    sizeof(struct ra_prefix_conf));
415 			SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list,
416 			    ra_prefix_conf, entry);
417 			break;
418 		case IMSG_RECONF_RA_RDNSS:
419 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
420 			    ra_rdnss_conf))
421 				fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: "
422 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
423 			if ((ra_rdnss_conf = malloc(sizeof(struct
424 			    ra_rdnss_conf))) == NULL)
425 				fatal(NULL);
426 			memcpy(ra_rdnss_conf, imsg.data, sizeof(struct
427 			    ra_rdnss_conf));
428 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list,
429 			    ra_rdnss_conf, entry);
430 			break;
431 		case IMSG_RECONF_RA_DNSSL:
432 			if (IMSG_DATA_SIZE(imsg) != sizeof(struct
433 			    ra_dnssl_conf))
434 				fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: "
435 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
436 			if ((ra_dnssl_conf = malloc(sizeof(struct
437 			    ra_dnssl_conf))) == NULL)
438 				fatal(NULL);
439 			memcpy(ra_dnssl_conf, imsg.data, sizeof(struct
440 			    ra_dnssl_conf));
441 			SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list,
442 			    ra_dnssl_conf, entry);
443 			break;
444 		case IMSG_RECONF_END:
445 			if (nconf == NULL)
446 				fatalx("%s: IMSG_RECONF_END without "
447 				    "IMSG_RECONF_CONF", __func__);
448 			merge_config(frontend_conf, nconf);
449 			merge_ra_interfaces();
450 			nconf = NULL;
451 			break;
452 		case IMSG_ICMP6SOCK:
453 			if ((icmp6sock = imsg.fd) == -1)
454 				fatalx("%s: expected to receive imsg "
455 				    "ICMPv6 fd but didn't receive any",
456 				    __func__);
457 			if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain))
458 				fatalx("%s: IMSG_ICMP6SOCK wrong length: "
459 				    "%lu", __func__, IMSG_DATA_SIZE(imsg));
460 			memcpy(&rdomain, imsg.data, sizeof(rdomain));
461 			set_icmp6sock(icmp6sock, rdomain);
462 			break;
463 		case IMSG_ROUTESOCK:
464 			if (routesock != -1)
465 				fatalx("%s: received unexpected routesock fd",
466 				    __func__);
467 			if ((routesock = imsg.fd) == -1)
468 				fatalx("%s: expected to receive imsg "
469 				    "routesocket fd but didn't receive any",
470 				    __func__);
471 			event_set(&ev_route, routesock, EV_READ | EV_PERSIST,
472 			    route_receive, NULL);
473 			break;
474 		case IMSG_STARTUP:
475 			frontend_startup();
476 			break;
477 		case IMSG_CONTROLFD:
478 			if (control_state.fd != -1)
479 				fatalx("%s: received unexpected controlsock",
480 				    __func__);
481 			if ((fd = imsg.fd) == -1)
482 				fatalx("%s: expected to receive imsg "
483 				    "control fd but didn't receive any",
484 				    __func__);
485 			control_state.fd = fd;
486 			/* Listen on control socket. */
487 			TAILQ_INIT(&ctl_conns);
488 			control_listen();
489 			break;
490 		default:
491 			log_debug("%s: error handling imsg %d", __func__,
492 			    imsg.hdr.type);
493 			break;
494 		}
495 		imsg_free(&imsg);
496 	}
497 	if (!shut)
498 		imsg_event_add(iev);
499 	else {
500 		/* This pipe is dead. Remove its event handler. */
501 		event_del(&iev->ev);
502 		event_loopexit(NULL);
503 	}
504 }
505 
506 void
507 frontend_dispatch_engine(int fd, short event, void *bula)
508 {
509 	struct imsgev		*iev = bula;
510 	struct imsgbuf		*ibuf = &iev->ibuf;
511 	struct imsg		 imsg;
512 	struct imsg_send_ra	 send_ra;
513 	struct ra_iface		*ra_iface;
514 	uint32_t		 if_index;
515 	int			 n, shut = 0;
516 
517 	if (event & EV_READ) {
518 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
519 			fatal("imsg_read error");
520 		if (n == 0)	/* Connection closed. */
521 			shut = 1;
522 	}
523 	if (event & EV_WRITE) {
524 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
525 			fatal("msgbuf_write");
526 		if (n == 0)	/* Connection closed. */
527 			shut = 1;
528 	}
529 
530 	for (;;) {
531 		if ((n = imsg_get(ibuf, &imsg)) == -1)
532 			fatal("%s: imsg_get error", __func__);
533 		if (n == 0)	/* No more messages. */
534 			break;
535 
536 		switch (imsg.hdr.type) {
537 		case IMSG_SEND_RA:
538 			if (IMSG_DATA_SIZE(imsg) != sizeof(send_ra))
539 				fatalx("%s: IMSG_SEND_RA wrong length: %lu",
540 				    __func__, IMSG_DATA_SIZE(imsg));
541 			memcpy(&send_ra, imsg.data, sizeof(send_ra));
542 			ra_iface = find_ra_iface_by_id(send_ra.if_index);
543 			if (ra_iface)
544 				ra_output(ra_iface, &send_ra.to);
545 			break;
546 		case IMSG_REMOVE_IF:
547 			if (IMSG_DATA_SIZE(imsg) != sizeof(if_index))
548 				fatalx("%s: IMSG_REMOVE_IF wrong length: %lu",
549 				    __func__, IMSG_DATA_SIZE(imsg));
550 			memcpy(&if_index, imsg.data, sizeof(if_index));
551 			ra_iface = find_ra_iface_by_id(if_index);
552 			if (ra_iface) {
553 				TAILQ_REMOVE(&ra_interfaces, ra_iface, entry);
554 				free_ra_iface(ra_iface);
555 			}
556 			break;
557 		default:
558 			log_debug("%s: error handling imsg %d", __func__,
559 			    imsg.hdr.type);
560 			break;
561 		}
562 		imsg_free(&imsg);
563 	}
564 	if (!shut)
565 		imsg_event_add(iev);
566 	else {
567 		/* This pipe is dead. Remove its event handler. */
568 		event_del(&iev->ev);
569 		event_loopexit(NULL);
570 	}
571 }
572 
573 void
574 frontend_startup(void)
575 {
576 	if (!event_initialized(&ev_route))
577 		fatalx("%s: did not receive a route socket from the main "
578 		    "process", __func__);
579 
580 	event_add(&ev_route, NULL);
581 }
582 
583 
584 void
585 icmp6_receive(int fd, short events, void *arg)
586 {
587 	struct icmp6_ev		*icmp6ev;
588 	struct icmp6_hdr	*icmp6_hdr;
589 	struct imsg_ra_rs	 ra_rs;
590 	struct in6_pktinfo	*pi = NULL;
591 	struct cmsghdr		*cm;
592 	ssize_t			 len;
593 	int			 if_index = 0, *hlimp = NULL;
594 	char			 ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
595 
596 	icmp6ev = arg;
597 	if ((len = recvmsg(fd, &icmp6ev->rcvmhdr, 0)) == -1) {
598 		log_warn("recvmsg");
599 		return;
600 	}
601 
602 	if ((size_t)len < sizeof(struct icmp6_hdr))
603 		return;
604 
605 	icmp6_hdr = (struct icmp6_hdr *)icmp6ev->answer;
606 	if (icmp6_hdr->icmp6_type != ND_ROUTER_ADVERT &&
607 	    icmp6_hdr->icmp6_type != ND_ROUTER_SOLICIT)
608 		return;
609 
610 	/* extract optional information via Advanced API */
611 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev->rcvmhdr); cm;
612 	    cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev->rcvmhdr, cm)) {
613 		if (cm->cmsg_level == IPPROTO_IPV6 &&
614 		    cm->cmsg_type == IPV6_PKTINFO &&
615 		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
616 			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
617 			if_index = pi->ipi6_ifindex;
618 		}
619 		if (cm->cmsg_level == IPPROTO_IPV6 &&
620 		    cm->cmsg_type == IPV6_HOPLIMIT &&
621 		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
622 			hlimp = (int *)CMSG_DATA(cm);
623 	}
624 
625 	if (if_index == 0) {
626 		log_warnx("failed to get receiving interface");
627 		return;
628 	}
629 
630 	if (hlimp == NULL) {
631 		log_warnx("failed to get receiving hop limit");
632 		return;
633 	}
634 
635 	if (*hlimp != 255) {
636 		log_warnx("invalid RA or RS with hop limit of %d from %s on %s",
637 		    *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
638 		    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
639 		    ifnamebuf));
640 		return;
641 	}
642 
643 	log_debug("RA or RS with hop limit of %d from %s on %s",
644 	    *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
645 	    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
646 	    ifnamebuf));
647 
648 	if ((size_t)len > sizeof(ra_rs.packet)) {
649 		log_warnx("invalid RA or RS with size %ld from %s on %s",
650 		    len, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
651 		    ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
652 		    ifnamebuf));
653 		return;
654 	}
655 
656 	ra_rs.if_index = if_index;
657 	memcpy(&ra_rs.from,  &icmp6ev->from, sizeof(ra_rs.from));
658 	ra_rs.len = len;
659 	memcpy(ra_rs.packet, icmp6ev->answer, len);
660 
661 	frontend_imsg_compose_engine(IMSG_RA_RS, 0, &ra_rs, sizeof(ra_rs));
662 }
663 
664 void
665 join_all_routers_mcast_group(struct ra_iface *ra_iface)
666 {
667 	if (!event_initialized(&ra_iface->icmp6ev->ev))
668 		return;
669 	log_debug("joining multicast group on %s", ra_iface->name);
670 	all_routers.ipv6mr_interface = ra_iface->if_index;
671 	if (setsockopt(EVENT_FD(&ra_iface->icmp6ev->ev), IPPROTO_IPV6,
672 	    IPV6_JOIN_GROUP, &all_routers, sizeof(all_routers)) == -1)
673 		fatal("IPV6_JOIN_GROUP(%s)", ra_iface->name);
674 }
675 
676 void
677 leave_all_routers_mcast_group(struct ra_iface *ra_iface)
678 {
679 	if (!event_initialized(&ra_iface->icmp6ev->ev))
680 		return;
681 	log_debug("leaving multicast group on %s", ra_iface->name);
682 	all_routers.ipv6mr_interface = ra_iface->if_index;
683 	setsockopt(EVENT_FD(&ra_iface->icmp6ev->ev), IPPROTO_IPV6,
684 	    IPV6_LEAVE_GROUP, &all_routers, sizeof(all_routers));
685 }
686 
687 struct ra_iface*
688 find_ra_iface_by_id(uint32_t if_index)
689 {
690 	struct ra_iface	*ra_iface;
691 
692 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
693 		if (ra_iface->if_index == if_index)
694 			return ra_iface;
695 	}
696 	return (NULL);
697 }
698 
699 struct ra_iface*
700 find_ra_iface_by_name(char *if_name)
701 {
702 	struct ra_iface	*ra_iface;
703 
704 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
705 		if (strcmp(ra_iface->name, if_name) == 0)
706 			return ra_iface;
707 	}
708 	return (NULL);
709 }
710 
711 struct ra_iface_conf*
712 find_ra_iface_conf(struct ra_iface_conf_head *head, char *if_name)
713 {
714 	struct ra_iface_conf	*ra_iface_conf;
715 
716 	SIMPLEQ_FOREACH(ra_iface_conf, head, entry) {
717 		if (strcmp(ra_iface_conf->name, if_name) == 0)
718 			return ra_iface_conf;
719 	}
720 	return (NULL);
721 }
722 
723 int
724 get_link_state(char *if_name)
725 {
726 	struct ifaddrs	*ifap, *ifa;
727 	int		 ls = LINK_STATE_UNKNOWN;
728 
729 	if (getifaddrs(&ifap) != 0) {
730 		log_warn("getifaddrs");
731 		return LINK_STATE_UNKNOWN;
732 	}
733 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
734 		if (ifa->ifa_addr == NULL ||
735 		    ifa->ifa_addr->sa_family != AF_LINK)
736 			continue;
737 		if (strcmp(if_name, ifa->ifa_name) != 0)
738 			continue;
739 
740 		ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
741 		break;
742 	}
743 	freeifaddrs(ifap);
744 	return ls;
745 }
746 
747 int
748 get_ifrdomain(char *if_name)
749 {
750 	struct ifreq		 ifr;
751 
752 	strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
753 	if (ioctl(ioctlsock, SIOCGIFRDOMAIN, (caddr_t)&ifr) == -1) {
754 		log_warn("SIOCGIFRDOMAIN");
755 		return -1;
756 	}
757 	return ifr.ifr_rdomainid;
758 }
759 
760 void
761 merge_ra_interface(char *name, char *conf_name)
762 {
763 	struct ra_iface		*ra_iface;
764 	uint32_t		 if_index;
765 	int			 link_state, has_linklocal, ifrdomain;
766 
767 	link_state = get_link_state(name);
768 	has_linklocal = interface_has_linklocal_address(name);
769 	ifrdomain = get_ifrdomain(name);
770 
771 	if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
772 		ra_iface->link_state = link_state;
773 		if (!LINK_STATE_IS_UP(link_state)) {
774 			log_debug("%s down, removing", name);
775 			ra_iface->removed = 1;
776 		} else if (!has_linklocal) {
777 			log_debug("%s has no IPv6 link-local address, "
778 			    "removing", name);
779 			ra_iface->removed = 1;
780 		} else if (ifrdomain == -1) {
781 			log_debug("can't get rdomain for %s, removing", name);
782 			ra_iface->removed = 1;
783 		} else if (ra_iface->rdomain != ifrdomain) {
784 			leave_all_routers_mcast_group(ra_iface);
785 			unref_icmp6ev(ra_iface);
786 			ra_iface->rdomain = ifrdomain;
787 			ra_iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain);
788 			join_all_routers_mcast_group(ra_iface);
789 			ra_iface->removed = 0;
790 		} else {
791 			log_debug("keeping interface %s", name);
792 			ra_iface->removed = 0;
793 		}
794 		return;
795 	}
796 
797 	if (!LINK_STATE_IS_UP(link_state)) {
798 		log_debug("%s down, ignoring", name);
799 		return;
800 	}
801 
802 	if (!has_linklocal) {
803 		log_debug("%s has no IPv6 link-local address, ignoring", name);
804 		return;
805 	}
806 
807 	log_debug("new interface %s", name);
808 	if ((if_index = if_nametoindex(name)) == 0)
809 		return;
810 
811 	log_debug("adding interface %s", name);
812 	if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
813 		fatal("%s", __func__);
814 
815 	strlcpy(ra_iface->name, name, sizeof(ra_iface->name));
816 	strlcpy(ra_iface->conf_name, conf_name,
817 	    sizeof(ra_iface->conf_name));
818 
819 	ra_iface->if_index = if_index;
820 	ra_iface->rdomain = ifrdomain;
821 
822 	SIMPLEQ_INIT(&ra_iface->prefixes);
823 
824 	ra_iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain);
825 	join_all_routers_mcast_group(ra_iface);
826 	TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry);
827 }
828 
829 void
830 merge_ra_interfaces(void)
831 {
832 	struct ra_iface_conf	*ra_iface_conf;
833 	struct ra_prefix_conf	*ra_prefix_conf;
834 	struct ra_iface		*ra_iface;
835 	struct ifgroupreq	 ifgr;
836 	struct ifg_req		*ifg;
837 	char			*conf_name;
838 	unsigned int		 len;
839 
840 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry)
841 		ra_iface->removed = 1;
842 
843 	SIMPLEQ_FOREACH(ra_iface_conf, &frontend_conf->ra_iface_list, entry) {
844 		conf_name = ra_iface_conf->name;
845 
846 		/* check if network interface or group */
847 		if (isdigit((unsigned char)conf_name[strlen(conf_name) - 1])) {
848 			merge_ra_interface(conf_name, conf_name);
849 		} else {
850 			log_debug("interface group %s", conf_name);
851 
852 			memset(&ifgr, 0, sizeof(ifgr));
853 			strlcpy(ifgr.ifgr_name, conf_name,
854 			    sizeof(ifgr.ifgr_name));
855 			if (ioctl(ioctlsock, SIOCGIFGMEMB,
856 			    (caddr_t)&ifgr) == -1)
857 				continue;
858 
859 			len = ifgr.ifgr_len;
860 			if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
861 				fatal("%s: calloc", __func__);
862 			if (ioctl(ioctlsock, SIOCGIFGMEMB,
863 			    (caddr_t)&ifgr) == -1) {
864 				log_debug("group %s without members",
865 				    conf_name);
866 				free(ifgr.ifgr_groups);
867 				continue;
868 			}
869 
870 			for (ifg = ifgr.ifgr_groups;
871 			    (ifg != NULL) && (len >= sizeof(struct ifg_req));
872 			    ifg++) {
873 				len -= sizeof(struct ifg_req);
874 				merge_ra_interface(ifg->ifgrq_member,
875 				    conf_name);
876 			}
877 			free(ifgr.ifgr_groups);
878 		}
879 	}
880 
881 	TAILQ_FOREACH(ra_iface, &ra_interfaces, entry) {
882 		while ((ra_prefix_conf = SIMPLEQ_FIRST(&ra_iface->prefixes))
883 		    != NULL) {
884 			SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes,
885 			    entry);
886 			free(ra_prefix_conf);
887 		}
888 		ra_iface->prefix_count = 0;
889 
890 		if (ra_iface->removed) {
891 			log_debug("iface removed: %s", ra_iface->name);
892 			build_leaving_packet(ra_iface);
893 			frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0,
894 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
895 			continue;
896 		}
897 
898 		ra_iface_conf = find_ra_iface_conf(
899 		    &frontend_conf->ra_iface_list, ra_iface->conf_name);
900 
901 		log_debug("add static prefixes for %s", ra_iface->name);
902 
903 		SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface_conf->ra_prefix_list,
904 		    entry) {
905 			add_new_prefix_to_ra_iface(ra_iface,
906 			    &ra_prefix_conf->prefix,
907 			    ra_prefix_conf->prefixlen, ra_prefix_conf);
908 		}
909 
910 		if (ra_iface_conf->autoprefix)
911 			get_interface_prefixes(ra_iface,
912 			    ra_iface_conf->autoprefix);
913 
914 		build_packet(ra_iface);
915 	}
916 }
917 
918 void
919 free_ra_iface(struct ra_iface *ra_iface)
920 {
921 	struct ra_prefix_conf	*prefix;
922 
923 	leave_all_routers_mcast_group(ra_iface);
924 
925 	while ((prefix = SIMPLEQ_FIRST(&ra_iface->prefixes)) != NULL) {
926 		SIMPLEQ_REMOVE_HEAD(&ra_iface->prefixes, entry);
927 		free(prefix);
928 	}
929 
930 	unref_icmp6ev(ra_iface);
931 	free(ra_iface);
932 }
933 
934 /* from kame via ifconfig, where it's called prefix() */
935 int
936 in6_mask2prefixlen(struct in6_addr *in6)
937 {
938 	u_char *nam = (u_char *)in6;
939 	int byte, bit, plen = 0, size = sizeof(struct in6_addr);
940 
941 	for (byte = 0; byte < size; byte++, plen += 8)
942 		if (nam[byte] != 0xff)
943 			break;
944 	if (byte == size)
945 		return (plen);
946 	for (bit = 7; bit != 0; bit--, plen++)
947 		if (!(nam[byte] & (1 << bit)))
948 			break;
949 	for (; bit != 0; bit--)
950 		if (nam[byte] & (1 << bit))
951 			return (0);
952 	byte++;
953 	for (; byte < size; byte++)
954 		if (nam[byte])
955 			return (0);
956 	return (plen);
957 }
958 
959 int
960 interface_has_linklocal_address(char *name)
961 {
962 	struct ifaddrs		*ifap, *ifa;
963 	struct sockaddr_in6	*sin6;
964 	struct in6_ifreq	 ifr6;
965 	int			 ret = 0;
966 
967 	if (getifaddrs(&ifap) != 0)
968 		fatal("getifaddrs");
969 
970 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
971 		if (strcmp(name, ifa->ifa_name) != 0)
972 			continue;
973 		if (ifa->ifa_addr == NULL ||
974 		    ifa->ifa_addr->sa_family != AF_INET6)
975 			continue;
976 
977 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
978 
979 		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
980 			continue;
981 
982 		memset(&ifr6, 0, sizeof(ifr6));
983 		strlcpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
984 		memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr));
985 		if (ioctl(ioctlsock, SIOCGIFAFLAG_IN6, (caddr_t)&ifr6) == -1) {
986 			log_warn("SIOCGIFAFLAG_IN6");
987 			continue;
988 		}
989 
990 		if (ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_TENTATIVE |
991 		    IN6_IFF_DUPLICATED))
992 			continue;
993 
994 		ret = 1;
995 		break;
996 	}
997 	freeifaddrs(ifap);
998 	return (ret);
999 }
1000 
1001 void
1002 get_interface_prefixes(struct ra_iface *ra_iface, struct ra_prefix_conf
1003     *autoprefix)
1004 {
1005 	struct in6_ifreq	 ifr6;
1006 	struct ifaddrs		*ifap, *ifa;
1007 	struct sockaddr_in6	*sin6;
1008 	int			 prefixlen;
1009 
1010 	log_debug("%s: %s", __func__, ra_iface->name);
1011 
1012 	if (getifaddrs(&ifap) != 0)
1013 		fatal("getifaddrs");
1014 
1015 	for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
1016 		if (strcmp(ra_iface->name, ifa->ifa_name) != 0)
1017 			continue;
1018 		if (ifa->ifa_addr == NULL ||
1019 		    ifa->ifa_addr->sa_family != AF_INET6)
1020 			continue;
1021 
1022 		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1023 
1024 		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
1025 			continue;
1026 
1027 		memset(&ifr6, 0, sizeof(ifr6));
1028 		strlcpy(ifr6.ifr_name, ra_iface->name, sizeof(ifr6.ifr_name));
1029 		memcpy(&ifr6.ifr_addr, sin6, sizeof(ifr6.ifr_addr));
1030 
1031 		if (ioctl(ioctlsock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) == -1)
1032 			continue; /* addr got deleted while we were looking */
1033 
1034 		prefixlen = in6_mask2prefixlen(&((struct sockaddr_in6 *)
1035 		    &ifr6.ifr_addr)->sin6_addr);
1036 
1037 		if (prefixlen == 128)
1038 			continue;
1039 
1040 		mask_prefix(&sin6->sin6_addr, prefixlen);
1041 
1042 		add_new_prefix_to_ra_iface(ra_iface, &sin6->sin6_addr,
1043 		    prefixlen, autoprefix);
1044 	}
1045 	freeifaddrs(ifap);
1046 }
1047 
1048 struct ra_prefix_conf*
1049 find_ra_prefix_conf(struct ra_prefix_conf_head* head, struct in6_addr *prefix,
1050     int prefixlen)
1051 {
1052 	struct ra_prefix_conf	*ra_prefix_conf;
1053 
1054 	SIMPLEQ_FOREACH(ra_prefix_conf, head, entry) {
1055 		if (ra_prefix_conf->prefixlen == prefixlen &&
1056 		    memcmp(&ra_prefix_conf->prefix, prefix, sizeof(*prefix)) ==
1057 		    0)
1058 			return (ra_prefix_conf);
1059 	}
1060 	return (NULL);
1061 }
1062 
1063 void
1064 add_new_prefix_to_ra_iface(struct ra_iface *ra_iface, struct in6_addr *addr,
1065     int prefixlen, struct ra_prefix_conf *ra_prefix_conf)
1066 {
1067 	struct ra_prefix_conf	*new_ra_prefix_conf;
1068 
1069 	if (find_ra_prefix_conf(&ra_iface->prefixes, addr, prefixlen)) {
1070 		log_debug("ignoring duplicate %s/%d prefix",
1071 		    in6_to_str(addr), prefixlen);
1072 		return;
1073 	}
1074 
1075 	log_debug("adding %s/%d prefix", in6_to_str(addr), prefixlen);
1076 
1077 	if ((new_ra_prefix_conf = calloc(1, sizeof(*ra_prefix_conf))) == NULL)
1078 		fatal("%s", __func__);
1079 	new_ra_prefix_conf->prefix = *addr;
1080 	new_ra_prefix_conf->prefixlen = prefixlen;
1081 	new_ra_prefix_conf->vltime = ra_prefix_conf->vltime;
1082 	new_ra_prefix_conf->pltime = ra_prefix_conf->pltime;
1083 	new_ra_prefix_conf->aflag = ra_prefix_conf->aflag;
1084 	new_ra_prefix_conf->lflag = ra_prefix_conf->lflag;
1085 	SIMPLEQ_INSERT_TAIL(&ra_iface->prefixes, new_ra_prefix_conf, entry);
1086 	ra_iface->prefix_count++;
1087 }
1088 
1089 void
1090 build_packet(struct ra_iface *ra_iface)
1091 {
1092 	struct nd_router_advert		*ra;
1093 	struct nd_opt_mtu		*ndopt_mtu;
1094 	struct nd_opt_prefix_info	*ndopt_pi;
1095 	struct ra_iface_conf		*ra_iface_conf;
1096 	struct ra_options_conf		*ra_options_conf;
1097 	struct ra_prefix_conf		*ra_prefix_conf;
1098 	struct nd_opt_rdnss		*ndopt_rdnss;
1099 	struct nd_opt_dnssl		*ndopt_dnssl;
1100 	struct ra_rdnss_conf		*ra_rdnss;
1101 	struct ra_dnssl_conf		*ra_dnssl;
1102 	size_t				 len, label_len;
1103 	uint8_t				*p, buf[RA_MAX_SIZE];
1104 	char				*label_start, *label_end;
1105 
1106 	ra_iface_conf = find_ra_iface_conf(&frontend_conf->ra_iface_list,
1107 	    ra_iface->conf_name);
1108 	ra_options_conf = &ra_iface_conf->ra_options;
1109 
1110 	len = sizeof(*ra);
1111 	if (ra_options_conf->mtu > 0)
1112 		len += sizeof(*ndopt_mtu);
1113 	len += sizeof(*ndopt_pi) * ra_iface->prefix_count;
1114 	if (ra_iface_conf->ra_options.rdnss_count > 0)
1115 		len += sizeof(*ndopt_rdnss) +
1116 		    ra_iface_conf->ra_options.rdnss_count *
1117 		    sizeof(struct in6_addr);
1118 
1119 	if (ra_iface_conf->ra_options.dnssl_len > 0)
1120 		/* round up to 8 byte boundary */
1121 		len += sizeof(*ndopt_dnssl) +
1122 		    ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7);
1123 
1124 	if (len > sizeof(ra_iface->data))
1125 		fatalx("%s: packet too big", __func__); /* XXX send multiple */
1126 
1127 	p = buf;
1128 
1129 	ra = (struct nd_router_advert *)p;
1130 
1131 	memset(ra, 0, sizeof(*ra));
1132 
1133 	ra->nd_ra_type = ND_ROUTER_ADVERT;
1134 	ra->nd_ra_curhoplimit = ra_options_conf->cur_hl;
1135 	if (ra_options_conf->m_flag)
1136 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
1137 	if (ra_options_conf->o_flag)
1138 		ra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
1139 	if (ra_iface->removed)
1140 		/* tell clients that we are no longer a default router */
1141 		ra->nd_ra_router_lifetime = 0;
1142 	else if (ra_options_conf->dfr) {
1143 		ra->nd_ra_router_lifetime =
1144 		    htons(ra_options_conf->router_lifetime);
1145 	}
1146 	ra->nd_ra_reachable = htonl(ra_options_conf->reachable_time);
1147 	ra->nd_ra_retransmit = htonl(ra_options_conf->retrans_timer);
1148 	p += sizeof(*ra);
1149 
1150 	if (ra_options_conf->mtu > 0) {
1151 		ndopt_mtu = (struct nd_opt_mtu *)p;
1152 		ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
1153 		ndopt_mtu->nd_opt_mtu_len = 1;
1154 		ndopt_mtu->nd_opt_mtu_reserved = 0;
1155 		ndopt_mtu->nd_opt_mtu_mtu = htonl(ra_options_conf->mtu);
1156 		p += sizeof(*ndopt_mtu);
1157 	}
1158 
1159 	SIMPLEQ_FOREACH(ra_prefix_conf, &ra_iface->prefixes, entry) {
1160 		ndopt_pi = (struct nd_opt_prefix_info *)p;
1161 		memset(ndopt_pi, 0, sizeof(*ndopt_pi));
1162 		ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
1163 		ndopt_pi->nd_opt_pi_len = 4;
1164 		ndopt_pi->nd_opt_pi_prefix_len = ra_prefix_conf->prefixlen;
1165 		if (ra_prefix_conf->lflag)
1166 			ndopt_pi->nd_opt_pi_flags_reserved |=
1167 			    ND_OPT_PI_FLAG_ONLINK;
1168 		if (ra_prefix_conf->aflag)
1169 			ndopt_pi->nd_opt_pi_flags_reserved |=
1170 			    ND_OPT_PI_FLAG_AUTO;
1171 		ndopt_pi->nd_opt_pi_valid_time = htonl(ra_prefix_conf->vltime);
1172 		ndopt_pi->nd_opt_pi_preferred_time =
1173 		    htonl(ra_prefix_conf->pltime);
1174 		ndopt_pi->nd_opt_pi_prefix = ra_prefix_conf->prefix;
1175 
1176 		p += sizeof(*ndopt_pi);
1177 	}
1178 
1179 	if (ra_iface_conf->ra_options.rdnss_count > 0) {
1180 		ndopt_rdnss = (struct nd_opt_rdnss *)p;
1181 		ndopt_rdnss->nd_opt_rdnss_type = ND_OPT_RDNSS;
1182 		ndopt_rdnss->nd_opt_rdnss_len = 1 +
1183 		    ra_iface_conf->ra_options.rdnss_count * 2;
1184 		ndopt_rdnss->nd_opt_rdnss_reserved = 0;
1185 		ndopt_rdnss->nd_opt_rdnss_lifetime =
1186 		    htonl(ra_iface_conf->ra_options.rdns_lifetime);
1187 		p += sizeof(struct nd_opt_rdnss);
1188 		SIMPLEQ_FOREACH(ra_rdnss,
1189 		    &ra_iface_conf->ra_options.ra_rdnss_list, entry) {
1190 			memcpy(p, &ra_rdnss->rdnss, sizeof(ra_rdnss->rdnss));
1191 			p += sizeof(ra_rdnss->rdnss);
1192 		}
1193 	}
1194 
1195 	if (ra_iface_conf->ra_options.dnssl_len > 0) {
1196 		ndopt_dnssl = (struct nd_opt_dnssl *)p;
1197 		ndopt_dnssl->nd_opt_dnssl_type = ND_OPT_DNSSL;
1198 		/* round up to 8 byte boundary */
1199 		ndopt_dnssl->nd_opt_dnssl_len = 1 +
1200 		    ((ra_iface_conf->ra_options.dnssl_len + 7) & ~7) / 8;
1201 		ndopt_dnssl->nd_opt_dnssl_reserved = 0;
1202 		ndopt_dnssl->nd_opt_dnssl_lifetime =
1203 		    htonl(ra_iface_conf->ra_options.rdns_lifetime);
1204 		p += sizeof(struct nd_opt_dnssl);
1205 
1206 		SIMPLEQ_FOREACH(ra_dnssl,
1207 		    &ra_iface_conf->ra_options.ra_dnssl_list, entry) {
1208 			label_start = ra_dnssl->search;
1209 			while ((label_end = strchr(label_start, '.')) != NULL) {
1210 				label_len = label_end - label_start;
1211 				*p++ = label_len;
1212 				memcpy(p, label_start, label_len);
1213 				p += label_len;
1214 				label_start = label_end + 1;
1215 			}
1216 			*p++ = '\0'; /* last dot */
1217 		}
1218 		/* zero pad */
1219 		while (((uintptr_t)p) % 8 != 0)
1220 			*p++ = '\0';
1221 	}
1222 
1223 	if (len != ra_iface->datalen || memcmp(buf, ra_iface->data, len)
1224 	    != 0) {
1225 		memcpy(ra_iface->data, buf, len);
1226 		ra_iface->datalen = len;
1227 		/* packet changed; tell engine to send new advertisments */
1228 		if (event_initialized(&ra_iface->icmp6ev->ev))
1229 			frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
1230 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
1231 	}
1232 }
1233 
1234 void
1235 build_leaving_packet(struct ra_iface *ra_iface)
1236 {
1237 	struct nd_router_advert		 ra;
1238 	size_t				 len;
1239 
1240 	len = sizeof(ra);
1241 
1242 	memset(&ra, 0, sizeof(ra));
1243 
1244 	ra.nd_ra_type = ND_ROUTER_ADVERT;
1245 
1246 	memcpy(ra_iface->data, &ra, sizeof(ra));
1247 	ra_iface->datalen = sizeof(ra);
1248 }
1249 
1250 void
1251 ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to)
1252 {
1253 
1254 	struct cmsghdr		*cm;
1255 	struct in6_pktinfo	*pi;
1256 	ssize_t			 len;
1257 	int			 hoplimit = 255;
1258 
1259 	if (!LINK_STATE_IS_UP(ra_iface->link_state))
1260 		return;
1261 
1262 	sndmhdr.msg_name = to;
1263 	sndmhdr.msg_iov[0].iov_base = ra_iface->data;
1264 	sndmhdr.msg_iov[0].iov_len = ra_iface->datalen;
1265 
1266 	cm = CMSG_FIRSTHDR(&sndmhdr);
1267 	/* specify the outgoing interface */
1268 	cm->cmsg_level = IPPROTO_IPV6;
1269 	cm->cmsg_type = IPV6_PKTINFO;
1270 	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1271 	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
1272 	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));
1273 	pi->ipi6_ifindex = ra_iface->if_index;
1274 
1275 	/* specify the hop limit of the packet */
1276 	cm = CMSG_NXTHDR(&sndmhdr, cm);
1277 	cm->cmsg_level = IPPROTO_IPV6;
1278 	cm->cmsg_type = IPV6_HOPLIMIT;
1279 	cm->cmsg_len = CMSG_LEN(sizeof(int));
1280 	memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
1281 
1282 	log_debug("send RA on %s", ra_iface->name);
1283 
1284 	len = sendmsg(EVENT_FD(&ra_iface->icmp6ev->ev), &sndmhdr, 0);
1285 	if (len == -1)
1286 		log_warn("sendmsg on %s", ra_iface->name);
1287 
1288 }
1289 
1290 #define ROUNDUP(a) \
1291 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1292 
1293 void
1294 get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
1295 {
1296 	int	i;
1297 
1298 	for (i = 0; i < RTAX_MAX; i++) {
1299 		if (addrs & (1 << i)) {
1300 			rti_info[i] = sa;
1301 			sa = (struct sockaddr *)((char *)(sa) +
1302 			    ROUNDUP(sa->sa_len));
1303 		} else
1304 			rti_info[i] = NULL;
1305 	}
1306 }
1307 
1308 void
1309 route_receive(int fd, short events, void *arg)
1310 {
1311 	static uint8_t			 *buf;
1312 
1313 	struct rt_msghdr		*rtm;
1314 	struct sockaddr			*sa, *rti_info[RTAX_MAX];
1315 	ssize_t				 n;
1316 
1317 	if (buf == NULL) {
1318 		buf = malloc(ROUTE_SOCKET_BUF_SIZE);
1319 		if (buf == NULL)
1320 			fatal("malloc");
1321 	}
1322 	rtm = (struct rt_msghdr *)buf;
1323 	if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) {
1324 		if (errno == EAGAIN || errno == EINTR)
1325 			return;
1326 		log_warn("dispatch_rtmsg: read error");
1327 		return;
1328 	}
1329 
1330 	if (n == 0)
1331 		fatal("routing socket closed");
1332 
1333 	if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
1334 		log_warnx("partial rtm of %zd in buffer", n);
1335 		return;
1336 	}
1337 
1338 	if (rtm->rtm_version != RTM_VERSION)
1339 		return;
1340 
1341 	sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
1342 	get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1343 
1344 	handle_route_message(rtm, rti_info);
1345 }
1346 
1347 void
1348 handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
1349 {
1350 	switch (rtm->rtm_type) {
1351 	case RTM_IFINFO:
1352 	case RTM_NEWADDR:
1353 	case RTM_DELADDR:
1354 	case RTM_CHGADDRATTR:
1355 		/*
1356 		 * do the same thing as after a config reload when interfaces
1357 		 * change or IPv6 addresses show up / disappear
1358 		 */
1359 		merge_ra_interfaces();
1360 		break;
1361 	default:
1362 		log_debug("unexpected RTM: %d", rtm->rtm_type);
1363 		break;
1364 	}
1365 }
1366 
1367 struct icmp6_ev*
1368 get_icmp6ev_by_rdomain(int rdomain)
1369 {
1370 	struct ra_iface	*ra_iface;
1371 	struct icmp6_ev	*icmp6ev = NULL;
1372 
1373 	TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
1374 		if (ra_iface->rdomain == rdomain) {
1375 			icmp6ev = ra_iface->icmp6ev;
1376 			break;
1377 		}
1378 	}
1379 
1380 	if (icmp6ev == NULL) {
1381 		if ((icmp6ev = calloc(1, sizeof(*icmp6ev))) == NULL)
1382 			fatal("calloc");
1383 
1384 		icmp6ev->rcviov[0].iov_base = (caddr_t)icmp6ev->answer;
1385 		icmp6ev->rcviov[0].iov_len = sizeof(icmp6ev->answer);
1386 		icmp6ev->rcvmhdr.msg_name = (caddr_t)&icmp6ev->from;
1387 		icmp6ev->rcvmhdr.msg_namelen = sizeof(icmp6ev->from);
1388 		icmp6ev->rcvmhdr.msg_iov = icmp6ev->rcviov;
1389 		icmp6ev->rcvmhdr.msg_iovlen = 1;
1390 		icmp6ev->rcvmhdr.msg_controllen =
1391 		    CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1392 		    CMSG_SPACE(sizeof(int));
1393 		if ((icmp6ev->rcvmhdr.msg_control = malloc(icmp6ev->
1394 		    rcvmhdr.msg_controllen)) == NULL)
1395 			fatal("malloc");
1396 		frontend_imsg_compose_main(IMSG_OPEN_ICMP6SOCK, 0,
1397 		    &rdomain, sizeof(rdomain));
1398 	}
1399 
1400 	icmp6ev->refcnt++;
1401 	return (icmp6ev);
1402 }
1403 
1404 void
1405 unref_icmp6ev(struct ra_iface *ra_iface)
1406 {
1407 	struct icmp6_ev *icmp6ev = ra_iface->icmp6ev;
1408 
1409 	ra_iface->icmp6ev = NULL;
1410 
1411 	if (icmp6ev != NULL) {
1412 		icmp6ev->refcnt--;
1413 		if (icmp6ev->refcnt == 0) {
1414 			event_del(&icmp6ev->ev);
1415 			close(EVENT_FD(&icmp6ev->ev));
1416 			free(icmp6ev);
1417 		}
1418 	}
1419 }
1420 
1421 void
1422 set_icmp6sock(int icmp6sock, int rdomain)
1423 {
1424 	struct ra_iface	*ra_iface;
1425 
1426 	TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
1427 		if (!event_initialized(&ra_iface->icmp6ev->ev) &&
1428 		    ra_iface->rdomain == rdomain) {
1429 			event_set(&ra_iface->icmp6ev->ev, icmp6sock, EV_READ |
1430 			    EV_PERSIST, icmp6_receive, ra_iface->icmp6ev);
1431 			event_add(&ra_iface->icmp6ev->ev, NULL);
1432 			icmp6sock = -1;
1433 			break;
1434 		}
1435 	}
1436 
1437 	if (icmp6sock != -1) {
1438 		/*
1439 		 * The interface disappeared or changed rdomain while we were
1440 		 * waiting for the parent process to open the raw socket.
1441 		 */
1442 		close(icmp6sock);
1443 		return;
1444 	}
1445 
1446 	TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
1447 		if (ra_iface->rdomain == rdomain) {
1448 			join_all_routers_mcast_group(ra_iface);
1449 			frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
1450 			    &ra_iface->if_index, sizeof(ra_iface->if_index));
1451 		}
1452 	}
1453 }
1454