static bool test_4to6(l4_protocol l4_proto) { struct tuple in, out; int field = 0; bool success = true; if (is_error(init_ipv4_tuple(&in, remote4, 80, local4, 5678, l4_proto))) return false; success &= assert_equals_int(VER_CONTINUE, compute_out_tuple(&in, &out, NULL), "Call"); success &= assert_equals_int(L3PROTO_IPV6, out.l3_proto, "l3 proto"); success &= assert_equals_int(l4_proto, out.l4_proto, "l4 proto"); success &= assert_equals_ipv6_str(local6, &out.src.addr6.l3, "src addr"); if (l4_proto == L4PROTO_ICMP) success &= assert_equals_u16(1234, out.src.addr6.l4, "src port (icmp id)"); else success &= assert_equals_u16(80, out.src.addr6.l4, "src port"); success &= assert_equals_ipv6_str(remote6, &out.dst.addr6.l3, "dst addr"); success &= assert_equals_u16(1234, out.dst.addr6.l4, "dst port"); success &= assert_equals_int(0, field, "unchanged field"); return success; }
static bool test_hairpin(l4_protocol l4_proto, skb_creator create_skb_fn) { struct sk_buff *skb_in = NULL; struct sk_buff *skb_out = NULL; struct sk_buff *skb_tmp = NULL; struct bib_entry *static_bib = NULL; struct bib_entry *dynamic_bib = NULL; struct session_entry *static_session = NULL; struct session_entry *dynamic_session = NULL; struct tuple tuple6; bool success = true; static_bib = bib_create_str(SERVER_ADDR6, SERVER_PORT6, NAT64_POOL4, SERVER_PORT6, l4_proto); dynamic_bib = bib_create_str(CLIENT_ADDR, CLIENT_PORT, NAT64_POOL4, DYNAMIC_BIB_IPV4_PORT, l4_proto); static_session = session_create_str( SERVER_ADDR6, SERVER_PORT6, SERVER_HAIRPIN_ADDR, DYNAMIC_BIB_IPV4_PORT, NAT64_POOL4, SERVER_PORT6, NAT64_POOL4, DYNAMIC_BIB_IPV4_PORT, l4_proto); dynamic_session = session_create_str(CLIENT_ADDR, CLIENT_PORT, SERVER_HAIRPIN_ADDR, SERVER_PORT6, NAT64_POOL4, DYNAMIC_BIB_IPV4_PORT, NAT64_POOL4, SERVER_PORT6, l4_proto); if (!static_bib || !dynamic_bib || !static_session || !dynamic_session) goto fail; /* Send the request. */ if (is_error(init_ipv6_tuple(&tuple6, CLIENT_ADDR, CLIENT_PORT, SERVER_HAIRPIN_ADDR, SERVER_PORT6, l4_proto))) goto fail; if (is_error(create_skb_fn(&tuple6, &skb_in, 40, 32))) goto fail; success &= send(skb_in); success &= BIB_ASSERT(l4_proto, static_bib, dynamic_bib); success &= SESSION_ASSERT(l4_proto, static_session, dynamic_session); skb_out = skb_tmp = get_sent_skb(); success &= assert_not_null(skb_out, "Request packet"); if (!success) goto fail; do { success &= assert_equals_ipv6_str(SERVER_HAIRPIN_ADDR, &ipv6_hdr(skb_tmp)->saddr, "out src"); success &= assert_equals_ipv6_str(SERVER_ADDR6, &ipv6_hdr(skb_tmp)->daddr, "out dst"); skb_tmp = skb_tmp->next; } while (skb_tmp); switch (l4_proto) { case L4PROTO_UDP: success &= assert_equals_u16(DYNAMIC_BIB_IPV4_PORT, be16_to_cpu(udp_hdr(skb_out)->source), "out's src port"); success &= assert_equals_u16(SERVER_PORT6, be16_to_cpu(udp_hdr(skb_out)->dest), "out's dst port"); break; case L4PROTO_TCP: success &= assert_equals_u16(DYNAMIC_BIB_IPV4_PORT, be16_to_cpu(tcp_hdr(skb_out)->source), "out's src port"); success &= assert_equals_u16(SERVER_PORT6, be16_to_cpu(tcp_hdr(skb_out)->dest), "out's dst port"); break; case L4PROTO_ICMP: case L4PROTO_OTHER: log_err("Test is not designed for protocol %d.", l4_proto); success = false; break; } if (!success) goto fail; kfree_skb(skb_out); /* Send the response. */ if (is_error(init_ipv6_tuple(&tuple6, SERVER_ADDR6, SERVER_PORT6, SERVER_HAIRPIN_ADDR, DYNAMIC_BIB_IPV4_PORT, l4_proto))) goto fail; if (is_error(create_skb_fn(&tuple6, &skb_in, 100, 32))) goto fail; success &= send(skb_in); /* The module should have reused the entries, so the database shouldn't have changed. */ success &= BIB_ASSERT(l4_proto, static_bib, dynamic_bib); success &= SESSION_ASSERT(l4_proto, static_session, dynamic_session); skb_out = skb_tmp = get_sent_skb(); success &= assert_not_null(skb_out, "Response packet"); if (!success) goto fail; do { success &= assert_equals_ipv6_str(SERVER_HAIRPIN_ADDR, &ipv6_hdr(skb_out)->saddr, "out src"); success &= assert_equals_ipv6_str(CLIENT_ADDR, &ipv6_hdr(skb_out)->daddr, "out dst"); skb_tmp = skb_tmp->next; } while (skb_tmp); switch (l4_proto) { case L4PROTO_UDP: success &= assert_equals_u16(SERVER_PORT6, be16_to_cpu(udp_hdr(skb_out)->source), "out's src port"); success &= assert_equals_u16(CLIENT_PORT, be16_to_cpu(udp_hdr(skb_out)->dest), "out's dst port"); break; case L4PROTO_TCP: success &= assert_equals_u16(SERVER_PORT6, be16_to_cpu(tcp_hdr(skb_out)->source), "out's src port"); success &= assert_equals_u16(CLIENT_PORT, be16_to_cpu(tcp_hdr(skb_out)->dest), "out's dst port"); break; case L4PROTO_ICMP: case L4PROTO_OTHER: log_err("Test is not designed for protocol %d.", l4_proto); success = false; break; } kfree_skb(skb_out); session_return(dynamic_session); session_return(static_session); bib_kfree(dynamic_bib); bib_kfree(static_bib); return success; fail: kfree_skb(skb_out); if (dynamic_session) session_return(dynamic_session); if (static_session) session_return(static_session); if (dynamic_bib) bib_kfree(dynamic_bib); if (static_bib) bib_kfree(static_bib); return false; }