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