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