1 /* $NetBSD: route6d.c,v 1.67 2013/04/15 07:58:35 kardel 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.67 2013/04/15 07:58:35 kardel 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_RESOLVE: 1601 case RTM_GET: 1602 case RTM_LOCK: 1603 /* nothing to be done here */ 1604 trace(1, "\tnothing to be done, ignored\n"); 1605 continue; 1606 } 1607 1608 #if 0 1609 if (rta[RTAX_DST] == NULL) { 1610 trace(1, "\tno destination, ignored\n"); 1611 continue; 1612 } 1613 if (rta[RTAX_DST]->sin6_family != AF_INET6) { 1614 trace(1, "\taf mismatch, ignored\n"); 1615 continue; 1616 } 1617 if (IN6_IS_ADDR_LINKLOCAL(&rta[RTAX_DST]->sin6_addr)) { 1618 trace(1, "\tlinklocal destination, ignored\n"); 1619 continue; 1620 } 1621 if (IN6_ARE_ADDR_EQUAL(&rta[RTAX_DST]->sin6_addr, &in6addr_loopback)) { 1622 trace(1, "\tloopback destination, ignored\n"); 1623 continue; /* Loopback */ 1624 } 1625 if (IN6_IS_ADDR_MULTICAST(&rta[RTAX_DST]->sin6_addr)) { 1626 trace(1, "\tmulticast destination, ignored\n"); 1627 continue; 1628 } 1629 #endif 1630 1631 /* hard ones */ 1632 switch (((struct rt_msghdr *)p)->rtm_type) { 1633 case RTM_NEWADDR: 1634 case RTM_IFINFO: 1635 case RTM_ADD: 1636 case RTM_LOSING: 1637 case RTM_MISS: 1638 case RTM_RESOLVE: 1639 case RTM_GET: 1640 case RTM_LOCK: 1641 /* should already be handled */ 1642 fatal("rtrecv: never reach here"); 1643 /*NOTREACHED*/ 1644 case RTM_DELETE: 1645 if (!rta[RTAX_DST] || !rta[RTAX_GATEWAY]) { 1646 trace(1, "\tsome of dst/gw/netamsk are " 1647 "unavailable, ignored\n"); 1648 break; 1649 } 1650 if ((rtm->rtm_flags & RTF_HOST) != 0) { 1651 mask.sin6_len = sizeof(mask); 1652 memset(&mask.sin6_addr, 0xff, 1653 sizeof(mask.sin6_addr)); 1654 rta[RTAX_NETMASK] = &mask; 1655 } else if (!rta[RTAX_NETMASK]) { 1656 trace(1, "\tsome of dst/gw/netamsk are " 1657 "unavailable, ignored\n"); 1658 break; 1659 } 1660 if (rt_del(rta[RTAX_DST], rta[RTAX_GATEWAY], 1661 rta[RTAX_NETMASK]) == 0) { 1662 rtable++; /*just to be sure*/ 1663 } 1664 break; 1665 case RTM_CHANGE: 1666 case RTM_REDIRECT: 1667 trace(1, "\tnot supported yet, ignored\n"); 1668 break; 1669 case RTM_DELADDR: 1670 if (!rta[RTAX_NETMASK] || !rta[RTAX_IFA]) { 1671 trace(1, "\tno netmask or ifa given, ignored\n"); 1672 break; 1673 } 1674 if (ifam->ifam_index < nindex2ifc) 1675 ifcp = index2ifc[ifam->ifam_index]; 1676 else 1677 ifcp = NULL; 1678 if (!ifcp) { 1679 trace(1, "\tinvalid ifam_index %d, ignored\n", 1680 ifam->ifam_index); 1681 break; 1682 } 1683 if (!rt_deladdr(ifcp, rta[RTAX_IFA], rta[RTAX_NETMASK])) 1684 iface++; 1685 break; 1686 case RTM_OLDADD: 1687 case RTM_OLDDEL: 1688 trace(1, "\tnot supported yet, ignored\n"); 1689 break; 1690 } 1691 1692 } 1693 1694 if (iface) { 1695 trace(1, "rtsock: reconfigure interfaces, refresh interface routes\n"); 1696 ifconfig(); 1697 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) 1698 if (ifcp->ifc_cflags & IFC_CHANGED) { 1699 if (ifrt(ifcp, 1)) { 1700 for (ic = ifc; ic; ic = ic->ifc_next) { 1701 if (ifcp->ifc_index == ic->ifc_index) 1702 continue; 1703 if (ic->ifc_flags & IFF_UP) 1704 ripsend(ic, &ic->ifc_ripsin, 1705 RRTF_CHANGED); 1706 } 1707 /* Reset the flag */ 1708 for (rrt = riprt; rrt; rrt = rrt->rrt_next) 1709 rrt->rrt_rflags &= ~RRTF_CHANGED; 1710 } 1711 ifcp->ifc_cflags &= ~IFC_CHANGED; 1712 } 1713 } 1714 if (rtable) { 1715 trace(1, "rtsock: read routing table again\n"); 1716 krtread(1); 1717 } 1718 } 1719 1720 /* 1721 * remove specified route from the internal routing table. 1722 */ 1723 static int 1724 rt_del(const struct sockaddr_in6 *sdst, const struct sockaddr_in6 *sgw, 1725 const struct sockaddr_in6 *smask) 1726 { 1727 const struct in6_addr *dst = NULL; 1728 const struct in6_addr *gw = NULL; 1729 int prefix; 1730 struct netinfo6 ni6; 1731 struct riprt *rrt = NULL; 1732 time_t t_lifetime; 1733 1734 if (sdst->sin6_family != AF_INET6) { 1735 trace(1, "\tother AF, ignored\n"); 1736 return -1; 1737 } 1738 if (IN6_IS_ADDR_LINKLOCAL(&sdst->sin6_addr) 1739 || IN6_ARE_ADDR_EQUAL(&sdst->sin6_addr, &in6addr_loopback) 1740 || IN6_IS_ADDR_MULTICAST(&sdst->sin6_addr)) { 1741 trace(1, "\taddress %s not interesting, ignored\n", 1742 inet6_n2p(&sdst->sin6_addr)); 1743 return -1; 1744 } 1745 dst = &sdst->sin6_addr; 1746 if (sgw->sin6_family == AF_INET6) { 1747 /* easy case */ 1748 gw = &sgw->sin6_addr; 1749 prefix = sin6mask2len(smask); 1750 } else if (sgw->sin6_family == AF_LINK) { 1751 /* 1752 * Interface route... a hard case. We need to get the prefix 1753 * length from the kernel, but we now are parsing rtmsg. 1754 * We'll purge matching routes from my list, then get the 1755 * fresh list. 1756 */ 1757 struct riprt *longest; 1758 trace(1, "\t%s is an interface route, guessing prefixlen\n", 1759 inet6_n2p(dst)); 1760 longest = NULL; 1761 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 1762 if (IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, 1763 &sdst->sin6_addr) 1764 && IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw)) { 1765 if (!longest 1766 || longest->rrt_info.rip6_plen < 1767 rrt->rrt_info.rip6_plen) { 1768 longest = rrt; 1769 } 1770 } 1771 } 1772 rrt = longest; 1773 if (!rrt) { 1774 trace(1, "\tno matching interface route found\n"); 1775 return -1; 1776 } 1777 gw = &in6addr_loopback; 1778 prefix = rrt->rrt_info.rip6_plen; 1779 } else { 1780 trace(1, "\tunsupported af: (gw=%d)\n", sgw->sin6_family); 1781 return -1; 1782 } 1783 1784 trace(1, "\tdeleting %s/%d ", inet6_n2p(dst), prefix); 1785 trace(1, "gw %s\n", inet6_n2p(gw)); 1786 t_lifetime = time(NULL) - RIP_LIFETIME; 1787 /* age route for interface address */ 1788 memset(&ni6, 0, sizeof(ni6)); 1789 ni6.rip6_dest = *dst; 1790 ni6.rip6_plen = prefix; 1791 applyplen(&ni6.rip6_dest, ni6.rip6_plen); /*to be sure*/ 1792 trace(1, "\tfind route %s/%d\n", inet6_n2p(&ni6.rip6_dest), 1793 ni6.rip6_plen); 1794 if (!rrt && (rrt = rtsearch(&ni6, NULL)) == NULL) { 1795 trace(1, "\tno route found\n"); 1796 return -1; 1797 } 1798 #if 0 1799 if ((rrt->rrt_flags & RTF_STATIC) == 0) { 1800 trace(1, "\tyou can delete static routes only\n"); 1801 } else 1802 #endif 1803 if (!IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, gw)) { 1804 trace(1, "\tgw mismatch: %s <-> ", 1805 inet6_n2p(&rrt->rrt_gw)); 1806 trace(1, "%s\n", inet6_n2p(gw)); 1807 } else { 1808 trace(1, "\troute found, age it\n"); 1809 if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) { 1810 rrt->rrt_t = t_lifetime; 1811 rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 1812 } 1813 } 1814 return 0; 1815 } 1816 1817 /* 1818 * remove specified address from internal interface/routing table. 1819 */ 1820 static int 1821 rt_deladdr(struct ifc *ifcp, const struct sockaddr_in6 *sifa, 1822 const struct sockaddr_in6 *smask) 1823 { 1824 const struct in6_addr *addr = NULL; 1825 int prefix; 1826 struct ifac *ifa = NULL; 1827 struct netinfo6 ni6; 1828 struct riprt *rrt = NULL; 1829 time_t t_lifetime; 1830 int updated = 0; 1831 1832 if (sifa->sin6_family != AF_INET6) { 1833 trace(1, "\tother AF, ignored\n"); 1834 return -1; 1835 } 1836 addr = &sifa->sin6_addr; 1837 prefix = sin6mask2len(smask); 1838 1839 trace(1, "\tdeleting %s/%d from %s\n", 1840 inet6_n2p(addr), prefix, ifcp->ifc_name); 1841 ifa = ifa_match(ifcp, addr, prefix); 1842 if (!ifa) { 1843 trace(1, "\tno matching ifa found for %s/%d on %s\n", 1844 inet6_n2p(addr), prefix, ifcp->ifc_name); 1845 return -1; 1846 } 1847 if (ifa->ifa_conf != ifcp) { 1848 trace(1, "\taddress table corrupt: back pointer does not match " 1849 "(%s != %s)\n", 1850 ifcp->ifc_name, ifa->ifa_conf->ifc_name); 1851 return -1; 1852 } 1853 /* remove ifa from interface */ 1854 if (ifcp->ifc_addr == ifa) 1855 ifcp->ifc_addr = ifa->ifa_next; 1856 else { 1857 struct ifac *p; 1858 for (p = ifcp->ifc_addr; p; p = p->ifa_next) { 1859 if (p->ifa_next == ifa) { 1860 p->ifa_next = ifa->ifa_next; 1861 break; 1862 } 1863 } 1864 } 1865 ifa->ifa_next = NULL; 1866 ifa->ifa_conf = NULL; 1867 t_lifetime = time(NULL) - RIP_LIFETIME; 1868 /* age route for interface address */ 1869 memset(&ni6, 0, sizeof(ni6)); 1870 ni6.rip6_dest = ifa->ifa_addr; 1871 ni6.rip6_plen = ifa->ifa_plen; 1872 applyplen(&ni6.rip6_dest, ni6.rip6_plen); 1873 trace(1, "\tfind interface route %s/%d on %d\n", 1874 inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen, ifcp->ifc_index); 1875 if ((rrt = rtsearch(&ni6, NULL)) != NULL) { 1876 struct in6_addr none; 1877 memset(&none, 0, sizeof(none)); 1878 if (rrt->rrt_index == ifcp->ifc_index && 1879 (IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &none) || 1880 IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw))) { 1881 trace(1, "\troute found, age it\n"); 1882 if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) { 1883 rrt->rrt_t = t_lifetime; 1884 rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 1885 } 1886 updated++; 1887 } else { 1888 trace(1, "\tnon-interface route found: %s/%d on %d\n", 1889 inet6_n2p(&rrt->rrt_info.rip6_dest), 1890 rrt->rrt_info.rip6_plen, 1891 rrt->rrt_index); 1892 } 1893 } else 1894 trace(1, "\tno interface route found\n"); 1895 /* age route for p2p destination */ 1896 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 1897 memset(&ni6, 0, sizeof(ni6)); 1898 ni6.rip6_dest = ifa->ifa_raddr; 1899 ni6.rip6_plen = 128; 1900 applyplen(&ni6.rip6_dest, ni6.rip6_plen); /*to be sure*/ 1901 trace(1, "\tfind p2p route %s/%d on %d\n", 1902 inet6_n2p(&ni6.rip6_dest), ni6.rip6_plen, 1903 ifcp->ifc_index); 1904 if ((rrt = rtsearch(&ni6, NULL)) != NULL) { 1905 if (rrt->rrt_index == ifcp->ifc_index && 1906 IN6_ARE_ADDR_EQUAL(&rrt->rrt_gw, &ifa->ifa_addr)) { 1907 trace(1, "\troute found, age it\n"); 1908 if (rrt->rrt_t == 0 || rrt->rrt_t > t_lifetime) { 1909 rrt->rrt_t = t_lifetime; 1910 rrt->rrt_info.rip6_metric = 1911 HOPCNT_INFINITY6; 1912 updated++; 1913 } 1914 } else { 1915 trace(1, "\tnon-p2p route found: %s/%d on %d\n", 1916 inet6_n2p(&rrt->rrt_info.rip6_dest), 1917 rrt->rrt_info.rip6_plen, 1918 rrt->rrt_index); 1919 } 1920 } else 1921 trace(1, "\tno p2p route found\n"); 1922 } 1923 return updated ? 0 : -1; 1924 } 1925 1926 /* 1927 * Get each interface address and put those interface routes to the route 1928 * list. 1929 */ 1930 static int 1931 ifrt(struct ifc *ifcp, int again) 1932 { 1933 struct ifac *ifa; 1934 struct riprt *rrt = NULL, *search_rrt, *prev_rrt, *loop_rrt; 1935 struct netinfo6 *np; 1936 time_t t_lifetime; 1937 int need_trigger = 0; 1938 1939 #if 0 1940 if (ifcp->ifc_flags & IFF_LOOPBACK) 1941 return 0; /* ignore loopback */ 1942 #endif 1943 1944 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 1945 ifrt_p2p(ifcp, again); 1946 return 0; 1947 } 1948 1949 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 1950 if (IN6_IS_ADDR_LINKLOCAL(&ifa->ifa_addr)) { 1951 #if 0 1952 trace(1, "route: %s on %s: " 1953 "skip linklocal interface address\n", 1954 inet6_n2p(&ifa->ifa_addr), ifcp->ifc_name); 1955 #endif 1956 continue; 1957 } 1958 if (IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_addr)) { 1959 #if 0 1960 trace(1, "route: %s: skip unspec interface address\n", 1961 ifcp->ifc_name); 1962 #endif 1963 continue; 1964 } 1965 if (IN6_IS_ADDR_LOOPBACK(&ifa->ifa_addr)) { 1966 #if 0 1967 trace(1, "route: %s: skip loopback address\n", 1968 ifcp->ifc_name); 1969 #endif 1970 continue; 1971 } 1972 if (ifcp->ifc_flags & IFF_UP) { 1973 if ((rrt = MALLOC(struct riprt)) == NULL) 1974 fatal("malloc: struct riprt"); 1975 memset(rrt, 0, sizeof(*rrt)); 1976 rrt->rrt_same = NULL; 1977 rrt->rrt_index = ifcp->ifc_index; 1978 rrt->rrt_t = 0; /* don't age */ 1979 rrt->rrt_info.rip6_dest = ifa->ifa_addr; 1980 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 1981 rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric; 1982 rrt->rrt_info.rip6_plen = ifa->ifa_plen; 1983 if (ifa->ifa_plen == 128) 1984 rrt->rrt_flags = RTF_HOST; 1985 else 1986 rrt->rrt_flags = RTF_CLONING; 1987 rrt->rrt_rflags |= RRTF_CHANGED; 1988 applyplen(&rrt->rrt_info.rip6_dest, ifa->ifa_plen); 1989 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 1990 rrt->rrt_gw = ifa->ifa_addr; 1991 np = &rrt->rrt_info; 1992 search_rrt = rtsearch(np, &prev_rrt); 1993 if (search_rrt != NULL) { 1994 if (search_rrt->rrt_info.rip6_metric <= 1995 rrt->rrt_info.rip6_metric) { 1996 /* Already have better route */ 1997 if (!again) { 1998 trace(1, "route: %s/%d: " 1999 "already registered (%s)\n", 2000 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2001 ifcp->ifc_name); 2002 } 2003 goto next; 2004 } 2005 2006 if (prev_rrt) 2007 prev_rrt->rrt_next = rrt->rrt_next; 2008 else 2009 riprt = rrt->rrt_next; 2010 delroute(&rrt->rrt_info, &rrt->rrt_gw); 2011 } 2012 /* Attach the route to the list */ 2013 trace(1, "route: %s/%d: register route (%s)\n", 2014 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2015 ifcp->ifc_name); 2016 rrt->rrt_next = riprt; 2017 riprt = rrt; 2018 addroute(rrt, &rrt->rrt_gw, ifcp); 2019 rrt = NULL; 2020 sendrequest(ifcp); 2021 ripsend(ifcp, &ifcp->ifc_ripsin, 0); 2022 need_trigger = 1; 2023 } else { 2024 for (loop_rrt = riprt; loop_rrt; loop_rrt = loop_rrt->rrt_next) { 2025 if (loop_rrt->rrt_index == ifcp->ifc_index) { 2026 t_lifetime = time(NULL) - RIP_LIFETIME; 2027 if (loop_rrt->rrt_t == 0 || loop_rrt->rrt_t > t_lifetime) { 2028 loop_rrt->rrt_t = t_lifetime; 2029 loop_rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 2030 loop_rrt->rrt_rflags |= RRTF_CHANGED; 2031 need_trigger = 1; 2032 } 2033 } 2034 } 2035 } 2036 next: 2037 if (rrt) 2038 free(rrt); 2039 } 2040 return need_trigger; 2041 } 2042 2043 /* 2044 * there are couple of p2p interface routing models. "behavior" lets 2045 * you pick one. it looks that gated behavior fits best with BSDs, 2046 * since BSD kernels do not look at prefix length on p2p interfaces. 2047 */ 2048 static void 2049 ifrt_p2p(struct ifc *ifcp, int again) 2050 { 2051 struct ifac *ifa; 2052 struct riprt *rrt, *orrt, *prevrrt; 2053 struct netinfo6 *np; 2054 struct in6_addr addr, dest; 2055 int advert, ignore, i; 2056 #define P2PADVERT_NETWORK 1 2057 #define P2PADVERT_ADDR 2 2058 #define P2PADVERT_DEST 4 2059 #define P2PADVERT_MAX 4 2060 #define CISCO 0 2061 #define GATED 1 2062 #define ROUTE6D 2 2063 #define BEHAVIOR GATED 2064 const char *category = ""; 2065 const char *noadv; 2066 2067 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 2068 addr = ifa->ifa_addr; 2069 dest = ifa->ifa_raddr; 2070 applyplen(&addr, ifa->ifa_plen); 2071 applyplen(&dest, ifa->ifa_plen); 2072 advert = ignore = 0; 2073 #if BEHAVIOR == CISCO 2074 /* 2075 * honor addr/plen, just like normal shared medium 2076 * interface. this may cause trouble if you reuse 2077 * addr/plen on other interfaces. 2078 * 2079 * advertise addr/plen. 2080 */ 2081 advert |= P2PADVERT_NETWORK; 2082 #endif 2083 #if BEHAVIOR == GATED 2084 /* 2085 * prefixlen on p2p interface is meaningless. 2086 * advertise addr/128 and dest/128. 2087 * 2088 * do not install network route to route6d routing 2089 * table (if we do, it would prevent route installation 2090 * for other p2p interface that shares addr/plen). 2091 * 2092 * XXX what should we do if dest is ::? it will not 2093 * get announced anyways (see following filter), 2094 * but we need to think. 2095 */ 2096 advert |= P2PADVERT_ADDR; 2097 advert |= P2PADVERT_DEST; 2098 ignore |= P2PADVERT_NETWORK; 2099 #endif 2100 #if BEHAVIOR == ROUTE6D 2101 /* 2102 * just for testing. actually the code is redundant 2103 * given the current p2p interface address assignment 2104 * rule for kame kernel. 2105 * 2106 * intent: 2107 * A/n -> announce A/n 2108 * A B/n, A and B share prefix -> A/n (= B/n) 2109 * A B/n, do not share prefix -> A/128 and B/128 2110 * actually, A/64 and A B/128 are the only cases 2111 * permitted by the kernel: 2112 * A/64 -> A/64 2113 * A B/128 -> A/128 and B/128 2114 */ 2115 if (!IN6_IS_ADDR_UNSPECIFIED(&ifa->ifa_raddr)) { 2116 if (IN6_ARE_ADDR_EQUAL(&addr, &dest)) 2117 advert |= P2PADVERT_NETWORK; 2118 else { 2119 advert |= P2PADVERT_ADDR; 2120 advert |= P2PADVERT_DEST; 2121 ignore |= P2PADVERT_NETWORK; 2122 } 2123 } else 2124 advert |= P2PADVERT_NETWORK; 2125 #endif 2126 2127 for (i = 1; i <= P2PADVERT_MAX; i *= 2) { 2128 if ((ignore & i) != 0) 2129 continue; 2130 if ((rrt = MALLOC(struct riprt)) == NULL) { 2131 fatal("malloc: struct riprt"); 2132 /*NOTREACHED*/ 2133 } 2134 memset(rrt, 0, sizeof(*rrt)); 2135 rrt->rrt_same = NULL; 2136 rrt->rrt_index = ifcp->ifc_index; 2137 rrt->rrt_t = 0; /* don't age */ 2138 switch (i) { 2139 case P2PADVERT_NETWORK: 2140 rrt->rrt_info.rip6_dest = ifa->ifa_addr; 2141 rrt->rrt_info.rip6_plen = ifa->ifa_plen; 2142 applyplen(&rrt->rrt_info.rip6_dest, 2143 ifa->ifa_plen); 2144 category = "network"; 2145 break; 2146 case P2PADVERT_ADDR: 2147 rrt->rrt_info.rip6_dest = ifa->ifa_addr; 2148 rrt->rrt_info.rip6_plen = 128; 2149 rrt->rrt_gw = in6addr_loopback; 2150 category = "addr"; 2151 break; 2152 case P2PADVERT_DEST: 2153 rrt->rrt_info.rip6_dest = ifa->ifa_raddr; 2154 rrt->rrt_info.rip6_plen = 128; 2155 rrt->rrt_gw = ifa->ifa_addr; 2156 category = "dest"; 2157 break; 2158 } 2159 if (IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_info.rip6_dest) || 2160 IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_info.rip6_dest)) { 2161 #if 0 2162 trace(1, "route: %s: skip unspec/linklocal " 2163 "(%s on %s)\n", category, ifcp->ifc_name); 2164 #endif 2165 free(rrt); 2166 continue; 2167 } 2168 if ((advert & i) == 0) { 2169 rrt->rrt_rflags |= RRTF_NOADVERTISE; 2170 noadv = ", NO-ADV"; 2171 } else 2172 noadv = ""; 2173 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 2174 rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric; 2175 np = &rrt->rrt_info; 2176 orrt = rtsearch(np, &prevrrt); 2177 if (!orrt) { 2178 /* Attach the route to the list */ 2179 trace(1, "route: %s/%d: register route " 2180 "(%s on %s%s)\n", 2181 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2182 category, ifcp->ifc_name, noadv); 2183 rrt->rrt_next = riprt; 2184 riprt = rrt; 2185 } else if (rrt->rrt_index != orrt->rrt_index || 2186 rrt->rrt_info.rip6_metric != orrt->rrt_info.rip6_metric) { 2187 /* swap route */ 2188 rrt->rrt_next = orrt->rrt_next; 2189 if (prevrrt) 2190 prevrrt->rrt_next = rrt; 2191 else 2192 riprt = rrt; 2193 free(orrt); 2194 2195 trace(1, "route: %s/%d: update (%s on %s%s)\n", 2196 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2197 category, ifcp->ifc_name, noadv); 2198 } else { 2199 /* Already found */ 2200 if (!again) { 2201 trace(1, "route: %s/%d: " 2202 "already registered (%s on %s%s)\n", 2203 inet6_n2p(&np->rip6_dest), 2204 np->rip6_plen, category, 2205 ifcp->ifc_name, noadv); 2206 } 2207 free(rrt); 2208 } 2209 } 2210 } 2211 #undef P2PADVERT_NETWORK 2212 #undef P2PADVERT_ADDR 2213 #undef P2PADVERT_DEST 2214 #undef P2PADVERT_MAX 2215 } 2216 2217 static int 2218 getifmtu(int ifindex) 2219 { 2220 int mib[6]; 2221 char *buf; 2222 size_t msize; 2223 struct if_msghdr *ifm; 2224 int mtu; 2225 2226 mib[0] = CTL_NET; 2227 mib[1] = PF_ROUTE; 2228 mib[2] = 0; 2229 mib[3] = AF_INET6; 2230 mib[4] = NET_RT_IFLIST; 2231 mib[5] = ifindex; 2232 if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0) { 2233 fatal("sysctl estimate NET_RT_IFLIST"); 2234 /*NOTREACHED*/ 2235 } 2236 if ((buf = malloc(msize)) == NULL) { 2237 fatal("malloc"); 2238 /*NOTREACHED*/ 2239 } 2240 if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0) { 2241 fatal("sysctl NET_RT_IFLIST"); 2242 /*NOTREACHED*/ 2243 } 2244 ifm = (struct if_msghdr *)buf; 2245 mtu = ifm->ifm_data.ifi_mtu; 2246 #ifdef __FreeBSD__ 2247 if (ifindex != ifm->ifm_index) { 2248 fatal("ifindex does not match with ifm_index"); 2249 /*NOTREACHED*/ 2250 } 2251 #endif 2252 free(buf); 2253 return mtu; 2254 } 2255 2256 static const char * 2257 rttypes(struct rt_msghdr *rtm) 2258 { 2259 #define RTTYPE(s, f) \ 2260 do { \ 2261 if (rtm->rtm_type == (f)) \ 2262 return (s); \ 2263 } while (0) 2264 RTTYPE("ADD", RTM_ADD); 2265 RTTYPE("DELETE", RTM_DELETE); 2266 RTTYPE("CHANGE", RTM_CHANGE); 2267 RTTYPE("GET", RTM_GET); 2268 RTTYPE("LOSING", RTM_LOSING); 2269 RTTYPE("REDIRECT", RTM_REDIRECT); 2270 RTTYPE("MISS", RTM_MISS); 2271 RTTYPE("LOCK", RTM_LOCK); 2272 RTTYPE("OLDADD", RTM_OLDADD); 2273 RTTYPE("OLDDEL", RTM_OLDDEL); 2274 RTTYPE("RESOLVE", RTM_RESOLVE); 2275 RTTYPE("NEWADDR", RTM_NEWADDR); 2276 RTTYPE("DELADDR", RTM_DELADDR); 2277 RTTYPE("IFINFO", RTM_IFINFO); 2278 #ifdef RTM_OLDADD 2279 RTTYPE("OLDADD", RTM_OLDADD); 2280 #endif 2281 #ifdef RTM_OLDDEL 2282 RTTYPE("OLDDEL", RTM_OLDDEL); 2283 #endif 2284 #ifdef RTM_OIFINFO 2285 RTTYPE("OIFINFO", RTM_OIFINFO); 2286 #endif 2287 #ifdef RTM_IFANNOUNCE 2288 RTTYPE("IFANNOUNCE", RTM_IFANNOUNCE); 2289 #endif 2290 #ifdef RTM_NEWMADDR 2291 RTTYPE("NEWMADDR", RTM_NEWMADDR); 2292 #endif 2293 #ifdef RTM_DELMADDR 2294 RTTYPE("DELMADDR", RTM_DELMADDR); 2295 #endif 2296 #undef RTTYPE 2297 return NULL; 2298 } 2299 2300 static const char * 2301 rtflags(struct rt_msghdr *rtm) 2302 { 2303 static char buf[BUFSIZ]; 2304 2305 /* 2306 * letter conflict should be okay. painful when *BSD diverges... 2307 */ 2308 strlcpy(buf, "", sizeof(buf)); 2309 #define RTFLAG(s, f) \ 2310 do { \ 2311 if (rtm->rtm_flags & (f)) \ 2312 strlcat(buf, (s), sizeof(buf)); \ 2313 } while (0) 2314 RTFLAG("U", RTF_UP); 2315 RTFLAG("G", RTF_GATEWAY); 2316 RTFLAG("H", RTF_HOST); 2317 RTFLAG("R", RTF_REJECT); 2318 RTFLAG("D", RTF_DYNAMIC); 2319 RTFLAG("M", RTF_MODIFIED); 2320 RTFLAG("d", RTF_DONE); 2321 #ifdef RTF_MASK 2322 RTFLAG("m", RTF_MASK); 2323 #endif 2324 RTFLAG("C", RTF_CLONING); 2325 #ifdef RTF_CLONED 2326 RTFLAG("c", RTF_CLONED); 2327 #endif 2328 #ifdef RTF_PRCLONING 2329 RTFLAG("c", RTF_PRCLONING); 2330 #endif 2331 #ifdef RTF_WASCLONED 2332 RTFLAG("W", RTF_WASCLONED); 2333 #endif 2334 RTFLAG("X", RTF_XRESOLVE); 2335 RTFLAG("L", RTF_LLINFO); 2336 RTFLAG("S", RTF_STATIC); 2337 RTFLAG("B", RTF_BLACKHOLE); 2338 #ifdef RTF_PROTO3 2339 RTFLAG("3", RTF_PROTO3); 2340 #endif 2341 RTFLAG("2", RTF_PROTO2); 2342 RTFLAG("1", RTF_PROTO1); 2343 #ifdef RTF_BROADCAST 2344 RTFLAG("b", RTF_BROADCAST); 2345 #endif 2346 #ifdef RTF_DEFAULT 2347 RTFLAG("d", RTF_DEFAULT); 2348 #endif 2349 #ifdef RTF_ISAROUTER 2350 RTFLAG("r", RTF_ISAROUTER); 2351 #endif 2352 #ifdef RTF_TUNNEL 2353 RTFLAG("T", RTF_TUNNEL); 2354 #endif 2355 #ifdef RTF_AUTH 2356 RTFLAG("A", RTF_AUTH); 2357 #endif 2358 #ifdef RTF_CRYPT 2359 RTFLAG("E", RTF_CRYPT); 2360 #endif 2361 #undef RTFLAG 2362 return buf; 2363 } 2364 2365 static const char * 2366 ifflags(int flags) 2367 { 2368 static char buf[BUFSIZ]; 2369 2370 strlcpy(buf, "", sizeof(buf)); 2371 #define IFFLAG(s, f) \ 2372 do { \ 2373 if (flags & (f)) { \ 2374 if (buf[0]) \ 2375 strlcat(buf, ",", sizeof(buf)); \ 2376 strlcat(buf, (s), sizeof(buf)); \ 2377 } \ 2378 } while (0) 2379 IFFLAG("UP", IFF_UP); 2380 IFFLAG("BROADCAST", IFF_BROADCAST); 2381 IFFLAG("DEBUG", IFF_DEBUG); 2382 IFFLAG("LOOPBACK", IFF_LOOPBACK); 2383 IFFLAG("POINTOPOINT", IFF_POINTOPOINT); 2384 #ifdef IFF_NOTRAILERS 2385 IFFLAG("NOTRAILERS", IFF_NOTRAILERS); 2386 #endif 2387 #ifdef IFF_SMART 2388 IFFLAG("SMART", IFF_SMART); 2389 #endif 2390 IFFLAG("RUNNING", IFF_RUNNING); 2391 IFFLAG("NOARP", IFF_NOARP); 2392 IFFLAG("PROMISC", IFF_PROMISC); 2393 IFFLAG("ALLMULTI", IFF_ALLMULTI); 2394 IFFLAG("OACTIVE", IFF_OACTIVE); 2395 IFFLAG("SIMPLEX", IFF_SIMPLEX); 2396 IFFLAG("LINK0", IFF_LINK0); 2397 IFFLAG("LINK1", IFF_LINK1); 2398 IFFLAG("LINK2", IFF_LINK2); 2399 IFFLAG("MULTICAST", IFF_MULTICAST); 2400 #undef IFFLAG 2401 return buf; 2402 } 2403 2404 static void 2405 krtread(int again) 2406 { 2407 int mib[6]; 2408 size_t msize; 2409 char *buf = NULL, *p, *lim; 2410 struct rt_msghdr *rtm; 2411 int retry; 2412 const char *errmsg; 2413 2414 retry = 0; 2415 buf = NULL; 2416 mib[0] = CTL_NET; 2417 mib[1] = PF_ROUTE; 2418 mib[2] = 0; 2419 mib[3] = AF_INET6; /* Address family */ 2420 mib[4] = NET_RT_DUMP; /* Dump the kernel routing table */ 2421 mib[5] = 0; /* No flags */ 2422 do { 2423 retry++; 2424 errmsg = NULL; 2425 if (buf) { 2426 free(buf); 2427 buf = NULL; 2428 } 2429 if (sysctl(mib, 6, NULL, &msize, NULL, 0) < 0) { 2430 errmsg = "sysctl estimate"; 2431 continue; 2432 } 2433 if ((buf = malloc(msize)) == NULL) { 2434 errmsg = "malloc"; 2435 continue; 2436 } 2437 if (sysctl(mib, 6, buf, &msize, NULL, 0) < 0) { 2438 errmsg = "sysctl NET_RT_DUMP"; 2439 continue; 2440 } 2441 } while (retry < 5 && errmsg != NULL); 2442 if (errmsg) { 2443 fatal("%s (with %d retries, msize=%lu)", errmsg, retry, 2444 (u_long)msize); 2445 /*NOTREACHED*/ 2446 } else if (1 < retry) 2447 syslog(LOG_INFO, "NET_RT_DUMP %d retries", retry); 2448 2449 lim = buf + msize; 2450 for (p = buf; p < lim; p += rtm->rtm_msglen) { 2451 rtm = (struct rt_msghdr *)p; 2452 rt_entry(rtm, again); 2453 } 2454 free(buf); 2455 } 2456 2457 static void 2458 rt_entry(struct rt_msghdr *rtm, int again) 2459 { 2460 struct sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask; 2461 struct sockaddr_in6 *sin6_genmask, *sin6_ifp; 2462 char *rtmp, *ifname = NULL; 2463 struct riprt *rrt, *orrt; 2464 struct netinfo6 *np; 2465 int s; 2466 2467 sin6_dst = sin6_gw = sin6_mask = sin6_genmask = sin6_ifp = 0; 2468 if ((rtm->rtm_flags & RTF_UP) == 0 || rtm->rtm_flags & 2469 (RTF_CLONING|RTF_XRESOLVE|RTF_LLINFO|RTF_BLACKHOLE)) { 2470 return; /* not interested in the link route */ 2471 } 2472 /* do not look at cloned routes */ 2473 #ifdef RTF_WASCLONED 2474 if (rtm->rtm_flags & RTF_WASCLONED) 2475 return; 2476 #endif 2477 #ifdef RTF_CLONED 2478 if (rtm->rtm_flags & RTF_CLONED) 2479 return; 2480 #endif 2481 /* 2482 * do not look at dynamic routes. 2483 * netbsd/openbsd cloned routes have UGHD. 2484 */ 2485 if (rtm->rtm_flags & RTF_DYNAMIC) 2486 return; 2487 rtmp = (char *)(rtm + 1); 2488 /* Destination */ 2489 if ((rtm->rtm_addrs & RTA_DST) == 0) 2490 return; /* ignore routes without destination address */ 2491 sin6_dst = (struct sockaddr_in6 *)rtmp; 2492 rtmp += ROUNDUP(sin6_dst->sin6_len); 2493 if (rtm->rtm_addrs & RTA_GATEWAY) { 2494 sin6_gw = (struct sockaddr_in6 *)rtmp; 2495 rtmp += ROUNDUP(sin6_gw->sin6_len); 2496 } 2497 if (rtm->rtm_addrs & RTA_NETMASK) { 2498 sin6_mask = (struct sockaddr_in6 *)rtmp; 2499 rtmp += ROUNDUP(sin6_mask->sin6_len); 2500 } 2501 if (rtm->rtm_addrs & RTA_GENMASK) { 2502 sin6_genmask = (struct sockaddr_in6 *)rtmp; 2503 rtmp += ROUNDUP(sin6_genmask->sin6_len); 2504 } 2505 if (rtm->rtm_addrs & RTA_IFP) { 2506 sin6_ifp = (struct sockaddr_in6 *)rtmp; 2507 rtmp += ROUNDUP(sin6_ifp->sin6_len); 2508 } 2509 2510 /* Destination */ 2511 if (sin6_dst->sin6_family != AF_INET6) 2512 return; 2513 if (IN6_IS_ADDR_LINKLOCAL(&sin6_dst->sin6_addr)) 2514 return; /* Link-local */ 2515 if (IN6_ARE_ADDR_EQUAL(&sin6_dst->sin6_addr, &in6addr_loopback)) 2516 return; /* Loopback */ 2517 if (IN6_IS_ADDR_MULTICAST(&sin6_dst->sin6_addr)) 2518 return; 2519 2520 if ((rrt = MALLOC(struct riprt)) == NULL) { 2521 fatal("malloc: struct riprt"); 2522 /*NOTREACHED*/ 2523 } 2524 memset(rrt, 0, sizeof(*rrt)); 2525 np = &rrt->rrt_info; 2526 rrt->rrt_same = NULL; 2527 rrt->rrt_t = time(NULL); 2528 if (aflag == 0 && (rtm->rtm_flags & RTF_STATIC)) 2529 rrt->rrt_t = 0; /* Don't age static routes */ 2530 if ((rtm->rtm_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 2531 rrt->rrt_t = 0; /* Don't age non-gateway host routes */ 2532 np->rip6_tag = 0; 2533 np->rip6_metric = rtm->rtm_rmx.rmx_hopcount; 2534 if (np->rip6_metric < 1) 2535 np->rip6_metric = 1; 2536 rrt->rrt_flags = rtm->rtm_flags; 2537 np->rip6_dest = sin6_dst->sin6_addr; 2538 2539 /* Mask or plen */ 2540 if (rtm->rtm_flags & RTF_HOST) 2541 np->rip6_plen = 128; /* Host route */ 2542 else if (sin6_mask) 2543 np->rip6_plen = sin6mask2len(sin6_mask); 2544 else 2545 np->rip6_plen = 0; 2546 2547 orrt = rtsearch(np, NULL); 2548 if (orrt && orrt->rrt_info.rip6_metric != HOPCNT_INFINITY6) { 2549 /* Already found */ 2550 if (!again) { 2551 trace(1, "route: %s/%d flags %s: already registered\n", 2552 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2553 rtflags(rtm)); 2554 } 2555 free(rrt); 2556 return; 2557 } 2558 /* Gateway */ 2559 if (!sin6_gw) 2560 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2561 else { 2562 if (sin6_gw->sin6_family == AF_INET6) 2563 rrt->rrt_gw = sin6_gw->sin6_addr; 2564 else if (sin6_gw->sin6_family == AF_LINK) { 2565 /* XXX in case ppp link? */ 2566 rrt->rrt_gw = in6addr_loopback; 2567 } else 2568 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2569 } 2570 trace(1, "route: %s/%d flags %s", 2571 inet6_n2p(&np->rip6_dest), np->rip6_plen, rtflags(rtm)); 2572 trace(1, " gw %s", inet6_n2p(&rrt->rrt_gw)); 2573 2574 /* Interface */ 2575 s = rtm->rtm_index; 2576 if (s < nindex2ifc && index2ifc[s]) 2577 ifname = index2ifc[s]->ifc_name; 2578 else { 2579 trace(1, " not configured\n"); 2580 free(rrt); 2581 return; 2582 } 2583 trace(1, " if %s sock %d", ifname, s); 2584 rrt->rrt_index = s; 2585 2586 trace(1, "\n"); 2587 2588 /* Check gateway */ 2589 if (!IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_gw) && 2590 !IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw) 2591 #ifdef __FreeBSD__ 2592 && (rrt->rrt_flags & RTF_LOCAL) == 0 2593 #endif 2594 ) { 2595 trace(0, "***** Gateway %s is not a link-local address.\n", 2596 inet6_n2p(&rrt->rrt_gw)); 2597 trace(0, "***** dest(%s) if(%s) -- Not optimized.\n", 2598 inet6_n2p(&rrt->rrt_info.rip6_dest), ifname); 2599 rrt->rrt_rflags |= RRTF_NH_NOT_LLADDR; 2600 } 2601 2602 /* Put it to the route list */ 2603 if (orrt && orrt->rrt_info.rip6_metric == HOPCNT_INFINITY6) { 2604 /* replace route list */ 2605 rrt->rrt_next = orrt->rrt_next; 2606 *orrt = *rrt; 2607 trace(1, "route: %s/%d flags %s: replace new route\n", 2608 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2609 rtflags(rtm)); 2610 free(rrt); 2611 } else { 2612 rrt->rrt_next = riprt; 2613 riprt = rrt; 2614 } 2615 } 2616 2617 static int 2618 addroute(struct riprt *rrt, const struct in6_addr *gw, struct ifc *ifcp) 2619 { 2620 struct netinfo6 *np; 2621 u_char buf[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ]; 2622 struct rt_msghdr *rtm; 2623 struct sockaddr_in6 *sin6; 2624 int len; 2625 2626 np = &rrt->rrt_info; 2627 inet_ntop(AF_INET6, (const void *)gw, (char *)buf1, sizeof(buf1)); 2628 inet_ntop(AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2)); 2629 tracet(1, "ADD: %s/%d gw %s [%d] ifa %s\n", 2630 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2631 np->rip6_metric - 1, buf2); 2632 if (rtlog) 2633 fprintf(rtlog, "%s: ADD: %s/%d gw %s [%d] ifa %s\n", hms(), 2634 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2635 np->rip6_metric - 1, buf2); 2636 if (nflag) 2637 return 0; 2638 2639 memset(buf, 0, sizeof(buf)); 2640 rtm = (struct rt_msghdr *)buf; 2641 rtm->rtm_type = RTM_ADD; 2642 rtm->rtm_version = RTM_VERSION; 2643 rtm->rtm_seq = ++seq; 2644 rtm->rtm_pid = pid; 2645 rtm->rtm_flags = rrt->rrt_flags; 2646 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2647 rtm->rtm_rmx.rmx_hopcount = np->rip6_metric - 1; 2648 rtm->rtm_inits = RTV_HOPCOUNT; 2649 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2650 /* Destination */ 2651 sin6->sin6_len = sizeof(struct sockaddr_in6); 2652 sin6->sin6_family = AF_INET6; 2653 sin6->sin6_addr = np->rip6_dest; 2654 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2655 /* Gateway */ 2656 sin6->sin6_len = sizeof(struct sockaddr_in6); 2657 sin6->sin6_family = AF_INET6; 2658 sin6->sin6_addr = *gw; 2659 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2660 /* Netmask */ 2661 sin6->sin6_len = sizeof(struct sockaddr_in6); 2662 sin6->sin6_family = AF_INET6; 2663 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2664 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2665 2666 len = (char *)sin6 - (char *)buf; 2667 rtm->rtm_msglen = len; 2668 if (write(rtsock, buf, len) > 0) 2669 return 0; 2670 2671 if (errno == EEXIST) { 2672 trace(0, "ADD: Route already exists %s/%d gw %s\n", 2673 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2674 if (rtlog) 2675 fprintf(rtlog, "ADD: Route already exists %s/%d gw %s\n", 2676 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2677 } else { 2678 trace(0, "Can not write to rtsock (addroute): %s\n", 2679 strerror(errno)); 2680 if (rtlog) 2681 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2682 strerror(errno)); 2683 } 2684 return -1; 2685 } 2686 2687 static int 2688 delroute(struct netinfo6 *np, struct in6_addr *gw) 2689 { 2690 u_char buf[BUFSIZ], buf2[BUFSIZ]; 2691 struct rt_msghdr *rtm; 2692 struct sockaddr_in6 *sin6; 2693 int len; 2694 2695 inet_ntop(AF_INET6, (void *)gw, (char *)buf2, sizeof(buf2)); 2696 tracet(1, "DEL: %s/%d gw %s\n", inet6_n2p(&np->rip6_dest), 2697 np->rip6_plen, buf2); 2698 if (rtlog) 2699 fprintf(rtlog, "%s: DEL: %s/%d gw %s\n", 2700 hms(), inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2701 if (nflag) 2702 return 0; 2703 2704 memset(buf, 0, sizeof(buf)); 2705 rtm = (struct rt_msghdr *)buf; 2706 rtm->rtm_type = RTM_DELETE; 2707 rtm->rtm_version = RTM_VERSION; 2708 rtm->rtm_seq = ++seq; 2709 rtm->rtm_pid = pid; 2710 rtm->rtm_flags = RTF_UP | RTF_GATEWAY; 2711 if (np->rip6_plen == sizeof(struct in6_addr) * 8) 2712 rtm->rtm_flags |= RTF_HOST; 2713 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2714 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2715 /* Destination */ 2716 sin6->sin6_len = sizeof(struct sockaddr_in6); 2717 sin6->sin6_family = AF_INET6; 2718 sin6->sin6_addr = np->rip6_dest; 2719 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2720 /* Gateway */ 2721 sin6->sin6_len = sizeof(struct sockaddr_in6); 2722 sin6->sin6_family = AF_INET6; 2723 sin6->sin6_addr = *gw; 2724 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2725 /* Netmask */ 2726 sin6->sin6_len = sizeof(struct sockaddr_in6); 2727 sin6->sin6_family = AF_INET6; 2728 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2729 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2730 2731 len = (char *)sin6 - (char *)buf; 2732 rtm->rtm_msglen = len; 2733 if (write(rtsock, buf, len) >= 0) 2734 return 0; 2735 2736 if (errno == ESRCH) { 2737 trace(0, "RTDEL: Route does not exist: %s/%d gw %s\n", 2738 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2739 if (rtlog) 2740 fprintf(rtlog, "RTDEL: Route does not exist: %s/%d gw %s\n", 2741 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2742 } else { 2743 trace(0, "Can not write to rtsock (delroute): %s\n", 2744 strerror(errno)); 2745 if (rtlog) 2746 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2747 strerror(errno)); 2748 } 2749 return -1; 2750 } 2751 2752 static const char * 2753 inet6_n2p(const struct in6_addr *p) 2754 { 2755 static char buf[BUFSIZ]; 2756 2757 return inet_ntop(AF_INET6, (const void *)p, buf, sizeof(buf)); 2758 } 2759 2760 static void 2761 ifrtdump(int sig) 2762 { 2763 2764 ifdump(sig); 2765 rtdump(sig); 2766 } 2767 2768 static void 2769 ifdump(int sig) 2770 { 2771 struct ifc *ifcp; 2772 FILE *dump; 2773 int i; 2774 2775 if (sig == 0) 2776 dump = stderr; 2777 else 2778 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 2779 dump = stderr; 2780 2781 fprintf(dump, "%s: Interface Table Dump\n", hms()); 2782 fprintf(dump, " Number of interfaces: %d\n", nifc); 2783 for (i = 0; i < 2; i++) { 2784 fprintf(dump, " %sadvertising interfaces:\n", i ? "non-" : ""); 2785 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 2786 if (i == 0) { 2787 if ((ifcp->ifc_flags & IFF_UP) == 0) 2788 continue; 2789 if (iff_find(ifcp, 'N') != NULL) 2790 continue; 2791 } else { 2792 if (ifcp->ifc_flags & IFF_UP) 2793 continue; 2794 } 2795 ifdump0(dump, ifcp); 2796 } 2797 } 2798 fprintf(dump, "\n"); 2799 if (dump != stderr) 2800 fclose(dump); 2801 } 2802 2803 static void 2804 ifdump0(FILE *dump, const struct ifc *ifcp) 2805 { 2806 struct ifac *ifa; 2807 struct iff *iffp; 2808 char buf[BUFSIZ]; 2809 const char *ft; 2810 int addr; 2811 2812 fprintf(dump, " %s: index(%d) flags(%s) addr(%s) mtu(%d) metric(%d)\n", 2813 ifcp->ifc_name, ifcp->ifc_index, ifflags(ifcp->ifc_flags), 2814 inet6_n2p(&ifcp->ifc_mylladdr), 2815 ifcp->ifc_mtu, ifcp->ifc_metric); 2816 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 2817 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 2818 inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr, 2819 buf, sizeof(buf)); 2820 fprintf(dump, "\t%s/%d -- %s\n", 2821 inet6_n2p(&ifa->ifa_addr), 2822 ifa->ifa_plen, buf); 2823 } else { 2824 fprintf(dump, "\t%s/%d\n", 2825 inet6_n2p(&ifa->ifa_addr), 2826 ifa->ifa_plen); 2827 } 2828 } 2829 if (ifcp->ifc_filter) { 2830 fprintf(dump, "\tFilter:"); 2831 for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { 2832 addr = 0; 2833 switch (iffp->iff_type) { 2834 case 'A': 2835 ft = "Aggregate"; addr++; break; 2836 case 'N': 2837 ft = "No-use"; break; 2838 case 'O': 2839 ft = "Advertise-only"; addr++; break; 2840 case 'T': 2841 ft = "Default-only"; break; 2842 case 'L': 2843 ft = "Listen-only"; addr++; break; 2844 default: 2845 snprintf(buf, sizeof(buf), "Unknown-%c", iffp->iff_type); 2846 ft = buf; 2847 addr++; 2848 break; 2849 } 2850 fprintf(dump, " %s", ft); 2851 if (addr) { 2852 fprintf(dump, "(%s/%d)", inet6_n2p(&iffp->iff_addr), 2853 iffp->iff_plen); 2854 } 2855 } 2856 fprintf(dump, "\n"); 2857 } 2858 } 2859 2860 static void 2861 rtdump(int sig) 2862 { 2863 struct riprt *rrt; 2864 char buf[BUFSIZ]; 2865 FILE *dump; 2866 time_t t, age; 2867 2868 if (sig == 0) 2869 dump = stderr; 2870 else 2871 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 2872 dump = stderr; 2873 2874 t = time(NULL); 2875 fprintf(dump, "\n%s: Routing Table Dump\n", hms()); 2876 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 2877 if (rrt->rrt_t == 0) 2878 age = 0; 2879 else 2880 age = t - rrt->rrt_t; 2881 inet_ntop(AF_INET6, (void *)&rrt->rrt_info.rip6_dest, 2882 buf, sizeof(buf)); 2883 fprintf(dump, " %s/%d if(%d:%s) gw(%s) [%d] age(%ld)", 2884 buf, rrt->rrt_info.rip6_plen, rrt->rrt_index, 2885 index2ifc[rrt->rrt_index]->ifc_name, 2886 inet6_n2p(&rrt->rrt_gw), 2887 rrt->rrt_info.rip6_metric, (long)age); 2888 if (rrt->rrt_info.rip6_tag) { 2889 fprintf(dump, " tag(0x%04x)", 2890 ntohs(rrt->rrt_info.rip6_tag) & 0xffff); 2891 } 2892 if (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR) 2893 fprintf(dump, " NOT-LL"); 2894 if (rrt->rrt_rflags & RRTF_NOADVERTISE) 2895 fprintf(dump, " NO-ADV"); 2896 fprintf(dump, "\n"); 2897 } 2898 fprintf(dump, "\n"); 2899 if (dump != stderr) 2900 fclose(dump); 2901 } 2902 2903 /* 2904 * Parse the -A (and -O) options and put corresponding filter object to the 2905 * specified interface structures. Each of the -A/O option has the following 2906 * syntax: -A 5f09:c400::/32,ef0,ef1 (aggregate) 2907 * -O 5f09:c400::/32,ef0,ef1 (only when match) 2908 */ 2909 static void 2910 filterconfig(void) 2911 { 2912 int i; 2913 char *p, *ap, *iflp, *ifname, *ep; 2914 struct iff ftmp, *iff_obj; 2915 struct ifc *ifcp; 2916 struct riprt *rrt; 2917 #if 0 2918 struct in6_addr gw; 2919 #endif 2920 u_long plen; 2921 2922 for (i = 0; i < nfilter; i++) { 2923 ap = filter[i]; 2924 iflp = NULL; 2925 ifcp = NULL; 2926 if (filtertype[i] == 'N' || filtertype[i] == 'T') { 2927 iflp = ap; 2928 goto ifonly; 2929 } 2930 if ((p = strchr(ap, ',')) != NULL) { 2931 *p++ = '\0'; 2932 iflp = p; 2933 } 2934 if ((p = strchr(ap, '/')) == NULL) { 2935 fatal("no prefixlen specified for '%s'", ap); 2936 /*NOTREACHED*/ 2937 } 2938 *p++ = '\0'; 2939 if (inet_pton(AF_INET6, ap, &ftmp.iff_addr) != 1) { 2940 fatal("invalid prefix specified for '%s'", ap); 2941 /*NOTREACHED*/ 2942 } 2943 errno = 0; 2944 ep = NULL; 2945 plen = strtoul(p, &ep, 10); 2946 if (errno || !*p || *ep || plen > sizeof(ftmp.iff_addr) * 8) { 2947 fatal("invalid prefix length specified for '%s'", ap); 2948 /*NOTREACHED*/ 2949 } 2950 ftmp.iff_plen = plen; 2951 ftmp.iff_next = NULL; 2952 applyplen(&ftmp.iff_addr, ftmp.iff_plen); 2953 ifonly: 2954 ftmp.iff_type = filtertype[i]; 2955 if (iflp == NULL || *iflp == '\0') { 2956 fatal("no interface specified for '%s'", ap); 2957 /*NOTREACHED*/ 2958 } 2959 /* parse the interface listing portion */ 2960 while (iflp) { 2961 ifname = iflp; 2962 if ((iflp = strchr(iflp, ',')) != NULL) 2963 *iflp++ = '\0'; 2964 ifcp = ifc_find(ifname); 2965 if (ifcp == NULL) { 2966 fatal("no interface %s exists", ifname); 2967 /*NOTREACHED*/ 2968 } 2969 iff_obj = (struct iff *)malloc(sizeof(struct iff)); 2970 if (iff_obj == NULL) { 2971 fatal("malloc of iff_obj"); 2972 /*NOTREACHED*/ 2973 } 2974 memcpy((void *)iff_obj, (void *)&ftmp, 2975 sizeof(struct iff)); 2976 /* link it to the interface filter */ 2977 iff_obj->iff_next = ifcp->ifc_filter; 2978 ifcp->ifc_filter = iff_obj; 2979 } 2980 2981 /* 2982 * -A: aggregate configuration. 2983 */ 2984 if (filtertype[i] != 'A') 2985 continue; 2986 /* put the aggregate to the kernel routing table */ 2987 rrt = (struct riprt *)malloc(sizeof(struct riprt)); 2988 if (rrt == NULL) { 2989 fatal("malloc: rrt"); 2990 /*NOTREACHED*/ 2991 } 2992 memset(rrt, 0, sizeof(struct riprt)); 2993 rrt->rrt_info.rip6_dest = ftmp.iff_addr; 2994 rrt->rrt_info.rip6_plen = ftmp.iff_plen; 2995 rrt->rrt_info.rip6_metric = 1; 2996 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 2997 rrt->rrt_gw = in6addr_loopback; 2998 rrt->rrt_flags = RTF_UP | RTF_REJECT; 2999 rrt->rrt_rflags = RRTF_AGGREGATE; 3000 rrt->rrt_t = 0; 3001 rrt->rrt_index = loopifcp->ifc_index; 3002 #if 0 3003 if (getroute(&rrt->rrt_info, &gw)) { 3004 #if 0 3005 /* 3006 * When the address has already been registered in the 3007 * kernel routing table, it should be removed 3008 */ 3009 delroute(&rrt->rrt_info, &gw); 3010 #else 3011 /* it is safer behavior */ 3012 errno = EINVAL; 3013 fatal("%s/%u already in routing table, " 3014 "cannot aggregate", 3015 inet6_n2p(&rrt->rrt_info.rip6_dest), 3016 rrt->rrt_info.rip6_plen); 3017 /*NOTREACHED*/ 3018 #endif 3019 } 3020 #endif 3021 /* Put the route to the list */ 3022 rrt->rrt_next = riprt; 3023 riprt = rrt; 3024 trace(1, "Aggregate: %s/%d for %s\n", 3025 inet6_n2p(&ftmp.iff_addr), ftmp.iff_plen, 3026 ifcp->ifc_name); 3027 /* Add this route to the kernel */ 3028 if (nflag) /* do not modify kernel routing table */ 3029 continue; 3030 addroute(rrt, &in6addr_loopback, loopifcp); 3031 } 3032 } 3033 3034 /***************** utility functions *****************/ 3035 3036 /* 3037 * Returns a pointer to ifac whose address and prefix length matches 3038 * with the address and prefix length specified in the arguments. 3039 */ 3040 static struct ifac * 3041 ifa_match(const struct ifc *ifcp, const struct in6_addr *ia, int plen) 3042 { 3043 struct ifac *ifa; 3044 3045 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 3046 if (IN6_ARE_ADDR_EQUAL(&ifa->ifa_addr, ia) && 3047 ifa->ifa_plen == plen) 3048 break; 3049 } 3050 return ifa; 3051 } 3052 3053 /* 3054 * Return a pointer to riprt structure whose address and prefix length 3055 * matches with the address and prefix length found in the argument. 3056 * Note: This is not a rtalloc(). Therefore exact match is necessary. 3057 */ 3058 static struct riprt * 3059 rtsearch(struct netinfo6 *np, struct riprt **prev_rrt) 3060 { 3061 struct riprt *rrt; 3062 3063 if (prev_rrt) 3064 *prev_rrt = NULL; 3065 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 3066 if (rrt->rrt_info.rip6_plen == np->rip6_plen && 3067 IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, 3068 &np->rip6_dest)) 3069 return rrt; 3070 if (prev_rrt) 3071 *prev_rrt = rrt; 3072 } 3073 if (prev_rrt) 3074 *prev_rrt = NULL; 3075 return 0; 3076 } 3077 3078 static int 3079 sin6mask2len(const struct sockaddr_in6 *sin6) 3080 { 3081 3082 return mask2len(&sin6->sin6_addr, 3083 sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr)); 3084 } 3085 3086 static int 3087 mask2len(const struct in6_addr *addr, int lenlim) 3088 { 3089 int i = 0, j; 3090 const u_char *p = (const u_char *)addr; 3091 3092 for (j = 0; j < lenlim; j++, p++) { 3093 if (*p != 0xff) 3094 break; 3095 i += 8; 3096 } 3097 if (j < lenlim) { 3098 switch (*p) { 3099 #define MASKLEN(m, l) case m: do { i += l; break; } while (0) 3100 MASKLEN(0xfe, 7); break; 3101 MASKLEN(0xfc, 6); break; 3102 MASKLEN(0xf8, 5); break; 3103 MASKLEN(0xf0, 4); break; 3104 MASKLEN(0xe0, 3); break; 3105 MASKLEN(0xc0, 2); break; 3106 MASKLEN(0x80, 1); break; 3107 #undef MASKLEN 3108 } 3109 } 3110 return i; 3111 } 3112 3113 static const u_char plent[8] = { 3114 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 3115 }; 3116 3117 static void 3118 applyplen(struct in6_addr *ia, int plen) 3119 { 3120 u_char *p; 3121 int i; 3122 3123 p = ia->s6_addr; 3124 for (i = 0; i < 16; i++) { 3125 if (plen <= 0) 3126 *p = 0; 3127 else if (plen < 8) 3128 *p &= plent[plen]; 3129 p++, plen -= 8; 3130 } 3131 } 3132 3133 static const int pl2m[9] = { 3134 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff 3135 }; 3136 3137 static struct in6_addr * 3138 plen2mask(int n) 3139 { 3140 static struct in6_addr ia; 3141 u_char *p; 3142 int i; 3143 3144 memset(&ia, 0, sizeof(struct in6_addr)); 3145 p = (u_char *)&ia; 3146 for (i = 0; i < 16; i++, p++, n -= 8) { 3147 if (n >= 8) { 3148 *p = 0xff; 3149 continue; 3150 } 3151 *p = pl2m[n]; 3152 break; 3153 } 3154 return &ia; 3155 } 3156 3157 static char * 3158 allocopy(char *p) 3159 { 3160 int len = strlen(p) + 1; 3161 char *q = (char *)malloc(len); 3162 3163 if (!q) { 3164 fatal("malloc"); 3165 /*NOTREACHED*/ 3166 } 3167 3168 strlcpy(q, p, len); 3169 return q; 3170 } 3171 3172 static char * 3173 hms(void) 3174 { 3175 static char buf[BUFSIZ]; 3176 time_t t; 3177 struct tm *tm; 3178 3179 t = time(NULL); 3180 if ((tm = localtime(&t)) == 0) { 3181 fatal("localtime"); 3182 /*NOTREACHED*/ 3183 } 3184 snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, 3185 tm->tm_sec); 3186 return buf; 3187 } 3188 3189 #define RIPRANDDEV 1.0 /* 30 +- 15, max - min = 30 */ 3190 3191 static int 3192 ripinterval(int timer) 3193 { 3194 double r = rand(); 3195 3196 interval = (int)(timer + timer * RIPRANDDEV * (r / RAND_MAX - 0.5)); 3197 nextalarm = time(NULL) + interval; 3198 return interval; 3199 } 3200 3201 static void 3202 fatal(const char *fmt, ...) 3203 { 3204 va_list ap; 3205 char buf[1024]; 3206 3207 va_start(ap, fmt); 3208 vsnprintf(buf, sizeof(buf), fmt, ap); 3209 va_end(ap); 3210 perror(buf); 3211 if (errno) 3212 syslog(LOG_ERR, "%s: %s", buf, strerror(errno)); 3213 else 3214 syslog(LOG_ERR, "%s", buf); 3215 rtdexit(); 3216 } 3217 3218 static void 3219 tracet(int level, const char *fmt, ...) 3220 { 3221 va_list ap; 3222 3223 if (level <= dflag) { 3224 va_start(ap, fmt); 3225 fprintf(stderr, "%s: ", hms()); 3226 vfprintf(stderr, fmt, ap); 3227 va_end(ap); 3228 } 3229 if (dflag) { 3230 va_start(ap, fmt); 3231 if (level > 0) 3232 vsyslog(LOG_DEBUG, fmt, ap); 3233 else 3234 vsyslog(LOG_WARNING, fmt, ap); 3235 va_end(ap); 3236 } 3237 } 3238 3239 static void 3240 trace(int level, const char *fmt, ...) 3241 { 3242 va_list ap; 3243 3244 if (level <= dflag) { 3245 va_start(ap, fmt); 3246 vfprintf(stderr, fmt, ap); 3247 va_end(ap); 3248 } 3249 if (dflag) { 3250 va_start(ap, fmt); 3251 if (level > 0) 3252 vsyslog(LOG_DEBUG, fmt, ap); 3253 else 3254 vsyslog(LOG_WARNING, fmt, ap); 3255 va_end(ap); 3256 } 3257 } 3258 3259 static struct ifc * 3260 ifc_find(char *name) 3261 { 3262 struct ifc *ifcp; 3263 3264 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 3265 if (strcmp(name, ifcp->ifc_name) == 0) 3266 return ifcp; 3267 } 3268 return NULL; 3269 } 3270 3271 static struct iff * 3272 iff_find(struct ifc *ifcp, int type) 3273 { 3274 struct iff *iffp; 3275 3276 for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { 3277 if (iffp->iff_type == type) 3278 return iffp; 3279 } 3280 return NULL; 3281 } 3282 3283 static void 3284 setindex2ifc(int idx, struct ifc *ifcp) 3285 { 3286 int n, nsize; 3287 struct ifc **p; 3288 3289 if (!index2ifc) { 3290 nindex2ifc = 5; /*initial guess*/ 3291 index2ifc = (struct ifc **) 3292 malloc(sizeof(*index2ifc) * nindex2ifc); 3293 if (index2ifc == NULL) { 3294 fatal("malloc"); 3295 /*NOTREACHED*/ 3296 } 3297 memset(index2ifc, 0, sizeof(*index2ifc) * nindex2ifc); 3298 } 3299 n = nindex2ifc; 3300 for (nsize = nindex2ifc; nsize <= idx; nsize *= 2) 3301 ; 3302 if (n != nsize) { 3303 p = (struct ifc **)realloc(index2ifc, 3304 sizeof(*index2ifc) * nsize); 3305 if (p == NULL) { 3306 fatal("realloc"); 3307 /*NOTREACHED*/ 3308 } 3309 memset(p + n, 0, sizeof(*index2ifc) * (nindex2ifc - n)); 3310 index2ifc = p; 3311 nindex2ifc = nsize; 3312 } 3313 index2ifc[idx] = ifcp; 3314 } 3315