GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/rtadvd/rtadvd.c Lines: 0 606 0.0 %
Date: 2017-11-07 Branches: 0 349 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: rtadvd.c,v 1.91 2017/08/22 01:44:09 jca Exp $	*/
2
/*	$KAME: rtadvd.c,v 1.66 2002/05/29 14:18:36 itojun Exp $	*/
3
4
/*
5
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the project nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
#include <sys/uio.h>
36
#include <sys/time.h>
37
#include <sys/queue.h>
38
39
#include <net/if.h>
40
#include <net/route.h>
41
#include <netinet/in.h>
42
#include <netinet/ip6.h>
43
#include <netinet6/ip6_var.h>
44
#include <netinet/icmp6.h>
45
46
#include <arpa/inet.h>
47
48
#include <time.h>
49
#include <unistd.h>
50
#include <stdio.h>
51
#include <stdlib.h>
52
#include <err.h>
53
#include <errno.h>
54
#include <event.h>
55
#include <string.h>
56
#include <pwd.h>
57
#include <signal.h>
58
#include <fcntl.h>
59
#include <paths.h>
60
61
#include "rtadvd.h"
62
#include "advcap.h"
63
#include "if.h"
64
#include "config.h"
65
#include "dump.h"
66
#include "log.h"
67
68
struct msghdr rcvmhdr;
69
static u_char *rcvcmsgbuf;
70
static size_t rcvcmsgbuflen;
71
static u_char *sndcmsgbuf = NULL;
72
static size_t sndcmsgbuflen;
73
struct msghdr sndmhdr;
74
struct iovec rcviov[2];
75
struct iovec sndiov[2];
76
static char *rtsockbuf;
77
static size_t rtsockbuflen;
78
struct sockaddr_in6 from;
79
struct sockaddr_in6 sin6_allnodes = {sizeof(sin6_allnodes), AF_INET6};
80
int sock;
81
int rtsock = -1;
82
int ioctl_sock;
83
int dflag = 0, sflag = 0;
84
85
u_char *conffile = NULL;
86
87
struct ralist ralist;
88
89
struct nd_opt {
90
	SLIST_ENTRY(nd_opt)	 entry;
91
	struct nd_opt_hdr	*opt;
92
};
93
94
union nd_opts {
95
	struct nd_opt_hdr *nd_opt_array[9];
96
	struct {
97
		struct nd_opt_hdr *zero;
98
		struct nd_opt_hdr *src_lladdr;
99
		struct nd_opt_hdr *tgt_lladdr;
100
		struct nd_opt_prefix_info *pi;
101
		struct nd_opt_rd_hdr *rh;
102
		struct nd_opt_mtu *mtu;
103
		SLIST_HEAD(nd_optlist, nd_opt)	list;
104
	} nd_opt_each;
105
};
106
#define nd_opts_src_lladdr	nd_opt_each.src_lladdr
107
#define nd_opts_tgt_lladdr	nd_opt_each.tgt_lladdr
108
#define nd_opts_pi		nd_opt_each.pi
109
#define nd_opts_rh		nd_opt_each.rh
110
#define nd_opts_mtu		nd_opt_each.mtu
111
#define nd_opts_list		nd_opt_each.list
112
113
#define NDOPT_FLAG_SRCLINKADDR	(1 << 0)
114
#define NDOPT_FLAG_TGTLINKADDR	(1 << 1)
115
#define NDOPT_FLAG_PREFIXINFO	(1 << 2)
116
#define NDOPT_FLAG_RDHDR	(1 << 3)
117
#define NDOPT_FLAG_MTU		(1 << 4)
118
#define NDOPT_FLAG_RDNSS	(1 << 5)
119
#define NDOPT_FLAG_DNSSL	(1 << 6)
120
#define NDOPT_FLAG_ROUTE_INFO	(1 << 7)
121
122
u_int32_t ndopt_flags[] = {
123
	[ND_OPT_SOURCE_LINKADDR]	= NDOPT_FLAG_SRCLINKADDR,
124
	[ND_OPT_TARGET_LINKADDR]	= NDOPT_FLAG_TGTLINKADDR,
125
	[ND_OPT_PREFIX_INFORMATION]	= NDOPT_FLAG_PREFIXINFO,
126
	[ND_OPT_REDIRECTED_HEADER]	= NDOPT_FLAG_RDHDR,
127
	[ND_OPT_MTU]			= NDOPT_FLAG_MTU,
128
	[ND_OPT_ROUTE_INFO]		= NDOPT_FLAG_ROUTE_INFO,
129
	[ND_OPT_RDNSS]			= NDOPT_FLAG_RDNSS,
130
	[ND_OPT_DNSSL]			= NDOPT_FLAG_DNSSL,
131
};
132
133
static __dead void usage(void);
134
static void sock_open(void);
135
static void rtsock_open(void);
136
static void rs_input(int, struct nd_router_solicit *,
137
    struct in6_pktinfo *, struct sockaddr_in6 *);
138
static void ra_input(int, struct nd_router_advert *,
139
    struct in6_pktinfo *, struct sockaddr_in6 *);
140
static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *,
141
    struct sockaddr_in6 *);
142
static int nd6_options(struct nd_opt_hdr *, int,
143
    union nd_opts *, u_int32_t);
144
static void free_ndopts(union nd_opts *);
145
static void ra_output(struct rainfo *, struct sockaddr_in6 *);
146
static struct rainfo *if_indextorainfo(int);
147
static int rdaemon(int);
148
149
static void dump_cb(int, short, void *);
150
static void die_cb(int, short, void *);
151
static void rtsock_cb(int, short, void *);
152
static void sock_cb(int, short, void *);
153
static void timer_cb(int, short, void *);
154
155
int
156
main(int argc, char *argv[])
157
{
158
	struct passwd *pw;
159
	int ch;
160
	int devnull = -1;
161
	struct event ev_sock;
162
	struct event ev_rtsock;
163
	struct event ev_sigterm;
164
	struct event ev_sigusr1;
165
	struct rainfo *rai;
166
167
	log_procname = getprogname();
168
	log_init(1);		/* log to stderr until daemonized */
169
170
	closefrom(3);
171
172
	/* get command line options and arguments */
173
	while ((ch = getopt(argc, argv, "c:ds")) != -1) {
174
		switch (ch) {
175
		case 'c':
176
			conffile = optarg;
177
			break;
178
		case 'd':
179
			dflag = 1;
180
			break;
181
		case 's':
182
			sflag = 1;
183
			break;
184
		default:
185
			usage();
186
		}
187
	}
188
	argc -= optind;
189
	argv += optind;
190
	if (argc == 0)
191
		usage();
192
193
	if (!dflag) {
194
		devnull = open(_PATH_DEVNULL, O_RDWR, 0);
195
		if (devnull == -1)
196
			fatal("open(\"" _PATH_DEVNULL "\")");
197
	} else
198
		log_verbose(1);
199
200
	SLIST_INIT(&ralist);
201
202
	/* get iflist block from kernel */
203
	init_iflist();
204
205
	if (conffile == NULL)
206
		log_init(dflag);
207
208
	if ((ioctl_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
209
		fatal("socket");
210
211
	while (argc--)
212
		getconfig(*argv++);
213
214
	if (inet_pton(AF_INET6, ALLNODES, &sin6_allnodes.sin6_addr) != 1)
215
		fatal("inet_pton failed");
216
217
	sock_open();
218
219
	if (sflag == 0)
220
		rtsock_open();
221
222
	if ((pw = getpwnam(RTADVD_USER)) == NULL)
223
		fatal("getpwnam(" RTADVD_USER ")");
224
	if (chroot(pw->pw_dir) == -1)
225
		fatal("chroot");
226
	if (chdir("/") == -1)
227
		fatal("chdir(\"/\")");
228
	if (setgroups(1, &pw->pw_gid) == -1 ||
229
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
230
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
231
		fatal("cannot drop privileges");
232
233
	if (!dflag) {
234
		if (rdaemon(devnull) == -1)
235
			fatal("rdaemon");
236
	}
237
238
	if (conffile != NULL)
239
		log_init(dflag);
240
241
	if (pledge("stdio inet route flock rpath cpath wpath", NULL) == -1)
242
		err(1, "pledge");
243
244
	event_init();
245
246
	signal_set(&ev_sigterm, SIGTERM, die_cb, NULL);
247
	signal_add(&ev_sigterm, NULL);
248
	signal_set(&ev_sigusr1, SIGUSR1, dump_cb, NULL);
249
	signal_add(&ev_sigusr1, NULL);
250
251
	event_set(&ev_sock, sock, EV_READ|EV_PERSIST, sock_cb, NULL);
252
	event_add(&ev_sock, NULL);
253
	if (rtsock != -1) {
254
		event_set(&ev_rtsock, rtsock, EV_READ|EV_PERSIST, rtsock_cb,
255
		    NULL);
256
		event_add(&ev_rtsock, NULL);
257
	}
258
259
	SLIST_FOREACH(rai, &ralist, entry) {
260
		evtimer_set(&rai->timer.ev, timer_cb, rai);
261
		evtimer_add(&rai->timer.ev, &rai->timer.tm);
262
	}
263
264
	event_dispatch();
265
266
	log_warn("event_dispatch returned");
267
268
	return 1;
269
}
270
271
static void
272
usage(void)
273
{
274
	fprintf(stderr, "usage: %s [-ds] [-c configfile] interface ...\n",
275
	    getprogname());
276
	exit(1);
277
}
278
279
static void
280
dump_cb(int sig, short event, void *arg)
281
{
282
	rtadvd_dump();
283
}
284
285
static void
286
die_cb(int sig, short event, void *arg)
287
{
288
	struct rainfo *ra;
289
	int i;
290
	const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS;
291
292
	log_debug("cease to be an advertising router");
293
294
	SLIST_FOREACH(ra, &ralist, entry) {
295
		ra->lifetime = 0;
296
		make_packet(ra);
297
	}
298
	for (i = 0; i < retrans; i++) {
299
		SLIST_FOREACH(ra, &ralist, entry)
300
			ra_output(ra, &sin6_allnodes);
301
		sleep(MIN_DELAY_BETWEEN_RAS);
302
	}
303
	exit(0);
304
	/*NOTREACHED*/
305
}
306
307
static void
308
rtsock_cb(int fd, short event, void *arg)
309
{
310
	int n, type, ifindex = 0, oldifflags, plen;
311
	char *rtm;
312
	u_char ifname[IF_NAMESIZE];
313
	struct prefix *prefix;
314
	struct rainfo *rai;
315
	struct in6_addr *addr;
316
	char addrbuf[INET6_ADDRSTRLEN];
317
318
	n = read(rtsock, rtsockbuf, rtsockbuflen);
319
	log_debug("received a routing message "
320
	    "(type = %d, len = %d)", rtmsg_type(rtsockbuf), n);
321
322
	rtm = rtsockbuf;
323
	if (validate_msg(rtm) == -1)
324
		return;
325
326
	type = rtmsg_type(rtm);
327
	switch (type) {
328
	case RTM_ADD:
329
	case RTM_DELETE:
330
		ifindex = get_rtm_ifindex(rtm);
331
		break;
332
	case RTM_NEWADDR:
333
	case RTM_DELADDR:
334
		ifindex = get_ifam_ifindex(rtm);
335
		break;
336
	case RTM_IFINFO:
337
		ifindex = get_ifm_ifindex(rtm);
338
		break;
339
	default:
340
		/* should not reach here */
341
		log_debug("unknown rtmsg %d on %s",
342
		    type, if_indextoname(ifindex, ifname));
343
		return;
344
	}
345
346
	if ((rai = if_indextorainfo(ifindex)) == NULL) {
347
		log_debug("route changed on "
348
		    "non advertising interface(%s)",
349
		    if_indextoname(ifindex, ifname));
350
		return;
351
	}
352
	oldifflags = iflist[ifindex]->ifm_flags;
353
354
	switch (type) {
355
	case RTM_ADD:
356
		/* init ifflags because it may have changed */
357
		iflist[ifindex]->ifm_flags =
358
			if_getflags(ifindex, iflist[ifindex]->ifm_flags);
359
360
		if (sflag)
361
			break;	/* we aren't interested in prefixes  */
362
363
		addr = get_addr(rtm);
364
		plen = get_prefixlen(rtm);
365
		/* sanity check for plen */
366
		/* as RFC2373, prefixlen is at least 4 */
367
		if (plen < 4 || plen > 127) {
368
			log_info("new interface route's"
369
			    " plen %d is invalid for a prefix", plen);
370
			break;
371
		}
372
		prefix = find_prefix(rai, addr, plen);
373
		if (prefix) {
374
			log_debug("new prefix(%s/%d) "
375
			    "added on %s, "
376
			    "but it was already in list",
377
			    inet_ntop(AF_INET6, addr,
378
				addrbuf, INET6_ADDRSTRLEN),
379
			    plen, rai->ifname);
380
			break;
381
		}
382
		make_prefix(rai, ifindex, addr, plen);
383
		break;
384
	case RTM_DELETE:
385
		/* init ifflags because it may have changed */
386
		iflist[ifindex]->ifm_flags =
387
			if_getflags(ifindex, iflist[ifindex]->ifm_flags);
388
389
		if (sflag)
390
			break;
391
392
		addr = get_addr(rtm);
393
		plen = get_prefixlen(rtm);
394
		/* sanity check for plen */
395
		/* as RFC2373, prefixlen is at least 4 */
396
		if (plen < 4 || plen > 127) {
397
			log_info("deleted interface route's "
398
			    "plen %d is invalid for a prefix", plen);
399
			break;
400
		}
401
		prefix = find_prefix(rai, addr, plen);
402
		if (prefix == NULL) {
403
			log_debug("prefix(%s/%d) was "
404
			    "deleted on %s, "
405
			    "but it was not in list",
406
			    inet_ntop(AF_INET6, addr,
407
				addrbuf, INET6_ADDRSTRLEN),
408
			    plen, rai->ifname);
409
			break;
410
		}
411
		delete_prefix(rai, prefix);
412
		break;
413
	case RTM_NEWADDR:
414
	case RTM_DELADDR:
415
		/* init ifflags because it may have changed */
416
		iflist[ifindex]->ifm_flags =
417
			if_getflags(ifindex, iflist[ifindex]->ifm_flags);
418
		break;
419
	case RTM_IFINFO:
420
		iflist[ifindex]->ifm_flags = get_ifm_flags(rtm);
421
		break;
422
	default:
423
		/* should not reach here */
424
		log_debug("unknown rtmsg %d on %s",
425
		    type, if_indextoname(ifindex, ifname));
426
		return;
427
	}
428
429
	/* check if an interface flag is changed */
430
	if ((oldifflags & IFF_UP) != 0 &&	/* UP to DOWN */
431
	    (iflist[ifindex]->ifm_flags & IFF_UP) == 0) {
432
		log_info("interface %s becomes down. stop timer.",
433
		    rai->ifname);
434
		evtimer_del(&rai->timer.ev);
435
	} else if ((oldifflags & IFF_UP) == 0 && /* DOWN to UP */
436
	    (iflist[ifindex]->ifm_flags & IFF_UP) != 0) {
437
		log_info("interface %s becomes up. restart timer.",
438
		    rai->ifname);
439
440
		rai->initcounter = 0; /* reset the counter */
441
		rai->waiting = 0; /* XXX */
442
		ra_timer_update(rai);
443
		evtimer_add(&rai->timer.ev, &rai->timer.tm);
444
	}
445
}
446
447
void
448
sock_cb(int fd, short event, void *arg)
449
{
450
	ssize_t len;
451
	int *hlimp = NULL;
452
	struct icmp6_hdr *icp;
453
	int ifindex = 0;
454
	struct cmsghdr *cm;
455
	struct in6_pktinfo *pi = NULL;
456
	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
457
	struct in6_addr dst = in6addr_any;
458
459
	/*
460
	 * Get message. We reset msg_controllen since the field could
461
	 * be modified if we had received a message before setting
462
	 * receive options.
463
	 */
464
	rcvmhdr.msg_controllen = rcvcmsgbuflen;
465
	if ((len = recvmsg(sock, &rcvmhdr, 0)) < 0)
466
		return;
467
468
	/* extract optional information via Advanced API */
469
	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr);
470
	     cm;
471
	     cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) {
472
		if (cm->cmsg_level == IPPROTO_IPV6 &&
473
		    cm->cmsg_type == IPV6_PKTINFO &&
474
		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
475
			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
476
			ifindex = pi->ipi6_ifindex;
477
			dst = pi->ipi6_addr;
478
		}
479
		if (cm->cmsg_level == IPPROTO_IPV6 &&
480
		    cm->cmsg_type == IPV6_HOPLIMIT &&
481
		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
482
			hlimp = (int *)CMSG_DATA(cm);
483
	}
484
	if (ifindex == 0) {
485
		log_warnx("failed to get receiving interface");
486
		return;
487
	}
488
	if (hlimp == NULL) {
489
		log_warnx("failed to get receiving hop limit");
490
		return;
491
	}
492
493
	/*
494
	 * If we happen to receive data on an interface which is now down,
495
	 * just discard the data.
496
	 */
497
	if ((iflist[pi->ipi6_ifindex]->ifm_flags & IFF_UP) == 0) {
498
		log_info("received data on a disabled interface (%s)",
499
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
500
		return;
501
	}
502
503
	if (len < sizeof(struct icmp6_hdr)) {
504
		log_warnx("packet size(%zd) is too short", len);
505
		return;
506
	}
507
508
	icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;
509
510
	switch (icp->icmp6_type) {
511
	case ND_ROUTER_SOLICIT:
512
		/*
513
		 * Message verification - RFC-2461 6.1.1
514
		 * XXX: these checks must be done in the kernel as well,
515
		 *      but we can't completely rely on them.
516
		 */
517
		if (*hlimp != 255) {
518
			log_info("RS with invalid hop limit(%d) "
519
			    "received from %s on %s",
520
			    *hlimp,
521
			    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
522
			    INET6_ADDRSTRLEN),
523
			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
524
			return;
525
		}
526
		if (icp->icmp6_code) {
527
			log_info("RS with invalid ICMP6 code(%d) "
528
			    "received from %s on %s",
529
			    icp->icmp6_code,
530
			    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
531
			    INET6_ADDRSTRLEN),
532
			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
533
			return;
534
		}
535
		if (len < sizeof(struct nd_router_solicit)) {
536
			log_info("RS from %s on %s too short (len = %zd)",
537
			    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
538
			    INET6_ADDRSTRLEN),
539
			    if_indextoname(pi->ipi6_ifindex, ifnamebuf), len);
540
			return;
541
		}
542
		rs_input(len, (struct nd_router_solicit *)icp, pi, &from);
543
		break;
544
	case ND_ROUTER_ADVERT:
545
		/*
546
		 * Message verification - RFC-2461 6.1.2
547
		 * XXX: there's a same dilemma as above...
548
		 */
549
		if (*hlimp != 255) {
550
			log_info("RA with invalid hop limit(%d) "
551
			    "received from %s on %s",
552
			    *hlimp,
553
			    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
554
			    INET6_ADDRSTRLEN),
555
			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
556
			return;
557
		}
558
		if (icp->icmp6_code) {
559
			log_info("RA with invalid ICMP6 code(%d) "
560
			    "received from %s on %s",
561
			    icp->icmp6_code,
562
			    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
563
			    INET6_ADDRSTRLEN),
564
			    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
565
			return;
566
		}
567
		if (len < sizeof(struct nd_router_advert)) {
568
			log_info("RA from %s on %s too short (len = %zd)",
569
			    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
570
			    INET6_ADDRSTRLEN),
571
			    if_indextoname(pi->ipi6_ifindex, ifnamebuf), len);
572
			return;
573
		}
574
		ra_input(len, (struct nd_router_advert *)icp, pi, &from);
575
		break;
576
	default:
577
		/*
578
		 * Note that this case is POSSIBLE, especially just
579
		 * after invocation of the daemon. This is because we
580
		 * could receive message after opening the socket and
581
		 * before setting ICMP6 type filter(see sock_open()).
582
		 */
583
		log_warnx("invalid icmp type(%d)", icp->icmp6_type);
584
	}
585
}
586
587
static void
588
rs_input(int len, struct nd_router_solicit *rs,
589
	 struct in6_pktinfo *pi, struct sockaddr_in6 *from)
590
{
591
	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
592
	union nd_opts ndopts;
593
	struct rainfo *ra;
594
595
	log_debug("RS received from %s on %s",
596
	    inet_ntop(AF_INET6, &from->sin6_addr,
597
		ntopbuf, INET6_ADDRSTRLEN),
598
	    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
599
600
	/* ND option check */
601
	memset(&ndopts, 0, sizeof(ndopts));
602
	SLIST_INIT(&ndopts.nd_opts_list);
603
	if (nd6_options((struct nd_opt_hdr *)(rs + 1),
604
			len - sizeof(struct nd_router_solicit),
605
			&ndopts, NDOPT_FLAG_SRCLINKADDR)) {
606
		log_debug("ND option check failed for an RS from %s on %s",
607
		    inet_ntop(AF_INET6, &from->sin6_addr,
608
			ntopbuf, INET6_ADDRSTRLEN),
609
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
610
		return;
611
	}
612
613
	/*
614
	 * If the IP source address is the unspecified address, there
615
	 * must be no source link-layer address option in the message.
616
	 * (RFC-2461 6.1.1)
617
	 */
618
	if (IN6_IS_ADDR_UNSPECIFIED(&from->sin6_addr) &&
619
	    ndopts.nd_opts_src_lladdr) {
620
		log_warnx("RS from unspecified src on %s has a link-layer"
621
		       " address option",
622
		       if_indextoname(pi->ipi6_ifindex, ifnamebuf));
623
		goto done;
624
	}
625
626
	SLIST_FOREACH(ra, &ralist, entry) {
627
		if (pi->ipi6_ifindex == ra->ifindex)
628
			break;
629
	}
630
	if (ra == NULL) {
631
		log_info("RS received on non advertising interface(%s)",
632
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
633
		goto done;
634
	}
635
636
	ra->rsinput++;		/* increment statistics */
637
638
	if (ndopts.nd_opts_src_lladdr)
639
		ra_output(ra, from);
640
	else {
641
		/*
642
		 * Decide whether to send RA according to the rate-limit
643
		 * consideration.
644
		 */
645
		long delay;	/* must not be greater than 1000000 */
646
		struct timeval interval, now, min_delay, tm_tmp, next,
647
		    computed;
648
649
		/*
650
		 * If there is already a waiting RS packet, don't
651
		 * update the timer.
652
		 */
653
		if (ra->waiting++)
654
			goto done;
655
656
		gettimeofday(&now, NULL);
657
658
		/*
659
		 * Compute a random delay. If the computed value
660
		 * corresponds to a time later than the time the next
661
		 * multicast RA is scheduled to be sent, ignore the random
662
		 * delay and send the advertisement at the
663
		 * already-scheduled time. RFC-2461 6.2.6
664
		 */
665
		delay = arc4random_uniform(MAX_RA_DELAY_TIME);
666
		interval.tv_sec = 0;
667
		interval.tv_usec = delay;
668
		/*
669
		 * Could happen if an interface has transitioned from DOWN to
670
		 * UP and we haven't re-enabled the timer yet.
671
		 */
672
		if (!evtimer_pending(&ra->timer.ev, &next))
673
			goto done;
674
		timeradd(&now, &interval, &computed);
675
		if (timercmp(&computed, &next, >)) {
676
			log_debug("random delay is larger than "
677
			    "the rest of normal timer");
678
			goto done;
679
		}
680
681
		/*
682
		 * If we sent a multicast Router Advertisement within
683
		 * the last MIN_DELAY_BETWEEN_RAS seconds, schedule
684
		 * the advertisement to be sent at a time corresponding to
685
		 * MIN_DELAY_BETWEEN_RAS plus the random value after the
686
		 * previous advertisement was sent.
687
		 */
688
		min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS;
689
		min_delay.tv_usec = 0;
690
		timeradd(&ra->lastsent, &min_delay, &tm_tmp);
691
		if (timercmp(&computed, &tm_tmp, <))
692
			computed = tm_tmp;
693
		timersub(&computed, &now, &computed);
694
		evtimer_add(&ra->timer.ev, &computed);
695
	}
696
697
  done:
698
	free_ndopts(&ndopts);
699
}
700
701
static void
702
ra_input(int len, struct nd_router_advert *ra,
703
	 struct in6_pktinfo *pi, struct sockaddr_in6 *from)
704
{
705
	struct rainfo *rai;
706
	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
707
	union nd_opts ndopts;
708
	char *on_off[] = {"OFF", "ON"};
709
	u_int32_t reachabletime, retranstimer, mtu;
710
	int inconsistent = 0;
711
712
	log_debug("RA received from %s on %s",
713
	    inet_ntop(AF_INET6, &from->sin6_addr,
714
		ntopbuf, INET6_ADDRSTRLEN),
715
	    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
716
717
	/* ND option check */
718
	memset(&ndopts, 0, sizeof(ndopts));
719
	SLIST_INIT(&ndopts.nd_opts_list);
720
	if (nd6_options((struct nd_opt_hdr *)(ra + 1),
721
			len - sizeof(struct nd_router_advert),
722
			&ndopts, NDOPT_FLAG_SRCLINKADDR | NDOPT_FLAG_PREFIXINFO
723
			| NDOPT_FLAG_MTU | NDOPT_FLAG_ROUTE_INFO
724
			| NDOPT_FLAG_RDNSS | NDOPT_FLAG_DNSSL)) {
725
		log_warnx("ND option check failed for an RA from %s on %s",
726
		    inet_ntop(AF_INET6, &from->sin6_addr,
727
			ntopbuf, INET6_ADDRSTRLEN),
728
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
729
		return;
730
	}
731
732
	/*
733
	 * RA consistency check according to RFC-2461 6.2.7
734
	 */
735
	if ((rai = if_indextorainfo(pi->ipi6_ifindex)) == NULL)
736
		goto done;	/* not our interface */
737
738
	rai->rainput++;		/* increment statistics */
739
740
	/* Cur Hop Limit value */
741
	if (ra->nd_ra_curhoplimit && rai->hoplimit &&
742
	    ra->nd_ra_curhoplimit != rai->hoplimit) {
743
		log_info("CurHopLimit inconsistent on %s:  %d from %s,"
744
		    " %d from us",
745
		    rai->ifname,
746
		    ra->nd_ra_curhoplimit,
747
		    inet_ntop(AF_INET6, &from->sin6_addr,
748
			ntopbuf, INET6_ADDRSTRLEN),
749
		    rai->hoplimit);
750
		inconsistent++;
751
	}
752
	/* M flag */
753
	if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) !=
754
	    rai->managedflg) {
755
		log_info("M flag inconsistent on %s: %s from %s, %s from us",
756
		    rai->ifname, on_off[rai->managedflg ? 0 : 1],
757
		    inet_ntop(AF_INET6, &from->sin6_addr,
758
			ntopbuf, INET6_ADDRSTRLEN),
759
		    on_off[rai->managedflg ? 1 : 0]);
760
		inconsistent++;
761
	}
762
	/* O flag */
763
	if ((ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) !=
764
	    rai->otherflg) {
765
		log_info("O flag inconsistent on %s: %s from %s, %s from us",
766
		    rai->ifname, on_off[rai->otherflg ? 0 : 1],
767
		    inet_ntop(AF_INET6, &from->sin6_addr,
768
			ntopbuf, INET6_ADDRSTRLEN),
769
		    on_off[rai->otherflg ? 1 : 0]);
770
		inconsistent++;
771
	}
772
	/* Reachable Time */
773
	reachabletime = ntohl(ra->nd_ra_reachable);
774
	if (reachabletime && rai->reachabletime &&
775
	    reachabletime != rai->reachabletime) {
776
		log_info("ReachableTime inconsistent on %s:"
777
		    " %d from %s, %d from us",
778
		    rai->ifname, reachabletime,
779
		    inet_ntop(AF_INET6, &from->sin6_addr,
780
			ntopbuf, INET6_ADDRSTRLEN),
781
		    rai->reachabletime);
782
		inconsistent++;
783
	}
784
	/* Retrans Timer */
785
	retranstimer = ntohl(ra->nd_ra_retransmit);
786
	if (retranstimer && rai->retranstimer &&
787
	    retranstimer != rai->retranstimer) {
788
		log_info("RetransTimer inconsistent on %s:"
789
		    " %d from %s, %d from us",
790
		    rai->ifname, retranstimer,
791
		    inet_ntop(AF_INET6, &from->sin6_addr,
792
			ntopbuf, INET6_ADDRSTRLEN),
793
		    rai->retranstimer);
794
		inconsistent++;
795
	}
796
	/* Values in the MTU options */
797
	if (ndopts.nd_opts_mtu) {
798
		mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
799
		if (mtu && rai->linkmtu && mtu != rai->linkmtu) {
800
			log_info("MTU option value inconsistent on %s:"
801
			    " %d from %s, %d from us",
802
			    rai->ifname, mtu,
803
			    inet_ntop(AF_INET6, &from->sin6_addr,
804
				ntopbuf, INET6_ADDRSTRLEN),
805
			    rai->linkmtu);
806
			inconsistent++;
807
		}
808
	}
809
	/* Preferred and Valid Lifetimes for prefixes */
810
	{
811
		struct nd_opt 	*optp;
812
813
		if (ndopts.nd_opts_pi)
814
			if (prefix_check(ndopts.nd_opts_pi, rai, from))
815
				inconsistent++;
816
		SLIST_FOREACH(optp, &ndopts.nd_opts_list, entry) {
817
			if (prefix_check((struct nd_opt_prefix_info *)optp->opt,
818
					 rai, from))
819
				inconsistent++;
820
		}
821
	}
822
823
	if (inconsistent)
824
		rai->rainconsistent++;
825
826
  done:
827
	free_ndopts(&ndopts);
828
}
829
830
/* return a non-zero value if the received prefix is inconsistent with ours */
831
static int
832
prefix_check(struct nd_opt_prefix_info *pinfo,
833
	     struct rainfo *rai, struct sockaddr_in6 *from)
834
{
835
	time_t preferred_time, valid_time;
836
	struct prefix *pp;
837
	int inconsistent = 0;
838
	u_char ntopbuf[INET6_ADDRSTRLEN], prefixbuf[INET6_ADDRSTRLEN];
839
	struct timeval now;
840
841
	/*
842
	 * log if the advertised prefix has link-local scope(sanity check?)
843
	 */
844
	if (IN6_IS_ADDR_LINKLOCAL(&pinfo->nd_opt_pi_prefix))
845
		log_info("link-local prefix %s/%d is advertised "
846
		    "from %s on %s",
847
		    inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
848
			prefixbuf, INET6_ADDRSTRLEN),
849
		    pinfo->nd_opt_pi_prefix_len,
850
		    inet_ntop(AF_INET6, &from->sin6_addr,
851
			ntopbuf, INET6_ADDRSTRLEN),
852
		    rai->ifname);
853
854
	if ((pp = find_prefix(rai, &pinfo->nd_opt_pi_prefix,
855
			      pinfo->nd_opt_pi_prefix_len)) == NULL) {
856
		log_info("prefix %s/%d from %s on %s is not in our list",
857
		    inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
858
			prefixbuf, INET6_ADDRSTRLEN),
859
		    pinfo->nd_opt_pi_prefix_len,
860
		    inet_ntop(AF_INET6, &from->sin6_addr,
861
			ntopbuf, INET6_ADDRSTRLEN),
862
		    rai->ifname);
863
		return(0);
864
	}
865
866
	preferred_time = ntohl(pinfo->nd_opt_pi_preferred_time);
867
	if (pp->pltimeexpire) {
868
		/*
869
		 * The lifetime is decremented in real time, so we should
870
		 * compare the expiration time.
871
		 * (RFC 2461 Section 6.2.7.)
872
		 * XXX: can we really expect that all routers on the link
873
		 * have synchronized clocks?
874
		 */
875
		gettimeofday(&now, NULL);
876
		preferred_time += now.tv_sec;
877
878
		if (rai->clockskew &&
879
		    llabs(preferred_time - pp->pltimeexpire) > rai->clockskew) {
880
			log_info("preferred lifetime for %s/%d"
881
			    " (decr. in real time) inconsistent on %s:"
882
			    " %lld from %s, %lld from us",
883
			    inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
884
				prefixbuf, INET6_ADDRSTRLEN),
885
			    pinfo->nd_opt_pi_prefix_len,
886
			    rai->ifname, (long long)preferred_time,
887
			    inet_ntop(AF_INET6, &from->sin6_addr,
888
				ntopbuf, INET6_ADDRSTRLEN),
889
			    (long long)pp->pltimeexpire);
890
			inconsistent++;
891
		}
892
	} else if (preferred_time != pp->preflifetime)
893
		log_info("preferred lifetime for %s/%d"
894
		    " inconsistent on %s:"
895
		    " %lld from %s, %d from us",
896
		    inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
897
			prefixbuf, INET6_ADDRSTRLEN),
898
		    pinfo->nd_opt_pi_prefix_len,
899
		    rai->ifname, (long long)preferred_time,
900
		    inet_ntop(AF_INET6, &from->sin6_addr,
901
			ntopbuf, INET6_ADDRSTRLEN),
902
		    pp->preflifetime);
903
904
	valid_time = ntohl(pinfo->nd_opt_pi_valid_time);
905
	if (pp->vltimeexpire) {
906
		gettimeofday(&now, NULL);
907
		valid_time += now.tv_sec;
908
909
		if (rai->clockskew &&
910
		    llabs(valid_time - pp->vltimeexpire) > rai->clockskew) {
911
			log_info("valid lifetime for %s/%d"
912
			    " (decr. in real time) inconsistent on %s:"
913
			    " %lld from %s, %lld from us",
914
			    inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
915
				prefixbuf, INET6_ADDRSTRLEN),
916
			    pinfo->nd_opt_pi_prefix_len,
917
			    rai->ifname, (long long)preferred_time,
918
			    inet_ntop(AF_INET6, &from->sin6_addr,
919
				ntopbuf, INET6_ADDRSTRLEN),
920
			    (long long)pp->vltimeexpire);
921
			inconsistent++;
922
		}
923
	} else if (valid_time != pp->validlifetime) {
924
		log_info("valid lifetime for %s/%d"
925
		    " inconsistent on %s:"
926
		    " %lld from %s, %d from us",
927
		    inet_ntop(AF_INET6, &pinfo->nd_opt_pi_prefix,
928
			prefixbuf, INET6_ADDRSTRLEN),
929
		    pinfo->nd_opt_pi_prefix_len,
930
		    rai->ifname, (long long)valid_time,
931
		    inet_ntop(AF_INET6, &from->sin6_addr,
932
			ntopbuf, INET6_ADDRSTRLEN),
933
		    pp->validlifetime);
934
		inconsistent++;
935
	}
936
937
	return(inconsistent);
938
}
939
940
struct prefix *
941
find_prefix(struct rainfo *rai, struct in6_addr *prefix, int plen)
942
{
943
	struct prefix *pp;
944
	int bytelen, bitlen;
945
	u_char bitmask;
946
947
	TAILQ_FOREACH(pp, &rai->prefixes, entry) {
948
		if (plen != pp->prefixlen)
949
			continue;
950
		bytelen = plen / 8;
951
		bitlen = plen % 8;
952
		bitmask = 0xff << (8 - bitlen);
953
		if (memcmp(prefix, &pp->prefix, bytelen))
954
			continue;
955
		if (bitlen == 0 ||
956
		    ((prefix->s6_addr[bytelen] & bitmask) ==
957
		     (pp->prefix.s6_addr[bytelen] & bitmask))) {
958
			return(pp);
959
		}
960
	}
961
962
	return(NULL);
963
}
964
965
static int
966
nd6_options(struct nd_opt_hdr *hdr, int limit,
967
	    union nd_opts *ndopts, u_int32_t optflags)
968
{
969
	int optlen = 0;
970
971
	for (; limit > 0; limit -= optlen) {
972
		if (limit < sizeof(struct nd_opt_hdr)) {
973
			log_info("short option header");
974
			goto bad;
975
		}
976
977
		hdr = (struct nd_opt_hdr *)((char *)hdr + optlen);
978
		if (hdr->nd_opt_len == 0) {
979
			log_warnx("bad ND option length(0) (type = %d)",
980
			    hdr->nd_opt_type);
981
			goto bad;
982
		}
983
		optlen = hdr->nd_opt_len << 3;
984
		if (optlen > limit) {
985
			log_info("short option");
986
			goto bad;
987
		}
988
989
		if (hdr->nd_opt_type > ND_OPT_MTU &&
990
		    hdr->nd_opt_type != ND_OPT_ROUTE_INFO &&
991
		    hdr->nd_opt_type != ND_OPT_RDNSS &&
992
		    hdr->nd_opt_type != ND_OPT_DNSSL)
993
		{
994
			log_info("unknown ND option(type %d)",
995
			    hdr->nd_opt_type);
996
			continue;
997
		}
998
999
		if ((ndopt_flags[hdr->nd_opt_type] & optflags) == 0) {
1000
			log_info("unexpected ND option(type %d)",
1001
			    hdr->nd_opt_type);
1002
			continue;
1003
		}
1004
1005
		/*
1006
		 * Option length check.  Do it here for all fixed-length
1007
		 * options.
1008
		 */
1009
		if ((hdr->nd_opt_type == ND_OPT_RDNSS && (optlen < 24 ||
1010
		    ((optlen - sizeof(struct nd_opt_rdnss)) % 16 != 0))) ||
1011
		    (hdr->nd_opt_type == ND_OPT_DNSSL && optlen < 16) ||
1012
		    (hdr->nd_opt_type == ND_OPT_MTU &&
1013
		    (optlen != sizeof(struct nd_opt_mtu))) ||
1014
		    ((hdr->nd_opt_type == ND_OPT_PREFIX_INFORMATION &&
1015
		    optlen != sizeof(struct nd_opt_prefix_info)))) {
1016
			log_info("invalid option length");
1017
			continue;
1018
		}
1019
1020
		switch (hdr->nd_opt_type) {
1021
		case ND_OPT_SOURCE_LINKADDR:
1022
			ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
1023
			break;
1024
		case ND_OPT_TARGET_LINKADDR:
1025
		case ND_OPT_REDIRECTED_HEADER:
1026
		case ND_OPT_ROUTE_INFO:
1027
		case ND_OPT_RDNSS:
1028
		case ND_OPT_DNSSL:
1029
			break;	/* we don't care about these options */
1030
		case ND_OPT_MTU:
1031
			if (ndopts->nd_opt_array[hdr->nd_opt_type]) {
1032
				log_info("duplicated ND option (type = %d)",
1033
				    hdr->nd_opt_type);
1034
			}
1035
			ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
1036
			break;
1037
		case ND_OPT_PREFIX_INFORMATION:
1038
		{
1039
			struct nd_opt	*pfx;
1040
1041
			if (ndopts->nd_opts_pi == 0) {
1042
				ndopts->nd_opts_pi =
1043
				    (struct nd_opt_prefix_info *)hdr;
1044
				continue;
1045
			}
1046
			if ((pfx = malloc(sizeof(*pfx))) == NULL) {
1047
				log_warn(NULL);
1048
				goto bad;
1049
			}
1050
1051
			pfx->opt = hdr;
1052
			SLIST_INSERT_HEAD(&ndopts->nd_opts_list, pfx, entry);
1053
1054
			break;
1055
		}
1056
		default:	/* impossible */
1057
			break;
1058
		}
1059
	}
1060
1061
	return(0);
1062
1063
  bad:
1064
	free_ndopts(ndopts);
1065
1066
	return(-1);
1067
}
1068
1069
static void
1070
free_ndopts(union nd_opts *ndopts)
1071
{
1072
	struct nd_opt *opt;
1073
1074
	while (!SLIST_EMPTY(&ndopts->nd_opts_list)) {
1075
		opt = SLIST_FIRST(&ndopts->nd_opts_list);
1076
		SLIST_REMOVE_HEAD(&ndopts->nd_opts_list, entry);
1077
		free(opt);
1078
	}
1079
}
1080
1081
static void
1082
sock_open(void)
1083
{
1084
	struct rainfo	*ra;
1085
	struct icmp6_filter filt;
1086
	struct ipv6_mreq mreq;
1087
	int on;
1088
	/* XXX: should be max MTU attached to the node */
1089
	static u_char answer[1500];
1090
1091
	rcvcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1092
	    CMSG_SPACE(sizeof(int));
1093
	rcvcmsgbuf = malloc(rcvcmsgbuflen);
1094
	if (rcvcmsgbuf == NULL)
1095
		fatal(NULL);
1096
1097
	sndcmsgbuflen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
1098
	    CMSG_SPACE(sizeof(int));
1099
	sndcmsgbuf = malloc(sndcmsgbuflen);
1100
	if (sndcmsgbuf == NULL)
1101
		fatal(NULL);
1102
1103
	if ((sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
1104
		fatal("socket");
1105
1106
	/* specify to tell receiving interface */
1107
	on = 1;
1108
	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on))
1109
	    < 0)
1110
		fatal("IPV6_RECVPKTINFO");
1111
1112
	on = 1;
1113
	/* specify to tell value of hoplimit field of received IP6 hdr */
1114
	if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on))
1115
	    < 0)
1116
		fatal("IPV6_RECVHOPLIMIT");
1117
1118
	ICMP6_FILTER_SETBLOCKALL(&filt);
1119
	ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
1120
	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
1121
	if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt))
1122
	    < 0)
1123
		fatal("ICMP6_FILTER");
1124
1125
	/*
1126
	 * join all routers multicast address on each advertising interface.
1127
	 */
1128
	if (inet_pton(AF_INET6, ALLROUTERS_LINK, &mreq.ipv6mr_multiaddr.s6_addr)
1129
	    != 1)
1130
		fatal("inet_pton");
1131
	SLIST_FOREACH(ra, &ralist, entry) {
1132
		mreq.ipv6mr_interface = ra->ifindex;
1133
		if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
1134
		    sizeof(mreq)) < 0)
1135
			fatal("IPV6_JOIN_GROUP(link) on %s", ra->ifname);
1136
	}
1137
1138
	/* initialize msghdr for receiving packets */
1139
	rcviov[0].iov_base = answer;
1140
	rcviov[0].iov_len = sizeof(answer);
1141
	rcvmhdr.msg_name = &from;
1142
	rcvmhdr.msg_namelen = sizeof(from);
1143
	rcvmhdr.msg_iov = rcviov;
1144
	rcvmhdr.msg_iovlen = 1;
1145
	rcvmhdr.msg_control = rcvcmsgbuf;
1146
	rcvmhdr.msg_controllen = rcvcmsgbuflen;
1147
1148
	/* initialize msghdr for sending packets */
1149
	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
1150
	sndmhdr.msg_iov = sndiov;
1151
	sndmhdr.msg_iovlen = 1;
1152
	sndmhdr.msg_control = sndcmsgbuf;
1153
	sndmhdr.msg_controllen = sndcmsgbuflen;
1154
}
1155
1156
/* open a routing socket to watch the routing table */
1157
static void
1158
rtsock_open(void)
1159
{
1160
	unsigned int rtfilter;
1161
1162
	if ((rtsock = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
1163
		fatal("socket");
1164
1165
	rtfilter =
1166
	    ROUTE_FILTER(RTM_ADD) |
1167
	    ROUTE_FILTER(RTM_DELETE) |
1168
	    ROUTE_FILTER(RTM_NEWADDR) |
1169
	    ROUTE_FILTER(RTM_DELADDR) |
1170
	    ROUTE_FILTER(RTM_IFINFO);
1171
1172
	if (setsockopt(rtsock, PF_ROUTE, ROUTE_MSGFILTER,
1173
	    &rtfilter, sizeof(rtfilter)) == -1)
1174
		fatal("setsockopt(ROUTE_MSGFILTER)");
1175
1176
	rtsockbuflen = 2048;
1177
	rtsockbuf = malloc(rtsockbuflen);
1178
	if (rtsockbuf == NULL)
1179
		fatal(NULL);
1180
}
1181
1182
static struct rainfo *
1183
if_indextorainfo(int index)
1184
{
1185
	struct rainfo *rai;
1186
1187
	SLIST_FOREACH(rai, &ralist, entry) {
1188
		if (rai->ifindex == index)
1189
			return(rai);
1190
	}
1191
1192
	return(NULL);		/* search failed */
1193
}
1194
1195
static void
1196
ra_output(struct rainfo *rainfo, struct sockaddr_in6 *to)
1197
{
1198
	struct cmsghdr *cm;
1199
	struct in6_pktinfo *pi;
1200
	ssize_t len;
1201
1202
	if ((iflist[rainfo->ifindex]->ifm_flags & IFF_UP) == 0) {
1203
		log_debug("%s is not up, skip sending RA", rainfo->ifname);
1204
		return;
1205
	}
1206
1207
	make_packet(rainfo);	/* XXX: inefficient */
1208
1209
	sndmhdr.msg_name = to;
1210
	sndmhdr.msg_iov[0].iov_base = rainfo->ra_data;
1211
	sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
1212
1213
	cm = CMSG_FIRSTHDR(&sndmhdr);
1214
	/* specify the outgoing interface */
1215
	cm->cmsg_level = IPPROTO_IPV6;
1216
	cm->cmsg_type = IPV6_PKTINFO;
1217
	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1218
	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
1219
	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));	/*XXX*/
1220
	pi->ipi6_ifindex = rainfo->ifindex;
1221
1222
	/* specify the hop limit of the packet */
1223
	{
1224
		int hoplimit = 255;
1225
1226
		cm = CMSG_NXTHDR(&sndmhdr, cm);
1227
		cm->cmsg_level = IPPROTO_IPV6;
1228
		cm->cmsg_type = IPV6_HOPLIMIT;
1229
		cm->cmsg_len = CMSG_LEN(sizeof(int));
1230
		memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
1231
	}
1232
1233
	log_debug("send RA on %s, # of waitings = %u",
1234
	    rainfo->ifname, rainfo->waiting);
1235
1236
	len = sendmsg(sock, &sndmhdr, 0);
1237
	if (len < 0) {
1238
		log_warn("sendmsg on %s", rainfo->ifname);
1239
		return;
1240
	}
1241
1242
	rainfo->raoutput++;
1243
1244
	if (memcmp(to, &sin6_allnodes, sizeof(sin6_allnodes)) == 0) {
1245
		/* update counter */
1246
		if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
1247
			rainfo->initcounter++;
1248
		/* update timestamp */
1249
		gettimeofday(&rainfo->lastsent, NULL);
1250
1251
		/* reset waiting counter */
1252
		rainfo->waiting = 0;
1253
	}
1254
}
1255
1256
/* process RA timer */
1257
void
1258
timer_cb(int fd, short event, void *data)
1259
{
1260
	struct rainfo *rai = (struct rainfo *)data;
1261
1262
	log_debug("RA timer on %s is expired", rai->ifname);
1263
1264
	ra_output(rai, &sin6_allnodes);
1265
1266
	ra_timer_update(rai);
1267
	evtimer_add(&rai->timer.ev, &rai->timer.tm);
1268
}
1269
1270
/* update RA timer */
1271
void
1272
ra_timer_update(struct rainfo *rai)
1273
{
1274
	struct timeval *tm = &rai->timer.tm;
1275
	long interval;
1276
1277
	/*
1278
	 * Whenever a multicast advertisement is sent from an interface,
1279
	 * the timer is reset to a uniformly-distributed random value
1280
	 * between the interface's configured MinRtrAdvInterval and
1281
	 * MaxRtrAdvInterval (RFC2461 6.2.4).
1282
	 */
1283
	interval = rai->mininterval;
1284
	interval += arc4random_uniform(rai->maxinterval - rai->mininterval);
1285
1286
	/*
1287
	 * For the first few advertisements (up to
1288
	 * MAX_INITIAL_RTR_ADVERTISEMENTS), if the randomly chosen interval
1289
	 * is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL, the timer
1290
	 * SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead.
1291
	 * (RFC-2461 6.2.4)
1292
	 */
1293
	if (rai->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS &&
1294
	    interval > MAX_INITIAL_RTR_ADVERT_INTERVAL)
1295
		interval = MAX_INITIAL_RTR_ADVERT_INTERVAL;
1296
1297
	tm->tv_sec = interval;
1298
	tm->tv_usec = 0;
1299
1300
	log_debug("RA timer on %s set to %lld.%lds", rai->ifname,
1301
	    (long long)tm->tv_sec, tm->tv_usec);
1302
}
1303
1304
int
1305
rdaemon(int devnull)
1306
{
1307
	if (devnull == -1) {
1308
		errno = EBADF;
1309
		return (-1);
1310
	}
1311
	if (fcntl(devnull, F_GETFL) == -1)
1312
		return (-1);
1313
1314
	switch (fork()) {
1315
	case -1:
1316
		return (-1);
1317
	case 0:
1318
		break;
1319
	default:
1320
		_exit(0);
1321
	}
1322
1323
	if (setsid() == -1)
1324
		return (-1);
1325
1326
	(void)dup2(devnull, STDIN_FILENO);
1327
	(void)dup2(devnull, STDOUT_FILENO);
1328
	(void)dup2(devnull, STDERR_FILENO);
1329
	if (devnull > 2)
1330
		(void)close(devnull);
1331
1332
	return (0);
1333
}