net/lwip: na message handler
handling na messages with exception control according to RFC 4861
@@ -309,23 +309,36 @@ void nd6_input(struct pbuf *p, struct netif *inp)
nd6_send_q(i);
}
} else {
+ s32_t nd6_oflag = ND6H_NA_FLAG(na_hdr) & ND6_FLAG_OVERRIDE;
+ s32_t nd6_sflag = ND6H_NA_FLAG(na_hdr) & ND6_FLAG_SOLICITED;
+ s32_t nd6_rflag = ND6H_NA_FLAG(na_hdr) & ND6_FLAG_ROUTER;
+ s32_t lladdr_diff = 0;
+
if (lladdr_opt) {
- if (memcmp(neighbor_cache[i].lladdr, ND6H_LLADDR_OPT_ADDR(lladdr_opt), inp->hwaddr_len) != 0) {
- /* update the neighbor cache lladdr */
- MEMCPY(neighbor_cache[i].lladdr, ND6H_LLADDR_OPT_ADDR(lladdr_opt), inp->hwaddr_len);
+ lladdr_diff = memcmp(neighbor_cache[i].lladdr, ND6H_LLADDR_OPT_ADDR(lladdr_opt), inp->hwaddr_len);
+ }
- if ((ND6H_NA_FLAG(na_hdr) & ND6_FLAG_SOLICITED) == 0) {
+ if (nd6_oflag == 0 && lladdr_diff != 0) {
+ /* O flag is clear and lladdr is different between TLLA and cache entry */
+ if (neighbor_cache[i].state == ND6_REACHABLE) {
+ /* State is REACHABLE */
neighbor_cache[i].state = ND6_STALE;
}
+ } else {
+ if (lladdr_diff != 0) {
+ MEMCPY(neighbor_cache[i].lladdr, ND6H_LLADDR_OPT_ADDR(lladdr_opt), inp->hwaddr_len);
+
+ if (nd6_sflag == 0) {
+ neighbor_cache[i].state = ND6_STALE;
}
}
- if ((ND6H_NA_FLAG(na_hdr) & ND6_FLAG_SOLICITED)) {
+ if (nd6_sflag) {
neighbor_cache[i].state = ND6_REACHABLE;
neighbor_cache[i].counter.reachable_time = reachable_time;
}
- if ((ND6H_NA_FLAG(na_hdr) & ND6_FLAG_ROUTER)) {
+ if (nd6_rflag) {
neighbor_cache[i].isrouter = 1;
} else {
/* RFC 7.2.5
@@ -360,6 +373,7 @@ void nd6_input(struct pbuf *p, struct netif *inp)
}
}
}
+ }
break; /* ICMP6_TYPE_NA */
}
