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