Esempio n. 1
0
static bool test_last_function_unsupported(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	struct frag_hdr *fragment_hdr;
	struct ipv6_opt_hdr *esp_hdr;
	struct ipv6_opt_hdr *routing_hdr;
	unsigned char *payload;

	ip6_header = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN + ROUTING_HDR_LEN + 4, NEXTHDR_FRAGMENT);
	if (!ip6_header)
		return false;
	fragment_hdr = add_frag_hdr(ip6_header, sizeof(struct ipv6hdr), NEXTHDR_ESP);
	esp_hdr = add_opt_hdr(fragment_hdr, FRAG_HDR_LEN, FRAG_HDR_LEN);
	routing_hdr = add_routing_hdr(esp_hdr, OPT_HDR_LEN, NEXTHDR_UDP);
	payload = add_payload(routing_hdr, ROUTING_HDR_LEN);

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_int(HDR_ITERATOR_UNSUPPORTED, hdr_iterator_last(&iterator), "Result");
	success &= assert_equals_ptr(esp_hdr, iterator.data, "Last function, data");
	success &= assert_equals_u8(NEXTHDR_ESP, iterator.hdr_type, "Last function, type");

	/* End */
	kfree(ip6_header);
	return success;
}
Esempio n. 2
0
static bool test_last_unsupported(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *hdr6;
	struct frag_hdr *hdr_frag;
	struct ipv6_opt_hdr *hdr_esp;
	struct ipv6_opt_hdr *hdr_route;
	unsigned char *payload;

	hdr6 = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN + ROUTE_HDR_LEN + 4,
			NEXTHDR_FRAGMENT);
	if (!hdr6)
		return false;
	hdr_frag = add_frag_hdr(hdr6, HDR6_LEN, NEXTHDR_ESP);
	hdr_esp = add_opt_hdr(hdr_frag, FRAG_HDR_LEN, FRAG_HDR_LEN);
	hdr_route = add_route_hdr(hdr_esp, OPT_HDR_LEN, NEXTHDR_UDP);
	payload = add_payload(hdr_route, ROUTE_HDR_LEN);

	/* Test */
	hdr_iterator_init(&iterator, hdr6);
	hdr_iterator_last(&iterator);
	success &= ASSERT_PTR(hdr_esp, iterator.data, "Last:data");
	success &= ASSERT_UINT(NEXTHDR_ESP, iterator.hdr_type, "Last:type");

	/* End */
	kfree(hdr6);
	return success;
}
Esempio n. 3
0
static bool test_next_subheaders(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *hdr6;
	struct frag_hdr *hdr_frag;
	struct ipv6_opt_hdr *hdr_hop;
	struct ipv6_opt_hdr *hdr_route;
	unsigned char *payload;

	hdr6 = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN + ROUTE_HDR_LEN + 4,
			NEXTHDR_FRAGMENT);
	if (!hdr6)
		return false;
	hdr_frag = add_frag_hdr(hdr6, HDR6_LEN, NEXTHDR_HOP);
	hdr_hop = add_opt_hdr(hdr_frag, FRAG_HDR_LEN, NEXTHDR_ROUTING);
	hdr_route = add_route_hdr(hdr_hop, OPT_HDR_LEN, NEXTHDR_UDP);
	payload = add_payload(hdr_route, ROUTE_HDR_LEN);

	/* Test */
	hdr_iterator_init(&iterator, hdr6);
	success &= ASSERT_PTR(hdr_frag, iterator.data, "Frag:data");
	success &= ASSERT_UINT(NEXTHDR_FRAGMENT, iterator.hdr_type,
			"Frag:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(EAGAIN, hdr_iterator_next(&iterator), "Next 1");
	success &= ASSERT_PTR(hdr_hop, iterator.data, "Hop:data");
	success &= ASSERT_UINT(NEXTHDR_HOP, iterator.hdr_type, "Hop:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(EAGAIN, hdr_iterator_next(&iterator), "Next 2");
	success &= ASSERT_PTR(hdr_route, iterator.data, "Routing:data");
	success &= ASSERT_UINT(NEXTHDR_ROUTING, iterator.hdr_type,
			"Routing:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(EAGAIN, hdr_iterator_next(&iterator), "Next 3");
	success &= ASSERT_PTR(payload, iterator.data, "Payload1:data");
	success &= ASSERT_UINT(NEXTHDR_UDP, iterator.hdr_type, "Payload1:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(0, hdr_iterator_next(&iterator), "Next 4");
	success &= ASSERT_PTR(payload, iterator.data, "Payload2:data");
	success &= ASSERT_UINT(NEXTHDR_UDP, iterator.hdr_type, "Payload2:type");
	/* Fall through. */

end:
	kfree(hdr6);
	return success;
}
Esempio n. 4
0
void hdr_iterator_init_truncated(struct hdr_iterator *iterator, struct ipv6hdr *main_hdr,
		unsigned int limit)
{
	void *limit_ptr = main_hdr + limit;

	hdr_iterator_init(iterator, main_hdr);

	if (limit_ptr < iterator->limit)
		iterator->limit = limit_ptr;
}
Esempio n. 5
0
static bool test_next_function_subheaders(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	struct frag_hdr *fragment_hdr;
	struct ipv6_opt_hdr *hop_by_hop_hdr;
	struct ipv6_opt_hdr *routing_hdr;
	unsigned char *payload;

	ip6_header = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN + ROUTING_HDR_LEN + 4, NEXTHDR_FRAGMENT);
	if (!ip6_header)
		return false;
	fragment_hdr = add_frag_hdr(ip6_header, sizeof(struct ipv6hdr), NEXTHDR_HOP);
	hop_by_hop_hdr = add_opt_hdr(fragment_hdr, FRAG_HDR_LEN, NEXTHDR_ROUTING);
	routing_hdr = add_routing_hdr(hop_by_hop_hdr, OPT_HDR_LEN, NEXTHDR_UDP);
	payload = add_payload(routing_hdr, ROUTING_HDR_LEN);

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_ptr(fragment_hdr, iterator.data, "Frag hdr, data");
	success &= assert_equals_u8(NEXTHDR_FRAGMENT, iterator.hdr_type, "Frag hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_SUCCESS, hdr_iterator_next(&iterator), "Next 1");
	success &= assert_equals_ptr(hop_by_hop_hdr, iterator.data, "Hop-by-hop hdr, data");
	success &= assert_equals_u8(NEXTHDR_HOP, iterator.hdr_type, "Hop-by-hop hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_SUCCESS, hdr_iterator_next(&iterator), "Next 2");
	success &= assert_equals_ptr(routing_hdr, iterator.data, "Routing hdr, data");
	success &= assert_equals_u8(NEXTHDR_ROUTING, iterator.hdr_type, "Routing hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_SUCCESS, hdr_iterator_next(&iterator), "Next 3");
	success &= assert_equals_ptr(payload, iterator.data, "Payload 1, data");
	success &= assert_equals_u8(NEXTHDR_UDP, iterator.hdr_type, "Payload 1, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_END, hdr_iterator_next(&iterator), "Next 4");
	success &= assert_equals_ptr(payload, iterator.data, "Payload 2, data");
	success &= assert_equals_u8(NEXTHDR_UDP, iterator.hdr_type, "Payload 2, type");
	/* Fall through. */

end:
	kfree(ip6_header);
	return success;
}
Esempio n. 6
0
static bool test_next_unsupported(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *hdr6;
	struct frag_hdr *hdr_frag;
	struct ipv6_opt_hdr *hdr_esp;
	struct ipv6_opt_hdr *hdr_route;
	unsigned char *payload;

	hdr6 = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN + ROUTE_HDR_LEN + 4,
			NEXTHDR_FRAGMENT);
	if (!hdr6)
		return false;
	hdr_frag = add_frag_hdr(hdr6, HDR6_LEN, NEXTHDR_ESP);
	hdr_esp = add_opt_hdr(hdr_frag, FRAG_HDR_LEN, FRAG_HDR_LEN);
	hdr_route = add_route_hdr(hdr_esp, OPT_HDR_LEN, NEXTHDR_UDP);
	payload = add_payload(hdr_route, ROUTE_HDR_LEN);

	/* Test */
	hdr_iterator_init(&iterator, hdr6);
	success &= ASSERT_PTR(hdr_frag, iterator.data, "Frag:pointer");
	success &= ASSERT_UINT(NEXTHDR_FRAGMENT, iterator.hdr_type,
			"Frag:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(EAGAIN, hdr_iterator_next(&iterator), "Next 1");
	success &= ASSERT_PTR(hdr_esp, iterator.data, "ESP1:pointer");
	success &= ASSERT_UINT(NEXTHDR_ESP, iterator.hdr_type, "ESP1:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(0, hdr_iterator_next(&iterator), "Next 2");
	success &= ASSERT_PTR(hdr_esp, iterator.data, "ESP2:pointer");
	success &= ASSERT_UINT(NEXTHDR_ESP, iterator.hdr_type, "ESP2:type");
	/* Fall through. */

end:
	kfree(hdr6);
	return success;
}
Esempio n. 7
0
static bool test_next_function_unsupported(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	struct frag_hdr *fragment_hdr;
	struct ipv6_opt_hdr *esp_hdr;
	struct ipv6_opt_hdr *routing_hdr;
	unsigned char *payload;

	ip6_header = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN + ROUTING_HDR_LEN + 4, NEXTHDR_FRAGMENT);
	if (!ip6_header)
		return false;
	fragment_hdr = add_frag_hdr(ip6_header, sizeof(struct ipv6hdr), NEXTHDR_ESP);
	esp_hdr = add_opt_hdr(fragment_hdr, FRAG_HDR_LEN, FRAG_HDR_LEN);
	routing_hdr = add_routing_hdr(esp_hdr, OPT_HDR_LEN, NEXTHDR_UDP);
	payload = add_payload(routing_hdr, ROUTING_HDR_LEN);

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_ptr(fragment_hdr, iterator.data, "Frag hdr, pointer");
	success &= assert_equals_u8(NEXTHDR_FRAGMENT, iterator.hdr_type, "Frag hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_SUCCESS, hdr_iterator_next(&iterator), "Next 1");
	success &= assert_equals_ptr(esp_hdr, iterator.data, "ESP hdr, pointer");
	success &= assert_equals_u8(NEXTHDR_ESP, iterator.hdr_type, "ESP hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_UNSUPPORTED, hdr_iterator_next(&iterator), "Next 2");
	success &= assert_equals_ptr(esp_hdr, iterator.data, "Still ESP header, pointer");
	success &= assert_equals_u8(NEXTHDR_ESP, iterator.hdr_type, "Still ESP header, type");
	/* Fall through. */

end:
	kfree(ip6_header);
	return success;
}
Esempio n. 8
0
static bool test_next_function_no_subheaders(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	unsigned char *payload;

	ip6_header = kmalloc_packet(4, NEXTHDR_UDP);
	if (!ip6_header)
		return false;
	payload = add_payload(ip6_header, sizeof(struct ipv6hdr));

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_ptr(payload, iterator.data, "Payload 1, data");
	success &= assert_equals_u8(NEXTHDR_UDP, iterator.hdr_type, "Payload 1, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_END, hdr_iterator_next(&iterator), "Result 1");
	success &= assert_equals_ptr(payload, iterator.data, "Payload 2, data");
	success &= assert_equals_u8(NEXTHDR_UDP, iterator.hdr_type, "Payload 2, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_END, hdr_iterator_next(&iterator), "Result 2");
	success &= assert_equals_int(HDR_ITERATOR_END, hdr_iterator_next(&iterator), "Result 3");
	success &= assert_equals_int(HDR_ITERATOR_END, hdr_iterator_next(&iterator), "Result 4");
	success &= assert_equals_ptr(payload, iterator.data, "Payload 3, data");
	success &= assert_equals_u8(NEXTHDR_UDP, iterator.hdr_type, "Payload 3, type");
	/* Fall through. */

end:
	kfree(ip6_header);
	return success;
}
Esempio n. 9
0
static bool test_next_no_subheaders(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *hdr6;
	unsigned char *payload;

	hdr6 = kmalloc_packet(4, NEXTHDR_UDP);
	if (!hdr6)
		return false;
	payload = add_payload(hdr6, HDR6_LEN);

	/* Test */
	hdr_iterator_init(&iterator, hdr6);
	success &= ASSERT_PTR(payload, iterator.data, "Payload1:data");
	success &= ASSERT_UINT(NEXTHDR_UDP, iterator.hdr_type, "Payload1:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(0, hdr_iterator_next(&iterator), "Result1");
	success &= ASSERT_PTR(payload, iterator.data, "Payload2:data");
	success &= ASSERT_UINT(NEXTHDR_UDP, iterator.hdr_type, "Payload2:type");
	if (!success)
		goto end;

	success &= ASSERT_INT(0, hdr_iterator_next(&iterator), "Result2");
	success &= ASSERT_INT(0, hdr_iterator_next(&iterator), "Result3");
	success &= ASSERT_INT(0, hdr_iterator_next(&iterator), "Result4");
	success &= ASSERT_PTR(payload, iterator.data, "Payload3:data");
	success &= ASSERT_UINT(NEXTHDR_UDP, iterator.hdr_type, "Payload3:type");
	/* Fall through. */

end:
	kfree(hdr6);
	return success;
}
Esempio n. 10
0
static bool test_last_function_overflow(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	struct frag_hdr *fragment_hdr;
	struct ipv6_opt_hdr *hop_by_hop_hdr;

	ip6_header = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN, NEXTHDR_FRAGMENT);
	if (!ip6_header)
		return false;
	fragment_hdr = add_frag_hdr(ip6_header, sizeof(struct ipv6hdr), NEXTHDR_HOP);
	hop_by_hop_hdr = add_opt_hdr(fragment_hdr, NEXTHDR_FRAGMENT, NEXTHDR_ROUTING);

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_int(HDR_ITERATOR_OVERFLOW, hdr_iterator_last(&iterator), "Result");

	/* End */
	kfree(ip6_header);
	return success;
}
Esempio n. 11
0
static bool test_last_function_no_subheaders(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	unsigned char *payload;

	ip6_header = kmalloc_packet(4, NEXTHDR_UDP);
	if (!ip6_header)
		return false;
	payload = add_payload(ip6_header, sizeof(struct ipv6hdr));

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_int(HDR_ITERATOR_END, hdr_iterator_last(&iterator), "Result");
	success &= assert_equals_ptr(payload, iterator.data, "Last function, data");
	success &= assert_equals_u8(NEXTHDR_UDP, iterator.hdr_type, "Last function, type");

	/* End */
	kfree(ip6_header);
	return success;
}
Esempio n. 12
0
static bool test_next_function_overflow(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *ip6_header;
	struct frag_hdr *fragment_hdr;
	struct ipv6_opt_hdr *hop_by_hop_hdr;

	ip6_header = kmalloc_packet(FRAG_HDR_LEN + OPT_HDR_LEN, NEXTHDR_FRAGMENT);
	if (!ip6_header)
		return false;
	fragment_hdr = add_frag_hdr(ip6_header, sizeof(struct ipv6hdr), NEXTHDR_HOP);
	hop_by_hop_hdr = add_opt_hdr(fragment_hdr, FRAG_HDR_LEN, NEXTHDR_ROUTING);

	/* Test */
	hdr_iterator_init(&iterator, ip6_header);
	success &= assert_equals_ptr(fragment_hdr, iterator.data, "Frag hdr, data");
	success &= assert_equals_u8(NEXTHDR_FRAGMENT, iterator.hdr_type, "Frag hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_SUCCESS, hdr_iterator_next(&iterator), "Next 1");
	success &= assert_equals_ptr(hop_by_hop_hdr, iterator.data, "Hop-by-hop hdr, data");
	success &= assert_equals_u8(NEXTHDR_HOP, iterator.hdr_type, "Hop-by-hop hdr, type");
	if (!success)
		goto end;

	success &= assert_equals_int(HDR_ITERATOR_OVERFLOW, hdr_iterator_next(&iterator), "Next 2");
	/* Fall through. */

end:
	kfree(ip6_header);
	return success;
}
Esempio n. 13
0
static bool test_last_no_subheaders(void)
{
	bool success = true;
	struct hdr_iterator iterator;

	/* Init */
	struct ipv6hdr *hdr6;
	unsigned char *payload;

	hdr6 = kmalloc_packet(4, NEXTHDR_UDP);
	if (!hdr6)
		return false;
	payload = add_payload(hdr6, HDR6_LEN);

	/* Test */
	hdr_iterator_init(&iterator, hdr6);
	hdr_iterator_last(&iterator);
	success &= ASSERT_PTR(payload, iterator.data, "Last:data");
	success &= ASSERT_UINT(NEXTHDR_UDP, iterator.hdr_type, "Last:type");

	/* End */
	kfree(hdr6);
	return success;
}
Esempio n. 14
0
bool determine_in_tuple(struct sk_buff *skb, struct tuple *tuple)
{
	struct iphdr *hdr4;
	struct ipv6hdr *hdr6;
	struct icmphdr *icmp4;
	struct icmp6hdr *icmp6;
	struct hdr_iterator iterator;

	log_debug("Step 1: Determining the Incoming Tuple");

	switch (be16_to_cpu(skb->protocol)) {
	case ETH_P_IP:
		hdr4 = ip_hdr(skb);
		switch (hdr4->protocol) {
		case IPPROTO_UDP:
			if (!ipv4_udp(hdr4, ipv4_extract_l4_hdr(hdr4), tuple))
				return false;
			break;
		case IPPROTO_TCP:
			if (!ipv4_tcp(hdr4, ipv4_extract_l4_hdr(hdr4), tuple))
				return false;
			break;
		case IPPROTO_ICMP:
			icmp4 = ipv4_extract_l4_hdr(hdr4);
			if (is_icmp4_info(icmp4->type)) {
				if (!ipv4_icmp_info(hdr4, icmp4, tuple))
					return false;
			} else {
				if (!ipv4_icmp_err(hdr4, icmp4, tuple))
					return false;
			}
			break;
		default:
			log_info("Unsupported transport protocol for IPv4: %d.", hdr4->protocol);
			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
			return false;
		}
		break;

	case ETH_P_IPV6:
		hdr6 = ipv6_hdr(skb);
		hdr_iterator_init(&iterator, hdr6);
		hdr_iterator_last(&iterator);
		switch (iterator.hdr_type) {
		case IPPROTO_UDP:
			if (!ipv6_udp(hdr6, iterator.data, tuple))
				return false;
			break;
		case IPPROTO_TCP:
			if (!ipv6_tcp(hdr6, iterator.data, tuple))
				return false;
			break;
		case IPPROTO_ICMPV6:
			icmp6 = iterator.data;
			if (is_icmp6_info(icmp6->icmp6_type)) {
				if (!ipv6_icmp_info(hdr6, icmp6, tuple))
					return false;
			} else {
				if (!ipv6_icmp_err(hdr6, icmp6, tuple))
					return false;
			}
			break;
		default:
			log_info("Unsupported transport protocol for IPv6: %d.", iterator.hdr_type);
			icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
			return false;
		}
		break;

	default:
		log_info("Packet's protocol (%d) is not IPv4 or IPv6.", be16_to_cpu(skb->protocol));
		return false;
	}

	log_tuple(tuple);
	log_debug("Done step 1.");
	return true;
}
Esempio n. 15
0
static bool test_subheaders(void)
{
	// Init.
	const __u16 HOP_BY_HOP_HDR_LEN = 32;
	const __u16 ROUTING_HDR_LEN = 40;

	struct ipv6hdr *ip6_header;
	struct frag_hdr *fragment_hdr;
	struct ipv6_opt_hdr *hop_by_hop_hdr;
	struct ipv6_opt_hdr *routing_hdr;
	unsigned char *payload;

	ip6_header = kmalloc(sizeof(struct ipv6hdr)
				+ sizeof(struct frag_hdr)
				+ HOP_BY_HOP_HDR_LEN
				+ ROUTING_HDR_LEN
				+ 4, // (payload.)
				GFP_ATOMIC);
	if (!ip6_header) {
		log_warning("Unable to allocate a test header.");
		return false;
	}
	ip6_header->nexthdr = NEXTHDR_FRAGMENT;

	fragment_hdr = (struct frag_hdr *) (ip6_header + 1);
	fragment_hdr->nexthdr = NEXTHDR_HOP;

	hop_by_hop_hdr = (struct ipv6_opt_hdr *) (fragment_hdr + 1);
	hop_by_hop_hdr->nexthdr = NEXTHDR_ROUTING;
	hop_by_hop_hdr->hdrlen = (HOP_BY_HOP_HDR_LEN / 8) - 1;

	routing_hdr = ((void *) hop_by_hop_hdr) + HOP_BY_HOP_HDR_LEN;
	routing_hdr->nexthdr = NEXTHDR_UDP;
	routing_hdr->hdrlen = (ROUTING_HDR_LEN / 8) - 1;

	payload = ((void *) routing_hdr) + ROUTING_HDR_LEN;

	// Test next function.
	{
		struct hdr_iterator next_iterator = HDR_ITERATOR_INIT(ip6_header);
		ASSERT_EQUALS_PTR(ip6_header, next_iterator.data, "First (main) header, data");
		ASSERT_EQUALS(-1, next_iterator.hdr_type, "First (main) header, hdr type");

		hdr_iterator_next(&next_iterator);
		ASSERT_EQUALS_PTR(fragment_hdr, next_iterator.data, "Second (frag) header, data");
		ASSERT_EQUALS(NEXTHDR_FRAGMENT, next_iterator.hdr_type, "Second (frag) header, hdr type");

		hdr_iterator_next(&next_iterator);
		ASSERT_EQUALS_PTR(hop_by_hop_hdr, next_iterator.data, "Third (hop-by-hop) header, data");
		ASSERT_EQUALS(NEXTHDR_HOP, next_iterator.hdr_type, "Third (hop-by-hop) header, hdr type");

		hdr_iterator_next(&next_iterator);
		ASSERT_EQUALS_PTR(routing_hdr, next_iterator.data, "Fourth (Routing) header, data");
		ASSERT_EQUALS(NEXTHDR_ROUTING, next_iterator.hdr_type, "Fourth (Routing) header, hdr type");

		hdr_iterator_next(&next_iterator);
		ASSERT_EQUALS_PTR(payload, next_iterator.data, "Payload 1st, data");
		ASSERT_EQUALS(NEXTHDR_UDP, next_iterator.hdr_type, "Payload 1st, hdr type");

		hdr_iterator_next(&next_iterator);
		ASSERT_EQUALS_PTR(payload, next_iterator.data, "Payload 2nd, data");
		ASSERT_EQUALS(NEXTHDR_UDP, next_iterator.hdr_type, "Payload 2nd, hdr type");
	}

	// Test last function.
	{
		struct hdr_iterator last_iterator = HDR_ITERATOR_INIT(ip6_header);
		hdr_iterator_init(&last_iterator, ip6_header);
		hdr_iterator_last(&last_iterator);
		ASSERT_EQUALS_PTR(payload, last_iterator.data, "Last function, data");
		ASSERT_EQUALS(NEXTHDR_UDP, last_iterator.hdr_type, "Last function, hdr type");
	}

	// Test get extension header function.
	{
		void *frag_hdr_computed = get_extension_header(ip6_header, NEXTHDR_FRAGMENT);
		void *hop_by_hop_hdr_computed = get_extension_header(ip6_header, NEXTHDR_HOP);
		void *udp_hdr_computed = get_extension_header(ip6_header, NEXTHDR_UDP);

		ASSERT_EQUALS_PTR(fragment_hdr, frag_hdr_computed, "Get function, frag hdr");
		ASSERT_EQUALS_PTR(hop_by_hop_hdr, hop_by_hop_hdr_computed, "Get function, hop-by-hop hdr");
		// Cause the UDP header is not an extension header.
		ASSERT_EQUALS_PTR(NULL, udp_hdr_computed, "Get function, payload");
	}

	return true;
}