diff --git a/sys/include/net/gnrc/sixlowpan/nd.h b/sys/include/net/gnrc/sixlowpan/nd.h index 0b3b3aefac..bcfe53614b 100644 --- a/sys/include/net/gnrc/sixlowpan/nd.h +++ b/sys/include/net/gnrc/sixlowpan/nd.h @@ -195,6 +195,7 @@ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, e * @param[in] ipv6 The IPv6 header the ARO was received in. * @param[in] icmpv6_type Message type of the ICMPv6 message that contained. * this message. + * @param[in] addr The IPv6 address to register. * @param[in] ar_opt The address registration option. * @param[in] sl2a The link-layer source address contained in SL2A accompanying this * option. May be NULL for icmpv6_type == ICMPV6_NBR_ADV. @@ -203,7 +204,8 @@ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, e * @return Status for the ARO in the replying NA (always 0 if icmpv6_type == ICMPV6_NBR_ADV). */ uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, - uint8_t icmpv6_type, sixlowpan_nd_opt_ar_t *ar_opt, + uint8_t icmpv6_type, ipv6_addr_t *addr, + sixlowpan_nd_opt_ar_t *ar_opt, uint8_t *sl2a, size_t sl2a_len); /** diff --git a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c index 31068f361f..b565e6683a 100644 --- a/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c +++ b/sys/net/gnrc/network_layer/ndp/gnrc_ndp.c @@ -167,7 +167,9 @@ void gnrc_ndp_nbr_sol_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, if ((sl2a_opt != NULL) && (ar_opt != NULL) && (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) { - uint8_t status = gnrc_sixlowpan_nd_opt_ar_handle(iface, ipv6, nbr_sol->type, ar_opt, + uint8_t status = gnrc_sixlowpan_nd_opt_ar_handle(iface, ipv6, + nbr_sol->type, + &ipv6->src, ar_opt, l2src, l2src_len); /* check for multihop DAD return */ nbr_adv_opts = gnrc_sixlowpan_nd_opt_ar_build(status, GNRC_SIXLOWPAN_ND_AR_LTIME, @@ -253,7 +255,9 @@ void gnrc_ndp_nbr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, case NDP_OPT_AR: /* address registration option is always ignored when invalid */ gnrc_sixlowpan_nd_opt_ar_handle(iface, ipv6, nbr_adv->type, - (sixlowpan_nd_opt_ar_t *)opt, NULL, 0); + &nbr_adv->tgt, + (sixlowpan_nd_opt_ar_t *)opt, + NULL, 0); break; #endif default: diff --git a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c index f3e9078a7f..9e744c50ae 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c +++ b/sys/net/gnrc/network_layer/sixlowpan/nd/gnrc_sixlowpan_nd.c @@ -242,9 +242,10 @@ gnrc_pktsnip_t *gnrc_sixlowpan_nd_opt_ar_build(uint8_t status, uint16_t ltime, e return pkt; } -uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, uint8_t icmpv6_type, - sixlowpan_nd_opt_ar_t *ar_opt, uint8_t *sl2a, - size_t sl2a_len) +uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, + uint8_t icmpv6_type, ipv6_addr_t *addr, + sixlowpan_nd_opt_ar_t *ar_opt, + uint8_t *sl2a, size_t sl2a_len) { eui64_t eui64; gnrc_ipv6_netif_t *ipv6_iface; @@ -262,7 +263,7 @@ uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, ui return 0; } ipv6_iface = gnrc_ipv6_netif_get(iface); - nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src); + nc_entry = gnrc_ipv6_nc_get(iface, addr); switch (icmpv6_type) { case ICMPV6_NBR_ADV: if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { @@ -273,6 +274,12 @@ uint8_t gnrc_sixlowpan_nd_opt_ar_handle(kernel_pid_t iface, ipv6_hdr_t *ipv6, ui /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */ return 0; } + /* we expect the sender to be already in neighbor cache, if not we + * ignore it */ + if (nc_entry == NULL) { + DEBUG("6lo nd: sending router not in neighbor cache\n"); + return 0; + } switch (ar_opt->status) { case SIXLOWPAN_ND_STATUS_SUCCESS: DEBUG("6lo nd: address registration successful\n");