1 /* $NetBSD: route6d.c,v 1.31 2002/01/11 04:20:56 itojun Exp $ */ 2 /* $KAME: route6d.c,v 1.73 2001/09/05 01:12:34 itojun Exp $ */ 3 4 /* 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 #ifndef lint 35 __RCSID("$NetBSD: route6d.c,v 1.31 2002/01/11 04:20:56 itojun Exp $"); 36 #endif 37 38 #include <stdio.h> 39 40 #include <time.h> 41 #include <unistd.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <signal.h> 45 #ifdef __STDC__ 46 #include <stdarg.h> 47 #else 48 #include <varargs.h> 49 #endif 50 #include <syslog.h> 51 #include <stddef.h> 52 #include <errno.h> 53 #include <err.h> 54 55 #include <sys/types.h> 56 #include <sys/param.h> 57 #include <sys/file.h> 58 #include <sys/socket.h> 59 #include <sys/ioctl.h> 60 #include <sys/sysctl.h> 61 #include <sys/uio.h> 62 #include <net/if.h> 63 #if defined(__FreeBSD__) && __FreeBSD__ >= 3 64 #include <net/if_var.h> 65 #endif /* __FreeBSD__ >= 3 */ 66 #define KERNEL 1 67 #define _KERNEL 1 68 #include <net/route.h> 69 #undef KERNEL 70 #undef _KERNEL 71 #include <netinet/in.h> 72 #include <netinet/in_var.h> 73 #include <netinet/ip6.h> 74 #include <netinet/udp.h> 75 #include <netdb.h> 76 #include <ifaddrs.h> 77 78 #include <arpa/inet.h> 79 80 #include "route6d.h" 81 82 #define MAXFILTER 40 83 84 #ifdef DEBUG 85 #define INIT_INTERVAL6 6 86 #else 87 #define INIT_INTERVAL6 10 /* Wait to submit a initial riprequest */ 88 #endif 89 90 /* alignment constraint for routing socket */ 91 #define ROUNDUP(a) \ 92 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 93 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 94 95 /* 96 * Following two macros are highly depending on KAME Release 97 */ 98 #define IN6_LINKLOCAL_IFINDEX(addr) \ 99 ((addr).s6_addr[2] << 8 | (addr).s6_addr[3]) 100 101 #define SET_IN6_LINKLOCAL_IFINDEX(addr, index) \ 102 do { \ 103 (addr).s6_addr[2] = ((index) >> 8) & 0xff; \ 104 (addr).s6_addr[3] = (index) & 0xff; \ 105 } while (0) 106 107 struct ifc { /* Configuration of an interface */ 108 char *ifc_name; /* if name */ 109 struct ifc *ifc_next; 110 int ifc_index; /* if index */ 111 int ifc_mtu; /* if mtu */ 112 int ifc_metric; /* if metric */ 113 u_int ifc_flags; /* flags */ 114 short ifc_cflags; /* IFC_XXX */ 115 struct in6_addr ifc_mylladdr; /* my link-local address */ 116 struct sockaddr_in6 ifc_ripsin; /* rip multicast address */ 117 struct iff *ifc_filter; /* filter structure */ 118 struct ifac *ifc_addr; /* list of AF_INET6 addresses */ 119 int ifc_joined; /* joined to ff02::9 */ 120 }; 121 122 struct ifac { /* Adddress associated to an interface */ 123 struct ifc *ifa_conf; /* back pointer */ 124 struct ifac *ifa_next; 125 struct in6_addr ifa_addr; /* address */ 126 struct in6_addr ifa_raddr; /* remote address, valid in p2p */ 127 int ifa_plen; /* prefix length */ 128 }; 129 130 struct iff { 131 int iff_type; 132 struct in6_addr iff_addr; 133 int iff_plen; 134 struct iff *iff_next; 135 }; 136 137 struct ifc *ifc; 138 int nifc; /* number of valid ifc's */ 139 struct ifc **index2ifc; 140 int nindex2ifc; 141 struct ifc *loopifcp = NULL; /* pointing to loopback */ 142 int loopifindex = 0; /* ditto */ 143 fd_set sockvec; /* vector to select() for receiving */ 144 int rtsock; /* the routing socket */ 145 int ripsock; /* socket to send/receive RIP datagram */ 146 int maxfd; /* maximum fd for select() */ 147 148 struct rip6 *ripbuf; /* packet buffer for sending */ 149 150 /* 151 * Maintain the routes in a linked list. When the number of the routes 152 * grows, somebody would like to introduce a hash based or a radix tree 153 * based structure. I believe the number of routes handled by RIP is 154 * limited and I don't have to manage a complex data structure, however. 155 * 156 * One of the major drawbacks of the linear linked list is the difficulty 157 * of representing the relationship between a couple of routes. This may 158 * be a significant problem when we have to support route aggregation with 159 * supressing the specifices covered by the aggregate. 160 */ 161 162 struct riprt { 163 struct riprt *rrt_next; /* next destination */ 164 struct riprt *rrt_same; /* same destination - future use */ 165 struct netinfo6 rrt_info; /* network info */ 166 struct in6_addr rrt_gw; /* gateway */ 167 u_long rrt_flags; /* kernel routing table flags */ 168 u_long rrt_rflags; /* route6d routing table flags */ 169 time_t rrt_t; /* when the route validated */ 170 int rrt_index; /* ifindex from which this route got */ 171 }; 172 173 struct riprt *riprt = 0; 174 175 int dflag = 0; /* debug flag */ 176 int qflag = 0; /* quiet flag */ 177 int nflag = 0; /* don't update kernel routing table */ 178 int aflag = 0; /* age out even the statically defined routes */ 179 int hflag = 0; /* don't split horizon */ 180 int lflag = 0; /* exchange site local routes */ 181 int sflag = 0; /* announce static routes w/ split horizon */ 182 int Sflag = 0; /* announce static routes to every interface */ 183 unsigned long routetag = 0; /* route tag attached on originating case */ 184 185 char *filter[MAXFILTER]; 186 int filtertype[MAXFILTER]; 187 int nfilter = 0; 188 189 pid_t pid; 190 191 struct sockaddr_storage ripsin; 192 193 struct rtentry rtentry; 194 195 int interval = 1; 196 time_t nextalarm = 0; 197 time_t sup_trig_update = 0; 198 199 FILE *rtlog = NULL; 200 201 int logopened = 0; 202 203 static u_long seq = 0; 204 205 volatile int signo; 206 volatile sig_atomic_t seenalrm; 207 volatile sig_atomic_t seenquit; 208 volatile sig_atomic_t seenusr1; 209 210 #define RRTF_AGGREGATE 0x08000000 211 #define RRTF_NOADVERTISE 0x10000000 212 #define RRTF_NH_NOT_LLADDR 0x20000000 213 #define RRTF_SENDANYWAY 0x40000000 214 #define RRTF_CHANGED 0x80000000 215 216 int main __P((int, char **)); 217 void sighandler __P((int)); 218 void ripalarm __P((void)); 219 void riprecv __P((void)); 220 void ripsend __P((struct ifc *, struct sockaddr_in6 *, int)); 221 int out_filter __P((struct riprt *, struct ifc *)); 222 void init __P((void)); 223 void sockopt __P((struct ifc *)); 224 void ifconfig __P((void)); 225 void ifconfig1 __P((const char *, const struct sockaddr *, struct ifc *, int)); 226 void rtrecv __P((void)); 227 int rt_del __P((const struct sockaddr_in6 *, const struct sockaddr_in6 *, 228 const struct sockaddr_in6 *)); 229 int rt_deladdr __P((struct ifc *, const struct sockaddr_in6 *, 230 const struct sockaddr_in6 *)); 231 void filterconfig __P((void)); 232 int getifmtu __P((int)); 233 const char *rttypes __P((struct rt_msghdr *)); 234 const char *rtflags __P((struct rt_msghdr *)); 235 const char *ifflags __P((int)); 236 int ifrt __P((struct ifc *, int)); 237 void ifrt_p2p __P((struct ifc *, int)); 238 void applymask __P((struct in6_addr *, struct in6_addr *)); 239 void applyplen __P((struct in6_addr *, int)); 240 void ifrtdump __P((int)); 241 void ifdump __P((int)); 242 void ifdump0 __P((FILE *, const struct ifc *)); 243 void rtdump __P((int)); 244 void rt_entry __P((struct rt_msghdr *, int)); 245 void rtdexit __P((void)); 246 void riprequest __P((struct ifc *, struct netinfo6 *, int, 247 struct sockaddr_in6 *)); 248 void ripflush __P((struct ifc *, struct sockaddr_in6 *)); 249 void sendrequest __P((struct ifc *)); 250 int sin6mask2len __P((const struct sockaddr_in6 *)); 251 int mask2len __P((const struct in6_addr *, int)); 252 int sendpacket __P((struct sockaddr_in6 *, int)); 253 int addroute __P((struct riprt *, const struct in6_addr *, struct ifc *)); 254 int delroute __P((struct netinfo6 *, struct in6_addr *)); 255 struct in6_addr *getroute __P((struct netinfo6 *, struct in6_addr *)); 256 void krtread __P((int)); 257 int tobeadv __P((struct riprt *, struct ifc *)); 258 char *allocopy __P((char *)); 259 char *hms __P((void)); 260 const char *inet6_n2p __P((const struct in6_addr *)); 261 struct ifac *ifa_match __P((const struct ifc *, const struct in6_addr *, int)); 262 struct in6_addr *plen2mask __P((int)); 263 struct riprt *rtsearch __P((struct netinfo6 *, struct riprt **)); 264 int ripinterval __P((int)); 265 time_t ripsuptrig __P((void)); 266 void fatal __P((const char *, ...)) 267 __attribute__((__format__(__printf__, 1, 2))); 268 void trace __P((int, const char *, ...)) 269 __attribute__((__format__(__printf__, 2, 3))); 270 void tracet __P((int, const char *, ...)) 271 __attribute__((__format__(__printf__, 2, 3))); 272 unsigned int if_maxindex __P((void)); 273 struct ifc *ifc_find __P((char *)); 274 struct iff *iff_find __P((struct ifc *, int)); 275 void setindex2ifc __P((int, struct ifc *)); 276 277 #define MALLOC(type) ((type *)malloc(sizeof(type))) 278 279 int 280 main(argc, argv) 281 int argc; 282 char **argv; 283 { 284 int ch; 285 int error = 0; 286 struct ifc *ifcp; 287 sigset_t mask, omask; 288 FILE *pidfile; 289 char *progname; 290 char *ep; 291 292 progname = strrchr(*argv, '/'); 293 if (progname) 294 progname++; 295 else 296 progname = *argv; 297 298 pid = getpid(); 299 while ((ch = getopt(argc, argv, "A:N:O:R:T:L:t:adDhlnqsS")) != -1) { 300 switch (ch) { 301 case 'A': 302 case 'N': 303 case 'O': 304 case 'T': 305 case 'L': 306 if (nfilter >= MAXFILTER) { 307 fatal("Exceeds MAXFILTER"); 308 /*NOTREACHED*/ 309 } 310 filtertype[nfilter] = ch; 311 filter[nfilter++] = allocopy(optarg); 312 break; 313 case 't': 314 ep = NULL; 315 routetag = strtoul(optarg, &ep, 0); 316 if (!ep || *ep != '\0' || (routetag & ~0xffff) != 0) { 317 fatal("invalid route tag"); 318 /*NOTREACHED*/ 319 } 320 break; 321 case 'R': 322 if ((rtlog = fopen(optarg, "w")) == NULL) { 323 fatal("Can not write to routelog"); 324 /*NOTREACHED*/ 325 } 326 break; 327 #define FLAG(c, flag, n) case c: do { flag = n; break; } while(0) 328 FLAG('a', aflag, 1); break; 329 FLAG('d', dflag, 1); break; 330 FLAG('D', dflag, 2); break; 331 FLAG('h', hflag, 1); break; 332 FLAG('l', lflag, 1); break; 333 FLAG('n', nflag, 1); break; 334 FLAG('q', qflag, 1); break; 335 FLAG('s', sflag, 1); break; 336 FLAG('S', Sflag, 1); break; 337 #undef FLAG 338 default: 339 fatal("Invalid option specified, terminating"); 340 /*NOTREACHED*/ 341 } 342 } 343 argc -= optind; 344 argv += optind; 345 if (argc > 0) { 346 fatal("bogus extra arguments"); 347 /*NOTREACHED*/ 348 } 349 350 if (geteuid()) { 351 nflag = 1; 352 fprintf(stderr, "No kernel update is allowed\n"); 353 } 354 355 if (dflag == 0) { 356 if (daemon(0, 0) < 0) { 357 fatal("daemon"); 358 /*NOTREACHED*/ 359 } 360 } 361 362 openlog(progname, LOG_NDELAY|LOG_PID, LOG_DAEMON); 363 logopened++; 364 365 if ((ripbuf = (struct rip6 *)malloc(RIP6_MAXMTU)) == NULL) 366 fatal("malloc"); 367 memset(ripbuf, 0, RIP6_MAXMTU); 368 ripbuf->rip6_cmd = RIP6_RESPONSE; 369 ripbuf->rip6_vers = RIP6_VERSION; 370 ripbuf->rip6_res1[0] = 0; 371 ripbuf->rip6_res1[1] = 0; 372 373 init(); 374 ifconfig(); 375 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 376 if (ifcp->ifc_index < 0) { 377 fprintf(stderr, 378 "No ifindex found at %s (no link-local address?)\n", 379 ifcp->ifc_name); 380 error++; 381 } 382 } 383 if (error) 384 exit(1); 385 if (loopifcp == NULL) { 386 fatal("No loopback found"); 387 /*NOTREACHED*/ 388 } 389 loopifindex = loopifcp->ifc_index; 390 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) 391 ifrt(ifcp, 0); 392 filterconfig(); 393 krtread(0); 394 if (dflag) 395 ifrtdump(0); 396 397 pid = getpid(); 398 if ((pidfile = fopen(ROUTE6D_PID, "w")) != NULL) { 399 fprintf(pidfile, "%d\n", pid); 400 fclose(pidfile); 401 } 402 403 if ((ripbuf = (struct rip6 *)malloc(RIP6_MAXMTU)) == NULL) { 404 fatal("malloc"); 405 /*NOTREACHED*/ 406 } 407 memset(ripbuf, 0, RIP6_MAXMTU); 408 ripbuf->rip6_cmd = RIP6_RESPONSE; 409 ripbuf->rip6_vers = RIP6_VERSION; 410 ripbuf->rip6_res1[0] = 0; 411 ripbuf->rip6_res1[1] = 0; 412 413 if (signal(SIGALRM, sighandler) == SIG_ERR || 414 signal(SIGQUIT, sighandler) == SIG_ERR || 415 signal(SIGTERM, sighandler) == SIG_ERR || 416 signal(SIGUSR1, sighandler) == SIG_ERR || 417 signal(SIGHUP, sighandler) == SIG_ERR || 418 signal(SIGINT, sighandler) == SIG_ERR) { 419 fatal("signal"); 420 /*NOTREACHED*/ 421 } 422 /* 423 * To avoid rip packet congestion (not on a cable but in this 424 * process), wait for a moment to send the first RIP6_RESPONSE 425 * packets. 426 */ 427 alarm(ripinterval(INIT_INTERVAL6)); 428 429 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 430 if (iff_find(ifcp, 'N')) 431 continue; 432 if (ifcp->ifc_index > 0 && (ifcp->ifc_flags & IFF_UP)) 433 sendrequest(ifcp); 434 } 435 436 syslog(LOG_INFO, "**** Started ****"); 437 sigemptyset(&mask); 438 sigaddset(&mask, SIGALRM); 439 while (1) { 440 fd_set recvec; 441 442 if (seenalrm) { 443 ripalarm(); 444 seenalrm = 0; 445 continue; 446 } 447 if (seenquit) { 448 rtdexit(); 449 seenquit = 0; 450 continue; 451 } 452 if (seenusr1) { 453 ifrtdump(SIGUSR1); 454 seenusr1 = 0; 455 continue; 456 } 457 458 FD_COPY(&sockvec, &recvec); 459 signo = 0; 460 switch (select(maxfd + 1, &recvec, 0, 0, 0)) { 461 case -1: 462 if (errno != EINTR) { 463 fatal("select"); 464 /*NOTREACHED*/ 465 } 466 continue; 467 case 0: 468 continue; 469 default: 470 if (FD_ISSET(ripsock, &recvec)) { 471 sigprocmask(SIG_BLOCK, &mask, &omask); 472 riprecv(); 473 sigprocmask(SIG_SETMASK, &omask, NULL); 474 } 475 if (FD_ISSET(rtsock, &recvec)) { 476 sigprocmask(SIG_BLOCK, &mask, &omask); 477 rtrecv(); 478 sigprocmask(SIG_SETMASK, &omask, NULL); 479 } 480 } 481 } 482 } 483 484 void 485 sighandler(sig) 486 int sig; 487 { 488 489 signo = sig; 490 switch (signo) { 491 case SIGALRM: 492 seenalrm++; 493 break; 494 case SIGQUIT: 495 case SIGTERM: 496 seenquit++; 497 break; 498 case SIGUSR1: 499 case SIGHUP: 500 case SIGINT: 501 seenusr1++; 502 break; 503 } 504 } 505 506 /* 507 * gracefully exits after resetting sockopts. 508 */ 509 /* ARGSUSED */ 510 void 511 rtdexit() 512 { 513 struct riprt *rrt; 514 515 alarm(0); 516 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 517 if (rrt->rrt_rflags & RRTF_AGGREGATE) { 518 delroute(&rrt->rrt_info, &rrt->rrt_gw); 519 } 520 } 521 close(ripsock); 522 close(rtsock); 523 syslog(LOG_INFO, "**** Terminated ****"); 524 closelog(); 525 exit(1); 526 } 527 528 /* 529 * Called periodically: 530 * 1. age out the learned route. remove it if necessary. 531 * 2. submit RIP6_RESPONSE packets. 532 * Invoked in every SUPPLY_INTERVAL6 (30) seconds. I believe we don't have 533 * to invoke this function in every 1 or 5 or 10 seconds only to age the 534 * routes more precisely. 535 */ 536 /* ARGSUSED */ 537 void 538 ripalarm() 539 { 540 struct ifc *ifcp; 541 struct riprt *rrt, *rrt_prev, *rrt_next; 542 time_t t_lifetime, t_holddown; 543 544 /* age the RIP routes */ 545 rrt_prev = 0; 546 t_lifetime = time(NULL) - RIP_LIFETIME; 547 t_holddown = t_lifetime - RIP_HOLDDOWN; 548 for (rrt = riprt; rrt; rrt = rrt_next) { 549 rrt_next = rrt->rrt_next; 550 551 if (rrt->rrt_t == 0) { 552 rrt_prev = rrt; 553 continue; 554 } 555 if (rrt->rrt_t < t_holddown) { 556 if (rrt_prev) { 557 rrt_prev->rrt_next = rrt->rrt_next; 558 } else { 559 riprt = rrt->rrt_next; 560 } 561 delroute(&rrt->rrt_info, &rrt->rrt_gw); 562 free(rrt); 563 continue; 564 } 565 if (rrt->rrt_t < t_lifetime) 566 rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 567 rrt_prev = rrt; 568 } 569 /* Supply updates */ 570 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 571 if (ifcp->ifc_index > 0 && (ifcp->ifc_flags & IFF_UP)) 572 ripsend(ifcp, &ifcp->ifc_ripsin, 0); 573 } 574 alarm(ripinterval(SUPPLY_INTERVAL6)); 575 } 576 577 void 578 init() 579 { 580 int i, int0, int255, error; 581 struct addrinfo hints, *res; 582 char port[10]; 583 584 ifc = (struct ifc *)NULL; 585 nifc = 0; 586 nindex2ifc = 0; /*initial guess*/ 587 index2ifc = NULL; 588 snprintf(port, sizeof(port), "%d", RIP6_PORT); 589 590 memset(&hints, 0, sizeof(hints)); 591 hints.ai_family = PF_INET6; 592 hints.ai_socktype = SOCK_DGRAM; 593 hints.ai_flags = AI_PASSIVE; 594 error = getaddrinfo(NULL, port, &hints, &res); 595 if (error) { 596 fatal("%s", gai_strerror(error)); 597 /*NOTREACHED*/ 598 } 599 if (res->ai_next) { 600 fatal(":: resolved to multiple address"); 601 /*NOTREACHED*/ 602 } 603 604 int0 = 0; int255 = 255; 605 ripsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 606 if (ripsock < 0) { 607 fatal("rip socket"); 608 /*NOTREACHED*/ 609 } 610 if (bind(ripsock, res->ai_addr, res->ai_addrlen) < 0) { 611 fatal("rip bind"); 612 /*NOTREACHED*/ 613 } 614 if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, 615 &int255, sizeof(int255)) < 0) { 616 fatal("rip IPV6_MULTICAST_HOPS"); 617 /*NOTREACHED*/ 618 } 619 if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, 620 &int0, sizeof(int0)) < 0) { 621 fatal("rip IPV6_MULTICAST_LOOP"); 622 /*NOTREACHED*/ 623 } 624 625 i = 1; 626 #ifdef IPV6_RECVPKTINFO 627 if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &i, 628 sizeof(i)) < 0) { 629 fatal("rip IPV6_RECVPKTINFO"); 630 /*NOTREACHED*/ 631 } 632 #else /* old adv. API */ 633 if (setsockopt(ripsock, IPPROTO_IPV6, IPV6_PKTINFO, &i, 634 sizeof(i)) < 0) { 635 fatal("rip IPV6_PKTINFO"); 636 /*NOTREACHED*/ 637 } 638 #endif 639 640 memset(&hints, 0, sizeof(hints)); 641 hints.ai_family = PF_INET6; 642 hints.ai_socktype = SOCK_DGRAM; 643 error = getaddrinfo(RIP6_DEST, port, &hints, &res); 644 if (error) { 645 fatal("%s", gai_strerror(error)); 646 /*NOTREACHED*/ 647 } 648 if (res->ai_next) { 649 fatal("%s resolved to multiple address", RIP6_DEST); 650 /*NOTREACHED*/ 651 } 652 memcpy(&ripsin, res->ai_addr, res->ai_addrlen); 653 654 #ifdef FD_ZERO 655 FD_ZERO(&sockvec); 656 #else 657 memset(&sockvec, 0, sizeof(sockvec)); 658 #endif 659 FD_SET(ripsock, &sockvec); 660 maxfd = ripsock; 661 662 if (nflag == 0) { 663 if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { 664 fatal("route socket"); 665 /*NOTREACHED*/ 666 } 667 FD_SET(rtsock, &sockvec); 668 if (rtsock > maxfd) 669 maxfd = rtsock; 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, sin6) 685 struct ifc *ifcp; 686 struct sockaddr_in6 *sin6; 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(&sin6->sin6_addr), ntohs(sin6->sin6_port)); 695 else 696 tracet(1, "Send: info(%d) to %s.%d\n", 697 nrt, inet6_n2p(&sin6->sin6_addr), ntohs(sin6->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(sin6, 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, sin6, flag) 736 struct ifc *ifcp; 737 struct sockaddr_in6 *sin6; 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, sin6); 762 nh = NULL; 763 } 764 } 765 if (nrt) /* Send last packet */ 766 ripflush(NULL, sin6); 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, sin6); 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, sin6); 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, sin6); 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, sin6); 850 nh = NULL; 851 } 852 } 853 if (nrt) /* Send last packet */ 854 ripflush(ifcp, sin6); 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(sin6, len) 962 struct sockaddr_in6 *sin6; 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 = *sin6; 980 sin6 = &sincopy; 981 982 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) 983 || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 984 idx = IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr); 985 SET_IN6_LINKLOCAL_IFINDEX(sin6->sin6_addr, 0); 986 } else 987 idx = 0; 988 989 m.msg_name = (caddr_t)sin6; 990 m.msg_namelen = sizeof(*sin6); 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, sin6) 1338 struct ifc *ifcp; 1339 struct netinfo6 *np; 1340 int nn; 1341 struct sockaddr_in6 *sin6; 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(sin6, RIPSIZE(nn)); 1358 return; 1359 } 1360 /* Whole routing table dump */ 1361 trace(1, "\tRIP Request -- whole routing table\n"); 1362 ripsend(ifcp, sin6, 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 *sin6; 1449 struct ifac *ifa; 1450 int plen; 1451 char buf[BUFSIZ]; 1452 1453 sin6 = (const struct sockaddr_in6 *)sa; 1454 if (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !lflag) 1455 return; 1456 ifr.ifr_addr = *sin6; 1457 strcpy(ifr.ifr_name, name); 1458 if (ioctl(s, SIOCGIFNETMASK_IN6, (char *)&ifr) < 0) { 1459 fatal("ioctl: SIOCGIFNETMASK_IN6"); 1460 /*NOTREACHED*/ 1461 } 1462 plen = sin6mask2len(&ifr.ifr_addr); 1463 if ((ifa = ifa_match(ifcp, &sin6->sin6_addr, plen)) != NULL) { 1464 /* same interface found */ 1465 /* need check if something changed */ 1466 /* XXX not yet implemented */ 1467 return; 1468 } 1469 /* 1470 * New address is found 1471 */ 1472 if ((ifa = MALLOC(struct ifac)) == NULL) { 1473 fatal("malloc: struct ifac"); 1474 /*NOTREACHED*/ 1475 } 1476 memset(ifa, 0, sizeof(*ifa)); 1477 ifa->ifa_conf = ifcp; 1478 ifa->ifa_next = ifcp->ifc_addr; 1479 ifcp->ifc_addr = ifa; 1480 ifa->ifa_addr = sin6->sin6_addr; 1481 ifa->ifa_plen = plen; 1482 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 1483 ifr.ifr_addr = *sin6; 1484 if (ioctl(s, SIOCGIFDSTADDR_IN6, (char *)&ifr) < 0) { 1485 fatal("ioctl: SIOCGIFDSTADDR_IN6"); 1486 /*NOTREACHED*/ 1487 } 1488 ifa->ifa_raddr = ifr.ifr_dstaddr.sin6_addr; 1489 inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr, buf, sizeof(buf)); 1490 trace(1, "found address %s/%d -- %s\n", 1491 inet6_n2p(&ifa->ifa_addr), ifa->ifa_plen, buf); 1492 } else { 1493 trace(1, "found address %s/%d\n", 1494 inet6_n2p(&ifa->ifa_addr), ifa->ifa_plen); 1495 } 1496 if (ifcp->ifc_index < 0 && IN6_IS_ADDR_LINKLOCAL(&ifa->ifa_addr)) { 1497 ifcp->ifc_mylladdr = ifa->ifa_addr; 1498 ifcp->ifc_index = IN6_LINKLOCAL_IFINDEX(ifa->ifa_addr); 1499 memcpy(&ifcp->ifc_ripsin, &ripsin, ripsin.ss_len); 1500 SET_IN6_LINKLOCAL_IFINDEX(ifcp->ifc_ripsin.sin6_addr, 1501 ifcp->ifc_index); 1502 setindex2ifc(ifcp->ifc_index, ifcp); 1503 ifcp->ifc_mtu = getifmtu(ifcp->ifc_index); 1504 if (ifcp->ifc_mtu > RIP6_MAXMTU) 1505 ifcp->ifc_mtu = RIP6_MAXMTU; 1506 if (ioctl(s, SIOCGIFMETRIC, (char *)&ifr) < 0) { 1507 fatal("ioctl: SIOCGIFMETRIC"); 1508 /*NOTREACHED*/ 1509 } 1510 ifcp->ifc_metric = ifr.ifr_metric; 1511 trace(1, "\tindex: %d, mtu: %d, metric: %d\n", 1512 ifcp->ifc_index, ifcp->ifc_mtu, ifcp->ifc_metric); 1513 } else 1514 ifcp->ifc_cflags |= IFC_CHANGED; 1515 } 1516 1517 /* 1518 * Receive and process routing messages. 1519 * Update interface information as necesssary. 1520 */ 1521 void 1522 rtrecv() 1523 { 1524 char buf[BUFSIZ]; 1525 char *p, *q; 1526 struct rt_msghdr *rtm; 1527 struct ifa_msghdr *ifam; 1528 struct if_msghdr *ifm; 1529 int len; 1530 struct ifc *ifcp, *ic; 1531 int iface = 0, rtable = 0; 1532 struct sockaddr_in6 *rta[RTAX_MAX]; 1533 struct sockaddr_in6 mask; 1534 int i, addrs; 1535 struct riprt *rrt; 1536 1537 if ((len = read(rtsock, buf, sizeof(buf))) < 0) { 1538 perror("read from rtsock"); 1539 exit(1); 1540 } 1541 if (len < sizeof(*rtm)) { 1542 trace(1, "short read from rtsock: %d (should be > %lu)\n", 1543 len, (u_long)sizeof(*rtm)); 1544 return; 1545 } 1546 if (dflag >= 2) { 1547 fprintf(stderr, "rtmsg:\n"); 1548 for (i = 0; i < len; i++) { 1549 fprintf(stderr, "%02x ", buf[i] & 0xff); 1550 if (i % 16 == 15) fprintf(stderr, "\n"); 1551 } 1552 fprintf(stderr, "\n"); 1553 } 1554 1555 for (p = buf; p - buf < len; p += ((struct rt_msghdr *)p)->rtm_msglen) { 1556 /* safety against bogus message */ 1557 if (((struct rt_msghdr *)p)->rtm_msglen <= 0) { 1558 trace(1, "bogus rtmsg: length=%d\n", 1559 ((struct rt_msghdr *)p)->rtm_msglen); 1560 break; 1561 } 1562 rtm = NULL; 1563 ifam = NULL; 1564 ifm = NULL; 1565 switch (((struct rt_msghdr *)p)->rtm_type) { 1566 case RTM_NEWADDR: 1567 case RTM_DELADDR: 1568 ifam = (struct ifa_msghdr *)p; 1569 addrs = ifam->ifam_addrs; 1570 q = (char *)(ifam + 1); 1571 break; 1572 case RTM_IFINFO: 1573 ifm = (struct if_msghdr *)p; 1574 addrs = ifm->ifm_addrs; 1575 q = (char *)(ifm + 1); 1576 break; 1577 default: 1578 rtm = (struct rt_msghdr *)p; 1579 addrs = rtm->rtm_addrs; 1580 q = (char *)(rtm + 1); 1581 if (rtm->rtm_version != RTM_VERSION) { 1582 trace(1, "unexpected rtmsg version %d " 1583 "(should be %d)\n", 1584 rtm->rtm_version, RTM_VERSION); 1585 continue; 1586 } 1587 if (rtm->rtm_pid == pid) { 1588 #if 0 1589 trace(1, "rtmsg looped back to me, ignored\n"); 1590 #endif 1591 continue; 1592 } 1593 break; 1594 } 1595 memset(&rta, 0, sizeof(rta)); 1596 for (i = 0; i < RTAX_MAX; i++) { 1597 if (addrs & (1 << i)) { 1598 rta[i] = (struct sockaddr_in6 *)q; 1599 q += ROUNDUP(rta[i]->sin6_len); 1600 } 1601 } 1602 1603 trace(1, "rtsock: %s (addrs=%x)\n", 1604 rttypes((struct rt_msghdr *)p), addrs); 1605 if (dflag >= 2) { 1606 for (i = 0; 1607 i < ((struct rt_msghdr *)p)->rtm_msglen; 1608 i++) { 1609 fprintf(stderr, "%02x ", p[i] & 0xff); 1610 if (i % 16 == 15) fprintf(stderr, "\n"); 1611 } 1612 fprintf(stderr, "\n"); 1613 } 1614 1615 /* 1616 * Easy ones first. 1617 * 1618 * We may be able to optimize by using ifm->ifm_index or 1619 * ifam->ifam_index. For simplicity we don't do that here. 1620 */ 1621 switch (((struct rt_msghdr *)p)->rtm_type) { 1622 case RTM_NEWADDR: 1623 case RTM_IFINFO: 1624 iface++; 1625 continue; 1626 case RTM_ADD: 1627 rtable++; 1628 continue; 1629 case RTM_LOSING: 1630 case RTM_MISS: 1631 case RTM_RESOLVE: 1632 case RTM_GET: 1633 case RTM_LOCK: 1634 /* nothing to be done here */ 1635 trace(1, "\tnothing to be done, ignored\n"); 1636 continue; 1637 } 1638 1639 #if 0 1640 if (rta[RTAX_DST] == NULL) { 1641 trace(1, "\tno destination, ignored\n"); 1642 continue; 1643 } 1644 if (rta[RTAX_DST]->sin6_family != AF_INET6) { 1645 trace(1, "\taf mismatch, ignored\n"); 1646 continue; 1647 } 1648 if (IN6_IS_ADDR_LINKLOCAL(&rta[RTAX_DST]->sin6_addr)) { 1649 trace(1, "\tlinklocal destination, ignored\n"); 1650 continue; 1651 } 1652 if (IN6_ARE_ADDR_EQUAL(&rta[RTAX_DST]->sin6_addr, &in6addr_loopback)) { 1653 trace(1, "\tloopback destination, ignored\n"); 1654 continue; /* Loopback */ 1655 } 1656 if (IN6_IS_ADDR_MULTICAST(&rta[RTAX_DST]->sin6_addr)) { 1657 trace(1, "\tmulticast destination, ignored\n"); 1658 continue; 1659 } 1660 #endif 1661 1662 /* hard ones */ 1663 switch (((struct rt_msghdr *)p)->rtm_type) { 1664 case RTM_NEWADDR: 1665 case RTM_IFINFO: 1666 case RTM_ADD: 1667 case RTM_LOSING: 1668 case RTM_MISS: 1669 case RTM_RESOLVE: 1670 case RTM_GET: 1671 case RTM_LOCK: 1672 /* should already be handled */ 1673 fatal("rtrecv: never reach here"); 1674 /*NOTREACHED*/ 1675 case RTM_DELETE: 1676 if (!rta[RTAX_DST] || !rta[RTAX_GATEWAY]) { 1677 trace(1, "\tsome of dst/gw/netamsk are " 1678 "unavailable, ignored\n"); 1679 break; 1680 } 1681 if ((rtm->rtm_flags & RTF_HOST) != 0) { 1682 mask.sin6_len = sizeof(mask); 1683 memset(&mask.sin6_addr, 0xff, 1684 sizeof(mask.sin6_addr)); 1685 rta[RTAX_NETMASK] = &mask; 1686 } else if (!rta[RTAX_NETMASK]) { 1687 trace(1, "\tsome of dst/gw/netamsk are " 1688 "unavailable, ignored\n"); 1689 break; 1690 } 1691 if (rt_del(rta[RTAX_DST], rta[RTAX_GATEWAY], 1692 rta[RTAX_NETMASK]) == 0) { 1693 rtable++; /*just to be sure*/ 1694 } 1695 break; 1696 case RTM_CHANGE: 1697 case RTM_REDIRECT: 1698 trace(1, "\tnot supported yet, ignored\n"); 1699 break; 1700 case RTM_DELADDR: 1701 if (!rta[RTAX_NETMASK] || !rta[RTAX_IFA]) { 1702 trace(1, "\tno netmask or ifa given, ignored\n"); 1703 break; 1704 } 1705 if (ifam->ifam_index < nindex2ifc) 1706 ifcp = index2ifc[ifam->ifam_index]; 1707 else 1708 ifcp = NULL; 1709 if (!ifcp) { 1710 trace(1, "\tinvalid ifam_index %d, ignored\n", 1711 ifam->ifam_index); 1712 break; 1713 } 1714 if (!rt_deladdr(ifcp, rta[RTAX_IFA], rta[RTAX_NETMASK])) 1715 iface++; 1716 break; 1717 case RTM_OLDADD: 1718 case RTM_OLDDEL: 1719 trace(1, "\tnot supported yet, ignored\n"); 1720 break; 1721 } 1722 1723 } 1724 1725 if (iface) { 1726 trace(1, "rtsock: reconfigure interfaces, refresh interface routes\n"); 1727 ifconfig(); 1728 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) 1729 if (ifcp->ifc_cflags & IFC_CHANGED) { 1730 if (ifrt(ifcp, 1)) { 1731 for (ic = ifc; ic; ic = ic->ifc_next) { 1732 if (ifcp->ifc_index == ic->ifc_index) 1733 continue; 1734 if (ic->ifc_flags & IFF_UP) 1735 ripsend(ic, &ic->ifc_ripsin, 1736 RRTF_CHANGED); 1737 } 1738 /* Reset the flag */ 1739 for (rrt = riprt; rrt; rrt = rrt->rrt_next) 1740 rrt->rrt_rflags &= ~RRTF_CHANGED; 1741 } 1742 ifcp->ifc_cflags &= ~IFC_CHANGED; 1743 } 1744 } 1745 if (rtable) { 1746 trace(1, "rtsock: read routing table again\n"); 1747 krtread(1); 1748 } 1749 } 1750 1751 /* 1752 * remove specified route from the internal routing table. 1753 */ 1754 int 1755 rt_del(sdst, sgw, smask) 1756 const struct sockaddr_in6 *sdst; 1757 const struct sockaddr_in6 *sgw; 1758 const struct sockaddr_in6 *smask; 1759 { 1760 const struct in6_addr *dst = NULL; 1761 const struct in6_addr *gw = NULL; 1762 int prefix; 1763 struct netinfo6 ni6; 1764 struct riprt *rrt = NULL; 1765 time_t t_lifetime; 1766 1767 if (sdst->sin6_family != AF_INET6) { 1768 trace(1, "\tother AF, ignored\n"); 1769 return -1; 1770 } 1771 if (IN6_IS_ADDR_LINKLOCAL(&sdst->sin6_addr) 1772 || IN6_ARE_ADDR_EQUAL(&sdst->sin6_addr, &in6addr_loopback) 1773 || IN6_IS_ADDR_MULTICAST(&sdst->sin6_addr)) { 1774 trace(1, "\taddress %s not interesting, ignored\n", 1775 inet6_n2p(&sdst->sin6_addr)); 1776 return -1; 1777 } 1778 dst = &sdst->sin6_addr; 1779 if (sgw->sin6_family == AF_INET6) { 1780 /* easy case */ 1781 gw = &sgw->sin6_addr; 1782 prefix = sin6mask2len(smask); 1783 } else if (sgw->sin6_family == AF_LINK) { 1784 /* 1785 * Interface route... a hard case. We need to get the prefix 1786 * length from the kernel, but we now are parsing rtmsg. 1787 * We'll purge matching routes from my list, then get the 1788 * fresh list. 1789 */ 1790 struct riprt *longest; 1791 trace(1, "\t%s is a interface route, guessing prefixlen\n", 1792 inet6_n2p(dst)); 1793 longest = NULL; 1794 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 1795 if (IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, 1796 &sdst->sin6_addr) 1797 && IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw)) { 1798 if (!longest 1799 || longest->rrt_info.rip6_plen < 1800 rrt->rrt_info.rip6_plen) { 1801 longest = rrt; 1802 } 1803 } 1804 } 1805 rrt = longest; 1806 if (!rrt) { 1807 trace(1, "\tno matching interface route found\n"); 1808 return -1; 1809 } 1810 gw = &in6addr_loopback; 1811 prefix = rrt->rrt_info.rip6_plen; 1812 } else { 1813 trace(1, "\tunsupported af: (gw=%d)\n", sgw->sin6_family); 1814 return -1; 1815 } 1816 1817 trace(1, "\tdeleting %s/%d ", inet6_n2p(dst), prefix); 1818 trace(1, "gw %s\n", inet6_n2p(gw)); 1819 t_lifetime = time(NULL) - RIP_LIFETIME; 1820 /* age route for interface address */ 1821 memset(&ni6, 0, sizeof(ni6)); 1822 ni6.rip6_dest = *dst; 1823 ni6.rip6_plen = prefix; 1824 applyplen(&ni6.rip6_dest, ni6.rip6_plen); /*to be sure*/ 1825 trace(1, "\tfind route %s/%d\n", inet6_n2p(&ni6.rip6_dest), 1826 ni6.rip6_plen); 1827 if (!rrt && (rrt = rtsearch(&ni6, NULL)) == NULL) { 1828 trace(1, "\tno route found\n"); 1829 return -1; 1830 } 1831 #if 0 1832 if ((rrt->rrt_flags & RTF_STATIC) == 0) { 1833 trace(1, "\tyou can delete static routes only\n"); 1834 } else 1835 #endif 1836 if (!IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, gw)) { 1837 trace(1, "\tgw mismatch: %s <-> ", 1838 inet6_n2p(&rrt->rrt_gw)); 1839 trace(1, "%s\n", inet6_n2p(gw)); 1840 } else { 1841 trace(1, "\troute found, age it\n"); 1842 if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) { 1843 rrt->rrt_t = t_lifetime; 1844 rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 1845 } 1846 } 1847 return 0; 1848 } 1849 1850 /* 1851 * remove specified address from internal interface/routing table. 1852 */ 1853 int 1854 rt_deladdr(ifcp, sifa, smask) 1855 struct ifc *ifcp; 1856 const struct sockaddr_in6 *sifa; 1857 const struct sockaddr_in6 *smask; 1858 { 1859 const struct in6_addr *addr = NULL; 1860 int prefix; 1861 struct ifac *ifa = NULL; 1862 struct netinfo6 ni6; 1863 struct riprt *rrt = NULL; 1864 time_t t_lifetime; 1865 int updated = 0; 1866 1867 if (sifa->sin6_family != AF_INET6) { 1868 trace(1, "\tother AF, ignored\n"); 1869 return -1; 1870 } 1871 addr = &sifa->sin6_addr; 1872 prefix = sin6mask2len(smask); 1873 1874 trace(1, "\tdeleting %s/%d from %s\n", 1875 inet6_n2p(addr), prefix, ifcp->ifc_name); 1876 ifa = ifa_match(ifcp, addr, prefix); 1877 if (!ifa) { 1878 trace(1, "\tno matching ifa found for %s/%d on %s\n", 1879 inet6_n2p(addr), prefix, ifcp->ifc_name); 1880 return -1; 1881 } 1882 if (ifa->ifa_conf != ifcp) { 1883 trace(1, "\taddress table corrupt: back pointer does not match " 1884 "(%s != %s)\n", 1885 ifcp->ifc_name, ifa->ifa_conf->ifc_name); 1886 return -1; 1887 } 1888 /* remove ifa from interface */ 1889 if (ifcp->ifc_addr == ifa) 1890 ifcp->ifc_addr = ifa->ifa_next; 1891 else { 1892 struct ifac *p; 1893 for (p = ifcp->ifc_addr; p; p = p->ifa_next) { 1894 if (p->ifa_next == ifa) { 1895 p->ifa_next = ifa->ifa_next; 1896 break; 1897 } 1898 } 1899 } 1900 ifa->ifa_next = NULL; 1901 ifa->ifa_conf = NULL; 1902 t_lifetime = time(NULL) - RIP_LIFETIME; 1903 /* age route for interface address */ 1904 memset(&ni6, 0, sizeof(ni6)); 1905 ni6.rip6_dest = ifa->ifa_addr; 1906 ni6.rip6_plen = ifa->ifa_plen; 1907 applyplen(&ni6.rip6_dest, ni6.rip6_plen); 1908 trace(1, "\tfind interface route %s/%d on %d\n", 1909 inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen, ifcp->ifc_index); 1910 if ((rrt = rtsearch(&ni6, NULL)) != NULL) { 1911 struct in6_addr none; 1912 memset(&none, 0, sizeof(none)); 1913 if (rrt->rrt_index == ifcp->ifc_index && 1914 (IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &none) || 1915 IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw))) { 1916 trace(1, "\troute found, age it\n"); 1917 if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) { 1918 rrt->rrt_t = t_lifetime; 1919 rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 1920 } 1921 updated++; 1922 } else { 1923 trace(1, "\tnon-interface route found: %s/%d on %d\n", 1924 inet6_n2p(&rrt->rrt_info.rip6_dest), 1925 rrt->rrt_info.rip6_plen, 1926 rrt->rrt_index); 1927 } 1928 } else 1929 trace(1, "\tno interface route found\n"); 1930 /* age route for p2p destination */ 1931 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 1932 memset(&ni6, 0, sizeof(ni6)); 1933 ni6.rip6_dest = ifa->ifa_raddr; 1934 ni6.rip6_plen = 128; 1935 applyplen(&ni6.rip6_dest, ni6.rip6_plen); /*to be sure*/ 1936 trace(1, "\tfind p2p route %s/%d on %d\n", 1937 inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen, 1938 ifcp->ifc_index); 1939 if ((rrt = rtsearch(&ni6, NULL)) != NULL) { 1940 if (rrt->rrt_index == ifcp->ifc_index && 1941 IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &ifa->ifa_addr)) { 1942 trace(1, "\troute found, age it\n"); 1943 if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) { 1944 rrt->rrt_t = t_lifetime; 1945 rrt->rrt_info.rip6_metric = 1946 HOPCNT_INFINITY6; 1947 updated++; 1948 } 1949 } else { 1950 trace(1, "\tnon-p2p route found: %s/%d on %d\n", 1951 inet6_n2p(&rrt->rrt_info.rip6_dest), 1952 rrt->rrt_info.rip6_plen, 1953 rrt->rrt_index); 1954 } 1955 } else 1956 trace(1, "\tno p2p route found\n"); 1957 } 1958 return updated ? 0 : -1; 1959 } 1960 1961 /* 1962 * Get each interface address and put those interface routes to the route 1963 * list. 1964 */ 1965 int 1966 ifrt(ifcp, again) 1967 struct ifc *ifcp; 1968 int again; 1969 { 1970 struct ifac *ifa; 1971 struct riprt *rrt = NULL, *search_rrt, *prev_rrt, *loop_rrt; 1972 struct netinfo6 *np; 1973 time_t t_lifetime; 1974 int need_trigger = 0; 1975 1976 if (ifcp->ifc_flags & IFF_LOOPBACK) 1977 return 0; /* ignore loopback */ 1978 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 1979 ifrt_p2p(ifcp, again); 1980 return 0; 1981 } 1982 1983 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 1984 if (IN6_IS_ADDR_LINKLOCAL(&ifa->ifa_addr)) { 1985 #if 0 1986 trace(1, "route: %s on %s: " 1987 "skip linklocal interface address\n", 1988 inet6_n2p(&ifa->ifa_addr), ifcp->ifc_name); 1989 #endif 1990 continue; 1991 } 1992 if (IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_addr)) { 1993 #if 0 1994 trace(1, "route: %s: skip unspec interface address\n", 1995 ifcp->ifc_name); 1996 #endif 1997 continue; 1998 } 1999 if (ifcp->ifc_flags & IFF_UP) { 2000 if ((rrt = MALLOC(struct riprt)) == NULL) 2001 fatal("malloc: struct riprt"); 2002 memset(rrt, 0, sizeof(*rrt)); 2003 rrt->rrt_same = NULL; 2004 rrt->rrt_index = ifcp->ifc_index; 2005 rrt->rrt_t = 0; /* don't age */ 2006 rrt->rrt_info.rip6_dest = ifa->ifa_addr; 2007 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 2008 rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric; 2009 rrt->rrt_info.rip6_plen = ifa->ifa_plen; 2010 rrt->rrt_flags = RTF_CLONING; 2011 rrt->rrt_rflags |= RRTF_CHANGED; 2012 applyplen(&rrt->rrt_info.rip6_dest, ifa->ifa_plen); 2013 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2014 rrt->rrt_gw = ifa->ifa_addr; 2015 np = &rrt->rrt_info; 2016 search_rrt = rtsearch(np, &prev_rrt); 2017 if (search_rrt != NULL) { 2018 if (search_rrt->rrt_info.rip6_metric <= 2019 rrt->rrt_info.rip6_metric) { 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 goto next; 2028 } 2029 2030 if (prev_rrt) 2031 prev_rrt->rrt_next = rrt->rrt_next; 2032 else 2033 riprt = rrt->rrt_next; 2034 delroute(&rrt->rrt_info, &rrt->rrt_gw); 2035 } 2036 /* Attach the route to the list */ 2037 trace(1, "route: %s/%d: register route (%s)\n", 2038 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2039 ifcp->ifc_name); 2040 rrt->rrt_next = riprt; 2041 riprt = rrt; 2042 addroute(rrt, &rrt->rrt_gw, ifcp); 2043 rrt = NULL; 2044 sendrequest(ifcp); 2045 ripsend(ifcp, &ifcp->ifc_ripsin, 0); 2046 need_trigger = 1; 2047 } else { 2048 for (loop_rrt = riprt; loop_rrt; loop_rrt = loop_rrt->rrt_next) { 2049 if (loop_rrt->rrt_index == ifcp->ifc_index) { 2050 t_lifetime = time(NULL) - RIP_LIFETIME; 2051 if (loop_rrt->rrt_t == 0 || loop_rrt->rrt_t > t_lifetime) { 2052 loop_rrt->rrt_t = t_lifetime; 2053 loop_rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 2054 loop_rrt->rrt_rflags |= RRTF_CHANGED; 2055 need_trigger = 1; 2056 } 2057 } 2058 } 2059 } 2060 next: 2061 if (rrt) 2062 free(rrt); 2063 } 2064 return need_trigger; 2065 } 2066 2067 /* 2068 * there are couple of p2p interface routing models. "behavior" lets 2069 * you pick one. it looks that gated behavior fits best with BSDs, 2070 * since BSD kernels does not look at prefix length on p2p interfaces. 2071 */ 2072 void 2073 ifrt_p2p(ifcp, again) 2074 struct ifc *ifcp; 2075 int again; 2076 { 2077 struct ifac *ifa; 2078 struct riprt *rrt, *orrt, *prevrrt; 2079 struct netinfo6 *np; 2080 struct in6_addr addr, dest; 2081 int advert, ignore, i; 2082 #define P2PADVERT_NETWORK 1 2083 #define P2PADVERT_ADDR 2 2084 #define P2PADVERT_DEST 4 2085 #define P2PADVERT_MAX 4 2086 const enum { CISCO, GATED, ROUTE6D } behavior = GATED; 2087 const char *category = ""; 2088 const char *noadv; 2089 2090 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 2091 addr = ifa->ifa_addr; 2092 dest = ifa->ifa_raddr; 2093 applyplen(&addr, ifa->ifa_plen); 2094 applyplen(&dest, ifa->ifa_plen); 2095 advert = ignore = 0; 2096 switch (behavior) { 2097 case CISCO: 2098 /* 2099 * honor addr/plen, just like normal shared medium 2100 * interface. this may cause trouble if you reuse 2101 * addr/plen on other interfaces. 2102 * 2103 * advertise addr/plen. 2104 */ 2105 advert |= P2PADVERT_NETWORK; 2106 break; 2107 case GATED: 2108 /* 2109 * prefixlen on p2p interface is meaningless. 2110 * advertise addr/128 and dest/128. 2111 * 2112 * do not install network route to route6d routing 2113 * table (if we do, it would prevent route installation 2114 * for other p2p interface that shares addr/plen). 2115 * 2116 * XXX what should we do if dest is ::? it will not 2117 * get announced anyways (see following filter), 2118 * but we need to think. 2119 */ 2120 advert |= P2PADVERT_ADDR; 2121 advert |= P2PADVERT_DEST; 2122 ignore |= P2PADVERT_NETWORK; 2123 break; 2124 case ROUTE6D: 2125 /* 2126 * just for testing. actually the code is redundant 2127 * given the current p2p interface address assignment 2128 * rule for kame kernel. 2129 * 2130 * intent: 2131 * A/n -> announce A/n 2132 * A B/n, A and B share prefix -> A/n (= B/n) 2133 * A B/n, do not share prefix -> A/128 and B/128 2134 * actually, A/64 and A B/128 are the only cases 2135 * permitted by the kernel: 2136 * A/64 -> A/64 2137 * A B/128 -> A/128 and B/128 2138 */ 2139 if (!IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_raddr)) { 2140 if (IN6_ARE_ADDR_EQUAL(&addr, &dest)) 2141 advert |= P2PADVERT_NETWORK; 2142 else { 2143 advert |= P2PADVERT_ADDR; 2144 advert |= P2PADVERT_DEST; 2145 ignore |= P2PADVERT_NETWORK; 2146 } 2147 } else 2148 advert |= P2PADVERT_NETWORK; 2149 break; 2150 } 2151 2152 for (i = 1; i <= P2PADVERT_MAX; i *= 2) { 2153 if ((ignore & i) != 0) 2154 continue; 2155 if ((rrt = MALLOC(struct riprt)) == NULL) { 2156 fatal("malloc: struct riprt"); 2157 /*NOTREACHED*/ 2158 } 2159 memset(rrt, 0, sizeof(*rrt)); 2160 rrt->rrt_same = NULL; 2161 rrt->rrt_index = ifcp->ifc_index; 2162 rrt->rrt_t = 0; /* don't age */ 2163 switch (i) { 2164 case P2PADVERT_NETWORK: 2165 rrt->rrt_info.rip6_dest = ifa->ifa_addr; 2166 rrt->rrt_info.rip6_plen = ifa->ifa_plen; 2167 applyplen(&rrt->rrt_info.rip6_dest, 2168 ifa->ifa_plen); 2169 category = "network"; 2170 break; 2171 case P2PADVERT_ADDR: 2172 rrt->rrt_info.rip6_dest = ifa->ifa_addr; 2173 rrt->rrt_info.rip6_plen = 128; 2174 rrt->rrt_gw = in6addr_loopback; 2175 category = "addr"; 2176 break; 2177 case P2PADVERT_DEST: 2178 rrt->rrt_info.rip6_dest = ifa->ifa_raddr; 2179 rrt->rrt_info.rip6_plen = 128; 2180 rrt->rrt_gw = ifa->ifa_addr; 2181 category = "dest"; 2182 break; 2183 } 2184 if (IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_info.rip6_dest) || 2185 IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_info.rip6_dest)) { 2186 #if 0 2187 trace(1, "route: %s: skip unspec/linklocal " 2188 "(%s on %s)\n", category, ifcp->ifc_name); 2189 #endif 2190 free(rrt); 2191 continue; 2192 } 2193 if ((advert & i) == 0) { 2194 rrt->rrt_rflags |= RRTF_NOADVERTISE; 2195 noadv = ", NO-ADV"; 2196 } else 2197 noadv = ""; 2198 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 2199 rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric; 2200 np = &rrt->rrt_info; 2201 orrt = rtsearch(np, &prevrrt); 2202 if (!orrt) { 2203 /* Attach the route to the list */ 2204 trace(1, "route: %s/%d: register route " 2205 "(%s on %s%s)\n", 2206 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2207 category, ifcp->ifc_name, noadv); 2208 rrt->rrt_next = riprt; 2209 riprt = rrt; 2210 } else if (rrt->rrt_index != orrt->rrt_index || 2211 rrt->rrt_info.rip6_metric != orrt->rrt_info.rip6_metric) { 2212 /* swap route */ 2213 rrt->rrt_next = orrt->rrt_next; 2214 if (prevrrt) 2215 prevrrt->rrt_next = rrt; 2216 else 2217 riprt = rrt; 2218 free(orrt); 2219 2220 trace(1, "route: %s/%d: update (%s on %s%s)\n", 2221 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2222 category, ifcp->ifc_name, noadv); 2223 } else { 2224 /* Already found */ 2225 if (!again) { 2226 trace(1, "route: %s/%d: " 2227 "already registered (%s on %s%s)\n", 2228 inet6_n2p(&np->rip6_dest), 2229 np->rip6_plen, category, 2230 ifcp->ifc_name, noadv); 2231 } 2232 free(rrt); 2233 } 2234 } 2235 } 2236 #undef P2PADVERT_NETWORK 2237 #undef P2PADVERT_ADDR 2238 #undef P2PADVERT_DEST 2239 #undef P2PADVERT_MAX 2240 } 2241 2242 int 2243 getifmtu(ifindex) 2244 int ifindex; 2245 { 2246 int mib[6]; 2247 char *buf; 2248 size_t msize; 2249 struct if_msghdr *ifm; 2250 int mtu; 2251 2252 mib[0] = CTL_NET; 2253 mib[1] = PF_ROUTE; 2254 mib[2] = 0; 2255 mib[3] = AF_INET6; 2256 mib[4] = NET_RT_IFLIST; 2257 mib[5] = ifindex; 2258 if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0) { 2259 fatal("sysctl estimate NET_RT_IFLIST"); 2260 /*NOTREACHED*/ 2261 } 2262 if ((buf = malloc(msize)) == NULL) { 2263 fatal("malloc"); 2264 /*NOTREACHED*/ 2265 } 2266 if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0) { 2267 fatal("sysctl NET_RT_IFLIST"); 2268 /*NOTREACHED*/ 2269 } 2270 ifm = (struct if_msghdr *)buf; 2271 mtu = ifm->ifm_data.ifi_mtu; 2272 #ifdef __FreeBSD__ 2273 if (ifindex != ifm->ifm_index) { 2274 fatal("ifindex does not match with ifm_index"); 2275 /*NOTREACHED*/ 2276 } 2277 #endif 2278 free(buf); 2279 return mtu; 2280 } 2281 2282 const char * 2283 rttypes(rtm) 2284 struct rt_msghdr *rtm; 2285 { 2286 #define RTTYPE(s, f) \ 2287 do { \ 2288 if (rtm->rtm_type == (f)) \ 2289 return (s); \ 2290 } while (0) 2291 RTTYPE("ADD", RTM_ADD); 2292 RTTYPE("DELETE", RTM_DELETE); 2293 RTTYPE("CHANGE", RTM_CHANGE); 2294 RTTYPE("GET", RTM_GET); 2295 RTTYPE("LOSING", RTM_LOSING); 2296 RTTYPE("REDIRECT", RTM_REDIRECT); 2297 RTTYPE("MISS", RTM_MISS); 2298 RTTYPE("LOCK", RTM_LOCK); 2299 RTTYPE("OLDADD", RTM_OLDADD); 2300 RTTYPE("OLDDEL", RTM_OLDDEL); 2301 RTTYPE("RESOLVE", RTM_RESOLVE); 2302 RTTYPE("NEWADDR", RTM_NEWADDR); 2303 RTTYPE("DELADDR", RTM_DELADDR); 2304 RTTYPE("IFINFO", RTM_IFINFO); 2305 #ifdef RTM_OLDADD 2306 RTTYPE("OLDADD", RTM_OLDADD); 2307 #endif 2308 #ifdef RTM_OLDDEL 2309 RTTYPE("OLDDEL", RTM_OLDDEL); 2310 #endif 2311 #ifdef RTM_OIFINFO 2312 RTTYPE("OIFINFO", RTM_OIFINFO); 2313 #endif 2314 #ifdef RTM_IFANNOUNCE 2315 RTTYPE("IFANNOUNCE", RTM_IFANNOUNCE); 2316 #endif 2317 #ifdef RTM_NEWMADDR 2318 RTTYPE("NEWMADDR", RTM_NEWMADDR); 2319 #endif 2320 #ifdef RTM_DELMADDR 2321 RTTYPE("DELMADDR", RTM_DELMADDR); 2322 #endif 2323 #undef RTTYPE 2324 return NULL; 2325 } 2326 2327 const char * 2328 rtflags(rtm) 2329 struct rt_msghdr *rtm; 2330 { 2331 static char buf[BUFSIZ]; 2332 2333 /* 2334 * letter conflict should be okay. painful when *BSD diverges... 2335 */ 2336 strlcpy(buf, "", sizeof(buf)); 2337 #define RTFLAG(s, f) \ 2338 do { \ 2339 if (rtm->rtm_flags & (f)) \ 2340 strlcat(buf, (s), sizeof(buf)); \ 2341 } while (0) 2342 RTFLAG("U", RTF_UP); 2343 RTFLAG("G", RTF_GATEWAY); 2344 RTFLAG("H", RTF_HOST); 2345 RTFLAG("R", RTF_REJECT); 2346 RTFLAG("D", RTF_DYNAMIC); 2347 RTFLAG("M", RTF_MODIFIED); 2348 RTFLAG("d", RTF_DONE); 2349 #ifdef RTF_MASK 2350 RTFLAG("m", RTF_MASK); 2351 #endif 2352 RTFLAG("C", RTF_CLONING); 2353 #ifdef RTF_CLONED 2354 RTFLAG("c", RTF_CLONED); 2355 #endif 2356 #ifdef RTF_PRCLONING 2357 RTFLAG("c", RTF_PRCLONING); 2358 #endif 2359 #ifdef RTF_WASCLONED 2360 RTFLAG("W", RTF_WASCLONED); 2361 #endif 2362 RTFLAG("X", RTF_XRESOLVE); 2363 RTFLAG("L", RTF_LLINFO); 2364 RTFLAG("S", RTF_STATIC); 2365 RTFLAG("B", RTF_BLACKHOLE); 2366 #ifdef RTF_PROTO3 2367 RTFLAG("3", RTF_PROTO3); 2368 #endif 2369 RTFLAG("2", RTF_PROTO2); 2370 RTFLAG("1", RTF_PROTO1); 2371 #ifdef RTF_BROADCAST 2372 RTFLAG("b", RTF_BROADCAST); 2373 #endif 2374 #ifdef RTF_DEFAULT 2375 RTFLAG("d", RTF_DEFAULT); 2376 #endif 2377 #ifdef RTF_ISAROUTER 2378 RTFLAG("r", RTF_ISAROUTER); 2379 #endif 2380 #ifdef RTF_TUNNEL 2381 RTFLAG("T", RTF_TUNNEL); 2382 #endif 2383 #ifdef RTF_AUTH 2384 RTFLAG("A", RTF_AUTH); 2385 #endif 2386 #ifdef RTF_CRYPT 2387 RTFLAG("E", RTF_CRYPT); 2388 #endif 2389 #undef RTFLAG 2390 return buf; 2391 } 2392 2393 const char * 2394 ifflags(flags) 2395 int flags; 2396 { 2397 static char buf[BUFSIZ]; 2398 2399 strlcpy(buf, "", sizeof(buf)); 2400 #define IFFLAG(s, f) \ 2401 do { \ 2402 if (flags & (f)) { \ 2403 if (buf[0]) \ 2404 strlcat(buf, ",", sizeof(buf)); \ 2405 strlcat(buf, (s), sizeof(buf)); \ 2406 } \ 2407 } while (0) 2408 IFFLAG("UP", IFF_UP); 2409 IFFLAG("BROADCAST", IFF_BROADCAST); 2410 IFFLAG("DEBUG", IFF_DEBUG); 2411 IFFLAG("LOOPBACK", IFF_LOOPBACK); 2412 IFFLAG("POINTOPOINT", IFF_POINTOPOINT); 2413 #ifdef IFF_NOTRAILERS 2414 IFFLAG("NOTRAILERS", IFF_NOTRAILERS); 2415 #endif 2416 #ifdef IFF_SMART 2417 IFFLAG("SMART", IFF_SMART); 2418 #endif 2419 IFFLAG("RUNNING", IFF_RUNNING); 2420 IFFLAG("NOARP", IFF_NOARP); 2421 IFFLAG("PROMISC", IFF_PROMISC); 2422 IFFLAG("ALLMULTI", IFF_ALLMULTI); 2423 IFFLAG("OACTIVE", IFF_OACTIVE); 2424 IFFLAG("SIMPLEX", IFF_SIMPLEX); 2425 IFFLAG("LINK0", IFF_LINK0); 2426 IFFLAG("LINK1", IFF_LINK1); 2427 IFFLAG("LINK2", IFF_LINK2); 2428 IFFLAG("MULTICAST", IFF_MULTICAST); 2429 #undef IFFLAG 2430 return buf; 2431 } 2432 2433 void 2434 krtread(again) 2435 int again; 2436 { 2437 int mib[6]; 2438 size_t msize; 2439 char *buf, *p, *lim; 2440 struct rt_msghdr *rtm; 2441 int retry; 2442 const char *errmsg; 2443 2444 retry = 0; 2445 buf = NULL; 2446 mib[0] = CTL_NET; 2447 mib[1] = PF_ROUTE; 2448 mib[2] = 0; 2449 mib[3] = AF_INET6; /* Address family */ 2450 mib[4] = NET_RT_DUMP; /* Dump the kernel routing table */ 2451 mib[5] = 0; /* No flags */ 2452 do { 2453 retry++; 2454 errmsg = NULL; 2455 if (buf) 2456 free(buf); 2457 if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0) { 2458 errmsg = "sysctl estimate"; 2459 continue; 2460 } 2461 if ((buf = malloc(msize)) == NULL) { 2462 errmsg = "malloc"; 2463 continue; 2464 } 2465 if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0) { 2466 errmsg = "sysctl NET_RT_DUMP"; 2467 continue; 2468 } 2469 } while (retry < 5 && errmsg != NULL); 2470 if (errmsg) { 2471 fatal("%s (with %d retries, msize=%lu)", errmsg, retry, 2472 (u_long)msize); 2473 /*NOTREACHED*/ 2474 } else if (1 < retry) 2475 syslog(LOG_INFO, "NET_RT_DUMP %d retires", retry); 2476 2477 lim = buf + msize; 2478 for (p = buf; p < lim; p += rtm->rtm_msglen) { 2479 rtm = (struct rt_msghdr *)p; 2480 rt_entry(rtm, again); 2481 } 2482 free(buf); 2483 } 2484 2485 void 2486 rt_entry(rtm, again) 2487 struct rt_msghdr *rtm; 2488 int again; 2489 { 2490 struct sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask; 2491 struct sockaddr_in6 *sin6_genmask, *sin6_ifp; 2492 char *rtmp, *ifname = NULL; 2493 struct riprt *rrt, *orrt; 2494 struct netinfo6 *np; 2495 int s; 2496 2497 sin6_dst = sin6_gw = sin6_mask = sin6_genmask = sin6_ifp = 0; 2498 if ((rtm->rtm_flags & RTF_UP) == 0 || rtm->rtm_flags & 2499 (RTF_CLONING|RTF_XRESOLVE|RTF_LLINFO|RTF_BLACKHOLE)) { 2500 return; /* not interested in the link route */ 2501 } 2502 /* do not look at cloned routes */ 2503 #ifdef RTF_WASCLONED 2504 if (rtm->rtm_flags & RTF_WASCLONED) 2505 return; 2506 #endif 2507 #ifdef RTF_CLONED 2508 if (rtm->rtm_flags & RTF_CLONED) 2509 return; 2510 #endif 2511 /* 2512 * do not look at dynamic routes. 2513 * netbsd/openbsd cloned routes have UGHD. 2514 */ 2515 if (rtm->rtm_flags & RTF_DYNAMIC) 2516 return; 2517 rtmp = (char *)(rtm + 1); 2518 /* Destination */ 2519 if ((rtm->rtm_addrs & RTA_DST) == 0) 2520 return; /* ignore routes without destination address */ 2521 sin6_dst = (struct sockaddr_in6 *)rtmp; 2522 rtmp += ROUNDUP(sin6_dst->sin6_len); 2523 if (rtm->rtm_addrs & RTA_GATEWAY) { 2524 sin6_gw = (struct sockaddr_in6 *)rtmp; 2525 rtmp += ROUNDUP(sin6_gw->sin6_len); 2526 } 2527 if (rtm->rtm_addrs & RTA_NETMASK) { 2528 sin6_mask = (struct sockaddr_in6 *)rtmp; 2529 rtmp += ROUNDUP(sin6_mask->sin6_len); 2530 } 2531 if (rtm->rtm_addrs & RTA_GENMASK) { 2532 sin6_genmask = (struct sockaddr_in6 *)rtmp; 2533 rtmp += ROUNDUP(sin6_genmask->sin6_len); 2534 } 2535 if (rtm->rtm_addrs & RTA_IFP) { 2536 sin6_ifp = (struct sockaddr_in6 *)rtmp; 2537 rtmp += ROUNDUP(sin6_ifp->sin6_len); 2538 } 2539 2540 /* Destination */ 2541 if (sin6_dst->sin6_family != AF_INET6) 2542 return; 2543 if (IN6_IS_ADDR_LINKLOCAL(&sin6_dst->sin6_addr)) 2544 return; /* Link-local */ 2545 if (IN6_ARE_ADDR_EQUAL(&sin6_dst->sin6_addr, &in6addr_loopback)) 2546 return; /* Loopback */ 2547 if (IN6_IS_ADDR_MULTICAST(&sin6_dst->sin6_addr)) 2548 return; 2549 2550 if ((rrt = MALLOC(struct riprt)) == NULL) { 2551 fatal("malloc: struct riprt"); 2552 /*NOTREACHED*/ 2553 } 2554 memset(rrt, 0, sizeof(*rrt)); 2555 np = &rrt->rrt_info; 2556 rrt->rrt_same = NULL; 2557 rrt->rrt_t = time(NULL); 2558 if (aflag == 0 && (rtm->rtm_flags & RTF_STATIC)) 2559 rrt->rrt_t = 0; /* Don't age static routes */ 2560 np->rip6_tag = 0; 2561 np->rip6_metric = rtm->rtm_rmx.rmx_hopcount; 2562 if (np->rip6_metric < 1) 2563 np->rip6_metric = 1; 2564 rrt->rrt_flags = rtm->rtm_flags; 2565 np->rip6_dest = sin6_dst->sin6_addr; 2566 2567 /* Mask or plen */ 2568 if (rtm->rtm_flags & RTF_HOST) 2569 np->rip6_plen = 128; /* Host route */ 2570 else if (sin6_mask) 2571 np->rip6_plen = sin6mask2len(sin6_mask); 2572 else 2573 np->rip6_plen = 0; 2574 2575 orrt = rtsearch(np, NULL); 2576 if (orrt && orrt->rrt_info.rip6_metric != HOPCNT_INFINITY6) { 2577 /* Already found */ 2578 if (!again) { 2579 trace(1, "route: %s/%d flags %s: already registered\n", 2580 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2581 rtflags(rtm)); 2582 } 2583 free(rrt); 2584 return; 2585 } 2586 /* Gateway */ 2587 if (!sin6_gw) 2588 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2589 else { 2590 if (sin6_gw->sin6_family == AF_INET6) 2591 rrt->rrt_gw = sin6_gw->sin6_addr; 2592 else if (sin6_gw->sin6_family == AF_LINK) { 2593 /* XXX in case ppp link? */ 2594 rrt->rrt_gw = in6addr_loopback; 2595 } else 2596 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2597 } 2598 trace(1, "route: %s/%d flags %s", 2599 inet6_n2p(&np->rip6_dest), np->rip6_plen, rtflags(rtm)); 2600 trace(1, " gw %s", inet6_n2p(&rrt->rrt_gw)); 2601 2602 /* Interface */ 2603 s = rtm->rtm_index; 2604 if (s < nindex2ifc && index2ifc[s]) 2605 ifname = index2ifc[s]->ifc_name; 2606 else { 2607 trace(1, " not configured\n"); 2608 free(rrt); 2609 return; 2610 } 2611 trace(1, " if %s sock %d", ifname, s); 2612 rrt->rrt_index = s; 2613 2614 trace(1, "\n"); 2615 2616 /* Check gateway */ 2617 if (!IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_gw) && 2618 !IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw) 2619 #ifdef __FreeBSD__ 2620 && (rrt->rrt_flags & RTF_LOCAL) == 0 2621 #endif 2622 ) { 2623 trace(0, "***** Gateway %s is not a link-local address.\n", 2624 inet6_n2p(&rrt->rrt_gw)); 2625 trace(0, "***** dest(%s) if(%s) -- Not optimized.\n", 2626 inet6_n2p(&rrt->rrt_info.rip6_dest), ifname); 2627 rrt->rrt_rflags |= RRTF_NH_NOT_LLADDR; 2628 } 2629 2630 /* Put it to the route list */ 2631 if (orrt && orrt->rrt_info.rip6_metric == HOPCNT_INFINITY6) { 2632 /* replace route list */ 2633 rrt->rrt_next = orrt->rrt_next; 2634 *orrt = *rrt; 2635 trace(1, "route: %s/%d flags %s: replace new route\n", 2636 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2637 rtflags(rtm)); 2638 free(rrt); 2639 } else { 2640 rrt->rrt_next = riprt; 2641 riprt = rrt; 2642 } 2643 } 2644 2645 int 2646 addroute(rrt, gw, ifcp) 2647 struct riprt *rrt; 2648 const struct in6_addr *gw; 2649 struct ifc *ifcp; 2650 { 2651 struct netinfo6 *np; 2652 u_char buf[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ]; 2653 struct rt_msghdr *rtm; 2654 struct sockaddr_in6 *sin6; 2655 int len; 2656 2657 np = &rrt->rrt_info; 2658 inet_ntop(AF_INET6, (const void *)gw, (char *)buf1, sizeof(buf1)); 2659 inet_ntop(AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2)); 2660 tracet(1, "ADD: %s/%d gw %s [%d] ifa %s\n", 2661 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2662 np->rip6_metric - 1, buf2); 2663 if (rtlog) 2664 fprintf(rtlog, "%s: ADD: %s/%d gw %s [%d] ifa %s\n", hms(), 2665 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2666 np->rip6_metric - 1, buf2); 2667 if (nflag) 2668 return 0; 2669 2670 memset(buf, 0, sizeof(buf)); 2671 rtm = (struct rt_msghdr *)buf; 2672 rtm->rtm_type = RTM_ADD; 2673 rtm->rtm_version = RTM_VERSION; 2674 rtm->rtm_seq = ++seq; 2675 rtm->rtm_pid = pid; 2676 rtm->rtm_flags = rrt->rrt_flags; 2677 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2678 rtm->rtm_rmx.rmx_hopcount = np->rip6_metric - 1; 2679 rtm->rtm_inits = RTV_HOPCOUNT; 2680 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2681 /* Destination */ 2682 sin6->sin6_len = sizeof(struct sockaddr_in6); 2683 sin6->sin6_family = AF_INET6; 2684 sin6->sin6_addr = np->rip6_dest; 2685 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2686 /* Gateway */ 2687 sin6->sin6_len = sizeof(struct sockaddr_in6); 2688 sin6->sin6_family = AF_INET6; 2689 sin6->sin6_addr = *gw; 2690 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2691 /* Netmask */ 2692 sin6->sin6_len = sizeof(struct sockaddr_in6); 2693 sin6->sin6_family = AF_INET6; 2694 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2695 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2696 2697 len = (char *)sin6 - (char *)buf; 2698 rtm->rtm_msglen = len; 2699 if (write(rtsock, buf, len) > 0) 2700 return 0; 2701 2702 if (errno == EEXIST) { 2703 trace(0, "ADD: Route already exists %s/%d gw %s\n", 2704 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2705 if (rtlog) 2706 fprintf(rtlog, "ADD: Route already exists %s/%d gw %s\n", 2707 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2708 } else { 2709 trace(0, "Can not write to rtsock (addroute): %s\n", 2710 strerror(errno)); 2711 if (rtlog) 2712 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2713 strerror(errno)); 2714 } 2715 return -1; 2716 } 2717 2718 int 2719 delroute(np, gw) 2720 struct netinfo6 *np; 2721 struct in6_addr *gw; 2722 { 2723 u_char buf[BUFSIZ], buf2[BUFSIZ]; 2724 struct rt_msghdr *rtm; 2725 struct sockaddr_in6 *sin6; 2726 int len; 2727 2728 inet_ntop(AF_INET6, (void *)gw, (char *)buf2, sizeof(buf2)); 2729 tracet(1, "DEL: %s/%d gw %s\n", inet6_n2p(&np->rip6_dest), 2730 np->rip6_plen, buf2); 2731 if (rtlog) 2732 fprintf(rtlog, "%s: DEL: %s/%d gw %s\n", 2733 hms(), inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2734 if (nflag) 2735 return 0; 2736 2737 memset(buf, 0, sizeof(buf)); 2738 rtm = (struct rt_msghdr *)buf; 2739 rtm->rtm_type = RTM_DELETE; 2740 rtm->rtm_version = RTM_VERSION; 2741 rtm->rtm_seq = ++seq; 2742 rtm->rtm_pid = pid; 2743 rtm->rtm_flags = RTF_UP | RTF_GATEWAY; 2744 if (np->rip6_plen == sizeof(struct in6_addr) * 8) 2745 rtm->rtm_flags |= RTF_HOST; 2746 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2747 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2748 /* Destination */ 2749 sin6->sin6_len = sizeof(struct sockaddr_in6); 2750 sin6->sin6_family = AF_INET6; 2751 sin6->sin6_addr = np->rip6_dest; 2752 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2753 /* Gateway */ 2754 sin6->sin6_len = sizeof(struct sockaddr_in6); 2755 sin6->sin6_family = AF_INET6; 2756 sin6->sin6_addr = *gw; 2757 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2758 /* Netmask */ 2759 sin6->sin6_len = sizeof(struct sockaddr_in6); 2760 sin6->sin6_family = AF_INET6; 2761 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2762 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2763 2764 len = (char *)sin6 - (char *)buf; 2765 rtm->rtm_msglen = len; 2766 if (write(rtsock, buf, len) >= 0) 2767 return 0; 2768 2769 if (errno == ESRCH) { 2770 trace(0, "RTDEL: Route does not exist: %s/%d gw %s\n", 2771 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2772 if (rtlog) 2773 fprintf(rtlog, "RTDEL: Route does not exist: %s/%d gw %s\n", 2774 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2775 } else { 2776 trace(0, "Can not write to rtsock (delroute): %s\n", 2777 strerror(errno)); 2778 if (rtlog) 2779 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2780 strerror(errno)); 2781 } 2782 return -1; 2783 } 2784 2785 struct in6_addr * 2786 getroute(np, gw) 2787 struct netinfo6 *np; 2788 struct in6_addr *gw; 2789 { 2790 u_char buf[BUFSIZ]; 2791 u_long myseq; 2792 int len; 2793 struct rt_msghdr *rtm; 2794 struct sockaddr_in6 *sin6; 2795 2796 rtm = (struct rt_msghdr *)buf; 2797 len = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in6); 2798 memset(rtm, 0, len); 2799 rtm->rtm_type = RTM_GET; 2800 rtm->rtm_version = RTM_VERSION; 2801 myseq = ++seq; 2802 rtm->rtm_seq = myseq; 2803 rtm->rtm_addrs = RTA_DST; 2804 rtm->rtm_msglen = len; 2805 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2806 sin6->sin6_len = sizeof(struct sockaddr_in6); 2807 sin6->sin6_family = AF_INET6; 2808 sin6->sin6_addr = np->rip6_dest; 2809 if (write(rtsock, buf, len) < 0) { 2810 if (errno == ESRCH) /* No such route found */ 2811 return NULL; 2812 perror("write to rtsock"); 2813 exit(1); 2814 } 2815 do { 2816 if ((len = read(rtsock, buf, sizeof(buf))) < 0) { 2817 perror("read from rtsock"); 2818 exit(1); 2819 } 2820 rtm = (struct rt_msghdr *)buf; 2821 } while (rtm->rtm_seq != myseq || rtm->rtm_pid != pid); 2822 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2823 if (rtm->rtm_addrs & RTA_DST) { 2824 sin6 = (struct sockaddr_in6 *) 2825 ((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2826 } 2827 if (rtm->rtm_addrs & RTA_GATEWAY) { 2828 *gw = sin6->sin6_addr; 2829 return gw; 2830 } 2831 return NULL; 2832 } 2833 2834 const char * 2835 inet6_n2p(p) 2836 const struct in6_addr *p; 2837 { 2838 static char buf[BUFSIZ]; 2839 2840 return inet_ntop(AF_INET6, (const void *)p, buf, sizeof(buf)); 2841 } 2842 2843 void 2844 ifrtdump(sig) 2845 int sig; 2846 { 2847 2848 ifdump(sig); 2849 rtdump(sig); 2850 } 2851 2852 void 2853 ifdump(sig) 2854 int sig; 2855 { 2856 struct ifc *ifcp; 2857 FILE *dump; 2858 int i; 2859 2860 if (sig == 0) 2861 dump = stderr; 2862 else 2863 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 2864 dump = stderr; 2865 2866 fprintf(dump, "%s: Interface Table Dump\n", hms()); 2867 fprintf(dump, " Number of interfaces: %d\n", nifc); 2868 for (i = 0; i < 2; i++) { 2869 fprintf(dump, " %sadvertising interfaces:\n", i ? "non-" : ""); 2870 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 2871 if (i == 0) { 2872 if ((ifcp->ifc_flags & IFF_UP) == 0) 2873 continue; 2874 if (iff_find(ifcp, 'N') != NULL) 2875 continue; 2876 } else { 2877 if (ifcp->ifc_flags & IFF_UP) 2878 continue; 2879 } 2880 ifdump0(dump, ifcp); 2881 } 2882 } 2883 fprintf(dump, "\n"); 2884 if (dump != stderr) 2885 fclose(dump); 2886 } 2887 2888 void 2889 ifdump0(dump, ifcp) 2890 FILE *dump; 2891 const struct ifc *ifcp; 2892 { 2893 struct ifac *ifa; 2894 struct iff *iffp; 2895 char buf[BUFSIZ]; 2896 const char *ft; 2897 int addr; 2898 2899 fprintf(dump, " %s: index(%d) flags(%s) addr(%s) mtu(%d) metric(%d)\n", 2900 ifcp->ifc_name, ifcp->ifc_index, ifflags(ifcp->ifc_flags), 2901 inet6_n2p(&ifcp->ifc_mylladdr), 2902 ifcp->ifc_mtu, ifcp->ifc_metric); 2903 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 2904 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 2905 inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr, 2906 buf, sizeof(buf)); 2907 fprintf(dump, "\t%s/%d -- %s\n", 2908 inet6_n2p(&ifa->ifa_addr), 2909 ifa->ifa_plen, buf); 2910 } else { 2911 fprintf(dump, "\t%s/%d\n", 2912 inet6_n2p(&ifa->ifa_addr), 2913 ifa->ifa_plen); 2914 } 2915 } 2916 if (ifcp->ifc_filter) { 2917 fprintf(dump, "\tFilter:"); 2918 for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { 2919 addr = 0; 2920 switch (iffp->iff_type) { 2921 case 'A': 2922 ft = "Aggregate"; addr++; break; 2923 case 'N': 2924 ft = "No-use"; break; 2925 case 'O': 2926 ft = "Advertise-only"; addr++; break; 2927 case 'T': 2928 ft = "Default-only"; break; 2929 case 'L': 2930 ft = "Listen-only"; addr++; break; 2931 default: 2932 snprintf(buf, sizeof(buf), "Unknown-%c", iffp->iff_type); 2933 ft = buf; 2934 addr++; 2935 break; 2936 } 2937 fprintf(dump, " %s", ft); 2938 if (addr) { 2939 fprintf(dump, "(%s/%d)", inet6_n2p(&iffp->iff_addr), 2940 iffp->iff_plen); 2941 } 2942 } 2943 fprintf(dump, "\n"); 2944 } 2945 } 2946 2947 void 2948 rtdump(sig) 2949 int sig; 2950 { 2951 struct riprt *rrt; 2952 char buf[BUFSIZ]; 2953 FILE *dump; 2954 time_t t, age; 2955 2956 if (sig == 0) 2957 dump = stderr; 2958 else 2959 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 2960 dump = stderr; 2961 2962 t = time(NULL); 2963 fprintf(dump, "\n%s: Routing Table Dump\n", hms()); 2964 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 2965 if (rrt->rrt_t == 0) 2966 age = 0; 2967 else 2968 age = t - rrt->rrt_t; 2969 inet_ntop(AF_INET6, (void *)&rrt->rrt_info.rip6_dest, 2970 buf, sizeof(buf)); 2971 fprintf(dump, " %s/%d if(%d:%s) gw(%s) [%d] age(%ld)", 2972 buf, rrt->rrt_info.rip6_plen, rrt->rrt_index, 2973 index2ifc[rrt->rrt_index]->ifc_name, 2974 inet6_n2p(&rrt->rrt_gw), 2975 rrt->rrt_info.rip6_metric, (long)age); 2976 if (rrt->rrt_info.rip6_tag) { 2977 fprintf(dump, " tag(0x%04x)", 2978 ntohs(rrt->rrt_info.rip6_tag) & 0xffff); 2979 } 2980 if (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR) 2981 fprintf(dump, " NOT-LL"); 2982 if (rrt->rrt_rflags & RRTF_NOADVERTISE) 2983 fprintf(dump, " NO-ADV"); 2984 fprintf(dump, "\n"); 2985 } 2986 fprintf(dump, "\n"); 2987 if (dump != stderr) 2988 fclose(dump); 2989 } 2990 2991 /* 2992 * Parse the -A (and -O) options and put corresponding filter object to the 2993 * specified interface structures. Each of the -A/O option has the following 2994 * syntax: -A 5f09:c400::/32,ef0,ef1 (aggregate) 2995 * -O 5f09:c400::/32,ef0,ef1 (only when match) 2996 */ 2997 void 2998 filterconfig() 2999 { 3000 int i; 3001 char *p, *ap, *iflp, *ifname; 3002 struct iff ftmp, *iff_obj; 3003 struct ifc *ifcp; 3004 struct riprt *rrt; 3005 #if 0 3006 struct in6_addr gw; 3007 #endif 3008 3009 for (i = 0; i < nfilter; i++) { 3010 ap = filter[i]; 3011 iflp = NULL; 3012 ifcp = NULL; 3013 if (filtertype[i] == 'N' || filtertype[i] == 'T') { 3014 iflp = ap; 3015 goto ifonly; 3016 } 3017 if ((p = index(ap, ',')) != NULL) { 3018 *p++ = '\0'; 3019 iflp = p; 3020 } 3021 if ((p = index(ap, '/')) == NULL) { 3022 fatal("no prefixlen specified for '%s'", ap); 3023 /*NOTREACHED*/ 3024 } 3025 *p++ = '\0'; 3026 if (inet_pton(AF_INET6, ap, &ftmp.iff_addr) != 1) { 3027 fatal("invalid prefix specified for '%s'", ap); 3028 /*NOTREACHED*/ 3029 } 3030 ftmp.iff_plen = atoi(p); 3031 ftmp.iff_next = NULL; 3032 applyplen(&ftmp.iff_addr, ftmp.iff_plen); 3033 ifonly: 3034 ftmp.iff_type = filtertype[i]; 3035 if (iflp == NULL || *iflp == '\0') { 3036 fatal("no interface specified for '%s'", ap); 3037 /*NOTREACHED*/ 3038 } 3039 /* parse the interface listing portion */ 3040 while (iflp) { 3041 ifname = iflp; 3042 if ((iflp = index(iflp, ',')) != NULL) 3043 *iflp++ = '\0'; 3044 ifcp = ifc_find(ifname); 3045 if (ifcp == NULL) { 3046 fatal("no interface %s exists", ifname); 3047 /*NOTREACHED*/ 3048 } 3049 iff_obj = (struct iff *)malloc(sizeof(struct iff)); 3050 if (iff_obj == NULL) { 3051 fatal("malloc of iff_obj"); 3052 /*NOTREACHED*/ 3053 } 3054 memcpy((void *)iff_obj, (void *)&ftmp, 3055 sizeof(struct iff)); 3056 /* link it to the interface filter */ 3057 iff_obj->iff_next = ifcp->ifc_filter; 3058 ifcp->ifc_filter = iff_obj; 3059 } 3060 3061 /* 3062 * -A: aggregate configuration. 3063 */ 3064 if (filtertype[i] != 'A') 3065 continue; 3066 /* put the aggregate to the kernel routing table */ 3067 rrt = (struct riprt *)malloc(sizeof(struct riprt)); 3068 if (rrt == NULL) { 3069 fatal("malloc: rrt"); 3070 /*NOTREACHED*/ 3071 } 3072 memset(rrt, 0, sizeof(struct riprt)); 3073 rrt->rrt_info.rip6_dest = ftmp.iff_addr; 3074 rrt->rrt_info.rip6_plen = ftmp.iff_plen; 3075 rrt->rrt_info.rip6_metric = 1; 3076 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 3077 rrt->rrt_gw = in6addr_loopback; 3078 rrt->rrt_flags = RTF_UP | RTF_REJECT; 3079 rrt->rrt_rflags = RRTF_AGGREGATE; 3080 rrt->rrt_t = 0; 3081 rrt->rrt_index = loopifindex; 3082 #if 0 3083 if (getroute(&rrt->rrt_info, &gw)) { 3084 #if 0 3085 /* 3086 * When the address has already been registered in the 3087 * kernel routing table, it should be removed 3088 */ 3089 delroute(&rrt->rrt_info, &gw); 3090 #else 3091 /* it is safer behavior */ 3092 errno = EINVAL; 3093 fatal("%s/%u already in routing table, " 3094 "cannot aggregate", 3095 inet6_n2p(&rrt->rrt_info.rip6_dest), 3096 rrt->rrt_info.rip6_plen); 3097 /*NOTREACHED*/ 3098 #endif 3099 } 3100 #endif 3101 /* Put the route to the list */ 3102 rrt->rrt_next = riprt; 3103 riprt = rrt; 3104 trace(1, "Aggregate: %s/%d for %s\n", 3105 inet6_n2p(&ftmp.iff_addr), ftmp.iff_plen, 3106 ifcp->ifc_name); 3107 /* Add this route to the kernel */ 3108 if (nflag) /* do not modify kernel routing table */ 3109 continue; 3110 addroute(rrt, &in6addr_loopback, loopifcp); 3111 } 3112 } 3113 3114 /***************** utility functions *****************/ 3115 3116 /* 3117 * Returns a pointer to ifac whose address and prefix length matches 3118 * with the address and prefix length specified in the arguments. 3119 */ 3120 struct ifac * 3121 ifa_match(ifcp, ia, plen) 3122 const struct ifc *ifcp; 3123 const struct in6_addr *ia; 3124 int plen; 3125 { 3126 struct ifac *ifa; 3127 3128 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 3129 if (IN6_ARE_ADDR_EQUAL(&ifa->ifa_addr, ia) && 3130 ifa->ifa_plen == plen) 3131 break; 3132 } 3133 return ifa; 3134 } 3135 3136 /* 3137 * Return a pointer to riprt structure whose address and prefix length 3138 * matches with the address and prefix length found in the argument. 3139 * Note: This is not a rtalloc(). Therefore exact match is necessary. 3140 */ 3141 struct riprt * 3142 rtsearch(np, prev_rrt) 3143 struct netinfo6 *np; 3144 struct riprt **prev_rrt; 3145 { 3146 struct riprt *rrt; 3147 3148 if (prev_rrt) 3149 *prev_rrt = NULL; 3150 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 3151 if (rrt->rrt_info.rip6_plen == np->rip6_plen && 3152 IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, 3153 &np->rip6_dest)) 3154 return rrt; 3155 if (prev_rrt) 3156 *prev_rrt = rrt; 3157 } 3158 if (prev_rrt) 3159 *prev_rrt = NULL; 3160 return 0; 3161 } 3162 3163 int 3164 sin6mask2len(sin6) 3165 const struct sockaddr_in6 *sin6; 3166 { 3167 3168 return mask2len(&sin6->sin6_addr, 3169 sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr)); 3170 } 3171 3172 int 3173 mask2len(addr, lenlim) 3174 const struct in6_addr *addr; 3175 int lenlim; 3176 { 3177 int i = 0, j; 3178 const u_char *p = (const u_char *)addr; 3179 3180 for (j = 0; j < lenlim; j++, p++) { 3181 if (*p != 0xff) 3182 break; 3183 i += 8; 3184 } 3185 if (j < lenlim) { 3186 switch (*p) { 3187 #define MASKLEN(m, l) case m: do { i += l; break; } while (0) 3188 MASKLEN(0xfe, 7); break; 3189 MASKLEN(0xfc, 6); break; 3190 MASKLEN(0xf8, 5); break; 3191 MASKLEN(0xf0, 4); break; 3192 MASKLEN(0xe0, 3); break; 3193 MASKLEN(0xc0, 2); break; 3194 MASKLEN(0x80, 1); break; 3195 #undef MASKLEN 3196 } 3197 } 3198 return i; 3199 } 3200 3201 void 3202 applymask(addr, mask) 3203 struct in6_addr *addr, *mask; 3204 { 3205 int i; 3206 u_long *p, *q; 3207 3208 p = (u_long *)addr; q = (u_long *)mask; 3209 for (i = 0; i < 4; i++) 3210 *p++ &= *q++; 3211 } 3212 3213 static const u_char plent[8] = { 3214 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 3215 }; 3216 3217 void 3218 applyplen(ia, plen) 3219 struct in6_addr *ia; 3220 int plen; 3221 { 3222 u_char *p; 3223 int i; 3224 3225 p = ia->s6_addr; 3226 for (i = 0; i < 16; i++) { 3227 if (plen <= 0) 3228 *p = 0; 3229 else if (plen < 8) 3230 *p &= plent[plen]; 3231 p++, plen -= 8; 3232 } 3233 } 3234 3235 static const int pl2m[9] = { 3236 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff 3237 }; 3238 3239 struct in6_addr * 3240 plen2mask(n) 3241 int n; 3242 { 3243 static struct in6_addr ia; 3244 u_char *p; 3245 int i; 3246 3247 memset(&ia, 0, sizeof(struct in6_addr)); 3248 p = (u_char *)&ia; 3249 for (i = 0; i < 16; i++, p++, n -= 8) { 3250 if (n >= 8) { 3251 *p = 0xff; 3252 continue; 3253 } 3254 *p = pl2m[n]; 3255 break; 3256 } 3257 return &ia; 3258 } 3259 3260 char * 3261 allocopy(p) 3262 char *p; 3263 { 3264 char *q = (char *)malloc(strlen(p) + 1); 3265 3266 strcpy(q, p); 3267 return q; 3268 } 3269 3270 char * 3271 hms() 3272 { 3273 static char buf[BUFSIZ]; 3274 time_t t; 3275 struct tm *tm; 3276 3277 t = time(NULL); 3278 if ((tm = localtime(&t)) == 0) { 3279 fatal("localtime"); 3280 /*NOTREACHED*/ 3281 } 3282 snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, 3283 tm->tm_sec); 3284 return buf; 3285 } 3286 3287 #define RIPRANDDEV 1.0 /* 30 +- 15, max - min = 30 */ 3288 3289 int 3290 ripinterval(timer) 3291 int timer; 3292 { 3293 double r = rand(); 3294 3295 interval = (int)(timer + timer * RIPRANDDEV * (r / RAND_MAX - 0.5)); 3296 nextalarm = time(NULL) + interval; 3297 return interval; 3298 } 3299 3300 time_t 3301 ripsuptrig() 3302 { 3303 time_t t; 3304 3305 double r = rand(); 3306 t = (int)(RIP_TRIG_INT6_MIN + 3307 (RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / RAND_MAX)); 3308 sup_trig_update = time(NULL) + t; 3309 return t; 3310 } 3311 3312 void 3313 #ifdef __STDC__ 3314 fatal(const char *fmt, ...) 3315 #else 3316 fatal(fmt, va_alist) 3317 char *fmt; 3318 va_dcl 3319 #endif 3320 { 3321 va_list ap; 3322 char buf[1024]; 3323 3324 #ifdef __STDC__ 3325 va_start(ap, fmt); 3326 #else 3327 va_start(ap); 3328 #endif 3329 vsnprintf(buf, sizeof(buf), fmt, ap); 3330 va_end(ap); 3331 perror(buf); 3332 syslog(LOG_ERR, "%s: %s", buf, strerror(errno)); 3333 rtdexit(); 3334 } 3335 3336 void 3337 #ifdef __STDC__ 3338 tracet(int level, const char *fmt, ...) 3339 #else 3340 tracet(level, fmt, va_alist) 3341 int level; 3342 char *fmt; 3343 va_dcl 3344 #endif 3345 { 3346 va_list ap; 3347 3348 if (level <= dflag) { 3349 #ifdef __STDC__ 3350 va_start(ap, fmt); 3351 #else 3352 va_start(ap); 3353 #endif 3354 fprintf(stderr, "%s: ", hms()); 3355 vfprintf(stderr, fmt, ap); 3356 va_end(ap); 3357 } 3358 if (dflag) { 3359 #ifdef __STDC__ 3360 va_start(ap, fmt); 3361 #else 3362 va_start(ap); 3363 #endif 3364 if (level > 0) 3365 vsyslog(LOG_DEBUG, fmt, ap); 3366 else 3367 vsyslog(LOG_WARNING, fmt, ap); 3368 va_end(ap); 3369 } 3370 } 3371 3372 void 3373 #ifdef __STDC__ 3374 trace(int level, const char *fmt, ...) 3375 #else 3376 trace(level, fmt, va_alist) 3377 int level; 3378 char *fmt; 3379 va_dcl 3380 #endif 3381 { 3382 va_list ap; 3383 3384 if (level <= dflag) { 3385 #ifdef __STDC__ 3386 va_start(ap, fmt); 3387 #else 3388 va_start(ap); 3389 #endif 3390 vfprintf(stderr, fmt, ap); 3391 va_end(ap); 3392 } 3393 if (dflag) { 3394 #ifdef __STDC__ 3395 va_start(ap, fmt); 3396 #else 3397 va_start(ap); 3398 #endif 3399 if (level > 0) 3400 vsyslog(LOG_DEBUG, fmt, ap); 3401 else 3402 vsyslog(LOG_WARNING, fmt, ap); 3403 va_end(ap); 3404 } 3405 } 3406 3407 unsigned int 3408 if_maxindex() 3409 { 3410 struct if_nameindex *p, *p0; 3411 unsigned int max = 0; 3412 3413 p0 = if_nameindex(); 3414 for (p = p0; p && p->if_index && p->if_name; p++) { 3415 if (max < p->if_index) 3416 max = p->if_index; 3417 } 3418 if_freenameindex(p0); 3419 return max; 3420 } 3421 3422 struct ifc * 3423 ifc_find(name) 3424 char *name; 3425 { 3426 struct ifc *ifcp; 3427 3428 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 3429 if (strcmp(name, ifcp->ifc_name) == 0) 3430 return ifcp; 3431 } 3432 return (struct ifc *)NULL; 3433 } 3434 3435 struct iff * 3436 iff_find(ifcp, type) 3437 struct ifc *ifcp; 3438 int type; 3439 { 3440 struct iff *iffp; 3441 3442 for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { 3443 if (iffp->iff_type == type) 3444 return iffp; 3445 } 3446 return NULL; 3447 } 3448 3449 void 3450 setindex2ifc(idx, ifcp) 3451 int idx; 3452 struct ifc *ifcp; 3453 { 3454 int n; 3455 struct ifc **p; 3456 3457 if (!index2ifc) { 3458 nindex2ifc = 5; /*initial guess*/ 3459 index2ifc = (struct ifc **) 3460 malloc(sizeof(*index2ifc) * nindex2ifc); 3461 if (index2ifc == NULL) { 3462 fatal("malloc"); 3463 /*NOTREACHED*/ 3464 } 3465 memset(index2ifc, 0, sizeof(*index2ifc) * nindex2ifc); 3466 } 3467 n = nindex2ifc; 3468 while (nindex2ifc <= idx) 3469 nindex2ifc *= 2; 3470 if (n != nindex2ifc) { 3471 p = (struct ifc **)realloc(index2ifc, 3472 sizeof(*index2ifc) * nindex2ifc); 3473 if (p == NULL) { 3474 fatal("realloc"); 3475 /*NOTREACHED*/ 3476 } 3477 memset(p + n, 0, sizeof(*index2ifc) * (nindex2ifc - n)); 3478 index2ifc = p; 3479 } 3480 index2ifc[idx] = ifcp; 3481 } 3482