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