support craft packet from scratch
This commit is contained in:
@@ -79,12 +79,15 @@ int packet_get_layer_by_idx(const struct packet *pkt, int idx, struct layer *out
|
|||||||
for (int i = packet_get_layer_count(pkt) - 1; i >= 0 && packet_get_layer_by_idx(pkt, i, &layer) == 0; i--)
|
for (int i = packet_get_layer_count(pkt) - 1; i >= 0 && packet_get_layer_by_idx(pkt, i, &layer) == 0; i--)
|
||||||
|
|
||||||
#define PACKET_GETALL_LAYERS(pkt, layers) \
|
#define PACKET_GETALL_LAYERS(pkt, layers) \
|
||||||
{ \
|
({ \
|
||||||
int num = MIN(packet_get_layer_count(pkt), (sizeof(layers) / sizeof(layers[0]))); \
|
memset(layers, 0, sizeof(layers)); \
|
||||||
|
int size = sizeof(layers) / sizeof(layers[0]); \
|
||||||
|
int count = packet_get_layer_count(pkt); \
|
||||||
|
int num = count > size ? size : count; \
|
||||||
for (int i = 0; i < num && packet_get_layer_by_idx(pkt, i, &layers[i]) == 0; i++) \
|
for (int i = 0; i < num && packet_get_layer_by_idx(pkt, i, &layers[i]) == 0; i++) \
|
||||||
/* void */; \
|
/* void */; \
|
||||||
return num; \
|
num; \
|
||||||
}
|
})
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ uint16_t packet_get_payload_len(const struct packet *pkt);
|
|||||||
|
|
||||||
struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, const char *tcp_payload, uint16_t tcp_payload_len);
|
struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, const char *tcp_payload, uint16_t tcp_payload_len);
|
||||||
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
||||||
|
struct packet *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,3 +253,120 @@ struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *u
|
|||||||
|
|
||||||
return new_pkt;
|
return new_pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct packet *craft_packet_from_scratch(const struct layer layers[], uint16_t layer_count, const char *payload, uint16_t payload_len)
|
||||||
|
{
|
||||||
|
// check arguments
|
||||||
|
if (layers == NULL || layer_count == 0 || (payload == NULL && payload_len != 0) || (payload != NULL && payload_len == 0))
|
||||||
|
{
|
||||||
|
PACKET_BUILD_LOG_ERROR("craft packet from scratch failed, invalid arguments");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate the new packet length
|
||||||
|
uint16_t new_pkt_len = 0;
|
||||||
|
for (int i = 0; i < layer_count; i++)
|
||||||
|
{
|
||||||
|
if (layers[i].hdr.raw == NULL || layers[i].hdr_len == 0)
|
||||||
|
{
|
||||||
|
PACKET_BUILD_LOG_ERROR("craft packet from scratch failed, the header of layer %d is invalid", i);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
new_pkt_len += layers[i].hdr_len;
|
||||||
|
}
|
||||||
|
new_pkt_len += payload_len;
|
||||||
|
struct packet *new_pkt = packet_new(new_pkt_len);
|
||||||
|
if (new_pkt == NULL)
|
||||||
|
{
|
||||||
|
PACKET_BUILD_LOG_ERROR("craft packet from scratch 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);
|
||||||
|
int offset = 0;
|
||||||
|
for (int i = 0; i < layer_count; i++)
|
||||||
|
{
|
||||||
|
memcpy(new_pkt_data + offset, layers[i].hdr.raw, layers[i].hdr_len);
|
||||||
|
offset += layers[i].hdr_len;
|
||||||
|
}
|
||||||
|
memcpy(new_pkt_data + offset, payload, payload_len);
|
||||||
|
|
||||||
|
// update the headers of the new packet
|
||||||
|
struct tcphdr *tcp_hdr = NULL;
|
||||||
|
struct udphdr *udp_hdr = NULL;
|
||||||
|
struct ip *ip4_hdr = NULL;
|
||||||
|
struct ip6_hdr *ip6_hdr = NULL;
|
||||||
|
// update checksums and lengths
|
||||||
|
uint16_t curr_layer_payload_len = payload_len;
|
||||||
|
for (int i = layer_count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
switch (layers[i].proto)
|
||||||
|
{
|
||||||
|
case LAYER_PROTO_TCP:
|
||||||
|
tcp_hdr = (struct tcphdr *)(new_pkt_data + new_pkt_len - layers[i].hdr_len - curr_layer_payload_len);
|
||||||
|
// update the TCP header
|
||||||
|
tcp_hdr_set_hdr_len(tcp_hdr, layers[i].hdr_len);
|
||||||
|
tcp_hdr_set_checksum(tcp_hdr, 0);
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_UDP:
|
||||||
|
udp_hdr = (struct udphdr *)(new_pkt_data + new_pkt_len - layers[i].hdr_len - curr_layer_payload_len);
|
||||||
|
// update the UDP header
|
||||||
|
udp_hdr_set_total_len(udp_hdr, layers[i].hdr_len + curr_layer_payload_len);
|
||||||
|
udp_hdr_set_checksum(udp_hdr, 0);
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_IPV4:
|
||||||
|
ip4_hdr = (struct ip *)(new_pkt_data + new_pkt_len - layers[i].hdr_len - curr_layer_payload_len);
|
||||||
|
// update the checksums of the upper layer
|
||||||
|
if (i + 1 < layer_count && layers[i + 1].proto == LAYER_PROTO_TCP)
|
||||||
|
{
|
||||||
|
tcp_hdr = (struct tcphdr *)(new_pkt_data + new_pkt_len - curr_layer_payload_len);
|
||||||
|
tcp_hdr->th_sum = checksum_v4(tcp_hdr, curr_layer_payload_len, IPPROTO_TCP, &ip4_hdr->ip_src, &ip4_hdr->ip_dst);
|
||||||
|
}
|
||||||
|
if (i + 1 < layer_count && layers[i + 1].proto == LAYER_PROTO_UDP)
|
||||||
|
{
|
||||||
|
udp_hdr = (struct udphdr *)(new_pkt_data + new_pkt_len - curr_layer_payload_len);
|
||||||
|
udp_hdr->uh_sum = checksum_v4(udp_hdr, curr_layer_payload_len, IPPROTO_UDP, &ip4_hdr->ip_src, &ip4_hdr->ip_dst);
|
||||||
|
}
|
||||||
|
// update the IPv4 header
|
||||||
|
ipv4_hdr_set_hdr_len(ip4_hdr, layers[i].hdr_len);
|
||||||
|
ipv4_hdr_set_total_len(ip4_hdr, layers[i].hdr_len + curr_layer_payload_len);
|
||||||
|
ip4_hdr->ip_sum = 0;
|
||||||
|
ip4_hdr->ip_sum = checksum((const char *)ip4_hdr, layers[i].hdr_len);
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_IPV6:
|
||||||
|
ip6_hdr = (struct ip6_hdr *)(new_pkt_data + new_pkt_len - layers[i].hdr_len - curr_layer_payload_len);
|
||||||
|
// update the checksums of the upper layer
|
||||||
|
if (i + 1 < layer_count && layers[i + 1].proto == LAYER_PROTO_TCP)
|
||||||
|
{
|
||||||
|
tcp_hdr = (struct tcphdr *)(new_pkt_data + new_pkt_len - curr_layer_payload_len);
|
||||||
|
tcp_hdr->th_sum = checksum_v6(tcp_hdr, curr_layer_payload_len, IPPROTO_TCP, &ip6_hdr->ip6_src, &ip6_hdr->ip6_dst);
|
||||||
|
}
|
||||||
|
if (i + 1 < layer_count && layers[i + 1].proto == LAYER_PROTO_UDP)
|
||||||
|
{
|
||||||
|
udp_hdr = (struct udphdr *)(new_pkt_data + new_pkt_len - curr_layer_payload_len);
|
||||||
|
udp_hdr->uh_sum = checksum_v6(udp_hdr, curr_layer_payload_len, IPPROTO_UDP, &ip6_hdr->ip6_src, &ip6_hdr->ip6_dst);
|
||||||
|
}
|
||||||
|
// update the IPv6 header
|
||||||
|
ipv6_hdr_set_payload_len(ip6_hdr, layers[i].hdr_len + curr_layer_payload_len - sizeof(struct ip6_hdr));
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_GRE:
|
||||||
|
// TODO
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
curr_layer_payload_len += layers[i].hdr_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_parse(new_pkt, new_pkt_data, new_pkt_len);
|
||||||
|
// no metadata for the new packet from scratch
|
||||||
|
new_pkt->meta.origin_ctx = NULL;
|
||||||
|
|
||||||
|
return new_pkt;
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ extern "C"
|
|||||||
|
|
||||||
struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, const char *tcp_payload, uint16_t tcp_payload_len);
|
struct packet *imitate_tcp_packet(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags, const char *tcp_payload, uint16_t tcp_payload_len);
|
||||||
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
struct packet *imitate_udp_packet(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
|
||||||
|
struct packet *craft_packet_from_scratch(const struct layer larers[], uint16_t layer_count, const char *payload, uint16_t payload_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ global:
|
|||||||
packet_get_payload_len;
|
packet_get_payload_len;
|
||||||
imitate_tcp_packet;
|
imitate_tcp_packet;
|
||||||
imitate_udp_packet;
|
imitate_udp_packet;
|
||||||
|
craft_packet_from_scratch;
|
||||||
|
|
||||||
session_exdata_free;
|
session_exdata_free;
|
||||||
stellar_session_exdata_new_index;
|
stellar_session_exdata_new_index;
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
add_subdirectory(packet_inject)
|
add_subdirectory(packet_inject)
|
||||||
add_subdirectory(packet_parser)
|
add_subdirectory(packet_tool)
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include <pcap/pcap.h>
|
|
||||||
#include "packet_def.h"
|
|
||||||
#include "packet_layer.h"
|
|
||||||
#include "packet_parse.h"
|
|
||||||
#include "eth_utils.h"
|
|
||||||
#include "vlan_utils.h"
|
|
||||||
#include "ipv4_utils.h"
|
|
||||||
#include "ipv6_utils.h"
|
|
||||||
#include "tcp_utils.h"
|
|
||||||
#include "udp_utils.h"
|
|
||||||
|
|
||||||
struct options
|
|
||||||
{
|
|
||||||
char *file;
|
|
||||||
int print_tshark_format;
|
|
||||||
int print_readable_format;
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint64_t number = 0;
|
|
||||||
|
|
||||||
#define MAX_BUFF_SIZE 2048
|
|
||||||
struct buffer
|
|
||||||
{
|
|
||||||
char buff[MAX_BUFF_SIZE];
|
|
||||||
int used;
|
|
||||||
char elimiter;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void buffer_push(struct buffer *buff, const char *str)
|
|
||||||
{
|
|
||||||
int len = strlen(str);
|
|
||||||
if (buff->used + len + 1 >= MAX_BUFF_SIZE)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (buff->used)
|
|
||||||
{
|
|
||||||
buff->buff[buff->used++] = buff->elimiter;
|
|
||||||
}
|
|
||||||
memcpy(buff->buff + buff->used, str, len);
|
|
||||||
buff->used += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void packet_to_tshark_format(const struct packet *pkt, uint64_t idx)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
tshark -r ${pcap} -T fields \
|
|
||||||
-e frame.number \
|
|
||||||
-e frame.protocols \
|
|
||||||
-e eth.src \
|
|
||||||
-e eth.dst \
|
|
||||||
-e vlan.id \
|
|
||||||
-e ip.src \
|
|
||||||
-e ip.dst \
|
|
||||||
-e ipv6.src \
|
|
||||||
-e ipv6.dst \
|
|
||||||
-e tcp.srcport \
|
|
||||||
-e tcp.dstport \
|
|
||||||
-e udp.srcport \
|
|
||||||
-e udp.dstport \
|
|
||||||
>> tshark_output.txt
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct buffer buff_proto = {.buff = {0}, .used = 0, .elimiter = ':'};
|
|
||||||
struct buffer buff_eth_src = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_eth_dst = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_vlan_id = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_ipv4_src = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_ipv4_dst = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_ipv6_src = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_ipv6_dst = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_tcp_src = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_tcp_dst = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_udp_src = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
struct buffer buff_udp_dst = {.buff = {0}, .used = 0, .elimiter = ','};
|
|
||||||
const struct ethhdr *eth_hdr = NULL;
|
|
||||||
const struct vlan_hdr *vlan_hdr = NULL;
|
|
||||||
const struct ip *ipv4_hdr = NULL;
|
|
||||||
const struct ip6_hdr *ipv6_hdr = NULL;
|
|
||||||
const struct tcphdr *tcp_hdr = NULL;
|
|
||||||
const struct udphdr *udp_hdr = NULL;
|
|
||||||
struct in_addr src_addr_v4 = {0};
|
|
||||||
struct in_addr dst_addr_v4 = {0};
|
|
||||||
struct in6_addr src_addr_v6 = {0};
|
|
||||||
struct in6_addr dst_addr_v6 = {0};
|
|
||||||
uint16_t src_port = 0;
|
|
||||||
uint16_t dst_port = 0;
|
|
||||||
uint16_t vlan_id = 0;
|
|
||||||
char tmp_src_buff[256] = {0};
|
|
||||||
char tmp_dst_buff[256] = {0};
|
|
||||||
|
|
||||||
int num = packet_get_layer_count(pkt);
|
|
||||||
for (int i = 0; i < num; i++)
|
|
||||||
{
|
|
||||||
memset(tmp_src_buff, 0, sizeof(tmp_src_buff));
|
|
||||||
memset(tmp_dst_buff, 0, sizeof(tmp_dst_buff));
|
|
||||||
const struct raw_layer *layer = packet_get_raw_layer(pkt, i);
|
|
||||||
switch (layer->proto)
|
|
||||||
{
|
|
||||||
case LAYER_PROTO_ETHER:
|
|
||||||
buffer_push(&buff_proto, "eth:ethertype");
|
|
||||||
eth_hdr = (const struct ethhdr *)layer->hdr_ptr;
|
|
||||||
eth_hdr_get_source(eth_hdr, tmp_src_buff, sizeof(tmp_src_buff));
|
|
||||||
eth_hdr_get_dest(eth_hdr, tmp_dst_buff, sizeof(tmp_dst_buff));
|
|
||||||
buffer_push(&buff_eth_src, tmp_src_buff);
|
|
||||||
buffer_push(&buff_eth_dst, tmp_dst_buff);
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_PWETH:
|
|
||||||
buffer_push(&buff_proto, "pwethheuristic:pwethcw");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_PPP:
|
|
||||||
buffer_push(&buff_proto, "ppp");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_L2TP:
|
|
||||||
buffer_push(&buff_proto, "l2tp");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_VLAN:
|
|
||||||
buffer_push(&buff_proto, "vlan:ethertype");
|
|
||||||
vlan_hdr = (const struct vlan_hdr *)layer->hdr_ptr;
|
|
||||||
vlan_id = vlan_hdr_get_vid(vlan_hdr);
|
|
||||||
snprintf(tmp_src_buff, sizeof(tmp_src_buff), "%u", vlan_id);
|
|
||||||
buffer_push(&buff_vlan_id, tmp_src_buff);
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_PPPOE:
|
|
||||||
buffer_push(&buff_proto, "pppoes");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_MPLS:
|
|
||||||
buffer_push(&buff_proto, "mpls");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_IPV4:
|
|
||||||
buffer_push(&buff_proto, "ip");
|
|
||||||
ipv4_hdr = (const struct ip *)layer->hdr_ptr;
|
|
||||||
src_addr_v4 = ipv4_hdr_get_src_in_addr(ipv4_hdr);
|
|
||||||
dst_addr_v4 = ipv4_hdr_get_dst_in_addr(ipv4_hdr);
|
|
||||||
inet_ntop(AF_INET, &src_addr_v4, tmp_src_buff, sizeof(tmp_src_buff));
|
|
||||||
inet_ntop(AF_INET, &dst_addr_v4, tmp_dst_buff, sizeof(tmp_dst_buff));
|
|
||||||
buffer_push(&buff_ipv4_src, tmp_src_buff);
|
|
||||||
buffer_push(&buff_ipv4_dst, tmp_dst_buff);
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_IPV6:
|
|
||||||
buffer_push(&buff_proto, "ipv6");
|
|
||||||
ipv6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
|
|
||||||
switch (ipv6_hdr_get_next_header(ipv6_hdr))
|
|
||||||
{
|
|
||||||
case IPPROTO_HOPOPTS:
|
|
||||||
buffer_push(&buff_proto, "ipv6.hopopts");
|
|
||||||
break;
|
|
||||||
case IPPROTO_ROUTING:
|
|
||||||
buffer_push(&buff_proto, "ipv6.routing");
|
|
||||||
break;
|
|
||||||
case IPPROTO_AH:
|
|
||||||
buffer_push(&buff_proto, "ah");
|
|
||||||
break;
|
|
||||||
case IPPROTO_DSTOPTS:
|
|
||||||
buffer_push(&buff_proto, "ipv6.dstopts");
|
|
||||||
break;
|
|
||||||
case IPPROTO_FRAGMENT:
|
|
||||||
buffer_push(&buff_proto, "ipv6.fraghdr");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
src_addr_v6 = ipv6_hdr_get_src_in6_addr(ipv6_hdr);
|
|
||||||
dst_addr_v6 = ipv6_hdr_get_dst_in6_addr(ipv6_hdr);
|
|
||||||
inet_ntop(AF_INET6, &src_addr_v6, tmp_src_buff, sizeof(tmp_src_buff));
|
|
||||||
inet_ntop(AF_INET6, &dst_addr_v6, tmp_dst_buff, sizeof(tmp_dst_buff));
|
|
||||||
buffer_push(&buff_ipv6_src, tmp_src_buff);
|
|
||||||
buffer_push(&buff_ipv6_dst, tmp_dst_buff);
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_IPAH:
|
|
||||||
buffer_push(&buff_proto, "ah");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_GRE:
|
|
||||||
buffer_push(&buff_proto, "gre");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_UDP:
|
|
||||||
buffer_push(&buff_proto, "udp");
|
|
||||||
udp_hdr = (const struct udphdr *)layer->hdr_ptr;
|
|
||||||
src_port = udp_hdr_get_src_port(udp_hdr);
|
|
||||||
dst_port = udp_hdr_get_dst_port(udp_hdr);
|
|
||||||
snprintf(tmp_src_buff, sizeof(tmp_src_buff), "%u", src_port);
|
|
||||||
snprintf(tmp_dst_buff, sizeof(tmp_dst_buff), "%u", dst_port);
|
|
||||||
buffer_push(&buff_udp_src, tmp_src_buff);
|
|
||||||
buffer_push(&buff_udp_dst, tmp_dst_buff);
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_TCP:
|
|
||||||
buffer_push(&buff_proto, "tcp");
|
|
||||||
tcp_hdr = (const struct tcphdr *)layer->hdr_ptr;
|
|
||||||
src_port = tcp_hdr_get_src_port(tcp_hdr);
|
|
||||||
dst_port = tcp_hdr_get_dst_port(tcp_hdr);
|
|
||||||
snprintf(tmp_src_buff, sizeof(tmp_src_buff), "%u", src_port);
|
|
||||||
snprintf(tmp_dst_buff, sizeof(tmp_dst_buff), "%u", dst_port);
|
|
||||||
buffer_push(&buff_tcp_src, tmp_src_buff);
|
|
||||||
buffer_push(&buff_tcp_dst, tmp_dst_buff);
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_ICMP:
|
|
||||||
buffer_push(&buff_proto, "icmp");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_ICMP6:
|
|
||||||
buffer_push(&buff_proto, "icmpv6");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_VXLAN:
|
|
||||||
buffer_push(&buff_proto, "vxlan");
|
|
||||||
break;
|
|
||||||
case LAYER_PROTO_GTP:
|
|
||||||
buffer_push(&buff_proto, "gtp");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
buffer_push(&buff_proto, "unknown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%lu\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
|
||||||
number,
|
|
||||||
buff_proto.buff,
|
|
||||||
buff_eth_src.buff,
|
|
||||||
buff_eth_dst.buff,
|
|
||||||
buff_vlan_id.buff,
|
|
||||||
buff_ipv4_src.buff,
|
|
||||||
buff_ipv4_dst.buff,
|
|
||||||
buff_ipv6_src.buff,
|
|
||||||
buff_ipv6_dst.buff,
|
|
||||||
buff_tcp_src.buff,
|
|
||||||
buff_tcp_dst.buff,
|
|
||||||
buff_udp_src.buff,
|
|
||||||
buff_udp_dst.buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
|
||||||
{
|
|
||||||
struct options *opts = (struct options *)user;
|
|
||||||
|
|
||||||
struct packet pkt;
|
|
||||||
memset(&pkt, 0, sizeof(pkt));
|
|
||||||
packet_parse(&pkt, (const char *)bytes, h->caplen);
|
|
||||||
number++;
|
|
||||||
|
|
||||||
if (opts->print_readable_format)
|
|
||||||
{
|
|
||||||
printf("\033[0;32m frame=%lu len=%u \033[0m", number, h->caplen);
|
|
||||||
packet_print(&pkt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts->print_tshark_format)
|
|
||||||
{
|
|
||||||
packet_to_tshark_format(&pkt, number);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(char *cmd)
|
|
||||||
{
|
|
||||||
printf("Usage: %s\n", cmd);
|
|
||||||
printf("Options:\n");
|
|
||||||
printf(" -f <pcap file> pcap file\n");
|
|
||||||
printf(" -t print tshark format\n");
|
|
||||||
printf(" -r print readable format\n");
|
|
||||||
printf(" -h print help\n");
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int opt = 0;
|
|
||||||
struct options opts = {0};
|
|
||||||
while ((opt = getopt(argc, argv, "f:trh")) != -1)
|
|
||||||
{
|
|
||||||
switch (opt)
|
|
||||||
{
|
|
||||||
case 'f':
|
|
||||||
opts.file = optarg;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
opts.print_tshark_format = 1;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
opts.print_readable_format = 1;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
default:
|
|
||||||
usage(argv[0]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.file == NULL)
|
|
||||||
{
|
|
||||||
usage(argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcap_t *pcap = pcap_open_offline(opts.file, NULL);
|
|
||||||
if (pcap == NULL)
|
|
||||||
{
|
|
||||||
printf("pcap_open_offline() failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pcap_loop(pcap, -1, packet_handler, (u_char *)&opts);
|
|
||||||
pcap_close(pcap);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
# build packet_parser
|
add_executable(packet_tool packet_tool.cpp)
|
||||||
add_executable(packet_parser packet_parser.cpp)
|
target_link_libraries(packet_tool packet pcap)
|
||||||
target_link_libraries(packet_parser packet pcap)
|
|
||||||
|
|
||||||
file(COPY split_pcap.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
file(COPY split_pcap.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
file(COPY cmp_layers.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
file(COPY cmp_layers.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
@@ -122,8 +122,8 @@ function preprocess_tshark_ouput() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# When MPLS is nested, packet_parser will output multiple mpls fields, and tshark will only output one mpls field, so we need to preprocess the output
|
# When MPLS is nested, packet_tool will output multiple mpls fields, and tshark will only output one mpls field, so we need to preprocess the output
|
||||||
function preprocess_parser_ouput() {
|
function preprocess_tool_ouput() {
|
||||||
input_file=$1
|
input_file=$1
|
||||||
output_file=$2
|
output_file=$2
|
||||||
cp ${input_file} ${output_file}
|
cp ${input_file} ${output_file}
|
||||||
@@ -167,13 +167,13 @@ for pcap in "${pcap_files[@]}"; do
|
|||||||
-e udp.dstport \
|
-e udp.dstport \
|
||||||
>>${tmp_file_dir}/tshark_output.txt
|
>>${tmp_file_dir}/tshark_output.txt
|
||||||
|
|
||||||
# packet_parser output
|
# packet_tool output
|
||||||
./packet_parser -f ${pcap} -t >>${tmp_file_dir}/parser_output.txt
|
./packet_tool -f ${pcap} -t >>${tmp_file_dir}/tool_output.txt
|
||||||
|
|
||||||
# compare tshark and packet_parser output
|
# compare tshark and packet_tool output
|
||||||
preprocess_tshark_ouput ${tmp_file_dir}/tshark_output.txt ${tmp_file_dir}/tshark_format.txt
|
preprocess_tshark_ouput ${tmp_file_dir}/tshark_output.txt ${tmp_file_dir}/tshark_format.txt
|
||||||
preprocess_parser_ouput ${tmp_file_dir}/parser_output.txt ${tmp_file_dir}/parser_format.txt
|
preprocess_tool_ouput ${tmp_file_dir}/tool_output.txt ${tmp_file_dir}/tool_format.txt
|
||||||
diff ${tmp_file_dir}/tshark_format.txt ${tmp_file_dir}/parser_format.txt >>${tmp_file_dir}/diff.txt
|
diff ${tmp_file_dir}/tshark_format.txt ${tmp_file_dir}/tool_format.txt >>${tmp_file_dir}/diff.txt
|
||||||
|
|
||||||
# print result
|
# print result
|
||||||
line_count=$(cat ${tmp_file_dir}/diff.txt | wc -l)
|
line_count=$(cat ${tmp_file_dir}/diff.txt | wc -l)
|
||||||
434
test/packet_tool/packet_tool.cpp
Normal file
434
test/packet_tool/packet_tool.cpp
Normal file
@@ -0,0 +1,434 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <pcap/pcap.h>
|
||||||
|
|
||||||
|
#include "eth_utils.h"
|
||||||
|
#include "vlan_utils.h"
|
||||||
|
#include "ipv4_utils.h"
|
||||||
|
#include "ipv6_utils.h"
|
||||||
|
#include "tcp_utils.h"
|
||||||
|
#include "udp_utils.h"
|
||||||
|
#include "packet_def.h"
|
||||||
|
#include "packet_layer.h"
|
||||||
|
#include "packet_parse.h"
|
||||||
|
#include "packet_utils.h"
|
||||||
|
|
||||||
|
#define MAX_BUFF_SIZE 2048
|
||||||
|
#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__)
|
||||||
|
|
||||||
|
struct str_buff
|
||||||
|
{
|
||||||
|
char data[MAX_BUFF_SIZE];
|
||||||
|
int used;
|
||||||
|
char elimiter;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct runtime
|
||||||
|
{
|
||||||
|
char *pcap_file;
|
||||||
|
uint64_t pcap_count;
|
||||||
|
int tshark_format;
|
||||||
|
int print_verbose;
|
||||||
|
int craft_compare;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void str_buff_push(struct str_buff *buff, const char *str)
|
||||||
|
{
|
||||||
|
int len = strlen(str);
|
||||||
|
if (buff->used + len + 1 >= MAX_BUFF_SIZE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buff->used)
|
||||||
|
{
|
||||||
|
buff->data[buff->used++] = buff->elimiter;
|
||||||
|
}
|
||||||
|
memcpy(buff->data + buff->used, str, len);
|
||||||
|
buff->used += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_pcap(const char *file, const char *data, uint16_t len)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
} pcap_pkt_hdr = {0};
|
||||||
|
|
||||||
|
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_*)
|
||||||
|
} pcap_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)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = fopen(file, "w+");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval ts = {0};
|
||||||
|
gettimeofday(&ts, NULL);
|
||||||
|
|
||||||
|
pcap_pkt_hdr.tv_sec = ts.tv_sec;
|
||||||
|
pcap_pkt_hdr.tv_usec = ts.tv_usec;
|
||||||
|
pcap_pkt_hdr.caplen = len;
|
||||||
|
pcap_pkt_hdr.len = len;
|
||||||
|
|
||||||
|
fwrite(&pcap_file_hdr, sizeof(struct pcap_file_hdr), 1, fp);
|
||||||
|
fwrite(&pcap_pkt_hdr, sizeof(struct pcap_pkt_hdr), 1, fp);
|
||||||
|
fwrite(data, 1, len, fp);
|
||||||
|
fflush(fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tshark_format(const struct runtime *rte, const struct packet *pkt)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
tshark -r ${pcap} -T fields \
|
||||||
|
-e frame.number \
|
||||||
|
-e frame.protocols \
|
||||||
|
-e eth.src \
|
||||||
|
-e eth.dst \
|
||||||
|
-e vlan.id \
|
||||||
|
-e ip.src \
|
||||||
|
-e ip.dst \
|
||||||
|
-e ipv6.src \
|
||||||
|
-e ipv6.dst \
|
||||||
|
-e tcp.srcport \
|
||||||
|
-e tcp.dstport \
|
||||||
|
-e udp.srcport \
|
||||||
|
-e udp.dstport \
|
||||||
|
>> tshark_output.txt
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct str_buff buff_proto = {.data = {0}, .used = 0, .elimiter = ':'};
|
||||||
|
struct str_buff buff_eth_src = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_eth_dst = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_vlan_id = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_ipv4_src = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_ipv4_dst = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_ipv6_src = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_ipv6_dst = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_tcp_src = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_tcp_dst = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_udp_src = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
struct str_buff buff_udp_dst = {.data = {0}, .used = 0, .elimiter = ','};
|
||||||
|
|
||||||
|
const struct ethhdr *eth_hdr = NULL;
|
||||||
|
const struct vlan_hdr *vlan_hdr = NULL;
|
||||||
|
const struct ip *ip4_hdr = NULL;
|
||||||
|
const struct ip6_hdr *ip6_hdr = NULL;
|
||||||
|
const struct tcphdr *tcp_hdr = NULL;
|
||||||
|
const struct udphdr *udp_hdr = NULL;
|
||||||
|
|
||||||
|
struct in_addr src_addr_v4 = {0};
|
||||||
|
struct in_addr dst_addr_v4 = {0};
|
||||||
|
struct in6_addr src_addr_v6 = {0};
|
||||||
|
struct in6_addr dst_addr_v6 = {0};
|
||||||
|
|
||||||
|
uint16_t src_port = 0;
|
||||||
|
uint16_t dst_port = 0;
|
||||||
|
uint16_t vlan_id = 0;
|
||||||
|
|
||||||
|
char tmp_src_buff[256] = {0};
|
||||||
|
char tmp_dst_buff[256] = {0};
|
||||||
|
|
||||||
|
int num = packet_get_layer_count(pkt);
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
memset(tmp_src_buff, 0, sizeof(tmp_src_buff));
|
||||||
|
memset(tmp_dst_buff, 0, sizeof(tmp_dst_buff));
|
||||||
|
const struct raw_layer *layer = packet_get_raw_layer(pkt, i);
|
||||||
|
switch (layer->proto)
|
||||||
|
{
|
||||||
|
case LAYER_PROTO_ETHER:
|
||||||
|
str_buff_push(&buff_proto, "eth:ethertype");
|
||||||
|
|
||||||
|
eth_hdr = (const struct ethhdr *)layer->hdr_ptr;
|
||||||
|
eth_hdr_get_source(eth_hdr, tmp_src_buff, sizeof(tmp_src_buff));
|
||||||
|
eth_hdr_get_dest(eth_hdr, tmp_dst_buff, sizeof(tmp_dst_buff));
|
||||||
|
str_buff_push(&buff_eth_src, tmp_src_buff);
|
||||||
|
str_buff_push(&buff_eth_dst, tmp_dst_buff);
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_PWETH:
|
||||||
|
str_buff_push(&buff_proto, "pwethheuristic:pwethcw");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_PPP:
|
||||||
|
str_buff_push(&buff_proto, "ppp");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_L2TP:
|
||||||
|
str_buff_push(&buff_proto, "l2tp");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_VLAN:
|
||||||
|
str_buff_push(&buff_proto, "vlan:ethertype");
|
||||||
|
|
||||||
|
vlan_hdr = (const struct vlan_hdr *)layer->hdr_ptr;
|
||||||
|
vlan_id = vlan_hdr_get_vid(vlan_hdr);
|
||||||
|
snprintf(tmp_src_buff, sizeof(tmp_src_buff), "%u", vlan_id);
|
||||||
|
str_buff_push(&buff_vlan_id, tmp_src_buff);
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_PPPOE:
|
||||||
|
str_buff_push(&buff_proto, "pppoes");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_MPLS:
|
||||||
|
str_buff_push(&buff_proto, "mpls");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_IPV4:
|
||||||
|
str_buff_push(&buff_proto, "ip");
|
||||||
|
|
||||||
|
ip4_hdr = (const struct ip *)layer->hdr_ptr;
|
||||||
|
src_addr_v4 = ipv4_hdr_get_src_in_addr(ip4_hdr);
|
||||||
|
dst_addr_v4 = ipv4_hdr_get_dst_in_addr(ip4_hdr);
|
||||||
|
inet_ntop(AF_INET, &src_addr_v4, tmp_src_buff, sizeof(tmp_src_buff));
|
||||||
|
inet_ntop(AF_INET, &dst_addr_v4, tmp_dst_buff, sizeof(tmp_dst_buff));
|
||||||
|
str_buff_push(&buff_ipv4_src, tmp_src_buff);
|
||||||
|
str_buff_push(&buff_ipv4_dst, tmp_dst_buff);
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_IPV6:
|
||||||
|
str_buff_push(&buff_proto, "ipv6");
|
||||||
|
ip6_hdr = (const struct ip6_hdr *)layer->hdr_ptr;
|
||||||
|
switch (ipv6_hdr_get_next_header(ip6_hdr))
|
||||||
|
{
|
||||||
|
case IPPROTO_HOPOPTS:
|
||||||
|
str_buff_push(&buff_proto, "ipv6.hopopts");
|
||||||
|
break;
|
||||||
|
case IPPROTO_ROUTING:
|
||||||
|
str_buff_push(&buff_proto, "ipv6.routing");
|
||||||
|
break;
|
||||||
|
case IPPROTO_AH:
|
||||||
|
str_buff_push(&buff_proto, "ah");
|
||||||
|
break;
|
||||||
|
case IPPROTO_DSTOPTS:
|
||||||
|
str_buff_push(&buff_proto, "ipv6.dstopts");
|
||||||
|
break;
|
||||||
|
case IPPROTO_FRAGMENT:
|
||||||
|
str_buff_push(&buff_proto, "ipv6.fraghdr");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
src_addr_v6 = ipv6_hdr_get_src_in6_addr(ip6_hdr);
|
||||||
|
dst_addr_v6 = ipv6_hdr_get_dst_in6_addr(ip6_hdr);
|
||||||
|
inet_ntop(AF_INET6, &src_addr_v6, tmp_src_buff, sizeof(tmp_src_buff));
|
||||||
|
inet_ntop(AF_INET6, &dst_addr_v6, tmp_dst_buff, sizeof(tmp_dst_buff));
|
||||||
|
str_buff_push(&buff_ipv6_src, tmp_src_buff);
|
||||||
|
str_buff_push(&buff_ipv6_dst, tmp_dst_buff);
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_IPAH:
|
||||||
|
str_buff_push(&buff_proto, "ah");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_GRE:
|
||||||
|
str_buff_push(&buff_proto, "gre");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_UDP:
|
||||||
|
str_buff_push(&buff_proto, "udp");
|
||||||
|
|
||||||
|
udp_hdr = (const struct udphdr *)layer->hdr_ptr;
|
||||||
|
src_port = udp_hdr_get_src_port(udp_hdr);
|
||||||
|
dst_port = udp_hdr_get_dst_port(udp_hdr);
|
||||||
|
snprintf(tmp_src_buff, sizeof(tmp_src_buff), "%u", src_port);
|
||||||
|
snprintf(tmp_dst_buff, sizeof(tmp_dst_buff), "%u", dst_port);
|
||||||
|
str_buff_push(&buff_udp_src, tmp_src_buff);
|
||||||
|
str_buff_push(&buff_udp_dst, tmp_dst_buff);
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_TCP:
|
||||||
|
str_buff_push(&buff_proto, "tcp");
|
||||||
|
|
||||||
|
tcp_hdr = (const struct tcphdr *)layer->hdr_ptr;
|
||||||
|
src_port = tcp_hdr_get_src_port(tcp_hdr);
|
||||||
|
dst_port = tcp_hdr_get_dst_port(tcp_hdr);
|
||||||
|
snprintf(tmp_src_buff, sizeof(tmp_src_buff), "%u", src_port);
|
||||||
|
snprintf(tmp_dst_buff, sizeof(tmp_dst_buff), "%u", dst_port);
|
||||||
|
str_buff_push(&buff_tcp_src, tmp_src_buff);
|
||||||
|
str_buff_push(&buff_tcp_dst, tmp_dst_buff);
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_ICMP:
|
||||||
|
str_buff_push(&buff_proto, "icmp");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_ICMP6:
|
||||||
|
str_buff_push(&buff_proto, "icmpv6");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_VXLAN:
|
||||||
|
str_buff_push(&buff_proto, "vxlan");
|
||||||
|
break;
|
||||||
|
case LAYER_PROTO_GTP:
|
||||||
|
str_buff_push(&buff_proto, "gtp");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str_buff_push(&buff_proto, "unknown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%lu\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
|
||||||
|
rte->pcap_count,
|
||||||
|
buff_proto.data,
|
||||||
|
buff_eth_src.data,
|
||||||
|
buff_eth_dst.data,
|
||||||
|
buff_vlan_id.data,
|
||||||
|
buff_ipv4_src.data,
|
||||||
|
buff_ipv4_dst.data,
|
||||||
|
buff_ipv6_src.data,
|
||||||
|
buff_ipv6_dst.data,
|
||||||
|
buff_tcp_src.data,
|
||||||
|
buff_tcp_dst.data,
|
||||||
|
buff_udp_src.data,
|
||||||
|
buff_udp_dst.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void craft_compare(const struct runtime *rte, const struct packet *raw_pkt)
|
||||||
|
{
|
||||||
|
struct layer layers[PACKET_MAX_LAYERS];
|
||||||
|
int layer_count = PACKET_GETALL_LAYERS(raw_pkt, layers);
|
||||||
|
|
||||||
|
struct packet *new_pkt = craft_packet_from_scratch(layers, layer_count, packet_get_payload(raw_pkt), packet_get_payload_len(raw_pkt));
|
||||||
|
if (new_pkt == NULL)
|
||||||
|
{
|
||||||
|
PRINT_RED("craft compare: failed (craft error)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte->print_verbose)
|
||||||
|
{
|
||||||
|
packet_print(new_pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte->tshark_format)
|
||||||
|
{
|
||||||
|
tshark_format(rte, new_pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *raw_pkt_data = packet_get_raw_data(raw_pkt);
|
||||||
|
const char *new_pkt_data = packet_get_raw_data(new_pkt);
|
||||||
|
uint16_t raw_pkt_len = packet_get_raw_len(raw_pkt);
|
||||||
|
uint16_t new_pkt_len = packet_get_raw_len(new_pkt);
|
||||||
|
|
||||||
|
if (raw_pkt_len != new_pkt_len)
|
||||||
|
{
|
||||||
|
PRINT_RED("craft compare: failed (length mismatch)");
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(raw_pkt_data, new_pkt_data, raw_pkt_len) != 0)
|
||||||
|
{
|
||||||
|
PRINT_RED("craft compare: failed (data mismatch)");
|
||||||
|
goto error_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_GREEN("craft compare: success");
|
||||||
|
|
||||||
|
error_out:
|
||||||
|
char file[256] = {0};
|
||||||
|
snprintf(file, sizeof(file), "craft%lu.pcap", rte->pcap_count);
|
||||||
|
dump_pcap(file, new_pkt_data, new_pkt_len);
|
||||||
|
packet_free(new_pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
||||||
|
{
|
||||||
|
struct runtime *rte = (struct runtime *)user;
|
||||||
|
|
||||||
|
struct packet pkt;
|
||||||
|
memset(&pkt, 0, sizeof(pkt));
|
||||||
|
packet_parse(&pkt, (const char *)bytes, h->caplen);
|
||||||
|
rte->pcap_count++;
|
||||||
|
|
||||||
|
if (rte->print_verbose)
|
||||||
|
{
|
||||||
|
PRINT_GREEN("frame=%lu len=%u", rte->pcap_count, h->caplen);
|
||||||
|
packet_print(&pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte->tshark_format)
|
||||||
|
{
|
||||||
|
tshark_format(rte, &pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte->craft_compare)
|
||||||
|
{
|
||||||
|
craft_compare(rte, &pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(char *cmd)
|
||||||
|
{
|
||||||
|
printf("Usage: %s\n", cmd);
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" -f <pcap file> pcap file\n");
|
||||||
|
printf(" -t print tshark format\n");
|
||||||
|
printf(" -v print verbose info\n");
|
||||||
|
printf(" -c compare recrafted packet\n");
|
||||||
|
printf(" -h print help\n");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opt = 0;
|
||||||
|
struct runtime rte = {0};
|
||||||
|
while ((opt = getopt(argc, argv, "f:tvch")) != -1)
|
||||||
|
{
|
||||||
|
switch (opt)
|
||||||
|
{
|
||||||
|
case 'f':
|
||||||
|
rte.pcap_file = optarg;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
rte.tshark_format = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
rte.print_verbose = 1;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
rte.craft_compare = 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte.pcap_file == NULL)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte.print_verbose)
|
||||||
|
{
|
||||||
|
PRINT_GREEN("pcap=%s", rte.pcap_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
pcap_t *pcap = pcap_open_offline(rte.pcap_file, NULL);
|
||||||
|
if (pcap == NULL)
|
||||||
|
{
|
||||||
|
printf("pcap_open_offline() failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pcap_loop(pcap, -1, packet_handler, (u_char *)&rte);
|
||||||
|
pcap_close(pcap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user