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