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