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