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