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