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