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