mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-03 22:08:28 +00:00 
			
		
		
		
	Based on app-trace component, it's able to send sniffer packets to host via JTAG interface.
		
			
				
	
	
		
			139 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/unistd.h>
 | 
						|
#include <sys/fcntl.h>
 | 
						|
#include "esp_types.h"
 | 
						|
#include "esp_err.h"
 | 
						|
#include "esp_log.h"
 | 
						|
#include "pcap.h"
 | 
						|
 | 
						|
static const char *PCAP_TAG = "pcap";
 | 
						|
#define PCAP_CHECK(a, str, goto_tag, ...)                                              \
 | 
						|
    do                                                                                 \
 | 
						|
    {                                                                                  \
 | 
						|
        if (!(a))                                                                      \
 | 
						|
        {                                                                              \
 | 
						|
            ESP_LOGE(PCAP_TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
 | 
						|
            goto goto_tag;                                                             \
 | 
						|
        }                                                                              \
 | 
						|
    } while (0)
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Pcap File Header
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct {
 | 
						|
    uint32_t magic;     /*!< Magic Number */
 | 
						|
    uint16_t major;     /*!< Major Version */
 | 
						|
    uint16_t minor;     /*!< Minor Version */
 | 
						|
    uint32_t zone;      /*!< Time Zone Offset */
 | 
						|
    uint32_t sigfigs;   /*!< Timestamp Accuracy */
 | 
						|
    uint32_t snaplen;   /*!< Max Length to Capture */
 | 
						|
    uint32_t link_type; /*!< Link Layer Type */
 | 
						|
} pcap_file_header_t;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Pcap Packet Header
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct {
 | 
						|
    uint32_t seconds;        /*!< Number of seconds since January 1st, 1970, 00:00:00 GMT */
 | 
						|
    uint32_t microseconds;   /*!< Number of microseconds when the packet was captured (offset from seconds) */
 | 
						|
    uint32_t capture_length; /*!< Number of bytes of captured data, no longer than packet_length */
 | 
						|
    uint32_t packet_length;  /*!< Actual length of current packet */
 | 
						|
} pcap_packet_header_t;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Pcap Runtime Handle
 | 
						|
 *
 | 
						|
 */
 | 
						|
typedef struct {
 | 
						|
    FILE *file; /*!< File handle */
 | 
						|
} pcap_runtime_t;
 | 
						|
 | 
						|
esp_err_t pcap_capture_packet(pcap_handle_t handle, void *payload, uint32_t length, uint32_t seconds, uint32_t microseconds)
 | 
						|
{
 | 
						|
    PCAP_CHECK(handle, "pcap handle is NULL", err);
 | 
						|
    pcap_runtime_t *pcap_rt = (pcap_runtime_t *)handle;
 | 
						|
    PCAP_CHECK(pcap_rt->file, "pcap file is NULL", err);
 | 
						|
    size_t real_write = 0;
 | 
						|
    pcap_packet_header_t header = {
 | 
						|
        .seconds = seconds,
 | 
						|
        .microseconds = microseconds,
 | 
						|
        .capture_length = length,
 | 
						|
        .packet_length = length
 | 
						|
    };
 | 
						|
    real_write = fwrite(&header, sizeof(header), 1, pcap_rt->file);
 | 
						|
    PCAP_CHECK(real_write == 1, "write packet header error", err);
 | 
						|
    real_write = fwrite(payload, sizeof(uint8_t), length, pcap_rt->file);
 | 
						|
    PCAP_CHECK(real_write == length, "write packet payload error", err);
 | 
						|
    /* Flush content in the buffer into device */
 | 
						|
    fflush(pcap_rt->file);
 | 
						|
    return ESP_OK;
 | 
						|
err:
 | 
						|
    return ESP_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
esp_err_t pcap_deinit(pcap_handle_t handle)
 | 
						|
{
 | 
						|
    PCAP_CHECK(handle, "pcap handle is NULL", err);
 | 
						|
    pcap_runtime_t *pcap_rt = (pcap_runtime_t *)handle;
 | 
						|
    PCAP_CHECK(pcap_rt->file, "pcap file is NULL", err);
 | 
						|
    PCAP_CHECK(fclose(pcap_rt->file) == 0, "close pcap file failed", err);
 | 
						|
    pcap_rt->file = NULL;
 | 
						|
    free(pcap_rt);
 | 
						|
    ESP_LOGD(PCAP_TAG, "pcap deinit OK");
 | 
						|
    return ESP_OK;
 | 
						|
err:
 | 
						|
    ESP_LOGW(PCAP_TAG, "pcap deinit failed");
 | 
						|
    return ESP_FAIL;
 | 
						|
}
 | 
						|
 | 
						|
esp_err_t pcap_init(pcap_config_t *config, pcap_handle_t *handle)
 | 
						|
{
 | 
						|
    PCAP_CHECK(config, "config is NULL", err);
 | 
						|
    PCAP_CHECK(handle, "pcap handle is NULL", err);
 | 
						|
    pcap_runtime_t *pcap_rt = calloc(sizeof(pcap_runtime_t), 1);
 | 
						|
    PCAP_CHECK(pcap_rt, "calloc pcap runtime failed", err);
 | 
						|
    pcap_rt->file = config->fp;
 | 
						|
    /* Write Pcap File header */
 | 
						|
    pcap_file_header_t header = {
 | 
						|
        .magic = PCAP_MAGIC_BIG_ENDIAN,
 | 
						|
        .major = PCAP_VERSION_MAJOR,
 | 
						|
        .minor = PCAP_VERSION_MINOR,
 | 
						|
        .zone = PCAP_TIME_ZONE_GMT,
 | 
						|
        .sigfigs = 0,
 | 
						|
        .snaplen = 0x40000,
 | 
						|
        .link_type = config->link_type
 | 
						|
    };
 | 
						|
    size_t real_write = fwrite(&header, sizeof(header), 1, pcap_rt->file);
 | 
						|
    PCAP_CHECK(real_write == 1, "write pcap file header failed", err_write);
 | 
						|
    /* Flush content in the buffer into device */
 | 
						|
    fflush(pcap_rt->file);
 | 
						|
    *handle = (pcap_handle_t)pcap_rt;
 | 
						|
    ESP_LOGD(PCAP_TAG, "pcap init OK");
 | 
						|
    return ESP_OK;
 | 
						|
    /* Error Handling */
 | 
						|
err_write:
 | 
						|
    fclose(pcap_rt->file);
 | 
						|
    pcap_rt->file = NULL;
 | 
						|
    free(pcap_rt);
 | 
						|
err:
 | 
						|
    ESP_LOGW(PCAP_TAG, "pcap init failed");
 | 
						|
    return ESP_FAIL;
 | 
						|
}
 |