test: add imitate_tcp_packet test case (TCP over GREv0: GRE enable checksum)

This commit is contained in:
luwenpeng
2024-07-15 15:07:38 +08:00
parent d31cfd02fd
commit 07ce636f64
13 changed files with 408 additions and 150 deletions

View File

@@ -46,8 +46,8 @@ target_link_libraries(gtest_packet_frag packet gtest)
add_executable(gtest_packet_parse gtest_packet_parse.cpp)
target_link_libraries(gtest_packet_parse packet gtest)
add_executable(gtest_packet_build gtest_packet_build.cpp)
target_link_libraries(gtest_packet_build packet gtest)
add_executable(gtest_packet_craft gtest_packet_craft.cpp)
target_link_libraries(gtest_packet_craft packet gtest)
add_executable(gtest_packet_ldbc gtest_packet_ldbc.cpp)
target_link_libraries(gtest_packet_ldbc packet gtest)
@@ -69,5 +69,5 @@ gtest_discover_tests(gtest_gtp1_utils)
gtest_discover_tests(gtest_gtp2_utils)
gtest_discover_tests(gtest_packet_frag)
gtest_discover_tests(gtest_packet_parse)
gtest_discover_tests(gtest_packet_build)
gtest_discover_tests(gtest_packet_craft)
gtest_discover_tests(gtest_packet_ldbc)

View File

@@ -6,11 +6,12 @@
#include "ip4_utils.h"
#include "ip6_utils.h"
#include "gtp_utils.h"
#include "gre_utils.h"
#include "packet_def.h"
#include "packet_dump.h"
#include "packet_layer.h"
#include "packet_parse.h"
#include "packet_build.h"
#include "packet_craft.h"
#define PRINT_GREEN(fmt, ...) printf("\033[0;32m" fmt "\033[0m\n", ##__VA_ARGS__)
#define PRINT_RED(fmt, ...) printf("\033[0;31m" fmt "\033[0m\n", ##__VA_ARGS__)
@@ -120,13 +121,13 @@ unsigned char data1[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/*
* imitate_tcp_packet()
* craft_tcp_packet()
* -> ETH->IPv4->TCP
* -> with TCP options
* -> with TCP payload
*/
#if 1
TEST(PACKET_BUILD_TCP, ETH_IP4_TCP)
TEST(PACKET_CRAFT_TCP, ETH_IP4_TCP)
{
struct packet orig_pkt;
memset(&orig_pkt, 0, sizeof(orig_pkt));
@@ -134,13 +135,13 @@ TEST(PACKET_BUILD_TCP, ETH_IP4_TCP)
PRINT_GREEN("origin packet:");
packet_print(&orig_pkt);
struct packet *new_pkt = imitate_tcp_packet(&orig_pkt, 1, 2, TH_ACK, (const char *)&ts_pad_opt, sizeof(ts_pad_opt), "Hello", 5);
struct packet *new_pkt = craft_tcp_packet(&orig_pkt, 1, 2, TH_ACK, (const char *)&ts_pad_opt, sizeof(ts_pad_opt), "Hello", 5);
EXPECT_TRUE(new_pkt != nullptr);
PRINT_GREEN("new packet:");
packet_print(new_pkt);
packet_dump_hex(new_pkt, STDOUT_FILENO);
packet_dump_pcap(new_pkt, "imitate-eth-ipv4-tcp.pcap");
packet_dump_pcap(new_pkt, "craft-eth-ipv4-tcp.pcap");
const char *orig_pkt_data = packet_get_raw_data(&orig_pkt);
uint16_t orig_pkt_len = packet_get_raw_len(&orig_pkt);
@@ -155,25 +156,25 @@ TEST(PACKET_BUILD_TCP, ETH_IP4_TCP)
{
if (layer.proto == LAYER_PROTO_IPV4)
{
const struct ip *ip = (struct ip *)layer.hdr.raw;
const struct ip *ip = (const struct ip *)layer.hdr.raw;
EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 57);
EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0xb7e1);
break;
}
if (layer.proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp = (struct tcphdr *)layer.hdr.raw;
const struct tcphdr *tcp = (const struct tcphdr *)layer.hdr.raw;
EXPECT_TRUE(tcp_hdr_get_seq(tcp) == 1);
EXPECT_TRUE(tcp_hdr_get_ack(tcp) == 2);
EXPECT_TRUE(tcp_hdr_get_flags(tcp) == TH_ACK);
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp) == 32);
EXPECT_TRUE(tcp_hdr_get_checksum(tcp) == 0xaf73);
break;
}
}
for (uint16_t i = 0; i < new_pkt_len - 12 - 5; i++)
{
if ((16 <= i && i <= 17) || // skip IPv4 total length
(18 <= i && i <= 19) || // skip IPv4 identification
i == 22 || // skip IPv4 TTL
(24 <= i && i <= 25)) // skip IPv4 checksum
{
continue;
@@ -182,7 +183,6 @@ TEST(PACKET_BUILD_TCP, ETH_IP4_TCP)
(42 <= i && i <= 45) || // skip TCP ack
i == 46 || // skip TCP data offset
i == 47 || // skip TCP flags
(48 <= i && i <= 49) || // skip TCP window
(50 <= i && i <= 51)) // skip TCP checksum
{
continue;
@@ -257,12 +257,12 @@ unsigned char data2[] = {
0x04, 0x02};
/*
* imitate_tcp_packet()
* craft_tcp_packet()
* -> ETH->IPv4->IPv6->TCP
* -> with TCP payload
*/
#if 1
TEST(PACKET_BUILD_TCP, ETH_IP4_IP6_TCP)
TEST(PACKET_CRAFT_TCP, ETH_IP4_IP6_TCP)
{
struct packet orig_pkt;
memset(&orig_pkt, 0, sizeof(orig_pkt));
@@ -270,13 +270,13 @@ TEST(PACKET_BUILD_TCP, ETH_IP4_IP6_TCP)
PRINT_GREEN("origin packet:");
packet_print(&orig_pkt);
struct packet *new_pkt = imitate_tcp_packet(&orig_pkt, 1234, 2345, TH_ACK, NULL, 0, "Hello", 5);
struct packet *new_pkt = craft_tcp_packet(&orig_pkt, 1234, 2345, TH_ACK, NULL, 0, "Hello", 5);
EXPECT_TRUE(new_pkt != nullptr);
PRINT_GREEN("new packet:");
packet_print(new_pkt);
packet_dump_hex(new_pkt, STDOUT_FILENO);
packet_dump_pcap(new_pkt, "imitate-eth-ipv4-ipv6-tcp.pcap");
packet_dump_pcap(new_pkt, "craft-eth-ipv4-ipv6-tcp.pcap");
const char *orig_pkt_data = packet_get_raw_data(&orig_pkt);
uint16_t orig_pkt_len = packet_get_raw_len(&orig_pkt);
@@ -291,37 +291,36 @@ TEST(PACKET_BUILD_TCP, ETH_IP4_IP6_TCP)
{
if (layer.proto == LAYER_PROTO_IPV4)
{
const struct ip *ip = (struct ip *)layer.hdr.raw;
const struct ip *ip = (const struct ip *)layer.hdr.raw;
EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 85);
EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0x09cf);
break;
}
if (layer.proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6 = (struct ip6_hdr *)layer.hdr.raw;
const struct ip6_hdr *ip6 = (const struct ip6_hdr *)layer.hdr.raw;
EXPECT_TRUE(ip6_hdr_get_payload_len(ip6) == 25);
break;
}
if (layer.proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp = (struct tcphdr *)layer.hdr.raw;
const struct tcphdr *tcp = (const struct tcphdr *)layer.hdr.raw;
EXPECT_TRUE(tcp_hdr_get_seq(tcp) == 1234);
EXPECT_TRUE(tcp_hdr_get_ack(tcp) == 2345);
EXPECT_TRUE(tcp_hdr_get_flags(tcp) == TH_ACK);
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp) == 20);
EXPECT_TRUE(tcp_hdr_get_checksum(tcp) == 0xe350);
break;
}
}
for (uint16_t i = 0; i < new_pkt_len - 5; i++)
{
if ((16 <= i && i <= 17) || // skip IPv4 total length
(18 <= i && i <= 19) || // skip IPv4 identification
i == 22 || // skip IPv4 TTL
(24 <= i && i <= 25)) // skip IPv4 checksum
{
continue;
}
if ((38 <= i && i <= 39) || // skip IPv6 payload length
i == 41) // skip IPv6 hop limit
if (38 <= i && i <= 39) // skip IPv6 payload length
{
continue;
}
@@ -329,7 +328,6 @@ TEST(PACKET_BUILD_TCP, ETH_IP4_IP6_TCP)
(82 <= i && i <= 85) || // skip TCP ack
i == 86 || // skip TCP data offset
i == 87 || // skip TCP flags
(88 <= i && i <= 89) || // skip TCP window
(90 <= i && i <= 91)) // skip TCP checksum
{
continue;
@@ -473,12 +471,12 @@ unsigned char data3[] = {
0x4f, 0xe9, 0xf5, 0xf0, 0x61, 0x5d, 0x7f, 0xc4, 0xc4, 0xd1, 0x05, 0x54, 0x13, 0xdb};
/*
* imitate_tcp_packet()
* craft_tcp_packet()
* -> ETH->IPv6->UDP->GTP->IPv4->TCP
* -> with TCP payload
*/
#if 1
TEST(PACKET_BUILD_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
TEST(PACKET_CRAFT_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
{
struct packet orig_pkt;
memset(&orig_pkt, 0, sizeof(orig_pkt));
@@ -486,13 +484,13 @@ TEST(PACKET_BUILD_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
PRINT_GREEN("origin packet:");
packet_print(&orig_pkt);
struct packet *new_pkt = imitate_tcp_packet(&orig_pkt, 1, 2, TH_ACK, NULL, 0, "Hello", 5);
struct packet *new_pkt = craft_tcp_packet(&orig_pkt, 1, 2, TH_ACK, NULL, 0, "Hello", 5);
EXPECT_TRUE(new_pkt != nullptr);
PRINT_GREEN("new packet:");
packet_print(new_pkt);
packet_dump_hex(new_pkt, STDOUT_FILENO);
packet_dump_pcap(new_pkt, "imitate-eth-ipv6-udp-gtp-ipv4-tcp.pcap");
packet_dump_pcap(new_pkt, "craft-eth-ipv6-udp-gtp-ipv4-tcp.pcap");
const char *orig_pkt_data = packet_get_raw_data(&orig_pkt);
uint16_t orig_pkt_len = packet_get_raw_len(&orig_pkt);
@@ -507,45 +505,46 @@ TEST(PACKET_BUILD_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
{
if (layer.proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6 = (struct ip6_hdr *)layer.hdr.raw;
const struct ip6_hdr *ip6 = (const struct ip6_hdr *)layer.hdr.raw;
EXPECT_TRUE(ip6_hdr_get_payload_len(ip6) == 61);
break;
}
if (layer.proto == LAYER_PROTO_UDP)
{
const struct udphdr *udp = (struct udphdr *)layer.hdr.raw;
const struct udphdr *udp = (const struct udphdr *)layer.hdr.raw;
EXPECT_TRUE(udp_hdr_get_total_len(udp) == 61);
EXPECT_TRUE(udp_hdr_get_checksum(udp) == 0xd375);
break;
}
if (layer.proto == LAYER_PROTO_GTP_U)
{
EXPECT_TRUE(peek_gtp_version(layer.hdr.raw, layer.hdr_len) == 1);
const struct gtp1_hdr *gtp1 = (struct gtp1_hdr *)layer.hdr.raw;
const struct gtp1_hdr *gtp1 = (const struct gtp1_hdr *)layer.hdr.raw;
EXPECT_TRUE(gtp1_hdr_get_msg_len(gtp1) == 45);
break;
}
if (layer.proto == LAYER_PROTO_IPV4)
{
const struct ip *ip = (struct ip *)layer.hdr.raw;
const struct ip *ip = (const struct ip *)layer.hdr.raw;
EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 45);
EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0x4906);
break;
}
if (layer.proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp = (struct tcphdr *)layer.hdr.raw;
const struct tcphdr *tcp = (const struct tcphdr *)layer.hdr.raw;
EXPECT_TRUE(tcp_hdr_get_seq(tcp) == 1);
EXPECT_TRUE(tcp_hdr_get_ack(tcp) == 2);
EXPECT_TRUE(tcp_hdr_get_flags(tcp) == TH_ACK);
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp) == 20);
EXPECT_TRUE(tcp_hdr_get_checksum(tcp) == 0xcce5);
break;
}
}
for (uint16_t i = 0; i < new_pkt_len - 5; i++)
{
if ((18 <= i && i <= 19) || // skip IPv6 payload length
i == 20) // skip IPv6 hop limit
if (18 <= i && i <= 19) // skip IPv6 payload length
{
continue;
}
@@ -559,18 +558,221 @@ TEST(PACKET_BUILD_TCP, ETH_IP6_UDP_GTP_IP4_TCP)
continue;
}
if ((72 <= i && i <= 73) || // skip IPv4 total length
(74 <= i && i <= 75) || // skip IPv4 identification
i == 78 || // skip IPv4 TTL
(80 <= i && i <= 81)) // skip IPv4 checksum
{
continue;
}
if ((94 <= i && i <= 98) || // skip TCP seq
(99 <= i && i <= 103) || // skip TCP ack
i == 104 || // skip TCP data offset
i == 105 || // skip TCP flags
(106 <= i && i <= 107) || // skip TCP window
(108 <= i && i <= 109)) // skip TCP checksum
if ((94 <= i && i <= 98) || // skip TCP seq
(99 <= i && i <= 103) || // skip TCP ack
i == 104 || // skip TCP data offset
i == 105 || // skip TCP flags
(106 <= i && i <= 107)) // skip TCP checksum
{
continue;
}
// printf(("idx: %d, orig: %02x, new: %02x\n"), i, orig_pkt_data[i], new_pkt_data[i]);
EXPECT_TRUE(orig_pkt_data[i] == new_pkt_data[i]);
}
}
#endif
/******************************************************************************
* [Protocols in frame: eth:ethertype:ip:gre:ipv6:tcp]
******************************************************************************
*
* Frame 1: 102 bytes on wire (816 bits), 102 bytes captured (816 bits)
* Ethernet II, Src: a0:b1:c2:d3:e4:f5 (a0:b1:c2:d3:e4:f5), Dst: CIMSYS_33:44:55 (00:11:22:33:44:55)
* Destination: CIMSYS_33:44:55 (00:11:22:33:44:55)
* Address: CIMSYS_33:44:55 (00:11:22:33:44:55)
* .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
* .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
* Source: a0:b1:c2:d3:e4:f5 (a0:b1:c2:d3:e4:f5)
* Address: a0:b1:c2:d3:e4:f5 (a0:b1:c2:d3:e4:f5)
* .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
* .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
* Type: IPv4 (0x0800)
* Internet Protocol Version 4, Src: 10.0.0.1, Dst: 192.168.1.1
* 0100 .... = Version: 4
* .... 0101 = Header Length: 20 bytes (5)
* Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
* 0000 00.. = Differentiated Services Codepoint: Default (0)
* .... ..00 = Explicit Congestion Notification: Not ECN-Capable Transport (0)
* Total Length: 88
* Identification: 0x0001 (1)
* 000. .... = Flags: 0x0
* 0... .... = Reserved bit: Not set
* .0.. .... = Don't fragment: Not set
* ..0. .... = More fragments: Not set
* ...0 0000 0000 0000 = Fragment Offset: 0
* Time to Live: 64
* Protocol: Generic Routing Encapsulation (47)
* Header Checksum: 0xaecc [correct]
* [Header checksum status: Good]
* [Calculated Checksum: 0xaecc]
* Source Address: 10.0.0.1
* Destination Address: 192.168.1.1
* Generic Routing Encapsulation (IPv6)
* Flags and Version: 0x8000
* 1... .... .... .... = Checksum Bit: Yes
* .0.. .... .... .... = Routing Bit: No
* ..0. .... .... .... = Key Bit: No
* ...0 .... .... .... = Sequence Number Bit: No
* .... 0... .... .... = Strict Source Route Bit: No
* .... .000 .... .... = Recursion control: 0
* .... .... 0000 0... = Flags (Reserved): 0
* .... .... .... .000 = Version: GRE (0)
* Protocol Type: IPv6 (0x86dd)
* Checksum: 0x92e7 [correct]
* [Checksum Status: Good]
* Offset: 0
* Internet Protocol Version 6, Src: ::, Dst: 2001:db8::1
* 0110 .... = Version: 6
* .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
* .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
* .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
* .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
* Payload Length: 20
* Next Header: TCP (6)
* Hop Limit: 64
* Source Address: ::
* Destination Address: 2001:db8::1
* Transmission Control Protocol, Src Port: 12345, Dst Port: 80, Seq: 0, Len: 0
* Source Port: 12345
* Destination Port: 80
* [Stream index: 0]
* [Conversation completeness: Incomplete, SYN_SENT (1)]
* ..0. .... = RST: Absent
* ...0 .... = FIN: Absent
* .... 0... = Data: Absent
* .... .0.. = ACK: Absent
* .... ..0. = SYN-ACK: Absent
* .... ...1 = SYN: Present
* [Completeness Flags: ·····S]
* [TCP Segment Len: 0]
* Sequence Number: 0
* [Next Sequence Number: 1]
* Acknowledgment Number: 0
* Acknowledgment number (raw): 0
* 0101 .... = Header Length: 20 bytes (5)
* Flags: 0x002 (SYN)
* 000. .... .... = Reserved: Not set
* ...0 .... .... = Accurate ECN: Not set
* .... 0... .... = Congestion Window Reduced: Not set
* .... .0.. .... = ECN-Echo: Not set
* .... ..0. .... = Urgent: Not set
* .... ...0 .... = Acknowledgment: Not set
* .... .... 0... = Push: Not set
* .... .... .0.. = Reset: Not set
* .... .... ..1. = Syn: Set
* [Expert Info (Chat/Sequence): Connection establish request (SYN): server port 80]
* [Connection establish request (SYN): server port 80]
* [Severity level: Chat]
* [Group: Sequence]
* .... .... ...0 = Fin: Not set
* [TCP Flags: ··········S·]
* Window: 8192
* [Calculated window size: 8192]
* Checksum: 0x31a0 [correct]
* [Calculated Checksum: 0x31a0]
* [Checksum Status: Good]
* Urgent Pointer: 0
* [Timestamps]
* [Time since first frame in this TCP stream: 0.000000000 seconds]
* [Time since previous frame in this TCP stream: 0.000000000 seconds]
*/
unsigned char data4[] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x08, 0x00, 0x45, 0x00, 0x00, 0x58, 0x00, 0x01, 0x00, 0x00, 0x40, 0x2f, 0xae, 0xcc,
0x0a, 0x00, 0x00, 0x01, 0xc0, 0xa8, 0x01, 0x01, 0x80, 0x00, 0x86, 0xdd, 0x92, 0xe7, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x30, 0x39, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, 0x20, 0x00, 0x31, 0xa0, 0x00, 0x00};
/*
* craft_tcp_packet()
* -> ETH->IPv4->GRE->IPv6->TCP
* -> with TCP payload
* -> with GRE checksum
*/
#if 1
TEST(PACKET_CRAFT_TCP, ETH_IP4_GRE_IP6_TCP)
{
struct packet orig_pkt;
memset(&orig_pkt, 0, sizeof(orig_pkt));
packet_parse(&orig_pkt, (const char *)data4, sizeof(data4));
PRINT_GREEN("origin packet:");
packet_print(&orig_pkt);
struct packet *new_pkt = craft_tcp_packet(&orig_pkt, 1, 2, TH_ACK, NULL, 0, "Hello", 5);
EXPECT_TRUE(new_pkt != nullptr);
PRINT_GREEN("new packet:");
packet_print(new_pkt);
packet_dump_hex(new_pkt, STDOUT_FILENO);
packet_dump_pcap(new_pkt, "craft-eth-ipv4-gre-ipv6-tcp.pcap");
const char *orig_pkt_data = packet_get_raw_data(&orig_pkt);
uint16_t orig_pkt_len = packet_get_raw_len(&orig_pkt);
const char *new_pkt_data = packet_get_raw_data(new_pkt);
uint16_t new_pkt_len = packet_get_raw_len(new_pkt);
EXPECT_TRUE(orig_pkt_len ==
new_pkt_len - 5); // trim TCP payload
struct layer layer;
PACKET_FOREACH_LAYER_INORDER(new_pkt, layer)
{
if (layer.proto == LAYER_PROTO_IPV4)
{
const struct ip *ip = (const struct ip *)layer.hdr.raw;
EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 93);
EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0xaec7);
break;
}
if (layer.proto == LAYER_PROTO_GRE)
{
const struct gre0_hdr *gre = (const struct gre0_hdr *)layer.hdr.raw;
EXPECT_TRUE(gre0_hdr_get_version(gre) == 0);
EXPECT_TRUE(gre0_hdr_get_checksum(gre) == 0x92e7);
break;
}
if (layer.proto == LAYER_PROTO_IPV6)
{
const struct ip6_hdr *ip6 = (const struct ip6_hdr *)layer.hdr.raw;
EXPECT_TRUE(ip6_hdr_get_payload_len(ip6) == 25);
break;
}
if (layer.proto == LAYER_PROTO_TCP)
{
const struct tcphdr *tcp = (const struct tcphdr *)layer.hdr.raw;
EXPECT_TRUE(tcp_hdr_get_seq(tcp) == 1);
EXPECT_TRUE(tcp_hdr_get_ack(tcp) == 2);
EXPECT_TRUE(tcp_hdr_get_flags(tcp) == TH_ACK);
EXPECT_TRUE(tcp_hdr_get_hdr_len(tcp) == 20);
EXPECT_TRUE(tcp_hdr_get_checksum(tcp) == 0x0db8);
break;
}
}
for (uint16_t i = 0; i < new_pkt_len - 5; i++)
{
if ((16 <= i && i <= 17) || // skip IP total length
(24 <= i && i <= 25)) // skip IP checksum
{
continue;
}
if (38 <= i && i <= 39) // skip GRE checksum
{
continue;
}
if (47 <= i && i <= 48) // skip IPv6 payload length
{
continue;
}
if ((86 <= i && i <= 89) || // skip TCP seq
(90 <= i && i <= 93) || // skip TCP ack
i == 95 || // skip TCP flags
(98 <= i && i <= 99)) // skip TCP checksum
{
continue;
}