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