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