xref: /openbsd/usr.sbin/route6d/route6d.c (revision fc61954a)
1 /*	$OpenBSD: route6d.c,v 1.91 2016/08/05 11:38:00 jca Exp $	*/
2 /*	$KAME: route6d.c,v 1.111 2006/10/25 06:38:13 jinmei Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
36 #include <sys/sysctl.h>
37 #include <sys/uio.h>
38 
39 #include <net/if.h>
40 #include <net/route.h>
41 #include <netinet/in.h>
42 #include <netinet/ip6.h>
43 #include <netinet/udp.h>
44 #include <netinet6/in6_var.h>
45 
46 #include <arpa/inet.h>
47 #include <errno.h>
48 #include <ifaddrs.h>
49 #include <netdb.h>
50 #include <poll.h>
51 #include <signal.h>
52 #include <stdarg.h>
53 #include <stddef.h>
54 #include <stdint.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <time.h>
59 #include <unistd.h>
60 
61 #include "route6d.h"
62 #include "log.h"
63 
64 #define	MAXFILTER	40
65 
66 #ifdef	DEBUG
67 #define	INIT_INTERVAL6	6
68 #else
69 #define	INIT_INTERVAL6	10	/* Wait to submit a initial riprequest */
70 #endif
71 
72 /* alignment constraint for routing socket */
73 #define ROUNDUP(a) \
74 	((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
75 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
76 
77 /*
78  * Following two macros are highly depending on KAME Release
79  */
80 #define	IN6_LINKLOCAL_IFINDEX(addr) \
81 	((addr).s6_addr[2] << 8 | (addr).s6_addr[3])
82 
83 #define	SET_IN6_LINKLOCAL_IFINDEX(addr, index) \
84 	do { \
85 		(addr).s6_addr[2] = ((index) >> 8) & 0xff; \
86 		(addr).s6_addr[3] = (index) & 0xff; \
87 	} while (0)
88 
89 struct	ifc {			/* Configuration of an interface */
90 	char	*ifc_name;			/* if name */
91 	struct	ifc *ifc_next;
92 	int	ifc_index;			/* if index */
93 	int	ifc_mtu;			/* if mtu */
94 	int	ifc_metric;			/* if metric */
95 	u_int	ifc_flags;			/* flags */
96 	short	ifc_cflags;			/* IFC_XXX */
97 	struct	in6_addr ifc_mylladdr;		/* my link-local address */
98 	struct	sockaddr_in6 ifc_ripsin;	/* rip multicast address */
99 	struct	iff *ifc_filter;		/* filter structure */
100 	struct	ifac *ifc_addr;			/* list of AF_INET6 addresses */
101 	int	ifc_joined;			/* joined to ff02::9 */
102 };
103 
104 struct	ifac {			/* Address associated to an interface */
105 	struct	ifc *ifa_conf;		/* back pointer */
106 	struct	ifac *ifa_next;
107 	struct	in6_addr ifa_addr;	/* address */
108 	struct	in6_addr ifa_raddr;	/* remote address, valid in p2p */
109 	int	ifa_plen;		/* prefix length */
110 };
111 
112 struct	iff {
113 	int	iff_type;
114 	struct	in6_addr iff_addr;
115 	int	iff_plen;
116 	struct	iff *iff_next;
117 };
118 
119 struct	ifc *ifc;
120 int	nifc;		/* number of valid ifc's */
121 struct	ifc **index2ifc;
122 int	nindex2ifc;
123 struct	ifc *loopifcp = NULL;	/* pointing to loopback */
124 struct	pollfd pfd[2];
125 int	rtsock;		/* the routing socket */
126 int	ripsock;	/* socket to send/receive RIP datagram */
127 
128 struct	rip6 *ripbuf;	/* packet buffer for sending */
129 
130 /*
131  * Maintain the routes in a linked list.  When the number of the routes
132  * grows, somebody would like to introduce a hash based or a radix tree
133  * based structure.  I believe the number of routes handled by RIP is
134  * limited and I don't have to manage a complex data structure, however.
135  *
136  * One of the major drawbacks of the linear linked list is the difficulty
137  * of representing the relationship between a couple of routes.  This may
138  * be a significant problem when we have to support route aggregation with
139  * suppressing the specifics covered by the aggregate.
140  */
141 
142 struct	riprt {
143 	struct	riprt *rrt_next;	/* next destination */
144 	struct	netinfo6 rrt_info;	/* network info */
145 	struct	in6_addr rrt_gw;	/* gateway */
146 	u_long	rrt_flags;		/* kernel routing table flags */
147 	u_long	rrt_rflags;		/* route6d routing table flags */
148 	time_t	rrt_t;			/* when the route validated */
149 	int	rrt_index;		/* ifindex from which this route got */
150 };
151 
152 struct	riprt *riprt = 0;
153 
154 int	dflag = 0;	/* debug flag */
155 int	qflag = 0;	/* quiet flag */
156 int	nflag = 0;	/* don't update kernel routing table */
157 int	aflag = 0;	/* age out even the statically defined routes */
158 int	hflag = 0;	/* don't split horizon */
159 int	lflag = 0;	/* exchange site local routes */
160 int	sflag = 0;	/* announce static routes w/ split horizon */
161 int	Sflag = 0;	/* announce static routes to every interface */
162 int	uflag = 0;	/* always log route updates (additions/deletions) */
163 unsigned long routetag = 0;	/* route tag attached on originating case */
164 
165 char	*filter[MAXFILTER];
166 int	filtertype[MAXFILTER];
167 int	nfilter = 0;
168 
169 pid_t	pid;
170 
171 struct	sockaddr_storage ripsin;
172 
173 time_t	nextalarm = 0;
174 time_t	sup_trig_update = 0;
175 
176 static	int	seq = 0;
177 
178 volatile sig_atomic_t seenalrm;
179 volatile sig_atomic_t seenquit;
180 volatile sig_atomic_t seenusr1;
181 
182 #define	RRTF_AGGREGATE		0x08000000
183 #define	RRTF_NOADVERTISE	0x10000000
184 #define	RRTF_NH_NOT_LLADDR	0x20000000
185 #define RRTF_SENDANYWAY		0x40000000
186 #define	RRTF_CHANGED		0x80000000
187 
188 void sighandler(int);
189 void ripalarm(void);
190 void riprecv(void);
191 void ripsend(struct ifc *, struct sockaddr_in6 *, int);
192 int out_filter(struct riprt *, struct ifc *);
193 void init(void);
194 void sockopt(struct ifc *);
195 void ifconfig(void);
196 void ifconfig1(const char *, const struct sockaddr *, struct ifc *, int);
197 void rtrecv(void);
198 int rt_del(const struct sockaddr_in6 *, const struct sockaddr_in6 *,
199     const struct sockaddr_in6 *);
200 int rt_deladdr(struct ifc *, const struct sockaddr_in6 *,
201     const struct sockaddr_in6 *);
202 void filterconfig(void);
203 int getifmtu(int);
204 const char *rttypes(struct rt_msghdr *);
205 const char *rtflags(struct rt_msghdr *);
206 const char *ifflags(int);
207 int ifrt(struct ifc *, int);
208 void ifrt_p2p(struct ifc *, int);
209 void applyplen(struct in6_addr *, int);
210 void ifrtdump(int);
211 void ifdump(int);
212 void ifdump0(const struct ifc *);
213 void rtdump(int);
214 void rt_entry(struct rt_msghdr *, int);
215 __dead void rtdexit(void);
216 void riprequest(struct ifc *, struct netinfo6 *, int, struct sockaddr_in6 *);
217 void ripflush(struct ifc *, struct sockaddr_in6 *);
218 void sendrequest(struct ifc *);
219 int sin6mask2len(const struct sockaddr_in6 *);
220 int mask2len(const struct in6_addr *, int);
221 int sendpacket(struct sockaddr_in6 *, int);
222 int addroute(struct riprt *, const struct in6_addr *, struct ifc *);
223 int delroute(struct netinfo6 *, struct in6_addr *);
224 struct in6_addr *getroute(struct netinfo6 *, struct in6_addr *);
225 void krtread(int);
226 int tobeadv(struct riprt *, struct ifc *);
227 char *xstrdup(const char *);
228 const char *hms(void);
229 const char *inet6_n2p(const struct in6_addr *);
230 struct ifac *ifa_match(const struct ifc *, const struct in6_addr *, int);
231 struct in6_addr *plen2mask(int);
232 struct riprt *rtsearch(struct netinfo6 *, struct riprt **);
233 int ripinterval(int);
234 time_t ripsuptrig(void);
235 unsigned int if_maxindex(void);
236 struct ifc *ifc_find(char *);
237 struct iff *iff_find(struct ifc *, int);
238 void setindex2ifc(int, struct ifc *);
239 
240 int
241 main(int argc, char *argv[])
242 {
243 	int	ch;
244 	int	error = 0;
245 	struct	ifc *ifcp;
246 	sigset_t mask, omask;
247 	char *ep;
248 
249 	log_init(1); /* log to stderr until daemonized */
250 
251 	while ((ch = getopt(argc, argv, "A:N:O:T:L:t:adDhlnqsSu")) != -1) {
252 		switch (ch) {
253 		case 'A':
254 		case 'N':
255 		case 'O':
256 		case 'T':
257 		case 'L':
258 			if (nfilter >= MAXFILTER) {
259 				fatalx("Exceeds MAXFILTER");
260 				/*NOTREACHED*/
261 			}
262 			filtertype[nfilter] = ch;
263 			filter[nfilter++] = xstrdup(optarg);
264 			break;
265 		case 't':
266 			ep = NULL;
267 			routetag = strtoul(optarg, &ep, 0);
268 			if (!ep || *ep != '\0' || (routetag & ~0xffff) != 0) {
269 				fatalx("invalid route tag");
270 				/*NOTREACHED*/
271 			}
272 			break;
273 #define	FLAG(c, flag, n)	case c: do { flag = n; break; } while(0)
274 		FLAG('a', aflag, 1); break;
275 		FLAG('d', dflag, 1); break;
276 		FLAG('D', dflag, 2); break;
277 		FLAG('h', hflag, 1); break;
278 		FLAG('l', lflag, 1); break;
279 		FLAG('n', nflag, 1); break;
280 		FLAG('q', qflag, 1); break;
281 		FLAG('s', sflag, 1); break;
282 		FLAG('S', Sflag, 1); break;
283 		FLAG('u', uflag, 1); break;
284 #undef	FLAG
285 		default:
286 			fatalx("Invalid option specified, terminating");
287 			/*NOTREACHED*/
288 		}
289 	}
290 	argc -= optind;
291 	argv += optind;
292 	if (argc > 0) {
293 		fatalx("bogus extra arguments");
294 		/*NOTREACHED*/
295 	}
296 
297 	if (geteuid()) {
298 		nflag = 1;
299 		log_warn("No kernel update is allowed");
300 	}
301 
302 	if (dflag == 0) {
303 		if (daemon(0, 0) < 0) {
304 			fatal("daemon");
305 			/*NOTREACHED*/
306 		}
307 	}
308 
309 	log_init(dflag);
310 
311 	pid = getpid();
312 
313 	if ((ripbuf = calloc(RIP6_MAXMTU, 1)) == NULL)
314 		fatal(NULL);
315 	ripbuf->rip6_cmd = RIP6_RESPONSE;
316 	ripbuf->rip6_vers = RIP6_VERSION;
317 	ripbuf->rip6_res1[0] = 0;
318 	ripbuf->rip6_res1[1] = 0;
319 
320 	init();
321 
322 	if (pledge("stdio inet route mcast", NULL) == -1)
323 		fatal("pledge");
324 
325 	ifconfig();
326 
327 	for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) {
328 		if (ifcp->ifc_index < 0) {
329 			log_warn(
330 "No ifindex found at %s (no link-local address?)",
331 				ifcp->ifc_name);
332 			error++;
333 		}
334 	}
335 	if (error)
336 		exit(1);
337 	if (loopifcp == NULL) {
338 		fatalx("No loopback found");
339 		/*NOTREACHED*/
340 	}
341 	for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next)
342 		ifrt(ifcp, 0);
343 	filterconfig();
344 	krtread(0);
345 	if (dflag)
346 		ifrtdump(0);
347 
348 	if (signal(SIGALRM, sighandler) == SIG_ERR ||
349 	    signal(SIGQUIT, sighandler) == SIG_ERR ||
350 	    signal(SIGTERM, sighandler) == SIG_ERR ||
351 	    signal(SIGUSR1, sighandler) == SIG_ERR ||
352 	    signal(SIGHUP, sighandler) == SIG_ERR ||
353 	    signal(SIGINT, sighandler) == SIG_ERR) {
354 		fatal("signal");
355 		/*NOTREACHED*/
356 	}
357 	/*
358 	 * To avoid rip packet congestion (not on a cable but in this
359 	 * process), wait for a moment to send the first RIP6_RESPONSE
360 	 * packets.
361 	 */
362 	alarm(ripinterval(INIT_INTERVAL6));
363 
364 	for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) {
365 		if (iff_find(ifcp, 'N'))
366 			continue;
367 		if (ifcp->ifc_index > 0 && (ifcp->ifc_flags & IFF_UP))
368 			sendrequest(ifcp);
369 	}
370 
371 	log_info("**** Started ****");
372 	sigemptyset(&mask);
373 	sigaddset(&mask, SIGALRM);
374 	while (1) {
375 		if (seenalrm) {
376 			ripalarm();
377 			seenalrm = 0;
378 			continue;
379 		}
380 		if (seenquit) {
381 			rtdexit();
382 			seenquit = 0;
383 			continue;
384 		}
385 		if (seenusr1) {
386 			ifrtdump(SIGUSR1);
387 			seenusr1 = 0;
388 			continue;
389 		}
390 
391 		switch (poll(pfd, 2, INFTIM))
392 		{
393 		case -1:
394 			if (errno != EINTR) {
395 				fatal("poll");
396 				/*NOTREACHED*/
397 			}
398 			continue;
399 		case 0:
400 			continue;
401 		default:
402 			if (pfd[0].revents & POLLIN) {
403 				sigprocmask(SIG_BLOCK, &mask, &omask);
404 				riprecv();
405 				sigprocmask(SIG_SETMASK, &omask, NULL);
406 			}
407 			if (pfd[1].revents & POLLIN) {
408 				sigprocmask(SIG_BLOCK, &mask, &omask);
409 				rtrecv();
410 				sigprocmask(SIG_SETMASK, &omask, NULL);
411 			}
412 		}
413 	}
414 }
415 
416 void
417 sighandler(int signo)
418 {
419 
420 	switch (signo) {
421 	case SIGALRM:
422 		seenalrm++;
423 		break;
424 	case SIGQUIT:
425 	case SIGTERM:
426 		seenquit++;
427 		break;
428 	case SIGUSR1:
429 	case SIGHUP:
430 	case SIGINT:
431 		seenusr1++;
432 		break;
433 	}
434 }
435 
436 /*
437  * gracefully exits after resetting sockopts.
438  */
439 void
440 rtdexit(void)
441 {
442 	struct	riprt *rrt;
443 
444 	alarm(0);
445 	for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
446 		if (rrt->rrt_rflags & RRTF_AGGREGATE) {
447 			delroute(&rrt->rrt_info, &rrt->rrt_gw);
448 		}
449 	}
450 	close(ripsock);
451 	close(rtsock);
452 	log_info("**** Terminated ****");
453 	exit(1);
454 }
455 
456 /*
457  * Called periodically:
458  *	1. age out the learned route. remove it if necessary.
459  *	2. submit RIP6_RESPONSE packets.
460  * Invoked in every SUPPLY_INTERVAL6 (30) seconds.  I believe we don't have
461  * to invoke this function in every 1 or 5 or 10 seconds only to age the
462  * routes more precisely.
463  */
464 void
465 ripalarm(void)
466 {
467 	struct	ifc *ifcp;
468 	struct	riprt *rrt, *rrt_prev, *rrt_next;
469 	time_t	t_lifetime, t_holddown;
470 
471 	/* age the RIP routes */
472 	rrt_prev = 0;
473 	t_lifetime = time(NULL) - RIP_LIFETIME;
474 	t_holddown = t_lifetime - RIP_HOLDDOWN;
475 	for (rrt = riprt; rrt; rrt = rrt_next) {
476 		rrt_next = rrt->rrt_next;
477 
478 		if (rrt->rrt_t == 0) {
479 			rrt_prev = rrt;
480 			continue;
481 		}
482 		if (rrt->rrt_t < t_holddown) {
483 			if (rrt_prev) {
484 				rrt_prev->rrt_next = rrt->rrt_next;
485 			} else {
486 				riprt = rrt->rrt_next;
487 			}
488 			delroute(&rrt->rrt_info, &rrt->rrt_gw);
489 			free(rrt);
490 			continue;
491 		}
492 		if (rrt->rrt_t < t_lifetime)
493 			rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6;
494 		rrt_prev = rrt;
495 	}
496 	/* Supply updates */
497 	for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) {
498 		if (ifcp->ifc_index > 0 && (ifcp->ifc_flags & IFF_UP))
499 			ripsend(ifcp, &ifcp->ifc_ripsin, 0);
500 	}
501 	alarm(ripinterval(SUPPLY_INTERVAL6));
502 }
503 
504 void
505 init(void)
506 {
507 	int	i, error;
508 	const int int0 = 0, int1 = 1, int255 = 255;
509 	struct	addrinfo hints, *res;
510 	char	port[NI_MAXSERV];
511 
512 	ifc = (struct ifc *)NULL;
513 	nifc = 0;
514 	nindex2ifc = 0;	/*initial guess*/
515 	index2ifc = NULL;
516 	snprintf(port, sizeof(port), "%u", RIP6_PORT);
517 
518 	memset(&hints, 0, sizeof(hints));
519 	hints.ai_family = PF_INET6;
520 	hints.ai_socktype = SOCK_DGRAM;
521 	hints.ai_flags = AI_PASSIVE;
522 	error = getaddrinfo(NULL, port, &hints, &res);
523 	if (error) {
524 		fatalx(gai_strerror(error));
525 		/*NOTREACHED*/
526 	}
527 	if (res->ai_next) {
528 		fatalx(":: resolved to multiple address");
529 		/*NOTREACHED*/
530 	}
531 
532 	ripsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
533 	if (ripsock < 0) {
534 		fatal("rip socket");
535 		/*NOTREACHED*/
536 	}
537 	if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_V6ONLY,
538 	    &int1, sizeof(int1)) < 0) {
539 		fatal("rip IPV6_V6ONLY");
540 		/*NOTREACHED*/
541 	}
542 	if (bind(ripsock, res->ai_addr, res->ai_addrlen) < 0) {
543 		fatal("rip bind");
544 		/*NOTREACHED*/
545 	}
546 	if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
547 	    &int255, sizeof(int255)) < 0) {
548 		fatal("rip IPV6_MULTICAST_HOPS");
549 		/*NOTREACHED*/
550 	}
551 	if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
552 	    &int0, sizeof(int0)) < 0) {
553 		fatal("rip IPV6_MULTICAST_LOOP");
554 		/*NOTREACHED*/
555 	}
556 
557 	i = 1;
558 	if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &i,
559 	    sizeof(i)) < 0) {
560 		fatal("rip IPV6_RECVPKTINFO");
561 		/*NOTREACHED*/
562 	}
563 
564 	if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
565 	    &int1, sizeof(int1)) < 0) {
566 		fatal("rip IPV6_RECVHOPLIMIT");
567 		/*NOTREACHED*/
568 	}
569 
570 	memset(&hints, 0, sizeof(hints));
571 	hints.ai_family = PF_INET6;
572 	hints.ai_socktype = SOCK_DGRAM;
573 	error = getaddrinfo(RIP6_DEST, port, &hints, &res);
574 	if (error) {
575 		fatalx(gai_strerror(error));
576 		/*NOTREACHED*/
577 	}
578 	if (res->ai_next) {
579 		fatalx(RIP6_DEST " resolved to multiple address");
580 		/*NOTREACHED*/
581 	}
582 	memcpy(&ripsin, res->ai_addr, res->ai_addrlen);
583 
584 	pfd[0].fd = ripsock;
585 	pfd[0].events = POLLIN;
586 
587 	if (nflag == 0) {
588 		if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) {
589 			fatal("route socket");
590 			/*NOTREACHED*/
591 		}
592 		pfd[1].fd = rtsock;
593 		pfd[1].events = POLLIN;
594 	} else
595 		pfd[1].fd = -1;
596 
597 }
598 
599 #define	RIPSIZE(n) \
600 	(sizeof(struct rip6) + ((n)-1) * sizeof(struct netinfo6))
601 
602 /*
603  * ripflush flushes the rip datagram stored in the rip buffer
604  */
605 static int nrt;
606 static struct netinfo6 *np;
607 
608 void
609 ripflush(struct ifc *ifcp, struct sockaddr_in6 *sin6)
610 {
611 	int i;
612 	int error;
613 
614 	if (ifcp)
615 		log_debug("Send(%s): info(%d) to %s.%d",
616 			ifcp->ifc_name, nrt,
617 			inet6_n2p(&sin6->sin6_addr), ntohs(sin6->sin6_port));
618 	else
619 		log_debug("Send: info(%d) to %s.%d",
620 			nrt, inet6_n2p(&sin6->sin6_addr), ntohs(sin6->sin6_port));
621 	if (dflag >= 2) {
622 		np = ripbuf->rip6_nets;
623 		for (i = 0; i < nrt; i++, np++) {
624 			if (np->rip6_metric == NEXTHOP_METRIC) {
625 				if (IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest))
626 					log_enqueue("    NextHop reset");
627 				else {
628 					log_enqueue("    NextHop %s",
629 						inet6_n2p(&np->rip6_dest));
630 				}
631 			} else {
632 				log_enqueue("    %s/%d[%d]",
633 					inet6_n2p(&np->rip6_dest),
634 					np->rip6_plen, np->rip6_metric);
635 			}
636 			if (np->rip6_tag) {
637 				log_enqueue("  tag=0x%04x",
638 					ntohs(np->rip6_tag) & 0xffff);
639 			}
640 			log_debug("");
641 		}
642 	}
643 	error = sendpacket(sin6, RIPSIZE(nrt));
644 	if (error == EAFNOSUPPORT) {
645 		/* Protocol not supported */
646 		log_debug("Could not send info to %s (%s): "
647 			"set IFF_UP to 0",
648 			ifcp->ifc_name, inet6_n2p(&ifcp->ifc_ripsin.sin6_addr));
649 		ifcp->ifc_flags &= ~IFF_UP;	/* As if down for AF_INET6 */
650 	}
651 	nrt = 0; np = ripbuf->rip6_nets;
652 }
653 
654 /*
655  * Generate RIP6_RESPONSE packets and send them.
656  */
657 void
658 ripsend(struct ifc *ifcp, struct sockaddr_in6 *sin6, int flag)
659 {
660 	struct	riprt *rrt;
661 	struct	in6_addr *nh;	/* next hop */
662 	int	maxrte;
663 
664 	if (qflag)
665 		return;
666 
667 	if (ifcp == NULL) {
668 		/*
669 		 * Request from non-link local address is not
670 		 * a regular route6d update.
671 		 */
672 		maxrte = (IFMINMTU - sizeof(struct ip6_hdr) -
673 				sizeof(struct udphdr) -
674 				sizeof(struct rip6) + sizeof(struct netinfo6)) /
675 				sizeof(struct netinfo6);
676 		nrt = 0; np = ripbuf->rip6_nets; nh = NULL;
677 		for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
678 			if (rrt->rrt_rflags & RRTF_NOADVERTISE)
679 				continue;
680 			/* Put the route to the buffer */
681 			*np = rrt->rrt_info;
682 			np++; nrt++;
683 			if (nrt == maxrte) {
684 				ripflush(NULL, sin6);
685 				nh = NULL;
686 			}
687 		}
688 		if (nrt)	/* Send last packet */
689 			ripflush(NULL, sin6);
690 		return;
691 	}
692 
693 	if ((flag & RRTF_SENDANYWAY) == 0 &&
694 	    (qflag || (ifcp->ifc_flags & IFF_LOOPBACK)))
695 		return;
696 
697 	/* -N: no use */
698 	if (iff_find(ifcp, 'N') != NULL)
699 		return;
700 
701 	/* -T: generate default route only */
702 	if (iff_find(ifcp, 'T') != NULL) {
703 		struct netinfo6 rrt_info;
704 		memset(&rrt_info, 0, sizeof(struct netinfo6));
705 		rrt_info.rip6_dest = in6addr_any;
706 		rrt_info.rip6_plen = 0;
707 		rrt_info.rip6_metric = 1;
708 		rrt_info.rip6_metric += ifcp->ifc_metric;
709 		rrt_info.rip6_tag = htons(routetag & 0xffff);
710 		np = ripbuf->rip6_nets;
711 		*np = rrt_info;
712 		nrt = 1;
713 		ripflush(ifcp, sin6);
714 		return;
715 	}
716 
717 	maxrte = (ifcp->ifc_mtu - sizeof(struct ip6_hdr) -
718 			sizeof(struct udphdr) -
719 			sizeof(struct rip6) + sizeof(struct netinfo6)) /
720 			sizeof(struct netinfo6);
721 
722 	nrt = 0; np = ripbuf->rip6_nets; nh = NULL;
723 	for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
724 		if (rrt->rrt_rflags & RRTF_NOADVERTISE)
725 			continue;
726 
727 		/* Need to check filter here */
728 		if (out_filter(rrt, ifcp) == 0)
729 			continue;
730 
731 		/* Check split horizon and other conditions */
732 		if (tobeadv(rrt, ifcp) == 0)
733 			continue;
734 
735 		/* Only considers the routes with flag if specified */
736 		if ((flag & RRTF_CHANGED) &&
737 		    (rrt->rrt_rflags & RRTF_CHANGED) == 0)
738 			continue;
739 
740 		/* Check nexthop */
741 		if (rrt->rrt_index == ifcp->ifc_index &&
742 		    !IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_gw) &&
743 		    (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR) == 0) {
744 			if (nh == NULL || !IN6_ARE_ADDR_EQUAL(nh, &rrt->rrt_gw)) {
745 				if (nrt == maxrte - 2)
746 					ripflush(ifcp, sin6);
747 				np->rip6_dest = rrt->rrt_gw;
748 				if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest))
749 					SET_IN6_LINKLOCAL_IFINDEX(np->rip6_dest, 0);
750 				np->rip6_plen = 0;
751 				np->rip6_tag = 0;
752 				np->rip6_metric = NEXTHOP_METRIC;
753 				nh = &rrt->rrt_gw;
754 				np++; nrt++;
755 			}
756 		} else if (nh && (rrt->rrt_index != ifcp->ifc_index ||
757 			          !IN6_ARE_ADDR_EQUAL(nh, &rrt->rrt_gw) ||
758 				  rrt->rrt_rflags & RRTF_NH_NOT_LLADDR)) {
759 			/* Reset nexthop */
760 			if (nrt == maxrte - 2)
761 				ripflush(ifcp, sin6);
762 			memset(np, 0, sizeof(struct netinfo6));
763 			np->rip6_metric = NEXTHOP_METRIC;
764 			nh = NULL;
765 			np++; nrt++;
766 		}
767 
768 		/* Put the route to the buffer */
769 		*np = rrt->rrt_info;
770 		np++; nrt++;
771 		if (nrt == maxrte) {
772 			ripflush(ifcp, sin6);
773 			nh = NULL;
774 		}
775 	}
776 	if (nrt)	/* Send last packet */
777 		ripflush(ifcp, sin6);
778 }
779 
780 /*
781  * outbound filter logic, per-route/interface.
782  */
783 int
784 out_filter(struct riprt *rrt, struct ifc *ifcp)
785 {
786 	struct iff *iffp;
787 	struct in6_addr ia;
788 	int ok;
789 
790 	/*
791 	 * -A: filter out less specific routes, if we have aggregated
792 	 * route configured.
793 	 */
794 	for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
795 		if (iffp->iff_type != 'A')
796 			continue;
797 		if (rrt->rrt_info.rip6_plen <= iffp->iff_plen)
798 			continue;
799 		ia = rrt->rrt_info.rip6_dest;
800 		applyplen(&ia, iffp->iff_plen);
801 		if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr))
802 			return 0;
803 	}
804 
805 	/*
806 	 * if it is an aggregated route, advertise it only to the
807 	 * interfaces specified on -A.
808 	 */
809 	if ((rrt->rrt_rflags & RRTF_AGGREGATE) != 0) {
810 		ok = 0;
811 		for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
812 			if (iffp->iff_type != 'A')
813 				continue;
814 			if (rrt->rrt_info.rip6_plen == iffp->iff_plen &&
815 			    IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest,
816 			    &iffp->iff_addr)) {
817 				ok = 1;
818 				break;
819 			}
820 		}
821 		if (!ok)
822 			return 0;
823 	}
824 
825 	/*
826 	 * -O: advertise only if prefix matches the configured prefix.
827 	 */
828 	if (iff_find(ifcp, 'O')) {
829 		ok = 0;
830 		for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
831 			if (iffp->iff_type != 'O')
832 				continue;
833 			if (rrt->rrt_info.rip6_plen < iffp->iff_plen)
834 				continue;
835 			ia = rrt->rrt_info.rip6_dest;
836 			applyplen(&ia, iffp->iff_plen);
837 			if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr)) {
838 				ok = 1;
839 				break;
840 			}
841 		}
842 		if (!ok)
843 			return 0;
844 	}
845 
846 	/* the prefix should be advertised */
847 	return 1;
848 }
849 
850 /*
851  * Determine if the route is to be advertised on the specified interface.
852  * It checks options specified in the arguments and the split horizon rule.
853  */
854 int
855 tobeadv(struct riprt *rrt, struct ifc *ifcp)
856 {
857 
858 	/* Special care for static routes */
859 	if (rrt->rrt_flags & RTF_STATIC) {
860 		/* XXX don't advertise reject/blackhole routes */
861 		if (rrt->rrt_flags & (RTF_REJECT | RTF_BLACKHOLE))
862 			return 0;
863 
864 		if (Sflag)	/* Yes, advertise it anyway */
865 			return 1;
866 		if (sflag && rrt->rrt_index != ifcp->ifc_index)
867 			return 1;
868 		return 0;
869 	}
870 	/* Regular split horizon */
871 	if (hflag == 0 && rrt->rrt_index == ifcp->ifc_index)
872 		return 0;
873 	return 1;
874 }
875 
876 /*
877  * Send a rip packet actually.
878  */
879 int
880 sendpacket(struct sockaddr_in6 *sin6, int len)
881 {
882 	struct msghdr m;
883 	struct cmsghdr *cm;
884 	struct iovec iov[2];
885 	union {
886 		struct cmsghdr hdr;
887 		u_char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
888 	} cmsgbuf;
889 	struct in6_pktinfo *pi;
890 	int idx;
891 	struct sockaddr_in6 sincopy;
892 
893 	/* do not overwrite the given sin */
894 	sincopy = *sin6;
895 	sin6 = &sincopy;
896 
897 	if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
898 	    IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
899 		/* XXX: do not mix the interface index and link index */
900 		idx = IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr);
901 		SET_IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr, 0);
902 		sin6->sin6_scope_id = idx;
903 	} else
904 		idx = 0;
905 
906 	m.msg_name = (caddr_t)sin6;
907 	m.msg_namelen = sizeof(*sin6);
908 	iov[0].iov_base = (caddr_t)ripbuf;
909 	iov[0].iov_len = len;
910 	m.msg_iov = iov;
911 	m.msg_iovlen = 1;
912 	if (!idx) {
913 		m.msg_control = NULL;
914 		m.msg_controllen = 0;
915 	} else {
916 		memset(&cmsgbuf, 0, sizeof(cmsgbuf));
917 		m.msg_control = (caddr_t)&cmsgbuf.buf;
918 		m.msg_controllen = sizeof(cmsgbuf.buf);
919 		cm = CMSG_FIRSTHDR(&m);
920 		cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
921 		cm->cmsg_level = IPPROTO_IPV6;
922 		cm->cmsg_type = IPV6_PKTINFO;
923 		pi = (struct in6_pktinfo *)CMSG_DATA(cm);
924 		memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*::*/
925 		pi->ipi6_ifindex = idx;
926 	}
927 
928 	if (sendmsg(ripsock, &m, 0) < 0) {
929 		log_debug("sendmsg: %s", strerror(errno));
930 		return errno;
931 	}
932 
933 	return 0;
934 }
935 
936 /*
937  * Receive and process RIP packets.  Update the routes/kernel forwarding
938  * table if necessary.
939  */
940 void
941 riprecv(void)
942 {
943 	struct	ifc *ifcp, *ic;
944 	struct	sockaddr_in6 fsock;
945 	struct	in6_addr nh;	/* next hop */
946 	struct	rip6 *rp;
947 	struct	netinfo6 *np, *nq;
948 	struct	riprt *rrt;
949 	ssize_t	len, nn;
950 	unsigned int need_trigger, idx;
951 	char	buf[4 * RIP6_MAXMTU];
952 	time_t	t;
953 	struct msghdr m;
954 	struct cmsghdr *cm;
955 	struct iovec iov[2];
956 	union {
957 		struct cmsghdr hdr;
958 		u_char buf[CMSG_SPACE(sizeof(struct in6_pktinfo)) +
959 		    CMSG_SPACE(sizeof(int))];
960 	} cmsgbuf;
961 	struct in6_pktinfo *pi = NULL;
962 	int *hlimp = NULL;
963 	struct iff *iffp;
964 	struct in6_addr ia;
965 	int ok;
966 	time_t t_half_lifetime;
967 
968 	need_trigger = 0;
969 
970 	m.msg_name = (caddr_t)&fsock;
971 	m.msg_namelen = sizeof(fsock);
972 	iov[0].iov_base = (caddr_t)buf;
973 	iov[0].iov_len = sizeof(buf);
974 	m.msg_iov = iov;
975 	m.msg_iovlen = 1;
976 	m.msg_control = (caddr_t)&cmsgbuf.buf;
977 	m.msg_controllen = sizeof(cmsgbuf.buf);
978 	if ((len = recvmsg(ripsock, &m, 0)) < 0) {
979 		fatal("recvmsg");
980 		/*NOTREACHED*/
981 	}
982 	idx = 0;
983 	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m);
984 	     cm;
985 	     cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) {
986 		if (cm->cmsg_level != IPPROTO_IPV6)
987 			continue;
988 		switch (cm->cmsg_type) {
989 		case IPV6_PKTINFO:
990 			if (cm->cmsg_len != CMSG_LEN(sizeof(*pi))) {
991 				log_debug(
992 				    "invalid cmsg length for IPV6_PKTINFO");
993 				return;
994 			}
995 			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
996 			idx = pi->ipi6_ifindex;
997 			break;
998 		case IPV6_HOPLIMIT:
999 			if (cm->cmsg_len != CMSG_LEN(sizeof(int))) {
1000 				log_debug(
1001 				    "invalid cmsg length for IPV6_HOPLIMIT");
1002 				return;
1003 			}
1004 			hlimp = (int *)CMSG_DATA(cm);
1005 			break;
1006 		}
1007 	}
1008 	if (idx && IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr))
1009 		SET_IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr, idx);
1010 
1011 	if (len < sizeof(struct rip6)) {
1012 		log_debug("Packet too short");
1013 		return;
1014 	}
1015 
1016 	if (pi == NULL || hlimp == NULL) {
1017 		/*
1018 		 * This can happen when the kernel failed to allocate memory
1019 		 * for the ancillary data.  Although we might be able to handle
1020 		 * some cases without this info, those are minor and not so
1021 		 * important, so it's better to discard the packet for safer
1022 		 * operation.
1023 		 */
1024 		log_debug("IPv6 packet information cannot be retrieved");
1025 		return;
1026 	}
1027 
1028 	nh = fsock.sin6_addr;
1029 	nn = (len - sizeof(struct rip6) + sizeof(struct netinfo6)) /
1030 		sizeof(struct netinfo6);
1031 	rp = (struct rip6 *)buf;
1032 	np = rp->rip6_nets;
1033 
1034 	if (rp->rip6_vers != RIP6_VERSION) {
1035 		log_debug("Incorrect RIP version %d", rp->rip6_vers);
1036 		return;
1037 	}
1038 	if (rp->rip6_cmd == RIP6_REQUEST) {
1039 		if (idx && idx < nindex2ifc) {
1040 			ifcp = index2ifc[idx];
1041 			riprequest(ifcp, np, nn, &fsock);
1042 		} else {
1043 			riprequest(NULL, np, nn, &fsock);
1044 		}
1045 		return;
1046 	}
1047 
1048 	if (!IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr)) {
1049 		log_debug("Response from non-ll addr: %s",
1050 		    inet6_n2p(&fsock.sin6_addr));
1051 		return;		/* Ignore packets from non-link-local addr */
1052 	}
1053 	if (ntohs(fsock.sin6_port) != RIP6_PORT) {
1054 		log_debug("Response from non-rip port from %s",
1055 		    inet6_n2p(&fsock.sin6_addr));
1056 		return;
1057 	}
1058 	if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) && *hlimp != 255) {
1059 		log_debug(
1060 		    "Response packet with a smaller hop limit (%d) from %s",
1061 		    *hlimp, inet6_n2p(&fsock.sin6_addr));
1062 		return;
1063 	}
1064 	/*
1065 	 * Further validation: since this program does not send off-link
1066 	 * requests, an incoming response must always come from an on-link
1067 	 * node.  Although this is normally ensured by the source address
1068 	 * check above, it may not 100% be safe because there are router
1069 	 * implementations that (invalidly) allow a packet with a link-local
1070 	 * source address to be forwarded to a different link.
1071 	 * So we also check whether the destination address is a link-local
1072 	 * address or the hop limit is 255.  Note that RFC2080 does not require
1073 	 * the specific hop limit for a unicast response, so we cannot assume
1074 	 * the limitation.
1075 	 */
1076 	if (!IN6_IS_ADDR_LINKLOCAL(&pi->ipi6_addr) && *hlimp != 255) {
1077 		log_debug(
1078 		    "Response packet possibly from an off-link node: "
1079 		    "from %s to %s hlim=%d",
1080 		    inet6_n2p(&fsock.sin6_addr), inet6_n2p(&pi->ipi6_addr),
1081 		    *hlimp);
1082 		return;
1083 	}
1084 
1085 	idx = IN6_LINKLOCAL_IFINDEX(fsock.sin6_addr);
1086 	ifcp = (idx < nindex2ifc) ? index2ifc[idx] : NULL;
1087 	if (!ifcp) {
1088 		log_debug("Packets to unknown interface index %d", idx);
1089 		return;		/* Ignore it */
1090 	}
1091 	if (IN6_ARE_ADDR_EQUAL(&ifcp->ifc_mylladdr, &fsock.sin6_addr))
1092 		return;		/* The packet is from me; ignore */
1093 	if (rp->rip6_cmd != RIP6_RESPONSE) {
1094 		log_debug("Invalid command %d", rp->rip6_cmd);
1095 		return;
1096 	}
1097 
1098 	/* -N: no use */
1099 	if (iff_find(ifcp, 'N') != NULL)
1100 		return;
1101 
1102 	log_debug("Recv(%s): from %s.%d info(%zd)",
1103 	    ifcp->ifc_name, inet6_n2p(&nh), ntohs(fsock.sin6_port), nn);
1104 
1105 	t = time(NULL);
1106 	t_half_lifetime = t - (RIP_LIFETIME/2);
1107 	for (; nn; nn--, np++) {
1108 		if (np->rip6_metric == NEXTHOP_METRIC) {
1109 			/* modify neighbor address */
1110 			if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest)) {
1111 				nh = np->rip6_dest;
1112 				SET_IN6_LINKLOCAL_IFINDEX(nh, idx);
1113 				log_debug("\tNexthop: %s", inet6_n2p(&nh));
1114 			} else if (IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest)) {
1115 				nh = fsock.sin6_addr;
1116 				log_debug("\tNexthop: %s", inet6_n2p(&nh));
1117 			} else {
1118 				nh = fsock.sin6_addr;
1119 				log_debug("\tInvalid Nexthop: %s",
1120 				    inet6_n2p(&np->rip6_dest));
1121 			}
1122 			continue;
1123 		}
1124 		if (IN6_IS_ADDR_MULTICAST(&np->rip6_dest)) {
1125 			log_debug("\tMulticast netinfo6: %s/%d [%d]",
1126 				inet6_n2p(&np->rip6_dest),
1127 				np->rip6_plen, np->rip6_metric);
1128 			continue;
1129 		}
1130 		if (IN6_IS_ADDR_LOOPBACK(&np->rip6_dest)) {
1131 			log_debug("\tLoopback netinfo6: %s/%d [%d]",
1132 				inet6_n2p(&np->rip6_dest),
1133 				np->rip6_plen, np->rip6_metric);
1134 			continue;
1135 		}
1136 		if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest)) {
1137 			log_debug("\tLink Local netinfo6: %s/%d [%d]",
1138 				inet6_n2p(&np->rip6_dest),
1139 				np->rip6_plen, np->rip6_metric);
1140 			continue;
1141 		}
1142 		/* may need to pass sitelocal prefix in some case, however*/
1143 		if (IN6_IS_ADDR_SITELOCAL(&np->rip6_dest) && !lflag) {
1144 			log_debug("\tSite Local netinfo6: %s/%d [%d]",
1145 				inet6_n2p(&np->rip6_dest),
1146 				np->rip6_plen, np->rip6_metric);
1147 			continue;
1148 		}
1149 		if (dflag >= 2) {
1150 			log_enqueue("\tnetinfo6: %s/%d [%d]",
1151 			    inet6_n2p(&np->rip6_dest),
1152 			    np->rip6_plen, np->rip6_metric);
1153 			if (np->rip6_tag)
1154 				log_enqueue("  tag=0x%04x",
1155 				    ntohs(np->rip6_tag) & 0xffff);
1156 			ia = np->rip6_dest;
1157 			applyplen(&ia, np->rip6_plen);
1158 			if (!IN6_ARE_ADDR_EQUAL(&ia, &np->rip6_dest))
1159 				log_enqueue(" [junk outside prefix]");
1160 		}
1161 
1162 		/*
1163 		 * -L: listen only if the prefix matches the configuration
1164 		 */
1165 		ok = 1;		/* if there's no L filter, it is ok */
1166 		for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
1167 			if (iffp->iff_type != 'L')
1168 				continue;
1169 			ok = 0;
1170 			if (np->rip6_plen < iffp->iff_plen)
1171 				continue;
1172 			/* special rule: ::/0 means default, not "in /0" */
1173 			if (iffp->iff_plen == 0 && np->rip6_plen > 0)
1174 				continue;
1175 			ia = np->rip6_dest;
1176 			applyplen(&ia, iffp->iff_plen);
1177 			if (IN6_ARE_ADDR_EQUAL(&ia, &iffp->iff_addr)) {
1178 				ok = 1;
1179 				break;
1180 			}
1181 		}
1182 
1183 		if (!ok) {
1184 			if (dflag >= 2)
1185 				log_debug("  (filtered)");
1186 			continue;
1187 		}
1188 
1189 		if (dflag >= 2)
1190 			log_debug("");
1191 
1192 		np->rip6_metric++;
1193 		np->rip6_metric += ifcp->ifc_metric;
1194 		if (np->rip6_metric > HOPCNT_INFINITY6)
1195 			np->rip6_metric = HOPCNT_INFINITY6;
1196 
1197 		applyplen(&np->rip6_dest, np->rip6_plen);
1198 		if ((rrt = rtsearch(np, NULL)) != NULL) {
1199 			if (rrt->rrt_t == 0)
1200 				continue;	/* Intf route has priority */
1201 			nq = &rrt->rrt_info;
1202 			if (nq->rip6_metric > np->rip6_metric) {
1203 				if (rrt->rrt_index == ifcp->ifc_index &&
1204 				    IN6_ARE_ADDR_EQUAL(&nh, &rrt->rrt_gw)) {
1205 					/* Small metric from the same gateway */
1206 					nq->rip6_metric = np->rip6_metric;
1207 				} else {
1208 					/* Better route found */
1209 					rrt->rrt_index = ifcp->ifc_index;
1210 					/* Update routing table */
1211 					delroute(nq, &rrt->rrt_gw);
1212 					rrt->rrt_gw = nh;
1213 					*nq = *np;
1214 					addroute(rrt, &nh, ifcp);
1215 				}
1216 				rrt->rrt_rflags |= RRTF_CHANGED;
1217 				rrt->rrt_t = t;
1218 				need_trigger = 1;
1219 			} else if (nq->rip6_metric < np->rip6_metric &&
1220 				   rrt->rrt_index == ifcp->ifc_index &&
1221 				   IN6_ARE_ADDR_EQUAL(&nh, &rrt->rrt_gw)) {
1222 				/* Got worse route from same gw */
1223 				nq->rip6_metric = np->rip6_metric;
1224 				rrt->rrt_t = t;
1225 				rrt->rrt_rflags |= RRTF_CHANGED;
1226 				need_trigger = 1;
1227 			} else if (nq->rip6_metric == np->rip6_metric &&
1228 				   np->rip6_metric < HOPCNT_INFINITY6) {
1229 				if (rrt->rrt_index == ifcp->ifc_index &&
1230 				   IN6_ARE_ADDR_EQUAL(&nh, &rrt->rrt_gw)) {
1231 					/* same metric, same route from same gw */
1232 					rrt->rrt_t = t;
1233 				} else if (rrt->rrt_t < t_half_lifetime) {
1234 					/* Better route found */
1235 					rrt->rrt_index = ifcp->ifc_index;
1236 					/* Update routing table */
1237 					delroute(nq, &rrt->rrt_gw);
1238 					rrt->rrt_gw = nh;
1239 					*nq = *np;
1240 					addroute(rrt, &nh, ifcp);
1241 					rrt->rrt_rflags |= RRTF_CHANGED;
1242 					rrt->rrt_t = t;
1243 				}
1244 			}
1245 			/*
1246 			 * if nq->rip6_metric == HOPCNT_INFINITY6 then
1247 			 * do not update age value.  Do nothing.
1248 			 */
1249 		} else if (np->rip6_metric < HOPCNT_INFINITY6) {
1250 			/* Got a new valid route */
1251 			if ((rrt = calloc(1, sizeof(struct riprt))) == NULL) {
1252 				fatal("calloc: struct riprt");
1253 				/*NOTREACHED*/
1254 			}
1255 			nq = &rrt->rrt_info;
1256 
1257 			rrt->rrt_index = ifcp->ifc_index;
1258 			rrt->rrt_flags = RTF_UP|RTF_GATEWAY;
1259 			rrt->rrt_gw = nh;
1260 			*nq = *np;
1261 			applyplen(&nq->rip6_dest, nq->rip6_plen);
1262 			if (nq->rip6_plen == sizeof(struct in6_addr) * 8)
1263 				rrt->rrt_flags |= RTF_HOST;
1264 
1265 			/* Put the route to the list */
1266 			rrt->rrt_next = riprt;
1267 			riprt = rrt;
1268 			/* Update routing table */
1269 			addroute(rrt, &nh, ifcp);
1270 			rrt->rrt_rflags |= RRTF_CHANGED;
1271 			need_trigger = 1;
1272 			rrt->rrt_t = t;
1273 		}
1274 	}
1275 	/* XXX need to care the interval between triggered updates */
1276 	if (need_trigger) {
1277 		if (nextalarm > time(NULL) + RIP_TRIG_INT6_MAX) {
1278 			for (ic = ifc; ic; ic = ic->ifc_next) {
1279 				if (ifcp->ifc_index == ic->ifc_index)
1280 					continue;
1281 				if (ic->ifc_flags & IFF_UP)
1282 					ripsend(ic, &ic->ifc_ripsin,
1283 						RRTF_CHANGED);
1284 			}
1285 		}
1286 		/* Reset the flag */
1287 		for (rrt = riprt; rrt; rrt = rrt->rrt_next)
1288 			rrt->rrt_rflags &= ~RRTF_CHANGED;
1289 	}
1290 }
1291 
1292 /*
1293  * Send all routes request packet to the specified interface.
1294  */
1295 void
1296 sendrequest(struct ifc *ifcp)
1297 {
1298 	struct netinfo6 *np;
1299 	int error;
1300 
1301 	if (ifcp->ifc_flags & IFF_LOOPBACK)
1302 		return;
1303 	ripbuf->rip6_cmd = RIP6_REQUEST;
1304 	np = ripbuf->rip6_nets;
1305 	memset(np, 0, sizeof(struct netinfo6));
1306 	np->rip6_metric = HOPCNT_INFINITY6;
1307 	log_debug("Send rtdump Request to %s (%s)",
1308 		ifcp->ifc_name, inet6_n2p(&ifcp->ifc_ripsin.sin6_addr));
1309 	error = sendpacket(&ifcp->ifc_ripsin, RIPSIZE(1));
1310 	if (error == EAFNOSUPPORT) {
1311 		/* Protocol not supported */
1312 		log_debug("Could not send rtdump Request to %s (%s): "
1313 			"set IFF_UP to 0",
1314 			ifcp->ifc_name, inet6_n2p(&ifcp->ifc_ripsin.sin6_addr));
1315 		ifcp->ifc_flags &= ~IFF_UP;	/* As if down for AF_INET6 */
1316 	}
1317 	ripbuf->rip6_cmd = RIP6_RESPONSE;
1318 }
1319 
1320 /*
1321  * Process a RIP6_REQUEST packet.
1322  */
1323 void
1324 riprequest(struct ifc *ifcp, struct netinfo6 *np, int nn,
1325     struct sockaddr_in6 *sin6)
1326 {
1327 	int i;
1328 	struct riprt *rrt;
1329 
1330 	if (!(nn == 1 && IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest) &&
1331 	      np->rip6_plen == 0 && np->rip6_metric == HOPCNT_INFINITY6)) {
1332 		/* Specific response, don't split-horizon */
1333 		log_debug("\tRIP Request");
1334 		for (i = 0; i < nn; i++, np++) {
1335 			rrt = rtsearch(np, NULL);
1336 			if (rrt)
1337 				np->rip6_metric = rrt->rrt_info.rip6_metric;
1338 			else
1339 				np->rip6_metric = HOPCNT_INFINITY6;
1340 		}
1341 		(void)sendpacket(sin6, RIPSIZE(nn));
1342 		return;
1343 	}
1344 	/* Whole routing table dump */
1345 	log_debug("\tRIP Request -- whole routing table");
1346 	ripsend(ifcp, sin6, RRTF_SENDANYWAY);
1347 }
1348 
1349 /*
1350  * Get information of each interface.
1351  */
1352 void
1353 ifconfig(void)
1354 {
1355 	struct ifaddrs *ifap, *ifa;
1356 	struct ifc *ifcp;
1357 	struct ipv6_mreq mreq;
1358 	int s;
1359 
1360 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1361 		fatal("socket");
1362 		/*NOTREACHED*/
1363 	}
1364 
1365 	if (getifaddrs(&ifap) != 0) {
1366 		fatal("getifaddrs");
1367 		/*NOTREACHED*/
1368 	}
1369 
1370 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1371 		if (ifa->ifa_addr->sa_family != AF_INET6)
1372 			continue;
1373 		ifcp = ifc_find(ifa->ifa_name);
1374 		/* we are interested in multicast-capable interfaces */
1375 		if ((ifa->ifa_flags & IFF_MULTICAST) == 0)
1376 			continue;
1377 		if (!ifcp) {
1378 			/* new interface */
1379 			if ((ifcp = calloc(1, sizeof(struct ifc))) == NULL) {
1380 				fatal("calloc: struct ifc");
1381 				/*NOTREACHED*/
1382 			}
1383 			ifcp->ifc_index = -1;
1384 			ifcp->ifc_next = ifc;
1385 			ifc = ifcp;
1386 			nifc++;
1387 			ifcp->ifc_name = xstrdup(ifa->ifa_name);
1388 			ifcp->ifc_addr = 0;
1389 			ifcp->ifc_filter = 0;
1390 			ifcp->ifc_flags = ifa->ifa_flags;
1391 			log_debug("newif %s <%s>", ifcp->ifc_name,
1392 				ifflags(ifcp->ifc_flags));
1393 			if (!strcmp(ifcp->ifc_name, LOOPBACK_IF))
1394 				loopifcp = ifcp;
1395 		} else {
1396 			/* update flag, this may be up again */
1397 			if (ifcp->ifc_flags != ifa->ifa_flags) {
1398 				log_enqueue("%s: <%s> -> ", ifcp->ifc_name,
1399 					ifflags(ifcp->ifc_flags));
1400 				log_debug("<%s>", ifflags(ifa->ifa_flags));
1401 				ifcp->ifc_cflags |= IFC_CHANGED;
1402 			}
1403 			ifcp->ifc_flags = ifa->ifa_flags;
1404 		}
1405 		ifconfig1(ifa->ifa_name, ifa->ifa_addr, ifcp, s);
1406 		if ((ifcp->ifc_flags & (IFF_LOOPBACK | IFF_UP)) == IFF_UP
1407 		 && 0 < ifcp->ifc_index && !ifcp->ifc_joined) {
1408 			mreq.ipv6mr_multiaddr = ifcp->ifc_ripsin.sin6_addr;
1409 			mreq.ipv6mr_interface = ifcp->ifc_index;
1410 			if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
1411 			    &mreq, sizeof(mreq)) < 0) {
1412 				fatalx("IPV6_JOIN_GROUP");
1413 				/*NOTREACHED*/
1414 			}
1415 			log_debug("join %s %s", ifcp->ifc_name, RIP6_DEST);
1416 			ifcp->ifc_joined++;
1417 		}
1418 	}
1419 	close(s);
1420 	freeifaddrs(ifap);
1421 }
1422 
1423 void
1424 ifconfig1(const char *name, const struct sockaddr *sa, struct ifc *ifcp, int s)
1425 {
1426 	struct	in6_ifreq ifr;
1427 	const struct sockaddr_in6 *sin6;
1428 	struct	ifac *ifa;
1429 	int	plen;
1430 	char	buf[BUFSIZ];
1431 
1432 	sin6 = (const struct sockaddr_in6 *)sa;
1433 	if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !lflag)
1434 		return;
1435 	ifr.ifr_addr = *sin6;
1436 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
1437 	if (ioctl(s, SIOCGIFNETMASK_IN6, (char *)&ifr) < 0) {
1438 		fatal("ioctl: SIOCGIFNETMASK_IN6");
1439 		/*NOTREACHED*/
1440 	}
1441 	plen = sin6mask2len(&ifr.ifr_addr);
1442 	if ((ifa = ifa_match(ifcp, &sin6->sin6_addr, plen)) != NULL) {
1443 		/* same interface found */
1444 		/* need check if something changed */
1445 		/* XXX not yet implemented */
1446 		return;
1447 	}
1448 	/*
1449 	 * New address is found
1450 	 */
1451 	if ((ifa = calloc(1, sizeof(struct ifac))) == NULL) {
1452 		fatal("calloc: struct ifac");
1453 		/*NOTREACHED*/
1454 	}
1455 	ifa->ifa_conf = ifcp;
1456 	ifa->ifa_next = ifcp->ifc_addr;
1457 	ifcp->ifc_addr = ifa;
1458 	ifa->ifa_addr = sin6->sin6_addr;
1459 	ifa->ifa_plen = plen;
1460 	if (ifcp->ifc_flags & IFF_POINTOPOINT) {
1461 		ifr.ifr_addr = *sin6;
1462 		if (ioctl(s, SIOCGIFDSTADDR_IN6, (char *)&ifr) < 0) {
1463 			fatal("ioctl: SIOCGIFDSTADDR_IN6");
1464 			/*NOTREACHED*/
1465 		}
1466 		ifa->ifa_raddr = ifr.ifr_dstaddr.sin6_addr;
1467 		inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr, buf, sizeof(buf));
1468 		log_debug("found address %s/%d -- %s",
1469 			inet6_n2p(&ifa->ifa_addr), ifa->ifa_plen, buf);
1470 	} else {
1471 		log_debug("found address %s/%d",
1472 			inet6_n2p(&ifa->ifa_addr), ifa->ifa_plen);
1473 	}
1474 	if (ifcp->ifc_index < 0 && IN6_IS_ADDR_LINKLOCAL(&ifa->ifa_addr)) {
1475 		ifcp->ifc_mylladdr = ifa->ifa_addr;
1476 		ifcp->ifc_index = IN6_LINKLOCAL_IFINDEX(ifa->ifa_addr);
1477 		memcpy(&ifcp->ifc_ripsin, &ripsin, ripsin.ss_len);
1478 		SET_IN6_LINKLOCAL_IFINDEX(ifcp->ifc_ripsin.sin6_addr,
1479 			ifcp->ifc_index);
1480 		setindex2ifc(ifcp->ifc_index, ifcp);
1481 		ifcp->ifc_mtu = getifmtu(ifcp->ifc_index);
1482 		if (ifcp->ifc_mtu > RIP6_MAXMTU)
1483 			ifcp->ifc_mtu = RIP6_MAXMTU;
1484 		if (ioctl(s, SIOCGIFMETRIC, (char *)&ifr) < 0) {
1485 			fatal("ioctl: SIOCGIFMETRIC");
1486 			/*NOTREACHED*/
1487 		}
1488 		ifcp->ifc_metric = ifr.ifr_metric;
1489 		log_debug("\tindex: %d, mtu: %d, metric: %d",
1490 			ifcp->ifc_index, ifcp->ifc_mtu, ifcp->ifc_metric);
1491 	} else
1492 		ifcp->ifc_cflags |= IFC_CHANGED;
1493 }
1494 
1495 /*
1496  * Receive and process routing messages.
1497  * Update interface information as necesssary.
1498  */
1499 void
1500 rtrecv(void)
1501 {
1502 	char buf[BUFSIZ];
1503 	char *p, *q;
1504 	struct rt_msghdr *rtm;
1505 	struct ifa_msghdr *ifam;
1506 	struct if_msghdr *ifm;
1507 	int len;
1508 	struct ifc *ifcp, *ic;
1509 	int iface = 0, rtable = 0;
1510 	struct sockaddr_in6 *rta[RTAX_MAX];
1511 	struct sockaddr_in6 mask;
1512 	int i, addrs;
1513 	struct riprt *rrt;
1514 
1515 	if ((len = read(rtsock, buf, sizeof(buf))) < 0) {
1516 		perror("read from rtsock");
1517 		exit(1);
1518 	}
1519 	if (len < sizeof(*rtm)) {
1520 		log_debug("short read from rtsock: %d (should be > %zu)",
1521 			len, sizeof(*rtm));
1522 		return;
1523 	}
1524 	if (dflag >= 2) {
1525 		log_debug("rtmsg:");
1526 		for (i = 0; i < len; i++) {
1527 			log_enqueue("%02x ", buf[i] & 0xff);
1528 			if (i % 16 == 15)
1529 				log_debug("");
1530 		}
1531 		log_debug("");
1532 	}
1533 
1534 	for (p = buf; p - buf < len; p += ((struct rt_msghdr *)p)->rtm_msglen) {
1535 		/* safety against bogus message */
1536 		if (((struct rt_msghdr *)p)->rtm_msglen <= 0) {
1537 			log_debug("bogus rtmsg: length=%d",
1538 				((struct rt_msghdr *)p)->rtm_msglen);
1539 			break;
1540 		}
1541 		if (((struct rt_msghdr *)p)->rtm_version != RTM_VERSION)
1542 			continue;
1543 
1544 		rtm = NULL;
1545 		ifam = NULL;
1546 		ifm = NULL;
1547 		switch (((struct rt_msghdr *)p)->rtm_type) {
1548 		case RTM_NEWADDR:
1549 		case RTM_DELADDR:
1550 			ifam = (struct ifa_msghdr *)p;
1551 			addrs = ifam->ifam_addrs;
1552 			q = (char *)(ifam + 1);
1553 			break;
1554 		case RTM_IFINFO:
1555 			ifm = (struct if_msghdr *)p;
1556 			addrs = ifm->ifm_addrs;
1557 			q = (char *)(ifm + 1);
1558 			break;
1559 		default:
1560 			rtm = (struct rt_msghdr *)p;
1561 			addrs = rtm->rtm_addrs;
1562 			q = (char *)(p + rtm->rtm_hdrlen);
1563 			if (rtm->rtm_pid == pid) {
1564 #if 0
1565 				log_debug("rtmsg looped back to me, ignored");
1566 #endif
1567 				continue;
1568 			}
1569 			break;
1570 		}
1571 		memset(&rta, 0, sizeof(rta));
1572 		for (i = 0; i < RTAX_MAX; i++) {
1573 			if (addrs & (1 << i)) {
1574 				rta[i] = (struct sockaddr_in6 *)q;
1575 				q += ROUNDUP(rta[i]->sin6_len);
1576 			}
1577 		}
1578 
1579 		log_debug("rtsock: %s (addrs=%x)",
1580 			rttypes((struct rt_msghdr *)p), addrs);
1581  		if (dflag >= 2) {
1582  			for (i = 0;
1583  			     i < ((struct rt_msghdr *)p)->rtm_msglen;
1584  			     i++) {
1585 				log_enqueue("%02x ", p[i] & 0xff);
1586 				if (i % 16 == 15)
1587 					log_debug("");
1588 			}
1589 			log_debug("");
1590 		}
1591 		/*
1592 		 * Easy ones first.
1593 		 *
1594 		 * We may be able to optimize by using ifm->ifm_index or
1595 		 * ifam->ifam_index.  For simplicity we don't do that here.
1596 		 */
1597 		switch (((struct rt_msghdr *)p)->rtm_type) {
1598 		case RTM_NEWADDR:
1599 		case RTM_IFINFO:
1600 			iface++;
1601 			continue;
1602 		case RTM_ADD:
1603 			rtable++;
1604 			continue;
1605 		case RTM_LOSING:
1606 		case RTM_MISS:
1607 		case RTM_RESOLVE:
1608 		case RTM_GET:
1609 		case RTM_LOCK:
1610 			/* nothing to be done here */
1611 			log_debug("\tnothing to be done, ignored");
1612 			continue;
1613 		}
1614 
1615 #if 0
1616 		if (rta[RTAX_DST] == NULL) {
1617 			log_debug("\tno destination, ignored");
1618 			continue;
1619 		}
1620 		if (rta[RTAX_DST]->sin6_family != AF_INET6) {
1621 			log_debug("\taf mismatch, ignored");
1622 			continue;
1623 		}
1624 		if (IN6_IS_ADDR_LINKLOCAL(&rta[RTAX_DST]->sin6_addr)) {
1625 			log_debug("\tlinklocal destination, ignored");
1626 			continue;
1627 		}
1628 		if (IN6_ARE_ADDR_EQUAL(&rta[RTAX_DST]->sin6_addr, &in6addr_loopback)) {
1629 			log_debug("\tloopback destination, ignored");
1630 			continue;		/* Loopback */
1631 		}
1632 		if (IN6_IS_ADDR_MULTICAST(&rta[RTAX_DST]->sin6_addr)) {
1633 			log_debug("\tmulticast destination, ignored");
1634 			continue;
1635 		}
1636 #endif
1637 
1638 		/* hard ones */
1639 		switch (((struct rt_msghdr *)p)->rtm_type) {
1640 		case RTM_NEWADDR:
1641 		case RTM_IFINFO:
1642 		case RTM_ADD:
1643 		case RTM_LOSING:
1644 		case RTM_MISS:
1645 		case RTM_RESOLVE:
1646 		case RTM_GET:
1647 		case RTM_LOCK:
1648 			/* should already be handled */
1649 			fatalx("rtrecv: never reach here");
1650 			/*NOTREACHED*/
1651 		case RTM_DELETE:
1652 			if (!rta[RTAX_DST] || !rta[RTAX_GATEWAY]) {
1653 				log_debug("\tsome of dst/gw/netmask are "
1654 				    "unavailable, ignored");
1655 				break;
1656 			}
1657 			if ((rtm->rtm_flags & RTF_HOST) != 0) {
1658 				mask.sin6_len = sizeof(mask);
1659 				memset(&mask.sin6_addr, 0xff,
1660 				    sizeof(mask.sin6_addr));
1661 				rta[RTAX_NETMASK] = &mask;
1662 			} else if (!rta[RTAX_NETMASK]) {
1663 				log_debug("\tsome of dst/gw/netmask are "
1664 				    "unavailable, ignored");
1665 				break;
1666 			}
1667 			if (rt_del(rta[RTAX_DST], rta[RTAX_GATEWAY],
1668 			    rta[RTAX_NETMASK]) == 0) {
1669 				rtable++;	/*just to be sure*/
1670 			}
1671 			break;
1672 		case RTM_CHANGE:
1673 		case RTM_REDIRECT:
1674 			log_debug("\tnot supported yet, ignored");
1675 			break;
1676 		case RTM_DELADDR:
1677 			if (!rta[RTAX_NETMASK] || !rta[RTAX_IFA]) {
1678 				log_debug("\tno netmask or ifa given, ignored");
1679 				break;
1680 			}
1681 			if (ifam->ifam_index < nindex2ifc)
1682 				ifcp = index2ifc[ifam->ifam_index];
1683 			else
1684 				ifcp = NULL;
1685 			if (!ifcp) {
1686 				log_debug("\tinvalid ifam_index %d, ignored",
1687 					ifam->ifam_index);
1688 				break;
1689 			}
1690 			if (!rt_deladdr(ifcp, rta[RTAX_IFA], rta[RTAX_NETMASK]))
1691 				iface++;
1692 			break;
1693 		}
1694 
1695 	}
1696 
1697 	if (iface) {
1698 		log_debug("rtsock: reconfigure interfaces, refresh interface routes");
1699 		ifconfig();
1700 		for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next)
1701 			if (ifcp->ifc_cflags & IFC_CHANGED) {
1702 				if (ifrt(ifcp, 1)) {
1703 					for (ic = ifc; ic; ic = ic->ifc_next) {
1704 						if (ifcp->ifc_index == ic->ifc_index)
1705 							continue;
1706 						if (ic->ifc_flags & IFF_UP)
1707 							ripsend(ic, &ic->ifc_ripsin,
1708 							RRTF_CHANGED);
1709 					}
1710 					/* Reset the flag */
1711 					for (rrt = riprt; rrt; rrt = rrt->rrt_next)
1712 						rrt->rrt_rflags &= ~RRTF_CHANGED;
1713 				}
1714 				ifcp->ifc_cflags &= ~IFC_CHANGED;
1715 			}
1716 	}
1717 	if (rtable) {
1718 		log_debug("rtsock: read routing table again");
1719 		krtread(1);
1720 	}
1721 }
1722 
1723 /*
1724  * remove specified route from the internal routing table.
1725  */
1726 int
1727 rt_del(const struct sockaddr_in6 *sdst, const struct sockaddr_in6 *sgw,
1728     const struct sockaddr_in6 *smask)
1729 {
1730 	const struct in6_addr *dst = NULL;
1731 	const struct in6_addr *gw = NULL;
1732 	int prefix;
1733 	struct netinfo6 ni6;
1734 	struct riprt *rrt = NULL;
1735 	time_t t_lifetime;
1736 
1737 	if (sdst->sin6_family != AF_INET6) {
1738 		log_debug("\tother AF, ignored");
1739 		return -1;
1740 	}
1741 	if (IN6_IS_ADDR_LINKLOCAL(&sdst->sin6_addr)
1742 	 || IN6_ARE_ADDR_EQUAL(&sdst->sin6_addr, &in6addr_loopback)
1743 	 || IN6_IS_ADDR_MULTICAST(&sdst->sin6_addr)) {
1744 		log_debug("\taddress %s not interesting, ignored",
1745 			inet6_n2p(&sdst->sin6_addr));
1746 		return -1;
1747 	}
1748 	dst = &sdst->sin6_addr;
1749 	if (sgw->sin6_family == AF_INET6) {
1750 		/* easy case */
1751 		gw = &sgw->sin6_addr;
1752 		prefix = sin6mask2len(smask);
1753 	} else if (sgw->sin6_family == AF_LINK) {
1754 		/*
1755 		 * Interface route... a hard case.  We need to get the prefix
1756 		 * length from the kernel, but we now are parsing rtmsg.
1757 		 * We'll purge matching routes from my list, then get the
1758 		 * fresh list.
1759 		 */
1760 		struct riprt *longest;
1761 		log_debug("\t%s is a interface route, guessing prefixlen",
1762 			inet6_n2p(dst));
1763 		longest = NULL;
1764 		for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
1765 			if (IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest,
1766 					&sdst->sin6_addr)
1767 			 && IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw)) {
1768 				if (!longest
1769 				 || longest->rrt_info.rip6_plen <
1770 						 rrt->rrt_info.rip6_plen) {
1771 					longest = rrt;
1772 				}
1773 			}
1774 		}
1775 		rrt = longest;
1776 		if (!rrt) {
1777 			log_debug("\tno matching interface route found");
1778 			return -1;
1779 		}
1780 		gw = &in6addr_loopback;
1781 		prefix = rrt->rrt_info.rip6_plen;
1782 	} else {
1783 		log_debug("\tunsupported af: (gw=%d)", sgw->sin6_family);
1784 		return -1;
1785 	}
1786 
1787 	log_enqueue("\tdeleting %s/%d ", inet6_n2p(dst), prefix);
1788 	log_debug("gw %s", inet6_n2p(gw));
1789 	t_lifetime = time(NULL) - RIP_LIFETIME;
1790 	/* age route for interface address */
1791 	memset(&ni6, 0, sizeof(ni6));
1792 	ni6.rip6_dest = *dst;
1793 	ni6.rip6_plen = prefix;
1794 	applyplen(&ni6.rip6_dest, ni6.rip6_plen);	/*to be sure*/
1795 	log_debug("\tfind route %s/%d", inet6_n2p(&ni6.rip6_dest),
1796 		ni6.rip6_plen);
1797 	if (!rrt && (rrt = rtsearch(&ni6, NULL)) == NULL) {
1798 		log_debug("\tno route found");
1799 		return -1;
1800 	}
1801 #if 0
1802 	if ((rrt->rrt_flags & RTF_STATIC) == 0) {
1803 		log_debug("\tyou can delete static routes only");
1804 	} else
1805 #endif
1806 	if (!IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, gw)) {
1807 		log_enqueue("\tgw mismatch: %s <-> ",
1808 			inet6_n2p(&rrt->rrt_gw));
1809 		log_debug("%s", inet6_n2p(gw));
1810 	} else {
1811 		log_debug("\troute found, age it");
1812 		if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) {
1813 			rrt->rrt_t = t_lifetime;
1814 			rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6;
1815 		}
1816 	}
1817 	return 0;
1818 }
1819 
1820 /*
1821  * remove specified address from internal interface/routing table.
1822  */
1823 int
1824 rt_deladdr(struct ifc *ifcp, const struct sockaddr_in6 *sifa,
1825     const struct sockaddr_in6 *smask)
1826 {
1827 	const struct in6_addr *addr = NULL;
1828 	int prefix;
1829 	struct ifac *ifa = NULL;
1830 	struct netinfo6 ni6;
1831 	struct riprt *rrt = NULL;
1832 	time_t t_lifetime;
1833 	int updated = 0;
1834 
1835 	if (sifa->sin6_family != AF_INET6) {
1836 		log_debug("\tother AF, ignored");
1837 		return -1;
1838 	}
1839 	addr = &sifa->sin6_addr;
1840 	prefix = sin6mask2len(smask);
1841 
1842 	log_debug("\tdeleting %s/%d from %s",
1843 		inet6_n2p(addr), prefix, ifcp->ifc_name);
1844 	ifa = ifa_match(ifcp, addr, prefix);
1845 	if (!ifa) {
1846 		log_debug("\tno matching ifa found for %s/%d on %s",
1847 			inet6_n2p(addr), prefix, ifcp->ifc_name);
1848 		return -1;
1849 	}
1850 	if (ifa->ifa_conf != ifcp) {
1851 		log_debug("\taddress table corrupt: back pointer does not match "
1852 			"(%s != %s)",
1853 			ifcp->ifc_name, ifa->ifa_conf->ifc_name);
1854 		return -1;
1855 	}
1856 	/* remove ifa from interface */
1857 	if (ifcp->ifc_addr == ifa)
1858 		ifcp->ifc_addr = ifa->ifa_next;
1859 	else {
1860 		struct ifac *p;
1861 		for (p = ifcp->ifc_addr; p; p = p->ifa_next) {
1862 			if (p->ifa_next == ifa) {
1863 				p->ifa_next = ifa->ifa_next;
1864 				break;
1865 			}
1866 		}
1867 	}
1868 	ifa->ifa_next = NULL;
1869 	ifa->ifa_conf = NULL;
1870 	t_lifetime = time(NULL) - RIP_LIFETIME;
1871 	/* age route for interface address */
1872 	memset(&ni6, 0, sizeof(ni6));
1873 	ni6.rip6_dest = ifa->ifa_addr;
1874 	ni6.rip6_plen = ifa->ifa_plen;
1875 	applyplen(&ni6.rip6_dest, ni6.rip6_plen);
1876 	log_debug("\tfind interface route %s/%d on %d",
1877 		inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen, ifcp->ifc_index);
1878 	if ((rrt = rtsearch(&ni6, NULL)) != NULL) {
1879 		struct in6_addr none;
1880 		memset(&none, 0, sizeof(none));
1881 		if (rrt->rrt_index == ifcp->ifc_index &&
1882 		    (IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &none) ||
1883 		     IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw))) {
1884 			log_debug("\troute found, age it");
1885 			if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) {
1886 				rrt->rrt_t = t_lifetime;
1887 				rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6;
1888 			}
1889 			updated++;
1890 		} else {
1891 			log_debug("\tnon-interface route found: %s/%d on %d",
1892 				inet6_n2p(&rrt->rrt_info.rip6_dest),
1893 				rrt->rrt_info.rip6_plen,
1894 				rrt->rrt_index);
1895 		}
1896 	} else
1897 		log_debug("\tno interface route found");
1898 	/* age route for p2p destination */
1899 	if (ifcp->ifc_flags & IFF_POINTOPOINT) {
1900 		memset(&ni6, 0, sizeof(ni6));
1901 		ni6.rip6_dest = ifa->ifa_raddr;
1902 		ni6.rip6_plen = 128;
1903 		applyplen(&ni6.rip6_dest, ni6.rip6_plen);	/*to be sure*/
1904 		log_debug("\tfind p2p route %s/%d on %d",
1905 			inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen,
1906 			ifcp->ifc_index);
1907 		if ((rrt = rtsearch(&ni6, NULL)) != NULL) {
1908 			if (rrt->rrt_index == ifcp->ifc_index &&
1909 			    IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &ifa->ifa_addr)) {
1910 				log_debug("\troute found, age it");
1911 				if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) {
1912 					rrt->rrt_t = t_lifetime;
1913 					rrt->rrt_info.rip6_metric =
1914 					    HOPCNT_INFINITY6;
1915 					updated++;
1916 				}
1917 			} else {
1918 				log_debug("\tnon-p2p route found: %s/%d on %d",
1919 					inet6_n2p(&rrt->rrt_info.rip6_dest),
1920 					rrt->rrt_info.rip6_plen,
1921 					rrt->rrt_index);
1922 			}
1923 		} else
1924 			log_debug("\tno p2p route found");
1925 	}
1926 	return updated ? 0 : -1;
1927 }
1928 
1929 /*
1930  * Get each interface address and put those interface routes to the route
1931  * list.
1932  */
1933 int
1934 ifrt(struct ifc *ifcp, int again)
1935 {
1936 	struct ifac *ifa;
1937 	struct riprt *rrt = NULL, *search_rrt, *prev_rrt, *loop_rrt;
1938 	struct netinfo6 *np;
1939 	time_t t_lifetime;
1940 	int need_trigger = 0;
1941 
1942 #if 0
1943 	if (ifcp->ifc_flags & IFF_LOOPBACK)
1944 		return 0;			/* ignore loopback */
1945 #endif
1946 
1947 	if (ifcp->ifc_flags & IFF_POINTOPOINT) {
1948 		ifrt_p2p(ifcp, again);
1949 		return 0;
1950 	}
1951 
1952 	for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
1953 		if (IN6_IS_ADDR_LINKLOCAL(&ifa->ifa_addr)) {
1954 #if 0
1955 			log_debug("route: %s on %s: "
1956 			    "skip linklocal interface address",
1957 			    inet6_n2p(&ifa->ifa_addr), ifcp->ifc_name);
1958 #endif
1959 			continue;
1960 		}
1961 		if (IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_addr)) {
1962 #if 0
1963 			log_debug("route: %s: skip unspec interface address",
1964 			    ifcp->ifc_name);
1965 #endif
1966 			continue;
1967 		}
1968 		if (IN6_IS_ADDR_LOOPBACK(&ifa->ifa_addr)) {
1969 #if 0
1970 			log_debug("route: %s: skip loopback address",
1971 			    ifcp->ifc_name);
1972 #endif
1973 			continue;
1974 		}
1975 		if (ifcp->ifc_flags & IFF_UP) {
1976 			if ((rrt = calloc(1, sizeof(struct riprt))) == NULL)
1977 				fatal("calloc: struct riprt");
1978 			rrt->rrt_index = ifcp->ifc_index;
1979 			rrt->rrt_t = 0;	/* don't age */
1980 			rrt->rrt_info.rip6_dest = ifa->ifa_addr;
1981 			rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
1982 			rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric;
1983 			rrt->rrt_info.rip6_plen = ifa->ifa_plen;
1984 			if (ifa->ifa_plen == 128)
1985 				rrt->rrt_flags = RTF_HOST;
1986 			else
1987 				rrt->rrt_flags = RTF_CLONING;
1988 			rrt->rrt_rflags |= RRTF_CHANGED;
1989 			applyplen(&rrt->rrt_info.rip6_dest, ifa->ifa_plen);
1990 			memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
1991 			rrt->rrt_gw = ifa->ifa_addr;
1992 			np = &rrt->rrt_info;
1993 			search_rrt = rtsearch(np, &prev_rrt);
1994 			if (search_rrt != NULL) {
1995 				if (search_rrt->rrt_info.rip6_metric <=
1996 				    rrt->rrt_info.rip6_metric) {
1997 					/* Already have better route */
1998 					if (!again) {
1999 						log_debug("route: %s/%d: "
2000 						    "already registered (%s)",
2001 						    inet6_n2p(&np->rip6_dest), np->rip6_plen,
2002 						    ifcp->ifc_name);
2003 					}
2004 					goto next;
2005 				}
2006 
2007 				if (prev_rrt)
2008 					prev_rrt->rrt_next = rrt->rrt_next;
2009 				else
2010 					riprt = rrt->rrt_next;
2011 				delroute(&rrt->rrt_info, &rrt->rrt_gw);
2012 			}
2013 			/* Attach the route to the list */
2014 			log_debug("route: %s/%d: register route (%s)",
2015 			    inet6_n2p(&np->rip6_dest), np->rip6_plen,
2016 			    ifcp->ifc_name);
2017 			rrt->rrt_next = riprt;
2018 			riprt = rrt;
2019 			addroute(rrt, &rrt->rrt_gw, ifcp);
2020 			rrt = NULL;
2021 			sendrequest(ifcp);
2022 			ripsend(ifcp, &ifcp->ifc_ripsin, 0);
2023 			need_trigger = 1;
2024 		} else {
2025 			for (loop_rrt = riprt; loop_rrt; loop_rrt = loop_rrt->rrt_next) {
2026 				if (loop_rrt->rrt_index == ifcp->ifc_index) {
2027 					t_lifetime = time(NULL) - RIP_LIFETIME;
2028 					if (loop_rrt->rrt_t == 0 || loop_rrt->rrt_t > t_lifetime) {
2029 						loop_rrt->rrt_t = t_lifetime;
2030 						loop_rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6;
2031 						loop_rrt->rrt_rflags |= RRTF_CHANGED;
2032 						need_trigger = 1;
2033 					}
2034 				}
2035 			}
2036                 }
2037 	next:
2038 		free(rrt);
2039 	}
2040 	return need_trigger;
2041 }
2042 
2043 /*
2044  * there are couple of p2p interface routing models.  "behavior" lets
2045  * you pick one.  it looks that gated behavior fits best with BSDs,
2046  * since BSD kernels do not look at prefix length on p2p interfaces.
2047  */
2048 void
2049 ifrt_p2p(struct ifc *ifcp, int again)
2050 {
2051 	struct ifac *ifa;
2052 	struct riprt *rrt, *orrt, *prevrrt;
2053 	struct netinfo6 *np;
2054 	struct in6_addr addr, dest;
2055 	int advert, ignore, i;
2056 #define P2PADVERT_NETWORK	1
2057 #define P2PADVERT_ADDR		2
2058 #define P2PADVERT_DEST		4
2059 #define P2PADVERT_MAX		4
2060 	const enum { CISCO, GATED, ROUTE6D } behavior = GATED;
2061 	const char *category = "";
2062 	const char *noadv;
2063 
2064 	for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
2065 		addr = ifa->ifa_addr;
2066 		dest = ifa->ifa_raddr;
2067 		applyplen(&addr, ifa->ifa_plen);
2068 		applyplen(&dest, ifa->ifa_plen);
2069 		advert = ignore = 0;
2070 		switch (behavior) {
2071 		case CISCO:
2072 			/*
2073 			 * honor addr/plen, just like normal shared medium
2074 			 * interface.  this may cause trouble if you reuse
2075 			 * addr/plen on other interfaces.
2076 			 *
2077 			 * advertise addr/plen.
2078 			 */
2079 			advert |= P2PADVERT_NETWORK;
2080 			break;
2081 		case GATED:
2082 			/*
2083 			 * prefixlen on p2p interface is meaningless.
2084 			 * advertise addr/128 and dest/128.
2085 			 *
2086 			 * do not install network route to route6d routing
2087 			 * table (if we do, it would prevent route installation
2088 			 * for other p2p interface that shares addr/plen).
2089 			 *
2090 			 * XXX what should we do if dest is ::?  it will not
2091 			 * get announced anyways (see following filter),
2092 			 * but we need to think.
2093 			 */
2094 			advert |= P2PADVERT_ADDR;
2095 			advert |= P2PADVERT_DEST;
2096 			ignore |= P2PADVERT_NETWORK;
2097 			break;
2098 		case ROUTE6D:
2099 			/*
2100 			 * just for testing.  actually the code is redundant
2101 			 * given the current p2p interface address assignment
2102 			 * rule for kame kernel.
2103 			 *
2104 			 * intent:
2105 			 *	A/n -> announce A/n
2106 			 *	A B/n, A and B share prefix -> A/n (= B/n)
2107 			 *	A B/n, do not share prefix -> A/128 and B/128
2108 			 * actually, A/64 and A B/128 are the only cases
2109 			 * permitted by the kernel:
2110 			 *	A/64 -> A/64
2111 			 *	A B/128 -> A/128 and B/128
2112 			 */
2113 			if (!IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_raddr)) {
2114 				if (IN6_ARE_ADDR_EQUAL(&addr, &dest))
2115 					advert |= P2PADVERT_NETWORK;
2116 				else {
2117 					advert |= P2PADVERT_ADDR;
2118 					advert |= P2PADVERT_DEST;
2119 					ignore |= P2PADVERT_NETWORK;
2120 				}
2121 			} else
2122 				advert |= P2PADVERT_NETWORK;
2123 			break;
2124 		}
2125 
2126 		for (i = 1; i <= P2PADVERT_MAX; i *= 2) {
2127 			if ((ignore & i) != 0)
2128 				continue;
2129 			if ((rrt = calloc(1, sizeof(struct riprt))) == NULL) {
2130 				fatal("calloc: struct riprt");
2131 				/*NOTREACHED*/
2132 			}
2133 			rrt->rrt_index = ifcp->ifc_index;
2134 			rrt->rrt_t = 0;	/* don't age */
2135 			switch (i) {
2136 			case P2PADVERT_NETWORK:
2137 				rrt->rrt_info.rip6_dest = ifa->ifa_addr;
2138 				rrt->rrt_info.rip6_plen = ifa->ifa_plen;
2139 				applyplen(&rrt->rrt_info.rip6_dest,
2140 				    ifa->ifa_plen);
2141 				category = "network";
2142 				break;
2143 			case P2PADVERT_ADDR:
2144 				rrt->rrt_info.rip6_dest = ifa->ifa_addr;
2145 				rrt->rrt_info.rip6_plen = 128;
2146 				rrt->rrt_gw = in6addr_loopback;
2147 				category = "addr";
2148 				break;
2149 			case P2PADVERT_DEST:
2150 				rrt->rrt_info.rip6_dest = ifa->ifa_raddr;
2151 				rrt->rrt_info.rip6_plen = 128;
2152 				rrt->rrt_gw = ifa->ifa_addr;
2153 				category = "dest";
2154 				break;
2155 			}
2156 			if (IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_info.rip6_dest) ||
2157 			    IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_info.rip6_dest)) {
2158 #if 0
2159 				log_debug("route: %s: skip unspec/linklocal "
2160 				    "(%s on %s)", category, ifcp->ifc_name);
2161 #endif
2162 				free(rrt);
2163 				continue;
2164 			}
2165 			if ((advert & i) == 0) {
2166 				rrt->rrt_rflags |= RRTF_NOADVERTISE;
2167 				noadv = ", NO-ADV";
2168 			} else
2169 				noadv = "";
2170 			rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
2171 			rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric;
2172 			np = &rrt->rrt_info;
2173 			orrt = rtsearch(np, &prevrrt);
2174 			if (!orrt) {
2175 				/* Attach the route to the list */
2176 				log_debug("route: %s/%d: register route "
2177 				    "(%s on %s%s)",
2178 				    inet6_n2p(&np->rip6_dest), np->rip6_plen,
2179 				    category, ifcp->ifc_name, noadv);
2180 				rrt->rrt_next = riprt;
2181 				riprt = rrt;
2182 			} else if (rrt->rrt_index != orrt->rrt_index ||
2183 			    rrt->rrt_info.rip6_metric != orrt->rrt_info.rip6_metric) {
2184 				/* swap route */
2185 				rrt->rrt_next = orrt->rrt_next;
2186 				if (prevrrt)
2187 					prevrrt->rrt_next = rrt;
2188 				else
2189 					riprt = rrt;
2190 				free(orrt);
2191 
2192 				log_debug("route: %s/%d: update (%s on %s%s)",
2193 				    inet6_n2p(&np->rip6_dest), np->rip6_plen,
2194 				    category, ifcp->ifc_name, noadv);
2195 			} else {
2196 				/* Already found */
2197 				if (!again) {
2198 					log_debug("route: %s/%d: "
2199 					    "already registered (%s on %s%s)",
2200 					    inet6_n2p(&np->rip6_dest),
2201 					    np->rip6_plen, category,
2202 					    ifcp->ifc_name, noadv);
2203 				}
2204 				free(rrt);
2205 			}
2206 		}
2207 	}
2208 #undef P2PADVERT_NETWORK
2209 #undef P2PADVERT_ADDR
2210 #undef P2PADVERT_DEST
2211 #undef P2PADVERT_MAX
2212 }
2213 
2214 int
2215 getifmtu(int ifindex)
2216 {
2217 	int	mib[6];
2218 	char	*buf = NULL;
2219 	size_t	needed;
2220 	struct	if_msghdr *ifm;
2221 	int	mtu;
2222 
2223 	mib[0] = CTL_NET;
2224 	mib[1] = PF_ROUTE;
2225 	mib[2] = 0;
2226 	mib[3] = AF_INET6;
2227 	mib[4] = NET_RT_IFLIST;
2228 	mib[5] = ifindex;
2229 	while (1) {
2230 		if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
2231 			fatal("sysctl estimate NET_RT_IFLIST");
2232 		if (needed == 0)
2233 			break;
2234 		if ((buf = realloc(buf, needed)) == NULL)
2235 			fatal(NULL);
2236 		if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) {
2237 			if (errno == ENOMEM)
2238 				continue;
2239 			fatal("sysctl NET_RT_IFLIST");
2240 		}
2241 		break;
2242 	}
2243 	ifm = (struct if_msghdr *)buf;
2244 	mtu = ifm->ifm_data.ifi_mtu;
2245 	free(buf);
2246 	return mtu;
2247 }
2248 
2249 const char *
2250 rttypes(struct rt_msghdr *rtm)
2251 {
2252 #define	RTTYPE(s, f) \
2253 do { \
2254 	if (rtm->rtm_type == (f)) \
2255 		return (s); \
2256 } while (0)
2257 	RTTYPE("ADD", RTM_ADD);
2258 	RTTYPE("DELETE", RTM_DELETE);
2259 	RTTYPE("CHANGE", RTM_CHANGE);
2260 	RTTYPE("GET", RTM_GET);
2261 	RTTYPE("LOSING", RTM_LOSING);
2262 	RTTYPE("REDIRECT", RTM_REDIRECT);
2263 	RTTYPE("MISS", RTM_MISS);
2264 	RTTYPE("LOCK", RTM_LOCK);
2265 	RTTYPE("RESOLVE", RTM_RESOLVE);
2266 	RTTYPE("NEWADDR", RTM_NEWADDR);
2267 	RTTYPE("DELADDR", RTM_DELADDR);
2268 	RTTYPE("IFINFO", RTM_IFINFO);
2269 #ifdef RTM_OIFINFO
2270 	RTTYPE("OIFINFO", RTM_OIFINFO);
2271 #endif
2272 #ifdef RTM_IFANNOUNCE
2273 	RTTYPE("IFANNOUNCE", RTM_IFANNOUNCE);
2274 #endif
2275 #ifdef RTM_NEWMADDR
2276 	RTTYPE("NEWMADDR", RTM_NEWMADDR);
2277 #endif
2278 #ifdef RTM_DELMADDR
2279 	RTTYPE("DELMADDR", RTM_DELMADDR);
2280 #endif
2281 #undef RTTYPE
2282 	return NULL;
2283 }
2284 
2285 const char *
2286 rtflags(struct rt_msghdr *rtm)
2287 {
2288 	static char buf[BUFSIZ];
2289 
2290 	/*
2291 	 * letter conflict should be okay.  painful when *BSD diverges...
2292 	 */
2293 	strlcpy(buf, "", sizeof(buf));
2294 #define	RTFLAG(s, f) \
2295 do { \
2296 	if (rtm->rtm_flags & (f)) \
2297 		strlcat(buf, (s), sizeof(buf)); \
2298 } while (0)
2299 	RTFLAG("U", RTF_UP);
2300 	RTFLAG("G", RTF_GATEWAY);
2301 	RTFLAG("H", RTF_HOST);
2302 	RTFLAG("R", RTF_REJECT);
2303 	RTFLAG("D", RTF_DYNAMIC);
2304 	RTFLAG("M", RTF_MODIFIED);
2305 	RTFLAG("d", RTF_DONE);
2306 	RTFLAG("m", RTF_MULTICAST);
2307 	RTFLAG("C", RTF_CLONING);
2308 	RTFLAG("c", RTF_CLONED);
2309 	RTFLAG("L", RTF_LLINFO);
2310 	RTFLAG("S", RTF_STATIC);
2311 	RTFLAG("B", RTF_BLACKHOLE);
2312 	RTFLAG("3", RTF_PROTO3);
2313 	RTFLAG("2", RTF_PROTO2);
2314 	RTFLAG("1", RTF_PROTO1);
2315 	RTFLAG("b", RTF_BROADCAST);
2316 #undef RTFLAG
2317 	return buf;
2318 }
2319 
2320 const char *
2321 ifflags(int flags)
2322 {
2323 	static char buf[BUFSIZ];
2324 
2325 	strlcpy(buf, "", sizeof(buf));
2326 #define	IFFLAG(s, f) \
2327 do { \
2328 	if (flags & (f)) { \
2329 		if (buf[0]) \
2330 			strlcat(buf, ",", sizeof(buf)); \
2331 		strlcat(buf, (s), sizeof(buf)); \
2332 	} \
2333 } while (0)
2334 	IFFLAG("UP", IFF_UP);
2335 	IFFLAG("BROADCAST", IFF_BROADCAST);
2336 	IFFLAG("DEBUG", IFF_DEBUG);
2337 	IFFLAG("LOOPBACK", IFF_LOOPBACK);
2338 	IFFLAG("POINTOPOINT", IFF_POINTOPOINT);
2339 #ifdef IFF_NOTRAILERS
2340 	IFFLAG("NOTRAILERS", IFF_NOTRAILERS);
2341 #endif
2342 #ifdef IFF_SMART
2343 	IFFLAG("SMART", IFF_SMART);
2344 #endif
2345 	IFFLAG("RUNNING", IFF_RUNNING);
2346 	IFFLAG("NOARP", IFF_NOARP);
2347 	IFFLAG("PROMISC", IFF_PROMISC);
2348 	IFFLAG("ALLMULTI", IFF_ALLMULTI);
2349 	IFFLAG("OACTIVE", IFF_OACTIVE);
2350 	IFFLAG("SIMPLEX", IFF_SIMPLEX);
2351 	IFFLAG("LINK0", IFF_LINK0);
2352 	IFFLAG("LINK1", IFF_LINK1);
2353 	IFFLAG("LINK2", IFF_LINK2);
2354 	IFFLAG("MULTICAST", IFF_MULTICAST);
2355 #undef IFFLAG
2356 	return buf;
2357 }
2358 
2359 void
2360 krtread(int again)
2361 {
2362 	int mib[6];
2363 	size_t msize;
2364 	char *buf, *p, *lim;
2365 	struct rt_msghdr *rtm;
2366 	int retry;
2367 	const char *errmsg;
2368 
2369 	retry = 0;
2370 	buf = NULL;
2371 	mib[0] = CTL_NET;
2372 	mib[1] = PF_ROUTE;
2373 	mib[2] = 0;
2374 	mib[3] = AF_INET6;	/* Address family */
2375 	mib[4] = NET_RT_DUMP;	/* Dump the kernel routing table */
2376 	mib[5] = 0;		/* No flags */
2377 	do {
2378 		retry++;
2379 		free(buf);
2380 		buf = NULL;
2381 		errmsg = NULL;
2382 		if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0) {
2383 			errmsg = "sysctl estimate";
2384 			continue;
2385 		}
2386 		if ((buf = malloc(msize)) == NULL) {
2387 			errmsg = "malloc";
2388 			continue;
2389 		}
2390 		if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0) {
2391 			errmsg = "sysctl NET_RT_DUMP";
2392 			continue;
2393 		}
2394 	} while (retry < 5 && errmsg != NULL);
2395 	if (errmsg) {
2396 		fatal(errmsg);
2397 		/*NOTREACHED*/
2398 	} else if (1 < retry)
2399 		log_info("NET_RT_DUMP %d retries", retry);
2400 
2401 	lim = buf + msize;
2402 	for (p = buf; p < lim; p += rtm->rtm_msglen) {
2403 		rtm = (struct rt_msghdr *)p;
2404 		if (rtm->rtm_version != RTM_VERSION)
2405 			continue;
2406 		rt_entry(rtm, again);
2407 	}
2408 	free(buf);
2409 }
2410 
2411 void
2412 rt_entry(struct rt_msghdr *rtm, int again)
2413 {
2414 	struct	sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask;
2415 	struct	sockaddr_in6 *sin6_ifp;
2416 	char	*rtmp, *ifname = NULL;
2417 	struct	riprt *rrt, *orrt;
2418 	struct	netinfo6 *np;
2419 	int	s;
2420 
2421 	sin6_dst = sin6_gw = sin6_mask = sin6_ifp = 0;
2422 	if ((rtm->rtm_flags & RTF_UP) == 0 || rtm->rtm_flags &
2423 		(RTF_CLONING|RTF_LLINFO|RTF_BLACKHOLE)) {
2424 		return;		/* not interested in the link route */
2425 	}
2426 	/* do not look at cloned routes */
2427 #ifdef RTF_WASCLONED
2428 	if (rtm->rtm_flags & RTF_WASCLONED)
2429 		return;
2430 #endif
2431 #ifdef RTF_CLONED
2432 	if (rtm->rtm_flags & RTF_CLONED)
2433 		return;
2434 #endif
2435 	/*
2436 	 * do not look at dynamic routes.
2437 	 * netbsd/openbsd cloned routes have UGHD.
2438 	 */
2439 	if (rtm->rtm_flags & RTF_DYNAMIC)
2440 		return;
2441 	rtmp = (char *)((char *)rtm + rtm->rtm_hdrlen);
2442 	/* Destination */
2443 	if ((rtm->rtm_addrs & RTA_DST) == 0)
2444 		return;		/* ignore routes without destination address */
2445 	sin6_dst = (struct sockaddr_in6 *)rtmp;
2446 	rtmp += ROUNDUP(sin6_dst->sin6_len);
2447 	if (rtm->rtm_addrs & RTA_GATEWAY) {
2448 		sin6_gw = (struct sockaddr_in6 *)rtmp;
2449 		rtmp += ROUNDUP(sin6_gw->sin6_len);
2450 	}
2451 	if (rtm->rtm_addrs & RTA_NETMASK) {
2452 		sin6_mask = (struct sockaddr_in6 *)rtmp;
2453 		rtmp += ROUNDUP(sin6_mask->sin6_len);
2454 	}
2455 	if (rtm->rtm_addrs & RTA_IFP) {
2456 		sin6_ifp = (struct sockaddr_in6 *)rtmp;
2457 		rtmp += ROUNDUP(sin6_ifp->sin6_len);
2458 	}
2459 
2460 	/* Destination */
2461 	if (sin6_dst->sin6_family != AF_INET6)
2462 		return;
2463 	if (IN6_IS_ADDR_LINKLOCAL(&sin6_dst->sin6_addr))
2464 		return;		/* Link-local */
2465 	if (IN6_ARE_ADDR_EQUAL(&sin6_dst->sin6_addr, &in6addr_loopback))
2466 		return;		/* Loopback */
2467 	if (IN6_IS_ADDR_MULTICAST(&sin6_dst->sin6_addr))
2468 		return;
2469 
2470 	if ((rrt = calloc(1, sizeof(struct riprt))) == NULL) {
2471 		fatal("calloc: struct riprt");
2472 		/*NOTREACHED*/
2473 	}
2474 	np = &rrt->rrt_info;
2475 	rrt->rrt_t = time(NULL);
2476 	if (aflag == 0 && (rtm->rtm_flags & RTF_STATIC))
2477 		rrt->rrt_t = 0;	/* Don't age static routes */
2478 	if ((rtm->rtm_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
2479 		rrt->rrt_t = 0;	/* Don't age non-gateway host routes */
2480 	np->rip6_tag = 0;
2481 	np->rip6_metric = 1;
2482 	rrt->rrt_flags = rtm->rtm_flags;
2483 	np->rip6_dest = sin6_dst->sin6_addr;
2484 
2485 	/* Mask or plen */
2486 	if (rtm->rtm_flags & RTF_HOST)
2487 		np->rip6_plen = 128;	/* Host route */
2488 	else if (sin6_mask)
2489 		np->rip6_plen = sin6mask2len(sin6_mask);
2490 	else
2491 		np->rip6_plen = 0;
2492 
2493 	orrt = rtsearch(np, NULL);
2494 	if (orrt && orrt->rrt_info.rip6_metric != HOPCNT_INFINITY6) {
2495 		/* Already found */
2496 		if (!again) {
2497 			log_debug("route: %s/%d flags %s: already registered",
2498 				inet6_n2p(&np->rip6_dest), np->rip6_plen,
2499 				rtflags(rtm));
2500 		}
2501 		free(rrt);
2502 		return;
2503 	}
2504 	/* Gateway */
2505 	if (!sin6_gw)
2506 		memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
2507 	else {
2508 		if (sin6_gw->sin6_family == AF_INET6)
2509 			rrt->rrt_gw = sin6_gw->sin6_addr;
2510 		else if (sin6_gw->sin6_family == AF_LINK) {
2511 			/* XXX in case ppp link? */
2512 			rrt->rrt_gw = in6addr_loopback;
2513 		} else
2514 			memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
2515 	}
2516 	log_enqueue("route: %s/%d flags %s",
2517 		inet6_n2p(&np->rip6_dest), np->rip6_plen, rtflags(rtm));
2518 	log_enqueue(" gw %s", inet6_n2p(&rrt->rrt_gw));
2519 
2520 	/* Interface */
2521 	s = rtm->rtm_index;
2522 	if (s < nindex2ifc && index2ifc[s])
2523 		ifname = index2ifc[s]->ifc_name;
2524 	else {
2525 		log_debug(" not configured");
2526 		free(rrt);
2527 		return;
2528 	}
2529 	log_debug(" if %s sock %d", ifname, s);
2530 	rrt->rrt_index = s;
2531 
2532 	/* Check gateway */
2533 	if (!IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_gw) &&
2534 	    !IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw)) {
2535 		log_warnx("***** Gateway %s is not a link-local address.",
2536 			inet6_n2p(&rrt->rrt_gw));
2537 		log_warnx("*****     dest(%s) if(%s) -- Not optimized.",
2538 			inet6_n2p(&rrt->rrt_info.rip6_dest), ifname);
2539 		rrt->rrt_rflags |= RRTF_NH_NOT_LLADDR;
2540 	}
2541 
2542 	/* Put it to the route list */
2543 	if (orrt && orrt->rrt_info.rip6_metric == HOPCNT_INFINITY6) {
2544 		/* replace route list */
2545 		rrt->rrt_next = orrt->rrt_next;
2546 		*orrt = *rrt;
2547 		log_debug("route: %s/%d flags %s: replace new route",
2548 		    inet6_n2p(&np->rip6_dest), np->rip6_plen,
2549 		    rtflags(rtm));
2550 		free(rrt);
2551 	} else {
2552 		rrt->rrt_next = riprt;
2553 		riprt = rrt;
2554 	}
2555 }
2556 
2557 int
2558 addroute(struct riprt *rrt, const struct in6_addr *gw, struct ifc *ifcp)
2559 {
2560 	struct	netinfo6 *np;
2561 	u_char	buf[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ];
2562 	struct	rt_msghdr	*rtm;
2563 	struct	sockaddr_in6	*sin6;
2564 	int	len;
2565 
2566 	np = &rrt->rrt_info;
2567 	inet_ntop(AF_INET6, (const void *)gw, (char *)buf1, sizeof(buf1));
2568 	inet_ntop(AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2));
2569 	if (uflag)
2570 		log_info("RTADD: %s/%d gw %s [%d] ifa %s",
2571 		    inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1,
2572 		    np->rip6_metric - 1, buf2);
2573 	else
2574 		log_debug("RTADD: %s/%d gw %s [%d] ifa %s",
2575 		    inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1,
2576 		    np->rip6_metric - 1, buf2);
2577 
2578 	if (nflag)
2579 		return 0;
2580 
2581 	memset(buf, 0, sizeof(buf));
2582 	rtm = (struct rt_msghdr *)buf;
2583 	rtm->rtm_type = RTM_ADD;
2584 	rtm->rtm_version = RTM_VERSION;
2585 	rtm->rtm_seq = ++seq;
2586 	rtm->rtm_flags = rrt->rrt_flags;
2587 	rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
2588 	rtm->rtm_inits = RTV_HOPCOUNT;
2589 	sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
2590 	/* Destination */
2591 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2592 	sin6->sin6_family = AF_INET6;
2593 	sin6->sin6_addr = np->rip6_dest;
2594 	sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
2595 	/* Gateway */
2596 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2597 	sin6->sin6_family = AF_INET6;
2598 	sin6->sin6_addr = *gw;
2599 	sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
2600 	/* Netmask */
2601 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2602 	sin6->sin6_family = AF_INET6;
2603 	sin6->sin6_addr = *(plen2mask(np->rip6_plen));
2604 	sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
2605 
2606 	len = (char *)sin6 - (char *)buf;
2607 	rtm->rtm_msglen = len;
2608 	if (write(rtsock, buf, len) > 0)
2609 		return 0;
2610 
2611 	if (errno == EEXIST) {
2612 		log_warnx("RTADD: Route already exists %s/%d gw %s",
2613 		    inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1);
2614 	} else {
2615 		log_warnx("RTADD: Can not write to rtsock (addroute): %s",
2616 		    strerror(errno));
2617 	}
2618 	return -1;
2619 }
2620 
2621 int
2622 delroute(struct netinfo6 *np, struct in6_addr *gw)
2623 {
2624 	u_char	buf[BUFSIZ], buf2[BUFSIZ];
2625 	struct	rt_msghdr	*rtm;
2626 	struct	sockaddr_in6	*sin6;
2627 	int	len;
2628 
2629 	inet_ntop(AF_INET6, (void *)gw, (char *)buf2, sizeof(buf2));
2630 	if (uflag)
2631 		log_info("RTDEL: %s/%d gw %s", inet6_n2p(&np->rip6_dest),
2632 		    np->rip6_plen, buf2);
2633 	else
2634 		log_debug("RTDEL: %s/%d gw %s", inet6_n2p(&np->rip6_dest),
2635 		    np->rip6_plen, buf2);
2636 
2637 	if (nflag)
2638 		return 0;
2639 
2640 	memset(buf, 0, sizeof(buf));
2641 	rtm = (struct rt_msghdr *)buf;
2642 	rtm->rtm_type = RTM_DELETE;
2643 	rtm->rtm_version = RTM_VERSION;
2644 	rtm->rtm_seq = ++seq;
2645 	rtm->rtm_flags = RTF_UP | RTF_GATEWAY;
2646 	if (np->rip6_plen == sizeof(struct in6_addr) * 8)
2647 		rtm->rtm_flags |= RTF_HOST;
2648 	rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
2649 	sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
2650 	/* Destination */
2651 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2652 	sin6->sin6_family = AF_INET6;
2653 	sin6->sin6_addr = np->rip6_dest;
2654 	sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
2655 	/* Gateway */
2656 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2657 	sin6->sin6_family = AF_INET6;
2658 	sin6->sin6_addr = *gw;
2659 	sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
2660 	/* Netmask */
2661 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2662 	sin6->sin6_family = AF_INET6;
2663 	sin6->sin6_addr = *(plen2mask(np->rip6_plen));
2664 	sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
2665 
2666 	len = (char *)sin6 - (char *)buf;
2667 	rtm->rtm_msglen = len;
2668 	if (write(rtsock, buf, len) >= 0)
2669 		return 0;
2670 
2671 	if (errno == ESRCH) {
2672 		log_warnx("RTDEL: Route does not exist: %s/%d gw %s",
2673 		    inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2);
2674 	} else {
2675 		log_warnx("RTDEL: Can not write to rtsock (delroute): %s",
2676 		    strerror(errno));
2677 	}
2678 	return -1;
2679 }
2680 
2681 struct in6_addr *
2682 getroute(struct netinfo6 *np, struct in6_addr *gw)
2683 {
2684 	u_char buf[BUFSIZ];
2685 	int len;
2686 	struct rt_msghdr *rtm;
2687 	struct sockaddr_in6 *sin6;
2688 
2689 	rtm = (struct rt_msghdr *)buf;
2690 	len = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in6);
2691 	memset(rtm, 0, len);
2692 	rtm->rtm_type = RTM_GET;
2693 	rtm->rtm_version = RTM_VERSION;
2694 	rtm->rtm_seq = ++seq;
2695 	rtm->rtm_addrs = RTA_DST;
2696 	rtm->rtm_msglen = len;
2697 	sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
2698 	sin6->sin6_len = sizeof(struct sockaddr_in6);
2699 	sin6->sin6_family = AF_INET6;
2700 	sin6->sin6_addr = np->rip6_dest;
2701 	if (write(rtsock, buf, len) < 0) {
2702 		if (errno == ESRCH)	/* No such route found */
2703 			return NULL;
2704 		perror("write to rtsock");
2705 		exit(1);
2706 	}
2707 	do {
2708 		if ((len = read(rtsock, buf, sizeof(buf))) < 0) {
2709 			perror("read from rtsock");
2710 			exit(1);
2711 		}
2712 		rtm = (struct rt_msghdr *)buf;
2713 	} while (rtm->rtm_version != RTM_VERSION ||
2714 	    rtm->rtm_seq != seq || rtm->rtm_pid != pid);
2715 	sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)];
2716 	if (rtm->rtm_addrs & RTA_DST) {
2717 		sin6 = (struct sockaddr_in6 *)
2718 			((char *)sin6 + ROUNDUP(sin6->sin6_len));
2719 	}
2720 	if (rtm->rtm_addrs & RTA_GATEWAY) {
2721 		*gw = sin6->sin6_addr;
2722 		return gw;
2723 	}
2724 	return NULL;
2725 }
2726 
2727 const char *
2728 inet6_n2p(const struct in6_addr *p)
2729 {
2730 	static char buf[BUFSIZ];
2731 
2732 	return inet_ntop(AF_INET6, (const void *)p, buf, sizeof(buf));
2733 }
2734 
2735 void
2736 ifrtdump(int sig)
2737 {
2738 
2739 	ifdump(sig);
2740 	rtdump(sig);
2741 }
2742 
2743 void
2744 ifdump(int sig)
2745 {
2746 	struct ifc *ifcp;
2747 	int i;
2748 
2749 	log_info("%s: Interface Table Dump", hms());
2750 	log_info("  Number of interfaces: %d", nifc);
2751 	for (i = 0; i < 2; i++) {
2752 		log_info("  %sadvertising interfaces:", i ? "non-" : "");
2753 		for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) {
2754 			if (i == 0) {
2755 				if ((ifcp->ifc_flags & IFF_UP) == 0)
2756 					continue;
2757 				if (iff_find(ifcp, 'N') != NULL)
2758 					continue;
2759 			} else {
2760 				if (ifcp->ifc_flags & IFF_UP)
2761 					continue;
2762 			}
2763 			ifdump0(ifcp);
2764 		}
2765 	}
2766 	log_info("");
2767 }
2768 
2769 void
2770 ifdump0(const struct ifc *ifcp)
2771 {
2772 	struct ifac *ifa;
2773 	struct iff *iffp;
2774 	char buf[BUFSIZ];
2775 	const char *ft;
2776 	int addr;
2777 
2778 	log_info("    %s: index(%d) flags(%s) addr(%s) mtu(%d) metric(%d)",
2779 		ifcp->ifc_name, ifcp->ifc_index, ifflags(ifcp->ifc_flags),
2780 		inet6_n2p(&ifcp->ifc_mylladdr),
2781 		ifcp->ifc_mtu, ifcp->ifc_metric);
2782 	for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
2783 		if (ifcp->ifc_flags & IFF_POINTOPOINT) {
2784 			inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr,
2785 				buf, sizeof(buf));
2786 			log_info("\t%s/%d -- %s",
2787 				inet6_n2p(&ifa->ifa_addr),
2788 				ifa->ifa_plen, buf);
2789 		} else {
2790 			log_info("\t%s/%d",
2791 				inet6_n2p(&ifa->ifa_addr),
2792 				ifa->ifa_plen);
2793 		}
2794 	}
2795 	if (ifcp->ifc_filter) {
2796 		log_enqueue("\tFilter:");
2797 		for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
2798 			addr = 0;
2799 			switch (iffp->iff_type) {
2800 			case 'A':
2801 				ft = "Aggregate"; addr++; break;
2802 			case 'N':
2803 				ft = "No-use"; break;
2804 			case 'O':
2805 				ft = "Advertise-only"; addr++; break;
2806 			case 'T':
2807 				ft = "Default-only"; break;
2808 			case 'L':
2809 				ft = "Listen-only"; addr++; break;
2810 			default:
2811 				snprintf(buf, sizeof(buf), "Unknown-%c", iffp->iff_type);
2812 				ft = buf;
2813 				addr++;
2814 				break;
2815 			}
2816 			log_enqueue(" %s", ft);
2817 			if (addr) {
2818 				log_enqueue("(%s/%d)",
2819 				    inet6_n2p(&iffp->iff_addr), iffp->iff_plen);
2820 			}
2821 		}
2822 		log_info("");
2823 	}
2824 }
2825 
2826 void
2827 rtdump(int sig)
2828 {
2829 	struct	riprt *rrt;
2830 	char	buf[BUFSIZ];
2831 	time_t	t, age;
2832 
2833 	t = time(NULL);
2834 	log_info("%s: Routing Table Dump", hms());
2835 	for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
2836 		if (rrt->rrt_t == 0)
2837 			age = 0;
2838 		else
2839 			age = t - rrt->rrt_t;
2840 		inet_ntop(AF_INET6, (void *)&rrt->rrt_info.rip6_dest,
2841 			buf, sizeof(buf));
2842 		log_enqueue("    %s/%d if(%d:%s) gw(%s) [%d] age(%lld)",
2843 			buf, rrt->rrt_info.rip6_plen, rrt->rrt_index,
2844 			index2ifc[rrt->rrt_index]->ifc_name,
2845 			inet6_n2p(&rrt->rrt_gw),
2846 			rrt->rrt_info.rip6_metric, (long long)age);
2847 		if (rrt->rrt_info.rip6_tag) {
2848 			log_enqueue(" tag(0x%04x)",
2849 				ntohs(rrt->rrt_info.rip6_tag) & 0xffff);
2850 		}
2851 		if (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR)
2852 			log_enqueue(" NOT-LL");
2853 		if (rrt->rrt_rflags & RRTF_NOADVERTISE)
2854 			log_enqueue(" NO-ADV");
2855 		log_info("");
2856 	}
2857 }
2858 
2859 /*
2860  * Parse the -A (and -O) options and put corresponding filter object to the
2861  * specified interface structures.  Each of the -A/O option has the following
2862  * syntax:	-A 5f09:c400::/32,ef0,ef1  (aggregate)
2863  * 		-O 5f09:c400::/32,ef0,ef1  (only when match)
2864  */
2865 void
2866 filterconfig(void)
2867 {
2868 	int i;
2869 	char *p, *ap, *iflp, *ifname, *ep;
2870 	struct iff ftmp, *iff_obj;
2871 	struct ifc *ifcp;
2872 	struct riprt *rrt;
2873 #if 0
2874 	struct in6_addr gw;
2875 #endif
2876 	u_long plen;
2877 
2878 	for (i = 0; i < nfilter; i++) {
2879 		ap = filter[i];
2880 		iflp = NULL;
2881 		ifcp = NULL;
2882 		if (filtertype[i] == 'N' || filtertype[i] == 'T') {
2883 			iflp = ap;
2884 			goto ifonly;
2885 		}
2886 		if ((p = strchr(ap, ',')) != NULL) {
2887 			*p++ = '\0';
2888 			iflp = p;
2889 		}
2890 		if ((p = strchr(ap, '/')) == NULL) {
2891 			log_warnx("no prefixlen specified for '%s'", ap);
2892 			fatalx("exiting");
2893 			/*NOTREACHED*/
2894 		}
2895 		*p++ = '\0';
2896 		if (inet_pton(AF_INET6, ap, &ftmp.iff_addr) != 1) {
2897 			log_warnx("invalid prefix specified for '%s'", ap);
2898 			fatalx("exiting");
2899 			/*NOTREACHED*/
2900 		}
2901 		errno = 0;
2902 		ep = NULL;
2903 		plen = strtoul(p, &ep, 10);
2904 		if (errno || !*p || *ep || plen > sizeof(ftmp.iff_addr) * 8) {
2905 			log_warnx("invalid prefix length specified for '%s'", ap);
2906 			fatalx("exiting");
2907 			/*NOTREACHED*/
2908 		}
2909 		ftmp.iff_plen = plen;
2910 		ftmp.iff_next = NULL;
2911 		applyplen(&ftmp.iff_addr, ftmp.iff_plen);
2912 ifonly:
2913 		ftmp.iff_type = filtertype[i];
2914 		if (iflp == NULL || *iflp == '\0') {
2915 			log_warnx("no interface specified for '%s'", ap);
2916 			fatal("exiting");
2917 			/*NOTREACHED*/
2918 		}
2919 		/* parse the interface listing portion */
2920 		while (iflp) {
2921 			ifname = iflp;
2922 			if ((iflp = strchr(iflp, ',')) != NULL)
2923 				*iflp++ = '\0';
2924 			ifcp = ifc_find(ifname);
2925 			if (ifcp == NULL) {
2926 				log_warnx("no interface %s exists", ifname);
2927 				fatalx("exiting");
2928 				/*NOTREACHED*/
2929 			}
2930 			iff_obj = malloc(sizeof(struct iff));
2931 			if (iff_obj == NULL) {
2932 				fatal("malloc of iff_obj");
2933 				/*NOTREACHED*/
2934 			}
2935 			memcpy((void *)iff_obj, (void *)&ftmp,
2936 			    sizeof(struct iff));
2937 			/* link it to the interface filter */
2938 			iff_obj->iff_next = ifcp->ifc_filter;
2939 			ifcp->ifc_filter = iff_obj;
2940 		}
2941 
2942 		/*
2943 		 * -A: aggregate configuration.
2944 		 */
2945 		if (filtertype[i] != 'A')
2946 			continue;
2947 		/* put the aggregate to the kernel routing table */
2948 		rrt = calloc(1, sizeof(struct riprt));
2949 		if (rrt == NULL) {
2950 			fatal("calloc: rrt");
2951 			/*NOTREACHED*/
2952 		}
2953 		rrt->rrt_info.rip6_dest = ftmp.iff_addr;
2954 		rrt->rrt_info.rip6_plen = ftmp.iff_plen;
2955 		rrt->rrt_info.rip6_metric = 1;
2956 		rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
2957 		rrt->rrt_gw = in6addr_loopback;
2958 		rrt->rrt_flags = RTF_UP | RTF_REJECT;
2959 		rrt->rrt_rflags = RRTF_AGGREGATE;
2960 		rrt->rrt_t = 0;
2961 		rrt->rrt_index = loopifcp->ifc_index;
2962 #if 0
2963 		if (getroute(&rrt->rrt_info, &gw)) {
2964 #if 0
2965 			/*
2966 			 * When the address has already been registered in the
2967 			 * kernel routing table, it should be removed
2968 			 */
2969 			delroute(&rrt->rrt_info, &gw);
2970 #else
2971 			/* it is safer behavior */
2972 			errno = EINVAL;
2973 			fatal("%s/%u already in routing table, "
2974 			    "cannot aggregate",
2975 			    inet6_n2p(&rrt->rrt_info.rip6_dest),
2976 			    rrt->rrt_info.rip6_plen);
2977 			/*NOTREACHED*/
2978 #endif
2979 		}
2980 #endif
2981 		/* Put the route to the list */
2982 		rrt->rrt_next = riprt;
2983 		riprt = rrt;
2984 		log_debug("Aggregate: %s/%d for %s",
2985 			inet6_n2p(&ftmp.iff_addr), ftmp.iff_plen,
2986 			ifcp->ifc_name);
2987 		/* Add this route to the kernel */
2988 		if (nflag) 	/* do not modify kernel routing table */
2989 			continue;
2990 		addroute(rrt, &in6addr_loopback, loopifcp);
2991 	}
2992 }
2993 
2994 /***************** utility functions *****************/
2995 
2996 /*
2997  * Returns a pointer to ifac whose address and prefix length matches
2998  * with the address and prefix length specified in the arguments.
2999  */
3000 struct ifac *
3001 ifa_match(const struct ifc *ifcp, const struct in6_addr *ia, int plen)
3002 {
3003 	struct ifac *ifa;
3004 
3005 	for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) {
3006 		if (IN6_ARE_ADDR_EQUAL(&ifa->ifa_addr, ia) &&
3007 		    ifa->ifa_plen == plen)
3008 			break;
3009 	}
3010 	return ifa;
3011 }
3012 
3013 /*
3014  * Return a pointer to riprt structure whose address and prefix length
3015  * matches with the address and prefix length found in the argument.
3016  * Note: This is not a rtalloc().  Therefore exact match is necessary.
3017  */
3018 struct riprt *
3019 rtsearch(struct	netinfo6 *np, struct riprt **prev_rrt)
3020 {
3021 	struct	riprt	*rrt;
3022 
3023 	if (prev_rrt)
3024 		*prev_rrt = NULL;
3025 	for (rrt = riprt; rrt; rrt = rrt->rrt_next) {
3026 		if (rrt->rrt_info.rip6_plen == np->rip6_plen &&
3027 		    IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest,
3028 				       &np->rip6_dest))
3029 			return rrt;
3030 		if (prev_rrt)
3031 			*prev_rrt = rrt;
3032 	}
3033 	if (prev_rrt)
3034 		*prev_rrt = NULL;
3035 	return 0;
3036 }
3037 
3038 int
3039 sin6mask2len(const struct sockaddr_in6 *sin6)
3040 {
3041 
3042 	return mask2len(&sin6->sin6_addr,
3043 	    sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr));
3044 }
3045 
3046 int
3047 mask2len(const struct in6_addr *addr, int lenlim)
3048 {
3049 	int i = 0, j;
3050 	const u_char *p = (const u_char *)addr;
3051 
3052 	for (j = 0; j < lenlim; j++, p++) {
3053 		if (*p != 0xff)
3054 			break;
3055 		i += 8;
3056 	}
3057 	if (j < lenlim) {
3058 		switch (*p) {
3059 #define	MASKLEN(m, l)	case m: do { i += l; break; } while (0)
3060 		MASKLEN(0xfe, 7); break;
3061 		MASKLEN(0xfc, 6); break;
3062 		MASKLEN(0xf8, 5); break;
3063 		MASKLEN(0xf0, 4); break;
3064 		MASKLEN(0xe0, 3); break;
3065 		MASKLEN(0xc0, 2); break;
3066 		MASKLEN(0x80, 1); break;
3067 #undef	MASKLEN
3068 		}
3069 	}
3070 	return i;
3071 }
3072 
3073 void
3074 applyplen(struct in6_addr *ia, int plen)
3075 {
3076 	static const u_char plent[8] = {
3077 		0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe
3078 	};
3079 	u_char	*p;
3080 	int	i;
3081 
3082 	p = ia->s6_addr;
3083 	for (i = 0; i < 16; i++) {
3084 		if (plen <= 0)
3085 			*p = 0;
3086 		else if (plen < 8)
3087 			*p &= plent[plen];
3088 		p++, plen -= 8;
3089 	}
3090 }
3091 
3092 struct in6_addr *
3093 plen2mask(int n)
3094 {
3095 	static const int pl2m[9] = {
3096 		0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
3097 	};
3098 	static struct in6_addr ia;
3099 	u_char	*p;
3100 	int	i;
3101 
3102 	memset(&ia, 0, sizeof(struct in6_addr));
3103 	p = (u_char *)&ia;
3104 	for (i = 0; i < 16; i++, p++, n -= 8) {
3105 		if (n >= 8) {
3106 			*p = 0xff;
3107 			continue;
3108 		}
3109 		*p = pl2m[n];
3110 		break;
3111 	}
3112 	return &ia;
3113 }
3114 
3115 char *
3116 xstrdup(const char *p)
3117 {
3118 	char *q;
3119 
3120 	q = strdup(p);
3121 	if (q == NULL) {
3122 		fatal("strdup");
3123 		/*NOTREACHED*/
3124 	}
3125 	return q;
3126 }
3127 
3128 const char *
3129 hms(void)
3130 {
3131 	static char buf[BUFSIZ];
3132 	time_t t;
3133 	struct	tm *tm;
3134 
3135 	t = time(NULL);
3136 	if ((tm = localtime(&t)) == 0) {
3137 		fatal("localtime");
3138 		/*NOTREACHED*/
3139 	}
3140 	snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
3141 	    tm->tm_sec);
3142 	return buf;
3143 }
3144 
3145 #define	RIPRANDDEV	1.0	/* 30 +- 15, max - min = 30 */
3146 
3147 int
3148 ripinterval(int timer)
3149 {
3150 	double r = arc4random();
3151 	int interval;
3152 
3153 	interval = (int)(timer + timer * RIPRANDDEV * (r / UINT32_MAX - 0.5));
3154 	nextalarm = time(NULL) + interval;
3155 	return interval;
3156 }
3157 
3158 time_t
3159 ripsuptrig(void)
3160 {
3161 	time_t t;
3162 
3163 	double r = arc4random();
3164 	t  = (int)(RIP_TRIG_INT6_MIN +
3165 		(RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / UINT32_MAX));
3166 	sup_trig_update = time(NULL) + t;
3167 	return t;
3168 }
3169 
3170 unsigned int
3171 if_maxindex(void)
3172 {
3173 	struct if_nameindex *p, *p0;
3174 	unsigned int max = 0;
3175 
3176 	p0 = if_nameindex();
3177 	for (p = p0; p && p->if_index && p->if_name; p++) {
3178 		if (max < p->if_index)
3179 			max = p->if_index;
3180 	}
3181 	if_freenameindex(p0);
3182 	return max;
3183 }
3184 
3185 struct ifc *
3186 ifc_find(char *name)
3187 {
3188 	struct ifc *ifcp;
3189 
3190 	for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) {
3191 		if (strcmp(name, ifcp->ifc_name) == 0)
3192 			return ifcp;
3193 	}
3194 	return (struct ifc *)NULL;
3195 }
3196 
3197 struct iff *
3198 iff_find(struct ifc *ifcp, int type)
3199 {
3200 	struct iff *iffp;
3201 
3202 	for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) {
3203 		if (iffp->iff_type == type)
3204 			return iffp;
3205 	}
3206 	return NULL;
3207 }
3208 
3209 void
3210 setindex2ifc(int idx, struct ifc *ifcp)
3211 {
3212 	int n;
3213 	struct ifc **p;
3214 
3215 	if (!index2ifc) {
3216 		nindex2ifc = 5;	/*initial guess*/
3217 		index2ifc = calloc(nindex2ifc, sizeof(*index2ifc));
3218 		if (index2ifc == NULL) {
3219 			fatal("calloc");
3220 			/*NOTREACHED*/
3221 		}
3222 	}
3223 	n = nindex2ifc;
3224 	while (nindex2ifc <= idx)
3225 		nindex2ifc *= 2;
3226 	if (n != nindex2ifc) {
3227 		p = reallocarray(index2ifc, nindex2ifc, sizeof(*index2ifc));
3228 		if (p == NULL) {
3229 			fatal("reallocarray");
3230 			/*NOTREACHED*/
3231 		}
3232 		memset(p + n, 0, (nindex2ifc - n) * sizeof(*index2ifc));
3233 		index2ifc = p;
3234 	}
3235 	index2ifc[idx] = ifcp;
3236 }
3237