Exemplo n.º 1
0
void _handle_snd_mc_ra(gnrc_netif_t *netif)
{
    gnrc_netif_acquire(netif);
    assert(netif != NULL);
    if (!gnrc_netif_is_6ln(netif)) {
        bool final_ra = (netif->ipv6.ra_sent > (UINT8_MAX - NDP_MAX_FIN_RA_NUMOF));
        uint32_t next_ra_time = random_uint32_range(NDP_MIN_RA_INTERVAL_MS,
                                                    NDP_MAX_RA_INTERVAL_MS);
        uint32_t next_scheduled = _evtimer_lookup(netif, GNRC_IPV6_NIB_SND_MC_RA);

        /* router has router advertising interface or the RA is one of the
         * (now deactivated) routers final one (and there is no next
         * scheduled within the possible time for next_ra_time) */
        if ((final_ra && (next_scheduled > NDP_MAX_RA_INTERVAL_MS)) ||
            gnrc_netif_is_rtr_adv(netif)) {
            _snd_rtr_advs(netif, NULL, final_ra);
            netif->ipv6.last_ra = (xtimer_now_usec64() / US_PER_MS) & UINT32_MAX;
            if ((netif->ipv6.ra_sent < NDP_MAX_INIT_RA_NUMOF) || final_ra) {
                if ((netif->ipv6.ra_sent < NDP_MAX_INIT_RA_NUMOF) &&
                    (next_ra_time > NDP_MAX_INIT_RA_INTERVAL)) {
                    next_ra_time = NDP_MAX_INIT_RA_INTERVAL;
                }
                netif->ipv6.ra_sent++;
            }
            /* netif->ipv6.ra_sent overflowed => this was our last final RA */
            if (netif->ipv6.ra_sent != 0) {
                _evtimer_add(netif, GNRC_IPV6_NIB_SND_MC_RA, &netif->ipv6.snd_mc_ra,
                             next_ra_time);
            }
        }
    }
    gnrc_netif_release(netif);
}
Exemplo n.º 2
0
_nib_abr_entry_t *_handle_abro(const sixlowpan_nd_opt_abr_t *abro)
{
    _nib_abr_entry_t *abr = NULL;

    if (abro->len != SIXLOWPAN_ND_OPT_ABR_LEN) {
        /* ignore silently */
        return NULL;
    }
    abr = _nib_abr_add(&abro->braddr);
    if (abr != NULL) {
        uint32_t abro_version = sixlowpan_nd_opt_abr_get_version(abro);
        uint16_t ltime = byteorder_ntohs(abro->ltime);

        if (abr->version >= abro_version) {
            abr->version = abro_version;
            abr->valid_until = _now_min() + ltime;
        }
        /* correct for default value */
        ltime = (ltime == 0) ? SIXLOWPAN_ND_OPT_ABR_LTIME_DEFAULT : ltime;
        _evtimer_add(abr, GNRC_IPV6_NIB_ABR_TIMEOUT, &abr->timeout,
                     /* UINT16_MAX min < UINT32_MAX ms so no risk of overflow */
                     MS_PER_SEC * SEC_PER_MIN * ltime);
    }
    return abr;
}
Exemplo n.º 3
0
void _handle_rereg_address(const ipv6_addr_t *addr)
{
    gnrc_netif_t *netif = gnrc_netif_get_by_ipv6_addr(addr);
    _nib_dr_entry_t *router = _nib_drl_get_dr();
    const bool router_reachable = (router != NULL) &&
                                  _is_reachable(router->next_hop);

    if (router_reachable && (netif != NULL)) {
        assert((unsigned)netif->pid == _nib_onl_get_if(router->next_hop));
        DEBUG("nib: Re-registering %s",
              ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
        DEBUG(" with upstream router %s\n",
              ipv6_addr_to_str(addr_str, &router->next_hop->ipv6,
                               sizeof(addr_str)));
        _snd_ns(&router->next_hop->ipv6, netif, addr, &router->next_hop->ipv6);
    }
    else {
        DEBUG("nib: Couldn't re-register %s, no current router found or address "
              "wasn't assigned to any interface anymore.\n",
              ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)));
    }
    if (netif != NULL) {
        int idx = gnrc_netif_ipv6_addr_idx(netif, addr);

        if (router_reachable &&
            (_is_valid(netif, idx) || (_is_tentative(netif, idx) &&
             (gnrc_netif_ipv6_addr_dad_trans(netif, idx) <
              SIXLOWPAN_ND_REG_TRANSMIT_NUMOF)))) {
            uint32_t retrans_time;

            if (_is_valid(netif, idx)) {
                retrans_time = SIXLOWPAN_ND_MAX_RS_SEC_INTERVAL * MS_PER_SEC;
            }
            else {
                retrans_time = netif->ipv6.retrans_time;
                /* increment encoded retransmission count */
                netif->ipv6.addrs_flags[idx]++;
            }
            _evtimer_add(&netif->ipv6.addrs[idx], GNRC_IPV6_NIB_REREG_ADDRESS,
                         &netif->ipv6.addrs_timers[idx], retrans_time);
        }
        else {
            netif->ipv6.rs_sent = 0;
            _handle_search_rtr(netif);
        }
    }
}
Exemplo n.º 4
0
void _handle_dad(const ipv6_addr_t *addr)
{
    ipv6_addr_t sol_nodes;
    gnrc_netif_t *netif = NULL;
    int idx = _get_netif_state(&netif, addr);
    if (idx >= 0) {
        ipv6_addr_set_solicited_nodes(&sol_nodes, addr);
        _snd_ns(addr, netif, &ipv6_addr_unspecified, &sol_nodes);
        _evtimer_add((void *)addr, GNRC_IPV6_NIB_VALID_ADDR,
                     &netif->ipv6.addrs_timers[idx],
                     netif->ipv6.retrans_time);
    }
    if (netif != NULL) {
        /* was acquired in `_get_netif_state()` */
        gnrc_netif_release(netif);
    }
}
Exemplo n.º 5
0
uint8_t _handle_aro(gnrc_netif_t *netif, const ipv6_hdr_t *ipv6,
                    const icmpv6_hdr_t *icmpv6,
                    const sixlowpan_nd_opt_ar_t *aro, const ndp_opt_t *sl2ao,
                    _nib_onl_entry_t *nce)
{
    assert(netif != NULL);
    if (gnrc_netif_is_6ln(netif) && (aro->len == SIXLOWPAN_ND_OPT_AR_LEN)) {
        DEBUG("nib: valid ARO received\n");
        DEBUG(" - length: %u\n", aro->len);
        DEBUG(" - status: %u\n", aro->status);
        DEBUG(" - registration lifetime: %u\n", byteorder_ntohs(aro->ltime));
        DEBUG(" - EUI-64: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
              aro->eui64.uint8[0], aro->eui64.uint8[1], aro->eui64.uint8[2],
              aro->eui64.uint8[3], aro->eui64.uint8[4], aro->eui64.uint8[5],
              aro->eui64.uint8[6], aro->eui64.uint8[7]);
        if (icmpv6->type == ICMPV6_NBR_ADV) {
            if (!_is_iface_eui64(netif, &aro->eui64)) {
                DEBUG("nib: ARO EUI-64 is not mine, ignoring ARO\n");
                return _ADDR_REG_STATUS_IGNORE;
            }
            switch (aro->status) {
                case SIXLOWPAN_ND_STATUS_SUCCESS: {
                    uint16_t ltime = byteorder_ntohs(aro->ltime);
                    uint32_t rereg_time;
                    int idx = gnrc_netif_ipv6_addr_idx(netif, &ipv6->dst);
                    /* if ltime 1min, reschedule NS in 30sec, otherwise 1min
                     * before timeout */
                    rereg_time = (ltime == 1U) ? (30 * MS_PER_SEC) :
                                 (ltime - 1U) * SEC_PER_MIN * MS_PER_SEC;
                    DEBUG("nib: Address registration of %s successful. "
                          "Scheduling re-registration in %" PRIu32 "ms\n",
                          ipv6_addr_to_str(addr_str, &ipv6->dst,
                                           sizeof(addr_str)), rereg_time);
                    netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK;
                    netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID;
                    _evtimer_add(&netif->ipv6.addrs[idx],
                                 GNRC_IPV6_NIB_REREG_ADDRESS,
                                 &netif->ipv6.addrs_timers[idx],
                                 rereg_time);
                    break;
                }
                case SIXLOWPAN_ND_STATUS_DUP:
                    DEBUG("nib: Address registration reports duplicate. "
                          "Removing address %s%%%u\n",
                          ipv6_addr_to_str(addr_str,
                                           &ipv6->dst,
                                           sizeof(addr_str)), netif->pid);
                    gnrc_netif_ipv6_addr_remove_internal(netif, &ipv6->dst);
                    /* TODO: generate new address */
                    break;
                case SIXLOWPAN_ND_STATUS_NC_FULL: {
                        DEBUG("nib: Router's neighbor cache is full. "
                              "Searching new router for DAD\n");
                        _nib_dr_entry_t *dr = _nib_drl_get(&ipv6->src, netif->pid);
                        assert(dr != NULL); /* otherwise we wouldn't be here */
                        _nib_drl_remove(dr);
                        if (_nib_drl_iter(NULL) == NULL) { /* no DRL left */
                            netif->ipv6.rs_sent = 0;
                            /* search (hopefully) new router */
                            _handle_search_rtr(netif);
                        }
                        else {
                            assert(dr->next_hop != NULL);
                            _handle_rereg_address(&ipv6->dst);
                        }
                    }
                    break;
            }
            return aro->status;
        }
#if GNRC_IPV6_NIB_CONF_6LR
        else if (gnrc_netif_is_6lr(netif) &&
                 (icmpv6->type == ICMPV6_NBR_SOL)) {
            return _reg_addr_upstream(netif, ipv6, icmpv6, aro, sl2ao, nce);
        }
#else   /* GNRC_IPV6_NIB_CONF_6LR */
        (void)sl2ao;
        (void)nce;
#endif  /* GNRC_IPV6_NIB_CONF_6LR */
    }
#if ENABLE_DEBUG
    else if (aro->len != SIXLOWPAN_ND_OPT_AR_LEN) {
        DEBUG("nib: ARO of unexpected length %u, ignoring ARO\n", aro->len);
    }
#endif  /* ENABLE_DEBUG */
    return _ADDR_REG_STATUS_IGNORE;
}