146 lines
3.9 KiB
C
146 lines
3.9 KiB
C
/**
|
|
* @file pcap_serializer.c
|
|
* @brief PCAP file serializer implementation
|
|
*
|
|
* Generates PCAP format files compatible with Wireshark and other tools
|
|
*/
|
|
#include "pcap_serializer.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include "esp_log.h"
|
|
|
|
static const char *TAG = "pcap_serializer";
|
|
|
|
// PCAP Constants
|
|
#define PCAP_MAGIC_NUMBER 0xa1b2c3d4
|
|
#define SNAPLEN 65535
|
|
#define LINKTYPE_IEEE802_11 105 // 802.11 wireless
|
|
#define MAX_PCAP_SIZE (512 * 1024) // 512KB limit to prevent memory exhaustion
|
|
|
|
// Buffer management
|
|
static uint8_t *pcap_buffer = NULL;
|
|
static unsigned pcap_size = 0;
|
|
static unsigned packet_count = 0;
|
|
|
|
uint8_t* pcap_serializer_init(void) {
|
|
// Free any existing buffer
|
|
if (pcap_buffer) {
|
|
free(pcap_buffer);
|
|
}
|
|
|
|
// Create global header
|
|
pcap_global_header_t header = {
|
|
.magic_number = PCAP_MAGIC_NUMBER,
|
|
.version_major = 2,
|
|
.version_minor = 4,
|
|
.thiszone = 0,
|
|
.sigfigs = 0,
|
|
.snaplen = SNAPLEN,
|
|
.network = LINKTYPE_IEEE802_11
|
|
};
|
|
|
|
// Allocate buffer for header
|
|
pcap_buffer = malloc(sizeof(pcap_global_header_t));
|
|
if (!pcap_buffer) {
|
|
ESP_LOGE(TAG, "Failed to allocate PCAP buffer");
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(pcap_buffer, &header, sizeof(pcap_global_header_t));
|
|
pcap_size = sizeof(pcap_global_header_t);
|
|
packet_count = 0;
|
|
|
|
ESP_LOGI(TAG, "PCAP serializer initialized");
|
|
return pcap_buffer;
|
|
}
|
|
|
|
void pcap_serializer_append_frame(const uint8_t *buffer, unsigned size, unsigned ts_usec) {
|
|
if (!buffer || size == 0) {
|
|
ESP_LOGD(TAG, "Empty frame, not appending");
|
|
return;
|
|
}
|
|
|
|
if (!pcap_buffer) {
|
|
ESP_LOGW(TAG, "PCAP not initialized, initializing now");
|
|
pcap_serializer_init();
|
|
if (!pcap_buffer) return;
|
|
}
|
|
|
|
// Create record header
|
|
pcap_record_header_t record = {
|
|
.ts_sec = ts_usec / 1000000,
|
|
.ts_usec = ts_usec % 1000000,
|
|
.incl_len = size,
|
|
.orig_len = size
|
|
};
|
|
|
|
// Limit to SNAPLEN
|
|
if (size > SNAPLEN) {
|
|
size = SNAPLEN;
|
|
record.incl_len = SNAPLEN;
|
|
}
|
|
|
|
// Reallocate buffer
|
|
unsigned new_size = pcap_size + sizeof(pcap_record_header_t) + size;
|
|
|
|
// Check if new size exceeds maximum limit
|
|
if (new_size > MAX_PCAP_SIZE) {
|
|
ESP_LOGW(TAG, "PCAP buffer limit reached (%u bytes), dropping frame", MAX_PCAP_SIZE);
|
|
return;
|
|
}
|
|
|
|
uint8_t *new_buffer = realloc(pcap_buffer, new_size);
|
|
if (!new_buffer) {
|
|
ESP_LOGE(TAG, "Failed to reallocate PCAP buffer (size: %u bytes)! PCAP may be incomplete.", new_size);
|
|
// Optionally: Could implement packet dropping strategy here (FIFO)
|
|
return;
|
|
}
|
|
|
|
// Append record header and data
|
|
memcpy(new_buffer + pcap_size, &record, sizeof(pcap_record_header_t));
|
|
memcpy(new_buffer + pcap_size + sizeof(pcap_record_header_t), buffer, size);
|
|
|
|
pcap_buffer = new_buffer;
|
|
pcap_size = new_size;
|
|
packet_count++;
|
|
|
|
ESP_LOGD(TAG, "Appended frame: %u bytes (total: %u bytes, %u packets)",
|
|
size, pcap_size, packet_count);
|
|
}
|
|
|
|
void pcap_serializer_deinit(void) {
|
|
if (pcap_buffer) {
|
|
free(pcap_buffer);
|
|
pcap_buffer = NULL;
|
|
}
|
|
pcap_size = 0;
|
|
packet_count = 0;
|
|
ESP_LOGI(TAG, "PCAP serializer deinitialized");
|
|
}
|
|
|
|
unsigned pcap_serializer_get_size(void) {
|
|
return pcap_size;
|
|
}
|
|
|
|
uint8_t* pcap_serializer_get_buffer(void) {
|
|
return pcap_buffer;
|
|
}
|
|
|
|
void pcap_serializer_reset(void) {
|
|
// Keep just the global header
|
|
if (pcap_buffer && pcap_size > sizeof(pcap_global_header_t)) {
|
|
uint8_t *new_buffer = realloc(pcap_buffer, sizeof(pcap_global_header_t));
|
|
if (new_buffer) {
|
|
pcap_buffer = new_buffer;
|
|
}
|
|
}
|
|
pcap_size = sizeof(pcap_global_header_t);
|
|
packet_count = 0;
|
|
ESP_LOGI(TAG, "PCAP buffer reset");
|
|
}
|
|
|
|
unsigned pcap_serializer_get_packet_count(void) {
|
|
return packet_count;
|
|
}
|