diff options
| author | Hans Dedecker | 2020-03-28 19:47:18 +0000 |
|---|---|---|
| committer | Hans Dedecker | 2020-03-28 19:57:25 +0000 |
| commit | f575351cbb3defc0bf52680c9082912a6c264374 (patch) | |
| tree | a9148e4a8c28455d989c753d40e161471fe2f853 | |
| parent | 49305e6847efa43e008d0bebdc176e1833120947 (diff) | |
| download | odhcp6c-f575351cbb3defc0bf52680c9082912a6c264374.tar.gz | |
ra: fix sending router solicitations
Only stop sending router solicitations when a RA is received with a
valid router lifetime as specified in RFC4861 §6.3.7
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
| -rw-r--r-- | src/ra.c | 26 |
1 files changed, 17 insertions, 9 deletions
@@ -377,6 +377,9 @@ bool ra_process(void) .msg_controllen = sizeof(cmsg_buf), .msg_flags = 0 }; + struct icmpv6_opt *opt; + uint32_t router_valid; + int hlim = 0; ssize_t len = recvmsg(sock, &msg, MSG_DONTWAIT); if (len <= 0) @@ -385,7 +388,6 @@ bool ra_process(void) if (IN6_IS_ADDR_UNSPECIFIED(&lladdr)) continue; - int hlim = 0; for (struct cmsghdr *ch = CMSG_FIRSTHDR(&msg); ch != NULL; ch = CMSG_NXTHDR(&msg, ch)) if (ch->cmsg_level == IPPROTO_IPV6 && @@ -395,17 +397,24 @@ bool ra_process(void) if (!ra_icmpv6_valid(&from, hlim, buf, len)) continue; - // Stop sending solicits - if (rs_attempt > 0) { - alarm(0); - rs_attempt = 0; - } - if (!found) { odhcp6c_expire(); found = true; } - uint32_t router_valid = ntohs(adv->nd_ra_router_lifetime); + + router_valid = ntohs(adv->nd_ra_router_lifetime); + + /* RFC4861 §6.3.7 + * Once the host sends a Router Solicitation, and receives a valid + * Router Advertisement with a non-zero Router Lifetime, the host MUST + * desist from sending additional solicitations on that interface + * Moreover, a host SHOULD send at least one solicitation in the case + * where an advertisement is received prior to having sent a solicitation. + */ + if (rs_attempt > 0 && router_valid > 0) { + alarm(0); + rs_attempt = 0; + } // Parse default route entry->target = any; @@ -428,7 +437,6 @@ bool ra_process(void) changed |= ra_set_retransmit(ntohl(adv->nd_ra_retransmit)); // Evaluate options - struct icmpv6_opt *opt; icmpv6_for_each_option(opt, &adv[1], &buf[len]) { if (opt->type == ND_OPT_MTU) { uint32_t *mtu = (uint32_t*)&opt->data[2]; |