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