1 /* $KAME: rtsold.c,v 1.67 2003/05/17 18:16:15 itojun Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the project nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD$ 34 */ 35 36 #include <sys/param.h> 37 #include <sys/capsicum.h> 38 #include <sys/event.h> 39 #include <sys/ioctl.h> 40 #include <sys/socket.h> 41 42 #include <net/if.h> 43 #include <net/if_dl.h> 44 45 #include <netinet/in.h> 46 #include <netinet/icmp6.h> 47 #include <netinet/in_var.h> 48 #include <arpa/inet.h> 49 50 #include <netinet6/nd6.h> 51 52 #include <capsicum_helpers.h> 53 #include <err.h> 54 #include <errno.h> 55 #include <ifaddrs.h> 56 #include <libgen.h> 57 #include <signal.h> 58 #include <stdarg.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <syslog.h> 63 #include <time.h> 64 #include <unistd.h> 65 66 #include <libcasper.h> 67 #include <casper/cap_syslog.h> 68 #include <libutil.h> 69 70 #include "rtsold.h" 71 72 #define RTSOL_DUMPFILE "/var/run/rtsold.dump" 73 74 struct timespec tm_max; 75 static int log_upto = 999; 76 static int fflag = 0; 77 78 int Fflag = 0; /* force setting sysctl parameters */ 79 int aflag = 0; 80 int dflag = 0; 81 int uflag = 0; 82 83 const char *otherconf_script; 84 const char *resolvconf_script = "/sbin/resolvconf"; 85 86 cap_channel_t *capllflags, *capscript, *capsendmsg, *capsyslog; 87 88 /* protocol constants */ 89 #define MAX_RTR_SOLICITATION_DELAY 1 /* second */ 90 #define RTR_SOLICITATION_INTERVAL 4 /* seconds */ 91 #define MAX_RTR_SOLICITATIONS 3 /* times */ 92 93 /* 94 * implementation dependent constants in seconds 95 * XXX: should be configurable 96 */ 97 #define PROBE_INTERVAL 60 98 99 /* static variables and functions */ 100 static int mobile_node = 0; 101 102 static sig_atomic_t do_dump, do_exit; 103 static struct pidfh *pfh; 104 105 static char **autoifprobe(void); 106 static int ifconfig(char *ifname); 107 static int init_capabilities(void); 108 static int make_packet(struct ifinfo *); 109 static struct timespec *rtsol_check_timer(void); 110 111 static void set_dumpfile(int); 112 static void set_exit(int); 113 static void usage(const char *progname); 114 115 int 116 main(int argc, char **argv) 117 { 118 struct kevent events[2]; 119 FILE *dumpfp; 120 struct ifinfo *ifi; 121 struct timespec *timeout; 122 const char *opts, *pidfilepath, *progname; 123 int ch, error, kq, once, rcvsock, rtsock; 124 125 progname = basename(argv[0]); 126 if (strcmp(progname, "rtsold") == 0) { 127 opts = "adDfFm1O:p:R:u"; 128 once = 0; 129 pidfilepath = NULL; 130 } else { 131 opts = "adDFO:R:u"; 132 fflag = 1; 133 once = 1; 134 } 135 136 while ((ch = getopt(argc, argv, opts)) != -1) { 137 switch (ch) { 138 case 'a': 139 aflag = 1; 140 break; 141 case 'd': 142 dflag += 1; 143 break; 144 case 'D': 145 dflag += 2; 146 break; 147 case 'f': 148 fflag = 1; 149 break; 150 case 'F': 151 Fflag = 1; 152 break; 153 case 'm': 154 mobile_node = 1; 155 break; 156 case '1': 157 once = 1; 158 break; 159 case 'O': 160 otherconf_script = optarg; 161 break; 162 case 'p': 163 pidfilepath = optarg; 164 break; 165 case 'R': 166 resolvconf_script = optarg; 167 break; 168 case 'u': 169 uflag = 1; 170 break; 171 default: 172 usage(progname); 173 } 174 } 175 argc -= optind; 176 argv += optind; 177 178 if ((!aflag && argc == 0) || (aflag && argc != 0)) 179 usage(progname); 180 181 /* Generate maximum time in timespec. */ 182 tm_max.tv_sec = (-1) & ~((time_t)1 << ((sizeof(tm_max.tv_sec) * 8) - 1)); 183 tm_max.tv_nsec = (-1) & ~((long)1 << ((sizeof(tm_max.tv_nsec) * 8) - 1)); 184 185 /* set log level */ 186 if (dflag > 1) 187 log_upto = LOG_DEBUG; 188 else if (dflag > 0) 189 log_upto = LOG_INFO; 190 else 191 log_upto = LOG_NOTICE; 192 193 if (otherconf_script != NULL && *otherconf_script != '/') 194 errx(1, "configuration script (%s) must be an absolute path", 195 otherconf_script); 196 if (*resolvconf_script != '/') 197 errx(1, "configuration script (%s) must be an absolute path", 198 resolvconf_script); 199 200 if (!fflag) { 201 pfh = pidfile_open(pidfilepath, 0644, NULL); 202 if (pfh == NULL) 203 errx(1, "failed to open pidfile: %s", strerror(errno)); 204 if (daemon(0, 0) != 0) 205 errx(1, "failed to daemonize"); 206 } 207 208 if ((error = init_capabilities()) != 0) 209 err(1, "failed to initialize capabilities"); 210 211 if (!fflag) { 212 cap_openlog(capsyslog, progname, LOG_NDELAY | LOG_PID, 213 LOG_DAEMON); 214 if (log_upto >= 0) 215 (void)cap_setlogmask(capsyslog, LOG_UPTO(log_upto)); 216 (void)signal(SIGTERM, set_exit); 217 (void)signal(SIGINT, set_exit); 218 (void)signal(SIGUSR1, set_dumpfile); 219 dumpfp = rtsold_init_dumpfile(RTSOL_DUMPFILE); 220 } else 221 dumpfp = NULL; 222 223 kq = kqueue(); 224 if (kq < 0) { 225 warnmsg(LOG_ERR, __func__, "failed to create a kqueue: %s", 226 strerror(errno)); 227 exit(1); 228 } 229 230 /* Open global sockets and register for read events. */ 231 if ((rtsock = rtsock_open()) < 0) { 232 warnmsg(LOG_ERR, __func__, "failed to open routing socket"); 233 exit(1); 234 } 235 if ((rcvsock = recvsockopen()) < 0) { 236 warnmsg(LOG_ERR, __func__, "failed to open receive socket"); 237 exit(1); 238 } 239 EV_SET(&events[0], rtsock, EVFILT_READ, EV_ADD, 0, 0, NULL); 240 EV_SET(&events[1], rcvsock, EVFILT_READ, EV_ADD, 0, 0, NULL); 241 if (kevent(kq, events, 2, NULL, 0, NULL) < 0) { 242 warnmsg(LOG_ERR, __func__, "kevent(): %s", strerror(errno)); 243 exit(1); 244 } 245 246 /* Probe network interfaces and set up tracking info. */ 247 if (ifinit() != 0) { 248 warnmsg(LOG_ERR, __func__, "failed to initialize interfaces"); 249 exit(1); 250 } 251 if (aflag) 252 argv = autoifprobe(); 253 while (argv && *argv) { 254 if (ifconfig(*argv)) { 255 warnmsg(LOG_ERR, __func__, 256 "failed to initialize %s", *argv); 257 exit(1); 258 } 259 argv++; 260 } 261 262 /* Write to our pidfile. */ 263 if (pfh != NULL && pidfile_write(pfh) != 0) { 264 warnmsg(LOG_ERR, __func__, 265 "failed to open pidfile: %s", strerror(errno)); 266 exit(1); 267 } 268 269 /* Enter capability mode. */ 270 caph_cache_catpages(); 271 if (caph_enter_casper() != 0) { 272 warnmsg(LOG_ERR, __func__, "caph_enter(): %s", strerror(errno)); 273 exit(1); 274 } 275 276 for (;;) { 277 if (do_exit) { 278 /* Handle SIGTERM, SIGINT. */ 279 if (pfh != NULL) 280 pidfile_remove(pfh); 281 break; 282 } 283 if (do_dump) { 284 /* Handle SIGUSR1. */ 285 do_dump = 0; 286 if (dumpfp != NULL) 287 rtsold_dump(dumpfp); 288 } 289 290 timeout = rtsol_check_timer(); 291 292 if (once) { 293 /* if we have no timeout, we are done (or failed) */ 294 if (timeout == NULL) 295 break; 296 297 /* if all interfaces have got RA packet, we are done */ 298 TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) { 299 if (ifi->state != IFS_DOWN && ifi->racnt == 0) 300 break; 301 } 302 if (ifi == NULL) 303 break; 304 } 305 306 error = kevent(kq, NULL, 0, &events[0], 1, timeout); 307 if (error < 1) { 308 if (error < 0 && errno != EINTR) 309 warnmsg(LOG_ERR, __func__, "kevent(): %s", 310 strerror(errno)); 311 continue; 312 } 313 314 if (events[0].ident == (uintptr_t)rtsock) 315 rtsock_input(rtsock); 316 else 317 rtsol_input(rcvsock); 318 } 319 320 return (0); 321 } 322 323 static int 324 init_capabilities(void) 325 { 326 #ifdef WITH_CASPER 327 const char *const scripts[2] = { resolvconf_script, otherconf_script }; 328 cap_channel_t *capcasper; 329 nvlist_t *limits; 330 331 capcasper = cap_init(); 332 if (capcasper == NULL) 333 return (-1); 334 335 capllflags = cap_service_open(capcasper, "rtsold.llflags"); 336 if (capllflags == NULL) 337 return (-1); 338 339 capscript = cap_service_open(capcasper, "rtsold.script"); 340 if (capscript == NULL) 341 return (-1); 342 limits = nvlist_create(0); 343 nvlist_add_string_array(limits, "scripts", scripts, 344 otherconf_script != NULL ? 2 : 1); 345 if (cap_limit_set(capscript, limits) != 0) 346 return (-1); 347 348 capsendmsg = cap_service_open(capcasper, "rtsold.sendmsg"); 349 if (capsendmsg == NULL) 350 return (-1); 351 352 if (!fflag) { 353 capsyslog = cap_service_open(capcasper, "system.syslog"); 354 if (capsyslog == NULL) 355 return (-1); 356 } 357 358 cap_close(capcasper); 359 #endif /* WITH_CASPER */ 360 return (0); 361 } 362 363 static int 364 ifconfig(char *ifname) 365 { 366 struct ifinfo *ifi; 367 struct sockaddr_dl *sdl; 368 int flags; 369 370 ifi = NULL; 371 if ((sdl = if_nametosdl(ifname)) == NULL) { 372 warnmsg(LOG_ERR, __func__, 373 "failed to get link layer information for %s", ifname); 374 goto bad; 375 } 376 if (find_ifinfo(sdl->sdl_index)) { 377 warnmsg(LOG_ERR, __func__, 378 "interface %s was already configured", ifname); 379 goto bad; 380 } 381 382 if (Fflag) { 383 struct in6_ndireq nd; 384 int s; 385 386 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 387 warnmsg(LOG_ERR, __func__, "socket() failed."); 388 goto bad; 389 } 390 memset(&nd, 0, sizeof(nd)); 391 strlcpy(nd.ifname, ifname, sizeof(nd.ifname)); 392 if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 393 warnmsg(LOG_ERR, __func__, 394 "cannot get accept_rtadv flag"); 395 (void)close(s); 396 goto bad; 397 } 398 nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV; 399 if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) { 400 warnmsg(LOG_ERR, __func__, 401 "cannot set accept_rtadv flag"); 402 (void)close(s); 403 goto bad; 404 } 405 (void)close(s); 406 } 407 408 if ((ifi = malloc(sizeof(*ifi))) == NULL) { 409 warnmsg(LOG_ERR, __func__, "memory allocation failed"); 410 goto bad; 411 } 412 memset(ifi, 0, sizeof(*ifi)); 413 ifi->sdl = sdl; 414 ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO; 415 ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO; 416 TAILQ_INIT(&ifi->ifi_rainfo); 417 strlcpy(ifi->ifname, ifname, sizeof(ifi->ifname)); 418 419 /* construct a router solicitation message */ 420 if (make_packet(ifi)) 421 goto bad; 422 423 /* set link ID of this interface. */ 424 #ifdef HAVE_SCOPELIB 425 if (inet_zoneid(AF_INET6, 2, ifname, &ifi->linkid)) 426 goto bad; 427 #else 428 /* XXX: assume interface IDs as link IDs */ 429 ifi->linkid = ifi->sdl->sdl_index; 430 #endif 431 432 /* 433 * check if the interface is available. 434 * also check if SIOCGIFMEDIA ioctl is OK on the interface. 435 */ 436 ifi->mediareqok = 1; 437 ifi->active = interface_status(ifi); 438 if (!ifi->mediareqok) { 439 /* 440 * probe routers periodically even if the link status 441 * does not change. 442 */ 443 ifi->probeinterval = PROBE_INTERVAL; 444 } 445 446 /* activate interface: interface_up returns 0 on success */ 447 flags = interface_up(ifi->ifname); 448 if (flags == 0) 449 ifi->state = IFS_DELAY; 450 else if (flags == IFS_TENTATIVE) 451 ifi->state = IFS_TENTATIVE; 452 else 453 ifi->state = IFS_DOWN; 454 455 rtsol_timer_update(ifi); 456 457 TAILQ_INSERT_TAIL(&ifinfo_head, ifi, ifi_next); 458 return (0); 459 460 bad: 461 free(sdl); 462 free(ifi); 463 return (-1); 464 } 465 466 struct rainfo * 467 find_rainfo(struct ifinfo *ifi, struct sockaddr_in6 *sin6) 468 { 469 struct rainfo *rai; 470 471 TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) 472 if (memcmp(&rai->rai_saddr.sin6_addr, &sin6->sin6_addr, 473 sizeof(rai->rai_saddr.sin6_addr)) == 0) 474 return (rai); 475 476 return (NULL); 477 } 478 479 struct ifinfo * 480 find_ifinfo(int ifindex) 481 { 482 struct ifinfo *ifi; 483 484 TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) { 485 if (ifi->sdl->sdl_index == ifindex) 486 return (ifi); 487 } 488 return (NULL); 489 } 490 491 static int 492 make_packet(struct ifinfo *ifi) 493 { 494 size_t packlen = sizeof(struct nd_router_solicit), lladdroptlen = 0; 495 struct nd_router_solicit *rs; 496 char *buf; 497 498 if ((lladdroptlen = lladdropt_length(ifi->sdl)) == 0) { 499 warnmsg(LOG_INFO, __func__, 500 "link-layer address option has null length" 501 " on %s. Treat as not included.", ifi->ifname); 502 } 503 packlen += lladdroptlen; 504 ifi->rs_datalen = packlen; 505 506 /* allocate buffer */ 507 if ((buf = malloc(packlen)) == NULL) { 508 warnmsg(LOG_ERR, __func__, 509 "memory allocation failed for %s", ifi->ifname); 510 return (-1); 511 } 512 ifi->rs_data = buf; 513 514 /* fill in the message */ 515 rs = (struct nd_router_solicit *)buf; 516 rs->nd_rs_type = ND_ROUTER_SOLICIT; 517 rs->nd_rs_code = 0; 518 rs->nd_rs_cksum = 0; 519 rs->nd_rs_reserved = 0; 520 buf += sizeof(*rs); 521 522 /* fill in source link-layer address option */ 523 if (lladdroptlen) 524 lladdropt_fill(ifi->sdl, (struct nd_opt_hdr *)buf); 525 526 return (0); 527 } 528 529 static struct timespec * 530 rtsol_check_timer(void) 531 { 532 static struct timespec returnval; 533 struct timespec now, rtsol_timer; 534 struct ifinfo *ifi; 535 struct rainfo *rai; 536 struct ra_opt *rao, *raotmp; 537 int error, flags; 538 539 clock_gettime(CLOCK_MONOTONIC_FAST, &now); 540 541 rtsol_timer = tm_max; 542 543 TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) { 544 if (TS_CMP(&ifi->expire, &now, <=)) { 545 warnmsg(LOG_DEBUG, __func__, "timer expiration on %s, " 546 "state = %d", ifi->ifname, ifi->state); 547 548 while((rai = TAILQ_FIRST(&ifi->ifi_rainfo)) != NULL) { 549 /* Remove all RA options. */ 550 TAILQ_REMOVE(&ifi->ifi_rainfo, rai, rai_next); 551 while ((rao = TAILQ_FIRST(&rai->rai_ra_opt)) != 552 NULL) { 553 TAILQ_REMOVE(&rai->rai_ra_opt, rao, 554 rao_next); 555 if (rao->rao_msg != NULL) 556 free(rao->rao_msg); 557 free(rao); 558 } 559 free(rai); 560 } 561 switch (ifi->state) { 562 case IFS_DOWN: 563 case IFS_TENTATIVE: 564 /* interface_up returns 0 on success */ 565 flags = interface_up(ifi->ifname); 566 if (flags == 0) 567 ifi->state = IFS_DELAY; 568 else if (flags == IFS_TENTATIVE) 569 ifi->state = IFS_TENTATIVE; 570 else 571 ifi->state = IFS_DOWN; 572 break; 573 case IFS_IDLE: 574 { 575 int oldstatus = ifi->active; 576 int probe = 0; 577 578 ifi->active = interface_status(ifi); 579 580 if (oldstatus != ifi->active) { 581 warnmsg(LOG_DEBUG, __func__, 582 "%s status is changed" 583 " from %d to %d", 584 ifi->ifname, 585 oldstatus, ifi->active); 586 probe = 1; 587 ifi->state = IFS_DELAY; 588 } else if (ifi->probeinterval && 589 (ifi->probetimer -= 590 ifi->timer.tv_sec) <= 0) { 591 /* probe timer expired */ 592 ifi->probetimer = 593 ifi->probeinterval; 594 probe = 1; 595 ifi->state = IFS_PROBE; 596 } 597 598 /* 599 * If we need a probe, clear the previous 600 * status wrt the "other" configuration. 601 */ 602 if (probe) 603 ifi->otherconfig = 0; 604 if (probe && mobile_node) { 605 error = cap_probe_defrouters(capsendmsg, 606 ifi); 607 if (error != 0) 608 warnmsg(LOG_DEBUG, __func__, 609 "failed to probe routers: %d", 610 error); 611 } 612 break; 613 } 614 case IFS_DELAY: 615 ifi->state = IFS_PROBE; 616 (void)cap_rssend(capsendmsg, ifi); 617 break; 618 case IFS_PROBE: 619 if (ifi->probes < MAX_RTR_SOLICITATIONS) 620 (void)cap_rssend(capsendmsg, ifi); 621 else { 622 warnmsg(LOG_INFO, __func__, 623 "No answer after sending %d RSs", 624 ifi->probes); 625 ifi->probes = 0; 626 ifi->state = IFS_IDLE; 627 } 628 break; 629 } 630 rtsol_timer_update(ifi); 631 } else { 632 /* Expiration check for RA options. */ 633 int expire = 0; 634 635 TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) { 636 TAILQ_FOREACH_SAFE(rao, &rai->rai_ra_opt, 637 rao_next, raotmp) { 638 warnmsg(LOG_DEBUG, __func__, 639 "RA expiration timer: " 640 "type=%d, msg=%s, expire=%s", 641 rao->rao_type, (char *)rao->rao_msg, 642 sec2str(&rao->rao_expire)); 643 if (TS_CMP(&now, &rao->rao_expire, 644 >=)) { 645 warnmsg(LOG_DEBUG, __func__, 646 "RA expiration timer: " 647 "expired."); 648 TAILQ_REMOVE(&rai->rai_ra_opt, 649 rao, rao_next); 650 if (rao->rao_msg != NULL) 651 free(rao->rao_msg); 652 free(rao); 653 expire = 1; 654 } 655 } 656 } 657 if (expire) 658 ra_opt_handler(ifi); 659 } 660 if (TS_CMP(&ifi->expire, &rtsol_timer, <)) 661 rtsol_timer = ifi->expire; 662 } 663 664 if (TS_CMP(&rtsol_timer, &tm_max, ==)) { 665 warnmsg(LOG_DEBUG, __func__, "there is no timer"); 666 return (NULL); 667 } else if (TS_CMP(&rtsol_timer, &now, <)) 668 /* this may occur when the interval is too small */ 669 returnval.tv_sec = returnval.tv_nsec = 0; 670 else 671 TS_SUB(&rtsol_timer, &now, &returnval); 672 673 now.tv_sec += returnval.tv_sec; 674 now.tv_nsec += returnval.tv_nsec; 675 warnmsg(LOG_DEBUG, __func__, "New timer is %s", 676 sec2str(&now)); 677 678 return (&returnval); 679 } 680 681 void 682 rtsol_timer_update(struct ifinfo *ifi) 683 { 684 #define MILLION 1000000 685 #define DADRETRY 10 /* XXX: adhoc */ 686 long interval; 687 struct timespec now; 688 689 bzero(&ifi->timer, sizeof(ifi->timer)); 690 691 switch (ifi->state) { 692 case IFS_DOWN: 693 case IFS_TENTATIVE: 694 if (++ifi->dadcount > DADRETRY) { 695 ifi->dadcount = 0; 696 ifi->timer.tv_sec = PROBE_INTERVAL; 697 } else 698 ifi->timer.tv_sec = 1; 699 break; 700 case IFS_IDLE: 701 if (mobile_node) 702 /* XXX should be configurable */ 703 ifi->timer.tv_sec = 3; 704 else 705 ifi->timer = tm_max; /* stop timer(valid?) */ 706 break; 707 case IFS_DELAY: 708 interval = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY * MILLION); 709 ifi->timer.tv_sec = interval / MILLION; 710 ifi->timer.tv_nsec = (interval % MILLION) * 1000; 711 break; 712 case IFS_PROBE: 713 if (ifi->probes < MAX_RTR_SOLICITATIONS) 714 ifi->timer.tv_sec = RTR_SOLICITATION_INTERVAL; 715 else 716 /* 717 * After sending MAX_RTR_SOLICITATIONS solicitations, 718 * we're just waiting for possible replies; there 719 * will be no more solicitation. Thus, we change 720 * the timer value to MAX_RTR_SOLICITATION_DELAY based 721 * on RFC 2461, Section 6.3.7. 722 */ 723 ifi->timer.tv_sec = MAX_RTR_SOLICITATION_DELAY; 724 break; 725 default: 726 warnmsg(LOG_ERR, __func__, 727 "illegal interface state(%d) on %s", 728 ifi->state, ifi->ifname); 729 return; 730 } 731 732 /* reset the timer */ 733 if (TS_CMP(&ifi->timer, &tm_max, ==)) { 734 ifi->expire = tm_max; 735 warnmsg(LOG_DEBUG, __func__, 736 "stop timer for %s", ifi->ifname); 737 } else { 738 clock_gettime(CLOCK_MONOTONIC_FAST, &now); 739 TS_ADD(&now, &ifi->timer, &ifi->expire); 740 741 now.tv_sec += ifi->timer.tv_sec; 742 now.tv_nsec += ifi->timer.tv_nsec; 743 warnmsg(LOG_DEBUG, __func__, "set timer for %s to %s", 744 ifi->ifname, sec2str(&now)); 745 } 746 747 #undef MILLION 748 } 749 750 static void 751 set_dumpfile(int sig __unused) 752 { 753 754 do_dump = 1; 755 } 756 757 static void 758 set_exit(int sig __unused) 759 { 760 761 do_exit = 1; 762 } 763 764 static void 765 usage(const char *progname) 766 { 767 768 if (strcmp(progname, "rtsold") == 0) { 769 fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] " 770 "[-p pidfile] [-R script-name] interface ...\n"); 771 fprintf(stderr, "usage: rtsold [-dDfFm1] [-O script-name] " 772 "[-p pidfile] [-R script-name] -a\n"); 773 } else { 774 fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] " 775 "[-p pidfile] [-R script-name] interface ...\n"); 776 fprintf(stderr, "usage: rtsol [-dDF] [-O script-name] " 777 "[-p pidfile] [-R script-name] -a\n"); 778 } 779 exit(1); 780 } 781 782 void 783 warnmsg(int priority, const char *func, const char *msg, ...) 784 { 785 va_list ap; 786 char buf[BUFSIZ]; 787 788 va_start(ap, msg); 789 if (fflag) { 790 if (priority <= log_upto) 791 vwarnx(msg, ap); 792 } else { 793 snprintf(buf, sizeof(buf), "<%s> %s", func, msg); 794 msg = buf; 795 cap_vsyslog(capsyslog, priority, msg, ap); 796 } 797 va_end(ap); 798 } 799 800 /* 801 * return a list of interfaces which is suitable to sending an RS. 802 */ 803 static char ** 804 autoifprobe(void) 805 { 806 static char **argv = NULL; 807 static int n = 0; 808 char **a; 809 int s = 0, i, found; 810 struct ifaddrs *ifap, *ifa; 811 struct in6_ndireq nd; 812 813 /* initialize */ 814 while (n--) 815 free(argv[n]); 816 if (argv) { 817 free(argv); 818 argv = NULL; 819 } 820 n = 0; 821 822 if (getifaddrs(&ifap) != 0) 823 return (NULL); 824 825 if (!Fflag && (s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { 826 warnmsg(LOG_ERR, __func__, "socket"); 827 exit(1); 828 } 829 830 /* find an ethernet */ 831 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 832 if ((ifa->ifa_flags & IFF_UP) == 0) 833 continue; 834 if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0) 835 continue; 836 if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) 837 continue; 838 if ((ifa->ifa_flags & IFF_MULTICAST) == 0) 839 continue; 840 841 if (ifa->ifa_addr->sa_family != AF_INET6) 842 continue; 843 844 found = 0; 845 for (i = 0; i < n; i++) { 846 if (strcmp(argv[i], ifa->ifa_name) == 0) { 847 found++; 848 break; 849 } 850 } 851 if (found) 852 continue; 853 854 /* 855 * Skip the interfaces which IPv6 and/or accepting RA 856 * is disabled. 857 */ 858 if (!Fflag) { 859 memset(&nd, 0, sizeof(nd)); 860 strlcpy(nd.ifname, ifa->ifa_name, sizeof(nd.ifname)); 861 if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) { 862 warnmsg(LOG_ERR, __func__, 863 "ioctl(SIOCGIFINFO_IN6)"); 864 exit(1); 865 } 866 if ((nd.ndi.flags & ND6_IFF_IFDISABLED)) 867 continue; 868 if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) 869 continue; 870 } 871 872 /* if we find multiple candidates, just warn. */ 873 if (n != 0 && dflag > 1) 874 warnmsg(LOG_WARNING, __func__, 875 "multiple interfaces found"); 876 877 a = realloc(argv, (n + 1) * sizeof(char *)); 878 if (a == NULL) { 879 warnmsg(LOG_ERR, __func__, "realloc"); 880 exit(1); 881 } 882 argv = a; 883 argv[n] = strdup(ifa->ifa_name); 884 if (!argv[n]) { 885 warnmsg(LOG_ERR, __func__, "malloc"); 886 exit(1); 887 } 888 n++; 889 } 890 891 if (n) { 892 a = realloc(argv, (n + 1) * sizeof(char *)); 893 if (a == NULL) { 894 warnmsg(LOG_ERR, __func__, "realloc"); 895 exit(1); 896 } 897 argv = a; 898 argv[n] = NULL; 899 900 if (dflag > 0) { 901 for (i = 0; i < n; i++) 902 warnmsg(LOG_WARNING, __func__, "probing %s", 903 argv[i]); 904 } 905 } 906 if (!Fflag) 907 close(s); 908 freeifaddrs(ifap); 909 return (argv); 910 } 911