static void test_ipv6_nc_remove__success(void) { ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr); TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); }
static void test_ipv6_nc_remove__no_entry_addr2(void) { ipv6_addr_t addr = IPV6_ADDR_UNSPECIFIED; ipv6_addr_t exp_addr = DEFAULT_TEST_IPV6_ADDR; test_ipv6_nc_add__success(); /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF */ gnrc_ipv6_nc_remove(DEFAULT_TEST_NETIF, &addr); TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &exp_addr)); TEST_ASSERT_NULL(gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr)); }
static int _ipv6_nc_reset(void) { gnrc_ipv6_nc_t *tmp = NULL; for (gnrc_ipv6_nc_t *entry = gnrc_ipv6_nc_get_next(NULL); entry != NULL; tmp = entry, entry = gnrc_ipv6_nc_get_next(entry)) { if (tmp) { gnrc_ipv6_nc_remove(tmp->iface, &tmp->ipv6_addr); } } /* remove last entry */ if (tmp) { gnrc_ipv6_nc_remove(tmp->iface, &tmp->ipv6_addr); } printf("success: reset neighbor cache\n"); return 0; }
static int _ipv6_nc_del(char *ipv6_addr_str) { ipv6_addr_t ipv6_addr; if (ipv6_addr_from_str(&ipv6_addr, ipv6_addr_str) == NULL) { puts("error: unable to parse IPv6 address."); return 1; } gnrc_ipv6_nc_remove(KERNEL_PID_UNDEF, &ipv6_addr); printf("success: removed %s from neighbor cache\n", ipv6_addr_str); return 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); }
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)); }
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; }