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; }
/** * 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; }
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; }
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; }