-/* $OpenBSD: rtadvd.c,v 1.85 2017/04/05 14:50:05 jca Exp $ */
+/* $OpenBSD: rtadvd.c,v 1.86 2017/06/09 13:31:03 florian Exp $ */
/* $KAME: rtadvd.c,v 1.66 2002/05/29 14:18:36 itojun Exp $ */
/*
static int nd6_options(struct nd_opt_hdr *, int,
union nd_opts *, u_int32_t);
static void free_ndopts(union nd_opts *);
-static void ra_output(struct rainfo *);
+static void ra_output(struct rainfo *, struct sockaddr_in6 *);
static struct rainfo *if_indextorainfo(int);
static int rdaemon(int);
}
for (i = 0; i < retrans; i++) {
SLIST_FOREACH(ra, &ralist, entry)
- ra_output(ra);
+ ra_output(ra, &sin6_allnodes);
sleep(MIN_DELAY_BETWEEN_RAS);
}
exit(0);
ra->rsinput++; /* increment statistics */
- /*
- * Decide whether to send RA according to the rate-limit
- * consideration.
- */
- {
+ if (ndopts.nd_opts_src_lladdr)
+ ra_output(ra, from);
+ else {
+ /*
+ * Decide whether to send RA according to the rate-limit
+ * consideration.
+ */
long delay; /* must not be greater than 1000000 */
struct timeval interval, now, min_delay, tm_tmp, next,
computed;
switch (hdr->nd_opt_type) {
case ND_OPT_SOURCE_LINKADDR:
+ ndopts->nd_opt_array[hdr->nd_opt_type] = hdr;
+ break;
case ND_OPT_TARGET_LINKADDR:
case ND_OPT_REDIRECTED_HEADER:
case ND_OPT_ROUTE_INFO:
}
static void
-ra_output(struct rainfo *rainfo)
+ra_output(struct rainfo *rainfo, struct sockaddr_in6 *to)
{
struct cmsghdr *cm;
struct in6_pktinfo *pi;
make_packet(rainfo); /* XXX: inefficient */
- sndmhdr.msg_name = &sin6_allnodes;
+ sndmhdr.msg_name = to;
sndmhdr.msg_iov[0].iov_base = rainfo->ra_data;
sndmhdr.msg_iov[0].iov_len = rainfo->ra_datalen;
return;
}
- /* update counter */
- if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
- rainfo->initcounter++;
rainfo->raoutput++;
- /* update timestamp */
- gettimeofday(&rainfo->lastsent, NULL);
+ if (memcmp(to, &sin6_allnodes, sizeof(sin6_allnodes)) == 0) {
+ /* update counter */
+ if (rainfo->initcounter < MAX_INITIAL_RTR_ADVERTISEMENTS)
+ rainfo->initcounter++;
+ /* update timestamp */
+ gettimeofday(&rainfo->lastsent, NULL);
- /* reset waiting counter */
- rainfo->waiting = 0;
+ /* reset waiting counter */
+ rainfo->waiting = 0;
+ }
}
/* process RA timer */
log_debug("RA timer on %s is expired", rai->ifname);
- ra_output(rai);
+ ra_output(rai, &sin6_allnodes);
ra_timer_update(rai);
evtimer_add(&rai->timer.ev, &rai->timer.tm);