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