1 /* $NetBSD: route6d.c,v 1.47 2003/08/22 08:24:26 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.47 2003/08/22 08:24:26 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[NI_MAXSERV]; 568 569 ifc = (struct ifc *)NULL; 570 nifc = 0; 571 nindex2ifc = 0; /*initial guess*/ 572 index2ifc = NULL; 573 snprintf(port, sizeof(port), "%u", 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 if ((rtm->rtm_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 2524 rrt->rrt_t = 0; /* Don't age non-gateway host routes */ 2525 np->rip6_tag = 0; 2526 np->rip6_metric = rtm->rtm_rmx.rmx_hopcount; 2527 if (np->rip6_metric < 1) 2528 np->rip6_metric = 1; 2529 rrt->rrt_flags = rtm->rtm_flags; 2530 np->rip6_dest = sin6_dst->sin6_addr; 2531 2532 /* Mask or plen */ 2533 if (rtm->rtm_flags & RTF_HOST) 2534 np->rip6_plen = 128; /* Host route */ 2535 else if (sin6_mask) 2536 np->rip6_plen = sin6mask2len(sin6_mask); 2537 else 2538 np->rip6_plen = 0; 2539 2540 orrt = rtsearch(np, NULL); 2541 if (orrt && orrt->rrt_info.rip6_metric != HOPCNT_INFINITY6) { 2542 /* Already found */ 2543 if (!again) { 2544 trace(1, "route: %s/%d flags %s: already registered\n", 2545 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2546 rtflags(rtm)); 2547 } 2548 free(rrt); 2549 return; 2550 } 2551 /* Gateway */ 2552 if (!sin6_gw) 2553 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2554 else { 2555 if (sin6_gw->sin6_family == AF_INET6) 2556 rrt->rrt_gw = sin6_gw->sin6_addr; 2557 else if (sin6_gw->sin6_family == AF_LINK) { 2558 /* XXX in case ppp link? */ 2559 rrt->rrt_gw = in6addr_loopback; 2560 } else 2561 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2562 } 2563 trace(1, "route: %s/%d flags %s", 2564 inet6_n2p(&np->rip6_dest), np->rip6_plen, rtflags(rtm)); 2565 trace(1, " gw %s", inet6_n2p(&rrt->rrt_gw)); 2566 2567 /* Interface */ 2568 s = rtm->rtm_index; 2569 if (s < nindex2ifc && index2ifc[s]) 2570 ifname = index2ifc[s]->ifc_name; 2571 else { 2572 trace(1, " not configured\n"); 2573 free(rrt); 2574 return; 2575 } 2576 trace(1, " if %s sock %d", ifname, s); 2577 rrt->rrt_index = s; 2578 2579 trace(1, "\n"); 2580 2581 /* Check gateway */ 2582 if (!IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_gw) && 2583 !IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw) 2584 #ifdef __FreeBSD__ 2585 && (rrt->rrt_flags & RTF_LOCAL) == 0 2586 #endif 2587 ) { 2588 trace(0, "***** Gateway %s is not a link-local address.\n", 2589 inet6_n2p(&rrt->rrt_gw)); 2590 trace(0, "***** dest(%s) if(%s) -- Not optimized.\n", 2591 inet6_n2p(&rrt->rrt_info.rip6_dest), ifname); 2592 rrt->rrt_rflags |= RRTF_NH_NOT_LLADDR; 2593 } 2594 2595 /* Put it to the route list */ 2596 if (orrt && orrt->rrt_info.rip6_metric == HOPCNT_INFINITY6) { 2597 /* replace route list */ 2598 rrt->rrt_next = orrt->rrt_next; 2599 *orrt = *rrt; 2600 trace(1, "route: %s/%d flags %s: replace new route\n", 2601 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2602 rtflags(rtm)); 2603 free(rrt); 2604 } else { 2605 rrt->rrt_next = riprt; 2606 riprt = rrt; 2607 } 2608 } 2609 2610 int 2611 addroute(struct riprt *rrt, const struct in6_addr *gw, struct ifc *ifcp) 2612 { 2613 struct netinfo6 *np; 2614 u_char buf[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ]; 2615 struct rt_msghdr *rtm; 2616 struct sockaddr_in6 *sin6; 2617 int len; 2618 2619 np = &rrt->rrt_info; 2620 inet_ntop(AF_INET6, (const void *)gw, (char *)buf1, sizeof(buf1)); 2621 inet_ntop(AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2)); 2622 tracet(1, "ADD: %s/%d gw %s [%d] ifa %s\n", 2623 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2624 np->rip6_metric - 1, buf2); 2625 if (rtlog) 2626 fprintf(rtlog, "%s: ADD: %s/%d gw %s [%d] ifa %s\n", hms(), 2627 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2628 np->rip6_metric - 1, buf2); 2629 if (nflag) 2630 return 0; 2631 2632 memset(buf, 0, sizeof(buf)); 2633 rtm = (struct rt_msghdr *)buf; 2634 rtm->rtm_type = RTM_ADD; 2635 rtm->rtm_version = RTM_VERSION; 2636 rtm->rtm_seq = ++seq; 2637 rtm->rtm_pid = pid; 2638 rtm->rtm_flags = rrt->rrt_flags; 2639 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2640 rtm->rtm_rmx.rmx_hopcount = np->rip6_metric - 1; 2641 rtm->rtm_inits = RTV_HOPCOUNT; 2642 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2643 /* Destination */ 2644 sin6->sin6_len = sizeof(struct sockaddr_in6); 2645 sin6->sin6_family = AF_INET6; 2646 sin6->sin6_addr = np->rip6_dest; 2647 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2648 /* Gateway */ 2649 sin6->sin6_len = sizeof(struct sockaddr_in6); 2650 sin6->sin6_family = AF_INET6; 2651 sin6->sin6_addr = *gw; 2652 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2653 /* Netmask */ 2654 sin6->sin6_len = sizeof(struct sockaddr_in6); 2655 sin6->sin6_family = AF_INET6; 2656 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2657 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2658 2659 len = (char *)sin6 - (char *)buf; 2660 rtm->rtm_msglen = len; 2661 if (write(rtsock, buf, len) > 0) 2662 return 0; 2663 2664 if (errno == EEXIST) { 2665 trace(0, "ADD: Route already exists %s/%d gw %s\n", 2666 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2667 if (rtlog) 2668 fprintf(rtlog, "ADD: Route already exists %s/%d gw %s\n", 2669 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2670 } else { 2671 trace(0, "Can not write to rtsock (addroute): %s\n", 2672 strerror(errno)); 2673 if (rtlog) 2674 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2675 strerror(errno)); 2676 } 2677 return -1; 2678 } 2679 2680 int 2681 delroute(struct netinfo6 *np, struct in6_addr *gw) 2682 { 2683 u_char buf[BUFSIZ], buf2[BUFSIZ]; 2684 struct rt_msghdr *rtm; 2685 struct sockaddr_in6 *sin6; 2686 int len; 2687 2688 inet_ntop(AF_INET6, (void *)gw, (char *)buf2, sizeof(buf2)); 2689 tracet(1, "DEL: %s/%d gw %s\n", inet6_n2p(&np->rip6_dest), 2690 np->rip6_plen, buf2); 2691 if (rtlog) 2692 fprintf(rtlog, "%s: DEL: %s/%d gw %s\n", 2693 hms(), inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2694 if (nflag) 2695 return 0; 2696 2697 memset(buf, 0, sizeof(buf)); 2698 rtm = (struct rt_msghdr *)buf; 2699 rtm->rtm_type = RTM_DELETE; 2700 rtm->rtm_version = RTM_VERSION; 2701 rtm->rtm_seq = ++seq; 2702 rtm->rtm_pid = pid; 2703 rtm->rtm_flags = RTF_UP | RTF_GATEWAY; 2704 if (np->rip6_plen == sizeof(struct in6_addr) * 8) 2705 rtm->rtm_flags |= RTF_HOST; 2706 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2707 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2708 /* Destination */ 2709 sin6->sin6_len = sizeof(struct sockaddr_in6); 2710 sin6->sin6_family = AF_INET6; 2711 sin6->sin6_addr = np->rip6_dest; 2712 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2713 /* Gateway */ 2714 sin6->sin6_len = sizeof(struct sockaddr_in6); 2715 sin6->sin6_family = AF_INET6; 2716 sin6->sin6_addr = *gw; 2717 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2718 /* Netmask */ 2719 sin6->sin6_len = sizeof(struct sockaddr_in6); 2720 sin6->sin6_family = AF_INET6; 2721 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2722 sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2723 2724 len = (char *)sin6 - (char *)buf; 2725 rtm->rtm_msglen = len; 2726 if (write(rtsock, buf, len) >= 0) 2727 return 0; 2728 2729 if (errno == ESRCH) { 2730 trace(0, "RTDEL: Route does not exist: %s/%d gw %s\n", 2731 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2732 if (rtlog) 2733 fprintf(rtlog, "RTDEL: Route does not exist: %s/%d gw %s\n", 2734 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2735 } else { 2736 trace(0, "Can not write to rtsock (delroute): %s\n", 2737 strerror(errno)); 2738 if (rtlog) 2739 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2740 strerror(errno)); 2741 } 2742 return -1; 2743 } 2744 2745 struct in6_addr * 2746 getroute(struct netinfo6 *np, struct in6_addr *gw) 2747 { 2748 u_char buf[BUFSIZ]; 2749 int myseq; 2750 int len; 2751 struct rt_msghdr *rtm; 2752 struct sockaddr_in6 *sin6; 2753 2754 rtm = (struct rt_msghdr *)buf; 2755 len = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in6); 2756 memset(rtm, 0, len); 2757 rtm->rtm_type = RTM_GET; 2758 rtm->rtm_version = RTM_VERSION; 2759 myseq = ++seq; 2760 rtm->rtm_seq = myseq; 2761 rtm->rtm_addrs = RTA_DST; 2762 rtm->rtm_msglen = len; 2763 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2764 sin6->sin6_len = sizeof(struct sockaddr_in6); 2765 sin6->sin6_family = AF_INET6; 2766 sin6->sin6_addr = np->rip6_dest; 2767 if (write(rtsock, buf, len) < 0) { 2768 if (errno == ESRCH) /* No such route found */ 2769 return NULL; 2770 perror("write to rtsock"); 2771 exit(1); 2772 } 2773 do { 2774 if ((len = read(rtsock, buf, sizeof(buf))) < 0) { 2775 perror("read from rtsock"); 2776 exit(1); 2777 } 2778 rtm = (struct rt_msghdr *)buf; 2779 } while (rtm->rtm_seq != myseq || rtm->rtm_pid != pid); 2780 sin6 = (struct sockaddr_in6 *)&buf[sizeof(struct rt_msghdr)]; 2781 if (rtm->rtm_addrs & RTA_DST) { 2782 sin6 = (struct sockaddr_in6 *) 2783 ((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2784 } 2785 if (rtm->rtm_addrs & RTA_GATEWAY) { 2786 *gw = sin6->sin6_addr; 2787 return gw; 2788 } 2789 return NULL; 2790 } 2791 2792 const char * 2793 inet6_n2p(const struct in6_addr *p) 2794 { 2795 static char buf[BUFSIZ]; 2796 2797 return inet_ntop(AF_INET6, (const void *)p, buf, sizeof(buf)); 2798 } 2799 2800 void 2801 ifrtdump(int sig) 2802 { 2803 2804 ifdump(sig); 2805 rtdump(sig); 2806 } 2807 2808 void 2809 ifdump(int sig) 2810 { 2811 struct ifc *ifcp; 2812 FILE *dump; 2813 int i; 2814 2815 if (sig == 0) 2816 dump = stderr; 2817 else 2818 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 2819 dump = stderr; 2820 2821 fprintf(dump, "%s: Interface Table Dump\n", hms()); 2822 fprintf(dump, " Number of interfaces: %d\n", nifc); 2823 for (i = 0; i < 2; i++) { 2824 fprintf(dump, " %sadvertising interfaces:\n", i ? "non-" : ""); 2825 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 2826 if (i == 0) { 2827 if ((ifcp->ifc_flags & IFF_UP) == 0) 2828 continue; 2829 if (iff_find(ifcp, 'N') != NULL) 2830 continue; 2831 } else { 2832 if (ifcp->ifc_flags & IFF_UP) 2833 continue; 2834 } 2835 ifdump0(dump, ifcp); 2836 } 2837 } 2838 fprintf(dump, "\n"); 2839 if (dump != stderr) 2840 fclose(dump); 2841 } 2842 2843 void 2844 ifdump0(FILE *dump, const struct ifc *ifcp) 2845 { 2846 struct ifac *ifa; 2847 struct iff *iffp; 2848 char buf[BUFSIZ]; 2849 const char *ft; 2850 int addr; 2851 2852 fprintf(dump, " %s: index(%d) flags(%s) addr(%s) mtu(%d) metric(%d)\n", 2853 ifcp->ifc_name, ifcp->ifc_index, ifflags(ifcp->ifc_flags), 2854 inet6_n2p(&ifcp->ifc_mylladdr), 2855 ifcp->ifc_mtu, ifcp->ifc_metric); 2856 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 2857 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 2858 inet_ntop(AF_INET6, (void *)&ifa->ifa_raddr, 2859 buf, sizeof(buf)); 2860 fprintf(dump, "\t%s/%d -- %s\n", 2861 inet6_n2p(&ifa->ifa_addr), 2862 ifa->ifa_plen, buf); 2863 } else { 2864 fprintf(dump, "\t%s/%d\n", 2865 inet6_n2p(&ifa->ifa_addr), 2866 ifa->ifa_plen); 2867 } 2868 } 2869 if (ifcp->ifc_filter) { 2870 fprintf(dump, "\tFilter:"); 2871 for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { 2872 addr = 0; 2873 switch (iffp->iff_type) { 2874 case 'A': 2875 ft = "Aggregate"; addr++; break; 2876 case 'N': 2877 ft = "No-use"; break; 2878 case 'O': 2879 ft = "Advertise-only"; addr++; break; 2880 case 'T': 2881 ft = "Default-only"; break; 2882 case 'L': 2883 ft = "Listen-only"; addr++; break; 2884 default: 2885 snprintf(buf, sizeof(buf), "Unknown-%c", iffp->iff_type); 2886 ft = buf; 2887 addr++; 2888 break; 2889 } 2890 fprintf(dump, " %s", ft); 2891 if (addr) { 2892 fprintf(dump, "(%s/%d)", inet6_n2p(&iffp->iff_addr), 2893 iffp->iff_plen); 2894 } 2895 } 2896 fprintf(dump, "\n"); 2897 } 2898 } 2899 2900 void 2901 rtdump(int sig) 2902 { 2903 struct riprt *rrt; 2904 char buf[BUFSIZ]; 2905 FILE *dump; 2906 time_t t, age; 2907 2908 if (sig == 0) 2909 dump = stderr; 2910 else 2911 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 2912 dump = stderr; 2913 2914 t = time(NULL); 2915 fprintf(dump, "\n%s: Routing Table Dump\n", hms()); 2916 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 2917 if (rrt->rrt_t == 0) 2918 age = 0; 2919 else 2920 age = t - rrt->rrt_t; 2921 inet_ntop(AF_INET6, (void *)&rrt->rrt_info.rip6_dest, 2922 buf, sizeof(buf)); 2923 fprintf(dump, " %s/%d if(%d:%s) gw(%s) [%d] age(%ld)", 2924 buf, rrt->rrt_info.rip6_plen, rrt->rrt_index, 2925 index2ifc[rrt->rrt_index]->ifc_name, 2926 inet6_n2p(&rrt->rrt_gw), 2927 rrt->rrt_info.rip6_metric, (long)age); 2928 if (rrt->rrt_info.rip6_tag) { 2929 fprintf(dump, " tag(0x%04x)", 2930 ntohs(rrt->rrt_info.rip6_tag) & 0xffff); 2931 } 2932 if (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR) 2933 fprintf(dump, " NOT-LL"); 2934 if (rrt->rrt_rflags & RRTF_NOADVERTISE) 2935 fprintf(dump, " NO-ADV"); 2936 fprintf(dump, "\n"); 2937 } 2938 fprintf(dump, "\n"); 2939 if (dump != stderr) 2940 fclose(dump); 2941 } 2942 2943 /* 2944 * Parse the -A (and -O) options and put corresponding filter object to the 2945 * specified interface structures. Each of the -A/O option has the following 2946 * syntax: -A 5f09:c400::/32,ef0,ef1 (aggregate) 2947 * -O 5f09:c400::/32,ef0,ef1 (only when match) 2948 */ 2949 void 2950 filterconfig(void) 2951 { 2952 int i; 2953 char *p, *ap, *iflp, *ifname, *ep; 2954 struct iff ftmp, *iff_obj; 2955 struct ifc *ifcp; 2956 struct riprt *rrt; 2957 #if 0 2958 struct in6_addr gw; 2959 #endif 2960 u_long plen; 2961 2962 for (i = 0; i < nfilter; i++) { 2963 ap = filter[i]; 2964 iflp = NULL; 2965 ifcp = NULL; 2966 if (filtertype[i] == 'N' || filtertype[i] == 'T') { 2967 iflp = ap; 2968 goto ifonly; 2969 } 2970 if ((p = strchr(ap, ',')) != NULL) { 2971 *p++ = '\0'; 2972 iflp = p; 2973 } 2974 if ((p = strchr(ap, '/')) == NULL) { 2975 fatal("no prefixlen specified for '%s'", ap); 2976 /*NOTREACHED*/ 2977 } 2978 *p++ = '\0'; 2979 if (inet_pton(AF_INET6, ap, &ftmp.iff_addr) != 1) { 2980 fatal("invalid prefix specified for '%s'", ap); 2981 /*NOTREACHED*/ 2982 } 2983 errno = 0; 2984 ep = NULL; 2985 plen = strtoul(p, &ep, 10); 2986 if (errno || !*p || *ep || plen > sizeof(ftmp.iff_addr) * 8) { 2987 fatal("invalid prefix length specified for '%s'", ap); 2988 /*NOTREACHED*/ 2989 } 2990 ftmp.iff_plen = plen; 2991 ftmp.iff_next = NULL; 2992 applyplen(&ftmp.iff_addr, ftmp.iff_plen); 2993 ifonly: 2994 ftmp.iff_type = filtertype[i]; 2995 if (iflp == NULL || *iflp == '\0') { 2996 fatal("no interface specified for '%s'", ap); 2997 /*NOTREACHED*/ 2998 } 2999 /* parse the interface listing portion */ 3000 while (iflp) { 3001 ifname = iflp; 3002 if ((iflp = strchr(iflp, ',')) != NULL) 3003 *iflp++ = '\0'; 3004 ifcp = ifc_find(ifname); 3005 if (ifcp == NULL) { 3006 fatal("no interface %s exists", ifname); 3007 /*NOTREACHED*/ 3008 } 3009 iff_obj = (struct iff *)malloc(sizeof(struct iff)); 3010 if (iff_obj == NULL) { 3011 fatal("malloc of iff_obj"); 3012 /*NOTREACHED*/ 3013 } 3014 memcpy((void *)iff_obj, (void *)&ftmp, 3015 sizeof(struct iff)); 3016 /* link it to the interface filter */ 3017 iff_obj->iff_next = ifcp->ifc_filter; 3018 ifcp->ifc_filter = iff_obj; 3019 } 3020 3021 /* 3022 * -A: aggregate configuration. 3023 */ 3024 if (filtertype[i] != 'A') 3025 continue; 3026 /* put the aggregate to the kernel routing table */ 3027 rrt = (struct riprt *)malloc(sizeof(struct riprt)); 3028 if (rrt == NULL) { 3029 fatal("malloc: rrt"); 3030 /*NOTREACHED*/ 3031 } 3032 memset(rrt, 0, sizeof(struct riprt)); 3033 rrt->rrt_info.rip6_dest = ftmp.iff_addr; 3034 rrt->rrt_info.rip6_plen = ftmp.iff_plen; 3035 rrt->rrt_info.rip6_metric = 1; 3036 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 3037 rrt->rrt_gw = in6addr_loopback; 3038 rrt->rrt_flags = RTF_UP | RTF_REJECT; 3039 rrt->rrt_rflags = RRTF_AGGREGATE; 3040 rrt->rrt_t = 0; 3041 rrt->rrt_index = loopifcp->ifc_index; 3042 #if 0 3043 if (getroute(&rrt->rrt_info, &gw)) { 3044 #if 0 3045 /* 3046 * When the address has already been registered in the 3047 * kernel routing table, it should be removed 3048 */ 3049 delroute(&rrt->rrt_info, &gw); 3050 #else 3051 /* it is safer behavior */ 3052 errno = EINVAL; 3053 fatal("%s/%u already in routing table, " 3054 "cannot aggregate", 3055 inet6_n2p(&rrt->rrt_info.rip6_dest), 3056 rrt->rrt_info.rip6_plen); 3057 /*NOTREACHED*/ 3058 #endif 3059 } 3060 #endif 3061 /* Put the route to the list */ 3062 rrt->rrt_next = riprt; 3063 riprt = rrt; 3064 trace(1, "Aggregate: %s/%d for %s\n", 3065 inet6_n2p(&ftmp.iff_addr), ftmp.iff_plen, 3066 ifcp->ifc_name); 3067 /* Add this route to the kernel */ 3068 if (nflag) /* do not modify kernel routing table */ 3069 continue; 3070 addroute(rrt, &in6addr_loopback, loopifcp); 3071 } 3072 } 3073 3074 /***************** utility functions *****************/ 3075 3076 /* 3077 * Returns a pointer to ifac whose address and prefix length matches 3078 * with the address and prefix length specified in the arguments. 3079 */ 3080 struct ifac * 3081 ifa_match(const struct ifc *ifcp, const struct in6_addr *ia, int plen) 3082 { 3083 struct ifac *ifa; 3084 3085 for (ifa = ifcp->ifc_addr; ifa; ifa = ifa->ifa_next) { 3086 if (IN6_ARE_ADDR_EQUAL(&ifa->ifa_addr, ia) && 3087 ifa->ifa_plen == plen) 3088 break; 3089 } 3090 return ifa; 3091 } 3092 3093 /* 3094 * Return a pointer to riprt structure whose address and prefix length 3095 * matches with the address and prefix length found in the argument. 3096 * Note: This is not a rtalloc(). Therefore exact match is necessary. 3097 */ 3098 struct riprt * 3099 rtsearch(struct netinfo6 *np, struct riprt **prev_rrt) 3100 { 3101 struct riprt *rrt; 3102 3103 if (prev_rrt) 3104 *prev_rrt = NULL; 3105 for (rrt = riprt; rrt; rrt = rrt->rrt_next) { 3106 if (rrt->rrt_info.rip6_plen == np->rip6_plen && 3107 IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, 3108 &np->rip6_dest)) 3109 return rrt; 3110 if (prev_rrt) 3111 *prev_rrt = rrt; 3112 } 3113 if (prev_rrt) 3114 *prev_rrt = NULL; 3115 return 0; 3116 } 3117 3118 int 3119 sin6mask2len(const struct sockaddr_in6 *sin6) 3120 { 3121 3122 return mask2len(&sin6->sin6_addr, 3123 sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr)); 3124 } 3125 3126 int 3127 mask2len(const struct in6_addr *addr, int lenlim) 3128 { 3129 int i = 0, j; 3130 const u_char *p = (const u_char *)addr; 3131 3132 for (j = 0; j < lenlim; j++, p++) { 3133 if (*p != 0xff) 3134 break; 3135 i += 8; 3136 } 3137 if (j < lenlim) { 3138 switch (*p) { 3139 #define MASKLEN(m, l) case m: do { i += l; break; } while (0) 3140 MASKLEN(0xfe, 7); break; 3141 MASKLEN(0xfc, 6); break; 3142 MASKLEN(0xf8, 5); break; 3143 MASKLEN(0xf0, 4); break; 3144 MASKLEN(0xe0, 3); break; 3145 MASKLEN(0xc0, 2); break; 3146 MASKLEN(0x80, 1); break; 3147 #undef MASKLEN 3148 } 3149 } 3150 return i; 3151 } 3152 3153 void 3154 applymask(struct in6_addr *addr, struct in6_addr *mask) 3155 { 3156 int i; 3157 u_long *p, *q; 3158 3159 p = (u_long *)addr; q = (u_long *)mask; 3160 for (i = 0; i < 4; i++) 3161 *p++ &= *q++; 3162 } 3163 3164 static const u_char plent[8] = { 3165 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 3166 }; 3167 3168 void 3169 applyplen(struct in6_addr *ia, int plen) 3170 { 3171 u_char *p; 3172 int i; 3173 3174 p = ia->s6_addr; 3175 for (i = 0; i < 16; i++) { 3176 if (plen <= 0) 3177 *p = 0; 3178 else if (plen < 8) 3179 *p &= plent[plen]; 3180 p++, plen -= 8; 3181 } 3182 } 3183 3184 static const int pl2m[9] = { 3185 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff 3186 }; 3187 3188 struct in6_addr * 3189 plen2mask(int n) 3190 { 3191 static struct in6_addr ia; 3192 u_char *p; 3193 int i; 3194 3195 memset(&ia, 0, sizeof(struct in6_addr)); 3196 p = (u_char *)&ia; 3197 for (i = 0; i < 16; i++, p++, n -= 8) { 3198 if (n >= 8) { 3199 *p = 0xff; 3200 continue; 3201 } 3202 *p = pl2m[n]; 3203 break; 3204 } 3205 return &ia; 3206 } 3207 3208 char * 3209 allocopy(char *p) 3210 { 3211 int len = strlen(p) + 1; 3212 char *q = (char *)malloc(len); 3213 3214 if (!q) { 3215 fatal("malloc"); 3216 /*NOTREACHED*/ 3217 } 3218 3219 strlcpy(q, p, len); 3220 return q; 3221 } 3222 3223 char * 3224 hms(void) 3225 { 3226 static char buf[BUFSIZ]; 3227 time_t t; 3228 struct tm *tm; 3229 3230 t = time(NULL); 3231 if ((tm = localtime(&t)) == 0) { 3232 fatal("localtime"); 3233 /*NOTREACHED*/ 3234 } 3235 snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, 3236 tm->tm_sec); 3237 return buf; 3238 } 3239 3240 #define RIPRANDDEV 1.0 /* 30 +- 15, max - min = 30 */ 3241 3242 int 3243 ripinterval(int timer) 3244 { 3245 double r = rand(); 3246 3247 interval = (int)(timer + timer * RIPRANDDEV * (r / RAND_MAX - 0.5)); 3248 nextalarm = time(NULL) + interval; 3249 return interval; 3250 } 3251 3252 time_t 3253 ripsuptrig(void) 3254 { 3255 time_t t; 3256 3257 double r = rand(); 3258 t = (int)(RIP_TRIG_INT6_MIN + 3259 (RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / RAND_MAX)); 3260 sup_trig_update = time(NULL) + t; 3261 return t; 3262 } 3263 3264 void 3265 fatal(const char *fmt, ...) 3266 { 3267 va_list ap; 3268 char buf[1024]; 3269 3270 va_start(ap, fmt); 3271 vsnprintf(buf, sizeof(buf), fmt, ap); 3272 va_end(ap); 3273 perror(buf); 3274 if (errno) 3275 syslog(LOG_ERR, "%s: %s", buf, strerror(errno)); 3276 else 3277 syslog(LOG_ERR, "%s", buf); 3278 rtdexit(); 3279 } 3280 3281 void 3282 tracet(int level, const char *fmt, ...) 3283 { 3284 va_list ap; 3285 3286 if (level <= dflag) { 3287 va_start(ap, fmt); 3288 fprintf(stderr, "%s: ", hms()); 3289 vfprintf(stderr, fmt, ap); 3290 va_end(ap); 3291 } 3292 if (dflag) { 3293 va_start(ap, fmt); 3294 if (level > 0) 3295 vsyslog(LOG_DEBUG, fmt, ap); 3296 else 3297 vsyslog(LOG_WARNING, fmt, ap); 3298 va_end(ap); 3299 } 3300 } 3301 3302 void 3303 trace(int level, const char *fmt, ...) 3304 { 3305 va_list ap; 3306 3307 if (level <= dflag) { 3308 va_start(ap, fmt); 3309 vfprintf(stderr, fmt, ap); 3310 va_end(ap); 3311 } 3312 if (dflag) { 3313 va_start(ap, fmt); 3314 if (level > 0) 3315 vsyslog(LOG_DEBUG, fmt, ap); 3316 else 3317 vsyslog(LOG_WARNING, fmt, ap); 3318 va_end(ap); 3319 } 3320 } 3321 3322 unsigned int 3323 if_maxindex(void) 3324 { 3325 struct if_nameindex *p, *p0; 3326 unsigned int max = 0; 3327 3328 p0 = if_nameindex(); 3329 for (p = p0; p && p->if_index && p->if_name; p++) { 3330 if (max < p->if_index) 3331 max = p->if_index; 3332 } 3333 if_freenameindex(p0); 3334 return max; 3335 } 3336 3337 struct ifc * 3338 ifc_find(char *name) 3339 { 3340 struct ifc *ifcp; 3341 3342 for (ifcp = ifc; ifcp; ifcp = ifcp->ifc_next) { 3343 if (strcmp(name, ifcp->ifc_name) == 0) 3344 return ifcp; 3345 } 3346 return (struct ifc *)NULL; 3347 } 3348 3349 struct iff * 3350 iff_find(struct ifc *ifcp, int type) 3351 { 3352 struct iff *iffp; 3353 3354 for (iffp = ifcp->ifc_filter; iffp; iffp = iffp->iff_next) { 3355 if (iffp->iff_type == type) 3356 return iffp; 3357 } 3358 return NULL; 3359 } 3360 3361 void 3362 setindex2ifc(int idx, struct ifc *ifcp) 3363 { 3364 int n; 3365 struct ifc **p; 3366 3367 if (!index2ifc) { 3368 nindex2ifc = 5; /*initial guess*/ 3369 index2ifc = (struct ifc **) 3370 malloc(sizeof(*index2ifc) * nindex2ifc); 3371 if (index2ifc == NULL) { 3372 fatal("malloc"); 3373 /*NOTREACHED*/ 3374 } 3375 memset(index2ifc, 0, sizeof(*index2ifc) * nindex2ifc); 3376 } 3377 n = nindex2ifc; 3378 while (nindex2ifc <= idx) 3379 nindex2ifc *= 2; 3380 if (n != nindex2ifc) { 3381 p = (struct ifc **)realloc(index2ifc, 3382 sizeof(*index2ifc) * nindex2ifc); 3383 if (p == NULL) { 3384 fatal("realloc"); 3385 /*NOTREACHED*/ 3386 } 3387 memset(p + n, 0, sizeof(*index2ifc) * (nindex2ifc - n)); 3388 index2ifc = p; 3389 } 3390 index2ifc[idx] = ifcp; 3391 } 3392