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, rrt, rrt_next); 2227 delroute(&rrt->rrt_info, &rrt->rrt_gw); 2228 } 2229 /* Attach the route to the list */ 2230 trace(1, "route: %s/%d: register route (%s)\n", 2231 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2232 ifcp->ifc_name); 2233 TAILQ_INSERT_HEAD(&riprt_head, rrt, rrt_next); 2234 addroute(rrt, &rrt->rrt_gw, ifcp); 2235 rrt = NULL; 2236 sendrequest(ifcp); 2237 ripsend(ifcp, &ifcp->ifc_ripsin, 0); 2238 need_trigger = 1; 2239 } else { 2240 TAILQ_FOREACH(loop_rrt, &riprt_head, rrt_next) { 2241 if (loop_rrt->rrt_index == ifcp->ifc_index) { 2242 t_lifetime = time(NULL) - RIP_LIFETIME; 2243 if (loop_rrt->rrt_t == 0 || loop_rrt->rrt_t > t_lifetime) { 2244 loop_rrt->rrt_t = t_lifetime; 2245 loop_rrt->rrt_info.rip6_metric = HOPCNT_INFINITY6; 2246 loop_rrt->rrt_rflags |= RRTF_CHANGED; 2247 need_trigger = 1; 2248 } 2249 } 2250 } 2251 } 2252 next: 2253 if (rrt) 2254 free(rrt); 2255 } 2256 return need_trigger; 2257 } 2258 2259 /* 2260 * there are couple of p2p interface routing models. "behavior" lets 2261 * you pick one. it looks that gated behavior fits best with BSDs, 2262 * since BSD kernels do not look at prefix length on p2p interfaces. 2263 */ 2264 static void 2265 ifrt_p2p(struct ifc *ifcp, int again) 2266 { 2267 struct ifac *ifac; 2268 struct riprt *rrt, *orrt; 2269 struct netinfo6 *np; 2270 struct in6_addr addr, dest; 2271 int advert, ignore, i; 2272 #define P2PADVERT_NETWORK 1 2273 #define P2PADVERT_ADDR 2 2274 #define P2PADVERT_DEST 4 2275 #define P2PADVERT_MAX 4 2276 const enum { CISCO, GATED, ROUTE6D } behavior = GATED; 2277 const char *category = ""; 2278 const char *noadv; 2279 2280 TAILQ_FOREACH(ifac, &ifcp->ifc_ifac_head, ifac_next) { 2281 addr = ifac->ifac_addr; 2282 dest = ifac->ifac_raddr; 2283 applyplen(&addr, ifac->ifac_plen); 2284 applyplen(&dest, ifac->ifac_plen); 2285 advert = ignore = 0; 2286 switch (behavior) { 2287 case CISCO: 2288 /* 2289 * honor addr/plen, just like normal shared medium 2290 * interface. this may cause trouble if you reuse 2291 * addr/plen on other interfaces. 2292 * 2293 * advertise addr/plen. 2294 */ 2295 advert |= P2PADVERT_NETWORK; 2296 break; 2297 case GATED: 2298 /* 2299 * prefixlen on p2p interface is meaningless. 2300 * advertise addr/128 and dest/128. 2301 * 2302 * do not install network route to route6d routing 2303 * table (if we do, it would prevent route installation 2304 * for other p2p interface that shares addr/plen). 2305 * 2306 * XXX what should we do if dest is ::? it will not 2307 * get announced anyways (see following filter), 2308 * but we need to think. 2309 */ 2310 advert |= P2PADVERT_ADDR; 2311 advert |= P2PADVERT_DEST; 2312 ignore |= P2PADVERT_NETWORK; 2313 break; 2314 case ROUTE6D: 2315 /* 2316 * just for testing. actually the code is redundant 2317 * given the current p2p interface address assignment 2318 * rule for kame kernel. 2319 * 2320 * intent: 2321 * A/n -> announce A/n 2322 * A B/n, A and B share prefix -> A/n (= B/n) 2323 * A B/n, do not share prefix -> A/128 and B/128 2324 * actually, A/64 and A B/128 are the only cases 2325 * permitted by the kernel: 2326 * A/64 -> A/64 2327 * A B/128 -> A/128 and B/128 2328 */ 2329 if (!IN6_IS_ADDR_UNSPECIFIED(&ifac->ifac_raddr)) { 2330 if (IN6_ARE_ADDR_EQUAL(&addr, &dest)) 2331 advert |= P2PADVERT_NETWORK; 2332 else { 2333 advert |= P2PADVERT_ADDR; 2334 advert |= P2PADVERT_DEST; 2335 ignore |= P2PADVERT_NETWORK; 2336 } 2337 } else 2338 advert |= P2PADVERT_NETWORK; 2339 break; 2340 } 2341 2342 for (i = 1; i <= P2PADVERT_MAX; i *= 2) { 2343 if ((ignore & i) != 0) 2344 continue; 2345 if ((rrt = MALLOC(struct riprt)) == NULL) { 2346 fatal("malloc: struct riprt"); 2347 /*NOTREACHED*/ 2348 } 2349 memset(rrt, 0, sizeof(*rrt)); 2350 rrt->rrt_same = NULL; 2351 rrt->rrt_index = ifcp->ifc_index; 2352 rrt->rrt_t = 0; /* don't age */ 2353 switch (i) { 2354 case P2PADVERT_NETWORK: 2355 rrt->rrt_info.rip6_dest = ifac->ifac_addr; 2356 rrt->rrt_info.rip6_plen = ifac->ifac_plen; 2357 applyplen(&rrt->rrt_info.rip6_dest, 2358 ifac->ifac_plen); 2359 category = "network"; 2360 break; 2361 case P2PADVERT_ADDR: 2362 rrt->rrt_info.rip6_dest = ifac->ifac_addr; 2363 rrt->rrt_info.rip6_plen = 128; 2364 rrt->rrt_gw = in6addr_loopback; 2365 category = "addr"; 2366 break; 2367 case P2PADVERT_DEST: 2368 rrt->rrt_info.rip6_dest = ifac->ifac_raddr; 2369 rrt->rrt_info.rip6_plen = 128; 2370 rrt->rrt_gw = ifac->ifac_addr; 2371 category = "dest"; 2372 break; 2373 } 2374 if (IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_info.rip6_dest) || 2375 IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_info.rip6_dest)) { 2376 #if 0 2377 trace(1, "route: %s: skip unspec/linklocal " 2378 "(%s on %s)\n", category, ifcp->ifc_name); 2379 #endif 2380 free(rrt); 2381 continue; 2382 } 2383 if ((advert & i) == 0) { 2384 rrt->rrt_rflags |= RRTF_NOADVERTISE; 2385 noadv = ", NO-ADV"; 2386 } else 2387 noadv = ""; 2388 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 2389 rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric; 2390 np = &rrt->rrt_info; 2391 orrt = rtsearch(np); 2392 if (!orrt) { 2393 /* Attach the route to the list */ 2394 trace(1, "route: %s/%d: register route " 2395 "(%s on %s%s)\n", 2396 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2397 category, ifcp->ifc_name, noadv); 2398 TAILQ_INSERT_HEAD(&riprt_head, rrt, rrt_next); 2399 } else if (rrt->rrt_index != orrt->rrt_index || 2400 rrt->rrt_info.rip6_metric != orrt->rrt_info.rip6_metric) { 2401 /* replace route */ 2402 TAILQ_INSERT_BEFORE(orrt, rrt, rrt_next); 2403 TAILQ_REMOVE(&riprt_head, orrt, rrt_next); 2404 free(orrt); 2405 2406 trace(1, "route: %s/%d: update (%s on %s%s)\n", 2407 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2408 category, ifcp->ifc_name, noadv); 2409 } else { 2410 /* Already found */ 2411 if (!again) { 2412 trace(1, "route: %s/%d: " 2413 "already registered (%s on %s%s)\n", 2414 inet6_n2p(&np->rip6_dest), 2415 np->rip6_plen, category, 2416 ifcp->ifc_name, noadv); 2417 } 2418 free(rrt); 2419 } 2420 } 2421 } 2422 #undef P2PADVERT_NETWORK 2423 #undef P2PADVERT_ADDR 2424 #undef P2PADVERT_DEST 2425 #undef P2PADVERT_MAX 2426 } 2427 2428 static int 2429 getifmtu(int ifindex) 2430 { 2431 int mib[6]; 2432 char *buf; 2433 size_t msize; 2434 struct if_msghdr *ifm; 2435 int mtu; 2436 2437 mib[0] = CTL_NET; 2438 mib[1] = PF_ROUTE; 2439 mib[2] = 0; 2440 mib[3] = AF_INET6; 2441 mib[4] = NET_RT_IFLIST; 2442 mib[5] = ifindex; 2443 if (sysctl(mib, nitems(mib), NULL, &msize, NULL, 0) < 0) { 2444 fatal("sysctl estimate NET_RT_IFLIST"); 2445 /*NOTREACHED*/ 2446 } 2447 if ((buf = malloc(msize)) == NULL) { 2448 fatal("malloc"); 2449 /*NOTREACHED*/ 2450 } 2451 if (sysctl(mib, nitems(mib), buf, &msize, NULL, 0) < 0) { 2452 fatal("sysctl NET_RT_IFLIST"); 2453 /*NOTREACHED*/ 2454 } 2455 ifm = (struct if_msghdr *)(void *)buf; 2456 mtu = ifm->ifm_data.ifi_mtu; 2457 if (ifindex != ifm->ifm_index) { 2458 fatal("ifindex does not match with ifm_index"); 2459 /*NOTREACHED*/ 2460 } 2461 free(buf); 2462 return mtu; 2463 } 2464 2465 static const char * 2466 rttypes(struct rt_msghdr *rtm) 2467 { 2468 #define RTTYPE(s, f) \ 2469 do { \ 2470 if (rtm->rtm_type == (f)) \ 2471 return (s); \ 2472 } while (0) 2473 RTTYPE("ADD", RTM_ADD); 2474 RTTYPE("DELETE", RTM_DELETE); 2475 RTTYPE("CHANGE", RTM_CHANGE); 2476 RTTYPE("GET", RTM_GET); 2477 RTTYPE("LOSING", RTM_LOSING); 2478 RTTYPE("REDIRECT", RTM_REDIRECT); 2479 RTTYPE("MISS", RTM_MISS); 2480 RTTYPE("LOCK", RTM_LOCK); 2481 RTTYPE("NEWADDR", RTM_NEWADDR); 2482 RTTYPE("DELADDR", RTM_DELADDR); 2483 RTTYPE("IFINFO", RTM_IFINFO); 2484 #ifdef RTM_OIFINFO 2485 RTTYPE("OIFINFO", RTM_OIFINFO); 2486 #endif 2487 #ifdef RTM_IFANNOUNCE 2488 RTTYPE("IFANNOUNCE", RTM_IFANNOUNCE); 2489 #endif 2490 #ifdef RTM_NEWMADDR 2491 RTTYPE("NEWMADDR", RTM_NEWMADDR); 2492 #endif 2493 #ifdef RTM_DELMADDR 2494 RTTYPE("DELMADDR", RTM_DELMADDR); 2495 #endif 2496 #undef RTTYPE 2497 return NULL; 2498 } 2499 2500 static const char * 2501 rtflags(struct rt_msghdr *rtm) 2502 { 2503 static char buf[BUFSIZ]; 2504 2505 /* 2506 * letter conflict should be okay. painful when *BSD diverges... 2507 */ 2508 strlcpy(buf, "", sizeof(buf)); 2509 #define RTFLAG(s, f) \ 2510 do { \ 2511 if (rtm->rtm_flags & (f)) \ 2512 strlcat(buf, (s), sizeof(buf)); \ 2513 } while (0) 2514 RTFLAG("U", RTF_UP); 2515 RTFLAG("G", RTF_GATEWAY); 2516 RTFLAG("H", RTF_HOST); 2517 RTFLAG("R", RTF_REJECT); 2518 RTFLAG("D", RTF_DYNAMIC); 2519 RTFLAG("M", RTF_MODIFIED); 2520 RTFLAG("d", RTF_DONE); 2521 #ifdef RTF_MASK 2522 RTFLAG("m", RTF_MASK); 2523 #endif 2524 #ifdef RTF_CLONED 2525 RTFLAG("c", RTF_CLONED); 2526 #endif 2527 RTFLAG("X", RTF_XRESOLVE); 2528 #ifdef RTF_LLINFO 2529 RTFLAG("L", RTF_LLINFO); 2530 #endif 2531 RTFLAG("S", RTF_STATIC); 2532 RTFLAG("B", RTF_BLACKHOLE); 2533 #ifdef RTF_PROTO3 2534 RTFLAG("3", RTF_PROTO3); 2535 #endif 2536 RTFLAG("2", RTF_PROTO2); 2537 RTFLAG("1", RTF_PROTO1); 2538 #ifdef RTF_BROADCAST 2539 RTFLAG("b", RTF_BROADCAST); 2540 #endif 2541 #ifdef RTF_DEFAULT 2542 RTFLAG("d", RTF_DEFAULT); 2543 #endif 2544 #ifdef RTF_ISAROUTER 2545 RTFLAG("r", RTF_ISAROUTER); 2546 #endif 2547 #ifdef RTF_TUNNEL 2548 RTFLAG("T", RTF_TUNNEL); 2549 #endif 2550 #ifdef RTF_AUTH 2551 RTFLAG("A", RTF_AUTH); 2552 #endif 2553 #ifdef RTF_CRYPT 2554 RTFLAG("E", RTF_CRYPT); 2555 #endif 2556 #undef RTFLAG 2557 return buf; 2558 } 2559 2560 static const char * 2561 ifflags(int flags) 2562 { 2563 static char buf[BUFSIZ]; 2564 2565 strlcpy(buf, "", sizeof(buf)); 2566 #define IFFLAG(s, f) \ 2567 do { \ 2568 if (flags & (f)) { \ 2569 if (buf[0]) \ 2570 strlcat(buf, ",", sizeof(buf)); \ 2571 strlcat(buf, (s), sizeof(buf)); \ 2572 } \ 2573 } while (0) 2574 IFFLAG("UP", IFF_UP); 2575 IFFLAG("BROADCAST", IFF_BROADCAST); 2576 IFFLAG("DEBUG", IFF_DEBUG); 2577 IFFLAG("LOOPBACK", IFF_LOOPBACK); 2578 IFFLAG("POINTOPOINT", IFF_POINTOPOINT); 2579 #ifdef IFF_NOTRAILERS 2580 IFFLAG("NOTRAILERS", IFF_NOTRAILERS); 2581 #endif 2582 IFFLAG("RUNNING", IFF_RUNNING); 2583 IFFLAG("NOARP", IFF_NOARP); 2584 IFFLAG("PROMISC", IFF_PROMISC); 2585 IFFLAG("ALLMULTI", IFF_ALLMULTI); 2586 IFFLAG("OACTIVE", IFF_OACTIVE); 2587 IFFLAG("SIMPLEX", IFF_SIMPLEX); 2588 IFFLAG("LINK0", IFF_LINK0); 2589 IFFLAG("LINK1", IFF_LINK1); 2590 IFFLAG("LINK2", IFF_LINK2); 2591 IFFLAG("MULTICAST", IFF_MULTICAST); 2592 #undef IFFLAG 2593 return buf; 2594 } 2595 2596 static void 2597 krtread(int again) 2598 { 2599 int mib[6]; 2600 size_t msize; 2601 char *buf, *p, *lim; 2602 struct rt_msghdr *rtm; 2603 int retry; 2604 const char *errmsg; 2605 2606 retry = 0; 2607 buf = NULL; 2608 mib[0] = CTL_NET; 2609 mib[1] = PF_ROUTE; 2610 mib[2] = 0; 2611 mib[3] = AF_INET6; /* Address family */ 2612 mib[4] = NET_RT_DUMP; /* Dump the kernel routing table */ 2613 mib[5] = 0; /* No flags */ 2614 do { 2615 if (retry) 2616 sleep(1); 2617 retry++; 2618 errmsg = NULL; 2619 if (buf) { 2620 free(buf); 2621 buf = NULL; 2622 } 2623 if (sysctl(mib, nitems(mib), NULL, &msize, NULL, 0) < 0) { 2624 errmsg = "sysctl estimate"; 2625 continue; 2626 } 2627 if ((buf = malloc(msize)) == NULL) { 2628 errmsg = "malloc"; 2629 continue; 2630 } 2631 if (sysctl(mib, nitems(mib), buf, &msize, NULL, 0) < 0) { 2632 errmsg = "sysctl NET_RT_DUMP"; 2633 continue; 2634 } 2635 } while (retry < RT_DUMP_MAXRETRY && errmsg != NULL); 2636 if (errmsg) { 2637 fatal("%s (with %d retries, msize=%lu)", errmsg, retry, 2638 (u_long)msize); 2639 /*NOTREACHED*/ 2640 } else if (1 < retry) 2641 syslog(LOG_INFO, "NET_RT_DUMP %d retires", retry); 2642 2643 lim = buf + msize; 2644 for (p = buf; p < lim; p += rtm->rtm_msglen) { 2645 rtm = (struct rt_msghdr *)(void *)p; 2646 rt_entry(rtm, again); 2647 } 2648 free(buf); 2649 } 2650 2651 static void 2652 rt_entry(struct rt_msghdr *rtm, int again) 2653 { 2654 struct sockaddr_in6 *sin6_dst, *sin6_gw, *sin6_mask; 2655 struct sockaddr_in6 *sin6_genmask, *sin6_ifp; 2656 char *rtmp, *ifname = NULL; 2657 struct riprt *rrt, *orrt; 2658 struct netinfo6 *np; 2659 int ifindex; 2660 2661 sin6_dst = sin6_gw = sin6_mask = sin6_genmask = sin6_ifp = 0; 2662 if ((rtm->rtm_flags & RTF_UP) == 0 || rtm->rtm_flags & 2663 (RTF_XRESOLVE|RTF_BLACKHOLE)) { 2664 return; /* not interested in the link route */ 2665 } 2666 /* do not look at cloned routes */ 2667 #ifdef RTF_WASCLONED 2668 if (rtm->rtm_flags & RTF_WASCLONED) 2669 return; 2670 #endif 2671 #ifdef RTF_CLONED 2672 if (rtm->rtm_flags & RTF_CLONED) 2673 return; 2674 #endif 2675 /* XXX: Ignore connected routes. */ 2676 if (!(rtm->rtm_flags & (RTF_GATEWAY|RTF_HOST|RTF_STATIC))) 2677 return; 2678 /* 2679 * do not look at dynamic routes. 2680 * netbsd/openbsd cloned routes have UGHD. 2681 */ 2682 if (rtm->rtm_flags & RTF_DYNAMIC) 2683 return; 2684 rtmp = (char *)(rtm + 1); 2685 /* Destination */ 2686 if ((rtm->rtm_addrs & RTA_DST) == 0) 2687 return; /* ignore routes without destination address */ 2688 sin6_dst = (struct sockaddr_in6 *)(void *)rtmp; 2689 rtmp += ROUNDUP(sin6_dst->sin6_len); 2690 if (rtm->rtm_addrs & RTA_GATEWAY) { 2691 sin6_gw = (struct sockaddr_in6 *)(void *)rtmp; 2692 rtmp += ROUNDUP(sin6_gw->sin6_len); 2693 } 2694 if (rtm->rtm_addrs & RTA_NETMASK) { 2695 sin6_mask = (struct sockaddr_in6 *)(void *)rtmp; 2696 rtmp += ROUNDUP(sin6_mask->sin6_len); 2697 } 2698 if (rtm->rtm_addrs & RTA_GENMASK) { 2699 sin6_genmask = (struct sockaddr_in6 *)(void *)rtmp; 2700 rtmp += ROUNDUP(sin6_genmask->sin6_len); 2701 } 2702 if (rtm->rtm_addrs & RTA_IFP) { 2703 sin6_ifp = (struct sockaddr_in6 *)(void *)rtmp; 2704 rtmp += ROUNDUP(sin6_ifp->sin6_len); 2705 } 2706 2707 /* Destination */ 2708 if (sin6_dst->sin6_family != AF_INET6) 2709 return; 2710 if (IN6_IS_ADDR_LINKLOCAL(&sin6_dst->sin6_addr)) 2711 return; /* Link-local */ 2712 if (IN6_ARE_ADDR_EQUAL(&sin6_dst->sin6_addr, &in6addr_loopback)) 2713 return; /* Loopback */ 2714 if (IN6_IS_ADDR_MULTICAST(&sin6_dst->sin6_addr)) 2715 return; 2716 2717 if ((rrt = MALLOC(struct riprt)) == NULL) { 2718 fatal("malloc: struct riprt"); 2719 /*NOTREACHED*/ 2720 } 2721 memset(rrt, 0, sizeof(*rrt)); 2722 np = &rrt->rrt_info; 2723 rrt->rrt_same = NULL; 2724 rrt->rrt_t = time(NULL); 2725 if (aflag == 0 && (rtm->rtm_flags & RTF_STATIC)) 2726 rrt->rrt_t = 0; /* Don't age static routes */ 2727 if (rtm->rtm_flags & Pflag) 2728 rrt->rrt_t = 0; /* Don't age PROTO[123] routes */ 2729 if ((rtm->rtm_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST) 2730 rrt->rrt_t = 0; /* Don't age non-gateway host routes */ 2731 np->rip6_tag = 0; 2732 np->rip6_metric = rtm->rtm_rmx.rmx_hopcount; 2733 if (np->rip6_metric < 1) 2734 np->rip6_metric = 1; 2735 rrt->rrt_flags = rtm->rtm_flags; 2736 np->rip6_dest = sin6_dst->sin6_addr; 2737 2738 /* Mask or plen */ 2739 if (rtm->rtm_flags & RTF_HOST) 2740 np->rip6_plen = 128; /* Host route */ 2741 else if (sin6_mask) 2742 np->rip6_plen = sin6mask2len(sin6_mask); 2743 else 2744 np->rip6_plen = 0; 2745 2746 orrt = rtsearch(np); 2747 if (orrt && orrt->rrt_info.rip6_metric != HOPCNT_INFINITY6) { 2748 /* Already found */ 2749 if (!again) { 2750 trace(1, "route: %s/%d flags %s: already registered\n", 2751 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2752 rtflags(rtm)); 2753 } 2754 free(rrt); 2755 return; 2756 } 2757 /* Gateway */ 2758 if (!sin6_gw) 2759 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2760 else { 2761 if (sin6_gw->sin6_family == AF_INET6) 2762 rrt->rrt_gw = sin6_gw->sin6_addr; 2763 else if (sin6_gw->sin6_family == AF_LINK) { 2764 /* XXX in case ppp link? */ 2765 rrt->rrt_gw = in6addr_loopback; 2766 } else 2767 memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr)); 2768 } 2769 trace(1, "route: %s/%d flags %s", 2770 inet6_n2p(&np->rip6_dest), np->rip6_plen, rtflags(rtm)); 2771 trace(1, " gw %s", inet6_n2p(&rrt->rrt_gw)); 2772 2773 /* Interface */ 2774 ifindex = rtm->rtm_index; 2775 if ((unsigned int)ifindex < nindex2ifc && index2ifc[ifindex]) 2776 ifname = index2ifc[ifindex]->ifc_name; 2777 else { 2778 trace(1, " not configured\n"); 2779 free(rrt); 2780 return; 2781 } 2782 trace(1, " if %s sock %d", ifname, ifindex); 2783 rrt->rrt_index = ifindex; 2784 2785 trace(1, "\n"); 2786 2787 /* Check gateway */ 2788 if (!IN6_IS_ADDR_LINKLOCAL(&rrt->rrt_gw) && 2789 !IN6_IS_ADDR_LOOPBACK(&rrt->rrt_gw) && 2790 (rrt->rrt_flags & RTF_LOCAL) == 0) { 2791 trace(0, "***** Gateway %s is not a link-local address.\n", 2792 inet6_n2p(&rrt->rrt_gw)); 2793 trace(0, "***** dest(%s) if(%s) -- Not optimized.\n", 2794 inet6_n2p(&rrt->rrt_info.rip6_dest), ifname); 2795 rrt->rrt_rflags |= RRTF_NH_NOT_LLADDR; 2796 } 2797 2798 /* Put it to the route list */ 2799 if (orrt && orrt->rrt_info.rip6_metric == HOPCNT_INFINITY6) { 2800 /* replace route list */ 2801 TAILQ_INSERT_BEFORE(orrt, rrt, rrt_next); 2802 TAILQ_REMOVE(&riprt_head, orrt, rrt_next); 2803 2804 trace(1, "route: %s/%d flags %s: replace new route\n", 2805 inet6_n2p(&np->rip6_dest), np->rip6_plen, 2806 rtflags(rtm)); 2807 free(orrt); 2808 } else 2809 TAILQ_INSERT_HEAD(&riprt_head, rrt, rrt_next); 2810 } 2811 2812 static int 2813 addroute(struct riprt *rrt, 2814 const struct in6_addr *gw, 2815 struct ifc *ifcp) 2816 { 2817 struct netinfo6 *np; 2818 u_char buf[BUFSIZ], buf1[BUFSIZ], buf2[BUFSIZ]; 2819 struct rt_msghdr *rtm; 2820 struct sockaddr_in6 *sin6; 2821 int len; 2822 2823 np = &rrt->rrt_info; 2824 inet_ntop(AF_INET6, (const void *)gw, (char *)buf1, sizeof(buf1)); 2825 inet_ntop(AF_INET6, (void *)&ifcp->ifc_mylladdr, (char *)buf2, sizeof(buf2)); 2826 tracet(1, "ADD: %s/%d gw %s [%d] ifa %s\n", 2827 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2828 np->rip6_metric - 1, buf2); 2829 if (rtlog) 2830 fprintf(rtlog, "%s: ADD: %s/%d gw %s [%d] ifa %s\n", hms(), 2831 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1, 2832 np->rip6_metric - 1, buf2); 2833 if (nflag) 2834 return 0; 2835 2836 memset(buf, 0, sizeof(buf)); 2837 rtm = (struct rt_msghdr *)(void *)buf; 2838 rtm->rtm_type = RTM_ADD; 2839 rtm->rtm_version = RTM_VERSION; 2840 rtm->rtm_seq = ++seq; 2841 rtm->rtm_pid = pid; 2842 rtm->rtm_flags = rrt->rrt_flags; 2843 rtm->rtm_flags |= Qflag; 2844 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2845 rtm->rtm_rmx.rmx_hopcount = np->rip6_metric - 1; 2846 rtm->rtm_inits = RTV_HOPCOUNT; 2847 sin6 = (struct sockaddr_in6 *)(void *)&buf[sizeof(struct rt_msghdr)]; 2848 /* Destination */ 2849 sin6->sin6_len = sizeof(struct sockaddr_in6); 2850 sin6->sin6_family = AF_INET6; 2851 sin6->sin6_addr = np->rip6_dest; 2852 sin6 = (struct sockaddr_in6 *)(void *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2853 /* Gateway */ 2854 sin6->sin6_len = sizeof(struct sockaddr_in6); 2855 sin6->sin6_family = AF_INET6; 2856 sin6->sin6_addr = *gw; 2857 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 2858 sin6->sin6_scope_id = ifcp->ifc_index; 2859 sin6 = (struct sockaddr_in6 *)(void *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2860 /* Netmask */ 2861 sin6->sin6_len = sizeof(struct sockaddr_in6); 2862 sin6->sin6_family = AF_INET6; 2863 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2864 sin6 = (struct sockaddr_in6 *)(void *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2865 2866 len = (char *)sin6 - (char *)buf; 2867 rtm->rtm_msglen = len; 2868 if (write(rtsock, buf, len) > 0) 2869 return 0; 2870 2871 if (errno == EEXIST) { 2872 trace(0, "ADD: Route already exists %s/%d gw %s\n", 2873 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2874 if (rtlog) 2875 fprintf(rtlog, "ADD: Route already exists %s/%d gw %s\n", 2876 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf1); 2877 } else { 2878 trace(0, "Can not write to rtsock (addroute): %s\n", 2879 strerror(errno)); 2880 if (rtlog) 2881 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2882 strerror(errno)); 2883 } 2884 return -1; 2885 } 2886 2887 static int 2888 delroute(struct netinfo6 *np, struct in6_addr *gw) 2889 { 2890 u_char buf[BUFSIZ], buf2[BUFSIZ]; 2891 struct rt_msghdr *rtm; 2892 struct sockaddr_in6 *sin6; 2893 int len; 2894 2895 inet_ntop(AF_INET6, (void *)gw, (char *)buf2, sizeof(buf2)); 2896 tracet(1, "DEL: %s/%d gw %s\n", inet6_n2p(&np->rip6_dest), 2897 np->rip6_plen, buf2); 2898 if (rtlog) 2899 fprintf(rtlog, "%s: DEL: %s/%d gw %s\n", 2900 hms(), inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2901 if (nflag) 2902 return 0; 2903 2904 memset(buf, 0, sizeof(buf)); 2905 rtm = (struct rt_msghdr *)(void *)buf; 2906 rtm->rtm_type = RTM_DELETE; 2907 rtm->rtm_version = RTM_VERSION; 2908 rtm->rtm_seq = ++seq; 2909 rtm->rtm_pid = pid; 2910 rtm->rtm_flags = RTF_UP | RTF_GATEWAY; 2911 rtm->rtm_flags |= Qflag; 2912 if (np->rip6_plen == sizeof(struct in6_addr) * 8) 2913 rtm->rtm_flags |= RTF_HOST; 2914 rtm->rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 2915 sin6 = (struct sockaddr_in6 *)(void *)&buf[sizeof(struct rt_msghdr)]; 2916 /* Destination */ 2917 sin6->sin6_len = sizeof(struct sockaddr_in6); 2918 sin6->sin6_family = AF_INET6; 2919 sin6->sin6_addr = np->rip6_dest; 2920 sin6 = (struct sockaddr_in6 *)(void *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2921 /* Gateway */ 2922 sin6->sin6_len = sizeof(struct sockaddr_in6); 2923 sin6->sin6_family = AF_INET6; 2924 sin6->sin6_addr = *gw; 2925 sin6 = (struct sockaddr_in6 *)(void *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2926 /* Netmask */ 2927 sin6->sin6_len = sizeof(struct sockaddr_in6); 2928 sin6->sin6_family = AF_INET6; 2929 sin6->sin6_addr = *(plen2mask(np->rip6_plen)); 2930 sin6 = (struct sockaddr_in6 *)(void *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2931 2932 len = (char *)sin6 - (char *)buf; 2933 rtm->rtm_msglen = len; 2934 if (write(rtsock, buf, len) >= 0) 2935 return 0; 2936 2937 if (errno == ESRCH) { 2938 trace(0, "RTDEL: Route does not exist: %s/%d gw %s\n", 2939 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2940 if (rtlog) 2941 fprintf(rtlog, "RTDEL: Route does not exist: %s/%d gw %s\n", 2942 inet6_n2p(&np->rip6_dest), np->rip6_plen, buf2); 2943 } else { 2944 trace(0, "Can not write to rtsock (delroute): %s\n", 2945 strerror(errno)); 2946 if (rtlog) 2947 fprintf(rtlog, "\tCan not write to rtsock: %s\n", 2948 strerror(errno)); 2949 } 2950 return -1; 2951 } 2952 2953 #if 0 2954 static struct in6_addr * 2955 getroute(struct netinfo6 *np, struct in6_addr *gw) 2956 { 2957 u_char buf[BUFSIZ]; 2958 int myseq; 2959 int len; 2960 struct rt_msghdr *rtm; 2961 struct sockaddr_in6 *sin6; 2962 2963 rtm = (struct rt_msghdr *)(void *)buf; 2964 len = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in6); 2965 memset(rtm, 0, len); 2966 rtm->rtm_type = RTM_GET; 2967 rtm->rtm_version = RTM_VERSION; 2968 myseq = ++seq; 2969 rtm->rtm_seq = myseq; 2970 rtm->rtm_addrs = RTA_DST; 2971 rtm->rtm_msglen = len; 2972 sin6 = (struct sockaddr_in6 *)(void *)&buf[sizeof(struct rt_msghdr)]; 2973 sin6->sin6_len = sizeof(struct sockaddr_in6); 2974 sin6->sin6_family = AF_INET6; 2975 sin6->sin6_addr = np->rip6_dest; 2976 if (write(rtsock, buf, len) < 0) { 2977 if (errno == ESRCH) /* No such route found */ 2978 return NULL; 2979 perror("write to rtsock"); 2980 exit(1); 2981 } 2982 do { 2983 if ((len = read(rtsock, buf, sizeof(buf))) < 0) { 2984 perror("read from rtsock"); 2985 exit(1); 2986 } 2987 rtm = (struct rt_msghdr *)(void *)buf; 2988 } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != myseq || 2989 rtm->rtm_pid != pid); 2990 sin6 = (struct sockaddr_in6 *)(void *)&buf[sizeof(struct rt_msghdr)]; 2991 if (rtm->rtm_addrs & RTA_DST) { 2992 sin6 = (struct sockaddr_in6 *)(void *) 2993 ((char *)sin6 + ROUNDUP(sin6->sin6_len)); 2994 } 2995 if (rtm->rtm_addrs & RTA_GATEWAY) { 2996 *gw = sin6->sin6_addr; 2997 return gw; 2998 } 2999 return NULL; 3000 } 3001 #endif 3002 3003 static const char * 3004 inet6_n2p(const struct in6_addr *p) 3005 { 3006 static char buf[BUFSIZ]; 3007 3008 return inet_ntop(AF_INET6, (const void *)p, buf, sizeof(buf)); 3009 } 3010 3011 static void 3012 ifrtdump(int sig) 3013 { 3014 3015 ifdump(sig); 3016 rtdump(sig); 3017 } 3018 3019 static void 3020 ifdump(int sig) 3021 { 3022 struct ifc *ifcp; 3023 FILE *dump; 3024 int nifc = 0; 3025 3026 if (sig == 0) 3027 dump = stderr; 3028 else 3029 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 3030 dump = stderr; 3031 3032 fprintf(dump, "%s: Interface Table Dump\n", hms()); 3033 TAILQ_FOREACH(ifcp, &ifc_head, ifc_next) 3034 nifc++; 3035 fprintf(dump, " Number of interfaces: %d\n", nifc); 3036 3037 fprintf(dump, " advertising interfaces:\n"); 3038 TAILQ_FOREACH(ifcp, &ifc_head, ifc_next) { 3039 if ((ifcp->ifc_flags & IFF_UP) == 0) 3040 continue; 3041 if (iff_find(ifcp, IFIL_TYPE_N) != NULL) 3042 continue; 3043 ifdump0(dump, ifcp); 3044 } 3045 fprintf(dump, "\n"); 3046 fprintf(dump, " non-advertising interfaces:\n"); 3047 TAILQ_FOREACH(ifcp, &ifc_head, ifc_next) { 3048 if ((ifcp->ifc_flags & IFF_UP) && 3049 (iff_find(ifcp, IFIL_TYPE_N) == NULL)) 3050 continue; 3051 ifdump0(dump, ifcp); 3052 } 3053 fprintf(dump, "\n"); 3054 if (dump != stderr) 3055 fclose(dump); 3056 } 3057 3058 static void 3059 ifdump0(FILE *dump, const struct ifc *ifcp) 3060 { 3061 struct ifac *ifac; 3062 struct iff *iffp; 3063 char buf[BUFSIZ]; 3064 const char *ft; 3065 int addr; 3066 3067 fprintf(dump, " %s: index(%d) flags(%s) addr(%s) mtu(%d) metric(%d)\n", 3068 ifcp->ifc_name, ifcp->ifc_index, ifflags(ifcp->ifc_flags), 3069 inet6_n2p(&ifcp->ifc_mylladdr), 3070 ifcp->ifc_mtu, ifcp->ifc_metric); 3071 TAILQ_FOREACH(ifac, &ifcp->ifc_ifac_head, ifac_next) { 3072 if (ifcp->ifc_flags & IFF_POINTOPOINT) { 3073 inet_ntop(AF_INET6, (void *)&ifac->ifac_raddr, 3074 buf, sizeof(buf)); 3075 fprintf(dump, "\t%s/%d -- %s\n", 3076 inet6_n2p(&ifac->ifac_addr), 3077 ifac->ifac_plen, buf); 3078 } else { 3079 fprintf(dump, "\t%s/%d\n", 3080 inet6_n2p(&ifac->ifac_addr), 3081 ifac->ifac_plen); 3082 } 3083 } 3084 3085 fprintf(dump, "\tFilter:\n"); 3086 TAILQ_FOREACH(iffp, &ifcp->ifc_iff_head, iff_next) { 3087 addr = 0; 3088 switch (iffp->iff_type) { 3089 case IFIL_TYPE_A: 3090 ft = "Aggregate"; addr++; break; 3091 case IFIL_TYPE_N: 3092 ft = "No-use"; break; 3093 case IFIL_TYPE_O: 3094 ft = "Advertise-only"; addr++; break; 3095 case IFIL_TYPE_T: 3096 ft = "Default-only"; break; 3097 case IFIL_TYPE_L: 3098 ft = "Listen-only"; addr++; break; 3099 default: 3100 snprintf(buf, sizeof(buf), "Unknown-%c", iffp->iff_type); 3101 ft = buf; 3102 addr++; 3103 break; 3104 } 3105 fprintf(dump, "\t\t%s", ft); 3106 if (addr) 3107 fprintf(dump, "(%s/%d)", inet6_n2p(&iffp->iff_addr), 3108 iffp->iff_plen); 3109 fprintf(dump, "\n"); 3110 } 3111 fprintf(dump, "\n"); 3112 } 3113 3114 static void 3115 rtdump(int sig) 3116 { 3117 struct riprt *rrt; 3118 char buf[BUFSIZ]; 3119 FILE *dump; 3120 time_t t, age; 3121 3122 if (sig == 0) 3123 dump = stderr; 3124 else 3125 if ((dump = fopen(ROUTE6D_DUMP, "a")) == NULL) 3126 dump = stderr; 3127 3128 t = time(NULL); 3129 fprintf(dump, "\n%s: Routing Table Dump\n", hms()); 3130 TAILQ_FOREACH(rrt, &riprt_head, rrt_next) { 3131 if (rrt->rrt_t == 0) 3132 age = 0; 3133 else 3134 age = t - rrt->rrt_t; 3135 inet_ntop(AF_INET6, (void *)&rrt->rrt_info.rip6_dest, 3136 buf, sizeof(buf)); 3137 fprintf(dump, " %s/%d if(%d:%s) gw(%s) [%d] age(%ld)", 3138 buf, rrt->rrt_info.rip6_plen, rrt->rrt_index, 3139 index2ifc[rrt->rrt_index]->ifc_name, 3140 inet6_n2p(&rrt->rrt_gw), 3141 rrt->rrt_info.rip6_metric, (long)age); 3142 if (rrt->rrt_info.rip6_tag) { 3143 fprintf(dump, " tag(0x%04x)", 3144 ntohs(rrt->rrt_info.rip6_tag) & 0xffff); 3145 } 3146 if (rrt->rrt_rflags & RRTF_NH_NOT_LLADDR) 3147 fprintf(dump, " NOT-LL"); 3148 if (rrt->rrt_rflags & RRTF_NOADVERTISE) 3149 fprintf(dump, " NO-ADV"); 3150 fprintf(dump, "\n"); 3151 } 3152 fprintf(dump, "\n"); 3153 if (dump != stderr) 3154 fclose(dump); 3155 } 3156 3157 /* 3158 * Parse the -A (and -O) options and put corresponding filter object to the 3159 * specified interface structures. Each of the -A/O option has the following 3160 * syntax: -A 5f09:c400::/32,ef0,ef1 (aggregate) 3161 * -O 5f09:c400::/32,ef0,ef1 (only when match) 3162 */ 3163 static void 3164 filterconfig(void) 3165 { 3166 int i; 3167 char *p, *ap, *iflp, *ifname, *ep; 3168 struct iff iff, *iffp; 3169 struct ifc *ifcp; 3170 struct riprt *rrt; 3171 #if 0 3172 struct in6_addr gw; 3173 #endif 3174 u_long plen; 3175 3176 for (i = 0; i < nfilter; i++) { 3177 ap = filter[i]; 3178 iflp = NULL; 3179 iffp = ⇔ 3180 memset(iffp, 0, sizeof(*iffp)); 3181 if (filtertype[i] == 'N' || filtertype[i] == 'T') { 3182 iflp = ap; 3183 goto ifonly; 3184 } 3185 if ((p = strchr(ap, ',')) != NULL) { 3186 *p++ = '\0'; 3187 iflp = p; 3188 } 3189 if ((p = strchr(ap, '/')) == NULL) { 3190 fatal("no prefixlen specified for '%s'", ap); 3191 /*NOTREACHED*/ 3192 } 3193 *p++ = '\0'; 3194 if (inet_pton(AF_INET6, ap, &iffp->iff_addr) != 1) { 3195 fatal("invalid prefix specified for '%s'", ap); 3196 /*NOTREACHED*/ 3197 } 3198 errno = 0; 3199 ep = NULL; 3200 plen = strtoul(p, &ep, 10); 3201 if (errno || !*p || *ep || plen > sizeof(iffp->iff_addr) * 8) { 3202 fatal("invalid prefix length specified for '%s'", ap); 3203 /*NOTREACHED*/ 3204 } 3205 iffp->iff_plen = plen; 3206 applyplen(&iffp->iff_addr, iffp->iff_plen); 3207 ifonly: 3208 iffp->iff_type = filtertype[i]; 3209 if (iflp == NULL || *iflp == '\0') { 3210 fatal("no interface specified for '%s'", ap); 3211 /*NOTREACHED*/ 3212 } 3213 /* parse the interface listing portion */ 3214 while (iflp) { 3215 ifname = iflp; 3216 if ((iflp = strchr(iflp, ',')) != NULL) 3217 *iflp++ = '\0'; 3218 3219 TAILQ_FOREACH(ifcp, &ifc_head, ifc_next) { 3220 if (fnmatch(ifname, ifcp->ifc_name, 0) != 0) 3221 continue; 3222 3223 iffp = malloc(sizeof(*iffp)); 3224 if (iffp == NULL) { 3225 fatal("malloc of iff"); 3226 /*NOTREACHED*/ 3227 } 3228 memcpy(iffp, &iff, sizeof(*iffp)); 3229 #if 0 3230 syslog(LOG_INFO, "Add filter: type %d, ifname %s.", iffp->iff_type, ifname); 3231 #endif 3232 TAILQ_INSERT_HEAD(&ifcp->ifc_iff_head, iffp, iff_next); 3233 } 3234 } 3235 3236 /* 3237 * -A: aggregate configuration. 3238 */ 3239 if (filtertype[i] != IFIL_TYPE_A) 3240 continue; 3241 /* put the aggregate to the kernel routing table */ 3242 rrt = (struct riprt *)malloc(sizeof(struct riprt)); 3243 if (rrt == NULL) { 3244 fatal("malloc: rrt"); 3245 /*NOTREACHED*/ 3246 } 3247 memset(rrt, 0, sizeof(struct riprt)); 3248 rrt->rrt_info.rip6_dest = iff.iff_addr; 3249 rrt->rrt_info.rip6_plen = iff.iff_plen; 3250 rrt->rrt_info.rip6_metric = 1; 3251 rrt->rrt_info.rip6_tag = htons(routetag & 0xffff); 3252 rrt->rrt_gw = in6addr_loopback; 3253 rrt->rrt_flags = RTF_UP | RTF_REJECT; 3254 rrt->rrt_rflags = RRTF_AGGREGATE; 3255 rrt->rrt_t = 0; 3256 rrt->rrt_index = loopifcp->ifc_index; 3257 #if 0 3258 if (getroute(&rrt->rrt_info, &gw)) { 3259 #if 0 3260 /* 3261 * When the address has already been registered in the 3262 * kernel routing table, it should be removed 3263 */ 3264 delroute(&rrt->rrt_info, &gw); 3265 #else 3266 /* it is safer behavior */ 3267 errno = EINVAL; 3268 fatal("%s/%u already in routing table, " 3269 "cannot aggregate", 3270 inet6_n2p(&rrt->rrt_info.rip6_dest), 3271 rrt->rrt_info.rip6_plen); 3272 /*NOTREACHED*/ 3273 #endif 3274 } 3275 #endif 3276 /* Put the route to the list */ 3277 TAILQ_INSERT_HEAD(&riprt_head, rrt, rrt_next); 3278 trace(1, "Aggregate: %s/%d for %s\n", 3279 inet6_n2p(&iff.iff_addr), iff.iff_plen, 3280 loopifcp->ifc_name); 3281 /* Add this route to the kernel */ 3282 if (nflag) /* do not modify kernel routing table */ 3283 continue; 3284 addroute(rrt, &in6addr_loopback, loopifcp); 3285 } 3286 } 3287 3288 /***************** utility functions *****************/ 3289 3290 /* 3291 * Returns a pointer to ifac whose address and prefix length matches 3292 * with the address and prefix length specified in the arguments. 3293 */ 3294 static struct ifac * 3295 ifa_match(const struct ifc *ifcp, 3296 const struct in6_addr *ia, 3297 int plen) 3298 { 3299 struct ifac *ifac; 3300 3301 TAILQ_FOREACH(ifac, &ifcp->ifc_ifac_head, ifac_next) { 3302 if (IN6_ARE_ADDR_EQUAL(&ifac->ifac_addr, ia) && 3303 ifac->ifac_plen == plen) 3304 break; 3305 } 3306 3307 return (ifac); 3308 } 3309 3310 /* 3311 * Return a pointer to riprt structure whose address and prefix length 3312 * matches with the address and prefix length found in the argument. 3313 * Note: This is not a rtalloc(). Therefore exact match is necessary. 3314 */ 3315 static struct riprt * 3316 rtsearch(struct netinfo6 *np) 3317 { 3318 struct riprt *rrt; 3319 3320 TAILQ_FOREACH(rrt, &riprt_head, rrt_next) { 3321 if (rrt->rrt_info.rip6_plen == np->rip6_plen && 3322 IN6_ARE_ADDR_EQUAL(&rrt->rrt_info.rip6_dest, 3323 &np->rip6_dest)) 3324 break; 3325 } 3326 3327 return (rrt); 3328 } 3329 3330 static int 3331 sin6mask2len(const struct sockaddr_in6 *sin6) 3332 { 3333 3334 return mask2len(&sin6->sin6_addr, 3335 sin6->sin6_len - offsetof(struct sockaddr_in6, sin6_addr)); 3336 } 3337 3338 static int 3339 mask2len(const struct in6_addr *addr, int lenlim) 3340 { 3341 int i = 0, j; 3342 const u_char *p = (const u_char *)addr; 3343 3344 for (j = 0; j < lenlim; j++, p++) { 3345 if (*p != 0xff) 3346 break; 3347 i += 8; 3348 } 3349 if (j < lenlim) { 3350 switch (*p) { 3351 #define MASKLEN(m, l) case m: do { i += l; break; } while (0) 3352 MASKLEN(0xfe, 7); break; 3353 MASKLEN(0xfc, 6); break; 3354 MASKLEN(0xf8, 5); break; 3355 MASKLEN(0xf0, 4); break; 3356 MASKLEN(0xe0, 3); break; 3357 MASKLEN(0xc0, 2); break; 3358 MASKLEN(0x80, 1); break; 3359 #undef MASKLEN 3360 } 3361 } 3362 return i; 3363 } 3364 3365 static const u_char plent[8] = { 3366 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe 3367 }; 3368 3369 static void 3370 applyplen(struct in6_addr *ia, int plen) 3371 { 3372 u_char *p; 3373 int i; 3374 3375 p = ia->s6_addr; 3376 for (i = 0; i < 16; i++) { 3377 if (plen <= 0) 3378 *p = 0; 3379 else if (plen < 8) 3380 *p &= plent[plen]; 3381 p++, plen -= 8; 3382 } 3383 } 3384 3385 static const int pl2m[9] = { 3386 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff 3387 }; 3388 3389 static struct in6_addr * 3390 plen2mask(int n) 3391 { 3392 static struct in6_addr ia; 3393 u_char *p; 3394 int i; 3395 3396 memset(&ia, 0, sizeof(struct in6_addr)); 3397 p = (u_char *)&ia; 3398 for (i = 0; i < 16; i++, p++, n -= 8) { 3399 if (n >= 8) { 3400 *p = 0xff; 3401 continue; 3402 } 3403 *p = pl2m[n]; 3404 break; 3405 } 3406 return &ia; 3407 } 3408 3409 static char * 3410 allocopy(char *p) 3411 { 3412 int len = strlen(p) + 1; 3413 char *q = (char *)malloc(len); 3414 3415 if (!q) { 3416 fatal("malloc"); 3417 /*NOTREACHED*/ 3418 } 3419 3420 strlcpy(q, p, len); 3421 return q; 3422 } 3423 3424 static char * 3425 hms(void) 3426 { 3427 static char buf[BUFSIZ]; 3428 time_t t; 3429 struct tm *tm; 3430 3431 t = time(NULL); 3432 if ((tm = localtime(&t)) == 0) { 3433 fatal("localtime"); 3434 /*NOTREACHED*/ 3435 } 3436 snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, 3437 tm->tm_sec); 3438 return buf; 3439 } 3440 3441 #define RIPRANDDEV 1.0 /* 30 +- 15, max - min = 30 */ 3442 3443 static int 3444 ripinterval(int timer) 3445 { 3446 double r = rand(); 3447 3448 interval = (int)(timer + timer * RIPRANDDEV * (r / RAND_MAX - 0.5)); 3449 nextalarm = time(NULL) + interval; 3450 return interval; 3451 } 3452 3453 #if 0 3454 static time_t 3455 ripsuptrig(void) 3456 { 3457 time_t t; 3458 3459 double r = rand(); 3460 t = (int)(RIP_TRIG_INT6_MIN + 3461 (RIP_TRIG_INT6_MAX - RIP_TRIG_INT6_MIN) * (r / RAND_MAX)); 3462 sup_trig_update = time(NULL) + t; 3463 return t; 3464 } 3465 #endif 3466 3467 static void 3468 fatal(const char *fmt, ...) 3469 { 3470 va_list ap; 3471 char buf[1024]; 3472 3473 va_start(ap, fmt); 3474 vsnprintf(buf, sizeof(buf), fmt, ap); 3475 va_end(ap); 3476 perror(buf); 3477 if (errno) 3478 syslog(LOG_ERR, "%s: %s", buf, strerror(errno)); 3479 else 3480 syslog(LOG_ERR, "%s", buf); 3481 rtdexit(); 3482 } 3483 3484 static void 3485 tracet(int level, const char *fmt, ...) 3486 { 3487 va_list ap; 3488 3489 if (level <= dflag) { 3490 va_start(ap, fmt); 3491 fprintf(stderr, "%s: ", hms()); 3492 vfprintf(stderr, fmt, ap); 3493 va_end(ap); 3494 } 3495 if (dflag) { 3496 va_start(ap, fmt); 3497 if (level > 0) 3498 vsyslog(LOG_DEBUG, fmt, ap); 3499 else 3500 vsyslog(LOG_WARNING, fmt, ap); 3501 va_end(ap); 3502 } 3503 } 3504 3505 static void 3506 trace(int level, const char *fmt, ...) 3507 { 3508 va_list ap; 3509 3510 if (level <= dflag) { 3511 va_start(ap, fmt); 3512 vfprintf(stderr, fmt, ap); 3513 va_end(ap); 3514 } 3515 if (dflag) { 3516 va_start(ap, fmt); 3517 if (level > 0) 3518 vsyslog(LOG_DEBUG, fmt, ap); 3519 else 3520 vsyslog(LOG_WARNING, fmt, ap); 3521 va_end(ap); 3522 } 3523 } 3524 3525 static struct ifc * 3526 ifc_find(char *name) 3527 { 3528 struct ifc *ifcp; 3529 3530 TAILQ_FOREACH(ifcp, &ifc_head, ifc_next) { 3531 if (strcmp(name, ifcp->ifc_name) == 0) 3532 break; 3533 } 3534 return (ifcp); 3535 } 3536 3537 static struct iff * 3538 iff_find(struct ifc *ifcp, int type) 3539 { 3540 struct iff *iffp; 3541 3542 TAILQ_FOREACH(iffp, &ifcp->ifc_iff_head, iff_next) { 3543 if (type == IFIL_TYPE_ANY || 3544 type == iffp->iff_type) 3545 break; 3546 } 3547 3548 return (iffp); 3549 } 3550 3551 static void 3552 setindex2ifc(int idx, struct ifc *ifcp) 3553 { 3554 int n, nsize; 3555 struct ifc **p; 3556 3557 if (!index2ifc) { 3558 nindex2ifc = 5; /*initial guess*/ 3559 index2ifc = (struct ifc **) 3560 malloc(sizeof(*index2ifc) * nindex2ifc); 3561 if (index2ifc == NULL) { 3562 fatal("malloc"); 3563 /*NOTREACHED*/ 3564 } 3565 memset(index2ifc, 0, sizeof(*index2ifc) * nindex2ifc); 3566 } 3567 n = nindex2ifc; 3568 for (nsize = nindex2ifc; nsize <= idx; nsize *= 2) 3569 ; 3570 if (n != nsize) { 3571 p = (struct ifc **)realloc(index2ifc, 3572 sizeof(*index2ifc) * nsize); 3573 if (p == NULL) { 3574 fatal("realloc"); 3575 /*NOTREACHED*/ 3576 } 3577 memset(p + n, 0, sizeof(*index2ifc) * (nindex2ifc - n)); 3578 index2ifc = p; 3579 nindex2ifc = nsize; 3580 } 3581 index2ifc[idx] = ifcp; 3582 } 3583