Files
c5-project/ESP32-C5-Toolkit/main/pcap_serializer.c
2026-05-03 23:19:51 -07:00

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;
}