static void test_ipv6_nc_still_reachable__incomplete(void) { ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; gnrc_ipv6_nc_t *entry = NULL; /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF and sets flags to * (GNRC_IPV6_NC_STATE_INCOMPLETE << GNRC_IPV6_NC_STATE_POS) */ test_ipv6_nc_is_reachable__incomplete(); TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); TEST_ASSERT(!gnrc_ipv6_nc_is_reachable(entry)); TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_still_reachable(&addr)); TEST_ASSERT(!gnrc_ipv6_nc_is_reachable(entry)); }
static inline kernel_pid_t _next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len, kernel_pid_t iface, ipv6_addr_t *dst, gnrc_pktsnip_t *pkt) { kernel_pid_t found_iface; #if defined(MODULE_GNRC_SIXLOWPAN_ND) (void)pkt; found_iface = gnrc_sixlowpan_nd_next_hop_l2addr(l2addr, l2addr_len, iface, dst); if (found_iface > KERNEL_PID_UNDEF) { return found_iface; } #endif #if defined(MODULE_GNRC_NDP_NODE) found_iface = gnrc_ndp_node_next_hop_l2addr(l2addr, l2addr_len, iface, dst, pkt); #elif !defined(MODULE_GNRC_SIXLOWPAN_ND) && defined(MODULE_GNRC_IPV6_NC) (void)pkt; gnrc_ipv6_nc_t *nc = gnrc_ipv6_nc_get(iface, dst); if ((nc == NULL) || !gnrc_ipv6_nc_is_reachable(nc)) { return KERNEL_PID_UNDEF; } found_iface = nc->iface; *l2addr_len = nc->l2_addr_len; memcpy(l2addr, nc->l2_addr, nc->l2_addr_len); #elif !defined(MODULE_GNRC_SIXLOWPAN_ND) found_iface = KERNEL_PID_UNDEF; (void)l2addr; (void)l2addr_len; (void)iface; (void)dst; (void)pkt; *l2addr_len = 0; #endif return found_iface; }
static void test_ipv6_nc_still_reachable__success(void) { ipv6_addr_t addr = DEFAULT_TEST_IPV6_ADDR; gnrc_ipv6_nc_t *entry = NULL; /* adds DEFAULT_TEST_IPV6_ADDR to DEFAULT_TEST_NETIF and sets flags to * (GNRC_IPV6_NC_STATE_REACHABLE << GNRC_IPV6_NC_STATE_POS) */ test_ipv6_nc_is_reachable__reachable(); TEST_ASSERT_NOT_NULL((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); entry->flags = (GNRC_IPV6_NC_STATE_STALE << GNRC_IPV6_NC_STATE_POS); TEST_ASSERT_NOT_NULL(gnrc_ipv6_nc_still_reachable(&addr)); TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); }
static void test_ipv6_nc_is_reachable__unmanaged(void) { ipv6_addr_t addr = DEFAULT_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((entry = gnrc_ipv6_nc_get(DEFAULT_TEST_NETIF, &addr))); entry->flags = (GNRC_IPV6_NC_STATE_UNMANAGED << GNRC_IPV6_NC_STATE_POS); TEST_ASSERT(gnrc_ipv6_nc_is_reachable(entry)); }
static void test_ipv6_nc_is_reachable__incomplete(void) { ipv6_addr_t addr = DEFAULT_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((entry = gnrc_ipv6_nc_get(KERNEL_PID_UNDEF, &addr))); entry->flags = (GNRC_IPV6_NC_STATE_INCOMPLETE << GNRC_IPV6_NC_STATE_POS); TEST_ASSERT(!gnrc_ipv6_nc_is_reachable(entry)); }
kernel_pid_t gnrc_sixlowpan_nd_next_hop_l2addr(uint8_t *l2addr, uint8_t *l2addr_len, kernel_pid_t iface, ipv6_addr_t *dst) { ipv6_addr_t *next_hop = NULL; gnrc_ipv6_nc_t *nc_entry = NULL; #ifdef MODULE_GNRC_IPV6_EXT_RH ipv6_hdr_t *hdr; gnrc_pktsnip_t *ipv6; LL_SEARCH_SCALAR(pkt, ipv6, type, GNRC_NETTYPE_IPV6); assert(ipv6); hdr = ipv6->data; next_hop = ipv6_ext_rh_next_hop(hdr); #endif #ifdef MODULE_FIB ipv6_addr_t next_hop_actual; /* FIB copies address into this variable */ /* don't look-up link local addresses in FIB */ if ((next_hop == NULL) && !ipv6_addr_is_link_local(dst)) { size_t next_hop_size = sizeof(ipv6_addr_t); uint32_t next_hop_flags = 0; if ((next_hop == NULL) && (fib_get_next_hop(&gnrc_ipv6_fib_table, &iface, next_hop_actual.u8, &next_hop_size, &next_hop_flags, (uint8_t *)dst, sizeof(ipv6_addr_t), 0) >= 0) && (next_hop_size == sizeof(ipv6_addr_t))) { next_hop = &next_hop_actual; } } #endif #ifdef MODULE_GNRC_SIXLOWPAN_ND_ROUTER /* next hop determination: https://tools.ietf.org/html/rfc6775#section-6.5.4 */ nc_entry = gnrc_ipv6_nc_get(iface, dst); /* if NCE found */ if (nc_entry != NULL) { gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(nc_entry->iface); /* and interface is not 6LoWPAN */ if (!(ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) || /* or entry is registered */ (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_REGISTERED)) { next_hop = dst; } } #endif /* next hop determination according to: https://tools.ietf.org/html/rfc6775#section-5.6 */ if ((next_hop == NULL) && ipv6_addr_is_link_local(dst)) { /* prefix is "on-link" */ /* multicast is not handled here anyway so we don't need to check that */ next_hop = dst; } else if (next_hop == NULL) { /* prefix is off-link */ next_hop = gnrc_ndp_internal_default_router(); } /* address resolution of next_hop: https://tools.ietf.org/html/rfc6775#section-5.7 */ if ((nc_entry == NULL) || (next_hop != dst)) { /* get if not gotten from previous check */ nc_entry = gnrc_ipv6_nc_get(iface, next_hop); } /* If a NCE for this destination exist, we can use even for link-local * addresses. This should be only the case for 6LBRs. */ if ((ipv6_addr_is_link_local(next_hop)) && (nc_entry == NULL)) { /* in case of a border router there is no sensible way for address resolution * if the interface is not given */ #ifdef MODULE_GNRC_SIXLOWPAN_ND_BORDER_ROUTER /* if no interface is specified it is impossible to resolve the * link-layer address for a link-local address on a 6LBR */ if (iface == KERNEL_PID_UNDEF) { return KERNEL_PID_UNDEF; } #endif kernel_pid_t ifs[GNRC_NETIF_NUMOF]; size_t ifnum = gnrc_netif_get(ifs); /* we don't need address resolution, the EUI-64 is in next_hop's IID */ *l2addr_len = sizeof(eui64_t); memcpy(l2addr, &next_hop->u8[8], sizeof(eui64_t)); _revert_iid(l2addr); if (iface == KERNEL_PID_UNDEF) { for (unsigned i = 0; i < ifnum; i++) { gnrc_ipv6_netif_t *ipv6_if = gnrc_ipv6_netif_get(ifs[i]); if ((ipv6_if != NULL) && (ipv6_if->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN)) { /* always take the first 6LoWPAN interface we can find */ return ifs[i]; } } } return iface; } if ((nc_entry == NULL) || (!gnrc_ipv6_nc_is_reachable(nc_entry)) || (gnrc_ipv6_nc_get_type(nc_entry) == GNRC_IPV6_NC_TYPE_TENTATIVE)) { return KERNEL_PID_UNDEF; } else { if (nc_entry->l2_addr_len > 0) { memcpy(l2addr, nc_entry->l2_addr, nc_entry->l2_addr_len); } *l2addr_len = nc_entry->l2_addr_len; } return nc_entry->iface; }