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