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