diff --git a/src/packet/CMakeLists.txt b/src/packet/CMakeLists.txt index a86d537..32388f0 100644 --- a/src/packet/CMakeLists.txt +++ b/src/packet/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(packet packet_parse.cpp packet_build.cpp packet_utils.cpp packet_ldbc.cpp packet_layer.cpp packet_tunnel.cpp checksum.cpp) +add_library(packet packet_parse.cpp packet_build.cpp packet_dump.cpp packet_utils.cpp packet_ldbc.cpp packet_layer.cpp packet_tunnel.cpp checksum.cpp) target_include_directories(packet PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/deps/uthash) target_include_directories(packet PUBLIC ${CMAKE_SOURCE_DIR}/include) diff --git a/src/packet/packet_dump.cpp b/src/packet/packet_dump.cpp new file mode 100644 index 0000000..9de3e9b --- /dev/null +++ b/src/packet/packet_dump.cpp @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include + +#include "log.h" +#include "packet_dump.h" + +#define PACKET_DUMP_LOG_ERROR(format, ...) LOG_ERROR("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(const char *file, const char *data, uint16_t len) +{ + struct pcap_pkt_hdr pkt_hdr = {0}; + 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 = {0}; + 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; +} diff --git a/src/packet/packet_dump.h b/src/packet/packet_dump.h new file mode 100644 index 0000000..68ed69e --- /dev/null +++ b/src/packet/packet_dump.h @@ -0,0 +1,16 @@ +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +// return 0: success +// return -1: failed +int packet_dump(const char *file, const char *data, uint16_t len); + +#ifdef __cplusplus +} +#endif diff --git a/src/packet_io/dumpfile_io.cpp b/src/packet_io/dumpfile_io.cpp index 3b76c75..c43c89f 100644 --- a/src/packet_io/dumpfile_io.cpp +++ b/src/packet_io/dumpfile_io.cpp @@ -17,6 +17,7 @@ #include "packet_ldbc.h" #include "packet_utils.h" #include "packet_parse.h" +#include "packet_dump.h" #include "lock_free_queue.h" #define PACKET_IO_LOG_STATE(format, ...) LOG_STATE("dumpfile", format, ##__VA_ARGS__) @@ -44,90 +45,10 @@ struct pcap_pkt int len; }; -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_*) -}; - -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 DEFAULT_PCAP_FILE_HDR = - { - .magic = 0xA1B2C3D4, - .version_major = 0x0002, - .version_minor = 0x0004, - .thiszone = 0, - .sigfigs = 0, - .snaplen = 0xFFFF, - .linktype = 1}; - /****************************************************************************** * Private API ******************************************************************************/ -static void save_packet(const char *work_dir, struct packet *pkt, uint64_t idx) -{ - int len = 0; - FILE *fp = NULL; - struct tuple6 tuple; - struct timeval ts = {0}; - struct pcap_pkt_hdr pcap_hdr = {0}; - - char file[256] = {0}; - char src_addr[INET6_ADDRSTRLEN] = {0}; - char dst_addr[INET6_ADDRSTRLEN] = {0}; - - len = packet_get_raw_len(pkt); - memset(&tuple, 0, sizeof(struct tuple6)); - packet_get_innermost_tuple6(pkt, &tuple); - - if (tuple.ip_type == IP_TYPE_V4) - { - inet_ntop(AF_INET, &tuple.src_addr.v4, src_addr, INET6_ADDRSTRLEN); - inet_ntop(AF_INET, &tuple.dst_addr.v4, dst_addr, INET6_ADDRSTRLEN); - } - else - { - inet_ntop(AF_INET6, &tuple.src_addr.v6, src_addr, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, &tuple.dst_addr.v6, dst_addr, INET6_ADDRSTRLEN); - } - snprintf(file, sizeof(file), "%s/inject-%s:%u-%s:%u-%lu.pcap", work_dir, src_addr, ntohs(tuple.src_port), dst_addr, ntohs(tuple.dst_port), idx); - - fp = fopen(file, "w+"); - if (fp) - { - gettimeofday(&ts, NULL); - pcap_hdr.tv_sec = ts.tv_sec; - pcap_hdr.tv_usec = ts.tv_usec; - - pcap_hdr.caplen = len; - pcap_hdr.len = len; - - fwrite(&DEFAULT_PCAP_FILE_HDR, sizeof(DEFAULT_PCAP_FILE_HDR), 1, fp); - fwrite(&pcap_hdr, sizeof(struct pcap_pkt_hdr), 1, fp); - fwrite(packet_get_raw_data(pkt), 1, len, fp); - fflush(fp); - fclose(fp); - PACKET_IO_LOG_STATE("save packet to %s", file); - } - else - { - PACKET_IO_LOG_ERROR("unable to write pcap file: %s, %s", file, strerror(errno)); - } -} - typedef int file_handle(const char *file, void *arg); static int scan_directory(const char *dir, file_handle *handler, void *arg) @@ -464,14 +385,21 @@ void dumpfile_io_drop(struct dumpfile_io *handle, uint16_t thr_idx, struct packe int dumpfile_io_inject(struct dumpfile_io *handle, uint16_t thr_idx, struct packet *pkts, int nr_pkts) { - int len; + uint16_t len; struct packet *pkt = NULL; struct packet_io_stat *stat = &handle->stat[thr_idx]; + struct tuple6 tuple; + + const char *data; + char file[1024] = {0}; + char src_addr[INET6_ADDRSTRLEN] = {0}; + char dst_addr[INET6_ADDRSTRLEN] = {0}; for (int i = 0; i < nr_pkts; i++) { pkt = &pkts[i]; len = packet_get_raw_len(pkt); + data = packet_get_raw_data(pkt); stat->inject_pkts++; stat->inject_bytes += len; @@ -482,8 +410,29 @@ int dumpfile_io_inject(struct dumpfile_io *handle, uint16_t thr_idx, struct pack stat->dev_tx_pkts++; stat->dev_tx_bytes += len; - save_packet(handle->work_dir, pkt, stat->inject_pkts); + memset(&tuple, 0, sizeof(struct tuple6)); + packet_get_innermost_tuple6(pkt, &tuple); + if (tuple.ip_type == IP_TYPE_V4) + { + inet_ntop(AF_INET, &tuple.src_addr.v4, src_addr, INET6_ADDRSTRLEN); + inet_ntop(AF_INET, &tuple.dst_addr.v4, dst_addr, INET6_ADDRSTRLEN); + } + else + { + inet_ntop(AF_INET6, &tuple.src_addr.v6, src_addr, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &tuple.dst_addr.v6, dst_addr, INET6_ADDRSTRLEN); + } + snprintf(file, sizeof(file), "%s/inject-%s:%u-%s:%u-%lu.pcap", handle->work_dir, src_addr, ntohs(tuple.src_port), dst_addr, ntohs(tuple.dst_port), stat->inject_pkts); + + if (packet_dump(file, data, len) == -1) + { + PACKET_IO_LOG_ERROR("unable to dump pcap file: %s", file); + } + else + { + PACKET_IO_LOG_STATE("dump inject packet: %s", file); + } packet_free(pkt); } diff --git a/test/packet_tool/packet_tool.cpp b/test/packet_tool/packet_tool.cpp index e1ec6d3..e51d8cf 100644 --- a/test/packet_tool/packet_tool.cpp +++ b/test/packet_tool/packet_tool.cpp @@ -10,6 +10,7 @@ #include "packet_def.h" #include "packet_layer.h" #include "packet_parse.h" +#include "packet_dump.h" #include "packet_utils.h" #define MAX_BUFF_SIZE 2048 @@ -47,60 +48,6 @@ static void str_buff_push(struct str_buff *buff, const char *str) 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) { /* @@ -341,7 +288,7 @@ static void craft_compare(const struct runtime *rte, const struct packet *raw_pk 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_dump(file, new_pkt_data, new_pkt_len); packet_free(new_pkt); }