Exemple #1
0
/* sets an entry to stale if its l2addr differs from the given one or creates it stale if it
 * does not exist */
static void _stale_nc(kernel_pid_t iface, ipv6_addr_t *ipaddr, uint8_t *l2addr,
                      int l2addr_len)
{
    if (l2addr_len != -ENOTSUP) {
        gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, ipaddr);
        if (nc_entry == NULL) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            /* tentative type see https://tools.ietf.org/html/rfc6775#section-6.3 */
            gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
            if ((ipv6_iface == NULL) || (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
                timex_t t = { GNRC_SIXLOWPAN_ND_TENTATIVE_NCE_LIFETIME, 0 };
                gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                                 GNRC_IPV6_NC_STATE_STALE | GNRC_IPV6_NC_TYPE_TENTATIVE);
                vtimer_remove(&nc_entry->type_timeout);
                vtimer_set_msg(&nc_entry->type_timeout, t, gnrc_ipv6_pid,
                               GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT, nc_entry);
                return;
            }
#endif
            gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                             GNRC_IPV6_NC_STATE_STALE);
        }
        else if (((uint16_t)l2addr_len != nc_entry->l2_addr_len) ||
                 (memcmp(l2addr, nc_entry->l2_addr, l2addr_len) != 0)) {
            /* if entry exists but l2 address differs: set */
            nc_entry->l2_addr_len = (uint16_t)l2addr_len;
            memcpy(nc_entry->l2_addr, l2addr, l2addr_len);
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
    }
}
Exemple #2
0
static void test_ipv6_nc_add__address_registered(void)
{
    ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR;
    gnrc_ipv6_nc_t *entry1, *entry2;

    TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4,
                                                    sizeof(TEST_STRING4), 0)));
    TEST_ASSERT_NOT_NULL((entry2 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4,
                                                    sizeof(TEST_STRING4), 0)));
    TEST_ASSERT(entry1 == entry2);
}
Exemple #3
0
static void test_ipv6_nc_add__full(void)
{
    ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR;

    for (int i = 0; i < GNRC_IPV6_NC_SIZE; i++) {
        TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4,
                                              sizeof(TEST_STRING4), 0));
        addr.u16[7].u16++;
    }

    TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4,
                                      sizeof(TEST_STRING4), 0));
}
Exemple #4
0
static void test_ipv6_nc_add__l2addr_too_long(void)
{
    ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR;

    TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4,
                                      GNRC_IPV6_NC_L2_ADDR_MAX + TEST_UINT8, 0));
}
Exemple #5
0
static void test_ipv6_nc_add__addr_unspecified(void)
{
    ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED;

    TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING4,
                                      sizeof(TEST_STRING4), 0));
}
Exemple #6
0
static void test_ipv6_nc_add__iface_KERNEL_PID_UNDEF(void)
{
    ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR;

    TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(KERNEL_PID_UNDEF, &addr, TEST_STRING4,
                                          sizeof(TEST_STRING4), 0));
}
Exemple #7
0
static int _ipv6_nc_add(kernel_pid_t iface, char *ipv6_addr_str,
                        char *l2_addr_str)
{
    ipv6_addr_t ipv6_addr;
    uint8_t l2_addr[MAX_L2_ADDR_LEN];
    size_t l2_addr_len;

    if (ipv6_addr_from_str(&ipv6_addr, ipv6_addr_str) == NULL) {
        puts("error: unable to parse IPv6 address.");
        return 1;
    }

    if ((l2_addr_len = gnrc_netif_addr_from_str(l2_addr, sizeof(l2_addr),
                       l2_addr_str)) == 0) {
        puts("error: unable to parse link-layer address.");
        return 1;
    }

    if (gnrc_ipv6_nc_add(iface, &ipv6_addr, l2_addr, l2_addr_len, 0) == NULL) {
        puts("error: unable to add address to neighbor cache.");
        return 1;
    }

    printf("success: added IPv6 address %s to neighbor cache\n", ipv6_addr_str);
    return 0;
}
Exemple #8
0
static void test_ipv6_nc_add__address_update_despite_free_entry(void)
{
    ipv6_addr_t default_addr = DEFAULT_TEST_IPV6_ADDR;
    ipv6_addr_t other_addr = OTHER_TEST_IPV6_ADDR;
    gnrc_ipv6_nc_t *entry1, *entry2;

    TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(OTHER_TEST_NETIF, &other_addr, TEST_STRING4,
                                          sizeof(TEST_STRING4), 0));
    TEST_ASSERT_NOT_NULL((entry1 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &default_addr, TEST_STRING4,
                                                    sizeof(TEST_STRING4), 0)));

    /* create space by removing first entry and see if duplicate is still detected & updated */
    gnrc_ipv6_nc_remove(OTHER_TEST_NETIF, &other_addr);
    TEST_ASSERT_NOT_NULL((entry2 = gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &default_addr, TEST_STRING4,
                                                    sizeof(TEST_STRING4), 0)));
    TEST_ASSERT(entry1 == entry2);
}
Exemple #9
0
/* sets an entry to stale if its l2addr differs from the given one or creates it stale if it
 * does not exist */
static void _stale_nc(kernel_pid_t iface, ipv6_addr_t *ipaddr, uint8_t *l2addr,
                      int l2addr_len)
{
    if (l2addr_len != -ENOTSUP) {
        gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, ipaddr);
        if (nc_entry == NULL) {
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            /* tentative type see https://tools.ietf.org/html/rfc6775#section-6.3 */
            gnrc_ipv6_netif_t *ipv6_iface = gnrc_ipv6_netif_get(iface);
            if ((ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
                (ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
                if ((nc_entry = gnrc_ipv6_nc_add(iface, ipaddr, l2addr,
                                                 (uint16_t)l2addr_len,
                                                 GNRC_IPV6_NC_STATE_STALE |
                                                 GNRC_IPV6_NC_TYPE_TENTATIVE)) != NULL) {
                    xtimer_set_msg(&nc_entry->type_timeout,
                                   (GNRC_SIXLOWPAN_ND_TENTATIVE_NCE_LIFETIME * SEC_IN_USEC),
                                   &nc_entry->type_timeout_msg,
                                   gnrc_ipv6_pid);
                }
                return;
            }
#endif
            gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                             GNRC_IPV6_NC_STATE_STALE);
        }
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
        /* unreachable set in gnrc_ndp_retrans_nbr_sol() will just be staled */
        else if (gnrc_ipv6_nc_get_state(nc_entry) == GNRC_IPV6_NC_STATE_UNREACHABLE) {
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
#endif
        else if (((uint16_t)l2addr_len != nc_entry->l2_addr_len) ||
                 (memcmp(l2addr, nc_entry->l2_addr, l2addr_len) != 0)) {
            /* if entry exists but l2 address differs: set */
            nc_entry->l2_addr_len = (uint16_t)l2addr_len;
            memcpy(nc_entry->l2_addr, l2addr, l2addr_len);
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
    }
}
Exemple #10
0
static void test_ipv6_nc_get_next__2_entries(void)
{
    ipv6_addr_t addr = OTHER_TEST_IPV6_ADDR;
    gnrc_ipv6_nc_t *entry = NULL;

    test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
    TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr, TEST_STRING8,
                                          sizeof(TEST_STRING8) - 1, 0));


    TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(NULL)));
    TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(entry)));
    TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next(entry));
}
Exemple #11
0
static void test_ipv6_nc_get_next__holey(void)
{
    ipv6_addr_t addr1 = OTHER_TEST_IPV6_ADDR;
    ipv6_addr_t addr2 = THIRD_TEST_IPV6_ADDR;
    gnrc_ipv6_nc_t *entry = NULL, *exp_entry = NULL;

    /* adds DEFAULT_TEST_IPV6_ADDR and OTHER_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */
    test_ipv6_nc_get_next__2_entries();
    TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, &addr2, TEST_STRING8,
                                          sizeof(TEST_STRING8) - 2, 0));
    TEST_ASSERT_NOT_NULL((exp_entry = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr2)));
    gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr1);

    TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(NULL)));
    TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get_next(entry)));
    TEST_ASSERT(exp_entry == entry);
    TEST_ASSERT_NULL(gnrc_ipv6_nc_get_next(entry));
}
Exemple #12
0
/* sets an entry to stale if its l2addr differs from the given one or creates it stale if it
 * does not exist */
static void _stale_nc(kernel_pid_t iface, ipv6_addr_t *ipaddr, uint8_t *l2addr,
                      int l2addr_len)
{
    if (l2addr_len != -ENOTSUP) {
        gnrc_ipv6_nc_t *nc_entry = gnrc_ipv6_nc_get(iface, ipaddr);
        if (nc_entry == NULL) {
            gnrc_ipv6_nc_add(iface, ipaddr, l2addr, (uint16_t)l2addr_len,
                             GNRC_IPV6_NC_STATE_STALE);
        }
        else if (((uint16_t)l2addr_len != nc_entry->l2_addr_len) ||
                 (memcmp(l2addr, nc_entry->l2_addr, l2addr_len) != 0)) {
            /* if entry exists but l2 address differs: set */
            nc_entry->l2_addr_len = (uint16_t)l2addr_len;
            memcpy(nc_entry->l2_addr, l2addr, l2addr_len);
            gnrc_ndp_internal_set_state(nc_entry, GNRC_IPV6_NC_STATE_STALE);
        }
    }
}
Exemple #13
0
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)
{
    eui64_t eui64;
    gnrc_ipv6_netif_t *ipv6_iface;
    gnrc_ipv6_nc_t *nc_entry;
    uint8_t status = 0;
    (void)sl2a;
    (void)sl2a_len;
    if (ar_opt->len != SIXLOWPAN_ND_OPT_AR_LEN) {
        /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */
        return 0;
    }
    if (gnrc_netapi_get(iface, NETOPT_ADDRESS_LONG, 0, &eui64,
                        sizeof(eui64)) < 0) {
        /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */
        return 0;
    }
    ipv6_iface = gnrc_ipv6_netif_get(iface);
    nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src);
    switch (icmpv6_type) {
        case ICMPV6_NBR_ADV:
            if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) {
                DEBUG("6lo nd: interface not a 6LoWPAN interface\n");
                return 0;
            }
            if (eui64.uint64.u64 != ar_opt->eui64.uint64.u64) {
                /* discard silently: see https://tools.ietf.org/html/rfc6775#section-5.5.2 */
                return 0;
            }
            switch (ar_opt->status) {
                case SIXLOWPAN_ND_STATUS_SUCCESS:
                    DEBUG("6lo nd: address registration successful\n");
                    mutex_lock(&ipv6_iface->mutex);
                    /* reschedule 1 minute before lifetime expires */
                    timex_t t = { (uint32_t)(byteorder_ntohs(ar_opt->ltime) - 1) * 60, 0 };
                    vtimer_remove(&nc_entry->nbr_sol_timer);
                    vtimer_set_msg(&nc_entry->nbr_sol_timer, t, gnrc_ipv6_pid,
                                   GNRC_NDP_MSG_NBR_SOL_RETRANS, nc_entry);
                    mutex_unlock(&ipv6_iface->mutex);
                    break;
                case SIXLOWPAN_ND_STATUS_DUP:
                    DEBUG("6lo nd: address registration determined duplicated\n");
                    /* TODO: handle DAD failed case */
                    gnrc_ipv6_netif_remove_addr(iface, &ipv6->dst);
                    /* address should not be used anymore */
                    break;
                case SIXLOWPAN_ND_STATUS_NC_FULL:
                    DEBUG("6lo nd: neighbor cache on router is full\n");
                    gnrc_ipv6_nc_remove(iface, &ipv6->src);
                    /* try to find another router */
                    gnrc_sixlowpan_nd_init(ipv6_iface);
                    break;
                default:
                    DEBUG("6lo nd: unknown status for registration received\n");
                    break;
            }
            break;
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
        case ICMPV6_NBR_SOL:
            if (!(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) &&
                !(ipv6_iface->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER)) {
                DEBUG("6lo nd: interface not a 6LoWPAN or forwarding interface\n");
                return 0;
            }
            if ((ar_opt->status != 0) ||
                ipv6_addr_is_unspecified(&ipv6->src)) {
                /* discard silently */
                return 0;
            }
            /* TODO multihop DAD */
            if ((nc_entry != NULL) &&
                ((gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_REGISTERED) ||
                 (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_TENTATIVE)) &&
                ((nc_entry->eui64.uint64.u64 != 0) &&
                 (ar_opt->eui64.uint64.u64 != nc_entry->eui64.uint64.u64))) {
                /* there is already another node with this address */
                DEBUG("6lo nd: duplicate address detected\n");
                status = SIXLOWPAN_ND_STATUS_DUP;
            }
            else if ((nc_entry != NULL) && (ar_opt->ltime.u16 == 0)) {
                gnrc_ipv6_nc_remove(iface, &ipv6->src);
                /* TODO, notify routing protocol */
            }
            else if (ar_opt->ltime.u16 != 0) {
                /* TODO: multihop DAD behavior */
                uint16_t reg_ltime;
                if (nc_entry == NULL) {
                    if ((nc_entry = gnrc_ipv6_nc_add(iface, &ipv6->src, sl2a, sl2a_len,
                                                     GNRC_IPV6_NC_STATE_STALE)) == NULL) {
                        DEBUG("6lo nd: neighbor cache is full\n");
                        return SIXLOWPAN_ND_STATUS_NC_FULL;
                    }
                    nc_entry->eui64 = ar_opt->eui64;
                }
                nc_entry->flags &= ~GNRC_IPV6_NC_TYPE_MASK;
                nc_entry->flags |= GNRC_IPV6_NC_TYPE_REGISTERED;
                reg_ltime = byteorder_ntohs(ar_opt->ltime);
                /* TODO: notify routing protocol */
                vtimer_remove(&nc_entry->type_timeout);
                vtimer_set_msg(&nc_entry->type_timeout, timex_set(reg_ltime * 60, 0),
                               gnrc_ipv6_pid, GNRC_SIXLOWPAN_ND_MSG_AR_TIMEOUT, nc_entry);
            }
            break;
#endif
        default:
            break;
    }

    return status;
}
Exemple #14
0
void gnrc_ndp_rtr_adv_handle(kernel_pid_t iface, gnrc_pktsnip_t *pkt, ipv6_hdr_t *ipv6,
                             ndp_rtr_adv_t *rtr_adv, size_t icmpv6_size)
{
    uint8_t *buf = (uint8_t *)(rtr_adv + 1);
    gnrc_ipv6_nc_t *nc_entry = NULL;
    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);
    uint8_t l2src[GNRC_IPV6_NC_L2_ADDR_MAX];
#ifdef MODULE_GNRC_SIXLOWPAN_ND
    uint32_t next_rtr_sol = 0;
#endif
    int sicmpv6_size = (int)icmpv6_size, l2src_len = 0;
    uint16_t opt_offset = 0;

    if (!ipv6_addr_is_link_local(&ipv6->src) ||
        ipv6_addr_is_multicast(&ipv6->src) ||
        (ipv6->hl != 255) || (rtr_adv->code != 0) ||
        (icmpv6_size < sizeof(ndp_rtr_adv_t))) {
        DEBUG("ndp: router advertisement was invalid\n");
        /* ipv6 releases */
        return;
    }
    /* get source from default router list */
    nc_entry = gnrc_ipv6_nc_get(iface, &ipv6->src);
    if (nc_entry == NULL) { /* not in default router list */
        /* create default router list entry */
        nc_entry = gnrc_ipv6_nc_add(iface, &ipv6->src, NULL, 0,
                                    GNRC_IPV6_NC_IS_ROUTER);
        if (nc_entry == NULL) {
            DEBUG("ndp: error on default router list entry creation\n");
            return;
        }
    }
    else if ((nc_entry->flags & GNRC_IPV6_NC_IS_ROUTER) && (byteorder_ntohs(rtr_adv->ltime) == 0)) {
        nc_entry->flags &= ~GNRC_IPV6_NC_IS_ROUTER;
    }
    else {
        nc_entry->flags |= GNRC_IPV6_NC_IS_ROUTER;
    }
    /* set router life timer */
    if (rtr_adv->ltime.u16 != 0) {
        uint16_t ltime = byteorder_ntohs(rtr_adv->ltime);
#ifdef MODULE_GNRC_SIXLOWPAN_ND
        next_rtr_sol = ltime;
#endif
        xtimer_set_msg(&nc_entry->rtr_timeout, (ltime * SEC_IN_USEC),
                       &nc_entry->rtr_timeout_msg, thread_getpid());
    }
    /* set current hop limit from message if available */
    if (rtr_adv->cur_hl != 0) {
        if_entry->cur_hl = rtr_adv->cur_hl;
    }
    /* set flags from message */
    if_entry->flags &= ~GNRC_IPV6_NETIF_FLAGS_RTR_ADV_MASK;
    if_entry->flags |= (rtr_adv->flags << GNRC_IPV6_NETIF_FLAGS_RTR_ADV_POS) &
                       GNRC_IPV6_NETIF_FLAGS_RTR_ADV_MASK;
    /* set reachable time from message if it is not the same as the random base
     * value */
    if ((rtr_adv->reach_time.u32 != 0) &&
        (if_entry->reach_time_base != byteorder_ntohl(rtr_adv->reach_time))) {
        _set_reach_time(if_entry, byteorder_ntohl(rtr_adv->reach_time));
    }
    /* set retransmission timer from message */
    if (rtr_adv->retrans_timer.u32 != 0) {
        if_entry->retrans_timer = timex_set(0, byteorder_ntohl(rtr_adv->retrans_timer));
        timex_normalize(&if_entry->retrans_timer);
    }
    mutex_unlock(&if_entry->mutex);
    sicmpv6_size -= sizeof(ndp_rtr_adv_t);
    /* parse options */
    while (sicmpv6_size > 0) {
        ndp_opt_t *opt = (ndp_opt_t *)(buf + opt_offset);
        switch (opt->type) {
            case NDP_OPT_SL2A:
                if ((l2src_len = gnrc_ndp_internal_sl2a_opt_handle(pkt, ipv6, rtr_adv->type, opt,
                                                                   l2src)) < 0) {
                    /* -ENOTSUP can not happen */
                    /* invalid source link-layer address option */
                    return;
                }
                break;
            case NDP_OPT_MTU:
                if (!gnrc_ndp_internal_mtu_opt_handle(iface, rtr_adv->type, (ndp_opt_mtu_t *)opt)) {
                    /* invalid MTU option */
                    return;
                }
                break;
            case NDP_OPT_PI:
                if (!gnrc_ndp_internal_pi_opt_handle(iface, rtr_adv->type, (ndp_opt_pi_t *)opt)) {
                    /* invalid prefix information option */
                    return;
                }
#ifdef MODULE_GNRC_SIXLOWPAN_ND
                uint32_t valid_ltime = byteorder_ntohl(((ndp_opt_pi_t *)opt)->valid_ltime);
                if ((valid_ltime != 0) && (valid_ltime < next_rtr_sol)) {
                    next_rtr_sol = valid_ltime;
                }
#endif
                break;
#ifdef MODULE_GNRC_SIXLOWPAN_ND
            case NDP_OPT_6CTX:
                if (!gnrc_sixlowpan_nd_opt_6ctx_handle(rtr_adv->type,
                                                       (sixlowpan_nd_opt_6ctx_t *)opt)) {
                    /* invalid 6LoWPAN context option */
                    return;
                }
                uint16_t ltime = byteorder_ntohs(((sixlowpan_nd_opt_6ctx_t *)opt)->ltime);
                if ((ltime != 0) && (ltime < (next_rtr_sol / 60))) {
                    next_rtr_sol = ltime * 60;
                }

                break;
#endif
#ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER
            case NDP_OPT_ABR:
                gnrc_sixlowpan_nd_opt_abr_handle(iface, rtr_adv, icmpv6_size,
                                                 (sixlowpan_nd_opt_abr_t *)opt);
                break;
#endif
        }

        opt_offset += (opt->len * 8);
        sicmpv6_size -= (opt->len * 8);

#if ENABLE_DEBUG
        if (sicmpv6_size < 0) {
            DEBUG("ndp: Option parsing out of sync.\n");
        }
#endif
    }
#if ENABLE_DEBUG && defined(MODULE_GNRC_SIXLOWPAN_ND)
    if ((if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) && (l2src_len <= 0)) {
        DEBUG("ndp: Router advertisement did not contain any source address information\n");
    }
#endif
    _stale_nc(iface, &ipv6->src, l2src, l2src_len);
    /* stop multicast router solicitation retransmission timer */
    xtimer_remove(&if_entry->rtr_sol_timer);
#ifdef MODULE_GNRC_SIXLOWPAN_ND
    if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
        /* 3/4 of the time should be "well before" enough the respective timeout
         * not to run out; see https://tools.ietf.org/html/rfc6775#section-5.4.3 */
        next_rtr_sol *= 3;
        next_rtr_sol = (next_rtr_sol > 4) ? (next_rtr_sol >> 2) : 1;
        /* according to https://tools.ietf.org/html/rfc6775#section-5.3:
         * "In all cases, the RS retransmissions are terminated when an RA is
         *  received."
         *  Hence, reset router solicitation counter and reset timer. */
        if_entry->rtr_sol_count = 0;
        gnrc_sixlowpan_nd_rtr_sol_reschedule(nc_entry, next_rtr_sol);
        gnrc_ndp_internal_send_nbr_sol(nc_entry->iface, NULL, &nc_entry->ipv6_addr,
                                       &nc_entry->ipv6_addr);
        if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_ROUTER) {
            gnrc_ipv6_netif_set_rtr_adv(if_entry, true);
        }
    }
Exemple #15
0
static void test_ipv6_nc_add__address_NULL(void)
{
    TEST_ASSERT_NULL(gnrc_ipv6_nc_add(DEFAULT_TEST_NETIF, NULL, TEST_STRING4,
                                      sizeof(TEST_STRING4), 0));
}