mirror of
https://github.com/pavel-odintsov/fastnetmon.git
synced 2024-09-21 02:17:16 +00:00
Reworked pcap format to make it more cross platform and make it more ideomatic C++
This commit is contained in:
parent
a34c9b6c9f
commit
e376abaeed
@ -1,5 +1,5 @@
|
||||
#include "fastnetmon_pcap_format.hpp"
|
||||
#include <errno.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_parse_packet_function_ptr) {
|
||||
@ -10,10 +10,10 @@ int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_par
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct fastnetmon_pcap_file_header pcap_header;
|
||||
ssize_t file_header_readed_bytes = read(filedesc, &pcap_header, sizeof(struct fastnetmon_pcap_file_header));
|
||||
fastnetmon_pcap_file_header_t pcap_header{};
|
||||
ssize_t file_header_readed_bytes = read(filedesc, &pcap_header, sizeof(fastnetmon_pcap_file_header_t));
|
||||
|
||||
if (file_header_readed_bytes != sizeof(struct fastnetmon_pcap_file_header)) {
|
||||
if (file_header_readed_bytes != sizeof(fastnetmon_pcap_file_header_t)) {
|
||||
printf("Can't read pcap file header");
|
||||
}
|
||||
|
||||
@ -31,16 +31,17 @@ int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_par
|
||||
unsigned int read_packets = 0;
|
||||
while (1) {
|
||||
// printf("Start packet %d processing\n", read_packets);
|
||||
struct fastnetmon_pcap_pkthdr pcap_packet_header;
|
||||
ssize_t packet_header_readed_bytes = read(filedesc, &pcap_packet_header, sizeof(struct fastnetmon_pcap_pkthdr));
|
||||
fastnetmon_pcap_pkthdr_t pcap_packet_header;
|
||||
ssize_t packet_header_readed_bytes = read(filedesc, &pcap_packet_header, sizeof(fastnetmon_pcap_pkthdr_t));
|
||||
|
||||
if (packet_header_readed_bytes != sizeof(struct fastnetmon_pcap_pkthdr)) {
|
||||
if (packet_header_readed_bytes != sizeof(fastnetmon_pcap_pkthdr_t)) {
|
||||
// We haven't any packets
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcap_packet_header.incl_len > pcap_header.snaplen) {
|
||||
printf("Please enlarge packet buffer! We got packet with size: %d but our buffer is %d "
|
||||
printf("Please enlarge packet buffer! We got packet with size: %d but "
|
||||
"our buffer is %d "
|
||||
"bytes\n",
|
||||
pcap_packet_header.incl_len, pcap_header.snaplen);
|
||||
return -4;
|
||||
@ -65,13 +66,15 @@ int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_par
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool fill_pcap_header(struct fastnetmon_pcap_file_header* pcap_header, bpf_u_int32 snap_length) {
|
||||
// Move this code to constructor
|
||||
bool fill_pcap_header(fastnetmon_pcap_file_header_t* pcap_header, uint32_t snap_length) {
|
||||
pcap_header->magic = 0xa1b2c3d4;
|
||||
pcap_header->version_major = 2;
|
||||
pcap_header->version_minor = 4;
|
||||
pcap_header->thiszone = 0;
|
||||
pcap_header->sigfigs = 0;
|
||||
// TODO: fix this!!!
|
||||
|
||||
// Maximum really captured (not original packet) length for this file
|
||||
pcap_header->snaplen = snap_length;
|
||||
// http://www.tcpdump.org/linktypes.html
|
||||
// DLT_EN10MB = 1
|
||||
|
@ -1,68 +1,170 @@
|
||||
#ifndef FASTNETMON_PCAP_FORMAT_H
|
||||
#define FASTNETMON_PCAP_FORMAT_H
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <log4cpp/Appender.hh>
|
||||
#include <log4cpp/BasicLayout.hh>
|
||||
#include <log4cpp/Category.hh>
|
||||
#include <log4cpp/FileAppender.hh>
|
||||
#include <log4cpp/Layout.hh>
|
||||
#include <log4cpp/OstreamAppender.hh>
|
||||
#include <log4cpp/PatternLayout.hh>
|
||||
#include <log4cpp/Priority.hh>
|
||||
|
||||
#include "fastnetmon_simple_packet.hpp"
|
||||
|
||||
/*
|
||||
pcap dump format:
|
||||
global header: struct pcap_file_header
|
||||
packet header: struct fastnetmon_pcap_pkthdr
|
||||
global header: pcap_file_header
|
||||
packet header: fastnetmon_pcap_pkthdr_t
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compatibility for systems that have a bpf.h that
|
||||
* predates the bpf typedefs for 64-bit support.
|
||||
*/
|
||||
#if BPF_RELEASE - 0 < 199406
|
||||
typedef int bpf_int32;
|
||||
typedef u_int bpf_u_int32;
|
||||
#endif
|
||||
|
||||
// We use copy and paste from pcap.h here because we do not want to link with pcap here
|
||||
struct fastnetmon_pcap_file_header {
|
||||
bpf_u_int32 magic;
|
||||
u_short version_major;
|
||||
u_short version_minor;
|
||||
bpf_int32 thiszone; /* gmt to local correction */
|
||||
bpf_u_int32 sigfigs; /* accuracy of timestamps */
|
||||
bpf_u_int32 snaplen; /* max length saved portion of each pkt */
|
||||
bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
|
||||
// We use copy and paste from pcap.h here because we do not want to link with
|
||||
// pcap here
|
||||
class __attribute__((__packed__)) fastnetmon_pcap_file_header_t {
|
||||
public:
|
||||
uint32_t magic = 0;
|
||||
uint16_t version_major = 0;
|
||||
uint16_t version_minor = 0;
|
||||
int32_t thiszone = 0; /* gmt to local correction */
|
||||
uint32_t sigfigs = 0; /* accuracy of timestamps */
|
||||
uint32_t snaplen = 0; /* max length saved portion of each pkt */
|
||||
uint32_t linktype = 0; /* data link type (LINKTYPE_*) */
|
||||
};
|
||||
|
||||
/*
|
||||
TODO: move to this code, get rid any bpf* custom types
|
||||
struct fastnetmon_pcap_file_header {
|
||||
uint32_t magic;
|
||||
uint16_t version_major;
|
||||
uint16_t version_minor;
|
||||
int32_t thiszone;
|
||||
uint32_t sigfigs;
|
||||
uint32_t snaplen;
|
||||
uint32_t linktype;
|
||||
};
|
||||
*/
|
||||
static_assert(sizeof(fastnetmon_pcap_file_header_t) == 24, "Bad size for fastnetmon_pcap_file_header_t");
|
||||
|
||||
// Link types for PCAP which we use in FastNetMon
|
||||
#define FASTNETMON_PCAP_LINKTYPE_ETHERNET 1
|
||||
#define FASTNETMON_PCAP_LINKTYPE_LINUX_SLL 113
|
||||
|
||||
// We can't use pcap_pkthdr from upstream because it uses 16 bytes timeval instead of 8 byte and
|
||||
// We can't use pcap_pkthdr from upstream because it uses 16 bytes timeval
|
||||
// instead of 8 byte and
|
||||
// broke everything
|
||||
struct fastnetmon_pcap_pkthdr {
|
||||
uint32_t ts_sec; /* timestamp seconds */
|
||||
uint32_t ts_usec; /* timestamp microseconds */
|
||||
uint32_t incl_len; /* number of octets of packet saved in file */
|
||||
uint32_t orig_len; /* actual length of packet */
|
||||
class __attribute__((__packed__)) fastnetmon_pcap_pkthdr_t {
|
||||
public:
|
||||
uint32_t ts_sec = 0; /* timestamp seconds */
|
||||
uint32_t ts_usec = 0; /* timestamp microseconds */
|
||||
uint32_t incl_len = 0; /* number of octets of packet saved in file */
|
||||
uint32_t orig_len = 0; /* actual length of packet */
|
||||
};
|
||||
|
||||
static_assert(sizeof(fastnetmon_pcap_pkthdr_t) == 16, "Bad size for fastnetmon_pcap_pkthdr_t");
|
||||
|
||||
|
||||
// This class consist of pcap header and payload in same place
|
||||
class pcap_packet_information_t {
|
||||
public:
|
||||
uint32_t ts_sec = 0; /* timestamp seconds */
|
||||
uint32_t ts_usec = 0; /* timestamp microseconds */
|
||||
|
||||
uint32_t incl_len = 0;
|
||||
uint32_t orig_len = 0;
|
||||
char* data_pointer = nullptr;
|
||||
};
|
||||
|
||||
typedef void (*pcap_packet_parser_callback)(char* buffer, uint32_t len, uint32_t snaplen);
|
||||
|
||||
int pcap_reader(const char* pcap_file_path, pcap_packet_parser_callback pcap_parse_packet_function_ptr);
|
||||
|
||||
bool fill_pcap_header(struct fastnetmon_pcap_file_header* pcap_header, bpf_u_int32 snap_length);
|
||||
bool fill_pcap_header(fastnetmon_pcap_file_header_t* pcap_header, uint32_t snap_length);
|
||||
|
||||
#endif
|
||||
// Class for very convenient pcap file reading
|
||||
class pcap_roller_t {
|
||||
public:
|
||||
pcap_roller_t(const std::string& pcap_file_path) {
|
||||
this->pcap_file_path = pcap_file_path;
|
||||
}
|
||||
|
||||
~pcap_roller_t() {
|
||||
if (filedesc > 0) {
|
||||
close(filedesc);
|
||||
}
|
||||
|
||||
if (packet_buffer) {
|
||||
free(packet_buffer);
|
||||
packet_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool open() {
|
||||
extern log4cpp::Category& logger;
|
||||
|
||||
filedesc = ::open(pcap_file_path.c_str(), O_RDONLY);
|
||||
|
||||
if (filedesc <= 0) {
|
||||
logger << log4cpp::Priority::ERROR << "Can't open dump file, error: " << strerror(errno);
|
||||
return false;
|
||||
}
|
||||
|
||||
ssize_t file_header_readed_bytes = read(filedesc, &pcap_header, sizeof(fastnetmon_pcap_file_header_t));
|
||||
|
||||
if (file_header_readed_bytes != sizeof(fastnetmon_pcap_file_header_t)) {
|
||||
logger << log4cpp::Priority::ERROR << "Can't read pcap file header";
|
||||
return false;
|
||||
}
|
||||
|
||||
// http://www.tcpdump.org/manpages/pcap-savefile.5.html
|
||||
if (!(pcap_header.magic == 0xa1b2c3d4 or pcap_header.magic == 0xd4c3b2a1)) {
|
||||
logger << log4cpp::Priority::ERROR << "Magic in file header broken";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate read buffer
|
||||
packet_buffer = (char*)malloc(pcap_header.snaplen);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read on more packet from stream and returns false if we run out of packets
|
||||
bool read_next(pcap_packet_information_t& pcap_packet_information) {
|
||||
extern log4cpp::Category& logger;
|
||||
|
||||
fastnetmon_pcap_pkthdr_t pcap_packet_header;
|
||||
ssize_t packet_header_readed_bytes = read(filedesc, &pcap_packet_header, sizeof(fastnetmon_pcap_pkthdr_t));
|
||||
|
||||
if (packet_header_readed_bytes != sizeof(fastnetmon_pcap_pkthdr_t)) {
|
||||
// We have no more packets to read
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pcap_packet_header.incl_len > pcap_header.snaplen) {
|
||||
logger << log4cpp::Priority::ERROR << "Captured packet size for this dump exceed limit for pcap file";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read included part of raw packet from file
|
||||
ssize_t packet_payload_readed_bytes = read(filedesc, packet_buffer, pcap_packet_header.incl_len);
|
||||
|
||||
if (pcap_packet_header.incl_len != packet_payload_readed_bytes) {
|
||||
logger << log4cpp::Priority::ERROR << "We successfully read packet header but can't read packet payload";
|
||||
return false;
|
||||
}
|
||||
|
||||
pcap_packet_information.incl_len = pcap_packet_header.incl_len;
|
||||
pcap_packet_information.orig_len = pcap_packet_header.orig_len;
|
||||
pcap_packet_information.ts_sec = pcap_packet_header.ts_sec;
|
||||
pcap_packet_information.ts_usec = pcap_packet_header.ts_usec;
|
||||
pcap_packet_information.data_pointer = packet_buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
fastnetmon_pcap_file_header_t pcap_header{};
|
||||
|
||||
private:
|
||||
std::string pcap_file_path = "";
|
||||
int filedesc = 0;
|
||||
char* packet_buffer = nullptr;
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ class fixed_size_packet_storage_t {
|
||||
}
|
||||
|
||||
// Some useful information about this packet
|
||||
fastnetmon_pcap_pkthdr packet_metadata;
|
||||
fastnetmon_pcap_pkthdr_t packet_metadata;
|
||||
|
||||
// Packet itself. Let's zeroify packet payload
|
||||
uint8_t packet_payload[2048] = {};
|
||||
|
@ -22,7 +22,7 @@ class packet_storage_t {
|
||||
|
||||
bool allocate_buffer(unsigned int buffer_size_in_packets) {
|
||||
unsigned int memory_size_in_bytes =
|
||||
buffer_size_in_packets * (max_captured_packet_size + sizeof(fastnetmon_pcap_pkthdr)) + sizeof(fastnetmon_pcap_file_header);
|
||||
buffer_size_in_packets * (max_captured_packet_size + sizeof(fastnetmon_pcap_pkthdr_t)) + sizeof(fastnetmon_pcap_file_header_t);
|
||||
|
||||
// std::cout << "We will allocate " << memory_size_in_bytes << std::endl;
|
||||
|
||||
@ -62,7 +62,7 @@ class packet_storage_t {
|
||||
gettimeofday(¤t_time, NULL);
|
||||
}
|
||||
|
||||
fastnetmon_pcap_pkthdr pcap_packet_header;
|
||||
fastnetmon_pcap_pkthdr_t pcap_packet_header;
|
||||
|
||||
pcap_packet_header.ts_sec = current_time.tv_sec;
|
||||
pcap_packet_header.ts_usec = current_time.tv_usec;
|
||||
@ -93,7 +93,7 @@ class packet_storage_t {
|
||||
}
|
||||
|
||||
bool write_header() {
|
||||
struct fastnetmon_pcap_file_header pcap_header;
|
||||
fastnetmon_pcap_file_header_t pcap_header;
|
||||
|
||||
fill_pcap_header(&pcap_header, max_captured_packet_size);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user