/** * @file pcap_serializer.c * @brief PCAP file serializer implementation * * Generates PCAP format files compatible with Wireshark and other tools */ #include "pcap_serializer.h" #include #include #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; }