diff options
| author | luwenpeng <[email protected]> | 2024-09-13 16:08:07 +0800 |
|---|---|---|
| committer | luwenpeng <[email protected]> | 2024-09-13 18:07:40 +0800 |
| commit | 173a6ced619ebd93d7e52e455936b02c91d8e8b6 (patch) | |
| tree | 130674f20c0b86a041d72400526a1e5b51dd0bd7 /infra/packet_manager | |
| parent | 06c498409f0fef942e59143d1484e9679bd212d2 (diff) | |
refactor: rename the directory infra/packet_parser to infra/paket_manager
Diffstat (limited to 'infra/packet_manager')
33 files changed, 13114 insertions, 0 deletions
diff --git a/infra/packet_manager/CMakeLists.txt b/infra/packet_manager/CMakeLists.txt new file mode 100644 index 0000000..5a3949f --- /dev/null +++ b/infra/packet_manager/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(packet_manager + packet_utils.c + packet_parser.c + packet_builder.c + packet_filter.c + packet_dump.c + checksum.c) +target_include_directories(packet_manager PUBLIC ${CMAKE_CURRENT_LIST_DIR}) +target_include_directories(packet_manager PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash) +target_include_directories(packet_manager PUBLIC ${CMAKE_SOURCE_DIR}/deps/logger) +target_include_directories(packet_manager PUBLIC ${CMAKE_SOURCE_DIR}/include) +target_include_directories(packet_manager PUBLIC ${CMAKE_SOURCE_DIR}/infra) +target_link_libraries(packet_manager tuple logger dablooms) + +add_subdirectory(test)
\ No newline at end of file diff --git a/infra/packet_manager/checksum.c b/infra/packet_manager/checksum.c new file mode 100644 index 0000000..c7a8266 --- /dev/null +++ b/infra/packet_manager/checksum.c @@ -0,0 +1,104 @@ +#include "checksum.h" + +uint16_t checksum(const void *data, int len) +{ + uint16_t *ptr = (uint16_t *)data; + uint32_t sum = 0; + while (len > 1) + { + sum += *ptr++; + len -= 2; + } + if (len == 1) + { + sum += *(uint8_t *)ptr; + } + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + return (uint16_t)~sum; +} + +uint16_t checksum_v4(const void *l4_hdr_ptr, uint16_t l4_total_len, uint8_t l4_proto, struct in_addr *src_addr, struct in_addr *dst_addr) +{ + uint16_t *ip_src = (uint16_t *)src_addr; + uint16_t *ip_dst = (uint16_t *)dst_addr; + const uint16_t *buffer = (u_int16_t *)l4_hdr_ptr; + + uint32_t sum = 0; + size_t len = l4_total_len; + + while (len > 1) + { + sum += *buffer++; + if (sum & 0x80000000) + { + sum = (sum & 0xFFFF) + (sum >> 16); + } + len -= 2; + } + + if (len & 1) + { + sum += *((uint8_t *)buffer); + } + + sum += *(ip_src++); + sum += *ip_src; + sum += *(ip_dst++); + sum += *ip_dst; + sum += htons(l4_proto); + sum += htons(l4_total_len); + + while (sum >> 16) + { + sum = (sum & 0xFFFF) + (sum >> 16); + } + + return ((uint16_t)(~sum)); +} + +uint16_t checksum_v6(const void *l4_hdr_ptr, uint16_t l4_total_len, uint8_t l4_proto, struct in6_addr *src_addr, struct in6_addr *dst_addr) +{ + uint16_t *ip_src = (uint16_t *)src_addr; + uint16_t *ip_dst = (uint16_t *)dst_addr; + const uint16_t *buffer = (u_int16_t *)l4_hdr_ptr; + + uint32_t sum = 0; + size_t len = l4_total_len; + + while (len > 1) + { + sum += *buffer++; + if (sum & 0x80000000) + { + sum = (sum & 0xFFFF) + (sum >> 16); + } + len -= 2; + } + + if (len & 1) + { + sum += *((uint8_t *)buffer); + } + + for (int i = 0; i < 8; i++) + { + sum += *ip_src; + ip_src++; + } + + for (int i = 0; i < 8; i++) + { + sum += *ip_dst; + ip_dst++; + } + sum += htons(l4_proto); + sum += htons(l4_total_len); + + while (sum >> 16) + { + sum = (sum & 0xFFFF) + (sum >> 16); + } + + return ((uint16_t)(~sum)); +} diff --git a/infra/packet_manager/checksum.h b/infra/packet_manager/checksum.h new file mode 100644 index 0000000..3d762bb --- /dev/null +++ b/infra/packet_manager/checksum.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include <arpa/inet.h> + +uint16_t checksum(const void *data, int len); +uint16_t checksum_v4(const void *l4_hdr_ptr, uint16_t l4_total_len, uint8_t l4_proto, struct in_addr *src_addr, struct in_addr *dst_addr); +uint16_t checksum_v6(const void *l4_hdr_ptr, uint16_t l4_total_len, uint8_t l4_proto, struct in6_addr *src_addr, struct in6_addr *dst_addr); + +#ifdef __cplusplus +} +#endif diff --git a/infra/packet_manager/packet_builder.c b/infra/packet_manager/packet_builder.c new file mode 100644 index 0000000..fc95a81 --- /dev/null +++ b/infra/packet_manager/packet_builder.c @@ -0,0 +1,414 @@ +#include <time.h> + +#include "checksum.h" +#include "log_private.h" +#include "packet_helper.h" +#include "packet_parser.h" +#include "packet_private.h" + +#define PACKET_CRAFT_LOG_DEBUG(format, ...) STELLAR_LOG_DEBUG(__thread_local_logger, "packet craft", format, ##__VA_ARGS__) +#define PACKET_CRAFT_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet craft", format, ##__VA_ARGS__) + +struct fingerprint +{ + // TODO + uint16_t ip_id; + uint8_t ip_ttl; + uint16_t tcp_win; +}; + +static uint8_t append_fingerprint = 0; + +/****************************************************************************** + * Private API + ******************************************************************************/ + +static inline void calc_packet_fingerprint(struct fingerprint *finger) +{ + if (append_fingerprint) + { +#define RANGE(rand, start, end) (start + rand % (end - start + 1)) // [start, end] + struct timespec time; + clock_gettime(CLOCK_MONOTONIC_COARSE, &time); + uint64_t random = 0x013579ABCDEF ^ time.tv_nsec; + finger->ip_id = (uint16_t)(RANGE(random, 32767, 65535)); + finger->ip_ttl = (uint8_t)(RANGE(random, 48, 120)); + finger->tcp_win = (uint16_t)(RANGE(random, 1000, 1460)); + } + else + { + finger->ip_id = 0; + finger->ip_ttl = 0; + finger->tcp_win = 0; + } +} + +static void update_udp_hdr(struct udphdr *udp, int trim_len) +{ + uint16_t total = udp_hdr_get_total_len(udp); + udp_hdr_set_total_len(udp, total - trim_len); + udp_hdr_set_checksum(udp, 0); +} + +static void update_ip4_hdr(struct ip *ip, uint16_t ipid, uint8_t ttl, int trim_len) +{ + int hdr_len = ip4_hdr_get_hdr_len(ip); + uint16_t total = ip4_hdr_get_total_len(ip); + ip4_hdr_set_total_len(ip, total - trim_len); + if (ipid) + { + ip4_hdr_set_ipid(ip, ipid); + } + if (ttl) + { + ip4_hdr_set_ttl(ip, ttl); + } + ip->ip_sum = 0; + ip->ip_sum = checksum((const void *)ip, hdr_len); +} + +static void update_ip6_hdr(struct ip6_hdr *ip6, int trim_len) +{ + uint16_t len = ip6_hdr_get_payload_len(ip6); + ip6_hdr_set_payload_len(ip6, len - trim_len); +} + +static void update_gtp1_hdr(struct gtp1_hdr *gtp, int trim_len) +{ + uint16_t msg_len = gtp1_hdr_get_msg_len(gtp); + gtp1_hdr_set_msg_len(gtp, msg_len - trim_len); + if (gtp1_hdr_get_seq_flag(gtp) && gtp1_hdr_get_seq(gtp)) + { + PACKET_CRAFT_LOG_ERROR("build packets may be dropped by intermediate devices, the GTPv1 layer requires a sequence number"); + } +} + +static void update_gtp2_hdr(struct gtp2_hdr *gtp, int trim_len) +{ + uint16_t msg_len = gtp2_hdr_get_msg_len(gtp); + gtp2_hdr_set_msg_len(gtp, msg_len - trim_len); + if (gtp2_hdr_get_seq(gtp)) + { + PACKET_CRAFT_LOG_ERROR("build packets may be dropped by intermediate devices, the GTPv2 layer requires a sequence number"); + } +} + +static void update_gre1_hdr(struct gre1_hdr *gre, int trim_len) +{ + uint16_t payload_len = gre1_hdr_get_payload_length(gre); + gre1_hdr_set_payload_length(gre, payload_len - trim_len); +} + +// L2 -- data link layer +// LAYER_PROTO_ETHER: // SKIP +// LAYER_PROTO_PWETH: // SKIP +// LAYER_PROTO_PPP: // SKIP +// LAYER_PROTO_L2TP: // TODO ??? + +// L2 -- tunnel +// LAYER_PROTO_VLAN: // SKIP +// LAYER_PROTO_PPPOE: // TODO ???? +// LAYER_PROTO_MPLS: // SKIP + +// L3 -- network layer +// LAYER_PROTO_IPV4: // DONE +// LAYER_PROTO_IPV6: // DONE +// LAYER_PROTO_IPAH: // TODO ???? + +// L3 -- tunnel +// LAYER_PROTO_GRE: // DONE + +// L4 -- transport layer +// LAYER_PROTO_UDP: // DONE +// LAYER_PROTO_TCP: // DONE +// LAYER_PROTO_ICMP: +// LAYER_PROTO_ICMP6: + +// L4 -- tunnel +// LAYER_PROTO_VXLAN: // SKIP +// LAYER_PROTO_GTP_U: // DONE +// LAYER_PROTO_GTP_C: +static void calculate_length_and_checksum(const struct packet *origin_pkt, int layer_count, char *new_pkt_data, uint16_t new_pkt_len, int trim_len) +{ + uint8_t version = 0; + uint16_t sum = 0; + char *curr_hdr_ptr = NULL; + char *last_hdr_ptr = NULL; + struct tcphdr *tcp = NULL; + struct udphdr *udp = NULL; + struct ip *ip4 = NULL; + struct ip6_hdr *ip6 = NULL; + struct gtp1_hdr *gtp1 = NULL; + struct gtp2_hdr *gtp2 = NULL; + struct gre0_hdr *gre0 = NULL; + struct gre1_hdr *gre1 = NULL; + struct layer_private *curr_layer = NULL; + struct layer_private *last_layer = NULL; + struct fingerprint finger = {}; + calc_packet_fingerprint(&finger); + for (int i = layer_count - 1; i >= 0; i--) + { + curr_layer = (struct layer_private *)packet_get_layer(origin_pkt, i); + last_layer = (struct layer_private *)packet_get_layer(origin_pkt, i + 1); + curr_hdr_ptr = new_pkt_data + curr_layer->hdr_offset; + last_hdr_ptr = last_layer ? new_pkt_data + last_layer->hdr_offset : NULL; + switch (curr_layer->proto) + { + case LAYER_PROTO_TCP: + tcp = (struct tcphdr *)curr_hdr_ptr; + if (finger.tcp_win) + { + tcp_hdr_set_window(tcp, finger.tcp_win); + } + tcp_hdr_set_checksum(tcp, 0); + break; + case LAYER_PROTO_UDP: + udp = (struct udphdr *)curr_hdr_ptr; + update_udp_hdr(udp, trim_len); + break; + case LAYER_PROTO_IPV4: + ip4 = (struct ip *)curr_hdr_ptr; + if (last_layer && last_layer->proto == LAYER_PROTO_TCP) + { + tcp = (struct tcphdr *)last_hdr_ptr; + tcp->th_sum = checksum_v4(tcp, new_pkt_len - last_layer->hdr_offset, IPPROTO_TCP, &ip4->ip_src, &ip4->ip_dst); + } + if (last_layer && last_layer->proto == LAYER_PROTO_UDP) + { + udp = (struct udphdr *)last_hdr_ptr; + udp->uh_sum = checksum_v4(udp, new_pkt_len - last_layer->hdr_offset, IPPROTO_UDP, &ip4->ip_src, &ip4->ip_dst); + } + update_ip4_hdr(ip4, finger.ip_id, finger.ip_ttl, trim_len); + break; + case LAYER_PROTO_IPV6: + ip6 = (struct ip6_hdr *)curr_hdr_ptr; + if (last_layer && last_layer->proto == LAYER_PROTO_TCP) + { + tcp = (struct tcphdr *)last_hdr_ptr; + tcp->th_sum = checksum_v6(tcp, new_pkt_len - last_layer->hdr_offset, IPPROTO_TCP, &ip6->ip6_src, &ip6->ip6_dst); + } + if (last_layer && last_layer->proto == LAYER_PROTO_UDP) + { + udp = (struct udphdr *)last_hdr_ptr; + udp->uh_sum = checksum_v6(udp, new_pkt_len - last_layer->hdr_offset, IPPROTO_UDP, &ip6->ip6_src, &ip6->ip6_dst); + } + update_ip6_hdr(ip6, trim_len); + break; + case LAYER_PROTO_GTP_C: /* fall through */ + case LAYER_PROTO_GTP_U: + version = peek_gtp_version(curr_hdr_ptr, curr_layer->hdr_len); + if (version == 1) + { + gtp1 = (struct gtp1_hdr *)curr_hdr_ptr; + update_gtp1_hdr(gtp1, trim_len); + } + if (version == 2) + { + gtp2 = (struct gtp2_hdr *)curr_hdr_ptr; + update_gtp2_hdr(gtp2, trim_len); + } + break; + case LAYER_PROTO_GRE: + version = peek_gre_version(curr_hdr_ptr, curr_layer->hdr_len); + if (version == 0) + { + gre0 = (struct gre0_hdr *)curr_hdr_ptr; + if (gre0_hdr_get_checksum_flag(gre0)) + { + gre0_hdr_set_checksum(gre0, ntohs(0)); + sum = checksum((const void *)curr_hdr_ptr, new_pkt_len - curr_layer->hdr_offset); + gre0_hdr_set_checksum(gre0, ntohs(sum)); + } + } + if (version == 1) + { + gre1 = (struct gre1_hdr *)curr_hdr_ptr; + update_gre1_hdr(gre1, trim_len); + } + break; + default: + break; + } + } +} + +/****************************************************************************** + * Public API + ******************************************************************************/ + +void append_fingerprint_to_build_packet() +{ + append_fingerprint = 1; +} + +/* + * tcp_seq: the sequence number of the new TCP packet (in host byte order) + * tcp_ack: the acknowledgment number of the new TCP packet (in host byte order) + * tcp_options_len: the length of the options (must be a multiple of 4) + */ +struct packet *packet_build_tcp(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, + const char *tcp_options, uint16_t tcp_options_len, + const char *tcp_payload, uint16_t tcp_payload_len) +{ + // check arguments + if (origin_pkt == NULL || + (tcp_options == NULL && tcp_options_len != 0) || (tcp_options != NULL && tcp_options_len == 0) || + (tcp_payload == NULL && tcp_payload_len != 0) || (tcp_payload != NULL && tcp_payload_len == 0) || + (tcp_options_len && tcp_options_len % 4 != 0)) + { + PACKET_CRAFT_LOG_ERROR("craft TCP packet failed, invalid arguments"); + return NULL; + } + + // check the innermost layer of the original packet + int layer_count = packet_get_layer_count(origin_pkt); + const struct layer_private *tcp_layer = packet_get_layer(origin_pkt, layer_count - 1); + if (tcp_layer == NULL || tcp_layer->proto != LAYER_PROTO_TCP) + { + PACKET_CRAFT_LOG_ERROR("craft TCP packet failed, the innermost layer of the original packet is not TCP"); + return NULL; + } + + // calculate the new packet length + int trim_len = tcp_layer->hdr_len + tcp_layer->pld_len - tcp_options_len - tcp_payload_len - sizeof(struct tcphdr); + uint16_t new_pkt_len = origin_pkt->data_len - origin_pkt->trim_len - trim_len; + struct packet *new_pkt = packet_new(new_pkt_len); + if (new_pkt == NULL) + { + PACKET_CRAFT_LOG_ERROR("craft TCP packet failed, no space to allocate new packet"); + return NULL; + } + + // copy the data to the new packet + char *new_pkt_data = (char *)packet_get_raw_data(new_pkt); + memcpy(new_pkt_data, packet_get_raw_data(origin_pkt), tcp_layer->hdr_offset + sizeof(struct tcphdr)); + if (tcp_options_len) + { + memcpy(new_pkt_data + tcp_layer->hdr_offset + sizeof(struct tcphdr), tcp_options, tcp_options_len); + } + memcpy(new_pkt_data + tcp_layer->hdr_offset + sizeof(struct tcphdr) + tcp_options_len, tcp_payload, tcp_payload_len); + struct tcphdr *hdr = (struct tcphdr *)(new_pkt_data + tcp_layer->hdr_offset); + tcp_hdr_set_seq(hdr, tcp_seq); + tcp_hdr_set_ack(hdr, tcp_ack); + tcp_hdr_set_flags(hdr, tcp_flags); + tcp_hdr_set_hdr_len(hdr, sizeof(struct tcphdr) + tcp_options_len); + + calculate_length_and_checksum(origin_pkt, layer_count, new_pkt_data, new_pkt_len, trim_len); + + packet_parse(new_pkt, new_pkt_data, new_pkt_len); + memcpy(&new_pkt->meta, &origin_pkt->meta, sizeof(struct metadata)); + new_pkt->meta.origin_ctx = NULL; + + return new_pkt; +} + +struct packet *packet_build_udp(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len) +{ + // check arguments + if (origin_pkt == NULL || (udp_payload == NULL && udp_payload_len != 0) || (udp_payload != NULL && udp_payload_len == 0)) + { + PACKET_CRAFT_LOG_ERROR("craft UDP packet failed, invalid arguments"); + return NULL; + } + + // check the innermost layer of the original packet + int layer_count = packet_get_layer_count(origin_pkt); + const struct layer_private *udp_layer = packet_get_layer(origin_pkt, layer_count - 1); + if (udp_layer == NULL || udp_layer->proto != LAYER_PROTO_UDP) + { + PACKET_CRAFT_LOG_ERROR("craft UDP packet failed, the innermost layer of the original packet is not UDP"); + return NULL; + } + + // calculate the new packet length + int trim_len = udp_layer->hdr_len + udp_layer->pld_len - udp_payload_len - sizeof(struct udphdr); + uint16_t new_pkt_len = origin_pkt->data_len - origin_pkt->trim_len - trim_len; + struct packet *new_pkt = packet_new(new_pkt_len); + if (new_pkt == NULL) + { + PACKET_CRAFT_LOG_ERROR("craft UDP packet failed, no space to allocate new packet"); + return NULL; + } + + // copy the data to the new packet + char *new_pkt_data = (char *)packet_get_raw_data(new_pkt); + memcpy(new_pkt_data, packet_get_raw_data(origin_pkt), udp_layer->hdr_offset + sizeof(struct udphdr)); + memcpy(new_pkt_data + udp_layer->hdr_offset + sizeof(struct udphdr), udp_payload, udp_payload_len); + + calculate_length_and_checksum(origin_pkt, layer_count, new_pkt_data, new_pkt_len, trim_len); + + packet_parse(new_pkt, new_pkt_data, new_pkt_len); + memcpy(&new_pkt->meta, &origin_pkt->meta, sizeof(struct metadata)); + new_pkt->meta.origin_ctx = NULL; + + return new_pkt; +} + +struct packet *packet_build_l3(const struct packet *origin_pkt, uint8_t ip_proto, const char *l3_payload, uint16_t l3_payload_len) +{ + if (origin_pkt == NULL || (l3_payload == NULL && l3_payload_len != 0) || (l3_payload != NULL && l3_payload_len == 0)) + { + PACKET_CRAFT_LOG_ERROR("craft L3 packet failed, invalid arguments"); + return NULL; + } + + int i = 0; + int layers = packet_get_layer_count(origin_pkt); + const struct layer_private *l3_layer = NULL; + for (i = layers - 1; i >= 0; i--) + { + l3_layer = packet_get_layer(origin_pkt, i); + if (l3_layer->proto == LAYER_PROTO_IPV4 || l3_layer->proto == LAYER_PROTO_IPV6) + { + break; + } + else + { + l3_layer = NULL; + } + } + if (l3_layer == NULL) + { + PACKET_CRAFT_LOG_ERROR("craft L3 packet failed, the original packet does not contain an IP layer"); + return NULL; + } + + // calculate the new packet length + // trim IPv4 options + // trim IPv6 extension headers + int l3_hdr_len = l3_layer->proto == LAYER_PROTO_IPV4 ? sizeof(struct ip) : sizeof(struct ip6_hdr); + int trim_len = l3_layer->hdr_len + l3_layer->pld_len - l3_payload_len - l3_hdr_len; + uint16_t new_pkt_len = origin_pkt->data_len - origin_pkt->trim_len - trim_len; + struct packet *new_pkt = packet_new(new_pkt_len); + if (new_pkt == NULL) + { + PACKET_CRAFT_LOG_ERROR("craft L3 packet failed, no space to allocate new packet"); + return NULL; + } + + // copy the data to the new packet + char *new_pkt_data = (char *)packet_get_raw_data(new_pkt); + memcpy(new_pkt_data, packet_get_raw_data(origin_pkt), l3_layer->hdr_offset + l3_hdr_len); + if (l3_payload) + { + memcpy(new_pkt_data + l3_layer->hdr_offset + l3_hdr_len, l3_payload, l3_payload_len); + } + // update ip_proto + if (l3_layer->proto == LAYER_PROTO_IPV4) + { + struct ip *ip4 = (struct ip *)(new_pkt_data + l3_layer->hdr_offset); + ip4_hdr_set_protocol(ip4, ip_proto); + } + else + { + struct ip6_hdr *ip6 = (struct ip6_hdr *)(new_pkt_data + l3_layer->hdr_offset); + ip6_hdr_set_next_header(ip6, ip_proto); + } + calculate_length_and_checksum(origin_pkt, i + 1, new_pkt_data, new_pkt_len, trim_len); + + packet_parse(new_pkt, new_pkt_data, new_pkt_len); + memcpy(&new_pkt->meta, &origin_pkt->meta, sizeof(struct metadata)); + new_pkt->meta.origin_ctx = NULL; + + return new_pkt; +}
\ No newline at end of file diff --git a/infra/packet_manager/packet_dump.c b/infra/packet_manager/packet_dump.c new file mode 100644 index 0000000..8f12d2d --- /dev/null +++ b/infra/packet_manager/packet_dump.c @@ -0,0 +1,175 @@ +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <sys/time.h> + +#include "utils.h" +#include "log_private.h" +#include "packet_dump.h" +#include "packet_parser.h" +#include "packet_helper.h" +#include "packet_private.h" + +#define PACKET_DUMP_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet dump", format, ##__VA_ARGS__) + +struct pcap_pkt_hdr +{ + unsigned int tv_sec; // time stamp + unsigned int tv_usec; // time stamp + unsigned int caplen; // length of portion present + unsigned int len; // length this packet (off wire) +}; + +struct pcap_file_hdr +{ + unsigned int magic; + unsigned short version_major; + unsigned short version_minor; + unsigned int thiszone; // gmt to local correction + unsigned int sigfigs; // accuracy of timestamps + unsigned int snaplen; // max length saved portion of each pkt + unsigned int linktype; // data link type (LINKTYPE_*) +}; + +// return 0: success +// return -1: failed +int packet_dump_pcap(const struct packet *pkt, const char *file) +{ + const char *data = packet_get_raw_data(pkt); + uint16_t len = packet_get_raw_len(pkt); + + struct pcap_pkt_hdr pkt_hdr = {}; + struct pcap_file_hdr file_hdr = { + .magic = 0xA1B2C3D4, + .version_major = 0x0002, + .version_minor = 0x0004, + .thiszone = 0, + .sigfigs = 0, + .snaplen = 0xFFFF, + .linktype = 1}; + + if (file == NULL || data == NULL || len == 0) + { + PACKET_DUMP_LOG_ERROR("invalid parameter, file: %p, data: %p, len: %d", file, data, len); + return -1; + } + + FILE *fp = fopen(file, "w+"); + if (fp == NULL) + { + PACKET_DUMP_LOG_ERROR("fopen %s failed, %s", file, strerror(errno)); + return -1; + } + + struct timeval ts = {}; + gettimeofday(&ts, NULL); + + pkt_hdr.tv_sec = ts.tv_sec; + pkt_hdr.tv_usec = ts.tv_usec; + pkt_hdr.caplen = len; + pkt_hdr.len = len; + + fwrite(&file_hdr, sizeof(struct pcap_file_hdr), 1, fp); + fwrite(&pkt_hdr, sizeof(struct pcap_pkt_hdr), 1, fp); + fwrite(data, 1, len, fp); + fflush(fp); + fclose(fp); + + return 0; +} + +void packet_dump_hex(const struct packet *pkt, int fd) +{ + uint16_t len = packet_get_raw_len(pkt); + const char *data = packet_get_raw_data(pkt); + + hexdump_to_fd(fd, 0, data, len); +} + +int packet_dump_str(const struct packet *pkt, char *buff, int size) +{ + if (pkt == NULL) + { + return 0; + } + + int old = 0; + int used = 0; + memset(buff, 0, size); + used += snprintf(buff + used, size - used, "packet: %p, data_ptr: %p, data_len: %u, trim_len: %u, layers_used: %d, layers_size: %d\n", + pkt, pkt->data_ptr, pkt->data_len, pkt->trim_len, + pkt->layers_used, pkt->layers_size); + for (uint8_t i = 0; i < pkt->layers_used; i++) + { + const struct layer_private *layer = &pkt->layers[i]; + used += snprintf(buff + used, size - used, "layer[%u]: %p, proto: %s, header: {offset: %u, ptr: %p, len: %u}, payload: {ptr: %p, len: %u}\n", + i, layer, layer_proto_to_str(layer->proto), layer->hdr_offset, + layer->hdr_ptr, layer->hdr_len, layer->pld_ptr, layer->pld_len); + old = used; + switch (layer->proto) + { + case LAYER_PROTO_ETHER: + used += eth_hdr_to_str((const struct ethhdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_PWETH: + break; + case LAYER_PROTO_PPP: + break; + case LAYER_PROTO_L2TP: + used += l2tp_hdr_to_str((const struct l2tp_hdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_VLAN: + used += vlan_hdr_to_str((const struct vlan_hdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_PPPOE: + break; + case LAYER_PROTO_MPLS: + used += mpls_label_to_str((const struct mpls_label *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_IPV4: + used += ip4_hdr_to_str((const struct ip *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_IPV6: + used += ip6_hdr_to_str((const struct ip6_hdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_IPAH: + break; + case LAYER_PROTO_GRE: + used += gre_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buff + used, size - used); + break; + case LAYER_PROTO_UDP: + used += udp_hdr_to_str((const struct udphdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_TCP: + used += tcp_hdr_to_str((const struct tcphdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_ICMP: + break; + case LAYER_PROTO_ICMP6: + break; + case LAYER_PROTO_VXLAN: + used += vxlan_hdr_to_str((const struct vxlan_hdr *)layer->hdr_ptr, buff + used, size - used); + break; + case LAYER_PROTO_GTP_C: + case LAYER_PROTO_GTP_U: + used += gtp_hdr_to_str(layer->hdr_ptr, layer->hdr_len, buff + used, size - used); + break; + default: + break; + } + if (old != used) + { + used += snprintf(buff + used, size - used, "\n"); + } + } + + return used; +} + +void packet_print(const struct packet *pkt) +{ + char buff[4096] = {}; + packet_dump_str(pkt, buff, sizeof(buff)); + printf("%s\n", buff); +}
\ No newline at end of file diff --git a/infra/packet_manager/packet_dump.h b/infra/packet_manager/packet_dump.h new file mode 100644 index 0000000..75af2c6 --- /dev/null +++ b/infra/packet_manager/packet_dump.h @@ -0,0 +1,20 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct packet; + +// return 0: success +// return -1: failed +int packet_dump_pcap(const struct packet *pkt, const char *file); +void packet_dump_hex(const struct packet *pkt, int fd); +// return number of bytes written +int packet_dump_str(const struct packet *pkt, char *buff, int size); +void packet_print(const struct packet *pkt); + +#ifdef __cplusplus +} +#endif diff --git a/infra/packet_manager/packet_filter.c b/infra/packet_manager/packet_filter.c new file mode 100644 index 0000000..6167dbc --- /dev/null +++ b/infra/packet_manager/packet_filter.c @@ -0,0 +1,131 @@ +#include "dablooms.h" +#include "packet_filter.h" +#include "packet_private.h" + +struct packet_key +{ + // TCP or UDP + uint32_t seq; // network order + uint32_t ack; // network order + uint16_t src_port; // network order + uint16_t dst_port; // network order + uint16_t l4_checksum; // network order + + // IPv4 + uint16_t ip_id; // network order + uint32_t src_addr; // network order + uint32_t dst_addr; // network order +} __attribute__((__packed__)); + +struct packet_filter +{ + struct expiry_dablooms_handle *dablooms; +}; + +/****************************************************************************** + * Private API + ******************************************************************************/ + +// return 0: success +// reutrn -1: error +static inline int packet_key_get(const struct packet *packet, struct packet_key *key) +{ + const struct layer_private *ip_layer = packet_get_innermost_layer(packet, LAYER_PROTO_IPV4); + const struct layer_private *tcp_layer = packet_get_innermost_layer(packet, LAYER_PROTO_TCP); + const struct layer_private *udp_layer = packet_get_innermost_layer(packet, LAYER_PROTO_UDP); + if (ip_layer == NULL || (tcp_layer == NULL && udp_layer == NULL)) + { + return -1; + } + + memset(key, 0, sizeof(struct packet_key)); + + const struct ip *iphdr = (const struct ip *)ip_layer->hdr_ptr; + key->ip_id = iphdr->ip_id; + key->src_addr = iphdr->ip_src.s_addr; + key->dst_addr = iphdr->ip_dst.s_addr; + + if (tcp_layer) + { + const struct tcphdr *tcphdr = (const struct tcphdr *)tcp_layer->hdr_ptr; + key->seq = tcphdr->th_seq; + key->ack = tcphdr->th_ack; + key->src_port = tcphdr->th_sport; + key->dst_port = tcphdr->th_dport; + key->l4_checksum = tcphdr->th_sum; + } + else + { + const struct udphdr *udphdr = (const struct udphdr *)udp_layer->hdr_ptr; + key->src_port = udphdr->uh_sport; + key->dst_port = udphdr->uh_dport; + key->l4_checksum = udphdr->uh_sum; + } + + return 0; +} + +/****************************************************************************** + * Public API + ******************************************************************************/ + +struct packet_filter *packet_filter_new(uint32_t capacity, uint32_t timeout, double error_rate, uint64_t now) +{ + struct packet_filter *filter = (struct packet_filter *)calloc(1, sizeof(struct packet_filter)); + if (filter == NULL) + { + return NULL; + } + + filter->dablooms = expiry_dablooms_new(capacity, error_rate, now, timeout); + if (filter->dablooms == NULL) + { + free(filter); + return NULL; + } + + return filter; +} + +void packet_filter_free(struct packet_filter *filter) +{ + if (filter) + { + if (filter->dablooms) + { + expiry_dablooms_free(filter->dablooms); + filter->dablooms = NULL; + } + free(filter); + filter = NULL; + } +} + +// return 1: found +// reutrn 0: no found +int packet_filter_lookup(struct packet_filter *filter, const struct packet *packet, uint64_t now) +{ + struct packet_key key; + if (packet_key_get(packet, &key) == -1) + { + return 0; + } + + if (expiry_dablooms_search(filter->dablooms, (const char *)&key, sizeof(struct packet_key), now) == 1) + { + return 1; + } + + return 0; +} + +void packet_filter_add(struct packet_filter *filter, const struct packet *packet, uint64_t now) +{ + struct packet_key key; + if (packet_key_get(packet, &key) == -1) + { + return; + } + + expiry_dablooms_add(filter->dablooms, (const char *)&key, sizeof(struct packet_key), now); +} diff --git a/infra/packet_manager/packet_filter.h b/infra/packet_manager/packet_filter.h new file mode 100644 index 0000000..9a30f62 --- /dev/null +++ b/infra/packet_manager/packet_filter.h @@ -0,0 +1,22 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct packet; + +// Duplicated Packet Filter for IPv4 Packet +struct packet_filter; +struct packet_filter *packet_filter_new(uint32_t capacity, uint32_t timeout, double error_rate, uint64_t now); +void packet_filter_free(struct packet_filter *filter); + +// return 1: found +// reutrn 0: no found +int packet_filter_lookup(struct packet_filter *filter, const struct packet *pkt, uint64_t now); +void packet_filter_add(struct packet_filter *filter, const struct packet *pkt, uint64_t now); + +#ifdef __cplusplus +} +#endif diff --git a/infra/packet_manager/packet_helper.h b/infra/packet_manager/packet_helper.h new file mode 100644 index 0000000..4782fb9 --- /dev/null +++ b/infra/packet_manager/packet_helper.h @@ -0,0 +1,2871 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "utils.h" +#include <stdio.h> +#include <string.h> +#include <stdbool.h> +#include <arpa/inet.h> +#include <linux/if_ether.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> +#include <linux/mpls.h> +#define __FAVOR_BSD 1 +#include <netinet/tcp.h> +#include <netinet/udp.h> + +/****************************************************************************** + * ETH + ******************************************************************************/ + +static inline int eth_hdr_get_dest(const struct ethhdr *hdr, char *buff, int size) +{ + return snprintf(buff, size, "%02x:%02x:%02x:%02x:%02x:%02x", + hdr->h_dest[0], hdr->h_dest[1], hdr->h_dest[2], + hdr->h_dest[3], hdr->h_dest[4], hdr->h_dest[5]); +} + +static inline int eth_hdr_get_source(const struct ethhdr *hdr, char *buff, int size) +{ + return snprintf(buff, size, "%02x:%02x:%02x:%02x:%02x:%02x", + hdr->h_source[0], hdr->h_source[1], hdr->h_source[2], + hdr->h_source[3], hdr->h_source[4], hdr->h_source[5]); +} + +static inline uint16_t eth_hdr_get_proto(const struct ethhdr *hdr) +{ + return ntohs(hdr->h_proto); +} + +static inline void eth_hdr_set_dest(struct ethhdr *hdr, const char *dest) +{ + sscanf(dest, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &hdr->h_dest[0], &hdr->h_dest[1], &hdr->h_dest[2], + &hdr->h_dest[3], &hdr->h_dest[4], &hdr->h_dest[5]); +} + +static inline void eth_hdr_set_source(struct ethhdr *hdr, const char *source) +{ + sscanf(source, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &hdr->h_source[0], &hdr->h_source[1], &hdr->h_source[2], + &hdr->h_source[3], &hdr->h_source[4], &hdr->h_source[5]); +} + +static inline void eth_hdr_set_proto(struct ethhdr *hdr, uint16_t proto) +{ + hdr->h_proto = htons(proto); +} + +// /usr/include/linux/if_ether.h +static inline int is_eth_proto(uint16_t proto) +{ + switch (proto) + { + case ETH_P_LOOP: + case ETH_P_PUP: + case ETH_P_PUPAT: + case ETH_P_IP: + case ETH_P_X25: + case ETH_P_ARP: + case ETH_P_BPQ: + case ETH_P_IEEEPUP: + case ETH_P_IEEEPUPAT: + case ETH_P_DEC: + case ETH_P_DNA_DL: + case ETH_P_DNA_RC: + case ETH_P_DNA_RT: + case ETH_P_LAT: + case ETH_P_DIAG: + case ETH_P_CUST: + case ETH_P_SCA: + case ETH_P_TEB: + case ETH_P_RARP: + case ETH_P_ATALK: + case ETH_P_AARP: + case ETH_P_8021Q: + case ETH_P_8021AD: + case ETH_P_IPX: + case ETH_P_IPV6: + case ETH_P_PAUSE: + case ETH_P_SLOW: + case ETH_P_WCCP: + case ETH_P_PPP_DISC: + case ETH_P_PPP_SES: + case ETH_P_MPLS_UC: + case ETH_P_MPLS_MC: + case ETH_P_ATMMPOA: + case ETH_P_ATMFATE: + case ETH_P_PAE: + case ETH_P_AOE: + case ETH_P_TIPC: + case ETH_P_1588: + case ETH_P_FCOE: + case ETH_P_FIP: + case ETH_P_EDSA: + case ETH_P_802_3: + case ETH_P_AX25: + case ETH_P_ALL: + case ETH_P_802_2: + case ETH_P_SNAP: + case ETH_P_DDCMP: + case ETH_P_WAN_PPP: + case ETH_P_PPP_MP: + case ETH_P_LOCALTALK: + case ETH_P_CAN: + case ETH_P_PPPTALK: + case ETH_P_TR_802_2: + case ETH_P_MOBITEX: + case ETH_P_CONTROL: + case ETH_P_IRDA: + case ETH_P_ECONET: + case ETH_P_HDLC: + case ETH_P_ARCNET: + case ETH_P_DSA: + case ETH_P_TRAILER: + case ETH_P_PHONET: + case ETH_P_IEEE802154: + case 0x880B: // PPP:Point-to-Point Protoco + return 1; + default: + return 0; + } +} + +static inline const char *eth_proto_to_str(uint16_t proto) +{ + switch (proto) + { + case ETH_P_LOOP: + return "ETH_P_LOOP"; + case ETH_P_PUP: + return "ETH_P_PUP"; + case ETH_P_PUPAT: + return "ETH_P_PUPAT"; + case ETH_P_IP: + return "ETH_P_IP"; + case ETH_P_X25: + return "ETH_P_X25"; + case ETH_P_ARP: + return "ETH_P_ARP"; + case ETH_P_BPQ: + return "ETH_P_BPQ"; + case ETH_P_IEEEPUP: + return "ETH_P_IEEEPUP"; + case ETH_P_IEEEPUPAT: + return "ETH_P_IEEEPUPAT"; + case ETH_P_DEC: + return "ETH_P_DEC"; + case ETH_P_DNA_DL: + return "ETH_P_DNA_DL"; + case ETH_P_DNA_RC: + return "ETH_P_DNA_RC"; + case ETH_P_DNA_RT: + return "ETH_P_DNA_RT"; + case ETH_P_LAT: + return "ETH_P_LAT"; + case ETH_P_DIAG: + return "ETH_P_DIAG"; + case ETH_P_CUST: + return "ETH_P_CUST"; + case ETH_P_SCA: + return "ETH_P_SCA"; + case ETH_P_TEB: + return "ETH_P_TEB"; + case ETH_P_RARP: + return "ETH_P_RARP"; + case ETH_P_ATALK: + return "ETH_P_ATALK"; + case ETH_P_AARP: + return "ETH_P_AARP"; + case ETH_P_8021Q: + return "ETH_P_8021Q"; + case ETH_P_8021AD: + return "ETH_P_8021AD"; + case ETH_P_IPX: + return "ETH_P_IPX"; + case ETH_P_IPV6: + return "ETH_P_IPV6"; + case ETH_P_PAUSE: + return "ETH_P_PAUSE"; + case ETH_P_SLOW: + return "ETH_P_SLOW"; + case ETH_P_WCCP: + return "ETH_P_WCCP"; + case ETH_P_PPP_DISC: + return "ETH_P_PPP_DISC"; + case ETH_P_PPP_SES: + return "ETH_P_PPP_SES"; + case ETH_P_MPLS_UC: + return "ETH_P_MPLS_UC"; + case ETH_P_MPLS_MC: + return "ETH_P_MPLS_MC"; + case ETH_P_ATMMPOA: + return "ETH_P_ATMMPOA"; + case ETH_P_ATMFATE: + return "ETH_P_ATMFATE"; + case ETH_P_PAE: + return "ETH_P_PAE"; + case ETH_P_AOE: + return "ETH_P_AOE"; + case ETH_P_TIPC: + return "ETH_P_TIPC"; + case ETH_P_1588: + return "ETH_P_1588"; + case ETH_P_FCOE: + return "ETH_P_FCOE"; + case ETH_P_FIP: + return "ETH_P_FIP"; + case ETH_P_EDSA: + return "ETH_P_EDSA"; + case ETH_P_802_3: + return "ETH_P_802_3"; + case ETH_P_AX25: + return "ETH_P_AX25"; + case ETH_P_ALL: + return "ETH_P_ALL"; + case ETH_P_802_2: + return "ETH_P_802_2"; + case ETH_P_SNAP: + return "ETH_P_SNAP"; + case ETH_P_DDCMP: + return "ETH_P_DDCMP"; + case ETH_P_WAN_PPP: + return "ETH_P_WAN_PPP"; + case ETH_P_PPP_MP: + return "ETH_P_PPP_MP"; + case ETH_P_LOCALTALK: + return "ETH_P_LOCALTALK"; + case ETH_P_CAN: + return "ETH_P_CAN"; + case ETH_P_PPPTALK: + return "ETH_P_PPPTALK"; + case ETH_P_TR_802_2: + return "ETH_P_TR_802_2"; + case ETH_P_MOBITEX: + return "ETH_P_MOBITEX"; + case ETH_P_CONTROL: + return "ETH_P_CONTROL"; + case ETH_P_IRDA: + return "ETH_P_IRDA"; + case ETH_P_ECONET: + return "ETH_P_ECONET"; + case ETH_P_HDLC: + return "ETH_P_HDLC"; + case ETH_P_ARCNET: + return "ETH_P_ARCNET"; + case ETH_P_DSA: + return "ETH_P_DSA"; + case ETH_P_TRAILER: + return "ETH_P_TRAILER"; + case ETH_P_PHONET: + return "ETH_P_PHONET"; + case ETH_P_IEEE802154: + return "ETH_P_IEEE802154"; + case 0x880B: + return "ETH_P_PPP"; + default: + return "ETH_P_UNKNOWN"; + } +} + +static inline int eth_hdr_to_str(const struct ethhdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + char dest[18] = {0}; + char source[18] = {0}; + uint16_t proto = eth_hdr_get_proto(hdr); + eth_hdr_get_dest(hdr, dest, sizeof(dest)); + eth_hdr_get_source(hdr, source, sizeof(source)); + return snprintf(buf, size, "ETH: source=%s dest=%s proto=%s", + source, dest, eth_proto_to_str(proto)); +} + +/****************************************************************************** + * GREv0 + ******************************************************************************/ + +/* + * GRE Header Format (Version 0) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |C|R|K|S|s|Recur| Flags | Ver | Protocol Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Checksum (optional) | Offset (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Key (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number (optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Routing (optional) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Address Family | SRE Offset | SRE Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Routing Information ... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://datatracker.ietf.org/doc/html/rfc1701 + * https://datatracker.ietf.org/doc/html/rfc2890 + */ + +struct gre0_hdr +{ + uint16_t flags; + uint16_t protocol; +}; + +struct sre +{ + uint16_t family; + uint8_t offset; + uint8_t length; +}; + +#define GRE0_FLAG_CHECKSUM 0x8000 +#define GRE0_FLAG_ROUTING 0x4000 +#define GRE0_FLAG_KEY 0x2000 +#define GRE0_FLAG_SEQUENCE 0x1000 +#define GRE0_FLAG_STRICT 0x0800 +#define GRE0_FLAG_RECURSION 0x0700 +#define GRE0_FLAG_VERSION 0x0007 + +static inline uint16_t gre0_hdr_get_flags(const struct gre0_hdr *hdr) +{ + return ntohs(hdr->flags); +} + +static inline uint8_t gre0_hdr_get_checksum_flag(const struct gre0_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE0_FLAG_CHECKSUM) >> 15; +} + +static inline uint8_t gre0_hdr_get_routing_flag(const struct gre0_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE0_FLAG_ROUTING) >> 14; +} + +static inline uint8_t gre0_hdr_get_key_flag(const struct gre0_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE0_FLAG_KEY) >> 13; +} + +static inline uint8_t gre0_hdr_get_seq_flag(const struct gre0_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE0_FLAG_SEQUENCE) >> 12; +} + +static inline uint8_t gre0_hdr_get_strict_flag(const struct gre0_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE0_FLAG_STRICT) >> 11; +} + +static inline uint8_t gre0_hdr_get_version(const struct gre0_hdr *hdr) +{ + return ntohs(hdr->flags) & GRE0_FLAG_VERSION; +} + +// ethernet protocol +static inline uint16_t gre0_hdr_get_proto(const struct gre0_hdr *hdr) +{ + return ntohs(hdr->protocol); +} + +static inline uint16_t gre0_hdr_get_checksum(const struct gre0_hdr *hdr) +{ + if (gre0_hdr_get_checksum_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 4; + return ntohs(*(uint16_t *)ptr); + } + else + { + return 0; + } +} + +static inline uint16_t gre0_hdr_get_offset(const struct gre0_hdr *hdr) +{ + if (gre0_hdr_get_checksum_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 6; + return ntohs(*(uint16_t *)ptr); + } + else + { + return 0; + } +} + +static inline uint32_t gre0_hdr_get_key(const struct gre0_hdr *hdr) +{ + if (gre0_hdr_get_key_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 4; + if (gre0_hdr_get_checksum_flag(hdr)) + { + ptr += 4; + } + + return ntohl(*(uint32_t *)ptr); + } + else + { + return 0; + } +} + +static inline uint32_t gre0_hdr_get_seq(const struct gre0_hdr *hdr) +{ + if (gre0_hdr_get_seq_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 4; + if (gre0_hdr_get_checksum_flag(hdr)) + { + ptr += 4; + } + + if (gre0_hdr_get_key_flag(hdr)) + { + ptr += 4; + } + + return ntohl(*(uint32_t *)ptr); + } + else + { + return 0; + } +} + +static inline const char *gre0_hdr_get_routing_data(const struct gre0_hdr *hdr) +{ + if (gre0_hdr_get_routing_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 4; + if (gre0_hdr_get_checksum_flag(hdr)) + { + ptr += 4; + } + + if (gre0_hdr_get_key_flag(hdr)) + { + ptr += 4; + } + + if (gre0_hdr_get_seq_flag(hdr)) + { + ptr += 4; + } + + return ptr; + } + else + { + return NULL; + } +} + +static inline uint16_t gre0_hdr_get_routing_len(const struct gre0_hdr *hdr) +{ + if (gre0_hdr_get_routing_flag(hdr)) + { + const char *ptr = gre0_hdr_get_routing_data(hdr); + + uint16_t hdr_len = 0; + while (1) + { + struct sre *sre = (struct sre *)(ptr + hdr_len); + if (sre->length == 0) + { + hdr_len += sizeof(struct sre); + break; + } + else + { + hdr_len += sizeof(struct sre) + sre->length; + } + } + return hdr_len; + } + else + { + return 0; + } +} + +static inline uint16_t calc_gre0_hdr_len(const char *data, uint32_t len) +{ + if (data == NULL || len < sizeof(struct gre0_hdr)) + { + return 0; + } + const struct gre0_hdr *hdr = (const struct gre0_hdr *)data; + uint16_t hdr_len = 4; + uint16_t flags = ntohs(hdr->flags); + if ((flags & GRE0_FLAG_CHECKSUM) || (flags & GRE0_FLAG_ROUTING)) + { + hdr_len += 4; // skip checksum and offset fields + } + if (flags & GRE0_FLAG_KEY) + { + hdr_len += 4; // skip key field + } + if (flags & GRE0_FLAG_SEQUENCE) + { + hdr_len += 4; // skip sequence number field + } + if (flags & GRE0_FLAG_ROUTING) + { + while (hdr_len + sizeof(struct sre) <= len) + { + struct sre *sre = (struct sre *)((char *)data + hdr_len); + if (sre->length == 0) + { + hdr_len += sizeof(struct sre); + break; + } + else + { + hdr_len += sizeof(struct sre) + sre->length; + } + } + } + return hdr_len; +} + +static inline void gre0_hdr_set_flags(struct gre0_hdr *hdr, uint16_t flags) +{ + hdr->flags = htons(flags); +} + +static inline void gre0_hdr_set_checksum_flag(struct gre0_hdr *hdr, uint8_t flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_CHECKSUM) | flag << 15); +} + +static inline void gre0_hdr_set_routing_flag(struct gre0_hdr *hdr, uint8_t flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_ROUTING) | flag << 14); +} + +static inline void gre0_hdr_set_key_flag(struct gre0_hdr *hdr, uint8_t flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_KEY) | flag << 13); +} + +static inline void gre0_hdr_set_seq_flag(struct gre0_hdr *hdr, uint8_t flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_SEQUENCE) | flag << 12); +} + +static inline void gre0_hdr_set_strict_flag(struct gre0_hdr *hdr, uint8_t flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_STRICT) | flag << 11); +} + +static inline void gre0_hdr_set_version(struct gre0_hdr *hdr, uint8_t version) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE0_FLAG_VERSION) | version); +} + +static inline void gre0_hdr_set_proto(struct gre0_hdr *hdr, uint16_t proto) +{ + hdr->protocol = htons(proto); +} + +static inline void gre0_hdr_set_checksum(struct gre0_hdr *hdr, uint16_t checksum) +{ + if (gre0_hdr_get_checksum_flag(hdr)) + { + char *ptr = ((char *)hdr) + 4; + *(uint16_t *)ptr = htons(checksum); + } +} + +static inline void gre0_hdr_set_offset(struct gre0_hdr *hdr, uint16_t offset) +{ + if (gre0_hdr_get_checksum_flag(hdr)) + { + char *ptr = ((char *)hdr) + 6; + *(uint16_t *)ptr = htons(offset); + } +} + +static inline void gre0_hdr_set_key(struct gre0_hdr *hdr, uint32_t key) +{ + if (gre0_hdr_get_key_flag(hdr)) + { + char *ptr = ((char *)hdr) + 4; + if (gre0_hdr_get_checksum_flag(hdr)) + { + ptr += 4; + } + + *(uint32_t *)ptr = htonl(key); + } +} + +static inline void gre0_hdr_set_seq(struct gre0_hdr *hdr, uint32_t sequence) +{ + if (gre0_hdr_get_seq_flag(hdr)) + { + char *ptr = ((char *)hdr) + 4; + if (gre0_hdr_get_checksum_flag(hdr)) + { + ptr += 4; + } + + if (gre0_hdr_get_key_flag(hdr)) + { + ptr += 4; + } + + *(uint32_t *)ptr = htonl(sequence); + } +} + +static inline void gre0_hdr_set_routing_data(struct gre0_hdr *hdr, const char *data, uint16_t len) +{ + if (gre0_hdr_get_routing_flag(hdr)) + { + char *ptr = ((char *)hdr) + 4; + if (gre0_hdr_get_checksum_flag(hdr)) + { + ptr += 4; + } + + if (gre0_hdr_get_key_flag(hdr)) + { + ptr += 4; + } + + if (gre0_hdr_get_seq_flag(hdr)) + { + ptr += 4; + } + + memcpy(ptr, data, len); + } +} + +static inline int gre0_hdr_to_str(const struct gre0_hdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + + int used = 0; + uint16_t proto = gre0_hdr_get_proto(hdr); + used += snprintf(buf + used, size - used, "GRE: flags=0x%04x (checksum_flag=%u, routing_flag=%u, key_flag=%u, seq_flag=%u, strict_flag=%u, version=%u), proto=%s", + gre0_hdr_get_flags(hdr), gre0_hdr_get_checksum_flag(hdr), gre0_hdr_get_routing_flag(hdr), gre0_hdr_get_key_flag(hdr), + gre0_hdr_get_seq_flag(hdr), gre0_hdr_get_strict_flag(hdr), gre0_hdr_get_version(hdr), eth_proto_to_str(proto)); + if (gre0_hdr_get_checksum_flag(hdr)) + { + used += snprintf(buf + used, size - used, ", checksum=0x%x, offset=%u", gre0_hdr_get_checksum(hdr), gre0_hdr_get_offset(hdr)); + } + if (gre0_hdr_get_key_flag(hdr)) + { + used += snprintf(buf + used, size - used, ", key=%u", gre0_hdr_get_key(hdr)); + } + if (gre0_hdr_get_seq_flag(hdr)) + { + used += snprintf(buf + used, size - used, ", seq=%u", gre0_hdr_get_seq(hdr)); + } + if (gre0_hdr_get_routing_flag(hdr)) + { + used += snprintf(buf + used, size - used, ", routing_len=%u", gre0_hdr_get_routing_len(hdr)); + } + + return used; +} + +/****************************************************************************** + * GREv1 + ******************************************************************************/ + +/* + * Enhanced GRE header (Version 1) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |C|R|K|S|s|Recur|A| Flags | Ver | Protocol Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Key (HW) Payload Length | Key (LW) Call ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number (Optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Acknowledgment Number (Optional) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://datatracker.ietf.org/doc/html/rfc2637 + */ + +struct gre1_hdr +{ + uint16_t flags; + uint16_t protocol; + uint16_t payload_length; + uint16_t call_id; +}; + +#define GRE1_FLAG_CHECKSUM 0x8000 +#define GRE1_FLAG_ROUTING 0x4000 +#define GRE1_FLAG_KEY 0x2000 +#define GRE1_FLAG_SEQUENCE 0x1000 +#define GRE1_FLAG_STRICT 0x0800 +#define GRE1_FLAG_RECURSION 0x0700 +#define GRE1_FLAG_ACK 0x0080 /* only in special PPTPized GRE header */ +#define GRE1_FLAG_VERSION 0x0007 + +static inline uint16_t gre1_hdr_get_flags(const struct gre1_hdr *hdr) +{ + return ntohs(hdr->flags); +} + +static inline uint8_t gre1_hdr_get_seq_flag(const struct gre1_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE1_FLAG_SEQUENCE) >> 12; +} + +static inline uint8_t gre1_hdr_get_ack_flag(const struct gre1_hdr *hdr) +{ + return (ntohs(hdr->flags) & GRE1_FLAG_ACK) >> 7; +} + +static inline uint8_t gre1_hdr_get_version(const struct gre1_hdr *hdr) +{ + return ntohs(hdr->flags) & GRE1_FLAG_VERSION; +} + +// ethernet protocol type +static inline uint16_t gre1_hdr_get_proto(const struct gre1_hdr *hdr) +{ + return ntohs(hdr->protocol); +} + +static inline uint16_t gre1_hdr_get_payload_length(const struct gre1_hdr *hdr) +{ + return ntohs(hdr->payload_length); +} + +static inline uint16_t gre1_hdr_get_call_id(const struct gre1_hdr *hdr) +{ + return ntohs(hdr->call_id); +} + +static inline uint32_t gre1_hdr_get_seq(const struct gre1_hdr *hdr) +{ + if (gre1_hdr_get_seq_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 8; + return ntohl(*((uint32_t *)ptr)); + } + else + { + return 0; + } +} + +static inline uint32_t gre1_hdr_get_ack(const struct gre1_hdr *hdr) +{ + if (gre1_hdr_get_ack_flag(hdr)) + { + const char *ptr = ((const char *)hdr) + 8; + if (gre1_hdr_get_seq_flag(hdr)) + { + ptr += 4; + } + return ntohl(*((uint32_t *)ptr)); + } + else + { + return 0; + } +} + +static inline uint16_t calc_gre1_hdr_len(const char *data, uint32_t len) +{ + if (data == NULL || len < sizeof(struct gre1_hdr)) + { + return 0; + } + const struct gre1_hdr *hdr = (const struct gre1_hdr *)data; + uint16_t hdr_len = 8; + uint16_t flags = gre1_hdr_get_flags(hdr); + if (flags & GRE1_FLAG_SEQUENCE) + { + hdr_len += 4; + } + if (flags & GRE1_FLAG_ACK) + { + hdr_len += 4; + } + return hdr_len; +} + +static inline void gre1_hdr_set_flags(struct gre1_hdr *hdr, uint16_t flags) +{ + hdr->flags = htons(flags); +} + +static inline void gre1_hdr_set_seq_flag(struct gre1_hdr *hdr, uint8_t seq_flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE1_FLAG_SEQUENCE) | seq_flag << 12); +} + +static inline void gre1_hdr_set_ack_flag(struct gre1_hdr *hdr, uint8_t ack_flag) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE1_FLAG_ACK) | ack_flag << 7); +} + +static inline void gre1_hdr_set_version(struct gre1_hdr *hdr, uint8_t version) +{ + hdr->flags = htons((ntohs(hdr->flags) & ~GRE1_FLAG_VERSION) | version); +} + +static inline void gre1_hdr_set_proto(struct gre1_hdr *hdr, uint16_t proto) +{ + hdr->protocol = htons(proto); +} + +static inline void gre1_hdr_set_payload_length(struct gre1_hdr *hdr, uint16_t payload_length) +{ + hdr->payload_length = htons(payload_length); +} + +static inline void gre1_hdr_set_call_id(struct gre1_hdr *hdr, uint16_t call_id) +{ + hdr->call_id = htons(call_id); +} + +static inline void gre1_hdr_set_seq(struct gre1_hdr *hdr, uint32_t seq) +{ + if (gre1_hdr_get_seq_flag(hdr)) + { + char *ptr = ((char *)hdr) + 8; + *((uint32_t *)ptr) = htonl(seq); + } +} + +static inline void gre1_hdr_set_ack(struct gre1_hdr *hdr, uint32_t ack) +{ + if (gre1_hdr_get_ack_flag(hdr)) + { + char *ptr = ((char *)hdr) + 8; + if (gre1_hdr_get_seq_flag(hdr)) + { + ptr += 4; + } + *((uint32_t *)ptr) = htonl(ack); + } +} + +static inline int gre1_hdr_to_str(const struct gre1_hdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + + int used = 0; + uint16_t proto = gre1_hdr_get_proto(hdr); + used += snprintf(buf + used, size - used, "GRE: flags=0x%04x (seq_flag=%u ack_flag=%u version=%u), proto=%s, payload_length=%u, call_id=%u", + gre1_hdr_get_flags(hdr), gre1_hdr_get_seq_flag(hdr), gre1_hdr_get_ack_flag(hdr), gre1_hdr_get_version(hdr), + eth_proto_to_str(proto), gre1_hdr_get_payload_length(hdr), gre1_hdr_get_call_id(hdr)); + if (gre1_hdr_get_seq_flag(hdr)) + { + used += snprintf(buf + used, size - used, ", seq=%u", gre1_hdr_get_seq(hdr)); + } + if (gre1_hdr_get_ack_flag(hdr)) + { + used += snprintf(buf + used, size - used, ", ack=%u", gre1_hdr_get_ack(hdr)); + } + + return used; +} + +/****************************************************************************** + * GRE + ******************************************************************************/ + +// return GRE version 0 or 1 +// return 255 if not GRE +static inline uint8_t peek_gre_version(const char *data, uint32_t len) +{ + if (len < MIN(sizeof(struct gre0_hdr), sizeof(struct gre1_hdr))) + { + return 255; + } + + uint16_t flag = *(uint16_t *)data; + return ntohs(flag) & 0x0007; +} + +static inline uint16_t peek_gre_proto(const char *data, uint32_t len) +{ + switch (peek_gre_version(data, len)) + { + case 0: + return gre0_hdr_get_proto((const struct gre0_hdr *)data); + case 1: + return gre1_hdr_get_proto((const struct gre1_hdr *)data); + default: + return 0; + } +} + +static inline uint16_t calc_gre_hdr_len(const char *data, uint32_t len) +{ + switch (peek_gre_version(data, len)) + { + case 0: + return calc_gre0_hdr_len(data, len); + case 1: + return calc_gre1_hdr_len(data, len); + default: + return 0; + } +} + +static inline int gre_hdr_to_str(const char *hdr, uint16_t len, char *buf, size_t size) +{ + switch (peek_gre_version(hdr, len)) + { + case 0: + return gre0_hdr_to_str((const struct gre0_hdr *)hdr, buf, size); + case 1: + return gre1_hdr_to_str((const struct gre1_hdr *)hdr, buf, size); + default: + return 0; + } +} + +/****************************************************************************** + * GTPv1 + ******************************************************************************/ + +/* + * https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol + * + * GTP-C: Gateway GPRS Support Nodes (GGSN) <----> Serving GPRS support Nodes (SGSN) + * GTP-U: Radio Access Network <----> Core Network + * + * GTPv1: + * -> GTPv1-C + * -> GTPv1-U + */ + +/* + * GTP version 1 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver |T|R|E|S|N| Message Type | Message Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TEID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number(O) |N-PDU Number(O)|Next Ext Hdr(O)| (optional headers) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Message Length: + * a 16-bit field that indicates the length of the payload in bytes + * (rest of the packet following the mandatory 8-byte GTP header). + * Includes the optional fields. + */ + +/* + * Next Extension Headers + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Length | Contents | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ... | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Contents | Next Ext Hdr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Extension length + * an 8-bit field. This field states the length of this extension header, + * including the length, the contents, and the next extension header field, + * in 4-octet units, so the length of the extension must always be a multiple of 4. + */ + +struct gtp1_hdr +{ + uint8_t flags; + uint8_t msg_type; + uint16_t msg_len; + uint32_t teid; +} __attribute__((packed)); + +struct gtp1_hdr_long +{ + uint8_t flags; + uint8_t msg_type; + uint16_t msg_len; + uint32_t teid; + + uint16_t seq; + uint8_t npdu; + uint8_t next_ext_hdr; +} __attribute__((packed)); + +#define GTP1_FLAG_N_PDU (0x01) +#define GTP1_FLAG_SEQ_NUM (0x02) +#define GTP1_FLAG_EXT_HDR (0x04) +#define GTP1_FLAG_RESERVED (0x08) +#define GTP1_FLAG_PROTOCOL (0x10) +#define GTP1_FLAG_VERSION (0xE0) + +static inline uint8_t gtp1_hdr_get_flags(const struct gtp1_hdr *gtp) +{ + return gtp->flags; +} + +static inline uint8_t gtp1_hdr_get_version(const struct gtp1_hdr *gtp) +{ + return (gtp->flags & GTP1_FLAG_VERSION) >> 5; +} + +static inline uint8_t gtp1_hdr_get_proto(const struct gtp1_hdr *gtp) +{ + return (gtp->flags & GTP1_FLAG_PROTOCOL) >> 4; +} + +static inline uint8_t gtp1_hdr_get_reserved(const struct gtp1_hdr *gtp) +{ + return (gtp->flags & GTP1_FLAG_RESERVED) >> 3; +} + +static inline uint8_t gtp1_hdr_get_ext_flag(const struct gtp1_hdr *gtp) +{ + return (gtp->flags & GTP1_FLAG_EXT_HDR) >> 2; +} + +static inline uint8_t gtp1_hdr_get_seq_flag(const struct gtp1_hdr *gtp) +{ + return (gtp->flags & GTP1_FLAG_SEQ_NUM) >> 1; +} + +static inline uint8_t gtp1_hdr_get_npdu_flag(const struct gtp1_hdr *gtp) +{ + return (gtp->flags & GTP1_FLAG_N_PDU) >> 0; +} + +static inline uint8_t gtp1_hdr_get_msg_type(const struct gtp1_hdr *gtp) +{ + return gtp->msg_type; +} + +static inline uint16_t gtp1_hdr_get_msg_len(const struct gtp1_hdr *gtp) +{ + return ntohs(gtp->msg_len); +} + +static inline uint32_t gtp1_hdr_get_teid(const struct gtp1_hdr *gtp) +{ + return ntohl(gtp->teid); +} + +static inline uint16_t gtp1_hdr_get_seq(const struct gtp1_hdr *gtp) +{ + if (gtp1_hdr_get_seq_flag(gtp)) + { + const struct gtp1_hdr_long *gtp_long = (const struct gtp1_hdr_long *)gtp; + return ntohs(gtp_long->seq); + } + else + { + return 0; + } +} + +static inline uint8_t gtp1_hdr_get_npdu(const struct gtp1_hdr *gtp) +{ + if (gtp1_hdr_get_npdu_flag(gtp)) + { + const struct gtp1_hdr_long *gtp_long = (const struct gtp1_hdr_long *)gtp; + return gtp_long->npdu; + } + else + { + return 0; + } +} + +static inline uint8_t gtp1_hdr_get_next_ext_type(const struct gtp1_hdr *gtp) +{ + if (gtp1_hdr_get_ext_flag(gtp)) + { + const struct gtp1_hdr_long *gtp_long = (const struct gtp1_hdr_long *)gtp; + return gtp_long->next_ext_hdr; + } + else + { + return 0; + } +} + +// include gtp fixed header and optional headers and extension headers +static inline uint16_t calc_gtp1_hdr_len(const char *data, uint16_t len) +{ + if (data == NULL || len < sizeof(struct gtp1_hdr)) + { + return 0; + } + + const struct gtp1_hdr *gtp = (const struct gtp1_hdr *)data; + if (gtp1_hdr_get_version(gtp) != 1) + { + return 0; + } + + if (gtp1_hdr_get_flags(gtp) & (GTP1_FLAG_SEQ_NUM | GTP1_FLAG_N_PDU | GTP1_FLAG_EXT_HDR)) + { + if (sizeof(struct gtp1_hdr_long) > len) + { + return 0; + } + + const struct gtp1_hdr_long *gtp_long = (const struct gtp1_hdr_long *)data; + uint8_t next_ext_hdr = gtp_long->next_ext_hdr; + uint16_t offset = sizeof(struct gtp1_hdr_long); + + while (next_ext_hdr) + { + if (offset + 1 > len) + { + return 0; + } + uint16_t ext_hdr_len = *((char *)data + offset) * 4; + if (ext_hdr_len == 0 || offset + ext_hdr_len > len) + { + return 0; + } + offset += ext_hdr_len; // skip extension header + next_ext_hdr = *((char *)data + offset - 1); + } + + return offset; + } + else + { + return sizeof(struct gtp1_hdr); + } +} + +static inline void gtp1_hdr_set_flags(struct gtp1_hdr *gtp, uint8_t flags) +{ + gtp->flags = flags; +} + +static inline void gtp1_hdr_set_version(struct gtp1_hdr *gtp, uint8_t version) +{ + gtp->flags = (gtp->flags & ~GTP1_FLAG_VERSION) | (version << 5); +} + +static inline void gtp1_hdr_set_proto(struct gtp1_hdr *gtp, uint8_t protocol_type) +{ + gtp->flags = (gtp->flags & ~GTP1_FLAG_PROTOCOL) | (protocol_type << 4); +} + +static inline void gtp1_hdr_set_reserved(struct gtp1_hdr *gtp, uint8_t reserved) +{ + gtp->flags = (gtp->flags & ~GTP1_FLAG_RESERVED) | (reserved << 3); +} + +static inline void gtp1_hdr_set_ext_flag(struct gtp1_hdr *gtp, uint8_t ext_flag) +{ + gtp->flags = (gtp->flags & ~GTP1_FLAG_EXT_HDR) | (ext_flag << 2); +} + +static inline void gtp1_hdr_set_seq_flag(struct gtp1_hdr *gtp, uint8_t seq_flag) +{ + gtp->flags = (gtp->flags & ~GTP1_FLAG_SEQ_NUM) | (seq_flag << 1); +} + +static inline void gtp1_hdr_set_npdu_flag(struct gtp1_hdr *gtp, uint8_t npdu_flag) +{ + gtp->flags = (gtp->flags & ~GTP1_FLAG_N_PDU) | (npdu_flag << 0); +} + +static inline void gtp1_hdr_set_msg_type(struct gtp1_hdr *gtp, uint8_t msg_type) +{ + gtp->msg_type = msg_type; +} + +static inline void gtp1_hdr_set_msg_len(struct gtp1_hdr *gtp, uint16_t msg_len) +{ + gtp->msg_len = htons(msg_len); +} + +static inline void gtp1_hdr_set_teid(struct gtp1_hdr *gtp, uint32_t teid) +{ + gtp->teid = htonl(teid); +} + +static inline void gtp1_hdr_set_seq(struct gtp1_hdr *gtp, uint16_t seq) +{ + if (gtp1_hdr_get_seq_flag(gtp)) + { + struct gtp1_hdr_long *gtp_long = (struct gtp1_hdr_long *)gtp; + gtp_long->seq = htons(seq); + } +} + +static inline void gtp1_hdr_set_npdu(struct gtp1_hdr *gtp, uint8_t npdu) +{ + if (gtp1_hdr_get_npdu_flag(gtp)) + { + struct gtp1_hdr_long *gtp_long = (struct gtp1_hdr_long *)gtp; + gtp_long->npdu = npdu; + } +} + +static inline void gtp1_hdr_set_next_ext_type(struct gtp1_hdr *gtp, uint8_t next_ext_hdr) +{ + if (gtp1_hdr_get_ext_flag(gtp)) + { + struct gtp1_hdr_long *gtp_long = (struct gtp1_hdr_long *)gtp; + gtp_long->next_ext_hdr = next_ext_hdr; + } +} + +static inline int gtp1_hdr_to_str(const struct gtp1_hdr *gtp, char *buf, size_t len) +{ + memset(buf, 0, len); + + int used = 0; + used += snprintf(buf + used, len - used, "GTP: flags=0x%02x (version=%u, protocol=%u, reserved=%u, ext_flag=%u, seq_flag=%u, npdu_flag=%u), msg_type=0x%02x, msg_len=%u, teid=%u", + gtp1_hdr_get_flags(gtp), + gtp1_hdr_get_version(gtp), + gtp1_hdr_get_proto(gtp), + gtp1_hdr_get_reserved(gtp), + gtp1_hdr_get_ext_flag(gtp), + gtp1_hdr_get_seq_flag(gtp), + gtp1_hdr_get_npdu_flag(gtp), + gtp1_hdr_get_msg_type(gtp), + gtp1_hdr_get_msg_len(gtp), + gtp1_hdr_get_teid(gtp)); + + if (gtp1_hdr_get_seq_flag(gtp)) + { + used += snprintf(buf + used, len - used, ", seq=%u", gtp1_hdr_get_seq(gtp)); + } + if (gtp1_hdr_get_npdu_flag(gtp)) + { + used += snprintf(buf + used, len - used, ", npdu=%u", gtp1_hdr_get_npdu(gtp)); + } + if (gtp1_hdr_get_ext_flag(gtp)) + { + used += snprintf(buf + used, len - used, ", next_ext_hdr=%u", gtp1_hdr_get_next_ext_type(gtp)); + } + return used; +} + +/****************************************************************************** + * GTPv2 + ******************************************************************************/ + +/* + * https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol + * https://www.etsi.org/deliver/etsi_ts/129200_129299/129274/08.04.00_60/ts_129274v080400p.pdf + * + * GTP-C: Gateway GPRS Support Nodes (GGSN) <----> Serving GPRS support Nodes (SGSN) + * GTP-U: Radio Access Network <----> Core Network + * + * GTPv2: + * -> GTPv2-C + * -> (no GTPv2-U) + */ + +/* + * GTP version 2 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver |P|T|spare| Message Type | Message Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | TEID (only if T=1) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number | Spare | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Message length: + * This field shall indicate the length of the message in octets excluding the mandatory of the GTP-C header (the first 4 octets). + * The TEID (if present) and the Sequence Number shall be included in the length count. + */ + +struct gtp2_hdr +{ + uint8_t flags; + uint8_t msg_type; + uint16_t msg_len; + uint32_t seq_and_spare; +} __attribute__((packed)); + +struct gtp2_hdr_long +{ + uint8_t flags; + uint8_t msg_type; + uint16_t msg_len; + uint32_t teid; + uint32_t seq_and_spare; +} __attribute__((packed)); + +#define GPT2_FLAG_SPARE (0x07) +#define GTP2_FLAG_TEID (0x08) +#define GTP2_FLAG_PIGGYBACK (0x10) +#define GTP2_FLAG_VERSION (0xE0) + +static inline uint8_t gtp2_hdr_get_flags(const struct gtp2_hdr *gtp) +{ + return gtp->flags; +} + +static inline uint8_t gtp2_hdr_get_version(const struct gtp2_hdr *gtp) +{ + return (gtp->flags & GTP2_FLAG_VERSION) >> 5; +} + +static inline uint8_t gtp2_hdr_get_piggyback_flag(const struct gtp2_hdr *gtp) +{ + return (gtp->flags & GTP2_FLAG_PIGGYBACK) >> 4; +} + +static inline uint8_t gtp2_hdr_get_teid_flag(const struct gtp2_hdr *gtp) +{ + return (gtp->flags & GTP2_FLAG_TEID) >> 3; +} + +static inline uint8_t gtp2_hdr_get_spare_flag(const struct gtp2_hdr *gtp) +{ + return (gtp->flags & GPT2_FLAG_SPARE) >> 0; +} + +static inline uint8_t gtp2_hdr_get_msg_type(const struct gtp2_hdr *gtp) +{ + return gtp->msg_type; +} + +static inline uint16_t gtp2_hdr_get_msg_len(const struct gtp2_hdr *gtp) +{ + return ntohs(gtp->msg_len); +} + +static inline uint32_t gtp2_hdr_get_teid(const struct gtp2_hdr *gtp) +{ + if (gtp2_hdr_get_teid_flag(gtp)) + { + const struct gtp2_hdr_long *gtp_long = (const struct gtp2_hdr_long *)gtp; + return ntohl(gtp_long->teid); + } + else + { + return 0; + } +} + +static inline uint32_t gtp2_hdr_get_seq(const struct gtp2_hdr *gtp) +{ + if (gtp2_hdr_get_teid_flag(gtp)) + { + const struct gtp2_hdr_long *gtp_long = (const struct gtp2_hdr_long *)gtp; + return ntohl(gtp_long->seq_and_spare) >> 8; + } + else + { + return ntohl(gtp->seq_and_spare) >> 8; + } +} + +static inline uint8_t gtp2_hdr_get_spare(const struct gtp2_hdr *gtp) +{ + if (gtp2_hdr_get_teid_flag(gtp)) + { + const struct gtp2_hdr_long *gtp_long = (const struct gtp2_hdr_long *)gtp; + return ntohl(gtp_long->seq_and_spare) & 0xFF; + } + else + { + return ntohl(gtp->seq_and_spare) & 0xFF; + } +} + +static inline uint16_t calc_gtp2_hdr_len(const char *data, uint16_t len) +{ + if (len < sizeof(struct gtp2_hdr)) + { + return 0; + } + + const struct gtp2_hdr *gtp = (const struct gtp2_hdr *)data; + if (gtp2_hdr_get_version(gtp) == 2) + { + if (gtp2_hdr_get_teid_flag(gtp)) + { + return sizeof(struct gtp2_hdr_long); + } + else + { + return sizeof(struct gtp2_hdr); + } + } + + return 0; +} + +static inline void gtp2_hdr_set_flags(struct gtp2_hdr *gtp, uint8_t flags) +{ + gtp->flags = flags; +} + +static inline void gtp2_hdr_set_version(struct gtp2_hdr *gtp, uint8_t version) +{ + gtp->flags = (gtp->flags & ~GTP2_FLAG_VERSION) | (version << 5); +} + +static inline void gtp2_hdr_set_piggyback_flag(struct gtp2_hdr *gtp, uint8_t piggyback) +{ + gtp->flags = (gtp->flags & ~GTP2_FLAG_PIGGYBACK) | (piggyback << 4); +} + +static inline void gtp2_hdr_set_teid_flag(struct gtp2_hdr *gtp, uint8_t teid_flag) +{ + gtp->flags = (gtp->flags & ~GTP2_FLAG_TEID) | (teid_flag << 3); +} + +static inline void gtp2_hdr_set_spare_flag(struct gtp2_hdr *gtp, uint8_t spare_flag) +{ + gtp->flags = (gtp->flags & ~GPT2_FLAG_SPARE) | (spare_flag << 0); +} + +static inline void gtp2_hdr_set_msg_type(struct gtp2_hdr *gtp, uint8_t msg_type) +{ + gtp->msg_type = msg_type; +} + +static inline void gtp2_hdr_set_msg_len(struct gtp2_hdr *gtp, uint16_t msg_len) +{ + gtp->msg_len = htons(msg_len); +} + +static inline void gtp2_hdr_set_teid(struct gtp2_hdr *gtp, uint32_t teid) +{ + if (gtp2_hdr_get_teid_flag(gtp)) + { + struct gtp2_hdr_long *gtp_long = (struct gtp2_hdr_long *)gtp; + gtp_long->teid = htonl(teid); + } +} + +static inline void gtp2_hdr_set_seq(struct gtp2_hdr *gtp, uint32_t seq) +{ + if (gtp2_hdr_get_teid_flag(gtp)) + { + struct gtp2_hdr_long *gtp_long = (struct gtp2_hdr_long *)gtp; + gtp_long->seq_and_spare = htonl((seq << 8) | gtp2_hdr_get_spare(gtp)); + } + else + { + gtp->seq_and_spare = htonl((seq << 8) | gtp2_hdr_get_spare(gtp)); + } +} + +static inline void gtp2_hdr_set_spare(struct gtp2_hdr *gtp, uint8_t spare) +{ + if (gtp2_hdr_get_teid_flag(gtp)) + { + struct gtp2_hdr_long *gtp_long = (struct gtp2_hdr_long *)gtp; + gtp_long->seq_and_spare = htonl((gtp2_hdr_get_seq(gtp) << 8) | spare); + } + else + { + gtp->seq_and_spare = htonl((gtp2_hdr_get_seq(gtp) << 8) | spare); + } +} + +static inline int gtp2_hdr_to_str(const struct gtp2_hdr *gtp, char *buf, size_t len) +{ + memset(buf, 0, len); + + int used = 0; + used += snprintf(buf + used, len - used, "GTP: flags=0x%02x (version=%u, piggyback=%u, teid_flag=%u, spare_flag=%u), msg_type=0x%02x, msg_len=%u", + gtp2_hdr_get_flags(gtp), + gtp2_hdr_get_version(gtp), + gtp2_hdr_get_piggyback_flag(gtp), + gtp2_hdr_get_teid_flag(gtp), + gtp2_hdr_get_spare_flag(gtp), + gtp2_hdr_get_msg_type(gtp), + gtp2_hdr_get_msg_len(gtp)); + + if (gtp2_hdr_get_teid_flag(gtp)) + { + used += snprintf(buf + used, len - used, ", teid=%u", gtp2_hdr_get_teid(gtp)); + } + else + { + used += snprintf(buf + used, len - used, ", seq=%u, spare=%u", gtp2_hdr_get_seq(gtp), gtp2_hdr_get_spare(gtp)); + } + return used; +} + +/****************************************************************************** + * GTP + ******************************************************************************/ + +// return GTP version 0 or 1 +// return 255 if not GTP +static inline uint8_t peek_gtp_version(const char *data, uint16_t len) +{ + if (data == NULL || len == 0) + { + return 255; + } + + return ((*(uint8_t *)data) >> 5) & 0x07; +} + +static inline uint16_t calc_gtp_hdr_len(const char *data, uint32_t len) +{ + switch (peek_gtp_version(data, len)) + { + case 1: + return calc_gtp1_hdr_len(data, len); + case 2: + return calc_gtp2_hdr_len(data, len); + default: + return 0; + } +} + +static inline int gtp_hdr_to_str(const char *hdr, uint16_t len, char *buf, size_t size) +{ + switch (peek_gtp_version(hdr, len)) + { + case 1: + return gtp1_hdr_to_str((const struct gtp1_hdr *)hdr, buf, size); + case 2: + return gtp2_hdr_to_str((const struct gtp2_hdr *)hdr, buf, size); + default: + return 0; + } +} + +/****************************************************************************** + * IPv4 + ******************************************************************************/ + +/* + * Internet Header Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Version| IHL |Type of Service| Total Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identification |Flags| Fragment Offset | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Time to Live | Protocol | Header Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Destination Address | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Options | Padding | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +static inline uint8_t ip4_hdr_get_version(const struct ip *hdr) +{ + return hdr->ip_v; +} + +// IP Options are included in the hdr_len field +static inline uint8_t ip4_hdr_get_hdr_len(const struct ip *hdr) +{ + return hdr->ip_hl << 2; +} + +static inline uint8_t ip4_hdr_get_tos(const struct ip *hdr) +{ + return hdr->ip_tos; +} + +static inline uint16_t ip4_hdr_get_total_len(const struct ip *hdr) +{ + return ntohs(hdr->ip_len); +} + +static inline uint16_t ip4_hdr_get_ipid(const struct ip *hdr) +{ + return ntohs(hdr->ip_id); +} + +static inline uint8_t ip4_hdr_get_flags(const struct ip *hdr) +{ + return (ntohs(hdr->ip_off) & (~IP_OFFMASK)) >> 13; +} + +static inline bool ip4_hdr_get_rf_flag(const struct ip *hdr) +{ + return (ntohs(hdr->ip_off) & IP_RF) != 0; +} + +static inline bool ip4_hdr_get_df_flag(const struct ip *hdr) +{ + return (ntohs(hdr->ip_off) & IP_DF) != 0; +} + +static inline bool ip4_hdr_get_mf_flag(const struct ip *hdr) +{ + return (ntohs(hdr->ip_off) & IP_MF) != 0; +} + +static inline uint16_t ip4_hdr_get_frag_offset(const struct ip *hdr) +{ + return (ntohs(hdr->ip_off) & IP_OFFMASK) << 3; +} + +static inline uint8_t ip4_hdr_get_ttl(const struct ip *hdr) +{ + return hdr->ip_ttl; +} + +static inline uint8_t ip4_hdr_get_proto(const struct ip *hdr) +{ + return hdr->ip_p; +} + +static inline uint16_t ip4_hdr_get_checksum(const struct ip *hdr) +{ + return ntohs(hdr->ip_sum); +} + +static inline uint32_t ip4_hdr_get_src_addr(const struct ip *hdr) +{ + return ntohl(hdr->ip_src.s_addr); +} + +static inline uint32_t ip4_hdr_get_dst_addr(const struct ip *hdr) +{ + return ntohl(hdr->ip_dst.s_addr); +} + +static inline struct in_addr ip4_hdr_get_src_in_addr(const struct ip *hdr) +{ + return hdr->ip_src; +} + +static inline struct in_addr ip4_hdr_get_dst_in_addr(const struct ip *hdr) +{ + return hdr->ip_dst; +} + +static inline uint8_t ip4_hdr_get_opt_len(const struct ip *hdr) +{ + return ip4_hdr_get_hdr_len(hdr) - sizeof(struct ip); +} + +static inline const char *ip4_hdr_get_opt_data(const struct ip *hdr) +{ + if (ip4_hdr_get_opt_len(hdr) == 0) + { + return NULL; + } + + return (const char *)hdr + sizeof(struct ip); +} + +static inline void ip4_hdr_set_version(struct ip *hdr, uint8_t version) +{ + hdr->ip_v = version; +} + +static inline void ip4_hdr_set_hdr_len(struct ip *hdr, uint8_t hdr_len) +{ + hdr->ip_hl = hdr_len >> 2; +} + +static inline void ip4_hdr_set_tos(struct ip *hdr, uint8_t tos) +{ + hdr->ip_tos = tos; +} + +static inline void ip4_hdr_set_total_len(struct ip *hdr, uint16_t total_len) +{ + hdr->ip_len = htons(total_len); +} + +static inline void ip4_hdr_set_ipid(struct ip *hdr, uint16_t ipid) +{ + hdr->ip_id = htons(ipid); +} + +static inline void ip4_hdr_set_flags(struct ip *hdr, uint8_t flags) +{ + hdr->ip_off = htons((flags << 13) | (ntohs(hdr->ip_off) & IP_OFFMASK)); +} + +static inline void ip4_hdr_set_rf_flag(struct ip *hdr, bool flag) +{ + if (flag) + { + hdr->ip_off = htons(ntohs(hdr->ip_off) | IP_RF); + } + else + { + hdr->ip_off = htons(ntohs(hdr->ip_off) & ~IP_RF); + } +} + +static inline void ip4_hdr_set_df_flag(struct ip *hdr, bool flag) +{ + if (flag) + { + hdr->ip_off = htons(ntohs(hdr->ip_off) | IP_DF); + } + else + { + hdr->ip_off = htons(ntohs(hdr->ip_off) & ~IP_DF); + } +} + +static inline void ip4_hdr_set_mf_flag(struct ip *hdr, bool flag) +{ + if (flag) + { + hdr->ip_off = htons(ntohs(hdr->ip_off) | IP_MF); + } + else + { + hdr->ip_off = htons(ntohs(hdr->ip_off) & ~IP_MF); + } +} + +static inline void ip4_hdr_set_frag_offset(struct ip *hdr, uint16_t frag_offset) +{ + hdr->ip_off = htons((frag_offset >> 3) | (ntohs(hdr->ip_off) & ~IP_OFFMASK)); +} + +static inline void ip4_hdr_set_ttl(struct ip *hdr, uint8_t ttl) +{ + hdr->ip_ttl = ttl; +} + +static inline void ip4_hdr_set_protocol(struct ip *hdr, uint8_t protocol) +{ + hdr->ip_p = protocol; +} + +static inline void ip4_hdr_set_checksum(struct ip *hdr, uint16_t checksum) +{ + hdr->ip_sum = htons(checksum); +} + +static inline void ip4_hdr_set_src_addr(struct ip *hdr, uint32_t saddr) +{ + hdr->ip_src.s_addr = htonl(saddr); +} + +static inline void ip4_hdr_set_dst_addr(struct ip *hdr, uint32_t daddr) +{ + hdr->ip_dst.s_addr = htonl(daddr); +} + +static inline void ip4_hdr_set_src_in_addr(struct ip *hdr, struct in_addr saddr) +{ + hdr->ip_src = saddr; +} + +static inline void ip4_hdr_set_dst_in_addr(struct ip *hdr, struct in_addr daddr) +{ + hdr->ip_dst = daddr; +} + +static inline void ip4_hdr_set_opt_len(struct ip *hdr, uint8_t opt_len) +{ + ip4_hdr_set_hdr_len(hdr, opt_len + sizeof(struct ip)); +} + +// must be called after ip4_hdr_set_opt_len +static inline void ip4_hdr_set_opt_data(struct ip *hdr, const char *opt_data) +{ + if (opt_data) + { + memcpy((char *)hdr + sizeof(struct ip), opt_data, ip4_hdr_get_opt_len(hdr)); + } +} + +// /usr/include/netinet/in.h +static inline int is_ip_proto(uint16_t proto) +{ + switch (proto) + { + case IPPROTO_IP: + case IPPROTO_ICMP: + case IPPROTO_IGMP: + case IPPROTO_IPIP: + case IPPROTO_TCP: + case IPPROTO_EGP: + case IPPROTO_PUP: + case IPPROTO_UDP: + case IPPROTO_IDP: + case IPPROTO_TP: + case IPPROTO_DCCP: + case IPPROTO_IPV6: + case IPPROTO_RSVP: + case IPPROTO_GRE: + case IPPROTO_ESP: + case IPPROTO_AH: + case IPPROTO_MTP: + case IPPROTO_BEETPH: + case IPPROTO_ENCAP: + case IPPROTO_PIM: + case IPPROTO_COMP: + case IPPROTO_SCTP: + case IPPROTO_UDPLITE: + case IPPROTO_MPLS: + case IPPROTO_ETHERNET: + case IPPROTO_RAW: + case IPPROTO_MPTCP: + return 1; + default: + return 0; + } +} + +static inline const char *ip_proto_to_str(uint16_t proto) +{ + switch (proto) + { + case IPPROTO_IP: + return "IPPROTO_IP"; + case IPPROTO_ICMP: + return "IPPROTO_ICMP"; + case IPPROTO_IGMP: + return "IPPROTO_IGMP"; + case IPPROTO_IPIP: + return "IPPROTO_IPIP"; + case IPPROTO_TCP: + return "IPPROTO_TCP"; + case IPPROTO_EGP: + return "IPPROTO_EGP"; + case IPPROTO_PUP: + return "IPPROTO_PUP"; + case IPPROTO_UDP: + return "IPPROTO_UDP"; + case IPPROTO_IDP: + return "IPPROTO_IDP"; + case IPPROTO_TP: + return "IPPROTO_TP"; + case IPPROTO_DCCP: + return "IPPROTO_DCCP"; + case IPPROTO_IPV6: + return "IPPROTO_IPV6"; + case IPPROTO_RSVP: + return "IPPROTO_RSVP"; + case IPPROTO_GRE: + return "IPPROTO_GRE"; + case IPPROTO_ESP: + return "IPPROTO_ESP"; + case IPPROTO_AH: + return "IPPROTO_AH"; + case IPPROTO_MTP: + return "IPPROTO_MTP"; + case IPPROTO_BEETPH: + return "IPPROTO_BEETPH"; + case IPPROTO_ENCAP: + return "IPPROTO_ENCAP"; + case IPPROTO_PIM: + return "IPPROTO_PIM"; + case IPPROTO_COMP: + return "IPPROTO_COMP"; + case IPPROTO_SCTP: + return "IPPROTO_SCTP"; + case IPPROTO_UDPLITE: + return "IPPROTO_UDPLITE"; + case IPPROTO_MPLS: + return "IPPROTO_MPLS"; + case IPPROTO_ETHERNET: + return "IPPROTO_ETHERNET"; + case IPPROTO_RAW: + return "IPPROTO_RAW"; + case IPPROTO_MPTCP: + return "IPPROTO_MPTCP"; + default: + return "IPPROTO_UNKNOWN"; + } +} + +static inline int ip4_hdr_to_str(const struct ip *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + char src_addr_str[INET6_ADDRSTRLEN] = {0}; + char dst_addr_str[INET6_ADDRSTRLEN] = {0}; + + uint16_t proto = ip4_hdr_get_proto(hdr); + struct in_addr src_addr = ip4_hdr_get_src_in_addr(hdr); + struct in_addr dst_addr = ip4_hdr_get_dst_in_addr(hdr); + inet_ntop(AF_INET, &src_addr, src_addr_str, sizeof(src_addr_str)); + inet_ntop(AF_INET, &dst_addr, dst_addr_str, sizeof(dst_addr_str)); + + return snprintf(buf, size, "IPv4: version=%u hdr_len=%u tos=%u total_len=%u ipid=%u flags=%u(rf=%u df=%u mf=%u) frag_offset=%u ttl=%u proto=%s checksum=0x%x src_addr=%s dst_addr=%s opt_len=%u", + ip4_hdr_get_version(hdr), ip4_hdr_get_hdr_len(hdr), ip4_hdr_get_tos(hdr), + ip4_hdr_get_total_len(hdr), ip4_hdr_get_ipid(hdr), ip4_hdr_get_flags(hdr), + ip4_hdr_get_rf_flag(hdr), ip4_hdr_get_df_flag(hdr), ip4_hdr_get_mf_flag(hdr), + ip4_hdr_get_frag_offset(hdr), ip4_hdr_get_ttl(hdr), ip_proto_to_str(proto), + ip4_hdr_get_checksum(hdr), src_addr_str, dst_addr_str, ip4_hdr_get_opt_len(hdr)); +} + +/****************************************************************************** + * IPv6 + ******************************************************************************/ + +/* + * IPv6 Header Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Version| Traffic Class | Flow Label | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Payload Length | Next Header | Hop Limit | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + + + * | | + * + Source Address + + * | | + * + + + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + + + * | | + * + Destination Address + + * | | + * + + + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Fragment Header + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Next Header | Reserved | Fragment Offset |Res|M| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identification | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +static inline uint8_t ip6_hdr_get_version(const struct ip6_hdr *hdr) +{ + return (ntohl(hdr->ip6_flow) & 0xf0000000) >> 28; +} + +static inline uint8_t ip6_hdr_get_traffic_class(const struct ip6_hdr *hdr) +{ + return (ntohl(hdr->ip6_flow) & 0x0ff00000) >> 20; +} + +static inline uint32_t ip6_hdr_get_flow_label(const struct ip6_hdr *hdr) +{ + return ntohl(hdr->ip6_flow) & 0x000fffff; +} + +static inline uint16_t ip6_hdr_get_payload_len(const struct ip6_hdr *hdr) +{ + return ntohs(hdr->ip6_plen); +} + +static inline uint8_t ip6_hdr_get_next_header(const struct ip6_hdr *hdr) +{ + return hdr->ip6_nxt; +} + +static inline uint8_t ip6_hdr_get_hop_limit(const struct ip6_hdr *hdr) +{ + return hdr->ip6_hlim; +} + +static inline struct in6_addr ip6_hdr_get_src_in6_addr(const struct ip6_hdr *hdr) +{ + return hdr->ip6_src; +} + +static inline struct in6_addr ip6_hdr_get_dst_in6_addr(const struct ip6_hdr *hdr) +{ + return hdr->ip6_dst; +} + +static inline struct ip6_frag *ip6_hdr_get_frag_ext(const struct ip6_hdr *hdr) +{ + if (hdr->ip6_nxt != IPPROTO_FRAGMENT) + { + return NULL; + } + return (struct ip6_frag *)((char *)hdr + sizeof(struct ip6_hdr)); +} + +static inline void ip6_hdr_set_version(struct ip6_hdr *hdr, uint8_t version) +{ + hdr->ip6_flow = htonl((ntohl(hdr->ip6_flow) & 0x0fffffff) | (version << 28)); +} + +static inline void ip6_hdr_set_traffic_class(struct ip6_hdr *hdr, uint8_t traffic_class) +{ + hdr->ip6_flow = htonl((ntohl(hdr->ip6_flow) & 0xf00fffff) | (traffic_class << 20)); +} + +static inline void ip6_hdr_set_flow_label(struct ip6_hdr *hdr, uint32_t flow_label) +{ + hdr->ip6_flow = htonl((ntohl(hdr->ip6_flow) & 0xfff00000) | flow_label); +} + +static inline void ip6_hdr_set_payload_len(struct ip6_hdr *hdr, uint16_t payload_len) +{ + hdr->ip6_plen = htons(payload_len); +} + +static inline void ip6_hdr_set_next_header(struct ip6_hdr *hdr, uint8_t next_header) +{ + hdr->ip6_nxt = next_header; +} + +static inline void ip6_hdr_set_hop_limit(struct ip6_hdr *hdr, uint8_t hop_limit) +{ + hdr->ip6_hlim = hop_limit; +} + +static inline void ip6_hdr_set_src_in6_addr(struct ip6_hdr *hdr, struct in6_addr src_addr) +{ + hdr->ip6_src = src_addr; +} + +static inline void ip6_hdr_set_dst_in6_addr(struct ip6_hdr *hdr, struct in6_addr dst_addr) +{ + hdr->ip6_dst = dst_addr; +} + +static inline uint8_t ipv6_frag_get_next_header(const struct ip6_frag *frag) +{ + return frag->ip6f_nxt; +} + +static inline uint16_t ipv6_frag_get_offset(const struct ip6_frag *frag) +{ + return ntohs(frag->ip6f_offlg & IP6F_OFF_MASK); +} + +static inline uint32_t ipv6_frag_get_ident(const struct ip6_frag *frag) +{ + return ntohl(frag->ip6f_ident); +} + +static inline bool ipv6_frag_get_more(const struct ip6_frag *frag) +{ + return (frag->ip6f_offlg & IP6F_MORE_FRAG); +} + +static inline void ipv6_frag_set_next_header(struct ip6_frag *frag, uint8_t next_header) +{ + frag->ip6f_nxt = next_header; +} + +static inline void ipv6_frag_set_offset(struct ip6_frag *frag, uint16_t offset) +{ + frag->ip6f_offlg = (frag->ip6f_offlg & ~IP6F_OFF_MASK) | htons(offset); +} + +static inline void ipv6_frag_set_ident(struct ip6_frag *frag, uint32_t ident) +{ + frag->ip6f_ident = htonl(ident); +} + +static inline void ipv6_frag_set_more(struct ip6_frag *frag, bool more) +{ + if (more) + { + frag->ip6f_offlg |= IP6F_MORE_FRAG; + } + else + { + frag->ip6f_offlg &= ~IP6F_MORE_FRAG; + } +} + +static inline int ip6_hdr_to_str(const struct ip6_hdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + char src_addr_str[INET6_ADDRSTRLEN] = {0}; + char dst_addr_str[INET6_ADDRSTRLEN] = {0}; + + struct in6_addr src_addr = ip6_hdr_get_src_in6_addr(hdr); + struct in6_addr dst_addr = ip6_hdr_get_dst_in6_addr(hdr); + inet_ntop(AF_INET6, &src_addr, src_addr_str, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &dst_addr, dst_addr_str, INET6_ADDRSTRLEN); + + return snprintf(buf, size, "IPv6: version=%u traffic_class=%u flow_label=%u payload_len=%u next_header=%u hop_limit=%u src_addr=%s dst_addr=%s", + ip6_hdr_get_version(hdr), ip6_hdr_get_traffic_class(hdr), ip6_hdr_get_flow_label(hdr), ip6_hdr_get_payload_len(hdr), + ip6_hdr_get_next_header(hdr), ip6_hdr_get_hop_limit(hdr), src_addr_str, dst_addr_str); +} + +/****************************************************************************** + * L2TP + ******************************************************************************/ + +struct l2tp_hdr +{ + uint16_t flags; + // other option fields +}; + +#define L2TP_CONTROL_BIT 0x8000 +#define L2TP_LENGTH_BIT 0x4000 +#define L2TP_SEQUENCE_BIT 0x0800 +#define L2TP_OFFSET_BIT 0x0200 +#define L2TP_PRIORITY_BIT 0x0100 +#define L2TP_VERSION 0x000f + +static inline uint8_t l2tp_hdr_get_ver(const struct l2tp_hdr *hdr) +{ + return ntohs(hdr->flags) & L2TP_VERSION; +} + +// 1: control message +// 0: data message +static inline uint8_t l2tp_hdr_get_type(const struct l2tp_hdr *hdr) +{ + return (ntohs(hdr->flags) & L2TP_CONTROL_BIT) >> 15; +} + +/* + * Layer Two Tunneling Protocol "L2TP" (V2) + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Tunnel ID | Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ns (opt) | Nr (opt) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Offset Size (opt) | Offset pad... (opt) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://datatracker.ietf.org/doc/html/rfc2661 + */ + +static inline uint16_t calc_udp_l2tpv2_hdr_len(const char *data, uint16_t len) +{ + const struct l2tp_hdr *hdr = (const struct l2tp_hdr *)data; + uint16_t flags = ntohs(hdr->flags); + + // ctrl message + if (flags & L2TP_CONTROL_BIT) + { + if ((flags & L2TP_LENGTH_BIT) == 0 || (flags & L2TP_SEQUENCE_BIT) == 0 || + (flags & L2TP_OFFSET_BIT) != 0 || (flags & L2TP_PRIORITY_BIT) != 0) + { + return 0; + } + else + { + return ntohs(*((uint16_t *)(data + 2))); + } + } + // data message + else + { + uint16_t skip_len = 2; // skip flags field + if (flags & L2TP_LENGTH_BIT) + { + skip_len += 2; // skip length field + } + skip_len += 2; // skip tunnel id field + skip_len += 2; // skip session id field + if (flags & L2TP_SEQUENCE_BIT) + { + skip_len += 2; // skip ns field + skip_len += 2; // skip nr field + } + if (flags & L2TP_OFFSET_BIT) + { + if (skip_len + 2 > len) + { + return 0; + } + uint16_t offset = ntohs(*((uint16_t *)(data + skip_len))); + if (offset == 0) + { + skip_len += 2; // skip offset field + } + else + { + skip_len = offset; + } + } + return skip_len; + } +} + +/* + * Figure 4.1.1.1: L2TPv3 Session Header Over IP + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Cookie (optional, maximum 64 bits)... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Figure 4.1.1.2: L2TPv3 Control Message Header Over IP + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | (32 bits of zeros) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |T|L|x|x|S|x|x|x|x|x|x|x| Ver | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Control Connection ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ns | Nr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Note: Unlike L2TP over UDP, which uses the T bit to distinguish between + * L2TP control and data packets, L2TP over IP uses the reserved Session + * ID of zero (0) when sending control messages. + * + * https://www.rfc-editor.org/rfc/rfc3931.html + */ + +static inline uint16_t calc_ip_l2tpv3_hdr_len(const char *data, uint16_t len) +{ + if (len < 4) + { + return 0; + } + uint32_t session_id = ntohl(*((uint32_t *)data)); + // data message + if (session_id) + { + // TODO The optional Cookie field contains a variable-length value (maximum 64 bits) + // TODO L2-Specific Sublayer 4 bytes + return 4 + 4; + } + // control message + else + { + if (len < 16) + { + return 0; + } + uint16_t flags = ntohs(*((uint16_t *)(data + 4))); + if ((flags & L2TP_LENGTH_BIT) == 0 || (flags & L2TP_SEQUENCE_BIT) == 0) + { + return 0; + } + else + { + return ntohs(*((uint16_t *)(data + 4 + 2))); + } + } +} + +/* + * Layer Two Tunneling Protocol - Version 3 (L2TPv3) + * + * Figure 3.2.1: L2TP Control Message Header + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |T|L|x|x|S|x|x|x|x|x|x|x| Ver | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Control Connection ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ns | Nr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Figure 4.1.2.1: L2TPv3 Session Header over UDP + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |T|x|x|x|x|x|x|x|x|x|x|x| Ver | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Cookie (optional, maximum 64 bits)... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * https://www.rfc-editor.org/rfc/rfc3931.html + */ + +static inline uint16_t calc_udp_l2tpv3_hdr_len(const char *data, uint16_t len) +{ + if (len < 8) + { + return 0; + } + + const struct l2tp_hdr *hdr = (const struct l2tp_hdr *)data; + uint16_t flags = ntohs(hdr->flags); + + // ctrl message + if (flags & L2TP_CONTROL_BIT) + { + if ((flags & L2TP_LENGTH_BIT) == 0 || (flags & L2TP_SEQUENCE_BIT) == 0) + { + return 0; + } + else + { + return ntohs(*((uint16_t *)(data + 2))); + } + } + // data message + else + { + // TODO The optional Cookie field contains a variable-length value (maximum 64 bits) + // TODO L2-Specific Sublayer 4 bytes + return 8 + 4; + } +} + +static inline int l2tp_hdr_to_str(const struct l2tp_hdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + return snprintf(buf, size, "L2TP: type=%s version=%u", + l2tp_hdr_get_type(hdr) ? "control" : "data", l2tp_hdr_get_ver(hdr)); +} + +/****************************************************************************** + * MPLS + ******************************************************************************/ + +/* + * Reference: RFC 5462, RFC 3032 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Label | TC |S| TTL | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +static inline uint32_t mpls_label_get_label(const struct mpls_label *hdr) +{ + return ((ntohl(hdr->entry) & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT); +} + +static inline uint8_t mpls_label_get_tc(const struct mpls_label *hdr) +{ + return ((ntohl(hdr->entry) & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT); +} + +static inline uint8_t mpls_label_get_bos(const struct mpls_label *hdr) +{ + return ((ntohl(hdr->entry) & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT); +} + +static inline uint8_t mpls_label_get_ttl(const struct mpls_label *hdr) +{ + return ((ntohl(hdr->entry) & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT); +} + +static inline void mpls_label_set_label(struct mpls_label *hdr, uint32_t label) +{ + hdr->entry = htonl((ntohl(hdr->entry) & ~MPLS_LS_LABEL_MASK) | (label << MPLS_LS_LABEL_SHIFT)); +} + +static inline void mpls_label_set_tc(struct mpls_label *hdr, uint8_t tc) +{ + hdr->entry = htonl((ntohl(hdr->entry) & ~MPLS_LS_TC_MASK) | (tc << MPLS_LS_TC_SHIFT)); +} + +static inline void mpls_label_set_bos(struct mpls_label *hdr, uint8_t bos) +{ + hdr->entry = htonl((ntohl(hdr->entry) & ~MPLS_LS_S_MASK) | (bos << MPLS_LS_S_SHIFT)); +} + +static inline void mpls_label_set_ttl(struct mpls_label *hdr, uint8_t ttl) +{ + hdr->entry = htonl((ntohl(hdr->entry) & ~MPLS_LS_TTL_MASK) | (ttl << MPLS_LS_TTL_SHIFT)); +} + +static inline int mpls_label_to_str(const struct mpls_label *hdr, char *buf, size_t size) +{ + return snprintf(buf, size, "MPLS: label=%u tc=%u bos=%u ttl=%u", + mpls_label_get_label(hdr), mpls_label_get_tc(hdr), + mpls_label_get_bos(hdr), mpls_label_get_ttl(hdr)); +} + +/****************************************************************************** + * TCP + ******************************************************************************/ + +/* + * TCP Header Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source Port | Destination Port | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Acknowledgment Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Data | |U|A|P|R|S|F| | + * | Offset| Reserved |R|C|S|S|Y|I| Window | + * | | |G|K|H|T|N|N| | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Checksum | Urgent Pointer | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Options | Padding | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | data | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +static inline uint16_t tcp_hdr_get_src_port(const struct tcphdr *hdr) +{ + return ntohs(hdr->th_sport); +} + +static inline uint16_t tcp_hdr_get_dst_port(const struct tcphdr *hdr) +{ + return ntohs(hdr->th_dport); +} + +static inline uint32_t tcp_hdr_get_seq(const struct tcphdr *hdr) +{ + return ntohl(hdr->th_seq); +} + +static inline uint32_t tcp_hdr_get_ack(const struct tcphdr *hdr) +{ + return ntohl(hdr->th_ack); +} + +static inline uint8_t tcp_hdr_get_hdr_len(const struct tcphdr *hdr) +{ + return hdr->th_off << 2; +} + +static inline uint8_t tcp_hdr_get_flags(const struct tcphdr *hdr) +{ + return hdr->th_flags; +} + +static inline bool tcp_hdr_get_urg_flag(const struct tcphdr *hdr) +{ + return hdr->th_flags & TH_URG; +} + +static inline bool tcp_hdr_get_ack_flag(const struct tcphdr *hdr) +{ + return hdr->th_flags & TH_ACK; +} + +static inline bool tcp_hdr_get_push_flag(const struct tcphdr *hdr) +{ + return hdr->th_flags & TH_PUSH; +} + +static inline bool tcp_hdr_get_rst_flag(const struct tcphdr *hdr) +{ + return hdr->th_flags & TH_RST; +} + +static inline bool tcp_hdr_get_syn_flag(const struct tcphdr *hdr) +{ + return hdr->th_flags & TH_SYN; +} + +static inline bool tcp_hdr_get_fin_flag(const struct tcphdr *hdr) +{ + return hdr->th_flags & TH_FIN; +} + +static inline uint16_t tcp_hdr_get_window(const struct tcphdr *hdr) +{ + return ntohs(hdr->th_win); +} + +static inline uint16_t tcp_hdr_get_checksum(const struct tcphdr *hdr) +{ + return ntohs(hdr->th_sum); +} + +static inline uint16_t tcp_hdr_get_urg_ptr(const struct tcphdr *hdr) +{ + return ntohs(hdr->th_urp); +} + +static inline uint16_t tcp_hdr_get_opt_len(const struct tcphdr *hdr) +{ + return tcp_hdr_get_hdr_len(hdr) - sizeof(struct tcphdr); +} + +static inline const char *tcp_hdr_get_opt_data(const struct tcphdr *hdr) +{ + if (tcp_hdr_get_opt_len(hdr) == 0) + { + return NULL; + } + + return ((const char *)hdr) + sizeof(struct tcphdr); +} + +static inline void tcp_hdr_set_src_port(struct tcphdr *hdr, uint16_t port) +{ + hdr->th_sport = htons(port); +} + +static inline void tcp_hdr_set_dst_port(struct tcphdr *hdr, uint16_t port) +{ + hdr->th_dport = htons(port); +} + +static inline void tcp_hdr_set_seq(struct tcphdr *hdr, uint32_t seq) +{ + hdr->th_seq = htonl(seq); +} + +static inline void tcp_hdr_set_ack(struct tcphdr *hdr, uint32_t ack) +{ + hdr->th_ack = htonl(ack); +} + +static inline void tcp_hdr_set_hdr_len(struct tcphdr *hdr, uint8_t offset) +{ + hdr->th_off = offset >> 2; +} + +static inline void tcp_hdr_set_flags(struct tcphdr *hdr, uint8_t flags) +{ + hdr->th_flags = flags; +} + +static inline void tcp_hdr_set_urg_flag(struct tcphdr *hdr, bool flag) +{ + if (flag) + { + hdr->th_flags |= TH_URG; + } + else + { + hdr->th_flags &= ~TH_URG; + } +} + +static inline void tcp_hdr_set_ack_flag(struct tcphdr *hdr, bool flag) +{ + if (flag) + { + hdr->th_flags |= TH_ACK; + } + else + { + hdr->th_flags &= ~TH_ACK; + } +} + +static inline void tcp_hdr_set_push_flag(struct tcphdr *hdr, bool flag) +{ + if (flag) + { + hdr->th_flags |= TH_PUSH; + } + else + { + hdr->th_flags &= ~TH_PUSH; + } +} + +static inline void tcp_hdr_set_rst_flag(struct tcphdr *hdr, bool flag) +{ + if (flag) + { + hdr->th_flags |= TH_RST; + } + else + { + hdr->th_flags &= ~TH_RST; + } +} + +static inline void tcp_hdr_set_syn_flag(struct tcphdr *hdr, bool flag) +{ + if (flag) + { + hdr->th_flags |= TH_SYN; + } + else + { + hdr->th_flags &= ~TH_SYN; + } +} + +static inline void tcp_hdr_set_fin_flag(struct tcphdr *hdr, bool flag) +{ + if (flag) + { + hdr->th_flags |= TH_FIN; + } + else + { + hdr->th_flags &= ~TH_FIN; + } +} + +static inline void tcp_hdr_set_window(struct tcphdr *hdr, uint16_t window) +{ + hdr->th_win = htons(window); +} + +static inline void tcp_hdr_set_checksum(struct tcphdr *hdr, uint16_t checksum) +{ + hdr->th_sum = htons(checksum); +} + +static inline void tcp_hdr_set_urg_ptr(struct tcphdr *hdr, uint16_t ptr) +{ + hdr->th_urp = htons(ptr); +} + +static inline void tcp_hdr_set_opt_len(struct tcphdr *hdr, uint16_t len) +{ + hdr->th_off = (sizeof(struct tcphdr) + len) >> 2; +} + +// must be called after tcp_hdr_set_opt_len +static inline void tcp_hdr_set_opt_data(struct tcphdr *hdr, const char *ptr) +{ + memcpy((char *)hdr + sizeof(struct tcphdr), ptr, tcp_hdr_get_opt_len(hdr)); +} + +static inline int tcp_hdr_to_str(const struct tcphdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + return snprintf(buf, size, "TCP: src_port=%u dst_port=%u seq=%u ack=%u hdr_len=%u flags=0x%02x(%s%s%s%s%s%s) window=%u checksum=0x%x urg_ptr=%u opt_len=%u", + tcp_hdr_get_src_port(hdr), tcp_hdr_get_dst_port(hdr), + tcp_hdr_get_seq(hdr), tcp_hdr_get_ack(hdr), + tcp_hdr_get_hdr_len(hdr), tcp_hdr_get_flags(hdr), + tcp_hdr_get_urg_flag(hdr) ? "URG " : "", + tcp_hdr_get_ack_flag(hdr) ? "ACK " : "", + tcp_hdr_get_push_flag(hdr) ? "PSH " : "", + tcp_hdr_get_rst_flag(hdr) ? "RST " : "", + tcp_hdr_get_syn_flag(hdr) ? "SYN " : "", + tcp_hdr_get_fin_flag(hdr) ? "FIN " : "", + tcp_hdr_get_window(hdr), tcp_hdr_get_checksum(hdr), + tcp_hdr_get_urg_ptr(hdr), tcp_hdr_get_opt_len(hdr)); +} + +/****************************************************************************** + * UDP + ******************************************************************************/ + +/* + * User Datagram Header Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source Port | Destination Port | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Length | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Data | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +static inline uint16_t udp_hdr_get_src_port(const struct udphdr *hdr) +{ + return ntohs(hdr->uh_sport); +} + +static inline uint16_t udp_hdr_get_dst_port(const struct udphdr *hdr) +{ + return ntohs(hdr->uh_dport); +} + +static inline uint16_t udp_hdr_get_total_len(const struct udphdr *hdr) +{ + return ntohs(hdr->uh_ulen); +} + +static inline uint16_t udp_hdr_get_checksum(const struct udphdr *hdr) +{ + return ntohs(hdr->uh_sum); +} + +static inline void udp_hdr_set_src_port(struct udphdr *hdr, uint16_t port) +{ + hdr->uh_sport = htons(port); +} + +static inline void udp_hdr_set_dst_port(struct udphdr *hdr, uint16_t port) +{ + hdr->uh_dport = htons(port); +} + +static inline void udp_hdr_set_total_len(struct udphdr *hdr, uint16_t len) +{ + hdr->uh_ulen = htons(len); +} + +static inline void udp_hdr_set_checksum(struct udphdr *hdr, uint16_t sum) +{ + hdr->uh_sum = htons(sum); +} + +static inline int udp_hdr_to_str(const struct udphdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + return snprintf(buf, size, "UDP: src_port=%u dst_port=%u total_len=%u checksum=0x%x", + udp_hdr_get_src_port(hdr), udp_hdr_get_dst_port(hdr), + udp_hdr_get_total_len(hdr), udp_hdr_get_checksum(hdr)); +} + +/****************************************************************************** + * VLAN + ******************************************************************************/ + +/* + * VLAN Header Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Pri |I| VLAN ID | Ethertype | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +struct vlan_hdr +{ + uint16_t vlan_tci; + uint16_t vlan_ethertype; +}; + +static inline uint8_t vlan_hdr_get_priority(const struct vlan_hdr *hdr) +{ + return (ntohs(hdr->vlan_tci) & 0xe000) >> 13; +} + +static inline uint8_t vlan_hdr_get_dei(const struct vlan_hdr *hdr) +{ + return (ntohs(hdr->vlan_tci) & 0x1000) >> 12; +} + +static inline uint16_t vlan_hdr_get_vid(const struct vlan_hdr *hdr) +{ + return ntohs(hdr->vlan_tci) & 0x0fff; +} + +static inline uint16_t vlan_hdr_get_ethertype(const struct vlan_hdr *hdr) +{ + return ntohs(hdr->vlan_ethertype); +} + +static inline void vlan_hdr_set_priority(struct vlan_hdr *hdr, uint8_t priority) +{ + hdr->vlan_tci = htons((ntohs(hdr->vlan_tci) & ~0xe000) | (priority << 13)); +} + +static inline void vlan_hdr_set_dei(struct vlan_hdr *hdr, uint8_t dei) +{ + hdr->vlan_tci = htons((ntohs(hdr->vlan_tci) & ~0x1000) | (dei << 12)); +} + +static inline void vlan_hdr_set_vid(struct vlan_hdr *hdr, uint16_t vid) +{ + hdr->vlan_tci = htons((ntohs(hdr->vlan_tci) & ~0x0fff) | vid); +} + +static inline void vlan_hdr_set_ethertype(struct vlan_hdr *hdr, uint16_t ethertype) +{ + hdr->vlan_ethertype = htons(ethertype); +} + +static inline int vlan_hdr_to_str(const struct vlan_hdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + uint16_t proto = vlan_hdr_get_ethertype(hdr); + return snprintf(buf, size, "VLAN: priority=%u dei=%u id=%u ethertype=%s", + vlan_hdr_get_priority(hdr), vlan_hdr_get_dei(hdr), + vlan_hdr_get_vid(hdr), eth_proto_to_str(proto)); +} + +/****************************************************************************** + * VXLAN + ******************************************************************************/ + +/* + * VXLAN Header + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |R|R|R|R|I|R|R|R| Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | VXLAN Network Identifier (VNI) | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +struct vxlan_hdr +{ + uint32_t vxlan_flags; + uint32_t vxlan_vni; +}; + +static inline uint8_t vxlan_hdr_get_flags(const struct vxlan_hdr *hdr) +{ + return (ntohl(hdr->vxlan_flags) & 0xff000000) >> 24; +} + +static inline uint32_t vxlan_hdr_get_vni(const struct vxlan_hdr *hdr) +{ + return (ntohl(hdr->vxlan_vni) & 0xffffff00) >> 8; +} + +static inline void vxlan_hdr_set_flags(struct vxlan_hdr *hdr, uint8_t flags) +{ + hdr->vxlan_flags = htonl((ntohl(hdr->vxlan_flags) & ~0xff000000) | (flags << 24)); +} + +static inline void vxlan_hdr_set_vni(struct vxlan_hdr *hdr, uint32_t vni) +{ + hdr->vxlan_vni = htonl((ntohl(hdr->vxlan_vni) & ~0xffffff00) | (vni << 8)); +} + +static inline int vxlan_hdr_to_str(const struct vxlan_hdr *hdr, char *buf, size_t size) +{ + memset(buf, 0, size); + return snprintf(buf, size, "VXLAN: flags=%u vni=%u", + vxlan_hdr_get_flags(hdr), vxlan_hdr_get_vni(hdr)); +} + +#ifdef __cplusplus +} +#endif diff --git a/infra/packet_manager/packet_parser.c b/infra/packet_manager/packet_parser.c new file mode 100644 index 0000000..c206f19 --- /dev/null +++ b/infra/packet_manager/packet_parser.c @@ -0,0 +1,980 @@ +#include <string.h> +#include <stdlib.h> +#include <netinet/icmp6.h> +#include <netinet/ip_icmp.h> +#include <linux/ppp_defs.h> + +#include "log_private.h" +#include "packet_helper.h" +#include "packet_private.h" +#include "packet_parser.h" + +#define PACKET_PARSE_LOG_DEBUG(format, ...) // STELLAR_LOG_DEBUG(__thread_local_logger, "packet parse", format, ##__VA_ARGS__) +#define PACKET_PARSE_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet parse", format, ##__VA_ARGS__) +#define PACKET_PARSE_LOG_WARN(format, ...) STELLAR_LOG_WARN(__thread_local_logger, "packet parse", format, ##__VA_ARGS__) + +#define PACKET_LOG_DATA_INSUFFICIENCY(pkt, layer) \ + { \ + PACKET_PARSE_LOG_WARN("pkt: %p, layer: %s, data insufficiency", \ + (pkt), layer_proto_to_str(layer)); \ + } + +#define PACKET_LOG_UNSUPPORT_PROTO(pkt, layer, next_proto) \ + { \ + PACKET_PARSE_LOG_WARN("pkt: %p, layer: %s, unsupport next proto: %d", \ + (pkt), layer_proto_to_str(layer), (next_proto)); \ + } + +#define PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto) \ + { \ + PACKET_PARSE_LOG_WARN("pkt: %p, layer: L3, unsupport next proto: %d %s", \ + (pkt), (next_proto), eth_proto_to_str(next_proto)); \ + } + +#define PACKET_LOG_UNSUPPORT_IPPROTO(pkt, next_proto) \ + { \ + PACKET_PARSE_LOG_WARN("pkt: %p, layer: L4, unsupport next proto: %d %s", \ + (pkt), (next_proto), ip_proto_to_str(next_proto)); \ + } + +/****************************************************************************** + * Static API + ******************************************************************************/ + +static inline struct layer_private *get_free_layer(struct packet *pkt); + +// 数据链路层 +static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_pweth(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_l2tpv2_over_udp(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_l2tpv3_over_udp(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len); + +// 数据链路层 -- 隧道 +static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len); +// 网络层 +static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len); +// 网络层 -- 隧道 +static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len); +// 传输层 +static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_icmp(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint16_t len); +// 传输层 -- 隧道 +static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_gtp_u(struct packet *pkt, const char *data, uint16_t len); +static inline const char *parse_gtp_c(struct packet *pkt, const char *data, uint16_t len); +// L3/L4 +static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, const char *data, uint16_t len); +static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const char *data, uint16_t len); + +/****************************************************************************** + * Private API -- Utils + ******************************************************************************/ + +static inline struct layer_private *get_free_layer(struct packet *pkt) +{ + if (pkt->layers_used >= pkt->layers_size) + { + return NULL; + } + + return &pkt->layers[pkt->layers_used]; +} + +#define SET_LAYER(_pkt, _layer, _proto, _hdr_len, _data, _len, _trim) \ + { \ + (_layer)->proto = (_proto); \ + (_layer)->hdr_offset = (_pkt)->data_len - (_pkt)->trim_len - (_len); \ + (_layer)->hdr_ptr = (_data); \ + (_layer)->hdr_len = (_hdr_len); \ + (_layer)->pld_ptr = (_data) + (_hdr_len); \ + (_layer)->pld_len = (_len) - (_hdr_len) - (_trim); \ + (_pkt)->trim_len += (_trim); \ + (_pkt)->layers_used++; \ + PACKET_PARSE_LOG_DEBUG("layer[%d/%d]: %s, header: {offset: %d, ptr: %p, len: %d}, payload: {ptr: %p, len: %d}", \ + (_pkt)->layers_used - 1, (_pkt)->layers_size, layer_proto_to_str((_proto)), \ + (_layer)->hdr_offset, (_layer)->hdr_ptr, (_layer)->hdr_len, (_layer)->pld_ptr, (_layer)->pld_len); \ + } + +/****************************************************************************** + * Private API -- Parses + ******************************************************************************/ + +static inline const char *parse_ether(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct ethhdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ETHER); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + uint16_t next_proto = eth_hdr_get_proto((const struct ethhdr *)data); + SET_LAYER(pkt, layer, LAYER_PROTO_ETHER, sizeof(struct ethhdr), data, len, 0); + + return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_pweth(struct packet *pkt, const char *data, uint16_t len) +{ + /* + * PW Ethernet Control Word + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0 0 0 0| Reserved | Sequence Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Reference: https://tools.ietf.org/html/rfc4448 + */ + if (unlikely(len < 4)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PWETH); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_PWETH, 4, data, len, 0); + + return parse_ether(pkt, layer->pld_ptr, layer->pld_len); +} + +static inline int is_ppp_proto(uint16_t proto) +{ + // /usr/include/linux/ppp_defs.h.html + switch (proto) + { + case PPP_IP: /* Internet Protocol */ + case PPP_AT: /* AppleTalk Protocol */ + case PPP_IPX: /* IPX protocol */ + case PPP_VJC_COMP: /* VJ compressed TCP */ + case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ + case PPP_MP: /* Multilink protocol */ + case PPP_IPV6: /* Internet Protocol Version 6 */ + case PPP_COMPFRAG: /* fragment compressed below bundle */ + case PPP_COMP: /* compressed packet */ + case PPP_MPLS_UC: /* Multi Protocol Label Switching - Unicast */ + case PPP_MPLS_MC: /* Multi Protocol Label Switching - Multicast */ + case PPP_IPCP: /* IP Control Protocol */ + case PPP_ATCP: /* AppleTalk Control Protocol */ + case PPP_IPXCP: /* IPX Control Protocol */ + case PPP_IPV6CP: /* IPv6 Control Protocol */ + case PPP_CCPFRAG: /* CCP at link level (below MP bundle) */ + // case PPP_CCP: /* Compression Control Protocol */ (same as PPP_CCPFRAG) + case PPP_MPLSCP: /* MPLS Control Protocol */ + case PPP_LCP: /* Link Control Protocol */ + case PPP_PAP: /* Password Authentication Protocol */ + case PPP_LQR: /* Link Quality Report protocol */ + case PPP_CHAP: /* Cryptographic Handshake Auth. Protocol */ + case PPP_CBCP: /* Callback Control Protocol */ + return 1; + default: + return 0; + } +} + +static inline const char *parse_ppp(struct packet *pkt, const char *data, uint16_t len) +{ + /* + * https://datatracker.ietf.org/doc/html/rfc1661#section-2 + * +----------+-------------+---------+ + * | Protocol | Information | Padding | + * | 8/16 bits| * | * | + * +----------+-------------+---------+ + * + * https://datatracker.ietf.org/doc/html/rfc1331#section-3.1 + * +----------+----------+----------+----------+------------ + * | Flag | Address | Control | Protocol | Information + * | 01111110 | 11111111 | 00000011 | 16 bits | * + * +----------+----------+----------+----------+------------ + * ---+----------+----------+----------------- + * | FCS | Flag | Inter-frame Fill + * | 16 bits | 01111110 | or next Address + * ---+----------+----------+----------------- + */ + if (unlikely(len < 4)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PPP); + return data; + } + + uint16_t hdr_len = 0; + uint16_t next_proto = 0; + struct layer_private *layer = NULL; + + // ppp header 1 byte + next_proto = *((uint8_t *)data); + if (is_ppp_proto(next_proto)) + { + hdr_len = 1; + goto success; + } + + // ppp header 2 bytes + next_proto = ntohs(*((uint16_t *)data)); + if (is_ppp_proto(next_proto)) + { + hdr_len = 2; + goto success; + } + + // ppp header 4 bytes + next_proto = ntohs(*((uint16_t *)data + 1)); + hdr_len = 4; + +success: + layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_PPP, hdr_len, data, len, 0); + switch (next_proto) + { + case PPP_IP: + return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); + case PPP_IPV6: + return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); + default: + PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_PROTO_PPP, next_proto); + return layer->pld_ptr; + } +} + +static inline const char *parse_l2tpv2_over_udp(struct packet *pkt, const char *data, uint16_t len) +{ + uint16_t hdr_len = calc_udp_l2tpv2_hdr_len(data, len); + if (unlikely(hdr_len == 0 || hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0); + + // control message + if (l2tp_hdr_get_type((const struct l2tp_hdr *)data)) + { + return layer->pld_ptr; + } + // data message + else + { + return parse_ppp(pkt, layer->pld_ptr, layer->pld_len); + } +} + +static inline const char *parse_l2tpv3_over_udp(struct packet *pkt, const char *data, uint16_t len) +{ + uint16_t hdr_len = calc_udp_l2tpv3_hdr_len(data, len); + if (unlikely(hdr_len == 0 || hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0); + + // control message + if (l2tp_hdr_get_type((const struct l2tp_hdr *)data)) + { + return layer->pld_ptr; + } + // data message + else + { + // TOOD + return layer->pld_ptr; + } +} + +static inline const char *parse_l2tpv3_over_ip(struct packet *pkt, const char *data, uint16_t len) +{ + uint16_t hdr_len = calc_ip_l2tpv3_hdr_len(data, len); + if (unlikely(hdr_len == 0 || hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_L2TP); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_L2TP, hdr_len, data, len, 0); + + // data message + if (ntohl(*((uint32_t *)data))) + { + // TOOD + return layer->pld_ptr; + } + // control message + else + { + return layer->pld_ptr; + } +} + +static inline const char *parse_vlan(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct vlan_hdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_VLAN); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + uint16_t next_proto = vlan_hdr_get_ethertype((const struct vlan_hdr *)data); + SET_LAYER(pkt, layer, LAYER_PROTO_VLAN, sizeof(struct vlan_hdr), data, len, 0); + + return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_pppoe_ses(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < 6)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_PPPOE); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_PPPOE, 6, data, len, 0); + + return parse_ppp(pkt, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_mpls(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < 4)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_MPLS); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + + if (mpls_label_get_bos((const struct mpls_label *)data)) + { + SET_LAYER(pkt, layer, LAYER_PROTO_MPLS, 4, data, len, 0); + if (layer->pld_len == 0) + { + return layer->pld_ptr; + } + uint8_t next_proto = layer->pld_ptr[0] >> 4; + switch (next_proto) + { + case 0: + // the first four digits of the PW Ethernet control word must be "00000", but the first four digits of Ethernet may also be "0000" + if (layer->pld_len >= sizeof(struct ethhdr) && is_eth_proto(eth_hdr_get_proto((const struct ethhdr *)layer->pld_ptr))) + { + return parse_ether(pkt, layer->pld_ptr, layer->pld_len); + } + else + { + return parse_pweth(pkt, layer->pld_ptr, layer->pld_len); + } + case 4: + return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); + case 6: + return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); + default: + return parse_ether(pkt, layer->pld_ptr, layer->pld_len); + } + } + else + { + SET_LAYER(pkt, layer, LAYER_PROTO_MPLS, 4, data, len, 0); + return parse_mpls(pkt, layer->pld_ptr, layer->pld_len); + } +} + +static inline const char *parse_ipv4(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct ip))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + + const struct ip *hdr = (const struct ip *)data; + uint8_t version = ip4_hdr_get_version(hdr); + if (unlikely(version != 4)) + { + PACKET_PARSE_LOG_ERROR("packet %p ipv4 version %d != 4", pkt, version); + return data; + } + + uint16_t hdr_len = ip4_hdr_get_hdr_len(hdr); + if (unlikely(hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4); + return data; + } + + uint16_t total_len = ip4_hdr_get_total_len(hdr); + if (unlikely(total_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV4); + return data; + } + if (unlikely(total_len < hdr_len)) + { + PACKET_PARSE_LOG_ERROR("packet %p ip total_len %d < hdr_len %d", pkt, total_len, hdr_len); + return data; + } + uint16_t trim_len = len - total_len; + SET_LAYER(pkt, layer, LAYER_PROTO_IPV4, hdr_len, data, len, trim_len); + + // ip fragmented + if (ip4_hdr_get_mf_flag(hdr) || ip4_hdr_get_frag_offset(hdr)) + { + PACKET_PARSE_LOG_DEBUG("packet %p ip layer %p is fragmented", pkt, layer); + pkt->frag_layer = layer; + return layer->pld_ptr; + } + + uint8_t next_proto = ip4_hdr_get_proto(hdr); + return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_ipv6(struct packet *pkt, const char *data, uint16_t len) +{ + /* + * IP6 Extension Headers + * + * Internet Protocol, Version 6 (IPv6) : https://datatracker.ietf.org/doc/html/rfc2460 + * IP Encapsulating Security Payload (ESP) : https://datatracker.ietf.org/doc/html/rfc2406 + * IP Authentication Header : https://datatracker.ietf.org/doc/html/rfc4302 + * + * skip next header + * #define IPPROTO_HOPOPTS 0 // IP6 hop-by-hop options + * #define IPPROTO_ROUTING 43 // IP6 routing header + * #define IPPROTO_AH 51 // IP6 Auth Header + * #define IPPROTO_DSTOPTS 60 // IP6 destination option + * + * not skip next header + * #define IPPROTO_FRAGMENT 44 // IP6 fragmentation header + * #define IPPROTO_ESP 50 // IP6 Encap Sec. Payload + * #define IPPROTO_NONE 59 // IP6 no next header + */ + + if (unlikely(len < sizeof(struct ip6_hdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + const struct ip6_hdr *hdr = (const struct ip6_hdr *)data; + uint8_t version = ip6_hdr_get_version(hdr); + if (unlikely(version != 6)) + { + PACKET_PARSE_LOG_ERROR("packet %p ipv6 version %d != 6", pkt, version); + return data; + } + + uint16_t pld_len = ip6_hdr_get_payload_len(hdr); + if (unlikely(pld_len + sizeof(struct ip6_hdr) > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); + return data; + } + uint8_t next_proto = ip6_hdr_get_next_header(hdr); + uint16_t hdr_len = sizeof(struct ip6_hdr); + uint16_t trim_len = len - pld_len - sizeof(struct ip6_hdr); + const char *next_hdr_ptr = data + hdr_len; + while (next_proto == IPPROTO_HOPOPTS || next_proto == IPPROTO_ROUTING || next_proto == IPPROTO_AH || next_proto == IPPROTO_DSTOPTS) + { + if (unlikely(pld_len < 2)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); + return data; + } + struct ip6_ext *ext = (struct ip6_ext *)next_hdr_ptr; + uint16_t skip_len = 0; + if (next_proto == IPPROTO_AH) + { + /* + * https://datatracker.ietf.org/doc/html/rfc4302#section-2 + * For IPv6, the total length of the header must be a multiple of 8-octet units. + * (Note that although IPv6 [DH98] characterizes AH as an extension header, + * its length is measured in 32-bit words, not the 64-bit words used by other IPv6 extension headers.) + */ + skip_len = ext->ip6e_len * 4 + 8; + } + else + { + skip_len = ext->ip6e_len * 8 + 8; + } + if (unlikely(skip_len > pld_len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPV6); + return data; + } + hdr_len += skip_len; + pld_len -= skip_len; + next_hdr_ptr += skip_len; + next_proto = ext->ip6e_nxt; + } + SET_LAYER(pkt, layer, LAYER_PROTO_IPV6, hdr_len, data, len, trim_len); + + // ipv6 fragment + if (next_proto == IPPROTO_FRAGMENT) + { + PACKET_PARSE_LOG_DEBUG("packet %p ipv6 layer %p is fragmented", pkt, layer); + pkt->frag_layer = layer; + return layer->pld_ptr; + } + + return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_auth(struct packet *pkt, const char *data, uint16_t len) +{ + /* + * https://datatracker.ietf.org/doc/html/rfc4302#section-2 + * For IPv4: AH not IPv4 option, as an single layer + * For IPv6: AH as IPv6 extension header + * + * AH Format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Next Header | Payload Len | RESERVED | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Security Parameters Index (SPI) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number Field | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * + Integrity Check Value-ICV (variable) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + if (unlikely(len < 12)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPAH); + return data; + } + /* + * https://datatracker.ietf.org/doc/html/rfc4302#section-2 + * For IPv4, This 8-bit field specifies the length of AH in 32-bit words (4-byte units), minus "2". + * Thus, for example, if an integrity algorithm yields a 96-bit authentication value, + * this length field will be "4" (3 32-bit word fixed fields plus 3 32-bit words for the ICV, minus 2). + */ + uint8_t next_proto = ((const uint8_t *)data)[0]; + uint16_t hdr_len = ((const uint8_t *)data)[1] * 4 + 8; + if (unlikely(len < hdr_len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_IPAH); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_IPAH, hdr_len, data, len, 0); + + return parse_l4(pkt, next_proto, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_gre(struct packet *pkt, const char *data, uint16_t len) +{ + uint16_t hdr_len = calc_gre_hdr_len(data, len); + if (unlikely(hdr_len == 0 || hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GRE); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + uint16_t next_proto = peek_gre_proto(data, len); + SET_LAYER(pkt, layer, LAYER_PROTO_GRE, hdr_len, data, len, 0); + + return parse_l3(pkt, next_proto, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_udp(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct udphdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_UDP); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + const struct udphdr *udp_hdr = (struct udphdr *)data; + SET_LAYER(pkt, layer, LAYER_PROTO_UDP, sizeof(struct udphdr), data, len, 0); + + uint16_t src_port = udp_hdr_get_src_port(udp_hdr); + uint16_t dst_port = udp_hdr_get_dst_port(udp_hdr); + + if (dst_port == 4789) + { + // VXLAN_DPORT 4789 + return parse_vxlan(pkt, layer->pld_ptr, layer->pld_len); + } + + if (dst_port == 2152 || src_port == 2152) + { + // only GTPv1-U, no GTPv2-U + return parse_gtp_u(pkt, layer->pld_ptr, layer->pld_len); + } + + if (dst_port == 2123 || src_port == 2123) + { + // GTPv1-C or GTPv2-C + return parse_gtp_c(pkt, layer->pld_ptr, layer->pld_len); + } + + if (dst_port == 1701 || src_port == 1701) + { + // L2TP_DPORT 1701 + if (unlikely(layer->pld_len < 8)) + { + return layer->pld_ptr; + } + + switch (l2tp_hdr_get_ver((const struct l2tp_hdr *)layer->pld_ptr)) + { + case 2: + return parse_l2tpv2_over_udp(pkt, layer->pld_ptr, layer->pld_len); + case 3: + return parse_l2tpv3_over_udp(pkt, layer->pld_ptr, layer->pld_len); + default: + return layer->pld_ptr; + } + } + + if (dst_port == 3544 || src_port == 3544) + { + // Teredo IPv6 tunneling 3544 + if (unlikely(layer->pld_len < sizeof(struct ip6_hdr))) + { + return layer->pld_ptr; + } + const struct ip6_hdr *ipv6_hdr = (const struct ip6_hdr *)layer->pld_ptr; + if (ip6_hdr_get_version(ipv6_hdr) != 6) + { + return layer->pld_ptr; + } + return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); + } + + return layer->pld_ptr; +} + +static inline const char *parse_tcp(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct tcphdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_TCP); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + uint16_t hdr_len = tcp_hdr_get_hdr_len((const struct tcphdr *)data); + if (unlikely(hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_TCP); + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_TCP, hdr_len, data, len, 0); + + return layer->pld_ptr; +} + +static inline const char *parse_icmp(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct icmphdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ICMP); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_ICMP, sizeof(struct icmphdr), data, len, 0); + + return layer->pld_ptr; +} + +static inline const char *parse_icmp6(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct icmp6_hdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_ICMP6); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_ICMP6, sizeof(struct icmp6_hdr), data, len, 0); + + return layer->pld_ptr; +} + +static inline const char *parse_vxlan(struct packet *pkt, const char *data, uint16_t len) +{ + if (unlikely(len < sizeof(struct vxlan_hdr))) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_VXLAN); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_VXLAN, sizeof(struct vxlan_hdr), data, len, 0); + + return parse_ether(pkt, layer->pld_ptr, layer->pld_len); +} + +static inline const char *parse_gtp_u(struct packet *pkt, const char *data, uint16_t len) +{ + // only GTPv1-U, no GTPv2-U + uint8_t version = peek_gtp_version(data, len); + if (unlikely(version != 1)) + { + return data; + } + + uint16_t hdr_len = calc_gtp_hdr_len(data, len); + if (unlikely(hdr_len == 0 || hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GTP_U); + return data; + } + + uint8_t next_proto = (((const uint8_t *)(data + hdr_len))[0]) >> 4; + if (next_proto != 4 && next_proto != 6) + { + // next_proto is not IPv4 or IPv6, this is not a normal GTP-U packet, fallback to UDP + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_GTP_U, hdr_len, data, len, 0); + + switch (next_proto) + { + case 4: + return parse_ipv4(pkt, layer->pld_ptr, layer->pld_len); + case 6: + return parse_ipv6(pkt, layer->pld_ptr, layer->pld_len); + default: + PACKET_LOG_UNSUPPORT_PROTO(pkt, LAYER_PROTO_GTP_U, next_proto); + return layer->pld_ptr; + } +} + +static inline const char *parse_gtp_c(struct packet *pkt, const char *data, uint16_t len) +{ + // GTPv1-C or GTPv2-C + uint16_t hdr_len = calc_gtp_hdr_len(data, len); + if (unlikely(hdr_len == 0 || hdr_len > len)) + { + PACKET_LOG_DATA_INSUFFICIENCY(pkt, LAYER_PROTO_GTP_C); + return data; + } + + struct layer_private *layer = get_free_layer(pkt); + if (unlikely(layer == NULL)) + { + return data; + } + SET_LAYER(pkt, layer, LAYER_PROTO_GTP_C, hdr_len, data, len, 0); + + return layer->pld_ptr; +} + +static inline const char *parse_l3(struct packet *pkt, uint16_t next_proto, const char *data, uint16_t len) +{ + switch (next_proto) + { + case ETH_P_8021Q: + case ETH_P_8021AD: + return parse_vlan(pkt, data, len); + case ETH_P_IP: + return parse_ipv4(pkt, data, len); + case ETH_P_IPV6: + return parse_ipv6(pkt, data, len); + case ETH_P_PPP_SES: + return parse_pppoe_ses(pkt, data, len); + case ETH_P_MPLS_UC: + return parse_mpls(pkt, data, len); + case 0x880b: + return parse_ppp(pkt, data, len); + default: + PACKET_LOG_UNSUPPORT_ETHPROTO(pkt, next_proto); + return data; + } +} + +static inline const char *parse_l4(struct packet *pkt, uint8_t next_proto, const char *data, uint16_t len) +{ + switch (next_proto) + { + case IPPROTO_AH: + return parse_auth(pkt, data, len); + case IPPROTO_TCP: + return parse_tcp(pkt, data, len); + case IPPROTO_UDP: + return parse_udp(pkt, data, len); + case IPPROTO_IPIP: + return parse_ipv4(pkt, data, len); + case IPPROTO_IPV6: + return parse_ipv6(pkt, data, len); + case IPPROTO_GRE: + return parse_gre(pkt, data, len); + case IPPROTO_ICMP: + return parse_icmp(pkt, data, len); + case IPPROTO_ICMPV6: + return parse_icmp6(pkt, data, len); + case 115: + // L2TP + return parse_l2tpv3_over_ip(pkt, data, len); + default: + PACKET_LOG_UNSUPPORT_IPPROTO(pkt, next_proto); + return data; + } +} + +/****************************************************************************** + * Public API + ******************************************************************************/ + +// return innermost payload +const char *packet_parse(struct packet *pkt, const char *data, uint16_t len) +{ + pkt->frag_layer = NULL; + pkt->layers_used = 0; + pkt->layers_size = PACKET_MAX_LAYERS; + pkt->data_ptr = data; + pkt->data_len = len; + pkt->trim_len = 0; + + return parse_ether(pkt, data, len); +} + +const char *layer_proto_to_str(enum layer_proto proto) +{ + switch (proto) + { + case LAYER_PROTO_ETHER: + return "ETH"; + case LAYER_PROTO_PWETH: + return "PWETH"; + case LAYER_PROTO_PPP: + return "PPP"; + case LAYER_PROTO_L2TP: + return "L2TP"; + case LAYER_PROTO_VLAN: + return "VLAN"; + case LAYER_PROTO_PPPOE: + return "PPPOE"; + case LAYER_PROTO_MPLS: + return "MPLS"; + case LAYER_PROTO_IPV4: + return "IPV4"; + case LAYER_PROTO_IPV6: + return "IPV6"; + case LAYER_PROTO_IPAH: + return "IPAH"; + case LAYER_PROTO_GRE: + return "GRE"; + case LAYER_PROTO_UDP: + return "UDP"; + case LAYER_PROTO_TCP: + return "TCP"; + case LAYER_PROTO_ICMP: + return "ICMP"; + case LAYER_PROTO_ICMP6: + return "ICMP6"; + case LAYER_PROTO_VXLAN: + return "VXLAN"; + case LAYER_PROTO_GTP_C: + return "GTP-C"; + case LAYER_PROTO_GTP_U: + return "GTP-U"; + default: + return "UNKNOWN"; + } +}
\ No newline at end of file diff --git a/infra/packet_manager/packet_parser.h b/infra/packet_manager/packet_parser.h new file mode 100644 index 0000000..d85ed1c --- /dev/null +++ b/infra/packet_manager/packet_parser.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "stellar/packet.h" + +const char *packet_parse(struct packet *pkt, const char *data, uint16_t len); +const char *layer_proto_to_str(enum layer_proto proto); + +#ifdef __cplusplus +} +#endif diff --git a/infra/packet_manager/packet_private.h b/infra/packet_manager/packet_private.h new file mode 100644 index 0000000..69a2fb3 --- /dev/null +++ b/infra/packet_manager/packet_private.h @@ -0,0 +1,149 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "tuple.h" +#include "stellar/packet.h" + +#define PACKET_MAX_LAYERS 32 + +#define MAX_ROUTE_CTX 64 +struct route_ctx +{ + char data[MAX_ROUTE_CTX]; + int used; +}; + +struct metadata +{ + struct route_ctx route_ctx; + struct sids sids; + + uint64_t session_id; + uint64_t domain; + uint16_t link_id; + int is_ctrl; + + enum packet_direction direction; + enum packet_action action; + struct timeval tv; + const void *origin_ctx; +}; + +struct layer_private +{ + enum layer_proto proto; + + uint16_t hdr_len; // header length + const char *hdr_ptr; // header pointer + + uint16_t pld_len; // payload length + const char *pld_ptr; // payload pointer + + uint16_t hdr_offset; // header offset from data_ptr +}; + +struct packet +{ + void *user_data; + struct layer_private layers[PACKET_MAX_LAYERS]; + struct layer_private *frag_layer; // fragment layer + int8_t layers_used; + int8_t layers_size; + int8_t need_free; + + const char *data_ptr; + uint16_t data_len; + uint16_t trim_len; // trim eth padding + + struct metadata meta; +}; + +enum packet_load_balance_method +{ + PKT_LDBC_METH_OUTERMOST_INT_IP = 1, + PKT_LDBC_METH_OUTERMOST_EXT_IP = 2, + PKT_LDBC_METH_OUTERMOST_INT_EXT_IP = 3, + PKT_LDBC_METH_INNERMOST_INT_IP = 4, + PKT_LDBC_METH_INNERMOST_EXT_IP = 5, +}; + +/****************************************************************************** + * metadata utils + ******************************************************************************/ + +void packet_set_route_ctx(struct packet *pkt, const struct route_ctx *ctx); +const struct route_ctx *packet_get_route_ctx(const struct packet *pkt); + +void packet_set_origin_ctx(struct packet *pkt, void *ctx); +const void *packet_get_origin_ctx(const struct packet *pkt); + +void packet_set_sids(struct packet *pkt, const struct sids *sids); +const struct sids *packet_get_sids(const struct packet *pkt); + +void packet_set_session_id(struct packet *pkt, uint64_t id); +uint64_t packet_get_session_id(const struct packet *pkt); + +void packet_set_domain(struct packet *pkt, uint64_t domain); +uint64_t packet_get_domain(const struct packet *pkt); + +void packet_set_link_id(struct packet *pkt, uint16_t id); +uint16_t packet_get_link_id(const struct packet *pkt); + +void packet_set_ctrl(struct packet *pkt, uint8_t ctrl); +uint8_t packet_is_ctrl(const struct packet *pkt); + +void packet_set_direction(struct packet *pkt, enum packet_direction dir); + +void *packet_get_user_data(struct packet *pkt); +void packet_set_user_data(struct packet *pkt, void *data); + +/****************************************************************************** + * tuple uitls + ******************************************************************************/ + +// return 0: found +// return -1: not found +int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple); +int packet_get_outermost_tuple2(const struct packet *pkt, struct tuple2 *tuple); + +// return 0: found +// return -1: not found +int packet_get_innermost_tuple4(const struct packet *pkt, struct tuple4 *tuple); +int packet_get_outermost_tuple4(const struct packet *pkt, struct tuple4 *tuple); + +// return 0: found +// return -1: not found +int packet_get_innermost_tuple6(const struct packet *pkt, struct tuple6 *tuple); +int packet_get_outermost_tuple6(const struct packet *pkt, struct tuple6 *tuple); + +/****************************************************************************** + * layer uitls + ******************************************************************************/ + +const struct layer_private *packet_get_layer(const struct packet *pkt, int idx); +const struct layer_private *packet_get_innermost_layer(const struct packet *pkt, enum layer_proto proto); +const struct layer_private *packet_get_outermost_layer(const struct packet *pkt, enum layer_proto proto); + +/****************************************************************************** + * load balance uitls + ******************************************************************************/ + +uint64_t packet_ldbc_hash(const struct packet *pkt, enum packet_load_balance_method method, enum packet_direction direction); + +/****************************************************************************** + * other uitls + ******************************************************************************/ + +struct packet *packet_new(uint16_t pkt_len); +struct packet *packet_dup(const struct packet *pkt); +void packet_free(struct packet *pkt); + +int packet_is_fragment(const struct packet *pkt); + +#ifdef __cplusplus +} +#endif diff --git a/infra/packet_manager/packet_utils.c b/infra/packet_manager/packet_utils.c new file mode 100644 index 0000000..79485ec --- /dev/null +++ b/infra/packet_manager/packet_utils.c @@ -0,0 +1,931 @@ +#include "tuple.h" +#include "uthash.h" +#include "log_private.h" +#include "packet_helper.h" +#include "packet_private.h" + +#define PACKET_LOG_ERROR(format, ...) STELLAR_LOG_ERROR(__thread_local_logger, "packet", format, ##__VA_ARGS__) + +/****************************************************************************** + * metadata utils + ******************************************************************************/ + +void packet_set_route_ctx(struct packet *pkt, const struct route_ctx *ctx) +{ + pkt->meta.route_ctx = *ctx; +} + +const struct route_ctx *packet_get_route_ctx(const struct packet *pkt) +{ + return &pkt->meta.route_ctx; +} + +void packet_set_origin_ctx(struct packet *pkt, void *ctx) +{ + pkt->meta.origin_ctx = ctx; +} + +const void *packet_get_origin_ctx(const struct packet *pkt) +{ + return pkt->meta.origin_ctx; +} + +void packet_set_sids(struct packet *pkt, const struct sids *sids) +{ + pkt->meta.sids = *sids; +} + +const struct sids *packet_get_sids(const struct packet *pkt) +{ + return &pkt->meta.sids; +} + +void packet_prepend_sids(struct packet *pkt, const struct sids *sids) +{ + if (pkt->meta.sids.used + sids->used > MAX_SIDS) + { + PACKET_LOG_ERROR("sids overflow"); + return; + } + else + { + for (int i = pkt->meta.sids.used - 1; i >= 0; i--) + { + pkt->meta.sids.sid[i + sids->used] = pkt->meta.sids.sid[i]; + } + for (int i = 0; i < sids->used; i++) + { + pkt->meta.sids.sid[i] = sids->sid[i]; + } + pkt->meta.sids.used += sids->used; + } +} + +void packet_set_session_id(struct packet *pkt, uint64_t id) +{ + pkt->meta.session_id = id; +} + +uint64_t packet_get_session_id(const struct packet *pkt) +{ + return pkt->meta.session_id; +} + +void packet_set_domain(struct packet *pkt, uint64_t domain) +{ + pkt->meta.domain = domain; +} + +uint64_t packet_get_domain(const struct packet *pkt) +{ + return pkt->meta.domain; +} + +void packet_set_link_id(struct packet *pkt, uint16_t id) +{ + pkt->meta.link_id = id; +} + +uint16_t packet_get_link_id(const struct packet *pkt) +{ + return pkt->meta.link_id; +} + +void packet_set_ctrl(struct packet *pkt, uint8_t ctrl) +{ + pkt->meta.is_ctrl = ctrl; +} + +uint8_t packet_is_ctrl(const struct packet *pkt) +{ + return pkt->meta.is_ctrl; +} + +void packet_set_direction(struct packet *pkt, enum packet_direction dir) +{ + pkt->meta.direction = dir; +} + +enum packet_direction packet_get_direction(const struct packet *pkt) +{ + return pkt->meta.direction; +} + +void packet_set_action(struct packet *pkt, enum packet_action action) +{ + pkt->meta.action = action; +} + +enum packet_action packet_get_action(const struct packet *pkt) +{ + return pkt->meta.action; +} + +void packet_set_timeval(struct packet *pkt, const struct timeval *tv) +{ + pkt->meta.tv = *tv; +} + +const struct timeval *packet_get_timeval(const struct packet *pkt) +{ + return &pkt->meta.tv; +} + +void packet_set_user_data(struct packet *pkt, void *data) +{ + pkt->user_data = data; +} + +void *packet_get_user_data(struct packet *pkt) +{ + return pkt->user_data; +} + +/****************************************************************************** + * tuple uitls + ******************************************************************************/ + +// return 0 : found +// return -1 : not found +int packet_get_innermost_tuple2(const struct packet *pkt, struct tuple2 *tuple) +{ + memset(tuple, 0, sizeof(struct tuple2)); + const struct layer_private *layer = NULL; + + for (int8_t i = pkt->layers_used - 1; i >= 0; i--) + { + layer = &pkt->layers[i]; + + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; + tuple->addr_family = AF_INET; + tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); + tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); + return 0; + } + if (layer->proto == LAYER_PROTO_IPV6) + { + const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; + tuple->addr_family = AF_INET6; + tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); + tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); + return 0; + } + } + + return -1; +} + +// return 0 : found +// return -1 : not found +int packet_get_outermost_tuple2(const struct packet *pkt, struct tuple2 *tuple) +{ + memset(tuple, 0, sizeof(struct tuple2)); + const struct layer_private *layer = NULL; + + for (int8_t i = 0; i < pkt->layers_used; i++) + { + layer = &pkt->layers[i]; + + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; + tuple->addr_family = AF_INET; + tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); + tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); + return 0; + } + if (layer->proto == LAYER_PROTO_IPV6) + { + const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; + tuple->addr_family = AF_INET6; + tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); + tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); + return 0; + } + } + + return -1; +} + +// return 0 : found +// return -1 : not found +int packet_get_innermost_tuple4(const struct packet *pkt, struct tuple4 *tuple) +{ + memset(tuple, 0, sizeof(struct tuple4)); + const struct layer_private *layer_l3 = NULL; + const struct layer_private *layer_l4 = NULL; + const struct layer_private *layer = NULL; + + for (int8_t i = pkt->layers_used - 1; i >= 0; i--) + { + layer = &pkt->layers[i]; + + // first get L4 layer + if (layer->proto == LAYER_PROTO_UDP) + { + const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; + tuple->src_port = udp_hdr->uh_sport; + tuple->dst_port = udp_hdr->uh_dport; + layer_l4 = layer; + continue; + } + if (layer->proto == LAYER_PROTO_TCP) + { + const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; + tuple->src_port = tcp_hdr->th_sport; + tuple->dst_port = tcp_hdr->th_dport; + layer_l4 = layer; + continue; + } + + // second get L3 layer + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; + tuple->addr_family = AF_INET; + tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); + tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); + layer_l3 = layer; + break; + } + if (layer->proto == LAYER_PROTO_IPV6) + { + const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; + tuple->addr_family = AF_INET6; + tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); + tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); + layer_l3 = layer; + break; + } + } + + if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) + { + return 0; + } + else + { + return -1; + } +} + +// return 0 : found +// return -1 : not found +int packet_get_outermost_tuple4(const struct packet *pkt, struct tuple4 *tuple) +{ + memset(tuple, 0, sizeof(struct tuple4)); + const struct layer_private *layer_l3 = NULL; + const struct layer_private *layer_l4 = NULL; + const struct layer_private *layer = NULL; + + for (int8_t i = 0; i < pkt->layers_used; i++) + { + layer = &pkt->layers[i]; + + // first get L3 layer + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; + tuple->addr_family = AF_INET; + tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); + tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); + layer_l3 = layer; + continue; + } + if (layer->proto == LAYER_PROTO_IPV6) + { + const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; + tuple->addr_family = AF_INET6; + tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); + tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); + layer_l3 = layer; + continue; + } + + // second get L4 layer + if (layer->proto == LAYER_PROTO_UDP) + { + const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; + tuple->src_port = udp_hdr->uh_sport; + tuple->dst_port = udp_hdr->uh_dport; + layer_l4 = layer; + break; + } + if (layer->proto == LAYER_PROTO_TCP) + { + const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; + tuple->src_port = tcp_hdr->th_sport; + tuple->dst_port = tcp_hdr->th_dport; + layer_l4 = layer; + break; + } + } + + if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) + { + return 0; + } + else + { + return -1; + } +} + +// return 0 : found +// return -1 : not found +int packet_get_innermost_tuple6(const struct packet *pkt, struct tuple6 *tuple) +{ + memset(tuple, 0, sizeof(struct tuple6)); + const struct layer_private *layer_l3 = NULL; + const struct layer_private *layer_l4 = NULL; + const struct layer_private *layer = NULL; + + for (int8_t i = pkt->layers_used - 1; i >= 0; i--) + { + layer = &pkt->layers[i]; + + // first get L4 layer + if (layer->proto == LAYER_PROTO_UDP) + { + const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; + tuple->ip_proto = IPPROTO_UDP; + tuple->src_port = udp_hdr->uh_sport; + tuple->dst_port = udp_hdr->uh_dport; + layer_l4 = layer; + continue; + } + if (layer->proto == LAYER_PROTO_TCP) + { + const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; + tuple->ip_proto = IPPROTO_TCP; + tuple->src_port = tcp_hdr->th_sport; + tuple->dst_port = tcp_hdr->th_dport; + layer_l4 = layer; + continue; + } + + // second get L3 layer + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; + tuple->addr_family = AF_INET; + tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); + tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); + layer_l3 = layer; + break; + } + if (layer->proto == LAYER_PROTO_IPV6) + { + const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; + tuple->addr_family = AF_INET6; + tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); + tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); + layer_l3 = layer; + break; + } + } + + if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) + { + tuple->domain = packet_get_domain(pkt); + return 0; + } + else + { + return -1; + } +} + +// return 0 : found +// return -1 : not found +int packet_get_outermost_tuple6(const struct packet *pkt, struct tuple6 *tuple) +{ + memset(tuple, 0, sizeof(struct tuple6)); + const struct layer_private *layer_l3 = NULL; + const struct layer_private *layer_l4 = NULL; + const struct layer_private *layer = NULL; + + for (int8_t i = 0; i < pkt->layers_used; i++) + { + layer = &pkt->layers[i]; + + // first get L3 layer + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip4_hdr = (const struct ip *)layer->hdr_ptr; + tuple->addr_family = AF_INET; + tuple->src_addr.v4 = ip4_hdr_get_src_in_addr(ip4_hdr); + tuple->dst_addr.v4 = ip4_hdr_get_dst_in_addr(ip4_hdr); + layer_l3 = layer; + continue; + } + if (layer->proto == LAYER_PROTO_IPV6) + { + const struct ip6_hdr *ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr; + tuple->addr_family = AF_INET6; + tuple->src_addr.v6 = ip6_hdr_get_src_in6_addr(ip6_hdr); + tuple->dst_addr.v6 = ip6_hdr_get_dst_in6_addr(ip6_hdr); + layer_l3 = layer; + continue; + } + + // second get L4 layer + if (layer->proto == LAYER_PROTO_UDP) + { + const struct udphdr *udp_hdr = (const struct udphdr *)layer->hdr_ptr; + tuple->ip_proto = IPPROTO_UDP; + tuple->src_port = udp_hdr->uh_sport; + tuple->dst_port = udp_hdr->uh_dport; + layer_l4 = layer; + break; + } + if (layer->proto == LAYER_PROTO_TCP) + { + const struct tcphdr *tcp_hdr = (const struct tcphdr *)layer->hdr_ptr; + tuple->ip_proto = IPPROTO_TCP; + tuple->src_port = tcp_hdr->th_sport; + tuple->dst_port = tcp_hdr->th_dport; + layer_l4 = layer; + break; + } + } + + if (layer_l3 && layer_l4 && layer_l4 - layer_l3 == 1) + { + tuple->domain = packet_get_domain(pkt); + return 0; + } + else + { + return -1; + } +} + +/****************************************************************************** + * layer uitls + ******************************************************************************/ + +int packet_get_layer_count(const struct packet *pkt) +{ + return pkt->layers_used; +} + +const struct layer *packet_get_layer_by_idx(const struct packet *pkt, int idx) +{ + const struct layer_private *layer = packet_get_layer(pkt, idx); + if (layer == NULL) + { + return NULL; + } + else + { + return (const struct layer *)layer; + } +} + +const struct layer_private *packet_get_layer(const struct packet *pkt, int idx) +{ + if (idx < 0 || idx >= pkt->layers_used) + { + return NULL; + } + return &pkt->layers[idx]; +} + +const struct layer_private *packet_get_innermost_layer(const struct packet *pkt, enum layer_proto proto) +{ + const struct layer_private *layer = NULL; + + for (int8_t i = pkt->layers_used - 1; i >= 0; i--) + { + layer = &pkt->layers[i]; + if (layer->proto == proto) + { + return layer; + } + } + + return NULL; +} + +const struct layer_private *packet_get_outermost_layer(const struct packet *pkt, enum layer_proto proto) +{ + const struct layer_private *layer = NULL; + + for (int8_t i = 0; i < pkt->layers_used; i++) + { + layer = &pkt->layers[i]; + if (layer->proto == proto) + { + return layer; + } + } + + return NULL; +} + +/****************************************************************************** + * tunnel uitls + ******************************************************************************/ + +struct tunnel_detector +{ + enum tunnel_type type; + int contain_layers; + int (*identify_func)(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2); +}; + +static int is_ipv4_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2 __attribute__((unused))) +{ + if (curr && curr->proto == LAYER_PROTO_IPV4 && + next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6)) + { + return 1; + } + + return 0; +} + +static int is_ipv6_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2 __attribute__((unused))) +{ + if (curr && curr->proto == LAYER_PROTO_IPV6 && + next1 && (next1->proto == LAYER_PROTO_IPV4 || next1->proto == LAYER_PROTO_IPV6)) + { + return 1; + } + + return 0; +} + +static int is_gre_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2 __attribute__((unused))) +{ + if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && + next1 && next1->proto == LAYER_PROTO_GRE) + { + return 1; + } + + return 0; +} + +static int is_gtp_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) +{ + if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && + next1 && next1->proto == LAYER_PROTO_UDP && + next2 && next2->proto == LAYER_PROTO_GTP_U) + { + return 1; + } + + return 0; +} + +static int is_vxlan_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) +{ + if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && + next1 && next1->proto == LAYER_PROTO_UDP && + next2 && next2->proto == LAYER_PROTO_VXLAN) + { + return 1; + } + + return 0; +} + +static int is_l2tp_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) +{ + if (curr && (curr->proto == LAYER_PROTO_IPV4 || curr->proto == LAYER_PROTO_IPV6) && + next1 && next1->proto == LAYER_PROTO_UDP && + next2 && next2->proto == LAYER_PROTO_L2TP) + { + return 1; + } + + return 0; +} + +static int is_teredo_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) +{ + if (curr && curr->proto == LAYER_PROTO_IPV4 && + next1 && next1->proto == LAYER_PROTO_UDP && + next2 && next2->proto == LAYER_PROTO_IPV6) + { + return 1; + } + + return 0; +} + +static struct tunnel_detector detectors[] = { + {TUNNEL_IPV4, 1, is_ipv4_tunnel}, + {TUNNEL_IPV6, 1, is_ipv6_tunnel}, + {TUNNEL_GRE, 2, is_gre_tunnel}, + {TUNNEL_GTP, 3, is_gtp_tunnel}, + {TUNNEL_VXLAN, 3, is_vxlan_tunnel}, + {TUNNEL_L2TP, 3, is_l2tp_tunnel}, + {TUNNEL_TEREDO, 2, is_teredo_tunnel}, +}; + +// return index of detectors +static int detect_tunnel(const struct layer_private *curr, const struct layer_private *next1, const struct layer_private *next2) +{ + for (int i = 0; i < (int)(sizeof(detectors) / sizeof(detectors[0])); i++) + { + if (detectors[i].identify_func(curr, next1, next2)) + { + return i; + } + } + + return -1; +} + +int packet_get_tunnel_count(const struct packet *pkt) +{ + int count = 0; + int used = packet_get_layer_count(pkt); + const struct layer_private *curr = NULL; + const struct layer_private *next1 = NULL; + const struct layer_private *next2 = NULL; + + for (int i = 0; i < used; i++) + { + curr = packet_get_layer(pkt, i); + next1 = packet_get_layer(pkt, i + 1); + next2 = packet_get_layer(pkt, i + 2); + if (detect_tunnel(curr, next1, next2) >= 0) + { + count++; + } + } + + return count; +} + +// return 0: success +// return -1: failed +int packet_get_tunnel_by_idx(const struct packet *pkt, int idx, struct tunnel *out) +{ + int ret = -1; + int count = 0; + int used = packet_get_layer_count(pkt); + const struct layer_private *curr = NULL; + const struct layer_private *next1 = NULL; + const struct layer_private *next2 = NULL; + memset(out, 0, sizeof(struct tunnel)); + + for (int i = 0; i < used; i++) + { + curr = packet_get_layer(pkt, i); + next1 = packet_get_layer(pkt, i + 1); + next2 = packet_get_layer(pkt, i + 2); + ret = detect_tunnel(curr, next1, next2); + if (ret >= 0 && count++ == idx) + { + struct tunnel_detector *hit = &detectors[ret]; + out->type = hit->type; + out->layer_count = hit->contain_layers; + if (out->layer_count >= 1) + out->layers[0] = (const struct layer *)curr; + if (out->layer_count >= 2) + out->layers[1] = (const struct layer *)next1; + if (out->layer_count >= 3) + out->layers[2] = (const struct layer *)next2; + return 0; + } + } + + return -1; +} + +/****************************************************************************** + * load balance uitls + ******************************************************************************/ + +uint64_t packet_ldbc_hash(const struct packet *pkt, enum packet_load_balance_method method, enum packet_direction direction) +{ + uint64_t temp = 0; + uint64_t hash_value = 1; + + int inner_addr_len = 0; + int outer_addr_len = 0; + const char *inner_src_addr = NULL; + const char *inner_dst_addr = NULL; + const char *outer_src_addr = NULL; + const char *outer_dst_addr = NULL; + + struct tuple2 inner_addr; + struct tuple2 outer_addr; + + if (pkt == NULL) + { + return hash_value; + } + + if (packet_get_innermost_tuple2(pkt, &inner_addr) == -1) + { + return hash_value; + } + + if (packet_get_outermost_tuple2(pkt, &outer_addr) == -1) + { + return hash_value; + } + + if (inner_addr.addr_family == AF_INET) + { + inner_src_addr = (const char *)&inner_addr.src_addr.v4; + inner_dst_addr = (const char *)&inner_addr.dst_addr.v4; + inner_addr_len = sizeof(struct in_addr); + } + else + { + inner_src_addr = (const char *)&inner_addr.src_addr.v6; + inner_dst_addr = (const char *)&inner_addr.dst_addr.v6; + inner_addr_len = sizeof(struct in6_addr); + } + + if (outer_addr.addr_family == AF_INET) + { + outer_src_addr = (const char *)&outer_addr.src_addr.v4; + outer_dst_addr = (const char *)&outer_addr.dst_addr.v4; + outer_addr_len = sizeof(struct in_addr); + } + else + { + outer_src_addr = (const char *)&outer_addr.src_addr.v6; + outer_dst_addr = (const char *)&outer_addr.dst_addr.v6; + outer_addr_len = sizeof(struct in6_addr); + } + + switch (method) + { + case PKT_LDBC_METH_OUTERMOST_INT_IP: + if (direction == PACKET_DIRECTION_INCOMING) + { + // direction 1: E2I + HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value); + } + else + { + // direction 0: I2E + HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); + } + break; + case PKT_LDBC_METH_OUTERMOST_EXT_IP: + if (direction == PACKET_DIRECTION_INCOMING) + { + // direction 1: E2I + HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); + } + else + { + // direction 0: I2E + HASH_VALUE(outer_dst_addr, outer_addr_len, hash_value); + } + break; + case PKT_LDBC_METH_OUTERMOST_INT_EXT_IP: + HASH_VALUE(outer_src_addr, outer_addr_len, hash_value); + HASH_VALUE(outer_dst_addr, outer_addr_len, temp); + hash_value = hash_value ^ temp; + break; + case PKT_LDBC_METH_INNERMOST_INT_IP: + if (direction == PACKET_DIRECTION_INCOMING) + { + // direction 1: E2I + HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value); + } + else + { + // direction 0: I2E + HASH_VALUE(inner_src_addr, inner_addr_len, hash_value); + } + break; + case PKT_LDBC_METH_INNERMOST_EXT_IP: + if (direction == PACKET_DIRECTION_INCOMING) + { + // direction 1: E2I + HASH_VALUE(inner_src_addr, inner_addr_len, hash_value); + } + else + { + // direction 0: I2E + HASH_VALUE(inner_dst_addr, inner_addr_len, hash_value); + } + break; + default: + return hash_value; + } + + return hash_value; +} + +/****************************************************************************** + * other uitls + ******************************************************************************/ + +const char *packet_get_raw_data(const struct packet *pkt) +{ + return pkt->data_ptr; +} + +uint16_t packet_get_raw_len(const struct packet *pkt) +{ + return pkt->data_len; +} + +const char *packet_get_payload(const struct packet *pkt) +{ + if (pkt == NULL || pkt->layers_used == 0) + { + return NULL; + } + + if (pkt->layers[pkt->layers_used - 1].pld_len) + { + return pkt->layers[pkt->layers_used - 1].pld_ptr; + } + else + { + return NULL; + } +} + +uint16_t packet_get_payload_len(const struct packet *pkt) +{ + if (pkt == NULL || pkt->layers_used == 0) + { + return 0; + } + return pkt->layers[pkt->layers_used - 1].pld_len; +} + +struct packet *packet_new(uint16_t pkt_len) +{ + struct packet *pkt = (struct packet *)calloc(1, sizeof(struct packet) + pkt_len); + if (pkt == NULL) + { + return NULL; + } + pkt->data_len = pkt_len; + pkt->data_ptr = (const char *)pkt + sizeof(struct packet); + pkt->need_free = 1; + + return pkt; +} + +struct packet *packet_dup(const struct packet *pkt) +{ + if (pkt == NULL) + { + return NULL; + } + + struct packet *dup_pkt = packet_new(pkt->data_len); + if (dup_pkt == NULL) + { + return NULL; + } + + dup_pkt->layers_used = pkt->layers_used; + dup_pkt->layers_size = pkt->layers_size; + + memcpy((char *)dup_pkt->data_ptr, pkt->data_ptr, pkt->data_len); + dup_pkt->data_len = pkt->data_len; + packet_set_action(dup_pkt, PACKET_ACTION_DROP); + + for (int8_t i = 0; i < pkt->layers_used; i++) + { + dup_pkt->layers[i].proto = pkt->layers[i].proto; + dup_pkt->layers[i].hdr_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset; + dup_pkt->layers[i].pld_ptr = dup_pkt->data_ptr + pkt->layers[i].hdr_offset + pkt->layers[i].hdr_len; + dup_pkt->layers[i].hdr_offset = pkt->layers[i].hdr_offset; + dup_pkt->layers[i].hdr_len = pkt->layers[i].hdr_len; + dup_pkt->layers[i].pld_len = pkt->layers[i].pld_len; + } + + // update frag_layer + if (pkt->frag_layer) + { + dup_pkt->frag_layer = &dup_pkt->layers[pkt->frag_layer - pkt->layers]; + } + memcpy(&dup_pkt->meta, &pkt->meta, sizeof(struct metadata)); + packet_set_origin_ctx(dup_pkt, (void *)NULL); + + return dup_pkt; +} + +void packet_free(struct packet *pkt) +{ + if (pkt && pkt->need_free) + { + free((void *)pkt); + } +} + +int packet_is_fragment(const struct packet *pkt) +{ + return (pkt->frag_layer) ? 1 : 0; +} diff --git a/infra/packet_manager/test/CMakeLists.txt b/infra/packet_manager/test/CMakeLists.txt new file mode 100644 index 0000000..3d12184 --- /dev/null +++ b/infra/packet_manager/test/CMakeLists.txt @@ -0,0 +1,77 @@ +add_executable(gtest_tunnel gtest_tunnel.cpp) +target_link_libraries(gtest_tunnel packet_manager gtest) + +add_executable(gtest_udp_utils gtest_udp_utils.cpp) +target_link_libraries(gtest_udp_utils packet_manager gtest) + +add_executable(gtest_tcp_utils gtest_tcp_utils.cpp) +target_link_libraries(gtest_tcp_utils packet_manager gtest) + +add_executable(gtest_ip4_utils gtest_ip4_utils.cpp) +target_link_libraries(gtest_ip4_utils packet_manager gtest) + +add_executable(gtest_ip6_utils gtest_ip6_utils.cpp) +target_link_libraries(gtest_ip6_utils packet_manager gtest) + +add_executable(gtest_mpls_utils gtest_mpls_utils.cpp) +target_link_libraries(gtest_mpls_utils packet_manager gtest) + +add_executable(gtest_eth_utils gtest_eth_utils.cpp) +target_link_libraries(gtest_eth_utils packet_manager gtest) + +add_executable(gtest_vlan_utils gtest_vlan_utils.cpp) +target_link_libraries(gtest_vlan_utils packet_manager gtest) + +add_executable(gtest_vxlan_utils gtest_vxlan_utils.cpp) +target_link_libraries(gtest_vxlan_utils packet_manager gtest) + +add_executable(gtest_gre0_utils gtest_gre0_utils.cpp) +target_link_libraries(gtest_gre0_utils packet_manager gtest) + +add_executable(gtest_gre1_utils gtest_gre1_utils.cpp) +target_link_libraries(gtest_gre1_utils packet_manager gtest) + +add_executable(gtest_l2tp_utils gtest_l2tp_utils.cpp) +target_link_libraries(gtest_l2tp_utils packet_manager gtest) + +add_executable(gtest_gtp1_utils gtest_gtp1_utils.cpp) +target_link_libraries(gtest_gtp1_utils packet_manager gtest) + +add_executable(gtest_gtp2_utils gtest_gtp2_utils.cpp) +target_link_libraries(gtest_gtp2_utils packet_manager gtest) + +add_executable(gtest_packet_frag gtest_packet_frag.cpp) +target_link_libraries(gtest_packet_frag packet_manager gtest) + +add_executable(gtest_packet_parser gtest_packet_parser.cpp) +target_link_libraries(gtest_packet_parser packet_manager gtest) + +add_executable(gtest_packet_builder gtest_packet_builder.cpp) +target_link_libraries(gtest_packet_builder packet_manager gtest) + +add_executable(gtest_packet_filter gtest_packet_filter.cpp) +target_link_libraries(gtest_packet_filter packet_manager gtest) + +add_executable(gtest_packet_ldbc gtest_packet_ldbc.cpp) +target_link_libraries(gtest_packet_ldbc packet_manager gtest) + +include(GoogleTest) +gtest_discover_tests(gtest_tunnel) +gtest_discover_tests(gtest_udp_utils) +gtest_discover_tests(gtest_tcp_utils) +gtest_discover_tests(gtest_ip4_utils) +gtest_discover_tests(gtest_ip6_utils) +gtest_discover_tests(gtest_mpls_utils) +gtest_discover_tests(gtest_eth_utils) +gtest_discover_tests(gtest_vlan_utils) +gtest_discover_tests(gtest_vxlan_utils) +gtest_discover_tests(gtest_gre0_utils) +gtest_discover_tests(gtest_gre1_utils) +gtest_discover_tests(gtest_l2tp_utils) +gtest_discover_tests(gtest_gtp1_utils) +gtest_discover_tests(gtest_gtp2_utils) +gtest_discover_tests(gtest_packet_frag) +gtest_discover_tests(gtest_packet_parser) +gtest_discover_tests(gtest_packet_builder) +gtest_discover_tests(gtest_packet_filter) +gtest_discover_tests(gtest_packet_ldbc)
\ No newline at end of file diff --git a/infra/packet_manager/test/gtest_eth_utils.cpp b/infra/packet_manager/test/gtest_eth_utils.cpp new file mode 100644 index 0000000..e00f032 --- /dev/null +++ b/infra/packet_manager/test/gtest_eth_utils.cpp @@ -0,0 +1,49 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Ethernet II, Src: 00:00:00_00:04:36 (00:00:00:00:04:36), Dst: 18:10:04:00:03:1f (18:10:04:00:03:1f) + * Destination: 18:10:04:00:03:1f (18:10:04:00:03:1f) + * Address: 18:10:04:00:03:1f (18:10:04:00:03:1f) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Source: 00:00:00_00:04:36 (00:00:00:00:04:36) + * Address: 00:00:00_00:04:36 (00:00:00:00:04:36) + * .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default) + * .... ...0 .... .... .... .... = IG bit: Individual address (unicast) + * Type: MPLS label switched packet (0x8847) + */ + +unsigned char data[] = { + 0x18, 0x10, 0x04, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x04, 0x36, 0x88, 0x47}; + +TEST(ETH_UTILS, GET) +{ + const struct ethhdr *hdr = (struct ethhdr *)data; + + char dest[18] = {0}; + char source[18] = {0}; + EXPECT_TRUE(eth_hdr_get_dest(hdr, dest, sizeof(dest)) == 17); + EXPECT_TRUE(eth_hdr_get_source(hdr, source, sizeof(source)) == 17); + EXPECT_TRUE(memcmp(dest, "18:10:04:00:03:1f", 17) == 0); + EXPECT_TRUE(memcmp(source, "00:00:00:00:04:36", 17) == 0); + EXPECT_TRUE(eth_hdr_get_proto(hdr) == ETH_P_MPLS_UC); +} + +TEST(ETH_UTILS, SET) +{ + char buff[14] = {0}; + struct ethhdr *hdr = (struct ethhdr *)buff; + + eth_hdr_set_dest(hdr, "18:10:04:00:03:1f"); + eth_hdr_set_source(hdr, "00:00:00:00:04:36"); + eth_hdr_set_proto(hdr, ETH_P_MPLS_UC); + EXPECT_TRUE(memcmp(buff, data, 14) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_gre0_utils.cpp b/infra/packet_manager/test/gtest_gre0_utils.cpp new file mode 100644 index 0000000..e195f42 --- /dev/null +++ b/infra/packet_manager/test/gtest_gre0_utils.cpp @@ -0,0 +1,210 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Generic Routing Encapsulation (IP) + * Flags and Version: 0x0000 + * 0... .... .... .... = Checksum Bit: No + * .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: IP (0x0800) + */ + +unsigned char gre0_no_opt[] = { + 0x00, 0x00, 0x08, 0x00}; + +TEST(GRE0_UTILS, GET_1) +{ + const struct gre0_hdr *hdr = (struct gre0_hdr *)gre0_no_opt; + + EXPECT_TRUE(gre0_hdr_get_flags(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_checksum_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_routing_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_key_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_seq_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_strict_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_version(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_proto(hdr) == 0x0800); + EXPECT_TRUE(gre0_hdr_get_checksum(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_offset(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_key(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_seq(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_routing_data(hdr) == NULL); + EXPECT_TRUE(gre0_hdr_get_routing_len(hdr) == 0); + + EXPECT_TRUE(calc_gre0_hdr_len((const char *)gre0_no_opt, sizeof(gre0_no_opt)) == 4); +} + +TEST(GRE0_UTILS, SET_1) +{ + char buff[4] = {0}; + + struct gre0_hdr *hdr = (struct gre0_hdr *)buff; + gre0_hdr_set_flags(hdr, 0); + gre0_hdr_set_checksum_flag(hdr, 0); + gre0_hdr_set_routing_flag(hdr, 0); + gre0_hdr_set_key_flag(hdr, 0); + gre0_hdr_set_seq_flag(hdr, 0); + gre0_hdr_set_strict_flag(hdr, 0); + gre0_hdr_set_version(hdr, 0); + gre0_hdr_set_proto(hdr, 0x0800); + gre0_hdr_set_checksum(hdr, 0); + gre0_hdr_set_offset(hdr, 0); + gre0_hdr_set_key(hdr, 0); + gre0_hdr_set_seq(hdr, 0); + gre0_hdr_set_routing_data(hdr, NULL, 0); + + EXPECT_TRUE(memcmp(buff, gre0_no_opt, 4) == 0); +} + +/* + * Generic Routing Encapsulation (IP) + * Flags and Version: 0x2000 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..1. .... .... .... = Key Bit: Yes + * ...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: IP (0x0800) + * Key: 0x00000384 + */ + +unsigned char gre0_opt_key[] = {0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x84}; + +TEST(GRE0_UTILS, GET_2) +{ + const struct gre0_hdr *hdr = (struct gre0_hdr *)gre0_opt_key; + + EXPECT_TRUE(gre0_hdr_get_flags(hdr) == 0x2000); + EXPECT_TRUE(gre0_hdr_get_checksum_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_routing_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_key_flag(hdr) == 1); + EXPECT_TRUE(gre0_hdr_get_seq_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_strict_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_version(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_proto(hdr) == 0x0800); + EXPECT_TRUE(gre0_hdr_get_checksum(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_offset(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_key(hdr) == 0x00000384); + EXPECT_TRUE(gre0_hdr_get_seq(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_routing_data(hdr) == NULL); + EXPECT_TRUE(gre0_hdr_get_routing_len(hdr) == 0); + + EXPECT_TRUE(calc_gre0_hdr_len((const char *)gre0_opt_key, sizeof(gre0_opt_key)) == 8); +} + +TEST(GRE0_UTILS, SET_2) +{ + char buff[8] = {0}; + + struct gre0_hdr *hdr = (struct gre0_hdr *)buff; + gre0_hdr_set_flags(hdr, 0x2000); + gre0_hdr_set_checksum_flag(hdr, 0); + gre0_hdr_set_routing_flag(hdr, 0); + gre0_hdr_set_key_flag(hdr, 1); + gre0_hdr_set_seq_flag(hdr, 0); + gre0_hdr_set_strict_flag(hdr, 0); + gre0_hdr_set_version(hdr, 0); + gre0_hdr_set_proto(hdr, 0x0800); + gre0_hdr_set_checksum(hdr, 0); + gre0_hdr_set_offset(hdr, 0); + gre0_hdr_set_key(hdr, 0x00000384); + gre0_hdr_set_seq(hdr, 0); + gre0_hdr_set_routing_data(hdr, NULL, 0); + + EXPECT_TRUE(memcmp(buff, gre0_opt_key, 8) == 0); +} + +/* + * Generic Routing Encapsulation (IP) + * Flags and Version: 0xc000 + * 1... .... .... .... = Checksum Bit: Yes + * .1.. .... .... .... = Routing Bit: Yes + * ..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: IP (0x0800) + * Checksum: 0x0000 incorrect, should be 0xea95 + * [Expert Info (Warning/Protocol): Incorrect GRE Checksum [should be 0xea95]] + * [Incorrect GRE Checksum [should be 0xea95]] + * [Severity level: Warning] + * [Group: Protocol] + * [Checksum Status: Bad] + * Offset: 44 + * Routing + * Address Family: 2 + * SRE Offset: 0 + * SRE Length: 44 + * Routing Information: 6c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f206c696e6b5f696e666f2000000000 + * Routing + * Address Family: 0 + * SRE Offset: 0 + * SRE Length: 0 + */ + +unsigned char gre0_opt_chek_rout[] = { + 0xc0, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x02, 0x00, 0x2c, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, + 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +TEST(GRE0_UTILS, GET_3) +{ + const struct gre0_hdr *hdr = (struct gre0_hdr *)gre0_opt_chek_rout; + + EXPECT_TRUE(gre0_hdr_get_flags(hdr) == 0xc000); + EXPECT_TRUE(gre0_hdr_get_checksum_flag(hdr) == 1); + EXPECT_TRUE(gre0_hdr_get_routing_flag(hdr) == 1); + EXPECT_TRUE(gre0_hdr_get_key_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_seq_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_strict_flag(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_version(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_proto(hdr) == 0x0800); + EXPECT_TRUE(gre0_hdr_get_checksum(hdr) == 0x0000); + EXPECT_TRUE(gre0_hdr_get_offset(hdr) == 44); + EXPECT_TRUE(gre0_hdr_get_key(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_seq(hdr) == 0); + EXPECT_TRUE(gre0_hdr_get_routing_data(hdr) == (const char *)gre0_opt_chek_rout + 8); + EXPECT_TRUE(gre0_hdr_get_routing_len(hdr) == 52); + + EXPECT_TRUE(calc_gre0_hdr_len((const char *)gre0_opt_chek_rout, sizeof(gre0_opt_chek_rout)) == 60); +} + +TEST(GRE0_UTILS, SET_3) +{ + char buff[60] = {0}; + + struct gre0_hdr *hdr = (struct gre0_hdr *)buff; + gre0_hdr_set_flags(hdr, 0xc000); + gre0_hdr_set_checksum_flag(hdr, 1); + gre0_hdr_set_routing_flag(hdr, 1); + gre0_hdr_set_key_flag(hdr, 0); + gre0_hdr_set_seq_flag(hdr, 0); + gre0_hdr_set_strict_flag(hdr, 0); + gre0_hdr_set_version(hdr, 0); + gre0_hdr_set_proto(hdr, 0x0800); + gre0_hdr_set_checksum(hdr, 0x0000); + gre0_hdr_set_offset(hdr, 44); + gre0_hdr_set_key(hdr, 0); + gre0_hdr_set_seq(hdr, 0); + gre0_hdr_set_routing_data(hdr, (const char *)gre0_opt_chek_rout + 8, 52); + + EXPECT_TRUE(memcmp(buff, gre0_opt_chek_rout, 60) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_gre1_utils.cpp b/infra/packet_manager/test/gtest_gre1_utils.cpp new file mode 100644 index 0000000..92669f7 --- /dev/null +++ b/infra/packet_manager/test/gtest_gre1_utils.cpp @@ -0,0 +1,66 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Generic Routing Encapsulation (PPP) + * Flags and Version: 0x3081 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..1. .... .... .... = Key Bit: Yes + * ...1 .... .... .... = Sequence Number Bit: Yes + * .... 0... .... .... = Strict Source Route Bit: No + * .... .000 .... .... = Recursion control: 0 + * .... .... 1... .... = Acknowledgment: Yes + * .... .... .000 0... = Flags (Reserved): 0 + * .... .... .... .001 = Version: Enhanced GRE (1) + * Protocol Type: PPP (0x880b) + * Payload Length: 103 + * Call ID: 6016 + * Sequence Number: 430001 + * Acknowledgment Number: 539254 + */ + +unsigned char gre1_opt_seq_ack[] = { + 0x30, 0x81, 0x88, 0x0b, 0x00, 0x67, 0x17, 0x80, 0x00, 0x06, 0x8f, 0xb1, 0x00, 0x08, 0x3a, 0x76}; + +TEST(GRE1_UTILS, GET_1) +{ + const struct gre1_hdr *hdr = (struct gre1_hdr *)gre1_opt_seq_ack; + + EXPECT_TRUE(gre1_hdr_get_flags(hdr) == 0x3081); + EXPECT_TRUE(gre1_hdr_get_seq_flag(hdr) == 1); + EXPECT_TRUE(gre1_hdr_get_ack_flag(hdr) == 1); + EXPECT_TRUE(gre1_hdr_get_version(hdr) == 1); + EXPECT_TRUE(gre1_hdr_get_proto(hdr) == 0x880b); + EXPECT_TRUE(gre1_hdr_get_payload_length(hdr) == 103); + EXPECT_TRUE(gre1_hdr_get_call_id(hdr) == 6016); + EXPECT_TRUE(gre1_hdr_get_seq(hdr) == 430001); + EXPECT_TRUE(gre1_hdr_get_ack(hdr) == 539254); + + EXPECT_TRUE(calc_gre1_hdr_len((const char *)gre1_opt_seq_ack, sizeof(gre1_opt_seq_ack)) == 16); +} + +TEST(GRE1_UTILS, SET_1) +{ + char buff[16] = {0}; + + struct gre1_hdr *hdr = (struct gre1_hdr *)buff; + gre1_hdr_set_flags(hdr, 0x3081); + gre1_hdr_set_seq_flag(hdr, 1); + gre1_hdr_set_ack_flag(hdr, 1); + gre1_hdr_set_version(hdr, 1); + gre1_hdr_set_proto(hdr, 0x880b); + gre1_hdr_set_payload_length(hdr, 103); + gre1_hdr_set_call_id(hdr, 6016); + gre1_hdr_set_seq(hdr, 430001); + gre1_hdr_set_ack(hdr, 539254); + + EXPECT_TRUE(memcmp(buff, gre1_opt_seq_ack, 16) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_gtp1_utils.cpp b/infra/packet_manager/test/gtest_gtp1_utils.cpp new file mode 100644 index 0000000..270d36a --- /dev/null +++ b/infra/packet_manager/test/gtest_gtp1_utils.cpp @@ -0,0 +1,318 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * User Datagram Protocol, Src Port: 2123, Dst Port: 2123 + * GPRS Tunneling Protocol + * Flags: 0x32 + * 001. .... = Version: GTP release 99 version (1) + * ...1 .... = Protocol type: GTP (1) + * .... 0... = Reserved: 0 + * .... .0.. = Is Next Extension Header present?: No + * .... ..1. = Is Sequence Number present?: Yes + * .... ...0 = Is N-PDU number present?: No + * Message Type: Create PDP context request (0x10) + * Length: 151 + * TEID: 0x00000000 (0) + * Sequence number: 0x00fe (254) + * IMSI: 27203 + * [Association IMSI: 27203] + * Mobile Country Code (MCC): Ireland (272) + * Mobile Network Code (MNC): Eircom Ltd (03) + * Routing Area Identity + * Mobile Country Code (MCC): Ireland (272) + * Mobile Network Code (MNC): Eircom Ltd (03) + * Location Area Code (LAC): 65534 + * Routing Area Code (RAC): 255 + * Recovery: 93 + * Selection mode: MS or network provided APN, subscribed verified + * .... ..00 = Selection mode: MS or network provided APN, subscribed verified (0) + * TEID Data I: 0x372f0000 (925827072) + * TEID Control Plane: 0x372f0000 (925827072) + * NSAPI: 5 + * .... 0101 = NSAPI: 5 + * End user address (IETF/IPv4) + * Length: 2 + * PDP type organization: IETF (1) + * PDP type number: IPv4 (0x21) + * Access Point Name: mms.mymeteor.ie + * APN length: 16 + * APN: mms.mymeteor.ie + * Protocol configuration options + * Length: 34 + * [Link direction: MS to network (0)] + * 1... .... = Extension: True + * .... .000 = Configuration Protocol: PPP for use with IP PDP type or IP PDN type (0) + * Protocol or Container ID: Password Authentication Protocol (0xc023) + * Length: 0x0b (11) + * PPP Password Authentication Protocol + * Code: Authenticate-Request (1) + * Identifier: 0 + * Length: 11 + * Data + * Peer-ID-Length: 2 + * Peer-ID: my + * Password-Length: 3 + * Password: wap + * Protocol or Container ID: Internet Protocol Control Protocol (0x8021) + * Length: 0x10 (16) + * PPP IP Control Protocol + * Code: Configuration Request (1) + * Identifier: 0 (0x00) + * Length: 16 + * Options: (12 bytes), Primary DNS Server IP Address, Secondary DNS Server IP Address + * Primary DNS Server IP Address + * Type: Primary DNS Server IP Address (129) + * Length: 6 + * Primary DNS Address: 0.0.0.0 + * Secondary DNS Server IP Address + * Type: Secondary DNS Server IP Address (131) + * Length: 6 + * Secondary DNS Address: 0.0.0.0 + * GSN address : 212.129.65.13 + * GSN address length: 4 + * GSN address IPv4: 212.129.65.13 + * GSN address : 212.129.65.23 + * GSN address length: 4 + * GSN address IPv4: 212.129.65.23 + * MS international PSTN/ISDN number + * Length: 7 + * 1... .... = Extension: No Extension + * .001 .... = Nature of number: International Number (0x1) + * .... 0001 = Number plan: ISDN/Telephony Numbering (Rec ITU-T E.164) (0x1) + * E.164 number (MSISDN): 353800000000 + * Country Code: Ireland (353) + * Quality of Service + * Length: 12 + * Allocation/Retention priority: 2 + * 00.. .... = Spare: 0 + * ..10 0... = QoS delay: Delay class 4 (best effort) (4) + * .... .011 = QoS reliability: Unacknowledged GTP/LLC, Ack RLC, Protected data (3) + * 0110 .... = QoS peak: Up to 32 000 oct/s (6) + * .... 0... = Spare: 0 + * .... .010 = QoS precedence: Normal priority (2) + * 000. .... = Spare: 0 + * ...1 1111 = QoS mean: Best effort (31) + * 100. .... = Traffic class: Background class (4) + * ...1 0... = Delivery order: Without delivery order ('no') (2) + * .... .011 = Delivery of erroneous SDU: Erroneous SDUs are not delivered ('no') (3) + * Maximum SDU size: 1500 octets + * Maximum bit rate for uplink: 256 kbps + * Maximum bit rate for downlink: 256 kbps + * 0111 .... = Residual BER: 1/100 000 = 1x10^-5 (7) + * .... 0100 = SDU Error ratio: 1/10 000 = 1x10^-4 (4) + * 1111 10.. = Transfer delay: 4000 ms (62) + * .... ..11 = Traffic handling priority: Priority level 3 (3) + * Guaranteed bit rate for uplink: 0 kbps (255) + * Guaranteed bit rate for downlink: 0 kbps (255) + * RAT Type: GERAN + * Length: 1 + * RAT Type: GERAN (2) + * IMEI(SV): 3598100185893512 + * Length: 8 + * IMEI(SV): 3598100185893512 + * [Response In: 2] + */ + +unsigned char gtp1_c[] = { + 0x32, 0x10, 0x00, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x02, 0x72, 0x02, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x72, 0xf2, 0x30, 0xff, + 0xfe, 0xff, 0x0e, 0x5d, 0x0f, 0xfc, 0x10, 0x37, 0x2f, 0x00, 0x00, 0x11, 0x37, 0x2f, 0x00, 0x00, 0x14, 0x05, 0x80, 0x00, 0x02, 0xf1, 0x21, 0x83, 0x00, 0x10, + 0x03, 0x6d, 0x6d, 0x73, 0x08, 0x6d, 0x79, 0x6d, 0x65, 0x74, 0x65, 0x6f, 0x72, 0x02, 0x69, 0x65, 0x84, 0x00, 0x22, 0x80, 0xc0, 0x23, 0x0b, 0x01, 0x00, 0x00, + 0x0b, 0x02, 0x6d, 0x79, 0x03, 0x77, 0x61, 0x70, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x85, 0x00, 0x04, 0xd4, 0x81, 0x41, 0x0d, 0x85, 0x00, 0x04, 0xd4, 0x81, 0x41, 0x17, 0x86, 0x00, 0x07, 0x91, 0x53, 0x83, 0x00, 0x00, 0x00, 0x00, 0x87, + 0x00, 0x0c, 0x02, 0x23, 0x62, 0x1f, 0x93, 0x96, 0x58, 0x58, 0x74, 0xfb, 0xff, 0xff, 0x97, 0x00, 0x01, 0x02, 0x9a, 0x00, 0x08, 0x53, 0x89, 0x01, 0x10, 0x58, + 0x98, 0x53, 0x21}; + +TEST(GTP1_UTILS, C_GET) +{ + const struct gtp1_hdr *hdr = (struct gtp1_hdr *)gtp1_c; + + // GTP Fixed Header Length + GTPv1-C Optional Headers + GTPv1-C Extension Headers + EXPECT_TRUE(calc_gtp1_hdr_len((const char *)gtp1_c, sizeof(gtp1_c)) == 12); + EXPECT_TRUE(gtp1_hdr_get_flags(hdr) == 0x32); + EXPECT_TRUE(gtp1_hdr_get_version(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_proto(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_reserved(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_ext_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_seq_flag(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_npdu_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_msg_type(hdr) == 0x10); + EXPECT_TRUE(gtp1_hdr_get_msg_len(hdr) == 151); + EXPECT_TRUE(gtp1_hdr_get_teid(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_seq(hdr) == 254); + EXPECT_TRUE(gtp1_hdr_get_npdu(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_next_ext_type(hdr) == 0); + + char buff[1024] = {0}; + gtp1_hdr_to_str(hdr, buff, sizeof(buff)); + printf("%s\n", buff); +} + +TEST(GTP1_UTILS, C_SET) +{ + char buff[12] = {0}; + + struct gtp1_hdr *hdr = (struct gtp1_hdr *)buff; + gtp1_hdr_set_flags(hdr, 0x32); + gtp1_hdr_set_version(hdr, 1); + gtp1_hdr_set_proto(hdr, 1); + gtp1_hdr_set_reserved(hdr, 0); + gtp1_hdr_set_ext_flag(hdr, 0); + gtp1_hdr_set_seq_flag(hdr, 1); + gtp1_hdr_set_npdu_flag(hdr, 0); + gtp1_hdr_set_msg_type(hdr, 0x10); + gtp1_hdr_set_msg_len(hdr, 151); + gtp1_hdr_set_teid(hdr, 0); + gtp1_hdr_set_seq(hdr, 254); + gtp1_hdr_set_npdu(hdr, 0); + gtp1_hdr_set_next_ext_type(hdr, 0); + + EXPECT_TRUE(memcmp(buff, gtp1_c, 12) == 0); +} + +/* + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * GPRS Tunneling Protocol + * Flags: 0x30 + * 001. .... = Version: GTP release 99 version (1) + * ...1 .... = Protocol type: GTP (1) + * .... 0... = Reserved: 0 + * .... .0.. = Is Next Extension Header present?: No + * .... ..0. = Is Sequence Number present?: No + * .... ...0 = Is N-PDU number present?: No + * Message Type: T-PDU (0xff) + * Length: 40 + * TEID: 0x001e849a (2000026) + */ + +unsigned char gtp1_u1[] = { + 0x30, 0xff, 0x00, 0x28, 0x00, 0x1e, 0x84, 0x9a}; + +TEST(GTP1_UTILS, U1_GET) +{ + const struct gtp1_hdr *hdr = (struct gtp1_hdr *)gtp1_u1; + + // GTP Fixed Header Length + GTPv1-U Optional Headers + GTPv1-U Extension Headers + EXPECT_TRUE(calc_gtp1_hdr_len((const char *)gtp1_u1, sizeof(gtp1_u1)) == 8); + EXPECT_TRUE(gtp1_hdr_get_flags(hdr) == 0x30); + EXPECT_TRUE(gtp1_hdr_get_version(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_proto(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_reserved(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_ext_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_seq_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_npdu_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_msg_type(hdr) == 0xff); + EXPECT_TRUE(gtp1_hdr_get_msg_len(hdr) == 40); + EXPECT_TRUE(gtp1_hdr_get_teid(hdr) == 2000026); + EXPECT_TRUE(gtp1_hdr_get_seq(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_npdu(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_next_ext_type(hdr) == 0); + + char buff[1024] = {0}; + gtp1_hdr_to_str(hdr, buff, sizeof(buff)); + printf("%s\n", buff); +} + +TEST(GTP1_UTILS, U1_SET) +{ + char buff[8] = {0}; + + struct gtp1_hdr *hdr = (struct gtp1_hdr *)buff; + gtp1_hdr_set_flags(hdr, 0x30); + gtp1_hdr_set_version(hdr, 1); + gtp1_hdr_set_proto(hdr, 1); + gtp1_hdr_set_reserved(hdr, 0); + gtp1_hdr_set_ext_flag(hdr, 0); + gtp1_hdr_set_seq_flag(hdr, 0); + gtp1_hdr_set_npdu_flag(hdr, 0); + gtp1_hdr_set_msg_type(hdr, 0xff); + gtp1_hdr_set_msg_len(hdr, 40); + gtp1_hdr_set_teid(hdr, 2000026); + gtp1_hdr_set_seq(hdr, 0); + gtp1_hdr_set_npdu(hdr, 0); + gtp1_hdr_set_next_ext_type(hdr, 0); + + EXPECT_TRUE(memcmp(buff, gtp1_u1, 8) == 0); +} + +/* + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * GPRS Tunneling Protocol + * Flags: 0x34 + * 001. .... = Version: GTP release 99 version (1) + * ...1 .... = Protocol type: GTP (1) + * .... 0... = Reserved: 0 + * .... .1.. = Is Next Extension Header present?: Yes + * .... ..0. = Is Sequence Number present?: No + * .... ...0 = Is N-PDU number present?: No + * Message Type: T-PDU (0xff) + * Length: 445 + * TEID: 0x01447453 (21263443) + * Next extension header type: PDU Session container (0x85) + * Extension header (PDU Session container) + * Extension Header Length: 1 + * PDU Session Container + * 0001 .... = PDU Type: UL PDU SESSION INFORMATION (1) + * .... 0000 = Spare: 0x0 + * 00.. .... = Spare: 0x0 + * ..00 0001 = QoS Flow Identifier (QFI): 1 + * Next extension header type: No more extension headers (0x00) + */ + +unsigned char gtp1_u2[] = { + 0x34, 0xff, 0x01, 0xbd, 0x01, 0x44, 0x74, 0x53, 0x00, 0x00, 0x00, 0x85, 0x01, 0x10, 0x01, 0x00}; + +TEST(GTP1_UTILS, U2_GET) +{ + const struct gtp1_hdr *hdr = (struct gtp1_hdr *)gtp1_u2; + + // GTP Fixed Header Length + GTPv1-U Optional Headers + GTPv1-U Extension Headers + EXPECT_TRUE(calc_gtp1_hdr_len((const char *)gtp1_u2, sizeof(gtp1_u2)) == 16); + EXPECT_TRUE(gtp1_hdr_get_flags(hdr) == 0x34); + EXPECT_TRUE(gtp1_hdr_get_version(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_proto(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_reserved(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_ext_flag(hdr) == 1); + EXPECT_TRUE(gtp1_hdr_get_seq_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_npdu_flag(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_msg_type(hdr) == 0xff); + EXPECT_TRUE(gtp1_hdr_get_msg_len(hdr) == 445); + EXPECT_TRUE(gtp1_hdr_get_teid(hdr) == 21263443); + EXPECT_TRUE(gtp1_hdr_get_seq(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_npdu(hdr) == 0); + EXPECT_TRUE(gtp1_hdr_get_next_ext_type(hdr) == 0x85); + + char buff[1024] = {0}; + gtp1_hdr_to_str(hdr, buff, sizeof(buff)); + printf("%s\n", buff); +} + +TEST(GTP1_UTILS, U2_SET) +{ + char buff[16] = {0}; + + struct gtp1_hdr *hdr = (struct gtp1_hdr *)buff; + gtp1_hdr_set_flags(hdr, 0x34); + gtp1_hdr_set_version(hdr, 1); + gtp1_hdr_set_proto(hdr, 1); + gtp1_hdr_set_reserved(hdr, 0); + gtp1_hdr_set_ext_flag(hdr, 1); + gtp1_hdr_set_seq_flag(hdr, 0); + gtp1_hdr_set_npdu_flag(hdr, 0); + gtp1_hdr_set_msg_type(hdr, 0xff); + gtp1_hdr_set_msg_len(hdr, 445); + gtp1_hdr_set_teid(hdr, 21263443); + gtp1_hdr_set_seq(hdr, 0); + gtp1_hdr_set_npdu(hdr, 0); + gtp1_hdr_set_next_ext_type(hdr, 0x85); + + // not compare the extension header + EXPECT_TRUE(memcmp(buff, gtp1_u2, 12) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_gtp2_utils.cpp b/infra/packet_manager/test/gtest_gtp2_utils.cpp new file mode 100644 index 0000000..584abf7 --- /dev/null +++ b/infra/packet_manager/test/gtest_gtp2_utils.cpp @@ -0,0 +1,150 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * User Datagram Protocol, Src Port: 2123, Dst Port: 12491 + * GPRS Tunneling Protocol V2 + * Flags: 0x48 + * 010. .... = Version: 2 + * ...0 .... = Piggybacking flag (P): 0 + * .... 1... = TEID flag (T): 1 + * .... .0.. = Message Priority(MP): 0 + * Message Type: Delete Session Response (37) + * Message Length: 19 + * Tunnel Endpoint Identifier: 0x0e05cd4d (235261261) + * Sequence Number: 0x000ce7 (3303) + * Spare: 0 + * Cause : Request accepted (16) + * IE Type: Cause (2) + * IE Length: 2 + * 0000 .... = CR flag: 0 + * .... 0000 = Instance: 0 + * Cause: Request accepted (16) + * 0000 0... = Spare bit(s): 0 + * .... .0.. = PCE (PDN Connection IE Error): False + * .... ..0. = BCE (Bearer Context IE Error): False + * .... ...0 = CS (Cause Source): Originated by node sending the message + * Recovery (Restart Counter) : 13 + * IE Type: Recovery (Restart Counter) (3) + * IE Length: 1 + * 0000 .... = CR flag: 0 + * .... 0000 = Instance: 0 + * Restart Counter: 13 + */ + +unsigned char gtp2_c_pkt1[] = { + 0x48, 0x25, 0x00, 0x13, 0x0e, 0x05, 0xcd, 0x4d, 0x00, 0x0c, 0xe7, 0x00, 0x02, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0d}; + +// have teid + +TEST(GTP2_UTILS, C_GET1) +{ + const struct gtp2_hdr *hdr = (struct gtp2_hdr *)gtp2_c_pkt1; + + EXPECT_TRUE(calc_gtp2_hdr_len((const char *)gtp2_c_pkt1, sizeof(gtp2_c_pkt1)) == 12); + EXPECT_TRUE(gtp2_hdr_get_flags(hdr) == 0x48); + EXPECT_TRUE(gtp2_hdr_get_version(hdr) == 2); + EXPECT_TRUE(gtp2_hdr_get_piggyback_flag(hdr) == 0); + EXPECT_TRUE(gtp2_hdr_get_teid_flag(hdr) == 1); + EXPECT_TRUE(gtp2_hdr_get_spare_flag(hdr) == 0); + EXPECT_TRUE(gtp2_hdr_get_msg_type(hdr) == 37); + EXPECT_TRUE(gtp2_hdr_get_msg_len(hdr) == 19); + EXPECT_TRUE(gtp2_hdr_get_teid(hdr) == 0x0e05cd4d); + EXPECT_TRUE(gtp2_hdr_get_seq(hdr) == 0x000ce7); + EXPECT_TRUE(gtp2_hdr_get_spare(hdr) == 0); + + char buff[1024] = {0}; + gtp2_hdr_to_str(hdr, buff, sizeof(buff)); + printf("%s\n", buff); +} + +TEST(GTP2_UTILS, C_SET1) +{ + char buff[12] = {0}; + + struct gtp2_hdr *hdr = (struct gtp2_hdr *)buff; + gtp2_hdr_set_flags(hdr, 0x48); + gtp2_hdr_set_version(hdr, 2); + gtp2_hdr_set_piggyback_flag(hdr, 0); + gtp2_hdr_set_teid_flag(hdr, 1); + gtp2_hdr_set_spare_flag(hdr, 0); + gtp2_hdr_set_msg_type(hdr, 37); + gtp2_hdr_set_msg_len(hdr, 19); + gtp2_hdr_set_teid(hdr, 0x0e05cd4d); + gtp2_hdr_set_seq(hdr, 0x000ce7); + gtp2_hdr_set_spare(hdr, 0); + + EXPECT_TRUE(memcmp(buff, gtp2_c_pkt1, 12) == 0); +} + +/* + * User Datagram Protocol, Src Port: 2123, Dst Port: 2123 + * GPRS Tunneling Protocol V2 + * Flags: 0x40 + * 010. .... = Version: 2 + * ...0 .... = Piggybacking flag (P): 0 + * .... 0... = TEID flag (T): 0 + * .... .0.. = Message Priority(MP): 0 + * Message Type: Echo Request (1) + * Message Length: 9 + * Sequence Number: 0x0041d4 (16852) + * Spare: 0 + * Recovery (Restart Counter) : 5 + * IE Type: Recovery (Restart Counter) (3) + * IE Length: 1 + * 0000 .... = CR flag: 0 + * .... 0000 = Instance: 0 + * Restart Counter: 5 + */ + +unsigned char gtp2_c_pkt2[] = { + 0x40, 0x01, 0x00, 0x09, 0x00, 0x41, 0xd4, 0x00, 0x03, 0x00, 0x01, 0x00, 0x05}; + +// no teid + +TEST(GTP2_UTILS, C_GET2) +{ + const struct gtp2_hdr *hdr = (struct gtp2_hdr *)gtp2_c_pkt2; + + EXPECT_TRUE(calc_gtp2_hdr_len((const char *)gtp2_c_pkt2, sizeof(gtp2_c_pkt2)) == 8); + EXPECT_TRUE(gtp2_hdr_get_flags(hdr) == 0x40); + EXPECT_TRUE(gtp2_hdr_get_version(hdr) == 2); + EXPECT_TRUE(gtp2_hdr_get_piggyback_flag(hdr) == 0); + EXPECT_TRUE(gtp2_hdr_get_teid_flag(hdr) == 0); + EXPECT_TRUE(gtp2_hdr_get_spare_flag(hdr) == 0); + EXPECT_TRUE(gtp2_hdr_get_msg_type(hdr) == 1); + EXPECT_TRUE(gtp2_hdr_get_msg_len(hdr) == 9); + EXPECT_TRUE(gtp2_hdr_get_teid(hdr) == 0); + EXPECT_TRUE(gtp2_hdr_get_seq(hdr) == 0x0041d4); + EXPECT_TRUE(gtp2_hdr_get_spare(hdr) == 0); + + char buff[1024] = {0}; + gtp2_hdr_to_str(hdr, buff, sizeof(buff)); + printf("%s\n", buff); +} + +TEST(GTP2_UTILS, C_SET2) +{ + char buff[8] = {0}; + + struct gtp2_hdr *hdr = (struct gtp2_hdr *)buff; + gtp2_hdr_set_flags(hdr, 0x40); + gtp2_hdr_set_version(hdr, 2); + gtp2_hdr_set_piggyback_flag(hdr, 0); + gtp2_hdr_set_teid_flag(hdr, 0); + gtp2_hdr_set_spare_flag(hdr, 0); + gtp2_hdr_set_msg_type(hdr, 1); + gtp2_hdr_set_msg_len(hdr, 9); + gtp2_hdr_set_teid(hdr, 0); + gtp2_hdr_set_seq(hdr, 0x0041d4); + gtp2_hdr_set_spare(hdr, 0); + + EXPECT_TRUE(memcmp(buff, gtp2_c_pkt2, 8) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_ip4_utils.cpp b/infra/packet_manager/test/gtest_ip4_utils.cpp new file mode 100644 index 0000000..f6e98a1 --- /dev/null +++ b/infra/packet_manager/test/gtest_ip4_utils.cpp @@ -0,0 +1,274 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/****************************************************************************** + * more fragment + ******************************************************************************/ + +/* + * Internet Protocol Version 4, Src: 192.168.36.103, Dst: 192.168.40.137 + * 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: 44 + * Identification: 0xffff (65535) + * 001. .... = Flags: 0x1, More fragments + * 0... .... = Reserved bit: Not set + * .0.. .... = Don't fragment: Not set + * ..1. .... = More fragments: Set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 127 + * Protocol: TCP (6) + * Header Checksum: 0x4d8b [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x4d8b] + * Source Address: 192.168.36.103 + * Destination Address: 192.168.40.137 + * [Reassembled IPv4 in frame: 5] + * Data (24 bytes) + */ + +unsigned char data1[] = {0x45, 0x00, 0x00, 0x2c, 0xff, 0xff, 0x20, 0x00, 0x7f, 0x06, 0x4d, 0x8b, 0xc0, 0xa8, 0x24, 0x67, 0xc0, 0xa8, 0x28, 0x89}; + +TEST(IPV4_UTILS, GET1) +{ + const struct ip *hdr = (struct ip *)data1; + EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4); + EXPECT_TRUE(ip4_hdr_get_hdr_len(hdr) == 20); + EXPECT_TRUE(ip4_hdr_get_tos(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_total_len(hdr) == 44); + EXPECT_TRUE(ip4_hdr_get_ipid(hdr) == 65535); + EXPECT_TRUE(ip4_hdr_get_flags(hdr) == 1); + EXPECT_TRUE(ip4_hdr_get_rf_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_df_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_mf_flag(hdr) == true); + EXPECT_TRUE(ip4_hdr_get_frag_offset(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_ttl(hdr) == 127); + EXPECT_TRUE(ip4_hdr_get_proto(hdr) == 6); + EXPECT_TRUE(ip4_hdr_get_checksum(hdr) == 0x4d8b); + EXPECT_TRUE(ip4_hdr_get_src_addr(hdr) == 0xc0a82467); + EXPECT_TRUE(ip4_hdr_get_dst_addr(hdr) == 0xc0a82889); + EXPECT_TRUE(ip4_hdr_get_opt_len(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == NULL); +} + +TEST(IPV4_UTILS, SET1) +{ + char buff[20] = {0}; + + struct ip *hdr = (struct ip *)buff; + ip4_hdr_set_version(hdr, 4); + ip4_hdr_set_hdr_len(hdr, 20); + ip4_hdr_set_tos(hdr, 0); + ip4_hdr_set_total_len(hdr, 44); + ip4_hdr_set_ipid(hdr, 65535); + ip4_hdr_set_frag_offset(hdr, 0); + ip4_hdr_set_ttl(hdr, 127); + ip4_hdr_set_protocol(hdr, 6); + ip4_hdr_set_checksum(hdr, 0x4d8b); + ip4_hdr_set_src_addr(hdr, 0xc0a82467); + ip4_hdr_set_dst_addr(hdr, 0xc0a82889); + ip4_hdr_set_opt_len(hdr, 0); + ip4_hdr_set_opt_data(hdr, NULL); + + ip4_hdr_set_flags(hdr, 1); + EXPECT_TRUE(memcmp(buff, data1, 20) == 0); + + ip4_hdr_set_rf_flag(hdr, false); + ip4_hdr_set_df_flag(hdr, false); + ip4_hdr_set_mf_flag(hdr, true); + EXPECT_TRUE(memcmp(buff, data1, 20) == 0); +} + +/****************************************************************************** + * fragment offset + ******************************************************************************/ + +/* + * Frame 5: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) + * Ethernet II, Src: Fortinet_cc:87:22 (e8:1c:ba:cc:87:22), Dst: EvocInte_2f:35:b8 (00:22:46:2f:35:b8) + * Internet Protocol Version 4, Src: 192.168.36.103, Dst: 192.168.40.137 + * 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: 44 + * Identification: 0xffff (65535) + * 000. .... = Flags: 0x0 + * 0... .... = Reserved bit: Not set + * .0.. .... = Don't fragment: Not set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0011 = Fragment Offset: 24 + * Time to Live: 127 + * Protocol: TCP (6) + * Header Checksum: 0x6d88 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x6d88] + * Source Address: 192.168.36.103 + * Destination Address: 192.168.40.137 + * [2 IPv4 Fragments (48 bytes): #4(24), #5(24)] + * [Frame: 4, payload: 0-23 (24 bytes)] + * [Frame: 5, payload: 24-47 (24 bytes)] + * [Fragment count: 2] + * [Reassembled IPv4 length: 48] + * [Reassembled IPv4 data: f4a5270f9107248703d518e75018ff005e9200003132330af4a5270f9107248b03d518e7…] + * Transmission Control Protocol, Src Port: 62629, Dst Port: 9999, Seq: 1, Ack: 1, Len: 28 + * Data (28 bytes) + * Data: 3132330af4a5270f9107248b03d518e75018ff00301600006162630a + * [Length: 28] + */ + +unsigned char data2[] = {0x45, 0x00, 0x00, 0x2c, 0xff, 0xff, 0x00, 0x03, 0x7f, 0x06, 0x6d, 0x88, 0xc0, 0xa8, 0x24, 0x67, 0xc0, 0xa8, 0x28, 0x89}; + +TEST(IPV4_UTILS, GET2) +{ + const struct ip *hdr = (struct ip *)data2; + EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4); + EXPECT_TRUE(ip4_hdr_get_hdr_len(hdr) == 20); + EXPECT_TRUE(ip4_hdr_get_tos(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_total_len(hdr) == 44); + EXPECT_TRUE(ip4_hdr_get_ipid(hdr) == 65535); + EXPECT_TRUE(ip4_hdr_get_flags(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_rf_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_df_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_mf_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_frag_offset(hdr) == 24); + EXPECT_TRUE(ip4_hdr_get_ttl(hdr) == 127); + EXPECT_TRUE(ip4_hdr_get_proto(hdr) == 6); + EXPECT_TRUE(ip4_hdr_get_checksum(hdr) == 0x6d88); + EXPECT_TRUE(ip4_hdr_get_src_addr(hdr) == 0xc0a82467); + EXPECT_TRUE(ip4_hdr_get_dst_addr(hdr) == 0xc0a82889); + EXPECT_TRUE(ip4_hdr_get_opt_len(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == NULL); +} + +TEST(IPV4_UTILS, SET2) +{ + char buff[20] = {0}; + + struct ip *hdr = (struct ip *)buff; + ip4_hdr_set_version(hdr, 4); + ip4_hdr_set_hdr_len(hdr, 20); + ip4_hdr_set_tos(hdr, 0); + ip4_hdr_set_total_len(hdr, 44); + ip4_hdr_set_ipid(hdr, 65535); + ip4_hdr_set_frag_offset(hdr, 24); + ip4_hdr_set_ttl(hdr, 127); + ip4_hdr_set_protocol(hdr, 6); + ip4_hdr_set_checksum(hdr, 0x6d88); + ip4_hdr_set_src_addr(hdr, 0xc0a82467); + ip4_hdr_set_dst_addr(hdr, 0xc0a82889); + ip4_hdr_set_opt_len(hdr, 0); + ip4_hdr_set_opt_data(hdr, NULL); + + ip4_hdr_set_flags(hdr, 0); + EXPECT_TRUE(memcmp(buff, data2, 20) == 0); + + ip4_hdr_set_rf_flag(hdr, false); + ip4_hdr_set_df_flag(hdr, false); + ip4_hdr_set_mf_flag(hdr, false); + EXPECT_TRUE(memcmp(buff, data2, 20) == 0); +} + +/****************************************************************************** + * options + ******************************************************************************/ + +/* + * Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1 + * 0100 .... = Version: 4 + * .... 1111 = Header Length: 60 bytes (15) + * 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: 124 + * Identification: 0x0000 (0) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: ICMP (1) + * Header Checksum: 0xfd30 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xfd30] + * Source Address: 127.0.0.1 + * Destination Address: 127.0.0.1 + * Options: (40 bytes), Commercial Security + * IP Option - Commercial Security (40 bytes) + * Type: 134 + * 1... .... = Copy on fragmentation: Yes + * .00. .... = Class: Control (0) + * ...0 0110 = Number: Commercial IP security option (6) + * Length: 40 + * DOI: 1 + * Tag Type: Restrictive Category Bitmap (1) + * Sensitivity Level: 1 + * Categories: 0,2,4,5,6,239 + */ + +unsigned char data3[] = { + 0x4f, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x40, 0x00, 0x40, 0x01, 0xfd, 0x30, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x86, 0x28, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x22, 0x00, 0x01, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; + +TEST(IPV4_UTILS, GET3) +{ + const struct ip *hdr = (struct ip *)data3; + EXPECT_TRUE(ip4_hdr_get_version(hdr) == 4); + EXPECT_TRUE(ip4_hdr_get_hdr_len(hdr) == 60); + EXPECT_TRUE(ip4_hdr_get_tos(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_total_len(hdr) == 124); + EXPECT_TRUE(ip4_hdr_get_ipid(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_flags(hdr) == 2); + EXPECT_TRUE(ip4_hdr_get_rf_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_df_flag(hdr) == true); + EXPECT_TRUE(ip4_hdr_get_mf_flag(hdr) == false); + EXPECT_TRUE(ip4_hdr_get_frag_offset(hdr) == 0); + EXPECT_TRUE(ip4_hdr_get_ttl(hdr) == 64); + EXPECT_TRUE(ip4_hdr_get_proto(hdr) == 1); + EXPECT_TRUE(ip4_hdr_get_checksum(hdr) == 0xfd30); + EXPECT_TRUE(ip4_hdr_get_src_addr(hdr) == 0x7f000001); + EXPECT_TRUE(ip4_hdr_get_dst_addr(hdr) == 0x7f000001); + EXPECT_TRUE(ip4_hdr_get_opt_len(hdr) == 40); + EXPECT_TRUE(ip4_hdr_get_opt_data(hdr) == (const char *)(data3 + 20)); +} + +TEST(IPV4_UTILS, SET3) +{ + char buff[60] = {0}; + + struct ip *hdr = (struct ip *)buff; + ip4_hdr_set_version(hdr, 4); + ip4_hdr_set_hdr_len(hdr, 60); + ip4_hdr_set_tos(hdr, 0); + ip4_hdr_set_total_len(hdr, 124); + ip4_hdr_set_ipid(hdr, 0); + ip4_hdr_set_frag_offset(hdr, 0); + ip4_hdr_set_ttl(hdr, 64); + ip4_hdr_set_protocol(hdr, 1); + ip4_hdr_set_checksum(hdr, 0xfd30); + ip4_hdr_set_src_addr(hdr, 0x7f000001); + ip4_hdr_set_dst_addr(hdr, 0x7f000001); + ip4_hdr_set_opt_len(hdr, 40); + ip4_hdr_set_opt_data(hdr, (const char *)(data3 + 20)); + + ip4_hdr_set_flags(hdr, 2); + EXPECT_TRUE(memcmp(buff, data3, 60) == 0); + + ip4_hdr_set_rf_flag(hdr, false); + ip4_hdr_set_df_flag(hdr, true); + ip4_hdr_set_mf_flag(hdr, false); + EXPECT_TRUE(memcmp(buff, data3, 60) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_ip6_utils.cpp b/infra/packet_manager/test/gtest_ip6_utils.cpp new file mode 100644 index 0000000..94a51f8 --- /dev/null +++ b/infra/packet_manager/test/gtest_ip6_utils.cpp @@ -0,0 +1,104 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Internet Protocol Version 6, Src: fe80::250:56ff:fe69:dc00, Dst: ff02::1:2 + * 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: 60 + * Next Header: UDP (17) + * Hop Limit: 1 + * Source Address: fe80::250:56ff:fe69:dc00 + * Destination Address: ff02::1:2 + * [Source SLAAC MAC: VMware_69:dc:00 (00:50:56:69:dc:00)] + * */ + +unsigned char data[] = { + 0x60, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x11, 0x01, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x50, 0x56, 0xff, 0xfe, 0x69, 0xdc, 0x00, 0xff, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02}; + +TEST(IPV6_UTILS, GET) +{ + char src_str[INET6_ADDRSTRLEN]; + char dst_str[INET6_ADDRSTRLEN]; + const struct ip6_hdr *hdr = (struct ip6_hdr *)data; + EXPECT_TRUE(ip6_hdr_get_version(hdr) == 6); + EXPECT_TRUE(ip6_hdr_get_traffic_class(hdr) == 0); + EXPECT_TRUE(ip6_hdr_get_flow_label(hdr) == 0); + EXPECT_TRUE(ip6_hdr_get_payload_len(hdr) == 60); + EXPECT_TRUE(ip6_hdr_get_next_header(hdr) == 17); + EXPECT_TRUE(ip6_hdr_get_hop_limit(hdr) == 1); + struct in6_addr src_addr = ip6_hdr_get_src_in6_addr(hdr); + struct in6_addr dst_addr = ip6_hdr_get_dst_in6_addr(hdr); + + inet_ntop(AF_INET6, &src_addr, src_str, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &dst_addr, dst_str, INET6_ADDRSTRLEN); + EXPECT_TRUE(strcmp(src_str, "fe80::250:56ff:fe69:dc00") == 0); + EXPECT_TRUE(strcmp(dst_str, "ff02::1:2") == 0); +} + +TEST(IPV6_UTILS, SET) +{ + char buff[40] = {0}; + struct in6_addr src_addr; + struct in6_addr dst_addr; + struct ip6_hdr *hdr = (struct ip6_hdr *)buff; + + inet_pton(AF_INET6, "fe80::250:56ff:fe69:dc00", &src_addr); + inet_pton(AF_INET6, "ff02::1:2", &dst_addr); + ip6_hdr_set_version(hdr, 6); + ip6_hdr_set_traffic_class(hdr, 0); + ip6_hdr_set_flow_label(hdr, 0); + ip6_hdr_set_payload_len(hdr, 60); + ip6_hdr_set_next_header(hdr, 17); + ip6_hdr_set_hop_limit(hdr, 1); + ip6_hdr_set_src_in6_addr(hdr, src_addr); + ip6_hdr_set_dst_in6_addr(hdr, dst_addr); + + EXPECT_TRUE(memcmp(buff, data, 40) == 0); +} + +/* + * Fragment Header for IPv6 + * Next header: UDP (17) + * Reserved octet: 0x00 + * 0000 0101 1010 1... = Offset: 181 (1448 bytes) + * .... .... .... .00. = Reserved bits: 0 + * .... .... .... ...1 = More Fragments: Yes + * Identification: 0xf88eb466 + */ + +unsigned char frag[] = { + 0x11, 0x00, 0x05, 0xa9, 0xf8, 0x8e, 0xb4, 0x66}; + +TEST(IPV6_FRAG_HDR, GET) +{ + const struct ip6_frag *hdr = (struct ip6_frag *)frag; + EXPECT_TRUE(ipv6_frag_get_next_header(hdr) == 17); + EXPECT_TRUE(ipv6_frag_get_offset(hdr) == 1448); + EXPECT_TRUE(ipv6_frag_get_more(hdr) == 1); + EXPECT_TRUE(ipv6_frag_get_ident(hdr) == 0xf88eb466); +} + +TEST(IPV6_FRAG_HDR, SET) +{ + char buff[8] = {0}; + + struct ip6_frag *hdr = (struct ip6_frag *)buff; + ipv6_frag_set_next_header(hdr, 17); + ipv6_frag_set_offset(hdr, 1448); + ipv6_frag_set_more(hdr, 1); + ipv6_frag_set_ident(hdr, 0xf88eb466); + + EXPECT_TRUE(memcmp(buff, frag, 8) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_l2tp_utils.cpp b/infra/packet_manager/test/gtest_l2tp_utils.cpp new file mode 100644 index 0000000..3eb16bd --- /dev/null +++ b/infra/packet_manager/test/gtest_l2tp_utils.cpp @@ -0,0 +1,196 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Layer 2 Tunneling Protocol + * Flags: 0xc802, Type: Control Message, Length Bit, Sequence Bit + * 1... .... .... .... = Type: Control Message (1) + * .1.. .... .... .... = Length Bit: Length field is present + * .... 1... .... .... = Sequence Bit: Ns and Nr fields are present + * .... ..0. .... .... = Offset bit: Offset size field is not present + * .... ...0 .... .... = Priority: No priority + * .... .... .... 0010 = Version: 2 + * Length: 105 + * Tunnel ID: 0 + * Session ID: 0 + * Ns: 0 + * Nr: 0 + * Control Message AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1000 = Length: 8 + * Vendor ID: Reserved (0) + * AVP Type: Control Message (0) + * Message Type: Start_Control_Request (1) + * Protocol Version AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1000 = Length: 8 + * Vendor ID: Reserved (0) + * AVP Type: Protocol Version (2) + * Version: 1 + * Revision: 0 + * Framing Capabilities AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1010 = Length: 10 + * Vendor ID: Reserved (0) + * AVP Type: Framing Capabilities (3) + * .... .... .... .... .... .... .... ..0. = Async Framing Supported: False + * .... .... .... .... .... .... .... ...1 = Sync Framing Supported: True + * Bearer Capabilities AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1010 = Length: 10 + * Vendor ID: Reserved (0) + * AVP Type: Bearer Capabilities (4) + * .... .... .... .... .... .... .... ..0. = Analog Access Supported: False + * .... .... .... .... .... .... .... ...0 = Digital Access Supported: False + * Firmware Revision AVP + * 0... .... .... .... = Mandatory: False + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1000 = Length: 8 + * Vendor ID: Reserved (0) + * AVP Type: Firmware Revision (6) + * Firmware Revision: 1537 (0x0601) + * Host Name AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0001 0010 = Length: 18 + * Vendor ID: Reserved (0) + * AVP Type: Host Name (7) + * Host Name: IIE-SM-THINK + * Vendor Name AVP + * 0... .... .... .... = Mandatory: False + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1111 = Length: 15 + * Vendor ID: Reserved (0) + * AVP Type: Vendor Name (8) + * Vendor Name: Microsoft + * Assigned Tunnel ID AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1000 = Length: 8 + * Vendor ID: Reserved (0) + * AVP Type: Assigned Tunnel ID (9) + * Assigned Tunnel ID: 1 + * Receive Window Size AVP + * 1... .... .... .... = Mandatory: True + * .0.. .... .... .... = Hidden: False + * .... ..00 0000 1000 = Length: 8 + * Vendor ID: Reserved (0) + * AVP Type: Receive Window Size (10) + * Receive Window Size: 8 + */ + +unsigned char v2_over_udp_ctrl_msg[] = { + 0xc8, 0x02, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x02, + 0x01, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x06, 0x06, 0x01, 0x80, 0x12, 0x00, 0x00, 0x00, 0x07, 0x49, 0x49, 0x45, 0x2d, 0x53, 0x4d, 0x2d, 0x54, 0x48, 0x49, 0x4e, 0x4b, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x08, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x80, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x08}; + +TEST(L2TPV2_OVER_UDP_UTILS, CRTL_MSG) +{ + const struct l2tp_hdr *hdr = (struct l2tp_hdr *)v2_over_udp_ctrl_msg; + + EXPECT_TRUE(l2tp_hdr_get_ver(hdr) == 2); + EXPECT_TRUE(l2tp_hdr_get_type(hdr) == 1); + EXPECT_TRUE(calc_udp_l2tpv2_hdr_len((const char *)v2_over_udp_ctrl_msg, sizeof(v2_over_udp_ctrl_msg)) == 105); +} + +/* + * Layer 2 Tunneling Protocol + * Flags: 0x4002, Type: Data Message, Length Bit + * 0... .... .... .... = Type: Data Message (0) + * .1.. .... .... .... = Length Bit: Length field is present + * .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present + * .... ..0. .... .... = Offset bit: Offset size field is not present + * .... ...0 .... .... = Priority: No priority + * .... .... .... 0010 = Version: 2 + * Length: 78 + * Tunnel ID: 28998 + * Session ID: 2 + */ + +unsigned char v2_over_udp_data_msg[] = { + 0x40, 0x02, 0x00, 0x4e, 0x71, 0x46, 0x00, 0x02}; + +TEST(L2TPV2_OVER_UDP_UTILS, DATA_MSG) +{ + const struct l2tp_hdr *hdr = (struct l2tp_hdr *)v2_over_udp_data_msg; + + EXPECT_TRUE(l2tp_hdr_get_ver(hdr) == 2); + EXPECT_TRUE(l2tp_hdr_get_type(hdr) == 0); + EXPECT_TRUE(calc_udp_l2tpv2_hdr_len((const char *)v2_over_udp_data_msg, sizeof(v2_over_udp_data_msg)) == 8); +} + +/* + * TODO + */ + +unsigned char v3_over_udp_ctrl_msg[] = {}; + +TEST(L2TPV3_OVER_UDP_UTILS, CRTL_MSG) +{ + // TODO +} + +/* + * Layer 2 Tunneling Protocol version 3 + * Flags: 0x0003, Type: Data Message + * 0... .... .... .... = Type: Data Message (0) + * .0.. .... .... .... = Length Bit: Length field is not present + * .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present + * .... .... .... 0011 = Version: 3 + * Reserved: 0x0000 + * Session ID: 0x00000fa0 + * [Pseudowire Type: Unknown (0)] + * Cookie: 00000000 + */ + +unsigned char v3_over_udp_data_msg[] = { + 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xa0, 0x00, 0x00, 0x00, 0x00}; + +TEST(L2TPV3_OVER_UDP_UTILS, DATA_MSG) +{ + const struct l2tp_hdr *hdr = (struct l2tp_hdr *)v3_over_udp_data_msg; + + EXPECT_TRUE(l2tp_hdr_get_ver(hdr) == 3); + EXPECT_TRUE(l2tp_hdr_get_type(hdr) == 0); + EXPECT_TRUE(calc_udp_l2tpv3_hdr_len((const char *)v3_over_udp_data_msg, sizeof(v3_over_udp_data_msg)) == 12); +} + +/* + * TODO + */ + +unsigned char v3_over_ip_ctrl_msg[] = {}; + +TEST(L2TPV3_OVER_IP_UTILS, CRTL_MSG) +{ + // TODO +} + +/* + * Layer 2 Tunneling Protocol version 3 + * Session ID: 0x00009652 + * [Pseudowire Type: Unknown (0)] + * Cookie: ca031078 + */ + +unsigned char v3_over_ip_data_msg[] = { + 0x00, 0x00, 0x96, 0x52, 0xca, 0x03, 0x10, 0x78}; + +TEST(L2TPV3_OVER_IP_UTILS, DATA_MSG) +{ + EXPECT_TRUE(ntohl(*((uint32_t *)v3_over_ip_data_msg)) != 0); // data message + EXPECT_TRUE(calc_ip_l2tpv3_hdr_len((const char *)v3_over_ip_data_msg, sizeof(v3_over_ip_data_msg)) == 8); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_mpls_utils.cpp b/infra/packet_manager/test/gtest_mpls_utils.cpp new file mode 100644 index 0000000..9d3f0d8 --- /dev/null +++ b/infra/packet_manager/test/gtest_mpls_utils.cpp @@ -0,0 +1,42 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * MultiProtocol Label Switching Header, Label: 779408, Exp: 0, S: 0, TTL: 255 + * 1011 1110 0100 1001 0000 .... .... .... = MPLS Label: 779408 (0xbe490) + * .... .... .... .... .... 000. .... .... = MPLS Experimental Bits: 0 + * .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + */ + +unsigned char data[] = { + 0xbe, 0x49, 0x00, 0xff}; + +TEST(MPLS_UTILS, GET) +{ + const struct mpls_label *hdr = (struct mpls_label *)data; + + EXPECT_TRUE(mpls_label_get_label(hdr) == 0xbe490); + EXPECT_TRUE(mpls_label_get_tc(hdr) == 0); + EXPECT_TRUE(mpls_label_get_bos(hdr) == 0); + EXPECT_TRUE(mpls_label_get_ttl(hdr) == 255); +} + +TEST(MPLS_UTILS, SET) +{ + char buff[4] = {0}; + struct mpls_label *hdr = (struct mpls_label *)buff; + + mpls_label_set_label(hdr, 0xbe490); + mpls_label_set_tc(hdr, 0); + mpls_label_set_bos(hdr, 0); + mpls_label_set_ttl(hdr, 255); + EXPECT_TRUE(memcmp(buff, data, 4) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_packet_builder.cpp b/infra/packet_manager/test/gtest_packet_builder.cpp new file mode 100644 index 0000000..0bbf2bb --- /dev/null +++ b/infra/packet_manager/test/gtest_packet_builder.cpp @@ -0,0 +1,1230 @@ +#include <gtest/gtest.h> +#include <arpa/inet.h> + +#include "checksum.h" +#include "packet_helper.h" +#include "packet_private.h" +#include "packet_dump.h" +#include "packet_parser.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__) + +// https://dox.ipxe.org/tcp_8h_source.html +#define TCP_OPTION_TS 8 +#define TCP_OPTION_NOP 1 +struct tcp_timestamp_option +{ + uint8_t kind; + uint8_t length; + uint32_t tsval; + uint32_t tsecr; +} __attribute__((packed)); + +struct tcp_timestamp_padded_option +{ + uint8_t nop[2]; + struct tcp_timestamp_option tsopt; +} __attribute__((packed)); + +struct tcp_timestamp_padded_option ts_pad_opt = + { + .nop = {TCP_OPTION_NOP, TCP_OPTION_NOP}, + .tsopt = { + .kind = TCP_OPTION_TS, + .length = 10, + .tsval = 0x12345678, + .tsecr = 0x87654321, + }, +}; + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:tcp] + ****************************************************************************** + * + * Frame 1: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) + * Ethernet II, Src: 52:54:00:94:27:9b (52:54:00:94:27:9b), Dst: 52:54:00:19:8f:63 (52:54:00:19:8f:63) + * Destination: 52:54:00:19:8f:63 (52:54:00:19:8f:63) + * Source: 52:54:00:94:27:9b (52:54:00:94:27:9b) + * Type: IPv4 (0x0800) + * Padding: 000000000000 + * Internet Protocol Version 4, Src: 192.168.122.202, Dst: 192.168.122.100 + * 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: 40 + * Identification: 0x0c5e (3166) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: TCP (6) + * Header Checksum: 0xb7f2 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xb7f2] + * Source Address: 192.168.122.202 + * Destination Address: 192.168.122.100 + * Transmission Control Protocol, Src Port: 1080, Dst Port: 62395, Seq: 1457975085, Ack: 1047768425, Len: 0 + * Source Port: 1080 + * Destination Port: 62395 + * [Stream index: 0] + * [Conversation completeness: Incomplete (4)] + * ..0. .... = RST: Absent + * ...0 .... = FIN: Absent + * .... 0... = Data: Absent + * .... .1.. = ACK: Present + * .... ..0. = SYN-ACK: Absent + * .... ...0 = SYN: Absent + * [Completeness Flags: ···A··] + * [TCP Segment Len: 0] + * Sequence Number: 1457975085 + * [Next Sequence Number: 1457975085] + * Acknowledgment Number: 1047768425 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x010 (ACK) + * 000. .... .... = Reserved: Not set + * ...0 .... .... = Accurate ECN: Not set + * .... 0... .... = Congestion Window Reduced: Not set + * .... .0.. .... = ECN-Echo: Not set + * .... ..0. .... = Urgent: Not set + * .... ...1 .... = Acknowledgment: Set + * .... .... 0... = Push: Not set + * .... .... .0.. = Reset: Not set + * .... .... ..0. = Syn: Not set + * .... .... ...0 = Fin: Not set + * [TCP Flags: ·······A····] + * Window: 457 + * [Calculated window size: 457] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0x0da7 [correct] + * [Calculated Checksum: 0x0da7] + * [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 data1[] = { + 0x52, 0x54, 0x00, 0x19, 0x8f, 0x63, 0x52, 0x54, 0x00, 0x94, 0x27, 0x9b, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x0c, 0x5e, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xf2, + 0xc0, 0xa8, 0x7a, 0xca, 0xc0, 0xa8, 0x7a, 0x64, 0x04, 0x38, 0xf3, 0xbb, 0x56, 0xe6, 0xef, 0x2d, 0x3e, 0x73, 0xad, 0x69, 0x50, 0x10, 0x01, 0xc9, 0x0d, 0xa7, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/* + * packet_build_tcp() + * -> ETH->IPv4->TCP + * -> with TCP options + * -> with TCP payload + */ +#if 1 +TEST(PACKET_BUILD_TCP, ETH_IP4_TCP) +{ + struct packet orig_pkt; + memset(&orig_pkt, 0, sizeof(orig_pkt)); + packet_parse(&orig_pkt, (const char *)data1, sizeof(data1)); + PRINT_GREEN("origin packet:"); + packet_print(&orig_pkt); + + struct packet *new_pkt = packet_build_tcp(&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, "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); + + 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 - 6 == // trim Eth padding: 000000000000 + new_pkt_len - 12 - 5); // trim TCP options, TCP payload + int count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + if (layer->proto == LAYER_PROTO_IPV4) + { + 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 = (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 + (24 <= i && i <= 25)) // skip IPv4 checksum + { + continue; + } + if ((38 <= i && i <= 41) || // skip TCP seq + (42 <= i && i <= 45) || // skip TCP ack + i == 46 || // skip TCP data offset + i == 47 || // skip TCP flags + (50 <= i && i <= 51)) // 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]); + } + + packet_free(new_pkt); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:ipv6:tcp] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 92 + * Identification: 0x0b4d (2893) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 59 + * Protocol: IPv6 (41) + * Header Checksum: 0x09c8 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 210.77.88.163 + * Destination Address: 59.66.4.50 + * Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 32 + * Next Header: TCP (6) + * Hop Limit: 64 + * Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3 + * Destination Address: 2600:140e:6::1702:1058 + * [Source ISATAP IPv4: 210.77.88.163] + * Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 52556 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 2172673142 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x002 (SYN) + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0xf757 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * [Timestamps] + */ + +unsigned char data2[] = { + 0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8, + 0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00, + 0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50, + 0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, + 0x04, 0x02}; + +/* + * packet_build_tcp() + * -> ETH->IPv4->IPv6->TCP + * -> with TCP payload + */ +#if 1 +TEST(PACKET_BUILD_TCP, ETH_IP4_IP6_TCP) +{ + struct packet orig_pkt; + memset(&orig_pkt, 0, sizeof(orig_pkt)); + packet_parse(&orig_pkt, (const char *)data2, sizeof(data2)); + PRINT_GREEN("origin packet:"); + packet_print(&orig_pkt); + + struct packet *new_pkt = packet_build_tcp(&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, "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); + + 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 - 12 == // trim TCP options + new_pkt_len - 5); // trim TCP payload + int count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + if (layer->proto == LAYER_PROTO_IPV4) + { + 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 = (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) == 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 + (24 <= i && i <= 25)) // skip IPv4 checksum + { + continue; + } + if (38 <= i && i <= 39) // skip IPv6 payload length + { + continue; + } + if ((78 <= i && i <= 81) || // skip TCP seq + (82 <= i && i <= 85) || // skip TCP ack + i == 86 || // skip TCP data offset + i == 87 || // skip TCP flags + (90 <= i && i <= 91)) // 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]); + } + + packet_free(new_pkt); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ip:tcp:ja3:tls] + ****************************************************************************** + * + * Frame 1: 1470 bytes on wire (11760 bits), 1470 bytes captured (11760 bits) + * Ethernet II, Src: HuaweiTe_62:ee:70 (60:d7:55:62:ee:70), Dst: zte_0e:f5:1c (74:4a:a4:0e:f5:1c) + * Destination: zte_0e:f5:1c (74:4a:a4:0e:f5:1c) + * Source: HuaweiTe_62:ee:70 (60:d7:55:62:ee:70) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2409:8034:4025::50:a31, Dst: 2409:8034:4040:5301::204 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 1416 + * Next Header: UDP (17) + * Hop Limit: 252 + * Source Address: 2409:8034:4025::50:a31 + * Destination Address: 2409:8034:4040:5301::204 + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * Source Port: 2152 + * Destination Port: 2152 + * Length: 1416 + * Checksum: 0xc8df [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (1408 bytes) + * GPRS Tunneling Protocol + * Flags: 0x30 + * Message Type: T-PDU (0xff) + * Length: 1400 + * TEID: 0x6c2a4753 (1814710099) + * Internet Protocol Version 4, Src: 10.49.115.138, Dst: 121.196.250.66 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 1400 + * Identification: 0x0003 (3) + * 010. .... = Flags: 0x2, Don't fragment + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: TCP (6) + * Header Checksum: 0x43bb [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.49.115.138 + * Destination Address: 121.196.250.66 + * Transmission Control Protocol, Src Port: 50081, Dst Port: 443, Seq: 1, Ack: 1, Len: 1348 + * Source Port: 50081 + * Destination Port: 443 + * [Stream index: 0] + * [Conversation completeness: Incomplete (8)] + * [TCP Segment Len: 1348] + * Sequence Number: 1 (relative sequence number) + * Sequence Number (raw): 1522577104 + * [Next Sequence Number: 1349 (relative sequence number)] + * Acknowledgment Number: 1 (relative ack number) + * Acknowledgment number (raw): 3419365570 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x010 (ACK) + * Window: 2038 + * [Calculated window size: 2038] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0xd3c2 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps + * [Timestamps] + * [SEQ/ACK analysis] + * TCP payload (1348 bytes) + * Transport Layer Security + */ + +unsigned char data3[] = { + 0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x1c, 0x60, 0xd7, 0x55, 0x62, 0xee, 0x70, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x88, 0x11, 0xfc, 0x24, 0x09, 0x80, 0x34, + 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x0a, 0x31, 0x24, 0x09, 0x80, 0x34, 0x40, 0x40, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x08, 0x68, 0x08, 0x68, 0x05, 0x88, 0xc8, 0xdf, 0x30, 0xff, 0x05, 0x78, 0x6c, 0x2a, 0x47, 0x53, 0x45, 0x00, 0x05, 0x78, 0x00, 0x03, 0x40, 0x00, + 0x40, 0x06, 0x43, 0xbb, 0x0a, 0x31, 0x73, 0x8a, 0x79, 0xc4, 0xfa, 0x42, 0xc3, 0xa1, 0x01, 0xbb, 0x5a, 0xc0, 0xae, 0xd0, 0xcb, 0xcf, 0x60, 0xc2, 0x80, 0x10, + 0x07, 0xf6, 0xd3, 0xc2, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x85, 0x14, 0x0e, 0xb0, 0xcc, 0x45, 0xf8, 0x5f, 0xef, 0x49, 0x45, 0xa0, 0xbe, 0x21, 0xd6, 0x46, + 0x9f, 0xb5, 0x17, 0xb2, 0xfe, 0x61, 0x2d, 0xed, 0x4f, 0x0c, 0x1e, 0xb5, 0xda, 0x91, 0x40, 0x87, 0xab, 0x02, 0x0d, 0x01, 0xc8, 0xf1, 0x24, 0x05, 0x8a, 0x9d, + 0x8d, 0xfc, 0xbb, 0x82, 0x24, 0xf5, 0x7d, 0x2d, 0x10, 0x66, 0x30, 0x2a, 0xaa, 0x4a, 0x51, 0x8d, 0xe9, 0x9a, 0x65, 0xcf, 0x89, 0x0c, 0x9e, 0x0d, 0x82, 0xda, + 0x5e, 0xd3, 0x98, 0xe3, 0x23, 0xf7, 0x5a, 0xd4, 0x88, 0x94, 0xd2, 0xdf, 0xbe, 0x44, 0x20, 0x2b, 0x21, 0x2d, 0x38, 0xca, 0x29, 0x5e, 0xa3, 0xb7, 0xbb, 0x34, + 0x20, 0x42, 0x02, 0x71, 0x04, 0xda, 0xd2, 0xeb, 0xb8, 0x81, 0xa3, 0x48, 0xc8, 0x54, 0xad, 0x42, 0x35, 0xc4, 0x4f, 0x6b, 0x15, 0x50, 0x22, 0x3e, 0x26, 0xb3, + 0xfc, 0x30, 0x49, 0x71, 0x6f, 0x41, 0x66, 0xa2, 0x2e, 0xe9, 0xd3, 0x1a, 0x69, 0xa8, 0x87, 0x71, 0x65, 0xa2, 0xc7, 0xc7, 0x2b, 0x25, 0x1d, 0x3f, 0xfb, 0xe6, + 0x05, 0xe1, 0x09, 0xb9, 0x76, 0x1d, 0xb9, 0xf9, 0xaf, 0xb4, 0x79, 0xa1, 0x35, 0x05, 0x59, 0x88, 0xa0, 0x07, 0xb5, 0x2d, 0x02, 0x11, 0x0a, 0x89, 0xf1, 0x67, + 0xdb, 0xe5, 0x5c, 0x5c, 0xaa, 0x0e, 0x21, 0xa6, 0xa4, 0x1a, 0x9f, 0x9e, 0xc8, 0x2a, 0x36, 0x6f, 0xcc, 0xa3, 0x13, 0x78, 0xf1, 0xbe, 0x34, 0xa0, 0x35, 0xef, + 0x1f, 0xf4, 0x79, 0xcb, 0x37, 0x3e, 0x77, 0x14, 0xfb, 0x2e, 0x21, 0x4f, 0x6b, 0xe5, 0xe9, 0x3a, 0x90, 0x76, 0xa8, 0x55, 0x09, 0xb6, 0x68, 0xbf, 0x66, 0xae, + 0xf1, 0x55, 0xc0, 0x76, 0x8f, 0x16, 0x86, 0x49, 0x9a, 0x88, 0x01, 0xdb, 0x78, 0x1f, 0xde, 0xc2, 0x33, 0x92, 0xe3, 0x22, 0xc6, 0x8c, 0x20, 0x17, 0xa0, 0xb2, + 0x79, 0xf4, 0x60, 0x8e, 0x98, 0x53, 0xcd, 0x8f, 0xb2, 0x8f, 0x80, 0xda, 0x9f, 0xf6, 0x00, 0x0c, 0xf8, 0x6b, 0xdf, 0x7d, 0x93, 0x48, 0x5a, 0x23, 0x35, 0x0e, + 0x1b, 0xf7, 0x50, 0x87, 0x93, 0x29, 0xaa, 0xa1, 0xb8, 0x98, 0x9f, 0x89, 0xb2, 0x0a, 0x02, 0x27, 0x95, 0x01, 0x84, 0x5a, 0x09, 0xb8, 0xff, 0x23, 0x02, 0x89, + 0xef, 0x1b, 0x64, 0xb2, 0x38, 0x81, 0xc4, 0x36, 0xe3, 0xda, 0xb5, 0x3b, 0x80, 0x45, 0x52, 0x96, 0xab, 0x0e, 0xdb, 0xb6, 0x9c, 0xcb, 0xc4, 0xe5, 0xb9, 0x72, + 0x67, 0x57, 0x4b, 0xb9, 0x55, 0xcb, 0x6b, 0xc4, 0xec, 0x46, 0x4d, 0xa3, 0xe0, 0xda, 0xba, 0x70, 0x3d, 0xa6, 0xa7, 0x3f, 0x58, 0xd2, 0x9f, 0xb0, 0x11, 0x66, + 0xaf, 0x73, 0x09, 0x60, 0x6e, 0xe0, 0x71, 0xa5, 0x65, 0x41, 0x28, 0x3e, 0x70, 0x1d, 0x25, 0x77, 0x6a, 0x4e, 0xed, 0xb9, 0x27, 0x6c, 0xf0, 0xba, 0x54, 0x8d, + 0x77, 0xfb, 0xb6, 0x4e, 0xe2, 0xab, 0x8f, 0xe3, 0xd4, 0x02, 0x65, 0x0a, 0x49, 0xf3, 0xf9, 0xc7, 0x09, 0x76, 0x81, 0xf4, 0xf8, 0x3e, 0x1f, 0x74, 0x30, 0xaf, + 0x3b, 0x9e, 0x97, 0x00, 0xde, 0xd8, 0x9a, 0xaf, 0xcc, 0x72, 0xeb, 0x0a, 0xe7, 0xab, 0xc1, 0x53, 0x62, 0x3f, 0x08, 0xba, 0x43, 0x06, 0x13, 0x0a, 0x3b, 0x5c, + 0xb4, 0xe0, 0xc8, 0xa6, 0x41, 0x45, 0xaa, 0x1a, 0xc9, 0x88, 0x86, 0x31, 0x25, 0x02, 0x4a, 0x76, 0x66, 0xb6, 0x6d, 0xff, 0x50, 0x1d, 0x3c, 0xf3, 0x2d, 0xfe, + 0x7b, 0xb2, 0x75, 0x5d, 0x9a, 0x9a, 0xe5, 0x39, 0x31, 0x4f, 0x7b, 0xa5, 0x6f, 0x94, 0xed, 0x31, 0xd4, 0x61, 0xc7, 0x44, 0x1d, 0x37, 0x19, 0x76, 0x04, 0x0e, + 0xbd, 0xc4, 0x9e, 0xe3, 0xdf, 0x94, 0x49, 0x32, 0x65, 0xd0, 0x37, 0x64, 0xb5, 0x2a, 0x61, 0x2d, 0x05, 0xc5, 0xe5, 0x79, 0x3e, 0xcf, 0x5f, 0x77, 0x0a, 0x7c, + 0x29, 0x34, 0x1a, 0x45, 0x7e, 0x11, 0x68, 0xb4, 0x3a, 0xf6, 0x5b, 0x23, 0xe4, 0x32, 0xa4, 0x11, 0x1a, 0xba, 0xd6, 0x4a, 0x45, 0x42, 0x29, 0xac, 0xb0, 0x17, + 0x05, 0x1b, 0xee, 0xf6, 0x52, 0x6d, 0x8b, 0xb4, 0x3b, 0x63, 0xe2, 0xca, 0xbf, 0x7e, 0xd3, 0xf7, 0x96, 0x75, 0x67, 0x9d, 0x27, 0x15, 0x39, 0xde, 0x5f, 0x66, + 0x74, 0x7c, 0x46, 0x01, 0x48, 0xf7, 0x99, 0x33, 0x7d, 0xc6, 0x81, 0xc4, 0x82, 0x09, 0x00, 0x20, 0x3f, 0x5c, 0xe4, 0x51, 0x88, 0x5b, 0xac, 0x31, 0x17, 0x04, + 0xa4, 0xac, 0xbf, 0x3d, 0xff, 0xad, 0x51, 0x07, 0x0b, 0xc7, 0x26, 0xa7, 0x9f, 0x83, 0x17, 0xd8, 0x2f, 0x6a, 0x47, 0x96, 0x14, 0x47, 0x68, 0xd4, 0xc0, 0xc0, + 0x3b, 0x87, 0x51, 0x30, 0xe9, 0xfa, 0x21, 0x46, 0x80, 0x1a, 0x5a, 0xef, 0x78, 0xd0, 0x3a, 0xac, 0x73, 0x1e, 0x39, 0xba, 0x82, 0x43, 0x5d, 0xef, 0x15, 0x2c, + 0x9a, 0xe5, 0xeb, 0x6a, 0xe7, 0x24, 0x12, 0xe6, 0x2a, 0xd2, 0x09, 0xc2, 0x85, 0x69, 0x9d, 0x73, 0x16, 0xb0, 0xad, 0x51, 0xf8, 0x3d, 0x94, 0x6b, 0xb7, 0xb3, + 0x7f, 0xb4, 0x9e, 0xc1, 0xdc, 0x31, 0x27, 0xa1, 0x2d, 0xfe, 0x30, 0x15, 0x04, 0x20, 0x82, 0xdc, 0xbd, 0x8b, 0xc5, 0xb4, 0xcf, 0x91, 0x85, 0xae, 0x21, 0x5e, + 0x00, 0x10, 0x04, 0x62, 0x8a, 0xe2, 0x66, 0x74, 0xf8, 0x8d, 0x8b, 0x52, 0x17, 0xd9, 0x1a, 0xbd, 0x06, 0x2d, 0x07, 0x6a, 0xf5, 0x8b, 0xdf, 0x85, 0x2e, 0x36, + 0xec, 0x15, 0x6f, 0x7e, 0xd2, 0x04, 0x43, 0x6a, 0xd7, 0x60, 0xf5, 0x53, 0x0d, 0x2e, 0x2d, 0xf5, 0x52, 0x4c, 0xcc, 0xe5, 0xf4, 0x47, 0xdd, 0x34, 0xda, 0xc1, + 0xfc, 0x60, 0x00, 0xaa, 0x68, 0x01, 0x5c, 0x82, 0x4b, 0xf9, 0x57, 0x54, 0x9d, 0xd5, 0x8b, 0xb6, 0x42, 0x77, 0xd4, 0x47, 0x70, 0x23, 0x4c, 0xad, 0xc5, 0x00, + 0x73, 0x9b, 0xbb, 0x65, 0xa7, 0x46, 0x74, 0xcd, 0x2e, 0x61, 0x0f, 0xac, 0xeb, 0x53, 0x5a, 0x87, 0x70, 0xfc, 0x5d, 0x2e, 0xa1, 0xe3, 0x9a, 0x87, 0x01, 0x0f, + 0x2e, 0xef, 0x10, 0xe2, 0x82, 0xd8, 0x12, 0xe7, 0xb8, 0x94, 0xa4, 0xdd, 0x5f, 0xea, 0x21, 0x63, 0x26, 0x43, 0xec, 0xc3, 0x54, 0x76, 0xb1, 0xb2, 0x1c, 0x03, + 0x4c, 0x5c, 0x22, 0xb5, 0x00, 0x7d, 0x77, 0x3a, 0xb6, 0xbf, 0x50, 0xbd, 0xfd, 0x0a, 0x31, 0x2c, 0xdc, 0xab, 0xe2, 0xc0, 0x0b, 0xb6, 0x66, 0xad, 0x9c, 0xca, + 0x94, 0xed, 0xd8, 0x77, 0x1b, 0xf1, 0x94, 0xdd, 0x65, 0x61, 0xda, 0x7b, 0x04, 0x3c, 0x93, 0xcf, 0x96, 0x74, 0x35, 0x8e, 0x41, 0xe1, 0xa4, 0xbc, 0xf2, 0x4f, + 0xe9, 0xb8, 0x16, 0x55, 0x05, 0x5a, 0xac, 0x10, 0xd3, 0xdf, 0xea, 0x6a, 0xf8, 0xe0, 0xf3, 0xdf, 0x66, 0x00, 0xab, 0x3d, 0xb9, 0x44, 0x65, 0x34, 0x49, 0x89, + 0xf2, 0x1d, 0x09, 0xc9, 0xfc, 0xa5, 0x84, 0xa1, 0x03, 0x5b, 0x7a, 0x5c, 0x7e, 0x21, 0xe9, 0xb4, 0x3a, 0x4c, 0x2b, 0x94, 0x64, 0x1d, 0x9b, 0xa5, 0xbf, 0x7e, + 0x1c, 0x97, 0x7e, 0x3d, 0xbe, 0x84, 0xfc, 0xab, 0x6d, 0x2a, 0x50, 0x23, 0x9e, 0x11, 0x3f, 0xe2, 0xa0, 0x68, 0xe7, 0xd5, 0xba, 0x5e, 0x24, 0x8c, 0x4c, 0x46, + 0xe6, 0x5b, 0x10, 0xc3, 0x82, 0x32, 0x17, 0x32, 0xdc, 0xec, 0xaa, 0x1e, 0x73, 0xe5, 0x7d, 0xb8, 0x1c, 0x6c, 0x4c, 0x9f, 0x60, 0x7b, 0x66, 0x4c, 0x90, 0x69, + 0xc4, 0x23, 0x66, 0x67, 0xce, 0x6d, 0x24, 0x1d, 0xcc, 0x8e, 0x78, 0xa1, 0xa7, 0xde, 0x87, 0x81, 0xac, 0x62, 0x54, 0xbc, 0x47, 0x82, 0x3c, 0xad, 0x92, 0x29, + 0xd9, 0xc0, 0xed, 0x0c, 0x11, 0x0e, 0xc5, 0x75, 0xa4, 0xbd, 0xbf, 0xcb, 0x3a, 0xaf, 0x2b, 0x9f, 0xbe, 0xbb, 0xbc, 0x31, 0x07, 0xa7, 0xbe, 0x6c, 0xa9, 0x4e, + 0xff, 0x35, 0x80, 0x2f, 0x09, 0x77, 0xe0, 0xc0, 0xdc, 0x9c, 0xc6, 0xa6, 0x63, 0xab, 0x47, 0x74, 0x5f, 0x5c, 0xae, 0x75, 0xbf, 0x42, 0x67, 0x55, 0x89, 0xcf, + 0xd3, 0x65, 0x8d, 0x5b, 0x6f, 0x5c, 0xf9, 0xd1, 0x78, 0xa2, 0xfd, 0x4f, 0x54, 0x6a, 0x71, 0x0c, 0x58, 0x13, 0xb0, 0x48, 0x0a, 0x7b, 0xcc, 0x84, 0x61, 0xa7, + 0x7d, 0x39, 0xa2, 0xd1, 0xc0, 0xdb, 0x8e, 0x97, 0x20, 0x86, 0x97, 0x20, 0xda, 0xca, 0x56, 0x78, 0x61, 0xc2, 0x2f, 0x36, 0xdb, 0x95, 0xae, 0x7e, 0x8d, 0x97, + 0xcb, 0x45, 0x6a, 0x6d, 0x27, 0xaa, 0xab, 0x4e, 0x88, 0x23, 0xb6, 0x6a, 0x8a, 0xca, 0x71, 0xca, 0x39, 0xa2, 0x98, 0x0d, 0x53, 0xa9, 0x38, 0xd5, 0x9c, 0x5d, + 0x0e, 0x5e, 0xc9, 0xeb, 0x21, 0xab, 0x00, 0xca, 0xff, 0x92, 0x20, 0x9d, 0x65, 0x9d, 0x8d, 0x49, 0x46, 0xbe, 0x51, 0x97, 0xc1, 0x61, 0x02, 0x9e, 0xa8, 0xb9, + 0x2c, 0x27, 0x7d, 0x73, 0xf9, 0x12, 0x16, 0x45, 0x25, 0xbb, 0xb0, 0x51, 0x14, 0x18, 0x07, 0xab, 0xc7, 0x06, 0xc0, 0xe9, 0x1c, 0xf8, 0x6d, 0xe1, 0x80, 0x21, + 0x21, 0x68, 0x24, 0xf7, 0x28, 0xb9, 0x07, 0xd4, 0xd7, 0xdf, 0x3e, 0xff, 0xbc, 0xe3, 0xbc, 0x6e, 0x42, 0x76, 0x63, 0xbc, 0x82, 0x0a, 0xf5, 0x99, 0x65, 0x17, + 0xd2, 0x38, 0xa9, 0xa8, 0x31, 0xce, 0x1f, 0xf7, 0xef, 0x8d, 0x94, 0xae, 0x99, 0x50, 0x30, 0x12, 0xbd, 0x4b, 0x65, 0x56, 0x59, 0xfb, 0x33, 0x7b, 0x99, 0xc7, + 0xe5, 0x80, 0xe6, 0x92, 0x0e, 0x44, 0x1d, 0x17, 0xc2, 0xd0, 0x78, 0x76, 0x9d, 0x5b, 0x7d, 0x3c, 0xb4, 0xf8, 0xcb, 0x2f, 0x83, 0x23, 0x35, 0x49, 0xc0, 0x78, + 0x2d, 0x44, 0x05, 0x64, 0x0f, 0xaa, 0x84, 0x9d, 0x3f, 0xac, 0xef, 0x5b, 0x46, 0x44, 0xb8, 0x15, 0xbe, 0x4f, 0xe7, 0x25, 0xb7, 0xa0, 0xc8, 0x0f, 0x70, 0x1a, + 0xca, 0x7f, 0xce, 0x79, 0x7b, 0xf5, 0x7e, 0x21, 0x35, 0xc7, 0x0e, 0x99, 0xdc, 0x76, 0xe0, 0x36, 0x09, 0x6e, 0x6d, 0x5f, 0x98, 0x5e, 0xb8, 0xa4, 0x88, 0xea, + 0x0b, 0x4b, 0x21, 0xa2, 0x52, 0x86, 0x95, 0x4e, 0x18, 0xac, 0xa2, 0xaf, 0x29, 0x5b, 0xe7, 0x05, 0xa1, 0xc8, 0xe1, 0x80, 0xfa, 0xb6, 0x5a, 0xed, 0x94, 0x32, + 0x4f, 0xe9, 0xf5, 0xf0, 0x61, 0x5d, 0x7f, 0xc4, 0xc4, 0xd1, 0x05, 0x54, 0x13, 0xdb}; + +/* + * packet_build_tcp() + * -> ETH->IPv6->UDP->GTP->IPv4->TCP + * -> with TCP payload + */ +#if 1 +TEST(PACKET_BUILD_TCP, ETH_IP6_UDP_GTP_IP4_TCP) +{ + struct packet orig_pkt; + memset(&orig_pkt, 0, sizeof(orig_pkt)); + packet_parse(&orig_pkt, (const char *)data3, sizeof(data3)); + PRINT_GREEN("origin packet:"); + packet_print(&orig_pkt); + + struct packet *new_pkt = packet_build_tcp(&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-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); + + 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 - 12 - 1348 == // trim TCP options, TCP payload + new_pkt_len - 5); // trim TCP payload + int count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + 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) == 61); + break; + } + if (layer->proto == LAYER_PROTO_UDP) + { + 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 = (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 = (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 = (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 + { + continue; + } + if ((58 <= i && i <= 59) || // skip UDP length + (60 <= i && i <= 61)) // skip UDP checksum + { + continue; + } + if ((64 <= i && i <= 65)) // skip gtp length + { + continue; + } + if ((72 <= i && i <= 73) || // skip IPv4 total length + (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 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]); + } + + packet_free(new_pkt); +} +#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}; + +/* + * packet_build_tcp() + * -> ETH->IPv4->GRE->IPv6->TCP + * -> with TCP payload + * -> with GRE checksum + */ +#if 1 +TEST(PACKET_BUILD_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 = packet_build_tcp(&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 + int count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + 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; + } + + // 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]); + } + + packet_free(new_pkt); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:vlan:ethertype:ipv6:ip:gre:ppp:ip:udp:dns] + ****************************************************************************** + * + * Frame 1: 197 bytes on wire (1576 bits), 197 bytes captured (1576 bits) + * Ethernet II, Src: JuniperNetwo_f2:61:3d (00:12:1e:f2:61:3d), Dst: c5:00:00:00:82:c4 (c5:00:00:00:82:c4) + * Destination: c5:00:00:00:82:c4 (c5:00:00:00:82:c4) + * Source: JuniperNetwo_f2:61:3d (00:12:1e:f2:61:3d) + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 100 + * 000. .... .... .... = Priority: Best Effort (default) (0) + * ...0 .... .... .... = DEI: Ineligible + * .... 0000 0110 0100 = ID: 100 + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2402:f000:1:8e01::5555, Dst: 2607:fcd0:100:2300::b108:2a6b + * 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: 139 + * Next Header: IPIP (4) + * Hop Limit: 246 + * Source Address: 2402:f000:1:8e01::5555 + * Destination Address: 2607:fcd0:100:2300::b108:2a6b + * Internet Protocol Version 4, Src: 16.0.0.200, Dst: 192.52.166.154 + * 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: 139 + * Identification: 0x8caf (36015) + * 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: 0x75fe [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x75fe] + * Source Address: 16.0.0.200 + * Destination Address: 192.52.166.154 + * Generic Routing Encapsulation (PPP) + * Flags and Version: 0x3081 + * 0... .... .... .... = Checksum Bit: No + * .0.. .... .... .... = Routing Bit: No + * ..1. .... .... .... = Key Bit: Yes + * ...1 .... .... .... = Sequence Number Bit: Yes + * .... 0... .... .... = Strict Source Route Bit: No + * .... .000 .... .... = Recursion control: 0 + * .... .... 1... .... = Acknowledgment: Yes + * .... .... .000 0... = Flags (Reserved): 0 + * .... .... .... .001 = Version: Enhanced GRE (1) + * Protocol Type: PPP (0x880b) + * Payload Length: 103 + * Call ID: 6016 + * Sequence Number: 430001 + * Acknowledgment Number: 539254 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 172.16.44.3, Dst: 8.8.8.8 + * 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: 99 + * Identification: 0x0000 (0) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 60 + * Protocol: UDP (17) + * Header Checksum: 0x5667 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x5667] + * Source Address: 172.16.44.3 + * Destination Address: 8.8.8.8 + * User Datagram Protocol, Src Port: 40768, Dst Port: 53 + * Source Port: 40768 + * Destination Port: 53 + * Length: 79 + * Checksum: 0x2d23 [correct] + * [Calculated Checksum: 0x2d23] + * [Checksum Status: Good] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (71 bytes) + * Domain Name System (query) + * Transaction ID: 0xa62c + * Flags: 0x0100 Standard query + * 0... .... .... .... = Response: Message is a query + * .000 0... .... .... = Opcode: Standard query (0) + * .... ..0. .... .... = Truncated: Message is not truncated + * .... ...1 .... .... = Recursion desired: Do query recursively + * .... .... .0.. .... = Z: reserved (0) + * .... .... ...0 .... = Non-authenticated data: Unacceptable + * Questions: 1 + * Answer RRs: 0 + * Authority RRs: 0 + * Additional RRs: 0 + * Queries + * xqt-detect-mode2-97712e88-167a-45b9-93ee-913140e76678: type AAAA, class IN + * Name: xqt-detect-mode2-97712e88-167a-45b9-93ee-913140e76678 + * [Name Length: 53] + * [Label Count: 1] + * Type: AAAA (28) (IP6 Address) + * Class: IN (0x0001) + * [Response In: 2] + */ + +unsigned char data5[] = { + 0xc5, 0x00, 0x00, 0x00, 0x82, 0xc4, 0x00, 0x12, 0x1e, 0xf2, 0x61, 0x3d, 0x81, 0x00, 0x00, 0x64, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x04, 0xf6, + 0x24, 0x02, 0xf0, 0x00, 0x00, 0x01, 0x8e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x26, 0x07, 0xfc, 0xd0, 0x01, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb1, 0x08, 0x2a, 0x6b, 0x45, 0x00, 0x00, 0x8b, 0x8c, 0xaf, 0x00, 0x00, 0x40, 0x2f, 0x75, 0xfe, 0x10, 0x00, 0x00, 0xc8, 0xc0, 0x34, 0xa6, 0x9a, + 0x30, 0x81, 0x88, 0x0b, 0x00, 0x67, 0x17, 0x80, 0x00, 0x06, 0x8f, 0xb1, 0x00, 0x08, 0x3a, 0x76, 0xff, 0x03, 0x00, 0x21, 0x45, 0x00, 0x00, 0x63, 0x00, 0x00, + 0x40, 0x00, 0x3c, 0x11, 0x56, 0x67, 0xac, 0x10, 0x2c, 0x03, 0x08, 0x08, 0x08, 0x08, 0x9f, 0x40, 0x00, 0x35, 0x00, 0x4f, 0x2d, 0x23, 0xa6, 0x2c, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x78, 0x71, 0x74, 0x2d, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x32, 0x2d, + 0x39, 0x37, 0x37, 0x31, 0x32, 0x65, 0x38, 0x38, 0x2d, 0x31, 0x36, 0x37, 0x61, 0x2d, 0x34, 0x35, 0x62, 0x39, 0x2d, 0x39, 0x33, 0x65, 0x65, 0x2d, 0x39, 0x31, + 0x33, 0x31, 0x34, 0x30, 0x65, 0x37, 0x36, 0x36, 0x37, 0x38, 0x00, 0x00, 0x1c, 0x00, 0x01}; + +/* + * packet_build_udp() + * -> ETH->VLAN->IPv6->IPv4->GRE->PPP->IPv4->UDP->DNS + * -> with UDP payload + * -> with GRE payload length + */ +#if 1 +TEST(PACKET_BUILD_UDP, ETH_VLAN_IPv6_IPv4_GRE_PPP_IPv4_UDP_DNS) +{ + struct packet orig_pkt; + memset(&orig_pkt, 0, sizeof(orig_pkt)); + packet_parse(&orig_pkt, (const char *)data5, sizeof(data5)); + PRINT_GREEN("origin packet:"); + packet_print(&orig_pkt); + + struct packet *new_pkt = packet_build_udp(&orig_pkt, "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-vlan-ipv6-ipv4-gre-ppp-ipv4-udp-dns.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 - 71 == // trim DNS payload + new_pkt_len - 5); // trim UDP payload + int flag = 0; + int count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + 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) == 73); + } + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip = (const struct ip *)layer->hdr.raw; + if (flag == 0) + { + EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 73); + EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0x7640); + } + else + { + EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 33); + EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0x56a9); + } + flag++; + } + if (layer->proto == LAYER_PROTO_GRE) + { + const struct gre1_hdr *gre = (const struct gre1_hdr *)layer->hdr.raw; + EXPECT_TRUE(gre1_hdr_get_version(gre) == 1); + EXPECT_TRUE(gre1_hdr_get_payload_length(gre) == 37); + } + if (layer->proto == LAYER_PROTO_UDP) + { + const struct udphdr *udp = (const struct udphdr *)layer->hdr.raw; + EXPECT_TRUE(udp_hdr_get_total_len(udp) == 13); + EXPECT_TRUE(udp_hdr_get_checksum(udp) == 0x5469); + } + } + + for (uint16_t i = 0; i < new_pkt_len - 5; i++) + { + if (22 <= i && i <= 23) /// skip IPv6 payload length + { + continue; + } + if ((60 <= i && i <= 61) || // skip IPv4 total length + (68 <= i && i <= 69)) // skip IPv4 checksum + { + continue; + } + if ((82 <= i && i <= 83)) // skip GRE payload length + { + continue; + } + if ((100 <= i && i <= 101) || // skip IPv4 total length + (108 <= i && i <= 109)) // skip IPv4 checksum + { + continue; + } + if ((122 <= i && i <= 123) || // skip UDP total length + (124 <= i && i <= 125)) // skip UDP 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]); + } + + packet_free(new_pkt); +} +#endif + +/* + * packet_build_l3() + * -> ETH->IPv4->ICMP + * -> ICMPv4 checkum not include the pseudo-header of IPv4 header + */ +#if 1 +TEST(PACKET_BUILD_L3, ETH_IP4_ICMP) +{ + /* + * Internet Control Message Protocol + * Type: 8 (Echo (ping) request) + * Code: 0 + * Checksum: 0xaa4f [correct] + * [Checksum Status: Good] + * Identifier (BE): 27498 (0x6b6a) + * Identifier (LE): 27243 (0x6a6b) + * Sequence Number (BE): 0 (0x0000) + * Sequence Number (LE): 0 (0x0000) + * [Response frame: 31] + * Timestamp from icmp data: Aug 2, 2024 10:51:12.214771000 CST + * [Timestamp from icmp data (relative): 0.000093000 seconds] + * Data (48 bytes) + * Data: 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637 + * [Length: 48] + */ + unsigned char icmp_resp[] = { + 0x08, 0x00, 0xaa, 0x4f, 0x6b, 0x6a, 0x00, 0x00, 0x66, 0xac, 0x49, 0xa0, 0x00, 0x03, 0x46, 0xf3, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}; + + struct packet orig_pkt; + memset(&orig_pkt, 0, sizeof(orig_pkt)); + packet_parse(&orig_pkt, (const char *)data1, sizeof(data1)); + PRINT_GREEN("origin packet:"); + packet_print(&orig_pkt); + + struct icmphdr *icmp = (struct icmphdr *)icmp_resp; + icmp->checksum = 0; + icmp->checksum = checksum(icmp, sizeof(icmp_resp)); + + struct packet *new_pkt = packet_build_l3(&orig_pkt, IPPROTO_ICMP, (const char *)icmp_resp, sizeof(icmp_resp)); + 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-icmpv4.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 - 20 - 6 == // trim Eth padding, trim TCP header + new_pkt_len - 64); // trim ICMP + int count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip = (const struct ip *)layer->hdr.raw; + EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 84); + EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0xb7cb); + break; + } + if (layer->proto == LAYER_PROTO_ICMP) + { + // TODO + break; + } + } + for (uint16_t i = 0; i < new_pkt_len - sizeof(icmp_resp); i++) + { + if ((16 <= i && i <= 17) || // skip IPv4 total length + 23 == i || // skip IPv4 protocol + (24 <= i && i <= 25)) // skip IPv4 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]); + } + + packet_free(new_pkt); +} +#endif + +/* + * packet_build_l3() + * -> ETH->IPv4->IPv6->ICMPv6 + * -> ICMPv6 checkum need include the pseudo-header of IPv6 header + */ +#if 1 +TEST(PACKET_BUILD_L3, ETH_IP6_ICMP) +{ + /* + * Internet Control Message Protocol v6 + * Type: Echo (ping) request (128) + * Code: 0 + * Checksum: 0x7e8f [correct] + * [Checksum Status: Good] + * Identifier: 0x18dc + * Sequence: 0 + * [Response In: 2] + * Data (52 bytes) + * Data: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233 + * [Length: 52] + */ + unsigned char icmp_resp[] = { + 0x80, 0x00, 0x7e, 0x8f, 0x18, 0xdc, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33}; + + struct packet orig_pkt; + memset(&orig_pkt, 0, sizeof(orig_pkt)); + packet_parse(&orig_pkt, (const char *)data2, sizeof(data2)); + PRINT_GREEN("origin packet:"); + packet_print(&orig_pkt); + + struct icmp6_hdr *icmp = (struct icmp6_hdr *)icmp_resp; + icmp->icmp6_cksum = 0; + + int count = packet_get_layer_count(&orig_pkt); + for (int i = count - 1; i >= 0; i--) + { + const struct layer *layer = packet_get_layer_by_idx(&orig_pkt, i); + if (layer->proto == LAYER_PROTO_IPV6) + { + struct ip6_hdr *ip6 = (struct ip6_hdr *)layer->hdr.raw; + icmp->icmp6_cksum = checksum_v6(icmp, sizeof(icmp_resp), IPPROTO_ICMPV6, &ip6->ip6_src, &ip6->ip6_dst); + break; + } + } + + struct packet *new_pkt = packet_build_l3(&orig_pkt, IPPROTO_ICMPV6, (const char *)icmp_resp, sizeof(icmp_resp)); + 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-ipv6-icmpv6.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 - 32 == // trim TCP header + new_pkt_len - 60); // trim ICMPv6 header + count = packet_get_layer_count(new_pkt); + for (int i = 0; i < count; i++) + { + const struct layer *layer = packet_get_layer_by_idx(new_pkt, i); + if (layer->proto == LAYER_PROTO_IPV4) + { + const struct ip *ip = (const struct ip *)layer->hdr.raw; + EXPECT_TRUE(ip4_hdr_get_total_len(ip) == 120); + EXPECT_TRUE(ip4_hdr_get_checksum(ip) == 0x09ac); + 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) == 60); + break; + } + if (layer->proto == LAYER_PROTO_ICMP6) + { + // TODO + break; + } + } + for (uint16_t i = 0; i < new_pkt_len - 60; i++) + { + if ((16 <= i && i <= 17) || // skip IPv4 total length + (24 <= i && i <= 25)) // skip IPv4 checksum + { + continue; + } + if (38 <= i && i <= 39) // skip IPv6 payload length + { + continue; + } + if (40 == i) // skip IPv6 next header + { + 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]); + } + + packet_free(new_pkt); +} +#endif + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_packet_filter.cpp b/infra/packet_manager/test/gtest_packet_filter.cpp new file mode 100644 index 0000000..3263b90 --- /dev/null +++ b/infra/packet_manager/test/gtest_packet_filter.cpp @@ -0,0 +1,97 @@ +#include <gtest/gtest.h> + +#include "tuple.h" +#include "packet_private.h" +#include "packet_parser.h" +#include "packet_filter.h" + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:ipv6:tcp] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 92 + * Identification: 0x0b4d (2893) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 59 + * Protocol: IPv6 (41) + * Header Checksum: 0x09c8 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 210.77.88.163 + * Destination Address: 59.66.4.50 + * Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 32 + * Next Header: TCP (6) + * Hop Limit: 64 + * Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3 + * Destination Address: 2600:140e:6::1702:1058 + * [Source ISATAP IPv4: 210.77.88.163] + * Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 52556 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 2172673142 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x002 (SYN) + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0xf757 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * [Timestamps] + */ + +unsigned char data[] = { + 0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8, + 0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00, + 0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50, + 0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, + 0x04, 0x02}; + +TEST(DUPLICATED_PACKET_FILTER, TEST) +{ + struct packet pkt; + uint32_t capacity = 1000000; + uint32_t timeout = 2; + double error_rate = 0.00001; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data, sizeof(data)); + + struct packet_filter *filter = packet_filter_new(capacity, timeout, error_rate, 1); + EXPECT_TRUE(filter != nullptr); + + EXPECT_TRUE(packet_filter_lookup(filter, &pkt, 1) == 0); // no found + packet_filter_add(filter, &pkt, 1); // add + EXPECT_TRUE(packet_filter_lookup(filter, &pkt, 1) == 1); // found + EXPECT_TRUE(packet_filter_lookup(filter, &pkt, 2) == 1); // found + EXPECT_TRUE(packet_filter_lookup(filter, &pkt, 3) == 0); // not found + EXPECT_TRUE(packet_filter_lookup(filter, &pkt, 4) == 0); // not found + + packet_filter_free(filter); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_packet_frag.cpp b/infra/packet_manager/test/gtest_packet_frag.cpp new file mode 100644 index 0000000..222925b --- /dev/null +++ b/infra/packet_manager/test/gtest_packet_frag.cpp @@ -0,0 +1,315 @@ +#include <gtest/gtest.h> + +#include "packet_private.h" +#include "packet_parser.h" + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:data] + ****************************************************************************** + * + * Frame 4: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) + * Ethernet II, Src: Fortinet_cc:87:22 (e8:1c:ba:cc:87:22), Dst: EvocInte_2f:35:b8 (00:22:46:2f:35:b8) + * Destination: EvocInte_2f:35:b8 (00:22:46:2f:35:b8) + * Source: Fortinet_cc:87:22 (e8:1c:ba:cc:87:22) + * Type: IPv4 (0x0800) + * Padding: 0000 + * Internet Protocol Version 4, Src: 192.168.36.103, Dst: 192.168.40.137 + * 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: 44 + * Identification: 0xffff (65535) + * 001. .... = Flags: 0x1, More fragments + * 0... .... = Reserved bit: Not set + * .0.. .... = Don't fragment: Not set + * ..1. .... = More fragments: Set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 127 + * Protocol: TCP (6) + * Header Checksum: 0x4d8b [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x4d8b] + * Source Address: 192.168.36.103 + * Destination Address: 192.168.40.137 + * [Reassembled IPv4 in frame: 5] + * Data (24 bytes) + * Data: f4a5270f9107248703d518e75018ff005e9200003132330a + * [Length: 24] + */ + +unsigned char data1[] = { + 0x00, 0x22, 0x46, 0x2f, 0x35, 0xb8, 0xe8, 0x1c, 0xba, 0xcc, 0x87, 0x22, 0x08, 0x00, 0x45, 0x00, 0x00, 0x2c, 0xff, 0xff, 0x20, 0x00, 0x7f, 0x06, 0x4d, 0x8b, + 0xc0, 0xa8, 0x24, 0x67, 0xc0, 0xa8, 0x28, 0x89, 0xf4, 0xa5, 0x27, 0x0f, 0x91, 0x07, 0x24, 0x87, 0x03, 0xd5, 0x18, 0xe7, 0x50, 0x18, 0xff, 0x00, 0x5e, 0x92, + 0x00, 0x00, 0x31, 0x32, 0x33, 0x0a, 0x00, 0x00}; + +#if 1 +TEST(PACKET_FRAG, IPV4_FRAGMENT) +{ + struct packet handler; + memset(&handler, 0, sizeof(handler)); + packet_parse(&handler, (const char *)data1, sizeof(data1)); + EXPECT_TRUE(packet_is_fragment(&handler) == true); + + struct packet *dup = packet_dup(&handler); + EXPECT_TRUE(dup != NULL); + EXPECT_TRUE(packet_is_fragment(dup) == true); + packet_free(dup); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:ipv6.fraghdr:data] + ****************************************************************************** + * + * Frame 5: 1510 bytes on wire (12080 bits), 1510 bytes captured (12080 bits) + * Ethernet II, Src: Apple_c0:61:b6 (68:5b:35:c0:61:b6), Dst: Dell_94:65:38 (00:1d:09:94:65:38) + * Destination: Dell_94:65:38 (00:1d:09:94:65:38) + * Source: Apple_c0:61:b6 (68:5b:35:c0:61:b6) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2607:f010:3f9::1001, Dst: 2607:f010:3f9::11:0 + * 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) + * .... 0010 0001 0010 1000 1001 = Flow Label: 0x21289 + * Payload Length: 1456 + * Next Header: Fragment Header for IPv6 (44) + * Hop Limit: 64 + * Source Address: 2607:f010:3f9::1001 + * Destination Address: 2607:f010:3f9::11:0 + * Fragment Header for IPv6 + * Next header: UDP (17) + * Reserved octet: 0x00 + * 0000 1011 0101 0... = Offset: 362 (2896 bytes) + * .... .... .... .00. = Reserved bits: 0 + * .... .... .... ...1 = More Fragments: Yes + * Identification: 0xf88eb466 + * [Reassembled IPv6 in frame: 6] + * Data (1448 bytes) + * Data: 686868686868686868686868686868686868686868686868686868686868686868686868… + * [Length: 1448] + */ + +unsigned char data2[] = { + 0x00, 0x1d, 0x09, 0x94, 0x65, 0x38, 0x68, 0x5b, 0x35, 0xc0, 0x61, 0xb6, 0x86, 0xdd, 0x60, 0x02, 0x12, 0x89, 0x05, 0xb0, 0x2c, 0x40, 0x26, 0x07, 0xf0, 0x10, + 0x03, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x26, 0x07, 0xf0, 0x10, 0x03, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, + 0x00, 0x00, 0x11, 0x00, 0x0b, 0x51, 0xf8, 0x8e, 0xb4, 0x66, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, + 0x68, 0x68}; + +#if 1 +TEST(PACKET_FRAG, IPV6_FRAGMENT) +{ + struct packet handler; + memset(&handler, 0, sizeof(handler)); + packet_parse(&handler, (const char *)data2, sizeof(data2)); + EXPECT_TRUE(packet_is_fragment(&handler) == true); + + struct packet *dup = packet_dup(&handler); + EXPECT_TRUE(dup != NULL); + EXPECT_TRUE(packet_is_fragment(dup) == true); + packet_free(dup); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:ipv6:tcp] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 92 + * Identification: 0x0b4d (2893) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 59 + * Protocol: IPv6 (41) + * Header Checksum: 0x09c8 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 210.77.88.163 + * Destination Address: 59.66.4.50 + * Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 32 + * Next Header: TCP (6) + * Hop Limit: 64 + * Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3 + * Destination Address: 2600:140e:6::1702:1058 + * [Source ISATAP IPv4: 210.77.88.163] + * Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 52556 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 2172673142 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x002 (SYN) + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0xf757 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * [Timestamps] + */ + +unsigned char data3[] = { + 0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8, + 0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00, + 0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50, + 0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, + 0x04, 0x02}; + +#if 1 +TEST(PACKET_FRAG, IPV4_IPV6_NOT_FRAGMENT) +{ + struct packet handler; + memset(&handler, 0, sizeof(handler)); + packet_parse(&handler, (const char *)data3, sizeof(data3)); + EXPECT_TRUE(packet_is_fragment(&handler) == false); + + struct packet *dup = packet_dup(&handler); + EXPECT_TRUE(dup != NULL); + EXPECT_TRUE(packet_is_fragment(dup) == false); + packet_free(dup); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:ipv6:udp:data] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: Broadcast (ff:ff:ff:ff:ff:ff) + * Destination: Broadcast (ff:ff:ff:ff:ff:ff) + * Source: 00:00:00_00:00:00 (00:00:00:00:00:00) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2001:4f8:4:7:2e0:81ff:fe52:ffff, Dst: 2001:4f8:4:7:2e0:81ff:fe52:9a6b + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 52 + * Next Header: IPv6 (41) + * Hop Limit: 64 + * Source Address: 2001:4f8:4:7:2e0:81ff:fe52:ffff + * Destination Address: 2001:4f8:4:7:2e0:81ff:fe52:9a6b + * [Source SLAAC MAC: TyanComp_52:ff:ff (00:e0:81:52:ff:ff)] + * [Destination SLAAC MAC: TyanComp_52:9a:6b (00:e0:81:52:9a:6b)] + * Internet Protocol Version 6, Src: dead::beef, Dst: cafe::babe + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 12 + * Next Header: UDP (17) + * Hop Limit: 64 + * Source Address: dead::beef + * Destination Address: cafe::babe + * User Datagram Protocol, Src Port: 30000, Dst Port: 13000 + * Source Port: 30000 + * Destination Port: 13000 + * Length: 12 + * Checksum: 0x83d2 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (4 bytes) + * Data (4 bytes) + */ + +unsigned char data4[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x34, 0x29, 0x40, 0x20, 0x01, 0x04, 0xf8, + 0x00, 0x04, 0x00, 0x07, 0x02, 0xe0, 0x81, 0xff, 0xfe, 0x52, 0xff, 0xff, 0x20, 0x01, 0x04, 0xf8, 0x00, 0x04, 0x00, 0x07, 0x02, 0xe0, 0x81, 0xff, 0xfe, 0x52, + 0x9a, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, + 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xbe, 0x75, 0x30, 0x32, 0xc8, 0x00, 0x0c, 0x83, 0xd2, 0x58, 0x58, + 0x58, 0x58}; + +#if 1 +TEST(PACKET_FRAG, IPV6_IPV6_NOT_FRAGMENT) +{ + struct packet handler; + memset(&handler, 0, sizeof(handler)); + packet_parse(&handler, (const char *)data4, sizeof(data4)); + EXPECT_TRUE(packet_is_fragment(&handler) == false); + + struct packet *dup = packet_dup(&handler); + EXPECT_TRUE(dup != NULL); + EXPECT_TRUE(packet_is_fragment(dup) == false); + packet_free(dup); +} +#endif + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_packet_ldbc.cpp b/infra/packet_manager/test/gtest_packet_ldbc.cpp new file mode 100644 index 0000000..e2dd430 --- /dev/null +++ b/infra/packet_manager/test/gtest_packet_ldbc.cpp @@ -0,0 +1,96 @@ +#include <gtest/gtest.h> +#include <arpa/inet.h> + +#include "packet_private.h" +#include "packet_parser.h" +#include "packet_dump.h" + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:ipv6:tcp] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 92 + * Identification: 0x0b4d (2893) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 59 + * Protocol: IPv6 (41) + * Header Checksum: 0x09c8 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 210.77.88.163 + * Destination Address: 59.66.4.50 + * Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 32 + * Next Header: TCP (6) + * Hop Limit: 64 + * Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3 + * Destination Address: 2600:140e:6::1702:1058 + * [Source ISATAP IPv4: 210.77.88.163] + * Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 52556 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 2172673142 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x002 (SYN) + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0xf757 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * [Timestamps] + */ + +unsigned char data[] = { + 0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8, + 0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00, + 0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50, + 0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, + 0x04, 0x02}; + +#if 1 +TEST(PACKET_LDBC, HASH_VALUE) +{ + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data, sizeof(data)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data == 106); + packet_print(&handler); + + // buffer: "2001:da8:200:900e:200:5efe:d24d:58a3 0 2600:140e:6::1702:1058 0" + // buffer: "210.77.88.163 0 59.66.4.50 0" + + EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_EXT_IP, PACKET_DIRECTION_OUTGOING)); + EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_EXT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_IP, PACKET_DIRECTION_OUTGOING)); + + EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_EXT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_EXT_IP, PACKET_DIRECTION_OUTGOING)); + EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_INNERMOST_INT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_INNERMOST_EXT_IP, PACKET_DIRECTION_OUTGOING)); +} +#endif + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_packet_parser.cpp b/infra/packet_manager/test/gtest_packet_parser.cpp new file mode 100644 index 0000000..4fa3985 --- /dev/null +++ b/infra/packet_manager/test/gtest_packet_parser.cpp @@ -0,0 +1,3051 @@ +#include <gtest/gtest.h> +#include <arpa/inet.h> + +#include "tuple.h" +#include "packet_private.h" +#include "packet_parser.h" +#include "packet_dump.h" + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:vlan:ethertype:vlan:ethertype:ip:ip:udp:data] + ****************************************************************************** + * + * Frame 1: 170 bytes on wire (1360 bits), 170 bytes captured (1360 bits) + * Ethernet II, Src: HuaweiTe_3b:b3:9a (a4:c6:4f:3b:b3:9a), Dst: 00:00:00_00:00:04 (00:00:00:00:00:04) + * Destination: 00:00:00_00:00:04 (00:00:00:00:00:04) + * Source: HuaweiTe_3b:b3:9a (a4:c6:4f:3b:b3:9a) + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 1624 + * 011. .... .... .... = Priority: Critical Applications (3) + * ...0 .... .... .... = DEI: Ineligible + * .... 0110 0101 1000 = ID: 1624 + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 505 + * 011. .... .... .... = Priority: Critical Applications (3) + * ...0 .... .... .... = DEI: Ineligible + * .... 0001 1111 1001 = ID: 505 + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 69.67.35.146, Dst: 41.202.46.110 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0xb8 (DSCP: EF PHB, ECN: Not-ECT) + * Total Length: 148 + * Identification: 0xe858 (59480) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 255 + * Protocol: IPIP (4) + * Header Checksum: 0x1148 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 69.67.35.146 + * Destination Address: 41.202.46.110 + * Internet Protocol Version 4, Src: 10.10.100.25, Dst: 10.10.101.2 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0xb8 (DSCP: EF PHB, ECN: Not-ECT) + * Total Length: 128 + * Identification: 0x0001 (1) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 254 + * Protocol: UDP (17) + * Header Checksum: 0xde84 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.10.100.25 + * Destination Address: 10.10.101.2 + * User Datagram Protocol, Src Port: 62367, Dst Port: 17000 + * Source Port: 62367 + * Destination Port: 17000 + * Length: 108 + * Checksum: 0x4b9a [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (100 bytes) + * Data (100 bytes) + */ + +unsigned char data1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa4, 0xc6, 0x4f, 0x3b, 0xb3, 0x9a, 0x81, 0x00, 0x66, 0x58, 0x81, 0x00, 0x61, 0xf9, 0x08, 0x00, 0x45, 0xb8, 0x00, 0x94, + 0xe8, 0x58, 0x00, 0x00, 0xff, 0x04, 0x11, 0x48, 0x45, 0x43, 0x23, 0x92, 0x29, 0xca, 0x2e, 0x6e, 0x45, 0xb8, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x11, + 0xde, 0x84, 0x0a, 0x0a, 0x64, 0x19, 0x0a, 0x0a, 0x65, 0x02, 0xf3, 0x9f, 0x42, 0x68, 0x00, 0x6c, 0x4b, 0x9a, 0x00, 0x02, 0x00, 0x00, 0x04, 0x73, 0x6c, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd}; + +#if 1 +TEST(PACKET_PARSE, ETH_VLAN_VLAN_IP4_IP4_UDP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data1, sizeof(data1)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data1 == 70); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 156); + + // LAYER_PROTO_VLAN + const struct layer_private *outer_vlan_record = packet_get_outermost_layer(&handler, LAYER_PROTO_VLAN); + const struct layer_private *inner_vlan_record = packet_get_innermost_layer(&handler, LAYER_PROTO_VLAN); + + EXPECT_TRUE(outer_vlan_record != nullptr); + EXPECT_TRUE(inner_vlan_record != nullptr); + EXPECT_TRUE(outer_vlan_record->hdr_offset == 14); + EXPECT_TRUE(outer_vlan_record->hdr_len == 4); + EXPECT_TRUE(outer_vlan_record->pld_len == 152); + EXPECT_TRUE(inner_vlan_record->hdr_offset == 18); + EXPECT_TRUE(inner_vlan_record->hdr_len == 4); + EXPECT_TRUE(inner_vlan_record->pld_len == 148); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 22); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 128); + EXPECT_TRUE(inner_ipv4_record->hdr_offset == 42); + EXPECT_TRUE(inner_ipv4_record->hdr_len == 20); + EXPECT_TRUE(inner_ipv4_record->pld_len == 108); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record == inner_udp_record); + EXPECT_TRUE(outer_udp_record->hdr_offset == 62); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 100); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "69.67.35.146-41.202.46.110"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.10.100.25-10.10.101.2"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.10.100.25:62367-10.10.101.2:17000"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.10.100.25:62367-10.10.101.2:17000"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.10.100.25:62367-10.10.101.2:17000-17-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.10.100.25:62367-10.10.101.2:17000-17-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:ip:tcp:ssh] + ****************************************************************************** + * + * Frame 1: 726 bytes on wire (5808 bits), 726 bytes captured (5808 bits) + * Ethernet II, Src: EvocInte_36:51:3c (00:22:46:36:51:3c), Dst: EvocInte_36:51:38 (00:22:46:36:51:38) + * Destination: EvocInte_36:51:38 (00:22:46:36:51:38) + * Source: EvocInte_36:51:3c (00:22:46:36:51:3c) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2001::192:168:40:134, Dst: 2001::192:168:40:133 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 672 + * Next Header: IPIP (4) + * Hop Limit: 64 + * Source Address: 2001::192:168:40:134 + * Destination Address: 2001::192:168:40:133 + * [Source Teredo Server IPv4: 0.0.0.0] + * [Source Teredo Port: 65175] + * [Source Teredo Client IPv4: 255.191.254.203] + * [Destination Teredo Server IPv4: 0.0.0.0] + * [Destination Teredo Port: 65175] + * [Destination Teredo Client IPv4: 255.191.254.204] + * Internet Protocol Version 4, Src: 1.1.1.1, Dst: 2.2.2.2 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 672 + * Identification: 0x0968 (2408) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 212 + * Protocol: TCP (6) + * Header Checksum: 0xd4ea [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 1.1.1.1 + * Destination Address: 2.2.2.2 + * Transmission Control Protocol, Src Port: 57639, Dst Port: 22, Seq: 1, Ack: 1, Len: 632 + * Source Port: 57639 + * Destination Port: 22 + * [Stream index: 0] + * [Conversation completeness: Incomplete (8)] + * [TCP Segment Len: 632] + * Sequence Number: 1 (relative sequence number) + * Sequence Number (raw): 1508621024 + * [Next Sequence Number: 633 (relative sequence number)] + * Acknowledgment Number: 1 (relative ack number) + * Acknowledgment number (raw): 2828957019 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x018 (PSH, ACK) + * Window: 28584 + * [Calculated window size: 28584] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0xc51f [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * [Timestamps] + * [SEQ/ACK analysis] + * TCP payload (632 bytes) + * SSH Protocol + */ + +unsigned char data2[] = { + 0x00, 0x22, 0x46, 0x36, 0x51, 0x38, 0x00, 0x22, 0x46, 0x36, 0x51, 0x3c, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x02, 0xa0, 0x04, 0x40, 0x20, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x92, 0x01, 0x68, 0x00, 0x40, 0x01, 0x34, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x92, 0x01, 0x68, 0x00, 0x40, + 0x01, 0x33, 0x45, 0x00, 0x02, 0xa0, 0x09, 0x68, 0x00, 0x00, 0xd4, 0x06, 0xd4, 0xea, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0xe1, 0x27, 0x00, 0x16, + 0x59, 0xeb, 0xba, 0xe0, 0xa8, 0x9e, 0x75, 0x5b, 0x50, 0x18, 0x6f, 0xa8, 0xc5, 0x1f, 0x00, 0x00, 0x4f, 0xe3, 0xa9, 0x48, 0x9b, 0xbe, 0xa8, 0x07, 0x0e, 0xbb, + 0x5b, 0xf1, 0x15, 0x1d, 0xc9, 0xbe, 0xdf, 0x78, 0x89, 0xa2, 0x8f, 0x12, 0x5f, 0xad, 0x51, 0xd5, 0xfa, 0xa7, 0x0b, 0xf2, 0x34, 0x00, 0x5b, 0x77, 0xae, 0xab, + 0xe4, 0x49, 0xa7, 0xa5, 0xa7, 0x1f, 0xda, 0x90, 0xcc, 0xe1, 0x8e, 0x9f, 0xe9, 0xee, 0x53, 0x59, 0xa4, 0x17, 0xf8, 0x0d, 0x40, 0xe5, 0x75, 0x97, 0xf0, 0x29, + 0xfa, 0x7c, 0xb8, 0x12, 0x7e, 0x93, 0xbc, 0x7e, 0x0a, 0x69, 0x8f, 0x1d, 0x7b, 0x1a, 0x2e, 0xf6, 0xa6, 0x78, 0x67, 0x26, 0xfe, 0x8f, 0xcf, 0x5a, 0x02, 0x7d, + 0xbb, 0x1b, 0xdb, 0xc7, 0x71, 0xee, 0xe9, 0xd9, 0xc1, 0x48, 0xbf, 0xc7, 0xcc, 0x00, 0x82, 0x7f, 0x69, 0x52, 0xa7, 0xe1, 0x12, 0xec, 0xf1, 0x93, 0xa8, 0x55, + 0x5b, 0x33, 0xd3, 0x35, 0x11, 0x5d, 0xf8, 0x3d, 0x5b, 0x94, 0xc9, 0x67, 0xae, 0xba, 0xc0, 0x4a, 0x8b, 0x25, 0x8d, 0xbf, 0xd4, 0xcc, 0x24, 0xb7, 0x3d, 0x0f, + 0x1a, 0x57, 0x20, 0x5c, 0x64, 0x62, 0xf7, 0x3c, 0xff, 0xaf, 0x6b, 0xf2, 0xf3, 0xca, 0xd1, 0xcb, 0x7b, 0x9f, 0xc1, 0x31, 0x25, 0x01, 0xd1, 0x18, 0x78, 0x81, + 0xf8, 0xae, 0x61, 0x4b, 0x59, 0xa1, 0xbe, 0x4a, 0x94, 0x12, 0xa3, 0x05, 0x4a, 0x26, 0x85, 0xbd, 0x5e, 0x59, 0xb2, 0xc2, 0x24, 0xec, 0xd6, 0x94, 0x6e, 0xc5, + 0x7a, 0xdf, 0x21, 0x21, 0xe4, 0x06, 0x67, 0x89, 0xe0, 0x76, 0x85, 0xa9, 0x00, 0x43, 0xfe, 0x72, 0x8c, 0x10, 0xe4, 0x96, 0x63, 0x1a, 0xe8, 0x84, 0xe1, 0x86, + 0xa2, 0xa5, 0x67, 0x31, 0x67, 0x44, 0xca, 0xec, 0xe8, 0xa1, 0x3e, 0x5f, 0x4e, 0x71, 0x5d, 0xd4, 0x34, 0xa9, 0x3d, 0xfa, 0x6a, 0xdb, 0xfb, 0x28, 0x2b, 0x70, + 0xcc, 0xf1, 0x3c, 0x7c, 0xf5, 0x39, 0xb5, 0xd0, 0xa2, 0x56, 0x22, 0x96, 0x7e, 0xc5, 0x0e, 0x66, 0x2d, 0xcd, 0x5c, 0x33, 0x43, 0x1c, 0xca, 0x17, 0x77, 0x46, + 0xb2, 0x41, 0x06, 0x8a, 0x7c, 0x7c, 0x66, 0x06, 0x18, 0x33, 0x21, 0x16, 0x8f, 0x5a, 0xb7, 0xdd, 0x10, 0xa1, 0xab, 0xe9, 0x66, 0xf7, 0x90, 0x22, 0x2c, 0xbe, + 0xdd, 0xad, 0xe1, 0x40, 0xe9, 0x21, 0x53, 0x97, 0x07, 0x97, 0x6b, 0xd6, 0x91, 0x11, 0x44, 0x4e, 0x9d, 0x1f, 0x57, 0x07, 0xed, 0xa2, 0xac, 0x77, 0xc0, 0x84, + 0xb7, 0xc5, 0x2b, 0xaa, 0x17, 0xd2, 0xdb, 0x2a, 0x15, 0x47, 0x2b, 0x69, 0xf1, 0xb4, 0xb5, 0x8f, 0x98, 0xcf, 0x26, 0x03, 0xf0, 0x4b, 0x1a, 0xba, 0x94, 0xc4, + 0x12, 0xe3, 0xd1, 0x38, 0x0c, 0x2e, 0x87, 0x33, 0x0f, 0xe1, 0xa6, 0xba, 0x75, 0xd0, 0xa4, 0x94, 0x80, 0x49, 0x67, 0xa8, 0x90, 0x31, 0x19, 0xaa, 0xf9, 0x78, + 0x0d, 0xdd, 0x64, 0xe3, 0xc7, 0x0e, 0x81, 0xa7, 0x6b, 0x44, 0x0c, 0xb5, 0xa0, 0x25, 0x8a, 0xa2, 0xdc, 0x5e, 0xbc, 0xcd, 0xb4, 0x87, 0x1b, 0x6c, 0x08, 0x38, + 0x63, 0xa8, 0xc1, 0xde, 0xe2, 0xa1, 0xa4, 0x19, 0x1e, 0x3c, 0x67, 0x3b, 0xf7, 0x7f, 0x67, 0xfb, 0x50, 0x9a, 0x06, 0x5c, 0xdd, 0xf2, 0x26, 0x2c, 0xb9, 0xd2, + 0xbd, 0x80, 0xd5, 0xfc, 0xc5, 0x54, 0x6c, 0xc1, 0xea, 0x76, 0x3e, 0xd4, 0xbb, 0x57, 0x65, 0x6a, 0xf8, 0x8e, 0x3e, 0x93, 0xe5, 0x03, 0xfc, 0xce, 0xf1, 0x1c, + 0xf3, 0x10, 0xae, 0x87, 0x78, 0x46, 0x02, 0x63, 0xc5, 0xc0, 0x41, 0xbd, 0xae, 0x46, 0x68, 0x0c, 0x92, 0x22, 0xa4, 0xc0, 0xce, 0xf3, 0xc4, 0xf7, 0x83, 0xa9, + 0x22, 0x78, 0x74, 0x7f, 0x2e, 0xc1, 0xc6, 0x3b, 0x72, 0x26, 0x4b, 0x45, 0xbd, 0x1b, 0x9f, 0x66, 0x61, 0x46, 0xbb, 0x0f, 0xf3, 0xc5, 0x65, 0x95, 0xbc, 0xae, + 0x8f, 0x37, 0xfd, 0xa3, 0x20, 0xb6, 0xe4, 0xa8, 0xff, 0x45, 0xa1, 0x01, 0xa1, 0x76, 0xb3, 0xad, 0x16, 0x07, 0x39, 0x58, 0x3b, 0x34, 0xe9, 0xe6, 0xc0, 0xee, + 0x7f, 0x65, 0x6f, 0x68, 0xf4, 0x45, 0xa4, 0x85, 0xa7, 0x50, 0x63, 0xce, 0x0b, 0x0d, 0xbd, 0xd1, 0x20, 0xc8, 0x41, 0x37, 0x05, 0x1f, 0x81, 0xf3, 0x7c, 0xe7, + 0x67, 0x15, 0xce, 0xad, 0x76, 0x95, 0x1a, 0x93, 0x4a, 0xab, 0xc4, 0xea, 0x30, 0x44, 0x13, 0x47, 0xec, 0x79, 0xa2, 0x41, 0x0c, 0xdd, 0x42, 0xdf, 0xbf, 0x02, + 0xef, 0x9e, 0x67, 0x7e, 0x1e, 0xb0, 0x2a, 0x7f, 0x97, 0xf3, 0x5a, 0xbc, 0x21, 0x8d, 0xf9, 0xc3, 0x30, 0x45, 0xfe, 0x72, 0x74, 0x04, 0x53, 0x99, 0xe7, 0xd1, + 0x2b, 0xb6, 0x3a, 0x9c, 0x84, 0x0e, 0x15, 0x5e, 0x75, 0x3b, 0xc9, 0x0e, 0x94, 0xe6, 0x48, 0x0e, 0x37, 0x07, 0xf8, 0xd9, 0x59, 0x4b, 0x04, 0x50}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP6_IP4_TCP_SSH) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data2, sizeof(data2)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data2 == 94); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 712); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record == inner_ipv6_record); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 672); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 54); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 652); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 74); + EXPECT_TRUE(outer_tcp_record->hdr_len == 20); + EXPECT_TRUE(outer_tcp_record->pld_len == 632); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001::192:168:40:134-2001::192:168:40:133"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "1.1.1.1-2.2.2.2"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "1.1.1.1:57639-2.2.2.2:22"); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "1.1.1.1:57639-2.2.2.2:22"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "1.1.1.1:57639-2.2.2.2:22-6-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "1.1.1.1:57639-2.2.2.2:22-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:vlan:ethertype:ipv6:ip:gre:ppp:ip:udp:dns] + ****************************************************************************** + * + * Frame 1: 272 bytes on wire (2176 bits), 272 bytes captured (2176 bits) + * Ethernet II, Src: Cisco_e6:82:c4 (00:19:06:e6:82:c4), Dst: 10:01:00:00:61:3d (10:01:00:00:61:3d) + * Destination: 10:01:00:00:61:3d (10:01:00:00:61:3d) + * Source: Cisco_e6:82:c4 (00:19:06:e6:82:c4) + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 100 + * 000. .... .... .... = Priority: Best Effort (default) (0) + * ...0 .... .... .... = DEI: Ineligible + * .... 0000 0110 0100 = ID: 100 + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2607:fcd0:100:2300::b108:2a6b, Dst: 2402:f000:1:8e01::5555 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 214 + * Next Header: IPIP (4) + * Hop Limit: 57 + * Source Address: 2607:fcd0:100:2300::b108:2a6b + * Destination Address: 2402:f000:1:8e01::5555 + * Internet Protocol Version 4, Src: 192.52.166.154, Dst: 16.0.0.200 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 214 + * Identification: 0x842f (33839) + * 010. .... = Flags: 0x2, Don't fragment + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: Generic Routing Encapsulation (47) + * Header Checksum: 0x3e33 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 192.52.166.154 + * Destination Address: 16.0.0.200 + * Generic Routing Encapsulation (PPP) + * Flags and Version: 0x3081 + * Protocol Type: PPP (0x880b) + * Payload Length: 178 + * Call ID: 17 + * Sequence Number: 538640 + * Acknowledgment Number: 429725 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 8.8.8.8, Dst: 172.16.44.3 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 174 + * Identification: 0x2f9c (12188) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 50 + * Protocol: UDP (17) + * Header Checksum: 0x7080 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 8.8.8.8 + * Destination Address: 172.16.44.3 + * User Datagram Protocol, Src Port: 53, Dst Port: 9879 + * Source Port: 53 + * Destination Port: 9879 + * Length: 154 + * Checksum: 0x45d9 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (146 bytes) + * Domain Name System (response) + */ + +unsigned char data3[] = { + 0x10, 0x01, 0x00, 0x00, 0x61, 0x3d, 0x00, 0x19, 0x06, 0xe6, 0x82, 0xc4, 0x81, 0x00, 0x00, 0x64, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x04, 0x39, + 0x26, 0x07, 0xfc, 0xd0, 0x01, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x08, 0x2a, 0x6b, 0x24, 0x02, 0xf0, 0x00, 0x00, 0x01, 0x8e, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x45, 0x00, 0x00, 0xd6, 0x84, 0x2f, 0x40, 0x00, 0x40, 0x2f, 0x3e, 0x33, 0xc0, 0x34, 0xa6, 0x9a, 0x10, 0x00, 0x00, 0xc8, + 0x30, 0x81, 0x88, 0x0b, 0x00, 0xb2, 0x00, 0x11, 0x00, 0x08, 0x38, 0x10, 0x00, 0x06, 0x8e, 0x9d, 0xff, 0x03, 0x00, 0x21, 0x45, 0x00, 0x00, 0xae, 0x2f, 0x9c, + 0x00, 0x00, 0x32, 0x11, 0x70, 0x80, 0x08, 0x08, 0x08, 0x08, 0xac, 0x10, 0x2c, 0x03, 0x00, 0x35, 0x26, 0x97, 0x00, 0x9a, 0x45, 0xd9, 0xb4, 0xe2, 0x81, 0x83, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x35, 0x78, 0x71, 0x74, 0x2d, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x32, 0x2d, + 0x37, 0x38, 0x63, 0x30, 0x36, 0x64, 0x63, 0x37, 0x2d, 0x30, 0x34, 0x61, 0x37, 0x2d, 0x34, 0x38, 0x35, 0x33, 0x2d, 0x38, 0x34, 0x38, 0x33, 0x2d, 0x61, 0x35, + 0x36, 0x32, 0x38, 0x39, 0x37, 0x36, 0x65, 0x32, 0x33, 0x33, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x02, 0xf0, 0x00, 0x40, + 0x01, 0x61, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x03, 0x6e, 0x65, 0x74, 0x00, 0x05, 0x6e, 0x73, 0x74, 0x6c, 0x64, + 0x0c, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x67, 0x72, 0x73, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x78, 0x0d, 0x09, 0x09, 0x00, 0x00, 0x07, 0x08, + 0x00, 0x00, 0x03, 0x84, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51, 0x80}; + +#if 1 +TEST(PACKET_PARSE, ETH_VLAN_IP6_IP4_GRE_PPP_IP4_UDP_DNS) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data3, sizeof(data3)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data3 == 126); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 258); + + // LAYER_PROTO_VLAN + const struct layer_private *outer_vlan_record = packet_get_outermost_layer(&handler, LAYER_PROTO_VLAN); + const struct layer_private *inner_vlan_record = packet_get_innermost_layer(&handler, LAYER_PROTO_VLAN); + + EXPECT_TRUE(outer_vlan_record != nullptr); + EXPECT_TRUE(inner_vlan_record != nullptr); + EXPECT_TRUE(outer_vlan_record == inner_vlan_record); + EXPECT_TRUE(outer_vlan_record->hdr_offset == 14); + EXPECT_TRUE(outer_vlan_record->hdr_len == 4); + EXPECT_TRUE(outer_vlan_record->pld_len == 254); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record == inner_ipv6_record); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 18); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 214); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 58); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 194); + + // LAYER_PROTO_GRE + const struct layer_private *outer_gre_record = packet_get_outermost_layer(&handler, LAYER_PROTO_GRE); + const struct layer_private *inner_ger_record = packet_get_innermost_layer(&handler, LAYER_PROTO_GRE); + + EXPECT_TRUE(outer_gre_record != nullptr); + EXPECT_TRUE(inner_ger_record != nullptr); + EXPECT_TRUE(outer_gre_record == inner_ger_record); + EXPECT_TRUE(outer_gre_record->hdr_offset == 78); + EXPECT_TRUE(outer_gre_record->hdr_len == 16); + EXPECT_TRUE(outer_gre_record->pld_len == 178); + + // LAYER_PROTO_PPP + const struct layer_private *outer_ppp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_PPP); + const struct layer_private *inner_ppp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_PPP); + + EXPECT_TRUE(outer_ppp_record != nullptr); + EXPECT_TRUE(inner_ppp_record != nullptr); + EXPECT_TRUE(outer_ppp_record == inner_ppp_record); + EXPECT_TRUE(outer_ppp_record->hdr_offset == 94); + EXPECT_TRUE(outer_ppp_record->hdr_len == 4); + EXPECT_TRUE(outer_ppp_record->pld_len == 174); + + // LAYER_PROTO_IPV4 + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record->hdr_offset == 98); + EXPECT_TRUE(inner_ipv4_record->hdr_len == 20); + EXPECT_TRUE(inner_ipv4_record->pld_len == 154); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record == inner_udp_record); + EXPECT_TRUE(outer_udp_record->hdr_offset == 118); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 146); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2607:fcd0:100:2300::b108:2a6b-2402:f000:1:8e01::5555"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "8.8.8.8-172.16.44.3"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "8.8.8.8:53-172.16.44.3:9879"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "8.8.8.8:53-172.16.44.3:9879"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "8.8.8.8:53-172.16.44.3:9879-17-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "8.8.8.8:53-172.16.44.3:9879-17-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:ipv6:tcp] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00) + * Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 92 + * Identification: 0x0b4d (2893) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 59 + * Protocol: IPv6 (41) + * Header Checksum: 0x09c8 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 210.77.88.163 + * Destination Address: 59.66.4.50 + * Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 32 + * Next Header: TCP (6) + * Hop Limit: 64 + * Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3 + * Destination Address: 2600:140e:6::1702:1058 + * [Source ISATAP IPv4: 210.77.88.163] + * Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 52556 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 2172673142 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x002 (SYN) + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0xf757 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * [Timestamps] + */ + +unsigned char data4[] = { + 0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8, + 0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00, + 0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50, + 0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, + 0x04, 0x02}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP4_IP6_TCP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data4, sizeof(data4)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data4 == 106); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 92); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 72); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record == inner_ipv6_record); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 34); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 32); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 74); + EXPECT_TRUE(outer_tcp_record->hdr_len == 32); + EXPECT_TRUE(outer_tcp_record->pld_len == 0); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "210.77.88.163-59.66.4.50"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:da8:200:900e:200:5efe:d24d:58a3-2600:140e:6::1702:1058"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:da8:200:900e:200:5efe:d24d:58a3:52556-2600:140e:6::1702:1058:80"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:da8:200:900e:200:5efe:d24d:58a3:52556-2600:140e:6::1702:1058:80"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:da8:200:900e:200:5efe:d24d:58a3:52556-2600:140e:6::1702:1058:80-6-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:da8:200:900e:200:5efe:d24d:58a3:52556-2600:140e:6::1702:1058:80-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:ipv6:udp:data] + ****************************************************************************** + * + * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits) + * Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: Broadcast (ff:ff:ff:ff:ff:ff) + * Destination: Broadcast (ff:ff:ff:ff:ff:ff) + * Source: 00:00:00_00:00:00 (00:00:00:00:00:00) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2001:4f8:4:7:2e0:81ff:fe52:ffff, Dst: 2001:4f8:4:7:2e0:81ff:fe52:9a6b + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 52 + * Next Header: IPv6 (41) + * Hop Limit: 64 + * Source Address: 2001:4f8:4:7:2e0:81ff:fe52:ffff + * Destination Address: 2001:4f8:4:7:2e0:81ff:fe52:9a6b + * [Source SLAAC MAC: TyanComp_52:ff:ff (00:e0:81:52:ff:ff)] + * [Destination SLAAC MAC: TyanComp_52:9a:6b (00:e0:81:52:9a:6b)] + * Internet Protocol Version 6, Src: dead::beef, Dst: cafe::babe + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 12 + * Next Header: UDP (17) + * Hop Limit: 64 + * Source Address: dead::beef + * Destination Address: cafe::babe + * User Datagram Protocol, Src Port: 30000, Dst Port: 13000 + * Source Port: 30000 + * Destination Port: 13000 + * Length: 12 + * Checksum: 0x83d2 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (4 bytes) + * Data (4 bytes) + */ + +unsigned char data5[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x34, 0x29, 0x40, 0x20, 0x01, 0x04, 0xf8, + 0x00, 0x04, 0x00, 0x07, 0x02, 0xe0, 0x81, 0xff, 0xfe, 0x52, 0xff, 0xff, 0x20, 0x01, 0x04, 0xf8, 0x00, 0x04, 0x00, 0x07, 0x02, 0xe0, 0x81, 0xff, 0xfe, 0x52, + 0x9a, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x11, 0x40, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, + 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xbe, 0x75, 0x30, 0x32, 0xc8, 0x00, 0x0c, 0x83, 0xd2, 0x58, 0x58, + 0x58, 0x58}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP6_IP6_UDP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data5, sizeof(data5)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data5 == 102); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 92); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 52); + + // LAYER_PROTO_IPV6 + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record->hdr_offset == 54); + EXPECT_TRUE(inner_ipv6_record->hdr_len == 40); + EXPECT_TRUE(inner_ipv6_record->pld_len == 12); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record == inner_udp_record); + EXPECT_TRUE(outer_udp_record->hdr_offset == 94); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 4); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:4f8:4:7:2e0:81ff:fe52:ffff-2001:4f8:4:7:2e0:81ff:fe52:9a6b"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "dead::beef-cafe::babe"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "dead::beef:30000-cafe::babe:13000"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "dead::beef:30000-cafe::babe:13000"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "dead::beef:30000-cafe::babe:13000-17-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "dead::beef:30000-cafe::babe:13000-17-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:mpls:ip:tcp] + ****************************************************************************** + * + * Frame 1: 70 bytes on wire (560 bits), 70 bytes captured (560 bits) + * Ethernet II, Src: Hangzhou_d9:28:cc (00:23:89:d9:28:cc), Dst: HuaweiTe_7f:eb:f7 (d4:6a:a8:7f:eb:f7) + * Destination: HuaweiTe_7f:eb:f7 (d4:6a:a8:7f:eb:f7) + * Source: Hangzhou_d9:28:cc (00:23:89:d9:28:cc) + * Type: MPLS label switched packet (0x8847) + * MultiProtocol Label Switching Header, Label: 18, Exp: 6, S: 1, TTL: 254 + * 0000 0000 0000 0001 0010 .... .... .... = MPLS Label: 18 (0x00012) + * .... .... .... .... .... 110. .... .... = MPLS Experimental Bits: 6 + * .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1 + * .... .... .... .... .... .... 1111 1110 = MPLS TTL: 254 + * Internet Protocol Version 4, Src: 119.40.37.65, Dst: 123.125.29.250 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 52 + * Identification: 0x02a1 (673) + * 010. .... = Flags: 0x2, Don't fragment + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 126 + * Protocol: TCP (6) + * Header Checksum: 0xc442 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 119.40.37.65 + * Destination Address: 123.125.29.250 + * Transmission Control Protocol, Src Port: 61853, Dst Port: 80, Seq: 0, Len: 0 + * Source Port: 61853 + * Destination Port: 80 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 1710561749 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x002 (SYN) + * Window: 8192 + * [Calculated window size: 8192] + * Checksum: 0xa777 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted + * [Timestamps] + */ + +unsigned char data6[] = { + 0xd4, 0x6a, 0xa8, 0x7f, 0xeb, 0xf7, 0x00, 0x23, 0x89, 0xd9, 0x28, 0xcc, 0x88, 0x47, 0x00, 0x01, 0x2d, 0xfe, 0x45, 0x00, 0x00, 0x34, 0x02, 0xa1, 0x40, 0x00, + 0x7e, 0x06, 0xc4, 0x42, 0x77, 0x28, 0x25, 0x41, 0x7b, 0x7d, 0x1d, 0xfa, 0xf1, 0x9d, 0x00, 0x50, 0x65, 0xf5, 0x19, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, + 0x20, 0x00, 0xa7, 0x77, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02}; + +#if 1 +TEST(PACKET_PARSE, ETH_MPLS_IP4_TCP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data6, sizeof(data6)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data6 == 70); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 56); + + // LAYER_PROTO_MPLS + const struct layer_private *outer_mpls_record = packet_get_outermost_layer(&handler, LAYER_PROTO_MPLS); + const struct layer_private *inner_mpls_record = packet_get_innermost_layer(&handler, LAYER_PROTO_MPLS); + + EXPECT_TRUE(outer_mpls_record != nullptr); + EXPECT_TRUE(inner_mpls_record != nullptr); + EXPECT_TRUE(outer_mpls_record == inner_mpls_record); + EXPECT_TRUE(outer_mpls_record->hdr_offset == 14); + EXPECT_TRUE(outer_mpls_record->hdr_len == 4); + EXPECT_TRUE(outer_mpls_record->pld_len == 52); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 18); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 32); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 38); + EXPECT_TRUE(outer_tcp_record->hdr_len == 32); + EXPECT_TRUE(outer_tcp_record->pld_len == 0); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "119.40.37.65-123.125.29.250"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "119.40.37.65-123.125.29.250"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "119.40.37.65:61853-123.125.29.250:80"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "119.40.37.65:61853-123.125.29.250:80"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "119.40.37.65:61853-123.125.29.250:80-6-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "119.40.37.65:61853-123.125.29.250:80-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:mpls:ip:tcp] + ****************************************************************************** + * + * Frame 1: 66 bytes on wire (528 bits), 66 bytes captured (528 bits) + * Ethernet II, Src: Cisco_05:28:38 (00:30:96:05:28:38), Dst: Cisco_e6:fc:39 (00:30:96:e6:fc:39) + * Destination: Cisco_e6:fc:39 (00:30:96:e6:fc:39) + * Source: Cisco_05:28:38 (00:30:96:05:28:38) + * Type: MPLS label switched packet (0x8847) + * MultiProtocol Label Switching Header, Label: 18, Exp: 5, S: 0, TTL: 255 + * 0000 0000 0000 0001 0010 .... .... .... = MPLS Label: 18 (0x00012) + * .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5 + * .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + * MultiProtocol Label Switching Header, Label: 16, Exp: 5, S: 1, TTL: 255 + * 0000 0000 0000 0001 0000 .... .... .... = MPLS Label: 16 (0x00010) + * .... .... .... .... .... 101. .... .... = MPLS Experimental Bits: 5 + * .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + * Internet Protocol Version 4, Src: 10.31.0.1, Dst: 10.34.0.1 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0xb0 (DSCP: Unknown, ECN: Not-ECT) + * Total Length: 44 + * Identification: 0x0000 (0) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 255 + * Protocol: TCP (6) + * Header Checksum: 0xa6d9 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.31.0.1 + * Destination Address: 10.34.0.1 + * Transmission Control Protocol, Src Port: 11001, Dst Port: 23, Seq: 0, Len: 0 + * Source Port: 11001 + * Destination Port: 23 + * [Stream index: 0] + * [Conversation completeness: Incomplete (29)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 3481568569 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 0 + * Acknowledgment number (raw): 0 + * 0110 .... = Header Length: 24 bytes (6) + * Flags: 0x002 (SYN) + * Window: 4128 + * [Calculated window size: 4128] + * Checksum: 0xf791 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (4 bytes), Maximum segment size + * [Timestamps] + */ + +unsigned char data7[] = { + 0x00, 0x30, 0x96, 0xe6, 0xfc, 0x39, 0x00, 0x30, 0x96, 0x05, 0x28, 0x38, 0x88, 0x47, 0x00, 0x01, 0x2a, 0xff, 0x00, 0x01, 0x0b, 0xff, 0x45, 0xb0, 0x00, 0x2c, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x06, 0xa6, 0xd9, 0x0a, 0x1f, 0x00, 0x01, 0x0a, 0x22, 0x00, 0x01, 0x2a, 0xf9, 0x00, 0x17, 0xcf, 0x84, 0x85, 0x39, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x02, 0x10, 0x20, 0xf7, 0x91, 0x00, 0x00, 0x02, 0x04, 0x02, 0x18}; + +#if 1 +TEST(PACKET_PARSE, ETH_MPLS_MPLS_IP4_TCP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data7, sizeof(data7)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data7 == 66); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 52); + + // LAYER_PROTO_MPLS + const struct layer_private *outer_mpls_record = packet_get_outermost_layer(&handler, LAYER_PROTO_MPLS); + + EXPECT_TRUE(outer_mpls_record != nullptr); + EXPECT_TRUE(outer_mpls_record->hdr_offset == 14); + EXPECT_TRUE(outer_mpls_record->hdr_len == 4); + EXPECT_TRUE(outer_mpls_record->pld_len == 48); + + // LAYER_PROTO_MPLS + const struct layer_private *inner_mpls_record = packet_get_innermost_layer(&handler, LAYER_PROTO_MPLS); + + EXPECT_TRUE(inner_mpls_record != nullptr); + EXPECT_TRUE(inner_mpls_record->hdr_offset == 18); + EXPECT_TRUE(inner_mpls_record->hdr_len == 4); + EXPECT_TRUE(inner_mpls_record->pld_len == 44); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 22); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 24); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 42); + EXPECT_TRUE(outer_tcp_record->hdr_len == 24); + EXPECT_TRUE(outer_tcp_record->pld_len == 0); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.31.0.1-10.34.0.1"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.31.0.1-10.34.0.1"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.31.0.1:11001-10.34.0.1:23"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.31.0.1:11001-10.34.0.1:23"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.31.0.1:11001-10.34.0.1:23-6-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.31.0.1:11001-10.34.0.1:23-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:vlan:ethertype:pppoes:ppp:ip:tcp] + ****************************************************************************** + * + * Frame 55: 78 bytes on wire (624 bits), 78 bytes captured (624 bits) + * Ethernet II, Src: 00:00:00_00:04:46 (00:00:00:00:04:46), Dst: 18:10:04:00:02:27 (18:10:04:00:02:27) + * Destination: 18:10:04:00:02:27 (18:10:04:00:02:27) + * Source: 00:00:00_00:04:46 (00:00:00:00:04:46) + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 1476 + * 011. .... .... .... = Priority: Critical Applications (3) + * ...0 .... .... .... = DEI: Ineligible + * .... 0101 1100 0100 = ID: 1476 + * Type: PPPoE Session (0x8864) + * PPP-over-Ethernet Session + * 0001 .... = Version: 1 + * .... 0001 = Type: 1 + * Code: Session Data (0x00) + * Session ID: 0xb4bc + * Payload Length: 54 + * Point-to-Point Protocol + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 100.65.55.0, Dst: 91.185.14.33 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 52 + * Identification: 0x4ba7 (19367) + * 010. .... = Flags: 0x2, Don't fragment + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 63 + * Protocol: TCP (6) + * Header Checksum: 0xeb01 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 100.65.55.0 + * Destination Address: 91.185.14.33 + * Transmission Control Protocol, Src Port: 34532, Dst Port: 443, Seq: 491, Ack: 54523, Len: 0 + * Source Port: 34532 + * Destination Port: 443 + * [Stream index: 0] + * [Conversation completeness: Incomplete (12)] + * [TCP Segment Len: 0] + * Sequence Number: 491 (relative sequence number) + * Sequence Number (raw): 3064322674 + * [Next Sequence Number: 491 (relative sequence number)] + * Acknowledgment Number: 54523 (relative ack number) + * Acknowledgment number (raw): 2083649568 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x010 (ACK) + * Window: 4032 + * [Calculated window size: 4032] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0xc361 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps + * [Timestamps] + * [SEQ/ACK analysis] + */ + +unsigned char data8[] = { + 0x18, 0x10, 0x04, 0x00, 0x02, 0x27, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46, 0x81, 0x00, 0x65, 0xc4, 0x88, 0x64, 0x11, 0x00, 0xb4, 0xbc, 0x00, 0x36, 0x00, 0x21, + 0x45, 0x00, 0x00, 0x34, 0x4b, 0xa7, 0x40, 0x00, 0x3f, 0x06, 0xeb, 0x01, 0x64, 0x41, 0x37, 0x00, 0x5b, 0xb9, 0x0e, 0x21, 0x86, 0xe4, 0x01, 0xbb, 0xb6, 0xa5, + 0xda, 0x72, 0x7c, 0x31, 0xf8, 0x20, 0x80, 0x10, 0x0f, 0xc0, 0xc3, 0x61, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x00, 0x6f, 0xab, 0xdf, 0x9c, 0x61, 0xc7, 0xc5}; + +#if 1 +TEST(PACKET_PARSE, ETH_VLAN_PPPOE_IP4_TCP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data8, sizeof(data8)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data8 == 78); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 64); + + // LAYER_PROTO_VLAN + const struct layer_private *outer_vlan_record = packet_get_outermost_layer(&handler, LAYER_PROTO_VLAN); + const struct layer_private *inner_vlan_record = packet_get_innermost_layer(&handler, LAYER_PROTO_VLAN); + + EXPECT_TRUE(outer_vlan_record != nullptr); + EXPECT_TRUE(inner_vlan_record != nullptr); + EXPECT_TRUE(outer_vlan_record == inner_vlan_record); + EXPECT_TRUE(outer_vlan_record->hdr_offset == 14); + EXPECT_TRUE(outer_vlan_record->hdr_len == 4); + EXPECT_TRUE(outer_vlan_record->pld_len == 60); + + // LAYER_PROTO_PPPOE + const struct layer_private *outer_pppoe_record = packet_get_outermost_layer(&handler, LAYER_PROTO_PPPOE); + const struct layer_private *inner_pppoe_record = packet_get_innermost_layer(&handler, LAYER_PROTO_PPPOE); + + EXPECT_TRUE(outer_pppoe_record != nullptr); + EXPECT_TRUE(inner_pppoe_record != nullptr); + EXPECT_TRUE(outer_pppoe_record == inner_pppoe_record); + EXPECT_TRUE(outer_pppoe_record->hdr_offset == 18); + EXPECT_TRUE(outer_pppoe_record->hdr_len == 6); + EXPECT_TRUE(outer_pppoe_record->pld_len == 54); + + // LAYER_PROTO_PPP + const struct layer_private *outer_ppp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_PPP); + const struct layer_private *inner_ppp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_PPP); + + EXPECT_TRUE(outer_ppp_record != nullptr); + EXPECT_TRUE(inner_ppp_record != nullptr); + EXPECT_TRUE(outer_ppp_record == inner_ppp_record); + EXPECT_TRUE(outer_ppp_record->hdr_offset == 24); + EXPECT_TRUE(outer_ppp_record->hdr_len == 2); + EXPECT_TRUE(outer_ppp_record->pld_len == 52); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 26); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 32); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 46); + EXPECT_TRUE(outer_tcp_record->hdr_len == 32); + EXPECT_TRUE(outer_tcp_record->pld_len == 0); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "100.65.55.0-91.185.14.33"); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "100.65.55.0-91.185.14.33"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "100.65.55.0:34532-91.185.14.33:443"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "100.65.55.0:34532-91.185.14.33:443"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "100.65.55.0:34532-91.185.14.33:443-6-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "100.65.55.0:34532-91.185.14.33:443-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ipv6:tcp:ja3:tls] + ****************************************************************************** + * + * Frame 1: 1442 bytes on wire (11536 bits), 1442 bytes captured (11536 bits) + * Ethernet II, Src: zte_0e:f5:40 (74:4a:a4:0e:f5:40), Dst: HuaweiTe_40:e9:c2 (ac:b3:b5:40:e9:c2) + * Destination: HuaweiTe_40:e9:c2 (ac:b3:b5:40:e9:c2) + * Source: zte_0e:f5:40 (74:4a:a4:0e:f5:40) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2409:8034:4040:5300::105, Dst: 2409:8034:4025::60:61 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 1388 + * Next Header: UDP (17) + * Hop Limit: 127 + * Source Address: 2409:8034:4040:5300::105 + * Destination Address: 2409:8034:4025::60:61 + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * Source Port: 2152 + * Destination Port: 2152 + * Length: 1388 + * Checksum: 0xeb00 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (1380 bytes) + * GPRS Tunneling Protocol + * Flags: 0x30 + * Message Type: T-PDU (0xff) + * Length: 1372 + * TEID: 0x024c3cbd (38550717) + * Internet Protocol Version 6, Src: 2409:8c34:4400:700:0:4:0:3, Dst: 2409:8934:5082:2100:ecad:e0e4:530a:c269 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 1332 + * Next Header: TCP (6) + * Hop Limit: 56 + * Source Address: 2409:8c34:4400:700:0:4:0:3 + * Destination Address: 2409:8934:5082:2100:ecad:e0e4:530a:c269 + * Transmission Control Protocol, Src Port: 443, Dst Port: 46582, Seq: 1, Ack: 1, Len: 1312 + * Source Port: 443 + * Destination Port: 46582 + * [Stream index: 0] + * [Conversation completeness: Incomplete (8)] + * [TCP Segment Len: 1312] + * Sequence Number: 1 (relative sequence number) + * Sequence Number (raw): 2198097831 + * [Next Sequence Number: 1313 (relative sequence number)] + * Acknowledgment Number: 1 (relative ack number) + * Acknowledgment number (raw): 2264498872 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x010 (ACK) + * Window: 529 + * [Calculated window size: 529] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0x2c4b [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * [Timestamps] + * [SEQ/ACK analysis] + * TCP payload (1312 bytes) + * Transport Layer Security + */ + +unsigned char data9[] = { + 0xac, 0xb3, 0xb5, 0x40, 0xe9, 0xc2, 0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x40, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x6c, 0x11, 0x7f, 0x24, 0x09, 0x80, 0x34, + 0x40, 0x40, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x24, 0x09, 0x80, 0x34, 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x61, 0x08, 0x68, 0x08, 0x68, 0x05, 0x6c, 0xeb, 0x00, 0x30, 0xff, 0x05, 0x5c, 0x02, 0x4c, 0x3c, 0xbd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x34, 0x06, 0x38, + 0x24, 0x09, 0x8c, 0x34, 0x44, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x24, 0x09, 0x89, 0x34, 0x50, 0x82, 0x21, 0x00, 0xec, 0xad, + 0xe0, 0xe4, 0x53, 0x0a, 0xc2, 0x69, 0x01, 0xbb, 0xb5, 0xf6, 0x83, 0x04, 0x4f, 0xa7, 0x86, 0xf9, 0x82, 0xb8, 0x50, 0x10, 0x02, 0x11, 0x2c, 0x4b, 0x00, 0x00, + 0x17, 0x03, 0x03, 0x3c, 0x8c, 0x87, 0xa0, 0x99, 0x23, 0x5b, 0x53, 0x4a, 0x12, 0x1b, 0xf8, 0xba, 0xe8, 0x83, 0xc2, 0x95, 0xda, 0xb8, 0xea, 0x5b, 0xdc, 0x84, + 0x61, 0xa9, 0x86, 0x7e, 0x43, 0xc7, 0x31, 0x44, 0x6e, 0x11, 0xc1, 0x30, 0x21, 0x03, 0xb4, 0x21, 0x4a, 0xee, 0xc9, 0x2e, 0x14, 0xd2, 0x98, 0x63, 0x12, 0xfe, + 0x79, 0x58, 0xb3, 0x18, 0xa6, 0x8d, 0x0c, 0x62, 0x67, 0x51, 0xef, 0x02, 0x5a, 0xa8, 0xb3, 0x82, 0x1f, 0xe4, 0x51, 0xba, 0xde, 0xee, 0x83, 0x9c, 0x4e, 0xac, + 0x4d, 0xa2, 0xb7, 0x6a, 0x82, 0xe7, 0xbb, 0x00, 0xf7, 0x5a, 0xe7, 0x02, 0x71, 0x7e, 0x7d, 0x6f, 0xf2, 0xe5, 0x47, 0xd0, 0xba, 0x3c, 0x51, 0x09, 0x95, 0xcd, + 0xf6, 0xc9, 0x8b, 0x6f, 0xb0, 0x39, 0x11, 0x0d, 0xe9, 0x0d, 0x4d, 0x29, 0xd4, 0xcb, 0x87, 0xba, 0x11, 0xfa, 0x0d, 0x0b, 0x82, 0x95, 0xa5, 0x84, 0x94, 0x48, + 0xa2, 0xee, 0xa4, 0xb7, 0xb6, 0x76, 0x13, 0x4d, 0x18, 0x42, 0x91, 0x77, 0xad, 0x82, 0x38, 0xee, 0x34, 0x1c, 0xb7, 0xf6, 0x39, 0xdc, 0xa4, 0x23, 0xa1, 0x7c, + 0xa5, 0x0b, 0x7e, 0x4c, 0x8b, 0x81, 0x31, 0x48, 0xea, 0xf4, 0x18, 0x37, 0x09, 0x0a, 0x53, 0x13, 0x05, 0x90, 0x26, 0x10, 0x69, 0xb2, 0xa3, 0x36, 0xbc, 0xa5, + 0x83, 0xd8, 0x16, 0x77, 0x98, 0xc8, 0x21, 0x38, 0xd9, 0x88, 0x0c, 0xa7, 0x16, 0x97, 0x4e, 0x20, 0x6d, 0x68, 0xda, 0x1b, 0x3b, 0x4a, 0x62, 0xe0, 0x36, 0x0d, + 0xbf, 0x30, 0x71, 0xb1, 0xe9, 0xbe, 0x47, 0x77, 0x99, 0xb9, 0xe6, 0x26, 0xab, 0x81, 0x2e, 0x46, 0xf1, 0x1b, 0x1e, 0xfb, 0xd7, 0x81, 0x60, 0x21, 0x4a, 0x71, + 0x85, 0xf7, 0x9c, 0x9c, 0xd4, 0x1c, 0x52, 0xc4, 0x3d, 0x8d, 0x72, 0xf6, 0x7c, 0xd3, 0x58, 0x79, 0x0d, 0x78, 0xd7, 0x7c, 0x29, 0x2b, 0xc3, 0x96, 0x1d, 0xc7, + 0x96, 0x50, 0x42, 0xd7, 0xda, 0xeb, 0x29, 0x8e, 0x2a, 0x72, 0x23, 0x57, 0x0f, 0x6f, 0x37, 0x35, 0xb2, 0x42, 0x76, 0x78, 0xbf, 0xbf, 0x8c, 0x3f, 0x31, 0xa2, + 0x51, 0xec, 0x9e, 0x0d, 0xfd, 0xf2, 0xaf, 0x71, 0xa0, 0x4f, 0xa9, 0xf6, 0x19, 0xcf, 0x3e, 0x4b, 0xc8, 0xaa, 0x38, 0x06, 0xa1, 0x15, 0xde, 0xde, 0xef, 0x9b, + 0x25, 0xa3, 0xcc, 0x47, 0xca, 0x29, 0x30, 0x65, 0x5f, 0xc1, 0x8b, 0x12, 0x63, 0x79, 0xcd, 0x57, 0x4d, 0x99, 0xc0, 0xcd, 0xbe, 0x62, 0xcb, 0xc3, 0xf2, 0x6b, + 0x0b, 0x40, 0xc5, 0xee, 0x79, 0x0a, 0xa4, 0x75, 0x56, 0xe7, 0xe7, 0xf2, 0xfd, 0xe0, 0x72, 0x78, 0x04, 0xa2, 0x50, 0x31, 0x09, 0x8b, 0x57, 0xc3, 0x85, 0x4e, + 0xc4, 0xae, 0xde, 0x8a, 0xfa, 0xf6, 0x31, 0x06, 0xd2, 0x07, 0x25, 0x40, 0xce, 0x0d, 0xfd, 0x26, 0x98, 0x41, 0xa3, 0xa9, 0xa2, 0x8d, 0x8b, 0x7f, 0x6d, 0x63, + 0x87, 0x7e, 0x75, 0x2f, 0x78, 0xc9, 0xd5, 0x04, 0xb2, 0x4f, 0xc9, 0x94, 0xa7, 0x7f, 0xbc, 0x75, 0x7b, 0xb6, 0xfb, 0x2c, 0x46, 0xf6, 0xde, 0x36, 0x31, 0x2a, + 0x32, 0x1d, 0x7f, 0x30, 0x9e, 0x4a, 0x84, 0x69, 0x66, 0xac, 0xef, 0xbe, 0xb3, 0x83, 0x8c, 0xb8, 0x30, 0xd2, 0x3f, 0xcf, 0xb5, 0xbb, 0x65, 0xaa, 0xe7, 0x6b, + 0x74, 0x48, 0x2c, 0xb2, 0x72, 0x2b, 0x78, 0xaf, 0xd0, 0x71, 0x04, 0xa9, 0xb4, 0x65, 0xd9, 0xfc, 0x74, 0x23, 0xff, 0x89, 0xc1, 0x16, 0x23, 0xac, 0x59, 0x16, + 0x89, 0x41, 0xc3, 0xdb, 0xdb, 0x5b, 0x9a, 0x3d, 0x08, 0xc4, 0x12, 0x28, 0xf8, 0x10, 0xa5, 0xad, 0xc6, 0x81, 0xc0, 0x61, 0x48, 0xba, 0x9d, 0xef, 0xc7, 0xf8, + 0xad, 0x9a, 0xbd, 0x87, 0xfa, 0x7f, 0xa2, 0x4e, 0x4d, 0xe0, 0x19, 0xd5, 0x47, 0xc7, 0xd0, 0xfb, 0x00, 0x7b, 0xbf, 0x17, 0x80, 0xfe, 0xf5, 0x27, 0xec, 0x94, + 0x44, 0x3d, 0x4a, 0x34, 0x49, 0x60, 0xb4, 0x8d, 0x71, 0x6d, 0x9c, 0xf4, 0x4c, 0x33, 0xa9, 0x49, 0x58, 0x58, 0x6f, 0xe1, 0xd1, 0x7d, 0x36, 0x51, 0xf4, 0xd8, + 0x0d, 0x0b, 0xfc, 0xeb, 0xae, 0x58, 0x06, 0x08, 0xbf, 0x67, 0x07, 0x28, 0x7e, 0x68, 0x65, 0x79, 0x86, 0xfb, 0x43, 0x0f, 0x0a, 0xef, 0xd0, 0x97, 0x33, 0x10, + 0x7a, 0x20, 0xe8, 0x22, 0xe5, 0xdc, 0x0c, 0xa2, 0xa5, 0x50, 0x1b, 0x08, 0x15, 0xc2, 0xec, 0xd2, 0x06, 0x25, 0xd0, 0x3b, 0xfd, 0xe3, 0xa2, 0x6f, 0x41, 0x15, + 0x6d, 0x9f, 0x5f, 0xc4, 0x07, 0x5c, 0x99, 0x63, 0xd9, 0xd7, 0xdc, 0x90, 0xc9, 0x8f, 0x3a, 0x4b, 0x6a, 0x84, 0xe8, 0x3c, 0xc7, 0x71, 0x50, 0x71, 0x86, 0x71, + 0x7d, 0x54, 0x84, 0x7b, 0xb7, 0xca, 0xd5, 0x42, 0xaf, 0x88, 0xa5, 0xae, 0xa4, 0x9c, 0xfd, 0x71, 0x71, 0x0f, 0x67, 0xaa, 0x1b, 0x61, 0xd7, 0xf4, 0x50, 0x21, + 0x9d, 0x80, 0x6e, 0x54, 0xcd, 0xb6, 0xb9, 0x02, 0x3e, 0x59, 0x50, 0xff, 0xf2, 0xda, 0x21, 0x5c, 0x50, 0x6d, 0x64, 0x8c, 0x33, 0x75, 0x2a, 0xa4, 0x56, 0xb3, + 0xa8, 0xdb, 0xba, 0xbe, 0x52, 0xd4, 0xe5, 0x29, 0x68, 0xe2, 0x6b, 0x94, 0x6b, 0xb3, 0x90, 0x63, 0x91, 0x1a, 0x95, 0xb5, 0xd7, 0x10, 0x1b, 0xd9, 0x93, 0x4f, + 0x33, 0xb6, 0x6a, 0x4e, 0xcd, 0x40, 0x9d, 0x47, 0x76, 0x3e, 0x4b, 0xc7, 0x2f, 0x16, 0x96, 0x64, 0x9d, 0x4e, 0x8c, 0xfb, 0x0f, 0xd2, 0xec, 0x6c, 0xba, 0xf2, + 0x9c, 0xca, 0xd2, 0x3e, 0x64, 0x37, 0x32, 0x20, 0xd7, 0x4c, 0xb0, 0xe7, 0xd3, 0x75, 0x51, 0x3a, 0x94, 0xc1, 0xdf, 0x1c, 0xb3, 0x10, 0xd5, 0x1e, 0xcf, 0x7c, + 0xb7, 0xab, 0x4a, 0x93, 0xf0, 0x78, 0x58, 0x28, 0x63, 0x10, 0xee, 0xb0, 0xd6, 0x14, 0x81, 0x47, 0xeb, 0x2e, 0xc8, 0x6e, 0x33, 0x7e, 0xf3, 0x2d, 0xc8, 0xdb, + 0x29, 0x0c, 0x80, 0xe4, 0x2f, 0x10, 0x07, 0x8e, 0x08, 0x86, 0x97, 0x1b, 0x39, 0x98, 0x39, 0x06, 0xb3, 0x85, 0x53, 0xb7, 0xbb, 0x65, 0x65, 0x85, 0x0e, 0x0a, + 0x7d, 0x29, 0x3d, 0x3f, 0x52, 0xc2, 0x7b, 0x2b, 0x30, 0x94, 0x99, 0x6a, 0x4b, 0xad, 0xe9, 0xec, 0xcb, 0xcd, 0xae, 0x97, 0x45, 0x54, 0xd5, 0x00, 0x5e, 0xd8, + 0xac, 0xeb, 0x99, 0xdc, 0x58, 0x0b, 0x01, 0xeb, 0x32, 0x22, 0xc4, 0xec, 0x4f, 0xd2, 0x15, 0x03, 0x30, 0x88, 0xc7, 0x28, 0xaf, 0x78, 0xf5, 0x38, 0x84, 0x3b, + 0x3b, 0xe9, 0x29, 0x71, 0x50, 0xa3, 0x07, 0x49, 0x3b, 0xc6, 0x97, 0xc6, 0xf9, 0x53, 0x95, 0x51, 0x65, 0x7e, 0xd7, 0xd4, 0xe8, 0x76, 0x6a, 0x6d, 0x37, 0x6b, + 0xa5, 0x59, 0xaa, 0x14, 0x18, 0x8c, 0x8d, 0x65, 0x78, 0x67, 0xfb, 0x60, 0x56, 0xab, 0x04, 0xa0, 0xc2, 0x93, 0x46, 0xf1, 0x2b, 0x0d, 0x3b, 0x38, 0x62, 0x62, + 0x5e, 0xc8, 0x30, 0xf9, 0x45, 0x28, 0x6f, 0xa1, 0xb1, 0x88, 0xf1, 0x2b, 0x3b, 0xf8, 0xae, 0x91, 0x52, 0xc3, 0x72, 0x86, 0xe4, 0xec, 0xc3, 0x54, 0x86, 0xbf, + 0x8f, 0x33, 0xb1, 0x0f, 0x42, 0xc5, 0x9c, 0xb8, 0xc2, 0x67, 0x8b, 0xac, 0x78, 0xd7, 0x63, 0xab, 0x05, 0xc6, 0x6c, 0x37, 0xa1, 0x28, 0xef, 0x95, 0xc9, 0xf5, + 0x12, 0x38, 0x54, 0x34, 0x2e, 0x03, 0x6a, 0xaa, 0xa9, 0x97, 0x72, 0x22, 0x9f, 0x20, 0xec, 0x9e, 0x29, 0x09, 0xd8, 0x38, 0xd1, 0x86, 0x82, 0x99, 0xbd, 0x2a, + 0x03, 0xe9, 0x3d, 0xbd, 0xea, 0xc5, 0x8b, 0xb0, 0x4c, 0x8b, 0x7e, 0x78, 0x08, 0xef, 0x39, 0xa8, 0xb4, 0x47, 0xce, 0x44, 0xc3, 0x3f, 0x52, 0xe4, 0xbd, 0x9e, + 0xf6, 0xed, 0x6f, 0x6c, 0x05, 0x19, 0xa6, 0x0a, 0x1e, 0x48, 0xe3, 0x9b, 0x91, 0x61, 0xef, 0xf5, 0x91, 0x39, 0x70, 0x44, 0x1c, 0x08, 0x2e, 0x2c, 0x6c, 0x27, + 0xb9, 0x0e, 0xcc, 0x74, 0x69, 0xa5, 0xf8, 0x19, 0xd6, 0xbf, 0x57, 0x6c, 0x9a, 0x91, 0x74, 0xfd, 0xc2, 0x31, 0x32, 0x12, 0x06, 0xa3, 0x69, 0x71, 0xda, 0x40, + 0xa1, 0xf3, 0xb5, 0x9a, 0x43, 0xcc, 0xb4, 0x3c, 0x16, 0x40, 0x65, 0x2b, 0x02, 0xac, 0x5c, 0xae, 0xd6, 0x34, 0x34, 0xe3, 0x69, 0x76, 0x2c, 0xa8, 0xdd, 0x04, + 0x92, 0xa6, 0x7a, 0xc0, 0x87, 0x70, 0x8b, 0x85, 0xba, 0x5d, 0xbb, 0x62, 0x70, 0xcc, 0x1f, 0x21, 0x2c, 0x7e, 0xc3, 0x77, 0xcf, 0x23, 0x22, 0xf4, 0x16, 0x8e, + 0xf1, 0x3d, 0xdc, 0x33, 0x99, 0x5e, 0xaa, 0xa2, 0x50, 0x68, 0xde, 0x03, 0x44, 0xbb, 0xc7, 0x16, 0x2a, 0xf2, 0x08, 0xeb, 0x3d, 0x12, 0x6d, 0xcb, 0x2a, 0xaf, + 0xb4, 0x79, 0xdb, 0x74, 0x5e, 0x54, 0x89, 0x73, 0x0c, 0x48, 0x9c, 0x03, 0x33, 0xd2, 0x92, 0x22, 0xdb, 0x3a, 0xa0, 0x8c, 0xe2, 0x30, 0x6f, 0x39, 0xe4, 0xa9, + 0x24, 0x04, 0xbb, 0x85, 0x7d, 0x62, 0xc5, 0xa9, 0x98, 0x92, 0xef, 0xc6, 0xc8, 0xd1, 0x81, 0xad, 0x95, 0x40, 0x27, 0x09, 0xc7, 0x43, 0xcd, 0xb6, 0x94, 0xfc, + 0x1c, 0x7d, 0x1c, 0xd3, 0x47, 0xfe, 0x62, 0x9c, 0xfa, 0xeb, 0xfc, 0x02, 0x2e, 0x48, 0x62, 0xcf, 0x63, 0xdb, 0x63, 0xd9, 0x21, 0x86, 0xe8, 0x96, 0x54, 0xeb, + 0x6a, 0xa8, 0x78, 0x3c, 0x5b, 0xb6, 0xde, 0xa9, 0x04, 0x48, 0x63, 0xb2, 0x10, 0x02, 0x6a, 0x7f, 0x6d, 0xc8, 0x04, 0xdd, 0x99, 0x25, 0x08, 0xff, 0x80, 0x11, + 0x53, 0xfb, 0x7a, 0x07, 0x39, 0xd9, 0x97, 0xca, 0xf0, 0xa7, 0x46, 0x9c, 0xc2, 0xae, 0x2e, 0x05, 0x62, 0xa0, 0xd5, 0x5d, 0x17, 0x0e, 0x5c, 0x7e, 0x9a, 0xb2, + 0xb7, 0x9d, 0xd4, 0x4f, 0xe3, 0xac, 0x64, 0xdb, 0x6f, 0x1d, 0xdf, 0xd8, 0x41, 0xd7, 0xd9, 0x50, 0x55, 0x30, 0xeb, 0x4b, 0x19, 0xce, 0x78, 0x1f, 0xa8, 0x1e, + 0x87, 0x9c, 0x8f, 0x93, 0x97, 0xd4, 0xa2, 0x28, 0x2c, 0x79, 0x22, 0xc8}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP6_UDP_GTP_IP6_TCP_TLS) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data9, sizeof(data9)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data9 == 130); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 1428); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 1388); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record == inner_udp_record); + EXPECT_TRUE(outer_udp_record->hdr_offset == 54); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 1380); + + // LAYER_PROTO_GTP_U + const struct layer_private *outer_gtp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_GTP_U); + const struct layer_private *inner_gtp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_GTP_U); + + EXPECT_TRUE(outer_gtp_record != nullptr); + EXPECT_TRUE(inner_gtp_record != nullptr); + EXPECT_TRUE(outer_gtp_record == inner_gtp_record); + EXPECT_TRUE(outer_gtp_record->hdr_offset == 62); + EXPECT_TRUE(outer_gtp_record->hdr_len == 8); + EXPECT_TRUE(outer_gtp_record->pld_len == 1372); + + // LAYER_PROTO_IPV6 + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record->hdr_offset == 70); + EXPECT_TRUE(inner_ipv6_record->hdr_len == 40); + EXPECT_TRUE(inner_ipv6_record->pld_len == 1332); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 110); + EXPECT_TRUE(outer_tcp_record->hdr_len == 20); + EXPECT_TRUE(outer_tcp_record->pld_len == 1312); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8034:4040:5300::105-2409:8034:4025::60:61"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8c34:4400:700:0:4:0:3-2409:8934:5082:2100:ecad:e0e4:530a:c269"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8034:4040:5300::105:2152-2409:8034:4025::60:61:2152"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8c34:4400:700:0:4:0:3:443-2409:8934:5082:2100:ecad:e0e4:530a:c269:46582"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8034:4040:5300::105:2152-2409:8034:4025::60:61:2152-17-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8c34:4400:700:0:4:0:3:443-2409:8934:5082:2100:ecad:e0e4:530a:c269:46582-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ip:tcp:ja3:tls] + ****************************************************************************** + * + * Frame 1: 1470 bytes on wire (11760 bits), 1470 bytes captured (11760 bits) + * Ethernet II, Src: HuaweiTe_62:ee:70 (60:d7:55:62:ee:70), Dst: zte_0e:f5:1c (74:4a:a4:0e:f5:1c) + * Destination: zte_0e:f5:1c (74:4a:a4:0e:f5:1c) + * Source: HuaweiTe_62:ee:70 (60:d7:55:62:ee:70) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2409:8034:4025::50:a31, Dst: 2409:8034:4040:5301::204 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 1416 + * Next Header: UDP (17) + * Hop Limit: 252 + * Source Address: 2409:8034:4025::50:a31 + * Destination Address: 2409:8034:4040:5301::204 + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * Source Port: 2152 + * Destination Port: 2152 + * Length: 1416 + * Checksum: 0xc8df [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (1408 bytes) + * GPRS Tunneling Protocol + * Flags: 0x30 + * Message Type: T-PDU (0xff) + * Length: 1400 + * TEID: 0x6c2a4753 (1814710099) + * Internet Protocol Version 4, Src: 10.49.115.138, Dst: 121.196.250.66 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 1400 + * Identification: 0x0003 (3) + * 010. .... = Flags: 0x2, Don't fragment + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: TCP (6) + * Header Checksum: 0x43bb [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.49.115.138 + * Destination Address: 121.196.250.66 + * Transmission Control Protocol, Src Port: 50081, Dst Port: 443, Seq: 1, Ack: 1, Len: 1348 + * Source Port: 50081 + * Destination Port: 443 + * [Stream index: 0] + * [Conversation completeness: Incomplete (8)] + * [TCP Segment Len: 1348] + * Sequence Number: 1 (relative sequence number) + * Sequence Number (raw): 1522577104 + * [Next Sequence Number: 1349 (relative sequence number)] + * Acknowledgment Number: 1 (relative ack number) + * Acknowledgment number (raw): 3419365570 + * 1000 .... = Header Length: 32 bytes (8) + * Flags: 0x010 (ACK) + * Window: 2038 + * [Calculated window size: 2038] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0xd3c2 [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps + * [Timestamps] + * [SEQ/ACK analysis] + * TCP payload (1348 bytes) + * Transport Layer Security + */ + +unsigned char data10[] = { + 0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x1c, 0x60, 0xd7, 0x55, 0x62, 0xee, 0x70, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x88, 0x11, 0xfc, 0x24, 0x09, 0x80, 0x34, + 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x0a, 0x31, 0x24, 0x09, 0x80, 0x34, 0x40, 0x40, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x08, 0x68, 0x08, 0x68, 0x05, 0x88, 0xc8, 0xdf, 0x30, 0xff, 0x05, 0x78, 0x6c, 0x2a, 0x47, 0x53, 0x45, 0x00, 0x05, 0x78, 0x00, 0x03, 0x40, 0x00, + 0x40, 0x06, 0x43, 0xbb, 0x0a, 0x31, 0x73, 0x8a, 0x79, 0xc4, 0xfa, 0x42, 0xc3, 0xa1, 0x01, 0xbb, 0x5a, 0xc0, 0xae, 0xd0, 0xcb, 0xcf, 0x60, 0xc2, 0x80, 0x10, + 0x07, 0xf6, 0xd3, 0xc2, 0x00, 0x00, 0x01, 0x01, 0x08, 0x0a, 0x85, 0x14, 0x0e, 0xb0, 0xcc, 0x45, 0xf8, 0x5f, 0xef, 0x49, 0x45, 0xa0, 0xbe, 0x21, 0xd6, 0x46, + 0x9f, 0xb5, 0x17, 0xb2, 0xfe, 0x61, 0x2d, 0xed, 0x4f, 0x0c, 0x1e, 0xb5, 0xda, 0x91, 0x40, 0x87, 0xab, 0x02, 0x0d, 0x01, 0xc8, 0xf1, 0x24, 0x05, 0x8a, 0x9d, + 0x8d, 0xfc, 0xbb, 0x82, 0x24, 0xf5, 0x7d, 0x2d, 0x10, 0x66, 0x30, 0x2a, 0xaa, 0x4a, 0x51, 0x8d, 0xe9, 0x9a, 0x65, 0xcf, 0x89, 0x0c, 0x9e, 0x0d, 0x82, 0xda, + 0x5e, 0xd3, 0x98, 0xe3, 0x23, 0xf7, 0x5a, 0xd4, 0x88, 0x94, 0xd2, 0xdf, 0xbe, 0x44, 0x20, 0x2b, 0x21, 0x2d, 0x38, 0xca, 0x29, 0x5e, 0xa3, 0xb7, 0xbb, 0x34, + 0x20, 0x42, 0x02, 0x71, 0x04, 0xda, 0xd2, 0xeb, 0xb8, 0x81, 0xa3, 0x48, 0xc8, 0x54, 0xad, 0x42, 0x35, 0xc4, 0x4f, 0x6b, 0x15, 0x50, 0x22, 0x3e, 0x26, 0xb3, + 0xfc, 0x30, 0x49, 0x71, 0x6f, 0x41, 0x66, 0xa2, 0x2e, 0xe9, 0xd3, 0x1a, 0x69, 0xa8, 0x87, 0x71, 0x65, 0xa2, 0xc7, 0xc7, 0x2b, 0x25, 0x1d, 0x3f, 0xfb, 0xe6, + 0x05, 0xe1, 0x09, 0xb9, 0x76, 0x1d, 0xb9, 0xf9, 0xaf, 0xb4, 0x79, 0xa1, 0x35, 0x05, 0x59, 0x88, 0xa0, 0x07, 0xb5, 0x2d, 0x02, 0x11, 0x0a, 0x89, 0xf1, 0x67, + 0xdb, 0xe5, 0x5c, 0x5c, 0xaa, 0x0e, 0x21, 0xa6, 0xa4, 0x1a, 0x9f, 0x9e, 0xc8, 0x2a, 0x36, 0x6f, 0xcc, 0xa3, 0x13, 0x78, 0xf1, 0xbe, 0x34, 0xa0, 0x35, 0xef, + 0x1f, 0xf4, 0x79, 0xcb, 0x37, 0x3e, 0x77, 0x14, 0xfb, 0x2e, 0x21, 0x4f, 0x6b, 0xe5, 0xe9, 0x3a, 0x90, 0x76, 0xa8, 0x55, 0x09, 0xb6, 0x68, 0xbf, 0x66, 0xae, + 0xf1, 0x55, 0xc0, 0x76, 0x8f, 0x16, 0x86, 0x49, 0x9a, 0x88, 0x01, 0xdb, 0x78, 0x1f, 0xde, 0xc2, 0x33, 0x92, 0xe3, 0x22, 0xc6, 0x8c, 0x20, 0x17, 0xa0, 0xb2, + 0x79, 0xf4, 0x60, 0x8e, 0x98, 0x53, 0xcd, 0x8f, 0xb2, 0x8f, 0x80, 0xda, 0x9f, 0xf6, 0x00, 0x0c, 0xf8, 0x6b, 0xdf, 0x7d, 0x93, 0x48, 0x5a, 0x23, 0x35, 0x0e, + 0x1b, 0xf7, 0x50, 0x87, 0x93, 0x29, 0xaa, 0xa1, 0xb8, 0x98, 0x9f, 0x89, 0xb2, 0x0a, 0x02, 0x27, 0x95, 0x01, 0x84, 0x5a, 0x09, 0xb8, 0xff, 0x23, 0x02, 0x89, + 0xef, 0x1b, 0x64, 0xb2, 0x38, 0x81, 0xc4, 0x36, 0xe3, 0xda, 0xb5, 0x3b, 0x80, 0x45, 0x52, 0x96, 0xab, 0x0e, 0xdb, 0xb6, 0x9c, 0xcb, 0xc4, 0xe5, 0xb9, 0x72, + 0x67, 0x57, 0x4b, 0xb9, 0x55, 0xcb, 0x6b, 0xc4, 0xec, 0x46, 0x4d, 0xa3, 0xe0, 0xda, 0xba, 0x70, 0x3d, 0xa6, 0xa7, 0x3f, 0x58, 0xd2, 0x9f, 0xb0, 0x11, 0x66, + 0xaf, 0x73, 0x09, 0x60, 0x6e, 0xe0, 0x71, 0xa5, 0x65, 0x41, 0x28, 0x3e, 0x70, 0x1d, 0x25, 0x77, 0x6a, 0x4e, 0xed, 0xb9, 0x27, 0x6c, 0xf0, 0xba, 0x54, 0x8d, + 0x77, 0xfb, 0xb6, 0x4e, 0xe2, 0xab, 0x8f, 0xe3, 0xd4, 0x02, 0x65, 0x0a, 0x49, 0xf3, 0xf9, 0xc7, 0x09, 0x76, 0x81, 0xf4, 0xf8, 0x3e, 0x1f, 0x74, 0x30, 0xaf, + 0x3b, 0x9e, 0x97, 0x00, 0xde, 0xd8, 0x9a, 0xaf, 0xcc, 0x72, 0xeb, 0x0a, 0xe7, 0xab, 0xc1, 0x53, 0x62, 0x3f, 0x08, 0xba, 0x43, 0x06, 0x13, 0x0a, 0x3b, 0x5c, + 0xb4, 0xe0, 0xc8, 0xa6, 0x41, 0x45, 0xaa, 0x1a, 0xc9, 0x88, 0x86, 0x31, 0x25, 0x02, 0x4a, 0x76, 0x66, 0xb6, 0x6d, 0xff, 0x50, 0x1d, 0x3c, 0xf3, 0x2d, 0xfe, + 0x7b, 0xb2, 0x75, 0x5d, 0x9a, 0x9a, 0xe5, 0x39, 0x31, 0x4f, 0x7b, 0xa5, 0x6f, 0x94, 0xed, 0x31, 0xd4, 0x61, 0xc7, 0x44, 0x1d, 0x37, 0x19, 0x76, 0x04, 0x0e, + 0xbd, 0xc4, 0x9e, 0xe3, 0xdf, 0x94, 0x49, 0x32, 0x65, 0xd0, 0x37, 0x64, 0xb5, 0x2a, 0x61, 0x2d, 0x05, 0xc5, 0xe5, 0x79, 0x3e, 0xcf, 0x5f, 0x77, 0x0a, 0x7c, + 0x29, 0x34, 0x1a, 0x45, 0x7e, 0x11, 0x68, 0xb4, 0x3a, 0xf6, 0x5b, 0x23, 0xe4, 0x32, 0xa4, 0x11, 0x1a, 0xba, 0xd6, 0x4a, 0x45, 0x42, 0x29, 0xac, 0xb0, 0x17, + 0x05, 0x1b, 0xee, 0xf6, 0x52, 0x6d, 0x8b, 0xb4, 0x3b, 0x63, 0xe2, 0xca, 0xbf, 0x7e, 0xd3, 0xf7, 0x96, 0x75, 0x67, 0x9d, 0x27, 0x15, 0x39, 0xde, 0x5f, 0x66, + 0x74, 0x7c, 0x46, 0x01, 0x48, 0xf7, 0x99, 0x33, 0x7d, 0xc6, 0x81, 0xc4, 0x82, 0x09, 0x00, 0x20, 0x3f, 0x5c, 0xe4, 0x51, 0x88, 0x5b, 0xac, 0x31, 0x17, 0x04, + 0xa4, 0xac, 0xbf, 0x3d, 0xff, 0xad, 0x51, 0x07, 0x0b, 0xc7, 0x26, 0xa7, 0x9f, 0x83, 0x17, 0xd8, 0x2f, 0x6a, 0x47, 0x96, 0x14, 0x47, 0x68, 0xd4, 0xc0, 0xc0, + 0x3b, 0x87, 0x51, 0x30, 0xe9, 0xfa, 0x21, 0x46, 0x80, 0x1a, 0x5a, 0xef, 0x78, 0xd0, 0x3a, 0xac, 0x73, 0x1e, 0x39, 0xba, 0x82, 0x43, 0x5d, 0xef, 0x15, 0x2c, + 0x9a, 0xe5, 0xeb, 0x6a, 0xe7, 0x24, 0x12, 0xe6, 0x2a, 0xd2, 0x09, 0xc2, 0x85, 0x69, 0x9d, 0x73, 0x16, 0xb0, 0xad, 0x51, 0xf8, 0x3d, 0x94, 0x6b, 0xb7, 0xb3, + 0x7f, 0xb4, 0x9e, 0xc1, 0xdc, 0x31, 0x27, 0xa1, 0x2d, 0xfe, 0x30, 0x15, 0x04, 0x20, 0x82, 0xdc, 0xbd, 0x8b, 0xc5, 0xb4, 0xcf, 0x91, 0x85, 0xae, 0x21, 0x5e, + 0x00, 0x10, 0x04, 0x62, 0x8a, 0xe2, 0x66, 0x74, 0xf8, 0x8d, 0x8b, 0x52, 0x17, 0xd9, 0x1a, 0xbd, 0x06, 0x2d, 0x07, 0x6a, 0xf5, 0x8b, 0xdf, 0x85, 0x2e, 0x36, + 0xec, 0x15, 0x6f, 0x7e, 0xd2, 0x04, 0x43, 0x6a, 0xd7, 0x60, 0xf5, 0x53, 0x0d, 0x2e, 0x2d, 0xf5, 0x52, 0x4c, 0xcc, 0xe5, 0xf4, 0x47, 0xdd, 0x34, 0xda, 0xc1, + 0xfc, 0x60, 0x00, 0xaa, 0x68, 0x01, 0x5c, 0x82, 0x4b, 0xf9, 0x57, 0x54, 0x9d, 0xd5, 0x8b, 0xb6, 0x42, 0x77, 0xd4, 0x47, 0x70, 0x23, 0x4c, 0xad, 0xc5, 0x00, + 0x73, 0x9b, 0xbb, 0x65, 0xa7, 0x46, 0x74, 0xcd, 0x2e, 0x61, 0x0f, 0xac, 0xeb, 0x53, 0x5a, 0x87, 0x70, 0xfc, 0x5d, 0x2e, 0xa1, 0xe3, 0x9a, 0x87, 0x01, 0x0f, + 0x2e, 0xef, 0x10, 0xe2, 0x82, 0xd8, 0x12, 0xe7, 0xb8, 0x94, 0xa4, 0xdd, 0x5f, 0xea, 0x21, 0x63, 0x26, 0x43, 0xec, 0xc3, 0x54, 0x76, 0xb1, 0xb2, 0x1c, 0x03, + 0x4c, 0x5c, 0x22, 0xb5, 0x00, 0x7d, 0x77, 0x3a, 0xb6, 0xbf, 0x50, 0xbd, 0xfd, 0x0a, 0x31, 0x2c, 0xdc, 0xab, 0xe2, 0xc0, 0x0b, 0xb6, 0x66, 0xad, 0x9c, 0xca, + 0x94, 0xed, 0xd8, 0x77, 0x1b, 0xf1, 0x94, 0xdd, 0x65, 0x61, 0xda, 0x7b, 0x04, 0x3c, 0x93, 0xcf, 0x96, 0x74, 0x35, 0x8e, 0x41, 0xe1, 0xa4, 0xbc, 0xf2, 0x4f, + 0xe9, 0xb8, 0x16, 0x55, 0x05, 0x5a, 0xac, 0x10, 0xd3, 0xdf, 0xea, 0x6a, 0xf8, 0xe0, 0xf3, 0xdf, 0x66, 0x00, 0xab, 0x3d, 0xb9, 0x44, 0x65, 0x34, 0x49, 0x89, + 0xf2, 0x1d, 0x09, 0xc9, 0xfc, 0xa5, 0x84, 0xa1, 0x03, 0x5b, 0x7a, 0x5c, 0x7e, 0x21, 0xe9, 0xb4, 0x3a, 0x4c, 0x2b, 0x94, 0x64, 0x1d, 0x9b, 0xa5, 0xbf, 0x7e, + 0x1c, 0x97, 0x7e, 0x3d, 0xbe, 0x84, 0xfc, 0xab, 0x6d, 0x2a, 0x50, 0x23, 0x9e, 0x11, 0x3f, 0xe2, 0xa0, 0x68, 0xe7, 0xd5, 0xba, 0x5e, 0x24, 0x8c, 0x4c, 0x46, + 0xe6, 0x5b, 0x10, 0xc3, 0x82, 0x32, 0x17, 0x32, 0xdc, 0xec, 0xaa, 0x1e, 0x73, 0xe5, 0x7d, 0xb8, 0x1c, 0x6c, 0x4c, 0x9f, 0x60, 0x7b, 0x66, 0x4c, 0x90, 0x69, + 0xc4, 0x23, 0x66, 0x67, 0xce, 0x6d, 0x24, 0x1d, 0xcc, 0x8e, 0x78, 0xa1, 0xa7, 0xde, 0x87, 0x81, 0xac, 0x62, 0x54, 0xbc, 0x47, 0x82, 0x3c, 0xad, 0x92, 0x29, + 0xd9, 0xc0, 0xed, 0x0c, 0x11, 0x0e, 0xc5, 0x75, 0xa4, 0xbd, 0xbf, 0xcb, 0x3a, 0xaf, 0x2b, 0x9f, 0xbe, 0xbb, 0xbc, 0x31, 0x07, 0xa7, 0xbe, 0x6c, 0xa9, 0x4e, + 0xff, 0x35, 0x80, 0x2f, 0x09, 0x77, 0xe0, 0xc0, 0xdc, 0x9c, 0xc6, 0xa6, 0x63, 0xab, 0x47, 0x74, 0x5f, 0x5c, 0xae, 0x75, 0xbf, 0x42, 0x67, 0x55, 0x89, 0xcf, + 0xd3, 0x65, 0x8d, 0x5b, 0x6f, 0x5c, 0xf9, 0xd1, 0x78, 0xa2, 0xfd, 0x4f, 0x54, 0x6a, 0x71, 0x0c, 0x58, 0x13, 0xb0, 0x48, 0x0a, 0x7b, 0xcc, 0x84, 0x61, 0xa7, + 0x7d, 0x39, 0xa2, 0xd1, 0xc0, 0xdb, 0x8e, 0x97, 0x20, 0x86, 0x97, 0x20, 0xda, 0xca, 0x56, 0x78, 0x61, 0xc2, 0x2f, 0x36, 0xdb, 0x95, 0xae, 0x7e, 0x8d, 0x97, + 0xcb, 0x45, 0x6a, 0x6d, 0x27, 0xaa, 0xab, 0x4e, 0x88, 0x23, 0xb6, 0x6a, 0x8a, 0xca, 0x71, 0xca, 0x39, 0xa2, 0x98, 0x0d, 0x53, 0xa9, 0x38, 0xd5, 0x9c, 0x5d, + 0x0e, 0x5e, 0xc9, 0xeb, 0x21, 0xab, 0x00, 0xca, 0xff, 0x92, 0x20, 0x9d, 0x65, 0x9d, 0x8d, 0x49, 0x46, 0xbe, 0x51, 0x97, 0xc1, 0x61, 0x02, 0x9e, 0xa8, 0xb9, + 0x2c, 0x27, 0x7d, 0x73, 0xf9, 0x12, 0x16, 0x45, 0x25, 0xbb, 0xb0, 0x51, 0x14, 0x18, 0x07, 0xab, 0xc7, 0x06, 0xc0, 0xe9, 0x1c, 0xf8, 0x6d, 0xe1, 0x80, 0x21, + 0x21, 0x68, 0x24, 0xf7, 0x28, 0xb9, 0x07, 0xd4, 0xd7, 0xdf, 0x3e, 0xff, 0xbc, 0xe3, 0xbc, 0x6e, 0x42, 0x76, 0x63, 0xbc, 0x82, 0x0a, 0xf5, 0x99, 0x65, 0x17, + 0xd2, 0x38, 0xa9, 0xa8, 0x31, 0xce, 0x1f, 0xf7, 0xef, 0x8d, 0x94, 0xae, 0x99, 0x50, 0x30, 0x12, 0xbd, 0x4b, 0x65, 0x56, 0x59, 0xfb, 0x33, 0x7b, 0x99, 0xc7, + 0xe5, 0x80, 0xe6, 0x92, 0x0e, 0x44, 0x1d, 0x17, 0xc2, 0xd0, 0x78, 0x76, 0x9d, 0x5b, 0x7d, 0x3c, 0xb4, 0xf8, 0xcb, 0x2f, 0x83, 0x23, 0x35, 0x49, 0xc0, 0x78, + 0x2d, 0x44, 0x05, 0x64, 0x0f, 0xaa, 0x84, 0x9d, 0x3f, 0xac, 0xef, 0x5b, 0x46, 0x44, 0xb8, 0x15, 0xbe, 0x4f, 0xe7, 0x25, 0xb7, 0xa0, 0xc8, 0x0f, 0x70, 0x1a, + 0xca, 0x7f, 0xce, 0x79, 0x7b, 0xf5, 0x7e, 0x21, 0x35, 0xc7, 0x0e, 0x99, 0xdc, 0x76, 0xe0, 0x36, 0x09, 0x6e, 0x6d, 0x5f, 0x98, 0x5e, 0xb8, 0xa4, 0x88, 0xea, + 0x0b, 0x4b, 0x21, 0xa2, 0x52, 0x86, 0x95, 0x4e, 0x18, 0xac, 0xa2, 0xaf, 0x29, 0x5b, 0xe7, 0x05, 0xa1, 0xc8, 0xe1, 0x80, 0xfa, 0xb6, 0x5a, 0xed, 0x94, 0x32, + 0x4f, 0xe9, 0xf5, 0xf0, 0x61, 0x5d, 0x7f, 0xc4, 0xc4, 0xd1, 0x05, 0x54, 0x13, 0xdb}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP6_UDP_GTP_IP4_TCP_TLS) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data10, sizeof(data10)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data10 == 122); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 1456); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record == inner_ipv6_record); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 1416); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record == inner_udp_record); + EXPECT_TRUE(outer_udp_record->hdr_offset == 54); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 1408); + + // LAYER_PROTO_GTP_U + const struct layer_private *outer_gtp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_GTP_U); + const struct layer_private *inner_gtp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_GTP_U); + + EXPECT_TRUE(outer_gtp_record != nullptr); + EXPECT_TRUE(inner_gtp_record != nullptr); + EXPECT_TRUE(outer_gtp_record == inner_gtp_record); + EXPECT_TRUE(outer_gtp_record->hdr_offset == 62); + EXPECT_TRUE(outer_gtp_record->hdr_len == 8); + EXPECT_TRUE(outer_gtp_record->pld_len == 1400); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 70); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 1380); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 90); + EXPECT_TRUE(outer_tcp_record->hdr_len == 32); + EXPECT_TRUE(outer_tcp_record->pld_len == 1348); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8034:4025::50:a31-2409:8034:4040:5301::204"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.49.115.138-121.196.250.66"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8034:4025::50:a31:2152-2409:8034:4040:5301::204:2152"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.49.115.138:50081-121.196.250.66:443"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2409:8034:4025::50:a31:2152-2409:8034:4040:5301::204:2152-17-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.49.115.138:50081-121.196.250.66:443-6-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:udp:vxlan:eth:ethertype:ip:udp:dns] + ****************************************************************************** + * + * Frame 1: 124 bytes on wire (992 bits), 124 bytes captured (992 bits) + * Ethernet II, Src: zte_6c:fa:43 (00:1e:73:6c:fa:43), Dst: Shanghai_0d:0a (e4:95:6e:20:0d:0a) + * Destination: Shanghai_0d:0a (e4:95:6e:20:0d:0a) + * Source: zte_6c:fa:43 (00:1e:73:6c:fa:43) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 10.1.1.1, Dst: 192.168.1.10 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 110 + * Identification: 0x0000 (0) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 254 + * Protocol: UDP (17) + * Header Checksum: 0xefca [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.1.1.1 + * Destination Address: 192.168.1.10 + * User Datagram Protocol, Src Port: 50709, Dst Port: 4789 + * Source Port: 50709 + * Destination Port: 4789 + * Length: 90 + * Checksum: 0x0000 [zero-value ignored] + * [Stream index: 0] + * [Timestamps] + * UDP payload (82 bytes) + * Virtual eXtensible Local Area Network + * Flags: 0x0800, VXLAN Network ID (VNI) + * Group Policy ID: 0 + * VXLAN Network Identifier (VNI): 458755 + * Reserved: 0 + * Ethernet II, Src: WistronI_18:18:41 (3c:97:0e:18:18:41), Dst: DawningI_13:70:7a (e8:61:1f:13:70:7a) + * Destination: DawningI_13:70:7a (e8:61:1f:13:70:7a) + * Source: WistronI_18:18:41 (3c:97:0e:18:18:41) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 192.168.11.193, Dst: 114.114.114.114 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 60 + * Identification: 0x0cb6 (3254) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: UDP (17) + * Header Checksum: 0xbcad [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 192.168.11.193 + * Destination Address: 114.114.114.114 + * User Datagram Protocol, Src Port: 65290, Dst Port: 53 + * Source Port: 65290 + * Destination Port: 53 + * Length: 40 + * Checksum: 0x39e4 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 1] + * [Timestamps] + * UDP payload (32 bytes) + * Domain Name System (query) + */ + +unsigned char data11[] = { + 0xe4, 0x95, 0x6e, 0x20, 0x0d, 0x0a, 0x00, 0x1e, 0x73, 0x6c, 0xfa, 0x43, 0x08, 0x00, 0x45, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x11, 0xef, 0xca, + 0x0a, 0x01, 0x01, 0x01, 0xc0, 0xa8, 0x01, 0x0a, 0xc6, 0x15, 0x12, 0xb5, 0x00, 0x5a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0xe8, 0x61, + 0x1f, 0x13, 0x70, 0x7a, 0x3c, 0x97, 0x0e, 0x18, 0x18, 0x41, 0x08, 0x00, 0x45, 0x00, 0x00, 0x3c, 0x0c, 0xb6, 0x00, 0x00, 0x40, 0x11, 0xbc, 0xad, 0xc0, 0xa8, + 0x0b, 0xc1, 0x72, 0x72, 0x72, 0x72, 0xff, 0x0a, 0x00, 0x35, 0x00, 0x28, 0x39, 0xe4, 0x86, 0x84, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP4_UDP_VXLAN_ETH_IP4_UDP_DNS) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data11, sizeof(data11)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data11 == 92); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 110); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 90); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record->hdr_offset == 34); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 82); + + // LAYER_PROTO_VXLAN + const struct layer_private *outer_g_vlan_record = packet_get_outermost_layer(&handler, LAYER_PROTO_VXLAN); + const struct layer_private *inner_g_vlan_record = packet_get_innermost_layer(&handler, LAYER_PROTO_VXLAN); + + EXPECT_TRUE(outer_g_vlan_record != nullptr); + EXPECT_TRUE(inner_g_vlan_record != nullptr); + EXPECT_TRUE(outer_g_vlan_record == inner_g_vlan_record); + + EXPECT_TRUE(outer_g_vlan_record->hdr_offset == 42); + EXPECT_TRUE(outer_g_vlan_record->hdr_len == 8); + EXPECT_TRUE(outer_g_vlan_record->pld_len == 74); + + // LAYER_PROTO_ETHER + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record->hdr_offset == 50); + EXPECT_TRUE(inner_eth_record->hdr_len == 14); + EXPECT_TRUE(inner_eth_record->pld_len == 60); + + // LAYER_PROTO_IPV4 + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record->hdr_offset == 64); + EXPECT_TRUE(inner_ipv4_record->hdr_len == 20); + EXPECT_TRUE(inner_ipv4_record->pld_len == 40); + + // LAYER_PROTO_UDP + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record->hdr_offset == 84); + EXPECT_TRUE(inner_udp_record->hdr_len == 8); + EXPECT_TRUE(inner_udp_record->pld_len == 32); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.1.1.1-192.168.1.10"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.11.193-114.114.114.114"); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.1.1.1:50709-192.168.1.10:4789"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.11.193:65290-114.114.114.114:53"); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == 0); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&outer_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.1.1.1:50709-192.168.1.10:4789-17-0"); + memset(buffer, 0, sizeof(buffer)); + tuple6_to_str(&inner_tuple6, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.11.193:65290-114.114.114.114:53-17-0"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:mpls:pwethheuristic:pwethcw:eth:ethertype:arp] + ****************************************************************************** + * + * Frame 1: 90 bytes on wire (720 bits), 90 bytes captured (720 bits) + * Ethernet II, Src: cc:01:0d:5c:00:10 (cc:01:0d:5c:00:10), Dst: cc:00:0d:5c:00:10 (cc:00:0d:5c:00:10) + * Destination: cc:00:0d:5c:00:10 (cc:00:0d:5c:00:10) + * Source: cc:01:0d:5c:00:10 (cc:01:0d:5c:00:10) + * Type: MPLS label switched packet (0x8847) + * MultiProtocol Label Switching Header, Label: 19, Exp: 0, S: 0, TTL: 254 + * 0000 0000 0000 0001 0011 .... .... .... = MPLS Label: 19 (0x00013) + * .... .... .... .... .... 000. .... .... = MPLS Experimental Bits: 0 + * .... .... .... .... .... ...0 .... .... = MPLS Bottom Of Label Stack: 0 + * .... .... .... .... .... .... 1111 1110 = MPLS TTL: 254 + * MultiProtocol Label Switching Header, Label: 16, Exp: 0, S: 1, TTL: 255 + * 0000 0000 0000 0001 0000 .... .... .... = MPLS Label: 16 (0x00010) + * .... .... .... .... .... 000. .... .... = MPLS Experimental Bits: 0 + * .... .... .... .... .... ...1 .... .... = MPLS Bottom Of Label Stack: 1 + * .... .... .... .... .... .... 1111 1111 = MPLS TTL: 255 + * PW Ethernet Control Word + * Sequence Number: 0 + * Ethernet II, Src: Private_66:68:00 (00:50:79:66:68:00), Dst: Broadcast (ff:ff:ff:ff:ff:ff) + * Destination: Broadcast (ff:ff:ff:ff:ff:ff) + * Source: Private_66:68:00 (00:50:79:66:68:00) + * Type: ARP (0x0806) + * Trailer: 00000000000000000000000000000000000000000000 + * Address Resolution Protocol (request) + */ + +unsigned char data12[] = { + 0xcc, 0x00, 0x0d, 0x5c, 0x00, 0x10, 0xcc, 0x01, 0x0d, 0x5c, 0x00, 0x10, 0x88, 0x47, 0x00, 0x01, 0x30, 0xfe, 0x00, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x79, 0x66, 0x68, 0x00, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x00, 0x50, 0x79, 0x66, + 0x68, 0x00, 0xc0, 0xa8, 0x00, 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xa8, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#if 1 +TEST(PACKET_PARSE, ETH_MPLS_MPLS_PWETHCW_ETH_ARP) +{ + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data12, sizeof(data12)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data12 == 40); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 76); + + // LAYER_PROTO_MPLS + const struct layer_private *outer_mpls_record = packet_get_outermost_layer(&handler, LAYER_PROTO_MPLS); + + EXPECT_TRUE(outer_mpls_record != nullptr); + EXPECT_TRUE(outer_mpls_record->hdr_offset == 14); + EXPECT_TRUE(outer_mpls_record->hdr_len == 4); + EXPECT_TRUE(outer_mpls_record->pld_len == 72); + + // LAYER_PROTO_MPLS + const struct layer_private *inner_mpls_record = packet_get_innermost_layer(&handler, LAYER_PROTO_MPLS); + + EXPECT_TRUE(inner_mpls_record != nullptr); + EXPECT_TRUE(inner_mpls_record->hdr_offset == 18); + EXPECT_TRUE(inner_mpls_record->hdr_len == 4); + EXPECT_TRUE(inner_mpls_record->pld_len == 68); + + // LAYER_PROTO_PWETHCW + const struct layer_private *inner_pweth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_PWETH); + + EXPECT_TRUE(inner_pweth_record != nullptr); + EXPECT_TRUE(inner_pweth_record->hdr_offset == 22); + EXPECT_TRUE(inner_pweth_record->hdr_len == 4); + EXPECT_TRUE(inner_pweth_record->pld_len == 64); + + // LAYER_PROTO_ETHER + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record->hdr_offset == 26); + EXPECT_TRUE(inner_eth_record->hdr_len == 14); + EXPECT_TRUE(inner_eth_record->pld_len == 50); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == -1); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == -1); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == -1); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == -1); + + /****************************************************** + * packet_get_outermost/innermost_tuple6 + ******************************************************/ + + struct tuple6 outer_tuple6; + struct tuple6 inner_tuple6; + EXPECT_TRUE(packet_get_outermost_tuple6(&handler, &outer_tuple6) == -1); + EXPECT_TRUE(packet_get_innermost_tuple6(&handler, &inner_tuple6) == -1); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:icmp:data] + ****************************************************************************** + * + * Frame 1: 98 bytes on wire (784 bits), 98 bytes captured (784 bits) + * Ethernet II, Src: EvocIntellig_36:51:46 (00:22:46:36:51:46), Dst: EvocIntellig_36:51:3c (00:22:46:36:51:3c) + * Destination: EvocIntellig_36:51:3c (00:22:46:36:51:3c) + * Source: EvocIntellig_36:51:46 (00:22:46:36:51:46) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 192.168.40.138, Dst: 192.168.40.134 + * 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: 84 + * Identification: 0x22f6 (8950) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: ICMP (1) + * Header Checksum: 0x4552 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x4552] + * Source Address: 192.168.40.138 + * Destination Address: 192.168.40.134 + * Internet Control Message Protocol + * Type: 8 (Echo (ping) request) + * Code: 0 + * Checksum: 0xab05 [correct] + * [Checksum Status: Good] + * Identifier (BE): 24363 (0x5f2b) + * Identifier (LE): 11103 (0x2b5f) + * Sequence Number (BE): 1 (0x0001) + * Sequence Number (LE): 256 (0x0100) + * [Response frame: 2] + * Timestamp from icmp data: Jun 17, 2020 14:17:58.190124000 CST + * [Timestamp from icmp data (relative): -0.134576000 seconds] + * Data (40 bytes) + * Data: 101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637 + * [Length: 40] + */ + +unsigned char data13[] = { + 0x00, 0x22, 0x46, 0x36, 0x51, 0x3c, 0x00, 0x22, 0x46, 0x36, 0x51, 0x46, 0x08, 0x00, 0x45, 0x00, 0x00, 0x54, 0x22, 0xf6, 0x40, 0x00, 0x40, 0x01, 0x45, 0x52, + 0xc0, 0xa8, 0x28, 0x8a, 0xc0, 0xa8, 0x28, 0x86, 0x08, 0x00, 0xab, 0x05, 0x5f, 0x2b, 0x00, 0x01, 0x96, 0xb5, 0xe9, 0x5e, 0x00, 0x00, 0x00, 0x00, 0xac, 0xe6, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP4_ICMP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data13, sizeof(data13)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data13 == 14 + 20 + 8); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 84); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 64); + + // LAYER_PROTO_ICMP + const struct layer_private *outer_icmp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ICMP); + const struct layer_private *inner_icmp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ICMP); + + EXPECT_TRUE(outer_icmp_record != nullptr); + EXPECT_TRUE(inner_icmp_record != nullptr); + EXPECT_TRUE(outer_icmp_record == inner_icmp_record); + EXPECT_TRUE(outer_icmp_record->hdr_offset == 34); + EXPECT_TRUE(outer_icmp_record->hdr_len == 8); + EXPECT_TRUE(outer_icmp_record->pld_len == 56); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.40.138-192.168.40.134"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.40.138-192.168.40.134"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:icmpv6:data] + ****************************************************************************** + * + * Frame 1: 114 bytes on wire (912 bits), 114 bytes captured (912 bits) + * Ethernet II, Src: c2:00:51:fa:00:00 (c2:00:51:fa:00:00), Dst: c2:01:51:fa:00:00 (c2:01:51:fa:00:00) + * Destination: c2:01:51:fa:00:00 (c2:01:51:fa:00:00) + * Source: c2:00:51:fa:00:00 (c2:00:51:fa:00:00) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2001:db8:0:12::1, Dst: 2001:db8:0:12::2 + * 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: 60 + * Next Header: ICMPv6 (58) + * Hop Limit: 64 + * Source Address: 2001:db8:0:12::1 + * Destination Address: 2001:db8:0:12::2 + * Internet Control Message Protocol v6 + * Type: Echo (ping) request (128) + * Code: 0 + * Checksum: 0x863c [correct] + * [Checksum Status: Good] + * Identifier: 0x110d + * Sequence: 0 + * [Response In: 2] + * Data (52 bytes) + * Data: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233 + * [Length: 52] + */ + +unsigned char data14[] = { + 0xc2, 0x01, 0x51, 0xfa, 0x00, 0x00, 0xc2, 0x00, 0x51, 0xfa, 0x00, 0x00, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3a, 0x40, 0x20, 0x01, 0x0d, 0xb8, + 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x80, 0x00, 0x86, 0x3c, 0x11, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP6_ICMP6) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data14, sizeof(data14)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data14 == 14 + 40 + 8); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 100); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record == inner_ipv6_record); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 60); + + // LAYER_PROTO_ICMP6 + const struct layer_private *outer_icmp6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ICMP6); + const struct layer_private *inner_icmp6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ICMP6); + + EXPECT_TRUE(outer_icmp6_record != nullptr); + EXPECT_TRUE(inner_icmp6_record != nullptr); + EXPECT_TRUE(outer_icmp6_record == inner_icmp6_record); + EXPECT_TRUE(outer_icmp6_record->hdr_offset == 54); + EXPECT_TRUE(outer_icmp6_record->hdr_len == 8); + EXPECT_TRUE(outer_icmp6_record->pld_len == 52); + + /****************************************************** + * packet_get_outermost/innermost_tuple2 + ******************************************************/ + + struct tuple2 outer_tuple2; + struct tuple2 inner_tuple2; + EXPECT_TRUE(packet_get_outermost_tuple2(&handler, &outer_tuple2) == 0); + EXPECT_TRUE(packet_get_innermost_tuple2(&handler, &inner_tuple2) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&outer_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:db8:0:12::1-2001:db8:0:12::2"); + memset(buffer, 0, sizeof(buffer)); + tuple2_to_str(&inner_tuple2, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2001:db8:0:12::1-2001:db8:0:12::2"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:udp:l2tp:ppp:ip:udp:nbns] + ****************************************************************************** + * + * Frame 1: 150 bytes on wire (1200 bits), 150 bytes captured (1200 bits) + * Ethernet II, Src: LCFCElectron_43:38:37 (28:d2:44:43:38:37), Dst: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Destination: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Source: LCFCElectron_43:38:37 (28:d2:44:43:38:37) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 172.16.0.100, Dst: 172.16.0.254 + * 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: 136 + * Identification: 0x06ca (1738) + * 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: 128 + * Protocol: UDP (17) + * Header Checksum: 0xda18 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xda18] + * Source Address: 172.16.0.100 + * Destination Address: 172.16.0.254 + * User Datagram Protocol, Src Port: 1701, Dst Port: 1701 + * Source Port: 1701 + * Destination Port: 1701 + * Length: 116 + * Checksum: 0x962f [correct] + * [Calculated Checksum: 0x962f] + * [Checksum Status: Good] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (108 bytes) + * Layer 2 Tunneling Protocol + * Flags: 0x4002, Type: Data Message, Length Bit + * 0... .... .... .... = Type: Data Message (0) + * .1.. .... .... .... = Length Bit: Length field is present + * .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present + * .... ..0. .... .... = Offset bit: Offset size field is not present + * .... ...0 .... .... = Priority: No priority + * .... .... .... 0010 = Version: 2 + * Length: 108 + * Tunnel ID: 28998 + * Session ID: 2 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 172.16.2.100, Dst: 255.255.255.255 + * 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: 96 + * Identification: 0x0004 (4) + * 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: 128 + * Protocol: UDP (17) + * Header Checksum: 0x8c15 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x8c15] + * Source Address: 172.16.2.100 + * Destination Address: 255.255.255.255 + * User Datagram Protocol, Src Port: 137, Dst Port: 137 + * Source Port: 137 + * Destination Port: 137 + * Length: 76 + * Checksum: 0xba80 [correct] + * [Calculated Checksum: 0xba80] + * [Checksum Status: Good] + * [Stream index: 1] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (68 bytes) + * NetBIOS Name Service + */ + +unsigned char data15[] = { + 0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x28, 0xd2, 0x44, 0x43, 0x38, 0x37, 0x08, 0x00, 0x45, 0x00, 0x00, 0x88, 0x06, 0xca, 0x00, 0x00, 0x80, 0x11, 0xda, 0x18, + 0xac, 0x10, 0x00, 0x64, 0xac, 0x10, 0x00, 0xfe, 0x06, 0xa5, 0x06, 0xa5, 0x00, 0x74, 0x96, 0x2f, 0x40, 0x02, 0x00, 0x6c, 0x71, 0x46, 0x00, 0x02, 0xff, 0x03, + 0x00, 0x21, 0x45, 0x00, 0x00, 0x60, 0x00, 0x04, 0x00, 0x00, 0x80, 0x11, 0x8c, 0x15, 0xac, 0x10, 0x02, 0x64, 0xff, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89, + 0x00, 0x4c, 0xba, 0x80, 0xc6, 0x46, 0x29, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x45, 0x4a, 0x45, 0x4a, 0x45, 0x46, 0x43, 0x4e, 0x46, + 0x44, 0x45, 0x4e, 0x43, 0x4e, 0x46, 0x45, 0x45, 0x49, 0x45, 0x4a, 0x45, 0x4f, 0x45, 0x4c, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00, 0x00, 0x20, + 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x20, 0x00, 0x01, 0x00, 0x04, 0x93, 0xe0, 0x00, 0x06, 0x00, 0x00, 0xac, 0x10, 0x02, 0x64}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP4_UDP_L2TPV2_PPP_IP4_UDP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data15, sizeof(data15)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data15 == 14 + 20 + 8 + 8 + 4 + 20 + 8); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 136); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 116); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record->hdr_offset == 34); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 108); + + // LAYER_PROTO_L2TP + const struct layer_private *outer_l2tpv2_record = packet_get_outermost_layer(&handler, LAYER_PROTO_L2TP); + + EXPECT_TRUE(outer_l2tpv2_record != nullptr); + EXPECT_TRUE(outer_l2tpv2_record->hdr_offset == 42); + EXPECT_TRUE(outer_l2tpv2_record->hdr_len == 8); + EXPECT_TRUE(outer_l2tpv2_record->pld_len == 100); + + // LAYER_PROTO_PPP + const struct layer_private *outer_ppp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_PPP); + + EXPECT_TRUE(outer_ppp_record != nullptr); + EXPECT_TRUE(outer_ppp_record->hdr_offset == 50); + EXPECT_TRUE(outer_ppp_record->hdr_len == 4); + EXPECT_TRUE(outer_ppp_record->pld_len == 96); + + // LAYER_PROTO_IPV4 + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record->hdr_offset == 54); + EXPECT_TRUE(inner_ipv4_record->hdr_len == 20); + EXPECT_TRUE(inner_ipv4_record->pld_len == 76); + + // LAYER_PROTO_UDP + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record->hdr_offset == 74); + EXPECT_TRUE(inner_udp_record->hdr_len == 8); + EXPECT_TRUE(inner_udp_record->pld_len == 68); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "172.16.0.100:1701-172.16.0.254:1701"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "172.16.2.100:137-255.255.255.255:137"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:tcp] + ****************************************************************************** + * + * Frame 1: 60 bytes on wire (480 bits), 60 bytes captured (480 bits) + * Ethernet II, Src: 52:54:00:94:27:9b (52:54:00:94:27:9b), Dst: 52:54:00:19:8f:63 (52:54:00:19:8f:63) + * Destination: 52:54:00:19:8f:63 (52:54:00:19:8f:63) + * Source: 52:54:00:94:27:9b (52:54:00:94:27:9b) + * Type: IPv4 (0x0800) + * Padding: 000000000000 + * Internet Protocol Version 4, Src: 192.168.122.202, Dst: 192.168.122.100 + * 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: 40 + * Identification: 0x0c5e (3166) + * 010. .... = Flags: 0x2, Don't fragment + * 0... .... = Reserved bit: Not set + * .1.. .... = Don't fragment: Set + * ..0. .... = More fragments: Not set + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: TCP (6) + * Header Checksum: 0xb7f2 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xb7f2] + * Source Address: 192.168.122.202 + * Destination Address: 192.168.122.100 + * Transmission Control Protocol, Src Port: 1080, Dst Port: 62395, Seq: 1457975085, Ack: 1047768425, Len: 0 + * Source Port: 1080 + * Destination Port: 62395 + * [Stream index: 0] + * [Conversation completeness: Incomplete (4)] + * ..0. .... = RST: Absent + * ...0 .... = FIN: Absent + * .... 0... = Data: Absent + * .... .1.. = ACK: Present + * .... ..0. = SYN-ACK: Absent + * .... ...0 = SYN: Absent + * [Completeness Flags: ···A··] + * [TCP Segment Len: 0] + * Sequence Number: 1457975085 + * [Next Sequence Number: 1457975085] + * Acknowledgment Number: 1047768425 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x010 (ACK) + * 000. .... .... = Reserved: Not set + * ...0 .... .... = Accurate ECN: Not set + * .... 0... .... = Congestion Window Reduced: Not set + * .... .0.. .... = ECN-Echo: Not set + * .... ..0. .... = Urgent: Not set + * .... ...1 .... = Acknowledgment: Set + * .... .... 0... = Push: Not set + * .... .... .0.. = Reset: Not set + * .... .... ..0. = Syn: Not set + * .... .... ...0 = Fin: Not set + * [TCP Flags: ·······A····] + * Window: 457 + * [Calculated window size: 457] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0x0da7 [correct] + * [Calculated Checksum: 0x0da7] + * [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 data16[] = { + 0x52, 0x54, 0x00, 0x19, 0x8f, 0x63, 0x52, 0x54, 0x00, 0x94, 0x27, 0x9b, 0x08, 0x00, 0x45, 0x00, 0x00, 0x28, 0x0c, 0x5e, 0x40, 0x00, 0x40, 0x06, 0xb7, 0xf2, + 0xc0, 0xa8, 0x7a, 0xca, 0xc0, 0xa8, 0x7a, 0x64, 0x04, 0x38, 0xf3, 0xbb, 0x56, 0xe6, 0xef, 0x2d, 0x3e, 0x73, 0xad, 0x69, 0x50, 0x10, 0x01, 0xc9, 0x0d, 0xa7, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP4_TCP_PADDING) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data16, sizeof(data16)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data16 == 14 + 20 + 20); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 46); + + // LAYER_PROTO_IPV4 + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record == inner_ipv4_record); + EXPECT_TRUE(outer_ipv4_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv4_record->hdr_len == 20); + EXPECT_TRUE(outer_ipv4_record->pld_len == 20); + + // LAYER_PROTO_TCP + const struct layer_private *outer_tcp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_TCP); + const struct layer_private *inner_tcp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_TCP); + + EXPECT_TRUE(outer_tcp_record != nullptr); + EXPECT_TRUE(inner_tcp_record != nullptr); + EXPECT_TRUE(outer_tcp_record == inner_tcp_record); + EXPECT_TRUE(outer_tcp_record->hdr_offset == 34); + EXPECT_TRUE(outer_tcp_record->hdr_len == 20); + EXPECT_TRUE(outer_tcp_record->pld_len == 0); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.122.202:1080-192.168.122.100:62395"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "192.168.122.202:1080-192.168.122.100:62395"); +} +#endif + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ip:udp:data] + ****************************************************************************** + * + * Frame 1: 515 bytes on wire (4120 bits), 515 bytes captured (4120 bits) + * Ethernet II, Src: 00:00:00_00:03:1c (00:00:00:00:03:1c), Dst: HuaweiTechno_f4:fc:31 (3c:9d:56:f4:fc:31) + * Destination: HuaweiTechno_f4:fc:31 (3c:9d:56:f4:fc:31) + * Source: 00:00:00_00:03:1c (00:00:00:00:03:1c) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2408:8161:e100:10:0:16:3:a, Dst: 2408:8141:e0f0:1f08::4 + * 0110 .... = Version: 6 + * .... 1011 1000 .... .... .... .... .... = Traffic Class: 0xb8 (DSCP: EF PHB, ECN: Not-ECT) + * .... 1011 10.. .... .... .... .... .... = Differentiated Services Codepoint: Expedited Forwarding (46) + * .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0) + * .... 0100 0111 0100 0101 0011 = Flow Label: 0x47453 + * Payload Length: 461 + * Next Header: UDP (17) + * Hop Limit: 252 + * Source Address: 2408:8161:e100:10:0:16:3:a + * Destination Address: 2408:8141:e0f0:1f08::4 + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * Source Port: 2152 + * Destination Port: 2152 + * Length: 461 + * Checksum: 0x6312 [correct] + * [Calculated Checksum: 0x6312] + * [Checksum Status: Good] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (453 bytes) + * GPRS Tunneling Protocol + * Flags: 0x34 + * 001. .... = Version: GTP release 99 version (1) + * ...1 .... = Protocol type: GTP (1) + * .... 0... = Reserved: 0 + * .... .1.. = Is Next Extension Header present?: Yes + * .... ..0. = Is Sequence Number present?: No + * .... ...0 = Is N-PDU number present?: No + * Message Type: T-PDU (0xff) + * Length: 445 + * TEID: 0x01447453 (21263443) + * Next extension header type: PDU Session container (0x85) + * Extension header (PDU Session container) + * Extension Header Length: 1 + * PDU Session Container + * 0001 .... = PDU Type: UL PDU SESSION INFORMATION (1) + * .... 0000 = Spare: 0x0 + * 00.. .... = Spare: 0x0 + * ..00 0001 = QoS Flow Identifier (QFI): 1 + * Next extension header type: No more extension headers (0x00) + * Internet Protocol Version 4, Src: 10.67.71.179, Dst: 120.225.133.208 + * 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: 437 + * Identification: 0x51bf (20927) + * 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: UDP (17) + * Header Checksum: 0xd6d1 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xd6d1] + * Source Address: 10.67.71.179 + * Destination Address: 120.225.133.208 + * User Datagram Protocol, Src Port: 11102, Dst Port: 2152 + * Source Port: 11102 + * Destination Port: 2152 + * Length: 417 + * Checksum: 0x3bc2 [correct] + * [Calculated Checksum: 0x3bc2] + * [Checksum Status: Good] + * [Stream index: 1] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (409 bytes) + * Data (409 bytes) + * Data [truncated]: 226f2fcaba48055d4b5500030000019183000104090002810901000000110102010014100000011a3e425e9ae48c6929daebcd0e3cbd830402320bebc2000402270000000d02022800050215000a001800051c3503021612e5050217000000006d9f8ccd020218010402140000088 + * [Length: 409] + */ + +unsigned char data17[] = { + 0x3c, 0x9d, 0x56, 0xf4, 0xfc, 0x31, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1c, 0x86, 0xdd, 0x6b, 0x84, 0x74, 0x53, 0x01, 0xcd, 0x11, 0xfc, 0x24, 0x08, 0x81, 0x61, + 0xe1, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x0a, 0x24, 0x08, 0x81, 0x41, 0xe0, 0xf0, 0x1f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x08, 0x68, 0x08, 0x68, 0x01, 0xcd, 0x63, 0x12, 0x34, 0xff, 0x01, 0xbd, 0x01, 0x44, 0x74, 0x53, 0x00, 0x00, 0x00, 0x85, 0x01, 0x10, 0x01, 0x00, + 0x45, 0x00, 0x01, 0xb5, 0x51, 0xbf, 0x00, 0x00, 0x40, 0x11, 0xd6, 0xd1, 0x0a, 0x43, 0x47, 0xb3, 0x78, 0xe1, 0x85, 0xd0, 0x2b, 0x5e, 0x08, 0x68, 0x01, 0xa1, + 0x3b, 0xc2, 0x22, 0x6f, 0x2f, 0xca, 0xba, 0x48, 0x05, 0x5d, 0x4b, 0x55, 0x00, 0x03, 0x00, 0x00, 0x01, 0x91, 0x83, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x81, + 0x09, 0x01, 0x00, 0x00, 0x00, 0x11, 0x01, 0x02, 0x01, 0x00, 0x14, 0x10, 0x00, 0x00, 0x01, 0x1a, 0x3e, 0x42, 0x5e, 0x9a, 0xe4, 0x8c, 0x69, 0x29, 0xda, 0xeb, + 0xcd, 0x0e, 0x3c, 0xbd, 0x83, 0x04, 0x02, 0x32, 0x0b, 0xeb, 0xc2, 0x00, 0x04, 0x02, 0x27, 0x00, 0x00, 0x00, 0x0d, 0x02, 0x02, 0x28, 0x00, 0x05, 0x02, 0x15, + 0x00, 0x0a, 0x00, 0x18, 0x00, 0x05, 0x1c, 0x35, 0x03, 0x02, 0x16, 0x12, 0xe5, 0x05, 0x02, 0x17, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x9f, 0x8c, 0xcd, 0x02, 0x02, + 0x18, 0x01, 0x04, 0x02, 0x14, 0x00, 0x00, 0x08, 0x80, 0x06, 0x02, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x31, 0x30, 0x2e, 0x36, 0x37, 0x2e, 0x37, 0x31, 0x2e, 0x31, + 0x37, 0x39, 0x03, 0x02, 0x05, 0xdc, 0x01, 0x06, 0x02, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x31, 0x31, 0x32, 0x2e, 0x31, 0x31, 0x31, 0x2e, 0x35, 0x35, 0x2e, 0x32, + 0x34, 0x33, 0x03, 0x02, 0x08, 0xdc, 0x01, 0x01, 0x02, 0x09, 0x00, 0x14, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x6b, + 0x65, 0xf6, 0xf9, 0x33, 0xcc, 0xa9, 0x06, 0x02, 0x10, 0x00, 0x00, 0x00, 0x0d, 0x32, 0x31, 0x31, 0x2e, 0x39, 0x31, 0x2e, 0x31, 0x36, 0x36, 0x2e, 0x34, 0x34, + 0x03, 0x02, 0x11, 0x4e, 0x21, 0x06, 0x02, 0x1b, 0x00, 0x00, 0x00, 0xb8, 0x32, 0x31, 0x37, 0x36, 0x7c, 0x31, 0x30, 0x2e, 0x36, 0x37, 0x2e, 0x37, 0x31, 0x2e, + 0x31, 0x37, 0x39, 0x7c, 0x30, 0x7c, 0x35, 0x36, 0x33, 0x32, 0x31, 0x7c, 0x31, 0x31, 0x32, 0x2e, 0x31, 0x31, 0x31, 0x2e, 0x35, 0x35, 0x2e, 0x32, 0x34, 0x33, + 0x7c, 0x30, 0x7c, 0x35, 0x36, 0x33, 0x32, 0x31, 0x7c, 0x32, 0x31, 0x31, 0x2e, 0x39, 0x31, 0x2e, 0x31, 0x36, 0x36, 0x2e, 0x34, 0x34, 0x7c, 0x32, 0x30, 0x30, + 0x30, 0x31, 0x7c, 0x46, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x45, 0x33, 0x36, 0x42, 0x36, 0x35, 0x46, 0x36, 0x46, 0x39, 0x33, 0x33, 0x43, 0x43, 0x41, 0x39, 0x7c, 0x32, 0x34, 0x30, 0x38, 0x3a, 0x38, 0x34, 0x34, + 0x62, 0x3a, 0x31, 0x38, 0x33, 0x30, 0x3a, 0x36, 0x31, 0x63, 0x62, 0x3a, 0x65, 0x63, 0x34, 0x32, 0x3a, 0x37, 0x65, 0x35, 0x32, 0x3a, 0x65, 0x65, 0x37, 0x38, + 0x3a, 0x65, 0x32, 0x61, 0x38, 0x7c, 0x30, 0x7c, 0x38, 0x38, 0x38, 0x39, 0x7c, 0x32, 0x34, 0x30, 0x38, 0x3a, 0x38, 0x37, 0x33, 0x64, 0x3a, 0x31, 0x30, 0x3a, + 0x34, 0x3a, 0x38, 0x30, 0x30, 0x3a, 0x3a, 0x34, 0x7c, 0x32, 0x30, 0x30, 0x30, 0x31, 0x04, 0x09, 0x02, 0x00, 0x00, 0x01, 0xf8}; + +#if 1 +TEST(PACKET_PARSE, ETH_IP6_UDP_GTP_IP4_UDP) +{ + char buffer[256]; + struct packet handler; + + memset(&handler, 0, sizeof(handler)); + const char *payload = packet_parse(&handler, (const char *)data17, sizeof(data17)); + EXPECT_TRUE(payload != nullptr); + EXPECT_TRUE((char *)payload - (char *)&data17 == 14 + 40 + 8 + 16 + 20 + 8); + packet_print(&handler); + + /****************************************************** + * packet_get_outermost/innermost_layer + ******************************************************/ + + // LAYER_PROTO_ETHER + const struct layer_private *outer_eth_record = packet_get_outermost_layer(&handler, LAYER_PROTO_ETHER); + const struct layer_private *inner_eth_record = packet_get_innermost_layer(&handler, LAYER_PROTO_ETHER); + + EXPECT_TRUE(outer_eth_record != nullptr); + EXPECT_TRUE(inner_eth_record != nullptr); + EXPECT_TRUE(outer_eth_record == inner_eth_record); + EXPECT_TRUE(outer_eth_record->hdr_offset == 0); + EXPECT_TRUE(outer_eth_record->hdr_len == 14); + EXPECT_TRUE(outer_eth_record->pld_len == 501); + + // LAYER_PROTO_IPV6 + const struct layer_private *outer_ipv6_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV6); + const struct layer_private *inner_ipv6_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV6); + + EXPECT_TRUE(outer_ipv6_record != nullptr); + EXPECT_TRUE(inner_ipv6_record != nullptr); + EXPECT_TRUE(outer_ipv6_record == inner_ipv6_record); + EXPECT_TRUE(outer_ipv6_record->hdr_offset == 14); + EXPECT_TRUE(outer_ipv6_record->hdr_len == 40); + EXPECT_TRUE(outer_ipv6_record->pld_len == 461); + + // LAYER_PROTO_UDP + const struct layer_private *outer_udp_record = packet_get_outermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(outer_udp_record != nullptr); + EXPECT_TRUE(outer_udp_record->hdr_offset == 54); + EXPECT_TRUE(outer_udp_record->hdr_len == 8); + EXPECT_TRUE(outer_udp_record->pld_len == 453); + + // LAYER_PROTO_GTP_U + const struct layer_private *outer_gtpu_record = packet_get_outermost_layer(&handler, LAYER_PROTO_GTP_U); + const struct layer_private *inner_gtpu_record = packet_get_innermost_layer(&handler, LAYER_PROTO_GTP_U); + + EXPECT_TRUE(outer_gtpu_record != nullptr); + EXPECT_TRUE(inner_gtpu_record != nullptr); + EXPECT_TRUE(outer_gtpu_record == inner_gtpu_record); + EXPECT_TRUE(outer_gtpu_record->hdr_offset == 62); + EXPECT_TRUE(outer_gtpu_record->hdr_len == 16); + EXPECT_TRUE(outer_gtpu_record->pld_len == 437); + + // LAYER_PROTO_IPV4 + const struct layer_private *inner_ipv4_record = packet_get_innermost_layer(&handler, LAYER_PROTO_IPV4); + const struct layer_private *outer_ipv4_record = packet_get_outermost_layer(&handler, LAYER_PROTO_IPV4); + + EXPECT_TRUE(inner_ipv4_record != nullptr); + EXPECT_TRUE(outer_ipv4_record != nullptr); + EXPECT_TRUE(inner_ipv4_record == outer_ipv4_record); + EXPECT_TRUE(inner_ipv4_record->hdr_offset == 78); + EXPECT_TRUE(inner_ipv4_record->hdr_len == 20); + EXPECT_TRUE(inner_ipv4_record->pld_len == 417); + + // LAYER_PROTO_UDP + const struct layer_private *inner_udp_record = packet_get_innermost_layer(&handler, LAYER_PROTO_UDP); + + EXPECT_TRUE(inner_udp_record != nullptr); + EXPECT_TRUE(inner_udp_record->hdr_offset == 98); + EXPECT_TRUE(inner_udp_record->hdr_len == 8); + EXPECT_TRUE(inner_udp_record->pld_len == 409); + + /****************************************************** + * packet_get_outermost/innermost_tuple4 + ******************************************************/ + + struct tuple4 outer_tuple4; + struct tuple4 inner_tuple4; + EXPECT_TRUE(packet_get_outermost_tuple4(&handler, &outer_tuple4) == 0); + EXPECT_TRUE(packet_get_innermost_tuple4(&handler, &inner_tuple4) == 0); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&outer_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "2408:8161:e100:10:0:16:3:a:2152-2408:8141:e0f0:1f08::4:2152"); + memset(buffer, 0, sizeof(buffer)); + tuple4_to_str(&inner_tuple4, buffer, sizeof(buffer)); + EXPECT_STREQ(buffer, "10.67.71.179:11102-120.225.133.208:2152"); +} +#endif + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_tcp_utils.cpp b/infra/packet_manager/test/gtest_tcp_utils.cpp new file mode 100644 index 0000000..47223e4 --- /dev/null +++ b/infra/packet_manager/test/gtest_tcp_utils.cpp @@ -0,0 +1,148 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Transmission Control Protocol, Src Port: 55555, Dst Port: 40856, Seq: 0, Ack: 1, Len: 0 + * Source Port: 55555 + * Destination Port: 40856 + * [Stream index: 0] + * [Conversation completeness: Complete, WITH_DATA (31)] + * [TCP Segment Len: 0] + * Sequence Number: 0 (relative sequence number) + * Sequence Number (raw): 3965699644 + * [Next Sequence Number: 1 (relative sequence number)] + * Acknowledgment Number: 1 (relative ack number) + * Acknowledgment number (raw): 991053714 + * 1010 .... = Header Length: 40 bytes (10) + * Flags: 0x012 (SYN, ACK) + * 000. .... .... = Reserved: Not set + * ...0 .... .... = Accurate ECN: Not set + * .... 0... .... = Congestion Window Reduced: Not set + * .... .0.. .... = ECN-Echo: Not set + * .... ..0. .... = Urgent: Not set + * .... ...1 .... = Acknowledgment: Set + * .... .... 0... = Push: Not set + * .... .... .0.. = Reset: Not set + * .... .... ..1. = Syn: Set + * [Expert Info (Chat/Sequence): Connection establish acknowledge (SYN+ACK): server port 55555] + * [Connection establish acknowledge (SYN+ACK): server port 55555] + * [Severity level: Chat] + * [Group: Sequence] + * .... .... ...0 = Fin: Not set + * [TCP Flags: ·······A··S·] + * Window: 43690 + * [Calculated window size: 43690] + * Checksum: 0xfe30 incorrect, should be 0x65c9(maybe caused by "TCP checksum offload"?) + * [Expert Info (Error/Checksum): Bad checksum [should be 0x65c9]] + * [Bad checksum [should be 0x65c9]] + * [Severity level: Error] + * [Group: Checksum] + * [Checksum Status: Bad] + * [Calculated Checksum: 0x65c9] + * Urgent Pointer: 0 + * Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale + * TCP Option - Maximum segment size: 65495 bytes + * Kind: Maximum Segment Size (2) + * Length: 4 + * MSS Value: 65495 + * TCP Option - SACK permitted + * Kind: SACK Permitted (4) + * Length: 2 + * TCP Option - Timestamps + * Kind: Time Stamp Option (8) + * Length: 10 + * Timestamp value: 2767168460: TSval 2767168460, TSecr 2767168460 + * Timestamp echo reply: 2767168460 + * TCP Option - No-Operation (NOP) + * Kind: No-Operation (1) + * TCP Option - Window scale: 7 (multiply by 128) + * Kind: Window Scale (3) + * Length: 3 + * Shift count: 7 + * [Multiplier: 128] + * [Timestamps] + * [Time since first frame in this TCP stream: 475471172.552028000 seconds] + * [Time since previous frame in this TCP stream: 475471172.552028000 seconds] + * [SEQ/ACK analysis] + * [This is an ACK to the segment in frame: 1] + * [The RTT to ACK the segment was: 475471172.552028000 seconds] + * [iRTT: 0.000039000 seconds] + */ + +unsigned char data[] = { + 0xd9, 0x03, 0x9f, 0x98, 0xec, 0x5f, 0xc6, 0x3c, 0x3b, 0x12, 0x47, 0x92, 0xa0, 0x12, 0xaa, 0xaa, 0xfe, 0x30, 0x00, 0x00, 0x02, 0x04, 0xff, 0xd7, 0x04, 0x02, + 0x08, 0x0a, 0xa4, 0xef, 0xa3, 0xcc, 0xa4, 0xef, 0xa3, 0xcc, 0x01, 0x03, 0x03, 0x07}; + +TEST(TCP_UTILS, GET) +{ + const struct tcphdr *hdr = (struct tcphdr *)data; + EXPECT_TRUE(tcp_hdr_get_src_port(hdr) == 55555); + EXPECT_TRUE(tcp_hdr_get_dst_port(hdr) == 40856); + EXPECT_TRUE(tcp_hdr_get_seq(hdr) == 3965699644); + EXPECT_TRUE(tcp_hdr_get_ack(hdr) == 991053714); + EXPECT_TRUE(tcp_hdr_get_hdr_len(hdr) == 40); + EXPECT_TRUE(tcp_hdr_get_flags(hdr) == 0x012); + EXPECT_TRUE(tcp_hdr_get_urg_flag(hdr) == false); + EXPECT_TRUE(tcp_hdr_get_ack_flag(hdr) == true); + EXPECT_TRUE(tcp_hdr_get_push_flag(hdr) == false); + EXPECT_TRUE(tcp_hdr_get_rst_flag(hdr) == false); + EXPECT_TRUE(tcp_hdr_get_syn_flag(hdr) == true); + EXPECT_TRUE(tcp_hdr_get_fin_flag(hdr) == false); + EXPECT_TRUE(tcp_hdr_get_window(hdr) == 43690); + EXPECT_TRUE(tcp_hdr_get_checksum(hdr) == 0xfe30); + EXPECT_TRUE(tcp_hdr_get_urg_ptr(hdr) == 0); + EXPECT_TRUE(tcp_hdr_get_opt_len(hdr) == 20); + EXPECT_TRUE(tcp_hdr_get_opt_data(hdr) == (const char *)(data + 20)); +} + +TEST(TCP_UTILS, SET1) +{ + char buff[40] = {0}; + + struct tcphdr *hdr = (struct tcphdr *)buff; + tcp_hdr_set_src_port(hdr, 55555); + tcp_hdr_set_dst_port(hdr, 40856); + tcp_hdr_set_seq(hdr, 3965699644); + tcp_hdr_set_ack(hdr, 991053714); + tcp_hdr_set_hdr_len(hdr, 40); + tcp_hdr_set_flags(hdr, 0x012); + tcp_hdr_set_window(hdr, 43690); + tcp_hdr_set_checksum(hdr, 0xfe30); + tcp_hdr_set_urg_ptr(hdr, 0); + tcp_hdr_set_opt_len(hdr, 20); + tcp_hdr_set_opt_data(hdr, (const char *)(data + 20)); + + EXPECT_TRUE(memcmp(buff, data, 40) == 0); +} + +TEST(TCP_UTILS, SET2) +{ + char buff[40] = {0}; + + struct tcphdr *hdr = (struct tcphdr *)buff; + tcp_hdr_set_src_port(hdr, 55555); + tcp_hdr_set_dst_port(hdr, 40856); + tcp_hdr_set_seq(hdr, 3965699644); + tcp_hdr_set_ack(hdr, 991053714); + tcp_hdr_set_hdr_len(hdr, 40); + tcp_hdr_set_urg_flag(hdr, false); + tcp_hdr_set_ack_flag(hdr, true); + tcp_hdr_set_push_flag(hdr, false); + tcp_hdr_set_rst_flag(hdr, false); + tcp_hdr_set_syn_flag(hdr, true); + tcp_hdr_set_fin_flag(hdr, false); + tcp_hdr_set_window(hdr, 43690); + tcp_hdr_set_checksum(hdr, 0xfe30); + tcp_hdr_set_urg_ptr(hdr, 0); + tcp_hdr_set_opt_len(hdr, 20); + tcp_hdr_set_opt_data(hdr, (const char *)(data + 20)); + + EXPECT_TRUE(memcmp(buff, data, 40) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_tunnel.cpp b/infra/packet_manager/test/gtest_tunnel.cpp new file mode 100644 index 0000000..6d92cf0 --- /dev/null +++ b/infra/packet_manager/test/gtest_tunnel.cpp @@ -0,0 +1,719 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" +#include "packet_private.h" +#include "packet_parser.h" +#include "packet_dump.h" + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:vlan:ethertype:vlan:ethertype:ip:ip:udp:data] + ****************************************************************************** + * + * Frame 1: 170 bytes on wire (1360 bits), 170 bytes captured (1360 bits) + * Ethernet II, Src: HuaweiTe_3b:b3:9a (a4:c6:4f:3b:b3:9a), Dst: 00:00:00_00:00:04 (00:00:00:00:00:04) + * Destination: 00:00:00_00:00:04 (00:00:00:00:00:04) + * Source: HuaweiTe_3b:b3:9a (a4:c6:4f:3b:b3:9a) + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 1624 + * 011. .... .... .... = Priority: Critical Applications (3) + * ...0 .... .... .... = DEI: Ineligible + * .... 0110 0101 1000 = ID: 1624 + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 3, DEI: 0, ID: 505 + * 011. .... .... .... = Priority: Critical Applications (3) + * ...0 .... .... .... = DEI: Ineligible + * .... 0001 1111 1001 = ID: 505 + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 69.67.35.146, Dst: 41.202.46.110 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0xb8 (DSCP: EF PHB, ECN: Not-ECT) + * Total Length: 148 + * Identification: 0xe858 (59480) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 255 + * Protocol: IPIP (4) + * Header Checksum: 0x1148 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 69.67.35.146 + * Destination Address: 41.202.46.110 + * Internet Protocol Version 4, Src: 10.10.100.25, Dst: 10.10.101.2 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0xb8 (DSCP: EF PHB, ECN: Not-ECT) + * Total Length: 128 + * Identification: 0x0001 (1) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 254 + * Protocol: UDP (17) + * Header Checksum: 0xde84 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.10.100.25 + * Destination Address: 10.10.101.2 + * User Datagram Protocol, Src Port: 62367, Dst Port: 17000 + * Source Port: 62367 + * Destination Port: 17000 + * Length: 108 + * Checksum: 0x4b9a [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (100 bytes) + * Data (100 bytes) + */ + +unsigned char data1[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa4, 0xc6, 0x4f, 0x3b, 0xb3, 0x9a, 0x81, 0x00, 0x66, 0x58, 0x81, 0x00, 0x61, 0xf9, 0x08, 0x00, 0x45, 0xb8, 0x00, 0x94, + 0xe8, 0x58, 0x00, 0x00, 0xff, 0x04, 0x11, 0x48, 0x45, 0x43, 0x23, 0x92, 0x29, 0xca, 0x2e, 0x6e, 0x45, 0xb8, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0xfe, 0x11, + 0xde, 0x84, 0x0a, 0x0a, 0x64, 0x19, 0x0a, 0x0a, 0x65, 0x02, 0xf3, 0x9f, 0x42, 0x68, 0x00, 0x6c, 0x4b, 0x9a, 0x00, 0x02, 0x00, 0x00, 0x04, 0x73, 0x6c, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, + 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd, 0xab, 0xcd}; + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:vlan:ethertype:ipv6:ip:gre:ppp:ip:udp:dns] + ****************************************************************************** + * + * Frame 1: 272 bytes on wire (2176 bits), 272 bytes captured (2176 bits) + * Ethernet II, Src: Cisco_e6:82:c4 (00:19:06:e6:82:c4), Dst: 10:01:00:00:61:3d (10:01:00:00:61:3d) + * Destination: 10:01:00:00:61:3d (10:01:00:00:61:3d) + * Source: Cisco_e6:82:c4 (00:19:06:e6:82:c4) + * Type: 802.1Q Virtual LAN (0x8100) + * 802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 100 + * 000. .... .... .... = Priority: Best Effort (default) (0) + * ...0 .... .... .... = DEI: Ineligible + * .... 0000 0110 0100 = ID: 100 + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2607:fcd0:100:2300::b108:2a6b, Dst: 2402:f000:1:8e01::5555 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 214 + * Next Header: IPIP (4) + * Hop Limit: 57 + * Source Address: 2607:fcd0:100:2300::b108:2a6b + * Destination Address: 2402:f000:1:8e01::5555 + * Internet Protocol Version 4, Src: 192.52.166.154, Dst: 16.0.0.200 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 214 + * Identification: 0x842f (33839) + * 010. .... = Flags: 0x2, Don't fragment + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: Generic Routing Encapsulation (47) + * Header Checksum: 0x3e33 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 192.52.166.154 + * Destination Address: 16.0.0.200 + * Generic Routing Encapsulation (PPP) + * Flags and Version: 0x3081 + * Protocol Type: PPP (0x880b) + * Payload Length: 178 + * Call ID: 17 + * Sequence Number: 538640 + * Acknowledgment Number: 429725 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 8.8.8.8, Dst: 172.16.44.3 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 174 + * Identification: 0x2f9c (12188) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 50 + * Protocol: UDP (17) + * Header Checksum: 0x7080 [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 8.8.8.8 + * Destination Address: 172.16.44.3 + * User Datagram Protocol, Src Port: 53, Dst Port: 9879 + * Source Port: 53 + * Destination Port: 9879 + * Length: 154 + * Checksum: 0x45d9 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (146 bytes) + * Domain Name System (response) + */ + +unsigned char data2[] = { + 0x10, 0x01, 0x00, 0x00, 0x61, 0x3d, 0x00, 0x19, 0x06, 0xe6, 0x82, 0xc4, 0x81, 0x00, 0x00, 0x64, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x04, 0x39, + 0x26, 0x07, 0xfc, 0xd0, 0x01, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x08, 0x2a, 0x6b, 0x24, 0x02, 0xf0, 0x00, 0x00, 0x01, 0x8e, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x45, 0x00, 0x00, 0xd6, 0x84, 0x2f, 0x40, 0x00, 0x40, 0x2f, 0x3e, 0x33, 0xc0, 0x34, 0xa6, 0x9a, 0x10, 0x00, 0x00, 0xc8, + 0x30, 0x81, 0x88, 0x0b, 0x00, 0xb2, 0x00, 0x11, 0x00, 0x08, 0x38, 0x10, 0x00, 0x06, 0x8e, 0x9d, 0xff, 0x03, 0x00, 0x21, 0x45, 0x00, 0x00, 0xae, 0x2f, 0x9c, + 0x00, 0x00, 0x32, 0x11, 0x70, 0x80, 0x08, 0x08, 0x08, 0x08, 0xac, 0x10, 0x2c, 0x03, 0x00, 0x35, 0x26, 0x97, 0x00, 0x9a, 0x45, 0xd9, 0xb4, 0xe2, 0x81, 0x83, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x35, 0x78, 0x71, 0x74, 0x2d, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x32, 0x2d, + 0x37, 0x38, 0x63, 0x30, 0x36, 0x64, 0x63, 0x37, 0x2d, 0x30, 0x34, 0x61, 0x37, 0x2d, 0x34, 0x38, 0x35, 0x33, 0x2d, 0x38, 0x34, 0x38, 0x33, 0x2d, 0x61, 0x35, + 0x36, 0x32, 0x38, 0x39, 0x37, 0x36, 0x65, 0x32, 0x33, 0x33, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x02, 0xf0, 0x00, 0x40, + 0x01, 0x61, 0x0c, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x03, 0x6e, 0x65, 0x74, 0x00, 0x05, 0x6e, 0x73, 0x74, 0x6c, 0x64, + 0x0c, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2d, 0x67, 0x72, 0x73, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x78, 0x0d, 0x09, 0x09, 0x00, 0x00, 0x07, 0x08, + 0x00, 0x00, 0x03, 0x84, 0x00, 0x09, 0x3a, 0x80, 0x00, 0x01, 0x51, 0x80}; + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ipv6:udp:gtp:ipv6:tcp:ja3:tls] + ****************************************************************************** + * + * Frame 1: 1442 bytes on wire (11536 bits), 1442 bytes captured (11536 bits) + * Ethernet II, Src: zte_0e:f5:40 (74:4a:a4:0e:f5:40), Dst: HuaweiTe_40:e9:c2 (ac:b3:b5:40:e9:c2) + * Destination: HuaweiTe_40:e9:c2 (ac:b3:b5:40:e9:c2) + * Source: zte_0e:f5:40 (74:4a:a4:0e:f5:40) + * Type: IPv6 (0x86dd) + * Internet Protocol Version 6, Src: 2409:8034:4040:5300::105, Dst: 2409:8034:4025::60:61 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 1388 + * Next Header: UDP (17) + * Hop Limit: 127 + * Source Address: 2409:8034:4040:5300::105 + * Destination Address: 2409:8034:4025::60:61 + * User Datagram Protocol, Src Port: 2152, Dst Port: 2152 + * Source Port: 2152 + * Destination Port: 2152 + * Length: 1388 + * Checksum: 0xeb00 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 0] + * [Timestamps] + * UDP payload (1380 bytes) + * GPRS Tunneling Protocol + * Flags: 0x30 + * Message Type: T-PDU (0xff) + * Length: 1372 + * TEID: 0x024c3cbd (38550717) + * Internet Protocol Version 6, Src: 2409:8c34:4400:700:0:4:0:3, Dst: 2409:8934:5082:2100:ecad:e0e4:530a:c269 + * 0110 .... = Version: 6 + * .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT) + * .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000 + * Payload Length: 1332 + * Next Header: TCP (6) + * Hop Limit: 56 + * Source Address: 2409:8c34:4400:700:0:4:0:3 + * Destination Address: 2409:8934:5082:2100:ecad:e0e4:530a:c269 + * Transmission Control Protocol, Src Port: 443, Dst Port: 46582, Seq: 1, Ack: 1, Len: 1312 + * Source Port: 443 + * Destination Port: 46582 + * [Stream index: 0] + * [Conversation completeness: Incomplete (8)] + * [TCP Segment Len: 1312] + * Sequence Number: 1 (relative sequence number) + * Sequence Number (raw): 2198097831 + * [Next Sequence Number: 1313 (relative sequence number)] + * Acknowledgment Number: 1 (relative ack number) + * Acknowledgment number (raw): 2264498872 + * 0101 .... = Header Length: 20 bytes (5) + * Flags: 0x010 (ACK) + * Window: 529 + * [Calculated window size: 529] + * [Window size scaling factor: -1 (unknown)] + * Checksum: 0x2c4b [unverified] + * [Checksum Status: Unverified] + * Urgent Pointer: 0 + * [Timestamps] + * [SEQ/ACK analysis] + * TCP payload (1312 bytes) + * Transport Layer Security + */ + +unsigned char data3[] = { + 0xac, 0xb3, 0xb5, 0x40, 0xe9, 0xc2, 0x74, 0x4a, 0xa4, 0x0e, 0xf5, 0x40, 0x86, 0xdd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x6c, 0x11, 0x7f, 0x24, 0x09, 0x80, 0x34, + 0x40, 0x40, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x24, 0x09, 0x80, 0x34, 0x40, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x61, 0x08, 0x68, 0x08, 0x68, 0x05, 0x6c, 0xeb, 0x00, 0x30, 0xff, 0x05, 0x5c, 0x02, 0x4c, 0x3c, 0xbd, 0x60, 0x00, 0x00, 0x00, 0x05, 0x34, 0x06, 0x38, + 0x24, 0x09, 0x8c, 0x34, 0x44, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x24, 0x09, 0x89, 0x34, 0x50, 0x82, 0x21, 0x00, 0xec, 0xad, + 0xe0, 0xe4, 0x53, 0x0a, 0xc2, 0x69, 0x01, 0xbb, 0xb5, 0xf6, 0x83, 0x04, 0x4f, 0xa7, 0x86, 0xf9, 0x82, 0xb8, 0x50, 0x10, 0x02, 0x11, 0x2c, 0x4b, 0x00, 0x00, + 0x17, 0x03, 0x03, 0x3c, 0x8c, 0x87, 0xa0, 0x99, 0x23, 0x5b, 0x53, 0x4a, 0x12, 0x1b, 0xf8, 0xba, 0xe8, 0x83, 0xc2, 0x95, 0xda, 0xb8, 0xea, 0x5b, 0xdc, 0x84, + 0x61, 0xa9, 0x86, 0x7e, 0x43, 0xc7, 0x31, 0x44, 0x6e, 0x11, 0xc1, 0x30, 0x21, 0x03, 0xb4, 0x21, 0x4a, 0xee, 0xc9, 0x2e, 0x14, 0xd2, 0x98, 0x63, 0x12, 0xfe, + 0x79, 0x58, 0xb3, 0x18, 0xa6, 0x8d, 0x0c, 0x62, 0x67, 0x51, 0xef, 0x02, 0x5a, 0xa8, 0xb3, 0x82, 0x1f, 0xe4, 0x51, 0xba, 0xde, 0xee, 0x83, 0x9c, 0x4e, 0xac, + 0x4d, 0xa2, 0xb7, 0x6a, 0x82, 0xe7, 0xbb, 0x00, 0xf7, 0x5a, 0xe7, 0x02, 0x71, 0x7e, 0x7d, 0x6f, 0xf2, 0xe5, 0x47, 0xd0, 0xba, 0x3c, 0x51, 0x09, 0x95, 0xcd, + 0xf6, 0xc9, 0x8b, 0x6f, 0xb0, 0x39, 0x11, 0x0d, 0xe9, 0x0d, 0x4d, 0x29, 0xd4, 0xcb, 0x87, 0xba, 0x11, 0xfa, 0x0d, 0x0b, 0x82, 0x95, 0xa5, 0x84, 0x94, 0x48, + 0xa2, 0xee, 0xa4, 0xb7, 0xb6, 0x76, 0x13, 0x4d, 0x18, 0x42, 0x91, 0x77, 0xad, 0x82, 0x38, 0xee, 0x34, 0x1c, 0xb7, 0xf6, 0x39, 0xdc, 0xa4, 0x23, 0xa1, 0x7c, + 0xa5, 0x0b, 0x7e, 0x4c, 0x8b, 0x81, 0x31, 0x48, 0xea, 0xf4, 0x18, 0x37, 0x09, 0x0a, 0x53, 0x13, 0x05, 0x90, 0x26, 0x10, 0x69, 0xb2, 0xa3, 0x36, 0xbc, 0xa5, + 0x83, 0xd8, 0x16, 0x77, 0x98, 0xc8, 0x21, 0x38, 0xd9, 0x88, 0x0c, 0xa7, 0x16, 0x97, 0x4e, 0x20, 0x6d, 0x68, 0xda, 0x1b, 0x3b, 0x4a, 0x62, 0xe0, 0x36, 0x0d, + 0xbf, 0x30, 0x71, 0xb1, 0xe9, 0xbe, 0x47, 0x77, 0x99, 0xb9, 0xe6, 0x26, 0xab, 0x81, 0x2e, 0x46, 0xf1, 0x1b, 0x1e, 0xfb, 0xd7, 0x81, 0x60, 0x21, 0x4a, 0x71, + 0x85, 0xf7, 0x9c, 0x9c, 0xd4, 0x1c, 0x52, 0xc4, 0x3d, 0x8d, 0x72, 0xf6, 0x7c, 0xd3, 0x58, 0x79, 0x0d, 0x78, 0xd7, 0x7c, 0x29, 0x2b, 0xc3, 0x96, 0x1d, 0xc7, + 0x96, 0x50, 0x42, 0xd7, 0xda, 0xeb, 0x29, 0x8e, 0x2a, 0x72, 0x23, 0x57, 0x0f, 0x6f, 0x37, 0x35, 0xb2, 0x42, 0x76, 0x78, 0xbf, 0xbf, 0x8c, 0x3f, 0x31, 0xa2, + 0x51, 0xec, 0x9e, 0x0d, 0xfd, 0xf2, 0xaf, 0x71, 0xa0, 0x4f, 0xa9, 0xf6, 0x19, 0xcf, 0x3e, 0x4b, 0xc8, 0xaa, 0x38, 0x06, 0xa1, 0x15, 0xde, 0xde, 0xef, 0x9b, + 0x25, 0xa3, 0xcc, 0x47, 0xca, 0x29, 0x30, 0x65, 0x5f, 0xc1, 0x8b, 0x12, 0x63, 0x79, 0xcd, 0x57, 0x4d, 0x99, 0xc0, 0xcd, 0xbe, 0x62, 0xcb, 0xc3, 0xf2, 0x6b, + 0x0b, 0x40, 0xc5, 0xee, 0x79, 0x0a, 0xa4, 0x75, 0x56, 0xe7, 0xe7, 0xf2, 0xfd, 0xe0, 0x72, 0x78, 0x04, 0xa2, 0x50, 0x31, 0x09, 0x8b, 0x57, 0xc3, 0x85, 0x4e, + 0xc4, 0xae, 0xde, 0x8a, 0xfa, 0xf6, 0x31, 0x06, 0xd2, 0x07, 0x25, 0x40, 0xce, 0x0d, 0xfd, 0x26, 0x98, 0x41, 0xa3, 0xa9, 0xa2, 0x8d, 0x8b, 0x7f, 0x6d, 0x63, + 0x87, 0x7e, 0x75, 0x2f, 0x78, 0xc9, 0xd5, 0x04, 0xb2, 0x4f, 0xc9, 0x94, 0xa7, 0x7f, 0xbc, 0x75, 0x7b, 0xb6, 0xfb, 0x2c, 0x46, 0xf6, 0xde, 0x36, 0x31, 0x2a, + 0x32, 0x1d, 0x7f, 0x30, 0x9e, 0x4a, 0x84, 0x69, 0x66, 0xac, 0xef, 0xbe, 0xb3, 0x83, 0x8c, 0xb8, 0x30, 0xd2, 0x3f, 0xcf, 0xb5, 0xbb, 0x65, 0xaa, 0xe7, 0x6b, + 0x74, 0x48, 0x2c, 0xb2, 0x72, 0x2b, 0x78, 0xaf, 0xd0, 0x71, 0x04, 0xa9, 0xb4, 0x65, 0xd9, 0xfc, 0x74, 0x23, 0xff, 0x89, 0xc1, 0x16, 0x23, 0xac, 0x59, 0x16, + 0x89, 0x41, 0xc3, 0xdb, 0xdb, 0x5b, 0x9a, 0x3d, 0x08, 0xc4, 0x12, 0x28, 0xf8, 0x10, 0xa5, 0xad, 0xc6, 0x81, 0xc0, 0x61, 0x48, 0xba, 0x9d, 0xef, 0xc7, 0xf8, + 0xad, 0x9a, 0xbd, 0x87, 0xfa, 0x7f, 0xa2, 0x4e, 0x4d, 0xe0, 0x19, 0xd5, 0x47, 0xc7, 0xd0, 0xfb, 0x00, 0x7b, 0xbf, 0x17, 0x80, 0xfe, 0xf5, 0x27, 0xec, 0x94, + 0x44, 0x3d, 0x4a, 0x34, 0x49, 0x60, 0xb4, 0x8d, 0x71, 0x6d, 0x9c, 0xf4, 0x4c, 0x33, 0xa9, 0x49, 0x58, 0x58, 0x6f, 0xe1, 0xd1, 0x7d, 0x36, 0x51, 0xf4, 0xd8, + 0x0d, 0x0b, 0xfc, 0xeb, 0xae, 0x58, 0x06, 0x08, 0xbf, 0x67, 0x07, 0x28, 0x7e, 0x68, 0x65, 0x79, 0x86, 0xfb, 0x43, 0x0f, 0x0a, 0xef, 0xd0, 0x97, 0x33, 0x10, + 0x7a, 0x20, 0xe8, 0x22, 0xe5, 0xdc, 0x0c, 0xa2, 0xa5, 0x50, 0x1b, 0x08, 0x15, 0xc2, 0xec, 0xd2, 0x06, 0x25, 0xd0, 0x3b, 0xfd, 0xe3, 0xa2, 0x6f, 0x41, 0x15, + 0x6d, 0x9f, 0x5f, 0xc4, 0x07, 0x5c, 0x99, 0x63, 0xd9, 0xd7, 0xdc, 0x90, 0xc9, 0x8f, 0x3a, 0x4b, 0x6a, 0x84, 0xe8, 0x3c, 0xc7, 0x71, 0x50, 0x71, 0x86, 0x71, + 0x7d, 0x54, 0x84, 0x7b, 0xb7, 0xca, 0xd5, 0x42, 0xaf, 0x88, 0xa5, 0xae, 0xa4, 0x9c, 0xfd, 0x71, 0x71, 0x0f, 0x67, 0xaa, 0x1b, 0x61, 0xd7, 0xf4, 0x50, 0x21, + 0x9d, 0x80, 0x6e, 0x54, 0xcd, 0xb6, 0xb9, 0x02, 0x3e, 0x59, 0x50, 0xff, 0xf2, 0xda, 0x21, 0x5c, 0x50, 0x6d, 0x64, 0x8c, 0x33, 0x75, 0x2a, 0xa4, 0x56, 0xb3, + 0xa8, 0xdb, 0xba, 0xbe, 0x52, 0xd4, 0xe5, 0x29, 0x68, 0xe2, 0x6b, 0x94, 0x6b, 0xb3, 0x90, 0x63, 0x91, 0x1a, 0x95, 0xb5, 0xd7, 0x10, 0x1b, 0xd9, 0x93, 0x4f, + 0x33, 0xb6, 0x6a, 0x4e, 0xcd, 0x40, 0x9d, 0x47, 0x76, 0x3e, 0x4b, 0xc7, 0x2f, 0x16, 0x96, 0x64, 0x9d, 0x4e, 0x8c, 0xfb, 0x0f, 0xd2, 0xec, 0x6c, 0xba, 0xf2, + 0x9c, 0xca, 0xd2, 0x3e, 0x64, 0x37, 0x32, 0x20, 0xd7, 0x4c, 0xb0, 0xe7, 0xd3, 0x75, 0x51, 0x3a, 0x94, 0xc1, 0xdf, 0x1c, 0xb3, 0x10, 0xd5, 0x1e, 0xcf, 0x7c, + 0xb7, 0xab, 0x4a, 0x93, 0xf0, 0x78, 0x58, 0x28, 0x63, 0x10, 0xee, 0xb0, 0xd6, 0x14, 0x81, 0x47, 0xeb, 0x2e, 0xc8, 0x6e, 0x33, 0x7e, 0xf3, 0x2d, 0xc8, 0xdb, + 0x29, 0x0c, 0x80, 0xe4, 0x2f, 0x10, 0x07, 0x8e, 0x08, 0x86, 0x97, 0x1b, 0x39, 0x98, 0x39, 0x06, 0xb3, 0x85, 0x53, 0xb7, 0xbb, 0x65, 0x65, 0x85, 0x0e, 0x0a, + 0x7d, 0x29, 0x3d, 0x3f, 0x52, 0xc2, 0x7b, 0x2b, 0x30, 0x94, 0x99, 0x6a, 0x4b, 0xad, 0xe9, 0xec, 0xcb, 0xcd, 0xae, 0x97, 0x45, 0x54, 0xd5, 0x00, 0x5e, 0xd8, + 0xac, 0xeb, 0x99, 0xdc, 0x58, 0x0b, 0x01, 0xeb, 0x32, 0x22, 0xc4, 0xec, 0x4f, 0xd2, 0x15, 0x03, 0x30, 0x88, 0xc7, 0x28, 0xaf, 0x78, 0xf5, 0x38, 0x84, 0x3b, + 0x3b, 0xe9, 0x29, 0x71, 0x50, 0xa3, 0x07, 0x49, 0x3b, 0xc6, 0x97, 0xc6, 0xf9, 0x53, 0x95, 0x51, 0x65, 0x7e, 0xd7, 0xd4, 0xe8, 0x76, 0x6a, 0x6d, 0x37, 0x6b, + 0xa5, 0x59, 0xaa, 0x14, 0x18, 0x8c, 0x8d, 0x65, 0x78, 0x67, 0xfb, 0x60, 0x56, 0xab, 0x04, 0xa0, 0xc2, 0x93, 0x46, 0xf1, 0x2b, 0x0d, 0x3b, 0x38, 0x62, 0x62, + 0x5e, 0xc8, 0x30, 0xf9, 0x45, 0x28, 0x6f, 0xa1, 0xb1, 0x88, 0xf1, 0x2b, 0x3b, 0xf8, 0xae, 0x91, 0x52, 0xc3, 0x72, 0x86, 0xe4, 0xec, 0xc3, 0x54, 0x86, 0xbf, + 0x8f, 0x33, 0xb1, 0x0f, 0x42, 0xc5, 0x9c, 0xb8, 0xc2, 0x67, 0x8b, 0xac, 0x78, 0xd7, 0x63, 0xab, 0x05, 0xc6, 0x6c, 0x37, 0xa1, 0x28, 0xef, 0x95, 0xc9, 0xf5, + 0x12, 0x38, 0x54, 0x34, 0x2e, 0x03, 0x6a, 0xaa, 0xa9, 0x97, 0x72, 0x22, 0x9f, 0x20, 0xec, 0x9e, 0x29, 0x09, 0xd8, 0x38, 0xd1, 0x86, 0x82, 0x99, 0xbd, 0x2a, + 0x03, 0xe9, 0x3d, 0xbd, 0xea, 0xc5, 0x8b, 0xb0, 0x4c, 0x8b, 0x7e, 0x78, 0x08, 0xef, 0x39, 0xa8, 0xb4, 0x47, 0xce, 0x44, 0xc3, 0x3f, 0x52, 0xe4, 0xbd, 0x9e, + 0xf6, 0xed, 0x6f, 0x6c, 0x05, 0x19, 0xa6, 0x0a, 0x1e, 0x48, 0xe3, 0x9b, 0x91, 0x61, 0xef, 0xf5, 0x91, 0x39, 0x70, 0x44, 0x1c, 0x08, 0x2e, 0x2c, 0x6c, 0x27, + 0xb9, 0x0e, 0xcc, 0x74, 0x69, 0xa5, 0xf8, 0x19, 0xd6, 0xbf, 0x57, 0x6c, 0x9a, 0x91, 0x74, 0xfd, 0xc2, 0x31, 0x32, 0x12, 0x06, 0xa3, 0x69, 0x71, 0xda, 0x40, + 0xa1, 0xf3, 0xb5, 0x9a, 0x43, 0xcc, 0xb4, 0x3c, 0x16, 0x40, 0x65, 0x2b, 0x02, 0xac, 0x5c, 0xae, 0xd6, 0x34, 0x34, 0xe3, 0x69, 0x76, 0x2c, 0xa8, 0xdd, 0x04, + 0x92, 0xa6, 0x7a, 0xc0, 0x87, 0x70, 0x8b, 0x85, 0xba, 0x5d, 0xbb, 0x62, 0x70, 0xcc, 0x1f, 0x21, 0x2c, 0x7e, 0xc3, 0x77, 0xcf, 0x23, 0x22, 0xf4, 0x16, 0x8e, + 0xf1, 0x3d, 0xdc, 0x33, 0x99, 0x5e, 0xaa, 0xa2, 0x50, 0x68, 0xde, 0x03, 0x44, 0xbb, 0xc7, 0x16, 0x2a, 0xf2, 0x08, 0xeb, 0x3d, 0x12, 0x6d, 0xcb, 0x2a, 0xaf, + 0xb4, 0x79, 0xdb, 0x74, 0x5e, 0x54, 0x89, 0x73, 0x0c, 0x48, 0x9c, 0x03, 0x33, 0xd2, 0x92, 0x22, 0xdb, 0x3a, 0xa0, 0x8c, 0xe2, 0x30, 0x6f, 0x39, 0xe4, 0xa9, + 0x24, 0x04, 0xbb, 0x85, 0x7d, 0x62, 0xc5, 0xa9, 0x98, 0x92, 0xef, 0xc6, 0xc8, 0xd1, 0x81, 0xad, 0x95, 0x40, 0x27, 0x09, 0xc7, 0x43, 0xcd, 0xb6, 0x94, 0xfc, + 0x1c, 0x7d, 0x1c, 0xd3, 0x47, 0xfe, 0x62, 0x9c, 0xfa, 0xeb, 0xfc, 0x02, 0x2e, 0x48, 0x62, 0xcf, 0x63, 0xdb, 0x63, 0xd9, 0x21, 0x86, 0xe8, 0x96, 0x54, 0xeb, + 0x6a, 0xa8, 0x78, 0x3c, 0x5b, 0xb6, 0xde, 0xa9, 0x04, 0x48, 0x63, 0xb2, 0x10, 0x02, 0x6a, 0x7f, 0x6d, 0xc8, 0x04, 0xdd, 0x99, 0x25, 0x08, 0xff, 0x80, 0x11, + 0x53, 0xfb, 0x7a, 0x07, 0x39, 0xd9, 0x97, 0xca, 0xf0, 0xa7, 0x46, 0x9c, 0xc2, 0xae, 0x2e, 0x05, 0x62, 0xa0, 0xd5, 0x5d, 0x17, 0x0e, 0x5c, 0x7e, 0x9a, 0xb2, + 0xb7, 0x9d, 0xd4, 0x4f, 0xe3, 0xac, 0x64, 0xdb, 0x6f, 0x1d, 0xdf, 0xd8, 0x41, 0xd7, 0xd9, 0x50, 0x55, 0x30, 0xeb, 0x4b, 0x19, 0xce, 0x78, 0x1f, 0xa8, 0x1e, + 0x87, 0x9c, 0x8f, 0x93, 0x97, 0xd4, 0xa2, 0x28, 0x2c, 0x79, 0x22, 0xc8}; + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:udp:vxlan:eth:ethertype:ip:udp:dns] + ****************************************************************************** + * + * Frame 1: 124 bytes on wire (992 bits), 124 bytes captured (992 bits) + * Ethernet II, Src: zte_6c:fa:43 (00:1e:73:6c:fa:43), Dst: Shanghai_0d:0a (e4:95:6e:20:0d:0a) + * Destination: Shanghai_0d:0a (e4:95:6e:20:0d:0a) + * Source: zte_6c:fa:43 (00:1e:73:6c:fa:43) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 10.1.1.1, Dst: 192.168.1.10 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 110 + * Identification: 0x0000 (0) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 254 + * Protocol: UDP (17) + * Header Checksum: 0xefca [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 10.1.1.1 + * Destination Address: 192.168.1.10 + * User Datagram Protocol, Src Port: 50709, Dst Port: 4789 + * Source Port: 50709 + * Destination Port: 4789 + * Length: 90 + * Checksum: 0x0000 [zero-value ignored] + * [Stream index: 0] + * [Timestamps] + * UDP payload (82 bytes) + * Virtual eXtensible Local Area Network + * Flags: 0x0800, VXLAN Network ID (VNI) + * Group Policy ID: 0 + * VXLAN Network Identifier (VNI): 458755 + * Reserved: 0 + * Ethernet II, Src: WistronI_18:18:41 (3c:97:0e:18:18:41), Dst: DawningI_13:70:7a (e8:61:1f:13:70:7a) + * Destination: DawningI_13:70:7a (e8:61:1f:13:70:7a) + * Source: WistronI_18:18:41 (3c:97:0e:18:18:41) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 192.168.11.193, Dst: 114.114.114.114 + * 0100 .... = Version: 4 + * .... 0101 = Header Length: 20 bytes (5) + * Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT) + * Total Length: 60 + * Identification: 0x0cb6 (3254) + * 000. .... = Flags: 0x0 + * ...0 0000 0000 0000 = Fragment Offset: 0 + * Time to Live: 64 + * Protocol: UDP (17) + * Header Checksum: 0xbcad [validation disabled] + * [Header checksum status: Unverified] + * Source Address: 192.168.11.193 + * Destination Address: 114.114.114.114 + * User Datagram Protocol, Src Port: 65290, Dst Port: 53 + * Source Port: 65290 + * Destination Port: 53 + * Length: 40 + * Checksum: 0x39e4 [unverified] + * [Checksum Status: Unverified] + * [Stream index: 1] + * [Timestamps] + * UDP payload (32 bytes) + * Domain Name System (query) + */ + +unsigned char data4[] = { + 0xe4, 0x95, 0x6e, 0x20, 0x0d, 0x0a, 0x00, 0x1e, 0x73, 0x6c, 0xfa, 0x43, 0x08, 0x00, 0x45, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x11, 0xef, 0xca, + 0x0a, 0x01, 0x01, 0x01, 0xc0, 0xa8, 0x01, 0x0a, 0xc6, 0x15, 0x12, 0xb5, 0x00, 0x5a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0xe8, 0x61, + 0x1f, 0x13, 0x70, 0x7a, 0x3c, 0x97, 0x0e, 0x18, 0x18, 0x41, 0x08, 0x00, 0x45, 0x00, 0x00, 0x3c, 0x0c, 0xb6, 0x00, 0x00, 0x40, 0x11, 0xbc, 0xad, 0xc0, 0xa8, + 0x0b, 0xc1, 0x72, 0x72, 0x72, 0x72, 0xff, 0x0a, 0x00, 0x35, 0x00, 0x28, 0x39, 0xe4, 0x86, 0x84, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x77, 0x77, 0x77, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01}; + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:udp:l2tp:ppp:ip:udp:nbns] + ****************************************************************************** + * + * Frame 1: 150 bytes on wire (1200 bits), 150 bytes captured (1200 bits) + * Ethernet II, Src: LCFCElectron_43:38:37 (28:d2:44:43:38:37), Dst: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Destination: c0:00:14:8c:00:00 (c0:00:14:8c:00:00) + * Source: LCFCElectron_43:38:37 (28:d2:44:43:38:37) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 172.16.0.100, Dst: 172.16.0.254 + * 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: 136 + * Identification: 0x06ca (1738) + * 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: 128 + * Protocol: UDP (17) + * Header Checksum: 0xda18 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0xda18] + * Source Address: 172.16.0.100 + * Destination Address: 172.16.0.254 + * User Datagram Protocol, Src Port: 1701, Dst Port: 1701 + * Source Port: 1701 + * Destination Port: 1701 + * Length: 116 + * Checksum: 0x962f [correct] + * [Calculated Checksum: 0x962f] + * [Checksum Status: Good] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (108 bytes) + * Layer 2 Tunneling Protocol + * Flags: 0x4002, Type: Data Message, Length Bit + * 0... .... .... .... = Type: Data Message (0) + * .1.. .... .... .... = Length Bit: Length field is present + * .... 0... .... .... = Sequence Bit: Ns and Nr fields are not present + * .... ..0. .... .... = Offset bit: Offset size field is not present + * .... ...0 .... .... = Priority: No priority + * .... .... .... 0010 = Version: 2 + * Length: 108 + * Tunnel ID: 28998 + * Session ID: 2 + * Point-to-Point Protocol + * Address: 0xff + * Control: 0x03 + * Protocol: Internet Protocol version 4 (0x0021) + * Internet Protocol Version 4, Src: 172.16.2.100, Dst: 255.255.255.255 + * 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: 96 + * Identification: 0x0004 (4) + * 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: 128 + * Protocol: UDP (17) + * Header Checksum: 0x8c15 [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x8c15] + * Source Address: 172.16.2.100 + * Destination Address: 255.255.255.255 + * User Datagram Protocol, Src Port: 137, Dst Port: 137 + * Source Port: 137 + * Destination Port: 137 + * Length: 76 + * Checksum: 0xba80 [correct] + * [Calculated Checksum: 0xba80] + * [Checksum Status: Good] + * [Stream index: 1] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (68 bytes) + * NetBIOS Name Service + */ + +unsigned char data5[] = { + 0xc0, 0x00, 0x14, 0x8c, 0x00, 0x00, 0x28, 0xd2, 0x44, 0x43, 0x38, 0x37, 0x08, 0x00, 0x45, 0x00, 0x00, 0x88, 0x06, 0xca, 0x00, 0x00, 0x80, 0x11, 0xda, 0x18, + 0xac, 0x10, 0x00, 0x64, 0xac, 0x10, 0x00, 0xfe, 0x06, 0xa5, 0x06, 0xa5, 0x00, 0x74, 0x96, 0x2f, 0x40, 0x02, 0x00, 0x6c, 0x71, 0x46, 0x00, 0x02, 0xff, 0x03, + 0x00, 0x21, 0x45, 0x00, 0x00, 0x60, 0x00, 0x04, 0x00, 0x00, 0x80, 0x11, 0x8c, 0x15, 0xac, 0x10, 0x02, 0x64, 0xff, 0xff, 0xff, 0xff, 0x00, 0x89, 0x00, 0x89, + 0x00, 0x4c, 0xba, 0x80, 0xc6, 0x46, 0x29, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x45, 0x4a, 0x45, 0x4a, 0x45, 0x46, 0x43, 0x4e, 0x46, + 0x44, 0x45, 0x4e, 0x43, 0x4e, 0x46, 0x45, 0x45, 0x49, 0x45, 0x4a, 0x45, 0x4f, 0x45, 0x4c, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x41, 0x41, 0x00, 0x00, 0x20, + 0x00, 0x01, 0xc0, 0x0c, 0x00, 0x20, 0x00, 0x01, 0x00, 0x04, 0x93, 0xe0, 0x00, 0x06, 0x00, 0x00, 0xac, 0x10, 0x02, 0x64}; + +/****************************************************************************** + * [Protocols in frame: eth:ethertype:ip:udp:teredo:ipv6:udp:data] + ****************************************************************************** + * + * Frame 1: 108 bytes on wire (864 bits), 108 bytes captured (864 bits) + * Ethernet II, Src: Dell_c4:5b:ea (bc:30:5b:c4:5b:ea), Dst: Dell_3e:34:9c (b8:ac:6f:3e:34:9c) + * Destination: Dell_3e:34:9c (b8:ac:6f:3e:34:9c) + * Source: Dell_c4:5b:ea (bc:30:5b:c4:5b:ea) + * Type: IPv4 (0x0800) + * Internet Protocol Version 4, Src: 193.0.0.3, Dst: 193.0.0.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: 94 + * Identification: 0x62a0 (25248) + * 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: UDP (17) + * Header Checksum: 0x95ea [correct] + * [Header checksum status: Good] + * [Calculated Checksum: 0x95ea] + * Source Address: 193.0.0.3 + * Destination Address: 193.0.0.1 + * User Datagram Protocol, Src Port: 45802, Dst Port: 3544 + * Source Port: 45802 + * Destination Port: 3544 + * Length: 74 + * Checksum: 0x4b23 [correct] + * [Calculated Checksum: 0x4b23] + * [Checksum Status: Good] + * [Stream index: 0] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (66 bytes) + * Teredo IPv6 over UDP tunneling + * Internet Protocol Version 6, Src: 2002:0:c100:1:24ba:4d15:3eff:fffc, Dst: 2001:db8:1::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: 26 + * Next Header: UDP (17) + * Hop Limit: 128 + * Source Address: 2002:0:c100:1:24ba:4d15:3eff:fffc + * Destination Address: 2001:db8:1::1 + * [Source 6to4 Gateway IPv4: 0.0.193.0] + * [Source 6to4 SLA ID: 1] + * User Datagram Protocol, Src Port: 32768, Dst Port: 20480 + * Source Port: 32768 + * Destination Port: 20480 + * Length: 26 + * Checksum: 0xf017 [correct] + * [Calculated Checksum: 0xf017] + * [Checksum Status: Good] + * [Stream index: 1] + * [Timestamps] + * [Time since first frame: 0.000000000 seconds] + * [Time since previous frame: 0.000000000 seconds] + * UDP payload (18 bytes) + * Data (18 bytes) + * Data: 4fd54034712d3f014d3180b082c007d0e76c + * [Length: 18] + */ + +unsigned char data6[] = { + 0xb8, 0xac, 0x6f, 0x3e, 0x34, 0x9c, 0xbc, 0x30, 0x5b, 0xc4, 0x5b, 0xea, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5e, 0x62, 0xa0, 0x00, 0x00, 0x40, 0x11, 0x95, 0xea, + 0xc1, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x00, 0x01, 0xb2, 0xea, 0x0d, 0xd8, 0x00, 0x4a, 0x4b, 0x23, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x11, 0x80, 0x20, 0x02, + 0x00, 0x00, 0xc1, 0x00, 0x00, 0x01, 0x24, 0xba, 0x4d, 0x15, 0x3e, 0xff, 0xff, 0xfc, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x50, 0x00, 0x00, 0x1a, 0xf0, 0x17, 0x4f, 0xd5, 0x40, 0x34, 0x71, 0x2d, 0x3f, 0x01, 0x4d, 0x31, 0x80, 0xb0, 0x82, 0xc0, + 0x07, 0xd0, 0xe7, 0x6c}; + +TEST(TUNNEL, IPV4) +{ + struct packet pkt; + struct tunnel out; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data1, sizeof(data1)); + packet_print(&pkt); + + EXPECT_TRUE(packet_get_tunnel_count(&pkt) == 1); + + // IPv4 tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 0, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_IPV4); + EXPECT_TRUE(out.layer_count == 1); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV4); + EXPECT_TRUE(out.layers[0]->hdr_len == 20); + + // No tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 1, &out) == -1); +} + +TEST(TUNNEL, IPV6) +{ + // TEST ON GRE +} + +TEST(TUNNEL, GRE) +{ + struct packet pkt; + struct tunnel out; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data2, sizeof(data2)); + packet_print(&pkt); + + EXPECT_TRUE(packet_get_tunnel_count(&pkt) == 2); + + // IPv6 tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 0, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_IPV6); + EXPECT_TRUE(out.layer_count == 1); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV6); + EXPECT_TRUE(out.layers[0]->hdr_len == 40); + + // GRE tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 1, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_GRE); + EXPECT_TRUE(out.layer_count == 2); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV4); + EXPECT_TRUE(out.layers[0]->hdr_len == 20); + + EXPECT_TRUE(out.layers[1]->proto == LAYER_PROTO_GRE); + EXPECT_TRUE(out.layers[1]->hdr_len == 16); + + // No tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 2, &out) == -1); +} + +TEST(TUNNEL, GTP) +{ + struct packet pkt; + struct tunnel out; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data3, sizeof(data3)); + packet_print(&pkt); + + EXPECT_TRUE(packet_get_tunnel_count(&pkt) == 1); + + // GTP tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 0, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_GTP); + EXPECT_TRUE(out.layer_count == 3); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV6); + EXPECT_TRUE(out.layers[0]->hdr_len == 40); + + EXPECT_TRUE(out.layers[1]->proto == LAYER_PROTO_UDP); + EXPECT_TRUE(out.layers[1]->hdr_len == 8); + + EXPECT_TRUE(out.layers[2]->proto == LAYER_PROTO_GTP_U); + EXPECT_TRUE(out.layers[2]->hdr_len == 8); + + // No tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 1, &out) == -1); +} + +TEST(TUNNEL, VXLAN) +{ + struct packet pkt; + struct tunnel out; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data4, sizeof(data4)); + packet_print(&pkt); + + EXPECT_TRUE(packet_get_tunnel_count(&pkt) == 1); + + // VXLAN tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 0, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_VXLAN); + EXPECT_TRUE(out.layer_count == 3); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV4); + EXPECT_TRUE(out.layers[0]->hdr_len == 20); + + EXPECT_TRUE(out.layers[1]->proto == LAYER_PROTO_UDP); + EXPECT_TRUE(out.layers[1]->hdr_len == 8); + + EXPECT_TRUE(out.layers[2]->proto == LAYER_PROTO_VXLAN); + EXPECT_TRUE(out.layers[2]->hdr_len == 8); + + // No tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 1, &out) == -1); +} + +TEST(TUNNEL, L2TP) +{ + struct packet pkt; + struct tunnel out; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data5, sizeof(data5)); + packet_print(&pkt); + + EXPECT_TRUE(packet_get_tunnel_count(&pkt) == 1); + + // L2TP tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 0, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_L2TP); + EXPECT_TRUE(out.layer_count == 3); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV4); + EXPECT_TRUE(out.layers[0]->hdr_len == 20); + + EXPECT_TRUE(out.layers[1]->proto == LAYER_PROTO_UDP); + EXPECT_TRUE(out.layers[1]->hdr_len == 8); + + EXPECT_TRUE(out.layers[2]->proto == LAYER_PROTO_L2TP); + EXPECT_TRUE(out.layers[2]->hdr_len == 8); + + // No tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 1, &out) == -1); +} + +TEST(TUNNEL, TEREDO) +{ + struct packet pkt; + struct tunnel out; + + memset(&pkt, 0, sizeof(pkt)); + packet_parse(&pkt, (const char *)data6, sizeof(data6)); + packet_print(&pkt); + + EXPECT_TRUE(packet_get_tunnel_count(&pkt) == 1); + + // IPv4 tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 0, &out) == 0); + EXPECT_TRUE(out.type == TUNNEL_TEREDO); + EXPECT_TRUE(out.layer_count == 2); + + EXPECT_TRUE(out.layers[0]->proto == LAYER_PROTO_IPV4); + EXPECT_TRUE(out.layers[0]->hdr_len == 20); + + EXPECT_TRUE(out.layers[1]->proto == LAYER_PROTO_UDP); + EXPECT_TRUE(out.layers[1]->hdr_len == 8); + + // No tunnel + EXPECT_TRUE(packet_get_tunnel_by_idx(&pkt, 1, &out) == -1); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_udp_utils.cpp b/infra/packet_manager/test/gtest_udp_utils.cpp new file mode 100644 index 0000000..d8b2c9a --- /dev/null +++ b/infra/packet_manager/test/gtest_udp_utils.cpp @@ -0,0 +1,43 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * User Datagram Protocol, Src Port: 4001, Dst Port: 8000 + * Source Port: 4001 + * Destination Port: 8000 + * Length: 155 + * Checksum: 0x1e1e [correct] + * [Calculated Checksum: 0x1e1e] + * [Checksum Status: Good] + */ + +unsigned char data[] = {0x0f, 0xa1, 0x1f, 0x40, 0x00, 0x9b, 0x1e, 0x1e}; + +TEST(UDP_UTILS, GET) +{ + const struct udphdr *hdr = (struct udphdr *)data; + + EXPECT_TRUE(udp_hdr_get_src_port(hdr) == 4001); + EXPECT_TRUE(udp_hdr_get_dst_port(hdr) == 8000); + EXPECT_TRUE(udp_hdr_get_total_len(hdr) == 155); + EXPECT_TRUE(udp_hdr_get_checksum(hdr) == 0x1e1e); +} + +TEST(UDP_UTILS, SET) +{ + char buff[8] = {0}; + struct udphdr *hdr = (struct udphdr *)buff; + + udp_hdr_set_src_port(hdr, 4001); + udp_hdr_set_dst_port(hdr, 8000); + udp_hdr_set_total_len(hdr, 155); + udp_hdr_set_checksum(hdr, 0x1e1e); + EXPECT_TRUE(memcmp(buff, data, 8) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_vlan_utils.cpp b/infra/packet_manager/test/gtest_vlan_utils.cpp new file mode 100644 index 0000000..0832ef1 --- /dev/null +++ b/infra/packet_manager/test/gtest_vlan_utils.cpp @@ -0,0 +1,42 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * IEEE 802.1ad, ID: 1 + * 000. .... .... .... = Priority: 0 + * ...0 .... .... .... = DEI: 0 + * .... 0000 0000 0001 = ID: 1 + * Type: 802.1Q Virtual LAN (0x8100) + */ + +unsigned char data[] = { + 0x00, 0x01, 0x81, 0x00}; + +TEST(VLAN_UTILS, GET) +{ + const struct vlan_hdr *hdr = (struct vlan_hdr *)data; + + EXPECT_TRUE(vlan_hdr_get_priority(hdr) == 0); + EXPECT_TRUE(vlan_hdr_get_dei(hdr) == 0); + EXPECT_TRUE(vlan_hdr_get_vid(hdr) == 1); + EXPECT_TRUE(vlan_hdr_get_ethertype(hdr) == 0x8100); +} + +TEST(VLAN_UTILS, SET) +{ + char buff[4] = {0}; + struct vlan_hdr *hdr = (struct vlan_hdr *)buff; + + vlan_hdr_set_priority(hdr, 0); + vlan_hdr_set_dei(hdr, 0); + vlan_hdr_set_vid(hdr, 1); + vlan_hdr_set_ethertype(hdr, 0x8100); + EXPECT_TRUE(memcmp(buff, data, 4) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/infra/packet_manager/test/gtest_vxlan_utils.cpp b/infra/packet_manager/test/gtest_vxlan_utils.cpp new file mode 100644 index 0000000..81a24fe --- /dev/null +++ b/infra/packet_manager/test/gtest_vxlan_utils.cpp @@ -0,0 +1,43 @@ +#include <gtest/gtest.h> + +#include "packet_helper.h" + +/* + * Virtual eXtensible Local Area Network + * Flags: 0x0800, VXLAN Network ID (VNI) + * 0... .... .... .... = GBP Extension: Not defined + * .... 1... .... .... = VXLAN Network ID (VNI): True + * .... .... .0.. .... = Don't Learn: False + * .... .... .... 0... = Policy Applied: False + * .000 .000 0.00 .000 = Reserved(R): 0x0000 + * Group Policy ID: 0 + * VXLAN Network Identifier (VNI): 461829 + * Reserved: 0 + */ + +unsigned char data[] = { + 0x08, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x05, 0x00}; + +TEST(VXLAN_UTILS, GET) +{ + const struct vxlan_hdr *hdr = (struct vxlan_hdr *)data; + + EXPECT_TRUE(vxlan_hdr_get_flags(hdr) == 0x08); + EXPECT_TRUE(vxlan_hdr_get_vni(hdr) == 461829); +} + +TEST(VXLAN_UTILS, SET) +{ + char buff[8] = {0}; + struct vxlan_hdr *hdr = (struct vxlan_hdr *)buff; + + vxlan_hdr_set_flags(hdr, 0x08); + vxlan_hdr_set_vni(hdr, 461829); + EXPECT_TRUE(memcmp(buff, data, 8) == 0); +} + +int main(int argc, char **argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} |
