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