Enhanced packet_parser tools
This commit is contained in:
@@ -2,119 +2,222 @@
|
||||
#include <pcap/pcap.h>
|
||||
#include "ipv6_utils.h"
|
||||
#include "packet_priv.h"
|
||||
#include "eth_utils.h"
|
||||
#include "ipv4_utils.h"
|
||||
#include "ipv6_utils.h"
|
||||
#include "tcp_utils.h"
|
||||
#include "udp_utils.h"
|
||||
|
||||
struct options
|
||||
{
|
||||
char *file;
|
||||
int print_proto;
|
||||
int print_summary;
|
||||
int print_tshark_format;
|
||||
int print_readable_format;
|
||||
};
|
||||
|
||||
static uint64_t number = 0;
|
||||
|
||||
static int ipv6_proto_to_str(const struct packet_layer *ipv6_layer, char *buff, int size)
|
||||
#define MAX_BUFF_SIZE 2048
|
||||
struct buffer
|
||||
{
|
||||
int used = snprintf(buff, size, "ipv6");
|
||||
uint8_t next_hdr = ipv6_hdr_get_next_header((const struct ip6_hdr *)ipv6_layer->hdr_ptr);
|
||||
switch (next_hdr)
|
||||
{
|
||||
case IPPROTO_HOPOPTS:
|
||||
used += snprintf(buff + used, size - used, ":ipv6.hopopts");
|
||||
break;
|
||||
case IPPROTO_ROUTING:
|
||||
used += snprintf(buff + used, size - used, ":ipv6.routing");
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
used += snprintf(buff + used, size - used, ":ah");
|
||||
break;
|
||||
case IPPROTO_DSTOPTS:
|
||||
used += snprintf(buff + used, size - used, ":ipv6.dstopts");
|
||||
break;
|
||||
case IPPROTO_FRAGMENT:
|
||||
used += snprintf(buff + used, size - used, ":ipv6.fraghdr");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
char buff[MAX_BUFF_SIZE];
|
||||
int used;
|
||||
char elimiter;
|
||||
};
|
||||
|
||||
return used;
|
||||
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 int packet_proto_to_str(const struct packet *pkt, char *buff, int size)
|
||||
static void packet_to_tshark_format(const struct packet *pkt, uint64_t idx)
|
||||
{
|
||||
int used = 0;
|
||||
/*
|
||||
tshark -r ${pcap} -T fields \
|
||||
-e frame.number \
|
||||
-e frame.protocols \
|
||||
-e eth.src \
|
||||
-e eth.dst \
|
||||
-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_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 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;
|
||||
char tmp_src_buff[256] = {0};
|
||||
char tmp_dst_buff[256] = {0};
|
||||
|
||||
int8_t num = packet_get_layers_number(pkt);
|
||||
for (int8_t 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 packet_layer *layer = packet_get_layer(pkt, i);
|
||||
switch (layer->type)
|
||||
{
|
||||
case LAYER_TYPE_ETHER:
|
||||
used += snprintf(buff + used, size - used, "eth:ethertype");
|
||||
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_TYPE_PWETH:
|
||||
used += snprintf(buff + used, size - used, "pwethheuristic:pwethcw");
|
||||
buffer_push(&buff_proto, "pwethheuristic:pwethcw");
|
||||
break;
|
||||
case LAYER_TYPE_PPP:
|
||||
used += snprintf(buff + used, size - used, "ppp");
|
||||
buffer_push(&buff_proto, "ppp");
|
||||
break;
|
||||
case LAYER_TYPE_HDLC:
|
||||
used += snprintf(buff + used, size - used, "hdlc");
|
||||
buffer_push(&buff_proto, "hdlc");
|
||||
break;
|
||||
case LAYER_TYPE_L2TP:
|
||||
used += snprintf(buff + used, size - used, "l2tp");
|
||||
buffer_push(&buff_proto, "l2tp");
|
||||
break;
|
||||
case LAYER_TYPE_VLAN:
|
||||
used += snprintf(buff + used, size - used, "vlan:ethertype");
|
||||
buffer_push(&buff_proto, "vlan:ethertype");
|
||||
break;
|
||||
case LAYER_TYPE_PPPOE:
|
||||
used += snprintf(buff + used, size - used, "pppoes");
|
||||
buffer_push(&buff_proto, "pppoes");
|
||||
break;
|
||||
case LAYER_TYPE_MPLS:
|
||||
used += snprintf(buff + used, size - used, "mpls");
|
||||
buffer_push(&buff_proto, "mpls");
|
||||
break;
|
||||
case LAYER_TYPE_IPV4:
|
||||
used += snprintf(buff + used, size - used, "ip");
|
||||
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_TYPE_IPV6:
|
||||
used += ipv6_proto_to_str(layer, buff + used, size - used);
|
||||
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_TYPE_IPAH:
|
||||
used += snprintf(buff + used, size - used, "ah");
|
||||
buffer_push(&buff_proto, "ah");
|
||||
break;
|
||||
case LAYER_TYPE_GRE:
|
||||
used += snprintf(buff + used, size - used, "gre");
|
||||
buffer_push(&buff_proto, "gre");
|
||||
break;
|
||||
case LAYER_TYPE_UDP:
|
||||
used += snprintf(buff + used, size - used, "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_TYPE_TCP:
|
||||
used += snprintf(buff + used, size - used, "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_TYPE_ICMP:
|
||||
used += snprintf(buff + used, size - used, "icmp");
|
||||
buffer_push(&buff_proto, "icmp");
|
||||
break;
|
||||
case LAYER_TYPE_ICMP6:
|
||||
used += snprintf(buff + used, size - used, "icmpv6");
|
||||
buffer_push(&buff_proto, "icmpv6");
|
||||
break;
|
||||
case LAYER_TYPE_VXLAN:
|
||||
used += snprintf(buff + used, size - used, "vxlan");
|
||||
buffer_push(&buff_proto, "vxlan");
|
||||
break;
|
||||
case LAYER_TYPE_GTPV1_U:
|
||||
used += snprintf(buff + used, size - used, "gtp");
|
||||
buffer_push(&buff_proto, "gtp");
|
||||
break;
|
||||
default:
|
||||
used += snprintf(buff + used, size - used, "unknown");
|
||||
buffer_push(&buff_proto, "unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != num - 1)
|
||||
{
|
||||
used += snprintf(buff + used, size - used, ":");
|
||||
}
|
||||
}
|
||||
|
||||
return used;
|
||||
printf("%lu\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_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)
|
||||
@@ -125,17 +228,15 @@ static void packet_handler(u_char *user, const struct pcap_pkthdr *h, const u_ch
|
||||
packet_parse(&pkt, (const char *)bytes, h->caplen);
|
||||
number++;
|
||||
|
||||
if (opts->print_summary)
|
||||
if (opts->print_readable_format)
|
||||
{
|
||||
printf("\033[0;32m frame=%lu len=%u \033[0m", number, h->caplen);
|
||||
packet_print_str(&pkt);
|
||||
}
|
||||
|
||||
if (opts->print_proto)
|
||||
if (opts->print_tshark_format)
|
||||
{
|
||||
char buff[1024] = {0};
|
||||
packet_proto_to_str(&pkt, buff, sizeof(buff));
|
||||
printf("%lu %s\n", number, buff);
|
||||
packet_to_tshark_format(&pkt, number);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,8 +245,8 @@ static void usage(char *cmd)
|
||||
printf("Usage: %s\n", cmd);
|
||||
printf("Options:\n");
|
||||
printf(" -f <pcap file> pcap file\n");
|
||||
printf(" -p print protocol\n");
|
||||
printf(" -s print summary\n");
|
||||
printf(" -t print tshark format\n");
|
||||
printf(" -r print readable format\n");
|
||||
printf(" -h print help\n");
|
||||
printf("\n");
|
||||
}
|
||||
@@ -154,18 +255,18 @@ int main(int argc, char **argv)
|
||||
{
|
||||
int opt = 0;
|
||||
struct options opts = {0};
|
||||
while ((opt = getopt(argc, argv, "f:psh")) != -1)
|
||||
while ((opt = getopt(argc, argv, "f:trh")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'f':
|
||||
opts.file = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
opts.print_proto = 1;
|
||||
case 't':
|
||||
opts.print_tshark_format = 1;
|
||||
break;
|
||||
case 's':
|
||||
opts.print_summary = 1;
|
||||
case 'r':
|
||||
opts.print_readable_format = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user