Beispiel #1
0
static bool test_6to4(l4_protocol l4_proto,
		int (*create_skb6_fn)(struct tuple *, struct sk_buff **, u16, u8),
		int (*create_skb4_fn)(struct tuple *, struct sk_buff **, u16, u8),
		u16 expected_payload4_len)
{
	struct sk_buff *skb6 = NULL, *skb4_expected = NULL, *skb4_actual = NULL;
	struct tuple tuple6, tuple4;
	bool result = false;

	if (init_ipv6_tuple(&tuple6, "1::1", 50080, "64::192.0.2.5", 51234, L4PROTO_UDP) != 0
			|| init_ipv4_tuple(&tuple4, "192.0.2.2", 80, "192.0.2.5", 1234, L4PROTO_UDP) != 0
			|| create_skb6_fn(&tuple6, &skb6, 100, 32) != 0
			|| create_skb4_fn(&tuple4, &skb4_expected, expected_payload4_len, 31) != 0)
		goto end;

	if (translating_the_packet(&tuple4, skb6, &skb4_actual) != VER_CONTINUE)
		goto end;

	result = compare_skbs(skb4_expected, skb4_actual);
	/* Fall through. */

end:
	kfree_skb(skb6);
	kfree_skb(skb4_expected);
	kfree_skb(skb4_actual);
	return result;
}
Beispiel #2
0
/**
 * Mirrors the core's behavior by processing skb_in as if it was the incoming packet.
 *
 * @param skb_in the outgoing packet. Except because it's a hairpin, here it's treated as if it was
 *		the one received from the network.
 * @param tuple_in skb_in's tuple.
 * @return whether we managed to U-turn the packet successfully.
 */
verdict handling_hairpinning(struct sk_buff *skb_in, struct tuple *tuple_in)
{
	struct sk_buff *skb_out;
	struct tuple tuple_out;
	verdict result;

	log_debug("Step 5: Handling Hairpinning...");

	if (skb_l4_proto(skb_in) == L4PROTO_ICMP) {
		/* RFC 6146 section 2 (Definition of "Hairpinning"). */
		log_debug("ICMP is not supported by hairpinning. Dropping packet...");
		return VER_DROP;
	}

	result = filtering_and_updating(skb_in, tuple_in);
	if (result != VER_CONTINUE)
		return result;
	result = compute_out_tuple(tuple_in, &tuple_out, skb_in);
	if (result != VER_CONTINUE)
		return result;
	result = translating_the_packet(&tuple_out, skb_in, &skb_out);
	if (result != VER_CONTINUE)
		return result;
	result = sendpkt_send(skb_in, skb_out);
	if (result != VER_CONTINUE)
		return result;

	log_debug("Done step 5.");
	return VER_CONTINUE;
}
Beispiel #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;
}
/**
 * Mirrors the core's behavior by processing skb_in as if it was the incoming packet.
 *
 * @param skb_in the outgoing packet. Except because it's a hairpin, here it's treated as if it was
 *		the one received from the network.
 * @param tuple_in skb_in's tuple.
 * @return whether we managed to U-turn the packet successfully.
 */
verdict handling_hairpinning(struct packet *in, struct tuple *tuple_in)
{
	struct packet out;
	struct tuple tuple_out;
	verdict result;

	log_debug("Step 5: Handling Hairpinning...");

	if (pkt_l4_proto(in) == L4PROTO_ICMP) {
		/*
		 * RFC 6146 section 2 (Definition of "Hairpinning").
		 *
		 * Update 2014-11-21:
		 * Actually, since ICMP errors count as UDP or TCP packets tuple-wise, maybe the RFC means
		 * we should only filter out ICMP echoes.
		 * Or maybe not even that, since they're going to be dropped later anyway, once Jool fails
		 * to find the mapping.
		 * Unfortunately, if I remove this if, Jool crashes when I hairpin a ICMP error.
		 */
		log_debug("ICMP is not supported by hairpinning. Dropping packet...");
		return VERDICT_DROP;
	}

	result = filtering_and_updating(in, tuple_in);
	if (result != VERDICT_CONTINUE)
		return result;
	result = compute_out_tuple(tuple_in, &tuple_out, in);
	if (result != VERDICT_CONTINUE)
		return result;
	result = translating_the_packet(&tuple_out, in, &out);
	if (result != VERDICT_CONTINUE)
		return result;
	result = sendpkt_send(in, &out);
	if (result != VERDICT_CONTINUE)
		return result;

	log_debug("Done step 5.");
	return VERDICT_CONTINUE;
}
Beispiel #5
0
static unsigned int core_common(struct packet *in)
{
	struct packet out;
	verdict result;

	result = translating_the_packet(NULL, in, &out);
	if (result != VERDICT_CONTINUE)
		goto end;
	result = sendpkt_send(in, &out);
	if (result != VERDICT_CONTINUE)
		goto end;

	log_debug("Success.");
	/* See the large comment above. */
	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;
}