static void test_ipv6_netif_find_best_src_addr__success(void) { ipv6_addr_t ll_addr1 = IPV6_ADDR_UNSPECIFIED; ipv6_addr_t ll_addr2 = IPV6_ADDR_UNSPECIFIED; ipv6_addr_t mc_addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL; ipv6_addr_t *out = NULL; ll_addr1.u8[15] = 1; ipv6_addr_set_link_local_prefix(&ll_addr1); ll_addr2.u8[15] = 2; ipv6_addr_set_link_local_prefix(&ll_addr2); TEST_ASSERT_EQUAL_INT(126, ipv6_addr_match_prefix(&ll_addr2, &ll_addr1)); test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ TEST_ASSERT_NOT_NULL(ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &mc_addr, DEFAULT_TEST_PREFIX_LEN, 0)); TEST_ASSERT_NOT_NULL(ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &ll_addr1, DEFAULT_TEST_PREFIX_LEN, 0)); TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &ll_addr2))); TEST_ASSERT(out != &ll_addr1); TEST_ASSERT(out != &ll_addr2); TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &ll_addr1)); }
gnrc_sixlowpan_ctx_t *gnrc_sixlowpan_ctx_lookup_addr(const ipv6_addr_t *addr) { uint8_t best = 0; gnrc_sixlowpan_ctx_t *res = NULL; mutex_lock(&_ctx_mutex); for (unsigned int id = 0; id < GNRC_SIXLOWPAN_CTX_SIZE; id++) { if (_valid(id)) { uint8_t match = ipv6_addr_match_prefix(&_ctxs[id].prefix, addr); if ((_ctxs[id].prefix_len <= match) && (match > best)) { best = match; res = &(_ctxs[id]); } } } mutex_unlock(&_ctx_mutex); #if ENABLE_DEBUG if (res != NULL) { DEBUG("6lo ctx: found context (%u, %s/%" PRIu8 ") ", (res->flags_id & GNRC_SIXLOWPAN_CTX_FLAGS_CID_MASK), ipv6_addr_to_str(ipv6str, &res->prefix, sizeof(ipv6str)), res->prefix_len); DEBUG("for address %s\n", ipv6_addr_to_str(ipv6str, addr, sizeof(ipv6str))); } #endif return res; }
static inline bool _check_prefixes(gnrc_ipv6_netif_addr_t *a, gnrc_ipv6_netif_addr_t *b) { if ((a->prefix_len == b->prefix_len) && (ipv6_addr_match_prefix(&a->addr, &b->addr) >= a->prefix_len)) { return true; } return false; }
static uint8_t _find_by_prefix_unsafe(ipv6_addr_t **res, gnrc_ipv6_netif_t *iface, const ipv6_addr_t *addr, uint8_t *only) { uint8_t best_match = 0; for (int i = 0; i < GNRC_IPV6_NETIF_ADDR_NUMOF; i++) { uint8_t match; if ((only != NULL) && !(bf_isset(only, i))) { continue; } if (((only != NULL) && gnrc_ipv6_netif_addr_is_non_unicast(&(iface->addrs[i].addr))) || ipv6_addr_is_unspecified(&(iface->addrs[i].addr))) { continue; } match = ipv6_addr_match_prefix(&(iface->addrs[i].addr), addr); if ((only == NULL) && !ipv6_addr_is_multicast(addr) && (match < iface->addrs[i].prefix_len)) { /* match but not of same subnet */ continue; } if (match > best_match) { if (res != NULL) { *res = &(iface->addrs[i].addr); } best_match = match; } } #if ENABLE_DEBUG if (*res != NULL) { DEBUG("ipv6 netif: Found %s on interface %" PRIkernel_pid " matching ", ipv6_addr_to_str(addr_str, *res, sizeof(addr_str)), iface->pid); DEBUG("%s by %" PRIu8 " bits (used as source address = %s)\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), best_match, (only != NULL) ? "true" : "false"); } else { DEBUG("ipv6 netif: Did not found any address on interface %" PRIkernel_pid " matching %s (used as source address = %s)\n", iface->pid, ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), (only != NULL) ? "true" : "false"); } #endif return best_match; }
static void test_ipv6_netif_match_prefix__success3(void) { ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX64; ipv6_addr_t *out = NULL; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_match_prefix(DEFAULT_TEST_NETIF, &addr))); TEST_ASSERT(out != &addr); TEST_ASSERT_EQUAL_INT(64, ipv6_addr_match_prefix(out, &addr)); }
static void test_ipv6_netif_find_by_prefix__success2(void) { ipv6_addr_t addr = DEFAULT_TEST_IPV6_PREFIX18; ipv6_addr_t *out = NULL; test_ipv6_netif_add_addr__success(); /* adds DEFAULT_TEST_IPV6_ADDR to * DEFAULT_TEST_NETIF */ TEST_ASSERT_EQUAL_INT(DEFAULT_TEST_NETIF, ng_ipv6_netif_find_by_prefix(&out, &addr)); TEST_ASSERT_NOT_NULL(out); TEST_ASSERT(out != &addr); TEST_ASSERT_EQUAL_INT(18, ipv6_addr_match_prefix(out, &addr)); }
static gnrc_sixlowpan_nd_router_prf_t *_get_free_prefix(ipv6_addr_t *prefix, size_t prefix_len) { gnrc_sixlowpan_nd_router_prf_t *prf = NULL; for (int i = 0; i < GNRC_SIXLOWPAN_ND_ROUTER_ABR_NUMOF; i++) { if ((ipv6_addr_match_prefix(&_prefixes[i].prefix->addr, prefix) >= prefix_len) && (_prefixes[i].prefix->prefix_len == prefix_len)) { return &_prefixes[i]; } if ((prf == NULL) && ipv6_addr_is_unspecified(&_prefixes[i].prefix->addr)) { prf = &_prefixes[i]; } } return prf; }
static unsigned _match(const gnrc_netif_t *netif, const ipv6_addr_t *addr, const uint8_t *filter, int *idx) { unsigned best_match = 0; assert(idx != NULL); *idx = -1; for (int i = 0; i < GNRC_NETIF_IPV6_ADDRS_NUMOF; i++) { unsigned match; if ((netif->ipv6.addrs_flags[i] == 0) || ((filter != NULL) && _addr_anycast(netif, i)) || /* discard const intentionally */ ((filter != NULL) && !(bf_isset((uint8_t *)filter, i)))) { continue; } match = ipv6_addr_match_prefix(&(netif->ipv6.addrs[i]), addr); if (((match > 64U) || !ipv6_addr_is_link_local(&(netif->ipv6.addrs[i]))) && (match >= best_match)) { if (idx != NULL) { *idx = i; } best_match = match; } } if (*idx >= 0) { DEBUG("gnrc_netif: Found %s on interface %" PRIkernel_pid " matching ", ipv6_addr_to_str(addr_str, &netif->ipv6.addrs[*idx], sizeof(addr_str)), netif->pid); DEBUG("%s by %u bits (used as source address = %s)\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), best_match, (filter != NULL) ? "true" : "false"); } else { DEBUG("gnrc_netif: Did not found any address on interface %" PRIkernel_pid " matching %s (used as source address = %s)\n", netif->pid, ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), (filter != NULL) ? "true" : "false"); } return best_match; }
static void test_ipv6_netif_find_best_src_addr__no_unicast(void) { ipv6_addr_t ll_addr1 = IPV6_ADDR_UNSPECIFIED; ipv6_addr_t ll_addr2 = IPV6_ADDR_UNSPECIFIED; ipv6_addr_t mc_addr = IPV6_ADDR_ALL_NODES_LINK_LOCAL; ll_addr1.u8[15] = 1; ipv6_addr_set_link_local_prefix(&ll_addr1); ll_addr2.u8[15] = 2; ipv6_addr_set_link_local_prefix(&ll_addr2); TEST_ASSERT_EQUAL_INT(126, ipv6_addr_match_prefix(&ll_addr2, &ll_addr1)); test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ TEST_ASSERT_NOT_NULL(ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &mc_addr, DEFAULT_TEST_PREFIX_LEN, 0)); TEST_ASSERT_NOT_NULL(ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &ll_addr1, DEFAULT_TEST_PREFIX_LEN, NG_IPV6_NETIF_ADDR_FLAGS_NON_UNICAST)); TEST_ASSERT_NULL(ng_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &ll_addr2)); }
int gnrc_netif_ipv6_addr_add_internal(gnrc_netif_t *netif, const ipv6_addr_t *addr, unsigned pfx_len, uint8_t flags) { unsigned idx = UINT_MAX; assert((netif != NULL) && (addr != NULL)); assert(!(ipv6_addr_is_multicast(addr) || ipv6_addr_is_unspecified(addr) || ipv6_addr_is_loopback(addr))); assert((pfx_len > 0) && (pfx_len <= 128)); gnrc_netif_acquire(netif); if ((flags & GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_MASK) == GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE) { /* set to first retransmission */ flags &= ~GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_TENTATIVE; flags |= 0x1; } for (unsigned i = 0; i < GNRC_NETIF_IPV6_ADDRS_NUMOF; i++) { if (ipv6_addr_equal(&netif->ipv6.addrs[i], addr)) { gnrc_netif_release(netif); return i; } if ((idx == UINT_MAX) && (netif->ipv6.addrs_flags[i] == 0)) { idx = i; } } if (idx == UINT_MAX) { gnrc_netif_release(netif); return -ENOMEM; } netif->ipv6.addrs_flags[idx] = flags; memcpy(&netif->ipv6.addrs[idx], addr, sizeof(netif->ipv6.addrs[idx])); #ifdef MODULE_GNRC_IPV6_NIB #if GNRC_IPV6_NIB_CONF_ARSM ipv6_addr_t sol_nodes; int res; /* TODO: SHOULD delay join between 0 and MAX_RTR_SOLICITATION_DELAY * for SLAAC */ ipv6_addr_set_solicited_nodes(&sol_nodes, addr); res = gnrc_netif_ipv6_group_join_internal(netif, &sol_nodes); if (res < 0) { DEBUG("nib: Can't join solicited-nodes of %s on interface %u\n", ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)), netif->pid); } #endif /* GNRC_IPV6_NIB_CONF_ARSM */ if (_get_state(netif, idx) == GNRC_NETIF_IPV6_ADDRS_FLAGS_STATE_VALID) { void *state = NULL; gnrc_ipv6_nib_pl_t ple; bool in_pl = false; while (gnrc_ipv6_nib_pl_iter(netif->pid, &state, &ple)) { if (ipv6_addr_match_prefix(&ple.pfx, addr) >= pfx_len) { in_pl = true; } } if (!in_pl) { gnrc_ipv6_nib_pl_set(netif->pid, addr, pfx_len, UINT32_MAX, UINT32_MAX); } } #if GNRC_IPV6_NIB_CONF_SLAAC else { /* TODO: send out NS to solicited nodes for DAD probing */ } #endif #else (void)pfx_len; #endif gnrc_netif_release(netif); return idx; }