diff --git a/.clang-tidy-new b/.clang-tidy-new new file mode 100644 index 0000000000..c32d3842fc --- /dev/null +++ b/.clang-tidy-new @@ -0,0 +1,34 @@ +Checks: 'cert-*, +clang-analyzer-*, +concurrency-*, +cppcoreguidelines-*, +misc-*, +modernize-*, +performance-*, +portability-*, +readability-*, +-cert-env33-c, +-cert-err58-cpp, +-clang-analyzer-optin.cplusplus.VirtualCall, +-cppcoreguidelines-avoid-c-arrays, +-cppcoreguidelines-avoid-do-while, +-cppcoreguidelines-avoid-magic-numbers, +-cppcoreguidelines-avoid-non-const-global-variables, +-cppcoreguidelines-macro-usage, +-cppcoreguidelines-owning-memory, +-cppcoreguidelines-pro-bounds-array-to-pointer-decay, +-cppcoreguidelines-pro-bounds-constant-array-index, +-cppcoreguidelines-pro-bounds-pointer-arithmetic, +-cppcoreguidelines-pro-type-reinterpret-cast, +-cppcoreguidelines-pro-type-const-cast, +-cppcoreguidelines-pro-type-vararg, +-cppcoreguidelines-special-member-functions, +-modernize-avoid-c-arrays, +-modernize-use-trailing-return-type, +-misc-header-include-cycle, +-misc-include-cleaner, +-misc-no-recursion, +-misc-non-private-member-variables-in-classes, +-misc-use-anonymous-namespace, +-readability-function-cognitive-complexity, +-readability-magic-numbers' diff --git a/.codespellrc b/.codespellrc index c7019c766a..7506fd03df 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,4 +1,4 @@ [codespell] -skip = *.dat,typos-config.toml,.git,.venv,./ci,./Dist,./mk,./Tests/ExamplesTest/expected_output,./Tests/ExamplesTest/pcap_examples,./Tests/Packet++Test/PacketExamples,./Tests/Pcap++Test/PcapExamples,./3rdParty,./Examples/PcapSearch/dirent-for-Visual-Studio +skip = *.dat,typos-config.toml,.git,.venv,venv,./out,./ci,./Dist,./mk,./Tests/ExamplesTest/expected_output,./Tests/ExamplesTest/pcap_examples,./Tests/Packet++Test/PacketExamples,./Tests/Pcap++Test/PcapExamples,./3rdParty,./Examples/PcapSearch/dirent-for-Visual-Studio ignore-words = codespell-ignore-list.txt count = diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index c28480d3a9..bc9eeef8ba 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -36,7 +36,7 @@ jobs: apk update && apk add cppcheck python3-dev python3 -m venv .venv . .venv/bin/activate - python3 -m pip install pre-commit setuptools clang-format==18.1.6 clang-tidy==18.1.8 + python3 -m pip install pre-commit setuptools clang-format==19.1.6 clang-tidy==18.1.8 - name: Run pre-commit run: | @@ -701,7 +701,7 @@ jobs: ./gradlew assembleDebug xdp: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout code diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7968bad2f9..77ca6d1a3c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,4 @@ -exclude: '.*\.(pcap|pcapng|dat|txt)' +exclude: '.*\.(pcap|pcapng|dat)|(PacketExamples|PcapExamples|expected_output|pcap_examples).*\.txt' fail_fast: false repos: - repo: local @@ -22,7 +22,7 @@ repos: args: ['--fix=lf'] - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.1 + rev: v0.8.4 hooks: - id: ruff # Run the linter. types_or: [ python ] @@ -41,13 +41,14 @@ repos: rev: 0.17.1 hooks: - id: gersemi + args: ["-c"] - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: - id: codespell pass_filenames: false - repo: https://github.com/crate-ci/typos - rev: v1.28.1 + rev: codespell-dict-v0.5.0 hooks: - id: typos args: ['--config=typos-config.toml'] diff --git a/3rdParty/CMakeLists.txt b/3rdParty/CMakeLists.txt index 9af23e6138..26fe30f166 100644 --- a/3rdParty/CMakeLists.txt +++ b/3rdParty/CMakeLists.txt @@ -11,5 +11,6 @@ if(PCAPPP_INSTALL) EXPORT PcapPlusPlusTargets ARCHIVE DESTINATION ${PCAPPP_INSTALL_LIBDIR} LIBRARY DESTINATION ${PCAPPP_INSTALL_LIBDIR} - PUBLIC_HEADER DESTINATION ${PCAPPP_INSTALL_INCLUDEDIR}) + PUBLIC_HEADER DESTINATION ${PCAPPP_INSTALL_INCLUDEDIR} + ) endif() diff --git a/3rdParty/EndianPortable/CMakeLists.txt b/3rdParty/EndianPortable/CMakeLists.txt index bbd0d06d28..394a339afb 100644 --- a/3rdParty/EndianPortable/CMakeLists.txt +++ b/3rdParty/EndianPortable/CMakeLists.txt @@ -1,7 +1,5 @@ add_library(EndianPortable INTERFACE) -target_include_directories(EndianPortable - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(EndianPortable INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_sources(EndianPortable - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/EndianPortable.h) +target_sources(EndianPortable INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include/EndianPortable.h) diff --git a/3rdParty/Getopt-for-Visual-Studio/CMakeLists.txt b/3rdParty/Getopt-for-Visual-Studio/CMakeLists.txt index 487c5e1950..a9237880a6 100644 --- a/3rdParty/Getopt-for-Visual-Studio/CMakeLists.txt +++ b/3rdParty/Getopt-for-Visual-Studio/CMakeLists.txt @@ -1,7 +1,5 @@ add_library(Getopt-for-Visual-Studio INTERFACE) -target_include_directories(Getopt-for-Visual-Studio - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/) +target_include_directories(Getopt-for-Visual-Studio INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/) -target_sources(Getopt-for-Visual-Studio - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/getopt.h) +target_sources(Getopt-for-Visual-Studio INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/getopt.h) diff --git a/3rdParty/LightPcapNg/CMakeLists.txt b/3rdParty/LightPcapNg/CMakeLists.txt index 2f10732f09..c93b91a72d 100644 --- a/3rdParty/LightPcapNg/CMakeLists.txt +++ b/3rdParty/LightPcapNg/CMakeLists.txt @@ -7,7 +7,8 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/LightPcapNg/cmake/") option(LIGHT_PCAPNG_ZSTD "Build with ZSTD compression support" OFF) add_library( - light_pcapng OBJECT + light_pcapng + OBJECT LightPcapNg/src/light_advanced.c LightPcapNg/src/light_alloc.c LightPcapNg/src/light_compression.c @@ -20,7 +21,8 @@ add_library( LightPcapNg/src/light_pcapng_ext.c LightPcapNg/src/light_pcapng.c LightPcapNg/src/light_platform.c - LightPcapNg/src/light_zstd_compression.c) + LightPcapNg/src/light_zstd_compression.c +) target_compile_definitions(light_pcapng PUBLIC -DUNIVERSAL) @@ -28,8 +30,10 @@ if(BUILD_SHARED_LIBS) set_property(TARGET light_pcapng PROPERTY POSITION_INDEPENDENT_CODE ON) endif() -target_include_directories(light_pcapng PUBLIC $ - $) +target_include_directories( + light_pcapng + PUBLIC $ $ +) if(LIGHT_PCAPNG_ZSTD) find_package(ZSTD) diff --git a/3rdParty/LightPcapNg/LightPcapNg/CMakeLists.txt b/3rdParty/LightPcapNg/LightPcapNg/CMakeLists.txt index 82ca7acfb9..bc0bdbdc53 100644 --- a/3rdParty/LightPcapNg/LightPcapNg/CMakeLists.txt +++ b/3rdParty/LightPcapNg/LightPcapNg/CMakeLists.txt @@ -1,84 +1,66 @@ -cmake_minimum_required (VERSION 2.6) -project (light_pcapng C) -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/include/ -Wall -O2 -fPIC -DUNIVERSAL -g") - -add_library (light_pcapng SHARED - src/light_io.c - src/light_pcapng.c - src/light_pcapng_cont.c - src/light_platform.c - src/light_manipulate.c - src/light_internal.c - src/light_alloc.c - src/light_advanced.c - src/light_option.c - src/light_pcapng_ext.c - ) - -add_library (light_pcapng_static STATIC - src/light_io.c - src/light_pcapng.c - src/light_pcapng_cont.c - src/light_platform.c - src/light_manipulate.c - src/light_internal.c - src/light_alloc.c - src/light_advanced.c - src/light_option.c - src/light_pcapng_ext.c - ) - -add_executable (test_read.test - src/tests/test_read.c - ) -target_link_libraries(test_read.test light_pcapng_static) - -add_executable (test_read_write.test - src/tests/test_read_write.c - ) -target_link_libraries(test_read_write.test light_pcapng_static) - -add_executable (test_mem.test - src/tests/test_mem.c - ) -target_link_libraries(test_mem.test light_pcapng_static) - -add_executable (test_histogram.test - src/tests/test_histogram.c - ) -target_link_libraries(test_histogram.test light_pcapng_static) - -add_executable (test_subcapture.test - src/tests/test_subcapture.c - ) -target_link_libraries(test_subcapture.test light_pcapng_static) - -add_executable (test_feature.test - src/tests/test_feature.c - ) -target_link_libraries(test_feature.test light_pcapng_static) - -add_executable (test_flow.test - src/tests/test_flow.c - ) -target_link_libraries(test_flow.test light_pcapng_static) - -add_executable (test_feature_advanced.test - src/tests/test_feature_advanced.c - ) -target_link_libraries(test_feature_advanced.test light_pcapng_static dl) - -add_executable (test_read_packets.test - src/tests/test_read_packets.c - ) -target_link_libraries(test_read_packets.test light_pcapng_static) - -add_executable (test_read_write_packets.test - src/tests/test_read_write_packets.c - ) -target_link_libraries(test_read_write_packets.test light_pcapng_static) - -add_executable (test_split.test - src/tests/test_split.c - ) -target_link_libraries(test_split.test light_pcapng_static) +cmake_minimum_required(VERSION 2.6) +project(light_pcapng C) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/include/ -Wall -O2 -fPIC -DUNIVERSAL -g") + +add_library( + light_pcapng + SHARED + src/light_io.c + src/light_pcapng.c + src/light_pcapng_cont.c + src/light_platform.c + src/light_manipulate.c + src/light_internal.c + src/light_alloc.c + src/light_advanced.c + src/light_option.c + src/light_pcapng_ext.c +) + +add_library( + light_pcapng_static + STATIC + src/light_io.c + src/light_pcapng.c + src/light_pcapng_cont.c + src/light_platform.c + src/light_manipulate.c + src/light_internal.c + src/light_alloc.c + src/light_advanced.c + src/light_option.c + src/light_pcapng_ext.c +) + +add_executable(test_read.test src/tests/test_read.c) +target_link_libraries(test_read.test light_pcapng_static) + +add_executable(test_read_write.test src/tests/test_read_write.c) +target_link_libraries(test_read_write.test light_pcapng_static) + +add_executable(test_mem.test src/tests/test_mem.c) +target_link_libraries(test_mem.test light_pcapng_static) + +add_executable(test_histogram.test src/tests/test_histogram.c) +target_link_libraries(test_histogram.test light_pcapng_static) + +add_executable(test_subcapture.test src/tests/test_subcapture.c) +target_link_libraries(test_subcapture.test light_pcapng_static) + +add_executable(test_feature.test src/tests/test_feature.c) +target_link_libraries(test_feature.test light_pcapng_static) + +add_executable(test_flow.test src/tests/test_flow.c) +target_link_libraries(test_flow.test light_pcapng_static) + +add_executable(test_feature_advanced.test src/tests/test_feature_advanced.c) +target_link_libraries(test_feature_advanced.test light_pcapng_static dl) + +add_executable(test_read_packets.test src/tests/test_read_packets.c) +target_link_libraries(test_read_packets.test light_pcapng_static) + +add_executable(test_read_write_packets.test src/tests/test_read_write_packets.c) +target_link_libraries(test_read_write_packets.test light_pcapng_static) + +add_executable(test_split.test src/tests/test_split.c) +target_link_libraries(test_split.test light_pcapng_static) diff --git a/3rdParty/LightPcapNg/LightPcapNg/LICENSE.txt b/3rdParty/LightPcapNg/LightPcapNg/LICENSE.txt index 8cd5356ced..31b2af702d 100644 --- a/3rdParty/LightPcapNg/LightPcapNg/LICENSE.txt +++ b/3rdParty/LightPcapNg/LightPcapNg/LICENSE.txt @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng.c b/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng.c index bb8fdc2919..1db448de7f 100644 --- a/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng.c +++ b/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng.c @@ -90,12 +90,12 @@ void parse_by_block_type(struct _light_pcapng *current, const uint32_t *local_da switch (current->block_type) { case LIGHT_SECTION_HEADER_BLOCK: - { + { // PCPP patch DPRINT_HERE(LIGHT_SECTION_HEADER_BLOCK); struct _light_section_header *shb = calloc(1, sizeof(struct _light_section_header)); struct _light_option *opt = NULL; - uint32_t version; - int32_t local_offset; + uint32_t version = 0; + int32_t local_offset = 0; shb->byteorder_magic = *local_data++; // TODO check byte order. @@ -108,17 +108,19 @@ void parse_by_block_type(struct _light_pcapng *current, const uint32_t *local_da current->block_body = (uint32_t*)shb; local_offset = (size_t)local_data - (size_t)block_start; opt = __parse_options((uint32_t **)&local_data, current->block_total_length - local_offset - sizeof(current->block_total_length)); + if (opt == NULL) + opt = calloc(1, sizeof(struct _light_option)); current->options = opt; } break; case LIGHT_INTERFACE_BLOCK: - { + { // PCPP patch DPRINT_HERE(LIGHT_INTERFACE_BLOCK); struct _light_interface_description_block *idb = calloc(1, sizeof(struct _light_interface_description_block)); struct _light_option *opt = NULL; uint32_t link_reserved = *local_data++; - int32_t local_offset; + int32_t local_offset = 0; idb->link_type = link_reserved & 0xFFFF; idb->reserved = (link_reserved >> 16) & 0xFFFF; @@ -126,12 +128,14 @@ void parse_by_block_type(struct _light_pcapng *current, const uint32_t *local_da current->block_body = (uint32_t*)idb; local_offset = (size_t)local_data - (size_t)block_start; opt = __parse_options((uint32_t **)&local_data, current->block_total_length - local_offset - sizeof(current->block_total_length)); + if (opt == NULL) + opt = calloc(1, sizeof(struct _light_option)); current->options = opt; } break; case LIGHT_ENHANCED_PACKET_BLOCK: - { + { // PCPP Patch DPRINT_HERE(LIGHT_ENHANCED_PACKET_BLOCK); struct _light_enhanced_packet_block *epb = NULL; struct _light_option *opt = NULL; @@ -157,6 +161,8 @@ void parse_by_block_type(struct _light_pcapng *current, const uint32_t *local_da current->block_body = (uint32_t*)epb; local_offset = (size_t)local_data - (size_t)block_start; opt = __parse_options((uint32_t **)&local_data, current->block_total_length - local_offset - sizeof(current->block_total_length)); + if (opt == NULL) + opt = calloc(1, sizeof(struct _light_option)); current->options = opt; } break; @@ -200,6 +206,8 @@ void parse_by_block_type(struct _light_pcapng *current, const uint32_t *local_da current->block_body = (uint32_t*)cnb; local_offset = (size_t)local_data - (size_t)block_start; opt = __parse_options((uint32_t **)&local_data, current->block_total_length - local_offset - sizeof(current->block_total_length)); + if (opt == NULL) + opt = calloc(1, sizeof(struct _light_option)); current->options = opt; } break; diff --git a/3rdParty/MemPlumber/MemPlumber/CMakeLists.txt b/3rdParty/MemPlumber/MemPlumber/CMakeLists.txt index 7623c7490e..65e885094d 100644 --- a/3rdParty/MemPlumber/MemPlumber/CMakeLists.txt +++ b/3rdParty/MemPlumber/MemPlumber/CMakeLists.txt @@ -10,8 +10,7 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) endif() # Build options -option(MEMPLUMBER_COLLECT_STATIC_VAR_DATA - "Collect data also on static variable memory allocation" OFF) +option(MEMPLUMBER_COLLECT_STATIC_VAR_DATA "Collect data also on static variable memory allocation" OFF) option(MEMPLUMBER_DISABLE_BACKTRACE "Disable backtrace" OFF) option(MEMPLUMBER_BUILD_TESTS "Build Tests" ${MEMPLUMBER_MAIN_PROJECT}) option(MEMPLUMBER_BUILD_EXAMPLES "Build Examples" ${MEMPLUMBER_MAIN_PROJECT}) @@ -37,11 +36,11 @@ if(MEMPLUMBER_DISABLE_BACKTRACE) add_definitions(-DDISABLE_BACKTRACE) endif() -if (MEMPLUMBER_BUILD_TESTS) +if(MEMPLUMBER_BUILD_TESTS) enable_testing() add_subdirectory(Tests) endif() -if (MEMPLUMBER_BUILD_EXAMPLES) +if(MEMPLUMBER_BUILD_EXAMPLES) add_subdirectory(Examples) endif() diff --git a/3rdParty/MemPlumber/MemPlumber/Examples/CMakeLists.txt b/3rdParty/MemPlumber/MemPlumber/Examples/CMakeLists.txt index 04cafa091a..f1ed0f5462 100644 --- a/3rdParty/MemPlumber/MemPlumber/Examples/CMakeLists.txt +++ b/3rdParty/MemPlumber/MemPlumber/Examples/CMakeLists.txt @@ -1,25 +1,13 @@ -cmake_minimum_required (VERSION 3.0) - -add_executable(basic-example - basic-example.cpp -) - -target_link_libraries(basic-example PUBLIC - memplumber -) - -add_executable(static-example - static-example.cpp -) - -target_link_libraries(static-example PUBLIC - memplumber -) - -add_executable(dump-to-file-example - dump-to-file-example.cpp -) - -target_link_libraries(dump-to-file-example PUBLIC - memplumber -) \ No newline at end of file +cmake_minimum_required(VERSION 3.0) + +add_executable(basic-example basic-example.cpp) + +target_link_libraries(basic-example PUBLIC memplumber) + +add_executable(static-example static-example.cpp) + +target_link_libraries(static-example PUBLIC memplumber) + +add_executable(dump-to-file-example dump-to-file-example.cpp) + +target_link_libraries(dump-to-file-example PUBLIC memplumber) diff --git a/3rdParty/MemPlumber/MemPlumber/Tests/CMakeLists.txt b/3rdParty/MemPlumber/MemPlumber/Tests/CMakeLists.txt index 4f5f1517ec..b0b223b742 100644 --- a/3rdParty/MemPlumber/MemPlumber/Tests/CMakeLists.txt +++ b/3rdParty/MemPlumber/MemPlumber/Tests/CMakeLists.txt @@ -1,73 +1,39 @@ -cmake_minimum_required (VERSION 3.0) - -# Build options -option(TEST_VERBOSE "Run tests in verbose mode" OFF) -option(MEM_CHECK_VERBOSE "Run mem check in verbose mode" OFF) - -if(TEST_VERBOSE) - add_definitions(-DTEST_VERBOSE) -endif() - -if(MEM_CHECK_VERBOSE) - add_definitions(-DMEM_CHECK_VERBOSE) -endif() - -add_subdirectory(test-lib) - -add_executable(basic-tests - test-macros.h - basic-tests.cpp -) - -add_executable(static-var-tests - test-macros.h - static-var-tests.cpp -) - -add_executable(inner-lib-tests - test-macros.h - inner-lib-tests.cpp -) - -add_executable(load-tests - test-macros.h - load-tests.cpp -) - -target_link_libraries(basic-tests PUBLIC - memplumber -) - -target_link_libraries(static-var-tests PUBLIC - memplumber -) - -target_link_libraries(inner-lib-tests PUBLIC - memplumber - TestLib -) - -target_link_libraries(load-tests PUBLIC - memplumber - TestLib -) - -add_test( - NAME basic-tests - COMMAND $ -) - -add_test( - NAME static-var-tests - COMMAND $ -) - -add_test( - NAME inner-lib-tests - COMMAND $ -) - -add_test( - NAME load-tests - COMMAND $ -) \ No newline at end of file +cmake_minimum_required(VERSION 3.0) + +# Build options +option(TEST_VERBOSE "Run tests in verbose mode" OFF) +option(MEM_CHECK_VERBOSE "Run mem check in verbose mode" OFF) + +if(TEST_VERBOSE) + add_definitions(-DTEST_VERBOSE) +endif() + +if(MEM_CHECK_VERBOSE) + add_definitions(-DMEM_CHECK_VERBOSE) +endif() + +add_subdirectory(test-lib) + +add_executable(basic-tests test-macros.h basic-tests.cpp) + +add_executable(static-var-tests test-macros.h static-var-tests.cpp) + +add_executable(inner-lib-tests test-macros.h inner-lib-tests.cpp) + +add_executable(load-tests test-macros.h load-tests.cpp) + +target_link_libraries(basic-tests PUBLIC memplumber) + +target_link_libraries(static-var-tests PUBLIC memplumber) + +target_link_libraries(inner-lib-tests PUBLIC memplumber TestLib) + +target_link_libraries(load-tests PUBLIC memplumber TestLib) + +add_test(NAME basic-tests COMMAND $) + +add_test(NAME static-var-tests COMMAND $) + +add_test(NAME inner-lib-tests COMMAND $) + +add_test(NAME load-tests COMMAND $) diff --git a/3rdParty/MemPlumber/MemPlumber/Tests/test-lib/CMakeLists.txt b/3rdParty/MemPlumber/MemPlumber/Tests/test-lib/CMakeLists.txt index 8948533473..dd14bb0f84 100644 --- a/3rdParty/MemPlumber/MemPlumber/Tests/test-lib/CMakeLists.txt +++ b/3rdParty/MemPlumber/MemPlumber/Tests/test-lib/CMakeLists.txt @@ -1,7 +1,4 @@ -cmake_minimum_required (VERSION 3.0) -project (TestLib CXX) - -add_library (TestLib - test-lib.cpp - test-lib.h -) \ No newline at end of file +cmake_minimum_required(VERSION 3.0) +project(TestLib CXX) + +add_library(TestLib test-lib.cpp test-lib.h) diff --git a/3rdParty/OUIDataset/PCPP_OUIDataset.json b/3rdParty/OUIDataset/PCPP_OUIDataset.json index 889e2e2e1d..64cf364ca6 100644 --- a/3rdParty/OUIDataset/PCPP_OUIDataset.json +++ b/3rdParty/OUIDataset/PCPP_OUIDataset.json @@ -19887,7 +19887,7 @@ "vendor": "Matrix Inc." }, "6657": { - "vendor": "Smiths Medical" + "vendor": "ICU Medical, Inc." }, "6658": { "vendor": "Secure Care Products, Inc" @@ -25299,7 +25299,7 @@ "vendor": "Samsin Innotec" }, "8462": { - "vendor": "Orpak Systems L.T.D." + "vendor": "Gilbarco Inc." }, "8463": { "vendor": "Cernium Corp" @@ -32444,6 +32444,9 @@ "21016": { "vendor": "Wuxi Keboda Electron Co.Ltd" }, + "21061": { + "vendor": "Ganatechwin" + }, "21186": { "vendor": "peiker acustic GmbH" }, @@ -35144,6 +35147,9 @@ "39938": { "vendor": "Hewlett Packard" }, + "39959": { + "vendor": "Quectel Wireless Solutions Co.,Ltd." + }, "40128": { "vendor": "vivo Mobile Communication Co., Ltd." }, @@ -39146,6 +39152,9 @@ "270468": { "vendor": "zte corporation" }, + "270474": { + "vendor": "浙江路川科技有限公司" + }, "270490": { "vendor": "Panasonic Corporation AVC Networks Company" }, @@ -39254,6 +39263,9 @@ "277736": { "vendor": "Shenzhen SuperElectron Technology Co.,Ltd." }, + "277870": { + "vendor": "Nokia" + }, "277912": { "vendor": "ChongQing QingJia Electronics CO.,LTD" }, @@ -39809,6 +39821,9 @@ "311208": { "vendor": "ISB Corporation" }, + "311253": { + "vendor": "Apple, Inc." + }, "311387": { "vendor": "Tigo Energy" }, @@ -40850,6 +40865,9 @@ "540302": { "vendor": "Hon Hai Precision Ind. Co.,Ltd." }, + "540449": { + "vendor": "Motorola Mobility LLC, a Lenovo Company" + }, "540478": { "vendor": "WSH GmbH" }, @@ -41150,6 +41168,9 @@ "559047": { "vendor": "Apple, Inc." }, + "559857": { + "vendor": "Mercusys Technologies Co., Ltd." + }, "560072": { "vendor": "Google, Inc." }, @@ -41666,6 +41687,9 @@ "715035": { "vendor": "PADL Software Pty Ltd" }, + "719261": { + "vendor": "Fitipower Integrated Technology" + }, "786763": { "vendor": "zte corporation" }, @@ -42098,6 +42122,9 @@ "816922": { "vendor": "Apple, Inc." }, + "817493": { + "vendor": "Hui Zhou Gaoshengda Technology Co.,LTD" + }, "817685": { "vendor": "Intel Corporate" }, @@ -42110,6 +42137,9 @@ "818556": { "vendor": "Kexiang Information Technology Co, Ltd." }, + "818608": { + "vendor": "Motorola Mobility LLC, a Lenovo Company" + }, "818724": { "vendor": "Garmin International" }, @@ -42320,6 +42350,9 @@ "828458": { "vendor": "OB Telecom Electronic Technology Co., Ltd" }, + "829004": { + "vendor": "Hangzhou Ezviz Software Co.,Ltd." + }, "829076": { "vendor": "Sunitec Enterprise Co.,Ltd" }, @@ -42584,6 +42617,9 @@ "844004": { "vendor": "Plantronics, Inc." }, + "844028": { + "vendor": "Edgecore Americas Networking Corporation" + }, "844121": { "vendor": "Shenzhen iStartek Technology Co., Ltd." }, @@ -43364,6 +43400,9 @@ "1085692": { "vendor": "Shenzhen DOOGEE Hengtong Technology CO.,LTD" }, + "1085798": { + "vendor": "Shenzhen Yinwang Intelligent Technologies Co.,Ltd." + }, "1085864": { "vendor": "Espressif Inc." }, @@ -43463,6 +43502,9 @@ "1090488": { "vendor": "Iskratel d.o.o." }, + "1090640": { + "vendor": "Kwikset" + }, "1090745": { "vendor": "Baidu Online Network Technology (Beijing) Co., Ltd" }, @@ -43556,6 +43598,9 @@ "1096190": { "vendor": "Lika srl" }, + "1096218": { + "vendor": "SHENZHEN IK WORLD Technology Co., Ltd" + }, "1096357": { "vendor": "Gana I&C Co., Ltd" }, @@ -43634,6 +43679,9 @@ "1099516": { "vendor": "Garmin International" }, + "1099573": { + "vendor": "Microsoft Corporation" + }, "1099583": { "vendor": "Midas Klark Teknik Ltd" }, @@ -43898,6 +43946,9 @@ "1312736": { "vendor": "Abrantix AG" }, + "1312773": { + "vendor": "Sky Uk Limited" + }, "1313204": { "vendor": "zte corporation" }, @@ -44666,6 +44717,9 @@ "1358184": { "vendor": "Huawei Technologies Co.,Ltd" }, + "1358511": { + "vendor": "BKS GmbH" + }, "1358702": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -44828,6 +44882,9 @@ "1370546": { "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" }, + "1370723": { + "vendor": "Hui Zhou Gaoshengda Technology Co.,LTD" + }, "1370785": { "vendor": "Micronet union Technology (chengdu) co., Ltd" }, @@ -44936,6 +44993,9 @@ "1574674": { "vendor": "Shenzhen Dazoo Technologies CO.,Ltd" }, + "1575707": { + "vendor": "Amazon Technologies Inc." + }, "1575762": { "vendor": "Nanotron Technologies GmbH" }, @@ -45347,6 +45407,9 @@ "1597476": { "vendor": "Hewlett Packard" }, + "1597505": { + "vendor": "Arcadyan Corporation" + }, "1597895": { "vendor": "lemonbeat GmbH" }, @@ -46928,6 +46991,9 @@ "1888698": { "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" }, + "1888727": { + "vendor": "Hangzhou BroadLink Technology Co., Ltd" + }, "1888736": { "vendor": "Cisco Systems, Inc" }, @@ -47051,6 +47117,9 @@ "1898704": { "vendor": "Samsung Electronics Co.,Ltd" }, + "1898965": { + "vendor": "Apple, Inc." + }, "1899112": { "vendor": "Tp-Link Technologies Co.,Ltd." }, @@ -47300,6 +47369,9 @@ "2110715": { "vendor": "Xiaomi Communications Co Ltd" }, + "2110787": { + "vendor": "Sagemcom Broadband SAS" + }, "2111014": { "vendor": "TP-Link Corporation Limited" }, @@ -48053,6 +48125,9 @@ "2158740": { "vendor": "Google, Inc." }, + "2158880": { + "vendor": "Cisco Systems, Inc" + }, "2158972": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -48521,6 +48596,9 @@ "2383051": { "vendor": "AXIe Consortium, Inc." }, + "2383250": { + "vendor": "Juniper Networks" + }, "2383432": { "vendor": "Apple, Inc." }, @@ -49157,6 +49235,9 @@ "2421510": { "vendor": "Itel Mobile Limited" }, + "2421731": { + "vendor": "eero inc." + }, "2422142": { "vendor": "Hwh Co., Ltd." }, @@ -49178,6 +49259,9 @@ "2423653": { "vendor": "Huawei Technologies Co.,Ltd" }, + "2423779": { + "vendor": "HP Inc." + }, "2423886": { "vendor": "Juniper Networks" }, @@ -51323,6 +51407,9 @@ "2940978": { "vendor": "TCL King Electrical Appliances(Huizhou)Co.,Ltd" }, + "2941081": { + "vendor": "Fujian Star-Net Communication Co.,Ltd" + }, "2941608": { "vendor": "DeviceDesign" }, @@ -51632,6 +51719,9 @@ "3159250": { "vendor": "Availink, Inc." }, + "3159259": { + "vendor": "LG Innotek" + }, "3159286": { "vendor": "Vantiva Connected Home - Subcomponents" }, @@ -52193,6 +52283,12 @@ "3193725": { "vendor": "OnePlus Technology (Shenzhen) Co., Ltd" }, + "3194131": { + "vendor": "Zyxel Communications Corporation" + }, + "3194409": { + "vendor": "AltoBeam Inc." + }, "3194427": { "vendor": "Mitsubishi Electric Corporation" }, @@ -52907,6 +53003,9 @@ "3434105": { "vendor": "Huawei Technologies Co.,Ltd" }, + "3434129": { + "vendor": "Apple, Inc." + }, "3434218": { "vendor": "Vertu International Corporation Limited" }, @@ -53105,6 +53204,9 @@ "3444050": { "vendor": "Sichuan Tianyi Comheart Telecom Co.,LTD" }, + "3444361": { + "vendor": "Hangzhou BroadLink Technology Co., Ltd" + }, "3444519": { "vendor": "Ruckus Wireless" }, @@ -53429,6 +53531,9 @@ "3462371": { "vendor": "Atom Power, Inc." }, + "3462409": { + "vendor": "Genexis B.V." + }, "3462803": { "vendor": "Huawei Device Co., Ltd." }, @@ -53450,6 +53555,9 @@ "3463254": { "vendor": "Shenzhen Skyworth Digital Technology CO., Ltd" }, + "3463272": { + "vendor": "Broadcom Limited" + }, "3463508": { "vendor": "WiBotic Inc." }, @@ -54156,7 +54264,7 @@ "vendor": "Euronda SpA" }, "3700685": { - "vendor": "Kokusai Electric Corporation" + "vendor": "KOKUSAI DENKI Electric Inc." }, "3700834": { "vendor": "Sony Corporation" @@ -54236,6 +54344,9 @@ "3705936": { "vendor": "LG Electronics" }, + "3706173": { + "vendor": "Wistron Neweb Corporation" + }, "3706490": { "vendor": "Autoit" }, @@ -54362,6 +54473,9 @@ "3713514": { "vendor": "Hk Dapu Electronic Technology Co., Limited" }, + "3713545": { + "vendor": "Cisco Systems, Inc" + }, "3713568": { "vendor": "zte corporation" }, @@ -54473,6 +54587,9 @@ "3719866": { "vendor": "Cctv Neotech" }, + "3720250": { + "vendor": "Apple, Inc." + }, "3720424": { "vendor": "NSS Sp. z o.o." }, @@ -54539,6 +54656,9 @@ "3724832": { "vendor": "Limidea Concept Pte. Ltd." }, + "3725024": { + "vendor": "TOPDON TECHNOLOGY Co.,Ltd." + }, "3725258": { "vendor": "7Hugs Labs" }, @@ -54938,6 +55058,9 @@ "3938903": { "vendor": "Cardiopulmonary Corp" }, + "3938917": { + "vendor": "Nokia" + }, "3938937": { "vendor": "Huayuan Technology CO.,LTD" }, @@ -55277,6 +55400,9 @@ "3959463": { "vendor": "Intel Corporate" }, + "3959506": { + "vendor": "TP-Link Systems Inc." + }, "3960166": { "vendor": "NVIDIA Corporation" }, @@ -55466,6 +55592,9 @@ "3970830": { "vendor": "Wistron InfoComm(Kunshan)Co.,Ltd." }, + "3970850": { + "vendor": "shenzhen worldelite electronics co., LTD" + }, "3970942": { "vendor": "IPS Technology Limited" }, @@ -55640,6 +55769,9 @@ "3980496": { "vendor": "zte corporation" }, + "3980564": { + "vendor": "Diebold Nixdorf" + }, "3980606": { "vendor": "Beijing Xiaomi Electronics Co., Ltd." }, @@ -57053,6 +57185,9 @@ "4460802": { "vendor": "EDMI Europe Ltd" }, + "4460870": { + "vendor": "The Chamberlain Group, Inc" + }, "4460994": { "vendor": "Telegartner Karl Gartner GmbH" }, @@ -57656,6 +57791,9 @@ "4497464": { "vendor": "Huawei Device Co., Ltd." }, + "4497678": { + "vendor": "Apple, Inc." + }, "4497809": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -57788,6 +57926,9 @@ "4505948": { "vendor": "Texas Instruments" }, + "4506124": { + "vendor": "Cisco Systems, Inc" + }, "4506163": { "vendor": "Guangzhou Comet Technology Development Co.Ltd" }, @@ -58688,6 +58829,9 @@ "4754531": { "vendor": "Huawei Device Co., Ltd." }, + "4754552": { + "vendor": "Alpha Networks Inc." + }, "4754742": { "vendor": "Arcadyan Corporation" }, @@ -59120,6 +59264,9 @@ "4779654": { "vendor": "UTStarcom (China) Co.,Ltd" }, + "4779746": { + "vendor": "Roamwifi Technology(Hk) Limited" + }, "4779873": { "vendor": "Huawei Device Co., Ltd." }, @@ -59513,6 +59660,9 @@ "4999503": { "vendor": "zte corporation" }, + "4999528": { + "vendor": "Ruijie Networks Co.,LTD" + }, "4999532": { "vendor": "Intel Corporate" }, @@ -59792,6 +59942,9 @@ "5014494": { "vendor": "Cisco SPVTG" }, + "5014922": { + "vendor": "Buffalo.Inc" + }, "5015389": { "vendor": "Bose Corporation" }, @@ -60293,6 +60446,9 @@ "5243104": { "vendor": "Cisco Systems, Inc" }, + "5243110": { + "vendor": "Mellanox Technologies, Inc." + }, "5243243": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -60353,6 +60509,9 @@ "5245746": { "vendor": "Foxda Technology Industrial(ShenZhen)Co.,LTD" }, + "5245832": { + "vendor": "Moxa.Inc" + }, "5246573": { "vendor": "TrafficCast International" }, @@ -60371,9 +60530,15 @@ "5247773": { "vendor": "Motorola Mobility LLC, a Lenovo Company" }, + "5247845": { + "vendor": "Vola Networks Inc." + }, "5247893": { "vendor": "Sichuan AI-Link Technology Co., Ltd." }, + "5247901": { + "vendor": "Sierra Wireless, ULC" + }, "5248008": { "vendor": "AiNET" }, @@ -60708,7 +60873,7 @@ "vendor": "Texas Instruments" }, "5265064": { - "vendor": "Jolla Ltd" + "vendor": "Jollyboys Ltd" }, "5265087": { "vendor": "Samsung Electronics Co.,Ltd" @@ -61367,6 +61532,9 @@ "5303700": { "vendor": "Egatel Sl" }, + "5303858": { + "vendor": "Hon Hai Precision Industry Co.,LTD" + }, "5304323": { "vendor": "Open Stack, Inc." }, @@ -61511,6 +61679,9 @@ "5507722": { "vendor": "Jlztlink Industry(ShenZhen)Co.,Ltd." }, + "5508022": { + "vendor": "Variscite LTD" + }, "5508601": { "vendor": "Huawei Device Co., Ltd." }, @@ -61631,6 +61802,9 @@ "5514730": { "vendor": "Huawei Technologies Co.,Ltd" }, + "5514813": { + "vendor": "Sony Corporation" + }, "5514902": { "vendor": "Apple, Inc." }, @@ -61733,6 +61907,9 @@ "5520086": { "vendor": "Samsung Electronics Co.,Ltd" }, + "5520095": { + "vendor": "Qualfiber Technology Co.,Ltd" + }, "5520176": { "vendor": "duagon AG" }, @@ -61907,6 +62084,9 @@ "5531398": { "vendor": "Guangdong Oppo Mobile Telecommunications Corp.,Ltd" }, + "5531465": { + "vendor": "Google, Inc." + }, "5531473": { "vendor": "Compal Broadband Networks, Inc." }, @@ -62015,6 +62195,9 @@ "5537832": { "vendor": "Hewlett Packard Enterprise" }, + "5537930": { + "vendor": "Pt. Bizlink Technology Indonesia" + }, "5538093": { "vendor": "PAX Computer Technology(Shenzhen) Ltd." }, @@ -63305,6 +63488,9 @@ "5821706": { "vendor": "Murata Manufacturing Co., Ltd." }, + "5821747": { + "vendor": "Huaqin Technology Co.,Ltd" + }, "5821806": { "vendor": "D-Link International" }, @@ -63465,7 +63651,7 @@ "vendor": "Tozo Inc" }, "5831880": { - "vendor": "LenelS2 Carrier" + "vendor": "Honeywell" }, "5831907": { "vendor": "Funshion Online Technologies Co.,Ltd" @@ -63533,6 +63719,9 @@ "6030426": { "vendor": "Company NA Stage & Light" }, + "6030864": { + "vendor": "Cisco Meraki" + }, "6031192": { "vendor": "Ufispace Co., LTD." }, @@ -63917,6 +64106,9 @@ "6054074": { "vendor": "HP Inc." }, + "6054226": { + "vendor": "NXP Semiconductor (Tianjin) LTD." + }, "6054297": { "vendor": "Cloud Network Technology Singapore Pte. Ltd." }, @@ -64028,6 +64220,9 @@ "6061437": { "vendor": "Vantiva USA LLC" }, + "6061486": { + "vendor": "zte corporation" + }, "6061555": { "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" }, @@ -64106,6 +64301,9 @@ "6065486": { "vendor": "Apple, Inc." }, + "6065680": { + "vendor": "TimeWatch Infocom Pvt. Ltd." + }, "6065803": { "vendor": "Shenzhen Linghai Electronics Co.,Ltd" }, @@ -64163,6 +64361,9 @@ "6068952": { "vendor": "Fujitsu Limited" }, + "6069158": { + "vendor": "Apple, Inc." + }, "6070380": { "vendor": "Realme Chongqing Mobile Telecommunications Corp.,Ltd." }, @@ -64226,6 +64427,9 @@ "6073718": { "vendor": "Shenzhen TCL New Technology Co., Ltd" }, + "6073786": { + "vendor": "Apple, Inc." + }, "6073807": { "vendor": "Apple, Inc." }, @@ -64388,6 +64592,9 @@ "6081916": { "vendor": "MEIZU Technology Co.,Ltd." }, + "6081960": { + "vendor": "Itel Mobile Limited" + }, "6082221": { "vendor": "CDYNE Corporation" }, @@ -64889,6 +65096,9 @@ "6307113": { "vendor": "Huawei Technologies Co.,Ltd" }, + "6307169": { + "vendor": "Private" + }, "6307423": { "vendor": "Apple, Inc." }, @@ -65765,6 +65975,9 @@ "6554107": { "vendor": "Landis+Gyr GmbH" }, + "6554255": { + "vendor": "Silicon Laboratories" + }, "6554315": { "vendor": "Commscope" }, @@ -66017,6 +66230,9 @@ "6570822": { "vendor": "GuangDong Quick Network Computer CO.,LTD" }, + "6571131": { + "vendor": "vivo Mobile Communication Co., Ltd." + }, "6571221": { "vendor": "TD Tech" }, @@ -66290,6 +66506,9 @@ "6585118": { "vendor": "Sagemcom Broadband SAS" }, + "6585152": { + "vendor": "Sichuan AI-Link Technology Co., Ltd." + }, "6585294": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -66989,6 +67208,9 @@ "6825823": { "vendor": "zte corporation" }, + "6826092": { + "vendor": "Sony Interactive Entertainment Inc." + }, "6826170": { "vendor": "Dejai" }, @@ -67256,6 +67478,9 @@ "6842149": { "vendor": "Espressif Inc." }, + "6842311": { + "vendor": "Sagemcom Broadband SAS" + }, "6842670": { "vendor": "Zycoo Co.,Ltd" }, @@ -67946,6 +68171,9 @@ "7079034": { "vendor": "Huawei Technologies Co.,Ltd" }, + "7079379": { + "vendor": "China Dragon Technology Limited" + }, "7079381": { "vendor": "Ethertronics Inc" }, @@ -68471,6 +68699,9 @@ "7109048": { "vendor": "Texas Instruments" }, + "7110071": { + "vendor": "Cisco Meraki" + }, "7110247": { "vendor": "Apple, Inc." }, @@ -69092,6 +69323,9 @@ "7344897": { "vendor": "Vantiva - Connected Home" }, + "7345028": { + "vendor": "Apple, Inc." + }, "7345156": { "vendor": "Limited Liability Company" }, @@ -69126,7 +69360,7 @@ "vendor": "Intel Corporate" }, "7346901": { - "vendor": "Openpath Security, Inc." + "vendor": "Avigilon Alta" }, "7346925": { "vendor": "Advas Co., Ltd." @@ -69515,6 +69749,9 @@ "7366369": { "vendor": "dnt Innovation GmbH" }, + "7366769": { + "vendor": "FN-LINK TECHNOLOGY Ltd." + }, "7366777": { "vendor": "Saijo Denki International Co., Ltd." }, @@ -69806,6 +70043,9 @@ "7382732": { "vendor": "Intel Corporate" }, + "7382787": { + "vendor": "Honor Device Co., Ltd." + }, "7382849": { "vendor": "Ubiquiti Inc" }, @@ -70097,6 +70337,9 @@ "7400676": { "vendor": "Apple, Inc." }, + "7400954": { + "vendor": "imperix Ltd" + }, "7401040": { "vendor": "Netatmo" }, @@ -70238,6 +70481,9 @@ "7605979": { "vendor": "Optowiz Co., Ltd" }, + "7606496": { + "vendor": "Broadcom Limited" + }, "7606706": { "vendor": "Cisco Systems, Inc" }, @@ -70703,6 +70949,9 @@ "7632351": { "vendor": "Teclink" }, + "7632415": { + "vendor": "Microsoft Corporation" + }, "7632475": { "vendor": "Quectel Wireless Solutions Co.,Ltd." }, @@ -70982,6 +71231,9 @@ "7646647": { "vendor": "China Mobile Group Device Co.,Ltd." }, + "7646667": { + "vendor": "New H3C Technologies Co., Ltd" + }, "7646838": { "vendor": "iNovo Broadband, Inc." }, @@ -71348,6 +71600,9 @@ "7666122": { "vendor": "Nintendo Co.,Ltd" }, + "7666455": { + "vendor": "Qingdao Goertek Horizons Tecnology Co.,LTD" + }, "7667104": { "vendor": "Compupal (Group) Corporation" }, @@ -71492,6 +71747,9 @@ "7871578": { "vendor": "SHARP Corporation" }, + "7871645": { + "vendor": "Silicon Laboratories" + }, "7871818": { "vendor": "zte corporation" }, @@ -71672,6 +71930,9 @@ "7880469": { "vendor": "EasySYNC Ltd." }, + "7880525": { + "vendor": "Apple, Inc." + }, "7880932": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -72215,6 +72476,9 @@ "7910029": { "vendor": "Beijing Tengling Technology CO.Ltd" }, + "7910303": { + "vendor": "Sernet (Suzhou) Technologies Corporation" + }, "7910329": { "vendor": "ShangHai sunup lighting CO.,LTD" }, @@ -72419,6 +72683,9 @@ "7920290": { "vendor": "Cynosure Technologies Co.,Ltd" }, + "7920303": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "7920307": { "vendor": "GBO Technology" }, @@ -73223,6 +73490,9 @@ "8162250": { "vendor": "Tp-Link Technologies Co.,Ltd." }, + "8162313": { + "vendor": "Mellanox Technologies, Inc." + }, "8162705": { "vendor": "Shanghai Hongzhuo Information Technology co.,LTD" }, @@ -73382,6 +73652,9 @@ "8172959": { "vendor": "Huawei Technologies Co.,Ltd" }, + "8173197": { + "vendor": "Mist Systems, Inc." + }, "8173363": { "vendor": "Askey Computer Corp" }, @@ -73412,6 +73685,9 @@ "8174854": { "vendor": "AE REFUsol" }, + "8175310": { + "vendor": "Private" + }, "8175479": { "vendor": "Speedtech Corp. Jio" }, @@ -73490,6 +73766,9 @@ "8177879": { "vendor": "Damalisk" }, + "8177887": { + "vendor": "Apple, Inc." + }, "8177958": { "vendor": "Wuhan GreeNet Information Service Co.,Ltd." }, @@ -73568,6 +73847,9 @@ "8182680": { "vendor": "Askey Computer Corp" }, + "8182899": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "8182988": { "vendor": "Beijing Starblaze Technology Co.,Ltd" }, @@ -74333,6 +74615,9 @@ "8422133": { "vendor": "STMicrolectronics International NV" }, + "8422390": { + "vendor": "Apple, Inc." + }, "8422569": { "vendor": "oshkosh Corporation" }, @@ -74438,6 +74723,9 @@ "8429622": { "vendor": "Shanghai MXCHIP Information Technology Co., Ltd." }, + "8429975": { + "vendor": "u-blox AG" + }, "8429995": { "vendor": "Intellisis" }, @@ -74612,6 +74900,9 @@ "8440395": { "vendor": "Shenzhen Gongjin Electronics Co.,Ltd" }, + "8440402": { + "vendor": "Wistron InfoComm(Chongqing)Co.,Ltd." + }, "8440764": { "vendor": "Qingdao Intelligent&Precise Electronics Co.,Ltd." }, @@ -74768,6 +75059,9 @@ "8451055": { "vendor": "Meta Platforms Technologies, LLC" }, + "8451094": { + "vendor": "Chipsea Technologies (Shenzhen) Corp." + }, "8451331": { "vendor": "Commscope" }, @@ -74984,6 +75278,9 @@ "8661082": { "vendor": "Saffron Solutions Inc" }, + "8661206": { + "vendor": "Servercom (India) Private Limited" + }, "8661268": { "vendor": "EMPORIA TELECOM Produktions- und VertriebsgesmbH & Co KG" }, @@ -75122,6 +75419,9 @@ "8669461": { "vendor": "vArmour Networks, Inc." }, + "8669678": { + "vendor": "Demant Enterprise A/S" + }, "8670135": { "vendor": "Beijing Sankuai Online Technology Co.,Ltd" }, @@ -75428,6 +75728,9 @@ "8689281": { "vendor": "Cathay Communication Co.,Ltd" }, + "8689296": { + "vendor": "Murata Manufacturing Co., Ltd." + }, "8689368": { "vendor": "Commscope" }, @@ -75497,6 +75800,9 @@ "8693640": { "vendor": "Perples" }, + "8693796": { + "vendor": "Google, Inc." + }, "8693988": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -75800,6 +76106,9 @@ "8710809": { "vendor": "Vieworks" }, + "8710866": { + "vendor": "Koganei Corporation" + }, "8710893": { "vendor": "Roku, Inc" }, @@ -75866,6 +76175,9 @@ "8713987": { "vendor": "Espressif Inc." }, + "8714072": { + "vendor": "Huizhou BYD Electronic Co., Ltd." + }, "8714371": { "vendor": "Luminar Technologies" }, @@ -75887,6 +76199,9 @@ "8715729": { "vendor": "Intel Corporate" }, + "8715840": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "8715934": { "vendor": "RTC Industries, Inc." }, @@ -75944,6 +76259,9 @@ "8916752": { "vendor": "Huami Information Technology Co.,Ltd." }, + "8916834": { + "vendor": "Silicon Laboratories" + }, "8916898": { "vendor": "Sagemcom Broadband SAS" }, @@ -76232,6 +76550,9 @@ "8933754": { "vendor": "HMD Global Oy" }, + "8933874": { + "vendor": "Apple, Inc." + }, "8933883": { "vendor": "Hewlett Packard" }, @@ -76295,6 +76616,9 @@ "8938077": { "vendor": "Bitnetworks Co.,Ltd" }, + "8938437": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "8938463": { "vendor": "Apple, Inc." }, @@ -76512,7 +76836,7 @@ "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" }, "8950926": { - "vendor": "Max Weishaupt GmbH" + "vendor": "Max Weishaupt SE" }, "8950927": { "vendor": "Xi'an Zhisensor Technologies Co.,Ltd" @@ -76568,6 +76892,9 @@ "8953448": { "vendor": "Vantiva USA LLC" }, + "8953494": { + "vendor": "zte corporation" + }, "8953711": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -77684,6 +78011,9 @@ "9212753": { "vendor": "Jigowatts Inc." }, + "9212811": { + "vendor": "Realme Chongqing Mobile Telecommunications Corp.,Ltd." + }, "9212959": { "vendor": "Cisco Systems, Inc" }, @@ -77735,6 +78065,9 @@ "9217759": { "vendor": "Tp-Link Technologies Co.,Ltd." }, + "9218413": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "9218415": { "vendor": "D&M Holdings Inc." }, @@ -77768,6 +78101,9 @@ "9221711": { "vendor": "Cisco Systems, Inc" }, + "9221829": { + "vendor": "Mimosa Networks" + }, "9222135": { "vendor": "Shenzhen UniStrong Science & Technology Co., Ltd" }, @@ -78356,6 +78692,9 @@ "9452723": { "vendor": "Edgecore Networks Corporation" }, + "9452762": { + "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" + }, "9452890": { "vendor": "Shenzhen Wision Technology Holding Limited" }, @@ -78764,6 +79103,9 @@ "9475300": { "vendor": "D-Link International" }, + "9475335": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "9475827": { "vendor": "Buffalo.Inc" }, @@ -78953,6 +79295,9 @@ "9485798": { "vendor": "Quectel Wireless Solutions Co.,Ltd." }, + "9486297": { + "vendor": "Smart Innovation LLC" + }, "9486613": { "vendor": "Sony Corporation" }, @@ -79001,6 +79346,9 @@ "9489846": { "vendor": "Hon Hai Precision Ind. Co.,Ltd." }, + "9489896": { + "vendor": "Apple, Inc." + }, "9490104": { "vendor": "Texas Instruments" }, @@ -79304,6 +79652,9 @@ "9702731": { "vendor": "Cisco Systems, Inc" }, + "9702954": { + "vendor": "NXP Semiconductors Taiwan Ltd." + }, "9703019": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -79367,6 +79718,9 @@ "9707927": { "vendor": "Stalmart Technology Limited" }, + "9708108": { + "vendor": "Qingdao Haier Technology Co.,Ltd" + }, "9708398": { "vendor": "Shenzhen Junlan Electronic Ltd" }, @@ -79697,6 +80051,9 @@ "9730328": { "vendor": "Itel Mobile Limited" }, + "9730804": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "9730990": { "vendor": "Xiaomi Communications Co Ltd" }, @@ -80381,6 +80738,9 @@ "9962378": { "vendor": "Texas Instruments" }, + "9962382": { + "vendor": "TP-Link Systems Inc." + }, "9962395": { "vendor": "Mellanox Technologies, Inc." }, @@ -80993,6 +81353,9 @@ "10002019": { "vendor": "Apple, Inc." }, + "10002202": { + "vendor": "Private" + }, "10002206": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -81263,6 +81626,9 @@ "10020762": { "vendor": "Foxconn(NanJing) Communication Co.,Ltd." }, + "10020821": { + "vendor": "NXP Semiconductor (Tianjin) LTD." + }, "10020852": { "vendor": "Hewlett Packard" }, @@ -81716,6 +82082,9 @@ "10242683": { "vendor": "Nokia Corporation" }, + "10242923": { + "vendor": "iFlight Technology Company Limited" + }, "10243246": { "vendor": "Mesa Labs" }, @@ -81962,6 +82331,9 @@ "10254764": { "vendor": "Suntec Software(Shanghai) Co., Ltd." }, + "10254819": { + "vendor": "Apple, Inc." + }, "10254851": { "vendor": "Ciena Corporation" }, @@ -83006,6 +83378,9 @@ "10512964": { "vendor": "Vizio, Inc" }, + "10513226": { + "vendor": "TCT mobile ltd" + }, "10513509": { "vendor": "Texas Instruments" }, @@ -83210,6 +83585,9 @@ "10525274": { "vendor": "Time Domain" }, + "10525326": { + "vendor": "Apple, Inc." + }, "10525458": { "vendor": "China Mobile IOT Company Limited" }, @@ -83372,6 +83750,9 @@ "10534173": { "vendor": "Zhejiang Dahua Technology Co., Ltd." }, + "10534257": { + "vendor": "QUALCOMM Incorporated" + }, "10534349": { "vendor": "Sky Uk Limited" }, @@ -83381,6 +83762,9 @@ "10534821": { "vendor": "Coresys" }, + "10534934": { + "vendor": "Sichuan Changhong Network Technologies Co., Ltd." + }, "10535437": { "vendor": "Huawei Device Co., Ltd." }, @@ -83402,6 +83786,9 @@ "10536684": { "vendor": "ShenZhen ANYK Technology Co.,LTD" }, + "10536914": { + "vendor": "Cisco Systems, Inc" + }, "10537355": { "vendor": "Nokia Solutions and Networks GmbH & Co. KG" }, @@ -83513,6 +83900,9 @@ "10543141": { "vendor": "Provision-ISR" }, + "10543213": { + "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" + }, "10543279": { "vendor": "Cisco Systems, Inc" }, @@ -84197,6 +84587,9 @@ "10780410": { "vendor": "Withings" }, + "10780443": { + "vendor": "Juniper Networks" + }, "10781050": { "vendor": "Cig Shanghai Co Ltd" }, @@ -85004,6 +85397,9 @@ "11027585": { "vendor": "Nokia Corporation" }, + "11027626": { + "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" + }, "11027917": { "vendor": "Siselectron Technology LTD." }, @@ -85106,6 +85502,9 @@ "11033527": { "vendor": "Apple, Inc." }, + "11033553": { + "vendor": "Inventec Corporation" + }, "11033587": { "vendor": "Audivo GmbH" }, @@ -85608,7 +86007,7 @@ "vendor": "Lightware Visual Engineering" }, "11064264": { - "vendor": "Topcon Electronics GmbH & Co. KG" + "vendor": "Wachendorff Automation GmbH & CO.KG" }, "11064311": { "vendor": "Arcadyan Technology Corporation" @@ -86735,6 +87134,9 @@ "11323701": { "vendor": "Ness Corporation" }, + "11323919": { + "vendor": "Indisr Communication Services And Technologies India" + }, "11323988": { "vendor": "Telldus Technologies AB" }, @@ -86813,6 +87215,9 @@ "11327655": { "vendor": "BELLDESIGN Inc." }, + "11327785": { + "vendor": "Quectel Wireless Solutions Co.,Ltd." + }, "11327958": { "vendor": "tci GmbH" }, @@ -87056,6 +87461,9 @@ "11540291": { "vendor": "Edison Global Circuits Llc" }, + "11540529": { + "vendor": "Apple, Inc." + }, "11540614": { "vendor": "SmarDTV Corporation" }, @@ -88109,6 +88517,9 @@ "11800499": { "vendor": "vivo Mobile Communication Co., Ltd." }, + "11800698": { + "vendor": "Amazon Technologies Inc." + }, "11800699": { "vendor": "Texas Instruments" }, @@ -88427,6 +88838,9 @@ "11821935": { "vendor": "Nokia Solutions and Networks GmbH & Co. KG" }, + "11822101": { + "vendor": "Guangzhou V-Solution Telecommunication Technology Co.,Ltd." + }, "11822744": { "vendor": "Zealabs srl" }, @@ -89159,6 +89573,9 @@ "12064475": { "vendor": "Chant Sincere Co.,Ltd" }, + "12064579": { + "vendor": "shenzhen worldelite electronics co., LTD" + }, "12064706": { "vendor": "Apple, Inc." }, @@ -89594,6 +90011,9 @@ "12093382": { "vendor": "Prudential Technology co.,LTD" }, + "12093568": { + "vendor": "Shanghai Imilab Technology Co.Ltd" + }, "12093667": { "vendor": "Compal Information (Kunshan) Co., Ltd." }, @@ -90227,6 +90647,9 @@ "12322349": { "vendor": "Wacom Co.,Ltd." }, + "12322589": { + "vendor": "TP-Link Systems Inc." + }, "12322918": { "vendor": "Nestle Purina PetCare" }, @@ -90479,6 +90902,9 @@ "12336647": { "vendor": "Hitron Technologies. Inc" }, + "12336651": { + "vendor": "Panasonic Connect Co., Ltd." + }, "12336659": { "vendor": "Accordance Systems Inc." }, @@ -90611,6 +91037,9 @@ "12344883": { "vendor": "Hangzhou Hikvision Digital Technology Co.,Ltd." }, + "12344977": { + "vendor": "Honor Device Co., Ltd." + }, "12344993": { "vendor": "PsiKick, Inc." }, @@ -90797,6 +91226,9 @@ "12354902": { "vendor": "Hon Hai Precision Ind. Co.,Ltd." }, + "12355024": { + "vendor": "Sky Uk Limited" + }, "12355578": { "vendor": "Bose Corporation" }, @@ -90905,6 +91337,9 @@ "12361403": { "vendor": "Nintendo Co.,Ltd" }, + "12361560": { + "vendor": "Apple, Inc." + }, "12361700": { "vendor": "Hewlett Packard Enterprise" }, @@ -90923,6 +91358,9 @@ "12362042": { "vendor": "VusionGroup" }, + "12362289": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "12362623": { "vendor": "Rail-Mil Sp. z o.o. Sp. K." }, @@ -93317,6 +93755,9 @@ "12903327": { "vendor": "Guangdong Oppo Mobile Telecommunications Corp.,Ltd" }, + "12903374": { + "vendor": "EnGenius Technologies, Inc." + }, "12903686": { "vendor": "Piper Networks, Inc." }, @@ -93746,6 +94187,9 @@ "13125516": { "vendor": "Beken Corporation" }, + "13125637": { + "vendor": "Nintendo Co.,Ltd" + }, "13125877": { "vendor": "MEDISON Xray Co., Ltd" }, @@ -94025,6 +94469,9 @@ "13144202": { "vendor": "Samsung Electronics Co.,Ltd" }, + "13144232": { + "vendor": "Bouffalo Lab (Nanjing) Co., Ltd." + }, "13144569": { "vendor": "Sagemcom Broadband SAS" }, @@ -94124,6 +94571,9 @@ "13149197": { "vendor": "Cooler Master Technology Inc" }, + "13149389": { + "vendor": "Realme Chongqing Mobile Telecommunications Corp.,Ltd." + }, "13149704": { "vendor": "Ruckus Wireless" }, @@ -94163,6 +94613,9 @@ "13150924": { "vendor": "Private" }, + "13151285": { + "vendor": "PiLink Co., Ltd." + }, "13151900": { "vendor": "Shanghai TYD Elecronic Technology Co. Ltd" }, @@ -95363,6 +95816,9 @@ "13414682": { "vendor": "Samsung Electronics Co.,Ltd" }, + "13414728": { + "vendor": "Arcadyan Corporation" + }, "13414786": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -95996,6 +96452,9 @@ "13651244": { "vendor": "Roku, Inc." }, + "13651334": { + "vendor": "Apple, Inc." + }, "13651398": { "vendor": "Hewlett Packard Enterprise" }, @@ -96116,6 +96575,9 @@ "13655162": { "vendor": "Sartura d.o.o." }, + "13655983": { + "vendor": "Shenzhen C-Data Technology Co., Ltd." + }, "13655992": { "vendor": "Texas Instruments" }, @@ -96281,6 +96743,9 @@ "13665456": { "vendor": "Sagemcom Broadband SAS" }, + "13665603": { + "vendor": "Cisco Systems, Inc" + }, "13666229": { "vendor": "Safemo Pte. Ltd." }, @@ -96392,6 +96857,9 @@ "13674963": { "vendor": "EM Microelectronic" }, + "13675338": { + "vendor": "Telink Micro LLC" + }, "13675477": { "vendor": "Intel Corporate" }, @@ -97389,7 +97857,7 @@ "vendor": "Apple, Inc." }, "13930720": { - "vendor": "Topcon Electronics GmbH & Co. KG" + "vendor": "Wachendorff Automation GmbH & CO.KG" }, "13930767": { "vendor": "Amazon Technologies Inc." @@ -97763,6 +98231,12 @@ "13951941": { "vendor": "zte corporation" }, + "13952195": { + "vendor": "Ciena Corporation" + }, + "13952457": { + "vendor": "Senao Networks Inc." + }, "13952695": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -97913,6 +98387,9 @@ "14157521": { "vendor": "Honeywell Fire System (Shanghai) Co,. Ltd." }, + "14157555": { + "vendor": "Arista Networks" + }, "14157750": { "vendor": "Tp-Link Technologies Co.,Ltd." }, @@ -97961,6 +98438,9 @@ "14159769": { "vendor": "Hon Hai Precision Ind. Co.,Ltd." }, + "14159797": { + "vendor": "Shenzhen Ultraeasy Technology Co Ltd" + }, "14159976": { "vendor": "Murata Manufacturing Co., Ltd." }, @@ -98408,6 +98888,12 @@ "14185621": { "vendor": "zte corporation" }, + "14185695": { + "vendor": "Huawei Technologies Co.,Ltd" + }, + "14185711": { + "vendor": "Guangzhou Shiyuan Electronic Technology Company Limited" + }, "14185779": { "vendor": "Nokia Corporation" }, @@ -98441,6 +98927,9 @@ "14187741": { "vendor": "Sanix Incorporated" }, + "14187845": { + "vendor": "Nicent Technology Co., Ltd." + }, "14187903": { "vendor": "Sagemcom Broadband SAS" }, @@ -99269,6 +99758,9 @@ "14430673": { "vendor": "vivo Mobile Communication Co., Ltd." }, + "14430818": { + "vendor": "Nanjing Qinheng Microelectronics Co., Ltd." + }, "14430989": { "vendor": "Qing Dao Haier Telecom Co.,Ltd." }, @@ -99422,6 +99914,9 @@ "14439811": { "vendor": "Guangdong Oppo Mobile Telecommunications Corp.,Ltd" }, + "14440059": { + "vendor": "Cloud Network Technology Singapore Pte. Ltd." + }, "14440166": { "vendor": "Shenzhen Bococom Technology Co.,LTD" }, @@ -99587,6 +100082,9 @@ "14452683": { "vendor": "Beijing Perfectek Technologies Co., Ltd." }, + "14452897": { + "vendor": "Itel Mobile Limited" + }, "14453123": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -100230,7 +100728,7 @@ "vendor": "Extreme Networks Headquarters" }, "14687399": { - "vendor": "Arista Networks, Inc." + "vendor": "Arista Networks" }, "14687470": { "vendor": "Bravo Tech, Inc." @@ -101447,6 +101945,9 @@ "14958948": { "vendor": "Nokia" }, + "14959060": { + "vendor": "vivo Mobile Communication Co., Ltd." + }, "14959078": { "vendor": "Ottec Technology GmbH" }, @@ -102020,6 +102521,9 @@ "14994589": { "vendor": "Integrated Device Technology (Malaysia) Sdn. Bhd." }, + "14994855": { + "vendor": "zte corporation" + }, "14994946": { "vendor": "WyreStorm Technologies Ltd" }, @@ -102209,6 +102713,9 @@ "15007137": { "vendor": "Huawei Technologies Co.,Ltd" }, + "15007299": { + "vendor": "Beijing Xiaomi Mobile Software Co., Ltd" + }, "15007449": { "vendor": "EDMI Europe Ltd" }, @@ -102668,6 +103175,9 @@ "15232218": { "vendor": "Supercomputers and Neurocomputers Research Center" }, + "15232278": { + "vendor": "Elmec Elettronica SRL" + }, "15232338": { "vendor": "Commscope" }, @@ -103205,6 +103715,9 @@ "15262178": { "vendor": "Energotest" }, + "15262877": { + "vendor": "Nexthop Systems Inc." + }, "15263190": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -104297,6 +104810,9 @@ "15522694": { "vendor": "Api-K" }, + "15523108": { + "vendor": "Cisco Systems, Inc" + }, "15523389": { "vendor": "Lamprey Networks, Inc." }, @@ -104318,6 +104834,9 @@ "15524605": { "vendor": "SKG Electric Group(Thailand) Co., Ltd." }, + "15524660": { + "vendor": "Espressif Inc." + }, "15525138": { "vendor": "tado GmbH" }, @@ -104351,6 +104870,9 @@ "15526165": { "vendor": "STI Ltd" }, + "15526389": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "15526392": { "vendor": "Guang Zhou TRI-SUN Electronics Technology Co., Ltd" }, @@ -104438,6 +104960,9 @@ "15531646": { "vendor": "BlueRadios, Inc." }, + "15531834": { + "vendor": "Apple, Inc." + }, "15728767": { "vendor": "Janz - Contadores de Energia, SA" }, @@ -104453,6 +104978,9 @@ "15729548": { "vendor": "AzureWave Technology Inc." }, + "15729596": { + "vendor": "Cisco Systems, Inc" + }, "15729889": { "vendor": "Apple, Inc." }, @@ -104876,6 +105404,9 @@ "15758477": { "vendor": "Ruijie Networks Co.,LTD" }, + "15758527": { + "vendor": "Silicon Laboratories" + }, "15758564": { "vendor": "Thundercomm Technology Co., Ltd" }, @@ -105323,6 +105854,9 @@ "15784572": { "vendor": "Rlh Industries,Inc." }, + "15784746": { + "vendor": "Lanner Electronics, Inc." + }, "15784752": { "vendor": "Yottabyte" }, @@ -105707,6 +106241,9 @@ "16003880": { "vendor": "CIMCON Lighting Inc." }, + "16003986": { + "vendor": "Cisco Systems, Inc" + }, "16004336": { "vendor": "Apple, Inc." }, @@ -106206,7 +106743,7 @@ "vendor": "Juniper Networks" }, "16037193": { - "vendor": "Xiamen Yeastar Information Technology Co., Ltd." + "vendor": "Xiamen Yeastar Digital Technology Co., Ltd" }, "16037290": { "vendor": "zte corporation" @@ -106325,6 +106862,9 @@ "16042834": { "vendor": "Huawei Technologies Co.,Ltd" }, + "16042983": { + "vendor": "Apple, Inc." + }, "16043093": { "vendor": "Juniper Networks" }, @@ -106361,6 +106901,9 @@ "16044641": { "vendor": "SEMOCON Co., Ltd" }, + "16045140": { + "vendor": "Shenzhen Skyworth Digital Technology CO., Ltd" + }, "16045192": { "vendor": "Apple, Inc." }, @@ -106847,6 +107390,9 @@ "16267392": { "vendor": "Apple, Inc." }, + "16267405": { + "vendor": "New H3C Technologies Co., Ltd" + }, "16267544": { "vendor": "Cisco Systems, Inc" }, @@ -107288,6 +107834,9 @@ "16291753": { "vendor": "Ericsson AB" }, + "16291760": { + "vendor": "Goki Pty Ltd" + }, "16291791": { "vendor": "Daeshin-Information Technology Co., Ltd." }, @@ -107846,6 +108395,9 @@ "16515090": { "vendor": "Toshiba Samsung Storage Technolgoy Korea Corporation" }, + "16515372": { + "vendor": "Espressif Inc." + }, "16515452": { "vendor": "Hon Hai Precision Ind. Co.,Ltd." }, @@ -112298,6 +112850,26 @@ } ] }, + "5776316": { + "vendor": "", + "maskedFilters": [ + { + "mask": 28, + "vendors": { + "96910503313408": "Great Wall Power Supply Technology Co., Ltd.", + "96910504361984": "SHSYSTEM.Co.,LTD", + "96910507507712": "Next Vision", + "96910508556288": "Shenzhen MinDe Electronics Technology Ltd.", + "96910509604864": "Wuhan Rayoptek Co.,Ltd", + "96910510653440": "Annapurna labs", + "96910511702016": "Hangzhou Xindatong Communication Technology Co.,Ltd.", + "96910512750592": "Annapurna labs", + "96910513799168": "Yuyao Sunny Optical Intelligence Technology Co., Ltd", + "96910514847744": "New Energy Technology Co.,Ltd" + } + } + ] + }, "5785546": { "vendor": "", "maskedFilters": [ @@ -114451,14 +115023,20 @@ "mask": 28, "vendors": { "158916625301504": "shenzhen zovoton electronic co.,ltd", + "158916626350080": "Akarui Networks Pvt Ltd", "158916627398656": "合肥乾盾智能科技有限公司", + "158916628447232": "Hangzhou Hollysys Automation Co., Ltd", "158916629495808": "asmote ltd.", "158916630544384": "Shortcut Labs AB", "158916631592960": "Skysolid Information Security Systems(Shenzhen) Co., Ltd", + "158916632641536": "Wingtech Mobile Communications Co.,Ltd.", "158916633690112": "Samway Electronic SRL", + "158916634738688": "Nanjing Boswell Industrial Communication Technology Co., Ltd", "158916635787264": "Yi Tunnel(beijing) Technology Co.,Ltd", "158916636835840": "UXV Technologies ApS", - "158916638932992": "Remowireless Communication International Co.,Limited" + "158916637884416": "Rikom Technologies Sdn Bhd", + "158916638932992": "Remowireless Communication International Co.,Limited", + "158916639981568": "TeeJet Technologies" } } ] @@ -115294,6 +115872,31 @@ } ] }, + "10770899": { + "vendor": "", + "maskedFilters": [ + { + "mask": 28, + "vendors": { + "180705699037184": "VTECH Technology Corportion", + "180705700085760": "Rheinmetall Electronics UK Ltd", + "180705701134336": "Shenzhen Welltech Cable Co., Ltd", + "180705702182912": "SoftEnergy Controls Inc.", + "180705703231488": "Gre System Inc.", + "180705704280064": "Bettear - Accessibility Technologies Development Ltd", + "180705705328640": "FrontAct Co., Ltd.", + "180705706377216": "Dong Guan Fu Qiang Electronic Co.,Ltd", + "180705707425792": "Got Co.,Ltd", + "180705708474368": "Vivi International Pty Ltd", + "180705709522944": "OREX SAI Inc.", + "180705710571520": "HANSHIN YUSOKI Co,Ltd", + "180705711620096": "Safebase AS", + "180705712668672": "Seavan Technology Limited", + "180705713717248": "Ngen d.o.o." + } + } + ] + }, "10803746": { "vendor": "", "maskedFilters": [ @@ -116928,6 +117531,31 @@ } ] }, + "13675103": { + "vendor": "", + "maskedFilters": [ + { + "mask": 28, + "vendors": { + "229430156853248": "Hangzhou Jingtang Communication Technology Co.,Ltd.", + "229430157901824": "Xiaomi EV Technology Co., Ltd.", + "229430158950400": "ACCEL LAB ltd.", + "229430159998976": "Shenzhen Liandian Communication Technology Co.LTD", + "229430161047552": "Komer", + "229430162096128": "深圳麦源实业有限公司", + "229430163144704": "Sordin Ab", + "229430164193280": "GD Midea Heating & Ventilating Equipment Co., Ltd", + "229430165241856": "WeBank Co., Ltd.", + "229430166290432": "Hongci Monitor International Co., Ltd.", + "229430167339008": "Indra Air Traffic Inc", + "229430168387584": "Warner Electronics (I) Pvt. Ltd.", + "229430169436160": "Pacific Electronics", + "229430170484736": "Level Up Holding Co., Inc.", + "229430171533312": "MBX International Ltd." + } + } + ] + }, "13682775": { "vendor": "", "maskedFilters": [ @@ -125585,7 +126213,7 @@ "123917685415936": "Lockheed Martin - THAAD", "123917685420032": "Cottonwood Creek Technologies, Inc.", "123917685424128": "FUJICOM Co.,Ltd.", - "123917685428224": "RFEL Ltd", + "123917685428224": "Rheinmetall Electronics UK Ltd", "123917685432320": "Acorde Technologies", "123917685440512": "Tband srl", "123917685444608": "Vickers Electronics Ltd", @@ -127209,6 +127837,7 @@ "154066450132992": "Avionica", "154066450141184": "Sorb Engineering Llc", "154066450145280": "WEPTECH elektronik GmbH", + "154066450157568": "Anser-Net Co., Ltd", "154066450165760": "Shanghai Shenxu Technology Co., Ltd", "154066450173952": "Neetra Srl Sb", "154066450178048": "qiio AG", @@ -127269,6 +127898,7 @@ "154066450616320": "ikan International LLC", "154066450620416": "Nautel LTD", "154066450636800": "Indra Heera Technology LLP", + "154066450640896": "Pneumax Spa", "154066450649088": "ASW-ATI Srl", "154066450657280": "Kronotech Srl", "154066450661376": "Timebeat.app Ltd", @@ -127325,6 +127955,7 @@ "154066451091456": "Xiamen Rgblink Science & Technology Co., Ltd.", "154066451095552": "Benchmark Electronics BV", "154066451103744": "Fracarro Radioindustrie Srl", + "154066451120128": "KST technology", "154066451124224": "Wuhan YiValley Opto-electric technology Co.,Ltd", "154066451132416": "Emcom Systems", "154066451140608": "Agrowtek Inc.", @@ -127342,6 +127973,7 @@ "154066451255296": "VERIDAS Digital Authentication Solutions S.L", "154066451259392": "Secuinfo Co.Ltd", "154066451263488": "TEKVOX, Inc", + "154066451267584": "Reo Ag", "154066451279872": "FeedFlo", "154066451283968": "Aton srl", "154066451300352": "Engage Technologies", @@ -127414,6 +128046,7 @@ "154066451963904": "Giordano Controls Spa", "154066451980288": "Oriux", "154066451984384": "Dadhwal Weighing Instrument Repairing Works", + "154066451992576": "Tex Computer Srl", "154066452004864": "Shenzhen Link-All Technolgy Co., Ltd", "154066452008960": "Xi'An Jiaoda Kaida New Technology Co.Ltd", "154066452021248": "Accurate Optoelectronics Pvt. Ltd.", @@ -127438,6 +128071,7 @@ "154066452164608": "Distran AG", "154066452168704": "Invixium Access Inc", "154066452197376": "Oriux", + "154066452201472": "Tactical Blue Space Ventures LLC", "154066452213760": "Whizz Systems Inc.", "154066452217856": "Heitec Ag", "154066452221952": "Nvp Teco Ltd", @@ -127490,6 +128124,7 @@ "154066452623360": "Erba Lachema s.r.o.", "154066452631552": "GS Elektromedizinsiche Geräte G. Stemple GmbH", "154066452643840": "Sonora Network Solutions", + "154066452660224": "HD Vision Systems GmbH", "154066452668416": "Qualitrol LLC", "154066452672512": "Invisense AB", "154066452676608": "Switch Science, Inc.", @@ -127549,6 +128184,7 @@ "154066453102592": "Denso Manufacturing Tennessee", "154066453118976": "Opgal Optronic Industries ltd", "154066453123072": "Security&Best", + "154066453127168": "Test21 Taiwan Corp", "154066453143552": "Power Electronics Espana, S.L.", "154066453151744": "Tilak International", "154066453155840": "Vector Technologies, Llc", @@ -127561,6 +128197,7 @@ "154066453192704": "Abbott Diagnostics Technologies AS", "154066453196800": "Sp Manufacturing Pte Ltd", "154066453200896": "WOLF Advanced Technology", + "154066453204992": "Limab Ab", "154066453209088": "WINK Streaming", "154066453217280": "Accord Communications Ltd", "154066453221376": "Duevi Srl", @@ -127654,12 +128291,15 @@ "154066453909504": "Aspen Spectra Sdn Bhd", "154066453913600": "Linxpeed Limited", "154066453917696": "Gigalane", + "154066453925888": "J B Electronics Corp", "154066453934080": "Hiwin Mikrosystem Corp.", "154066453946368": "eumig industrie-TV GmbH.", "154066453950464": "MB connect line GmbH Fernwartungssysteme", "154066453958656": "Abbott Diagnostics Technologies AS", + "154066453962752": "Atonarp Inc.", "154066453966848": "Gamber Johnson-LLC", "154066453995520": "Rebel Systems", + "154066454016000": "Gogo BA", "154066454020096": "Integer.pl S.A.", "154066454024192": "Bornico", "154066454028288": "Spacelite Inc", @@ -127720,6 +128360,8 @@ "154066454503424": "KCS Co., Ltd.", "154066454507520": "miniDSP", "154066454511616": "U -Mei-Dah Int'L Enterprise Co.,Ltd.", + "154066454528000": "Point One Navigation", + "154066454544384": "astTECS Communications Private Limited", "154066454556672": "IWS Global Pty Ltd", "154066454573056": "Smart Monitoring Innovations Private Limited", "154066454581248": "Clock-O-Matic", @@ -127764,6 +128406,7 @@ "154066454904832": "Novanta IMS", "154066454908928": "Control Aut Tecnologia em Automação LTDA", "154066454913024": "Blik Sensing B.V.", + "154066454921216": "iOpt", "154066454929408": "Tcl Operations Polska Sp. Z O.O.", "154066454933504": "Smart Radar System, Inc", "154066454937600": "Wagner Group GmbH", @@ -127867,6 +128510,7 @@ "154066455736320": "GlobalInvacom", "154066455748608": "SekureTrak Inc. dba TraknProtect", "154066455752704": "Roesch Walter Industrie-Elektronik GmbH", + "154066455760896": "Power Electronics Espana, S.L.", "154066455769088": "Nixer Ltd", "154066455773184": "Wuxi Zetai Microelectronics Co., LTD", "154066455777280": "Telemetrics Inc.", @@ -127880,6 +128524,7 @@ "154066455842816": "HongSeok Ltd.", "154066455846912": "Forward Edge.AI", "154066455851008": "Eagle Harbor Technologies, Inc.", + "154066455859200": "Kronotech Srl", "154066455863296": "PolCam Systems Sp. z o.o.", "154066455867392": "Recom Llc.", "154066455871488": "Lance Design LLC", @@ -127949,6 +128594,7 @@ "154066456408064": "Hamamatsu Photonics K.K.", "154066456424448": "Slat", "154066456432640": "Sanchar Wireless Communications Ltd", + "154066456440832": "Lamontec", "154066456461312": "GuangZhou HOKO Electric CO.,LTD", "154066456481792": "Wende Tan", "154066456485888": "Nexilis Electronics India Pvt Ltd (PICSYS)", @@ -127996,6 +128642,7 @@ "154066456834048": "WiTricity Corporation", "154066456846336": "KMtronic ltd", "154066456854528": "Bit Trade One, Ltd.", + "154066456862720": "Cortical Labs Pte Ltd", "154066456887296": "Elsist Srl", "154066456899584": "EddyWorks Co.,Ltd", "154066456903680": "Proiker Technology Sl", @@ -128008,8 +128655,10 @@ "154066456965120": "Oas Ag", "154066456969216": "Zuum", "154066456981504": "Onicon", + "154066456985600": "Broyce Control Ltd", "154066456993792": "OvercomTech", "154066457010176": "Nexion Data Systems P/L", + "154066457014272": "Nstek Co., Ltd.", "154066457022464": "Internet Protocolo Logica Sl", "154066457034752": "Abb", "154066457042944": "Chell Instruments Ltd", @@ -128100,6 +128749,7 @@ "154066457694208": "Deviceroy", "154066457702400": "Kotsu Dengyosha Co., Ltd.", "154066457706496": "GO development GmbH", + "154066457731072": "CTI Intl Solutions", "154066457747456": "Flextronics International Kft", "154066457751552": "Ascon Tecnologic S.r.l.", "154066457755648": "Jacquet Dechaume", @@ -128144,6 +128794,7 @@ "154066458050560": "Kymata Srl", "154066458054656": "Panoramic Power", "154066458062848": "Pribusin Inc.", + "154066458066944": "Dti Srl", "154066458075136": "PalmSens BV", "154066458079232": "nke marine electronics", "154066458087424": "Warecube, Inc.", @@ -128154,6 +128805,7 @@ "154066458124288": "IP Devices", "154066458136576": "MTU Aero Engines AG", "154066458161152": "Flow Power", + "154066458165248": "Power Electronics Espana, S.L.", "154066458177536": "AnySignal", "154066458181632": "Vtron Pty Ltd", "154066458210304": "runZero, Inc", @@ -128163,6 +128815,7 @@ "154066458234880": "L-signature", "154066458238976": "Sicon srl", "154066458255360": "Potter Electric Signal Co. LLC", + "154066458271744": "Fo Xie Optoelectronics Technology Co., Ltd", "154066458279936": "Jena-Optronik GmbH", "154066458288128": "Bitmapper Integration Technologies Private Limited", "154066458296320": "AvMap srlu", @@ -128386,6 +129039,7 @@ "154066460106752": "secutech Co.,Ltd.", "154066460110848": "GJD Manufacturing", "154066460123136": "Shanghai Wise-Tech Intelligent Technology Co.,Ltd.", + "154066460127232": "Channel Master LLC", "154066460135424": "Lumiplan Duhamel", "154066460139520": "Elac Americas Inc.", "154066460143616": "Dorlet Sau", @@ -128393,6 +129047,7 @@ "154066460160000": "INVENTIA Sp. z o.o.", "154066460176384": "Pneumax Spa", "154066460192768": "Zilica Limited", + "154066460196864": "manageon", "154066460209152": "Hitachi Energy India Limited", "154066460237824": "Automatic Pty Ltd", "154066460250112": "Ringtail Security", @@ -128403,6 +129058,7 @@ "154066460286976": "Nautel LTD", "154066460291072": "RT Vision Technologies PVT LTD", "154066460295168": "Potter Electric Signal Co. LLC", + "154066460299264": "Joust Security Inc.", "154066460303360": "Dongguan Gago Electronics Co.,Ltd", "154066460311552": "NuGrid Power", "154066460323840": "Fujian Satlink Electronics Co., Ltd", @@ -128412,6 +129068,7 @@ "154066460360704": "Rapidev Pvt Ltd", "154066460372992": "Saarni Cloud Oy", "154066460381184": "Integer.pl S.A.", + "154066460385280": "YUYAMA MFG Co.,Ltd", "154066460393472": "Flextronics International Kft", "154066460401664": "Syscom Instruments SA", "154066460413952": "Babtel", @@ -128509,6 +129166,7 @@ "154066461196288": "MTU Aero Engines AG", "154066461208576": "Abode Systems Inc", "154066461212672": "Murata Manufacturing CO., Ltd.", + "154066461224960": "DAT Informatics Pvt Ltd", "154066461229056": "Grossenbacher Systeme AG", "154066461233152": "DITRON S.r.l.", "154066461241344": "Nov'in", @@ -128555,6 +129213,7 @@ "154066461634560": "Gateview Technologies", "154066461638656": "Evernet Co,.Ltd Taiwan", "154066461642752": "Scheurich GmbH", + "154066461659136": "Prolife Equipamentos Médicos Ltda.", "154066461663232": "Seed Core Co., LTD.", "154066461667328": "ShenZhen Australis Electronic Technology Co.,Ltd.", "154066461671424": "SPX Flow Technology", @@ -128583,6 +129242,7 @@ "154066461859840": "Grupo Epelsa S.L.", "154066461863936": "Zaruc Tecnologia LTDA", "154066461868032": "HIGH RIGHT CO.,Ltd", + "154066461876224": "NEOiD", "154066461880320": "Jiangxi Lv C-Chong Charging Technology Co.Ltd", "154066461884416": "ezDOOR, LLC", "154066461888512": "SmartD Technologies Inc", @@ -128595,7 +129255,9 @@ "154066461929472": "FoxIoT OÜ", "154066461933568": "EasyNet Industry (Shenzhen) Co., Ltd", "154066461941760": "Chengdu ZiChen Time&Frequency Technology Co.,Ltd", + "154066461945856": "UGARD NETWORKS TECHNOLOGY Co.,LTD", "154066461954048": "Gl Tech Co.,Ltd", + "154066461958144": "OPTOKON, a.s.", "154066461962240": "A&T Corporation", "154066461966336": "Sound Health Systems", "154066461970432": "A.L.S.E.", @@ -128607,6 +129269,7 @@ "154066462011392": "Union Electronic.", "154066462019584": "Watts", "154066462027776": "Cardinal Scales Manufacturing Co", + "154066462044160": "Mas Technology", "154066462052352": "Geolux", "154066462060544": "Reo Ag", "154066462081024": "Technologies Bacmove Inc.", @@ -128719,6 +129382,7 @@ "154066462924800": "Rowan Elettronica Srl", "154066462928896": "ARKRAY,Inc.Kyoto Laboratory", "154066462937088": "iC-Haus GmbH", + "154066462941184": "hiSky SCS Ltd", "154066462945280": "Maris Tech Ltd.", "154066462957568": "Circa Enterprises Inc", "154066462969856": "VITREA Smart Home Technologies Ltd.", @@ -128754,6 +129418,7 @@ "154066463256576": "Talleres de Escoriaza SAU", "154066463260672": "Power Electronics Espana, S.L.", "154066463264768": "Minartime(Beijing)Science &Technology Development Co.,Ltd", + "154066463277056": "KS Beschallungstechnik GmbH", "154066463285248": "Labforge Inc.", "154066463289344": "Mecco LLC", "154066463297536": "Benetel", @@ -128813,6 +129478,7 @@ "154066463801344": "Smri", "154066463809536": "Potter Electric Signal Co. LLC", "154066463813632": "DEUTA-WERKE GmbH", + "154066463817728": "SMITEC S.p.A.", "154066463825920": "Mitsubishi Electric India Pvt. Ltd.", "154066463830016": "Algodue Elettronica Srl", "154066463842304": "Smart Cabling & Transmission Corp.", @@ -128857,6 +129523,7 @@ "154066464153600": "Softgent sp. z o.o.", "154066464165888": "Gogo Business Aviation", "154066464182272": "EON Technology, Corp", + "154066464186368": "Natron Energy", "154066464190464": "PXM Marek Zupnik spolka komandytowa", "154066464198656": "PhotonPath", "154066464243712": "Wittra Networks AB", @@ -128867,6 +129534,7 @@ "154066464268288": "Nuvation Energy", "154066464276480": "Dvb-Tech S.R.L.", "154066464284672": "ITS Teknik A/S", + "154066464292864": "新川センサテクノロジ株式会社", "154066464313344": "Enless Wireless", "154066464321536": "Laurel Electronics LLC", "154066464325632": "Telestrider Sa", @@ -128886,6 +129554,8 @@ "154066464468992": "Breas Medical AB", "154066464473088": "VMukti Solutions Private Limited", "154066464485376": "Amiad Water Systems", + "154066464493568": "Horcery LLC", + "154066464514048": "AITEC Corporation", "154066464522240": "Finotex Electronic Solutions PVT LTD", "154066464534528": "Teletech Services", "154066464542720": "Grossenbacher Systeme AG", @@ -128943,6 +129613,7 @@ "154066464972800": "\"KB \"Modul\", LLC", "154066464980992": "Miracle Healthcare, Inc.", "154066464985088": "Messung Systems Pvt Ltd", + "154066464989184": "Traffic Polska sp. z o. o.", "154066465005568": "Aqua Broadcast Ltd", "154066465017856": "Meiryo Denshi Corp.", "154066465026048": "Delta Solutions LLC", @@ -128980,6 +129651,7 @@ "154066465361920": "Texi AS", "154066465370112": "Nagy Márton Jozsef e.v.", "154066465390592": "Televic Rail GmbH", + "154066465394688": "Ottronic GmbH", "154066465398784": "CAITRON GmbH", "154066465402880": "ACS Motion Control", "154066465406976": "Elektrosil GmbH", @@ -129029,6 +129701,7 @@ "154066465751040": "YUYAMA MFG Co.,Ltd", "154066465767424": "Sonatronic", "154066465771520": "Ophir Manufacturing Solutions Pte Ltd", + "154066465775616": "ITG Co.Ltd", "154066465779712": "Motion Impossible Ltd", "154066465783808": "Vision Systems Safety Tech", "154066465792000": "Contrader", diff --git a/CMakeLists.txt b/CMakeLists.txt index 2403dc5bca..78e03653ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,8 @@ project( PcapPlusPlus DESCRIPTION "PcapPlusPlus is a multiplatform C++ library for capturing, parsing and crafting of network packets." LANGUAGES CXX - HOMEPAGE_URL "https://pcapplusplus.github.io/") + HOMEPAGE_URL "https://pcapplusplus.github.io/" +) # Include our custom CMake modules list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") @@ -40,10 +41,7 @@ else() endif() # LINUX is set Only since 3.25 see: https://cmake.org/cmake/help/latest/variable/LINUX.html -if(UNIX - AND NOT APPLE - AND NOT CYGWIN - AND NOT ANDROID) +if(UNIX AND NOT APPLE AND NOT CYGWIN AND NOT ANDROID) set(LINUX True) endif() @@ -54,21 +52,18 @@ set(PCAPPP_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/pcapplusplus) set(PCAPPP_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}) # Build options enable sanitizers -set(PCAPPP_ALLOWED_SANITIZERS - "" - "AddressSanitizer" - "MemorySanitizer" - "ThreadSanitizer" - "UndefinedBehaviorSanitizer") -set(PCAPPP_USE_SANITIZER - "" - CACHE STRING "Compile with a sanitizer") +set( + PCAPPP_ALLOWED_SANITIZERS + "" + "AddressSanitizer" + "MemorySanitizer" + "ThreadSanitizer" + "UndefinedBehaviorSanitizer" +) +set(PCAPPP_USE_SANITIZER "" CACHE STRING "Compile with a sanitizer") set_property(CACHE PCAPPP_USE_SANITIZER PROPERTY STRINGS ${PCAPPP_ALLOWED_SANITIZERS}) -if(NOT - PCAPPP_USE_SANITIZER - IN_LIST - PCAPPP_ALLOWED_SANITIZERS) +if(NOT PCAPPP_USE_SANITIZER IN_LIST PCAPPP_ALLOWED_SANITIZERS) message(FATAL_ERROR "PCAPPP_USE_SANITIZER must be one of ${PCAPPP_ALLOWED_SANITIZERS}") endif() @@ -97,7 +92,8 @@ cmake_dependent_option( "Build Tutorials" OFF "PCAPPP_BUILD_EXAMPLES" - OFF) + OFF +) option(PCAPPP_BUILD_TESTS "Build Tests" ${PCAPPP_MAIN_PROJECT}) option(PCAPPP_BUILD_COVERAGE "Generate Coverage Report" OFF) option(PCAPPP_BUILD_FUZZERS "Build Fuzzers binaries" OFF) @@ -111,7 +107,8 @@ cmake_dependent_option( "Add KNI Support to Pcap++" OFF "PCAPPP_USE_DPDK" - OFF) + OFF +) option(PCAPPP_USE_PF_RING "Setup PcapPlusPlus with PF_RING. In this case you must also set PF_RING_ROOT") option(PCAPPP_USE_XDP "Setup PcapPlusPlus with XDP") option(PCAPPP_INSTALL "Install Pcap++" ${PCAPPP_MAIN_PROJECT}) @@ -127,9 +124,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Usually on Windows PCAP_ROOT and Packet_ROOT are at the same location -if(WIN32 - AND PCAP_ROOT - AND NOT Packet_ROOT) +if(WIN32 AND PCAP_ROOT AND NOT Packet_ROOT) set(Packet_ROOT ${PCAP_ROOT}) endif() @@ -162,8 +157,11 @@ if(PCAPPP_ENABLE_PCAP_IMMEDIATE_MODE) endif() # Enable the option if it's available -option(PCAPPP_ENABLE_PCAP_SET_DIRECTION - "Enable set direction for capturing incoming or outgoing packets (supported on libpcap>=0.9.1)" OFF) +option( + PCAPPP_ENABLE_PCAP_SET_DIRECTION + "Enable set direction for capturing incoming or outgoing packets (supported on libpcap>=0.9.1)" + OFF +) # Check in case user force it but it's not available if(PCAPPP_ENABLE_PCAP_SET_DIRECTION) @@ -210,12 +208,14 @@ if(Git_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} log -1 --format=%h WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE PCAPPP_GIT_COMMIT) + OUTPUT_VARIABLE PCAPPP_GIT_COMMIT + ) string(STRIP "${PCAPPP_GIT_COMMIT}" PCAPPP_GIT_COMMIT) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE PCAPPP_GIT_BRANCH) + OUTPUT_VARIABLE PCAPPP_GIT_BRANCH + ) string(STRIP "${PCAPPP_GIT_BRANCH}" PCAPPP_GIT_BRANCH) message(STATUS "Building from commit:${PCAPPP_GIT_COMMIT} on branch:${PCAPPP_GIT_BRANCH}") add_compile_definitions(GIT_COMMIT="${PCAPPP_GIT_COMMIT}") @@ -239,15 +239,11 @@ if(PCAPPP_USE_XDP) endif() if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE - "Release" - CACHE STRING "Choose the type of build." FORCE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release") endif() -if(PCAPPP_TARGET_COMPILER_CLANG - OR PCAPPP_TARGET_COMPILER_GCC - OR PCAPPP_TARGET_COMPILER_INTEL) +if(PCAPPP_TARGET_COMPILER_CLANG OR PCAPPP_TARGET_COMPILER_GCC OR PCAPPP_TARGET_COMPILER_INTEL) add_compile_options(-Wall) endif() @@ -300,9 +296,7 @@ if(PCAPPP_BUILD_EXAMPLES) add_subdirectory(Examples) endif() -if(PCAPPP_BUILD_TESTS - OR PCAPPP_BUILD_FUZZERS - OR PCAPPP_BUILD_EXAMPLES) +if(PCAPPP_BUILD_TESTS OR PCAPPP_BUILD_FUZZERS OR PCAPPP_BUILD_EXAMPLES) include(CTest) add_subdirectory(Tests) endif() @@ -314,8 +308,11 @@ if(PCAPPP_INSTALL) # Add System and CoreFoundation libs on MacOS set(PCAPPP_PKGCONFIG_EXTRA_LIBS "-framework SystemConfiguration -framework CoreFoundation") endif() - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlus.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlus.pc" - @ONLY) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlus.pc.in" + "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlus.pc" + @ONLY + ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlus.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif() @@ -338,26 +335,28 @@ if(PCAPPP_INSTALL) pcapp_install_cmake_module(ZSTD) endif() - install( - EXPORT PcapPlusPlusTargets - DESTINATION ${PCAPPP_INSTALL_CMAKEDIR} - NAMESPACE PcapPlusPlus::) + install(EXPORT PcapPlusPlusTargets DESTINATION ${PCAPPP_INSTALL_CMAKEDIR} NAMESPACE PcapPlusPlus::) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlusConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfig.cmake" INSTALL_DESTINATION "${PCAPPP_INSTALL_CMAKEDIR}") + "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfig.cmake" + INSTALL_DESTINATION "${PCAPPP_INSTALL_CMAKEDIR}" + ) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfigVersion.cmake" VERSION ${PCAPPP_VERSION} - COMPATIBILITY AnyNewerVersion) + COMPATIBILITY AnyNewerVersion + ) # CMake helpers to compile Pcap++ with CMake install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfigVersion.cmake" + FILES + "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfigVersion.cmake" COMPONENT devel - DESTINATION "${PCAPPP_INSTALL_CMAKEDIR}") + DESTINATION "${PCAPPP_INSTALL_CMAKEDIR}" + ) endif() if(PCAPPP_PACKAGE) @@ -369,28 +368,21 @@ if(PCAPPP_PACKAGE) set(CPACK_PACKAGE_VERSION "${PCAPPP_VERSION}") set(CPACK_PACKAGE_MAINTAINER "seladb") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_MAINTAINER}") - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY - "PcapPlusPlus is a multiplatform C++ library for capturing, parsing and crafting of network packets. It is designed to be efficient, powerful and easy to use." + set( + CPACK_PACKAGE_DESCRIPTION_SUMMARY + "PcapPlusPlus is a multiplatform C++ library for capturing, parsing and crafting of network packets. It is designed to be efficient, powerful and easy to use." ) # Default output a .tar.gz set(CPACK_GENERATOR "TGZ") # Remove the tweak for Compiler Version - string( - REPLACE "." - ";" - VERSION_LIST - ${CMAKE_CXX_COMPILER_VERSION}) + string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION}) list(LENGTH VERSION_LIST CMAKE_CXX_COMPILER_VERSION_LENGTH) if(${CMAKE_CXX_COMPILER_VERSION_LENGTH} GREATER 3) list(POP_BACK VERSION_LIST) endif() - list( - JOIN - VERSION_LIST - "." - PCAPP_CXX_COMPILER_VERSION) + list(JOIN VERSION_LIST "." PCAPP_CXX_COMPILER_VERSION) set(_PCAPPP_PACKAGE_README_PATH "${CMAKE_SOURCE_DIR}/cmake/package/READMEs") set(_PCAPPP_PACKAGE_README_OUTFILE "${CMAKE_BINARY_DIR}/README.release.md") @@ -415,14 +407,17 @@ if(PCAPPP_PACKAGE) elseif("${DISTRO_ID}" STREQUAL "freebsd") set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.freebsd") endif() - set(CPACK_SYSTEM_NAME - "${DISTRO_ID}-${DISTRO_VERSION_ID}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}-${CMAKE_SYSTEM_PROCESSOR}" + set( + CPACK_SYSTEM_NAME + "${DISTRO_ID}-${DISTRO_VERSION_ID}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}-${CMAKE_SYSTEM_PROCESSOR}" ) elseif(MINGW) # Check MinGW before WIN32 as MinGW defines both set(CPACK_GENERATOR "ZIP") - set(CPACK_SYSTEM_NAME - "windows-mingw64-${PCAPP_TARGET_ARCHITECTURE}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}") + set( + CPACK_SYSTEM_NAME + "windows-mingw64-${PCAPP_TARGET_ARCHITECTURE}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}" + ) set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.win.mingw") elseif(WIN32) set(CPACK_GENERATOR "ZIP") @@ -451,10 +446,12 @@ if(PCAPPP_PACKAGE) if(NOT CONVERTER) message(FATAL_ERROR "textutil executable not found") endif() - execute_process(COMMAND ${CONVERTER} -convert html "${CMAKE_SOURCE_DIR}/LICENSE" -output - "${CMAKE_BINARY_DIR}/LICENSE.html") - execute_process(COMMAND ${CONVERTER} -convert html "${_PCAPPP_PACKAGE_README_OUTFILE}" -output - "${CMAKE_BINARY_DIR}/README.html") + execute_process( + COMMAND ${CONVERTER} -convert html "${CMAKE_SOURCE_DIR}/LICENSE" -output "${CMAKE_BINARY_DIR}/LICENSE.html" + ) + execute_process( + COMMAND ${CONVERTER} -convert html "${_PCAPPP_PACKAGE_README_OUTFILE}" -output "${CMAKE_BINARY_DIR}/README.html" + ) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/LICENSE.html") set(CPACK_RESOURCE_FILE_README "${CMAKE_BINARY_DIR}/README.html") else() @@ -464,11 +461,13 @@ if(PCAPPP_PACKAGE) # used in CPackAdditionalInstall.cmake set(CPACK_ADDITIONAL_INSTALL_RESOURCES "${CPACK_RESOURCE_FILE_LICENSE}" "${CPACK_RESOURCE_FILE_README}") - set(CPACK_ADDITIONAL_EXAMPLE_APP - "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/1_packet.pcap" - "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/CMakeLists.txt" - "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/main.cpp" - "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/README.md") + set( + CPACK_ADDITIONAL_EXAMPLE_APP + "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/1_packet.pcap" + "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/CMakeLists.txt" + "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/main.cpp" + "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/README.md" + ) set(CPACK_INSTALL_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/CPackAdditionalInstall.cmake") include(CPack) @@ -480,7 +479,8 @@ if(NOT TARGET uninstall) "${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlusUninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusUninstall.cmake" IMMEDIATE - @ONLY) + @ONLY + ) add_custom_target(uninstall COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusUninstall.cmake") endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 578a5390fb..69530d8268 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ Every code contribution to this project is highly valued and appreciated. I enco - For Windows (using `choco`) `choco install cppcheck --version=2.7` - For Windows (MSI install): https://github.com/danmar/cppcheck/releases/download/2.7/cppcheck-2.7-x64-Setup.msi - Build from source: https://github.com/danmar/cppcheck/releases/tag/2.7 - - `clang-format`: `pip install clang-format==18.1.6` + - `clang-format`: `pip install clang-format==19.1.6` - After you commit the code and push it to GitHub, before creating the pull request please make sure that: - You merge all new code from **dev** to your fork - CI passes on all platforms diff --git a/Common++/CMakeLists.txt b/Common++/CMakeLists.txt index 5b75bf9f77..8ef1ca1f79 100644 --- a/Common++/CMakeLists.txt +++ b/Common++/CMakeLists.txt @@ -9,23 +9,27 @@ add_library( src/OUILookup.cpp src/PcapPlusPlusVersion.cpp src/SystemUtils.cpp - src/TablePrinter.cpp) + src/TablePrinter.cpp +) -set(public_headers - header/DeprecationUtils.h - header/GeneralUtils.h - header/IpAddress.h - header/IpAddressUtils.h - header/IpUtils.h - header/Logger.h - header/LRUList.h - header/MacAddress.h - header/OUILookup.h - header/PcapPlusPlusVersion.h - header/PointerVector.h - header/SystemUtils.h - header/TablePrinter.h - header/TimespecTimeval.h) +set( + public_headers + header/DeprecationUtils.h + header/GeneralUtils.h + header/IpAddress.h + header/IpAddressUtils.h + header/IpUtils.h + header/Logger.h + header/LRUList.h + header/MacAddress.h + header/ObjectPool.h + header/OUILookup.h + header/PcapPlusPlusVersion.h + header/PointerVector.h + header/SystemUtils.h + header/TablePrinter.h + header/TimespecTimeval.h +) # Set the public header that will be installed set_property(TARGET Common++ PROPERTY PUBLIC_HEADER ${public_headers}) @@ -35,7 +39,8 @@ target_include_directories( PUBLIC $ $ # Don't link with EndianPortable and json as it won't be exported PRIVATE $ - PRIVATE $) + PRIVATE $ +) if(WIN32) target_link_libraries(Common++ PRIVATE ws2_32 iphlpapi) @@ -48,7 +53,8 @@ if(PCAPPP_INSTALL) ARCHIVE DESTINATION ${PCAPPP_INSTALL_LIBDIR} LIBRARY DESTINATION ${PCAPPP_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${PCAPPP_INSTALL_INCLUDEDIR} - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR} + ) endif() set_property(TARGET Common++ PROPERTY OUTPUT_NAME "Common++") diff --git a/Common++/header/GeneralUtils.h b/Common++/header/GeneralUtils.h index 316ee22913..7e49fa12fc 100644 --- a/Common++/header/GeneralUtils.h +++ b/Common++/header/GeneralUtils.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include /// @file diff --git a/Common++/header/IpAddress.h b/Common++/header/IpAddress.h index 6cafb2ed7d..d93a341b70 100644 --- a/Common++/header/IpAddress.h +++ b/Common++/header/IpAddress.h @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include #include #include #include @@ -145,7 +145,7 @@ namespace pcpp uint32_t IPv4Address::toInt() const { - uint32_t addr; + uint32_t addr = 0; memcpy(&addr, m_Bytes.data(), m_Bytes.size() * sizeof(uint8_t)); return addr; } @@ -276,7 +276,7 @@ namespace pcpp { public: /// An enum representing the address type: IPv4 or IPv6 - enum AddressType + enum AddressType : uint8_t { /// IPv4 address type IPv4AddressType, @@ -395,7 +395,9 @@ namespace pcpp bool IPAddress::operator==(const IPAddress& rhs) const { if (isIPv4()) + { return rhs.isIPv4() ? (m_IPv4 == rhs.m_IPv4) : false; + } return rhs.isIPv6() ? m_IPv6 == rhs.m_IPv6 : false; } @@ -433,7 +435,7 @@ namespace pcpp /// A constructor that creates an instance of the class out of an address and a full prefix length, /// essentially making a network of consisting of only 1 address. /// @param address An address representing the network prefix. - explicit IPv4Network(const IPv4Address& address) : IPv4Network(address, 32u) + explicit IPv4Network(const IPv4Address& address) : IPv4Network(address, 32U) {} /// A constructor that creates an instance of the class out of an address representing the network prefix @@ -476,7 +478,7 @@ namespace pcpp /// @return The network prefix, for example: the network prefix of 10.10.10.10/16 is 10.10.0.0 IPv4Address getNetworkPrefix() const { - return IPv4Address(m_NetworkPrefix); + return m_NetworkPrefix; } /// @return The lowest non-reserved IPv4 address in this network, for example: the lowest address @@ -505,10 +507,10 @@ namespace pcpp std::string toString() const; private: - uint32_t m_NetworkPrefix; - uint32_t m_Mask; + uint32_t m_NetworkPrefix{}; + uint32_t m_Mask{}; - bool isValidNetmask(const IPv4Address& netmaskAddress); + static bool isValidNetmask(const IPv4Address& netmaskAddress); void initFromAddressAndPrefixLength(const IPv4Address& address, uint8_t prefixLen); void initFromAddressAndNetmask(const IPv4Address& address, const IPv4Address& netmaskAddress); }; @@ -521,7 +523,7 @@ namespace pcpp /// A constructor that creates an instance of the class out of an address and a full prefix length, /// essentially making a network of consisting of only 1 address. /// @param address An address representing the network prefix. - explicit IPv6Network(const IPv6Address& address) : IPv6Network(address, 128u) + explicit IPv6Network(const IPv6Address& address) : IPv6Network(address, 128U) {} /// A constructor that creates an instance of the class out of an address representing the network prefix @@ -564,7 +566,7 @@ namespace pcpp /// @return The network prefix, for example: the network prefix of 3546:f321::/16 is 3546:: IPv6Address getNetworkPrefix() const { - return IPv6Address(m_NetworkPrefix); + return { m_NetworkPrefix }; } /// @return The lowest non-reserved IPv6 address in this network, for example: the lowest address in 3546::/16 @@ -593,10 +595,10 @@ namespace pcpp std::string toString() const; private: - uint8_t m_NetworkPrefix[16]; - uint8_t m_Mask[16]; + uint8_t m_NetworkPrefix[16]{}; + uint8_t m_Mask[16]{}; - bool isValidNetmask(const IPv6Address& netmaskAddress); + static bool isValidNetmask(const IPv6Address& netmaskAddress); void initFromAddressAndPrefixLength(const IPv6Address& address, uint8_t prefixLen); void initFromAddressAndNetmask(const IPv6Address& address, const IPv6Address& netmaskAddress); }; @@ -609,7 +611,7 @@ namespace pcpp /// A constructor that creates an instance of the class out of an IP address and a full prefix length, /// essentially making a network of consisting of only 1 address. /// @param address An address representing the network prefix. - explicit IPNetwork(const IPAddress& address) : IPNetwork(address, address.isIPv4() ? 32u : 128u) + explicit IPNetwork(const IPAddress& address) : IPNetwork(address, address.isIPv4() ? 32U : 128U) {} /// A constructor that creates an instance of the class out of an address representing the network prefix @@ -692,14 +694,14 @@ namespace pcpp /// @return A reference to the assignee IPNetwork& operator=(const IPNetwork& other) { + // NOLINTBEGIN(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) if (other.isIPv4Network()) { return this->operator=(*other.m_IPv4Network); } - else - { - return this->operator=(*other.m_IPv6Network); - } + + return this->operator=(*other.m_IPv6Network); + // NOLINTEND(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) } /// Overload of an assignment operator. @@ -707,18 +709,9 @@ namespace pcpp /// @return A reference to the assignee IPNetwork& operator=(const IPv4Network& other) { - if (m_IPv4Network) - { - m_IPv4Network = nullptr; - } - - if (m_IPv6Network) - { - m_IPv6Network = nullptr; - } - + // Create the new instance first to maintain strong exception guarantee. m_IPv4Network = std::unique_ptr(new IPv4Network(other)); - + m_IPv6Network = nullptr; return *this; } @@ -727,18 +720,9 @@ namespace pcpp /// @return A reference to the assignee IPNetwork& operator=(const IPv6Network& other) { - if (m_IPv4Network) - { - m_IPv4Network = nullptr; - } - - if (m_IPv6Network) - { - m_IPv6Network = nullptr; - } - + // Create the new instance first to maintain strong exception guarantee. m_IPv6Network = std::unique_ptr(new IPv6Network(other)); - + m_IPv4Network = nullptr; return *this; } @@ -814,15 +798,13 @@ namespace pcpp return m_IPv4Network->includes(address.getIPv4()); } - else - { - if (address.isIPv4()) - { - return false; - } - return m_IPv6Network->includes(address.getIPv6()); + if (address.isIPv4()) + { + return false; } + + return m_IPv6Network->includes(address.getIPv6()); } /// @param network An IP network @@ -838,15 +820,13 @@ namespace pcpp return m_IPv4Network->includes(*network.m_IPv4Network); } - else - { - if (network.isIPv4Network()) - { - return false; - } - return m_IPv6Network->includes(*network.m_IPv6Network); + if (network.isIPv4Network()) + { + return false; } + + return m_IPv6Network->includes(*network.m_IPv6Network); } /// @return A string representation of the network in a format of NETWORK_PREFIX/PREFIX_LEN, for example: @@ -861,40 +841,39 @@ namespace pcpp std::unique_ptr m_IPv6Network; }; - inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv4Address& ipv4Address) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::IPv4Address& ipv4Address) { - os << ipv4Address.toString(); - return os; + oss << ipv4Address.toString(); + return oss; } - inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv6Address& ipv6Address) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::IPv6Address& ipv6Address) { - os << ipv6Address.toString(); - return os; + oss << ipv6Address.toString(); + return oss; } - inline std::ostream& operator<<(std::ostream& os, const pcpp::IPAddress& ipAddress) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::IPAddress& ipAddress) { - os << ipAddress.toString(); - return os; + oss << ipAddress.toString(); + return oss; } - inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv4Network& network) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::IPv4Network& network) { - os << network.toString(); - return os; + oss << network.toString(); + return oss; } - inline std::ostream& operator<<(std::ostream& os, const pcpp::IPv6Network& network) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::IPv6Network& network) { - os << network.toString(); - return os; + oss << network.toString(); + return oss; } - inline std::ostream& operator<<(std::ostream& os, const pcpp::IPNetwork& network) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::IPNetwork& network) { - os << network.toString(); - return os; + oss << network.toString(); + return oss; } - } // namespace pcpp diff --git a/Common++/header/IpUtils.h b/Common++/header/IpUtils.h index 6dadfb5028..46ad6f6617 100644 --- a/Common++/header/IpUtils.h +++ b/Common++/header/IpUtils.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #ifdef __linux__ # include # include @@ -53,34 +53,34 @@ namespace pcpp namespace internal { /// Extract IPv4 address from sockaddr - /// @param[in] sa - input sockaddr + /// @param[in] sAddr - input sockaddr /// @return Address in in_addr format /// @throws std::invalid_argument Sockaddr family is not AF_INET or sockaddr is nullptr. - in_addr* sockaddr2in_addr(sockaddr* sa); + in_addr* sockaddr2in_addr(sockaddr* sAddr); /// Attempt to extract IPv4 address from sockaddr - /// @param[in] sa - input sockaddr + /// @param[in] sAddr - input sockaddr /// @return Pointer to address in in_addr format or nullptr if extraction fails. - in_addr* try_sockaddr2in_addr(sockaddr* sa); + in_addr* try_sockaddr2in_addr(sockaddr* sAddr); /// Extract IPv6 address from sockaddr - /// @param[in] sa - input sockaddr + /// @param[in] sAddr - input sockaddr /// @return Address in in6_addr format /// @throws std::invalid_argument Sockaddr family is not AF_INET6 or sockaddr is nullptr. - in6_addr* sockaddr2in6_addr(sockaddr* sa); + in6_addr* sockaddr2in6_addr(sockaddr* sAddr); /// Attempt to extract IPv6 address from sockaddr - /// @param[in] sa - input sockaddr + /// @param[in] sAddr - input sockaddr /// @return Pointer to address in in6_addr format or nullptr if extraction fails. - in6_addr* try_sockaddr2in6_addr(sockaddr* sa); + in6_addr* try_sockaddr2in6_addr(sockaddr* sAddr); /// Converts a sockaddr format address to its string representation - /// @param[in] sa Address in sockaddr format + /// @param[in] sAddr Address in sockaddr format /// @param[out] resultString String representation of the address /// @param[in] resultBufLen Length of the result buffer. /// @throws std::invalid_argument Sockaddr family is not AF_INET or AF_INET6, sockaddr is nullptr or the result /// str buffer is insufficient. - void sockaddr2string(sockaddr const* sa, char* resultString, size_t resultBufLen); + void sockaddr2string(const sockaddr* sAddr, char* resultString, size_t resultBufLen); /// Convert a in_addr format address to 32bit representation /// @param[in] inAddr Address in in_addr format diff --git a/Common++/header/LRUList.h b/Common++/header/LRUList.h index 81bc6db3a7..002ea6721f 100644 --- a/Common++/header/LRUList.h +++ b/Common++/header/LRUList.h @@ -23,15 +23,13 @@ namespace pcpp template class LRUList { public: - typedef typename std::list::iterator ListIterator; - typedef typename std::unordered_map::iterator MapIterator; + using ListIterator = typename std::list::iterator; + using MapIterator = typename std::unordered_map::iterator; /// A c'tor for this class /// @param[in] maxSize The max size this list can go - explicit LRUList(std::size_t maxSize) - { - m_MaxSize = maxSize; - } + explicit LRUList(std::size_t maxSize) : m_MaxSize(maxSize) + {} /// Puts an element in the list. This element will be inserted (or advanced if it already exists) to the head of /// the list as the most recently used element. If the list already reached its max size and the element is new @@ -51,7 +49,7 @@ namespace pcpp // iterator to the element that prevented the insertion std::pair pair = m_CacheItemsMap.insert(std::make_pair(element, m_CacheItemsList.begin())); - if (pair.second == false) // already exists + if (!pair.second) // already exists { m_CacheItemsList.erase(pair.first->second); pair.first->second = m_CacheItemsList.begin(); @@ -63,11 +61,13 @@ namespace pcpp --lruIter; if (deletedValue != nullptr) + { #if __cplusplus > 199711L || _MSC_VER >= 1800 *deletedValue = std::move(*lruIter); #else *deletedValue = *lruIter; #endif + } m_CacheItemsMap.erase(*lruIter); m_CacheItemsList.erase(lruIter); return 1; @@ -96,7 +96,9 @@ namespace pcpp { MapIterator iter = m_CacheItemsMap.find(element); if (iter == m_CacheItemsMap.end()) + { return; + } m_CacheItemsList.erase(iter->second); m_CacheItemsMap.erase(iter); diff --git a/Common++/header/Logger.h b/Common++/header/Logger.h index 49d05ef759..df9ce372ee 100644 --- a/Common++/header/Logger.h +++ b/Common++/header/Logger.h @@ -1,10 +1,14 @@ #pragma once -#include -#include +#include +#include +#include +#include +#include +#include #include -#include -#include +#include "DeprecationUtils.h" +#include "ObjectPool.h" #ifndef LOG_MODULE # define LOG_MODULE UndefinedLogModule @@ -17,38 +21,32 @@ # define PCAPPP_FILENAME __FILE__ #endif -#define PCPP_LOG(level, message) \ - do \ - { \ - std::ostringstream* sstream = pcpp::Logger::getInstance().internalCreateLogStream(); \ - (*sstream) << message; \ - pcpp::Logger::getInstance().internalPrintLogMessage(sstream, level, PCAPPP_FILENAME, __FUNCTION__, __LINE__); \ - } while (0) - -#define PCPP_LOG_DEBUG(message) \ - do \ - { \ - if (pcpp::Logger::getInstance().logsEnabled() && pcpp::Logger::getInstance().isDebugEnabled(LOG_MODULE)) \ - { \ - PCPP_LOG(pcpp::Logger::Debug, message); \ - } \ - } while (0) +/// @file -#define PCPP_LOG_ERROR(message) \ - do \ - { \ - PCPP_LOG(pcpp::Logger::Error, message); \ - } while (0) +// Compile time log levels. +// Allows for conditional removal of unwanted log calls at compile time. +#define PCPP_LOG_LEVEL_OFF 0 +#define PCPP_LOG_LEVEL_ERROR 1 +#define PCPP_LOG_LEVEL_INFO 2 +#define PCPP_LOG_LEVEL_DEBUG 3 -/// @file +// All log messages built via a PCPP_LOG_* macro below the PCPP_ACTIVE_LOG_LEVEL will be removed at compile time. +// Uses the PCPP_ACTIVE_LOG_LEVEL if it is defined, otherwise defaults to PCAP_LOG_LEVEL_DEBUG +#ifndef PCPP_ACTIVE_LOG_LEVEL +# define PCPP_ACTIVE_LOG_LEVEL PCPP_LOG_LEVEL_DEBUG +#endif // !PCPP_ACTIVE_LOG_LEVEL /// @namespace pcpp /// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { + /// Cross-platform and thread-safe version of strerror + /// @param errnum Value of errno + /// @return String representation of the error number + std::string getErrorString(int errnum); /// An enum representing all PcapPlusPlus modules - enum LogModule + enum LogModule : uint8_t { UndefinedLogModule, CommonLogModuleIpUtils, ///< IP Utils module (Common++) @@ -75,6 +73,7 @@ namespace pcpp PacketLogModuleGreLayer, ///< GreLayer module (Packet++) PacketLogModuleSSLLayer, ///< SSLLayer module (Packet++) PacketLogModuleSllLayer, ///< SllLayer module (Packet++) + PacketLogModuleSll2Layer, ///< Sll2Layer module (Packet++) PacketLogModuleNflogLayer, ///< NflogLayer module (Packet++) PacketLogModuleDhcpLayer, ///< DhcpLayer module (Packet++) PacketLogModuleDhcpV6Layer, ///< DhcpV6Layer module (Packet++) @@ -109,10 +108,101 @@ namespace pcpp PcapLogModuleDpdkDevice, ///< DpdkDevice module (Pcap++) PcapLogModuleKniDevice, ///< KniDevice module (Pcap++) PcapLogModuleXdpDevice, ///< XdpDevice module (Pcap++) - NetworkUtils, ///< NetworkUtils module (Pcap++) + PcapLogModuleNetworkUtils, ///< Network Utils module (Pcap++) NumOfLogModules }; + /// @struct LogSource + /// Represents the source of a log message. + /// Contains information about the source file, function, line number, and the log module. + struct LogSource + { + /// Default constructor for LogSource. + constexpr LogSource() = default; + + /// Constructor for LogSource with only the log module. + /// @param logModule The log module. + explicit constexpr LogSource(LogModule logModule) : logModule(logModule) + {} + + /// Constructor for LogSource with all parameters. + /// @param logModule The log module. + /// @param file The source file. + /// @param function The source function. + /// @param line The line number. + constexpr LogSource(LogModule logModule, const char* file, const char* function, int line) + : file(file), function(function), line(line), logModule(logModule) + {} + + const char* file = nullptr; /**< The source file. */ + const char* function = nullptr; /**< The source function. */ + int line = 0; /**< The line number. */ + LogModule logModule = UndefinedLogModule; /**< The log module. */ + }; + + /// An enum representing the log level. Currently 4 log levels are supported: Off, Error, Info and Debug. Info is + /// the default log level + enum class LogLevel + { + Off = PCPP_LOG_LEVEL_OFF, ///< No log messages are emitted. + Error = PCPP_LOG_LEVEL_ERROR, ///< Error level logs are emitted. + Info = PCPP_LOG_LEVEL_INFO, ///< Info level logs and above are emitted. + Debug = PCPP_LOG_LEVEL_DEBUG ///< Debug level logs and above are emitted. + }; + + inline std::ostream& operator<<(std::ostream& s, LogLevel v) + { + return s << static_cast::type>(v); + } + + // Forward declaration + class Logger; + + namespace internal + { + /// @class LogContext + /// @brief A context encapsulating the details of a single log message to be passed to the Logger. + class LogContext + { + public: + friend class pcpp::Logger; + + /// @brief Creates a context with an empty message with Info level and no source. + LogContext() = default; + + /// @brief Creates a context with an empty message with the given level and source. + /// @param level The log level for this message. + /// @param source The log source. + explicit LogContext(LogLevel level, LogSource const& source = {}) : m_Source(source), m_Level(level) + {} + + /// @brief Initializes the context with an empty message and the given level and source. + /// @param level The log level for this message. + /// @param source The log source. + void init(LogLevel level, LogSource const& source) + { + m_Source = source; + m_Level = level; + m_Stream.clear(); + m_Stream.str({}); + } + + /// @brief Appends to the message. + /// @param value The value to append. + /// @return A reference to this context. + template inline LogContext& operator<<(T const& value) + { + m_Stream << value; + return *this; + } + + private: + std::ostringstream m_Stream; + LogSource m_Source; + LogLevel m_Level = LogLevel::Info; + }; + } // namespace internal + /// @class Logger /// PcapPlusPlus logger manager. /// PcapPlusPlus uses this logger to output both error and debug logs. @@ -133,14 +223,14 @@ namespace pcpp class Logger { public: - /// An enum representing the log level. Currently 3 log levels are supported: Error, Info and Debug. Info is the - /// default log level - enum LogLevel - { - Error, ///< Error log level - Info, ///< Info log level - Debug ///< Debug log level - }; + // Deprecated, Use the LogLevel in the pcpp namespace instead. + using LogLevel = pcpp::LogLevel; + PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.") + static const LogLevel Error = LogLevel::Error; + PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.") + static const LogLevel Info = LogLevel::Info; + PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.") + static const LogLevel Debug = LogLevel::Debug; /// @typedef LogPrinter /// Log printer callback. Used for printing the logs in a custom way. @@ -149,8 +239,10 @@ namespace pcpp /// @param[in] file The source file in PcapPlusPlus code the log message is coming from /// @param[in] method The method in PcapPlusPlus code the log message is coming from /// @param[in] line The line in PcapPlusPlus code the log message is coming from - typedef void (*LogPrinter)(LogLevel logLevel, const std::string& logMessage, const std::string& file, - const std::string& method, const int line); + /// @remarks The printer callback should support being called from multiple threads simultaneously. + using LogPrinter = + std::add_pointer::type; /// A static method for converting the log level enum to a string. /// @param[in] logLevel A log level enum @@ -178,7 +270,16 @@ namespace pcpp /// @return True if this module log level is "debug". False otherwise bool isDebugEnabled(LogModule module) const { - return m_LogModulesArray[module] == Debug; + return m_LogModulesArray[module] == LogLevel::Debug; + } + + /// @brief Check whether a log level should be emitted by the logger. + /// @param level The level of the log message. + /// @param module PcapPlusPlus module + /// @return True if the message should be emitted. False otherwise. + bool shouldLog(LogLevel level, LogModule module) const + { + return level != LogLevel::Off && m_LogModulesArray[module] >= level; } /// Set all PcapPlusPlus modules to a certain log level @@ -186,7 +287,9 @@ namespace pcpp void setAllModulesToLogLevel(LogLevel level) { for (int i = 1; i < NumOfLogModules; i++) + { m_LogModulesArray[i] = level; + } } /// Set a custom log printer. @@ -203,8 +306,9 @@ namespace pcpp } /// @return Get the last error message - std::string getLastError() + std::string getLastError() const { + std::lock_guard lock(m_LastErrorMtx); return m_LastError; } @@ -227,17 +331,32 @@ namespace pcpp return m_LogsEnabled; } - template Logger& operator<<(const T& msg) + /// @brief Controls if the logger should use a pool of LogContext objects. + /// + /// If enabled is set to false, preallocate and maxPoolSize are ignored. + /// @param enabled True to enable context pooling, false to disable. + /// @param preallocate The number of LogContext objects to preallocate in the pool. + /// @param maxPoolSize The maximum number of LogContext objects to keep in the pool. + /// @remarks Disabling the pooling clears the pool. + void useContextPooling(bool enabled, std::size_t preallocate = 2, std::size_t maxPoolSize = 10) { - (*m_LogStream) << msg; - return *this; - } + m_UseContextPooling = enabled; - std::ostringstream* internalCreateLogStream(); + if (m_UseContextPooling) + { + m_LogContextPool.setMaxSize(maxPoolSize); - /// An internal method to print log messages. Shouldn't be used externally. - void internalPrintLogMessage(std::ostringstream* logStream, Logger::LogLevel logLevel, const char* file, - const char* method, int line); + if (preallocate > 0) + { + m_LogContextPool.preallocate(preallocate); + } + } + else + { + // Clear the pool if we're disabling pooling. + m_LogContextPool.clear(); + } + } /// Get access to Logger singleton /// @todo: make this singleton thread-safe/ @@ -248,17 +367,74 @@ namespace pcpp return instance; } + /// @brief Creates a new LogContext with Info level and no source. + /// @return A new LogContext. + std::unique_ptr createLogContext(); + + /// @brief Creates a new LogContext with the given level and source. + /// @param level The log level for this message. + /// @param source The log source. + /// @return A new LogContext. + std::unique_ptr createLogContext(LogLevel level, LogSource const& source = {}); + + /// @brief Directly emits a log message bypassing all level checks. + /// @param source The log source. + /// @param level The log level for this message. This is only used for the log printer. + /// @param message The log message. + void emit(LogSource const& source, LogLevel level, std::string const& message); + + /// @brief Directly emits a log message bypassing all level checks. + /// @param message The log message. + void emit(std::unique_ptr message); + private: bool m_LogsEnabled; - Logger::LogLevel m_LogModulesArray[NumOfLogModules]; + std::array m_LogModulesArray; LogPrinter m_LogPrinter; + + mutable std::mutex m_LastErrorMtx; std::string m_LastError; - std::ostringstream* m_LogStream; + + bool m_UseContextPooling = true; + // Keep a maximum of 10 LogContext objects in the pool. + internal::DynamicObjectPool m_LogContextPool{ 10, 2 }; // private c'tor - this class is a singleton Logger(); static void defaultLogPrinter(LogLevel logLevel, const std::string& logMessage, const std::string& file, - const std::string& method, const int line); + const std::string& method, int line); }; + } // namespace pcpp + +#define PCPP_LOG(level, message) \ + do \ + { \ + auto& logger = pcpp::Logger::getInstance(); \ + if (logger.shouldLog(level, LOG_MODULE)) \ + { \ + auto ctx = \ + logger.createLogContext(level, pcpp::LogSource(LOG_MODULE, PCAPPP_FILENAME, __FUNCTION__, __LINE__)); \ + (*ctx) << message; \ + logger.emit(std::move(ctx)); \ + } \ + } while (0) + +#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_DEBUG +# define PCPP_LOG_DEBUG(message) PCPP_LOG(pcpp::LogLevel::Debug, message) +#else +# define PCPP_LOG_DEBUG(message) (void)0 +#endif + +#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_INFO +# define PCPP_LOG_INFO(message) PCPP_LOG(pcpp::LogLevel::Info, message) +#else +# define PCPP_LOG_INFO(message) (void)0 +#endif + +#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_ERROR +# define PCPP_LOG_ERROR(message) PCPP_LOG(pcpp::LogLevel::Error, message) +#else +# define PCPP_LOG_ERROR(message) (void)0 +#endif diff --git a/Common++/header/MacAddress.h b/Common++/header/MacAddress.h index 6e0834b013..1cf5852e6b 100644 --- a/Common++/header/MacAddress.h +++ b/Common++/header/MacAddress.h @@ -4,9 +4,9 @@ #include #include #include -#include -#include +#include #include +#include /// @file @@ -28,11 +28,17 @@ namespace pcpp /// The byte array length should be 6 (as MAC address is 6-byte long), and the remaining bytes are ignored. /// If the byte array is invalid, the constructor throws an exception. /// @param[in] addr A pointer to the byte array containing 6 bytes representing the MAC address - explicit MacAddress(const uint8_t* addr) + explicit MacAddress(const uint8_t addr[6]) { - memcpy(m_Address, addr, sizeof(m_Address)); + std::copy(addr, addr + 6, m_Address.begin()); } + /// A constructor that creates an instance of the class out of a std::array. + /// The array length should be 6 (as MAC address is 6-byte long). + /// @param [in] addr A std::array containing 6 bytes representing the MAC address + explicit MacAddress(const std::array& addr) : m_Address(addr) + {} + /// A constructor that creates an instance of the class out of a std::string. /// If the string doesn't represent a valid MAC address, the constructor throws an exception. /// @param[in] addr the string representing the MAC address in format "00:00:00:00:00:00" @@ -52,16 +58,10 @@ namespace pcpp /// @param[in] fourthOctet Represent the fourth octet in the address /// @param[in] fifthOctet Represent the fifth octet in the address /// @param[in] sixthOctet Represent the sixth octet in the address - inline MacAddress(uint8_t firstOctet, uint8_t secondOctet, uint8_t thirdOctet, uint8_t fourthOctet, - uint8_t fifthOctet, uint8_t sixthOctet) - { - m_Address[0] = firstOctet; - m_Address[1] = secondOctet; - m_Address[2] = thirdOctet; - m_Address[3] = fourthOctet; - m_Address[4] = fifthOctet; - m_Address[5] = sixthOctet; - } + MacAddress(uint8_t firstOctet, uint8_t secondOctet, uint8_t thirdOctet, uint8_t fourthOctet, uint8_t fifthOctet, + uint8_t sixthOctet) + : m_Address{ firstOctet, secondOctet, thirdOctet, fourthOctet, fifthOctet, sixthOctet } + {} /// A constructor that creates an instance out of the initializer list. /// The byte list length should be 6 (as MAC address is 6-byte long). @@ -69,7 +69,7 @@ namespace pcpp /// @param[in] octets An initializer list containing the values of type uint8_t representing the MAC address MacAddress(std::initializer_list octets) { - if (octets.size() != sizeof(m_Address)) + if (octets.size() != m_Address.size()) { throw std::invalid_argument("Invalid initializer list size, should be 6"); } @@ -81,7 +81,7 @@ namespace pcpp /// @return True if addresses are equal, false otherwise bool operator==(const MacAddress& other) const { - return memcmp(m_Address, other.m_Address, sizeof(m_Address)) == 0; + return m_Address == other.m_Address; } /// Overload of the not-equal operator @@ -103,7 +103,7 @@ namespace pcpp throw std::invalid_argument("Invalid initializer list size, should be 6"); } - std::copy(octets.begin(), octets.end(), std::begin(m_Address)); + std::copy(octets.begin(), octets.end(), m_Address.begin()); return *this; } @@ -111,40 +111,46 @@ namespace pcpp /// @return The pointer to raw data const uint8_t* getRawData() const { - return m_Address; + return m_Address.data(); } /// Returns a std::string representation of the address /// @return A string representation of the address std::string toString() const; + /// @return A 6-byte integer representing the MAC address + std::array toByteArray() const + { + return m_Address; + } + /// Allocates a byte array of length 6 and copies address value into it. Array deallocation is user /// responsibility /// @param[in] arr A pointer to where array will be allocated void copyTo(uint8_t** arr) const { - *arr = new uint8_t[sizeof(m_Address)]; - memcpy(*arr, m_Address, sizeof(m_Address)); + *arr = new uint8_t[m_Address.size()]; + std::copy(m_Address.begin(), m_Address.end(), *arr); } /// Gets a pointer to an already allocated byte array and copies the address value to it. /// This method assumes array allocated size is at least 6 (the size of a MAC address) /// @param[in] arr A pointer to the array which address will be copied to - void copyTo(uint8_t* arr) const + void copyTo(uint8_t arr[6]) const { - memcpy(arr, m_Address, sizeof(m_Address)); + std::copy(m_Address.begin(), m_Address.end(), arr); } /// A static value representing a zero value of MAC address, meaning address of value "00:00:00:00:00:00" static MacAddress Zero; private: - uint8_t m_Address[6] = { 0 }; + std::array m_Address{}; }; - inline std::ostream& operator<<(std::ostream& os, const pcpp::MacAddress& macAddress) + inline std::ostream& operator<<(std::ostream& oss, const pcpp::MacAddress& macAddress) { - os << macAddress.toString(); - return os; + oss << macAddress.toString(); + return oss; } } // namespace pcpp diff --git a/Common++/header/OUILookup.h b/Common++/header/OUILookup.h index 20ac58d56f..105c23b9a0 100644 --- a/Common++/header/OUILookup.h +++ b/Common++/header/OUILookup.h @@ -24,6 +24,10 @@ namespace pcpp /// be 36, and the second element will be unsigned integer equivalent of "XX:XX:XX:XX:X0:00" and vendor name. struct MaskedFilter { + MaskedFilter(int maskVal, std::unordered_map map) + : mask(maskVal), vendorMap(std::move(map)) + {} + int mask; std::unordered_map vendorMap; }; @@ -37,7 +41,7 @@ namespace pcpp /// MAC addresses with only first three octets. The first element is unsigned integer equivalent of "XX:XX:XX" /// formatted MAC address - typedef std::unordered_map OUIVendorMap; + using OUIVendorMap = std::unordered_map; /// Internal vendor list for MAC addresses OUIVendorMap vendorMap; diff --git a/Common++/header/ObjectPool.h b/Common++/header/ObjectPool.h new file mode 100644 index 0000000000..15d479cb90 --- /dev/null +++ b/Common++/header/ObjectPool.h @@ -0,0 +1,185 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace pcpp +{ + namespace internal + { + /// @brief A generic object pool implementation. + /// + /// This class provides a generic object pool that can be used to efficiently manage and reuse objects of any + /// type. Objects can be acquired from the pool using the `acquireObject` method, and released back to the pool + /// using the `releaseObject` method. If the pool is empty when acquiring an object, a new object will be + /// created. If the pool is full when releasing an object, the object will be deleted. + /// + /// @tparam T The type of objects managed by the pool. Must be default constructable. + template ::value, bool>::type = true> + class DynamicObjectPool + { + public: + constexpr static std::size_t DEFAULT_POOL_SIZE = 100; +#pragma push_macro("max") // Undefine max to avoid conflict with std::numeric_limits::max() +#undef max + constexpr static std::size_t INFINITE_POOL_SIZE = std::numeric_limits::max(); +#pragma pop_macro("max") + + /// A constructor for this class that creates a pool of objects + /// @param[in] maxPoolSize The maximum number of objects in the pool + /// @param[in] initialSize The number of objects to preallocate in the pool + explicit DynamicObjectPool(std::size_t maxPoolSize = DEFAULT_POOL_SIZE, std::size_t initialSize = 0) + : m_MaxPoolSize(maxPoolSize) + { + if (initialSize > maxPoolSize) + throw std::invalid_argument("Preallocated objects cannot exceed the maximum pool size"); + + if (initialSize > 0) + this->preallocate(initialSize); + } + + // These don't strictly need to be deleted, but don't need to be implemented for now either. + DynamicObjectPool(const DynamicObjectPool&) = delete; + DynamicObjectPool(DynamicObjectPool&&) = delete; + DynamicObjectPool& operator=(const DynamicObjectPool&) = delete; + DynamicObjectPool& operator=(DynamicObjectPool&&) = delete; + + /// A destructor for this class that deletes all objects in the pool + ~DynamicObjectPool() + { + clear(); + } + + /// @brief Acquires a unique pointer to an object from the pool. + /// + /// This method acquires a unique pointer to an object from the pool. + /// If the pool is empty, a new object will be created. + /// + /// @return A unique pointer to an object from the pool. + std::unique_ptr acquireObject() + { + return std::unique_ptr(acquireObjectRaw()); + } + + /// @brief Acquires a raw pointer to an object from the pool. + /// + /// This method acquires a raw pointer to an object from the pool. + /// If the pool is empty, a new object will be created. + /// + /// @return A raw pointer to an object from the pool. + T* acquireObjectRaw() + { + std::unique_lock lock(m_Mutex); + + if (m_Pool.empty()) + { + // We don't need the lock anymore, so release it. + lock.unlock(); + return new T(); + } + + T* obj = m_Pool.top(); + m_Pool.pop(); + return obj; + } + + /// @brief Releases a unique pointer to an object back to the pool. + /// + /// This method releases a unique pointer to an object back to the pool. + /// If the pool is full, the object will be deleted. + /// + /// @param[in] obj The unique pointer to the object to release. + void releaseObject(std::unique_ptr obj) + { + releaseObjectRaw(obj.release()); + } + + /// @brief Releases a raw pointer to an object back to the pool. + /// + /// This method releases a raw pointer to an object back to the pool. + /// If the pool is full, the object will be deleted. + /// + /// @param[in] obj The raw pointer to the object to release. + void releaseObjectRaw(T* obj) + { + std::unique_lock lock(m_Mutex); + + if (m_MaxPoolSize == INFINITE_POOL_SIZE || m_Pool.size() < m_MaxPoolSize) + { + m_Pool.push(obj); + } + else + { + // We don't need the lock anymore, so release it. + lock.unlock(); + delete obj; + } + } + + /// @brief Gets the current number of objects in the pool. + std::size_t size() const + { + std::lock_guard lock(m_Mutex); + return m_Pool.size(); + } + + /// @brief Gets the maximum number of objects in the pool. + std::size_t maxSize() const + { + std::lock_guard lock(m_Mutex); + return m_MaxPoolSize; + } + + /// @brief Sets the maximum number of objects in the pool. + void setMaxSize(std::size_t maxSize) + { + std::lock_guard lock(m_Mutex); + m_MaxPoolSize = maxSize; + + // If the new max size is less than the current size, we need to remove some objects from the pool. + while (m_Pool.size() > m_MaxPoolSize) + { + delete m_Pool.top(); + m_Pool.pop(); + } + } + + /// @brief Pre-allocates up to a minimum number of objects in the pool. + /// @param count The number of objects to pre-allocate. + void preallocate(std::size_t count) + { + std::unique_lock lock(m_Mutex); + + if (m_MaxPoolSize < count) + { + throw std::invalid_argument("Preallocated objects cannot exceed the maximum pool size"); + } + + // If the pool is already larger than the requested count, we don't need to do anything. + for (std::size_t i = m_Pool.size(); i < count; i++) + { + m_Pool.push(new T()); + } + } + + /// @brief Deallocates and releases all objects currently held by the pool. + void clear() + { + std::unique_lock lock(m_Mutex); + while (!m_Pool.empty()) + { + delete m_Pool.top(); + m_Pool.pop(); + } + } + + private: + std::size_t m_MaxPoolSize; ///< The maximum number of objects in the pool + mutable std::mutex m_Mutex; ///< Mutex for thread safety + std::stack m_Pool; ///< The pool of objects + }; + } // namespace internal +} // namespace pcpp diff --git a/Common++/header/PointerVector.h b/Common++/header/PointerVector.h index be2a072c56..399d7c62df 100644 --- a/Common++/header/PointerVector.h +++ b/Common++/header/PointerVector.h @@ -1,8 +1,8 @@ #pragma once #include -#include -#include +#include +#include #include #include #include @@ -56,8 +56,7 @@ namespace pcpp using ConstVectorIterator = typename std::vector::const_iterator; /// A constructor that create an empty instance of this object - PointerVector() - {} + PointerVector() = default; /// Copies the vector along with all elements inside it. /// All elements inside the copied vector are duplicates and the originals remain unchanged. @@ -86,6 +85,12 @@ namespace pcpp /// @return A reference to the current object. PointerVector& operator=(const PointerVector& other) { + // Self-assignment check. + if (this == &other) + { + return *this; + } + // Saves a copy of the old pointer to defer cleanup. auto oldValues = m_Vector; try @@ -277,7 +282,7 @@ namespace pcpp /// Removes an element from the vector and transfers ownership to the returned unique pointer. /// @param[in] position An iterator pointing to the element to detach. /// @return An unique pointer that holds ownership of the detached element. - std::unique_ptr getAndDetach(VectorIterator const& position) + std::unique_ptr getAndDetach(const VectorIterator& position) { std::unique_ptr result(*position); m_Vector.erase(position); @@ -304,7 +309,7 @@ namespace pcpp /// Performs a copy of the vector along with its elements. /// The caller is responsible of freeing the copied elements. /// @return A vector of pointers to the newly copied elements. - static std::vector deepCopyUnsafe(std::vector const& origin) + static std::vector deepCopyUnsafe(const std::vector& origin) { std::vector copyVec; // Allocate the vector initially to ensure no exceptions are thrown during push_back. @@ -335,7 +340,7 @@ namespace pcpp /// Calling this function with non-heap allocated pointers is UB. /// @param[in] origin The vector of elements to free. /// @remarks The vector's contents are not cleared and will point to invalid locations in memory. - static void freeVectorUnsafe(std::vector const& origin) + static void freeVectorUnsafe(const std::vector& origin) { for (auto& obj : origin) { diff --git a/Common++/header/SystemUtils.h b/Common++/header/SystemUtils.h index bd557ca824..f638a8dbb2 100644 --- a/Common++/header/SystemUtils.h +++ b/Common++/header/SystemUtils.h @@ -1,12 +1,17 @@ #pragma once -#include +#include "DeprecationUtils.h" + +#include #include #include /// @file -#define MAX_NUM_OF_CORES 32 +enum : uint8_t +{ + MAX_NUM_OF_CORES = 32 +}; #ifdef _MSC_VER int gettimeofday(struct timeval* tp, struct timezone* tzp); @@ -112,7 +117,7 @@ namespace pcpp static const SystemCore IdToSystemCore[MAX_NUM_OF_CORES]; }; - typedef uint32_t CoreMask; + using CoreMask = uint32_t; /// Get total number of cores on device /// @return Total number of CPU cores on device @@ -158,11 +163,17 @@ namespace pcpp /// A multi-platform version of the popular sleep method. This method simply runs the right sleep method, according /// to the platform it is running on. /// @param[in] seconds Number of seconds to sleep + /// @deprecated Please use std::this_thread::sleep_for(). It is a standard C++ (since C++11) method which is already + /// cross-platform + PCPP_DEPRECATED("Please use std::this_thread::sleep_for(std::chrono::seconds(seconds)) instead") void multiPlatformSleep(uint32_t seconds); /// A multi-platform version of sleep in milliseconds resolution. This method simply runs the right sleep method, /// according to the platform it is running on. /// @param[in] milliseconds Number of milliseconds to sleep + /// @deprecated Please use std::this_thread::sleep_for(). It is a standard C++ (since C++11) method which is already + /// cross-platform + PCPP_DEPRECATED("Please use std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)) instead") void multiPlatformMSleep(uint32_t milliseconds); /// A multi-platform version of `htons` which convert host to network byte order @@ -247,7 +258,7 @@ namespace pcpp /// @typedef EventHandlerCallback /// The callback to be invoked when the event occurs /// @param[in] cookie A pointer the the cookie provided by the user in ApplicationEventHandler c'tor - typedef void (*EventHandlerCallback)(void* cookie); + using EventHandlerCallback = void (*)(void*); /// As ApplicationEventHandler is a singleton, this is the static getter to retrieve its instance /// @return The singleton instance of ApplicationEventHandler diff --git a/Common++/src/GeneralUtils.cpp b/Common++/src/GeneralUtils.cpp index 04aec21a62..1143e25d96 100644 --- a/Common++/src/GeneralUtils.cpp +++ b/Common++/src/GeneralUtils.cpp @@ -12,14 +12,18 @@ namespace pcpp std::string byteArrayToHexString(const uint8_t* byteArr, size_t byteArrSize, int stringSizeLimit) { if (stringSizeLimit <= 0) - stringSizeLimit = byteArrSize; + { + stringSizeLimit = static_cast(byteArrSize); + } std::stringstream dataStream; dataStream << std::hex; for (size_t i = 0; i < byteArrSize; ++i) { if (i >= static_cast(stringSizeLimit)) + { break; + } dataStream << std::setw(2) << std::setfill('0') << static_cast(byteArr[i]); } @@ -30,11 +34,17 @@ namespace pcpp static int char2int(char input) { if (input >= '0' && input <= '9') + { return input - '0'; + } if (input >= 'A' && input <= 'F') + { return input - 'A' + 10; + } if (input >= 'a' && input <= 'f') + { return input - 'a' + 10; + } return -1; } @@ -50,10 +60,12 @@ namespace pcpp for (size_t i = 0; i < hexString.length(); i += 2) { if (i >= resultByteArrSize * 2) + { return resultByteArrSize; + } - int firstChar = char2int(hexString[i]); - int secondChar = char2int(hexString[i + 1]); + const int firstChar = char2int(hexString[i]); + const int secondChar = char2int(hexString[i + 1]); if (firstChar < 0 || secondChar < 0) { PCPP_LOG_ERROR("Input string has an illegal character"); @@ -82,12 +94,15 @@ namespace pcpp } if (0 == memcmp(ptr, needle, needleLen)) + { return ptr; - else - ++ptr; + } + ++ptr; } else + { break; + } } return nullptr; diff --git a/Common++/src/IpAddress.cpp b/Common++/src/IpAddress.cpp index dd1c1a3d5f..f42ddbcf87 100644 --- a/Common++/src/IpAddress.cpp +++ b/Common++/src/IpAddress.cpp @@ -33,9 +33,11 @@ namespace pcpp char addrBuffer[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, toBytes(), addrBuffer, sizeof(addrBuffer)) != nullptr) - return std::string(addrBuffer); + { + return addrBuffer; + } - return std::string(); + return {}; } bool IPv4Address::isMulticast() const @@ -66,6 +68,7 @@ namespace pcpp } catch (const std::invalid_argument& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled PCPP_LOG_ERROR(e.what()); return false; } @@ -73,7 +76,7 @@ namespace pcpp bool IPv4Address::isValidIPv4Address(const std::string& addrAsString) { - struct sockaddr_in sa_in; + sockaddr_in sa_in{}; return inet_pton(AF_INET, addrAsString.data(), &(sa_in.sin_addr)) > 0; } @@ -86,9 +89,11 @@ namespace pcpp char addrBuffer[INET6_ADDRSTRLEN]; if (inet_ntop(AF_INET6, toBytes(), addrBuffer, sizeof(addrBuffer)) != nullptr) - return std::string(addrBuffer); + { + return addrBuffer; + } - return std::string(); + return {}; } bool IPv6Address::isMulticast() const @@ -126,6 +131,7 @@ namespace pcpp } catch (const std::invalid_argument& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled PCPP_LOG_ERROR(e.what()); return false; } @@ -133,7 +139,7 @@ namespace pcpp bool IPv6Address::isValidIPv6Address(const std::string& addrAsString) { - struct sockaddr_in6 sa_in6; + sockaddr_in6 sa_in6{}; return inet_pton(AF_INET6, addrAsString.data(), &(sa_in6.sin6_addr)) > 0; } @@ -170,18 +176,16 @@ namespace pcpp return true; } - uint32_t maskAsInt = be32toh(maskAddress.toInt()); - std::bitset<32> bitset(maskAsInt); + const uint32_t maskAsInt = be32toh(maskAddress.toInt()); + const std::bitset<32> bitset(maskAsInt); auto bitsetCount = bitset.count(); if (bitsetCount == 32) { return true; } - else - { - return maskAsInt << bitsetCount == 0; - } + + return maskAsInt << bitsetCount == 0; } void IPv4Network::initFromAddressAndPrefixLength(const IPv4Address& address, uint8_t prefixLen) @@ -227,7 +231,8 @@ namespace pcpp IPv4Network::IPv4Network(const std::string& addressAndNetmask) { std::stringstream stream(addressAndNetmask); - std::string networkPrefixStr, netmaskStr; + std::string networkPrefixStr; + std::string netmaskStr; std::getline(stream, networkPrefixStr, '/'); std::getline(stream, netmaskStr); @@ -249,7 +254,7 @@ namespace pcpp if (std::all_of(netmaskStr.begin(), netmaskStr.end(), ::isdigit)) { - uint32_t prefixLen = std::stoi(netmaskStr); + const uint32_t prefixLen = std::stoi(netmaskStr); if (prefixLen > 32) { throw std::invalid_argument("Prefix length must be an integer between 0 and 32"); @@ -278,26 +283,26 @@ namespace pcpp uint8_t IPv4Network::getPrefixLen() const { - std::bitset<32> bitset(m_Mask); + const std::bitset<32> bitset(m_Mask); return bitset.count(); } IPv4Address IPv4Network::getLowestAddress() const { - std::bitset<32> bitset(m_Mask); + const std::bitset<32> bitset(m_Mask); return bitset.count() < 32 ? m_NetworkPrefix + htobe32(1) : m_NetworkPrefix; } IPv4Address IPv4Network::getHighestAddress() const { auto tempAddress = static_cast(m_NetworkPrefix | ~m_Mask); - std::bitset<32> bitset(m_Mask); + const std::bitset<32> bitset(m_Mask); return bitset.count() < 32 ? tempAddress - htobe32(1) : tempAddress; } uint64_t IPv4Network::getTotalAddressCount() const { - std::bitset<32> bitset(static_cast(~m_Mask)); + const std::bitset<32> bitset(~static_cast(m_Mask)); return 1ULL << bitset.count(); } @@ -308,8 +313,8 @@ namespace pcpp bool IPv4Network::includes(const IPv4Network& network) const { - uint32_t lowestAddress = network.m_NetworkPrefix; - uint32_t highestAddress = network.m_NetworkPrefix | ~network.m_Mask; + const uint32_t lowestAddress = network.m_NetworkPrefix; + const uint32_t highestAddress = network.m_NetworkPrefix | ~network.m_Mask; return ((lowestAddress & m_Mask) == m_NetworkPrefix && (highestAddress & m_Mask) == m_NetworkPrefix); } @@ -344,7 +349,7 @@ namespace pcpp { continue; } - std::bitset<8> bitset(curByte); + const std::bitset<8> bitset(curByte); if (((curByte << bitset.count()) & 0xff) != 0) { return false; @@ -364,15 +369,15 @@ namespace pcpp { memset(m_Mask, 0, IPV6_ADDR_SIZE); int remainingPrefixLen = prefixLen; - for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++) + for (auto& byte : m_Mask) { if (remainingPrefixLen >= 8) { - m_Mask[byteIndex] = 0xff; + byte = 0xff; } else if (remainingPrefixLen > 0) { - m_Mask[byteIndex] = 0xff << (8 - remainingPrefixLen); + byte = 0xff << (8 - remainingPrefixLen); } else { @@ -433,7 +438,8 @@ namespace pcpp IPv6Network::IPv6Network(const std::string& addressAndNetmask) { std::stringstream stream(addressAndNetmask); - std::string networkPrefixStr, netmaskStr; + std::string networkPrefixStr; + std::string netmaskStr; std::getline(stream, networkPrefixStr, '/'); std::getline(stream, netmaskStr); @@ -454,7 +460,7 @@ namespace pcpp } if (std::all_of(netmaskStr.begin(), netmaskStr.end(), ::isdigit)) { - uint32_t prefixLen = std::stoi(netmaskStr); + const uint32_t prefixLen = std::stoi(netmaskStr); if (prefixLen > 128) { throw std::invalid_argument("Prefix length must be an integer between 0 and 128"); @@ -484,10 +490,10 @@ namespace pcpp uint8_t IPv6Network::getPrefixLen() const { uint8_t result = 0; - for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++) + for (const auto& byte : m_Mask) { - std::bitset<8> bs(m_Mask[byteIndex]); - result += static_cast(bs.count()); + const std::bitset<8> bset(byte); + result += static_cast(bset.count()); } return result; } @@ -520,10 +526,10 @@ namespace pcpp uint64_t IPv6Network::getTotalAddressCount() const { int numOfBitset = 0; - for (auto byteIndex = 0; byteIndex < IPV6_ADDR_SIZE; byteIndex++) + for (const auto& byte : m_Mask) { - std::bitset<8> bitset(static_cast(~m_Mask[byteIndex])); - numOfBitset += bitset.count(); + const std::bitset<8> bitset(static_cast(~byte)); + numOfBitset += static_cast(bitset.count()); } if (numOfBitset >= 64) diff --git a/Common++/src/IpUtils.cpp b/Common++/src/IpUtils.cpp index 3c812d5bfe..e6fa1150b6 100644 --- a/Common++/src/IpUtils.cpp +++ b/Common++/src/IpUtils.cpp @@ -18,68 +18,82 @@ namespace pcpp { namespace internal { - in_addr* sockaddr2in_addr(sockaddr* sa) + in_addr* sockaddr2in_addr(sockaddr* sAddr) { - if (sa == nullptr) + if (sAddr == nullptr) + { throw std::invalid_argument("sockaddr is nullptr"); + } - if (sa->sa_family != AF_INET) + if (sAddr->sa_family != AF_INET) + { throw std::invalid_argument("sockaddr family is not AF_INET."); + } - return &(reinterpret_cast(sa)->sin_addr); + return &(reinterpret_cast(sAddr)->sin_addr); } - in_addr* try_sockaddr2in_addr(sockaddr* sa) + in_addr* try_sockaddr2in_addr(sockaddr* sAddr) { try { - return sockaddr2in_addr(sa); + return sockaddr2in_addr(sAddr); } catch (const std::invalid_argument& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_DEBUG is disabled PCPP_LOG_DEBUG("Extraction failed: " << e.what() << " Returning nullptr."); return nullptr; } } - in6_addr* sockaddr2in6_addr(sockaddr* sa) + in6_addr* sockaddr2in6_addr(sockaddr* sAddr) { - if (sa == nullptr) + if (sAddr == nullptr) + { throw std::invalid_argument("sockaddr is nullptr"); + } - if (sa->sa_family != AF_INET6) + if (sAddr->sa_family != AF_INET6) + { throw std::invalid_argument("sockaddr family is not AF_INET6."); + } - return &(reinterpret_cast(sa)->sin6_addr); + return &(reinterpret_cast(sAddr)->sin6_addr); } - in6_addr* try_sockaddr2in6_addr(sockaddr* sa) + in6_addr* try_sockaddr2in6_addr(sockaddr* sAddr) { try { - return sockaddr2in6_addr(sa); + return sockaddr2in6_addr(sAddr); } catch (const std::invalid_argument& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_DEBUG is disabled PCPP_LOG_DEBUG("Extraction failed: " << e.what() << " Returning nullptr."); return nullptr; } } - void sockaddr2string(sockaddr const* sa, char* resultString, size_t resultBufLen) + void sockaddr2string(const sockaddr* sAddr, char* resultString, size_t resultBufLen) { - if (sa == nullptr) + if (sAddr == nullptr) + { throw std::invalid_argument("sockaddr is nullptr"); + } - switch (sa->sa_family) + switch (sAddr->sa_family) { case AF_INET: { PCPP_LOG_DEBUG("IPv4 packet address"); if (resultBufLen < INET_ADDRSTRLEN) + { throw std::invalid_argument("Insufficient buffer"); + } - if (inet_ntop(AF_INET, &(reinterpret_cast(sa)->sin_addr), resultString, + if (inet_ntop(AF_INET, &(reinterpret_cast(sAddr)->sin_addr), resultString, resultBufLen) == nullptr) { throw std::runtime_error("Unknown error during conversion"); @@ -90,9 +104,11 @@ namespace pcpp { PCPP_LOG_DEBUG("IPv6 packet address"); if (resultBufLen < INET6_ADDRSTRLEN) + { throw std::invalid_argument("Insufficient buffer"); + } - if (inet_ntop(AF_INET6, &(reinterpret_cast(sa)->sin6_addr), resultString, + if (inet_ntop(AF_INET6, &(reinterpret_cast(sAddr)->sin6_addr), resultString, resultBufLen) == nullptr) { throw std::runtime_error("Unknown error during conversion"); diff --git a/Common++/src/Logger.cpp b/Common++/src/Logger.cpp index 7608911b6b..39056120cc 100644 --- a/Common++/src/Logger.cpp +++ b/Common++/src/Logger.cpp @@ -1,56 +1,110 @@ -#include #include "Logger.h" +#include +#include +#include +#include +#include + namespace pcpp { + // Alpine Linux incorrectly declares strerror_r + // https://stackoverflow.com/questions/41953104/strerror-r-is-incorrectly-declared-on-alpine-linux + char* checkError(int /*unused*/, char* buffer, int /*unused*/) + { + return buffer; + } + + char* checkError(char* result, const char* /*unused*/, int /*unused*/) + { + return result; + } + + std::string getErrorString(int errnum) + { + std::array buffer{}; +#if defined(_WIN32) + strerror_s(buffer.data(), buffer.size(), errnum); + return buffer.data(); +#else + return checkError(strerror_r(errnum, buffer.data(), BUFSIZ), buffer.data(), errnum); +#endif + } + Logger::Logger() : m_LogsEnabled(true), m_LogPrinter(&defaultLogPrinter) { m_LastError.reserve(200); - for (int i = 0; i < NumOfLogModules; i++) - m_LogModulesArray[i] = Info; + m_LogModulesArray.fill(LogLevel::Info); } std::string Logger::logLevelAsString(LogLevel logLevel) { switch (logLevel) { - case Logger::Error: + case LogLevel::Off: + return "OFF"; + case LogLevel::Error: return "ERROR"; - case Logger::Info: + case LogLevel::Info: return "INFO"; - default: + case LogLevel::Debug: return "DEBUG"; + default: + return "UNKNOWN"; } } - void Logger::defaultLogPrinter(LogLevel logLevel, const std::string& logMessage, const std::string& file, - const std::string& method, const int line) + std::unique_ptr Logger::createLogContext() { - std::ostringstream sstream; - sstream << file << ": " << method << ":" << line; - std::cerr << std::left << "[" << std::setw(5) << Logger::logLevelAsString(logLevel) << ": " << std::setw(45) - << sstream.str() << "] " << logMessage << std::endl; + return createLogContext(LogLevel::Info, {}); // call the other createLogContext method + } + std::unique_ptr Logger::createLogContext(LogLevel level, LogSource const& source) + { + if (m_UseContextPooling) + { + auto ctx = m_LogContextPool.acquireObject(); + ctx->init(level, source); + return ctx; + } + return std::unique_ptr(new internal::LogContext(level, source)); } - std::ostringstream* Logger::internalCreateLogStream() + void Logger::emit(std::unique_ptr message) { - return new std::ostringstream(); + emit(message->m_Source, message->m_Level, message->m_Stream.str()); + // Pushes the message back to the pool if pooling is enabled. Otherwise, the message is deleted. + if (m_UseContextPooling) + { + m_LogContextPool.releaseObject(std::move(message)); + } } - void Logger::internalPrintLogMessage(std::ostringstream* logStream, Logger::LogLevel logLevel, const char* file, - const char* method, int line) + void Logger::emit(LogSource const& source, LogLevel logLevel, std::string const& message) { - std::string logMessage = logStream->str(); - delete logStream; - if (logLevel == Logger::Error) + // If the log level is an error, save the error to the last error message variable. + if (logLevel == LogLevel::Error) { - m_LastError = logMessage; + std::lock_guard lock(m_LastErrorMtx); + m_LastError = message; } if (m_LogsEnabled) { - m_LogPrinter(logLevel, logMessage, file, method, line); + m_LogPrinter(logLevel, message, source.file, source.function, source.line); } } + void Logger::defaultLogPrinter(LogLevel logLevel, const std::string& logMessage, const std::string& file, + const std::string& method, const int line) + { + // This mutex is used to prevent multiple threads from writing to the console at the same time. + static std::mutex logMutex; + + std::ostringstream sstream; + sstream << file << ": " << method << ":" << line; + + std::unique_lock lock(logMutex); + std::cerr << std::left << "[" << std::setw(5) << Logger::logLevelAsString(logLevel) << ": " << std::setw(45) + << sstream.str() << "] " << logMessage << std::endl; + } } // namespace pcpp diff --git a/Common++/src/MacAddress.cpp b/Common++/src/MacAddress.cpp index 47d990a017..18886faaea 100644 --- a/Common++/src/MacAddress.cpp +++ b/Common++/src/MacAddress.cpp @@ -8,9 +8,12 @@ namespace pcpp std::string MacAddress::toString() const { char str[19]; - snprintf(str, sizeof str, "%02x:%02x:%02x:%02x:%02x:%02x", m_Address[0], m_Address[1], m_Address[2], - m_Address[3], m_Address[4], m_Address[5]); - return std::string(str); + if (snprintf(str, sizeof str, "%02x:%02x:%02x:%02x:%02x:%02x", m_Address[0], m_Address[1], m_Address[2], + m_Address[3], m_Address[4], m_Address[5]) < 0) + { + throw std::runtime_error("Conversion of MAC address to string failed"); + } + return str; } MacAddress::MacAddress(const std::string& address) @@ -18,6 +21,7 @@ namespace pcpp constexpr size_t validMacAddressLength = 17; unsigned int values[6]; if (address.size() != validMacAddressLength || + // NOLINTNEXTLINE(cert-err34-c) sscanf(address.c_str(), "%x:%x:%x:%x:%x:%x", &values[0], &values[1], &values[2], &values[3], &values[4], &values[5]) != 6) { diff --git a/Common++/src/OUILookup.cpp b/Common++/src/OUILookup.cpp index d116ee8388..6d1700a572 100644 --- a/Common++/src/OUILookup.cpp +++ b/Common++/src/OUILookup.cpp @@ -18,10 +18,14 @@ namespace pcpp for (const auto& line : parsedJson.items()) { if (!(line.value().is_object())) + { continue; + } auto val = line.value().get(); if (!(val.contains("vendor"))) + { continue; + } std::vector vLocalMaskedFilter; if (val.contains("maskedFilters") && val["maskedFilters"].is_array()) @@ -30,13 +34,15 @@ namespace pcpp for (const auto& entry : val["maskedFilters"]) { if (!entry.is_object()) + { continue; + } auto subVal = entry.get(); if (subVal.contains("mask") && subVal.contains("vendors") && subVal["mask"].is_number_integer() && subVal["vendors"].is_object()) { - int maskValue = subVal["mask"].get(); - vLocalMaskedFilter.push_back({ maskValue, {} }); + const int maskValue = subVal["mask"].get(); + vLocalMaskedFilter.emplace_back(maskValue, std::unordered_map{}); // Parse masked filter for (const auto& subentry : subVal["vendors"].items()) @@ -70,7 +76,7 @@ namespace pcpp dataFile.open(path); if (!dataFile.is_open()) { - PCPP_LOG_ERROR(std::string("Can't open OUI database: ") + strerror(errno)); + PCPP_LOG_ERROR(std::string("Can't open OUI database: ") + getErrorString(errno)); return -1; } @@ -81,28 +87,34 @@ namespace pcpp std::string OUILookup::getVendorName(const pcpp::MacAddress& addr) { if (vendorMap.empty()) + { PCPP_LOG_DEBUG("Vendor map is empty"); + } // Get MAC address uint8_t buffArray[6]; addr.copyTo(buffArray); - uint64_t macAddr = (((uint64_t)((buffArray)[5]) << 0) + ((uint64_t)((buffArray)[4]) << 8) + - ((uint64_t)((buffArray)[3]) << 16) + ((uint64_t)((buffArray)[2]) << 24) + - ((uint64_t)((buffArray)[1]) << 32) + ((uint64_t)((buffArray)[0]) << 40)); + const uint64_t macAddr = (((uint64_t)((buffArray)[5]) << 0) + ((uint64_t)((buffArray)[4]) << 8) + + ((uint64_t)((buffArray)[3]) << 16) + ((uint64_t)((buffArray)[2]) << 24) + + ((uint64_t)((buffArray)[1]) << 32) + ((uint64_t)((buffArray)[0]) << 40)); auto itr = vendorMap.find(macAddr >> 24); if (itr == vendorMap.end()) + { return "Unknown"; + } for (const auto& entry : itr->second.maskedFilter) { - uint64_t maskValue = ~((1 << (48 - entry.mask)) - 1); - uint64_t bufferAddr = macAddr & maskValue; + const uint64_t maskValue = ~((1 << (48 - entry.mask)) - 1); + const uint64_t bufferAddr = macAddr & maskValue; auto subItr = entry.vendorMap.find(bufferAddr); if (subItr != entry.vendorMap.end()) + { return subItr->second; + } } return itr->second.vendorName; diff --git a/Common++/src/SystemUtils.cpp b/Common++/src/SystemUtils.cpp index 9a5bc84a92..91e76583f4 100644 --- a/Common++/src/SystemUtils.cpp +++ b/Common++/src/SystemUtils.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #if defined(__APPLE__) # include # include @@ -121,13 +122,13 @@ namespace pcpp GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; #else - return sysconf(_SC_NPROCESSORS_ONLN); + return static_cast(sysconf(_SC_NPROCESSORS_ONLN)); #endif } CoreMask getCoreMaskForAllMachineCores() { - int numOfCores = getNumOfCores() < 32 ? getNumOfCores() : 32; + const int numOfCores = getNumOfCores() < 32 ? getNumOfCores() : 32; CoreMask result = 0; for (int i = 0; i < numOfCores; i++) { @@ -163,47 +164,49 @@ namespace pcpp void createCoreVectorFromCoreMask(CoreMask coreMask, std::vector& resultVec) { - int i = 0; + int idx = 0; while (coreMask != 0) { - if (1 & coreMask) + if ((1 & coreMask) != 0U) { - resultVec.push_back(SystemCores::IdToSystemCore[i]); + resultVec.push_back(SystemCores::IdToSystemCore[idx]); } coreMask = coreMask >> 1; - i++; + ++idx; } } std::string executeShellCommand(const std::string& command) { - std::unique_ptr pipe = std::unique_ptr(POPEN(command.c_str(), "r")); + const std::unique_ptr pipe = + std::unique_ptr(POPEN(command.c_str(), "r")); if (!pipe) { throw std::runtime_error("Error executing command: " + command); } - std::array buffer; + std::array buffer{}; std::string result; - while (!feof(pipe.get())) + while (feof(pipe.get()) == 0) { if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + { result += buffer.data(); // Using the C-string overload of string append. + } } return result; } bool directoryExists(const std::string& dirPath) { - struct stat info; + struct stat info{}; if (stat(dirPath.c_str(), &info) != 0) + { return false; - else if (info.st_mode & S_IFDIR) - return true; - else - return false; + } + return (info.st_mode & S_IFDIR) != 0; } int clockGetTime(long& sec, long& nsec) @@ -255,14 +258,14 @@ namespace pcpp #else // Linux -# include +# include - timespec ts; - int res = clock_gettime(CLOCK_REALTIME, &ts); + timespec tspec{}; + const int res = clock_gettime(CLOCK_REALTIME, &tspec); if (res == 0) { - sec = ts.tv_sec; - nsec = ts.tv_nsec; + sec = tspec.tv_sec; + nsec = tspec.tv_nsec; } return res; @@ -271,20 +274,12 @@ namespace pcpp void multiPlatformSleep(uint32_t seconds) { -#if defined(_WIN32) - Sleep(seconds * 1000); -#else - sleep(seconds); -#endif + std::this_thread::sleep_for(std::chrono::seconds(seconds)); } void multiPlatformMSleep(uint32_t milliseconds) { -#if defined(_WIN32) - Sleep(milliseconds); -#else - usleep(milliseconds * 1000); -#endif + std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds)); } uint16_t hostToNet16(uint16_t host) @@ -344,8 +339,10 @@ namespace pcpp const std::lock_guard lock(UnixLinuxHandlerRoutineMutex); if (ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler != nullptr) + { ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler( ApplicationEventHandler::getInstance().m_ApplicationInterruptedCookie); + } ApplicationEventHandler::getInstance().m_ApplicationInterruptedHandler = nullptr; @@ -371,7 +368,7 @@ namespace pcpp #if defined(_WIN32) SetConsoleCtrlHandler((PHANDLER_ROUTINE)handlerRoutine, TRUE); #else - struct sigaction action; + struct sigaction action{}; memset(&action, 0, sizeof(struct sigaction)); action.sa_handler = handlerRoutine; sigemptyset(&action.sa_mask); diff --git a/Common++/src/TablePrinter.cpp b/Common++/src/TablePrinter.cpp index ac7745f18f..9adb8fbd43 100644 --- a/Common++/src/TablePrinter.cpp +++ b/Common++/src/TablePrinter.cpp @@ -62,7 +62,7 @@ namespace pcpp std::cout << std::left << "| " << std::setw(m_ColumnWidths.at(i)) << val << " "; } - std::cout << "|" << std::endl; + std::cout << "|" << '\n'; return true; } @@ -90,18 +90,22 @@ namespace pcpp } auto totalLen = std::accumulate(m_ColumnWidths.begin(), m_ColumnWidths.end(), m_ColumnWidths.size() * 3) + 1; - std::cout << std::string(totalLen, '-') << std::endl; + std::cout << std::string(totalLen, '-') << '\n'; } void TablePrinter::closeTable() { // if this method was already called - do nothing if (m_TableClosed) + { return; + } // if no rows were printed - do nothing if (m_FirstRow) + { return; + } printSeparator(); @@ -124,7 +128,7 @@ namespace pcpp std::cout << std::left << "| " << std::setw(m_ColumnWidths.at(i)) << m_ColumnNames.at(i) << " "; } - std::cout << "|" << std::endl; + std::cout << "|" << '\n'; printSeparator(); } diff --git a/Examples/ArpSpoofing/CMakeLists.txt b/Examples/ArpSpoofing/CMakeLists.txt index 81aeb2443d..aba6a4272a 100644 --- a/Examples/ArpSpoofing/CMakeLists.txt +++ b/Examples/ArpSpoofing/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(ArpSpoofing PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS ArpSpoofing - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS ArpSpoofing EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/ArpSpoofing/main.cpp b/Examples/ArpSpoofing/main.cpp index 837e2555be..538dd4c7b8 100644 --- a/Examples/ArpSpoofing/main.cpp +++ b/Examples/ArpSpoofing/main.cpp @@ -85,7 +85,7 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe pDevice->sendPacket(&arpRequest); pcpp::RawPacketVector capturedPackets; pDevice->startCapture(capturedPackets); - pcpp::multiPlatformSleep(2); + std::this_thread::sleep_for(std::chrono::seconds(2)); pDevice->stopCapture(); if (capturedPackets.size() < 1) @@ -160,7 +160,7 @@ void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatew pDevice->sendPacket(&victimArpReply); std::cout << "Sent ARP reply: " << victimAddr << " [victim] is at MAC address " << deviceMacAddress << " [me]" << std::endl; - pcpp::multiPlatformSleep(5); + std::this_thread::sleep_for(std::chrono::seconds(5)); } } diff --git a/Examples/Arping/CMakeLists.txt b/Examples/Arping/CMakeLists.txt index 78e174f5c2..e2fd12f0cb 100644 --- a/Examples/Arping/CMakeLists.txt +++ b/Examples/Arping/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(Arping PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS Arping - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS Arping EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/DNSResolver/CMakeLists.txt b/Examples/DNSResolver/CMakeLists.txt index a66fe4722a..8c0b0782cd 100644 --- a/Examples/DNSResolver/CMakeLists.txt +++ b/Examples/DNSResolver/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(DNSResolver PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS DNSResolver - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS DNSResolver EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/DnsSpoofing/CMakeLists.txt b/Examples/DnsSpoofing/CMakeLists.txt index a883c9d2c8..8213558ba8 100644 --- a/Examples/DnsSpoofing/CMakeLists.txt +++ b/Examples/DnsSpoofing/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(DnsSpoofing PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS DnsSpoofing - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS DnsSpoofing EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/DnsSpoofing/main.cpp b/Examples/DnsSpoofing/main.cpp index 3e03c6833a..8d7ffb0127 100644 --- a/Examples/DnsSpoofing/main.cpp +++ b/Examples/DnsSpoofing/main.cpp @@ -348,7 +348,7 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, while (!args.shouldStop) { std::cout << "Spoofed " << args.stats.numOfSpoofedDnsRequests << " DNS requests so far" << std::endl; - pcpp::multiPlatformSleep(5); + std::this_thread::sleep_for(std::chrono::seconds(5)); } } diff --git a/Examples/DpdkBridge/CMakeLists.txt b/Examples/DpdkBridge/CMakeLists.txt index f460c1c6c7..972369fdbc 100644 --- a/Examples/DpdkBridge/CMakeLists.txt +++ b/Examples/DpdkBridge/CMakeLists.txt @@ -5,8 +5,5 @@ target_link_libraries(DpdkBridge PUBLIC PcapPlusPlus::Pcap++) set_target_properties(DpdkBridge PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS DpdkBridge - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS DpdkBridge EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/DpdkExample-FilterTraffic/CMakeLists.txt b/Examples/DpdkExample-FilterTraffic/CMakeLists.txt index 2c25d8d50f..25f02b628d 100644 --- a/Examples/DpdkExample-FilterTraffic/CMakeLists.txt +++ b/Examples/DpdkExample-FilterTraffic/CMakeLists.txt @@ -5,8 +5,5 @@ target_link_libraries(DpdkTrafficFilter PUBLIC PcapPlusPlus::Pcap++) set_target_properties(DpdkTrafficFilter PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS DpdkTrafficFilter - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS DpdkTrafficFilter EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/DpdkExample-FilterTraffic/main.cpp b/Examples/DpdkExample-FilterTraffic/main.cpp index c48e865677..be72a1ed81 100644 --- a/Examples/DpdkExample-FilterTraffic/main.cpp +++ b/Examples/DpdkExample-FilterTraffic/main.cpp @@ -162,7 +162,7 @@ void listDpdkPorts() void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, std::vector& coresToUse, bool writePacketsToDisk, const std::string& packetFilePath, pcpp::DpdkDevice* sendPacketsTo, - AppWorkerConfig workerConfigArr[], int workerConfigArrLen, uint16_t rxQueues) + std::vector& workerConfigArr, int workerConfigArrLen, uint16_t rxQueues) { // create a list of pairs of DpdkDevice and RX queues for all RX queues in all requested devices int totalNumOfRxQueues = 0; @@ -588,7 +588,7 @@ int main(int argc, char* argv[]) } // prepare configuration for every core - AppWorkerConfig workerConfigArr[coresToUse.size()]; + std::vector workerConfigArr(coresToUse.size()); prepareCoreConfiguration(dpdkDevicesToUse, coresToUse, writePacketsToDisk, packetFilePath, sendPacketsTo, workerConfigArr, coresToUse.size(), rxQueues); diff --git a/Examples/HttpAnalyzer/CMakeLists.txt b/Examples/HttpAnalyzer/CMakeLists.txt index 34e221a087..b8d2900353 100644 --- a/Examples/HttpAnalyzer/CMakeLists.txt +++ b/Examples/HttpAnalyzer/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(HttpAnalyzer PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS HttpAnalyzer - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS HttpAnalyzer EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/HttpAnalyzer/main.cpp b/Examples/HttpAnalyzer/main.cpp index 372d89b10a..b321e3cab0 100644 --- a/Examples/HttpAnalyzer/main.cpp +++ b/Examples/HttpAnalyzer/main.cpp @@ -468,7 +468,7 @@ void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriod while (!shouldStop) { - pcpp::multiPlatformSleep(printRatePeriod); + std::this_thread::sleep_for(std::chrono::seconds(printRatePeriod)); // calculate rates if (printRatesPeriodically) diff --git a/Examples/IPDefragUtil/CMakeLists.txt b/Examples/IPDefragUtil/CMakeLists.txt index 42335419d3..ee127e650f 100644 --- a/Examples/IPDefragUtil/CMakeLists.txt +++ b/Examples/IPDefragUtil/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(IPDefragUtil PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS IPDefragUtil - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS IPDefragUtil EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/IPFragUtil/CMakeLists.txt b/Examples/IPFragUtil/CMakeLists.txt index bbe1dee206..d1936cb0e1 100644 --- a/Examples/IPFragUtil/CMakeLists.txt +++ b/Examples/IPFragUtil/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(IPFragUtil PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS IPFragUtil - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS IPFragUtil EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/IcmpFileTransfer/CMakeLists.txt b/Examples/IcmpFileTransfer/CMakeLists.txt index d6a84fcc6e..a15fadcb1a 100644 --- a/Examples/IcmpFileTransfer/CMakeLists.txt +++ b/Examples/IcmpFileTransfer/CMakeLists.txt @@ -10,10 +10,7 @@ endif() set_target_properties(IcmpFileTransfer-catcher PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS IcmpFileTransfer-catcher - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS IcmpFileTransfer-catcher EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() add_executable(IcmpFileTransfer-pitcher Common.cpp IcmpFileTransfer-pitcher.cpp) @@ -28,8 +25,5 @@ endif() set_target_properties(IcmpFileTransfer-pitcher PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS IcmpFileTransfer-pitcher - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS IcmpFileTransfer-pitcher EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp b/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp index e17382f498..59019d0745 100644 --- a/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp +++ b/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp @@ -269,7 +269,7 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p nullptr, 0); icmpId++; // sleep for a few seconds between sending the message - pcpp::multiPlatformSleep(SEND_TIMEOUT_BEFORE_FT_START); + std::this_thread::sleep_for(std::chrono::seconds(SEND_TIMEOUT_BEFORE_FT_START)); } // stop capturing packets @@ -318,7 +318,7 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p if (packetPerSec > 1) usleep(sleepBetweenPackets); else if (packetPerSec == 1) - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); icmpId++; } @@ -504,7 +504,7 @@ void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IP if (packetPerSec > 1) usleep(sleepBetweenPackets); else if (packetPerSec == 1) - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); bytesSentSoFar += blockSize; diff --git a/Examples/KniPong/CMakeLists.txt b/Examples/KniPong/CMakeLists.txt index 058486bb8c..71a6e9828c 100644 --- a/Examples/KniPong/CMakeLists.txt +++ b/Examples/KniPong/CMakeLists.txt @@ -5,8 +5,5 @@ target_link_libraries(KniPong PUBLIC PcapPlusPlus::Pcap++) set_target_properties(KniPong PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS KniPong - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS KniPong EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/KniPong/main.cpp b/Examples/KniPong/main.cpp index 9de1bb2d6f..beb5f89e97 100644 --- a/Examples/KniPong/main.cpp +++ b/Examples/KniPong/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -384,7 +385,7 @@ namespace } /** - * Handle all UDP packets as a packet carying a "ping" string to "pong" to with same string. + * Handle all UDP packets as a packet carrying a "ping" string to "pong" to with same string. * Handle only packets that are of type: Eth / Ip / Udp / Payload. */ inline bool processUdp(pcpp::Packet& packet, pcpp::UdpLayer* udpLayer) diff --git a/Examples/PcapPlusPlus-benchmark/CMakeLists.txt b/Examples/PcapPlusPlus-benchmark/CMakeLists.txt index 4d9bfe865f..7fc45dad16 100644 --- a/Examples/PcapPlusPlus-benchmark/CMakeLists.txt +++ b/Examples/PcapPlusPlus-benchmark/CMakeLists.txt @@ -12,15 +12,12 @@ if("cxx_std_14" IN_LIST CMAKE_CXX_COMPILE_FEATURES) include(FetchContent) # Fetch Google Benchmark - fetchcontent_declare( - benchmark - GIT_REPOSITORY https://github.com/google/benchmark.git - GIT_TAG v1.9.0) + FetchContent_Declare(benchmark GIT_REPOSITORY https://github.com/google/benchmark.git GIT_TAG v1.9.0) # Disable testing and installation for Google Benchmark set(BENCHMARK_ENABLE_TESTING OFF) set(BENCHMARK_ENABLE_INSTALL OFF) - fetchcontent_makeavailable(benchmark) + FetchContent_MakeAvailable(benchmark) add_executable(BenchmarkExampleGoogle benchmark-google.cpp) @@ -34,17 +31,10 @@ else() message(WARNING "Google Benchmark backend requires C++14 support") endif() - if(PCAPPP_INSTALL) - install( - TARGETS BenchmarkExample - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS BenchmarkExample EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) if(TARGET BenchmarkExampleGoogle) - install( - TARGETS BenchmarkExampleGoogle - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS BenchmarkExampleGoogle EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() endif() diff --git a/Examples/PcapPrinter/CMakeLists.txt b/Examples/PcapPrinter/CMakeLists.txt index 67a15c40ee..5c9800de5c 100644 --- a/Examples/PcapPrinter/CMakeLists.txt +++ b/Examples/PcapPrinter/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(PcapPrinter PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS PcapPrinter - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS PcapPrinter EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/PcapSearch/CMakeLists.txt b/Examples/PcapSearch/CMakeLists.txt index ecfb9e992e..389e96177e 100644 --- a/Examples/PcapSearch/CMakeLists.txt +++ b/Examples/PcapSearch/CMakeLists.txt @@ -11,8 +11,5 @@ endif() set_target_properties(PcapSearch PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS PcapSearch - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS PcapSearch EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/PcapSplitter/CMakeLists.txt b/Examples/PcapSplitter/CMakeLists.txt index 4f65d07ea3..38173452a6 100644 --- a/Examples/PcapSplitter/CMakeLists.txt +++ b/Examples/PcapSplitter/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(PcapSplitter PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS PcapSplitter - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS PcapSplitter EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/PfRingExample-FilterTraffic/CMakeLists.txt b/Examples/PfRingExample-FilterTraffic/CMakeLists.txt index 0c8a1b37f5..9b8c9faae2 100644 --- a/Examples/PfRingExample-FilterTraffic/CMakeLists.txt +++ b/Examples/PfRingExample-FilterTraffic/CMakeLists.txt @@ -5,8 +5,5 @@ target_link_libraries(PfRingTrafficFilter PUBLIC PcapPlusPlus::Pcap++) set_target_properties(PfRingTrafficFilter PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS PfRingTrafficFilter - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS PfRingTrafficFilter EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/PfRingExample-FilterTraffic/main.cpp b/Examples/PfRingExample-FilterTraffic/main.cpp index e6c6a38942..7f7583ac9c 100644 --- a/Examples/PfRingExample-FilterTraffic/main.cpp +++ b/Examples/PfRingExample-FilterTraffic/main.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include // clang-format off @@ -406,7 +408,7 @@ int main(int argc, char* argv[]) int threadCount = 0; // create an array of packet stats with the size of all machine cores - PacketStats packetStatsArr[totalNumOfCores]; + std::vector packetStatsArr(totalNumOfCores); // init each packet stats instance with an illegal core ID for (int coreId = 0; coreId < totalNumOfCores; coreId++) @@ -430,7 +432,7 @@ int main(int argc, char* argv[]) PacketMatchingEngine matchingEngine(srcIPToMatch, dstIPToMatch, srcPortToMatch, dstPortToMatch, protocolToMatch); // create a flow table for each core - std::unordered_map flowTables[totalNumOfCores]; + std::vector> flowTables(totalNumOfCores); pcpp::PcapFileWriterDevice** pcapWriters = nullptr; @@ -463,9 +465,9 @@ int main(int argc, char* argv[]) // prepare packet capture configuration CaptureThreadArgs args; - args.packetStatArr = packetStatsArr; + args.packetStatArr = packetStatsArr.data(); args.matchingEngine = &matchingEngine; - args.flowTables = flowTables; + args.flowTables = flowTables.data(); args.sendPacketsTo = sendPacketsToIface; args.pcapWriters = pcapWriters; diff --git a/Examples/SSLAnalyzer/CMakeLists.txt b/Examples/SSLAnalyzer/CMakeLists.txt index 3bc682939f..8503224c4c 100644 --- a/Examples/SSLAnalyzer/CMakeLists.txt +++ b/Examples/SSLAnalyzer/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(SSLAnalyzer PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS SSLAnalyzer - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS SSLAnalyzer EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/SSLAnalyzer/main.cpp b/Examples/SSLAnalyzer/main.cpp index d600cfa196..bf644e748b 100644 --- a/Examples/SSLAnalyzer/main.cpp +++ b/Examples/SSLAnalyzer/main.cpp @@ -437,7 +437,7 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi while (!shouldStop) { - pcpp::multiPlatformSleep(printRatePeriod); + std::this_thread::sleep_for(std::chrono::seconds(printRatePeriod)); // calculate rates if (printRatesPeriodically) diff --git a/Examples/TLSFingerprinting/CMakeLists.txt b/Examples/TLSFingerprinting/CMakeLists.txt index f47aacdc8f..f79ba5adcb 100644 --- a/Examples/TLSFingerprinting/CMakeLists.txt +++ b/Examples/TLSFingerprinting/CMakeLists.txt @@ -7,12 +7,11 @@ if(MSVC) target_link_libraries(TLSFingerprinting PRIVATE Getopt-for-Visual-Studio) endif() -set_target_properties(TLSFingerprinting PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}" - RUNTIME_OUTPUT_NAME "TLSFingerprinting") +set_target_properties( + TLSFingerprinting + PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}" RUNTIME_OUTPUT_NAME "TLSFingerprinting" +) if(PCAPPP_INSTALL) - install( - TARGETS TLSFingerprinting - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS TLSFingerprinting EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/TLSFingerprinting/main.cpp b/Examples/TLSFingerprinting/main.cpp index 87acfa5af0..3c25dea9cb 100644 --- a/Examples/TLSFingerprinting/main.cpp +++ b/Examples/TLSFingerprinting/main.cpp @@ -516,7 +516,7 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: // run in an endless loop until the user press ctrl+c while (!shouldStop) - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); // stop capturing and close the live device dev->stopCapture(); diff --git a/Examples/TcpReassembly/CMakeLists.txt b/Examples/TcpReassembly/CMakeLists.txt index d2cbf5f2fc..d5b5835068 100644 --- a/Examples/TcpReassembly/CMakeLists.txt +++ b/Examples/TcpReassembly/CMakeLists.txt @@ -10,8 +10,5 @@ endif() set_target_properties(TcpReassembly PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS TcpReassembly - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS TcpReassembly EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Examples/TcpReassembly/main.cpp b/Examples/TcpReassembly/main.cpp index 56546258c2..5b6b8a5209 100644 --- a/Examples/TcpReassembly/main.cpp +++ b/Examples/TcpReassembly/main.cpp @@ -583,7 +583,7 @@ void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly // run in an endless loop until the user presses ctrl+c while (!shouldStop) - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); // stop capturing and close the live device dev->stopCapture(); diff --git a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp index 3f10863e99..2dbeb6fe60 100644 --- a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp +++ b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp @@ -152,7 +152,7 @@ int main(int argc, char* argv[]) dev->startCapture(onPacketArrives, &stats); // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread - pcpp::multiPlatformSleep(10); + std::this_thread::sleep_for(std::chrono::seconds(10)); // stop capturing packets dev->stopCapture(); @@ -176,7 +176,7 @@ int main(int argc, char* argv[]) dev->startCapture(packetVec); // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread - pcpp::multiPlatformSleep(10); + std::this_thread::sleep_for(std::chrono::seconds(10)); // stop capturing packets dev->stopCapture(); @@ -264,7 +264,7 @@ int main(int argc, char* argv[]) dev->startCapture(onPacketArrives, &stats); // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread - pcpp::multiPlatformSleep(10); + std::this_thread::sleep_for(std::chrono::seconds(10)); // stop capturing packets dev->stopCapture(); diff --git a/Examples/XdpExample-FilterTraffic/CMakeLists.txt b/Examples/XdpExample-FilterTraffic/CMakeLists.txt index 51a06b259a..16d1a3a48f 100644 --- a/Examples/XdpExample-FilterTraffic/CMakeLists.txt +++ b/Examples/XdpExample-FilterTraffic/CMakeLists.txt @@ -5,8 +5,5 @@ target_link_libraries(XdpTrafficFilter PUBLIC PcapPlusPlus::Pcap++) set_target_properties(XdpTrafficFilter PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PCAPPP_BINARY_EXAMPLES_DIR}") if(PCAPPP_INSTALL) - install( - TARGETS XdpTrafficFilter - EXPORT PcapPlusPlusTargets - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + install(TARGETS XdpTrafficFilter EXPORT PcapPlusPlusTargets RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) endif() diff --git a/Packet++/CMakeLists.txt b/Packet++/CMakeLists.txt index bab9488be6..2bae131ebd 100644 --- a/Packet++/CMakeLists.txt +++ b/Packet++/CMakeLists.txt @@ -68,74 +68,76 @@ add_library( # Force hash-library pcapng to be link fully static ) -set(public_headers - header/ArpLayer.h - header/Asn1Codec.h - header/BgpLayer.h - header/CotpLayer.h - header/DhcpLayer.h - header/DhcpV6Layer.h - header/DnsLayerEnums.h - header/DnsLayer.h - header/DnsResourceData.h - header/DnsResource.h - header/EthDot3Layer.h - header/EthLayer.h - header/FtpLayer.h - header/GreLayer.h - header/GtpLayer.h - header/HttpLayer.h - header/IcmpLayer.h - header/IcmpV6Layer.h - header/IgmpLayer.h - header/IPLayer.h - header/IPReassembly.h - header/IPSecLayer.h - header/IPv4Layer.h - header/IPv6Extensions.h - header/IPv6Layer.h - header/Layer.h - header/LdapLayer.h - header/LLCLayer.h - header/MplsLayer.h - header/NullLoopbackLayer.h - header/NdpLayer.h - header/NflogLayer.h - header/NtpLayer.h - header/Packet.h - header/PacketTrailerLayer.h - header/PacketUtils.h - header/PayloadLayer.h - header/PPPoELayer.h - header/ProtocolType.h - header/RadiusLayer.h - header/RawPacket.h - header/S7CommLayer.h - header/SdpLayer.h - header/SingleCommandTextProtocol.h - header/SipLayer.h - header/SllLayer.h - header/Sll2Layer.h - header/SmtpLayer.h - header/SomeIpLayer.h - header/SomeIpSdLayer.h - header/SSHLayer.h - header/SSLCommon.h - header/SSLHandshake.h - header/SSLLayer.h - header/StpLayer.h - header/TcpLayer.h - header/TcpReassembly.h - header/TelnetLayer.h - header/TextBasedProtocol.h - header/TLVData.h - header/TpktLayer.h - header/UdpLayer.h - header/VlanLayer.h - header/VrrpLayer.h - header/VxlanLayer.h - header/WakeOnLanLayer.h - header/WireGuardLayer.h) +set( + public_headers + header/ArpLayer.h + header/Asn1Codec.h + header/BgpLayer.h + header/CotpLayer.h + header/DhcpLayer.h + header/DhcpV6Layer.h + header/DnsLayerEnums.h + header/DnsLayer.h + header/DnsResourceData.h + header/DnsResource.h + header/EthDot3Layer.h + header/EthLayer.h + header/FtpLayer.h + header/GreLayer.h + header/GtpLayer.h + header/HttpLayer.h + header/IcmpLayer.h + header/IcmpV6Layer.h + header/IgmpLayer.h + header/IPLayer.h + header/IPReassembly.h + header/IPSecLayer.h + header/IPv4Layer.h + header/IPv6Extensions.h + header/IPv6Layer.h + header/Layer.h + header/LdapLayer.h + header/LLCLayer.h + header/MplsLayer.h + header/NullLoopbackLayer.h + header/NdpLayer.h + header/NflogLayer.h + header/NtpLayer.h + header/Packet.h + header/PacketTrailerLayer.h + header/PacketUtils.h + header/PayloadLayer.h + header/PPPoELayer.h + header/ProtocolType.h + header/RadiusLayer.h + header/RawPacket.h + header/S7CommLayer.h + header/SdpLayer.h + header/SingleCommandTextProtocol.h + header/SipLayer.h + header/SllLayer.h + header/Sll2Layer.h + header/SmtpLayer.h + header/SomeIpLayer.h + header/SomeIpSdLayer.h + header/SSHLayer.h + header/SSLCommon.h + header/SSLHandshake.h + header/SSLLayer.h + header/StpLayer.h + header/TcpLayer.h + header/TcpReassembly.h + header/TelnetLayer.h + header/TextBasedProtocol.h + header/TLVData.h + header/TpktLayer.h + header/UdpLayer.h + header/VlanLayer.h + header/VrrpLayer.h + header/VxlanLayer.h + header/WakeOnLanLayer.h + header/WireGuardLayer.h +) # Don't use set_target_properties CMake limit to 50 elements set_property(TARGET Packet++ PROPERTY PUBLIC_HEADER ${public_headers}) @@ -145,7 +147,8 @@ target_include_directories( PUBLIC $ $ # Don't link with hash-library nor EndianPortable as they won't be exported PRIVATE $ - PRIVATE $) + PRIVATE $ +) target_link_libraries(Packet++ PUBLIC Common++) @@ -156,7 +159,8 @@ if(PCAPPP_INSTALL) ARCHIVE DESTINATION ${PCAPPP_INSTALL_LIBDIR} LIBRARY DESTINATION ${PCAPPP_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${PCAPPP_INSTALL_INCLUDEDIR} - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR} + ) endif() set_property(TARGET Packet++ PROPERTY OUTPUT_NAME "Packet++") diff --git a/Packet++/header/Layer.h b/Packet++/header/Layer.h index 828cb5c84f..f2e1755e14 100644 --- a/Packet++/header/Layer.h +++ b/Packet++/header/Layer.h @@ -232,10 +232,9 @@ namespace pcpp virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten); }; + inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer& layer) + { + os << layer.toString(); + return os; + } } // namespace pcpp - -inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer& layer) -{ - os << layer.toString(); - return os; -} diff --git a/Packet++/header/LdapLayer.h b/Packet++/header/LdapLayer.h index 09e82c9ba1..9ab9b888dd 100644 --- a/Packet++/header/LdapLayer.h +++ b/Packet++/header/LdapLayer.h @@ -1320,47 +1320,47 @@ namespace pcpp : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} }; -} // namespace pcpp - -inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapControl& control) -{ - os << "{" << control.controlType << ", " << control.controlValue << "}"; - return os; -} -inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapAttribute& attr) -{ - os << "{" << attr.type << ", {"; + inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapControl& control) + { + os << "{" << control.controlType << ", " << control.controlValue << "}"; + return os; + } - std::string separator; - for (const auto& value : attr.values) + inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapAttribute& attr) { - os << separator << value; - if (separator.empty()) + os << "{" << attr.type << ", {"; + + std::string separator; + for (const auto& value : attr.values) { - separator = ", "; + os << separator << value; + if (separator.empty()) + { + separator = ", "; + } } - } - os << "}}"; - return os; -} - -inline std::ostream& operator<<(std::ostream& os, - const pcpp::LdapBindRequestLayer::SaslAuthentication& saslAuthentication) -{ - os << "{" << saslAuthentication.mechanism << ", {"; + os << "}}"; + return os; + } - std::string separator; - for (const auto& value : saslAuthentication.credentials) + inline std::ostream& operator<<(std::ostream& os, + const pcpp::LdapBindRequestLayer::SaslAuthentication& saslAuthentication) { - os << separator << "0x" << std::hex << static_cast(value) << std::dec; - if (separator.empty()) + os << "{" << saslAuthentication.mechanism << ", {"; + + std::string separator; + for (const auto& value : saslAuthentication.credentials) { - separator = ", "; + os << separator << "0x" << std::hex << static_cast(value) << std::dec; + if (separator.empty()) + { + separator = ", "; + } } - } - os << "}}"; - return os; -} + os << "}}"; + return os; + } +} // namespace pcpp diff --git a/Packet++/header/Packet.h b/Packet++/header/Packet.h index 4e7760f678..65324f6f26 100644 --- a/Packet++/header/Packet.h +++ b/Packet++/header/Packet.h @@ -445,10 +445,9 @@ namespace pcpp return dynamic_cast(curLayer); } + inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet) + { + os << packet.toString(); + return os; + } } // namespace pcpp - -inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet) -{ - os << packet.toString(); - return os; -} diff --git a/Packet++/header/StpLayer.h b/Packet++/header/StpLayer.h index f1b3cf75fd..d153bbb995 100644 --- a/Packet++/header/StpLayer.h +++ b/Packet++/header/StpLayer.h @@ -2,6 +2,7 @@ #include "Layer.h" #include "MacAddress.h" +#include /// @file diff --git a/Packet++/src/BgpLayer.cpp b/Packet++/src/BgpLayer.cpp index 4e1269abcf..b32ab8d010 100644 --- a/Packet++/src/BgpLayer.cpp +++ b/Packet++/src/BgpLayer.cpp @@ -542,6 +542,11 @@ namespace pcpp if (headerLen >= minLen) { size_t withdrawnRouteLen = getWithdrawnRoutesLength(); + // Ensure the memory access is within bounds + if (sizeof(bgp_common_header) + sizeof(uint16_t) + withdrawnRouteLen + sizeof(uint16_t) > headerLen) + { + return 0; // Invalid access, return 0 + } uint16_t res = be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrawnRouteLen)); if ((size_t)res > headerLen - minLen - withdrawnRouteLen) diff --git a/Packet++/src/CotpLayer.cpp b/Packet++/src/CotpLayer.cpp index 2a218f547a..1183df5f13 100644 --- a/Packet++/src/CotpLayer.cpp +++ b/Packet++/src/CotpLayer.cpp @@ -2,6 +2,8 @@ #include "S7CommLayer.h" #include +#include + namespace pcpp { diff --git a/Packet++/src/DnsResourceData.cpp b/Packet++/src/DnsResourceData.cpp index e735d447de..5365954639 100644 --- a/Packet++/src/DnsResourceData.cpp +++ b/Packet++/src/DnsResourceData.cpp @@ -204,8 +204,7 @@ namespace pcpp { if (m_DataLen == 0 || m_Data == nullptr) { - PCPP_LOG_ERROR("Input data is null or illegal" - << "|m_DataLen:" << m_DataLen); + PCPP_LOG_ERROR("Input data is null or illegal" << "|m_DataLen:" << m_DataLen); return false; } diff --git a/Packet++/src/EthDot3Layer.cpp b/Packet++/src/EthDot3Layer.cpp index 7a97897337..7091cd2eba 100644 --- a/Packet++/src/EthDot3Layer.cpp +++ b/Packet++/src/EthDot3Layer.cpp @@ -3,6 +3,8 @@ #include "PayloadLayer.h" #include "LLCLayer.h" +#include + namespace pcpp { diff --git a/Packet++/src/LLCLayer.cpp b/Packet++/src/LLCLayer.cpp index fe5c3c2fe5..5cfe5d84da 100644 --- a/Packet++/src/LLCLayer.cpp +++ b/Packet++/src/LLCLayer.cpp @@ -4,6 +4,8 @@ #include "PayloadLayer.h" #include "StpLayer.h" +#include + namespace pcpp { diff --git a/Packet++/src/S7CommLayer.cpp b/Packet++/src/S7CommLayer.cpp index 33358d23bb..0affaa8145 100644 --- a/Packet++/src/S7CommLayer.cpp +++ b/Packet++/src/S7CommLayer.cpp @@ -2,6 +2,7 @@ #include "S7CommLayer.h" #include +#include #include namespace pcpp diff --git a/Packet++/src/TpktLayer.cpp b/Packet++/src/TpktLayer.cpp index 2d003cd5e7..c3fe3a9ff7 100644 --- a/Packet++/src/TpktLayer.cpp +++ b/Packet++/src/TpktLayer.cpp @@ -2,6 +2,7 @@ #include "EndianPortable.h" #include "CotpLayer.h" #include "PayloadLayer.h" +#include #include namespace pcpp diff --git a/Packet++/src/VrrpLayer.cpp b/Packet++/src/VrrpLayer.cpp index c56cd7f058..8f391155a7 100644 --- a/Packet++/src/VrrpLayer.cpp +++ b/Packet++/src/VrrpLayer.cpp @@ -485,8 +485,7 @@ namespace pcpp auto* ipLayer = m_Packet->getLayerOfType(); if (ipLayer == nullptr) { - PCPP_LOG_ERROR("Calculate checksum failed, for can not get IPLayer" - << ""); + PCPP_LOG_ERROR("Calculate checksum failed, for can not get IPLayer" << ""); return 0; } diff --git a/Packet++/src/VxlanLayer.cpp b/Packet++/src/VxlanLayer.cpp index ec1acc1657..6001b4197b 100644 --- a/Packet++/src/VxlanLayer.cpp +++ b/Packet++/src/VxlanLayer.cpp @@ -2,6 +2,8 @@ #include "EthLayer.h" #include "EndianPortable.h" +#include + namespace pcpp { diff --git a/Pcap++/CMakeLists.txt b/Pcap++/CMakeLists.txt index ab3ef642bd..7eb772b142 100644 --- a/Pcap++/CMakeLists.txt +++ b/Pcap++/CMakeLists.txt @@ -22,41 +22,31 @@ add_library( src/RawSocketDevice.cpp $<$:src/WinPcapLiveDevice.cpp> # Force light pcapng to be link fully static - $) + $ +) -set(public_headers - header/Device.h - header/NetworkUtils.h - header/PcapDevice.h - header/PcapFileDevice.h - header/PcapFilter.h - header/PcapLiveDevice.h - header/PcapLiveDeviceList.h - header/RawSocketDevice.h) +set( + public_headers + header/Device.h + header/NetworkUtils.h + header/PcapDevice.h + header/PcapFileDevice.h + header/PcapFilter.h + header/PcapLiveDevice.h + header/PcapLiveDeviceList.h + header/RawSocketDevice.h +) if(PCAPPP_USE_DPDK) - list( - APPEND - public_headers - header/DpdkDevice.h - header/DpdkDeviceList.h - header/MBufRawPacket.h) + list(APPEND public_headers header/DpdkDevice.h header/DpdkDeviceList.h header/MBufRawPacket.h) endif() if(PCAPPP_USE_DPDK_KNI) - list( - APPEND - public_headers - header/KniDevice.h - header/KniDeviceList.h) + list(APPEND public_headers header/KniDevice.h header/KniDeviceList.h) endif() if(PCAPPP_USE_PF_RING) - list( - APPEND - public_headers - header/PfRingDevice.h - header/PfRingDeviceList.h) + list(APPEND public_headers header/PfRingDevice.h header/PfRingDeviceList.h) endif() if(PCAPPP_USE_XDP) @@ -68,12 +58,7 @@ if(LINUX) endif() if(WIN32) - list( - APPEND - public_headers - header/PcapRemoteDevice.h - header/PcapRemoteDeviceList.h - header/WinPcapLiveDevice.h) + list(APPEND public_headers header/PcapRemoteDevice.h header/PcapRemoteDeviceList.h header/WinPcapLiveDevice.h) endif() set_property(TARGET Pcap++ PROPERTY PUBLIC_HEADER ${public_headers}) @@ -91,18 +76,22 @@ target_include_directories( Pcap++ PUBLIC $ $ # Don't link with EndianPortable nor Light_PcapNG as they won't be exported - PRIVATE $ - $) + PRIVATE + $ + $ +) target_link_libraries( Pcap++ - PUBLIC Common++ - Packet++ - $<$:PF_RING::PF_RING> - $<$:DPDK::DPDK> - $<$:BPF::BPF> - PCAP::PCAP - Threads::Threads) + PUBLIC + Common++ + Packet++ + $<$:PF_RING::PF_RING> + $<$:DPDK::DPDK> + $<$:BPF::BPF> + PCAP::PCAP + Threads::Threads +) if(LIGHT_PCAPNG_ZSTD) target_link_libraries(Pcap++ PRIVATE light_pcapng) @@ -115,7 +104,8 @@ if(PCAPPP_INSTALL) ARCHIVE DESTINATION ${PCAPPP_INSTALL_LIBDIR} LIBRARY DESTINATION ${PCAPPP_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${PCAPPP_INSTALL_INCLUDEDIR} - RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR}) + RUNTIME DESTINATION ${PCAPPP_INSTALL_BINDIR} + ) endif() set_property(TARGET Pcap++ PROPERTY OUTPUT_NAME "Pcap++") diff --git a/Pcap++/header/Device.h b/Pcap++/header/Device.h index d8ba547076..ac493066e7 100644 --- a/Pcap++/header/Device.h +++ b/Pcap++/header/Device.h @@ -6,20 +6,16 @@ #include "RawPacket.h" #include "PcapFilter.h" -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /** A vector of pointers to RawPacket */ + /// A vector of pointers to RawPacket typedef PointerVector RawPacketVector; - /** - * @class IDevice - * An abstract interface representing all packet processing devices. It stands as the root class for all devices. - * This is an abstract class that cannot be instantiated - */ + /// @class IDevice + /// An abstract interface representing all packet processing devices. It stands as the root class for all devices. + /// This is an abstract class that cannot be instantiated class IDevice { protected: @@ -33,49 +29,37 @@ namespace pcpp virtual ~IDevice() {} - /** - * Open the device - * @return True if device was opened successfully, false otherwise - */ + /// Open the device + /// @return True if device was opened successfully, false otherwise virtual bool open() = 0; - /** - * Close the device - */ + /// Close the device virtual void close() = 0; - /** - * @return True if the file is opened, false otherwise - */ + /// @return True if the file is opened, false otherwise inline bool isOpened() { return m_DeviceOpened; } }; - /** - * @class IFilterableDevice - * An abstract interface representing all devices that have BPF (Berkeley Packet Filter) filtering capabilities, - * meaning devices that can filter packets based on the BPF filtering syntax. - * This is an abstract class that cannot be instantiated - */ + /// @class IFilterableDevice + /// An abstract interface representing all devices that have BPF (Berkeley Packet Filter) filtering capabilities, + /// meaning devices that can filter packets based on the BPF filtering syntax. + /// This is an abstract class that cannot be instantiated class IFilterableDevice { protected: // c'tor should not be public - IFilterableDevice() - {} + IFilterableDevice() = default; public: - virtual ~IFilterableDevice() - {} + virtual ~IFilterableDevice() = default; - /** - * Set a filter for the device. When implemented by the device, only packets that match the filter will be - * received - * @param[in] filter The filter to be set in PcapPlusPlus' GeneralFilter format - * @return True if filter set successfully, false otherwise - */ + /// Set a filter for the device. When implemented by the device, only packets that match the filter will be + /// received + /// @param[in] filter The filter to be set in PcapPlusPlus' GeneralFilter format + /// @return True if filter set successfully, false otherwise virtual bool setFilter(GeneralFilter& filter) { std::string filterAsString; @@ -83,19 +67,15 @@ namespace pcpp return setFilter(filterAsString); } - /** - * Set a filter for the device. When implemented by the device, only packets that match the filter will be - * received - * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax - * (http://biot.com/capstats/bpf.html) - * @return True if filter set successfully, false otherwise - */ + /// Set a filter for the device. When implemented by the device, only packets that match the filter will be + /// received + /// @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax + /// (http://biot.com/capstats/bpf.html) + /// @return True if filter set successfully, false otherwise virtual bool setFilter(std::string filterAsString) = 0; - /** - * Clear the filter currently set on the device - * @return True if filter was removed successfully or if no filter was set, false otherwise - */ + /// Clear the filter currently set on the device + /// @return True if filter was removed successfully or if no filter was set, false otherwise virtual bool clearFilter() = 0; }; } // namespace pcpp diff --git a/Pcap++/header/DeviceUtils.h b/Pcap++/header/DeviceUtils.h index b453eb3d97..d5525defe5 100644 --- a/Pcap++/header/DeviceUtils.h +++ b/Pcap++/header/DeviceUtils.h @@ -6,17 +6,17 @@ #include "IpAddress.h" #include "PcapUtils.h" +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { /// @cond PCPP_INTERNAL namespace internal { - /** - * Fetches a list of all network devices on the local machine that LibPcap/WinPcap/NPcap can find. - * @return A smart pointer to an interface list structure. - * @throws std::runtime_error The system encountered an error fetching the devices. - */ + /// Fetches a list of all network devices on the local machine that LibPcap/WinPcap/NPcap can find. + /// @return A smart pointer to an interface list structure. + /// @throws std::runtime_error The system encountered an error fetching the devices. std::unique_ptr getAllLocalPcapDevices(); } // namespace internal diff --git a/Pcap++/header/DpdkDevice.h b/Pcap++/header/DpdkDevice.h index 946c701074..0d011b483e 100644 --- a/Pcap++/header/DpdkDevice.h +++ b/Pcap++/header/DpdkDevice.h @@ -10,63 +10,59 @@ #include "Device.h" #include "MBufRawPacket.h" -/** - * @file - * This file and DpdkDeviceList.h provide PcapPlusPlus C++ wrapper for DPDK (stands for data-plan development kit). What - * is DPDK? as quoting from http://dpdk.org: "DPDK is a set of libraries and drivers for fast packet processing... These - * libraries can be used to: receive and send packets within the minimum number of CPU cycles (usually less than 80 - * cycles)... develop fast packet capture algorithms (tcpdump-like)... run third-party fast path stacks... Some packet - * processing functions have been benchmarked up to hundreds million frames per second, using 64-byte packets with a - * PCIe NIC"
As DPDK API is written in C, PcapPlusPlus wraps the main functionality in a C++ easy-to-use classes - * which should have minimum affect on performance and packet processing rate. In addition it brings DPDK to the - * PcapPlusPlus framework and API so you can use DPDK together with other PcapPlusPlus features such as packet parsing - * and editing, etc.
So how DPDK basically works? in order to boost packet processing performance on a commodity - * server DPDK is bypassing the Linux kernel. All the packet processing activity happens in the user space so basically - * packets are delivered from NIC hardware queues directly to user-space shared memory without going through the kernel. - * In addition DPDK uses polling instead of handling interrupts for each arrived packet (as interrupts create some - * delays). Other methods to boost packets processing implemented by DPDK are using Hugepages to decrease the size of - * TLB that results in a much faster virtual to physical page conversion, thread affinity to bind threads to a specific - * core, lock-free user-space multi-core synchronization using rings data structures and NUMA awareness to avoid - * expensive data transfers between sockets.
Not every NIC supports kernel-bypass capabilities so DPDK cannot work - * with any NIC. The list of supported NICs are in DPDK's web-site http://dpdk.org/doc/nics . For each such NIC the DPDK - * framework provides a module that called poll-mode-driver (PMD in short) that enables this NIC to the working with - * DPDK. PcapPlusPlus wasn't tested with most PMDs but all of them should theoretically work as PcapPlusPlus doesn't - * change the PMD behavior
DPDK has another basic data-structure called mbuf. An mbuf is DPDK wrapper struct for - * network packets. When working with packets in DPDK you actually work with mbufs. The mbuf contains the packet data - * (obviously) but also some metadata on the packet such as the DPDK port it was captured on, packet ref-count (which - * allows it to be referenced by several objects), etc. One important concept is that DPDK doesn't allocate mbufs - * on-the-fly but uses mbuf pools. These pools is allocated on application startup and used throughout the application. - * The goal of this, of course, is increasing packet processing performance as allocating memory has its cost. So pool - * size is important and varies between applications. For example: an application that stores packets in memory has to - * have a large pool of mbufs so mbufs doesn't run-out. PcapPlusPlus enables to choose the pool size at startup

- * PcapPlusPlus main wrapper classes for DPDK are: - * - DpdkDevice - a class that wraps a DPDK port and provides all capabilities of receiving and sending packets to - * this port - * - DpdkDeviceList - a singleton class that initializes the DPDK infrastructure and creates DpdkDevice instances to - * all available ports. In addition it allows starting and stopping of worker threads - * - MBufRawPacket - a child class to RawPacket which customizes it for working with mbuf - * - In addition PcapPlusPlus provides a shell script to initialize DPDK prerequisites: setup_dpdk.py. This is an - * easy-to-use script that sets up huge-pages, loads DPDK kernel module and sets up the NICs that will be used by - * DPDK. This script must run before an application that uses DPDK runs. If you forgot to run it the application - * will fail with an appropriate error that will remind - * - * DPDK initialization using PcapPlusPlus: - * - Before application runs: run the setup_dpdk.py script - * - On application startup call DpdkDeviceList#initDpdk() static method to initialize DPDK infrastructure and - * DpdkDevice instances - * - Open the relevant DpdkDevice(s) - * - Send & receive packets... - */ +/// @file +/// This file and DpdkDeviceList.h provide PcapPlusPlus C++ wrapper for DPDK (stands for data-plan development kit). +/// What is DPDK? as quoting from http://dpdk.org: "DPDK is a set of libraries and drivers for fast packet processing... +/// These libraries can be used to: receive and send packets within the minimum number of CPU cycles (usually less than +/// 80 cycles)... develop fast packet capture algorithms (tcpdump-like)... run third-party fast path stacks... Some +/// packet processing functions have been benchmarked up to hundreds million frames per second, using 64-byte packets +/// with a PCIe NIC"
As DPDK API is written in C, PcapPlusPlus wraps the main functionality in a C++ easy-to-use +/// classes which should have minimum affect on performance and packet processing rate. In addition it brings DPDK to +/// the PcapPlusPlus framework and API so you can use DPDK together with other PcapPlusPlus features such as packet +/// parsing and editing, etc.
So how DPDK basically works? in order to boost packet processing performance on a +/// commodity server DPDK is bypassing the Linux kernel. All the packet processing activity happens in the user space so +/// basically packets are delivered from NIC hardware queues directly to user-space shared memory without going through +/// the kernel. In addition DPDK uses polling instead of handling interrupts for each arrived packet (as interrupts +/// create some delays). Other methods to boost packets processing implemented by DPDK are using Hugepages to decrease +/// the size of TLB that results in a much faster virtual to physical page conversion, thread affinity to bind threads +/// to a specific core, lock-free user-space multi-core synchronization using rings data structures and NUMA awareness +/// to avoid expensive data transfers between sockets.
Not every NIC supports kernel-bypass capabilities so DPDK +/// cannot work with any NIC. The list of supported NICs are in DPDK's web-site http://dpdk.org/doc/nics . For each such +/// NIC the DPDK framework provides a module that called poll-mode-driver (PMD in short) that enables this NIC to the +/// working with DPDK. PcapPlusPlus wasn't tested with most PMDs but all of them should theoretically work as +/// PcapPlusPlus doesn't change the PMD behavior
DPDK has another basic data-structure called mbuf. An mbuf is DPDK +/// wrapper struct for network packets. When working with packets in DPDK you actually work with mbufs. The mbuf +/// contains the packet data (obviously) but also some metadata on the packet such as the DPDK port it was captured on, +/// packet ref-count (which allows it to be referenced by several objects), etc. One important concept is that DPDK +/// doesn't allocate mbufs on-the-fly but uses mbuf pools. These pools is allocated on application startup and used +/// throughout the application. The goal of this, of course, is increasing packet processing performance as allocating +/// memory has its cost. So pool size is important and varies between applications. For example: an application that +/// stores packets in memory has to have a large pool of mbufs so mbufs doesn't run-out. PcapPlusPlus enables to choose +/// the pool size at startup

PcapPlusPlus main wrapper classes for DPDK are: +/// - DpdkDevice - a class that wraps a DPDK port and provides all capabilities of receiving and sending packets to +/// this port +/// - DpdkDeviceList - a singleton class that initializes the DPDK infrastructure and creates DpdkDevice instances to +/// all available ports. In addition it allows starting and stopping of worker threads +/// - MBufRawPacket - a child class to RawPacket which customizes it for working with mbuf +/// - In addition PcapPlusPlus provides a shell script to initialize DPDK prerequisites: setup_dpdk.py. This is an +/// easy-to-use script that sets up huge-pages, loads DPDK kernel module and sets up the NICs that will be used by +/// DPDK. This script must run before an application that uses DPDK runs. If you forgot to run it the application +/// will fail with an appropriate error that will remind +/// +/// DPDK initialization using PcapPlusPlus: +/// - Before application runs: run the setup_dpdk.py script +/// - On application startup call DpdkDeviceList#initDpdk() static method to initialize DPDK infrastructure and +/// DpdkDevice instances +/// - Open the relevant DpdkDevice(s) +/// - Send & receive packets... struct rte_mbuf; struct rte_mempool; struct rte_eth_conf; struct rte_eth_dev_tx_buffer; -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { @@ -77,230 +73,206 @@ namespace pcpp class DpdkDeviceList; class DpdkDevice; - /** - * An enum describing all PMD (poll mode driver) types supported by DPDK. For more info about these PMDs please - * visit the DPDK web-site - */ + /// An enum describing all PMD (poll mode driver) types supported by DPDK. For more info about these PMDs please + /// visit the DPDK web-site enum DpdkPMDType { - /** Unknown PMD type */ + /// Unknown PMD type PMD_UNKNOWN, - /** Link Bonding for 1GbE and 10GbE ports to allow the aggregation of multiple (slave) NICs into a single - * logical interface*/ + /// Link Bonding for 1GbE and 10GbE ports to allow the aggregation of multiple (slave) NICs into a single + /// logical interface PMD_BOND, - /** Intel E1000 PMD */ + /// Intel E1000 PMD PMD_E1000EM, - /** Intel 1GbE PMD */ + /// Intel 1GbE PMD PMD_IGB, - /** Intel 1GbE virtual function PMD */ + /// Intel 1GbE virtual function PMD PMD_IGBVF, - /** Cisco enic (UCS Virtual Interface Card) PMD */ + /// Cisco enic (UCS Virtual Interface Card) PMD PMD_ENIC, - /** Intel fm10k PMD */ + /// Intel fm10k PMD PMD_FM10K, - /** Intel 40GbE PMD */ + /// Intel 40GbE PMD PMD_I40E, - /** Intel 40GbE virtual function PMD */ + /// Intel 40GbE virtual function PMD PMD_I40EVF, - /** Intel 10GbE PMD */ + /// Intel 10GbE PMD PMD_IXGBE, - /** Intel 10GbE virtual function PMD */ + /// Intel 10GbE virtual function PMD PMD_IXGBEVF, - /** Mellanox ConnectX-3, ConnectX-3 Pro PMD */ + /// Mellanox ConnectX-3, ConnectX-3 Pro PMD PMD_MLX4, - /** Null PMD */ + /// Null PMD PMD_NULL, - /** pcap file PMD */ + /// pcap file PMD PMD_PCAP, - /** ring-based (memory) PMD */ + /// ring-based (memory) PMD PMD_RING, - /** VirtIO PMD */ + /// VirtIO PMD PMD_VIRTIO, - /** VMWare VMXNET3 PMD */ + /// VMWare VMXNET3 PMD PMD_VMXNET3, - /** Xen Project PMD */ + /// Xen Project PMD PMD_XENVIRT, - /** AF_PACKET PMD */ + /// AF_PACKET PMD PMD_AF_PACKET }; - /** - * @typedef OnDpdkPacketsArriveCallback - * A callback that is called when a burst of packets are captured by DpdkDevice - * @param[in] packets A pointer to an array of MBufRawPacket - * @param[in] numOfPackets The length of the array - * @param[in] threadId The thread/core ID who captured the packets - * @param[in] device A pointer to the DpdkDevice who captured the packets - * @param[in] userCookie The user cookie assigned by the user in DpdkDevice#startCaptureSingleThread() or - * DpdkDevice#startCaptureMultiThreads - */ + /// @typedef OnDpdkPacketsArriveCallback + /// A callback that is called when a burst of packets are captured by DpdkDevice + /// @param[in] packets A pointer to an array of MBufRawPacket + /// @param[in] numOfPackets The length of the array + /// @param[in] threadId The thread/core ID who captured the packets + /// @param[in] device A pointer to the DpdkDevice who captured the packets + /// @param[in] userCookie The user cookie assigned by the user in DpdkDevice#startCaptureSingleThread() or + /// DpdkDevice#startCaptureMultiThreads typedef void (*OnDpdkPacketsArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, DpdkDevice* device, void* userCookie); - /** - * @class DpdkDevice - * Encapsulates a DPDK port and enables receiving and sending packets using DPDK as well as getting interface info & - * status, packet statistics, etc. This class has no public c'tor as it's constructed by DpdkDeviceList during - * initialization.
- * - * __RX/TX queues__: modern NICs provide hardware load-balancing for packets. This means that each packet received - * by the NIC is hashed by one or more parameter (IP address, port, etc.) and goes into one of several RX queues - * provided by the NIC. This enables applications to work in a multi-core environment where each core can read - * packets from different RX queue(s). Same goes for TX queues: it's possible to write packets to different TX - * queues and the NIC is taking care of sending them to the network. Different NICs provide different number of RX - * and TX queues. DPDK supports this capability and enables the user to open the DPDK port (DpdkDevice) with a - * single or multiple RX and TX queues. When receiving packets the user can decide from which RX queue to read from, - * and when transmitting packets the user can decide to which TX queue to send them to. RX/TX queues are configured - * when opening the DpdkDevice (see openMultiQueues())
- * - * __Capturing packets__: there are two ways to capture packets using DpdkDevice: - * - using worker threads (see DpdkDeviceList#startDpdkWorkerThreads() ). When using this method the worker - * should use the DpdkDevice#receivePackets() methods to get packets from the DpdkDevice - * - by setting a callback which is invoked each time a burst of packets arrives. For more details see - * DpdkDevice#startCaptureSingleThread() - * - * __Sending packets:__ DpdkDevice has various methods for sending packets. They enable sending raw packets, parsed - * packets, etc. for all opened TX queues. Also, DPDK provides an option to buffer TX packets and send them only - * when reaching a certain threshold (you can read more about it here: - * http://dpdk.org/doc/api/rte__ethdev_8h.html#a0e941a74ae1b1b886764bc282458d946). DpdkDevice supports that option - * as well. See DpdkDevice#sendPackets()
- * - * __Get interface info__: DpdkDevice provides all kind of information on the interface/device such as MAC address, - * MTU, link status, PCI address, PMD (poll-mode-driver) used for this port, etc. In addition it provides RX/TX - * statistics when receiving or sending packets
- * - * __Known limitations:__ - * - BPF filters are currently not supported by this device (as opposed to other PcapPlusPlus device types. This - * means that the device cannot filter packets before they get to the user - * - It's not possible to set or change NIC load-balancing method. DPDK provides this capability but it's still - * not supported by DpdkDevice - */ + /// @class DpdkDevice + /// Encapsulates a DPDK port and enables receiving and sending packets using DPDK as well as getting interface info + /// & status, packet statistics, etc. This class has no public c'tor as it's constructed by DpdkDeviceList during + /// initialization.
+ /// + /// __RX/TX queues__: modern NICs provide hardware load-balancing for packets. This means that each packet received + /// by the NIC is hashed by one or more parameter (IP address, port, etc.) and goes into one of several RX queues + /// provided by the NIC. This enables applications to work in a multi-core environment where each core can read + /// packets from different RX queue(s). Same goes for TX queues: it's possible to write packets to different TX + /// queues and the NIC is taking care of sending them to the network. Different NICs provide different number of RX + /// and TX queues. DPDK supports this capability and enables the user to open the DPDK port (DpdkDevice) with a + /// single or multiple RX and TX queues. When receiving packets the user can decide from which RX queue to read + /// from, and when transmitting packets the user can decide to which TX queue to send them to. RX/TX queues are + /// configured when opening the DpdkDevice (see openMultiQueues())
+ /// + /// __Capturing packets__: there are two ways to capture packets using DpdkDevice: + /// - using worker threads (see DpdkDeviceList#startDpdkWorkerThreads() ). When using this method the worker + /// should use the DpdkDevice#receivePackets() methods to get packets from the DpdkDevice + /// - by setting a callback which is invoked each time a burst of packets arrives. For more details see + /// DpdkDevice#startCaptureSingleThread() + /// + /// __Sending packets:__ DpdkDevice has various methods for sending packets. They enable sending raw packets, parsed + /// packets, etc. for all opened TX queues. Also, DPDK provides an option to buffer TX packets and send them only + /// when reaching a certain threshold (you can read more about it here: + /// http://dpdk.org/doc/api/rte__ethdev_8h.html#a0e941a74ae1b1b886764bc282458d946). DpdkDevice supports that option + /// as well. See DpdkDevice#sendPackets()
+ /// + /// __Get interface info__: DpdkDevice provides all kind of information on the interface/device such as MAC address, + /// MTU, link status, PCI address, PMD (poll-mode-driver) used for this port, etc. In addition it provides RX/TX + /// statistics when receiving or sending packets
+ /// + /// __Known limitations:__ + /// - BPF filters are currently not supported by this device (as opposed to other PcapPlusPlus device types. This + /// means that the device cannot filter packets before they get to the user + /// - It's not possible to set or change NIC load-balancing method. DPDK provides this capability but it's still + /// not supported by DpdkDevice class DpdkDevice : public IDevice { friend class DpdkDeviceList; friend class MBufRawPacket; public: - /** - * An enum describing all RSS (Receive Side Scaling) hash functions supported in DPDK. Notice not all - * PMDs support all types of hash functions - */ + /// An enum describing all RSS (Receive Side Scaling) hash functions supported in DPDK. Notice not all + /// PMDs support all types of hash functions enum DpdkRssHashFunction { - /** No RSS */ + /// No RSS RSS_NONE = 0, - /** IPv4 based flow */ + /// IPv4 based flow RSS_IPV4 = 0x1, - /** Fragmented IPv4 based flow */ + /// Fragmented IPv4 based flow RSS_FRAG_IPV4 = 0x2, - /** Non-fragmented IPv4 + TCP flow */ + /// Non-fragmented IPv4 + TCP flow RSS_NONFRAG_IPV4_TCP = 0x4, - /** Non-fragmented IPv4 + UDP flow */ + /// Non-fragmented IPv4 + UDP flow RSS_NONFRAG_IPV4_UDP = 0x8, - /** Non-fragmented IPv4 + SCTP flow */ + /// Non-fragmented IPv4 + SCTP flow RSS_NONFRAG_IPV4_SCTP = 0x10, - /** Non-fragmented IPv4 + non TCP/UDP/SCTP flow */ + /// Non-fragmented IPv4 + non TCP/UDP/SCTP flow RSS_NONFRAG_IPV4_OTHER = 0x20, - /** IPv6 based flow */ + /// IPv6 based flow RSS_IPV6 = 0x40, - /** Fragmented IPv6 based flow */ + /// Fragmented IPv6 based flow RSS_FRAG_IPV6 = 0x80, - /** Non-fragmented IPv6 + TCP flow */ + /// Non-fragmented IPv6 + TCP flow RSS_NONFRAG_IPV6_TCP = 0x100, - /** Non-fragmented IPv6 + UDP flow */ + /// Non-fragmented IPv6 + UDP flow RSS_NONFRAG_IPV6_UDP = 0x200, - /** Non-fragmented IPv6 + SCTP flow */ + /// Non-fragmented IPv6 + SCTP flow RSS_NONFRAG_IPV6_SCTP = 0x400, - /** Non-fragmented IPv6 + non TCP/UDP/SCTP flow */ + /// Non-fragmented IPv6 + non TCP/UDP/SCTP flow RSS_NONFRAG_IPV6_OTHER = 0x800, - /** L2 payload based flow */ + /// L2 payload based flow RSS_L2_PAYLOAD = 0x1000, - /** IPv6 Ex based flow */ + /// IPv6 Ex based flow RSS_IPV6_EX = 0x2000, - /** IPv6 + TCP Ex based flow */ + /// IPv6 + TCP Ex based flow RSS_IPV6_TCP_EX = 0x4000, - /** IPv6 + UDP Ex based flow */ + /// IPv6 + UDP Ex based flow RSS_IPV6_UDP_EX = 0x8000, - /** Consider device port number as a flow differentiator */ + /// Consider device port number as a flow differentiator RSS_PORT = 0x10000, - /** VXLAN protocol based flow */ + /// VXLAN protocol based flow RSS_VXLAN = 0x20000, - /** GENEVE protocol based flow */ + /// GENEVE protocol based flow RSS_GENEVE = 0x40000, - /** NVGRE protocol based flow */ + /// NVGRE protocol based flow RSS_NVGRE = 0x80000, - /** All RSS functions supported by the device */ + /// All RSS functions supported by the device RSS_ALL_SUPPORTED = -1, - /** A default set of RSS functions supported by the device */ + /// A default set of RSS functions supported by the device RSS_DEFAULT = PCPP_RSS_HASH_MAGIC_NUMBER }; - /** - * @struct DpdkDeviceConfiguration - * A struct that contains user configurable parameters for opening a DpdkDevice. All of these parameters have - * default values so the user doesn't have to use these parameters or understand exactly what is their effect - */ + /// @struct DpdkDeviceConfiguration + /// A struct that contains user configurable parameters for opening a DpdkDevice. All of these parameters have + /// default values so the user doesn't have to use these parameters or understand exactly what is their effect struct DpdkDeviceConfiguration { - /** - * When configuring a DPDK RX queue, DPDK creates descriptors it will use for receiving packets from the - * network to this RX queue. This parameter enables to configure the number of descriptors that will be - * created for each RX queue - */ + /// When configuring a DPDK RX queue, DPDK creates descriptors it will use for receiving packets from the + /// network to this RX queue. This parameter enables to configure the number of descriptors that will be + /// created for each RX queue uint16_t receiveDescriptorsNumber; - /** - * When configuring a DPDK TX queue, DPDK creates descriptors it will use for transmitting packets to the - * network through this TX queue. This parameter enables to configure the number of descriptors that will be - * created for each TX queue - */ + /// When configuring a DPDK TX queue, DPDK creates descriptors it will use for transmitting packets to the + /// network through this TX queue. This parameter enables to configure the number of descriptors that will + /// be created for each TX queue uint16_t transmitDescriptorsNumber; - /** - * Set the TX buffer flush timeout in millisecond (only relevant if sending packets using DPDK TX buffer - * mechanism). A value of zero means no timeout - */ + /// Set the TX buffer flush timeout in millisecond (only relevant if sending packets using DPDK TX buffer + /// mechanism). A value of zero means no timeout uint16_t flushTxBufferTimeout; - /** - * When configuring a DPDK device, DPDK supports to activate the Receive Side Scaling (RSS) feature to - * distribute traffic between the RX queues This parameter points to an array holding the RSS key to use for - * hashing specific header fields of received packets. The length of this array should be indicated by - * rssKeyLength below. Supplying a nullptr value causes a default random hash key to be used by the device - * driver - */ + /// When configuring a DPDK device, DPDK supports to activate the Receive Side Scaling (RSS) feature to + /// distribute traffic between the RX queues This parameter points to an array holding the RSS key to use + /// for hashing specific header fields of received packets. The length of this array should be indicated by + /// rssKeyLength below. Supplying a nullptr value causes a default random hash key to be used by the device + /// driver uint8_t* rssKey; - /** - * This parameter indicates the length in bytes of the array pointed by rssKey. - * This length will be checked in i40e only. Others assume 40 bytes to be used. - */ + /// This parameter indicates the length in bytes of the array pointed by rssKey. + /// This length will be checked in i40e only. Others assume 40 bytes to be used. uint8_t rssKeyLength; - /** - * This parameter enables to configure the types of packets to which the RSS hashing must be applied. The - * value is a mask composed of hash functions described in DpdkRssHashFunction enum. Supplying a value equal - * to zero disables the RSS feature. Supplying a value equal to -1 enables all hash functions supported by - * this PMD - */ + /// This parameter enables to configure the types of packets to which the RSS hashing must be applied. The + /// value is a mask composed of hash functions described in DpdkRssHashFunction enum. Supplying a value + /// equal to zero disables the RSS feature. Supplying a value equal to -1 enables all hash functions + /// supported by this PMD uint64_t rssHashFunction; - /** - * A c'tor for this struct - * @param[in] receiveDescriptorsNumber An optional parameter for defining the number of RX descriptors that - * will be allocated for each RX queue. Default value is 128 - * @param[in] transmitDescriptorsNumber An optional parameter for defining the number of TX descriptors that - * will be allocated for each TX queue. Default value is 512 - * @param[in] flushTxBufferTimeout An optional parameter for setting TX buffer timeout in usec. Default - * value is 100 usec - * @param[in] rssHashFunction This parameter enable to configure the types of packets to which the RSS - * hashing must be applied. The value provided here should be a mask composed of hash functions described in - * DpdkRssHashFunction enum. The default value is RSS_DEFAULT. - * @param[in] rssKey A pointer to an array holding the RSS key to use for hashing specific header of - * received packets. If not specified, there is a default key defined inside DpdkDevice - * @param[in] rssKeyLength The length in bytes of the array pointed by rssKey. Default value is the length - * of default rssKey - */ + /// A c'tor for this struct + /// @param[in] receiveDescriptorsNumber An optional parameter for defining the number of RX descriptors that + /// will be allocated for each RX queue. Default value is 128 + /// @param[in] transmitDescriptorsNumber An optional parameter for defining the number of TX descriptors + /// that will be allocated for each TX queue. Default value is 512 + /// @param[in] flushTxBufferTimeout An optional parameter for setting TX buffer timeout in usec. Default + /// value is 100 usec + /// @param[in] rssHashFunction This parameter enable to configure the types of packets to which the RSS + /// hashing must be applied. The value provided here should be a mask composed of hash functions described + /// in DpdkRssHashFunction enum. The default value is RSS_DEFAULT. + /// @param[in] rssKey A pointer to an array holding the RSS key to use for hashing specific header of + /// received packets. If not specified, there is a default key defined inside DpdkDevice + /// @param[in] rssKeyLength The length in bytes of the array pointed by rssKey. Default value is the length + /// of default rssKey explicit DpdkDeviceConfiguration(uint16_t receiveDescriptorsNumber = 128, uint16_t transmitDescriptorsNumber = 512, uint16_t flushTxBufferTimeout = 100, @@ -316,538 +288,447 @@ namespace pcpp } }; - /** - * @struct LinkStatus - * A struct that contains the link status of a DpdkDevice (DPDK port). Returned from DpdkDevice#getLinkStatus() - */ + /// @struct LinkStatus + /// A struct that contains the link status of a DpdkDevice (DPDK port). Returned from DpdkDevice#getLinkStatus() struct LinkStatus { - /** Enum for describing link duplex */ + /// Enum for describing link duplex enum LinkDuplex { - /** Full duplex */ + /// Full duplex FULL_DUPLEX, - /** Half duplex */ + /// Half duplex HALF_DUPLEX }; - /** True if link is up, false if it's down */ + /// True if link is up, false if it's down bool linkUp; - /** Link speed in Mbps (for example: 10Gbe will show 10000) */ + /// Link speed in Mbps (for example: 10Gbe will show 10000) int linkSpeedMbps; - /** Link duplex (half/full duplex) */ + /// Link duplex (half/full duplex) LinkDuplex linkDuplex; }; - /** - * @struct RxTxStats - * A container for RX/TX statistics - */ + /// @struct RxTxStats + /// A container for RX/TX statistics struct RxTxStats { - /** Total number of packets */ + /// Total number of packets uint64_t packets; - /** Total number of successfully received bytes */ + /// Total number of successfully received bytes uint64_t bytes; - /** Packets per second */ + /// Packets per second uint64_t packetsPerSec; - /** Bytes per second */ + /// Bytes per second uint64_t bytesPerSec; }; - /** - * @struct DpdkDeviceStats - * A container for DpdkDevice statistics - */ + /// @struct DpdkDeviceStats + /// A container for DpdkDevice statistics struct DpdkDeviceStats { - /** DpdkDevice ID */ + /// DpdkDevice ID uint8_t devId; - /** The timestamp of when the stats were written */ + /// The timestamp of when the stats were written timespec timestamp; - /** RX statistics per RX queue */ + /// RX statistics per RX queue RxTxStats rxStats[DPDK_MAX_RX_QUEUES]; - /** TX statistics per TX queue */ + /// TX statistics per TX queue RxTxStats txStats[DPDK_MAX_RX_QUEUES]; - /** RX statistics, aggregated for all RX queues */ + /// RX statistics, aggregated for all RX queues RxTxStats aggregatedRxStats; - /** TX statistics, aggregated for all TX queues */ + /// TX statistics, aggregated for all TX queues RxTxStats aggregatedTxStats; - /** Total number of RX packets dropped by H/W because there are no available buffers (i.e RX queues are - * full) */ + /// Total number of RX packets dropped by H/W because there are no available buffers (i.e RX queues are + /// full) uint64_t rxPacketsDroppedByHW; - /** Total number of erroneous packets */ + /// Total number of erroneous packets uint64_t rxErroneousPackets; - /** Total number of RX mbuf allocation failures */ + /// Total number of RX mbuf allocation failures uint64_t rxMbufAlocFailed; }; virtual ~DpdkDevice(); - /** - * @return The device ID (DPDK port ID) - */ + /// @return The device ID (DPDK port ID) int getDeviceId() const { return m_Id; } - /** - * @return The device name which is in the format of 'DPDK_[PORT-ID]' - */ + /// @return The device name which is in the format of 'DPDK_[PORT-ID]' std::string getDeviceName() const { return m_DeviceName; } - /** - * @return The MAC address of the device (DPDK port) - */ + /// @return The MAC address of the device (DPDK port) MacAddress getMacAddress() const { return m_MacAddress; } - /** - * @return The name of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in the - * DPDK documentation: http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html - */ + /// @return The name of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in the + /// DPDK documentation: http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html std::string getPMDName() const { return m_PMDName; } - /** - * @return The enum type of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs in - * the DPDK documentation: http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html - */ + /// @return The enum type of the PMD (poll mode driver) DPDK is using for this device. You can read about PMDs + /// in the DPDK documentation: http://dpdk.org/doc/guides/prog_guide/poll_mode_drv.html DpdkPMDType getPMDType() const { return m_PMDType; } - /** - * @return The PCI address of the device - */ + /// @return The PCI address of the device std::string getPciAddress() const { return m_PciAddress; } - /** - * @return The device's maximum transmission unit (MTU) in bytes - */ + /// @return The device's maximum transmission unit (MTU) in bytes uint16_t getMtu() const { return m_DeviceMtu; } - /** - * Set a new maximum transmission unit (MTU) for this device - * @param[in] newMtu The new MTU in bytes - * @return True if MTU was set successfully, false if operation failed or if PMD doesn't support changing the - * MTU - */ + /// Set a new maximum transmission unit (MTU) for this device + /// @param[in] newMtu The new MTU in bytes + /// @return True if MTU was set successfully, false if operation failed or if PMD doesn't support changing the + /// MTU bool setMtu(uint16_t newMtu); - /** - * @return True if this device is a virtual interface (such as VMXNET3, 1G/10G virtual function, etc.), false - * otherwise - */ + /// @return True if this device is a virtual interface (such as VMXNET3, 1G/10G virtual function, etc.), false + /// otherwise bool isVirtual() const; - /** - * Get the link status (link up/down, link speed and link duplex) - * @param[out] linkStatus A reference to object the result shall be written to - */ + /// Get the link status (link up/down, link speed and link duplex) + /// @param[out] linkStatus A reference to object the result shall be written to void getLinkStatus(LinkStatus& linkStatus) const; - /** - * @return The core ID used in this context - */ + /// @return The core ID used in this context uint32_t getCurrentCoreId() const; - /** - * @return The number of RX queues currently opened for this device (as configured in openMultiQueues() ) - */ + /// @return The number of RX queues currently opened for this device (as configured in openMultiQueues() ) uint16_t getNumOfOpenedRxQueues() const { return m_NumOfRxQueuesOpened; } - /** - * @return The number of TX queues currently opened for this device (as configured in openMultiQueues() ) - */ + /// @return The number of TX queues currently opened for this device (as configured in openMultiQueues() ) uint16_t getNumOfOpenedTxQueues() const { return m_NumOfTxQueuesOpened; } - /** - * @return The total number of RX queues available on this device - */ + /// @return The total number of RX queues available on this device uint16_t getTotalNumOfRxQueues() const { return m_TotalAvailableRxQueues; } - /** - * @return The total number of TX queues available on this device - */ + /// @return The total number of TX queues available on this device uint16_t getTotalNumOfTxQueues() const { return m_TotalAvailableTxQueues; } - /** - * Receive raw packets from the network - * @param[out] rawPacketsArr A vector where all received packets will be written into - * @param[in] rxQueueId The RX queue to receive packets from - * @return The number of packets received. If an error occurred 0 will be returned and the error will be printed - * to log - */ + /// Receive raw packets from the network + /// @param[out] rawPacketsArr A vector where all received packets will be written into + /// @param[in] rxQueueId The RX queue to receive packets from + /// @return The number of packets received. If an error occurred 0 will be returned and the error will be + /// printed to log uint16_t receivePackets(MBufRawPacketVector& rawPacketsArr, uint16_t rxQueueId) const; - /** - * Receive raw packets from the network. Please notice that in terms of performance, this is the best method to - * use for receiving packets because out of all receivePackets overloads this method requires the least overhead - * and is almost as efficient as receiving packets directly through DPDK. So if performance is a critical factor - * in your application, please use this method - * @param[out] rawPacketsArr A pointer to an array of MBufRawPacket pointers where all received packets will be - * written into. The array is expected to be allocated by the user and its length should be provided in - * rawPacketArrLength. Number of packets received will be returned. Notice it's the user responsibility to free - * the array and its content when done using it - * @param[out] rawPacketArrLength The length of MBufRawPacket pointers array - * @param[in] rxQueueId The RX queue to receive packets from - * @return The number of packets received. If an error occurred 0 will be returned and the error will be printed - * to log - */ + /// Receive raw packets from the network. Please notice that in terms of performance, this is the best method to + /// use for receiving packets because out of all receivePackets overloads this method requires the least + /// overhead and is almost as efficient as receiving packets directly through DPDK. So if performance is a + /// critical factor in your application, please use this method + /// @param[out] rawPacketsArr A pointer to an array of MBufRawPacket pointers where all received packets will be + /// written into. The array is expected to be allocated by the user and its length should be provided in + /// rawPacketArrLength. Number of packets received will be returned. Notice it's the user responsibility to free + /// the array and its content when done using it + /// @param[out] rawPacketArrLength The length of MBufRawPacket pointers array + /// @param[in] rxQueueId The RX queue to receive packets from + /// @return The number of packets received. If an error occurred 0 will be returned and the error will be + /// printed to log uint16_t receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength, uint16_t rxQueueId) const; - /** - * Receive parsed packets from the network - * @param[out] packetsArr A pointer to an allocated array of Packet pointers where all received packets will be - * written into. The array is expected to be allocated by the user and its length should be provided in - * packetsArrLength. Number of packets received will be returned. Notice it's the user responsibility to free - * the array and its content when done using it - * @param[out] packetsArrLength The length of Packet pointers array - * @param[in] rxQueueId The RX queue to receive packets from - * @return The number of packets received. If an error occurred 0 will be returned and the error will be printed - * to log - */ + /// Receive parsed packets from the network + /// @param[out] packetsArr A pointer to an allocated array of Packet pointers where all received packets will be + /// written into. The array is expected to be allocated by the user and its length should be provided in + /// packetsArrLength. Number of packets received will be returned. Notice it's the user responsibility to free + /// the array and its content when done using it + /// @param[out] packetsArrLength The length of Packet pointers array + /// @param[in] rxQueueId The RX queue to receive packets from + /// @return The number of packets received. If an error occurred 0 will be returned and the error will be + /// printed to log uint16_t receivePackets(Packet** packetsArr, uint16_t packetsArrLength, uint16_t rxQueueId) const; - /** - * Send an array of MBufRawPacket to the network. Please notice the following:
- * - In terms of performance, this is the best method to use for sending packets because out of all sendPackets - * overloads this method requires the least overhead and is almost as efficient as sending the packets - * directly through DPDK. So if performance is a critical factor in your application, please use this method - * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is - * typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let - * the TX descriptors clean - * - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK - *

- * @param[in] rawPacketsArr A pointer to an array of MBufRawPacket - * @param[in] arrLength The length of the array - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, - * 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be - * actually sent - */ + /// Send an array of MBufRawPacket to the network. Please notice the following:
+ /// - In terms of performance, this is the best method to use for sending packets because out of all sendPackets + /// overloads this method requires the least overhead and is almost as efficient as sending the packets + /// directly through DPDK. So if performance is a critical factor in your application, please use this method + /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is + /// typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let + /// the TX descriptors clean + /// - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK + ///

+ /// @param[in] rawPacketsArr A pointer to an array of MBufRawPacket + /// @param[in] arrLength The length of the array + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. + /// The default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't + /// open, 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be + /// actually sent uint16_t sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Send an array of parsed packets to the network. Please notice the following:
- * - If some or all of the packets contain raw packets which aren't of type MBufRawPacket, a new temp - * MBufRawPacket instances will be created and packet data will be copied to them. This is necessary to - * allocate mbufs which will store the data to be sent. If performance is a critical factor please make sure - * you send parsed packets that contain only raw packets of type MBufRawPacket - * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is - * typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let - * the TX descriptors clean - * - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by - * DPDK

- * @param[in] packetsArr A pointer to an array of parsed packet pointers - * @param[in] arrLength The length of the array - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, - * 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be - * actually sent - */ + /// Send an array of parsed packets to the network. Please notice the following:
+ /// - If some or all of the packets contain raw packets which aren't of type MBufRawPacket, a new temp + /// MBufRawPacket instances will be created and packet data will be copied to them. This is necessary to + /// allocate mbufs which will store the data to be sent. If performance is a critical factor please make sure + /// you send parsed packets that contain only raw packets of type MBufRawPacket + /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is + /// typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let + /// the TX descriptors clean + /// - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed + /// by DPDK

+ /// @param[in] packetsArr A pointer to an array of parsed packet pointers + /// @param[in] arrLength The length of the array + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. + /// The default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't + /// open, 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be + /// actually sent uint16_t sendPackets(Packet** packetsArr, uint16_t arrLength, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Send a vector of MBufRawPacket pointers to the network. Please notice the following:
- * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is - * typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let - * the TX descriptors clean - * - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK - *

- * @param[in] rawPacketsVec The vector of raw packet - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, - * 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be - * actually sent - */ + /// Send a vector of MBufRawPacket pointers to the network. Please notice the following:
+ /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is + /// typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let + /// the TX descriptors clean + /// - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK + ///

+ /// @param[in] rawPacketsVec The vector of raw packet + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. + /// The default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't + /// open, 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be + /// actually sent uint16_t sendPackets(MBufRawPacketVector& rawPacketsVec, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Send a vector of RawPacket pointers to the network. Please notice the following:
- * - If some or all of the raw packets aren't of type MBufRawPacket, a new temp MBufRawPacket instances will be - * created and packet data will be copied to them. This is necessary to allocate mbufs which will store the - * data to be sent. If performance is a critical factor please make sure you send only raw packets of type - * MBufRawPacket (or use the sendPackets overload that sends MBufRawPacketVector) - * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is - * typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let - * the TX descriptors clean - * - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by - * DPDK

- * @param[in] rawPacketsVec The vector of raw packet - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't open, - * 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be - * actually sent - */ + /// Send a vector of RawPacket pointers to the network. Please notice the following:
+ /// - If some or all of the raw packets aren't of type MBufRawPacket, a new temp MBufRawPacket instances will be + /// created and packet data will be copied to them. This is necessary to allocate mbufs which will store the + /// data to be sent. If performance is a critical factor please make sure you send only raw packets of type + /// MBufRawPacket (or use the sendPackets overload that sends MBufRawPacketVector) + /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - If the number of packets to send is higher than a threshold of 80% of total TX descriptors (which is + /// typically around 400 packets), then after reaching this threshold there is a built-in 0.2 sec sleep to let + /// the TX descriptors clean + /// - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed + /// by + /// DPDK

+ /// @param[in] rawPacketsVec The vector of raw packet + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packets will be sent to. + /// The default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return The number of packets actually and successfully sent. If device is not opened or TX queue isn't + /// open, 0 will be returned. Also, if TX buffer is being used and packets are buffered, some or all may not be + /// actually sent uint16_t sendPackets(RawPacketVector& rawPacketsVec, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Send a raw packet to the network. Please notice that if the raw packet isn't of type MBufRawPacket, a new - * temp MBufRawPacket will be created and the data will be copied to it. This is necessary to allocate an mbuf - * which will store the data to be sent. If performance is a critical factor please make sure you send a raw - * packet of type MBufRawPacket. Please also notice that the mbuf used or allocated in this method isn't freed - * by this method, it will be transparently freed by DPDK - * @param[in] rawPacket The raw packet to send - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if - * the packet wasn't sent for any other reason. Please notice that when using TX buffers the packet may be - * buffered and not sent immediately, which may also result in returning false - */ + /// Send a raw packet to the network. Please notice that if the raw packet isn't of type MBufRawPacket, a new + /// temp MBufRawPacket will be created and the data will be copied to it. This is necessary to allocate an mbuf + /// which will store the data to be sent. If performance is a critical factor please make sure you send a raw + /// packet of type MBufRawPacket. Please also notice that the mbuf used or allocated in this method isn't freed + /// by this method, it will be transparently freed by DPDK + /// @param[in] rawPacket The raw packet to send + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The + /// default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if + /// the packet wasn't sent for any other reason. Please notice that when using TX buffers the packet may be + /// buffered and not sent immediately, which may also result in returning false bool sendPacket(RawPacket& rawPacket, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Send a MBufRawPacket to the network. Please notice that the mbuf used in this method isn't freed by this - * method, it will be transparently freed by DPDK - * @param[in] rawPacket The MBufRawPacket to send - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if - * the packet wasn't sent for any other reason. Please notice that when using TX buffers the packet may be - * buffered and not sent immediately, which may also result in returning false - */ + /// Send a MBufRawPacket to the network. Please notice that the mbuf used in this method isn't freed by this + /// method, it will be transparently freed by DPDK + /// @param[in] rawPacket The MBufRawPacket to send + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent to. The + /// default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if + /// the packet wasn't sent for any other reason. Please notice that when using TX buffers the packet may be + /// buffered and not sent immediately, which may also result in returning false bool sendPacket(MBufRawPacket& rawPacket, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Send a parsed packet to the network. Please notice that the mbuf used or allocated in this method isn't freed - * by this method, it will be transparently freed by DPDK - * @param[in] packet The parsed packet to send. Please notice that if the packet contains a raw packet which - * isn't of type MBufRawPacket, a new temp MBufRawPacket will be created and the data will be copied to it. This - * is necessary to allocate an mbuf which will store the data to be sent. If performance is a critical factor - * please make sure you send a parsed packet that contains a raw packet of type MBufRawPacket - * @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent on. The - * default is TX queue 0 - * @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about - * DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use - * this mechanism) - * @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if - * the packet wasn't sent for any other reason. Please notice that when using TX buffers the packet may be - * buffered and not sent immediately, which may also result in returning false - */ + /// Send a parsed packet to the network. Please notice that the mbuf used or allocated in this method isn't + /// freed by this method, it will be transparently freed by DPDK + /// @param[in] packet The parsed packet to send. Please notice that if the packet contains a raw packet which + /// isn't of type MBufRawPacket, a new temp MBufRawPacket will be created and the data will be copied to it. + /// This is necessary to allocate an mbuf which will store the data to be sent. If performance is a critical + /// factor please make sure you send a parsed packet that contains a raw packet of type MBufRawPacket + /// @param[in] txQueueId An optional parameter which indicates to which TX queue the packet will be sent on. The + /// default is TX queue 0 + /// @param[in] useTxBuffer A flag which indicates whether to use TX buffer mechanism or not. To read more about + /// DPDK's TX buffer mechanism please refer to DpdkDevice class description. Default value is false (don't use + /// this mechanism) + /// @return True if packet was sent successfully or false if device is not opened, TX queue isn't opened, or if + /// the packet wasn't sent for any other reason. Please notice that when using TX buffers the packet may be + /// buffered and not sent immediately, which may also result in returning false bool sendPacket(Packet& packet, uint16_t txQueueId = 0, bool useTxBuffer = false); - /** - * Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__ - * @param[in] filter Not used in this method - * @return Always false with a "Filters aren't supported in DPDK device" error message - */ + /// Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__ + /// @param[in] filter Not used in this method + /// @return Always false with a "Filters aren't supported in DPDK device" error message bool setFilter(GeneralFilter& filter); - /** - * Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__ - * @param[in] filterAsString Not used in this method - * @return Always false with a "Filters aren't supported in DPDK device" error message - */ + /// Overridden method from IPcapDevice. __BPF filters are currently not implemented for DpdkDevice__ + /// @param[in] filterAsString Not used in this method + /// @return Always false with a "Filters aren't supported in DPDK device" error message bool setFilter(std::string filterAsString); - /** - * Open the DPDK device. Notice opening the device only makes it ready to use, it doesn't start packet - * capturing. This method initializes RX and TX queues, configures the DPDK port and starts it. Call close() to - * close the device. The device is opened in promiscuous mode - * @param[in] numOfRxQueuesToOpen Number of RX queues to setup. This number must be smaller or equal to the - * return value of getTotalNumOfRxQueues() - * @param[in] numOfTxQueuesToOpen Number of TX queues to setup. This number must be smaller or equal to the - * return value of getTotalNumOfTxQueues() - * @param[in] config Optional parameter for defining special port configuration parameters such as number of - * receive/transmit descriptors. If not set the default parameters will be set (see DpdkDeviceConfiguration) - * @return True if the device was opened successfully, false if device is already opened, if RX/TX queues - * configuration failed or of DPDK port configuration and startup failed - */ + /// Open the DPDK device. Notice opening the device only makes it ready to use, it doesn't start packet + /// capturing. This method initializes RX and TX queues, configures the DPDK port and starts it. Call close() to + /// close the device. The device is opened in promiscuous mode + /// @param[in] numOfRxQueuesToOpen Number of RX queues to setup. This number must be smaller or equal to the + /// return value of getTotalNumOfRxQueues() + /// @param[in] numOfTxQueuesToOpen Number of TX queues to setup. This number must be smaller or equal to the + /// return value of getTotalNumOfTxQueues() + /// @param[in] config Optional parameter for defining special port configuration parameters such as number of + /// receive/transmit descriptors. If not set the default parameters will be set (see DpdkDeviceConfiguration) + /// @return True if the device was opened successfully, false if device is already opened, if RX/TX queues + /// configuration failed or of DPDK port configuration and startup failed bool openMultiQueues(uint16_t numOfRxQueuesToOpen, uint16_t numOfTxQueuesToOpen, const DpdkDeviceConfiguration& config = DpdkDeviceConfiguration()); - /** - * There are two ways to capture packets using DpdkDevice: one of them is using worker threads (see - * DpdkDeviceList#startDpdkWorkerThreads() ) and the other way is setting a callback which is invoked each time - * a burst of packets is captured. This method implements the second way. After invoking this method the - * DpdkDevice enters capture mode and starts capturing packets. This method assumes there is only 1 RX queue - * opened for this device, otherwise an error is returned. It then allocates a core and creates 1 thread that - * runs in an endless loop and tries to capture packets using DPDK. Each time a burst of packets is captured the - * user callback is invoked with the user cookie as a parameter. This loop continues until stopCapture() is - * called. Notice: since the callback is invoked for every packet burst using this method can be slower than - * using worker threads. On the other hand, it's a simpler way comparing to worker threads - * @param[in] onPacketsArrive The user callback which will be invoked each time a packet burst is captured by - * the device - * @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be - * used to pass information from the user application to the callback - * @return True if capture thread started successfully or false if device is already in capture mode, number of - * opened RX queues isn't equal to 1, if the method couldn't find an available core to allocate for the capture - * thread, or if thread invocation failed. In all of these cases an appropriate error message will be printed - */ + /// There are two ways to capture packets using DpdkDevice: one of them is using worker threads (see + /// DpdkDeviceList#startDpdkWorkerThreads() ) and the other way is setting a callback which is invoked each time + /// a burst of packets is captured. This method implements the second way. After invoking this method the + /// DpdkDevice enters capture mode and starts capturing packets. This method assumes there is only 1 RX queue + /// opened for this device, otherwise an error is returned. It then allocates a core and creates 1 thread that + /// runs in an endless loop and tries to capture packets using DPDK. Each time a burst of packets is captured + /// the user callback is invoked with the user cookie as a parameter. This loop continues until stopCapture() is + /// called. Notice: since the callback is invoked for every packet burst using this method can be slower than + /// using worker threads. On the other hand, it's a simpler way comparing to worker threads + /// @param[in] onPacketsArrive The user callback which will be invoked each time a packet burst is captured by + /// the device + /// @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be + /// used to pass information from the user application to the callback + /// @return True if capture thread started successfully or false if device is already in capture mode, number of + /// opened RX queues isn't equal to 1, if the method couldn't find an available core to allocate for the capture + /// thread, or if thread invocation failed. In all of these cases an appropriate error message will be printed bool startCaptureSingleThread(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie); - /** - * This method does exactly what startCaptureSingleThread() does, but with more than one RX queue / capturing - * thread. It's called with a core mask as a parameter and creates a packet capture thread on every core. Each - * capturing thread is assigned with a specific RX queue. This method assumes all cores in the core-mask are - * available and there are enough opened RX queues to match for each thread. If these assumptions are not true - * an error is returned. After invoking all threads, all of them run in an endless loop and try to capture - * packets from their designated RX queues. Each time a burst of packets is captured the callback is invoked - * with the user cookie and the thread ID that captured the packets - * @param[in] onPacketsArrive The user callback which will be invoked each time a burst of packets is captured - * by the device - * @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be - * used to pass information from the user application to the callback - * @param coreMask The core-mask for creating the capture threads - * @return True if all capture threads started successfully or false if device is already in capture mode, not - * all cores in the core-mask are available to DPDK, there are not enough opened RX queues to match all cores in - * the core-mask, or if thread invocation failed. In all of these cases an appropriate error message will be - * printed - */ + /// This method does exactly what startCaptureSingleThread() does, but with more than one RX queue / capturing + /// thread. It's called with a core mask as a parameter and creates a packet capture thread on every core. Each + /// capturing thread is assigned with a specific RX queue. This method assumes all cores in the core-mask are + /// available and there are enough opened RX queues to match for each thread. If these assumptions are not true + /// an error is returned. After invoking all threads, all of them run in an endless loop and try to capture + /// packets from their designated RX queues. Each time a burst of packets is captured the callback is invoked + /// with the user cookie and the thread ID that captured the packets + /// @param[in] onPacketsArrive The user callback which will be invoked each time a burst of packets is captured + /// by the device + /// @param[in] onPacketsArriveUserCookie The user callback is invoked with this cookie as a parameter. It can be + /// used to pass information from the user application to the callback + /// @param coreMask The core-mask for creating the capture threads + /// @return True if all capture threads started successfully or false if device is already in capture mode, not + /// all cores in the core-mask are available to DPDK, there are not enough opened RX queues to match all cores + /// in the core-mask, or if thread invocation failed. In all of these cases an appropriate error message will be + /// printed bool startCaptureMultiThreads(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask); - /** - * If device is in capture mode started by invoking startCaptureSingleThread() or startCaptureMultiThreads(), - * this method will stop all capturing threads and set the device to non-capturing mode - */ + /// If device is in capture mode started by invoking startCaptureSingleThread() or startCaptureMultiThreads(), + /// this method will stop all capturing threads and set the device to non-capturing mode void stopCapture(); - /** - * @return The number of free mbufs in device's mbufs pool - */ + /// @return The number of free mbufs in device's mbufs pool int getAmountOfFreeMbufs() const; - /** - * @return The number of mbufs currently in use in device's mbufs pool - */ + /// @return The number of mbufs currently in use in device's mbufs pool int getAmountOfMbufsInUse() const; - /** - * Retrieve RX/TX statistics from device - * @param[out] stats A reference to a DpdkDeviceStats object where stats will be written into - */ + /// Retrieve RX/TX statistics from device + /// @param[out] stats A reference to a DpdkDeviceStats object where stats will be written into void getStatistics(DpdkDeviceStats& stats) const; - /** - * Clear device statistics - */ + /// Clear device statistics void clearStatistics(); - /** - * DPDK supports an option to buffer TX packets and send them only when reaching a certain threshold. This - * method enables the user to flush a TX buffer for certain TX queue and send the packets stored in it (you can - * read about it here: http://dpdk.org/doc/api/rte__ethdev_8h.html#a0e941a74ae1b1b886764bc282458d946). It has - * the option to flush only when timeout that was set in DpdkDeviceConfiguration#flushTxBufferTimeout expired or - * flush immediately regardless of the timeout. The usage of this method can be in the main loop where you can - * call this method once every a couple of iterations to make sure TX buffers are flushed - * @param[in] flushOnlyIfTimeoutExpired When set to true, flush will happen only if the timeout defined in - * DpdkDeviceConfiguration#flushTxBufferTimeout expired. If set to false flush will happen immediately. Default - * value is false - * @param[in] txQueueId The TX queue ID to flush its buffer. Default is 0 - * @return The number of packets sent after buffer was flushed - */ + /// DPDK supports an option to buffer TX packets and send them only when reaching a certain threshold. This + /// method enables the user to flush a TX buffer for certain TX queue and send the packets stored in it (you can + /// read about it here: http://dpdk.org/doc/api/rte__ethdev_8h.html#a0e941a74ae1b1b886764bc282458d946). It has + /// the option to flush only when timeout that was set in DpdkDeviceConfiguration#flushTxBufferTimeout expired + /// or flush immediately regardless of the timeout. The usage of this method can be in the main loop where you + /// can call this method once every a couple of iterations to make sure TX buffers are flushed + /// @param[in] flushOnlyIfTimeoutExpired When set to true, flush will happen only if the timeout defined in + /// DpdkDeviceConfiguration#flushTxBufferTimeout expired. If set to false flush will happen immediately. Default + /// value is false + /// @param[in] txQueueId The TX queue ID to flush its buffer. Default is 0 + /// @return The number of packets sent after buffer was flushed uint16_t flushTxBuffer(bool flushOnlyIfTimeoutExpired = false, uint16_t txQueueId = 0); - /** - * Check whether a specific RSS hash function is supported by this device (PMD) - * @param[in] rssHF RSS hash function to check - * @return True if this hash function is supported, false otherwise - */ + /// Check whether a specific RSS hash function is supported by this device (PMD) + /// @param[in] rssHF RSS hash function to check + /// @return True if this hash function is supported, false otherwise bool isDeviceSupportRssHashFunction(DpdkRssHashFunction rssHF) const; - /** - * Check whether a mask of RSS hash functions is supported by this device (PMD) - * @param[in] rssHFMask RSS hash functions mask to check. This mask should be built from values in - * DpdkRssHashFunction enum - * @return True if all hash functions in this mask are supported, false otherwise - */ + /// Check whether a mask of RSS hash functions is supported by this device (PMD) + /// @param[in] rssHFMask RSS hash functions mask to check. This mask should be built from values in + /// DpdkRssHashFunction enum + /// @return True if all hash functions in this mask are supported, false otherwise bool isDeviceSupportRssHashFunction(uint64_t rssHFMask) const; - /** - * @return A mask of all RSS hash functions supported by this device (PMD). This mask is built from values in - * DpdkRssHashFunction enum. Value of zero means RSS is not supported by this device - */ + /// @return A mask of all RSS hash functions supported by this device (PMD). This mask is built from values in + /// DpdkRssHashFunction enum. Value of zero means RSS is not supported by this device uint64_t getSupportedRssHashFunctions() const; - /** - * @return The RSS hash function mask configured for this device (PMD) - */ + /// @return The RSS hash function mask configured for this device (PMD) uint64_t getConfiguredRssHashFunction() const; - /** - * Translate RSS hash function mask to a list of their string representation - * @param rssHFMask RSS hash function mask - * @return RSS hash functions as strings - */ + /// Translate RSS hash function mask to a list of their string representation + /// @param rssHFMask RSS hash function mask + /// @return RSS hash functions as strings std::vector rssHashFunctionMaskToString(uint64_t rssHFMask) const; // overridden methods - /** - * Overridden method from IPcapDevice. It calls openMultiQueues() with 1 RX queue and 1 TX queue. - * Notice opening the device only makes it ready to use, it doesn't start packet capturing. The device is opened - * in promiscuous mode - * @return True if the device was opened successfully, false if device is already opened, if RX/TX queues - * configuration failed or of DPDK port configuration and startup failed - */ + /// Overridden method from IPcapDevice. It calls openMultiQueues() with 1 RX queue and 1 TX queue. + /// Notice opening the device only makes it ready to use, it doesn't start packet capturing. The device is + /// opened in promiscuous mode + /// @return True if the device was opened successfully, false if device is already opened, if RX/TX queues + /// configuration failed or of DPDK port configuration and startup failed bool open() override { return openMultiQueues(1, 1); }; - /** - * Close the DpdkDevice. When device is closed it's not possible work with it - */ + /// Close the DpdkDevice. When device is closed it's not possible work with it void close() override; private: diff --git a/Pcap++/header/DpdkDeviceList.h b/Pcap++/header/DpdkDeviceList.h index 7711b2a2ae..2d91f91ef7 100644 --- a/Pcap++/header/DpdkDeviceList.h +++ b/Pcap++/header/DpdkDeviceList.h @@ -7,71 +7,53 @@ #include "Logger.h" #include -/** - * @file - * For details about PcapPlusPlus support for DPDK see DpdkDevice.h file description - */ - -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @file +/// For details about PcapPlusPlus support for DPDK see DpdkDevice.h file description + +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class DpdkWorkerThread - * There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way is - * using a callback which is invoked on each a burst of packets are captured (see - * DpdkDevice#startCaptureSingleThread() ). This class is a base class for implementing workers. A worker is - * basically a class that is activated by DpdkDeviceList#startDpdkWorkerThreads() and runs on a designated core. - * When it runs it can do whatever the user wants it to do. The most common use it running in an endless loop and - * receive, analyze and send packets using one or more DpdkDevice instances. It can do all kinds of processing for - * these packets. The only restriction for a worker class is that it must implement the 3 abstract methods stated in - * this class-interface for start running, stop running and get the core ID the worker is running on. - */ + /// @class DpdkWorkerThread + /// There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way is + /// using a callback which is invoked on each a burst of packets are captured (see + /// DpdkDevice#startCaptureSingleThread() ). This class is a base class for implementing workers. A worker is + /// basically a class that is activated by DpdkDeviceList#startDpdkWorkerThreads() and runs on a designated core. + /// When it runs it can do whatever the user wants it to do. The most common use it running in an endless loop and + /// receive, analyze and send packets using one or more DpdkDevice instances. It can do all kinds of processing for + /// these packets. The only restriction for a worker class is that it must implement the 3 abstract methods stated + /// in this class-interface for start running, stop running and get the core ID the worker is running on. class DpdkWorkerThread { public: - /** - * A virtual d'tor. Can be overridden by child class if needed - */ - virtual ~DpdkWorkerThread() - {} - - /** - * An abstract method that must be implemented by child class. It's the indication for the worker to start - * running - * @param[in] coreId The core ID the worker is running on (should be returned in getCoreId() ) - * @return True if all went well or false otherwise - */ + /// A virtual d'tor. Can be overridden by child class if needed + virtual ~DpdkWorkerThread() = default; + + /// An abstract method that must be implemented by child class. It's the indication for the worker to start + /// running + /// @param[in] coreId The core ID the worker is running on (should be returned in getCoreId() ) + /// @return True if all went well or false otherwise virtual bool run(uint32_t coreId) = 0; - /** - * An abstract method that must be implemented by child class. It's the indication for the worker to stop - * running. After this method is called the caller expects the worker to stop running as fast as possible - */ + /// An abstract method that must be implemented by child class. It's the indication for the worker to stop + /// running. After this method is called the caller expects the worker to stop running as fast as possible virtual void stop() = 0; - /** - * An abstract method that must be implemented by child class. Get the core ID the worker is running on (as sent - * to the run() method as a parameter) - * @return The core ID the worker is running on - */ + /// An abstract method that must be implemented by child class. Get the core ID the worker is running on (as + /// sent to the run() method as a parameter) + /// @return The core ID the worker is running on virtual uint32_t getCoreId() const = 0; }; class KniDeviceList; - /** - * @class DpdkDeviceList - * A singleton class that encapsulates DPDK initialization and holds the list of DpdkDevice instances. As it's a - * singleton, it has only one active instance doesn't have a public c'tor. This class has several main uses: - * - it contains the initDpdk() static method which initializes the DPDK infrastructure. It should be called once - * in every application at its startup process - * - it contains the list of DpdkDevice instances and enables access to them - * - it has methods to start and stop worker threads. See more details in startDpdkWorkerThreads() - */ + /// @class DpdkDeviceList + /// A singleton class that encapsulates DPDK initialization and holds the list of DpdkDevice instances. As it's a + /// singleton, it has only one active instance doesn't have a public c'tor. This class has several main uses: + /// - it contains the initDpdk() static method which initializes the DPDK infrastructure. It should be called + /// once in every application at its startup process + /// - it contains the list of DpdkDevice instances and enables access to them + /// - it has methods to start and stop worker threads. See more details in startDpdkWorkerThreads() class DpdkDeviceList { friend class KniDeviceList; @@ -99,12 +81,10 @@ namespace pcpp public: ~DpdkDeviceList(); - /** - * As DpdkDeviceList is a singleton, this is the static getter to retrieve its instance. Note that if the static - * method initDpdk() was not called or returned false this instance won't be initialized and DpdkDevices won't - * be initialized either - * @return The singleton instance of DpdkDeviceList - */ + /// As DpdkDeviceList is a singleton, this is the static getter to retrieve its instance. Note that if the + /// static method initDpdk() was not called or returned false this instance won't be initialized and DpdkDevices + /// won't be initialized either + /// @return The singleton instance of DpdkDeviceList static DpdkDeviceList& getInstance() { static DpdkDeviceList instance; @@ -114,112 +94,92 @@ namespace pcpp return instance; } - /** - * A static method that has to be called once at the startup of every application that uses DPDK. It does - * several things: - * - verifies huge-pages are set and DPDK kernel module is loaded, unless specifically asked not to (these are - * set by the setup_dpdk.py external script that has to be run before application is started) - * - initializes the DPDK infrastructure - * - creates DpdkDevice instances for all ports available for DPDK - * - * @param[in] coreMask The cores to initialize DPDK with. After initialization, DPDK will only be able to use - * these cores for its work. The core mask should have a bit set for every core to use. For example: if the user - * want to use cores 1,2 the core mask should be 6 (binary: 110) - * @param[in] mBufPoolSizePerDevice The mbuf pool size each DpdkDevice will have. This has to be a number which - * is a power of 2 minus 1, for example: 1023 (= 2^10-1) or 4,294,967,295 (= 2^32-1), etc. This is a DPDK - * limitation, not PcapPlusPlus. The size of the mbuf pool size dictates how many packets can be handled by the - * application at the same time. For example: if pool size is 1023 it means that no more than 1023 packets can - * be handled or stored in application memory at every point in time - * @param[in] mBufDataSize The size of data buffer in each mbuf. If this value is less than 1, we will use - * RTE_MBUF_DEFAULT_BUF_SIZE. - * @param[in] masterCore The core DPDK will use as master to control all worker thread. The default, unless set - * otherwise, is 0 - * @param[in] initDpdkArgc Number of optional arguments - * @param[in] initDpdkArgv Optional arguments - * @param[in] appName Program name to be provided for the DPDK - * @param[in] verifyHugePagesAndDriver Verify huge-pages are set and DPDK kernel module is loaded. The default - * value it true - * @return True if initialization succeeded or false if huge-pages or DPDK kernel driver are not loaded, if - * mBufPoolSizePerDevice isn't power of 2 minus 1, if DPDK infra initialization failed or if DpdkDevice - * initialization failed. Anyway, if this method returned false it's impossible to use DPDK with PcapPlusPlus. - * You can get some more details about mbufs and pools in DpdkDevice.h file description or in DPDK web site - */ + /// A static method that has to be called once at the startup of every application that uses DPDK. It does + /// several things: + /// - verifies huge-pages are set and DPDK kernel module is loaded, unless specifically asked not to (these are + /// set by the setup_dpdk.py external script that has to be run before application is started) + /// - initializes the DPDK infrastructure + /// - creates DpdkDevice instances for all ports available for DPDK + /// + /// @param[in] coreMask The cores to initialize DPDK with. After initialization, DPDK will only be able to use + /// these cores for its work. The core mask should have a bit set for every core to use. For example: if the + /// user want to use cores 1,2 the core mask should be 6 (binary: 110) + /// @param[in] mBufPoolSizePerDevice The mbuf pool size each DpdkDevice will have. This has to be a number which + /// is a power of 2 minus 1, for example: 1023 (= 2^10-1) or 4,294,967,295 (= 2^32-1), etc. This is a DPDK + /// limitation, not PcapPlusPlus. The size of the mbuf pool size dictates how many packets can be handled by the + /// application at the same time. For example: if pool size is 1023 it means that no more than 1023 packets can + /// be handled or stored in application memory at every point in time + /// @param[in] mBufDataSize The size of data buffer in each mbuf. If this value is less than 1, we will use + /// RTE_MBUF_DEFAULT_BUF_SIZE. + /// @param[in] masterCore The core DPDK will use as master to control all worker thread. The default, unless set + /// otherwise, is 0 + /// @param[in] initDpdkArgc Number of optional arguments + /// @param[in] initDpdkArgv Optional arguments + /// @param[in] appName Program name to be provided for the DPDK + /// @param[in] verifyHugePagesAndDriver Verify huge-pages are set and DPDK kernel module is loaded. The default + /// value it true + /// @return True if initialization succeeded or false if huge-pages or DPDK kernel driver are not loaded, if + /// mBufPoolSizePerDevice isn't power of 2 minus 1, if DPDK infra initialization failed or if DpdkDevice + /// initialization failed. Anyway, if this method returned false it's impossible to use DPDK with PcapPlusPlus. + /// You can get some more details about mbufs and pools in DpdkDevice.h file description or in DPDK web site static bool initDpdk(CoreMask coreMask, uint32_t mBufPoolSizePerDevice, uint16_t mBufDataSize = 0, uint8_t masterCore = 0, uint32_t initDpdkArgc = 0, char** initDpdkArgv = nullptr, const std::string& appName = "pcapplusplusapp", bool verifyHugePagesAndDriver = true); - /** - * Get a DpdkDevice by port ID - * @param[in] portId The port ID - * @return A pointer to the DpdkDevice or nullptr if no such device is found - */ + /// Get a DpdkDevice by port ID + /// @param[in] portId The port ID + /// @return A pointer to the DpdkDevice or nullptr if no such device is found DpdkDevice* getDeviceByPort(int portId) const; - /** - * Get a DpdkDevice by port PCI address - * @param[in] pciAddr The port PCI address - * @return A pointer to the DpdkDevice or nullptr if no such device is found - */ + /// Get a DpdkDevice by port PCI address + /// @param[in] pciAddr The port PCI address + /// @return A pointer to the DpdkDevice or nullptr if no such device is found DpdkDevice* getDeviceByPciAddress(const std::string& pciAddr) const; - /** - * @return A vector of all DpdkDevice instances - */ + /// @return A vector of all DpdkDevice instances const std::vector& getDpdkDeviceList() const { return m_DpdkDeviceList; } - /** - * @return DPDK master core which is the core that initializes the application - */ + /// @return DPDK master core which is the core that initializes the application SystemCore getDpdkMasterCore() const; - /** - * Change the log level of all modules of DPDK - * @param[in] logLevel The log level to set. Logger#Info is RTE_LOG_NOTICE and Logger#Debug is RTE_LOG_DEBUG - */ + /// Change the log level of all modules of DPDK + /// @param[in] logLevel The log level to set. Logger#Info is RTE_LOG_NOTICE and Logger#Debug is RTE_LOG_DEBUG void setDpdkLogLevel(Logger::LogLevel logLevel); - /** - * @return The current DPDK log level. RTE_LOG_NOTICE and lower are considered as Logger#Info. RTE_LOG_INFO or - * RTE_LOG_DEBUG are considered as Logger#Debug - */ + /// @return The current DPDK log level. RTE_LOG_NOTICE and lower are considered as Logger#Info. RTE_LOG_INFO or + /// RTE_LOG_DEBUG are considered as Logger#Debug Logger::LogLevel getDpdkLogLevel() const; - /** - * Order DPDK to write all its logs to a file - * @param[in] logFile The file to write to - * @return True if action succeeded, false otherwise - */ + /// Order DPDK to write all its logs to a file + /// @param[in] logFile The file to write to + /// @return True if action succeeded, false otherwise bool writeDpdkLogToFile(FILE* logFile); - /** - * There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other way - * is setting a callback which is invoked each time a burst of packets is captured (see - * DpdkDevice#startCaptureSingleThread() ). This method implements the first way. See a detailed description of - * workers in DpdkWorkerThread class description. This method gets a vector of workers (classes that implement - * the DpdkWorkerThread interface) and a core mask and starts a worker thread on each core (meaning - call the - * worker's DpdkWorkerThread#run() method). Workers usually run in an endless loop and will be ordered to stop - * by calling stopDpdkWorkerThreads().
Note that number of cores in the core mask must be equal to the - * number of workers. In addition it's impossible to run a worker thread on DPDK master core, so the core mask - * shouldn't include the master core (you can find the master core by calling getDpdkMasterCore() ). - * @param[in] coreMask The bitmask of cores to run worker threads on. This list shouldn't include DPDK master - * core - * @param[in] workerThreadsVec A vector of worker instances to run (classes who implement the DpdkWorkerThread - * interface). Number of workers in this vector must be equal to the number of cores in the core mask. Notice - * that the instances of DpdkWorkerThread shouldn't be freed until calling stopDpdkWorkerThreads() as these - * instances are running - * @return True if all worker threads started successfully or false if: DPDK isn't initialized (initDpdk() - * wasn't called or returned false), number of cores differs from number of workers, core mask includes DPDK - * master core or if one of the worker threads couldn't be run - */ + /// There are two ways to capture packets using DpdkDevice: one of them is using worker threads and the other + /// way is setting a callback which is invoked each time a burst of packets is captured (see + /// DpdkDevice#startCaptureSingleThread() ). This method implements the first way. See a detailed description of + /// workers in DpdkWorkerThread class description. This method gets a vector of workers (classes that implement + /// the DpdkWorkerThread interface) and a core mask and starts a worker thread on each core (meaning - call the + /// worker's DpdkWorkerThread#run() method). Workers usually run in an endless loop and will be ordered to stop + /// by calling stopDpdkWorkerThreads().
Note that number of cores in the core mask must be equal to the + /// number of workers. In addition it's impossible to run a worker thread on DPDK master core, so the core mask + /// shouldn't include the master core (you can find the master core by calling getDpdkMasterCore() ). + /// @param[in] coreMask The bitmask of cores to run worker threads on. This list shouldn't include DPDK master + /// core + /// @param[in] workerThreadsVec A vector of worker instances to run (classes who implement the DpdkWorkerThread + /// interface). Number of workers in this vector must be equal to the number of cores in the core mask. Notice + /// that the instances of DpdkWorkerThread shouldn't be freed until calling stopDpdkWorkerThreads() as these + /// instances are running + /// @return True if all worker threads started successfully or false if: DPDK isn't initialized (initDpdk() + /// wasn't called or returned false), number of cores differs from number of workers, core mask includes DPDK + /// master core or if one of the worker threads couldn't be run bool startDpdkWorkerThreads(CoreMask coreMask, std::vector& workerThreadsVec); - /** - * Assuming worker threads are running, this method orders them to stop by calling DpdkWorkerThread#stop(). Then - * it waits until they stop running - */ + /// Assuming worker threads are running, this method orders them to stop by calling DpdkWorkerThread#stop(). + /// Then it waits until they stop running void stopDpdkWorkerThreads(); }; diff --git a/Pcap++/header/KniDevice.h b/Pcap++/header/KniDevice.h index 40e04a947b..64d3099e15 100644 --- a/Pcap++/header/KniDevice.h +++ b/Pcap++/header/KniDevice.h @@ -10,632 +10,518 @@ #include "MBufRawPacket.h" #include "LinuxNicInformationSocket.h" -/** - * @file - * @brief This file and KniDeviceList.h provide PcapPlusPlus C++ wrapper - * for DPDK KNI (Kernel Network Interface) library (librte_kni). - * The main propose of the rte_kni library is to provide a way to forward - * packets received by DPDK application to Linux kernel (a.e. to processes that - * have opened some kind of a net socket) for further processing and to obtain - * packets from Linux kernel. The KNI device is the bridge that accomplish the - * translation between DPDK packets (mbuf) and Linux kernel/socket packets - * (skbuf). Currently KNI devices report speeds up to 10 GBit/s.
- * KNI device is a virtual network interface so it can be created and destroyed - * programmatically at will. As a real network interface KNI deivice must - * be managed appropriately like other interfaces. To start operate it MUST be - * given an IP address for example by the means of ip a command and - * MUST be put up for example by ip l set [interface] up.
- * Additionally KNI interfaces support 4 other settings (depends on DPDK - * version used): - * - change link state: ip l set [interface] up/down - * - change MTU: ip l set dev [interface] mtu [mtu_count] - * - change MAC address: ip l set [interface] address [new_mac] - * - change promiscuous mode: ip l set [interface] promisc on/off - * - * Changes of each of this settings generates an event/request that must be - * handled by an application that have created the KNI device in 3 second - * period or it will be rejected and Linux kernel will not apply the change. - * The way that this requests MUST be handled is defined by DPDK and so for - * each type of request the application that creates the KNI device must provide - * the callback function to call. This callbacks are set in time of KNI device - * creation via KniIoctlCallbacks or KniOldIoctlCallbacks structures (the - * structure used is dependent on DPDK version).
- * There is a way to enable ethtool on KNI devices that include - * recompilation of DPDK and strict correspondence between KNI port id and DPDK - * port id, but it is not currently supported by PcapPlusPlus.
- * - * Known issues: - * - KNI device may not be able to set/update it's link status up - * (LINK_ERROR returned): - * The problem is laying in DPDK in rte_kni_update_link function - * (it is DPDK BUG if rte_kni_update_link is __rte_experimental). - * It is recommended to load rte_kni.ko module with "carrier=on" DPDK - * default is "carrier=off", provided setup_dpdk.py by default loads with - * "carrier=on" if Your DPDK version supports it. The good indication of - * this issue are "DPDK KNI Failed to update links state for device" - * messages when Pcap++Test application is being run. - * - Packets may not be seen by applications that have open sockets on KNI - * device: - * Check your iptables settings and other packet filters - KNI device - * is traditional network device so all caveats apply; - * - I see a lot of unknown traffic - what is it? - * This must be Linux kernel trying to communicate with other devices from - * KNI device and it will do so as long as You give the KNI device any IP - * address via ip command or by record in /etc/networking/interfaces; - * - On old versions of DPDK only 4 KNI devices may be created: - * Yep this is a limitation. You can change MAX_KNI_DEVICES constant in - * KniDeviceList.cpp to unlock this limit; - * - Any set* method never succeeds: - * You may forgot that they generate KNI requests that Your application MUST - * handle. Just use KniDevice#startRequestHandlerThread to handle all - * requests automatically. Or user running the application don't have - * suitable access rights (must have CAP_NET_ADMIN). - * - * Useful links: - * - KNI interface concept DPDK - * documentation - * - KNI PMD - * - KNI DPDK sample application - * - KNI DPDK test plan - */ - +/// @file +/// @brief This file and KniDeviceList.h provide PcapPlusPlus C++ wrapper +/// for DPDK KNI (Kernel Network Interface) library (librte_kni). +/// The main propose of the rte_kni library is to provide a way to forward +/// packets received by DPDK application to Linux kernel (a.e. to processes that +/// have opened some kind of a net socket) for further processing and to obtain +/// packets from Linux kernel. The KNI device is the bridge that accomplish the +/// translation between DPDK packets (mbuf) and Linux kernel/socket packets +/// (skbuf). Currently KNI devices report speeds up to 10 GBit/s.
+/// KNI device is a virtual network interface so it can be created and destroyed +/// programmatically at will. As a real network interface KNI deivice must +/// be managed appropriately like other interfaces. To start operate it MUST be +/// given an IP address for example by the means of ip a command and +/// MUST be put up for example by ip l set [interface] up.
+/// Additionally KNI interfaces support 4 other settings (depends on DPDK +/// version used): +/// - change link state: ip l set [interface] up/down +/// - change MTU: ip l set dev [interface] mtu [mtu_count] +/// - change MAC address: ip l set [interface] address [new_mac] +/// - change promiscuous mode: ip l set [interface] promisc on/off +/// +/// Changes of each of this settings generates an event/request that must be +/// handled by an application that have created the KNI device in 3 second +/// period or it will be rejected and Linux kernel will not apply the change. +/// The way that this requests MUST be handled is defined by DPDK and so for +/// each type of request the application that creates the KNI device must provide +/// the callback function to call. This callbacks are set in time of KNI device +/// creation via KniIoctlCallbacks or KniOldIoctlCallbacks structures (the +/// structure used is dependent on DPDK version).
+/// There is a way to enable ethtool on KNI devices that include +/// recompilation of DPDK and strict correspondence between KNI port id and DPDK +/// port id, but it is not currently supported by PcapPlusPlus.
+/// +/// Known issues: +/// - KNI device may not be able to set/update it's link status up +/// (LINK_ERROR returned): +/// The problem is laying in DPDK in rte_kni_update_link function +/// (it is DPDK BUG if rte_kni_update_link is __rte_experimental). +/// It is recommended to load rte_kni.ko module with "carrier=on" DPDK +/// default is "carrier=off", provided setup_dpdk.py by default loads with +/// "carrier=on" if Your DPDK version supports it. The good indication of +/// this issue are "DPDK KNI Failed to update links state for device" +/// messages when Pcap++Test application is being run. +/// - Packets may not be seen by applications that have open sockets on KNI +/// device: +/// Check your iptables settings and other packet filters - KNI device +/// is traditional network device so all caveats apply; +/// - I see a lot of unknown traffic - what is it? +/// This must be Linux kernel trying to communicate with other devices from +/// KNI device and it will do so as long as You give the KNI device any IP +/// address via ip command or by record in /etc/networking/interfaces; +/// - On old versions of DPDK only 4 KNI devices may be created: +/// Yep this is a limitation. You can change MAX_KNI_DEVICES constant in +/// KniDeviceList.cpp to unlock this limit; +/// - Any set* method never succeeds: +/// You may forgot that they generate KNI requests that Your application MUST +/// handle. Just use KniDevice#startRequestHandlerThread to handle all +/// requests automatically. Or user running the application don't have +/// suitable access rights (must have CAP_NET_ADMIN). +/// +/// Useful links: +/// - KNI interface concept DPDK +/// documentation +/// - KNI PMD +/// - KNI DPDK sample application +/// - KNI DPDK test plan struct rte_kni; -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { class KniDevice; class KniDeviceList; - /** - * Defines the signature callback used by capturing API on KNI device - */ + /// Defines the signature callback used by capturing API on KNI device typedef bool (*OnKniPacketArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, KniDevice* device, void* userCookie); - /** - * @class KniDevice - * This class represents special kind of DPDK devices called KNI - Kernel Network Interface - * that are used to exchange DPDK mbuf packets with Linux kernel network stack. - * This devices have only one RX and one TX queue so MT receiving or MT sending is not - * safe but simultaneous receiving and sending packets is MT safe. - * The RX queue of KNI device is pointed from kernel to application and TX queue is - * pointed in opposite direction - from application to kernel. So receive* methods will - * obtain packets from kernel and send* methods will send them to kernel.
- * The lifecycle of the KNI device is as follows: - * - KniDeviceConfiguration structure is created by user and filled with device settings; - * - The KniDeviceList#getInstance method is called to initialize the KNI module and - * obtain the KniDeviceList singleton; - * - KniDeviceList#createDevice method of the singleton is called to allocate new KNI device; - * - Device then must be opened by calling KniDevice#open; - * - During lifetime the application must handle the requests from kernel either by calling - * KniDevice#handleRequests to handle them synchronously or by starting separate thread - * to do this by calling KniDevice#startRequestHandlerThread; - * - During lifetime the packets may be send to/received from KNI device via - * calls to synchronous API (send/receive methods) or asynchronously by - * running capturing thread using KniDevice#startCapture; - * - KNI device will be destroyed or implicitly on application exit. User must assure - * that NO OTHER linux application is using KNI device when and after it is being - * destroyed otherwise Linux kernel may crush dramatically. - */ + /// @class KniDevice + /// This class represents special kind of DPDK devices called KNI - Kernel Network Interface + /// that are used to exchange DPDK mbuf packets with Linux kernel network stack. + /// This devices have only one RX and one TX queue so MT receiving or MT sending is not + /// safe but simultaneous receiving and sending packets is MT safe. + /// The RX queue of KNI device is pointed from kernel to application and TX queue is + /// pointed in opposite direction - from application to kernel. So receive* methods will + /// obtain packets from kernel and send* methods will send them to kernel.
+ /// The lifecycle of the KNI device is as follows: + /// - KniDeviceConfiguration structure is created by user and filled with device settings; + /// - The KniDeviceList#getInstance method is called to initialize the KNI module and + /// obtain the KniDeviceList singleton; + /// - KniDeviceList#createDevice method of the singleton is called to allocate new KNI device; + /// - Device then must be opened by calling KniDevice#open; + /// - During lifetime the application must handle the requests from kernel either by calling + /// KniDevice#handleRequests to handle them synchronously or by starting separate thread + /// to do this by calling KniDevice#startRequestHandlerThread; + /// - During lifetime the packets may be send to/received from KNI device via + /// calls to synchronous API (send/receive methods) or asynchronously by + /// running capturing thread using KniDevice#startCapture; + /// - KNI device will be destroyed or implicitly on application exit. User must assure + /// that NO OTHER linux application is using KNI device when and after it is being + /// destroyed otherwise Linux kernel may crush dramatically. class KniDevice : public IDevice { friend class KniDeviceList; friend class MBufRawPacket; public: - /** - * Various link related constants for KNI device - */ + /// Various link related constants for KNI device enum KniLinkState { - /** Returned by KNI functions if DPDK version used don't support link setup capability */ + /// Returned by KNI functions if DPDK version used don't support link setup capability LINK_NOT_SUPPORTED = -2, - /** Returned by KNI functions if link changing function meets an error */ + /// Returned by KNI functions if link changing function meets an error LINK_ERROR = -1, - /** Used to put link status on KNI device DOWN */ + /// Used to put link status on KNI device DOWN LINK_DOWN = 0, - /** Used to put link status on KNI device UP */ + /// Used to put link status on KNI device UP LINK_UP = 1 }; - /** - * Various information related constants for KNI device - */ + /// Various information related constants for KNI device enum KniInfoState { - /** Used to identify intent to obtain cached version of KNI device information */ + /// Used to identify intent to obtain cached version of KNI device information INFO_CACHED = 0, - /** Used to identify intent to renew/update KNI device information */ + /// Used to identify intent to renew/update KNI device information INFO_RENEW = 1 }; - /** - * Promiscuous mode related constants for KNI device - */ + /// Promiscuous mode related constants for KNI device enum KniPromiscuousMode { - /** Used to DISABLE promiscuous mode on KNI device */ + /// Used to DISABLE promiscuous mode on KNI device PROMISC_DISABLE = 0, - /** Used to ENABLE promiscuous mode on KNI device */ + /// Used to ENABLE promiscuous mode on KNI device PROMISC_ENABLE = 1 }; - /** - * @brief New callbacks for KNI device events. - * This structure MUST be used ONLY when KniDeviceList#callbackVersion returns - * KniDeviceList#KniCallbackVersion#CALLBACKS_NEW. - * Or if You are sure that DPDK version used is 17.11 or higher. - * If some callback is not provided (nullptr) the request will always succeeds - * if other is not specified in callback description. - * @note This callbacks are direct copy of one defined in rte_kni_ops. Future - * maintainers of KNI device feature MUST refer to rte_kni_ops structure in - * rte_kni.h header file of DPDK to track the difference in signatures - */ + /// @brief New callbacks for KNI device events. + /// This structure MUST be used ONLY when KniDeviceList#callbackVersion returns + /// KniDeviceList#KniCallbackVersion#CALLBACKS_NEW. + /// Or if You are sure that DPDK version used is 17.11 or higher. + /// If some callback is not provided (nullptr) the request will always succeeds + /// if other is not specified in callback description. + /// @note This callbacks are direct copy of one defined in rte_kni_ops. Future + /// maintainers of KNI device feature MUST refer to rte_kni_ops structure in + /// rte_kni.h header file of DPDK to track the difference in signatures struct KniIoctlCallbacks { - /** - * Pointer to function of changing MTU. - * Must return 0 in case of success or negative error code - */ + /// Pointer to function of changing MTU. + /// Must return 0 in case of success or negative error code int (*change_mtu)(uint16_t port_id, unsigned int new_mtu); - /** - * Pointer to function of configuring network interface. - * Must return 0 in case of success or negative error code - */ + /// Pointer to function of configuring network interface. + /// Must return 0 in case of success or negative error code int (*config_network_if)(uint16_t port_id, uint8_t if_up); - /** - * Pointer to function of configuring mac address. - * If callback is not provided and port_id of KNI device is not UINT16_MAX - * then DPDK will use predefined callback witch sets MAC address of - * DPDK port port_id via rte_eth_dev_default_mac_addr_set. - * Must return 0 in case of success or negative error code - */ + /// Pointer to function of configuring mac address. + /// If callback is not provided and port_id of KNI device is not UINT16_MAX + /// then DPDK will use predefined callback witch sets MAC address of + /// DPDK port port_id via rte_eth_dev_default_mac_addr_set. + /// Must return 0 in case of success or negative error code int (*config_mac_address)(uint16_t port_id, uint8_t mac_addr[]); - /** - * Pointer to function of configuring promiscuous mode. - * If callback is not provided and port_id of KNI device is not UINT16_MAX - * then DPDK will use predefined callback witch sets promiscuous mode of - * DPDK port port_id via rte_eth_promiscuous_enable/rte_eth_promiscuous_disable. - * Must return 0 in case of success or negative error code - */ + /// Pointer to function of configuring promiscuous mode. + /// If callback is not provided and port_id of KNI device is not UINT16_MAX + /// then DPDK will use predefined callback witch sets promiscuous mode of + /// DPDK port port_id via rte_eth_promiscuous_enable/rte_eth_promiscuous_disable. + /// Must return 0 in case of success or negative error code int (*config_promiscusity)(uint16_t port_id, uint8_t to_on); }; - /** - * @brief Old callbacks for KNI device events. - * This structure MUST be used ONLY when KniDeviceList#callbackVersion returns - * KniDeviceList#KniCallbackVersion#CALLBACKS_OLD. - * Or if You are sure that DPDK version used is lower than 17.11. - * If some callback is not provided (nullptr) the request will always succeeds. - */ + /// @brief Old callbacks for KNI device events. + /// This structure MUST be used ONLY when KniDeviceList#callbackVersion returns + /// KniDeviceList#KniCallbackVersion#CALLBACKS_OLD. + /// Or if You are sure that DPDK version used is lower than 17.11. + /// If some callback is not provided (nullptr) the request will always succeeds. struct KniOldIoctlCallbacks { - /** - * Pointer to function of changing MTU. - * Must return 0 in case of success or negative error code - */ + /// Pointer to function of changing MTU. + /// Must return 0 in case of success or negative error code int (*change_mtu)(uint8_t port_id, unsigned int new_mtu); - /** - * Pointer to function of configuring network interface. - * Must return 0 in case of success or negative error code - */ + /// Pointer to function of configuring network interface. + /// Must return 0 in case of success or negative error code int (*config_network_if)(uint8_t port_id, uint8_t if_up); }; - /** - * @brief KNI device initialization data. - * Used to create new KNI device. - * Usage of callbacks member or oldCallbacks member is defined by - * result of KniDeviceList#callbackVersion - */ + /// @brief KNI device initialization data. + /// Used to create new KNI device. + /// Usage of callbacks member or oldCallbacks member is defined by + /// result of KniDeviceList#callbackVersion struct KniDeviceConfiguration { - /** - * Name used to display device in system. - * Must not interfere with already existing network interfaces. - * Must be less than or equal to IFNAMSIZ (16 chars including \0 on most systems) - */ + /// Name used to display device in system. + /// Must not interfere with already existing network interfaces. + /// Must be less than or equal to IFNAMSIZ (16 chars including \0 on most systems) std::string name; union { KniIoctlCallbacks* callbacks; KniOldIoctlCallbacks* oldCallbacks; }; - /** - * MAC (ETHERNET) address of new KNI device. - * If MacAddress::Zero is provided then - * some valid address will be automatically generated. - * If provided (not MacAddress::Zero) will be cached by new KNI device info structure. - */ + /// MAC (ETHERNET) address of new KNI device. + /// If MacAddress::Zero is provided then + /// some valid address will be automatically generated. + /// If provided (not MacAddress::Zero) will be cached by new KNI device info structure. MacAddress mac; - /** - * Used in same way as DPDK port id. - * If some new callbacks are omitted then have separate meaning - * (see KniIoctlCallbacks#config_mac_address and KniIoctlCallbacks#config_promiscusity). - * Can be set to UINT16_MAX. - */ + /// Used in same way as DPDK port id. + /// If some new callbacks are omitted then have separate meaning + /// (see KniIoctlCallbacks#config_mac_address and KniIoctlCallbacks#config_promiscusity). + /// Can be set to UINT16_MAX. uint16_t portId; - /** MTU of new KNI device. Will be cached by new KNI device info structure */ + /// MTU of new KNI device. Will be cached by new KNI device info structure uint16_t mtu; - /** - * If set forces to bind KNI Linux kernel thread (NOT userspace thread) to specific core. - * If rte_kni kernel module is loaded with "kthread_mode=single" then - - * rebinds kernel thread used for all KNI devices to specified core. - * If rte_kni kernel module is loaded with "kthread_mode=multiple" then - - * binds new kernel thread for this device to specified core. - */ + /// If set forces to bind KNI Linux kernel thread (NOT userspace thread) to specific core. + /// If rte_kni kernel module is loaded with "kthread_mode=single" then - + /// rebinds kernel thread used for all KNI devices to specified core. + /// If rte_kni kernel module is loaded with "kthread_mode=multiple" then - + /// binds new kernel thread for this device to specified core. bool bindKthread; - /** ID of core to bind Linux kernel thread to (same as DPDK cores IDs) */ + /// ID of core to bind Linux kernel thread to (same as DPDK cores IDs) uint32_t kthreadCoreId; }; private: - /** All instances of this class MUST be produced by KniDeviceList class */ + /// All instances of this class MUST be produced by KniDeviceList class KniDevice(const KniDeviceConfiguration& conf, size_t mempoolSize, int unique); - /** This class is not copyable */ + /// This class is not copyable KniDevice(const KniDevice&); - /** This class is not copyable */ + /// This class is not copyable KniDevice& operator=(const KniDevice&); - /** All instances of this class MUST be destroyed by KniDeviceList class */ + /// All instances of this class MUST be destroyed by KniDeviceList class ~KniDevice(); public: - /* Information getters */ - - /** - * Indicates whether the KNI device was initialized successfully - */ + /// Indicates whether the KNI device was initialized successfully inline bool isInitialized() const { return !(m_Device == nullptr || m_MBufMempool == nullptr); } - /** - * Obtains name of KNI device in form of C++ string - */ + /// Obtains name of KNI device in form of C++ string inline std::string getName() const { return std::string(m_DeviceInfo.name); } - /** - * Obtains port ID of KNI device - */ + /// Obtains port ID of KNI device inline uint16_t getPort() const { return m_DeviceInfo.portId; } - /** - * @brief Obtains link status of KNI device. - * If called with INFO_CACHED - returns cached data about link state (SUPER FAST may be INACCURATE). - * If called with INFO_RENEW - makes system call to Linux to obtain - * link information and caches it (VERY SLOW but ACCURATE). - * @param[in] state Defines information relevance level - * @return LINK_UP, LINK_DOWN, LINK_NOT_SUPPORTED if device is not initialized, some times LINK_ERROR - */ + /// @brief Obtains link status of KNI device. + /// If called with INFO_CACHED - returns cached data about link state (SUPER FAST may be INACCURATE). + /// If called with INFO_RENEW - makes system call to Linux to obtain + /// link information and caches it (VERY SLOW but ACCURATE). + /// @param[in] state Defines information relevance level + /// @return LINK_UP, LINK_DOWN, LINK_NOT_SUPPORTED if device is not initialized, some times LINK_ERROR KniLinkState getLinkState(KniInfoState state = INFO_CACHED); - /** - * @brief Obtains MAC address of KNI device. - * If called with INFO_CACHED - returns cached data about MAC address (SUPER FAST may be INACCURATE). - * If called with INFO_RENEW - makes system call to Linux to obtain - * MAC address and caches it (VERY SLOW but ACCURATE). - * @param[in] state Defines information relevance level - * @return Known MAC address of KNI interface - */ + /// @brief Obtains MAC address of KNI device. + /// If called with INFO_CACHED - returns cached data about MAC address (SUPER FAST may be INACCURATE). + /// If called with INFO_RENEW - makes system call to Linux to obtain + /// MAC address and caches it (VERY SLOW but ACCURATE). + /// @param[in] state Defines information relevance level + /// @return Known MAC address of KNI interface MacAddress getMacAddress(KniInfoState state = INFO_CACHED); - /** - * @brief Obtains MTU of KNI device. - * If called with INFO_CACHED - returns cached data about MTU (SUPER FAST may be INACCURATE). - * If called with INFO_RENEW - makes system call to Linux to obtain - * MTU and caches it (VERY SLOW but ACCURATE). - * @param[in] state Defines information relevance level - * @return Known MTU of KNI interface - */ + /// @brief Obtains MTU of KNI device. + /// If called with INFO_CACHED - returns cached data about MTU (SUPER FAST may be INACCURATE). + /// If called with INFO_RENEW - makes system call to Linux to obtain + /// MTU and caches it (VERY SLOW but ACCURATE). + /// @param[in] state Defines information relevance level + /// @return Known MTU of KNI interface uint16_t getMtu(KniInfoState state = INFO_CACHED); - /** - * @brief Obtains information about promiscuous mode of KNI device. - * If called with INFO_CACHED - returns cached data about promiscuous mode (SUPER FAST may be INACCURATE). - * If called with INFO_RENEW - makes system call to Linux to obtain - * promiscuous mode and caches it (VERY SLOW but ACCURATE). - * @param[in] state Defines information relevance level - * @return Known promiscuous mode of KNI interface - */ + /// @brief Obtains information about promiscuous mode of KNI device. + /// If called with INFO_CACHED - returns cached data about promiscuous mode (SUPER FAST may be INACCURATE). + /// If called with INFO_RENEW - makes system call to Linux to obtain + /// promiscuous mode and caches it (VERY SLOW but ACCURATE). + /// @param[in] state Defines information relevance level + /// @return Known promiscuous mode of KNI interface KniPromiscuousMode getPromiscuous(KniInfoState state = INFO_CACHED); - /* Information setters */ - - /** - * @brief Sets link state of KNI device. - * Firstly the link information is updated as by call to getLinkState(INFO_RENEW). - * Then link state is set only if obtained state differs from provided. - * New link state of KNI device is cached. - * @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function - * @note Generates change link state request - * @param[in] state Must be LINK_UP or LINK_DOWN - * @return true if desired link state of KNI device is set (was as provided or set successfully), - * false if some error occurred (debug info is printed) - */ + /// @brief Sets link state of KNI device. + /// Firstly the link information is updated as by call to getLinkState(INFO_RENEW). + /// Then link state is set only if obtained state differs from provided. + /// New link state of KNI device is cached. + /// @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function + /// @note Generates change link state request + /// @param[in] state Must be LINK_UP or LINK_DOWN + /// @return true if desired link state of KNI device is set (was as provided or set successfully), + /// false if some error occurred (debug info is printed) bool setLinkState(KniLinkState state); - /** - * @brief Sets MAC address of KNI device. - * Unconditionally changes MAC of KNI device. - * If MAC is updated successfully then it is cached. - * @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function - * @note Generates change mac request - * @param[in] mac New MAC address of KNI device - * @return true if desired MAC address is set, false if not and some error occurred (debug info is printed) - */ + /// @brief Sets MAC address of KNI device. + /// Unconditionally changes MAC of KNI device. + /// If MAC is updated successfully then it is cached. + /// @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function + /// @note Generates change mac request + /// @param[in] mac New MAC address of KNI device + /// @return true if desired MAC address is set, false if not and some error occurred (debug info is printed) bool setMacAddress(const MacAddress& mac); - /** - * @brief Sets MTU of KNI device. - * Unconditionally changes MTU of KNI device. - * If MTU is updated successfully then it is cached. - * @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function - * @note Generates change mtu request - * @warning Low MTU values may crush Linux kernel. Follow Your kernel version documentation for details - * @param[in] mtu New MTU address of KNI device - * @return true if desired MTU is set, false if not and some error occurred (debug info is printed) - */ + /// @brief Sets MTU of KNI device. + /// Unconditionally changes MTU of KNI device. + /// If MTU is updated successfully then it is cached. + /// @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function + /// @note Generates change mtu request + /// @warning Low MTU values may crush Linux kernel. Follow Your kernel version documentation for details + /// @param[in] mtu New MTU address of KNI device + /// @return true if desired MTU is set, false if not and some error occurred (debug info is printed) bool setMtu(uint16_t mtu); - /** - * @brief Sets promiscuous mode of KNI device. - * Firstly the promiscuous mode information is updated as by call to getPromiscuous(INFO_RENEW). - * Then promiscuous mode is set only if obtained mode differs from provided. - * New promiscuous mode of KNI device is cached. - * @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function - * @note Generates promiscuous mode request - * @param[in] mode Must be PROMISC_DISABLE or PROMISC_ENABLE - * @return true if desired promiscuous mode of KNI device is set (was as provided or set successfully), - * false if some error occurred (debug info is printed) - */ + /// @brief Sets promiscuous mode of KNI device. + /// Firstly the promiscuous mode information is updated as by call to getPromiscuous(INFO_RENEW). + /// Then promiscuous mode is set only if obtained mode differs from provided. + /// New promiscuous mode of KNI device is cached. + /// @note You must be using sudo or be root or have CAP_NET_ADMIN capability to use this function + /// @note Generates promiscuous mode request + /// @param[in] mode Must be PROMISC_DISABLE or PROMISC_ENABLE + /// @return true if desired promiscuous mode of KNI device is set (was as provided or set successfully), + /// false if some error occurred (debug info is printed) bool setPromiscuous(KniPromiscuousMode mode); - /** - * @brief Updates link state of KNI device. - * Unconditionally updates link state of KNI device via call to DPDK librte_kni API. - * FASTER THAN setLinkState(state) but may not be supported or may fail. - * If link state is updated successfully then it is cached. - * @param[in] state New link state of KNI device - * @return LINK_NOT_SUPPORTED if this capability is not supported by DPDK version used (DPDK ver < 18.11), - * LINK_ERROR if attempt to set link state failed (may always fail on some systems see class description) - * LINK_DOWN - previous link state was DOWN, state is successfully updated to provided one - * LINK_UP - previous link state was UP, state is successfully updated to provided one - */ + /// @brief Updates link state of KNI device. + /// Unconditionally updates link state of KNI device via call to DPDK librte_kni API. + /// FASTER THAN setLinkState(state) but may not be supported or may fail. + /// If link state is updated successfully then it is cached. + /// @param[in] state New link state of KNI device + /// @return LINK_NOT_SUPPORTED if this capability is not supported by DPDK version used (DPDK ver < 18.11), + /// LINK_ERROR if attempt to set link state failed (may always fail on some systems see class description) + /// LINK_DOWN - previous link state was DOWN, state is successfully updated to provided one + /// LINK_UP - previous link state was UP, state is successfully updated to provided one KniLinkState updateLinkState(KniLinkState state); - /* Requests */ - - /** - * @brief Handle requests from Linux kernel synchronously in calling thread. - * When one of events which is needed application attention occurres it must be handled by calling this - * function (or by running RequestHandlerThread for this device). - * Until the request is handled the Linux kernel thread that manages this KNI is blocked. - * If it is not handled by application in 3 seconds the request is reported to kernel as failed one. - * Current known requests are: - * - change link state: ip l set [interface] up/down - * - change mtu: ip l set dev [interface] mtu [mtu_count] - * - change mac: ip l set [interface] address [new_mac] - * - change promiscuous mode: ip l set [interface] promisc on/off - * @warning Functions setLinkState, setMacAddress, setMtu and setPromiscuous will generate this requests. - * @note Callbacks provided for this KNI device will be called synchronously in calling thread during execution - * of this function - * @return true if no error happened during request handling false otherwise - */ + /// @brief Handle requests from Linux kernel synchronously in calling thread. + /// When one of events which is needed application attention occurres it must be handled by calling this + /// function (or by running RequestHandlerThread for this device). + /// Until the request is handled the Linux kernel thread that manages this KNI is blocked. + /// If it is not handled by application in 3 seconds the request is reported to kernel as failed one. + /// Current known requests are: + /// - change link state: ip l set [interface] up/down + /// - change mtu: ip l set dev [interface] mtu [mtu_count] + /// - change mac: ip l set [interface] address [new_mac] + /// - change promiscuous mode: ip l set [interface] promisc on/off + /// @warning Functions setLinkState, setMacAddress, setMtu and setPromiscuous will generate this requests. + /// @note Callbacks provided for this KNI device will be called synchronously in calling thread during execution + /// of this function + /// @return true if no error happened during request handling false otherwise bool handleRequests(); - /** - * @brief Starts new thread (using pthread) to asynchronously handle KNI device requests. - * See description of handleRequests() about requests. - * New thread is detached using pthread_detach. - * This thread can be stopped explicitly by calling stopRequestHandlerThread() or - * implicitly on KNI device destruction. - * Linux nanosleep() function is used for - * sleeping. - * @note Callbacks provided for this KNI device will be called asynchronously in new thread - * @param[in] sleepSeconds Sleeping time in seconds - * @param[in] sleepNanoSeconds Sleeping time in nanoseconds - * @return true if new thread is started successfully false otherwise - */ + /// @brief Starts new thread (using pthread) to asynchronously handle KNI device requests. + /// See description of handleRequests() about requests. + /// New thread is detached using pthread_detach. + /// This thread can be stopped explicitly by calling stopRequestHandlerThread() or + /// implicitly on KNI device destruction. + /// Linux nanosleep() function is used for + /// sleeping. + /// @note Callbacks provided for this KNI device will be called asynchronously in new thread + /// @param[in] sleepSeconds Sleeping time in seconds + /// @param[in] sleepNanoSeconds Sleeping time in nanoseconds + /// @return true if new thread is started successfully false otherwise bool startRequestHandlerThread(long sleepSeconds, long sleepNanoSeconds = 0); - /** - * @brief Explicitly stops request thread for this device if it was running. - * See description of handleRequests() about requests. - * @warning There may be a rare error when request thread handles requests on already - * destroyed device. It occurres only because request thread is detached one but it is really really rare. - * In case of this error occurring (must be SIGSEGV) change type of created thread in startRequestHandlerThread - * function from DETACHED to JOINABLE. - */ + /// @brief Explicitly stops request thread for this device if it was running. + /// See description of handleRequests() about requests. + /// @warning There may be a rare error when request thread handles requests on already + /// destroyed device. It occurres only because request thread is detached one but it is really really rare. + /// In case of this error occurring (must be SIGSEGV) change type of created thread in startRequestHandlerThread + /// function from DETACHED to JOINABLE. void stopRequestHandlerThread(); - /* Packet receive */ - - /** - * @brief Receive raw packets from kernel. - * @param[out] rawPacketsArr A vector where all received packets will be written into - * @return The number of packets received. If an error occurred 0 will be returned and the error will be printed - * to log - */ + /// @brief Receive raw packets from kernel. + /// @param[out] rawPacketsArr A vector where all received packets will be written into + /// @return The number of packets received. If an error occurred 0 will be returned and the error will be + /// printed to log uint16_t receivePackets(MBufRawPacketVector& rawPacketsArr); - /** - * @brief Receive raw packets from kernel. - * Please notice that in terms of performance, this is the best method to use - * for receiving packets because out of all receivePackets overloads this method requires the least overhead and - * is almost as efficient as receiving packets directly through DPDK. So if performance is a critical factor in - * your application, please use this method - * @param[out] rawPacketsArr A pointer to an array of MBufRawPacket pointers where all received packets will be - * written into. The array is expected to be allocated by the user and its length should be provided in - * rawPacketArrLength. Number of packets received will be returned. Notice it's the user responsibility to free - * the array and its content when done using it - * @param[out] rawPacketArrLength The length of MBufRawPacket pointers array - * @return The number of packets received. If an error occurred 0 will be returned and the error will be printed - * to log - */ + /// @brief Receive raw packets from kernel. + /// Please notice that in terms of performance, this is the best method to use + /// for receiving packets because out of all receivePackets overloads this method requires the least overhead + /// and is almost as efficient as receiving packets directly through DPDK. So if performance is a critical + /// factor in your application, please use this method + /// @param[out] rawPacketsArr A pointer to an array of MBufRawPacket pointers where all received packets will be + /// written into. The array is expected to be allocated by the user and its length should be provided in + /// rawPacketArrLength. Number of packets received will be returned. Notice it's the user responsibility to free + /// the array and its content when done using it + /// @param[out] rawPacketArrLength The length of MBufRawPacket pointers array + /// @return The number of packets received. If an error occurred 0 will be returned and the error will be + /// printed to log uint16_t receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength); - /** - * @brief Receive parsed packets from kernel. - * @param[out] packetsArr A pointer to an allocated array of Packet pointers where all received packets will be - * written into. The array is expected to be allocated by the user and its length should be provided in - * packetsArrLength. Number of packets received will be returned. Notice it's the user responsibility to free - * the array and its content when done using it - * @param[out] packetsArrLength The length of Packet pointers array - * @return The number of packets received. If an error occurred 0 will be returned and the error will be printed - * to log - */ + /// @brief Receive parsed packets from kernel. + /// @param[out] packetsArr A pointer to an allocated array of Packet pointers where all received packets will be + /// written into. The array is expected to be allocated by the user and its length should be provided in + /// packetsArrLength. Number of packets received will be returned. Notice it's the user responsibility to free + /// the array and its content when done using it + /// @param[out] packetsArrLength The length of Packet pointers array + /// @return The number of packets received. If an error occurred 0 will be returned and the error will be + /// printed to log uint16_t receivePackets(Packet** packetsArr, uint16_t packetsArrLength); - /* Packet send */ - - /** - * @brief Send an array of MBufRawPacket to kernel. - * Please notice the following:
- * - In terms of performance, this is the best method to use for sending packets because out of all sendPackets - * overloads this method requires the least overhead and is almost as efficient as sending the packets - * directly through DPDK. So if performance is a critical factor in your application, please use this method - * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK - *

- * @param[in] rawPacketsArr A pointer to an array of MBufRawPacket - * @param[in] arrLength The length of the array - * @return The number of packets actually and successfully sent - */ + /// @brief Send an array of MBufRawPacket to kernel. + /// Please notice the following:
+ /// - In terms of performance, this is the best method to use for sending packets because out of all sendPackets + /// overloads this method requires the least overhead and is almost as efficient as sending the packets + /// directly through DPDK. So if performance is a critical factor in your application, please use this method + /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK + ///

+ /// @param[in] rawPacketsArr A pointer to an array of MBufRawPacket + /// @param[in] arrLength The length of the array + /// @return The number of packets actually and successfully sent uint16_t sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength); - /** - * @brief Send an array of parsed packets to kernel. - * Please notice the following:
- * - If some or all of the packets contain raw packets which aren't of type MBufRawPacket, a new temp - * MBufRawPacket instances will be created and packet data will be copied to them. This is necessary to - * allocate mbufs which will store the data to be sent. If performance is a critical factor please make sure - * you send parsed packets that contain only raw packets of type MBufRawPacket - * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by - * DPDK

- * @param[in] packetsArr A pointer to an array of parsed packet pointers - * @param[in] arrLength The length of the array - * @return The number of packets actually and successfully sent - */ + /// @brief Send an array of parsed packets to kernel. + /// Please notice the following:
+ /// - If some or all of the packets contain raw packets which aren't of type MBufRawPacket, a new temp + /// MBufRawPacket instances will be created and packet data will be copied to them. This is necessary to + /// allocate mbufs which will store the data to be sent. If performance is a critical factor please make sure + /// you send parsed packets that contain only raw packets of type MBufRawPacket + /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed + /// by DPDK

+ /// @param[in] packetsArr A pointer to an array of parsed packet pointers + /// @param[in] arrLength The length of the array + /// @return The number of packets actually and successfully sent uint16_t sendPackets(Packet** packetsArr, uint16_t arrLength); - /** - * @brief Send a vector of MBufRawPacket pointers to kernel. - * Please notice the following:
- * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK - *

- * @param[in] rawPacketsVec The vector of raw packet - * @return The number of packets actually and successfully sent - */ + /// @brief Send a vector of MBufRawPacket pointers to kernel. + /// Please notice the following:
+ /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - The mbufs used in this method aren't freed by this method, they will be transparently freed by DPDK + ///

+ /// @param[in] rawPacketsVec The vector of raw packet + /// @return The number of packets actually and successfully sent uint16_t sendPackets(MBufRawPacketVector& rawPacketsVec); - /** - * @brief Send a vector of RawPacket pointers to kernel. - * Please notice the following:
- * - If some or all of the raw packets aren't of type MBufRawPacket, a new temp MBufRawPacket instances will be - * created and packet data will be copied to them. This is necessary to allocate mbufs which will store the - * data to be sent. If performance is a critical factor please make sure you send only raw packets of type - * MBufRawPacket (or use the sendPackets overload that sends MBufRawPacketVector) - * - If the number of packets to send is higher than 64 this method will run multiple iterations of sending - * packets to DPDK, each iteration of 64 packets - * - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed by - * DPDK

- * @param[in] rawPacketsVec The vector of raw packet - * @return The number of packets actually and successfully sent - */ + /// @brief Send a vector of RawPacket pointers to kernel. + /// Please notice the following:
+ /// - If some or all of the raw packets aren't of type MBufRawPacket, a new temp MBufRawPacket instances will be + /// created and packet data will be copied to them. This is necessary to allocate mbufs which will store the + /// data to be sent. If performance is a critical factor please make sure you send only raw packets of type + /// MBufRawPacket (or use the sendPackets overload that sends MBufRawPacketVector) + /// - If the number of packets to send is higher than 64 this method will run multiple iterations of sending + /// packets to DPDK, each iteration of 64 packets + /// - The mbufs used or allocated in this method aren't freed by this method, they will be transparently freed + /// by DPDK

+ /// @param[in] rawPacketsVec The vector of raw packet + /// @return The number of packets actually and successfully sent uint16_t sendPackets(RawPacketVector& rawPacketsVec); - /** - * @brief Send a raw packet to kernel. - * Please notice that if the raw packet isn't of type MBufRawPacket, a new temp MBufRawPacket - * will be created and the data will be copied to it. This is necessary to allocate an mbuf which will store the - * data to be sent. If performance is a critical factor please make sure you send a raw packet of type - * MBufRawPacket. Please also notice that the mbuf used or allocated in this method isn't freed by this method, - * it will be transparently freed by DPDK - * @param[in] rawPacket The raw packet to send - * @return True if packet was sent successfully or false if the packet wasn't sent for any other reason - */ + /// @brief Send a raw packet to kernel. + /// Please notice that if the raw packet isn't of type MBufRawPacket, a new temp MBufRawPacket + /// will be created and the data will be copied to it. This is necessary to allocate an mbuf which will store + /// the data to be sent. If performance is a critical factor please make sure you send a raw packet of type + /// MBufRawPacket. Please also notice that the mbuf used or allocated in this method isn't freed by this method, + /// it will be transparently freed by DPDK + /// @param[in] rawPacket The raw packet to send + /// @return True if packet was sent successfully or false if the packet wasn't sent for any other reason bool sendPacket(RawPacket& rawPacket); - /** - * @brief Send a MBufRawPacket to kernel. - * Please notice that the mbuf used in this method isn't freed by this method, it will be transparently freed by - * DPDK - * @param[in] rawPacket The MBufRawPacket to send - * @return True if packet was sent successfully or false if device is not opened or if the packet wasn't sent - * for any other reason - */ + /// @brief Send a MBufRawPacket to kernel. + /// Please notice that the mbuf used in this method isn't freed by this method, it will be transparently freed + /// by DPDK + /// @param[in] rawPacket The MBufRawPacket to send + /// @return True if packet was sent successfully or false if device is not opened or if the packet wasn't sent + /// for any other reason bool sendPacket(MBufRawPacket& rawPacket); - /** - * @brief Send a parsed packet to kernel. - * Please notice that the mbuf used or allocated in this method isn't freed by this method, it will be - * transparently freed by DPDK - * @param[in] packet The parsed packet to send. Please notice that if the packet contains a raw packet which - * isn't of type MBufRawPacket, a new temp MBufRawPacket will be created and the data will be copied to it. This - * is necessary to allocate an mbuf which will store the data to be sent. If performance is a critical factor - * please make sure you send a parsed packet that contains a raw packet of type MBufRawPacket - * @return True if packet was sent successfully or false if device is not opened or if the packet wasn't sent - * for any other reason - */ + /// @brief Send a parsed packet to kernel. + /// Please notice that the mbuf used or allocated in this method isn't freed by this method, it will be + /// transparently freed by DPDK + /// @param[in] packet The parsed packet to send. Please notice that if the packet contains a raw packet which + /// isn't of type MBufRawPacket, a new temp MBufRawPacket will be created and the data will be copied to it. + /// This is necessary to allocate an mbuf which will store the data to be sent. If performance is a critical + /// factor please make sure you send a parsed packet that contains a raw packet of type MBufRawPacket + /// @return True if packet was sent successfully or false if device is not opened or if the packet wasn't sent + /// for any other reason bool sendPacket(Packet& packet); - /* Packet capture */ - - /** - * @brief Start capturing packets asynchronously on this KNI interface. - * Each time a burst of packets is captured the onPacketArrives callback is called. - * The capture is done on a new thread created by this method, meaning all callback - * calls are done in a thread other than the caller thread. - * Capture process will stop and this capture thread will be terminated when calling stopCapture(). - * This method must be called after the device is opened (i.e the open() method was called), otherwise an error - * will be returned. Capturing thread will be terminated automatically on KNI device destruction or when close() - * is called. - * @param[in] onPacketArrives A callback that is called each time a burst of packets is captured - * @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to - * the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects that - * give context to the capture callback, for example: objects that counts packets, manages flow state or manages - * the application state according to the packet that was captured - * @return True if capture started successfully, false if (relevant log error is printed in any case): - * - Capture is already running - * - Device is not opened - * - Capture thread could not be created - */ + /// @brief Start capturing packets asynchronously on this KNI interface. + /// Each time a burst of packets is captured the onPacketArrives callback is called. + /// The capture is done on a new thread created by this method, meaning all callback + /// calls are done in a thread other than the caller thread. + /// Capture process will stop and this capture thread will be terminated when calling stopCapture(). + /// This method must be called after the device is opened (i.e the open() method was called), otherwise an error + /// will be returned. Capturing thread will be terminated automatically on KNI device destruction or when + /// close() is called. + /// @param[in] onPacketArrives A callback that is called each time a burst of packets is captured + /// @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to + /// the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects + /// that give context to the capture callback, for example: objects that counts packets, manages flow state or + /// manages the application state according to the packet that was captured + /// @return True if capture started successfully, false if (relevant log error is printed in any case): + /// - Capture is already running + /// - Device is not opened + /// - Capture thread could not be created bool startCapture(OnKniPacketArriveCallback onPacketArrives, void* onPacketArrivesUserCookie); - /** - * @brief Start capturing packets synchronously on this KNI interface in blocking mode. - * Blocking mode means that this method block and won't return until the user frees the blocking - * (via onPacketArrives callback) or until a user defined timeout expires. - * Whenever a burst of packets is captured the onPacketArrives callback is called and lets the user handle the - * packet. In each callback call the user should return true if he wants to release the block or false if it - * wants it to keep blocking. Regardless of this callback a timeout is defined when stop capturing. When this - * timeout expires the method will return.
Please notice that stopCapture() isn't needed here because when - * the method returns (after timeout or per user decision) capturing on the device is stopped. - * @param[in] onPacketArrives A callback given by the user for handling incoming packets. After handling each - * burst of packets the user needs to return a boolean value. True value indicates stop capturing and stop - * blocking and false value indicates continue capturing and blocking - * @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to - * the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects that - * give context to the capture callback, for example: objects that counts packets, manages flow state or manages - * the application state according to the packet that was captured - * @param[in] timeout A timeout in seconds for the blocking to stop even if the user didn't return "true" in the - * onPacketArrives callback If this timeout is set to 0 or less the timeout will be ignored, meaning the method - * will keep blocking until the user frees it via the onPacketArrives callback - * @return -1 if timeout expired, 1 if blocking was stopped via onPacketArrives callback or 0 if an error - * occurred (such as device not open etc.). When returning 0 an appropriate error message is printed to log - */ + /// @brief Start capturing packets synchronously on this KNI interface in blocking mode. + /// Blocking mode means that this method block and won't return until the user frees the blocking + /// (via onPacketArrives callback) or until a user defined timeout expires. + /// Whenever a burst of packets is captured the onPacketArrives callback is called and lets the user handle the + /// packet. In each callback call the user should return true if he wants to release the block or false if it + /// wants it to keep blocking. Regardless of this callback a timeout is defined when stop capturing. When this + /// timeout expires the method will return.
Please notice that stopCapture() isn't needed here because when + /// the method returns (after timeout or per user decision) capturing on the device is stopped. + /// @param[in] onPacketArrives A callback given by the user for handling incoming packets. After handling each + /// burst of packets the user needs to return a boolean value. True value indicates stop capturing and stop + /// blocking and false value indicates continue capturing and blocking + /// @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to + /// the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects + /// that give context to the capture callback, for example: objects that counts packets, manages flow state or + /// manages the application state according to the packet that was captured + /// @param[in] timeout A timeout in seconds for the blocking to stop even if the user didn't return "true" in + /// the onPacketArrives callback If this timeout is set to 0 or less the timeout will be ignored, meaning the + /// method will keep blocking until the user frees it via the onPacketArrives callback + /// @return -1 if timeout expired, 1 if blocking was stopped via onPacketArrives callback or 0 if an error + /// occurred (such as device not open etc.). When returning 0 an appropriate error message is printed to log + int startCaptureBlockingMode(OnKniPacketArriveCallback onPacketArrives, void* onPacketArrivesUserCookie, int timeout); - /** - * Stop a currently running asynchronous packet capture. - */ + /// Stop a currently running asynchronous packet capture. void stopCapture(); - /* Device control */ - - /** - * Takes appropriate actions for opening KNI device. - * @return true if the device was opened successfully, false if device is already opened, - * or KNI device configuration and startup failed - */ + /// Takes appropriate actions for opening KNI device. + /// @return true if the device was opened successfully, false if device is already opened, + /// or KNI device configuration and startup failed bool open(); - /** - * @brief Close the KNI device. - * When device is closed it's not possible to work with it. - * Stops asynchronous packet capture if it is running. - */ + /// @brief Close the KNI device. + /// When device is closed it's not possible to work with it. + /// Stops asynchronous packet capture if it is running. void close(); private: diff --git a/Pcap++/header/KniDeviceList.h b/Pcap++/header/KniDeviceList.h index ed5e737a97..bfd2386fd6 100644 --- a/Pcap++/header/KniDeviceList.h +++ b/Pcap++/header/KniDeviceList.h @@ -7,122 +7,93 @@ #include "KniDevice.h" #include "DpdkDeviceList.h" -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class KniDeviceList - * A singleton class that encapsulates DPDK KNI module initialization - * and holds the list of KniDevice instances. - * As it's a singleton, it has only one active instance doesn't have a public c'tor. - */ + /// @class KniDeviceList + /// A singleton class that encapsulates DPDK KNI module initialization + /// and holds the list of KniDevice instances. + /// As it's a singleton, it has only one active instance doesn't have a public c'tor. class KniDeviceList { KniDeviceList(); - /** - * @brief Explicit destruction of KNI device. - * After this call device is no longer available for external (by Linux) - * or internal (by application) usage. - * All threads running on this device are stopped (request and/or capturing). - * The device can no longer be found by it's name or id. - * @warning NOT MT SAFE - * @warning This method is forbidden as the result of discussion about packet memory pool - * lifetime made here. - * If You feel safe to use it please do, but no guarantee is provided. - * @param[in] kniDevice KNI device to be destroyed explicitly - */ + /// @brief Explicit destruction of KNI device. + /// After this call device is no longer available for external (by Linux) + /// or internal (by application) usage. + /// All threads running on this device are stopped (request and/or capturing). + /// The device can no longer be found by it's name or id. + /// @warning NOT MT SAFE + /// @warning This method is forbidden as the result of discussion about packet memory pool + /// lifetime made here. + /// If You feel safe to use it please do, but no guarantee is provided. + /// @param[in] kniDevice KNI device to be destroyed explicitly void destroyDevice(KniDevice* kniDevice); public: - /** - * Callback related constants for KNI device - */ + /// Callback related constants for KNI device enum KniCallbackVersion { - /** Reports that DPDK supports only KniDevice#KniIoctlCallbacks callback structure */ + /// Reports that DPDK supports only KniDevice#KniIoctlCallbacks callback structure CALLBACKS_NEW = 0, - /** Reports that DPDK supports only KniDevice#KniOldIoctlCallbacks callback structure */ + /// Reports that DPDK supports only KniDevice#KniOldIoctlCallbacks callback structure CALLBACKS_OLD = 1 }; - /** - * Various callback types supported by KNI device - */ + /// Various callback types supported by KNI device enum KniCallbackType { - /** KniDevice#KniIoctlCallbacks#change_mtu and KniDevice#KniOldIoctlCallbacks#change_mtu callback */ + /// KniDevice#KniIoctlCallbacks#change_mtu and KniDevice#KniOldIoctlCallbacks#change_mtu callback CALLBACK_MTU, - /** KniDevice#KniIoctlCallbacks#config_network_if and KniDevice#KniOldIoctlCallbacks#config_network_if - * callback */ + /// KniDevice#KniIoctlCallbacks#config_network_if and KniDevice#KniOldIoctlCallbacks#config_network_if + /// callback CALLBACK_LINK, - /** KniDevice#KniIoctlCallbacks#config_mac_address callback */ + /// KniDevice#KniIoctlCallbacks#config_mac_address callback CALLBACK_MAC, - /** KniDevice#KniIoctlCallbacks#config_promiscusity callback */ + /// KniDevice#KniIoctlCallbacks#config_promiscusity callback CALLBACK_PROMISC }; ~KniDeviceList(); - /** - * @brief Getter for singleton - * @warning Initialization of Kni module depends on initialization of DPDK made by DpdkDeviceList - * @return The singleton instance of KniDeviceList - */ + /// @brief Getter for singleton + /// @warning Initialization of Kni module depends on initialization of DPDK made by DpdkDeviceList + /// @return The singleton instance of KniDeviceList static KniDeviceList& getInstance(); - /** - * @return true if KNI module was initialized successfully false otherwise - */ + /// @return true if KNI module was initialized successfully false otherwise inline bool isInitialized() { return m_Initialized; } - /* Device manipulation */ - - /** - * @brief Factory method for KNI devices. - * Newly created device is remembered under portId and name provided in config and can be found later by them. - * If KNI device is not destroyed explicitly thru KniDeviceList#destroyDevice - * then it will be destroyed implicitly by the time application exits. - * @warning NOT MT SAFE - * @param[in] config KNI device configuration structure - * @param[in] mempoolSize Size of packet mempool used by this device - * @return Pointer to new KNI device or nullptr in case of error - */ + /// @brief Factory method for KNI devices. + /// Newly created device is remembered under portId and name provided in config and can be found later by them. + /// If KNI device is not destroyed explicitly thru KniDeviceList#destroyDevice + /// then it will be destroyed implicitly by the time application exits. + /// @warning NOT MT SAFE + /// @param[in] config KNI device configuration structure + /// @param[in] mempoolSize Size of packet mempool used by this device + /// @return Pointer to new KNI device or nullptr in case of error KniDevice* createDevice(const KniDevice::KniDeviceConfiguration& config, const size_t mempoolSize); - /** - * @brief Returns KNI device with specified portId. - * @note MT SAFE if createDevice or destroyDevice is not called concurrently - * @param[in] portId ID of KNI device to find - * @return Pointer to KNI device or nullptr if device not found - */ + /// @brief Returns KNI device with specified portId. + /// @note MT SAFE if createDevice or destroyDevice is not called concurrently + /// @param[in] portId ID of KNI device to find + /// @return Pointer to KNI device or nullptr if device not found KniDevice* getDeviceByPort(const uint16_t portId); - /** - * @brief Returns KNI device with specified name. - * @note MT SAFE if createDevice or destroyDevice is not called concurrently - * @param[in] name Name of KNI device to find - * @return Pointer to KNI device or nullptr if device not found - */ + /// @brief Returns KNI device with specified name. + /// @note MT SAFE if createDevice or destroyDevice is not called concurrently + /// @param[in] name Name of KNI device to find + /// @return Pointer to KNI device or nullptr if device not found KniDevice* getDeviceByName(const std::string& name); - /* Static information */ - - /** - * Returns KniCallbackVersion#CALLBACKS_NEW or - * KniCallbackVersion#CALLBACKS_OLD based on DPDK version used - * @note MT SAFE - */ + /// Returns KniCallbackVersion#CALLBACKS_NEW or + /// KniCallbackVersion#CALLBACKS_OLD based on DPDK version used + /// @note MT SAFE static KniCallbackVersion callbackVersion(); - /** - * Returns true if provided callback type is supported by used DPDK version - * @note MT SAFE - * @param[in] cbType One of KniCallbackType enum values - */ + /// Returns true if provided callback type is supported by used DPDK version + /// @note MT SAFE + /// @param[in] cbType One of KniCallbackType enum values static bool isCallbackSupported(const KniCallbackType cbType); private: diff --git a/Pcap++/header/LinuxNicInformationSocket.h b/Pcap++/header/LinuxNicInformationSocket.h index 2eb2b0dc47..8d29e22f97 100644 --- a/Pcap++/header/LinuxNicInformationSocket.h +++ b/Pcap++/header/LinuxNicInformationSocket.h @@ -2,71 +2,57 @@ struct ifreq; -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /** - * @class LinuxNicInformationSocket - * Simple wrapper over Linux socket for making the information - * requests about NICs or making some changes in NICs setup. - * All possible requests are described in - * netdevice(7). - * The instance of this class handles underlying socket during its lifetime - * and takes an appropriate actions to close socket on destruction. - * The user must call LinuxNicInformationSocket#makeRequest method with - * known ioctl type and properly filled ifreq structure for this ioctl type. - * Filling of ifr_name may be omitted as it will be done automatically from - * provided NIC name. - * @note Usage of this class requires the inclusion of and Linux headers - */ + /// @class LinuxNicInformationSocket + /// Simple wrapper over Linux socket for making the information + /// requests about NICs or making some changes in NICs setup. + /// All possible requests are described in + /// netdevice(7). + /// The instance of this class handles underlying socket during its lifetime + /// and takes an appropriate actions to close socket on destruction. + /// The user must call LinuxNicInformationSocket#makeRequest method with + /// known ioctl type and properly filled ifreq structure for this ioctl type. + /// Filling of ifr_name may be omitted as it will be done automatically from + /// provided NIC name. + /// @note Usage of this class requires the inclusion of and Linux headers class LinuxNicInformationSocket { public: - /** - * Simple type rename for convenience - */ + /// Simple type rename for convenience typedef int LinuxSocket; - /** - * Simple type rename for convenience - */ + /// Simple type rename for convenience typedef unsigned long IoctlType; - /** - * Tries to open handled socket on construction. - * If fails prints the debug message - */ + /// Tries to open handled socket on construction. + /// If fails prints the debug message LinuxNicInformationSocket(); - /** - * Closes handled socket on destruction. - * If no socket was opened prints the debug message - */ + /// Closes handled socket on destruction. + /// If no socket was opened prints the debug message ~LinuxNicInformationSocket(); - /** - * @brief Makes request to socket. - * Firstly tries to open socket if it is not opened. - * Then makes an ioctl(2) request to handled socket with provided request structure. - * See: netdevice(7) - * for description of possible values of ioctlType and content of request. - * @note User have no need to fill ifr_name field of request. It will be filled - * automatically from provided nicName argument. - * @param[in] nicName Name of internet controller as displayed by Linux - * @param[in] ioctlType Value of ioctl to make - * @param[in,out] request Pointer to ifreq structure that contains some information - * or will be used for obtaining the information (depends on ioctlType) - * @return false if request was not made or socket can't be opened otherwise true - * @warning For some types of requests to succeed You need to be a root - * or have the CAP_NET_ADMIN capability. - */ + /// @brief Makes request to socket. + /// Firstly tries to open socket if it is not opened. + /// Then makes an ioctl(2) request to handled socket with provided request structure. + /// See: netdevice(7) + /// for description of possible values of ioctlType and content of request. + /// @note User have no need to fill ifr_name field of request. It will be filled + /// automatically from provided nicName argument. + /// @param[in] nicName Name of internet controller as displayed by Linux + /// @param[in] ioctlType Value of ioctl to make + /// @param[in,out] request Pointer to ifreq structure that contains some information + /// or will be used for obtaining the information (depends on ioctlType) + /// @return false if request was not made or socket can't be opened otherwise true + /// @warning For some types of requests to succeed You need to be a root + /// or have the CAP_NET_ADMIN capability. bool makeRequest(const char* nicName, const IoctlType ioctlType, ifreq* request); private: - /* Hidden copy constructor. This structure is not copyable */ + /// Hidden copy constructor. This structure is not copyable LinuxNicInformationSocket(const LinuxNicInformationSocket&); - /* Hidden copy assignment operator. This structure is not copyable */ + /// Hidden copy assignment operator. This structure is not copyable LinuxNicInformationSocket operator=(const LinuxNicInformationSocket&); LinuxSocket m_Socket; }; diff --git a/Pcap++/header/MBufRawPacket.h b/Pcap++/header/MBufRawPacket.h index 51e024cbed..4568ee9d46 100644 --- a/Pcap++/header/MBufRawPacket.h +++ b/Pcap++/header/MBufRawPacket.h @@ -9,10 +9,8 @@ struct rte_mbuf; struct rte_mempool; -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { @@ -23,28 +21,26 @@ namespace pcpp #define MBUFRAWPACKET_OBJECT_TYPE 1 - /** - * @class MBufRawPacket - * A class that inherits RawPacket and wraps DPDK's mbuf object (see some info about mbuf in DpdkDevice.h) but is - * compatible with PcapPlusPlus framework. Using MBufRawPacket is be almost similar to using RawPacket, the - * implementation differences are encapsulated in the class implementation. For example: user can create and - * manipulate a Packet object from MBufRawPacket the same way it is done with RawPacket; User can use - * PcapFileWriterDevice to save MBufRawPacket to pcap the same way it's used with RawPacket; etc.
The main - * difference is that RawPacket contains a pointer to the data itself and MBufRawPacket is holding a pointer to an - * mbuf object which contains a pointer to the data. This implies that MBufRawPacket without an mbuf allocated to it - * is not usable. Getting instances of MBufRawPacket can be done in one to the following ways: - * - Receiving packets from DpdkDevice. In this case DpdkDevice takes care of getting the mbuf from DPDK and - * wrapping it with MBufRawPacket - * - Creating MBufRawPacket from scratch (in order to send it with DpdkDevice, for example). In this case the - * user should call the init() method after constructing the object in order to allocate a new mbuf from DPDK - * port pool (encapsulated by DpdkDevice) - * - * Limitations of this class: - * - Currently chained mbufs are not supported. An mbuf has the capability to be linked to another mbuf and - * create a linked list of mbufs. This is good for Jumbo packets or other uses. MBufRawPacket doesn't support - * this capability so there is no way to access the mbufs linked to the mbuf wrapped by MBufRawPacket instance. - * I hope I'll be able to add this support in the future - */ + /// @class MBufRawPacket + /// A class that inherits RawPacket and wraps DPDK's mbuf object (see some info about mbuf in DpdkDevice.h) but is + /// compatible with PcapPlusPlus framework. Using MBufRawPacket is be almost similar to using RawPacket, the + /// implementation differences are encapsulated in the class implementation. For example: user can create and + /// manipulate a Packet object from MBufRawPacket the same way it is done with RawPacket; User can use + /// PcapFileWriterDevice to save MBufRawPacket to pcap the same way it's used with RawPacket; etc.
The main + /// difference is that RawPacket contains a pointer to the data itself and MBufRawPacket is holding a pointer to an + /// mbuf object which contains a pointer to the data. This implies that MBufRawPacket without an mbuf allocated to + /// it is not usable. Getting instances of MBufRawPacket can be done in one to the following ways: + /// - Receiving packets from DpdkDevice. In this case DpdkDevice takes care of getting the mbuf from DPDK and + /// wrapping it with MBufRawPacket + /// - Creating MBufRawPacket from scratch (in order to send it with DpdkDevice, for example). In this case the + /// user should call the init() method after constructing the object in order to allocate a new mbuf from DPDK + /// port pool (encapsulated by DpdkDevice) + /// + /// Limitations of this class: + /// - Currently chained mbufs are not supported. An mbuf has the capability to be linked to another mbuf and + /// create a linked list of mbufs. This is good for Jumbo packets or other uses. MBufRawPacket doesn't support + /// this capability so there is no way to access the mbufs linked to the mbuf wrapped by MBufRawPacket + /// instance. I hope I'll be able to add this support in the future class MBufRawPacket : public RawPacket { friend class DpdkDevice; @@ -63,86 +59,70 @@ namespace pcpp bool initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool); public: - /** - * A default c'tor for this class. Constructs an instance of this class without an mbuf attached to it. In order - * to allocate an mbuf the user should call the init() method. Without calling init() the instance of this class - * is not usable. This c'tor can be used for initializing an array of MBufRawPacket (which requires an empty - * c'tor) - */ + /// A default c'tor for this class. Constructs an instance of this class without an mbuf attached to it. In + /// order to allocate an mbuf the user should call the init() method. Without calling init() the instance of + /// this class is not usable. This c'tor can be used for initializing an array of MBufRawPacket (which requires + /// an empty c'tor) MBufRawPacket() : RawPacket(), m_MBuf(nullptr), m_Mempool(nullptr), m_MbufDataSize(0), m_FreeMbuf(true) { m_DeleteRawDataAtDestructor = false; } - /** - * A d'tor for this class. Once called it frees the mbuf attached to it (returning it back to the mbuf pool it - * was allocated from) - */ + /// A d'tor for this class. Once called it frees the mbuf attached to it (returning it back to the mbuf pool it + /// was allocated from) virtual ~MBufRawPacket(); - /** - * A copy c'tor for this class. The copy c'tor allocates a new mbuf from the same pool the original mbuf was - * allocated from, attaches the new mbuf to this instance of MBufRawPacket and copies the data from the original - * mbuf to the new mbuf - * @param[in] other The MBufRawPacket instance to copy from - */ + /// A copy c'tor for this class. The copy c'tor allocates a new mbuf from the same pool the original mbuf was + /// allocated from, attaches the new mbuf to this instance of MBufRawPacket and copies the data from the + /// original mbuf to the new mbuf + /// @param[in] other The MBufRawPacket instance to copy from MBufRawPacket(const MBufRawPacket& other); - /** - * @brief Initialize an instance of this class from DpdkDevice. - * Initialization includes allocating an mbuf from the pool that resides in DpdkDevice. - * The user should call this method only once per instance. - * Calling it more than once will result with an error - * @param[in] device The DpdkDevice which has the pool to allocate the mbuf from - * @return True if initialization succeeded and false if this method was already called for this instance (and - * an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason - */ + /// @brief Initialize an instance of this class from DpdkDevice. + /// Initialization includes allocating an mbuf from the pool that resides in DpdkDevice. + /// The user should call this method only once per instance. + /// Calling it more than once will result with an error + /// @param[in] device The DpdkDevice which has the pool to allocate the mbuf from + /// @return True if initialization succeeded and false if this method was already called for this instance (and + /// an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason bool init(DpdkDevice* device); #ifdef USE_DPDK_KNI - /** - * @brief Initialize an instance of this class from KniDevice. - * Initialization includes allocating an mbuf from the pool that resides in KniDevice. - * The user should call this method only once per instance. - * Calling it more than once will result with an error - * @param[in] device The KniDevice which has the pool to allocate the mbuf from - * @return True if initialization succeeded and false if this method was already called for this instance (and - * an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason - */ + /// @brief Initialize an instance of this class from KniDevice. + /// Initialization includes allocating an mbuf from the pool that resides in KniDevice. + /// The user should call this method only once per instance. + /// Calling it more than once will result with an error + /// @param[in] device The KniDevice which has the pool to allocate the mbuf from + /// @return True if initialization succeeded and false if this method was already called for this instance (and + /// an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason bool init(KniDevice* device); #endif - /** - * @brief Initialize an instance of this class and copies the content of a RawPacket object. - * Initialization includes allocating an mbuf from the pool that resides in provided DpdkDevice, - * and copying the data from the input RawPacket object into this mBuf. - * The user should call this method only once per instance. - * Calling it more than once will result with an error - * @param[in] rawPacket A pointer to a RawPacket object from which data will be copied - * @param[in] device The DpdkDevice which has the pool to allocate the mbuf from - * @return True if initialization succeeded and false if this method was already called for this instance (and - * an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason - */ + /// @brief Initialize an instance of this class and copies the content of a RawPacket object. + /// Initialization includes allocating an mbuf from the pool that resides in provided DpdkDevice, + /// and copying the data from the input RawPacket object into this mBuf. + /// The user should call this method only once per instance. + /// Calling it more than once will result with an error + /// @param[in] rawPacket A pointer to a RawPacket object from which data will be copied + /// @param[in] device The DpdkDevice which has the pool to allocate the mbuf from + /// @return True if initialization succeeded and false if this method was already called for this instance (and + /// an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason bool initFromRawPacket(const RawPacket* rawPacket, DpdkDevice* device); #ifdef USE_DPDK_KNI - /** - * @brief Initialize an instance of this class and copies the content of a RawPacket object. - * Initialization includes allocating an mbuf from the pool that resides in provided KniDevice, - * and copying the data from the input RawPacket object into this mBuf. - * The user should call this method only once per instance. - * Calling it more than once will result with an error - * @param[in] rawPacket A pointer to a RawPacket object from which data will be copied - * @param[in] device The KniDevice which has the pool to allocate the mbuf from - * @return True if initialization succeeded and false if this method was already called for this instance (and - * an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason - */ + /// @brief Initialize an instance of this class and copies the content of a RawPacket object. + /// Initialization includes allocating an mbuf from the pool that resides in provided KniDevice, + /// and copying the data from the input RawPacket object into this mBuf. + /// The user should call this method only once per instance. + /// Calling it more than once will result with an error + /// @param[in] rawPacket A pointer to a RawPacket object from which data will be copied + /// @param[in] device The KniDevice which has the pool to allocate the mbuf from + /// @return True if initialization succeeded and false if this method was already called for this instance (and + /// an mbuf is already attached) or if allocating an mbuf from the pool failed for some reason bool initFromRawPacket(const RawPacket* rawPacket, KniDevice* device); #endif - /** - * @return A pointer to the DPDK mbuf stored in this object - */ + /// @return A pointer to the DPDK mbuf stored in this object inline rte_mbuf* getMBuf() { return m_MBuf; @@ -150,109 +130,87 @@ namespace pcpp // overridden methods - /** - * @return MBufRawPacket object type - */ + /// @return MBufRawPacket object type inline uint8_t getObjectType() const override { return MBUFRAWPACKET_OBJECT_TYPE; } - /** - * An assignment operator for this class. Copies the data from the mbuf attached to the other MBufRawPacket to - * the mbuf attached to this instance. If instance is not initialized (meaning no mbuf is attached) nothing will - * be copied and instance will remain uninitialized (also, an error will be printed) - * @param[in] other The MBufRawPacket to assign data from - */ + /// An assignment operator for this class. Copies the data from the mbuf attached to the other MBufRawPacket to + /// the mbuf attached to this instance. If instance is not initialized (meaning no mbuf is attached) nothing + /// will be copied and instance will remain uninitialized (also, an error will be printed) + /// @param[in] other The MBufRawPacket to assign data from MBufRawPacket& operator=(const MBufRawPacket& other); - /** - * @brief Clone this MBufRawPacket object. See copy constructor for details. - * The caller is responsible for the deallocation of the returned pointer. - * @return A pointer to the new MBufRawPacket object which is a clone of this object - */ + /// @brief Clone this MBufRawPacket object. See copy constructor for details. + /// The caller is responsible for the deallocation of the returned pointer. + /// @return A pointer to the new MBufRawPacket object which is a clone of this object MBufRawPacket* clone() const override; - /** - * Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method - * which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this - * pointer right away after data is copied to the mbuf. So when using this method please notice that after it's - * called pRawData memory is free, don't use this pointer again. In addition, if raw packet isn't initialized - * (mbuf is nullptr), this method will call the init() method - * @param[in] pRawData A pointer to the new raw data - * @param[in] rawDataLen The new raw data length in bytes - * @param[in] timestamp The timestamp packet was received by the NIC - * @param[in] layerType The link layer type for this raw data. Default is Ethernet - * @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the - * actual packet length. This parameter represents the packet length. This parameter is optional, if not set or - * set to -1 it is assumed both lengths are equal - * @return True if raw data was copied to the mbuf successfully, false if rawDataLen is larger than mbuf max - * size, if initialization failed or if copying the data to the mbuf failed. In all of these cases an error will - * be printed to log - */ + /// Set raw data to the mbuf by copying the data to it. In order to stay compatible with the ancestor method + /// which takes control of the data pointer and frees it when RawPacket is destroyed, this method frees this + /// pointer right away after data is copied to the mbuf. So when using this method please notice that after it's + /// called pRawData memory is free, don't use this pointer again. In addition, if raw packet isn't initialized + /// (mbuf is nullptr), this method will call the init() method + /// @param[in] pRawData A pointer to the new raw data + /// @param[in] rawDataLen The new raw data length in bytes + /// @param[in] timestamp The timestamp packet was received by the NIC + /// @param[in] layerType The link layer type for this raw data. Default is Ethernet + /// @param[in] frameLength When reading from pcap files, sometimes the captured length is different from the + /// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or + /// set to -1 it is assumed both lengths are equal + /// @return True if raw data was copied to the mbuf successfully, false if rawDataLen is larger than mbuf max + /// size, if initialization failed or if copying the data to the mbuf failed. In all of these cases an error + /// will be printed to log bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); - /** - * Clears the object and frees the mbuf - */ + /// Clears the object and frees the mbuf void clear(); - /** - * Append packet data at the end of current data. This method uses the same mbuf already allocated and tries to - * append more space and copy the data to it. If MBufRawPacket is not initialize (mbuf is nullptr) or mbuf - * append failed an error is printed to log - * @param[in] dataToAppend A pointer to the data to append - * @param[in] dataToAppendLen Length in bytes of dataToAppend - */ + /// Append packet data at the end of current data. This method uses the same mbuf already allocated and tries to + /// append more space and copy the data to it. If MBufRawPacket is not initialize (mbuf is nullptr) or mbuf + /// append failed an error is printed to log + /// @param[in] dataToAppend A pointer to the data to append + /// @param[in] dataToAppendLen Length in bytes of dataToAppend void appendData(const uint8_t* dataToAppend, size_t dataToAppendLen); - /** - * Insert raw data at some index of the current data and shift the remaining data to the end. This method uses - * the same mbuf already allocated and tries to append more space to it. Then it just copies dataToAppend at the - * relevant index and shifts the remaining data to the end. If MBufRawPacket is not initialize (mbuf is nullptr) - * or mbuf append failed an error is printed to log - * @param[in] atIndex The index to insert the new data to - * @param[in] dataToInsert A pointer to the new data to insert - * @param[in] dataToInsertLen Length in bytes of dataToInsert - */ + /// Insert raw data at some index of the current data and shift the remaining data to the end. This method uses + /// the same mbuf already allocated and tries to append more space to it. Then it just copies dataToAppend at + /// the relevant index and shifts the remaining data to the end. If MBufRawPacket is not initialize (mbuf is + /// nullptr) or mbuf append failed an error is printed to log + /// @param[in] atIndex The index to insert the new data to + /// @param[in] dataToInsert A pointer to the new data to insert + /// @param[in] dataToInsertLen Length in bytes of dataToInsert void insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen); - /** - * Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be shifted - * back. This method uses the mbuf already allocated and tries to trim space from it - * @param[in] atIndex The index to start removing bytes from - * @param[in] numOfBytesToRemove Number of bytes to remove - * @return True if all bytes were removed successfully, or false if MBufRawPacket is not initialize (mbuf is - * nullptr), mbuf trim failed or logatIndex+numOfBytesToRemove is out-of-bounds of the raw data buffer. In all - * of these cases an error is printed to log - */ + /// Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be + /// shifted back. This method uses the mbuf already allocated and tries to trim space from it + /// @param[in] atIndex The index to start removing bytes from + /// @param[in] numOfBytesToRemove Number of bytes to remove + /// @return True if all bytes were removed successfully, or false if MBufRawPacket is not initialize (mbuf is + /// nullptr), mbuf trim failed or logatIndex+numOfBytesToRemove is out-of-bounds of the raw data buffer. In all + /// of these cases an error is printed to log bool removeData(int atIndex, size_t numOfBytesToRemove); - /** - * This overridden method,in contrast to its ancestor RawPacket#reallocateData() doesn't need to do anything - * because mbuf is already allocated to its maximum extent. So it only performs a check to verify the size after - * re-allocation doesn't exceed mbuf max size - * @param[in] newBufferLength The new buffer length as required by the user - * @return True if new size is larger than current size but smaller than mbuf max size, false otherwise - */ + /// This overridden method,in contrast to its ancestor RawPacket#reallocateData() doesn't need to do anything + /// because mbuf is already allocated to its maximum extent. So it only performs a check to verify the size + /// after re-allocation doesn't exceed mbuf max size + /// @param[in] newBufferLength The new buffer length as required by the user + /// @return True if new size is larger than current size but smaller than mbuf max size, false otherwise bool reallocateData(size_t newBufferLength); - /** - * Set an indication whether to free the mbuf when done using it or not ("done using it" means setting another - * mbuf or class d'tor). Default value is true. - * @param[in] val The value to set. True means free the mbuf when done using it. Default it True - */ + /// Set an indication whether to free the mbuf when done using it or not ("done using it" means setting another + /// mbuf or class d'tor). Default value is true. + /// @param[in] val The value to set. True means free the mbuf when done using it. Default it True inline void setFreeMbuf(bool val = true) { m_FreeMbuf = val; } }; - /** - * @typedef MBufRawPacketVector - * A vector of pointers to MBufRawPacket - */ + /// @typedef MBufRawPacketVector + /// A vector of pointers to MBufRawPacket typedef PointerVector MBufRawPacketVector; } // namespace pcpp diff --git a/Pcap++/header/NetworkUtils.h b/Pcap++/header/NetworkUtils.h index 7df6b397a3..d6aebd50b9 100644 --- a/Pcap++/header/NetworkUtils.h +++ b/Pcap++/header/NetworkUtils.h @@ -6,88 +6,75 @@ /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class NetworkUtils - * This class bundles several network utilities that are very common and useful. These utilities use Pcap++ and - * Packet++ packet crafting and processing capabilities. This class is a singleton and can be access by - * getInstance() only - */ + /// @class NetworkUtils + /// This class bundles several network utilities that are very common and useful. These utilities use Pcap++ and + /// Packet++ packet crafting and processing capabilities. This class is a singleton and can be access by + /// getInstance() only class NetworkUtils { public: - /** - * The access method to the singleton - * @return The singleton instance of this class - */ + /// The access method to the singleton + /// @return The singleton instance of this class static NetworkUtils& getInstance() { static NetworkUtils instance; return instance; } - /** - * Default timeout used for several utilities. Currently set to 5 seconds - */ + /// Default timeout used for several utilities. Currently set to 5 seconds static const int DefaultTimeout; - /** - * Resolve the MAC address for a given IPv4 address. It's done using the ARP protocol: send an ARP request and - * interpret the response - * @param[in] ipAddr The IPv4 address to resolve MAC address to - * @param[in] device The interface to send and receive the ARP packets on - * @param[out] arpResponseTimeMS An output parameter that will contain the time in milliseconds that took the - * ARP response to arrive - * @param[in] sourceMac An optional parameter to set the source MAC address that will be sent with the ARP - * request if this parameter isn't set or set with MacAddress#Zero the MAC address of the interface will be used - * @param[in] sourceIP An optional parameter to set the source IPv4 address that will be sent with the ARP - * request if this parameter isn't set or set with IPv4Address#Zero the default IPv4 address of the interface - * will be used - * @param[in] arpTimeout An optional parameter to set the timeout to wait for the ARP response to return. - * If this parameter isn't set or set with a number smaller than 0, a default timeout of 5 seconds will be set - * @return The resolved MAC address or MacAddress#Zero if an error occurred or address could not be resolved. - * Errors will be printed to log - */ + /// Resolve the MAC address for a given IPv4 address. It's done using the ARP protocol: send an ARP request and + /// interpret the response + /// @param[in] ipAddr The IPv4 address to resolve MAC address to + /// @param[in] device The interface to send and receive the ARP packets on + /// @param[out] arpResponseTimeMS An output parameter that will contain the time in milliseconds that took the + /// ARP response to arrive + /// @param[in] sourceMac An optional parameter to set the source MAC address that will be sent with the ARP + /// request if this parameter isn't set or set with MacAddress#Zero the MAC address of the interface will be + /// used + /// @param[in] sourceIP An optional parameter to set the source IPv4 address that will be sent with the ARP + /// request if this parameter isn't set or set with IPv4Address#Zero the default IPv4 address of the interface + /// will be used + /// @param[in] arpTimeout An optional parameter to set the timeout to wait for the ARP response to return. + /// If this parameter isn't set or set with a number smaller than 0, a default timeout of 5 seconds will be set + /// @return The resolved MAC address or MacAddress#Zero if an error occurred or address could not be resolved. + /// Errors will be printed to log MacAddress getMacAddress(IPv4Address ipAddr, PcapLiveDevice* device, double& arpResponseTimeMS, MacAddress sourceMac = MacAddress::Zero, IPv4Address sourceIP = IPv4Address::Zero, int arpTimeout = -1) const; - /** - * Resolve an IPv4 address for a given hostname. Resolving is done in multiple phases: first resolving the LAN - * gateway MAC address (or default gateway if a gateway isn't provided) using ARP protocol (by using - * NetworkUtils#getMacAddress() ). Then a DNS request is sent to a DNS server (if specified) or to the LAN - * gateway (if DNS server is not specified). The DNS response is decoded and the IPv4 address is determined. In - * addition the method outputs the time it took the DNS response to arrive and the DNS TTL written on the DNS - * response. If DNS response doesn't contain an IPv4 address resolving an IPv4Address#Zero will be returned. - * @param[in] hostname The hostname to resolve - * @param[in] device The interface to send and receive packets on - * @param[out] dnsResponseTimeMS When method returns successfully will contain the time it took to receive the - * DNS response (in milli-seconds) - * @param[out] dnsTTL When method returns successfully will contain The DNS TTL written in the DNS response - * @param[in] dnsTimeout An optional parameter to specify the timeout to wait for a DNS response. If not - * specified the default timeout is 5 sec - * @param[in] dnsServerIP An optional parameter to specify the DNS server IP to send the DNS request to. If not - * specified or specified with IPv4Address#Zero the DNS request will be sent to the default DNS server - * configured in the system - * @param[in] gatewayIP An optional parameter to specify the LAN gateway to send the DNS request through. If not - * specified or specified with IPv4Address#Zero the interface's default gateway will be used - * @return The resolved IPv4 address or IPv4Address#Zero if something went wrong (in this case an error will be - * printed to log) - */ + /// Resolve an IPv4 address for a given hostname. Resolving is done in multiple phases: first resolving the LAN + /// gateway MAC address (or default gateway if a gateway isn't provided) using ARP protocol (by using + /// NetworkUtils#getMacAddress() ). Then a DNS request is sent to a DNS server (if specified) or to the LAN + /// gateway (if DNS server is not specified). The DNS response is decoded and the IPv4 address is determined. In + /// addition the method outputs the time it took the DNS response to arrive and the DNS TTL written on the DNS + /// response. If DNS response doesn't contain an IPv4 address resolving an IPv4Address#Zero will be returned. + /// @param[in] hostname The hostname to resolve + /// @param[in] device The interface to send and receive packets on + /// @param[out] dnsResponseTimeMS When method returns successfully will contain the time it took to receive the + /// DNS response (in milli-seconds) + /// @param[out] dnsTTL When method returns successfully will contain The DNS TTL written in the DNS response + /// @param[in] dnsTimeout An optional parameter to specify the timeout to wait for a DNS response. If not + /// specified the default timeout is 5 sec + /// @param[in] dnsServerIP An optional parameter to specify the DNS server IP to send the DNS request to. If not + /// specified or specified with IPv4Address#Zero the DNS request will be sent to the default DNS server + /// configured in the system + /// @param[in] gatewayIP An optional parameter to specify the LAN gateway to send the DNS request through. If + /// not specified or specified with IPv4Address#Zero the interface's default gateway will be used + /// @return The resolved IPv4 address or IPv4Address#Zero if something went wrong (in this case an error will be + /// printed to log) IPv4Address getIPv4Address(const std::string& hostname, PcapLiveDevice* device, double& dnsResponseTimeMS, uint32_t& dnsTTL, int dnsTimeout = -1, IPv4Address dnsServerIP = IPv4Address::Zero, IPv4Address gatewayIP = IPv4Address::Zero) const; private: // private c'tor - NetworkUtils() - {} + NetworkUtils() = default; }; } // namespace pcpp diff --git a/Pcap++/header/PcapDevice.h b/Pcap++/header/PcapDevice.h index 6c5d2ac84c..08176196ef 100644 --- a/Pcap++/header/PcapDevice.h +++ b/Pcap++/header/PcapDevice.h @@ -9,10 +9,8 @@ struct pcap_pkthdr; /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { // Forward Declaration - required for IPcapDevice::matchPacketWithFilter @@ -20,22 +18,16 @@ namespace pcpp namespace internal { - /** - * @class PcapHandle - * @brief A wrapper class for pcap_t* which is the libpcap packet capture descriptor. - * This class is used to manage the lifecycle of the pcap_t* object - */ + /// @class PcapHandle + /// @brief A wrapper class for pcap_t* which is the libpcap packet capture descriptor. + /// This class is used to manage the lifecycle of the pcap_t* object class PcapHandle { public: - /** - * @brief Creates an empty handle. - */ + /// @brief Creates an empty handle. constexpr PcapHandle() noexcept = default; - /** - * @brief Creates a handle from the provided pcap descriptor. - * @param pcapDescriptor The pcap descriptor to wrap. - */ + /// @brief Creates a handle from the provided pcap descriptor. + /// @param pcapDescriptor The pcap descriptor to wrap. explicit PcapHandle(pcap_t* pcapDescriptor) noexcept; PcapHandle(const PcapHandle&) = delete; @@ -47,45 +39,33 @@ namespace pcpp ~PcapHandle(); - /** - * @return True if the handle is not null, false otherwise. - */ + /// @return True if the handle is not null, false otherwise. bool isValid() const noexcept { return m_PcapDescriptor != nullptr; } - /** - * @return The underlying pcap descriptor. - */ + /// @return The underlying pcap descriptor. pcap_t* get() const noexcept { return m_PcapDescriptor; } - /** - * @brief Releases ownership of the handle and returns the pcap descriptor. - * @return The pcap descriptor or nullptr if no handle is owned. - */ + /// @brief Releases ownership of the handle and returns the pcap descriptor. + /// @return The pcap descriptor or nullptr if no handle is owned. pcap_t* release() noexcept; - /** - * @brief Replaces the managed handle with the provided one. - * @param pcapDescriptor A new pcap descriptor to manage. - * @remarks If the handle contains a non-null descriptor it will be closed. - */ + /// @brief Replaces the managed handle with the provided one. + /// @param pcapDescriptor A new pcap descriptor to manage. + /// @remarks If the handle contains a non-null descriptor it will be closed. void reset(pcap_t* pcapDescriptor = nullptr) noexcept; - /** - * @brief Helper function to retrieve a view of the last error string for this handle. - * @return A null-terminated view of the last error string. - * @remarks The returned view is only valid until the next call to a pcap function. - */ + /// @brief Helper function to retrieve a view of the last error string for this handle. + /// @return A null-terminated view of the last error string. + /// @remarks The returned view is only valid until the next call to a pcap function. char const* getLastError() const noexcept; - /** - * @return True if the handle is not null, false otherwise. - */ + /// @return True if the handle is not null, false otherwise. explicit operator bool() const noexcept { return isValid(); @@ -105,11 +85,9 @@ namespace pcpp }; } // namespace internal - /** - * @class IPcapDevice - * An abstract class representing all libpcap-based packet capturing devices: files, libPcap, WinPcap/Npcap and - * RemoteCapture. This class is abstract and cannot be instantiated - */ + /// @class IPcapDevice + /// An abstract class representing all libpcap-based packet capturing devices: files, libPcap, WinPcap/Npcap and + /// RemoteCapture. This class is abstract and cannot be instantiated class IPcapDevice : public IDevice, public IFilterableDevice { protected: @@ -120,63 +98,50 @@ namespace pcpp {} public: - /** - * @struct PcapStats - * A container for pcap device statistics - */ + /// @struct PcapStats + /// A container for pcap device statistics struct PcapStats { - /** Number of packets received */ + /// Number of packets received uint64_t packetsRecv; - /** Number of packets dropped */ + /// Number of packets dropped uint64_t packetsDrop; - /** number of packets dropped by interface (not supported on all platforms) */ + /// number of packets dropped by interface (not supported on all platforms) uint64_t packetsDropByInterface; }; virtual ~IPcapDevice(); - /** - * Get statistics from the device - * @param[out] stats An object containing the stats - */ + /// Get statistics from the device + /// @param[out] stats An object containing the stats virtual void getStatistics(PcapStats& stats) const = 0; - /** - * A static method for retrieving pcap lib (libpcap/WinPcap/etc.) version information. This method is actually - * a wrapper for [pcap_lib_version()](https://www.tcpdump.org/manpages/pcap_lib_version.3pcap.html) - * @return A string containing the pcap lib version information - */ + /// A static method for retrieving pcap lib (libpcap/WinPcap/etc.) version information. This method is actually + /// a wrapper for [pcap_lib_version()](https://www.tcpdump.org/manpages/pcap_lib_version.3pcap.html) + /// @return A string containing the pcap lib version information static std::string getPcapLibVersionInfo(); - /** - * Match a raw packet with a given BPF filter. Notice this method is static which means you don't need any - * device instance in order to perform this match - * @param[in] filter A filter class to test against - * @param[in] rawPacket A pointer to the raw packet to match the filter with - * @return True if raw packet matches the filter or false otherwise - */ + /// Match a raw packet with a given BPF filter. Notice this method is static which means you don't need any + /// device instance in order to perform this match + /// @param[in] filter A filter class to test against + /// @param[in] rawPacket A pointer to the raw packet to match the filter with + /// @return True if raw packet matches the filter or false otherwise static bool matchPacketWithFilter(GeneralFilter& filter, RawPacket* rawPacket); // implement abstract methods using IFilterableDevice::setFilter; - /** - * Set a filter for the device. When implemented by the device, only packets that match the filter will be - * received. Please note that when the device is closed the filter is reset so when reopening the device you - * need to call this method again in order to reactivate the filter - * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax - * (http://biot.com/capstats/bpf.html) - * @return True if filter set successfully, false otherwise - */ + /// Set a filter for the device. When implemented by the device, only packets that match the filter will be + /// received. Please note that when the device is closed the filter is reset so when reopening the device you + /// need to call this method again in order to reactivate the filter + /// @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax + /// (http://biot.com/capstats/bpf.html) + /// @return True if filter set successfully, false otherwise virtual bool setFilter(std::string filterAsString); - /** - * Clear the filter currently set on device - * @return True if filter was removed successfully or if no filter was set, false otherwise - */ + /// Clear the filter currently set on device + /// @return True if filter was removed successfully or if no filter was set, false otherwise bool clearFilter(); }; - } // namespace pcpp diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index 89dd8c7b12..a6172d5792 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -10,17 +10,13 @@ typedef struct pcap_dumper pcap_dumper_t; /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /** - * @enum FileTimestampPrecision - * An enumeration representing the precision of timestamps in a pcap file. - * The precision can be Unknown, Micro, or Nano. - */ + /// @enum FileTimestampPrecision + /// An enumeration representing the precision of timestamps in a pcap file. + /// The precision can be Unknown, Micro, or Nano. enum class FileTimestampPrecision : int8_t { /// Precision is unknown or not set/determined @@ -31,10 +27,8 @@ namespace pcpp Nanoseconds = 1 }; - /** - * @class IFileDevice - * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for all file devices - */ + /// @class IFileDevice + /// An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for all file devices class IFileDevice : public IPcapDevice { protected: @@ -44,74 +38,56 @@ namespace pcpp virtual ~IFileDevice(); public: - /** - * @return The name of the file - */ + /// @return The name of the file std::string getFileName() const; // override methods - /** - * Close the file - */ + /// Close the file void close() override; }; - /** - * @class IFileReaderDevice - * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file reader devices - */ + /// @class IFileReaderDevice + /// An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file reader + /// devices class IFileReaderDevice : public IFileDevice { protected: uint32_t m_NumOfPacketsRead; uint32_t m_NumOfPacketsNotParsed; - /** - * A constructor for this class that gets the pcap full path file name to open. Notice that after calling this - * constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() - * @param[in] fileName The full path of the file to read - */ + /// A constructor for this class that gets the pcap full path file name to open. Notice that after calling this + /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() + /// @param[in] fileName The full path of the file to read IFileReaderDevice(const std::string& fileName); public: - /** - * A destructor for this class - */ - virtual ~IFileReaderDevice() - {} + /// A destructor for this class + virtual ~IFileReaderDevice() = default; - /** - * @return The file size in bytes - */ + /// @return The file size in bytes uint64_t getFileSize() const; virtual bool getNextPacket(RawPacket& rawPacket) = 0; - /** - * Read the next N packets into a raw packet vector - * @param[out] packetVec The raw packet vector to read packets into - * @param[in] numOfPacketsToRead Number of packets to read. If value <0 all remaining packets in the file will - * be read into the raw packet vector (this is the default value) - * @return The number of packets actually read - */ + /// Read the next N packets into a raw packet vector + /// @param[out] packetVec The raw packet vector to read packets into + /// @param[in] numOfPacketsToRead Number of packets to read. If value <0 all remaining packets in the file will + /// be read into the raw packet vector (this is the default value) + /// @return The number of packets actually read int getNextPackets(RawPacketVector& packetVec, int numOfPacketsToRead = -1); - /** - * A static method that creates an instance of the reader best fit to read the file. It decides by the file - * extension: for .pcapng files it returns an instance of PcapNgFileReaderDevice and for all other extensions it - * returns an instance of PcapFileReaderDevice - * @param[in] fileName The file name to open - * @return An instance of the reader to read the file. Notice you should free this instance when done using it - */ + /// A static method that creates an instance of the reader best fit to read the file. It decides by the file + /// extension: for .pcapng files it returns an instance of PcapNgFileReaderDevice and for all other extensions + /// it returns an instance of PcapFileReaderDevice + /// @param[in] fileName The file name to open + /// @return An instance of the reader to read the file. Notice you should free this instance when done using it static IFileReaderDevice* getReader(const std::string& fileName); }; - /** - * @class PcapFileReaderDevice - * A class for opening a pcap file in read-only mode. This class enable to open the file and read all packets, - * packet-by-packet - */ + /// @class PcapFileReaderDevice + /// A class for opening a pcap file in read-only mode. This class enable to open the file and read all packets, + /// packet-by-packet class PcapFileReaderDevice : public IFileReaderDevice { private: @@ -123,83 +99,62 @@ namespace pcpp PcapFileReaderDevice& operator=(const PcapFileReaderDevice& other); public: - /** - * A constructor for this class that gets the pcap full path file name to open. Notice that after calling this - * constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() - * @param[in] fileName The full path of the file to read - */ + /// A constructor for this class that gets the pcap full path file name to open. Notice that after calling this + /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() + /// @param[in] fileName The full path of the file to read PcapFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName), m_Precision(FileTimestampPrecision::Unknown), m_PcapLinkLayerType(LINKTYPE_ETHERNET) {} - /** - * A destructor for this class - */ - virtual ~PcapFileReaderDevice() - {} + /// A destructor for this class + virtual ~PcapFileReaderDevice() = default; - /** - * @return The link layer type of this file - */ + /// @return The link layer type of this file LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; } - /** - * @return The precision of the timestamps in the file. If the platform supports nanosecond precision, this - * method will return nanoseconds even if the file has microseconds since libpcap scales timestamps before - * supply. Otherwise, it will return microseconds. - */ + /// @return The precision of the timestamps in the file. If the platform supports nanosecond precision, this + /// method will return nanoseconds even if the file has microseconds since libpcap scales timestamps before + /// supply. Otherwise, it will return microseconds. FileTimestampPrecision getTimestampPrecision() const { return m_Precision; } - /** - * A static method that checks if nano-second precision is supported in the current platform and environment - * @return True if nano-second precision is supported, false otherwise - */ + /// A static method that checks if nano-second precision is supported in the current platform and environment + /// @return True if nano-second precision is supported, false otherwise static bool isNanoSecondPrecisionSupported(); // overridden methods - /** - * Read the next packet from the file. Before using this method please verify the file is opened using open() - * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written - * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an - * error log will be printed) or if reached end-of-file - */ + /// Read the next packet from the file. Before using this method please verify the file is opened using open() + /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written + /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an + /// error log will be printed) or if reached end-of-file bool getNextPacket(RawPacket& rawPacket); - /** - * Open the file name which path was specified in the constructor in a read-only mode - * @return True if file was opened successfully or if file is already opened. False if opening the file failed - * for some reason (for example: file path does not exist) - */ + /// Open the file name which path was specified in the constructor in a read-only mode + /// @return True if file was opened successfully or if file is already opened. False if opening the file failed + /// for some reason (for example: file path does not exist) bool open(); - /** - * Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The - * rest of the members will contain 0 - * @param[out] stats The stats struct where stats are returned - */ + /// Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The + /// rest of the members will contain 0 + /// @param[out] stats The stats struct where stats are returned void getStatistics(PcapStats& stats) const; }; - /** - * @class SnoopFileReaderDevice - * A class for opening a snoop file in read-only mode. This class enable to open the file and read all packets, - * packet-by-packet - */ + /// @class SnoopFileReaderDevice + /// A class for opening a snoop file in read-only mode. This class enable to open the file and read all packets, + /// packet-by-packet class SnoopFileReaderDevice : public IFileReaderDevice { private: #pragma pack(1) - /* - * File format header. - */ + /// File format header. typedef struct { uint64_t identification_pattern; @@ -207,17 +162,15 @@ namespace pcpp uint32_t datalink_type; } snoop_file_header_t; - /* - * Packet record header. - */ + /// Packet record header. typedef struct { - uint32_t original_length; /* original packet length */ - uint32_t included_length; /* saved packet length */ - uint32_t packet_record_length; /* total record length */ - uint32_t ndrops_cumulative; /* cumulative drops */ - uint32_t time_sec; /* timestamp */ - uint32_t time_usec; /* microsecond timestamp */ + uint32_t original_length; ///< original packet length + uint32_t included_length; ///< saved packet length + uint32_t packet_record_length; ///< total record length + uint32_t ndrops_cumulative; ///< cumulative drops + uint32_t time_sec; ///< timestamp + uint32_t time_usec; ///< microsecond timestamp } snoop_packet_header_t; #pragma pack() @@ -229,23 +182,17 @@ namespace pcpp SnoopFileReaderDevice& operator=(const PcapFileReaderDevice& other); public: - /** - * A constructor for this class that gets the snoop full path file name to open. Notice that after calling this - * constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() - * @param[in] fileName The full path of the file to read - */ + /// A constructor for this class that gets the snoop full path file name to open. Notice that after calling this + /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() + /// @param[in] fileName The full path of the file to read SnoopFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET) {} - /** - * A destructor for this class - */ + /// A destructor for this class virtual ~SnoopFileReaderDevice(); - /** - * @return The link layer type of this file - */ + /// @return The link layer type of this file LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; @@ -253,39 +200,29 @@ namespace pcpp // overridden methods - /** - * Read the next packet from the file. Before using this method please verify the file is opened using open() - * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written - * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an - * error log will be printed) or if reached end-of-file - */ + /// Read the next packet from the file. Before using this method please verify the file is opened using open() + /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written + /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an + /// error log will be printed) or if reached end-of-file bool getNextPacket(RawPacket& rawPacket); - /** - * Open the file name which path was specified in the constructor in a read-only mode - * @return True if file was opened successfully or if file is already opened. False if opening the file failed - * for some reason (for example: file path does not exist) - */ + /// Open the file name which path was specified in the constructor in a read-only mode + /// @return True if file was opened successfully or if file is already opened. False if opening the file failed + /// for some reason (for example: file path does not exist) bool open(); - /** - * Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The - * rest of the members will contain 0 - * @param[out] stats The stats struct where stats are returned - */ + /// Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The + /// rest of the members will contain 0 + /// @param[out] stats The stats struct where stats are returned void getStatistics(PcapStats& stats) const; - /** - * Close the snoop file - */ + /// Close the snoop file void close(); }; - /** - * @class PcapNgFileReaderDevice - * A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets, - * packet-by-packet - */ + /// @class PcapNgFileReaderDevice + /// A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets, + /// packet-by-packet class PcapNgFileReaderDevice : public IFileReaderDevice { private: @@ -297,105 +234,80 @@ namespace pcpp PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other); public: - /** - * A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling - * this constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() - * @param[in] fileName The full path of the file to read - */ + /// A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling + /// this constructor the file isn't opened yet, so reading packets will fail. For opening the file call open() + /// @param[in] fileName The full path of the file to read PcapNgFileReaderDevice(const std::string& fileName); - /** - * A destructor for this class - */ + /// A destructor for this class virtual ~PcapNgFileReaderDevice() { close(); } - /** - * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string - * specifying the operating system that was used for capturing the packets. This method reads this string from - * the metadata (if exists) and returns it - * @return The operating system string if exists, or an empty string otherwise - */ + /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string + /// specifying the operating system that was used for capturing the packets. This method reads this string from + /// the metadata (if exists) and returns it + /// @return The operating system string if exists, or an empty string otherwise std::string getOS() const; - /** - * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string - * specifying the hardware that was used for capturing the packets. This method reads this string from the - * metadata (if exists) and returns it - * @return The hardware string if exists, or an empty string otherwise - */ + /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string + /// specifying the hardware that was used for capturing the packets. This method reads this string from the + /// metadata (if exists) and returns it + /// @return The hardware string if exists, or an empty string otherwise std::string getHardware() const; - /** - * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string - * specifying the capture application that was used for capturing the packets. This method reads this string - * from the metadata (if exists) and returns it - * @return The capture application string if exists, or an empty string otherwise - */ + /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string + /// specifying the capture application that was used for capturing the packets. This method reads this string + /// from the metadata (if exists) and returns it + /// @return The capture application string if exists, or an empty string otherwise std::string getCaptureApplication() const; - /** - * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string - * containing a user-defined comment (can be any string). This method reads this string from the metadata (if - * exists) and returns it - * @return The comment written inside the file if exists, or an empty string otherwise - */ + /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string + /// containing a user-defined comment (can be any string). This method reads this string from the metadata (if + /// exists) and returns it + /// @return The comment written inside the file if exists, or an empty string otherwise std::string getCaptureFileComment() const; - /** - * The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file). - * This method reads the next packet and the comment attached to it (if such comment exists), and returns them - * both - * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written - * @param[out] packetComment The comment attached to the packet or an empty string if no comment exists - * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an - * error log will be printed) or if reached end-of-file - */ + /// The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file). + /// This method reads the next packet and the comment attached to it (if such comment exists), and returns them + /// both + /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written + /// @param[out] packetComment The comment attached to the packet or an empty string if no comment exists + /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an + /// error log will be printed) or if reached end-of-file bool getNextPacket(RawPacket& rawPacket, std::string& packetComment); // overridden methods - /** - * Read the next packet from the file. Before using this method please verify the file is opened using open() - * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written - * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an - * error log will be printed) or if reached end-of-file - */ + /// Read the next packet from the file. Before using this method please verify the file is opened using open() + /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written + /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an + /// error log will be printed) or if reached end-of-file bool getNextPacket(RawPacket& rawPacket); - /** - * Open the file name which path was specified in the constructor in a read-only mode - * @return True if file was opened successfully or if file is already opened. False if opening the file failed - * for some reason (for example: file path does not exist) - */ + /// Open the file name which path was specified in the constructor in a read-only mode + /// @return True if file was opened successfully or if file is already opened. False if opening the file failed + /// for some reason (for example: file path does not exist) bool open(); - /** - * Get statistics of packets read so far. - * @param[out] stats The stats struct where stats are returned - */ + /// Get statistics of packets read so far. + /// @param[out] stats The stats struct where stats are returned void getStatistics(PcapStats& stats) const; - /** - * Set a filter for PcapNG reader device. Only packets that match the filter will be received - * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax - * (http://biot.com/capstats/bpf.html) - * @return True if filter set successfully, false otherwise - */ + /// Set a filter for PcapNG reader device. Only packets that match the filter will be received + /// @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax + /// (http://biot.com/capstats/bpf.html) + /// @return True if filter set successfully, false otherwise bool setFilter(std::string filterAsString); - /** - * Close the pacp-ng file - */ + /// Close the pacp-ng file void close(); }; - /** - * @class IFileWriterDevice - * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer devices - */ + /// @class IFileWriterDevice + /// An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer + /// devices class IFileWriterDevice : public IFileDevice { protected: @@ -405,9 +317,7 @@ namespace pcpp IFileWriterDevice(const std::string& fileName); public: - /** - * A destructor for this class - */ + /// A destructor for this class virtual ~IFileWriterDevice() {} @@ -419,12 +329,10 @@ namespace pcpp virtual bool open(bool appendMode) = 0; }; - /** - * @class PcapFileWriterDevice - * A class for opening a pcap file for writing or create a new pcap file and write packets to it. This class adds - * a unique capability that isn't supported in WinPcap and in older libpcap versions which is to open a pcap file - * in append mode where packets are written at the end of the pcap file instead of running it over - */ + /// @class PcapFileWriterDevice + /// A class for opening a pcap file for writing or create a new pcap file and write packets to it. This class adds + /// a unique capability that isn't supported in WinPcap and in older libpcap versions which is to open a pcap file + /// in append mode where packets are written at the end of the pcap file instead of running it over class PcapFileWriterDevice : public IFileWriterDevice { private: @@ -441,107 +349,84 @@ namespace pcpp void closeFile(); public: - /** - * A constructor for this class that gets the pcap full path file name to open for writing or create. Notice - * that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the - * file call open() - * @param[in] fileName The full path of the file - * @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is - * Ethernet - * @param[in] nanosecondsPrecision A boolean indicating whether to write timestamps in nano-precision. If set to - * false, timestamps will be written in micro-precision - */ + /// A constructor for this class that gets the pcap full path file name to open for writing or create. Notice + /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the + /// file call open() + /// @param[in] fileName The full path of the file + /// @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is + /// Ethernet + /// @param[in] nanosecondsPrecision A boolean indicating whether to write timestamps in nano-precision. If set + /// to false, timestamps will be written in micro-precision PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET, bool nanosecondsPrecision = false); - /** - * A destructor for this class - */ + /// A destructor for this class ~PcapFileWriterDevice() { PcapFileWriterDevice::close(); } - /** - * Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This - * method won't change the written packet - * @param[in] packet A reference for an existing RawPcket to write to the file - * @return True if a packet was written successfully. False will be returned if the file isn't opened - * or if the packet link layer type is different than the one defined for the file - * (in all cases, an error will be printed to log) - */ + /// Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This + /// method won't change the written packet + /// @param[in] packet A reference for an existing RawPcket to write to the file + /// @return True if a packet was written successfully. False will be returned if the file isn't opened + /// or if the packet link layer type is different than the one defined for the file + /// (in all cases, an error will be printed to log) bool writePacket(RawPacket const& packet) override; - /** - * Write multiple RawPacket to the file. Before using this method please verify the file is opened using open(). - * This method won't change the written packets or the RawPacketVector instance - * @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file - * @return True if all packets were written successfully to the file. False will be returned if the file isn't - * opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to - * the file - */ + /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using + /// open(). This method won't change the written packets or the RawPacketVector instance + /// @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the + /// file + /// @return True if all packets were written successfully to the file. False will be returned if the file isn't + /// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to + /// the file bool writePackets(const RawPacketVector& packets) override; - /** - * @return The precision of the timestamps in the file. - */ + /// @return The precision of the timestamps in the file. FileTimestampPrecision getTimestampPrecision() const { return m_Precision; } - /** - * A static method that checks if nano-second precision is supported in the current platform and environment - * @return True if nano-second precision is supported, false otherwise - */ + /// A static method that checks if nano-second precision is supported in the current platform and environment + /// @return True if nano-second precision is supported, false otherwise static bool isNanoSecondPrecisionSupported(); // override methods - /** - * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be - * overwritten, meaning all its current content will be deleted - * @return True if file was opened/created successfully or if file is already opened. False if opening the file - * failed for some reason (an error will be printed to log) - */ + /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be + /// overwritten, meaning all its current content will be deleted + /// @return True if file was opened/created successfully or if file is already opened. False if opening the file + /// failed for some reason (an error will be printed to log) bool open() override; - /** - * Same as open(), but enables to open the file in append mode in which packets will be appended to the file - * instead of overwrite its current content. In append mode file must exist, otherwise opening will fail - * @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false - * this method will act exactly like open(). If set to true, file will be opened in append mode - * @return True of managed to open the file successfully. In case appendMode is set to true, false will be - * returned if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in - * c'tor is different from current file link type. In case appendMode is set to false, please refer to open() - * for return values - */ + /// Same as open(), but enables to open the file in append mode in which packets will be appended to the file + /// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail + /// @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false + /// this method will act exactly like open(). If set to true, file will be opened in append mode + /// @return True of managed to open the file successfully. In case appendMode is set to true, false will be + /// returned if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in + /// c'tor is different from current file link type. In case appendMode is set to false, please refer to open() + /// for return values bool open(bool appendMode) override; - /** - * Flush and close the pacp file - */ + /// Flush and close the pacp file void close() override; - /** - * Flush packets to disk. - */ + /// Flush packets to disk. void flush(); - /** - * Get statistics of packets written so far. - * @param[out] stats The stats struct where stats are returned - */ + /// Get statistics of packets written so far. + /// @param[out] stats The stats struct where stats are returned void getStatistics(PcapStats& stats) const override; }; - /** - * @class PcapNgFileWriterDevice - * A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This class - * adds unique capabilities such as writing metadata attributes into the file header, adding comments per packet and - * opening the file in append mode where packets are added to a file instead of overriding it. This capabilities are - * part of the pcap-ng standard but aren't supported in most tools and libraries - */ + /// @class PcapNgFileWriterDevice + /// A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This + /// class adds unique capabilities such as writing metadata attributes into the file header, adding comments per + /// packet and opening the file in append mode where packets are added to a file instead of overriding it. This + /// capabilities are part of the pcap-ng standard but aren't supported in most tools and libraries class PcapNgFileWriterDevice : public IFileWriterDevice { private: @@ -554,116 +439,93 @@ namespace pcpp PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other); public: - /** - * A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice - * that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the - * file call open() - * @param[in] fileName The full path of the file - * @param[in] compressionLevel The compression level to use when writing the file, use 0 to disable compression - * or 10 for max compression. Default is 0 - */ + /// A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice + /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the + /// file call open() + /// @param[in] fileName The full path of the file + /// @param[in] compressionLevel The compression level to use when writing the file, use 0 to disable compression + /// or 10 for max compression. Default is 0 PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel = 0); - /** - * A destructor for this class - */ + /// A destructor for this class virtual ~PcapNgFileWriterDevice() { close(); } - /** - * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be - * overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows - * writing several metadata attributes that will be stored in the header of the file - * @param[in] os A string describing the operating system that was used to capture the packets. If this string - * is empty or null it will be ignored - * @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is - * empty or null it will be ignored - * @param[in] captureApp A string describing the application that was used to capture the packets. If this - * string is empty or null it will be ignored - * @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the - * file. If this string is empty or null it will be ignored - * @return True if file was opened/created successfully or if file is already opened. False if opening the file - * failed for some reason (an error will be printed to log) - */ + /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be + /// overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows + /// writing several metadata attributes that will be stored in the header of the file + /// @param[in] os A string describing the operating system that was used to capture the packets. If this string + /// is empty or null it will be ignored + /// @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is + /// empty or null it will be ignored + /// @param[in] captureApp A string describing the application that was used to capture the packets. If this + /// string is empty or null it will be ignored + /// @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the + /// file. If this string is empty or null it will be ignored + /// @return True if file was opened/created successfully or if file is already opened. False if opening the file + /// failed for some reason (an error will be printed to log) bool open(const std::string& os, const std::string& hardware, const std::string& captureApp, const std::string& fileComment); - /** - * The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a - * RawPacket to the file and adds a comment to it. Before using this method please verify the file is opened - * using open(). This method won't change the written packet or the input comment - * @param[in] packet A reference for an existing RawPcket to write to the file - * @param[in] comment The comment to be written for the packet. If this string is empty or null it will be - * ignored - * @return True if a packet was written successfully. False will be returned if the file isn't opened (an error - * will be printed to log) - */ + /// The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a + /// RawPacket to the file and adds a comment to it. Before using this method please verify the file is opened + /// using open(). This method won't change the written packet or the input comment + /// @param[in] packet A reference for an existing RawPcket to write to the file + /// @param[in] comment The comment to be written for the packet. If this string is empty or null it will be + /// ignored + /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error + /// will be printed to log) bool writePacket(RawPacket const& packet, const std::string& comment); // overridden methods - /** - * Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This - * method won't change the written packet - * @param[in] packet A reference for an existing RawPcket to write to the file - * @return True if a packet was written successfully. False will be returned if the file isn't opened (an error - * will be printed to log) - */ + /// Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This + /// method won't change the written packet + /// @param[in] packet A reference for an existing RawPcket to write to the file + /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error + /// will be printed to log) bool writePacket(RawPacket const& packet); - /** - * Write multiple RawPacket to the file. Before using this method please verify the file is opened using open(). - * This method won't change the written packets or the RawPacketVector instance - * @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file - * @return True if all packets were written successfully to the file. False will be returned if the file isn't - * opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to - * the file - */ + /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using + /// open(). This method won't change the written packets or the RawPacketVector instance + /// @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the + /// file + /// @return True if all packets were written successfully to the file. False will be returned if the file isn't + /// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to + /// the file bool writePackets(const RawPacketVector& packets); - /** - * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be - * overwritten, meaning all its current content will be deleted - * @return True if file was opened/created successfully or if file is already opened. False if opening the file - * failed for some reason (an error will be printed to log) - */ + /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be + /// overwritten, meaning all its current content will be deleted + /// @return True if file was opened/created successfully or if file is already opened. False if opening the file + /// failed for some reason (an error will be printed to log) bool open(); - /** - * Same as open(), but enables to open the file in append mode in which packets will be appended to the file - * instead of overwrite its current content. In append mode file must exist, otherwise opening will fail - * @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false - * this method will act exactly like open(). If set to true, file will be opened in append mode - * @return True of managed to open the file successfully. In case appendMode is set to true, false will be - * returned if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to - * false, please refer to open() for return values - */ + /// Same as open(), but enables to open the file in append mode in which packets will be appended to the file + /// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail + /// @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false + /// this method will act exactly like open(). If set to true, file will be opened in append mode + /// @return True of managed to open the file successfully. In case appendMode is set to true, false will be + /// returned if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to + /// false, please refer to open() for return values bool open(bool appendMode); - /** - * Flush packets to the pcap-ng file - */ + /// Flush packets to the pcap-ng file void flush(); - /** - * Flush and close the pcap-ng file - */ + /// Flush and close the pcap-ng file void close(); - /** - * Get statistics of packets written so far. - * @param[out] stats The stats struct where stats are returned - */ + /// Get statistics of packets written so far. + /// @param[out] stats The stats struct where stats are returned void getStatistics(PcapStats& stats) const; - /** - * Set a filter for PcapNG writer device. Only packets that match the filter will be persisted - * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax - * (http://biot.com/capstats/bpf.html) - * @return True if filter set successfully, false otherwise - */ + /// Set a filter for PcapNG writer device. Only packets that match the filter will be persisted + /// @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax + /// (http://biot.com/capstats/bpf.html) + /// @return True if filter set successfully, false otherwise bool setFilter(std::string filterAsString); }; diff --git a/Pcap++/header/PcapFilter.h b/Pcap++/header/PcapFilter.h index 9e72ed8b7b..3f77392650 100644 --- a/Pcap++/header/PcapFilter.h +++ b/Pcap++/header/PcapFilter.h @@ -11,83 +11,71 @@ // Forward Declaration - used in GeneralFilter struct bpf_program; -/** - * @file - * Most packet capture engines contain packet filtering capabilities. In order to set the filters there should be a - * known syntax user can use. The most popular syntax is Berkeley Packet Filter (BPF) - see more in here: - * http://en.wikipedia.org/wiki/Berkeley_Packet_Filter. Detailed explanation of the syntax can be found here: - * http://www.tcpdump.org/manpages/pcap-filter.7.html. - * - * The problem with BPF is that, for my opinion, the syntax is too complicated and too poorly documented. In addition - * the BPF filter compilers may output syntax errors that are hard to understand. My experience with BPF was not good, - * so I decided to make the filters mechanism more structured, easier to understand and less error-prone by creating - * classes that represent filters. Each possible filter phrase is represented by a class. The filter, at the end, is - * that class. - * For example: the filter "src net 1.1.1.1" will be represented by IPFilter instance; "dst port 80" - * will be represented by PortFilter, and so on. - * So what about complex filters that involve "and", "or"? There are - * also 2 classes: AndFilter and OrFilter that can store more filters (in a composite idea) and connect them by "and" or - * "or". For example: "src host 1.1.1.1 and dst port 80" will be represented by an AndFilter that holds IPFilter and - * PortFilter inside it - */ - -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @file +/// Most packet capture engines contain packet filtering capabilities. In order to set the filters there should be a +/// known syntax user can use. The most popular syntax is Berkeley Packet Filter (BPF) - see more in here: +/// http://en.wikipedia.org/wiki/Berkeley_Packet_Filter. Detailed explanation of the syntax can be found here: +/// http://www.tcpdump.org/manpages/pcap-filter.7.html. +/// +/// The problem with BPF is that, for my opinion, the syntax is too complicated and too poorly documented. In addition +/// the BPF filter compilers may output syntax errors that are hard to understand. My experience with BPF was not good, +/// so I decided to make the filters mechanism more structured, easier to understand and less error-prone by creating +/// classes that represent filters. Each possible filter phrase is represented by a class. The filter, at the end, is +/// that class. +/// For example: the filter "src net 1.1.1.1" will be represented by IPFilter instance; "dst port 80" +/// will be represented by PortFilter, and so on. +/// So what about complex filters that involve "and", "or"? There are +/// also 2 classes: AndFilter and OrFilter that can store more filters (in a composite idea) and connect them by "and" +/// or "or". For example: "src host 1.1.1.1 and dst port 80" will be represented by an AndFilter that holds IPFilter and +/// PortFilter inside it + +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { // Forward Declaration - used in GeneralFilter class RawPacket; - /** - * An enum that contains direction (source or destination) - */ + /// An enum that contains direction (source or destination) typedef enum { - /** Source */ + /// Source SRC, - /** Destination */ + /// Destination DST, - /** Source or destination */ + /// Source or destination SRC_OR_DST } Direction; - /** - * Supported operators enum - */ + /// Supported operators enum typedef enum { - /** Equals */ + /// Equals EQUALS, - /** Not equals */ + /// Not equals NOT_EQUALS, - /** Greater than */ + /// Greater than GREATER_THAN, - /** Greater or equal */ + /// Greater or equal GREATER_OR_EQUAL, - /** Less than */ + /// Less than LESS_THAN, - /** Less or equal */ + /// Less or equal LESS_OR_EQUAL } FilterOperator; namespace internal { - /** - * @class BpfProgramDeleter - * A deleter that cleans up a bpf_program object. - */ + /// @class BpfProgramDeleter + /// A deleter that cleans up a bpf_program object. struct BpfProgramDeleter { void operator()(bpf_program* ptr) const; }; } // namespace internal - /** - * @class BpfFilterWrapper - * A wrapper class for BPF filtering. Enables setting a BPF filter and matching it against a packet - */ + /// @class BpfFilterWrapper + /// A wrapper class for BPF filtering. Enables setting a BPF filter and matching it against a packet class BpfFilterWrapper { private: @@ -98,98 +86,75 @@ namespace pcpp void freeProgram(); public: - /** - * A c'tor for this class - */ + /// A c'tor for this class BpfFilterWrapper(); - /** - * A copy constructor for this class. - * @param[in] other The instance to copy from - */ + /// A copy constructor for this class. + /// @param[in] other The instance to copy from BpfFilterWrapper(const BpfFilterWrapper& other); - /** - * A copy assignment operator for this class. - * @param[in] other An instance of IPNetwork to assign - * @return A reference to the assignee - */ + /// A copy assignment operator for this class. + /// @param[in] other An instance of IPNetwork to assign + /// @return A reference to the assignee BpfFilterWrapper& operator=(const BpfFilterWrapper& other); - /** - * Set a filter. This method receives a filter in BPF syntax (https://biot.com/capstats/bpf.html) and an - * optional link type, compiles them, and if compilation is successful it stores the filter. - * @param[in] filter A filter in BPF syntax - * @param[in] linkType An optional parameter to set the filter's link type. The default is LINKTYPE_ETHERNET - * @return True if compilation is successful and filter is stored in side this object, false otherwise - */ + /// Set a filter. This method receives a filter in BPF syntax (https://biot.com/capstats/bpf.html) and an + /// optional link type, compiles them, and if compilation is successful it stores the filter. + /// @param[in] filter A filter in BPF syntax + /// @param[in] linkType An optional parameter to set the filter's link type. The default is LINKTYPE_ETHERNET + /// @return True if compilation is successful and filter is stored in side this object, false otherwise bool setFilter(const std::string& filter, LinkLayerType linkType = LINKTYPE_ETHERNET); - /** - * Match a packet with the filter stored in this object. If the filter is empty the method returns "true". - * If the link type of the raw packet is different than the one set in setFilter(), the filter will be - * re-compiled and stored in the object. - * @param[in] rawPacket A pointer to a raw packet which the filter will be matched against - * @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter - * could not be compiled - */ + /// Match a packet with the filter stored in this object. If the filter is empty the method returns "true". + /// If the link type of the raw packet is different than the one set in setFilter(), the filter will be + /// re-compiled and stored in the object. + /// @param[in] rawPacket A pointer to a raw packet which the filter will be matched against + /// @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter + /// could not be compiled bool matchPacketWithFilter(const RawPacket* rawPacket); - /** - * Match a packet data with the filter stored in this object. If the filter is empty the method returns "true". - * If the link type provided is different than the one set in setFilter(), the filter will be re-compiled - * and stored in the object. - * @param[in] packetData A byte stream containing the packet data - * @param[in] packetDataLength The length in [bytes] of the byte stream - * @param[in] packetTimestamp The packet timestamp - * @param[in] linkType The packet link type - * @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter - * could not be compiled - */ + /// Match a packet data with the filter stored in this object. If the filter is empty the method returns "true". + /// If the link type provided is different than the one set in setFilter(), the filter will be re-compiled + /// and stored in the object. + /// @param[in] packetData A byte stream containing the packet data + /// @param[in] packetDataLength The length in [bytes] of the byte stream + /// @param[in] packetTimestamp The packet timestamp + /// @param[in] linkType The packet link type + /// @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter + /// could not be compiled bool matchPacketWithFilter(const uint8_t* packetData, uint32_t packetDataLength, timespec packetTimestamp, uint16_t linkType); }; - /** - * @class GeneralFilter - * The base class for all filter classes. This class is virtual and abstract, hence cannot be instantiated. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class GeneralFilter + /// The base class for all filter classes. This class is virtual and abstract, hence cannot be instantiated. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class GeneralFilter { protected: BpfFilterWrapper m_BpfWrapper; public: - /** - * A method that parses the class instance into BPF string format - * @param[out] result An empty string that the parsing will be written into. If the string isn't empty, its - * content will be overridden - */ + /// A method that parses the class instance into BPF string format + /// @param[out] result An empty string that the parsing will be written into. If the string isn't empty, its + /// content will be overridden virtual void parseToString(std::string& result) = 0; - /** - * Match a raw packet with a given BPF filter. - * @param[in] rawPacket A pointer to the raw packet to match the BPF filter with - * @return True if a raw packet matches the BPF filter or false otherwise - */ + /// Match a raw packet with a given BPF filter. + /// @param[in] rawPacket A pointer to the raw packet to match the BPF filter with + /// @return True if a raw packet matches the BPF filter or false otherwise bool matchPacketWithFilter(RawPacket* rawPacket); GeneralFilter() {} - /** - * Virtual destructor, frees the bpf program - */ - virtual ~GeneralFilter() - {} + /// Virtual destructor, frees the bpf program + virtual ~GeneralFilter() = default; }; - /** - * @class BPFStringFilter - * This class can be loaded with a BPF filter string and then can be used to verify the string is valid. - */ + /// @class BPFStringFilter + /// This class can be loaded with a BPF filter string and then can be used to verify the string is valid. class BPFStringFilter : public GeneralFilter { private: @@ -202,27 +167,21 @@ namespace pcpp virtual ~BPFStringFilter() {} - /** - * A method that parses the class instance into BPF string format - * @param[out] result An empty string that the parsing will be written into. If the string isn't empty, its - * content will be overridden If the filter is not valid the result will be an empty string - */ + /// A method that parses the class instance into BPF string format + /// @param[out] result An empty string that the parsing will be written into. If the string isn't empty, its + /// content will be overridden If the filter is not valid the result will be an empty string void parseToString(std::string& result) override; - /** - * Verify the filter is valid - * @return True if the filter is valid or false otherwise - */ + /// Verify the filter is valid + /// @return True if the filter is valid or false otherwise bool verifyFilter(); }; - /** - * @class IFilterWithDirection - * An abstract class that is the base class for all filters which contain a direction (source or destination). This - * class cannot be instantiated - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class IFilterWithDirection + /// An abstract class that is the base class for all filters which contain a direction (source or destination). This + /// class cannot be instantiated + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class IFilterWithDirection : public GeneralFilter { private: @@ -240,23 +199,19 @@ namespace pcpp } public: - /** - * Set the direction for the filter (source or destination) - * @param[in] dir The direction - */ + /// Set the direction for the filter (source or destination) + /// @param[in] dir The direction void setDirection(Direction dir) { m_Dir = dir; } }; - /** - * @class IFilterWithOperator - * An abstract class that is the base class for all filters which contain an operator (e.g X equals Y; A is greater - * than B; Z1 not equals Z2, etc.). This class cannot be instantiated - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class IFilterWithOperator + /// An abstract class that is the base class for all filters which contain an operator (e.g X equals Y; A is greater + /// than B; Z1 not equals Z2, etc.). This class cannot be instantiated + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class IFilterWithOperator : public GeneralFilter { private: @@ -274,22 +229,18 @@ namespace pcpp } public: - /** - * Set the operator for the filter - * @param[in] op The operator to set - */ + /// Set the operator for the filter + /// @param[in] op The operator to set void setOperator(FilterOperator op) { m_Operator = op; } }; - /** - * @class IPFilter - * A class for representing IPv4 or IPv6 address filter, equivalent to "net src x.x.x.x" or "net dst x.x.x.x" - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class IPFilter + /// A class for representing IPv4 or IPv6 address filter, equivalent to "net src x.x.x.x" or "net dst x.x.x.x" + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class IPFilter : public IFilterWithDirection { private: @@ -297,124 +248,105 @@ namespace pcpp IPNetwork m_Network; public: - /** - * The basic constructor that creates the filter from an IP address string and direction (source or destination) - * @param[in] ipAddress The IP address to build the filter with. - * @param[in] dir The address direction to filter (source or destination) - * @throws std::invalid_argument The provided address is not a valid IPv4 or IPv6 address. - */ + /// The basic constructor that creates the filter from an IP address string and direction (source or + /// destination) + /// @param[in] ipAddress The IP address to build the filter with. + /// @param[in] dir The address direction to filter (source or destination) + /// @throws std::invalid_argument The provided address is not a valid IPv4 or IPv6 address. IPFilter(const std::string& ipAddress, Direction dir) : IPFilter(IPAddress(ipAddress), dir) {} - /** - * The basic constructor that creates the filter from an IP address and direction (source or destination) - * @param[in] ipAddress The IP address to build the filter with. - * @param[in] dir The address direction to filter (source or destination) - */ + /// The basic constructor that creates the filter from an IP address and direction (source or destination) + /// @param[in] ipAddress The IP address to build the filter with. + /// @param[in] dir The address direction to filter (source or destination) IPFilter(const IPAddress& ipAddress, Direction dir) : IFilterWithDirection(dir), m_Address(ipAddress), m_Network(ipAddress) {} - /** - * A constructor that enable to filter only part of the address by using a mask (aka subnet). For example: - * "filter only IP addresses that matches the subnet 10.0.0.x" - * @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be matched. - * For example: if the address is "1.2.3.4" and the mask is "255.255.255.0" than the part of the address that - * will be matched is "1.2.3.X". - * @param[in] dir The address direction to filter (source or destination) - * @param[in] netmask The mask to use. The mask should be a valid IP address in either IPv4 dotted-decimal - * format (e.g., 255.255.255.0) or IPv6 colon-separated hexadecimal format (e.g., FFFF:FFFF:FFFF:FFFF::). - * @throws std::invalid_argument The provided address is not a valid IP address or the provided netmask string - * is invalid.. - */ + /// A constructor that enable to filter only part of the address by using a mask (aka subnet). For example: + /// "filter only IP addresses that matches the subnet 10.0.0.x" + /// @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be matched. + /// For example: if the address is "1.2.3.4" and the mask is "255.255.255.0" than the part of the address that + /// will be matched is "1.2.3.X". + /// @param[in] dir The address direction to filter (source or destination) + /// @param[in] netmask The mask to use. The mask should be a valid IP address in either IPv4 dotted-decimal + /// format (e.g., 255.255.255.0) or IPv6 colon-separated hexadecimal format (e.g., FFFF:FFFF:FFFF:FFFF::). + /// @throws std::invalid_argument The provided address is not a valid IP address or the provided netmask string + /// is invalid.. IPFilter(const std::string& ipAddress, Direction dir, const std::string& netmask) : IPFilter(IPv4Address(ipAddress), dir, netmask) {} - /** - * A constructor that enable to filter only part of the address by using a mask (aka subnet). For example: - * "filter only IP addresses that matches the subnet 10.0.0.x" - * @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be - * matched. For example: if the address is "1.2.3.4" and the mask is "255.255.255.0" than the part of the - * address that will be matched is "1.2.3.X". - * @param[in] dir The address direction to filter (source or destination) - * @param[in] netmask The mask to use. The mask should be a valid IP address in either IPv4 dotted-decimal - * format (e.g., 255.255.255.0) or IPv6 colon-separated hexadecimal format (e.g., FFFF:FFFF:FFFF:FFFF::). - * @throws std::invalid_argument The provided netmask string is invalid. - */ + /// A constructor that enable to filter only part of the address by using a mask (aka subnet). For example: + /// "filter only IP addresses that matches the subnet 10.0.0.x" + /// @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be + /// matched. For example: if the address is "1.2.3.4" and the mask is "255.255.255.0" than the part of the + /// address that will be matched is "1.2.3.X". + /// @param[in] dir The address direction to filter (source or destination) + /// @param[in] netmask The mask to use. The mask should be a valid IP address in either IPv4 dotted-decimal + /// format (e.g., 255.255.255.0) or IPv6 colon-separated hexadecimal format (e.g., FFFF:FFFF:FFFF:FFFF::). + /// @throws std::invalid_argument The provided netmask string is invalid. IPFilter(const IPAddress& ipAddress, Direction dir, const std::string& netmask) : IFilterWithDirection(dir), m_Address(ipAddress), m_Network(ipAddress, netmask) {} - /** - * A constructor that enables to filter by a subnet. For example: "filter only IP addresses that matches the - * subnet 10.0.0.3/24" which means the part of the address that will be matched is "10.0.0.X" - * @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be matched. - * For example: if the address is "1.2.3.4" and the subnet is "/24" than the part of the address that will be - * matched is "1.2.3.X". - * @param[in] dir The address direction to filter (source or destination) - * @param[in] len The subnet to use (e.g "/24"). Acceptable subnet values are [0, 32] for IPv4 and [0, 128] for - * IPv6. - * @throws std::invalid_argument The provided address is not a valid IPv4 or IPv6 address or the provided length - * is out of acceptable range. - */ + /// A constructor that enables to filter by a subnet. For example: "filter only IP addresses that matches the + /// subnet 10.0.0.3/24" which means the part of the address that will be matched is "10.0.0.X" + /// @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be matched. + /// For example: if the address is "1.2.3.4" and the subnet is "/24" than the part of the address that will be + /// matched is "1.2.3.X". + /// @param[in] dir The address direction to filter (source or destination) + /// @param[in] len The subnet to use (e.g "/24"). Acceptable subnet values are [0, 32] for IPv4 and [0, 128] for + /// IPv6. + /// @throws std::invalid_argument The provided address is not a valid IPv4 or IPv6 address or the provided + /// length is out of acceptable range. IPFilter(const std::string& ipAddress, Direction dir, int len) : IPFilter(IPAddress(ipAddress), dir, len) {} - /** - * A constructor that enables to filter by a subnet. For example: "filter only IP addresses that matches the - * subnet 10.0.0.3/24" which means the part of the address that will be matched is "10.0.0.X" - * @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be matched. - * For example: if the address is "1.2.3.4" and the subnet is "/24" than the part of the address that will be - * matched is "1.2.3.X". - * @param[in] dir The address direction to filter (source or destination) - * @param[in] len The subnet to use (e.g "/24"). Acceptable subnet values are [0, 32] for IPv4 and [0, 128] for - * IPv6. - * @throws std::invalid_argument The provided length is out of acceptable range. - */ + /// A constructor that enables to filter by a subnet. For example: "filter only IP addresses that matches the + /// subnet 10.0.0.3/24" which means the part of the address that will be matched is "10.0.0.X" + /// @param[in] ipAddress The IP address to use. Only the part of the address that is not masked will be matched. + /// For example: if the address is "1.2.3.4" and the subnet is "/24" than the part of the address that will be + /// matched is "1.2.3.X". + /// @param[in] dir The address direction to filter (source or destination) + /// @param[in] len The subnet to use (e.g "/24"). Acceptable subnet values are [0, 32] for IPv4 and [0, 128] for + /// IPv6. + /// @throws std::invalid_argument The provided length is out of acceptable range. IPFilter(const IPAddress& ipAddress, Direction dir, int len) : IFilterWithDirection(dir), m_Address(ipAddress), m_Network(ipAddress, len) {} - /** - * A constructor that enables to filter by a predefined network object. - * @param[in] network The network to use when filtering. IP address and subnet mask are taken from the network - * object. - * @param[in] dir The address direction to filter (source or destination) - */ + /// A constructor that enables to filter by a predefined network object. + /// @param[in] network The network to use when filtering. IP address and subnet mask are taken from the network + /// object. + /// @param[in] dir The address direction to filter (source or destination) IPFilter(const IPNetwork& network, Direction dir) : IFilterWithDirection(dir), m_Address(network.getNetworkPrefix()), m_Network(network) {} void parseToString(std::string& result) override; - /** - * Set the network to build the filter with. - * @param[in] network The IP Network object to be used when building the filter. - */ + /// Set the network to build the filter with. + /// @param[in] network The IP Network object to be used when building the filter. void setNetwork(const IPNetwork& network) { m_Network = network; m_Address = m_Network.getNetworkPrefix(); } - /** - * Set the IP address - * @param[in] ipAddress The IP address to build the filter with. - * @throws std::invalid_argument The provided string does not represent a valid IP address. - */ + /// Set the IP address + /// @param[in] ipAddress The IP address to build the filter with. + /// @throws std::invalid_argument The provided string does not represent a valid IP address. void setAddr(const std::string& ipAddress) { this->setAddr(IPAddress(ipAddress)); } - /** - * Set the IP address - * @param[in] ipAddress The IP address to build the filter with. - * @remarks Alternating between IPv4 and IPv6 can have unintended consequences on the subnet mask. - * Setting an IPv4 address when the prefix length is over 32 make the new prefix length 32. - * Setting an IPv6 address will keep the current IPv4 prefix mask length. - */ + /// Set the IP address + /// @param[in] ipAddress The IP address to build the filter with. + /// @remarks Alternating between IPv4 and IPv6 can have unintended consequences on the subnet mask. + /// Setting an IPv4 address when the prefix length is over 32 make the new prefix length 32. + /// Setting an IPv6 address will keep the current IPv4 prefix mask length. void setAddr(const IPAddress& ipAddress) { m_Address = ipAddress; @@ -427,122 +359,100 @@ namespace pcpp m_Network = IPNetwork(m_Address, newPrefixLen); } - /** - * Set the subnet mask - * @param[in] netmask The mask to use. The mask should match the IP version and be in a valid format. - * Valid formats: - * IPv4 - (X.X.X.X) - 'X' - a number in the range of 0 and 255 (inclusive)): - * IPv6 - (YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY) - 'Y' - a hexadecimal digit [0 - 9, A - F]. Short form - * IPv6 formats are allowed. - * @throws std::invalid_argument The provided netmask is invalid or does not correspond to the current IP - * address version. - */ + /// Set the subnet mask + /// @param[in] netmask The mask to use. The mask should match the IP version and be in a valid format. + /// Valid formats: + /// IPv4 - (X.X.X.X) - 'X' - a number in the range of 0 and 255 (inclusive)): + /// IPv6 - (YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY:YYYY) - 'Y' - a hexadecimal digit [0 - 9, A - F]. Short form + /// IPv6 formats are allowed. + /// @throws std::invalid_argument The provided netmask is invalid or does not correspond to the current IP + /// address version. void setMask(const std::string& netmask) { m_Network = IPNetwork(m_Address, netmask); } - /** - * Clears the subnet mask. - */ + /// Clears the subnet mask. void clearMask() { this->clearLen(); } - /** - * Set the subnet (IPv4) or prefix length (IPv6). - * Acceptable subnet values are [0, 32] for IPv4 and [0, 128] for IPv6. - * @param[in] len The subnet to use (e.g "/24") - * @throws std::invalid_argument The provided length is out of acceptable range. - */ + /// Set the subnet (IPv4) or prefix length (IPv6). + /// Acceptable subnet values are [0, 32] for IPv4 and [0, 128] for IPv6. + /// @param[in] len The subnet to use (e.g "/24") + /// @throws std::invalid_argument The provided length is out of acceptable range. void setLen(const int len) { m_Network = IPNetwork(m_Address, len); } - /** - * Clears the subnet mask length. - */ + /// Clears the subnet mask length. void clearLen() { m_Network = IPNetwork(m_Address); } }; - /** - * @class IPv4IDFilter - * A class for filtering IPv4 traffic by IP ID field of the IPv4 protocol, for example: - * "filter only IPv4 traffic which IP ID is greater than 1234" - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class IPv4IDFilter + /// A class for filtering IPv4 traffic by IP ID field of the IPv4 protocol, for example: + /// "filter only IPv4 traffic which IP ID is greater than 1234" + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class IPv4IDFilter : public IFilterWithOperator { private: uint16_t m_IpID; public: - /** - * A constructor that gets the IP ID to filter and the operator and creates the filter out of them - * @param[in] ipID The IP ID to filter - * @param[in] op The operator to use (e.g "equal", "greater than", etc.) - */ + /// A constructor that gets the IP ID to filter and the operator and creates the filter out of them + /// @param[in] ipID The IP ID to filter + /// @param[in] op The operator to use (e.g "equal", "greater than", etc.) IPv4IDFilter(uint16_t ipID, FilterOperator op) : IFilterWithOperator(op), m_IpID(ipID) {} void parseToString(std::string& result) override; - /** - * Set the IP ID to filter - * @param[in] ipID The IP ID to filter - */ + /// Set the IP ID to filter + /// @param[in] ipID The IP ID to filter void setIpID(uint16_t ipID) { m_IpID = ipID; } }; - /** - * @class IPv4TotalLengthFilter - * A class for filtering IPv4 traffic by "total length" field of the IPv4 protocol, for example: - * "filter only IPv4 traffic which "total length" value is less than 60B" - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class IPv4TotalLengthFilter + /// A class for filtering IPv4 traffic by "total length" field of the IPv4 protocol, for example: + /// "filter only IPv4 traffic which "total length" value is less than 60B" + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class IPv4TotalLengthFilter : public IFilterWithOperator { private: uint16_t m_TotalLength; public: - /** - * A constructor that gets the total length to filter and the operator and creates the filter out of them - * @param[in] totalLength The total length value to filter - * @param[in] op The operator to use (e.g "equal", "greater than", etc.) - */ + /// A constructor that gets the total length to filter and the operator and creates the filter out of them + /// @param[in] totalLength The total length value to filter + /// @param[in] op The operator to use (e.g "equal", "greater than", etc.) IPv4TotalLengthFilter(uint16_t totalLength, FilterOperator op) : IFilterWithOperator(op), m_TotalLength(totalLength) {} void parseToString(std::string& result) override; - /** - * Set the total length value - * @param[in] totalLength The total length value to filter - */ + /// Set the total length value + /// @param[in] totalLength The total length value to filter void setTotalLength(uint16_t totalLength) { m_TotalLength = totalLength; } }; - /** - * @class PortFilter - * A class for filtering TCP or UDP traffic by port, for example: "dst port 80" or "src port 12345". - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class PortFilter + /// A class for filtering TCP or UDP traffic by port, for example: "dst port 80" or "src port 12345". + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class PortFilter : public IFilterWithDirection { private: @@ -550,33 +460,27 @@ namespace pcpp void portToString(uint16_t portAsInt); public: - /** - * A constructor that gets the port and the direction and creates the filter - * @param[in] port The port to create the filter with - * @param[in] dir The port direction to filter (source or destination) - */ + /// A constructor that gets the port and the direction and creates the filter + /// @param[in] port The port to create the filter with + /// @param[in] dir The port direction to filter (source or destination) PortFilter(uint16_t port, Direction dir); void parseToString(std::string& result) override; - /** - * Set the port - * @param[in] port The port to create the filter with - */ + /// Set the port + /// @param[in] port The port to create the filter with void setPort(uint16_t port) { portToString(port); } }; - /** - * @class PortRangeFilter - * A class for filtering TCP or UDP port ranges, meaning match only packets which port is within this range, for - * example: "src portrange 1000-2000" will match only TCP or UDP traffic which source port is in the range of 1000 - - * 2000 - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class PortRangeFilter + /// A class for filtering TCP or UDP port ranges, meaning match only packets which port is within this range, for + /// example: "src portrange 1000-2000" will match only TCP or UDP traffic which source port is in the range of 1000 + /// - 2000 + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class PortRangeFilter : public IFilterWithDirection { private: @@ -584,175 +488,140 @@ namespace pcpp uint16_t m_ToPort; public: - /** - * A constructor that gets the port range the the direction and creates the filter with them - * @param[in] fromPort The lower end of the port range - * @param[in] toPort The higher end of the port range - * @param[in] dir The port range direction to filter (source or destination) - */ + /// A constructor that gets the port range the the direction and creates the filter with them + /// @param[in] fromPort The lower end of the port range + /// @param[in] toPort The higher end of the port range + /// @param[in] dir The port range direction to filter (source or destination) PortRangeFilter(uint16_t fromPort, uint16_t toPort, Direction dir) : IFilterWithDirection(dir), m_FromPort(fromPort), m_ToPort(toPort) {} void parseToString(std::string& result) override; - /** - * Set the lower end of the port range - * @param[in] fromPort The lower end of the port range - */ + /// Set the lower end of the port range + /// @param[in] fromPort The lower end of the port range void setFromPort(uint16_t fromPort) { m_FromPort = fromPort; } - /** - * Set the higher end of the port range - * @param[in] toPort The higher end of the port range - */ + /// Set the higher end of the port range + /// @param[in] toPort The higher end of the port range void setToPort(uint16_t toPort) { m_ToPort = toPort; } }; - /** - * @class MacAddressFilter - * A class for filtering Ethernet traffic by MAC addresses, for example: "ether src 12:34:56:78:90:12" or "ether dst - * 10:29:38:47:56:10:29" - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class MacAddressFilter + /// A class for filtering Ethernet traffic by MAC addresses, for example: "ether src 12:34:56:78:90:12" or "ether + /// dst 10:29:38:47:56:10:29" + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class MacAddressFilter : public IFilterWithDirection { private: MacAddress m_MacAddress; public: - /** - * A constructor that gets the MAC address and the direction and creates the filter with them - * @param[in] address The MAC address to use for filtering - * @param[in] dir The MAC address direction to filter (source or destination) - */ + /// A constructor that gets the MAC address and the direction and creates the filter with them + /// @param[in] address The MAC address to use for filtering + /// @param[in] dir The MAC address direction to filter (source or destination) MacAddressFilter(MacAddress address, Direction dir) : IFilterWithDirection(dir), m_MacAddress(address) {} void parseToString(std::string& result) override; - /** - * Set the MAC address - * @param[in] address The MAC address to use for filtering - */ + /// Set the MAC address + /// @param[in] address The MAC address to use for filtering void setMacAddress(MacAddress address) { m_MacAddress = address; } }; - /** - * @class EtherTypeFilter - * A class for filtering by EtherType field of the Ethernet protocol. This enables to filter packets from certain - * protocols, such as ARP, IPv4, IPv6, VLAN tags, etc. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class EtherTypeFilter + /// A class for filtering by EtherType field of the Ethernet protocol. This enables to filter packets from certain + /// protocols, such as ARP, IPv4, IPv6, VLAN tags, etc. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class EtherTypeFilter : public GeneralFilter { private: uint16_t m_EtherType; public: - /** - * A constructor that gets the EtherType and creates the filter with it - * @param[in] etherType The EtherType value to create the filter with - */ + /// A constructor that gets the EtherType and creates the filter with it + /// @param[in] etherType The EtherType value to create the filter with explicit EtherTypeFilter(uint16_t etherType) : m_EtherType(etherType) {} void parseToString(std::string& result) override; - /** - * Set the EtherType value - * @param[in] etherType The EtherType value to create the filter with - */ + /// Set the EtherType value + /// @param[in] etherType The EtherType value to create the filter with void setEtherType(uint16_t etherType) { m_EtherType = etherType; } }; - /** - * @class CompositeFilter - * The base class for all filter classes composed of several other filters. This class is virtual and abstract, - * hence cannot be instantiated. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class CompositeFilter + /// The base class for all filter classes composed of several other filters. This class is virtual and abstract, + /// hence cannot be instantiated. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class CompositeFilter : public GeneralFilter { protected: std::vector m_FilterList; public: - /** - * An empty constructor for this class. Use addFilter() to add filters to the composite filter. - */ + /// An empty constructor for this class. Use addFilter() to add filters to the composite filter. CompositeFilter() = default; - /** - * A constructor that gets a list of pointers to filters and creates one filter from all filters - * @param[in] filters The list of pointers to filters - */ + /// A constructor that gets a list of pointers to filters and creates one filter from all filters + /// @param[in] filters The list of pointers to filters explicit CompositeFilter(const std::vector& filters); - /** - * Add filter to the composite filter - * @param[in] filter The filter to add - */ + /// Add filter to the composite filter + /// @param[in] filter The filter to add void addFilter(GeneralFilter* filter) { m_FilterList.push_back(filter); } - /** - * Removes the first matching filter from the composite filter - * @param[in] filter The filter to remove - */ + /// Removes the first matching filter from the composite filter + /// @param[in] filter The filter to remove void removeFilter(GeneralFilter* filter); - /** - * Remove the current filters and set new ones - * @param[in] filters The new filters to set. The previous ones will be removed - */ + /// Remove the current filters and set new ones + /// @param[in] filters The new filters to set. The previous ones will be removed void setFilters(const std::vector& filters); - /** - * Remove all filters from the composite filter. - */ + /// Remove all filters from the composite filter. void clearAllFilters() { m_FilterList.clear(); } }; - /** - * Supported composite logic filter operators enum - */ + /// Supported composite logic filter operators enum enum class CompositeLogicFilterOp { - /** Logical AND operation */ + /// Logical AND operation AND, - /** Logical OR operation */ + /// Logical OR operation OR, }; namespace internal { - /* Could potentially be moved into CompositeLogicFilter as a private member function, with if constexpr when - * C++17 is the minimum supported standard.*/ - /** - * Returns the delimiter for joining filter strings for the composite logic filter operation. - * @return A string literal to place between the different filter strings to produce a composite expression. - */ + // Could potentially be moved into CompositeLogicFilter as a private member function, with if constexpr when + // C++17 is the minimum supported standard. + + /// Returns the delimiter for joining filter strings for the composite logic filter operation. + /// @return A string literal to place between the different filter strings to produce a composite expression. template constexpr const char* getCompositeLogicOpDelimiter() = delete; template <> constexpr const char* getCompositeLogicOpDelimiter() { @@ -764,12 +633,10 @@ namespace pcpp }; } // namespace internal - /** - * @class CompositeLogicFilter - * A class for connecting several filters into one filter with logical operation between them. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class CompositeLogicFilter + /// A class for connecting several filters into one filter with logical operation between them. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h template class CompositeLogicFilter : public CompositeFilter { public: @@ -791,44 +658,36 @@ namespace pcpp } }; - /** - * A class for connecting several filters into one filter with logical "and" between them. For example: if the 2 - * filters are: "IPv4 address = x.x.x.x" + "TCP port dst = 80", then the new filter will be: "IPv4 address = x.x.x.x - * _AND_ TCP port dst = 80" - * - * This class follows the composite design pattern. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// A class for connecting several filters into one filter with logical "and" between them. For example: if the 2 + /// filters are: "IPv4 address = x.x.x.x" + "TCP port dst = 80", then the new filter will be: "IPv4 address = + /// x.x.x.x _AND_ TCP port dst = 80" + /// + /// This class follows the composite design pattern. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h using AndFilter = CompositeLogicFilter; - /** - * A class for connecting several filters into one filter with logical "or" between them. For example: if the 2 - * filters are: "IPv4 address = x.x.x.x" + "TCP port dst = 80", then the new filter will be: "IPv4 address = x.x.x.x - * _OR_ TCP port dst = 80" - * - * This class follows the composite design pattern. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// A class for connecting several filters into one filter with logical "or" between them. For example: if the 2 + /// filters are: "IPv4 address = x.x.x.x" + "TCP port dst = 80", then the new filter will be: "IPv4 address = + /// x.x.x.x _OR_ TCP port dst = 80" + /// + /// This class follows the composite design pattern. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h using OrFilter = CompositeLogicFilter; - /** - * @class NotFilter - * A class for creating a filter which is inverse to another filter - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class NotFilter + /// A class for creating a filter which is inverse to another filter + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class NotFilter : public GeneralFilter { private: GeneralFilter* m_FilterToInverse; public: - /** - * A constructor that gets a pointer to a filter and create the inverse version of it - * @param[in] filterToInverse A pointer to filter which the created filter be the inverse of - */ + /// A constructor that gets a pointer to a filter and create the inverse version of it + /// @param[in] filterToInverse A pointer to filter which the created filter be the inverse of explicit NotFilter(GeneralFilter* filterToInverse) { m_FilterToInverse = filterToInverse; @@ -836,174 +695,144 @@ namespace pcpp void parseToString(std::string& result) override; - /** - * Set a filter to create an inverse filter from - * @param[in] filterToInverse A pointer to filter which the created filter be the inverse of - */ + /// Set a filter to create an inverse filter from + /// @param[in] filterToInverse A pointer to filter which the created filter be the inverse of void setFilter(GeneralFilter* filterToInverse) { m_FilterToInverse = filterToInverse; } }; - /** - * @class ProtoFilter - * A class for filtering traffic by protocol. Notice not all protocols are supported, only the following protocol - * are supported: - * ::TCP, ::UDP, ::ICMP, ::VLAN, ::IPv4, ::IPv6, ::ARP, ::Ethernet. - * In addition, the following protocol families are supported: ::GRE (distinguish between ::GREv0 and ::GREv1 is not - * supported), - * ::IGMP (distinguish between ::IGMPv1, ::IGMPv2 and ::IGMPv3 is not supported). - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class ProtoFilter + /// A class for filtering traffic by protocol. Notice not all protocols are supported, only the following protocol + /// are supported: + /// ::TCP, ::UDP, ::ICMP, ::VLAN, ::IPv4, ::IPv6, ::ARP, ::Ethernet. + /// In addition, the following protocol families are supported: ::GRE (distinguish between ::GREv0 and ::GREv1 is + /// not supported), + /// ::IGMP (distinguish between ::IGMPv1, ::IGMPv2 and ::IGMPv3 is not supported). + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class ProtoFilter : public GeneralFilter { private: ProtocolTypeFamily m_ProtoFamily; public: - /** - * A constructor that gets a protocol and creates the filter - * @param[in] proto The protocol to filter, only packets matching this protocol will be received. Please note - * not all protocols are supported. List of supported protocols is found in the class description - */ + /// A constructor that gets a protocol and creates the filter + /// @param[in] proto The protocol to filter, only packets matching this protocol will be received. Please note + /// not all protocols are supported. List of supported protocols is found in the class description explicit ProtoFilter(ProtocolType proto) : m_ProtoFamily(proto) {} - /** - * A constructor that gets a protocol family and creates the filter - * @param[in] protoFamily The protocol family to filter, only packets matching this protocol will be received. - * Please note not all protocols are supported. List of supported protocols is found in the class description - */ + /// A constructor that gets a protocol family and creates the filter + /// @param[in] protoFamily The protocol family to filter, only packets matching this protocol will be received. + /// Please note not all protocols are supported. List of supported protocols is found in the class description explicit ProtoFilter(ProtocolTypeFamily protoFamily) : m_ProtoFamily(protoFamily) {} void parseToString(std::string& result) override; - /** - * Set the protocol to filter with - * @param[in] proto The protocol to filter, only packets matching this protocol will be received. Please note - * not all protocol families are supported. List of supported protocols is found in the class description - */ + /// Set the protocol to filter with + /// @param[in] proto The protocol to filter, only packets matching this protocol will be received. Please note + /// not all protocol families are supported. List of supported protocols is found in the class description void setProto(ProtocolType proto) { m_ProtoFamily = proto; } - /** - * Set the protocol family to filter with - * @param[in] protoFamily The protocol family to filter, only packets matching this protocol will be received. - * Please note not all protocol families are supported. List of supported protocols is found in the class - * description - */ + /// Set the protocol family to filter with + /// @param[in] protoFamily The protocol family to filter, only packets matching this protocol will be received. + /// Please note not all protocol families are supported. List of supported protocols is found in the class + /// description void setProto(ProtocolTypeFamily protoFamily) { m_ProtoFamily = protoFamily; } }; - /** - * @class ArpFilter - * A class for filtering ARP packets according the ARP opcode. When using this filter only ARP packets with the - * relevant opcode will be received - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class ArpFilter + /// A class for filtering ARP packets according the ARP opcode. When using this filter only ARP packets with the + /// relevant opcode will be received + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class ArpFilter : public GeneralFilter { private: ArpOpcode m_OpCode; public: - /** - * A constructor that get the ARP opcode and creates the filter - * @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY - */ + /// A constructor that get the ARP opcode and creates the filter + /// @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY explicit ArpFilter(ArpOpcode opCode) : m_OpCode(opCode) {} void parseToString(std::string& result) override; - /** - * Set the ARP opcode - * @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY - */ + /// Set the ARP opcode + /// @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY void setOpCode(ArpOpcode opCode) { m_OpCode = opCode; } }; - /** - * @class VlanFilter - * A class for filtering VLAN tagged packets by VLAN ID. When using this filter only packets tagged with VLAN which - * has the specific VLAN ID will be received - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class VlanFilter + /// A class for filtering VLAN tagged packets by VLAN ID. When using this filter only packets tagged with VLAN which + /// has the specific VLAN ID will be received + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class VlanFilter : public GeneralFilter { private: uint16_t m_VlanID; public: - /** - * A constructor the gets the VLAN ID and creates the filter - * @param[in] vlanId The VLAN ID to use for the filter - */ + /// A constructor the gets the VLAN ID and creates the filter + /// @param[in] vlanId The VLAN ID to use for the filter explicit VlanFilter(uint16_t vlanId) : m_VlanID(vlanId) {} void parseToString(std::string& result) override; - /** - * Set the VLAN ID of the filter - * @param[in] vlanId The VLAN ID to use for the filter - */ + /// Set the VLAN ID of the filter + /// @param[in] vlanId The VLAN ID to use for the filter void setVlanID(uint16_t vlanId) { m_VlanID = vlanId; } }; - /** - * @class TcpFlagsFilter - * A class for filtering only TCP packets which certain TCP flags are set in them - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class TcpFlagsFilter + /// A class for filtering only TCP packets which certain TCP flags are set in them + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class TcpFlagsFilter : public GeneralFilter { public: - /** - * An enum of all TCP flags that can be use in the filter - */ + /// An enum of all TCP flags that can be use in the filter enum TcpFlags { - /** TCP FIN flag */ + /// TCP FIN flag tcpFin = 1, - /** TCP SYN flag */ + /// TCP SYN flag tcpSyn = 2, - /** TCP RST flag */ + /// TCP RST flag tcpRst = 4, - /** TCP PSH flag */ + /// TCP PSH flag tcpPush = 8, - /** TCP ACK flag */ + /// TCP ACK flag tcpAck = 16, - /** TCP URG flag */ + /// TCP URG flag tcpUrg = 32 }; - /** - * An enum for representing 2 type of matches: match only packets that contain all flags defined in the filter - * or match packets that contain at least one of the flags defined in the filter - */ + /// An enum for representing 2 type of matches: match only packets that contain all flags defined in the filter + /// or match packets that contain at least one of the flags defined in the filter enum MatchOptions { - /** Match only packets that contain all flags defined in the filter */ + /// Match only packets that contain all flags defined in the filter MatchAll, - /** Match packets that contain at least one of the flags defined in the filter */ + /// Match packets that contain at least one of the flags defined in the filter MatchOneAtLeast }; @@ -1012,25 +841,21 @@ namespace pcpp MatchOptions m_MatchOption; public: - /** - * A constructor that gets a 1-byte bitmask containing all TCP flags participating in the filter and the match - * option, and creates the filter - * @param[in] tcpFlagBitMask A 1-byte bitmask containing all TCP flags participating in the filter. This - * parameter can contain the following value for example: TcpFlagsFilter::tcpSyn | TcpFlagsFilter::tcpAck | - * TcpFlagsFilter::tcpUrg - * @param[in] matchOption The match option: TcpFlagsFilter::MatchAll or TcpFlagsFilter::MatchOneAtLeast - */ + /// A constructor that gets a 1-byte bitmask containing all TCP flags participating in the filter and the match + /// option, and creates the filter + /// @param[in] tcpFlagBitMask A 1-byte bitmask containing all TCP flags participating in the filter. This + /// parameter can contain the following value for example: TcpFlagsFilter::tcpSyn | TcpFlagsFilter::tcpAck | + /// TcpFlagsFilter::tcpUrg + /// @param[in] matchOption The match option: TcpFlagsFilter::MatchAll or TcpFlagsFilter::MatchOneAtLeast TcpFlagsFilter(uint8_t tcpFlagBitMask, MatchOptions matchOption) : m_TcpFlagsBitMask(tcpFlagBitMask), m_MatchOption(matchOption) {} - /** - * Set the TCP flags and the match option - * @param[in] tcpFlagBitMask A 1-byte bitmask containing all TCP flags participating in the filter. This - * parameter can contain the following value for example: TcpFlagsFilter::tcpSyn | TcpFlagsFilter::tcpAck | - * TcpFlagsFilter::tcpUrg - * @param[in] matchOption The match option: TcpFlagsFilter::MatchAll or TcpFlagsFilter::MatchOneAtLeast - */ + /// Set the TCP flags and the match option + /// @param[in] tcpFlagBitMask A 1-byte bitmask containing all TCP flags participating in the filter. This + /// parameter can contain the following value for example: TcpFlagsFilter::tcpSyn | TcpFlagsFilter::tcpAck | + /// TcpFlagsFilter::tcpUrg + /// @param[in] matchOption The match option: TcpFlagsFilter::MatchAll or TcpFlagsFilter::MatchOneAtLeast void setTcpFlagsBitMask(uint8_t tcpFlagBitMask, MatchOptions matchOption) { m_TcpFlagsBitMask = tcpFlagBitMask; @@ -1040,70 +865,57 @@ namespace pcpp void parseToString(std::string& result) override; }; - /** - * @class TcpWindowSizeFilter - * A class for filtering TCP packets that matches TCP window-size criteria. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class TcpWindowSizeFilter + /// A class for filtering TCP packets that matches TCP window-size criteria. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class TcpWindowSizeFilter : public IFilterWithOperator { private: uint16_t m_WindowSize; public: - /** - * A constructor that get the window-size and operator and creates the filter. For example: "filter all TCP - * packets with window-size less than 1000" - * @param[in] windowSize The window-size value that will be used in the filter - * @param[in] op The operator to use (e.g "equal", "greater than", etc.) - */ + /// A constructor that get the window-size and operator and creates the filter. For example: "filter all TCP + /// packets with window-size less than 1000" + /// @param[in] windowSize The window-size value that will be used in the filter + /// @param[in] op The operator to use (e.g "equal", "greater than", etc.) TcpWindowSizeFilter(uint16_t windowSize, FilterOperator op) : IFilterWithOperator(op), m_WindowSize(windowSize) {} void parseToString(std::string& result) override; - /** - * Set window-size value - * @param[in] windowSize The window-size value that will be used in the filter - */ + /// Set window-size value + /// @param[in] windowSize The window-size value that will be used in the filter void setWindowSize(uint16_t windowSize) { m_WindowSize = windowSize; } }; - /** - * @class UdpLengthFilter - * A class for filtering UDP packets that matches UDP length criteria. - * - * For deeper understanding of the filter concept please refer to PcapFilter.h - */ + /// @class UdpLengthFilter + /// A class for filtering UDP packets that matches UDP length criteria. + /// + /// For deeper understanding of the filter concept please refer to PcapFilter.h class UdpLengthFilter : public IFilterWithOperator { private: uint16_t m_Length; public: - /** - * A constructor that get the UDP length and operator and creates the filter. For example: "filter all UDP - * packets with length greater or equal to 500" - * @param[in] length The length value that will be used in the filter - * @param[in] op The operator to use (e.g "equal", "greater than", etc.) - */ + /// A constructor that get the UDP length and operator and creates the filter. For example: "filter all UDP + /// packets with length greater or equal to 500" + /// @param[in] length The length value that will be used in the filter + /// @param[in] op The operator to use (e.g "equal", "greater than", etc.) UdpLengthFilter(uint16_t length, FilterOperator op) : IFilterWithOperator(op), m_Length(length) {} void parseToString(std::string& result) override; - /** - * Set length value - * @param[in] length The length value that will be used in the filter - */ + /// Set length value + /// @param[in] length The length value that will be used in the filter void setLength(uint16_t length) { m_Length = length; } }; - } // namespace pcpp diff --git a/Pcap++/header/PcapLiveDevice.h b/Pcap++/header/PcapLiveDevice.h index e37e27d7cd..8af8ee067c 100644 --- a/Pcap++/header/PcapLiveDevice.h +++ b/Pcap++/header/PcapLiveDevice.h @@ -18,63 +18,52 @@ typedef struct pcap_addr pcap_addr_t; /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - class PcapLiveDevice; - /** - * A callback that is called when a packet is captured by PcapLiveDevice - * @param[in] packet A pointer to the raw packet - * @param[in] device A pointer to the PcapLiveDevice instance - * @param[in] userCookie A pointer to the object put by the user when packet capturing stared - */ + /// A callback that is called when a packet is captured by PcapLiveDevice + /// @param[in] packet A pointer to the raw packet + /// @param[in] device A pointer to the PcapLiveDevice instance + /// @param[in] userCookie A pointer to the object put by the user when packet capturing stared using OnPacketArrivesCallback = std::function; - /** - * A callback that is called when a packet is captured by PcapLiveDevice - * @param[in] packet A pointer to the raw packet - * @param[in] device A pointer to the PcapLiveDevice instance - * @param[in] userCookie A pointer to the object put by the user when packet capturing stared - * @return True when main thread should stop blocking or false otherwise - */ + /// A callback that is called when a packet is captured by PcapLiveDevice + /// @param[in] packet A pointer to the raw packet + /// @param[in] device A pointer to the PcapLiveDevice instance + /// @param[in] userCookie A pointer to the object put by the user when packet capturing stared + /// @return True when main thread should stop blocking or false otherwise using OnPacketArrivesStopBlocking = std::function; - /** - * A callback that is called periodically for stats collection if user asked to start packet capturing with periodic - * stats collection - * @param[in] stats A reference to the most updated stats - * @param[in] userCookie A pointer to the object put by the user when packet capturing stared - */ + /// A callback that is called periodically for stats collection if user asked to start packet capturing with + /// periodic stats collection + /// @param[in] stats A reference to the most updated stats + /// @param[in] userCookie A pointer to the object put by the user when packet capturing stared using OnStatsUpdateCallback = std::function; - /** - * @class PcapLiveDevice - * A class that wraps a network interface (each of the interfaces listed in ifconfig/ipconfig). - * This class wraps the libpcap capabilities of capturing packets from the network, filtering packets and sending - * packets back to the network. This class is relevant for Linux applications only. On Windows the WinPcapLiveDevice - * (which inherits this class) is used. Both classes are almost similar in capabilities, the main difference between - * them is adapting some capabilities to the specific OS. This class cannot be instantiated by the user (it has a - * private constructor), as network interfaces aren't dynamic. Instances of this class (one instance per network - * interface) are created by PcapLiveDeviceList singleton on application startup and the user can get access to them - * by using PcapLiveDeviceList public methods such as PcapLiveDeviceList#getPcapLiveDeviceByIp()
Main - * capabilities of this class: - * - Get all available information for this network interfaces such as name, IP addresses, MAC address, MTU, etc. - * This information is taken from both libpcap and the OS - * - Capture packets from the network. Capturing is always conducted on a different thread. PcapPlusPlus creates - * this thread when capturing starts and kills it when capturing ends. This prevents the application from being - * stuck while waiting for packets or processing them. Currently only one capturing thread is allowed, so when the - * interface is in capture mode, no further capturing is allowed. In addition to capturing the user can get stats - * on packets that were received by the application, dropped by the NIC (due to full NIC buffers), etc. Stats - * collection can be initiated by the user by calling getStatistics() or be pushed to the user periodically by - * supplying a callback and a timeout to startCapture() - * - Send packets back to the network. Sending the packets is done on the caller thread. No additional threads are - * created for this task - */ + /// @class PcapLiveDevice + /// A class that wraps a network interface (each of the interfaces listed in ifconfig/ipconfig). + /// This class wraps the libpcap capabilities of capturing packets from the network, filtering packets and sending + /// packets back to the network. This class is relevant for Linux applications only. On Windows the + /// WinPcapLiveDevice (which inherits this class) is used. Both classes are almost similar in capabilities, the main + /// difference between them is adapting some capabilities to the specific OS. This class cannot be instantiated by + /// the user (it has a private constructor), as network interfaces aren't dynamic. Instances of this class (one + /// instance per network interface) are created by PcapLiveDeviceList singleton on application startup and the user + /// can get access to them by using PcapLiveDeviceList public methods such as + /// PcapLiveDeviceList#getPcapLiveDeviceByIp()
Main capabilities of this class: + /// - Get all available information for this network interfaces such as name, IP addresses, MAC address, MTU, etc. + /// This information is taken from both libpcap and the OS + /// - Capture packets from the network. Capturing is always conducted on a different thread. PcapPlusPlus creates + /// this thread when capturing starts and kills it when capturing ends. This prevents the application from being + /// stuck while waiting for packets or processing them. Currently only one capturing thread is allowed, so when + /// the interface is in capture mode, no further capturing is allowed. In addition to capturing the user can get + /// stats on packets that were received by the application, dropped by the NIC (due to full NIC buffers), etc. + /// Stats collection can be initiated by the user by calling getStatistics() or be pushed to the user periodically + /// by supplying a callback and a timeout to startCapture() + /// - Send packets back to the network. Sending the packets is done on the caller thread. No additional threads are + /// created for this task class PcapLiveDevice : public IPcapDevice { friend class PcapLiveDeviceList; @@ -148,111 +137,93 @@ namespace pcpp static void onPacketArrivesBlockingMode(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet); public: - /** - * The type of the live device - */ + /// The type of the live device enum LiveDeviceType { - /** libPcap live device */ + /// libPcap live device LibPcapDevice, - /** WinPcap/Npcap live device */ + /// WinPcap/Npcap live device WinPcapDevice, - /** WinPcap/Npcap Remote Capture device */ + /// WinPcap/Npcap Remote Capture device RemoteDevice }; - /** - * Device capturing mode - */ + /// Device capturing mode enum DeviceMode { - /** Only packets that their destination is this NIC are captured */ + /// Only packets that their destination is this NIC are captured Normal = 0, - /** All packets that arrive to the NIC are captured, even packets that their destination isn't this NIC */ + /// All packets that arrive to the NIC are captured, even packets that their destination isn't this NIC Promiscuous = 1 }; - /** - * Set direction for capturing packets (you can read more here: - * ) - */ + /// Set direction for capturing packets (you can read more here: + /// ) enum PcapDirection { - /** Capture traffics both incoming and outgoing */ + /// Capture traffics both incoming and outgoing PCPP_INOUT = 0, - /** Only capture incoming traffics */ + /// Only capture incoming traffics PCPP_IN, - /** Only capture outgoing traffics */ + /// Only capture outgoing traffics PCPP_OUT }; - /** - * @struct DeviceConfiguration - * A struct that contains user configurable parameters for opening a device. All parameters have default values - * so the user isn't expected to set all parameters or understand exactly how they work - */ + /// @struct DeviceConfiguration + /// A struct that contains user configurable parameters for opening a device. All parameters have default values + /// so the user isn't expected to set all parameters or understand exactly how they work struct DeviceConfiguration { - /** Indicates whether to open the device in promiscuous or normal mode */ + /// Indicates whether to open the device in promiscuous or normal mode DeviceMode mode; - /** Set the packet buffer timeout in milliseconds. You can read more here: - * https://www.tcpdump.org/manpages/pcap.3pcap.html . - * Any value above 0 is considered legal, otherwise a value of 1 or -1 is used (depends on the platform) - */ + /// Set the packet buffer timeout in milliseconds. You can read more here: + /// https://www.tcpdump.org/manpages/pcap.3pcap.html . + /// Any value above 0 is considered legal, otherwise a value of 1 or -1 is used (depends on the platform) int packetBufferTimeoutMs; - /** - * Set the packet buffer size. You can read more about the packet buffer here: - * https://www.tcpdump.org/manpages/pcap.3pcap.html . - * Any value of 100 or above is considered valid, otherwise the default value is used (which varies between - * different OS's). However, please notice that setting values which are too low or two high may result in - * failure to open the device. These too low or too high thresholds may vary between OS's, as an example - * please refer to this thread: https://stackoverflow.com/questions/11397367/issue-in-pcap-set-buffer-size - */ + /// Set the packet buffer size. You can read more about the packet buffer here: + /// https://www.tcpdump.org/manpages/pcap.3pcap.html . + /// Any value of 100 or above is considered valid, otherwise the default value is used (which varies between + /// different OS's). However, please notice that setting values which are too low or two high may result in + /// failure to open the device. These too low or too high thresholds may vary between OS's, as an example + /// please refer to this thread: https://stackoverflow.com/questions/11397367/issue-in-pcap-set-buffer-size int packetBufferSize; - /** - * Set the direction for capturing packets. You can read more here: - * . - */ + /// Set the direction for capturing packets. You can read more here: + /// . PcapDirection direction; - /** - * Set the snapshot length. Snapshot length is the amount of data for each frame that is actually captured. - * Note that taking larger snapshots both increases the amount of time it takes to process packets and, - * effectively, decreases the amount of packet buffering. This may cause packets to be lost. Note also that - * taking smaller snapshots will discard data from protocols above the transport layer, which loses - * information that may be important. You can read more here: https://wiki.wireshark.org/SnapLen - */ + /// Set the snapshot length. Snapshot length is the amount of data for each frame that is actually captured. + /// Note that taking larger snapshots both increases the amount of time it takes to process packets and, + /// effectively, decreases the amount of packet buffering. This may cause packets to be lost. Note also that + /// taking smaller snapshots will discard data from protocols above the transport layer, which loses + /// information that may be important. You can read more here: https://wiki.wireshark.org/SnapLen int snapshotLength; - /** - * Set NFLOG group. Which NFLOG group to be listened to when connecting to NFLOG device. If device is not of - * type NFLOG this attribute is ignored. - */ + /// Set NFLOG group. Which NFLOG group to be listened to when connecting to NFLOG device. If device is not + /// of type NFLOG this attribute is ignored. unsigned int nflogGroup; /// In Unix-like system, use poll() for blocking mode. bool usePoll; - /** - * A c'tor for this struct - * @param[in] mode The mode to open the device: promiscuous or non-promiscuous. Default value is promiscuous - * @param[in] packetBufferTimeoutMs Buffer timeout in millisecond. Default value is 0 which means set - * timeout of 1 or -1 (depends on the platform) - * @param[in] packetBufferSize The packet buffer size. Default value is 0 which means use the default value - * (varies between different OS's) - * @param[in] direction Direction for capturing packets. Default value is INOUT which means capture both - * incoming and outgoing packets (not all platforms support this) - * @param[in] snapshotLength Snapshot length for capturing packets. Default value is 0 which means use the - * default value. A snapshot length of 262144 should be big enough for maximum-size Linux loopback packets - * (65549) and some USB packets captured with USBPcap (> 131072, < 262144). A snapshot length of 65535 - * should be sufficient, on most if not all networks, to capture all the data available from the packet. - * @param[in] nflogGroup NFLOG group for NFLOG devices. Default value is 0. - * @param[in] usePoll use `poll()` when capturing packets in blocking more (`startCaptureBlockingMode()`) on - * Unix-like system. Default value is false. - */ + /// A c'tor for this struct + /// @param[in] mode The mode to open the device: promiscuous or non-promiscuous. Default value is + /// promiscuous + /// @param[in] packetBufferTimeoutMs Buffer timeout in millisecond. Default value is 0 which means set + /// timeout of 1 or -1 (depends on the platform) + /// @param[in] packetBufferSize The packet buffer size. Default value is 0 which means use the default value + /// (varies between different OS's) + /// @param[in] direction Direction for capturing packets. Default value is INOUT which means capture both + /// incoming and outgoing packets (not all platforms support this) + /// @param[in] snapshotLength Snapshot length for capturing packets. Default value is 0 which means use the + /// default value. A snapshot length of 262144 should be big enough for maximum-size Linux loopback packets + /// (65549) and some USB packets captured with USBPcap (> 131072, < 262144). A snapshot length of 65535 + /// should be sufficient, on most if not all networks, to capture all the data available from the packet. + /// @param[in] nflogGroup NFLOG group for NFLOG devices. Default value is 0. + /// @param[in] usePoll use `poll()` when capturing packets in blocking more (`startCaptureBlockingMode()`) + /// on Unix-like system. Default value is false. explicit DeviceConfiguration(DeviceMode mode = Promiscuous, int packetBufferTimeoutMs = 0, int packetBufferSize = 0, PcapDirection direction = PCPP_INOUT, int snapshotLength = 0, unsigned int nflogGroup = 0, bool usePoll = false) @@ -269,380 +240,319 @@ namespace pcpp PcapLiveDevice(const PcapLiveDevice& other) = delete; PcapLiveDevice& operator=(const PcapLiveDevice& other) = delete; - /** - * A destructor for this class - */ + /// A destructor for this class ~PcapLiveDevice() override; - /** - * @return The type of the device (libPcap, WinPcap/Npcap or a remote device) - */ + /// @return The type of the device (libPcap, WinPcap/Npcap or a remote device) virtual LiveDeviceType getDeviceType() const { return LibPcapDevice; } - /** - * @return The name of the device (e.g eth0), taken from pcap_if_t->name - */ + /// @return The name of the device (e.g eth0), taken from pcap_if_t->name std::string getName() const { return m_InterfaceDetails.name; } - /** - * @return A human-readable description of the device, taken from pcap_if_t->description. May be empty string in - * some interfaces - */ + /// @return A human-readable description of the device, taken from pcap_if_t->description. May be empty string + /// in some interfaces std::string getDesc() const { return m_InterfaceDetails.description; } - /** - * @return True if this interface is a loopback interface, false otherwise - */ + /// @return True if this interface is a loopback interface, false otherwise bool getLoopback() const { return m_InterfaceDetails.isLoopback; } - /** - * @return The device's maximum transmission unit (MTU) in bytes - */ + /// @return The device's maximum transmission unit (MTU) in bytes virtual uint32_t getMtu() const { return m_DeviceMtu; } - /** - * @return The device's link layer type - */ + /// @return The device's link layer type virtual LinkLayerType getLinkType() const { return m_LinkType; } - /** - * @return A vector containing all IP addresses defined for this interface. - */ + /// @return A vector containing all IP addresses defined for this interface. std::vector getIPAddresses() const { return m_InterfaceDetails.addresses; } - /** - * @return The MAC address for this interface - */ + /// @return The MAC address for this interface virtual MacAddress getMacAddress() const { return m_MacAddress; } - /** - * @return The IPv4 address for this interface. If multiple IPv4 addresses are defined for this interface, the - * first will be picked. If no IPv4 addresses are defined, a zeroed IPv4 address (IPv4Address#Zero) will be - * returned - */ + /// @return The IPv4 address for this interface. If multiple IPv4 addresses are defined for this interface, the + /// first will be picked. If no IPv4 addresses are defined, a zeroed IPv4 address (IPv4Address#Zero) will be + /// returned IPv4Address getIPv4Address() const; - /** - * @return The IPv6 address for this interface. If multiple IPv6 addresses are defined for this interface, the - * first will be picked. If no IPv6 addresses are defined, a zeroed IPv6 address (IPv6Address#Zero) will be - * returned - */ + /// @return The IPv6 address for this interface. If multiple IPv6 addresses are defined for this interface, the + /// first will be picked. If no IPv6 addresses are defined, a zeroed IPv6 address (IPv6Address#Zero) will be + /// returned IPv6Address getIPv6Address() const; - /** - * @return The default gateway defined for this interface. If no default gateway is defined, if it's not IPv4 or - * if couldn't extract default gateway IPv4Address#Zero will be returned. If multiple gateways were defined the - * first one will be returned - */ + /// @return The default gateway defined for this interface. If no default gateway is defined, if it's not IPv4 + /// or if couldn't extract default gateway IPv4Address#Zero will be returned. If multiple gateways were defined + /// the first one will be returned IPv4Address getDefaultGateway() const; - /** - * @return A list of all DNS servers defined for this machine. If this list is empty it means no DNS servers - * were defined or they couldn't be extracted from some reason. This list is created in PcapLiveDeviceList class - * and can be also retrieved from there. This method exists for convenience - so it'll be possible to get this - * list from PcapLiveDevice as well - */ + /// @return A list of all DNS servers defined for this machine. If this list is empty it means no DNS servers + /// were defined or they couldn't be extracted from some reason. This list is created in PcapLiveDeviceList + /// class and can be also retrieved from there. This method exists for convenience - so it'll be possible to get + /// this list from PcapLiveDevice as well const std::vector& getDnsServers() const; - /** - * Start capturing packets on this network interface (device). Each time a packet is captured the - * onPacketArrives callback is called. The capture is done on a new thread created by this method, meaning all - * callback calls are done in a thread other than the caller thread. Capture process will stop and this capture - * thread will be terminated when calling stopCapture(). This method must be called after the device is opened - * (i.e the open() method was called), otherwise an error will be returned. - * @param[in] onPacketArrives A callback that is called each time a packet is captured - * @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to - * the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects that - * give context to the capture callback, for example: objects that counts packets, manages flow state or manages - * the application state according to the packet that was captured - * @return True if capture started successfully, false if (relevant log error is printed in any case): - * - Capture is already running - * - Device is not opened - * - Capture thread could not be created - */ + /// Start capturing packets on this network interface (device). Each time a packet is captured the + /// onPacketArrives callback is called. The capture is done on a new thread created by this method, meaning all + /// callback calls are done in a thread other than the caller thread. Capture process will stop and this capture + /// thread will be terminated when calling stopCapture(). This method must be called after the device is opened + /// (i.e the open() method was called), otherwise an error will be returned. + /// @param[in] onPacketArrives A callback that is called each time a packet is captured + /// @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to + /// the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects + /// that give context to the capture callback, for example: objects that counts packets, manages flow state or + /// manages the application state according to the packet that was captured + /// @return True if capture started successfully, false if (relevant log error is printed in any case): + /// - Capture is already running + /// - Device is not opened + /// - Capture thread could not be created virtual bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie); - /** - * Start capturing packets on this network interface (device) with periodic stats collection. Each time a packet - * is captured the onPacketArrives callback is called. In addition, each intervalInSecondsToUpdateStats seconds - * stats are collected from the device and the onStatsUpdate callback is called. Both the capture and periodic - * stats collection are done on new threads created by this method, each on a different thread, meaning all - * callback calls are done in threads other than the caller thread. Capture process and stats collection will - * stop and threads will be terminated when calling stopCapture(). This method must be called after the device - * is opened (i.e the open() method was called), otherwise an error will be returned. - * @param[in] onPacketArrives A callback that is called each time a packet is captured - * @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to - * the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects that - * give context to the capture callback, for example: objects that counts packets, manages flow state or manages - * the application state according to the packet that was captured - * @param[in] intervalInSecondsToUpdateStats The interval in seconds to activate periodic stats collection - * @param[in] onStatsUpdate A callback that will be called each time intervalInSecondsToUpdateStats expires and - * stats are collected. This callback will contain the collected stats - * @param[in] onStatsUpdateUserCookie A pointer to a user provided object. This object will be transferred to - * the onStatsUpdate callback each time it is called - * @return True if capture started successfully, false if (relevant log error is printed in any case): - * - Capture is already running - * - Device is not opened - * - Capture thread could not be created - * - Stats collection thread could not be created - */ + /// Start capturing packets on this network interface (device) with periodic stats collection. Each time a + /// packet is captured the onPacketArrives callback is called. In addition, each intervalInSecondsToUpdateStats + /// seconds stats are collected from the device and the onStatsUpdate callback is called. Both the capture and + /// periodic stats collection are done on new threads created by this method, each on a different thread, + /// meaning all callback calls are done in threads other than the caller thread. Capture process and stats + /// collection will stop and threads will be terminated when calling stopCapture(). This method must be called + /// after the device is opened (i.e the open() method was called), otherwise an error will be returned. + /// @param[in] onPacketArrives A callback that is called each time a packet is captured + /// @param[in] onPacketArrivesUserCookie A pointer to a user provided object. This object will be transferred to + /// the onPacketArrives callback each time it is called. This cookie is very useful for transferring objects + /// that give context to the capture callback, for example: objects that counts packets, manages flow state or + /// manages the application state according to the packet that was captured + /// @param[in] intervalInSecondsToUpdateStats The interval in seconds to activate periodic stats collection + /// @param[in] onStatsUpdate A callback that will be called each time intervalInSecondsToUpdateStats expires and + /// stats are collected. This callback will contain the collected stats + /// @param[in] onStatsUpdateUserCookie A pointer to a user provided object. This object will be transferred to + /// the onStatsUpdate callback each time it is called + /// @return True if capture started successfully, false if (relevant log error is printed in any case): + /// - Capture is already running + /// - Device is not opened + /// - Capture thread could not be created + /// - Stats collection thread could not be created virtual bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie); - /** - * Start capturing packets on this network interface (device) with periodic stats collection only. This means - * that packets arriving to the network interface aren't delivered to the user but only counted. Each - * intervalInSecondsToUpdateStats seconds stats are collected from the device and the onStatsUpdate callback is - * called with the updated counters. The periodic stats collection is done on a new thread created by this - * method, meaning all callback calls are done in threads other than the caller thread. Stats collection will - * stop and threads will be terminated when calling stopCapture(). This method must be called after the device - * is opened (i.e the open() method was called), otherwise an error will be returned. - * @param[in] intervalInSecondsToUpdateStats The interval in seconds to activate periodic stats collection - * @param[in] onStatsUpdate A callback that will be called each time intervalInSecondsToUpdateStats expires and - * stats are collected. This callback will contain the collected stats - * @param[in] onStatsUpdateUserCookie A pointer to a user provided object. This object will be transferred to - * the onStatsUpdate callback each time it is called - * @return True if capture started successfully, false if (relevant log error is printed in any case): - * - Capture is already running - * - Device is not opened - * - Stats collection thread could not be created - */ + /// Start capturing packets on this network interface (device) with periodic stats collection only. This means + /// that packets arriving to the network interface aren't delivered to the user but only counted. Each + /// intervalInSecondsToUpdateStats seconds stats are collected from the device and the onStatsUpdate callback is + /// called with the updated counters. The periodic stats collection is done on a new thread created by this + /// method, meaning all callback calls are done in threads other than the caller thread. Stats collection will + /// stop and threads will be terminated when calling stopCapture(). This method must be called after the device + /// is opened (i.e the open() method was called), otherwise an error will be returned. + /// @param[in] intervalInSecondsToUpdateStats The interval in seconds to activate periodic stats collection + /// @param[in] onStatsUpdate A callback that will be called each time intervalInSecondsToUpdateStats expires and + /// stats are collected. This callback will contain the collected stats + /// @param[in] onStatsUpdateUserCookie A pointer to a user provided object. This object will be transferred to + /// the onStatsUpdate callback each time it is called + /// @return True if capture started successfully, false if (relevant log error is printed in any case): + /// - Capture is already running + /// - Device is not opened + /// - Stats collection thread could not be created virtual bool startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie); - /** - * Start capturing packets on this network interface (device). All captured packets are added to - * capturedPacketsVector, so at the end of the capture (when calling stopCapture()) this vector contains - * pointers to all captured packets in the form of RawPacket. The capture is done on a new thread created by - * this method, meaning capturedPacketsVector is updated from another thread other than the caller thread (so - * user should avoid changing or iterating this vector while capture is on). Capture process will stop and this - * capture thread will be terminated when calling stopCapture(). This method must be called after the device is - * opened (i.e the open() method was called), otherwise an error will be returned. - * @param[in] capturedPacketsVector A reference to a RawPacketVector, meaning a vector of pointer to RawPacket - * objects - * @return True if capture started successfully, false if (relevant log error is printed in any case): - * - Capture is already running - * - Device is not opened - * - Capture thread could not be created - */ + /// Start capturing packets on this network interface (device). All captured packets are added to + /// capturedPacketsVector, so at the end of the capture (when calling stopCapture()) this vector contains + /// pointers to all captured packets in the form of RawPacket. The capture is done on a new thread created by + /// this method, meaning capturedPacketsVector is updated from another thread other than the caller thread (so + /// user should avoid changing or iterating this vector while capture is on). Capture process will stop and this + /// capture thread will be terminated when calling stopCapture(). This method must be called after the device is + /// opened (i.e the open() method was called), otherwise an error will be returned. + /// @param[in] capturedPacketsVector A reference to a RawPacketVector, meaning a vector of pointer to RawPacket + /// objects + /// @return True if capture started successfully, false if (relevant log error is printed in any case): + /// - Capture is already running + /// - Device is not opened + /// - Capture thread could not be created virtual bool startCapture(RawPacketVector& capturedPacketsVector); - /** - * Start capturing packets on this network interface (device) in blocking mode, meaning this method blocks and - * won't return until the user frees the blocking (via onPacketArrives callback) or until a user defined timeout - * expires. Whenever a packets is captured the onPacketArrives callback is called and lets the user handle the - * packet. In each callback call the user should return true if he wants to release the block or false if it - * wants it to keep blocking. Regardless of this callback a timeout is defined when start capturing. When this - * timeout expires the method will return.
Please notice that stopCapture() isn't needed here because when - * the method returns (after timeout or per user decision) capturing on the device is stopped - * @param[in] onPacketArrives A callback given by the user for handling incoming packets. After handling each - * packet the user needs to return a boolean value. True value indicates stop capturing and stop blocking and - * false value indicates continue capturing and blocking - * @param[in] userCookie A pointer to a user provided object. This object will be transferred to the - * onPacketArrives callback each time it is called. This cookie is very useful for transferring objects that - * give context to the capture callback, for example: objects that counts packets, manages flow state or manages - * the application state according to the packet that was captured - * @param[in] timeout A timeout in seconds for the blocking to stop even if the user didn't return "true" in the - * onPacketArrives callback. The precision of `timeout` is millisecond, e.g. 2.345 seconds means 2345 - * milliseconds. If this timeout is set to 0 or less the timeout will be ignored, meaning the method will keep - * handling packets until the `onPacketArrives` callback returns `true`. - * @return -1 if timeout expired, 1 if blocking was stopped via onPacketArrives callback or 0 if an error - * occurred (such as device not open etc.). When returning 0 an appropriate error message is printed to log - * @note On Unix-like systems, enabling the `usePoll` option in `DeviceConfiguration` prevents the method from - * blocking indefinitely when no packets are available, even if a timeout is set. - */ + /// Start capturing packets on this network interface (device) in blocking mode, meaning this method blocks and + /// won't return until the user frees the blocking (via onPacketArrives callback) or until a user defined + /// timeout expires. Whenever a packets is captured the onPacketArrives callback is called and lets the user + /// handle the packet. In each callback call the user should return true if he wants to release the block or + /// false if it wants it to keep blocking. Regardless of this callback a timeout is defined when start + /// capturing. When this timeout expires the method will return.
Please notice that stopCapture() isn't + /// needed here because when the method returns (after timeout or per user decision) capturing on the device is + /// stopped + /// @param[in] onPacketArrives A callback given by the user for handling incoming packets. After handling each + /// packet the user needs to return a boolean value. True value indicates stop capturing and stop blocking and + /// false value indicates continue capturing and blocking + /// @param[in] userCookie A pointer to a user provided object. This object will be transferred to the + /// onPacketArrives callback each time it is called. This cookie is very useful for transferring objects that + /// give context to the capture callback, for example: objects that counts packets, manages flow state or + /// manages the application state according to the packet that was captured + /// @param[in] timeout A timeout in seconds for the blocking to stop even if the user didn't return "true" in + /// the onPacketArrives callback. The precision of `timeout` is millisecond, e.g. 2.345 seconds means 2345 + /// milliseconds. If this timeout is set to 0 or less the timeout will be ignored, meaning the method will keep + /// handling packets until the `onPacketArrives` callback returns `true`. + /// @return -1 if timeout expired, 1 if blocking was stopped via onPacketArrives callback or 0 if an error + /// occurred (such as device not open etc.). When returning 0 an appropriate error message is printed to log + /// @note On Unix-like systems, enabling the `usePoll` option in `DeviceConfiguration` prevents the method from + /// blocking indefinitely when no packets are available, even if a timeout is set. virtual int startCaptureBlockingMode(OnPacketArrivesStopBlocking onPacketArrives, void* userCookie, const double timeout); - /** - * Stop a currently running packet capture. This method terminates gracefully both packet capture thread and - * periodic stats collection thread (both if exist) - */ + /// Stop a currently running packet capture. This method terminates gracefully both packet capture thread and + /// periodic stats collection thread (both if exist) void stopCapture(); - /** - * Check if a capture thread is running - * @return True if a capture thread is currently running - */ + /// Check if a capture thread is running + /// @return True if a capture thread is currently running bool captureActive(); - /** - * Checks whether the packetPayloadLength is larger than the device MTU. Logs an error if check fails - * @param[in] packetPayloadLength The length of the IP layer of the packet - * @return True if the packetPayloadLength is less than or equal to the device MTU - */ + /// Checks whether the packetPayloadLength is larger than the device MTU. Logs an error if check fails + /// @param[in] packetPayloadLength The length of the IP layer of the packet + /// @return True if the packetPayloadLength is less than or equal to the device MTU bool doMtuCheck(int packetPayloadLength) const; - /** - * Send a RawPacket to the network - * @param[in] rawPacket A reference to the raw packet to send. This method treats the raw packet as read-only, - * it doesn't change anything in it - * @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. If enabled - * this comes with a small performance penalty. Default value is false to avoid performance overhead. Set to - * true if you don't know whether packets fit the live device's MTU and you can afford the overhead. - * @return True if packet was sent successfully. False will be returned in the following cases (relevant log - * error is printed in any case): - * - Device is not opened - * - Packet length is 0 - * - Packet length is larger than device MTU - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send a RawPacket to the network + /// @param[in] rawPacket A reference to the raw packet to send. This method treats the raw packet as read-only, + /// it doesn't change anything in it + /// @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. If enabled + /// this comes with a small performance penalty. Default value is false to avoid performance overhead. Set to + /// true if you don't know whether packets fit the live device's MTU and you can afford the overhead. + /// @return True if packet was sent successfully. False will be returned in the following cases (relevant log + /// error is printed in any case): + /// - Device is not opened + /// - Packet length is 0 + /// - Packet length is larger than device MTU + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap bool sendPacket(RawPacket const& rawPacket, bool checkMtu = false); - /** - * Send a buffer containing packet raw data (including all layers) to the network. - * This particular version of the sendPacket method should only be used if you already have access to the size - * of the network layer of the packet, since it allows you to check the payload size (see packetPayloadLength - * parameter) MTU of the live device without incurring a parsing overhead. If the packetPayloadLength is - * unknown, please use a different implementation of the sendPacket method. - * @param[in] packetData The buffer containing the packet raw data - * @param[in] packetDataLength The length of the buffer (this is the entire packet, including link layer) - * @param[in] packetPayloadLength The length of the payload for the data link layer. This includes all data - * apart from the header for the data link layer. - * @return True if the packet was sent successfully. False will be returned in the following cases (relevant log - * error is printed in any case): - * - Device is not opened - * - Packet data length is 0 - * - Packet payload length is larger than device MTU - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send a buffer containing packet raw data (including all layers) to the network. + /// This particular version of the sendPacket method should only be used if you already have access to the size + /// of the network layer of the packet, since it allows you to check the payload size (see packetPayloadLength + /// parameter) MTU of the live device without incurring a parsing overhead. If the packetPayloadLength is + /// unknown, please use a different implementation of the sendPacket method. + /// @param[in] packetData The buffer containing the packet raw data + /// @param[in] packetDataLength The length of the buffer (this is the entire packet, including link layer) + /// @param[in] packetPayloadLength The length of the payload for the data link layer. This includes all data + /// apart from the header for the data link layer. + /// @return True if the packet was sent successfully. False will be returned in the following cases (relevant + /// log error is printed in any case): + /// - Device is not opened + /// - Packet data length is 0 + /// - Packet payload length is larger than device MTU + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap bool sendPacket(const uint8_t* packetData, int packetDataLength, int packetPayloadLength); - /** - * Send a buffer containing packet raw data (including all layers) to the network - * @param[in] packetData The buffer containing the packet raw data - * @param[in] packetDataLength The length of the buffer - * @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. If enabled - * this comes with a small performance penalty. Default value is false to avoid performance overhead. Set to - * true if you don't know whether packets fit the live device's MTU and you can afford the overhead. - * @param[in] linkType Only used if checkMtu is true. Defines the layer type for parsing the first layer of the - * packet. Used for parsing the packet to perform the MTU check. Default value is pcpp::LINKTYPE_ETHERNET. - * Ensure this parameter matches the linktype of the packet if checkMtu is true. - * @return True if packet was sent successfully. False will be returned in the following cases (relevant log - * error is printed in any case): - * - Device is not opened - * - Packet length is 0 - * - Packet length is larger than device MTU and checkMtu is true - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send a buffer containing packet raw data (including all layers) to the network + /// @param[in] packetData The buffer containing the packet raw data + /// @param[in] packetDataLength The length of the buffer + /// @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. If enabled + /// this comes with a small performance penalty. Default value is false to avoid performance overhead. Set to + /// true if you don't know whether packets fit the live device's MTU and you can afford the overhead. + /// @param[in] linkType Only used if checkMtu is true. Defines the layer type for parsing the first layer of the + /// packet. Used for parsing the packet to perform the MTU check. Default value is pcpp::LINKTYPE_ETHERNET. + /// Ensure this parameter matches the linktype of the packet if checkMtu is true. + /// @return True if packet was sent successfully. False will be returned in the following cases (relevant log + /// error is printed in any case): + /// - Device is not opened + /// - Packet length is 0 + /// - Packet length is larger than device MTU and checkMtu is true + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap bool sendPacket(const uint8_t* packetData, int packetDataLength, bool checkMtu = false, pcpp::LinkLayerType linkType = pcpp::LINKTYPE_ETHERNET); - /** - * Send a parsed Packet to the network - * @param[in] packet A pointer to the packet to send. This method treats the packet as read-only, it doesn't - * change anything in it - * @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. Default - * value is true, since the packet being passed in has already been parsed, so checking the MTU does not incur - * significant processing overhead. - * @return True if packet was sent successfully. False will be returned in the following cases (relevant log - * error is printed in any case): - * - Device is not opened - * - Packet length is 0 - * - Packet length is larger than device MTU and checkMtu is true - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send a parsed Packet to the network + /// @param[in] packet A pointer to the packet to send. This method treats the packet as read-only, it doesn't + /// change anything in it + /// @param[in] checkMtu Whether the length of the packet's payload should be checked against the MTU. Default + /// value is true, since the packet being passed in has already been parsed, so checking the MTU does not incur + /// significant processing overhead. + /// @return True if packet was sent successfully. False will be returned in the following cases (relevant log + /// error is printed in any case): + /// - Device is not opened + /// - Packet length is 0 + /// - Packet length is larger than device MTU and checkMtu is true + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap bool sendPacket(Packet* packet, bool checkMtu = true); - /** - * Send an array of RawPacket objects to the network - * @param[in] rawPacketsArr The array of RawPacket objects to send. This method treats all packets as read-only, - * it doesn't change anything in them - * @param[in] arrLength The length of the array - * @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Incurs a parsing - * overhead. Default value is false to avoid performance overhead. Set to true if you don't know whether packets - * fit the live device's MTU and you can afford the overhead. - * @return The number of packets sent successfully. Sending a packet can fail if: - * - Device is not opened. In this case no packets will be sent, return value will be 0 - * - Packet length is 0 - * - Packet length is larger than device MTU and checkMtu is true - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send an array of RawPacket objects to the network + /// @param[in] rawPacketsArr The array of RawPacket objects to send. This method treats all packets as + /// read-only, it doesn't change anything in them + /// @param[in] arrLength The length of the array + /// @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Incurs a parsing + /// overhead. Default value is false to avoid performance overhead. Set to true if you don't know whether + /// packets fit the live device's MTU and you can afford the overhead. + /// @return The number of packets sent successfully. Sending a packet can fail if: + /// - Device is not opened. In this case no packets will be sent, return value will be 0 + /// - Packet length is 0 + /// - Packet length is larger than device MTU and checkMtu is true + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap virtual int sendPackets(RawPacket* rawPacketsArr, int arrLength, bool checkMtu = false); - /** - * Send an array of pointers to Packet objects to the network - * @param[in] packetsArr The array of pointers to Packet objects to send. This method treats all packets as - * read-only, it doesn't change anything in them - * @param[in] arrLength The length of the array - * @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Default value is true, - * since the packets being passed in has already been parsed, so checking the MTU does not incur significant - * processing overhead. - * @return The number of packets sent successfully. Sending a packet can fail if: - * - Device is not opened. In this case no packets will be sent, return value will be 0 - * - Packet length is 0 - * - Packet length is larger than device MTU and checkMtu is true - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send an array of pointers to Packet objects to the network + /// @param[in] packetsArr The array of pointers to Packet objects to send. This method treats all packets as + /// read-only, it doesn't change anything in them + /// @param[in] arrLength The length of the array + /// @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Default value is true, + /// since the packets being passed in has already been parsed, so checking the MTU does not incur significant + /// processing overhead. + /// @return The number of packets sent successfully. Sending a packet can fail if: + /// - Device is not opened. In this case no packets will be sent, return value will be 0 + /// - Packet length is 0 + /// - Packet length is larger than device MTU and checkMtu is true + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap virtual int sendPackets(Packet** packetsArr, int arrLength, bool checkMtu = true); - /** - * Send a vector of pointers to RawPacket objects to the network - * @param[in] rawPackets The array of pointers to RawPacket objects to send. This method treats all packets as - * read-only, it doesn't change anything in them - * @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Incurs a parsing - * overhead. Default value is false to avoid performance overhead. Set to true if you don't know whether packets - * fit the live device's MTU and you can afford the overhead. - * @return The number of packets sent successfully. Sending a packet can fail if: - * - Device is not opened. In this case no packets will be sent, return value will be 0 - * - Packet length is 0 - * - Packet length is larger than device MTU and checkMtu is true - * - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - */ + /// Send a vector of pointers to RawPacket objects to the network + /// @param[in] rawPackets The array of pointers to RawPacket objects to send. This method treats all packets as + /// read-only, it doesn't change anything in them + /// @param[in] checkMtu Whether to check the size of the packet payload against MTU size. Incurs a parsing + /// overhead. Default value is false to avoid performance overhead. Set to true if you don't know whether + /// packets fit the live device's MTU and you can afford the overhead. + /// @return The number of packets sent successfully. Sending a packet can fail if: + /// - Device is not opened. In this case no packets will be sent, return value will be 0 + /// - Packet length is 0 + /// - Packet length is larger than device MTU and checkMtu is true + /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap virtual int sendPackets(const RawPacketVector& rawPackets, bool checkMtu = false); // implement abstract methods - /** - * Open the device using libpcap pcap_open_live. Opening the device only makes the device ready for use, it - * doesn't start packet capturing. For packet capturing the user should call startCapture(). This implies that - * calling this method is a must before calling startCapture() (otherwise startCapture() will fail with a - * "device not open" error). The device is opened in promiscuous mode - * @return True if the device was opened successfully, false otherwise. When opening the device fails an error - * will be printed to log as well - */ + /// Open the device using libpcap pcap_open_live. Opening the device only makes the device ready for use, it + /// doesn't start packet capturing. For packet capturing the user should call startCapture(). This implies that + /// calling this method is a must before calling startCapture() (otherwise startCapture() will fail with a + /// "device not open" error). The device is opened in promiscuous mode + /// @return True if the device was opened successfully, false otherwise. When opening the device fails an error + /// will be printed to log as well bool open() override; - /** - * Enables to open a device in a non-default configuration. Configuration has parameters like packet buffer - * timeout & size, open in promiscuous/non-promiscuous mode, etc. Please check DeviceConfiguration for more - * details - * @param[in] config The requested configuration - * @return Same as open() - */ + /// Enables to open a device in a non-default configuration. Configuration has parameters like packet buffer + /// timeout & size, open in promiscuous/non-promiscuous mode, etc. Please check DeviceConfiguration for more + /// details + /// @param[in] config The requested configuration + /// @return Same as open() bool open(const DeviceConfiguration& config); void close() override; - /** - * Clones the current device class - * @return Pointer to the copied class - */ + /// Clones the current device class + /// @return Pointer to the copied class virtual PcapLiveDevice* clone() const; void getStatistics(IPcapDevice::PcapStats& stats) const override; @@ -650,5 +560,4 @@ namespace pcpp protected: pcap_t* doOpen(const DeviceConfiguration& config); }; - } // namespace pcpp diff --git a/Pcap++/header/PcapLiveDeviceList.h b/Pcap++/header/PcapLiveDeviceList.h index 84f33b4ab6..bb4a842d6d 100644 --- a/Pcap++/header/PcapLiveDeviceList.h +++ b/Pcap++/header/PcapLiveDeviceList.h @@ -7,20 +7,15 @@ /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class PcapLiveDeviceList - * A singleton class that creates, stores and provides access to all PcapLiveDevice (on Linux) or WinPcapLiveDevice - * (on Windows) instances. All live devices are initialized on startup and wrap the network interfaces installed on - * the machine. This class enables access to them through their IP addresses or get a vector of all of them so the - * user can search them in some other way - */ + /// @class PcapLiveDeviceList + /// A singleton class that creates, stores and provides access to all PcapLiveDevice (on Linux) or WinPcapLiveDevice + /// (on Windows) instances. All live devices are initialized on startup and wrap the network interfaces installed on + /// the machine. This class enables access to them through their IP addresses or get a vector of all of them so the + /// user can search them in some other way class PcapLiveDeviceList { private: @@ -42,85 +37,63 @@ namespace pcpp PcapLiveDeviceList& operator=(const PcapLiveDeviceList&) = delete; PcapLiveDeviceList& operator=(PcapLiveDeviceList&&) noexcept = delete; - /** - * The access method to the singleton - * @return The singleton instance of this class - */ + /// The access method to the singleton + /// @return The singleton instance of this class static PcapLiveDeviceList& getInstance() { static PcapLiveDeviceList instance; return instance; } - /** - * @return A vector containing pointers to all live devices currently installed on the machine - */ + /// @return A vector containing pointers to all live devices currently installed on the machine const std::vector& getPcapLiveDevicesList() const { return m_LiveDeviceListView; }; - /** - * Get a pointer to the live device by its IP address. IP address can be both IPv4 or IPv6 - * @param[in] ipAddr The IP address defined for the device - * @return A pointer to the live device if this IP address exists. nullptr otherwise - */ + /// Get a pointer to the live device by its IP address. IP address can be both IPv4 or IPv6 + /// @param[in] ipAddr The IP address defined for the device + /// @return A pointer to the live device if this IP address exists. nullptr otherwise PcapLiveDevice* getPcapLiveDeviceByIp(const IPAddress& ipAddr) const; - /** - * Get a pointer to the live device by its IPv4 address - * @param[in] ipAddr The IPv4 address defined for the device - * @return A pointer to the live device if this IPv4 address exists. nullptr otherwise - */ + /// Get a pointer to the live device by its IPv4 address + /// @param[in] ipAddr The IPv4 address defined for the device + /// @return A pointer to the live device if this IPv4 address exists. nullptr otherwise PcapLiveDevice* getPcapLiveDeviceByIp(const IPv4Address& ipAddr) const; - /** - * Get a pointer to the live device by its IPv6 address - * @param[in] ip6Addr The IPv6 address defined for the device - * @return A pointer to the live device if this IPv6 address exists. nullptr otherwise - */ + /// Get a pointer to the live device by its IPv6 address + /// @param[in] ip6Addr The IPv6 address defined for the device + /// @return A pointer to the live device if this IPv6 address exists. nullptr otherwise PcapLiveDevice* getPcapLiveDeviceByIp(const IPv6Address& ip6Addr) const; - /** - * Get a pointer to the live device by its IP address represented as string. IP address can be both IPv4 or IPv6 - * @param[in] ipAddrAsString The IP address defined for the device as string - * @return A pointer to the live device if this IP address is valid and exists. nullptr otherwise - */ + /// Get a pointer to the live device by its IP address represented as string. IP address can be both IPv4 or + /// IPv6 + /// @param[in] ipAddrAsString The IP address defined for the device as string + /// @return A pointer to the live device if this IP address is valid and exists. nullptr otherwise PcapLiveDevice* getPcapLiveDeviceByIp(const std::string& ipAddrAsString) const; - /** - * Get a pointer to the live device by its name - * @param[in] name The name of the interface (e.g eth0) - * @return A pointer to the live device if this name exists. nullptr otherwise - */ + /// Get a pointer to the live device by its name + /// @param[in] name The name of the interface (e.g eth0) + /// @return A pointer to the live device if this name exists. nullptr otherwise PcapLiveDevice* getPcapLiveDeviceByName(const std::string& name) const; - /** - * Get a pointer to the live device by its IP address or name - * @param[in] ipOrName An IP address or name of the interface - * @return A pointer to the live device if exists, nullptr otherwise - */ + /// Get a pointer to the live device by its IP address or name + /// @param[in] ipOrName An IP address or name of the interface + /// @return A pointer to the live device if exists, nullptr otherwise PcapLiveDevice* getPcapLiveDeviceByIpOrName(const std::string& ipOrName) const; - /** - * @return A list of all DNS servers defined for this machine. If this list is empty it means no DNS servers - * were defined or they couldn't be extracted from some reason - */ + /// @return A list of all DNS servers defined for this machine. If this list is empty it means no DNS servers + /// were defined or they couldn't be extracted from some reason const std::vector& getDnsServers() const { return m_DnsServers; } - /** - * Copies the current live device list - * @return A pointer to the cloned device list - */ + /// Copies the current live device list + /// @return A pointer to the cloned device list PcapLiveDeviceList* clone(); - /** - * Reset the live device list and DNS server list, meaning clear and refetch them - */ + /// Reset the live device list and DNS server list, meaning clear and refetch them void reset(); }; - } // namespace pcpp diff --git a/Pcap++/header/PcapRemoteDevice.h b/Pcap++/header/PcapRemoteDevice.h index 8158be244c..f3bcb50505 100644 --- a/Pcap++/header/PcapRemoteDevice.h +++ b/Pcap++/header/PcapRemoteDevice.h @@ -8,79 +8,62 @@ struct pcap_rmtauth; -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @struct PcapRemoteAuthentication - * The remote daemon (rpcapd) can be configured to require authentication before allowing a client to connect. This - * is done for security reasons of course. This struct wraps the WinPcap/Npcap authentication object (pcap_rmtauth) - * and can (but not must) be given to PcapRemoteDeviceList when initiating a connection to the remote daemon - */ + /// @struct PcapRemoteAuthentication + /// The remote daemon (rpcapd) can be configured to require authentication before allowing a client to connect. This + /// is done for security reasons of course. This struct wraps the WinPcap/Npcap authentication object (pcap_rmtauth) + /// and can (but not must) be given to PcapRemoteDeviceList when initiating a connection to the remote daemon struct PcapRemoteAuthentication { public: - /** - * A constructor that sets username and password - * @param[in] username The username for authentication with the remote daemon - * @param[in] password The password for authentication with the remote daemon - */ + /// A constructor that sets username and password + /// @param[in] username The username for authentication with the remote daemon + /// @param[in] password The password for authentication with the remote daemon PcapRemoteAuthentication(const std::string& username, const std::string& password) : userName(username) { this->password = password; } - /** - * A copy c'tor for this object - * @param[in] other The object to copy from - */ + /// A copy c'tor for this object + /// @param[in] other The object to copy from PcapRemoteAuthentication(const PcapRemoteAuthentication& other) : userName(other.userName), password(other.password) {} - /** - * The username for authentication - */ + /// The username for authentication std::string userName; - /** - * The password for authentication - */ + /// The password for authentication std::string password; - /** - * A conversion method from PcapRemoteAuthentication to pcap_rmtauth. Note: the char* pointers of the returned - * pcap_rmtauth points to the same places in memory as PcapRemoteAuthentication::userName and - * PcapRemoteAuthentication::password so the user should avoid freeing this memory - * @return A pcap_rmtauth that is converted from this class - */ + /// A conversion method from PcapRemoteAuthentication to pcap_rmtauth. Note: the char* pointers of the returned + /// pcap_rmtauth points to the same places in memory as PcapRemoteAuthentication::userName and + /// PcapRemoteAuthentication::password so the user should avoid freeing this memory + /// @return A pcap_rmtauth that is converted from this class pcap_rmtauth getPcapRmAuth() const; }; - /** - * @class PcapRemoteDevice - * A class that provides a C++ wrapper for WinPcap/Npcap Remote Capture feature. This feature allows to interact to - * a remote machine and capture packets that are being transmitted on the remote network interfaces. This requires a - * remote daemon (called rpcapd) which performs the capture and sends data back and the local client (represented by - * PcapRemoteDevice) that sends the appropriate commands and receives the captured data. You can read more about - * this feature in WinPcap Remote Capture manual: https://www.winpcap.org/docs/docs_412/html/group__remote.html
- * Since this feature is supported in WinPcap and Npcap only and not in libpcap, PcapRemoteDevice can only be used - * in Windows only.
This class provides a wrapper for the local client, meaning it assumes the daemon (rpcapd) - * is already running on the remote machine and it tries to connect to it and start receiving/sending packets - * from/to it. This class assumes rpcapd is in passive mode, meaning PcapRemoteDevice connects to the remote daemon, - * sends the appropriate commands to it, and starts capturing packets, rather than letting the daemon connect to the - * client by itself. Using PcapRemoteDevice is very similar to using the other live devices (PcapLiveDevice or - * WinPcapLiveDevice), meaning the API's are the same and the same logic is used (for example: capturing is done on - * a different thread, sending packets are done on the same thread, etc.). For the full API and explanations, please - * refer to PcapLiveDevice. The reason for the similar API is that WinPcap/Npcap's API is very similar between - * Remote Capture and local network interface capture. The things that are different are some are some - * implementation details, mainly in making the connection to the remote daemon, and the way the user can get the - * instance of PcapRemoteDevice. For more details on that please refer to PcapRemoteDeviceList - */ + /// @class PcapRemoteDevice + /// A class that provides a C++ wrapper for WinPcap/Npcap Remote Capture feature. This feature allows to interact to + /// a remote machine and capture packets that are being transmitted on the remote network interfaces. This requires + /// a remote daemon (called rpcapd) which performs the capture and sends data back and the local client (represented + /// by PcapRemoteDevice) that sends the appropriate commands and receives the captured data. You can read more about + /// this feature in WinPcap Remote Capture manual: https://www.winpcap.org/docs/docs_412/html/group__remote.html
+ /// Since this feature is supported in WinPcap and Npcap only and not in libpcap, PcapRemoteDevice can only be used + /// in Windows only.
This class provides a wrapper for the local client, meaning it assumes the daemon (rpcapd) + /// is already running on the remote machine and it tries to connect to it and start receiving/sending packets + /// from/to it. This class assumes rpcapd is in passive mode, meaning PcapRemoteDevice connects to the remote + /// daemon, sends the appropriate commands to it, and starts capturing packets, rather than letting the daemon + /// connect to the client by itself. Using PcapRemoteDevice is very similar to using the other live devices + /// (PcapLiveDevice or WinPcapLiveDevice), meaning the API's are the same and the same logic is used (for example: + /// capturing is done on a different thread, sending packets are done on the same thread, etc.). For the full API + /// and explanations, please refer to PcapLiveDevice. The reason for the similar API is that WinPcap/Npcap's API is + /// very similar between Remote Capture and local network interface capture. The things that are different are some + /// are some implementation details, mainly in making the connection to the remote daemon, and the way the user can + /// get the instance of PcapRemoteDevice. For more details on that please refer to PcapRemoteDeviceList class PcapRemoteDevice : public PcapLiveDevice { friend class PcapRemoteDeviceList; @@ -107,62 +90,48 @@ namespace pcpp PcapRemoteDevice& operator=(const PcapRemoteDevice&) = delete; PcapRemoteDevice& operator=(PcapRemoteDevice&&) noexcept = delete; - ~PcapRemoteDevice() override - {} + ~PcapRemoteDevice() override = default; - /** - * @return The IP address of the remote machine where packets are transmitted from the remote machine to the - * client machine - */ + /// @return The IP address of the remote machine where packets are transmitted from the remote machine to the + /// client machine IPAddress getRemoteMachineIpAddress() const { return m_RemoteMachineIpAddress; } - /** - * @return The port of the remote machine where packets are transmitted from the remote machine to the client - * machine - */ + /// @return The port of the remote machine where packets are transmitted from the remote machine to the client + /// machine uint16_t getRemoteMachinePort() const { return m_RemoteMachinePort; } - /** - * @return The type of the device (libPcap, WinPcap/Npcap or a remote device) - */ + /// @return The type of the device (libPcap, WinPcap/Npcap or a remote device) LiveDeviceType getDeviceType() const override { return RemoteDevice; } - /** - * MTU isn't supported for remote devices - * @return 0 - */ + /// MTU isn't supported for remote devices + /// @return 0 uint32_t getMtu() const override; - /** - * MAC address isn't supported for remote devices - * @return MacAddress#Zero - */ + /// MAC address isn't supported for remote devices + /// @return MacAddress#Zero MacAddress getMacAddress() const override; - /** - * Open the device using pcap_open. Opening the device makes the connection to the remote daemon (including - * authentication if needed and provided). If this methods succeeds it means the connection to the remote daemon - * succeeded and the device is ready for use. As in PcapLiveDevice, packet capturing won't start yet. For packet - * capturing the user should call startCapture(). This implies that calling this method is a must before calling - * startCapture() (otherwise startCapture() will fail with a "device not open" error). The remote daemon is - * asked to capture packets in promiscuous mode - * @return True if the device was opened successfully, false otherwise. When opening the device fails an error - * will be printed to log as well, including the WinPcap/Npcap error if exists - */ + /// Open the device using pcap_open. Opening the device makes the connection to the remote daemon (including + /// authentication if needed and provided). If this methods succeeds it means the connection to the remote + /// daemon succeeded and the device is ready for use. As in PcapLiveDevice, packet capturing won't start yet. + /// For packet capturing the user should call startCapture(). This implies that calling this method is a must + /// before calling startCapture() (otherwise startCapture() will fail with a "device not open" error). The + /// remote daemon is asked to capture packets in promiscuous mode + /// @return True if the device was opened successfully, false otherwise. When opening the device fails an error + /// will be printed to log as well, including the WinPcap/Npcap error if exists bool open() override; void getStatistics(IPcapDevice::PcapStats& stats) const override; PcapRemoteDevice* clone() const override; }; - } // namespace pcpp diff --git a/Pcap++/header/PcapRemoteDeviceList.h b/Pcap++/header/PcapRemoteDeviceList.h index 9d1d1fac6c..b8a07bbf50 100644 --- a/Pcap++/header/PcapRemoteDeviceList.h +++ b/Pcap++/header/PcapRemoteDeviceList.h @@ -7,25 +7,20 @@ /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class PcapRemoteDeviceList - * A class that creates, stores and provides access to all instances of PcapRemoteDevice for a certain remote - * machine. To get an instance of this class use one of the static methods of getRemoteDeviceList(). These methods - * creates a PcapRemoteDeviceList instance for the certain remote machine which holds a list of PcapRemoteDevice - * instances, one for each remote network interface. Note there is not a public constructor for this class, so the - * only way to get an instance of it is through getRemoteDeviceList(). After getting this object, this class - * provides ways to access the PcapRemoteDevice instances: either through IP address of the remote network interface - * or by iterating the PcapRemoteDevice instances (through the PcapRemoteDeviceList#RemoteDeviceListIterator - * iterator)
Since Remote Capture is supported in WinPcap and Npcap only, this class is available in Windows - * only - */ + /// @class PcapRemoteDeviceList + /// A class that creates, stores and provides access to all instances of PcapRemoteDevice for a certain remote + /// machine. To get an instance of this class use one of the static methods of getRemoteDeviceList(). These methods + /// creates a PcapRemoteDeviceList instance for the certain remote machine which holds a list of PcapRemoteDevice + /// instances, one for each remote network interface. Note there is not a public constructor for this class, so the + /// only way to get an instance of it is through getRemoteDeviceList(). After getting this object, this class + /// provides ways to access the PcapRemoteDevice instances: either through IP address of the remote network + /// interface or by iterating the PcapRemoteDevice instances (through the + /// PcapRemoteDeviceList#RemoteDeviceListIterator iterator)
Since Remote Capture is supported in WinPcap and + /// Npcap only, this class is available in Windows only class PcapRemoteDeviceList { private: @@ -40,14 +35,10 @@ namespace pcpp std::vector deviceList); public: - /** - * Iterator object that can be used for iterating all PcapRemoteDevice in list - */ + /// Iterator object that can be used for iterating all PcapRemoteDevice in list using RemoteDeviceListIterator = typename std::vector::iterator; - /** - * Const iterator object that can be used for iterating all PcapRemoteDevice in a constant list - */ + /// Const iterator object that can be used for iterating all PcapRemoteDevice in a constant list using ConstRemoteDeviceListIterator = typename std::vector::const_iterator; PcapRemoteDeviceList(const PcapRemoteDeviceList&) = delete; @@ -57,166 +48,137 @@ namespace pcpp ~PcapRemoteDeviceList(); - /** - * A static method for creating a PcapRemoteDeviceList instance for a certain remote machine. This methods - * creates the instance, and also creates a list of PcapRemoteDevice instances stored in it, one for each remote - * network interface. Notice this method allocates the PcapRemoteDeviceList instance and returns a pointer to - * it. It's the user responsibility to free it when done using it
This method overload is for remote daemons - * which don't require authentication for accessing them. For daemons which do require authentication use the - * other method overload - * @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd - * daemon - * @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon - * @return A pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will be - * printed to log in each case): - * - IP address provided is nullptr or not valid - * - WinPcap/Npcap encountered an error in creating the remote connection string - * - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving - * devices on the remote machine - * @deprecated This factory function has been deprecated in favor of 'createRemoteDeviceList' factory for better - * memory safety. - */ + /// A static method for creating a PcapRemoteDeviceList instance for a certain remote machine. This methods + /// creates the instance, and also creates a list of PcapRemoteDevice instances stored in it, one for each + /// remote network interface. Notice this method allocates the PcapRemoteDeviceList instance and returns a + /// pointer to it. It's the user responsibility to free it when done using it
This method overload is for + /// remote daemons which don't require authentication for accessing them. For daemons which do require + /// authentication use the other method overload + /// @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd + /// daemon + /// @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon + /// @return A pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will be + /// printed to log in each case): + /// - IP address provided is nullptr or not valid + /// - WinPcap/Npcap encountered an error in creating the remote connection string + /// - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving + /// devices on the remote machine + /// @deprecated This factory function has been deprecated in favor of 'createRemoteDeviceList' factory for + /// better memory safety. PCPP_DEPRECATED("Please use 'createRemoteDeviceList' factory method instead.") static PcapRemoteDeviceList* getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port); - /** - * A static method for creating a PcapRemoteDeviceList instance for a specific remote machine. - * This methods creates the instance and populates it with PcapRemoteDevice instances. - * Each PcapRemoteDevice instance corresponds to a network interface on the remote machine. - * - * This method overload is for remote daemons which don't require authentication for accessing them. - * For daemons which do require authentication use the other method overload. - * - * @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd - * daemon - * @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon - * @return A smart pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will - * be printed to log in each case): - * - WinPcap/Npcap encountered an error in creating the remote connection string - * - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving - * devices on the remote machine - */ + /// A static method for creating a PcapRemoteDeviceList instance for a specific remote machine. + /// This methods creates the instance and populates it with PcapRemoteDevice instances. + /// Each PcapRemoteDevice instance corresponds to a network interface on the remote machine. + /// + /// This method overload is for remote daemons which don't require authentication for accessing them. + /// For daemons which do require authentication use the other method overload. + /// + /// @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd + /// daemon + /// @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon + /// @return A smart pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will + /// be printed to log in each case): + /// - WinPcap/Npcap encountered an error in creating the remote connection string + /// - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving + /// devices on the remote machine static std::unique_ptr createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port); - /** - * An overload of the previous getRemoteDeviceList() method but with authentication support. This method is - * suitable for connecting to remote daemons which require authentication for accessing them - * @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd - * daemon - * @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon - * @param[in] remoteAuth A pointer to the authentication object which contains the username and password for - * connecting to the remote daemon - * @return A pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will be - * printed to log in each case): - * - IP address provided is nullptr or not valid - * - WinPcap/Npcap encountered an error in creating the remote connection string - * - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving - * devices on the remote machine - * @deprecated This factory function has been deprecated in favor of 'createRemoteDeviceList' factory for better - * memory safety. - */ + /// An overload of the previous getRemoteDeviceList() method but with authentication support. This method is + /// suitable for connecting to remote daemons which require authentication for accessing them + /// @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd + /// daemon + /// @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon + /// @param[in] remoteAuth A pointer to the authentication object which contains the username and password for + /// connecting to the remote daemon + /// @return A pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will be + /// printed to log in each case): + /// - IP address provided is nullptr or not valid + /// - WinPcap/Npcap encountered an error in creating the remote connection string + /// - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving + /// devices on the remote machine + /// @deprecated This factory function has been deprecated in favor of 'createRemoteDeviceList' factory for + /// better memory safety. PCPP_DEPRECATED("Please use 'createRemoteDeviceList' factory method instead.") static PcapRemoteDeviceList* getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication* remoteAuth); - /** - * A static method for creating a PcapRemoteDeviceList instance for a specific remote machine. - * This methods creates the instance and populates it with PcapRemoteDevice instances. - * Each PcapRemoteDevice instance corresponds to a network interface on the remote machine. - * - * This method overload is for remote daemons which require authentication for accessing them. - * If no authentication is required, use the other method overload. - * - * @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd - * daemon - * @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon - * @param[in] remoteAuth A pointer to the authentication object which contains the username and password for - * connecting to the remote daemon - * @return A smart pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will - * be printed to log in each case): - * - WinPcap/Npcap encountered an error in creating the remote connection string - * - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving - * devices on the remote machine - */ + /// A static method for creating a PcapRemoteDeviceList instance for a specific remote machine. + /// This methods creates the instance and populates it with PcapRemoteDevice instances. + /// Each PcapRemoteDevice instance corresponds to a network interface on the remote machine. + /// + /// This method overload is for remote daemons which require authentication for accessing them. + /// If no authentication is required, use the other method overload. + /// + /// @param[in] ipAddress The IP address of the remote machine through which clients can connect to the rpcapd + /// daemon + /// @param[in] port The port of the remote machine through which clients can connect to the rpcapd daemon + /// @param[in] remoteAuth A pointer to the authentication object which contains the username and password for + /// connecting to the remote daemon + /// @return A smart pointer to the newly created PcapRemoteDeviceList, or nullptr if (an appropriate error will + /// be printed to log in each case): + /// - WinPcap/Npcap encountered an error in creating the remote connection string + /// - WinPcap/Npcap encountered an error connecting to the rpcapd daemon on the remote machine or retrieving + /// devices on the remote machine static std::unique_ptr createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication const* remoteAuth); - /** - * @return The IP address of the remote machine - */ + /// @return The IP address of the remote machine IPAddress getRemoteMachineIpAddress() const { return m_RemoteMachineIpAddress; } - /** - * @return The port of the remote machine where packets are transmitted from the remote machine to the client - * machine - */ + /// @return The port of the remote machine where packets are transmitted from the remote machine to the client + /// machine uint16_t getRemoteMachinePort() const { return m_RemoteMachinePort; } - /** - * Search a PcapRemoteDevice in the list by its IPv4 address - * @param[in] ip4Addr The IPv4 address - * @return The PcapRemoteDevice if found, nullptr otherwise - */ + /// Search a PcapRemoteDevice in the list by its IPv4 address + /// @param[in] ip4Addr The IPv4 address + /// @return The PcapRemoteDevice if found, nullptr otherwise PcapRemoteDevice* getRemoteDeviceByIP(const IPv4Address& ip4Addr) const; - /** - * Search a PcapRemoteDevice in the list by its IPv6 address - * @param[in] ip6Addr The IPv6 address - * @return The PcapRemoteDevice if found, nullptr otherwise - */ + /// Search a PcapRemoteDevice in the list by its IPv6 address + /// @param[in] ip6Addr The IPv6 address + /// @return The PcapRemoteDevice if found, nullptr otherwise PcapRemoteDevice* getRemoteDeviceByIP(const IPv6Address& ip6Addr) const; - /** - * Search a PcapRemoteDevice in the list by its IP address (IPv4 or IPv6) - * @param[in] ipAddr The IP address - * @return The PcapRemoteDevice if found, nullptr otherwise - */ + /// Search a PcapRemoteDevice in the list by its IP address (IPv4 or IPv6) + /// @param[in] ipAddr The IP address + /// @return The PcapRemoteDevice if found, nullptr otherwise PcapRemoteDevice* getRemoteDeviceByIP(const IPAddress& ipAddr) const; - /** - * Search a PcapRemoteDevice in the list by its IP address - * @param[in] ipAddrAsString The IP address in string format - * @return The PcapRemoteDevice if found, nullptr otherwise - */ + /// Search a PcapRemoteDevice in the list by its IP address + /// @param[in] ipAddrAsString The IP address in string format + /// @return The PcapRemoteDevice if found, nullptr otherwise PcapRemoteDevice* getRemoteDeviceByIP(const std::string& ipAddrAsString) const; - /** - * @return An iterator object pointing to the first PcapRemoteDevice in list - */ + /// @return An iterator object pointing to the first PcapRemoteDevice in list RemoteDeviceListIterator begin() { return m_RemoteDeviceList.begin(); } - /** - * @return A const iterator object pointing to the first PcapRemoteDevice in list - */ + /// @return A const iterator object pointing to the first PcapRemoteDevice in list ConstRemoteDeviceListIterator begin() const { return m_RemoteDeviceList.begin(); } - /** - * @return An iterator object pointing to the last PcapRemoteDevice in list - */ + /// @return An iterator object pointing to the last PcapRemoteDevice in list RemoteDeviceListIterator end() { return m_RemoteDeviceList.end(); } - /** - * @return A const iterator object pointing to the last PcapRemoteDevice in list - */ + /// @return A const iterator object pointing to the last PcapRemoteDevice in list ConstRemoteDeviceListIterator end() const { return m_RemoteDeviceList.end(); } }; - } // namespace pcpp diff --git a/Pcap++/header/PcapUtils.h b/Pcap++/header/PcapUtils.h index 5942ad2c5d..7fefa0abed 100644 --- a/Pcap++/header/PcapUtils.h +++ b/Pcap++/header/PcapUtils.h @@ -6,25 +6,23 @@ typedef pcap pcap_t; struct pcap_if; typedef pcap_if pcap_if_t; +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { /// @cond PCPP_INTERNAL namespace internal { - /** - * @class PcapCloseDeleter - * A deleter that cleans up a pcap_t structure by calling pcap_close. - */ + /// @class PcapCloseDeleter + /// A deleter that cleans up a pcap_t structure by calling pcap_close. struct PcapCloseDeleter { void operator()(pcap_t* ptr) const; }; - /** - * @class PcapFreeAllDevsDeleter - * A deleter that frees an interface list of pcap_if_t ptr by calling 'pcap_freealldevs' function on it. - */ + /// @class PcapFreeAllDevsDeleter + /// A deleter that frees an interface list of pcap_if_t ptr by calling 'pcap_freealldevs' function on it. struct PcapFreeAllDevsDeleter { void operator()(pcap_if_t* ptr) const; diff --git a/Pcap++/header/PfRingDevice.h b/Pcap++/header/PfRingDevice.h index 304f40c3c8..6ebdb47ed8 100644 --- a/Pcap++/header/PfRingDevice.h +++ b/Pcap++/header/PfRingDevice.h @@ -7,6 +7,7 @@ #include "SystemUtils.h" #include "Packet.h" #include +#include #include /// @file @@ -15,10 +16,8 @@ struct __pfring; typedef struct __pfring pfring; -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { @@ -27,10 +26,8 @@ namespace pcpp typedef void (*OnPfRingPacketsArriveCallback)(RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, PfRingDevice* device, void* userCookie); - /** - * @class PfRingDevice - * A class representing a PF_RING port - */ + /// @class PfRingDevice + /// A class representing a PF_RING port class PfRingDevice : public IDevice, public IFilterableDevice { friend class PfRingDeviceList; @@ -47,6 +44,13 @@ namespace pcpp void clear(); }; + struct StartupBlock + { + std::mutex Mutex; + std::condition_variable Cond; + int State = 0; + }; + pfring** m_PfRingDescriptors; uint8_t m_NumOfOpenedRxChannels; std::string m_DeviceName; @@ -64,7 +68,7 @@ namespace pcpp PfRingDevice(const char* deviceName); bool initCoreConfigurationByCoreMask(CoreMask coreMask); - void captureThreadMain(std::condition_variable* startCond, std::mutex* startMutex, const int* startState); + void captureThreadMain(std::shared_ptr startupBlock); int openSingleRxChannel(const char* deviceName, pfring** ring); @@ -83,293 +87,226 @@ namespace pcpp bool sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues); public: - /** - * An enum representing the type of packet distribution between different RX channels - */ + /// An enum representing the type of packet distribution between different RX channels enum ChannelDistribution { - /** - * Packets are distributed between channels in a round-robin manner - */ + /// Packets are distributed between channels in a round-robin manner RoundRobin, - /** - * Packets are distributed between channels per flow (each flow goes for different channel) - */ + /// Packets are distributed between channels per flow (each flow goes for different channel) PerFlow }; - /** - * @struct PfRingStats - * A container for PfRingDevice statistics - */ + /// @struct PfRingStats + /// A container for PfRingDevice statistics struct PfRingStats { - /** Number of packets received */ + /// Number of packets received uint64_t recv; - /** Number of packets dropped */ + /// Number of packets dropped uint64_t drop; }; - /** - * A destructor for PfRingDevice class - */ + /// A destructor for PfRingDevice class ~PfRingDevice(); - /** - * Get the MAC address of the current device - * @return The MAC address of the current device - */ + /// Get the MAC address of the current device + /// @return The MAC address of the current device MacAddress getMacAddress() { setPfRingDeviceAttributes(); return m_MacAddress; } - /** - * Get PF_RING interface index of the current device - * @return PF_RING interface index of the current device - */ + /// Get PF_RING interface index of the current device + /// @return PF_RING interface index of the current device int getInterfaceIndex() { setPfRingDeviceAttributes(); return m_InterfaceIndex; } - /** - * Get MTU of the current device - * @return Upon success return the device MTU, 0 otherwise - */ + /// Get MTU of the current device + /// @return Upon success return the device MTU, 0 otherwise int getMtu() { setPfRingDeviceAttributes(); return m_DeviceMTU; } - /** - * Return true if device supports hardware timestamping. If it does, this feature will be automatically set - * for this device. You can read more about this in PF_RING documentation - * @return True if device supports hardware timestamping, false otherwise - */ + /// Return true if device supports hardware timestamping. If it does, this feature will be automatically set + /// for this device. You can read more about this in PF_RING documentation + /// @return True if device supports hardware timestamping, false otherwise bool isHwClockEnabledForDevice() { setPfRingDeviceAttributes(); return m_HwClockEnabled; } - /** - * Gets the interface name (e.g eth0, eth1, etc.) - * @return The interface name - */ + /// Gets the interface name (e.g eth0, eth1, etc.) + /// @return The interface name std::string getDeviceName() const { return m_DeviceName; } - /** - * Start single-threaded capturing with callback. Works with open() or openSingleRxChannel(). - * @param[in] onPacketsArrive A callback to call whenever a packet arrives - * @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every - * packet - * @return True if this action succeeds, false otherwise - */ + /// Start single-threaded capturing with callback. Works with open() or openSingleRxChannel(). + /// @param[in] onPacketsArrive A callback to call whenever a packet arrives + /// @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every + /// packet + /// @return True if this action succeeds, false otherwise bool startCaptureSingleThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie); - /** - * Start multi-threaded (multi-core) capturing with callback. Works with openMultiRxChannels(). - * This method will return an error if the number of opened channels is different than the number of - * threads/cores requested - * @param[in] onPacketsArrive A callback to call whenever a packet arrives - * @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every - * packet - * @param[in] coreMask The cores to be used as mask. For example: - * @return True if this action succeeds, false otherwise - */ + /// Start multi-threaded (multi-core) capturing with callback. Works with openMultiRxChannels(). + /// This method will return an error if the number of opened channels is different than the number of + /// threads/cores requested + /// @param[in] onPacketsArrive A callback to call whenever a packet arrives + /// @param[in] onPacketsArriveUserCookie A cookie that will be delivered to onPacketsArrive callback on every + /// packet + /// @param[in] coreMask The cores to be used as mask. For example: + /// @return True if this action succeeds, false otherwise bool startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask); - /** - * Stops capturing packets (works will all type of startCapture*) - */ + /// Stops capturing packets (works will all type of startCapture*) void stopCapture(); - /** - * Opens a single RX channel (=RX queue) on this interface. All packets will be received on a single thread - * without core affinity. If the channel ID requested doesn't exist on this interface, the method will fail - * (return false) - * @param[in] channelId The requested channel ID - * @return True if this action succeeds, false otherwise - */ + /// Opens a single RX channel (=RX queue) on this interface. All packets will be received on a single thread + /// without core affinity. If the channel ID requested doesn't exist on this interface, the method will fail + /// (return false) + /// @param[in] channelId The requested channel ID + /// @return True if this action succeeds, false otherwise bool openSingleRxChannel(uint8_t channelId); - /** - * Opens a set of RX channels (=RX queues) on this interface, identified by their IDs. All packets will be - * received on a single thread without core affinity. If one of the channel IDs requested doesn't exist on this - * interface, the method will fail (return false) - * @param[in] channelIds An array of channel IDs - * @param[in] numOfChannelIds The channel ID array size - * @return True if this action succeeds, false otherwise - */ + /// Opens a set of RX channels (=RX queues) on this interface, identified by their IDs. All packets will be + /// received on a single thread without core affinity. If one of the channel IDs requested doesn't exist on this + /// interface, the method will fail (return false) + /// @param[in] channelIds An array of channel IDs + /// @param[in] numOfChannelIds The channel ID array size + /// @return True if this action succeeds, false otherwise bool openMultiRxChannels(const uint8_t* channelIds, int numOfChannelIds); - /** - * Opens numOfRxChannelsToOpen RX channels. If numOfRxChannelsToOpen is larger than available RX queues for this - * interface than a number of RX channels will be opened on each RX queue. For example: if the user asks for 10 - * RX channels but the interface has only 4 RX queues, then 3 RX channels will be opened for RX-queue0 and - * RX-queue2, and 2 RX channels will be opened for RX-queue2 and RX-queue3. Packets will be distributed between - * different RX queues on per-flow manner, but within multiple RX channels in the same RX queue packet will be - * distributed according to distribution requested by "dist" - * @param[in] numOfRxChannelsToOpen Number of RX channels to open - * @param[in] dist Distribution method - * @return True if this action succeeds, false otherwise - */ + /// Opens numOfRxChannelsToOpen RX channels. If numOfRxChannelsToOpen is larger than available RX queues for + /// this interface than a number of RX channels will be opened on each RX queue. For example: if the user asks + /// for 10 RX channels but the interface has only 4 RX queues, then 3 RX channels will be opened for RX-queue0 + /// and RX-queue2, and 2 RX channels will be opened for RX-queue2 and RX-queue3. Packets will be distributed + /// between different RX queues on per-flow manner, but within multiple RX channels in the same RX queue packet + /// will be distributed according to distribution requested by "dist" + /// @param[in] numOfRxChannelsToOpen Number of RX channels to open + /// @param[in] dist Distribution method + /// @return True if this action succeeds, false otherwise bool openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist); - /** - * Gets the number of RX channels currently open. RX channels aren't necessary interface's RX queues - * because in some cases the user asks to open several channels on the same queue. For example: if the user uses - * openMultiRxChannels() and asks to open 8 channels but interface has only 4 RX queues, 2 channels will be - * opened for each RX queue - * @return Number of opened RX channels - */ + /// Gets the number of RX channels currently open. RX channels aren't necessary interface's RX queues + /// because in some cases the user asks to open several channels on the same queue. For example: if the user + /// uses openMultiRxChannels() and asks to open 8 channels but interface has only 4 RX queues, 2 channels will + /// be opened for each RX queue + /// @return Number of opened RX channels uint8_t getNumOfOpenedRxChannels() const { return m_NumOfOpenedRxChannels; } - /** - * Gets the total number of RX channels (RX queues) this interface has - * @return The number of RX channels (queues) for this interface - */ + /// Gets the total number of RX channels (RX queues) this interface has + /// @return The number of RX channels (queues) for this interface uint8_t getTotalNumOfRxChannels() const; - /** - * Gets the core used in the current thread context - * @return The system core used in the current thread context - */ + /// Gets the core used in the current thread context + /// @return The system core used in the current thread context SystemCore getCurrentCoreId() const; - /** - * Get the statistics of a specific thread/core (=RX channel) - * @param[in] core The requested core - * @param[out] stats A reference for the stats object where the stats are written. Current values will be - * overridden - */ + /// Get the statistics of a specific thread/core (=RX channel) + /// @param[in] core The requested core + /// @param[out] stats A reference for the stats object where the stats are written. Current values will be + /// overridden void getThreadStatistics(SystemCore core, PfRingStats& stats) const; - /** - * Get the statistics of the current thread/core (=RX channel) - * @param[out] stats A reference for the stats object where the stats are written. Current values will be - * overridden - */ + /// Get the statistics of the current thread/core (=RX channel) + /// @param[out] stats A reference for the stats object where the stats are written. Current values will be + /// overridden void getCurrentThreadStatistics(PfRingStats& stats) const; - /** - * Get the statistics for the entire device. If more than 1 RX channel is opened, this method aggregates the - * stats of all channels - * @param[out] stats A reference for the stats object where the stats are written. Current values will be - * overridden - */ + /// Get the statistics for the entire device. If more than 1 RX channel is opened, this method aggregates the + /// stats of all channels + /// @param[out] stats A reference for the stats object where the stats are written. Current values will be + /// overridden void getStatistics(PfRingStats& stats) const; - /** - * Return true if filter is currently set - * @return True if filter is currently set, false otherwise - */ + /// Return true if filter is currently set + /// @return True if filter is currently set, false otherwise bool isFilterCurrentlySet() const; - /** - * Send a raw packet. This packet must be fully specified (the MAC address up) - * and it will be transmitted as-is without any further manipulation. - * This method doesn't change or manipulate the data in any way (hence the "const" declaration). - * Note this method flushes the TX queues after the data is sent. So if you want to send several packets - * In the burst please use sendPackets() - * @param[in] rawPacket The raw packet to send - * @return True if raw packet was sent completely, false otherwise - */ + /// Send a raw packet. This packet must be fully specified (the MAC address up) + /// and it will be transmitted as-is without any further manipulation. + /// This method doesn't change or manipulate the data in any way (hence the "const" declaration). + /// Note this method flushes the TX queues after the data is sent. So if you want to send several packets + /// In the burst please use sendPackets() + /// @param[in] rawPacket The raw packet to send + /// @return True if raw packet was sent completely, false otherwise bool sendPacket(const RawPacket& rawPacket); - /** - * Send raw data. This data must be a valid and fully specified packet (the MAC address up); - * it will be transmitted as-is without any further manipulation. - * This method doesn't change or manipulate the data in any way (hence the "const" declaration). - * Note this method flushes the TX queues after the data is sent. So if you want to send several packets - * in the burst please use sendPackets() - * @param[in] packetData The raw data to send - * @param[in] packetDataLength the length of packetData - * @return True if raw packet was sent completely, false otherwise - * - */ + /// Send raw data. This data must be a valid and fully specified packet (the MAC address up); + /// it will be transmitted as-is without any further manipulation. + /// This method doesn't change or manipulate the data in any way (hence the "const" declaration). + /// Note this method flushes the TX queues after the data is sent. So if you want to send several packets + /// in the burst please use sendPackets() + /// @param[in] packetData The raw data to send + /// @param[in] packetDataLength the length of packetData + /// @return True if raw packet was sent completely, false otherwise bool sendPacket(const uint8_t* packetData, int packetDataLength); - /** - * Send a packet. This packet must be fully specified (the MAC address up) - * and it will be transmitted as-is without any further manipulation. - * This method doesn't change or manipulate the data in any way (hence the "const" declaration). - * Note this method flushes the TX queues after the data is sent. So if you want to send several packets - * In the burst please use sendPackets() - * @param[in] packet The packet to send - * @return True if raw packet was sent completely, false otherwise - */ + /// Send a packet. This packet must be fully specified (the MAC address up) + /// and it will be transmitted as-is without any further manipulation. + /// This method doesn't change or manipulate the data in any way (hence the "const" declaration). + /// Note this method flushes the TX queues after the data is sent. So if you want to send several packets + /// In the burst please use sendPackets() + /// @param[in] packet The packet to send + /// @return True if raw packet was sent completely, false otherwise bool sendPacket(const Packet& packet); - /** - * Send raw packets. All raw packets must be fully specified (the MAC address up) - * and it will be transmitted as-is without any further manipulation. - * This method doesn't change or manipulate the raw packets data in any way (hence the "const" declaration). - * This method flushes the TX queues only when the last packet is sent - * @param[in] rawPacketsArr The RawPacket array - * @param[in] arrLength RawPacket array length - * @return Number of packets that were sent completely - */ + /// Send raw packets. All raw packets must be fully specified (the MAC address up) + /// and it will be transmitted as-is without any further manipulation. + /// This method doesn't change or manipulate the raw packets data in any way (hence the "const" declaration). + /// This method flushes the TX queues only when the last packet is sent + /// @param[in] rawPacketsArr The RawPacket array + /// @param[in] arrLength RawPacket array length + /// @return Number of packets that were sent completely int sendPackets(const RawPacket* rawPacketsArr, int arrLength); - /** - * Send packets. All packets must be fully specified (the MAC address up) - * and it will be transmitted as-is without any further manipulation. - * This method doesn't change or manipulate the packets data in any way (hence the "const" declaration). - * This method flushes the TX queues only when the last packet is sent - * @param[in] packetsArr An array of pointers to Packet objects - * @param[in] arrLength Packet pointers array length - * @return Number of packets that were sent completely - */ + /// Send packets. All packets must be fully specified (the MAC address up) + /// and it will be transmitted as-is without any further manipulation. + /// This method doesn't change or manipulate the packets data in any way (hence the "const" declaration). + /// This method flushes the TX queues only when the last packet is sent + /// @param[in] packetsArr An array of pointers to Packet objects + /// @param[in] arrLength Packet pointers array length + /// @return Number of packets that were sent completely int sendPackets(const Packet** packetsArr, int arrLength); - /** - * Send all raw packets pointed by the RawPacketVector. All packets must be fully specified (the MAC address up) - * and it will be transmitted as-is without any further manipulation. - * This method doesn't change or manipulate the packets data in any way (hence the "const" declaration). - * This method flushes the TX queues only when the last packet is sent - * @param[in] rawPackets The raw packet vector - * @return Number of raw packets that were sent completely - */ + /// Send all raw packets pointed by the RawPacketVector. All packets must be fully specified (the MAC address + /// up) and it will be transmitted as-is without any further manipulation. This method doesn't change or + /// manipulate the packets data in any way (hence the "const" declaration). This method flushes the TX queues + /// only when the last packet is sent + /// @param[in] rawPackets The raw packet vector + /// @return Number of raw packets that were sent completely int sendPackets(const RawPacketVector& rawPackets); // implement abstract methods - /** - * Opens the entire device (including all RX channels/queues on this interface). All packets will be received - * on a single thread without core affinity - * @return True if this action succeeds, false otherwise - */ + /// Opens the entire device (including all RX channels/queues on this interface). All packets will be received + /// on a single thread without core affinity + /// @return True if this action succeeds, false otherwise bool open(); - /** - * Closes all RX channels currently opened in device - */ + /// Closes all RX channels currently opened in device void close(); using IFilterableDevice::setFilter; - /** - * Sets a BPF filter to the device - * @param[in] filterAsString The BPF filter in string format - */ + /// Sets a BPF filter to the device + /// @param[in] filterAsString The BPF filter in string format bool setFilter(std::string filterAsString); - /** - * Remove a filter if currently set - * @return True if filter was removed successfully or if no filter was set, false otherwise - */ + /// Remove a filter if currently set + /// @return True if filter was removed successfully or if no filter was set, false otherwise bool clearFilter(); }; diff --git a/Pcap++/header/PfRingDeviceList.h b/Pcap++/header/PfRingDeviceList.h index f38928ad1a..6e364c59e6 100644 --- a/Pcap++/header/PfRingDeviceList.h +++ b/Pcap++/header/PfRingDeviceList.h @@ -6,18 +6,13 @@ /// @file -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class PfRingDeviceList - * A singleton class that holds all available PF_RING devices. Through this class the user can iterate all PF_RING - * devices or find a specific device by name - */ + /// @class PfRingDeviceList + /// A singleton class that holds all available PF_RING devices. Through this class the user can iterate all PF_RING + /// devices or find a specific device by name class PfRingDeviceList { private: @@ -33,36 +28,28 @@ namespace pcpp PfRingDeviceList& operator=(const PfRingDeviceList&) = delete; PfRingDeviceList& operator=(PfRingDeviceList&&) noexcept = delete; - /** - * A static method that returns the singleton object for PfRingDeviceList - * @return PfRingDeviceList singleton - */ + /// A static method that returns the singleton object for PfRingDeviceList + /// @return PfRingDeviceList singleton static PfRingDeviceList& getInstance() { static PfRingDeviceList instance; return instance; } - /** - * Return a list of all available PF_RING devices - * @return a list of all available PF_RING devices - */ + /// Return a list of all available PF_RING devices + /// @return a list of all available PF_RING devices const std::vector& getPfRingDevicesList() const { return m_PfRingDeviceListView; } - /** - * Get a PF_RING device by name. The name is the Linux interface name which appears in ifconfig - * (e.g eth0, eth1, etc.) - * @return A pointer to the PF_RING device - */ + /// Get a PF_RING device by name. The name is the Linux interface name which appears in ifconfig + /// (e.g eth0, eth1, etc.) + /// @return A pointer to the PF_RING device PfRingDevice* getPfRingDeviceByName(const std::string& devName) const; - /** - * Get installed PF_RING version - * @return A string representing PF_RING version - */ + /// Get installed PF_RING version + /// @return A string representing PF_RING version std::string getPfRingVersion() const { return m_PfRingVersion; diff --git a/Pcap++/header/RawSocketDevice.h b/Pcap++/header/RawSocketDevice.h index 254af4e186..8b69c84d87 100644 --- a/Pcap++/header/RawSocketDevice.h +++ b/Pcap++/header/RawSocketDevice.h @@ -5,144 +5,123 @@ #include "IpAddress.h" #include "Device.h" -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - /** - * @class RawSocketDevice - * A class that wraps the raw socket functionality. A raw socket is a network socket that allows direct sending and - * receiving of IP packets without any protocol-specific transport layer formatting (taken from Wikipedia: - * https://en.wikipedia.org/wiki/Network_socket#Raw_socket). This wrapper class enables creation of a raw socket, - * binding it to a network interface, and then receiving and sending packets on it. Current implementation supports - * only Windows and Linux because other platforms provide poor support for raw sockets making them practically - * unusable. There are also major differences between Linux and Windows in raw socket implementation, let's mention - * some of the: - * - On Windows administrative privileges are required for raw sockets creation, meaning the process running the - * code has to have these privileges. In Linux 'sudo' is required - * - On Windows raw sockets are implemented in L3, meaning the L2 (Ethernet) layer is omitted by the socket and - * only L3 and up are visible to the user. On Linux raw sockets are implemented on L2, meaning all layers - * (including the Ethernet data) are visible to the user. - * - On Windows sending packets is not supported, a raw socket can only receive packets. On Linux both send and - * receive are supported - * - Linux doesn't require binding to a specific network interface for receiving packets, but it does require - * binding for sending packets. Windows requires binding for receiving packets. For the sake of keeping a unified - * and simple cross-platform interface this class requires binding for both Linux and Windows, on both send and - * receive - * - * More details about opening the raw socket, receiving and sending packets are explained in the corresponding class - * methods. Raw sockets are supported for both IPv4 and IPv6, so you can create and bind raw sockets to each of the - * two. Also, there is no limit on the number of sockets opened for a specific IP address or network interface, so - * you can create multiple instances of this class and bind all of them to the same interface and IP address. - */ + /// @class RawSocketDevice + /// A class that wraps the raw socket functionality. A raw socket is a network socket that allows direct sending and + /// receiving of IP packets without any protocol-specific transport layer formatting (taken from Wikipedia: + /// https://en.wikipedia.org/wiki/Network_socket#Raw_socket). This wrapper class enables creation of a raw socket, + /// binding it to a network interface, and then receiving and sending packets on it. Current implementation supports + /// only Windows and Linux because other platforms provide poor support for raw sockets making them practically + /// unusable. There are also major differences between Linux and Windows in raw socket implementation, let's mention + /// some of the: + /// - On Windows administrative privileges are required for raw sockets creation, meaning the process running the + /// code has to have these privileges. In Linux 'sudo' is required + /// - On Windows raw sockets are implemented in L3, meaning the L2 (Ethernet) layer is omitted by the socket and + /// only L3 and up are visible to the user. On Linux raw sockets are implemented on L2, meaning all layers + /// (including the Ethernet data) are visible to the user. + /// - On Windows sending packets is not supported, a raw socket can only receive packets. On Linux both send and + /// receive are supported + /// - Linux doesn't require binding to a specific network interface for receiving packets, but it does require + /// binding for sending packets. Windows requires binding for receiving packets. For the sake of keeping a + /// unified and simple cross-platform interface this class requires binding for both Linux and Windows, on both + /// send and receive + /// + /// More details about opening the raw socket, receiving and sending packets are explained in the corresponding + /// class methods. Raw sockets are supported for both IPv4 and IPv6, so you can create and bind raw sockets to each + /// of the two. Also, there is no limit on the number of sockets opened for a specific IP address or network + /// interface, so you can create multiple instances of this class and bind all of them to the same interface and IP + /// address. class RawSocketDevice : public IDevice { public: - /** - * An enum for reporting packet receive results - */ + /// An enum for reporting packet receive results enum RecvPacketResult { - /** Receive success */ + /// Receive success RecvSuccess = 0, - /** Receive timeout - timeout expired without any packets being captured */ + /// Receive timeout - timeout expired without any packets being captured RecvTimeout = 1, - /** Receive would block - in non-blocking mode if there are no packets in the rx queue the receive method - * will return immediately with this return value */ + /// Receive would block - in non-blocking mode if there are no packets in the rx queue the receive method + /// will return immediately with this return value RecvWouldBlock = 2, - /** Receive error, usually will be followed by an error log */ + /// Receive error, usually will be followed by an error log RecvError = 3 }; - /* - * A c'tor for this class. This c'tor doesn't create the raw socket, but rather initializes internal structures. - * The actual raw socket creation is done in the open() method. Each raw socket is bound to a network interface - * which means packets will be received and sent from only from this network interface only - * @param[in] interfaceIP The network interface IP to bind the raw socket to. It can be either an IPv4 or IPv6 - * address (both are supported in raw sockets) - */ + /// A c'tor for this class. This c'tor doesn't create the raw socket, but rather initializes internal + /// structures. The actual raw socket creation is done in the open() method. Each raw socket is bound to a + /// network interface which means packets will be received and sent from only from this network interface only + /// @param[in] interfaceIP The network interface IP to bind the raw socket to. It can be either an IPv4 or IPv6 + /// address (both are supported in raw sockets) explicit RawSocketDevice(const IPAddress& interfaceIP); - /** - * A d'tor for this class. It closes the raw socket if not previously closed by calling close() - */ + /// A d'tor for this class. It closes the raw socket if not previously closed by calling close() ~RawSocketDevice(); - /** - * Receive a packet on the raw socket. This method has several modes of operation: - * - Blocking/non-blocking - in blocking mode the method will not return until a packet is received on the - * socket or until the timeout expires. In non-blocking mode it will return immediately and in case no - * packets are on the receive queue RawSocketDevice#RecvWouldBlock will be returned. Unless specified - * otherwise, the default value is blocking mode - * - Receive timeout - in blocking mode, the user can set a timeout to wait until a packet is received. If the - * timeout expires and no packets were received, the method will return RawSocketDevice#RecvTimeout. The - * default value is a negative value which means no timeout - * - * There is a slight difference on this method's behavior between Windows and Linux around how packets are - * received. On Linux the received packet contains all layers starting from the L2 (Ethernet). However on - * Windows raw socket are integrated in L3 level so the received packet contains only L3 (IP) layer and up. - * @param[out] rawPacket An empty packet instance where the received packet data will be written to - * @param[in] blocking Indicates whether to run in blocking or non-blocking mode. Default value is blocking - * @param[in] timeout When in blocking mode, specifies the timeout [in seconds] to wait for a packet. If timeout - * expired and no packets were captured the method will return RawSocketDevice#RecvTimeout. Zero or negative - * values mean no timeout. The default value is no timeout. The timeout precision is in milliseconds, for - * example a timeout of 0.123 means 123 milliseconds. - * @return The method returns one on the following values: - * - RawSocketDevice#RecvSuccess is returned if a packet was received successfully - * - RawSocketDevice#RecvTimeout is returned if in blocking mode and timeout expired - * - RawSocketDevice#RecvWouldBlock is returned if in non-blocking mode and no packets were captured - * - RawSocketDevice#RecvError is returned if an error occurred such as device is not opened or the recv - * operation returned some error. A log message will be followed specifying the error and error code - */ + /// Receive a packet on the raw socket. This method has several modes of operation: + /// - Blocking/non-blocking - in blocking mode the method will not return until a packet is received on the + /// socket or until the timeout expires. In non-blocking mode it will return immediately and in case no + /// packets are on the receive queue RawSocketDevice#RecvWouldBlock will be returned. Unless specified + /// otherwise, the default value is blocking mode + /// - Receive timeout - in blocking mode, the user can set a timeout to wait until a packet is received. If the + /// timeout expires and no packets were received, the method will return RawSocketDevice#RecvTimeout. The + /// default value is a negative value which means no timeout + /// + /// There is a slight difference on this method's behavior between Windows and Linux around how packets are + /// received. On Linux the received packet contains all layers starting from the L2 (Ethernet). However on + /// Windows raw socket are integrated in L3 level so the received packet contains only L3 (IP) layer and up. + /// @param[out] rawPacket An empty packet instance where the received packet data will be written to + /// @param[in] blocking Indicates whether to run in blocking or non-blocking mode. Default value is blocking + /// @param[in] timeout When in blocking mode, specifies the timeout [in seconds] to wait for a packet. If + /// timeout expired and no packets were captured the method will return RawSocketDevice#RecvTimeout. Zero or + /// negative values mean no timeout. The default value is no timeout. The timeout precision is in milliseconds, + /// for example a timeout of 0.123 means 123 milliseconds. + /// @return The method returns one on the following values: + /// - RawSocketDevice#RecvSuccess is returned if a packet was received successfully + /// - RawSocketDevice#RecvTimeout is returned if in blocking mode and timeout expired + /// - RawSocketDevice#RecvWouldBlock is returned if in non-blocking mode and no packets were captured + /// - RawSocketDevice#RecvError is returned if an error occurred such as device is not opened or the recv + /// operation returned some error. A log message will be followed specifying the error and error code RecvPacketResult receivePacket(RawPacket& rawPacket, bool blocking = true, double timeout = -1); - /** - * Receive packets into a packet vector for a certain amount of time. This method starts a timer and invokes the - * receivePacket() method in blocking mode repeatedly until the timeout expires. All packets received - * successfully are put into a packet vector - * @param[out] packetVec The packet vector to add the received packet to - * @param[in] timeout Timeout in seconds to receive packets on the raw socket. The timeout precision is in - * milliseconds, for example a timeout of 0.123 means 123 milliseconds. - * @param[out] failedRecv Number of receive attempts that failed - * @return The number of packets received successfully - */ + /// Receive packets into a packet vector for a certain amount of time. This method starts a timer and invokes + /// the receivePacket() method in blocking mode repeatedly until the timeout expires. All packets received + /// successfully are put into a packet vector + /// @param[out] packetVec The packet vector to add the received packet to + /// @param[in] timeout Timeout in seconds to receive packets on the raw socket. The timeout precision is in + /// milliseconds, for example a timeout of 0.123 means 123 milliseconds. + /// @param[out] failedRecv Number of receive attempts that failed + /// @return The number of packets received successfully int receivePackets(RawPacketVector& packetVec, double timeout, int& failedRecv); - /** - * Send an Ethernet packet to the network. L2 protocols other than Ethernet are not supported in raw sockets. - * The entire packet is sent as is, including the original Ethernet and IP data. - * This method is only supported in Linux as Windows doesn't allow sending packets from raw sockets. Using - * it from other platforms will also return "false" with a corresponding error log message - * @param[in] rawPacket The packet to send - * @return True if packet was sent successfully or false if the socket is not open, if the packet is not - * Ethernet or if there was a failure sending the packet - */ + /// Send an Ethernet packet to the network. L2 protocols other than Ethernet are not supported in raw sockets. + /// The entire packet is sent as is, including the original Ethernet and IP data. + /// This method is only supported in Linux as Windows doesn't allow sending packets from raw sockets. Using + /// it from other platforms will also return "false" with a corresponding error log message + /// @param[in] rawPacket The packet to send + /// @return True if packet was sent successfully or false if the socket is not open, if the packet is not + /// Ethernet or if there was a failure sending the packet bool sendPacket(const RawPacket* rawPacket); - /** - * Send a set of Ethernet packets to the network. L2 protocols other than Ethernet are not supported by raw - * sockets. The entire packet is sent as is, including the original Ethernet and IP data. This method is only - * supported in Linux as Windows doesn't allow sending packets from raw sockets. Using it from other platforms - * will return "false" with an appropriate error log message - * @param[in] packetVec The set of packets to send - * @return The number of packets sent successfully. For packets that weren't sent successfully there will be a - * corresponding error message printed to log - */ + /// Send a set of Ethernet packets to the network. L2 protocols other than Ethernet are not supported by raw + /// sockets. The entire packet is sent as is, including the original Ethernet and IP data. This method is only + /// supported in Linux as Windows doesn't allow sending packets from raw sockets. Using it from other platforms + /// will return "false" with an appropriate error log message + /// @param[in] packetVec The set of packets to send + /// @return The number of packets sent successfully. For packets that weren't sent successfully there will be a + /// corresponding error message printed to log int sendPackets(const RawPacketVector& packetVec); // overridden methods - /** - * Open the device by creating a raw socket and binding it to the network interface specified in the c'tor - * @return True if device was opened successfully, false otherwise with a corresponding error log message - */ + /// Open the device by creating a raw socket and binding it to the network interface specified in the c'tor + /// @return True if device was opened successfully, false otherwise with a corresponding error log message bool open() override; - /** - * Close the raw socket - */ + /// Close the raw socket void close() override; private: diff --git a/Pcap++/header/WinPcapLiveDevice.h b/Pcap++/header/WinPcapLiveDevice.h index c199428e32..7b91c9b877 100644 --- a/Pcap++/header/WinPcapLiveDevice.h +++ b/Pcap++/header/WinPcapLiveDevice.h @@ -4,20 +4,15 @@ #include "PcapLiveDevice.h" -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @brief The main namespace for the PcapPlusPlus lib namespace pcpp { - - /** - * @class WinPcapLiveDevice - * A class that wraps a Windows network interface (each of the interfaces listed in ipconfig). - * This class is almost similar in its capabilities to PcapLiveDevice (its parent class) with some small changes - * that mainly result from differences between libpcap and WinPcap/Npcap. Please see the reference for - * PcapLiveDevice for more details - */ + /// @class WinPcapLiveDevice + /// A class that wraps a Windows network interface (each of the interfaces listed in ipconfig). + /// This class is almost similar in its capabilities to PcapLiveDevice (its parent class) with some small changes + /// that mainly result from differences between libpcap and WinPcap/Npcap. Please see the reference for + /// PcapLiveDevice for more details class WinPcapLiveDevice : public PcapLiveDevice { friend class PcapLiveDeviceList; @@ -55,20 +50,16 @@ namespace pcpp using PcapLiveDevice::sendPackets; virtual int sendPackets(RawPacket* rawPacketsArr, int arrLength); - /** - * WinPcap/Npcap have a feature (that doesn't exist in libpcap) to change the minimum amount of data in the - * kernel buffer that causes a read from the application to return (unless the timeout expires). Please see - * documentation for pcap_setmintocopy for more info. This method enables the user to change this size. Note the - * device must be open for this method to work - * @param[in] size The size to set in bytes - * @return True if set succeeded, false if the device is closed or if pcap_setmintocopy failed - */ + /// WinPcap/Npcap have a feature (that doesn't exist in libpcap) to change the minimum amount of data in the + /// kernel buffer that causes a read from the application to return (unless the timeout expires). Please see + /// documentation for pcap_setmintocopy for more info. This method enables the user to change this size. Note + /// the device must be open for this method to work + /// @param[in] size The size to set in bytes + /// @return True if set succeeded, false if the device is closed or if pcap_setmintocopy failed bool setMinAmountOfDataToCopyFromKernelToApplication(int size); - /** - * @return The current amount of data in the kernel buffer that causes a read from the application to return - * (see also setMinAmountOfDataToCopyFromKernelToApplication()) - */ + /// @return The current amount of data in the kernel buffer that causes a read from the application to return + /// (see also setMinAmountOfDataToCopyFromKernelToApplication()) int getMinAmountOfDataToCopyFromKernelToApplication() const { return m_MinAmountOfDataToCopyFromKernelToApplication; @@ -76,5 +67,4 @@ namespace pcpp WinPcapLiveDevice* clone() const override; }; - } // namespace pcpp diff --git a/Pcap++/header/XdpDevice.h b/Pcap++/header/XdpDevice.h index 7e573e2304..e60498d505 100644 --- a/Pcap++/header/XdpDevice.h +++ b/Pcap++/header/XdpDevice.h @@ -6,112 +6,86 @@ #include #include -/** - * \namespace pcpp - * \brief The main namespace for the PcapPlusPlus lib - */ +/// @namespace pcpp +/// @ namespace pcpp { - /** - * @class XdpDevice - * A class wrapping the main functionality of using AF_XDP (XSK) sockets - * which are optimized for high performance packet processing. - * - * It provides methods for configuring and initializing an AF_XDP socket, and then send and receive packets through - * it. It also provides a method for gathering statistics from the socket. - */ + /// @class XdpDevice + /// A class wrapping the main functionality of using AF_XDP (XSK) sockets + /// which are optimized for high performance packet processing. + /// + /// It provides methods for configuring and initializing an AF_XDP socket, and then send and receive packets through + /// it. It also provides a method for gathering statistics from the socket. class XdpDevice : public IDevice { public: - /** - * @typedef OnPacketsArrive - * The callback that is called whenever packets are received on the socket - * @param[in] packets An array of the raw packets received - * @param[in] packetCount The number of packets received - * @param[in] device The XdpDevice packets are received from (represents the AF_XDP socket) - * @param[in] userCookie A pointer to an object set by the user when receivePackets() started - */ + /// @typedef OnPacketsArrive + /// The callback that is called whenever packets are received on the socket + /// @param[in] packets An array of the raw packets received + /// @param[in] packetCount The number of packets received + /// @param[in] device The XdpDevice packets are received from (represents the AF_XDP socket) + /// @param[in] userCookie A pointer to an object set by the user when receivePackets() started typedef void (*OnPacketsArrive)(RawPacket packets[], uint32_t packetCount, XdpDevice* device, void* userCookie); - /** - * @struct XdpDeviceConfiguration - * A struct containing the configuration parameters available for opening an XDP device - */ + /// @struct XdpDeviceConfiguration + /// A struct containing the configuration parameters available for opening an XDP device struct XdpDeviceConfiguration { - /** - * @enum AttachMode - * AF_XDP operation mode - */ + /// @enum AttachMode + /// AF_XDP operation mode enum AttachMode { - /** A fallback mode that works for any network device. Use it if the network driver doesn't have support - * for XDP */ + /// A fallback mode that works for any network device. Use it if the network driver doesn't have support + /// for XDP SkbMode = 1, - /** Use this mode if the network driver has support for XDP */ + /// Use this mode if the network driver has support for XDP DriverMode = 2, - /** Automatically detect whether driver mode is supported, otherwise fallback to SKB mode */ + /// Automatically detect whether driver mode is supported, otherwise fallback to SKB mode AutoMode = 3 }; - /** AF_XDP operation mode */ + /// AF_XDP operation mode AttachMode attachMode; - /** - * UMEM is a region of virtual contiguous memory, divided into equal-sized frames. - * This parameter determines the number of frames that will be allocated as pert of the UMEM. - **/ + /// UMEM is a region of virtual contiguous memory, divided into equal-sized frames. + /// This parameter determines the number of frames that will be allocated as pert of the UMEM. uint16_t umemNumFrames; - /** - * UMEM is a region of virtual contiguous memory, divided into equal-sized frames. - * This parameter determines the frame size that will be allocated. - * NOTE: the frame size should be equal to the memory page size (use getpagesize() to determine this size) - **/ + /// UMEM is a region of virtual contiguous memory, divided into equal-sized frames. + /// This parameter determines the frame size that will be allocated. + /// NOTE: the frame size should be equal to the memory page size (use getpagesize() to determine this size) uint16_t umemFrameSize; - /** - * The size of the fill ring used by the AF_XDP socket. This size should be a power of two - * and less or equal to the total number of UMEM frames - */ + /// The size of the fill ring used by the AF_XDP socket. This size should be a power of two + /// and less or equal to the total number of UMEM frames uint32_t fillRingSize; - /** - * The size of the completion ring used by the AF_XDP socket. This size should be a power of two - * and less or equal to the total number of UMEM frames - */ + /// The size of the completion ring used by the AF_XDP socket. This size should be a power of two + /// and less or equal to the total number of UMEM frames uint32_t completionRingSize; - /** - * The size of the RX ring used by the AF_XDP socket. This size should be a power of two - * and less or equal to the total number of UMEM frames - */ + /// The size of the RX ring used by the AF_XDP socket. This size should be a power of two + /// and less or equal to the total number of UMEM frames uint32_t rxSize; - /** - * The size of the TX ring used by the AF_XDP socket. This size should be a power of two - * and less or equal to the total number of UMEM frames - */ + /// The size of the TX ring used by the AF_XDP socket. This size should be a power of two + /// and less or equal to the total number of UMEM frames uint32_t txSize; - /** - * The max number of packets to be received or sent in one batch - */ + /// The max number of packets to be received or sent in one batch uint16_t rxTxBatchSize; - /** - * A c'tor for this struct. Each parameter has a default value described below. - * @param[in] attachMode AF_XDP operation mode. The default value is auto mode - * @param[in] umemNumFrames Number of UMEM frames to allocate. The default value is 4096 - * @param[in] umemFrameSize The size of each UMEM frame. The default value is equal to getpagesize() - * @param[in] fillRingSize The size of the fill ring used by the AF_XDP socket. The default value is 4096 - * @param[in] completionRingSize The size of the completion ring used by the AF_XDP socket. The default - * value is 2048 - * @param[in] rxSize The size of the RX ring used by the AF_XDP socket. The default value is 2048 - * @param[in] txSize The size of the TX ring used by the AF_XDP socket. The default value is 2048 - * @param[in] rxTxBatchSize The max number of packets to be received or sent in one batch. The default value - * is 64 - */ + /// A c'tor for this struct. Each parameter has a default value described below. + /// @param[in] attachMode AF_XDP operation mode. The default value is auto mode + /// @param[in] umemNumFrames Number of UMEM frames to allocate. The default value is 4096 + /// @param[in] umemFrameSize The size of each UMEM frame. The default value is equal to getpagesize() + /// @param[in] fillRingSize The size of the fill ring used by the AF_XDP socket. The default value is 4096 + /// @param[in] completionRingSize The size of the completion ring used by the AF_XDP socket. The default + /// value is 2048 + /// @param[in] rxSize The size of the RX ring used by the AF_XDP socket. The default value is 2048 + /// @param[in] txSize The size of the TX ring used by the AF_XDP socket. The default value is 2048 + /// @param[in] rxTxBatchSize The max number of packets to be received or sent in one batch. The default + /// value is 64 explicit XdpDeviceConfiguration(AttachMode attachMode = AutoMode, uint16_t umemNumFrames = 0, uint16_t umemFrameSize = 0, uint32_t fillRingSize = 0, uint32_t completionRingSize = 0, uint32_t rxSize = 0, uint32_t txSize = 0, @@ -128,156 +102,133 @@ namespace pcpp } }; - /** - * @struct XdpDeviceStats - * A container for XDP device statistics - */ + /// @struct XdpDeviceStats + /// A container for XDP device statistics struct XdpDeviceStats { - /** The timestamp when the stats were collected */ + /// The timestamp when the stats were collected timespec timestamp; - /** Number of packets received */ + /// Number of packets received uint64_t rxPackets; - /** Packets received per second. Measured from to the previous time stats were collected */ + /// Packets received per second. Measured from to the previous time stats were collected uint64_t rxPacketsPerSec; - /** Number of bytes received */ + /// Number of bytes received uint64_t rxBytes; - /** Bytes per second received. Measured from to the previous time stats were collected */ + /// Bytes per second received. Measured from to the previous time stats were collected uint64_t rxBytesPerSec; - /** Total number of dropped RX packets */ + /// Total number of dropped RX packets uint64_t rxDroppedTotalPackets; - /** RX packets dropped due to invalid descriptor */ + /// RX packets dropped due to invalid descriptor uint64_t rxDroppedInvalidPackets; - /** RX packets dropped due to RX ring being full */ + /// RX packets dropped due to RX ring being full uint64_t rxDroppedRxRingFullPackets; - /** Failed RX packets to retrieve item from fill ring */ + /// Failed RX packets to retrieve item from fill ring uint64_t rxDroppedFillRingPackets; - /** Number of poll() timeouts */ + /// Number of poll() timeouts uint64_t rxPollTimeout; - /** Number of packets sent from the application */ + /// Number of packets sent from the application uint64_t txSentPackets; - /** Packets sent from the app per second. Measured from to the previous time stats were collected */ + /// Packets sent from the app per second. Measured from to the previous time stats were collected uint64_t txSentPacketsPerSec; - /** Number of bytes sent from the application */ + /// Number of bytes sent from the application uint64_t txSentBytes; - /** Bytes per second sent from the app. Measured from to the previous time stats were collected */ + /// Bytes per second sent from the app. Measured from to the previous time stats were collected uint64_t txSentBytesPerSec; - /** Number of completed sent packets, meaning packets that were confirmed as sent by the kernel */ + /// Number of completed sent packets, meaning packets that were confirmed as sent by the kernel uint64_t txCompletedPackets; - /** Completed sent packets per second. Measured from to the previous time stats were collected */ + /// Completed sent packets per second. Measured from to the previous time stats were collected uint64_t txCompletedPacketsPerSec; - /** TX packets dropped due to invalid descriptor */ + /// TX packets dropped due to invalid descriptor uint64_t txDroppedInvalidPackets; - /** Current RX ring ID */ + /// Current RX ring ID uint64_t rxRingId; - /** Current TX ring ID */ + /// Current TX ring ID uint64_t txRingId; - /** Current fill ring ID */ + /// Current fill ring ID uint64_t fqRingId; - /** Current completion ring ID */ + /// Current completion ring ID uint64_t cqRingId; - /** Number of UMEM frames that are currently in-use (allocated) */ + /// Number of UMEM frames that are currently in-use (allocated) uint64_t umemAllocatedFrames; - /** Number of UMEM frames that are currently free (not allocated) */ + /// Number of UMEM frames that are currently free (not allocated) uint64_t umemFreeFrames; }; - /** - * A c'tor for this class. Please note that calling this c'tor doesn't initialize the AF_XDP socket. In order to - * set up the socket call open(). - * @param[in] interfaceName The interface name to open the AF_XDP socket on - */ + /// A c'tor for this class. Please note that calling this c'tor doesn't initialize the AF_XDP socket. In order + /// to set up the socket call open(). + /// @param[in] interfaceName The interface name to open the AF_XDP socket on explicit XdpDevice(std::string interfaceName); - /** - * A d'tor for this class. It closes the device if it's open. - */ + /// A d'tor for this class. It closes the device if it's open. ~XdpDevice() override; - /** - * Open the device with default configuration. Call getConfig() after opening the device to get the - * current configuration. - * This method initializes the UMEM, and then creates and configures the AF_XDP socket. If it succeeds the - * socket is ready to receive and send packets. - * @return True if device was opened successfully, false otherwise - */ + /// Open the device with default configuration. Call getConfig() after opening the device to get the + /// current configuration. + /// This method initializes the UMEM, and then creates and configures the AF_XDP socket. If it succeeds the + /// socket is ready to receive and send packets. + /// @return True if device was opened successfully, false otherwise bool open() override; - /** - * Open the device with custom configuration set by the user. - * This method initializes the UMEM, and then creates and configures the AF_XDP socket. If it succeeds the - * socket is ready to receive and send packets. - * @param[in] config The configuration to use for opening the device - * @return True if device was opened successfully, false otherwise - */ + /// Open the device with custom configuration set by the user. + /// This method initializes the UMEM, and then creates and configures the AF_XDP socket. If it succeeds the + /// socket is ready to receive and send packets. + /// @param[in] config The configuration to use for opening the device + /// @return True if device was opened successfully, false otherwise bool open(const XdpDeviceConfiguration& config); - /** - * Close the device. This method closes the AF_XDP socket and frees the UMEM that was allocated for it. - */ + /// Close the device. This method closes the AF_XDP socket and frees the UMEM that was allocated for it. void close() override; - /** - * Start receiving packets. In order to use this method the device should be open. Note that this method is - * blocking and will return if: - * - stopReceivePackets() was called from within the user callback - * - timeoutMS passed without receiving any packets - * - Some error occurred (an error log will be printed) - * @param[in] onPacketsArrive A callback to be called when packets are received - * @param[in] onPacketsArriveUserCookie The callback is invoked with this cookie as a parameter. It can be used - * to pass information from the user application to the callback - * @param[in] timeoutMS Timeout in milliseconds to stop if no packets are received. The default value is 5000 ms - * @return True if stopped receiving packets because stopReceivePackets() was called or because timeoutMS - * passed, or false if an error occurred. - */ + /// Start receiving packets. In order to use this method the device should be open. Note that this method is + /// blocking and will return if: + /// - stopReceivePackets() was called from within the user callback + /// - timeoutMS passed without receiving any packets + /// - Some error occurred (an error log will be printed) + /// @param[in] onPacketsArrive A callback to be called when packets are received + /// @param[in] onPacketsArriveUserCookie The callback is invoked with this cookie as a parameter. It can be used + /// to pass information from the user application to the callback + /// @param[in] timeoutMS Timeout in milliseconds to stop if no packets are received. The default value is 5000 + /// ms + /// @return True if stopped receiving packets because stopReceivePackets() was called or because timeoutMS + /// passed, or false if an error occurred. bool receivePackets(OnPacketsArrive onPacketsArrive, void* onPacketsArriveUserCookie, int timeoutMS = 5000); - /** - * Stop receiving packets. Call this method from within the callback passed to receivePackets() whenever you - * want to stop receiving packets. - */ + /// Stop receiving packets. Call this method from within the callback passed to receivePackets() whenever you + /// want to stop receiving packets. void stopReceivePackets(); - /** - * Send a vector of packet pointers. - * @param[in] packets A vector of packet pointers to send - * @param[in] waitForTxCompletion Wait for confirmation from the kernel that packets were sent. If set to true - * this method will wait until the number of packets in the completion ring is equal or greater to the number - * of packets that were sent. The default value is false - * @param[in] waitForTxCompletionTimeoutMS If waitForTxCompletion is set to true, poll the completion ring with - * this timeout. The default value is 5000 ms - * @return True if all packets were sent, or if waitForTxCompletion is true - all sent packets were confirmed. - * Returns false if an error occurred or if poll timed out. - */ + /// Send a vector of packet pointers. + /// @param[in] packets A vector of packet pointers to send + /// @param[in] waitForTxCompletion Wait for confirmation from the kernel that packets were sent. If set to true + /// this method will wait until the number of packets in the completion ring is equal or greater to the number + /// of packets that were sent. The default value is false + /// @param[in] waitForTxCompletionTimeoutMS If waitForTxCompletion is set to true, poll the completion ring with + /// this timeout. The default value is 5000 ms + /// @return True if all packets were sent, or if waitForTxCompletion is true - all sent packets were confirmed. + /// Returns false if an error occurred or if poll timed out. bool sendPackets(const RawPacketVector& packets, bool waitForTxCompletion = false, int waitForTxCompletionTimeoutMS = 5000); - /** - * Send an array of packets. - * @param[in] packets An array of raw packets to send - * @param[in] packetCount The length of the packet array - * @param[in] waitForTxCompletion Wait for confirmation from the kernel that packets were sent. If set to true - * this method will wait until the number of packets in the completion ring is equal or greater to the number - * of packets sent. The default value is false - * @param[in] waitForTxCompletionTimeoutMS If waitForTxCompletion is set to true, poll the completion ring with - * this timeout. The default value is 5000 ms - * @return True if all packets were sent, or if waitForTxCompletion is true - all sent packets were confirmed. - * Returns false if an error occurred or if poll timed out. - */ + /// Send an array of packets. + /// @param[in] packets An array of raw packets to send + /// @param[in] packetCount The length of the packet array + /// @param[in] waitForTxCompletion Wait for confirmation from the kernel that packets were sent. If set to true + /// this method will wait until the number of packets in the completion ring is equal or greater to the number + /// of packets sent. The default value is false + /// @param[in] waitForTxCompletionTimeoutMS If waitForTxCompletion is set to true, poll the completion ring with + /// this timeout. The default value is 5000 ms + /// @return True if all packets were sent, or if waitForTxCompletion is true - all sent packets were confirmed. + /// Returns false if an error occurred or if poll timed out. bool sendPackets(RawPacket packets[], size_t packetCount, bool waitForTxCompletion = false, int waitForTxCompletionTimeoutMS = 5000); - /** - * @return A pointer to the current device configuration. If the device is not open this method returns nullptr - */ + /// @return A pointer to the current device configuration. If the device is not open this method returns nullptr XdpDeviceConfiguration* getConfig() const { return m_Config; } - /** - * @return Current device statistics - */ + /// @return Current device statistics XdpDeviceStats getStatistics(); private: diff --git a/Pcap++/src/DpdkDevice.cpp b/Pcap++/src/DpdkDevice.cpp index bb4b025733..fadf38de76 100644 --- a/Pcap++/src/DpdkDevice.cpp +++ b/Pcap++/src/DpdkDevice.cpp @@ -34,18 +34,16 @@ namespace pcpp { - /** - * ================ - * Class DpdkDevice - * ================ - */ + /// ================ + /// Class DpdkDevice + /// ================ -#define DPDK_CONFIG_HEADER_SPLIT 0 /**< Header Split disabled */ +#define DPDK_CONFIG_HEADER_SPLIT 0 ///< Header Split disabled #define DPDK_CONFIG_SPLIT_HEADER_SIZE 0 -#define DPDK_CONFIG_HW_IP_CHECKSUM 0 /**< IP checksum offload disabled */ -#define DPDK_CONFIG_HW_VLAN_FILTER 0 /**< VLAN filtering disabled */ -#define DPDK_CONFIG_JUMBO_FRAME 0 /**< Jumbo Frame Support disabled */ -#define DPDK_CONFIG_HW_STRIP_CRC 0 /**< CRC stripped by hardware disabled */ +#define DPDK_CONFIG_HW_IP_CHECKSUM 0 ///< IP checksum offload disabled +#define DPDK_CONFIG_HW_VLAN_FILTER 0 ///< VLAN filtering disabled +#define DPDK_CONFIG_JUMBO_FRAME 0 ///< Jumbo Frame Support disabled +#define DPDK_CONFIG_HW_STRIP_CRC 0 ///< CRC stripped by hardware disabled #if (RTE_VER_YEAR < 21) || (RTE_VER_YEAR == 21 && RTE_VER_MONTH < 11) # define DPDK_CONFIG_ETH_LINK_FULL_DUPLEX ETH_LINK_FULL_DUPLEX # define DPDK_CONFIG_MQ_RSS ETH_RSS @@ -929,8 +927,8 @@ namespace pcpp return 0; } - struct rte_mbuf* mBufArray[rawPacketArrLength]; - uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, rawPacketArrLength); + std::vector mBufArray(rawPacketArrLength); + uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray.data(), rawPacketArrLength); if (unlikely(!packetsReceived)) { @@ -972,8 +970,8 @@ namespace pcpp return 0; } - struct rte_mbuf* mBufArray[packetsArrLength]; - uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, packetsArrLength); + std::vector mBufArray(packetsArrLength); + uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray.data(), packetsArrLength); if (unlikely(!packetsReceived)) { @@ -1133,9 +1131,9 @@ namespace pcpp uint16_t DpdkDevice::sendPackets(Packet** packetsArr, uint16_t arrLength, uint16_t txQueueId, bool useTxBuffer) { - rte_mbuf* mBufArr[arrLength]; + std::vector mBufArr(arrLength); MBufRawPacketVector mBufVec; - MBufRawPacket* mBufRawPacketArr[arrLength]; + std::vector mBufRawPacketArr(arrLength); for (size_t i = 0; i < arrLength; i++) { @@ -1162,7 +1160,7 @@ namespace pcpp } uint16_t packetsSent = - sendPacketsInner(txQueueId, (void*)mBufArr, getNextPacketFromMBufArray, arrLength, useTxBuffer); + sendPacketsInner(txQueueId, (void*)mBufArr.data(), getNextPacketFromMBufArray, arrLength, useTxBuffer); bool needToFreeMbuf = (!useTxBuffer && (packetsSent != arrLength)); for (int index = 0; index < arrLength; index++) @@ -1174,8 +1172,8 @@ namespace pcpp uint16_t DpdkDevice::sendPackets(RawPacketVector& rawPacketsVec, uint16_t txQueueId, bool useTxBuffer) { size_t vecSize = rawPacketsVec.size(); - rte_mbuf* mBufArr[vecSize]; - MBufRawPacket* mBufRawPacketArr[vecSize]; + std::vector mBufArr(vecSize); + std::vector mBufRawPacketArr(vecSize); MBufRawPacketVector mBufVec; int mBufIndex = 0; @@ -1204,7 +1202,7 @@ namespace pcpp } uint16_t packetsSent = - sendPacketsInner(txQueueId, (void*)mBufArr, getNextPacketFromMBufArray, vecSize, useTxBuffer); + sendPacketsInner(txQueueId, (void*)mBufArr.data(), getNextPacketFromMBufArray, vecSize, useTxBuffer); bool needToFreeMbuf = (!useTxBuffer && (packetsSent != vecSize)); for (size_t index = 0; index < rawPacketsVec.size(); index++) diff --git a/Pcap++/src/DpdkDeviceList.cpp b/Pcap++/src/DpdkDeviceList.cpp index f41d1bba9e..9331734707 100644 --- a/Pcap++/src/DpdkDeviceList.cpp +++ b/Pcap++/src/DpdkDeviceList.cpp @@ -121,7 +121,7 @@ namespace pcpp // Should be equal to the number of static params initDpdkArgc += 7; - std::string dpdkParamsArray[initDpdkArgc]; + std::vector dpdkParamsArray(initDpdkArgc); initDpdkArgvBuffer = new char*[initDpdkArgc]; i = 0; while (dpdkParamsStream.good() && i < initDpdkArgc) diff --git a/Pcap++/src/KniDevice.cpp b/Pcap++/src/KniDevice.cpp index 832bda282c..0adc8a73eb 100644 --- a/Pcap++/src/KniDevice.cpp +++ b/Pcap++/src/KniDevice.cpp @@ -41,11 +41,9 @@ namespace pcpp { - /** - * ========================== - * Class KniDevice::KniThread - * ========================== - */ + /// ========================== + /// Class KniDevice::KniThread + /// ========================== struct KniDevice::KniThread { @@ -90,11 +88,9 @@ namespace pcpp m_StopThread = true; } - /** - * =============== - * Class KniDevice - * =============== - */ + /// =============== + /// Class KniDevice + /// =============== namespace { @@ -960,9 +956,9 @@ namespace pcpp case LINK_ERROR: return m_DeviceOpened = false; case LINK_NOT_SUPPORTED: - /* fall through */ + // fall through case LINK_DOWN: - /* fall through */ + // fall through case LINK_UP: return m_DeviceOpened = true; } diff --git a/Pcap++/src/KniDeviceList.cpp b/Pcap++/src/KniDeviceList.cpp index 36a0856639..1b639c14f9 100644 --- a/Pcap++/src/KniDeviceList.cpp +++ b/Pcap++/src/KniDeviceList.cpp @@ -21,11 +21,9 @@ namespace pcpp { - /** - * =================== - * Class KniDeviceList - * =================== - */ + /// =================== + /// Class KniDeviceList + /// =================== static inline bool checkKniDriver() { @@ -153,11 +151,11 @@ namespace pcpp switch (cbType) { case KniDeviceList::CALLBACK_MTU: - /* fall through */ + // fall through case KniDeviceList::CALLBACK_LINK: return true; case KniDeviceList::CALLBACK_MAC: - /* fall through */ + // fall through case KniDeviceList::CALLBACK_PROMISC: #if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) return true; diff --git a/Pcap++/src/MBufRawPacket.cpp b/Pcap++/src/MBufRawPacket.cpp index fc271f0d64..9389a209f7 100644 --- a/Pcap++/src/MBufRawPacket.cpp +++ b/Pcap++/src/MBufRawPacket.cpp @@ -23,11 +23,9 @@ namespace pcpp { - /** - * =================== - * Class MBufRawPacket - * =================== - */ + /// =================== + /// Class MBufRawPacket + /// =================== MBufRawPacket::~MBufRawPacket() { diff --git a/Pcap++/src/NetworkUtils.cpp b/Pcap++/src/NetworkUtils.cpp index 6e595adfc8..75a19e5de8 100644 --- a/Pcap++/src/NetworkUtils.cpp +++ b/Pcap++/src/NetworkUtils.cpp @@ -1,4 +1,4 @@ -#define LOG_MODULE NetworkUtils +#define LOG_MODULE PcapLogModuleNetworkUtils #include #include @@ -57,7 +57,7 @@ namespace pcpp return; // verify it's the right ARP response - if (arpReplyLayer->getArpHeader()->hardwareType != htobe16(1) /* Ethernet */ + if (arpReplyLayer->getArpHeader()->hardwareType != htobe16(1) // Ethernet || arpReplyLayer->getArpHeader()->protocolType != htobe16(PCPP_ETHERTYPE_IP)) return; @@ -215,7 +215,7 @@ namespace pcpp return; // verify it's the right DNS response - if (dnsResponseLayer->getDnsHeader()->queryOrResponse != 1 /* DNS response */ + if (dnsResponseLayer->getDnsHeader()->queryOrResponse != 1 // DNS response || dnsResponseLayer->getDnsHeader()->numberOfAnswers < htobe16(1) || dnsResponseLayer->getDnsHeader()->transactionID != htobe16(data->transactionID)) { diff --git a/Pcap++/src/PcapDevice.cpp b/Pcap++/src/PcapDevice.cpp index f546be634c..c72585dd3a 100644 --- a/Pcap++/src/PcapDevice.cpp +++ b/Pcap++/src/PcapDevice.cpp @@ -82,10 +82,8 @@ namespace pcpp PCPP_LOG_DEBUG("Compiling the filter '" << filterAsString << "'"); if (pcap_compile(m_PcapDescriptor.get(), &prog, filterAsString.c_str(), 1, 0) < 0) { - /* - * Print out appropriate text, followed by the error message - * generated by the packet capture library. - */ + // Print out appropriate text, followed by the error message + // generated by the packet capture library. PCPP_LOG_ERROR("Error compiling filter. Error message is: " << m_PcapDescriptor.getLastError()); return false; } @@ -93,11 +91,9 @@ namespace pcpp PCPP_LOG_DEBUG("Setting the compiled filter"); if (pcap_setfilter(m_PcapDescriptor.get(), &prog) < 0) { - /* - * Print out error. The format will be the prefix string, - * created above, followed by the error message that the packet - * capture library generates. - */ + // Print out error. The format will be the prefix string, + // created above, followed by the error message that the packet + // capture library generates. PCPP_LOG_ERROR("Error setting a compiled filter. Error message is: " << m_PcapDescriptor.getLastError()); pcap_freecode(&prog); return false; diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index d37997e5ca..079d2ab2cc 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -166,15 +166,15 @@ namespace pcpp // From https://datatracker.ietf.org/doc/html/rfc1761 static const pcpp::LinkLayerType snoop_encap[] = { - LINKTYPE_ETHERNET, /* IEEE 802.3 */ - LINKTYPE_NULL, /* IEEE 802.4 Token Bus */ - LINKTYPE_IEEE802_5, /* IEEE 802.5 */ - LINKTYPE_NULL, /* IEEE 802.6 Metro Net */ - LINKTYPE_ETHERNET, /* Ethernet */ - LINKTYPE_C_HDLC, /* HDLC */ - LINKTYPE_NULL, /* Character Synchronous, e.g. bisync */ - LINKTYPE_NULL, /* IBM Channel-to-Channel */ - LINKTYPE_FDDI /* FDDI */ + LINKTYPE_ETHERNET, /// IEEE 802.3 + LINKTYPE_NULL, /// IEEE 802.4 Token Bus + LINKTYPE_IEEE802_5, /// IEEE 802.5 + LINKTYPE_NULL, /// IEEE 802.6 Metro Net + LINKTYPE_ETHERNET, /// Ethernet + LINKTYPE_C_HDLC, /// HDLC + LINKTYPE_NULL, /// Character Synchronous, e.g. bisync + LINKTYPE_NULL, /// IBM Channel-to-Channel + LINKTYPE_FDDI /// FDDI }; uint32_t datalink_type = be32toh(snoop_file_header.datalink_type); if (datalink_type > ARRAY_SIZE(snoop_encap) - 1) diff --git a/Pcap++/src/PcapLiveDevice.cpp b/Pcap++/src/PcapLiveDevice.cpp index 6eef2111d2..213295cee7 100644 --- a/Pcap++/src/PcapLiveDevice.cpp +++ b/Pcap++/src/PcapLiveDevice.cpp @@ -80,6 +80,8 @@ namespace pcpp return PCAP_D_OUT; case PcapLiveDevice::PCPP_INOUT: return PCAP_D_INOUT; + default: + throw std::invalid_argument("Unknown direction type"); } } #endif @@ -247,7 +249,7 @@ namespace pcpp PcapStats stats; getStatistics(stats); m_cbOnStatsUpdate(stats, m_cbOnStatsUpdateUserCookie); - multiPlatformSleep(m_IntervalToUpdateStats); + std::this_thread::sleep_for(std::chrono::seconds(m_IntervalToUpdateStats)); } PCPP_LOG_DEBUG("Ended stats thread for device '" << m_InterfaceDetails.name << "'"); } @@ -852,7 +854,7 @@ namespace pcpp { if (oidData->Length <= sizeof(uint32_t)) { - /* copy value from driver */ + // copy value from driver memcpy(&mtuValue, oidData->Data, oidData->Length); // Sometimes the query gives a wrong number that includes the link header size // A very common value is 1514 - if identify this value just reduce to 1500. @@ -865,7 +867,7 @@ namespace pcpp } else { - /* the driver returned a value that is longer than expected (and longer than the given buffer) */ + // the driver returned a value that is longer than expected (and longer than the given buffer) PCPP_LOG_ERROR( "Error in retrieving MTU: Size of Oid larger than uint32_t, OidLen: " << oidData->Length); return; @@ -929,7 +931,7 @@ namespace pcpp { # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Warray-bounds" - /* copy value from driver */ + // copy value from driver m_MacAddress = MacAddress(oidData->Data[0], oidData->Data[1], oidData->Data[2], oidData->Data[3], oidData->Data[4], oidData->Data[5]); # pragma GCC diagnostic pop @@ -937,7 +939,7 @@ namespace pcpp } else { - /* the driver returned a value that is longer than expected (and longer than the given buffer) */ + // the driver returned a value that is longer than expected (and longer than the given buffer) PCPP_LOG_DEBUG( "Error in retrieving MAC address: Size of Oid larger than 6, OidLen: " << oidData->Length); return; @@ -1044,6 +1046,7 @@ namespace pcpp } catch (const std::exception& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled PCPP_LOG_ERROR("Error retrieving default gateway address: " << e.what()); } break; diff --git a/Pcap++/src/PcapLiveDeviceList.cpp b/Pcap++/src/PcapLiveDeviceList.cpp index 9fb46b4ce4..a68e65a406 100644 --- a/Pcap++/src/PcapLiveDeviceList.cpp +++ b/Pcap++/src/PcapLiveDeviceList.cpp @@ -51,6 +51,7 @@ namespace pcpp } catch (const std::exception& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled PCPP_LOG_ERROR(e.what()); } diff --git a/Pcap++/src/PcapRemoteDeviceList.cpp b/Pcap++/src/PcapRemoteDeviceList.cpp index b725f3b817..ca8629c8f3 100644 --- a/Pcap++/src/PcapRemoteDeviceList.cpp +++ b/Pcap++/src/PcapRemoteDeviceList.cpp @@ -14,15 +14,13 @@ namespace pcpp namespace { - /** - * Fetches a list of all network devices on a remote machine that WinPcap/NPcap can find. - * @param[in] ipAddress IP address of the remote machine. - * @param[in] port Port to use when connecting to the remote machine. - * @param[in] pRmAuth Pointer to an authentication structure to use when connecting to the remote machine. - * Nullptr if no authentication is required. - * @return A smart pointer to an interface list structure. - * @throws std::runtime_error The system encountered an error fetching the devices. - */ + /// Fetches a list of all network devices on a remote machine that WinPcap/NPcap can find. + /// @param[in] ipAddress IP address of the remote machine. + /// @param[in] port Port to use when connecting to the remote machine. + /// @param[in] pRmAuth Pointer to an authentication structure to use when connecting to the remote machine. + /// Nullptr if no authentication is required. + /// @return A smart pointer to an interface list structure. + /// @throws std::runtime_error The system encountered an error fetching the devices. std::unique_ptr getAllRemotePcapDevices( const IPAddress& ipAddress, uint16_t port, pcap_rmtauth* pRmAuth = nullptr) { @@ -96,6 +94,7 @@ namespace pcpp } catch (const std::exception& e) { + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled PCPP_LOG_ERROR(e.what()); return nullptr; } @@ -120,6 +119,7 @@ namespace pcpp { delete device; } + (void)e; // Suppress the unreferenced local variable warning when PCPP_LOG_ERROR is disabled PCPP_LOG_ERROR("Error creating remote devices: " << e.what()); return nullptr; } diff --git a/Pcap++/src/PfRingDevice.cpp b/Pcap++/src/PfRingDevice.cpp index 8a945a9c20..55134abbe1 100644 --- a/Pcap++/src/PfRingDevice.cpp +++ b/Pcap++/src/PfRingDevice.cpp @@ -449,9 +449,7 @@ namespace pcpp return false; } - std::mutex mutex; - std::condition_variable cond; - int startThread = 0; + std::shared_ptr startupBlock = std::make_shared(); m_StopThread = false; int rxChannel = 0; @@ -468,7 +466,7 @@ namespace pcpp // create a new thread m_CoreConfiguration[coreId].Channel = m_PfRingDescriptors[rxChannel++]; m_CoreConfiguration[coreId].RxThread = - std::thread(&pcpp::PfRingDevice::captureThreadMain, this, &cond, &mutex, &startThread); + std::thread(&pcpp::PfRingDevice::captureThreadMain, this, startupBlock); // set affinity to cores cpu_set_t cpuset; @@ -479,14 +477,21 @@ namespace pcpp if (err != 0) { PCPP_LOG_ERROR("Error while binding thread to core " << coreId << ": errno=" << err); - startThread = 1; + { + std::unique_lock lock(startupBlock->Mutex); + startupBlock->State = 1; + } + startupBlock->Cond.notify_all(); clearCoreConfiguration(); return false; } } - startThread = 2; - cond.notify_all(); + { + std::unique_lock lock(startupBlock->Mutex); + startupBlock->State = 2; + } + startupBlock->Cond.notify_all(); return true; } @@ -517,28 +522,35 @@ namespace pcpp m_ReentrantMode = false; - std::mutex mutex; - std::condition_variable cond; - int startThread = 0; + std::shared_ptr startupBlock = std::make_shared(); cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); m_CoreConfiguration[0].IsInUse = true; m_CoreConfiguration[0].Channel = m_PfRingDescriptors[0]; - m_CoreConfiguration[0].RxThread = - std::thread(&pcpp::PfRingDevice::captureThreadMain, this, &cond, &mutex, &startThread); + m_CoreConfiguration[0].RxThread = std::thread(&pcpp::PfRingDevice::captureThreadMain, this, startupBlock); m_CoreConfiguration[0].IsAffinitySet = false; int err = pthread_setaffinity_np(m_CoreConfiguration[0].RxThread.native_handle(), sizeof(cpu_set_t), &cpuset); if (err != 0) { - startThread = 1; + { + std::unique_lock lock(startupBlock->Mutex); + startupBlock->State = 1; + } + startupBlock->Cond.notify_all(); + m_CoreConfiguration[0].RxThread.join(); + PCPP_LOG_ERROR("Error while binding thread to core 0: errno=" << err); clearCoreConfiguration(); return false; } - startThread = 2; - cond.notify_all(); + + { + std::unique_lock lock(startupBlock->Mutex); + startupBlock->State = 2; + } + startupBlock->Cond.notify_all(); PCPP_LOG_DEBUG("Capturing started for device [" << m_DeviceName << "]"); return true; @@ -559,19 +571,27 @@ namespace pcpp PCPP_LOG_DEBUG("All capturing threads stopped"); } - void PfRingDevice::captureThreadMain(std::condition_variable* startCond, std::mutex* startMutex, - const int* startState) + void PfRingDevice::captureThreadMain(std::shared_ptr startupBlock) { - while (*startState == 0) + if (startupBlock == nullptr) { - std::unique_lock lock(*startMutex); - startCond->wait_for(lock, std::chrono::milliseconds(100)); + PCPP_LOG_ERROR("Capture thread started without a startup block. Exiting capture thread"); + return; } - if (*startState == 1) + { - return; + std::unique_lock lock(startupBlock->Mutex); + startupBlock->Cond.wait(lock, [&] { return startupBlock->State != 0; }); + + if (startupBlock->State == 1) + { + return; + } } + // Startup is complete. The block is no longer needed. + startupBlock = nullptr; + int coreId = this->getCurrentCoreId().Id; pfring* ring = nullptr; diff --git a/Pcap++/src/PfRingDeviceList.cpp b/Pcap++/src/PfRingDeviceList.cpp index be41d07be8..bd1be57d75 100644 --- a/Pcap++/src/PfRingDeviceList.cpp +++ b/Pcap++/src/PfRingDeviceList.cpp @@ -17,10 +17,8 @@ namespace pcpp namespace { - /** - * @class PfRingCloseDeleter - * A deleter that cleans up a pfring structure by calling pfring_close. - */ + /// @class PfRingCloseDeleter + /// A deleter that cleans up a pfring structure by calling pfring_close. struct PfRingCloseDeleter { void operator()(pfring* ptr) const @@ -29,11 +27,9 @@ namespace pcpp } }; - /** - * Reads the ring version of a PF_RING handle. - * @param[in] ring A PF_RING handle. - * @return A string representation of the ring version or empty string if the read fails. - */ + /// Reads the ring version of a PF_RING handle. + /// @param[in] ring A PF_RING handle. + /// @return A string representation of the ring version or empty string if the read fails. std::string readPfRingVersion(pfring* ring) { uint32_t version; @@ -130,7 +126,6 @@ namespace pcpp return devIter->get(); } - } // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/RawSocketDevice.cpp b/Pcap++/src/RawSocketDevice.cpp index 40da2331e7..956d3460e9 100644 --- a/Pcap++/src/RawSocketDevice.cpp +++ b/Pcap++/src/RawSocketDevice.cpp @@ -24,8 +24,8 @@ namespace pcpp #if defined(_WIN32) # ifndef SIO_RCVALL -/* SIO_RCVALL defined on w2k and later. Not defined in Mingw32 */ -/* 0x98000001 = _WSAIOW(IOC_VENDOR,1) */ +// SIO_RCVALL defined on w2k and later. Not defined in Mingw32 +// 0x98000001 = _WSAIOW(IOC_VENDOR,1) # define SIO_RCVALL 0x98000001 # endif // SIO_RCVALL diff --git a/Pcap++/src/XdpDevice.cpp b/Pcap++/src/XdpDevice.cpp index d1f9e99f75..04378bcbf2 100644 --- a/Pcap++/src/XdpDevice.cpp +++ b/Pcap++/src/XdpDevice.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -144,6 +145,7 @@ namespace pcpp pollfd pollFds[1]; pollFds[0] = { .fd = xsk_socket__fd(socketInfo->xsk), .events = POLLIN }; + std::vector receiveBuffer; while (m_ReceivingPackets) { checkCompletionRing(); @@ -169,14 +171,16 @@ namespace pcpp uint32_t receivedPacketsCount = xsk_ring_cons__peek(&socketInfo->rx, m_Config->rxTxBatchSize, &rxId); - if (!receivedPacketsCount) + if (receivedPacketsCount == 0) { continue; } m_Stats.rxPackets += receivedPacketsCount; - RawPacket rawPacketsArr[receivedPacketsCount]; + // Reserves at least enough memory to hold all the received packets. No-op if capacity is enough. + // May hold more memory than needed if a previous cycle has reserved more already. + receiveBuffer.reserve(receivedPacketsCount); for (uint32_t i = 0; i < receivedPacketsCount; i++) { @@ -186,14 +190,15 @@ namespace pcpp auto data = m_Umem->getDataPtr(addr); timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - rawPacketsArr[i].initWithRawData(data, static_cast(len), ts); + // Initializes the RawPacket directly into the buffer. + receiveBuffer.emplace_back(data, static_cast(len), ts, false); m_Stats.rxBytes += len; m_Umem->freeFrame(addr); } - onPacketsArrive(rawPacketsArr, receivedPacketsCount, this, onPacketsArriveUserCookie); + onPacketsArrive(receiveBuffer.data(), receiveBuffer.size(), this, onPacketsArriveUserCookie); xsk_ring_cons__release(&socketInfo->rx, receivedPacketsCount); m_Stats.rxRingId = rxId + receivedPacketsCount; @@ -202,6 +207,9 @@ namespace pcpp { m_ReceivingPackets = false; } + + // Clears the receive buffer. + receiveBuffer.clear(); } return true; diff --git a/Tests/ExamplesTest/requirements.txt b/Tests/ExamplesTest/requirements.txt index 65b26b5092..1665e3e6ff 100644 --- a/Tests/ExamplesTest/requirements.txt +++ b/Tests/ExamplesTest/requirements.txt @@ -1,7 +1,7 @@ -attrs==24.2.0 +attrs==24.3.0 iniconfig==2.0.0 py==1.11.0 pyparsing==3.1.4 -pytest==8.3.3 +pytest==8.3.4 scapy==2.6.1 toml==0.10.2 diff --git a/Tests/Packet++Test/CMakeLists.txt b/Tests/Packet++Test/CMakeLists.txt index 0bcac69e63..082fb9c51b 100644 --- a/Tests/Packet++Test/CMakeLists.txt +++ b/Tests/Packet++Test/CMakeLists.txt @@ -43,14 +43,10 @@ add_executable( Tests/VrrpTest.cpp Tests/WakeOnLanTests.cpp Tests/WireGuardTests.cpp - Utils/TestUtils.cpp) + Utils/TestUtils.cpp +) -target_link_libraries( - Packet++Test - PUBLIC memplumber - Packet++ - PcppTestFramework - EndianPortable) +target_link_libraries(Packet++Test PUBLIC memplumber Packet++ PcppTestFramework EndianPortable) if(MSVC) # This executable requires getopt.h not available on VStudio @@ -60,7 +56,4 @@ endif() set_property(TARGET Packet++Test PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/Bin") set_property(TARGET Packet++Test PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/Bin") set_property(TARGET Packet++Test PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/Bin") -add_test( - NAME Packet++Test - COMMAND $ - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/) +add_test(NAME Packet++Test COMMAND $ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/) diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 4163780110..ebf1838620 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -85,7 +85,8 @@ int main(int argc, char* argv[]) #endif // The logger singleton looks like a memory leak. Invoke it before starting the memory check - pcpp::Logger::getInstance(); + // Disables context pooling to avoid false positives in the memory leak check, as the contexts persist in the pool. + pcpp::Logger::getInstance().useContextPooling(false); // cppcheck-suppress knownConditionTrueFalse if (skipMemLeakCheck) diff --git a/Tests/Pcap++Test/CMakeLists.txt b/Tests/Pcap++Test/CMakeLists.txt index 73c6fdcc06..1727a4d15b 100644 --- a/Tests/Pcap++Test/CMakeLists.txt +++ b/Tests/Pcap++Test/CMakeLists.txt @@ -10,19 +10,16 @@ add_executable( Tests/KniTests.cpp Tests/LiveDeviceTests.cpp Tests/LoggerTests.cpp + Tests/ObjectPoolTests.cpp Tests/PacketParsingTests.cpp Tests/PfRingTests.cpp Tests/RawSocketTests.cpp Tests/SystemUtilsTests.cpp Tests/TcpReassemblyTests.cpp - Tests/XdpTests.cpp) + Tests/XdpTests.cpp +) -target_link_libraries( - Pcap++Test - PUBLIC memplumber - Pcap++ - PcppTestFramework - EndianPortable) +target_link_libraries(Pcap++Test PUBLIC memplumber Pcap++ PcppTestFramework EndianPortable) if(MSVC) # This executable requires getopt.h not available on VStudio @@ -33,7 +30,4 @@ set_property(TARGET Pcap++Test PROPERTY RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURREN set_property(TARGET Pcap++Test PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/Bin") set_property(TARGET Pcap++Test PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/Bin") -add_test( - NAME Pcap++Test - COMMAND $ -n - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/) +add_test(NAME Pcap++Test COMMAND $ -n WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/) diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index ccaaec4756..74188ff885 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -12,6 +12,9 @@ PTF_TEST_CASE(TestIPv4Network); PTF_TEST_CASE(TestIPv6Network); PTF_TEST_CASE(TestIPNetwork); +// Implemented in ObjectPoolTests.cpp +PTF_TEST_CASE(TestObjectPool); + // Implemented in LoggerTests.cpp PTF_TEST_CASE(TestLogger); PTF_TEST_CASE(TestLoggerMultiThread); diff --git a/Tests/Pcap++Test/Tests/DpdkTests.cpp b/Tests/Pcap++Test/Tests/DpdkTests.cpp index b71226c3a2..169fc678fa 100644 --- a/Tests/Pcap++Test/Tests/DpdkTests.cpp +++ b/Tests/Pcap++Test/Tests/DpdkTests.cpp @@ -6,6 +6,7 @@ #ifdef USE_DPDK # include +# include # include "Logger.h" # include "PacketUtils.h" # include "IPv4Layer.h" @@ -57,7 +58,7 @@ int incSleep(int maxSleepTime, int minPacketCount, const DpdkPacketData& packetD int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; if (packetData.PacketCount > minPacketCount) break; @@ -72,7 +73,7 @@ int incSleepMultiThread(int maxSleepTime, DpdkPacketData packetData[], int total int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; int coresWithPacketCountNotZero = 0; @@ -665,7 +666,7 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) while (rxQueueId < numOfRxQueues) { dev->receivePackets(rawPacketVec, rxQueueId); - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); if (rawPacketVec.size() > 0) { isPacketRecvd = true; @@ -693,7 +694,7 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) while (rxQueueId < numOfRxQueues) { mBufRawPacketArrLen = dev->receivePackets(mBufRawPacketArr, 32, rxQueueId); - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); if (mBufRawPacketArrLen > 0) { isPacketRecvd = true; @@ -726,7 +727,7 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) while (rxQueueId < numOfRxQueues) { packetArrLen = dev->receivePackets(packetArr, 32, rxQueueId); - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); if (packetArrLen > 0) { isPacketRecvd = true; @@ -797,7 +798,7 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) PTF_PRINT_VERBOSE("Bytes captured on RX queue #" << i << " according to stats: " << stats.rxStats[i].bytes); } - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); if (stats.aggregatedRxStats.packets > curPackets) break; @@ -900,7 +901,7 @@ PTF_TEST_CASE(TestDpdkMbufRawPacket) for (int i = 0; i < dev->getNumOfOpenedRxQueues(); i++) { dev->receivePackets(rawPacketVec, i); - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); for (pcpp::MBufRawPacketVector::VectorIterator iter = rawPacketVec.begin(); iter != rawPacketVec.end(); iter++) { diff --git a/Tests/Pcap++Test/Tests/FilterTests.cpp b/Tests/Pcap++Test/Tests/FilterTests.cpp index 13f656fbb0..bb23059375 100644 --- a/Tests/Pcap++Test/Tests/FilterTests.cpp +++ b/Tests/Pcap++Test/Tests/FilterTests.cpp @@ -25,7 +25,7 @@ static int incSleep(const pcpp::RawPacketVector& capturedPackets, size_t expecte return totalSleepTime; } - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; } diff --git a/Tests/Pcap++Test/Tests/KniTests.cpp b/Tests/Pcap++Test/Tests/KniTests.cpp index 07bb1383ba..b090767f44 100644 --- a/Tests/Pcap++Test/Tests/KniTests.cpp +++ b/Tests/Pcap++Test/Tests/KniTests.cpp @@ -7,6 +7,7 @@ # include "PcapFileDevice.h" # include "RawSocketDevice.h" # include "SystemUtils.h" +# include extern PcapTestArgs PcapTestGlobalArgs; @@ -193,7 +194,7 @@ PTF_TEST_CASE(TestKniDevice) PTF_ASSERT_TRUE(device->open()); PTF_ASSERT_TRUE(device->startRequestHandlerThread(0, 150000000)); - pcpp::multiPlatformSleep(2); // Wait for thread to start + std::this_thread::sleep_for(std::chrono::seconds(2)); // Wait for thread to start if (pcpp::KniDeviceList::isCallbackSupported(pcpp::KniDeviceList::CALLBACK_PROMISC)) { bool modeSet = device->setPromiscuous(pcpp::KniDevice::PROMISC_ENABLE); @@ -337,7 +338,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) PTF_ASSERT_TRUE(device->startRequestHandlerThread(0, 250000000)); KniDeviceTeardown devTeardown(device); - pcpp::multiPlatformSleep(1); // Wait for thread to start + std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait for thread to start // KNI device management PTF_ASSERT_TRUE(setKniDeviceIp(kniIp, KNI_DEVICE1)); @@ -363,7 +364,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_FALSE(device->startCapture(KniRequestsCallbacksMock::onPacketsMock, NULL)); pcpp::Logger::getInstance().enableLogs(); - pcpp::multiPlatformSleep(1); // Give some time to start capture thread + std::this_thread::sleep_for(std::chrono::seconds(1)); // Give some time to start capture thread for (int i = 0; i < 10; ++i) { fileReaderDev.getNextPacket(rawPacket); @@ -374,12 +375,12 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) rsdevice.sendPackets(rawPacketVec); pcpp::Logger::getInstance().enableLogs(); rawPacketVec.clear(); - pcpp::multiPlatformSleep(1); // Give some time to receive packets + std::this_thread::sleep_for(std::chrono::seconds(1)); // Give some time to receive packets device->stopCapture(); PTF_PRINT_VERBOSE("KNI have captured " << counter << " packets in single burst on device " << KNI_DEVICE1); counter = 0; PTF_ASSERT_TRUE(device->startCapture(KniRequestsCallbacksMock::onPacketsCallback, &counter)); - pcpp::multiPlatformSleep(1); // Give some time to start capture thread + std::this_thread::sleep_for(std::chrono::seconds(1)); // Give some time to start capture thread pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_EQUAL(device->receivePackets(mbufRawPacketVec), 0); PTF_ASSERT_EQUAL(device->receivePackets(mBufRawPacketArr, mBufRawPacketArrLen), 0); @@ -395,7 +396,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) rsdevice.sendPackets(rawPacketVec); pcpp::Logger::getInstance().enableLogs(); rawPacketVec.clear(); - pcpp::multiPlatformSleep(1); // Give some time to receive packets + std::this_thread::sleep_for(std::chrono::seconds(1)); // Give some time to receive packets device->stopCapture(); PTF_PRINT_VERBOSE("KNI have captured " << counter << " packets on device " << KNI_DEVICE1); counter = 0; diff --git a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp index a8ee8dbad8..19d4954a02 100644 --- a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp +++ b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp @@ -316,7 +316,7 @@ PTF_TEST_CASE(TestPcapLiveDevice) int totalSleepTime = 0; while (totalSleepTime <= 20) { - pcpp::multiPlatformSleep(2); + std::this_thread::sleep_for(std::chrono::seconds(2)); totalSleepTime += 2; if (packetCount > 0) break; @@ -377,7 +377,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceClone) int totalSleepTime = 0; while (totalSleepTime <= 20) { - pcpp::multiPlatformSleep(2); + std::this_thread::sleep_for(std::chrono::seconds(2)); totalSleepTime += 2; if (packetCount > 0) break; @@ -447,7 +447,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceStatsMode) int totalSleepTime = 0; while (totalSleepTime <= 6) { - pcpp::multiPlatformSleep(2); + std::this_thread::sleep_for(std::chrono::seconds(2)); totalSleepTime += 2; pcpp::IPcapDevice::PcapStats statistics; liveDev->getStatistics(statistics); @@ -515,7 +515,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceBlockingMode) int totalSleepTime = 0; while (totalSleepTime <= 5) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; if (packetCount > 0) break; @@ -554,7 +554,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceBlockingMode) totalSleepTime = 0; while (totalSleepTime <= 5) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; if (packetCount > 0) break; @@ -599,7 +599,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceWithLambda) int totalSleepTime = 0; while (totalSleepTime <= 20) { - pcpp::multiPlatformSleep(2); + std::this_thread::sleep_for(std::chrono::seconds(2)); totalSleepTime += 2; if (packetCount > 0) break; @@ -985,7 +985,7 @@ PTF_TEST_CASE(TestRemoteCapture) break; } - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; } diff --git a/Tests/Pcap++Test/Tests/LoggerTests.cpp b/Tests/Pcap++Test/Tests/LoggerTests.cpp index 00f06d332a..5579c350c5 100644 --- a/Tests/Pcap++Test/Tests/LoggerTests.cpp +++ b/Tests/Pcap++Test/Tests/LoggerTests.cpp @@ -136,7 +136,7 @@ class LoggerCleaner ~LoggerCleaner() { pcpp::Logger::getInstance().enableLogs(); - pcpp::Logger::getInstance().setAllModulesToLogLevel(pcpp::Logger::Info); + pcpp::Logger::getInstance().setAllModulesToLogLevel(pcpp::LogLevel::Info); pcpp::Logger::getInstance().resetLogPrinter(); std::cout.clear(); LogPrinter::clean(); @@ -155,7 +155,7 @@ void printLogThread(int threadId) { pcpp::invokeErrorLog(threadIdAsString); int sleepTime = dist(simpleRand); - pcpp::multiPlatformMSleep(sleepTime); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); } } @@ -190,24 +190,39 @@ PTF_TEST_CASE(TestLoggerMultiThread) PTF_TEST_CASE(TestLogger) { + using pcpp::Logger; + using pcpp::LogLevel; + using pcpp::LogModule; + + auto& logger = Logger::getInstance(); + // cppcheck-suppress unusedVariable LoggerCleaner loggerCleaner; // verify all modules are on info log level - for (int module = 1; module < pcpp::NumOfLogModules; module++) + for (int moduleInt = 1; moduleInt < LogModule::NumOfLogModules; moduleInt++) { - PTF_ASSERT_EQUAL(pcpp::Logger::getInstance().getLogLevel((pcpp::LogModule)module), pcpp::Logger::Info, enum); - PTF_ASSERT_FALSE(pcpp::Logger::getInstance().isDebugEnabled((pcpp::LogModule)module)); + const LogModule moduleEnum = static_cast(moduleInt); + + PTF_ASSERT_EQUAL(logger.getLogLevel(moduleEnum), LogLevel::Info, enum); + PTF_ASSERT_FALSE(logger.isDebugEnabled(moduleEnum)); + + PTF_ASSERT_TRUE(logger.shouldLog(LogLevel::Error, moduleEnum)); + PTF_ASSERT_TRUE(logger.shouldLog(LogLevel::Info, moduleEnum)); + PTF_ASSERT_FALSE(logger.shouldLog(LogLevel::Debug, moduleEnum)); + PTF_ASSERT_FALSE(logger.shouldLog(LogLevel::Off, moduleEnum)); } // invoke debug and error logs - expect to see only the error log - pcpp::Logger::getInstance().setLogPrinter(&LogPrinter::logPrinter); + logger.setLogPrinter(&LogPrinter::logPrinter); + pcpp::invokeDebugLog(); PTF_ASSERT_EQUAL(LogPrinter::lastLogLevelSeen, 999); PTF_ASSERT_EQUAL(LogPrinter::lastLineSeen, 99999); PTF_ASSERT_NULL(LogPrinter::lastLogMessageSeen); PTF_ASSERT_NULL(LogPrinter::lastFilenameSeen); PTF_ASSERT_NULL(LogPrinter::lastMethodSeen); + pcpp::invokeErrorLog(); PTF_ASSERT_EQUAL(LogPrinter::lastLogLevelSeen, (int)pcpp::Logger::Error); PTF_ASSERT_EQUAL(*LogPrinter::lastLogMessageSeen, "error log"); @@ -216,9 +231,9 @@ PTF_TEST_CASE(TestLogger) PTF_ASSERT_EQUAL(LogPrinter::lastLineSeen, 21); // change one module log level - pcpp::Logger::getInstance().setLogLevel(pcpp::PacketLogModuleArpLayer, pcpp::Logger::Debug); - PTF_ASSERT_EQUAL(pcpp::Logger::getInstance().getLogLevel(pcpp::PacketLogModuleArpLayer), pcpp::Logger::Debug, enum); - PTF_ASSERT_TRUE(pcpp::Logger::getInstance().isDebugEnabled(pcpp::PacketLogModuleArpLayer)); + logger.setLogLevel(pcpp::PacketLogModuleArpLayer, pcpp::Logger::Debug); + PTF_ASSERT_EQUAL(logger.getLogLevel(pcpp::PacketLogModuleArpLayer), pcpp::LogLevel::Debug, enum); + PTF_ASSERT_TRUE(logger.isDebugEnabled(pcpp::PacketLogModuleArpLayer)); // invoke debug and error logs - expect to see both pcpp::invokeDebugLog(); @@ -236,14 +251,21 @@ PTF_TEST_CASE(TestLogger) PTF_ASSERT_EQUAL(LogPrinter::lastLineSeen, 21); // verify the last error message - PTF_ASSERT_EQUAL(pcpp::Logger::getInstance().getLastError(), "error log"); + PTF_ASSERT_EQUAL(logger.getLastError(), "error log"); // change all modules log level - pcpp::Logger::getInstance().setAllModulesToLogLevel(pcpp::Logger::Debug); - for (int module = 1; module < pcpp::NumOfLogModules; module++) + logger.setAllModulesToLogLevel(LogLevel::Debug); + for (int moduleInt = 1; moduleInt < LogModule::NumOfLogModules; moduleInt++) { - PTF_ASSERT_EQUAL(pcpp::Logger::getInstance().getLogLevel((pcpp::LogModule)module), pcpp::Logger::Debug, enum); - PTF_ASSERT_TRUE(pcpp::Logger::getInstance().isDebugEnabled((pcpp::LogModule)module)); + auto const moduleEnum = static_cast(moduleInt); + + PTF_ASSERT_EQUAL(logger.getLogLevel(static_cast(moduleEnum)), pcpp::LogLevel::Debug, enum); + PTF_ASSERT_TRUE(logger.isDebugEnabled(static_cast(moduleEnum))); + + PTF_ASSERT_TRUE(logger.shouldLog(LogLevel::Error, moduleEnum)); + PTF_ASSERT_TRUE(logger.shouldLog(LogLevel::Info, moduleEnum)); + PTF_ASSERT_TRUE(logger.shouldLog(LogLevel::Debug, moduleEnum)); + PTF_ASSERT_FALSE(logger.shouldLog(LogLevel::Off, moduleEnum)); } // invoke debug log - expect to see it @@ -255,9 +277,9 @@ PTF_TEST_CASE(TestLogger) PTF_ASSERT_EQUAL(LogPrinter::lastLineSeen, 16); // suppress logs - PTF_ASSERT_TRUE(pcpp::Logger::getInstance().logsEnabled()) - pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_FALSE(pcpp::Logger::getInstance().logsEnabled()) + PTF_ASSERT_TRUE(logger.logsEnabled()) + logger.suppressLogs(); + PTF_ASSERT_FALSE(logger.logsEnabled()) // reset LogPrinter LogPrinter::clean(); @@ -270,32 +292,32 @@ PTF_TEST_CASE(TestLogger) // invoke another error log - expect to see it as the last error message although logs are suppressed pcpp::invokeErrorLog("2"); - PTF_ASSERT_EQUAL(pcpp::Logger::getInstance().getLastError(), "error log2"); + PTF_ASSERT_EQUAL(logger.getLastError(), "error log2"); // re-enable logs - pcpp::Logger::getInstance().enableLogs(); - PTF_ASSERT_TRUE(pcpp::Logger::getInstance().logsEnabled()) + logger.enableLogs(); + PTF_ASSERT_TRUE(logger.logsEnabled()) // invoke error log - expect to see it pcpp::invokeErrorLog(); - PTF_ASSERT_EQUAL(LogPrinter::lastLogLevelSeen, (int)pcpp::Logger::Error); + PTF_ASSERT_EQUAL(LogPrinter::lastLogLevelSeen, static_cast(pcpp::LogLevel::Error)); PTF_ASSERT_EQUAL(*LogPrinter::lastLogMessageSeen, "error log"); PTF_ASSERT_EQUAL(getLowerCaseFileName(*LogPrinter::lastFilenameSeen), "loggertests.cpp"); PTF_ASSERT_EQUAL(getMethodWithoutNamespace(*LogPrinter::lastMethodSeen), "invokeErrorLog"); - PTF_ASSERT_EQUAL(pcpp::Logger::getInstance().getLastError(), "error log"); + PTF_ASSERT_EQUAL(logger.getLastError(), "error log"); PTF_ASSERT_EQUAL(LogPrinter::lastLineSeen, 21); // reset LogPrinter LogPrinter::clean(); // reset the log printer - pcpp::Logger::getInstance().resetLogPrinter(); + logger.resetLogPrinter(); // disable std::cout for a bit std::cout.setstate(std::ios_base::failbit); // set debug log for a module, don't expect to see it in the custom log printer - pcpp::Logger::getInstance().setLogLevel(pcpp::PacketLogModuleArpLayer, pcpp::Logger::Debug); + logger.setLogLevel(pcpp::PacketLogModuleArpLayer, pcpp::LogLevel::Debug); pcpp::invokeDebugLog(); pcpp::invokeErrorLog(); PTF_ASSERT_EQUAL(LogPrinter::lastLogLevelSeen, 999); diff --git a/Tests/Pcap++Test/Tests/ObjectPoolTests.cpp b/Tests/Pcap++Test/Tests/ObjectPoolTests.cpp new file mode 100644 index 0000000000..3f79e0ef30 --- /dev/null +++ b/Tests/Pcap++Test/Tests/ObjectPoolTests.cpp @@ -0,0 +1,79 @@ + +#include "../TestDefinition.h" + +#include "ObjectPool.h" + +PTF_TEST_CASE(TestObjectPool) +{ + using pcpp::internal::DynamicObjectPool; + + { + DynamicObjectPool pool; + PTF_ASSERT_EQUAL(pool.size(), 0); + PTF_ASSERT_EQUAL(pool.maxSize(), 100); + + pool.preallocate(2); + PTF_ASSERT_EQUAL(pool.size(), 2); + + pool.setMaxSize(1); + PTF_ASSERT_EQUAL(pool.size(), 1); + PTF_ASSERT_EQUAL(pool.maxSize(), 1); + + PTF_ASSERT_RAISES(pool.preallocate(2), std::invalid_argument, + "Preallocated objects cannot exceed the maximum pool size"); + + pool.clear(); + PTF_ASSERT_EQUAL(pool.size(), 0); + PTF_ASSERT_EQUAL(pool.maxSize(), 1); + } + + { + DynamicObjectPool pool(10, 2); + PTF_ASSERT_EQUAL(pool.size(), 2); + PTF_ASSERT_EQUAL(pool.maxSize(), 10); + + PTF_ASSERT_RAISES(DynamicObjectPool(0, 2), std::invalid_argument, + "Preallocated objects cannot exceed the maximum pool size"); + } + + { + DynamicObjectPool pool; + PTF_ASSERT_EQUAL(pool.size(), 0); + + // Acquire an object, since the pool is empty, a new object will be created. + auto obj1 = pool.acquireObject(); + PTF_ASSERT_NOT_NULL(obj1); + + // Acquire a second object, since the pool is still empty, a new object will be created. + auto obj2 = pool.acquireObject(); + + // For the purposes of this test a value will be assigned to track the object. + *obj1 = 55; + *obj2 = 66; + + // Release the objects back to the pool. + pool.releaseObject(std::move(obj1)); + pool.releaseObject(std::move(obj2)); + + PTF_ASSERT_EQUAL(pool.size(), 2); + + // Acquire an object again, this time the object should be reused. + // Since the pool is a LIFO stack the object that was released last should be acquired first. + obj1 = pool.acquireObject(); + + // The value should be the same as the one assigned before releasing the object. + PTF_ASSERT_EQUAL(*obj1, 66); + + // Acquire the second object, this time the object that was released first should be acquired. + obj2 = pool.acquireObject(); + PTF_ASSERT_EQUAL(*obj2, 55); + + // Set the max size of the pool to zero to test the deletion of objects. + pool.setMaxSize(0); + + // Release the objects back to the pool, this time the objects should be deleted. + pool.releaseObject(std::move(obj1)); + pool.releaseObject(std::move(obj2)); + PTF_ASSERT_EQUAL(pool.size(), 0); + } +} diff --git a/Tests/Pcap++Test/Tests/PfRingTests.cpp b/Tests/Pcap++Test/Tests/PfRingTests.cpp index a8adf6787a..aa97ac748a 100644 --- a/Tests/Pcap++Test/Tests/PfRingTests.cpp +++ b/Tests/Pcap++Test/Tests/PfRingTests.cpp @@ -10,6 +10,7 @@ # include "PfRingDeviceList.h" # include "PcapFileDevice.h" # include "PcapLiveDeviceList.h" +# include #endif extern PcapTestArgs PcapTestGlobalArgs; @@ -141,7 +142,7 @@ int incSleep(int maxSleepTime, const PfRingPacketData& packetData) int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; if (packetData.PacketCount > 0) break; @@ -156,7 +157,7 @@ int incSleepMultiThread(int maxSleepTime, PfRingPacketData packetData[], int tot int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; int coresWithPacketCountNotZero = 0; @@ -181,7 +182,7 @@ int incSleepSetFilter(int maxSleepTime, const SetFilterInstruction& packetData) int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) { - pcpp::multiPlatformSleep(1); + std::this_thread::sleep_for(std::chrono::seconds(1)); totalSleepTime += 1; if (packetData.PacketCount > 0) break; diff --git a/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp b/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp index 2635353be3..9b65d9f6a1 100644 --- a/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp +++ b/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "EndianPortable.h" #include "SystemUtils.h" #include "TcpReassembly.h" @@ -1137,7 +1138,7 @@ PTF_TEST_CASE(TestTcpReassemblyCleanup) PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn2->second), 0); PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn3->second), 0); - pcpp::multiPlatformSleep(3); + std::this_thread::sleep_for(std::chrono::seconds(3)); tcpReassembly.reassemblePacket(&lastPacket); // automatic cleanup of 1 item PTF_ASSERT_EQUAL(tcpReassembly.getConnectionInformation().size(), 2); diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 784a9e0d6f..204e34fee7 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -143,8 +143,9 @@ int main(int argc, char* argv[]) << " https://github.com/cpputest/cpputest/issues/786#issuecomment-148921958" << std::endl; #endif - // The logger singleton looks like a memory leak. Invoke it before starting the memory check - pcpp::Logger::getInstance(); + // The logger singleton looks like a memory leak. Invoke it before starting the memory check. + // Disables context pooling to avoid false positives in the memory leak check, as the contexts persist in the pool. + pcpp::Logger::getInstance().useContextPooling(false); // cppcheck-suppress knownConditionTrueFalse if (skipMemLeakCheck) @@ -209,6 +210,8 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestIPv6Network, "no_network;ip"); PTF_RUN_TEST(TestIPNetwork, "no_network;ip"); + PTF_RUN_TEST(TestObjectPool, "no_network"); + PTF_RUN_TEST(TestLogger, "no_network;logger"); PTF_RUN_TEST(TestLoggerMultiThread, "no_network;logger;skip_mem_leak_check"); diff --git a/Tests/PcppTestFramework/PcppTestFramework.h b/Tests/PcppTestFramework/PcppTestFramework.h index 9a1e60cad3..143e24332e 100644 --- a/Tests/PcppTestFramework/PcppTestFramework.h +++ b/Tests/PcppTestFramework/PcppTestFramework.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "memplumber.h" #include "PcppTestFrameworkCommon.h" diff --git a/ci/check-clang-format-version.py b/ci/check-clang-format-version.py index 7379a828a5..c2f97822d3 100644 --- a/ci/check-clang-format-version.py +++ b/ci/check-clang-format-version.py @@ -1,6 +1,6 @@ import subprocess -EXPECTED_CLANG_VERSION = "18.1.6" +EXPECTED_CLANG_VERSION = "19.1.6" def main(): diff --git a/ci/clang-tidy-all-new.sh b/ci/clang-tidy-all-new.sh new file mode 100755 index 0000000000..6d0dce5570 --- /dev/null +++ b/ci/clang-tidy-all-new.sh @@ -0,0 +1,43 @@ +#!/bin/sh +set -e + +IGNORE_LIST=".*dirent.* .*DpdkDevice* .*KniDevice* .*MBufRawPacket* .*PfRingDevice* .*RemoteDevice* .*XdpDevice* .*WinPcap* .*Examples* .*Tests* .*build* .*3rdParty* .*Packet\+\+* .*Pcap\+\+*" + +SCRIPT=$(readlink -f "$0") +SCRIPTPATH=$(dirname "${SCRIPT}") +ROOTPATH=$(realpath "${SCRIPTPATH}"/..) +if ! command -v clang-tidy; then + echo "clang-tidy is not found!" + exit 1 +fi + +# Determine the mode (all files or changed files) +MODE=${1:-all} +BUILD_DIR=${2:-build} + +if [ "$MODE" = "changed" ]; then + # Get the list of changed files from origin/dev + git fetch origin dev + files=$(git diff --name-only origin/dev -- '*.cpp' '*.h' | grep -v '3rdParty/' || true) +else + # Find all relevant files + files=$(find "${ROOTPATH}" -type f \( -name '*.cpp' -o -name '*.h' \) -not -path "*/3rdParty/*") +fi + +# Check if there are any files to process +if [ -z "$files" ]; then + echo "No files to process." + exit 0 +fi + +# Process each file +echo "$files" | while IFS= read -r file; do + for ignore in $IGNORE_LIST; do + if echo "$file" | grep -qE "$ignore"; then + echo "Ignoring: $file" + continue 2 + fi + done + echo "Checking: $file" + clang-tidy "$file" -p $BUILD_DIR --fix +done diff --git a/cmake/package/READMEs/release_notes.txt b/cmake/package/READMEs/release_notes.txt index 67e2915824..9e32a990c4 100644 --- a/cmake/package/READMEs/release_notes.txt +++ b/cmake/package/READMEs/release_notes.txt @@ -43,7 +43,7 @@ Release notes (changes from v23.09) - Fedora: added support for 39 and removed 37 (thanks @clementperon !) - Removed support for CentOS 7 - FreeBSD: added support for 14.0 and dropped 12 (thanks @clementperon !) -- Internal tools: +- Internal tools: - Reformatted the entire code base using `clang-format` (thanks @tigercosmos , @Dimi1010 !) - Added `dependabot` to keep GitHub Actions and Python packages up-to-date (thanks @egecetin !) - Added OpenSSF Scorecard automation to monitor and enhance security (thanks @egecetin !) @@ -112,11 +112,11 @@ Contributors - @axmahr - @Double0101 - @prudens -- @rtmeng -- @hidd3ncod3s +- @rtmeng +- @hidd3ncod3s - @WojtekMs - @mserdarsanli -- @MCredbear +- @MCredbear - @rahagal - @DeepakReddy1999 - @kraj