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