From ff354a61da4bd3688a102fed04823c6d5d87c16d Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Mon, 2 May 2022 16:11:36 +0200 Subject: [PATCH] pcap: Add PCAP component --- .github/workflows/upload_component.yml | 2 +- pcap/CMakeLists.txt | 2 + pcap/LICENSE | 202 ++++++++++++++++++++++ pcap/README.md | 5 + pcap/idf_component.yml | 5 + pcap/include/pcap.h | 128 ++++++++++++++ pcap/src/pcap.c | 223 +++++++++++++++++++++++++ test_app/CMakeLists.txt | 2 +- 8 files changed, 567 insertions(+), 2 deletions(-) create mode 100644 pcap/CMakeLists.txt create mode 100644 pcap/LICENSE create mode 100644 pcap/README.md create mode 100644 pcap/idf_component.yml create mode 100644 pcap/include/pcap.h create mode 100644 pcap/src/pcap.c diff --git a/.github/workflows/upload_component.yml b/.github/workflows/upload_component.yml index 53bd1aa..c889f0d 100644 --- a/.github/workflows/upload_component.yml +++ b/.github/workflows/upload_component.yml @@ -15,6 +15,6 @@ jobs: - name: Upload components to component service uses: espressif/github-actions/upload_components@master with: - directories: "cbor;jsmn;libsodium;pid_ctrl;qrcode;nghttp;sh2lib;expat;esp_encrypted_img;coap" + directories: "cbor;jsmn;libsodium;pid_ctrl;qrcode;nghttp;sh2lib;expat;esp_encrypted_img;coap;pcap" namespace: "espressif" api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }} diff --git a/pcap/CMakeLists.txt b/pcap/CMakeLists.txt new file mode 100644 index 0000000..21b6fac --- /dev/null +++ b/pcap/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "src/pcap.c" + INCLUDE_DIRS "include") diff --git a/pcap/LICENSE b/pcap/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/pcap/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/pcap/README.md b/pcap/README.md new file mode 100644 index 0000000..99145c3 --- /dev/null +++ b/pcap/README.md @@ -0,0 +1,5 @@ +# Simple PCAP file writer + +This component allows users to trace their captured packets in .pcap file format. + +More details about PCAP format can be found [here](https://wiki.wireshark.org/Development/LibpcapFileFormat). diff --git a/pcap/idf_component.yml b/pcap/idf_component.yml new file mode 100644 index 0000000..eed50e5 --- /dev/null +++ b/pcap/idf_component.yml @@ -0,0 +1,5 @@ +version: "1.0.0" +description: PCAP file writer +url: https://github.com/espressif/idf-extra-components/tree/master/pcap +dependencies: + idf: ">=4.4" diff --git a/pcap/include/pcap.h b/pcap/include/pcap.h new file mode 100644 index 0000000..2bb9d5f --- /dev/null +++ b/pcap/include/pcap.h @@ -0,0 +1,128 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCAP_DEFAULT_VERSION_MAJOR 0x02 /*!< Major Version */ +#define PCAP_DEFAULT_VERSION_MINOR 0x04 /*!< Minor Version */ +#define PCAP_DEFAULT_TIME_ZONE_GMT 0x00 /*!< Time Zone */ + +/** + * @brief Type of pcap file handle + * + */ +typedef struct pcap_file_t *pcap_file_handle_t; + +/** +* @brief Link layer Type Definition, used for Pcap reader to decode payload +* +*/ +typedef enum { + PCAP_LINK_TYPE_LOOPBACK = 0, /*!< Loopback devices, except for later OpenBSD */ + PCAP_LINK_TYPE_ETHERNET = 1, /*!< Ethernet, and Linux loopback devices */ + PCAP_LINK_TYPE_TOKEN_RING = 6, /*!< 802.5 Token Ring */ + PCAP_LINK_TYPE_ARCNET = 7, /*!< ARCnet */ + PCAP_LINK_TYPE_SLIP = 8, /*!< SLIP */ + PCAP_LINK_TYPE_PPP = 9, /*!< PPP */ + PCAP_LINK_TYPE_FDDI = 10, /*!< FDDI */ + PCAP_LINK_TYPE_ATM = 100, /*!< LLC/SNAP encapsulated ATM */ + PCAP_LINK_TYPE_RAW_IP = 101, /*!< Raw IP, without link */ + PCAP_LINK_TYPE_BSD_SLIP = 102, /*!< BSD/OS SLIP */ + PCAP_LINK_TYPE_BSD_PPP = 103, /*!< BSD/OS PPP */ + PCAP_LINK_TYPE_CISCO_HDLC = 104, /*!< Cisco HDLC */ + PCAP_LINK_TYPE_802_11 = 105, /*!< 802.11 */ + PCAP_LINK_TYPE_BSD_LOOPBACK = 108, /*!< OpenBSD loopback devices(with AF_value in network byte order) */ + PCAP_LINK_TYPE_LOCAL_TALK = 114 /*!< LocalTalk */ +} pcap_link_type_t; + +/** +* @brief Pcap configuration Type Definition +* +*/ +typedef struct { + FILE *fp; /*!< Pointer to a standard file handle */ + unsigned int major_version; /*!< Pcap version: major */ + unsigned int minor_version; /*!< Pcap version: minor */ + unsigned int time_zone; /*!< Pcap timezone code */ + struct { + unsigned int little_endian: 1; /*!< Whether the pcap file is recored in little endian format */ + } flags; +} pcap_config_t; + +/** + * @brief Create a new pcap session, and returns pcap file handle + * + * @note This function won't create the low level FILE* object, the user should take care of the creation of the File Stream. + * + * @param[in] config pcap file configuration + * @param[out] ret_pcap Returned pcap file handle + * @return + * - ESP_OK: Create pcap file successfully + * - ESP_ERR_INVALID_ARG: Create pcap file failed because of invalid argument + * - ESP_ERR_NO_MEM: Create pcap file failed because out of memory + * - ESP_FAIL: Create pcap file failed + */ +esp_err_t pcap_new_session(const pcap_config_t *config, pcap_file_handle_t *ret_pcap); + +/** + * @brief Delete the pcap session, and close the File Stream + * + * @param[in] pcap pcap file handle created by `pcap_new_session()` + * @return + * - ESP_OK: Delete pcap session successfully + * - ESP_ERR_INVALID_ARG: Delete pcap session failed because of invalid argument + * - ESP_FAIL: Delete pcap session failed + */ +esp_err_t pcap_del_session(pcap_file_handle_t pcap); + +/** + * @brief Write pcap file header + * + * @param[in] pcap pcap file handle created by `pcap_new_session()` + * @param[in] link_type Network link layer type + * @return + * - ESP_OK: Write pcap file header successfully + * - ESP_ERR_INVALID_ARG: Write pcap file header failed because of invalid argument + * - ESP_FAIL: Write pcap file header failed + */ +esp_err_t pcap_write_header(pcap_file_handle_t pcap, pcap_link_type_t link_type); + +/** + * @brief Capture one packet into pcap file + * + * @param[in] pcap pcap file handle created by `pcap_new_session()` + * @param[in] payload pointer of the captured data buffer + * @param[in] length length of captured data buffer + * @param[in] seconds second of capture time + * @param[in] microseconds microsecond of capture time + * @return + * - ESP_OK: Write network packet into pcap file successfully + * - ESP_ERR_INVALID_ARG: Write network packet into pcap file failed because of invalid argument + * - ESP_FAIL: Write network packet into pcap file failed + */ +esp_err_t pcap_capture_packet(pcap_file_handle_t pcap, void *payload, uint32_t length, uint32_t seconds, uint32_t microseconds); + +/** + * @brief Print the summary of pcap file into stream + * + * @param[in] pcap pcap file handle created by `pcap_new_session()` + * @param[in] print_file the file stream to save the summary + * @return + * - ESP_OK: Print pcap file summary successfully + * - ESP_ERR_INVALID_ARG: Print pcap file summary failed because of invalid argument + * - ESP_FAIL: Print pcap file summary failed + */ +esp_err_t pcap_print_summary(pcap_file_handle_t pcap, FILE *print_file); + +#ifdef __cplusplus +} +#endif diff --git a/pcap/src/pcap.c b/pcap/src/pcap.c new file mode 100644 index 0000000..886c736 --- /dev/null +++ b/pcap/src/pcap.c @@ -0,0 +1,223 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "esp_log.h" +#include "esp_check.h" +#include "pcap.h" + +static const char *TAG = "pcap"; + +#define PCAP_MAGIC_BIG_ENDIAN 0xA1B2C3D4 /*!< Big-Endian */ +#define PCAP_MAGIC_LITTLE_ENDIAN 0xD4C3B2A1 /*!< Little-Endian */ + +typedef struct pcap_file_t pcap_file_t; + +/** + * @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 + * + */ +struct pcap_file_t { + FILE *file; /*!< File handle */ + pcap_link_type_t link_type; /*!< Pcap Link Type */ + unsigned int major_version; /*!< Pcap version: major */ + unsigned int minor_version; /*!< Pcap version: minor */ + unsigned int time_zone; /*!< Pcap timezone code */ + uint32_t endian_magic; /*!< Magic value related to endian format */ +}; + +esp_err_t pcap_new_session(const pcap_config_t *config, pcap_file_handle_t *ret_pcap) +{ + esp_err_t ret = ESP_OK; + pcap_file_t *pcap = NULL; + ESP_GOTO_ON_FALSE(config && ret_pcap, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); + ESP_GOTO_ON_FALSE(config->fp, ESP_ERR_INVALID_ARG, err, TAG, "pcap file handle can't be NULL"); + pcap = calloc(1, sizeof(pcap_file_t)); + ESP_GOTO_ON_FALSE(pcap, ESP_ERR_NO_MEM, err, TAG, "no mem for pcap file object"); + pcap->file = config->fp; + pcap->major_version = config->major_version; + pcap->minor_version = config->minor_version; + pcap->endian_magic = config->flags.little_endian ? PCAP_MAGIC_LITTLE_ENDIAN : PCAP_MAGIC_BIG_ENDIAN; + pcap->time_zone = config->time_zone; + *ret_pcap = pcap; + return ret; +err: + if (pcap) { + free(pcap); + } + return ret; +} + +esp_err_t pcap_del_session(pcap_file_handle_t pcap) +{ + ESP_RETURN_ON_FALSE(pcap, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + if (pcap->file) { + fclose(pcap->file); + pcap->file = NULL; + } + free(pcap); + return ESP_OK; +} + +esp_err_t pcap_write_header(pcap_file_handle_t pcap, pcap_link_type_t link_type) +{ + ESP_RETURN_ON_FALSE(pcap, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + /* Write Pcap File header */ + pcap_file_header_t header = { + .magic = pcap->endian_magic, + .major = pcap->major_version, + .minor = pcap->minor_version, + .zone = pcap->time_zone, + .sigfigs = 0, + .snaplen = 0x40000, + .link_type = link_type, + }; + size_t real_write = fwrite(&header, sizeof(header), 1, pcap->file); + ESP_RETURN_ON_FALSE(real_write == 1, ESP_FAIL, TAG, "write pcap file header failed"); + /* Save the link type to pcap file object */ + pcap->link_type = link_type; + /* Flush content in the buffer into device */ + fflush(pcap->file); + return ESP_OK; +} + +esp_err_t pcap_capture_packet(pcap_file_handle_t pcap, void *payload, uint32_t length, uint32_t seconds, uint32_t microseconds) +{ + ESP_RETURN_ON_FALSE(pcap && payload, ESP_ERR_INVALID_ARG, TAG, "invalid argumnet"); + 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->file); + ESP_RETURN_ON_FALSE(real_write == 1, ESP_FAIL, TAG, "write packet header failed"); + real_write = fwrite(payload, sizeof(uint8_t), length, pcap->file); + ESP_RETURN_ON_FALSE(real_write == length, ESP_FAIL, TAG, "write packet payload failed"); + /* Flush content in the buffer into device */ + fflush(pcap->file); + return ESP_OK; +} + +esp_err_t pcap_print_summary(pcap_file_handle_t pcap, FILE *print_file) +{ + esp_err_t ret = ESP_OK; + long size = 0; + char *packet_payload = NULL; + ESP_RETURN_ON_FALSE(pcap && print_file, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + // get file size + fseek(pcap->file, 0L, SEEK_END); + size = ftell(pcap->file); + fseek(pcap->file, 0L, SEEK_SET); + // file empty is allowed, so return ESP_OK + ESP_RETURN_ON_FALSE(size, ESP_OK, TAG, "pcap file is empty"); + // packet index (by bytes) + uint32_t index = 0; + pcap_file_header_t file_header; + size_t real_read = fread(&file_header, sizeof(pcap_file_header_t), 1, pcap->file); + ESP_RETURN_ON_FALSE(real_read == 1, ESP_FAIL, TAG, "read pcap file header failed"); + index += sizeof(pcap_file_header_t); + //print pcap header information + fprintf(print_file, "------------------------------------------------------------------------\n"); + fprintf(print_file, "Pcap packet Head:\n"); + fprintf(print_file, "------------------------------------------------------------------------\n"); + fprintf(print_file, "Magic Number: %x\n", file_header.magic); + fprintf(print_file, "Major Version: %d\n", file_header.major); + fprintf(print_file, "Minor Version: %d\n", file_header.minor); + fprintf(print_file, "SnapLen: %d\n", file_header.snaplen); + fprintf(print_file, "LinkType: %d\n", file_header.link_type); + fprintf(print_file, "------------------------------------------------------------------------\n"); + uint32_t packet_num = 0; + pcap_packet_header_t packet_header; + while (index < size) { + real_read = fread(&packet_header, sizeof(pcap_packet_header_t), 1, pcap->file); + ESP_GOTO_ON_FALSE(real_read == 1, ESP_FAIL, err, TAG, "read pcap packet header failed"); + // print packet header information + fprintf(print_file, "Packet %d:\n", packet_num); + fprintf(print_file, "Timestamp (Seconds): %d\n", packet_header.seconds); + fprintf(print_file, "Timestamp (Microseconds): %d\n", packet_header.microseconds); + fprintf(print_file, "Capture Length: %d\n", packet_header.capture_length); + fprintf(print_file, "Packet Length: %d\n", packet_header.packet_length); + size_t payload_length = packet_header.capture_length; + packet_payload = malloc(payload_length); + ESP_GOTO_ON_FALSE(packet_payload, ESP_ERR_NO_MEM, err, TAG, "no mem to save packet payload"); + real_read = fread(packet_payload, payload_length, 1, pcap->file); + ESP_GOTO_ON_FALSE(real_read == 1, ESP_FAIL, err, TAG, "read payload error"); + // print packet information + if (file_header.link_type == PCAP_LINK_TYPE_802_11) { + // Frame Control Field is coded as LSB first + fprintf(print_file, "Frame Type: %2x\n", (packet_payload[0] >> 2) & 0x03); + fprintf(print_file, "Frame Subtype: %2x\n", (packet_payload[0] >> 4) & 0x0F); + fprintf(print_file, "Destination: "); + for (int j = 0; j < 5; j++) { + fprintf(print_file, "%2x ", packet_payload[4 + j]); + } + fprintf(print_file, "%2x\n", packet_payload[9]); + fprintf(print_file, "Source: "); + for (int j = 0; j < 5; j++) { + fprintf(print_file, "%2x ", packet_payload[10 + j]); + } + fprintf(print_file, "%2x\n", packet_payload[15]); + fprintf(print_file, "------------------------------------------------------------------------\n"); + } else if (file_header.link_type == PCAP_LINK_TYPE_ETHERNET) { + fprintf(print_file, "Destination: "); + for (int j = 0; j < 5; j++) { + fprintf(print_file, "%2x ", packet_payload[j]); + } + fprintf(print_file, "%2x\n", packet_payload[5]); + fprintf(print_file, "Source: "); + for (int j = 0; j < 5; j++) { + fprintf(print_file, "%2x ", packet_payload[6 + j]); + } + fprintf(print_file, "%2x\n", packet_payload[11]); + fprintf(print_file, "Type: 0x%x\n", packet_payload[13] | (packet_payload[12] << 8)); + fprintf(print_file, "------------------------------------------------------------------------\n"); + } else { + fprintf(print_file, "Unknown link type:%d\n", file_header.link_type); + fprintf(print_file, "------------------------------------------------------------------------\n"); + } + free(packet_payload); + packet_payload = NULL; + index += packet_header.capture_length + sizeof(pcap_packet_header_t); + packet_num ++; + } + fprintf(print_file, "Pcap packet Number: %d\n", packet_num); + fprintf(print_file, "------------------------------------------------------------------------\n"); + return ret; +err: + if (packet_payload) { + free(packet_payload); + } + return ret; +} diff --git a/test_app/CMakeLists.txt b/test_app/CMakeLists.txt index 77f9951..fe5570e 100644 --- a/test_app/CMakeLists.txt +++ b/test_app/CMakeLists.txt @@ -9,7 +9,7 @@ set(EXTRA_COMPONENT_DIRS ../libsodium ../expat ../cbor ../jsmn ../qrcode ../coap # 2. Add here if the component is compatible with IDF >= v4.4 if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "4.4") - list(APPEND EXTRA_COMPONENT_DIRS ../pid_ctrl ../esp_encrypted_img) + list(APPEND EXTRA_COMPONENT_DIRS ../pid_ctrl ../esp_encrypted_img ../pcap) endif() # 3. Add here if the component is compatible with IDF >= v5.0