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