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