static void test_ipv6_addr_set_all_nodes_multicast_unusual(void) { ng_ipv6_addr_t a; ng_ipv6_addr_mcast_scp_t scope = NG_IPV6_ADDR_MCAST_SCP_REALM_LOCAL; ng_ipv6_addr_set_all_nodes_multicast(&a, scope); TEST_ASSERT_EQUAL_INT(0xff030000, byteorder_ntohl(a.u32[0])); TEST_ASSERT_EQUAL_INT(0, a.u32[1].u32); TEST_ASSERT_EQUAL_INT(1, byteorder_ntohll(a.u64[1])); }
static void test_ipv6_addr_set_all_nodes_multicast_link_local(void) { ng_ipv6_addr_t a = NG_IPV6_ADDR_UNSPECIFIED; ng_ipv6_addr_t b = NG_IPV6_ADDR_ALL_NODES_LINK_LOCAL; ng_ipv6_addr_mcast_scp_t scope = NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL; TEST_ASSERT_EQUAL_INT(0xff020000, byteorder_ntohl(b.u32[0])); /* Don't trust the macro ;) */ TEST_ASSERT_EQUAL_INT(0, b.u32[1].u32); TEST_ASSERT_EQUAL_INT(1, byteorder_ntohll(b.u64[1])); ng_ipv6_addr_set_all_nodes_multicast(&a, scope); TEST_ASSERT_EQUAL_INT(true, ng_ipv6_addr_equal(&a, &b)); }
static void _send_nbr_adv(kernel_pid_t iface, ng_ipv6_addr_t *tgt, ng_ipv6_addr_t *dst, bool supply_tl2a) { ng_pktsnip_t *hdr, *pkt = NULL; uint8_t adv_flags = 0; DEBUG("ndp: send neighbor advertisement (iface: %" PRIkernel_pid ", tgt: %s, ", iface, ng_ipv6_addr_to_str(addr_str, tgt, sizeof(addr_str))); DEBUG("dst: %s, supply_tl2a: %d)\n", ng_ipv6_addr_to_str(addr_str, dst, sizeof(addr_str)), supply_tl2a); if (ng_ipv6_netif_get(iface)->flags & NG_IPV6_NETIF_FLAGS_ROUTER) { adv_flags |= NG_NDP_NBR_ADV_FLAGS_R; } if (ng_ipv6_addr_is_unspecified(dst)) { ng_ipv6_addr_set_all_nodes_multicast(dst, NG_IPV6_ADDR_MCAST_SCP_LINK_LOCAL); } else { adv_flags |= NG_NDP_NBR_ADV_FLAGS_S; } if (supply_tl2a) { uint8_t l2src[8]; uint16_t l2src_len; /* we previously checked if we are the target, so we can take our L2src */ l2src_len = _get_l2src(l2src, sizeof(l2src), iface); if (l2src_len > 0) { /* add target address link-layer address option */ pkt = ng_ndp_opt_tl2a_build(l2src, l2src_len, NULL); if (pkt == NULL) { DEBUG("ndp: error allocating Target Link-layer address option.\n"); ng_pktbuf_release(pkt); return; } } } /* TODO: also check if the node provides proxy servies for tgt */ if ((pkt != NULL) && !ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* TL2A is not supplied and tgt is not anycast */ adv_flags |= NG_NDP_NBR_ADV_FLAGS_O; } hdr = ng_ndp_nbr_adv_build(adv_flags, tgt, pkt); if (hdr == NULL) { DEBUG("ndp: error allocating Neighbor advertisement.\n"); ng_pktbuf_release(pkt); return; } pkt = hdr; hdr = ng_ipv6_hdr_build(pkt, NULL, 0, (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); if (ng_ipv6_netif_addr_is_non_unicast(tgt)) { /* avoid collision for anycast addresses * (see https://tools.ietf.org/html/rfc4861#section-7.2.7) */ timex_t delay = { _rand(0, NG_NDP_MAX_AC_TGT_DELAY), 0 }; ng_ipv6_nc_t *nc_entry = ng_ipv6_nc_get(iface, tgt); DEBUG("ndp: delay neighbor advertisement for %" PRIu32 " sec.", delay.seconds); /* nc_entry must be set so no need to check it */ _send_delayed(&nc_entry->nbr_adv_timer, delay, pkt); } else { ng_netapi_send(ng_ipv6_pid, pkt); } }