From: Roy Marples Date: Thu, 30 May 2013 12:07:25 +0000 (+0000) Subject: It's possible to receive an RA for an interface that has not yet X-Git-Tag: v5.99.7~26 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0e906716c515061199e4d24a2503daa853a48862;p=thirdparty%2Fdhcpcd.git It's possible to receive an RA for an interface that has not yet obtained a local link address to send an RS. If this happens, we should process the RA. --- diff --git a/ipv6.c b/ipv6.c index 6998c5ae..c7a515b6 100644 --- a/ipv6.c +++ b/ipv6.c @@ -373,13 +373,15 @@ ipv6_handleifa(int cmd, struct if_head *ifs, const char *ifname, dhcp6_handleifa(cmd, ifname, addr, flags); } -int -ipv6_interfacehaslinklocal(const struct interface *ifp) +const struct ll_addr * +ipv6_linklocal(const struct interface *ifp) { const struct ipv6_state *state; state = IPV6_CSTATE(ifp); - return (state && TAILQ_FIRST(&state->ll_addrs)) ? 1 : 0; + if (state) + return TAILQ_FIRST(&state->ll_addrs); + return NULL; } int ipv6_addlinklocalcallback(struct interface *ifp, diff --git a/ipv6.h b/ipv6.h index c99227e4..38b9a989 100644 --- a/ipv6.h +++ b/ipv6.h @@ -143,7 +143,7 @@ void ipv6_handleifa(int, struct if_head *, const char *, const struct in6_addr *, int); int ipv6_handleifa_addrs(int, struct ipv6_addrhead *, const struct in6_addr *, int); -int ipv6_interfacehaslinklocal(const struct interface *); +const struct ll_addr *ipv6_linklocal(const struct interface *); int ipv6_addlinklocalcallback(struct interface *, void (*)(void *), void *); void ipv6_free(struct interface *); int ipv6_removesubnet(const struct interface *, struct ipv6_addr *); diff --git a/ipv6ns.c b/ipv6ns.c index c588bc0e..00748819 100644 --- a/ipv6ns.c +++ b/ipv6ns.c @@ -337,9 +337,11 @@ ipv6ns_probeaddr(void *arg) if (ap->dadcallback == NULL) syslog(LOG_WARNING, "%s: no callback!", ap->iface->name); #endif - if (sendmsg(unspec_sock, &sndhdr, 0) == -1) + if (sendmsg(unspec_sock, &sndhdr, 0) == -1) { syslog(LOG_ERR, "%s: %s: sendmsg: %m", ap->iface->name, __func__); + return; + } if (ap->dadcallback) { ms_to_tv(&tv, RETRANS_TIMER); @@ -460,15 +462,17 @@ ipv6ns_proberouter(void *arg) syslog(LOG_INFO, "%s: sending IPv6 NS for %s", rap->iface->name, rap->sfrom); #endif - if (sendmsg(sock, &sndhdr, 0) == -1) + if (sendmsg(sock, &sndhdr, 0) == -1) { syslog(LOG_ERR, "%s: %s: sendmsg: %m", rap->iface->name, __func__); + return; + } ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans); ms_to_tv(&rtv, MIN_RANDOM_FACTOR); timeradd(&tv, &rtv, &tv); rtv.tv_sec = 0; - rtv.tv_usec = arc4random() % (MAX_RANDOM_FACTOR_U - MIN_RANDOM_FACTOR_U); + rtv.tv_usec = arc4random() % (MAX_RANDOM_FACTOR_U -MIN_RANDOM_FACTOR_U); timeradd(&tv, &rtv, &tv); eloop_timeout_add_tv(&tv, ipv6ns_proberouter, rap); diff --git a/ipv6rs.c b/ipv6rs.c index bc151c79..29d4d94d 100644 --- a/ipv6rs.c +++ b/ipv6rs.c @@ -232,7 +232,7 @@ ipv6rs_sendprobe(void *arg) struct in6_pktinfo pi; int hoplimit = HOPLIMIT; - if (!ipv6_interfacehaslinklocal(ifp)) { + if (ipv6_linklocal(ifp) == NULL) { syslog(LOG_DEBUG, "%s: delaying Router Soliciation for LL address", ifp->name); @@ -596,6 +596,16 @@ ipv6rs_handledata(__unused void *arg) #endif return; } + + /* We could recieve a RA before we sent a RS*/ + if (ipv6_linklocal(ifp) == NULL) { +#ifdef DEBUG_RS + syslog(LOG_DEBUG, "%s: received RA from %s (no link-local)", + ifp->name, sfrom); +#endif + return; + } + TAILQ_FOREACH(rap, &ipv6_routers, next) { if (ifp == rap->iface && memcmp(rap->from.s6_addr, from.sin6_addr.s6_addr,