void gnrc_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *tgt, ipv6_addr_t *dst) { gnrc_pktsnip_t *hdr, *pkt = NULL; ipv6_addr_t *src = NULL; DEBUG("ndp internal: send neighbor solicitation (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s)\n", ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); /* check if there is a fitting source address to target */ if ((src = gnrc_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) { uint8_t l2src[8]; size_t l2src_len; l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp internal: error allocating Source Link-layer address option.\n"); gnrc_pktbuf_release(pkt); return; } } } hdr = gnrc_ndp_nbr_sol_build(tgt, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Neighbor solicitation.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, src); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } gnrc_netapi_send(gnrc_ipv6_pid, hdr); }
void gnrc_ndp_internal_send_rtr_sol(kernel_pid_t iface, ipv6_addr_t *dst) { gnrc_pktsnip_t *hdr, *pkt = NULL; ipv6_addr_t *src = NULL, all_routers = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; DEBUG("ndp internal: send router solicitation (iface: %" PRIkernel_pid ", dst: ff02::2)\n", iface); if (dst == NULL) { dst = &all_routers; } /* check if there is a fitting source address to target */ if ((src = gnrc_ipv6_netif_find_best_src_addr(iface, dst)) != NULL) { uint8_t l2src[8]; size_t l2src_len; l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp internal: error allocating Source Link-layer address option.\n"); gnrc_pktbuf_release(pkt); return; } } } hdr = gnrc_ndp_rtr_sol_build(pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating router solicitation.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, src); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) { DEBUG("ndp internal: unable to send router solicitation\n"); gnrc_pktbuf_release(hdr); } }
void gnrc_ndp_internal_send_rtr_adv(kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst, bool fin) { gnrc_pktsnip_t *hdr, *pkt = NULL; ipv6_addr_t all_nodes = IPV6_ADDR_ALL_NODES_LINK_LOCAL; gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface); uint32_t reach_time = 0, retrans_timer = 0; uint16_t adv_ltime = 0; uint8_t cur_hl = 0; if (dst == NULL) { dst = &all_nodes; } DEBUG("ndp internal: send router advertisement (iface: %" PRIkernel_pid ", dst: %s%s\n", iface, ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), fin ? ", final" : ""); mutex_lock(&ipv6_iface->mutex); #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { #endif hdr = _add_pios(ipv6_iface, pkt); if (hdr == NULL) { /* pkt already released in _add_pios */ mutex_unlock(&ipv6_iface->mutex); return; } pkt = hdr; #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER } else { gnrc_sixlowpan_nd_router_abr_t *abr = gnrc_sixlowpan_nd_router_abr_get(); if (abr != NULL) { gnrc_sixlowpan_nd_router_prf_t *prf = abr->prfs; /* add prefixes from border router */ while (prf) { bool processed_before = false; /* skip if prefix does not belong to iface */ if (prf->iface != ipv6_iface) { prf = prf->next; continue; } /* skip if prefix has been processed already */ for (gnrc_sixlowpan_nd_router_prf_t *tmp = abr->prfs; tmp != prf; tmp = tmp->next) { if ((processed_before = _check_prefixes(prf->prefix, tmp->prefix))) { break; } } if (processed_before) { prf = prf->next; continue; } if (_pio_from_iface_addr(&hdr, prf->prefix, pkt)) { if (hdr != NULL) { pkt = hdr; } else { DEBUG("ndp rtr: error allocating PIO\n"); gnrc_pktbuf_release(pkt); return; } } prf = prf->next; } for (unsigned int i = 0; i < GNRC_SIXLOWPAN_CTX_SIZE; i++) { gnrc_sixlowpan_ctx_t *ctx; if (!bf_isset(abr->ctxs, i)) { continue; } ctx = gnrc_sixlowpan_ctx_lookup_id(i); hdr = gnrc_sixlowpan_nd_opt_6ctx_build(ctx->prefix_len, ctx->flags_id, ctx->ltime, &ctx->prefix, pkt); if (hdr == NULL) { DEBUG("ndp rtr: error allocating 6CO\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } hdr = gnrc_sixlowpan_nd_opt_abr_build(abr->version, abr->ltime, &abr->addr, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating ABRO.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } } #endif /* MODULE_GNRC_SIXLOWPAN_ND_ROUTER */ if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_MTU) { if ((hdr = gnrc_ndp_opt_mtu_build(ipv6_iface->mtu, pkt)) == NULL) { DEBUG("ndp rtr: no space left in packet buffer\n"); mutex_unlock(&ipv6_iface->mutex); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } if (src == NULL) { mutex_unlock(&ipv6_iface->mutex); /* get address from source selection algorithm */ src = gnrc_ipv6_netif_find_best_src_addr(iface, dst); mutex_lock(&ipv6_iface->mutex); } /* add SL2A for source address */ if (src != NULL) { DEBUG(" - SL2A\n"); uint8_t l2src[8]; size_t l2src_len; /* optimization note: MAY also be omitted to facilitate in-bound load balancing over * replicated interfaces. * source: https://tools.ietf.org/html/rfc4861#section-6.2.3 */ l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add source address link-layer address option */ hdr = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Source Link-layer address option.\n"); mutex_unlock(&ipv6_iface->mutex); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } } if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_CUR_HL) { cur_hl = ipv6_iface->cur_hl; } if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_REACH_TIME) { if (ipv6_iface->reach_time > (3600 * SEC_IN_USEC)) { /* reach_time > 1 hour */ reach_time = (3600 * SEC_IN_MS); } else { reach_time = ipv6_iface->reach_time / MS_IN_USEC; } } if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_RETRANS_TIMER) { retrans_timer = ipv6_iface->retrans_timer / MS_IN_USEC; } if (!fin) { adv_ltime = ipv6_iface->adv_ltime; } mutex_unlock(&ipv6_iface->mutex); hdr = gnrc_ndp_rtr_adv_build(cur_hl, (ipv6_iface->flags & (GNRC_IPV6_NETIF_FLAGS_OTHER_CONF | GNRC_IPV6_NETIF_FLAGS_MANAGED)) >> 8, adv_ltime, reach_time, retrans_timer, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating router advertisement.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, src); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) { DEBUG("ndp internal: unable to send router advertisement\n"); gnrc_pktbuf_release(hdr); } }
void gnrc_ndp_internal_send_nbr_sol(kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *tgt, ipv6_addr_t *dst) { #ifdef MODULE_GNRC_SIXLOWPAN_ND gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface); assert(ipv6_iface != NULL); #endif gnrc_pktsnip_t *hdr, *pkt = NULL; /* both suppressions, since they are needed in the MODULE_GNRC_SIXLOWPAN_ND branch */ /* cppcheck-suppress variableScope */ uint8_t l2src[8]; /* cppcheck-suppress variableScope */ size_t l2src_len = 0; DEBUG("ndp internal: send neighbor solicitation (iface: %" PRIkernel_pid ", src: %s, ", iface, ipv6_addr_to_str(addr_str, src, sizeof(addr_str))); DEBUG(" tgt: %s, ", ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s)\n", ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); /* check if there is a fitting source address to target */ if (src == NULL) { src = gnrc_ipv6_netif_find_best_src_addr(iface, tgt); } if (src != NULL) { l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp internal: error allocating Source Link-layer address option.\n"); gnrc_pktbuf_release(pkt); return; } } } #ifdef MODULE_GNRC_SIXLOWPAN_ND if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { if (l2src_len != sizeof(eui64_t)) { l2src_len = (uint16_t)gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, l2src, sizeof(l2src)); if (l2src_len != sizeof(eui64_t)) { DEBUG("ndp internal: can't get EUI-64 of the interface\n"); gnrc_pktbuf_release(pkt); return; } } hdr = gnrc_sixlowpan_nd_opt_ar_build(0, GNRC_SIXLOWPAN_ND_AR_LTIME, (eui64_t *)l2src, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocatin Address Registration option.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } #endif hdr = gnrc_ndp_nbr_sol_build(tgt, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Neighbor solicitation.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, src); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) { DEBUG("ndp internal: unable to send neighbor solicitation\n"); gnrc_pktbuf_release(hdr); } }
void gnrc_ndp_internal_send_nbr_adv(kernel_pid_t iface, ipv6_addr_t *tgt, ipv6_addr_t *dst, bool supply_tl2a, gnrc_pktsnip_t *ext_opts) { gnrc_pktsnip_t *hdr, *pkt = ext_opts; uint8_t adv_flags = 0; DEBUG("ndp internal: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s, supply_tl2a: %d)\n", ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a); if ((gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) && (gnrc_ipv6_netif_get(iface)->flags & GNRC_IPV6_NETIF_FLAGS_RTR_ADV)) { adv_flags |= NDP_NBR_ADV_FLAGS_R; } if (ipv6_addr_is_unspecified(dst)) { ipv6_addr_set_all_nodes_multicast(dst, IPV6_ADDR_MCAST_SCP_LINK_LOCAL); } else { adv_flags |= NDP_NBR_ADV_FLAGS_S; } if (supply_tl2a) { uint8_t l2src[8]; size_t l2src_len; /* we previously checked if we are the target, so we can take our L2src */ l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add target address link-layer address option */ pkt = gnrc_ndp_opt_tl2a_build(l2src, l2src_len, pkt); if (pkt == NULL) { DEBUG("ndp internal: error allocating Target Link-layer address option.\n"); gnrc_pktbuf_release(ext_opts); return; } } } /* TODO: also check if the node provides proxy servies for tgt */ if ((pkt != NULL) && !gnrc_ipv6_netif_addr_is_non_unicast(tgt)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NDP_NBR_ADV_FLAGS_O; } hdr = gnrc_ndp_nbr_adv_build(adv_flags, tgt, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating Neighbor advertisement.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, NULL); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } if (gnrc_ipv6_netif_addr_is_non_unicast(tgt)) { /* avoid collision for anycast addresses * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */ uint32_t delay = genrand_uint32_range(0, GNRC_NDP_MAX_AC_TGT_DELAY * SEC_IN_USEC); gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, dst); DEBUG("ndp internal: delay neighbor advertisement for %" PRIu32 " sec.", (delay / SEC_IN_USEC)); /* nc_entry must be set so no need to check it */ assert(nc_entry); _send_delayed(&nc_entry->nbr_adv_timer, &nc_entry->nbr_adv_msg, delay, hdr); } else if (gnrc_netapi_send(gnrc_ipv6_pid, hdr) < 1) { DEBUG("ndp internal: unable to send neighbor advertisement\n"); gnrc_pktbuf_release(hdr); } }
static void _send_nbr_adv(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst, bool supply_tl2a) { ng_pktsnip_t *hdr, *pkt = NULL; uint8_t adv_flags = 0; DEBUG("ndp: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s, supply_tl2a: %d)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a); if (ng_ipv6_netif_get(iface)->flags & NG_IPV6_NETIF_FLAGS_ROUTER) { adv_flags |= NG_NDP_NBR_ADV_FLAGS_R; } if (ng_ipv6_addr_is_unspecified(dst)) { ng_ipv6_addr_set_all_nodes_multicast(dst, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); } else { adv_flags |= NG_NDP_NBR_ADV_FLAGS_S; } if (supply_tl2a) { uint8_t l2src[8]; uint16_t l2src_len; /* we previously checked if we are the target, so we can take our L2src */ l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add target address link-layer address option */ pkt = ng_ndp_opt_tl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp: error allocating Target Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } /* TODO: also check if the node provides proxy servies for tgt */ if ((pkt != NULL) && !ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NG_NDP_NBR_ADV_FLAGS_O; } hdr = ng_ndp_nbr_adv_build(adv_flags, tgt, pkt); if (hdr == NULL) { DEBUG("ndp: error allocating Neighbor advertisement.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (uint8_t *)dst, sizeof(ng_ipv6_addr_t)); if (hdr == NULL) { DEBUG("ndp: error allocating IPv6 header.\n"); ng_pktbuf_release(pkt); return; } ((ng_ipv6_hdr_t *)hdr->data)->hl = 255; pkt = hdr; /* add netif header for send interface specification */ hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); if (hdr == NULL) { DEBUG("ndp: error allocating netif header.\n"); return; } ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); if (ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* avoid collision for anycast addresses * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */ timex_t delay = { _rand(0, NG_NDP_MAX_AC_TGT_DELAY), 0 }; ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt); DEBUG("ndp: delay neighbor advertisement for %" PRIu32 " sec.", delay.seconds); /* nc_entry must be set so no need to check it */ _send_delayed(&nc_entry->nbr_adv_timer, delay, pkt); } else { ng_netapi_send(ng_ipv6_pid, pkt); } }
static void _send_nbr_sol(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst) { ng_pktsnip_t *hdr, *pkt = NULL; ng_ipv6_addr_t *src = NULL; size_t src_len = 0; DEBUG("ndp: send neighbor solicitation (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); /* check if there is a fitting source address to target */ if ((src = ng_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) { uint8_t l2src[8]; uint16_t l2src_len; src_len = sizeof(ng_ipv6_addr_t); l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = ng_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp: error allocating Source Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } hdr = ng_ndp_nbr_sol_build(tgt, pkt); if (hdr == NULL) { DEBUG("ndp: error allocating Neighbor solicitation.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst, sizeof(ng_ipv6_addr_t)); if (hdr == NULL) { DEBUG("ndp: error allocating IPv6 header.\n"); ng_pktbuf_release(pkt); return; } ((ng_ipv6_hdr_t *)hdr->data)->hl = 255; pkt = hdr; /* add netif header for send interface specification */ hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); if (hdr == NULL) { DEBUG("ndp: error allocating netif header.\n"); return; } ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); ng_netapi_send(ng_ipv6_pid, pkt); }
void gnrc_ndp_internal_send_rtr_adv(kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst, bool fin) { gnrc_pktsnip_t *hdr, *pkt = NULL; ipv6_addr_t all_nodes = IPV6_ADDR_ALL_NODES_LINK_LOCAL; gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface); uint32_t reach_time = 0, retrans_timer = 0; uint16_t adv_ltime = 0; uint8_t cur_hl = 0; if (dst == NULL) { dst = &all_nodes; } DEBUG("ndp internal: send router advertisement (iface: %" PRIkernel_pid ", dst: %s%s\n", iface, ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), fin ? ", final" : ""); mutex_lock(&ipv6_iface->mutex); hdr = _add_pios(ipv6_iface, pkt); if (hdr == NULL) { /* pkt already released in _add_pios */ mutex_unlock(&ipv6_iface->mutex); return; } pkt = hdr; if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_MTU) { if ((hdr = gnrc_ndp_opt_mtu_build(ipv6_iface->mtu, pkt)) == NULL) { DEBUG("ndp rtr: no space left in packet buffer\n"); mutex_unlock(&ipv6_iface->mutex); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } if (src == NULL) { /* get address from source selection algorithm */ src = gnrc_ipv6_netif_find_best_src_addr(iface, dst); } /* add SL2A for source address */ if (src != NULL) { DEBUG(" - SL2A\n"); uint8_t l2src[8]; size_t l2src_len; /* optimization note: MAY also be omitted to facilitate in-bound load balancing over * replicated interfaces. * source: https://tools.ietf.org/html/rfc4861#section-6.2.3 */ l2src_len = _get_l2src(iface, l2src, sizeof(l2src)); if (l2src_len > 0) { /* add source address link-layer address option */ hdr = gnrc_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (hdr == NULL) { DEBUG("ndp internal: error allocating Source Link-layer address option.\n"); mutex_unlock(&ipv6_iface->mutex); gnrc_pktbuf_release(pkt); return; } pkt = hdr; } } if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_CUR_HL) { cur_hl = ipv6_iface->cur_hl; } if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_REACH_TIME) { uint64_t tmp = timex_uint64(ipv6_iface->reach_time) / MS_IN_USEC; if (tmp > (3600 * SEC_IN_MS)) { /* tmp > 1 hour */ tmp = (3600 * SEC_IN_MS); } reach_time = (uint32_t)tmp; } if (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ADV_RETRANS_TIMER) { uint64_t tmp = timex_uint64(ipv6_iface->retrans_timer) / MS_IN_USEC; if (tmp > UINT32_MAX) { tmp = UINT32_MAX; } retrans_timer = (uint32_t)tmp; } if (!fin) { adv_ltime = ipv6_iface->adv_ltime; } mutex_unlock(&ipv6_iface->mutex); hdr = gnrc_ndp_rtr_adv_build(cur_hl, (ipv6_iface->flags & (GNRC_IPV6_NETIF_FLAGS_OTHER_CONF | GNRC_IPV6_NETIF_FLAGS_MANAGED)) >> 8, adv_ltime, reach_time, retrans_timer, pkt); if (hdr == NULL) { DEBUG("ndp internal: error allocating router advertisement.\n"); gnrc_pktbuf_release(pkt); return; } pkt = hdr; hdr = _build_headers(iface, pkt, dst, src); if (hdr == NULL) { DEBUG("ndp internal: error adding lower-layer headers.\n"); gnrc_pktbuf_release(pkt); return; } gnrc_netapi_send(gnrc_ipv6_pid, hdr); }