Exemple #1
0
void _auto_configure_addr(gnrc_netif_t *netif, const ipv6_addr_t *pfx,
                          uint8_t pfx_len)
{
    ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED;
    int idx;
    uint8_t flags = GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE;

    if (!(netif->flags & GNRC_NETIF_FLAGS_HAS_L2ADDR)) {
        DEBUG("nib: interface %i has no link-layer addresses\n", netif->pid);
        return;
    }
    DEBUG("nib: add address based on %s/%u automatically to interface %u\n",
          ipv6_addr_to_str(addr_str, pfx, sizeof(addr_str)),
          pfx_len, netif->pid);
#if GNRC_IPV6_NIB_CONF_6LN
    bool new_address = false;
#endif  /* GNRC_IPV6_NIB_CONF_6LN */
    gnrc_netif_ipv6_get_iid(netif, (eui64_t *)&addr.u64[1]);
    ipv6_addr_init_prefix(&addr, pfx, pfx_len);
    if ((idx = gnrc_netif_ipv6_addr_idx(netif, &addr)) < 0) {
        if ((idx = gnrc_netif_ipv6_addr_add_internal(netif, &addr, pfx_len,
                                                     flags)) < 0) {
            DEBUG("nib: Can't add link-local address on interface %u\n",
                  netif->pid);
            return;
        }
#if GNRC_IPV6_NIB_CONF_6LN
        new_address = true;
#endif  /* GNRC_IPV6_NIB_CONF_6LN */
    }

#if GNRC_IPV6_NIB_CONF_6LN
    /* mark link-local addresses as valid on 6LN */
    if (gnrc_netif_is_6ln(netif) && ipv6_addr_is_link_local(pfx)) {
        /* don't do this beforehand or risk a deadlock:
         *  - gnrc_netif_ipv6_addr_add_internal() adds VALID (i.e. manually configured
         *    addresses to the prefix list locking the NIB's mutex which is already
         *    locked here) */
        netif->ipv6.addrs_flags[idx] &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK;
        netif->ipv6.addrs_flags[idx] |= GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID;
    }
#endif  /* GNRC_IPV6_NIB_CONF_6LN */
#if GNRC_IPV6_NIB_CONF_6LN
    if (new_address && gnrc_netif_is_6ln(netif) &&
        !gnrc_netif_is_6lbr(netif)) {
        _handle_rereg_address(&netif->ipv6.addrs[idx]);
    }
#else   /* GNRC_IPV6_NIB_CONF_6LN */
    (void)idx;
#endif  /* GNRC_IPV6_NIB_CONF_6LN */
}
Exemple #2
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;
}