/* * Something else arrives. */ static bool test_tcp_trans_state_handle_else(void) { struct session_entry *session; struct expire_timer *expirer; struct packet pkt; struct sk_buff *skb; unsigned long timeout = 0; bool success = true; /* Prepare */ session = session_create_str_tcp("1::2", 1212, "3::4", 3434, "5.6.7.8", 5678, "8.7.6.5", 8765, TRANS); if (!session) return false; if (is_error(create_tcp_packet(&skb, L3PROTO_IPV4, true, false, false))) return false; if (is_error(pkt_init_ipv4(&pkt, skb))) return false; /* Evaluate */ success &= assert_equals_int(0, tcp_trans_state_handle(&pkt, session, &expirer), "else-result"); success &= assert_equals_u8(ESTABLISHED, session->state, "else-state"); success &= assert_equals_int(0, sessiondb_get_timeout(session, &timeout), "else-toresult"); success &= assert_equals_ulong(TCPEST_TIMEOUT, timeout, "else-lifetime"); kfree_skb(skb); return success; }
unsigned int core_4to6(struct sk_buff *skb) { struct packet pkt; struct iphdr *hdr = ip_hdr(skb); int error; if (config_get_is_disable()) return NF_ACCEPT; /* Translation is disabled; let the packet pass. */ if (is_blacklisted4(hdr->saddr) || is_blacklisted4(hdr->daddr)) return NF_ACCEPT; if (nat64_is_stateful()) { if (!pool4_contains(hdr->daddr) || pool6_is_empty()) return NF_ACCEPT; /* Not meant for translation; let the kernel handle it. */ } log_debug("==============================================="); log_debug("Catching IPv4 packet: %pI4->%pI4", &hdr->saddr, &hdr->daddr); error = pkt_init_ipv4(&pkt, skb); /* Reminder: This function might change pointers. */ if (error) return NF_DROP; error = validate_icmp4_csum(&pkt); if (error) { inc_stats(&pkt, IPSTATS_MIB_INHDRERRORS); return NF_DROP; } return core_common(&pkt); }
/* * A V4 RST packet arrives. */ static bool test_tcp_trans_state_handle_v4rst(void) { struct session_entry *session; struct expire_timer *expirer; struct packet pkt; struct sk_buff *skb; bool success = true; /* Prepare */ session = session_create_str_tcp("1::2", 1212, "3::4", 3434, "5.6.7.8", 5678, "8.7.6.5", 8765, TRANS); if (!session) return false; if (is_error(create_tcp_packet(&skb, L3PROTO_IPV4, false, true, false))) return false; if (is_error(pkt_init_ipv4(&pkt, skb))) return false; /* Evaluate */ success &= assert_equals_int(0, tcp_trans_state_handle(&pkt, session, &expirer), "V4 rst-result"); success &= assert_equals_u8(TRANS, session->state, "V4 rst-state"); success &= assert_null(session->expirer, "null expirer"); kfree_skb(skb); return success; }
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; }
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 invert_packet(struct xlation *state, struct sk_buff **skb) { struct iphdr *hdr4; struct udphdr *uhdr; if (create_skb4_udp("1.1.1.1", 1111, "2.2.2.2", 2222, 100, 32, skb)) return false; if (invert_tuple(state)) return false; hdr4 = ip_hdr(*skb); uhdr = udp_hdr(*skb); hdr4->saddr = state->in.tuple.src.addr4.l3.s_addr; uhdr->source = cpu_to_be16(state->in.tuple.src.addr4.l4); hdr4->daddr = state->in.tuple.dst.addr4.l3.s_addr; uhdr->dest = cpu_to_be16(state->in.tuple.dst.addr4.l4); if (pkt_init_ipv4(state, *skb)) return false; return true; }
/** * We'll just chain a handful of packets, since testing every combination would * take forever and the inner functions are tested in session db anyway. * The chain is V6 SYN --> V4 SYN --> V6 RST --> V6 SYN. */ static bool test_tcp(void) { struct xlation state = { .jool = jool }; struct sk_buff *skb; bool success = true; log_debug("== V6 SYN =="); if (init_tuple6(&state.in.tuple, "1::2", 1212, "3::4", 3434, L4PROTO_TCP)) return false; if (create_tcp_packet(&skb, L3PROTO_IPV6, true, false, false)) return false; if (pkt_init_ipv6(&state, skb)) return false; success &= ASSERT_VERDICT(CONTINUE, ipv6_tcp(&state), "Closed-result"); success &= assert_bib_count(1, L4PROTO_TCP); success &= assert_bib_exists("1::2", 1212, "192.0.2.128", 1024, L4PROTO_TCP, 1); success &= assert_session_count(1, L4PROTO_TCP); success &= assert_session_exists("1::2", 1212, "3::4", 3434, "192.0.2.128", 1024, "0.0.0.4", 3434, L4PROTO_TCP, V6_INIT, SESSION_TIMER_TRANS, TCP_TRANS); kfree_skb(skb); log_debug("== V4 SYN =="); if (invert_tuple(&state)) return false; if (create_tcp_packet(&skb, L3PROTO_IPV4, true, false, false)) return false; if (pkt_init_ipv4(&state, skb)) return false; success &= ASSERT_VERDICT(CONTINUE, ipv4_tcp(&state), "V6 init-result"); success &= assert_bib_count(1, L4PROTO_TCP); success &= assert_bib_exists("1::2", 1212, "192.0.2.128", 1024, L4PROTO_TCP, 1); success &= assert_session_count(1, L4PROTO_TCP); success &= assert_session_exists("1::2", 1212, "3::4", 3434, "192.0.2.128", 1024, "0.0.0.4", 3434, L4PROTO_TCP, ESTABLISHED, SESSION_TIMER_EST, TCP_EST); kfree_skb(skb); log_debug("== V6 RST =="); if (init_tuple6(&state.in.tuple, "1::2", 1212, "3::4", 3434, L4PROTO_TCP)) return false; if (create_tcp_packet(&skb, L3PROTO_IPV6, false, true, false)) return false; if (pkt_init_ipv6(&state, skb)) return false; success &= ASSERT_VERDICT(CONTINUE, ipv6_tcp(&state), "Established-result"); success &= assert_bib_count(1, L4PROTO_TCP); success &= assert_bib_exists("1::2", 1212, "192.0.2.128", 1024, L4PROTO_TCP, 1); success &= assert_session_count(1, L4PROTO_TCP); success &= assert_session_exists("1::2", 1212, "3::4", 3434, "192.0.2.128", 1024, "0.0.0.4", 3434, L4PROTO_TCP, TRANS, SESSION_TIMER_TRANS, TCP_TRANS); kfree_skb(skb); log_debug("== V6 SYN =="); if (create_tcp_packet(&skb, L3PROTO_IPV6, true, false, false)) return false; if (pkt_init_ipv6(&state, skb)) return false; success &= ASSERT_VERDICT(CONTINUE, ipv6_tcp(&state), "Trans-result"); success &= assert_bib_count(1, L4PROTO_TCP); success &= assert_bib_exists("1::2", 1212, "192.0.2.128", 1024, L4PROTO_TCP, 1); success &= assert_session_count(1, L4PROTO_TCP); success &= assert_session_exists("1::2", 1212, "3::4", 3434, "192.0.2.128", 1024, "0.0.0.4", 3434, L4PROTO_TCP, ESTABLISHED, SESSION_TIMER_EST, TCP_EST); kfree_skb(skb); return success; }
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; }