gnrc_ipv6_nib: fix preparation of delayed NA

Currently the constructed NA for a delayed NA case is neither used nor
released nor does it get an IPv6 header to be used properly. This fixes
that case.
This commit is contained in:
Martine Lenders 2019-02-11 10:33:57 +01:00 committed by Martine Lenders
parent fa48e662a7
commit aa953a40ea

View File

@ -757,31 +757,46 @@ static inline size_t _get_l2src(const gnrc_netif_t *netif, uint8_t *l2src)
#endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */ #endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */
} }
static gnrc_pktsnip_t *_check_release_pkt(gnrc_pktsnip_t *pkt,
gnrc_pktsnip_t *payload)
{
if (pkt == NULL) {
DEBUG("nib: No space left in packet buffer. Not replying NS");
gnrc_pktbuf_release(payload);
}
return pkt;
}
static void _send_delayed_nbr_adv(const gnrc_netif_t *netif, static void _send_delayed_nbr_adv(const gnrc_netif_t *netif,
const ipv6_addr_t *tgt, const ipv6_addr_t *tgt,
const ipv6_addr_t *dst, const ipv6_hdr_t *ipv6_hdr,
gnrc_pktsnip_t *reply_aro) gnrc_pktsnip_t *payload)
{ {
gnrc_pktsnip_t *nbr_adv, *extra_opts = reply_aro; gnrc_pktsnip_t *pkt;
_nib_onl_entry_t *nce; _nib_onl_entry_t *nce;
uint8_t reply_flags = NDP_NBR_ADV_FLAGS_S; uint8_t reply_flags = NDP_NBR_ADV_FLAGS_S;
nce = _nib_onl_get(tgt, netif->pid);
if ((nce == NULL) || !(nce->mode & _NC)) {
/* usually this should be the case, but when NCE is full, just
* ignore the sending. Other nodes in this anycast group are
* then preferred */
gnrc_pktbuf_release(payload);
return;
}
#if GNRC_IPV6_NIB_CONF_ROUTER #if GNRC_IPV6_NIB_CONF_ROUTER
if (gnrc_netif_is_rtr(netif)) { if (gnrc_netif_is_rtr(netif)) {
reply_flags |= NDP_NBR_ADV_FLAGS_R; reply_flags |= NDP_NBR_ADV_FLAGS_R;
} }
#endif /* GNRC_IPV6_NIB_CONF_ROUTER */ #endif /* GNRC_IPV6_NIB_CONF_ROUTER */
#if GNRC_NETIF_L2ADDR_MAXLEN > 0 #if GNRC_NETIF_L2ADDR_MAXLEN > 0
if (ipv6_addr_is_multicast(dst)) { if (ipv6_addr_is_multicast(&ipv6_hdr->dst)) {
uint8_t l2addr[GNRC_NETIF_L2ADDR_MAXLEN]; uint8_t l2addr[GNRC_NETIF_L2ADDR_MAXLEN];
size_t l2addr_len = _get_l2src(netif, l2addr); size_t l2addr_len = _get_l2src(netif, l2addr);
if (l2addr_len > 0) { if (l2addr_len > 0) {
extra_opts = gnrc_ndp_opt_tl2a_build(l2addr, l2addr_len, pkt = gnrc_ndp_opt_tl2a_build(l2addr, l2addr_len, payload);
extra_opts); if ((payload = _check_release_pkt(pkt, payload)) == NULL) {
if (extra_opts == NULL) {
DEBUG("nib: No space left in packet buffer. Not replying NS");
gnrc_pktbuf_release(reply_aro);
return; return;
} }
} }
@ -796,20 +811,23 @@ static void _send_delayed_nbr_adv(const gnrc_netif_t *netif,
reply_flags |= NDP_NBR_ADV_FLAGS_O; reply_flags |= NDP_NBR_ADV_FLAGS_O;
#endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */ #endif /* GNRC_NETIF_L2ADDR_MAXLEN > 0 */
/* discard const qualifier */ /* discard const qualifier */
nbr_adv = gnrc_ndp_nbr_adv_build(tgt, reply_flags, extra_opts); pkt = gnrc_ndp_nbr_adv_build(tgt, reply_flags, payload);
if (nbr_adv == NULL) { if ((payload = _check_release_pkt(pkt, payload)) == NULL) {
DEBUG("nib: No space left in packet buffer. Not replying NS");
gnrc_pktbuf_release(extra_opts);
return; return;
} }
nce = _nib_onl_get(tgt, netif->pid); pkt = gnrc_ipv6_hdr_build(payload, NULL, &ipv6_hdr->src);
if ((nce != NULL) && (nce->mode & _NC)) { if ((payload = _check_release_pkt(pkt, payload)) == NULL) {
/* usually this should be the case, but when NCE is full, just return;
* ignore the sending. Other nodes in this anycast group are
* then preferred */
_evtimer_add(nce, GNRC_IPV6_NIB_SND_NA, &nce->snd_na,
random_uint32_range(0, NDP_MAX_ANYCAST_MS_DELAY));
} }
((ipv6_hdr_t *)payload->data)->hl = 255;
pkt = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
if ((pkt = _check_release_pkt(pkt, payload)) == NULL) {
return;
}
((gnrc_netif_hdr_t *)pkt->data)->if_pid = netif->pid;
LL_PREPEND(payload, pkt);
_evtimer_add(pkt, GNRC_IPV6_NIB_SND_NA, &nce->snd_na,
random_uint32_range(0, NDP_MAX_ANYCAST_MS_DELAY));
} }
static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6, static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
@ -935,7 +953,7 @@ static void _handle_nbr_sol(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
reply_aro = _copy_and_handle_aro(netif, ipv6, nbr_sol, aro, sl2ao); reply_aro = _copy_and_handle_aro(netif, ipv6, nbr_sol, aro, sl2ao);
/* check if target address is anycast */ /* check if target address is anycast */
if (netif->ipv6.addrs_flags[tgt_idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_ANYCAST) { if (netif->ipv6.addrs_flags[tgt_idx] & GNRC_NETIF_IPV6_ADDRS_FLAGS_ANYCAST) {
_send_delayed_nbr_adv(netif, &nbr_sol->tgt, &ipv6->dst, reply_aro); _send_delayed_nbr_adv(netif, &nbr_sol->tgt, ipv6, reply_aro);
} }
else { else {
gnrc_ndp_nbr_adv_send(&nbr_sol->tgt, netif, &ipv6->src, gnrc_ndp_nbr_adv_send(&nbr_sol->tgt, netif, &ipv6->src,