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