static void test_ipv6_netif_find_best_src_addr__success(void) { ng_ipv6_addr_t ll_addr1 = NG_IPV6_ADDR_UNSPECIFIED; ng_ipv6_addr_t ll_addr2 = NG_IPV6_ADDR_UNSPECIFIED; ng_ipv6_addr_t mc_addr = NG_IPV6_ADDR_ALL_NODES_LINK_LOCAL; ng_ipv6_addr_t *out = NULL; ll_addr1.u8[15] = 1; ng_ipv6_addr_set_link_local_prefix(&ll_addr1); ll_addr2.u8[15] = 2; ng_ipv6_addr_set_link_local_prefix(&ll_addr2); TEST_ASSERT_EQUAL_INT(126, ng_ipv6_addr_match_prefix(&ll_addr2, &ll_addr1)); test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ TEST_ASSERT_EQUAL_INT(0, ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &mc_addr, DEFAULT_TEST_PREFIX_LEN, false)); TEST_ASSERT_EQUAL_INT(0, ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &ll_addr1, DEFAULT_TEST_PREFIX_LEN, false)); 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, ng_ipv6_addr_equal(out, &ll_addr1)); }
static void test_ipv6_netif_find_best_src_addr__multicast_input(void) { ipv6_addr_t mc_addr = IPV6_ADDR_ALL_ROUTERS_LINK_LOCAL; ipv6_addr_t *out = NULL; /* Adds DEFAULT_TEST_NETIF as interface and to it fe80::1, fe80::2 and ff02::1 */ test_ipv6_netif_find_best_src_addr__success(); TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &mc_addr))); TEST_ASSERT_EQUAL_INT(false, ipv6_addr_equal(&mc_addr, out)); TEST_ASSERT_EQUAL_INT(false, ipv6_addr_is_unspecified(out)); }
static void test_ipv6_netif_find_best_src_addr__other_subnet(void) { ipv6_addr_t addr1 = DEFAULT_TEST_IPV6_ADDR; ipv6_addr_t addr2 = OTHER_TEST_IPV6_ADDR; ipv6_addr_t *out = NULL; test_ipv6_netif_add__success(); /* adds DEFAULT_TEST_NETIF as interface */ TEST_ASSERT_NOT_NULL(ng_ipv6_netif_add_addr(DEFAULT_TEST_NETIF, &addr1, DEFAULT_TEST_PREFIX_LEN, 0)); TEST_ASSERT_NOT_NULL((out = ng_ipv6_netif_find_best_src_addr(DEFAULT_TEST_NETIF, &addr2))); TEST_ASSERT(out != &addr1); TEST_ASSERT_EQUAL_INT(true, ipv6_addr_equal(out, &addr1)); }
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)); }
static void _send_nbr_sol(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst) { ng_pktsnip_t *hdr, *pkt = NULL; ng_ipv6_addr_t *src = NULL; size_t src_len = 0; DEBUG("ndp: send neighbor solicitation (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str))); /* check if there is a fitting source address to target */ if ((src = ng_ipv6_netif_find_best_src_addr(iface, tgt)) != NULL) { uint8_t l2src[8]; uint16_t l2src_len; src_len = sizeof(ng_ipv6_addr_t); l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add source address link-layer address option */ pkt = ng_ndp_opt_sl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp: error allocating Source Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } hdr = ng_ndp_nbr_sol_build(tgt, pkt); if (hdr == NULL) { DEBUG("ndp: error allocating Neighbor solicitation.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst, sizeof(ng_ipv6_addr_t)); if (hdr == NULL) { DEBUG("ndp: error allocating IPv6 header.\n"); ng_pktbuf_release(pkt); return; } ((ng_ipv6_hdr_t *)hdr->data)->hl = 255; pkt = hdr; /* add netif header for send interface specification */ hdr = ng_netif_hdr_build(NULL, 0, NULL, 0); if (hdr == NULL) { DEBUG("ndp: error allocating netif header.\n"); return; } ((ng_netif_hdr_t *)hdr->data)->if_pid = iface; LL_PREPEND(pkt, hdr); ng_netapi_send(ng_ipv6_pid, pkt); }
static int _fill_ipv6_hdr(kernel_pid_t iface, ng_pktsnip_t *ipv6, ng_pktsnip_t *payload) { int res; ng_ipv6_hdr_t *hdr = ipv6->data; hdr->len = byteorder_htons(ng_pkt_len(payload)); DEBUG("ipv6: set payload length to %zu (network byteorder %04" PRIx16 ")\n", ng_pkt_len(payload), hdr->len.u16); /* check if e.g. extension header was not already marked */ if (hdr->nh == NG_PROTNUM_RESERVED) { hdr->nh = ng_nettype_to_protnum(payload->type); /* if still reserved: mark no next header */ if (hdr->nh == NG_PROTNUM_RESERVED) { hdr->nh = NG_PROTNUM_IPV6_NONXT; } } DEBUG("ipv6: set next header to %" PRIu8 "\n", hdr->nh); if (hdr->hl == 0) { hdr->hl = ng_ipv6_netif_get(iface)->cur_hl; } if (ng_ipv6_addr_is_unspecified(&hdr->src)) { ng_ipv6_addr_t *src = ng_ipv6_netif_find_best_src_addr(iface, &hdr->dst); if (src != NULL) { DEBUG("ipv6: set packet source to %s\n", ng_ipv6_addr_to_str(addr_str, src, sizeof(addr_str))); memcpy(&hdr->src, src, sizeof(ng_ipv6_addr_t)); } /* Otherwise leave unspecified */ } DEBUG("ipv6: calculate checksum for upper header.\n"); #if NG_NETIF_NUMOF > 1 if (payload->users > 1) { ng_pktsnip_t *ptr = ipv6; /* We deal with multiple interfaces here (multicast) => possible * different source addresses => duplication of payload needed */ while (ptr != payload->next) { ng_pktsnip_t *old = ptr->next; /* duplicate everything including payload */ ptr->next = ng_pktbuf_start_write(ptr->next); if (ptr->next == NULL) { DEBUG("ipv6: unable to get write access to payload, drop it\n"); return -ENOBUFS; } ptr = old; } } #endif /* NG_NETIF_NUMOF */ if ((res = ng_netreg_calc_csum(payload, ipv6)) < 0) { if (res != -ENOENT) { /* if there is no checksum we are okay */ DEBUG("ipv6: checksum calculation failed.\n"); return res; } } return 0; }