int create_tcp_packet(struct sk_buff **skb, l3_protocol l3_proto, bool syn, bool rst, bool fin) { struct tcphdr *hdr_tcp; struct tuple tuple; int error; switch (l3_proto) { case L3PROTO_IPV4: error = init_tuple4(&tuple, "8.7.6.5", 8765, "5.6.7.8", 5678, L4PROTO_TCP); if (error) return error; error = create_skb4_tcp(&tuple, skb, 100, 32); if (error) return error; break; case L3PROTO_IPV6: error = init_tuple6(&tuple, "1::2", 1212, "3::4", 3434, L4PROTO_TCP); if (error) return error; error = create_skb6_tcp(&tuple, skb, 100, 32); if (error) return error; break; } hdr_tcp = tcp_hdr(*skb); hdr_tcp->syn = syn; hdr_tcp->rst = rst; hdr_tcp->fin = fin; return 0; }
static int init_payload_inner_ipv6(void *target, u16 payload_len) { struct ipv6hdr *hdr_ipv6; struct tcphdr *hdr_tcp; struct ipv6hdr tmp_hdr_ipv6; struct tcphdr tmp_hdr_tcp; unsigned char *inner_payload; struct tuple tuple6; int error; if (payload_len <= 0) return 0; /* Nothing to do here. */ error = init_tuple6(&tuple6, "1::1", 50080, "64::192.0.2.5", 51234, L4PROTO_TCP); if (error) return error; hdr_ipv6 = target; hdr_tcp = (struct tcphdr *) (hdr_ipv6 + 1); inner_payload = (unsigned char *) (hdr_tcp + 1); error = init_ipv6_hdr(&tmp_hdr_ipv6, 1300, NEXTHDR_TCP, &tuple6, true, false, 0, 32); if (error) return error; if (payload_len >= IPV6_HDR_LEN) { memcpy(hdr_ipv6, &tmp_hdr_ipv6, IPV6_HDR_LEN); payload_len -= IPV6_HDR_LEN; } else { memcpy(hdr_ipv6, &tmp_hdr_ipv6, payload_len); goto end; } error = init_tcp_hdr(&tmp_hdr_tcp, ETH_P_IPV6, 1300, &tuple6); if (error) return error; if (payload_len >= TCP_HDR_LEN) { memcpy(hdr_tcp, &tmp_hdr_tcp, TCP_HDR_LEN); payload_len -= TCP_HDR_LEN; } else { memcpy(hdr_tcp, &tmp_hdr_tcp, payload_len); goto end; } error = init_payload_normal(inner_payload, payload_len); if (error) return error; hdr_tcp->check = csum_ipv6_magic(&hdr_ipv6->saddr, &hdr_ipv6->daddr, sizeof(*hdr_tcp) + payload_len, NEXTHDR_TCP, csum_partial(hdr_tcp, sizeof(*hdr_tcp) + payload_len, 0)); /* Fall through. */ end: return 0; }
/** * 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; }