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