Esempio n. 1
0
static bool test_icmp(void)
{
	struct xlation state;
	struct sk_buff *skb;
	bool success = true;

	xlation_init(&state, &jool);

	log_debug("== IPv4 packet attempts to be translated without state ==");
	if (create_skb4_icmp_info("0.0.0.4", "192.0.2.128", 1024, 16, 32, &skb))
		return false;
	if (pkt_init_ipv4(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(UNTRANSLATABLE, ipv4_simple(&state), "result 1");
	success &= assert_bib_count(0, L4PROTO_ICMP);
	success &= assert_session_count(0, L4PROTO_ICMP);

	kfree_skb(skb);

	log_debug("== IPv6 packet and gets translated correctly ==");
	if (create_skb6_icmp_info("1::2", "3::4", 1212, 16, 32, &skb))
		return false;
	if (pkt_init_ipv6(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(CONTINUE, ipv6_simple(&state), "result 2");
	success &= assert_bib_count(1, L4PROTO_ICMP);
	success &= assert_bib_exists("1::2", 1212, "192.0.2.128", 1024, L4PROTO_ICMP, 1);
	success &= assert_session_count(1, L4PROTO_ICMP);
	success &= assert_session_exists("1::2", 1212, "3::4", 1212,
			"192.0.2.128", 1024, "0.0.0.4", 1024,
			L4PROTO_ICMP, ESTABLISHED,
			SESSION_TIMER_EST, ICMP_DEFAULT);

	kfree_skb(skb);

	log_debug("== Now that there's state, the IPv4 packet manages to traverse ==");
	if (!invert_packet(&state, &skb))
		return false;

	success &= ASSERT_VERDICT(CONTINUE, ipv4_simple(&state), "result 3");
	success &= assert_bib_count(1, L4PROTO_ICMP);
	success &= assert_bib_exists("1::2", 1212, "192.0.2.128", 1024, L4PROTO_ICMP, 1);
	success &= assert_session_count(1, L4PROTO_ICMP);
	success &= assert_session_exists("1::2", 1212, "3::4", 1212,
			"192.0.2.128", 1024, "0.0.0.4", 1024,
			L4PROTO_ICMP, ESTABLISHED,
			SESSION_TIMER_EST, ICMP_DEFAULT);

	kfree_skb(skb);

	return success;
}
Esempio n. 2
0
static unsigned int nat64_core(struct sk_buff *skb_in,
		bool (*compute_out_tuple_fn)(struct tuple *, struct sk_buff *, struct tuple *),
		bool (*translate_packet_fn)(struct tuple *, struct sk_buff *, struct sk_buff **),
		bool (*send_packet_fn)(struct sk_buff *, struct sk_buff *))
{
	struct sk_buff *skb_out = NULL;
	struct tuple tuple_in, tuple_out;

	if (!determine_in_tuple(skb_in, &tuple_in))
		goto free_and_fail;
	if (filtering_and_updating(skb_in, &tuple_in) != NF_ACCEPT)
		goto free_and_fail;
	if (!compute_out_tuple_fn(&tuple_in, skb_in, &tuple_out))
		goto free_and_fail;
	if (!translate_packet_fn(&tuple_out, skb_in, &skb_out))
		goto free_and_fail;
	if (is_hairpin(&tuple_out)) {
		if (!handling_hairpinning(skb_out, &tuple_out))
			goto free_and_fail;
	} else {
		if (!send_packet_fn(skb_in, skb_out))
			goto fail;
	}

	log_debug("Success.");
	return NF_DROP; /* Lol, the irony. */

free_and_fail:
	kfree_skb(skb_out);
	/* Fall through. */

fail:
	log_debug("Failure.");
	return NF_DROP;
}
Esempio n. 3
0
static unsigned int core_common(struct packet *in)
{
	struct packet out;
	struct tuple tuple_in;
	struct tuple tuple_out;
	verdict result;

	result = determine_in_tuple(in, &tuple_in);
	if (result != VERDICT_CONTINUE)
		goto end;
	result = filtering_and_updating(in, &tuple_in);
	if (result != VERDICT_CONTINUE)
		goto end;
	result = compute_out_tuple(&tuple_in, &tuple_out, in);
	if (result != VERDICT_CONTINUE)
		goto end;
	result = translating_the_packet(&tuple_out, in, &out);
	if (result != VERDICT_CONTINUE)
		goto end;

	if (is_hairpin(&out)) {
		result = handling_hairpinning(&out, &tuple_out);
		kfree_skb(out.skb);
	} else {
		result = sendpkt_send(in, &out);
		/* send_pkt releases skb_out regardless of verdict. */
	}

	if (result != VERDICT_CONTINUE)
		goto end;

	log_debug("Success.");
	/*
	 * The new packet was sent, so the original one can die; drop it.
	 *
	 * NF_DROP translates into an error (see nf_hook_slow()).
	 * Sending a replacing & translated version of the packet should not count as an error,
	 * so we free the incoming packet ourselves and return NF_STOLEN on success.
	 */
	kfree_skb(in->skb);
	result = VERDICT_STOLEN;
	/* Fall through. */

end:
	if (result == VERDICT_ACCEPT)
		log_debug("Returning the packet to the kernel.");

	return (unsigned int) result;
}
static bool test_determine_in_tuple_ipv6(void)
{
	struct packet pkt;
	struct sk_buff *skb;
	struct tuple actual, expected;
	bool success = true;

	if (is_error(init_ipv6_tuple(&expected, "1::2", 1212, "3::4", 3434, L4PROTO_TCP)))
		return false;
	if (is_error(create_skb6_tcp(&expected, &skb, 8, 32)))
		return false;
	if (is_error(pkt_init_ipv6(&pkt, skb)))
		return false;

	success &= assert_equals_int(VERDICT_CONTINUE, determine_in_tuple(&pkt, &actual), "verdict");
	success &= assert_equals_tuple(&expected, &actual, "tuple");

	kfree_skb(skb);
	return success;
}
static bool test_determine_in_tuple_ipv4(void)
{
	struct packet pkt;
	struct sk_buff *skb;
	struct tuple actual, expected;
	bool success = true;

	if (is_error(init_ipv4_tuple(&expected, "8.7.6.5", 8765, "5.6.7.8", 5678, L4PROTO_UDP)))
		return false;
	if (is_error(create_skb4_udp(&expected, &skb, 8, 32)))
		return false;
	if (is_error(pkt_init_ipv4(&pkt, skb)))
		return false;

	success &= assert_equals_int(VERDICT_CONTINUE, determine_in_tuple(&pkt, &actual), "verdict");
	success &= assert_equals_tuple(&expected, &actual, "tuple");

	kfree_skb(skb);
	return success;
}
static bool test_determine_in_tuple_ipv6(void)
{
	struct sk_buff *skb;
	struct fragment *frag;
	struct tuple actual, expected;
	struct ipv6_pair pair6;
	bool success = true;

	if (is_error(init_ipv6_tuple(&expected, "1::2", 1212, "3::4", 3434, L4PROTO_TCP)))
		return false;
	if (is_error(init_pair6(&pair6, "1::2", 1212, "3::4", 3434)))
		return false;
	if (is_error(create_skb_ipv6_tcp_fragment_1(&pair6, &skb, 8)))
		return false;
	if (is_error(frag_create_from_skb(skb, &frag)))
		return false;

	success &= assert_equals_int(VER_CONTINUE, determine_in_tuple(frag, &actual), "verdict");
	success &= assert_equals_tuple(&expected, &actual, "tuple");

	frag_kfree(frag);
	return success;
}
static bool test_determine_in_tuple_ipv4(void)
{
	struct sk_buff *skb;
	struct fragment *frag;
	struct tuple actual, expected;
	struct ipv4_pair pair4;
	bool success = true;

	if (is_error(init_ipv4_tuple(&expected, "8.7.6.5", 8765, "5.6.7.8", 5678, L4PROTO_UDP)))
		return false;
	if (is_error(init_pair4(&pair4, "8.7.6.5", 8765, "5.6.7.8", 5678)))
		return false;
	if (is_error(create_skb_ipv4_udp(&pair4, &skb, 8)))
		return false;
	if (is_error(frag_create_from_skb(skb, &frag)))
		return false;

	success &= assert_equals_int(VER_CONTINUE, determine_in_tuple(frag, &actual), "verdict");
	success &= assert_equals_tuple(&expected, &actual, "tuple");

	frag_kfree(frag);
	return success;
}
Esempio n. 8
0
static bool test_filtering_and_updating(void)
{
	struct xlation state;
	struct sk_buff *skb;
	bool success = true;

	xlation_init(&state, &jool);

	log_debug("== ICMPv4 errors should succeed but not affect the tables ==");
	if (create_skb4_icmp_error("8.7.6.5", "192.0.2.128", 100, 32, &skb))
		return false;
	if (pkt_init_ipv4(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(CONTINUE, filtering_and_updating(&state), "ICMP error 1");
	success &= assert_bib_count(0, L4PROTO_TCP);
	success &= assert_bib_count(0, L4PROTO_UDP);
	success &= assert_bib_count(0, L4PROTO_ICMP);
	success &= assert_session_count(0, L4PROTO_TCP);
	success &= assert_session_count(0, L4PROTO_UDP);
	success &= assert_session_count(0, L4PROTO_ICMP);

	kfree_skb(skb);
	if (!success)
		return false;

	log_debug("== ICMPv6 errors should succeed but not affect the tables ==");
	if (create_skb6_icmp_error("1::2", "3::3:4", 100, 32, &skb))
		return false;
	if (pkt_init_ipv6(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(CONTINUE, filtering_and_updating(&state), "ICMP error 2");
	success &= assert_bib_count(0, L4PROTO_TCP);
	success &= assert_bib_count(0, L4PROTO_UDP);
	success &= assert_bib_count(0, L4PROTO_ICMP);
	success &= assert_session_count(0, L4PROTO_TCP);
	success &= assert_session_count(0, L4PROTO_UDP);
	success &= assert_session_count(0, L4PROTO_ICMP);

	kfree_skb(skb);
	if (!success)
		return false;

	log_debug("== Hairpinning loops should be dropped ==");
	if (create_skb6_udp("3::1:2", 1212, "3::3:4", 3434, 100, 32, &skb))
		return false;
	if (pkt_init_ipv6(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(DROP, filtering_and_updating(&state), "Hairpinning");
	success &= assert_bib_count(0, L4PROTO_UDP);
	success &= assert_session_count(0, L4PROTO_UDP);

	kfree_skb(skb);
	if (!success)
		return false;

	log_debug("== Packets not headed to pool6 must not be translated ==");
	if (create_skb6_udp("1::2", 1212, "4::1", 3434, 100, 32, &skb))
		return false;
	if (pkt_init_ipv6(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(UNTRANSLATABLE, filtering_and_updating(&state), "Not pool6 packet");
	success &= assert_bib_count(0, L4PROTO_UDP);
	success &= assert_session_count(0, L4PROTO_UDP);

	kfree_skb(skb);
	if (!success)
		return false;

	log_debug("== Packets not headed to pool4 must not be translated ==");
	if (create_skb4_udp("8.7.6.5", 8765, "5.6.7.8", 5678, 100, 32, &skb))
		return false;
	if (pkt_init_ipv4(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(UNTRANSLATABLE, filtering_and_updating(&state), "Not pool4 packet");
	success &= assert_bib_count(0, L4PROTO_UDP);
	success &= assert_session_count(0, L4PROTO_UDP);

	kfree_skb(skb);
	if (!success)
		return false;

	log_debug("== Other IPv6 packets should survive validations ==");
	if (create_skb6_udp("1::2", 1212, "3::3:4", 3434, 100, 32, &skb))
		return false;
	if (pkt_init_ipv6(&state, skb))
		return false;
	if (determine_in_tuple(&state) != VERDICT_CONTINUE)
		return false;

	success &= ASSERT_VERDICT(CONTINUE, filtering_and_updating(&state), "IPv6 success");
	success &= assert_bib_count(1, L4PROTO_UDP);
	success &= assert_session_count(1, L4PROTO_UDP);

	kfree_skb(skb);
	if (!success)
		return false;

	log_debug("== Other IPv4 packets should survive validations ==");
	if (!invert_packet(&state, &skb))
		return false;

	success &= ASSERT_VERDICT(CONTINUE, filtering_and_updating(&state), "IPv4 success");
	success &= assert_bib_count(1, L4PROTO_UDP);
	success &= assert_session_count(1, L4PROTO_UDP);

	kfree_skb(skb);
	return success;
}