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