From e2e5dece58a0c5941474eaae7ad0bf724e3a58fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 12:33:43 +0300 Subject: [PATCH 01/35] Bump actions/checkout from 3.6.0 to 4.1.7 (#1490) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Commits](https://github.com/actions/checkout/compare/v3.6.0...v4.1.7) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/auto_update.yml | 4 ++-- .github/workflows/build_and_test.yml | 28 +++++++++++++------------- .github/workflows/check_dependabot.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/doxygen.yml | 4 ++-- .github/workflows/package.yml | 14 ++++++------- .github/workflows/scorecards.yml | 2 +- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/auto_update.yml b/.github/workflows/auto_update.yml index 7afef0803c..a254082adb 100644 --- a/.github/workflows/auto_update.yml +++ b/.github/workflows/auto_update.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: dev - name: Setup Python @@ -46,7 +46,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: ref: dev - name: Setup Python diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index edfbd28229..7f40638239 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -20,7 +20,7 @@ jobs: container: seladb/alpine317 steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Checkout is performed out of the container and doesn't match our user - name: Fix checkout ownership @@ -78,7 +78,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Checkout is performed out of the container and doesn't match our user - name: Fix checkout ownership @@ -152,7 +152,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Configure PcapPlusPlus run: cmake -DPCAPPP_USE_DPDK=ON ${{ matrix.additional-flags }} -S . -B "$BUILD_DIR" @@ -197,7 +197,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Configure PcapPlusPlus run: ${{ matrix.configure }} @@ -252,7 +252,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: @@ -329,7 +329,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: @@ -408,7 +408,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup MSYS2 uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # v2.23.0 @@ -502,7 +502,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: @@ -574,7 +574,7 @@ jobs: matrix: version: ["14.0", "13.2"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4.1.7 - name: Test in FreeBSD id: test uses: vmactions/freebsd-vm@v1 @@ -629,10 +629,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Checkout lipbcap for Android - uses: actions/checkout@cd7d8d697e10461458bc61a30d094dc601a8b017 # main + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # main with: repository: seladb/libpcap-android path: ./libpcap-android @@ -646,7 +646,7 @@ jobs: run: cmake --build "$BUILD_DIR" -j - name: Checkout ToyVpn-PcapPlusPlus - uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # master + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # master with: repository: seladb/ToyVpn-PcapPlusPlus path: ./ToyVpn-PcapPlusPlus @@ -677,7 +677,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Install dependencies run: | @@ -721,7 +721,7 @@ jobs: container: image: gcr.io/oss-fuzz-base/base-builder steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Install prerequisites run: | apt-get update && apt-get install -y cmake autoconf flex bison diff --git a/.github/workflows/check_dependabot.yml b/.github/workflows/check_dependabot.yml index 5b46b6c383..9d13a26c8e 100644 --- a/.github/workflows/check_dependabot.yml +++ b/.github/workflows/check_dependabot.yml @@ -13,6 +13,6 @@ jobs: validate: runs-on: ubuntu-latest steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: marocchino/validate-dependabot@d8ae5c0d03dd75fbd0ad5f8ab4ba8101ebbd4b37 # v3.0.0 id: validate diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 07fec5a18a..3f1ff5fc9d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index eb081d0bbd..91d4a8fd4f 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -14,10 +14,10 @@ jobs: container: seladb/ubuntu2204:latest steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Checkout docs repo - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: repository: PcapPlusPlus/pcapplusplus.github.io path: pcapplusplus.github.io diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 1b036b1a79..0e32c6f5ce 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Checkout is performed out of the container and doesn't match our user - name: Fix checkout ownership @@ -86,7 +86,7 @@ jobs: - freebsd-version: "14.0" steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Test in FreeBSD uses: vmactions/freebsd-vm@f8be330398166d1eb0601f01353839d4052367b2 # v1.0.7 @@ -125,7 +125,7 @@ jobs: xcode-version: "${{ matrix.xcode-version }}" - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Configure PcapPlusPlus run: | @@ -160,7 +160,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup MSYS2 uses: msys2/setup-msys2@d0e80f58dffbc64f6a3a1f43527d469b4fc7b6c8 # v2.23.0 @@ -221,7 +221,7 @@ jobs: contents: write steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0 @@ -268,10 +268,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Checkout lipbcap for Android - uses: actions/checkout@cd7d8d697e10461458bc61a30d094dc601a8b017 # main + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # main with: repository: seladb/libpcap-android path: ./libpcap-android diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 01e6b88b68..1fd17e362c 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -31,7 +31,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false From cda50ce7aadf94087a7c3a45b5b48f65325c799f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20=C3=87etin?= <64282645+egecetin@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:14:12 +0300 Subject: [PATCH 02/35] add group defs (#1494) --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8cf53b14b9..00c1188fff 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,9 @@ updates: target-branch: "dev" labels: - "automated-pr" + group: + name: "GitHub Actions" + package-ecosystem: "github-actions" - package-ecosystem: "pip" directories: @@ -17,3 +20,6 @@ updates: target-branch: "dev" labels: - "automated-pr" + group: + name: "pip updates" + package-ecosystem: "pip" From 754793da5d7a7a51a57fa0dd268ceb1cb204e775 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:17:11 -0700 Subject: [PATCH 03/35] Bump codecov/codecov-action from 3.1.6 to 4.5.0 (#1491) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.6 to 4.5.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/ab904c41d6ece82784817410c45d8b8c02684457...e28ff129e5465c2c0dcc6f003fc735cb6ae0c673) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build_and_test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 7f40638239..4dba9f592c 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -129,7 +129,7 @@ jobs: gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: ${{ matrix.image }},unittest @@ -312,7 +312,7 @@ jobs: gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: ${{ matrix.os-version }},unittest @@ -387,7 +387,7 @@ jobs: gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: ${{ matrix.os-version }},unittest @@ -469,7 +469,7 @@ jobs: run: gcovr -v -g -k -r . $env:GCOVR_FLAGS.split() -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: ${{ matrix.sys }},unittest @@ -559,7 +559,7 @@ jobs: python -m pytest --root-path=../../Dist/examples_bin - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./Tests/Pcap++Test/Pcap++Coverage.xml,./Tests/Packet++Test/Packet++Coverage.xml flags: ${{ matrix.os }},unittest,${{ matrix.pcap_lib }} @@ -701,7 +701,7 @@ jobs: gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: xdp,unittest From 1a436d9abf36a354e059d57f5f495b06f7ddca63 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Wed, 17 Jul 2024 06:03:15 +0300 Subject: [PATCH 04/35] Refactor of `PcapRemoteDeviceList`'s factory functions. (#1476) * Refactor PcapRemoteDeviceList with smart pointers - Introduced `createRemoteDeviceList` static methods in `PcapRemoteDeviceList` for creating and managing remote device lists using `std::unique_ptr`, enhancing memory management and safety. - Modified existing `getRemoteDeviceList` methods to utilize new `createRemoteDeviceList` methods, maintaining backward compatibility by returning raw pointers through `.release()`. - Adopted smart pointers (`std::unique_ptr`) in the implementation for automatic memory cleanup, reducing the risk of memory leaks and improving code maintainability. - Modernized the codebase by leveraging C++11 smart pointers, simplifying resource management and providing a clearer, more flexible API for handling remote device lists with and without authentication. * Refactor iterator type aliases in PcapRemoteDeviceList Modernized the syntax for defining iterator and const iterator type aliases in `PcapRemoteDeviceList.h` within the `pcpp` namespace. Replaced traditional `typedef` with the `using` syntax for `RemoteDeviceListIterator` and `ConstRemoteDeviceListIterator`. These changes enhance code readability and align with modern C++ best practices without altering functionality. * Enhance PcapRemoteDeviceList construction - Removed the default constructor of 'PcapRemoteDeviceList'. - Added a new constructor to `PcapRemoteDeviceList` for initializing with detailed remote machine info and authentication. - Corrected typographical errors in comments for better documentation clarity. - Improved const-correctness in `createRemoteDeviceList` by changing `remoteAuth` parameter type. - Refactored device creation logic in `createRemoteDeviceList` for clearer error handling and separation of concerns. - Enhanced error handling in device creation to prevent memory leaks on exceptions. - Transitioned to using `std::shared_ptr` for better memory management in device creation. - Simplified authentication object handling by converting to `std::shared_ptr` early in the device creation process. * Removed unused setter methods. * Refactor PcapRemoteDeviceList creation - Included DeprecationUtils.h in PcapRemoteDeviceList.h to mark certain functionalities as deprecated, indicating a move towards newer alternatives. - Updated the private constructor comment in PcapRemoteDeviceList to recommend using `createRemoteDeviceList` for instance creation, reflecting a shift to a new factory method. - Deprecated two static factory functions, `getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port)` and `getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication* remoteAuth)`, in favor of `createRemoteDeviceList`, enhancing memory safety and functionality. * Clarified variable name. * Renamed sRemoteAuth to remoteAuthCopy. * Updated variable name to conform with pointer naming conventions. --- Pcap++/header/PcapRemoteDeviceList.h | 59 ++++++++++++++++++--- Pcap++/src/PcapRemoteDeviceList.cpp | 76 ++++++++++++++++------------ 2 files changed, 94 insertions(+), 41 deletions(-) diff --git a/Pcap++/header/PcapRemoteDeviceList.h b/Pcap++/header/PcapRemoteDeviceList.h index 4d9e09a3d3..3b00bd2738 100644 --- a/Pcap++/header/PcapRemoteDeviceList.h +++ b/Pcap++/header/PcapRemoteDeviceList.h @@ -5,6 +5,7 @@ #include #include "IpAddress.h" #include "PcapRemoteDevice.h" +#include "DeprecationUtils.h" /// @file @@ -33,23 +34,21 @@ namespace pcpp uint16_t m_RemoteMachinePort; std::shared_ptr m_RemoteAuthentication; - // private c'tor. User should create the list via static methods PcapRemoteDeviceList::getRemoteDeviceList() - PcapRemoteDeviceList() : m_RemoteMachinePort(0), m_RemoteAuthentication(nullptr) {} - - void setRemoteMachineIpAddress(const IPAddress& ipAddress); - void setRemoteMachinePort(uint16_t port); - void setRemoteAuthentication(const PcapRemoteAuthentication* remoteAuth); + // private c'tor. User should create the list via static methods PcapRemoteDeviceList::createRemoteDeviceList() + PcapRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, + std::shared_ptr remoteAuth, + std::vector deviceList); public: /** * Iterator object that can be used for iterating all PcapRemoteDevice in list */ - typedef typename std::vector::iterator RemoteDeviceListIterator; + using RemoteDeviceListIterator = typename std::vector::iterator; /** * Const iterator object that can be used for iterating all PcapRemoteDevice in a constant list */ - typedef typename std::vector::const_iterator ConstRemoteDeviceListIterator; + using ConstRemoteDeviceListIterator = typename std::vector::const_iterator; PcapRemoteDeviceList(const PcapRemoteDeviceList&) = delete; PcapRemoteDeviceList(PcapRemoteDeviceList&&) noexcept = delete; @@ -70,9 +69,30 @@ namespace pcpp * - IP address provided is NULL 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 + */ + 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 @@ -84,9 +104,32 @@ namespace pcpp * - IP address provided is NULL 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 + */ + static std::unique_ptr createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication const* remoteAuth); + /** * @return The IP address of the remote machine */ diff --git a/Pcap++/src/PcapRemoteDeviceList.cpp b/Pcap++/src/PcapRemoteDeviceList.cpp index e852e6c297..bc479a2caf 100644 --- a/Pcap++/src/PcapRemoteDeviceList.cpp +++ b/Pcap++/src/PcapRemoteDeviceList.cpp @@ -48,19 +48,40 @@ namespace pcpp } } +PcapRemoteDeviceList::PcapRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, std::shared_ptr remoteAuth, std::vector deviceList) + : m_RemoteDeviceList(std::move(deviceList)) + , m_RemoteMachineIpAddress(ipAddress) + , m_RemoteMachinePort(port) + , m_RemoteAuthentication(std::move(remoteAuth)) +{} + PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port) { - return PcapRemoteDeviceList::getRemoteDeviceList(ipAddress, port, NULL); + auto result = PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port); + return result.release(); +} + +std::unique_ptr PcapRemoteDeviceList::createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port) +{ + return PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port, nullptr); } PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication* remoteAuth) { + auto result = PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port, remoteAuth); + return result.release(); +} + +std::unique_ptr PcapRemoteDeviceList::createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication const* remoteAuth) +{ + std::shared_ptr pRemoteAuthCopy; pcap_rmtauth* pRmAuth = nullptr; pcap_rmtauth rmAuth; if (remoteAuth != nullptr) { PCPP_LOG_DEBUG("Authentication requested. Username: " << remoteAuth->userName << ", Password: " << remoteAuth->password); - rmAuth = remoteAuth->getPcapRmAuth(); + pRemoteAuthCopy = std::make_shared(*remoteAuth); + rmAuth = pRemoteAuthCopy->getPcapRmAuth(); pRmAuth = &rmAuth; } @@ -75,20 +96,29 @@ PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& return nullptr; } - PcapRemoteDeviceList* resultList = new PcapRemoteDeviceList(); - resultList->setRemoteMachineIpAddress(ipAddress); - resultList->setRemoteMachinePort(port); - resultList->setRemoteAuthentication(remoteAuth); - - - for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next) + std::vector devices; + try + { + for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next) + { + auto pNewRemoteDevice = std::unique_ptr(new PcapRemoteDevice(currInterface, pRemoteAuthCopy, ipAddress, port)); + // Release is called after pushback to prevent memory leaks if vector reallocation fails. + // cppcheck-suppress danglingLifetime + devices.push_back(pNewRemoteDevice.get()); + pNewRemoteDevice.release(); + } + } + catch (const std::exception& e) { - PcapRemoteDevice* pNewRemoteDevice = new PcapRemoteDevice(currInterface, resultList->m_RemoteAuthentication, - resultList->getRemoteMachineIpAddress(), resultList->getRemoteMachinePort()); - resultList->m_RemoteDeviceList.push_back(pNewRemoteDevice); + for (auto device : devices) + { + delete device; + } + PCPP_LOG_ERROR("Error creating remote devices: " << e.what()); + return nullptr; } - return resultList; + return std::unique_ptr(new PcapRemoteDeviceList(ipAddress, port, pRemoteAuthCopy, devices)); } PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const std::string& ipAddrAsString) const @@ -190,26 +220,6 @@ PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPv6Address& i } -void PcapRemoteDeviceList::setRemoteMachineIpAddress(const IPAddress& ipAddress) -{ - m_RemoteMachineIpAddress = ipAddress; -} - -void PcapRemoteDeviceList::setRemoteMachinePort(uint16_t port) -{ - m_RemoteMachinePort = port; -} - -void PcapRemoteDeviceList::setRemoteAuthentication(const PcapRemoteAuthentication* remoteAuth) -{ - if (remoteAuth != nullptr) - m_RemoteAuthentication = std::shared_ptr(new PcapRemoteAuthentication(*remoteAuth)); - else - { - m_RemoteAuthentication = nullptr; - } -} - PcapRemoteDeviceList::~PcapRemoteDeviceList() { while (m_RemoteDeviceList.size() > 0) From d94d5a228946d5296781e9a7a0a6a77e55fa6d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20=C3=87etin?= <64282645+egecetin@users.noreply.github.com> Date: Thu, 18 Jul 2024 10:24:29 +0300 Subject: [PATCH 05/35] Fix dependabot config (#1501) * typo fix * fix dependabot config --- .github/dependabot.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 00c1188fff..21a9e3e180 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,9 +7,10 @@ updates: target-branch: "dev" labels: - "automated-pr" - group: - name: "GitHub Actions" - package-ecosystem: "github-actions" + groups: + actions-dependencies: + patterns: + - "*" - package-ecosystem: "pip" directories: @@ -20,6 +21,7 @@ updates: target-branch: "dev" labels: - "automated-pr" - group: - name: "pip updates" - package-ecosystem: "pip" + groups: + pip-dependencies: + patterns: + - "*" From a605fa8fa30ba6d6150bb780b448b0dd65bfbab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Fri, 19 Jul 2024 04:35:47 +0200 Subject: [PATCH 06/35] ci: github: save and restore ccache database (#1492) * ci: github: save and restore ccache database * workflows: ensure BUILD_DIR is only one param * workflow: merge MacOS jobs and use Ccache * workflows: uniformize python versions * workflows: add ccache for XDP * workflows: fix double space * workflows: add Ccache for Fuzzer * workflows: fix running macos cross binaries runs --- .github/workflows/build_and_test.yml | 210 +++++++++++++++------------ 1 file changed, 115 insertions(+), 95 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 4dba9f592c..f41055cef2 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -10,6 +10,7 @@ on: env: BUILD_DIR: Dist GCOVR_FLAGS: --gcov-ignore-parse-errors --exclude-throw-branches --filter Common --filter Pcap --filter Packet --xml + CCACHE_DIR: ${{ github.workspace }}/.ccache permissions: contents: read @@ -90,6 +91,13 @@ jobs: . /opt/intel/oneapi/setvars.sh printenv >> $GITHUB_ENV + - name: Restore Ccache + id: ccache-restore + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.image }}-ccache + - name: Configure PcapPlusPlus run: cmake -DLIGHT_PCAPNG_ZSTD=${{ matrix.config-zstd }} -DPCAPPP_BUILD_COVERAGE=ON ${{ matrix.additional-flags }} -S . -B "$BUILD_DIR" @@ -113,7 +121,7 @@ jobs: run: | cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR" cmake --build "$BUILD_DIR" -j - cmake --install $BUILD_DIR + cmake --install "$BUILD_DIR" - name: Build Tutorials run: | @@ -138,6 +146,12 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Save Ccache + uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache-restore.outputs.cache-primary-key }} + dpdk: runs-on: ubuntu-latest container: seladb/${{ matrix.image }} @@ -154,6 +168,13 @@ jobs: - name: Checkout code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Restore Ccache + id: ccache-restore + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.image }}-ccache + - name: Configure PcapPlusPlus run: cmake -DPCAPPP_USE_DPDK=ON ${{ matrix.additional-flags }} -S . -B "$BUILD_DIR" @@ -177,7 +198,7 @@ jobs: run: | cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR" cmake --build "$BUILD_DIR" -j - cmake --install $BUILD_DIR + cmake --install "$BUILD_DIR" - name: Build Tutorials run: | @@ -187,6 +208,12 @@ jobs: - name: Test Tutorials run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld + - name: Save Ccache + uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache-restore.outputs.cache-primary-key }} + pfring: runs-on: ubuntu-latest container: seladb/ubuntu2004-pfring @@ -199,6 +226,13 @@ jobs: - name: Checkout code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Restore Ccache + id: ccache-restore + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.image }}-ccache + - name: Configure PcapPlusPlus run: ${{ matrix.configure }} @@ -219,7 +253,7 @@ jobs: run: | cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR" cmake --build "$BUILD_DIR" -j - cmake --install $BUILD_DIR + cmake --install "$BUILD_DIR" - name: Build Tutorials run: | @@ -229,24 +263,39 @@ jobs: - name: Test Tutorials run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld - macos-x86: + - name: Save Ccache + uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache-restore.outputs.cache-primary-key }} + + macos: runs-on: ${{ matrix.os-version }} strategy: matrix: include: - os-version: macos-12 + host-arch: x86_64 arch: x86_64 config-zstd: OFF - os-version: macos-12 + host-arch: x86_64 arch: arm64 config-zstd: OFF - os-version: macos-13 + host-arch: x86_64 arch: x86_64 config-zstd: OFF - os-version: macos-13 + host-arch: x86_64 arch: x86_64 config-zstd: ON - os-version: macos-13 + host-arch: x86_64 + arch: arm64 + config-zstd: OFF + - os-version: macos-14 + host-arch: arm64 arch: arm64 config-zstd: OFF @@ -254,15 +303,27 @@ jobs: - name: Checkout code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + - name: Setup Python + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: # support version: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json python-version: "3.12" + - name: Install Requirements Ccache & Tcpreplay + run: brew install ccache tcpreplay + + - name: Restore Ccache + id: ccache-restore + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.os-version }}-ccache + - name: Configure PcapPlusPlus # Ensure user have access to network devices instead of giving super-user right run: | sudo chmod a+rw /dev/bpf* + sudo chmod a+rw /usr/local cmake -DLIGHT_PCAPNG_ZSTD=${{ matrix.config-zstd }} -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} -DPCAPPP_BUILD_COVERAGE=ON -S . -B "$BUILD_DIR" - name: Build PcapPlusPlus @@ -271,19 +332,16 @@ jobs: - name: Check architecture run: lipo $BUILD_DIR/Pcap++/libPcap++.a -verify_arch ${{ matrix.arch }} - - name: Install Tcpreplay - run: brew install tcpreplay - - name: Test PcapPlusPlus # We can't run cross compiled binaries - if: ${{ matrix.arch == 'x86_64' }} + if: ${{ matrix.host-arch == matrix.arch }} run: | python -m pip install -U pip python -m pip install -r ci/run_tests/requirements.txt python ci/run_tests/run_tests.py --interface en0 - name: Test Examples - if: ${{ matrix.arch == 'x86_64' }} + if: ${{ matrix.host-arch == matrix.arch }} run: | cd Tests/ExamplesTest python -m pip install -U pip @@ -294,7 +352,7 @@ jobs: run: | cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR" cmake --build "$BUILD_DIR" -j - cmake --install $BUILD_DIR + cmake --install "$BUILD_DIR" - name: Build Tutorials run: | @@ -303,7 +361,7 @@ jobs: cmake --build build_examples -j - name: Test Tutorials - if: ${{ matrix.arch == 'x86_64' }} + if: ${{ matrix.host-arch == matrix.arch }} run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld - name: Create Cobertura Report @@ -321,80 +379,11 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - macos-m1: - runs-on: ${{ matrix.os-version }} - strategy: - matrix: - os-version: [macos-14] - - steps: - - name: Checkout code - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 - with: - # support version: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json - python-version: "3.12" - - - name: Configure PcapPlusPlus - # Ensure user have access to network devices instead of giving super-user right - # Seems macos-14 has more strict file permission - run: | - sudo chmod a+rw /dev/bpf* - sudo chmod a+rw /usr/local - cmake -DPCAPPP_BUILD_COVERAGE=ON -S . -B "$BUILD_DIR" - - - name: Build PcapPlusPlus - run: cmake --build "$BUILD_DIR" -j - - - name: Check architecture - run: lipo $BUILD_DIR/Pcap++/libPcap++.a -verify_arch arm64 - - - name: Install Tcpreplay - run: brew install tcpreplay - - - name: Test PcapPlusPlus - run: | - python -m pip install -U pip - python -m pip install -r ci/run_tests/requirements.txt - python ci/run_tests/run_tests.py --interface en0 - - - name: Test Examples - run: | - cd Tests/ExamplesTest - python -m pip install -U pip - python -m pip install -r requirements.txt - python -m pytest --interface en0 --use-sudo --root-path=../../Dist/examples_bin - - - name: Check installation - run: | - cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR" - cmake --build "$BUILD_DIR" -j - cmake --install "$BUILD_DIR" - - - name: Build Tutorials - run: | - mkdir -p build_examples - cmake -DPCAPPP_BUILD_TUTORIALS=ON -S Examples -B build_examples - cmake --build build_examples -j - - - name: Test Tutorials - run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld - - - name: Create Cobertura Report - run: | - python3 -m pip install gcovr - gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - - - name: Upload Coverage Results - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + - name: Save Ccache + uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: - files: ./coverage.xml - flags: ${{ matrix.os-version }},unittest - fail_ci_if_error: false - verbose: true - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache-restore.outputs.cache-primary-key }} mingw-w64: runs-on: windows-latest @@ -423,7 +412,7 @@ jobs: - name: Setup Python uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: - python-version: "3.8.x" + python-version: "3.12" - name: Install NPcap env: @@ -504,9 +493,10 @@ jobs: - name: Checkout code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + - name: Setup Python + uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 with: - python-version: "3.8.x" + python-version: "3.12" - name: Add MSBuild to PATH uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0 @@ -660,7 +650,7 @@ jobs: PCAPPLUSPLUS_INCLUDE_PATH="$TOYVPN_PCAPPLUSPLUS/include" cmake -DPCAPPP_BUILD_COVERAGE=OFF -S . -B "$BUILD_DIR" cmake --build "$BUILD_DIR" -j - cmake --install $BUILD_DIR --prefix ${TOYVPN_PCAPPLUSPLUS} + cmake --install "$BUILD_DIR" --prefix ${TOYVPN_PCAPPLUSPLUS} mkdir -p ${PCAPPLUSPLUS_LIBS_PATH} ${PCAPPLUSPLUS_INCLUDE_PATH} mv ${TOYVPN_PCAPPLUSPLUS}/lib/*.a ${PCAPPLUSPLUS_LIBS_PATH}/ mv ${TOYVPN_PCAPPLUSPLUS}/include/pcapplusplus/*.h ${PCAPPLUSPLUS_INCLUDE_PATH}/ @@ -681,7 +671,14 @@ jobs: - name: Install dependencies run: | - sudo apt update && sudo apt -y install libpcap-dev libbpf-dev tcpreplay + sudo apt update && sudo apt -y install ccache libpcap-dev libbpf-dev tcpreplay + + - name: Restore Ccache + id: ccache-restore + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.image }}-ccache - name: Configure PcapPlusPlus run: cmake -DPCAPPP_USE_XDP=ON -DPCAPPP_BUILD_COVERAGE=ON -S . -B $BUILD_DIR @@ -692,8 +689,8 @@ jobs: - name: Test PcapPlusPlus run: | python -m pip install -U pip - python -m pip install -r ci/run_tests/requirements.txt - python ci/run_tests/run_tests.py --interface eth0 --use-sudo --pcap-test-args="-t xdp" + python -m pip install -r ci/run_tests/requirements.txt + python ci/run_tests/run_tests.py --interface eth0 --use-sudo --pcap-test-args="-t xdp" - name: Create Cobertura Report run: | @@ -710,6 +707,12 @@ jobs: env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Save Ccache + uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache-restore.outputs.cache-primary-key }} + test_regressions: name: Run ${{ matrix.engine }}-${{ matrix.sanitizer }} fuzzer for regressions runs-on: ubuntu-latest @@ -721,23 +724,40 @@ jobs: container: image: gcr.io/oss-fuzz-base/base-builder steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Checkout code + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Install prerequisites run: | - apt-get update && apt-get install -y cmake autoconf flex bison + apt-get update && apt-get install -y autoconf bison ccache cmake flex cd .. cp -r PcapPlusPlus/ $SRC/PcapPlusPlus git clone --depth=1 https://github.com/the-tcpdump-group/libpcap.git $SRC/libpcap cd $SRC/PcapPlusPlus/ - - name: Compile fuzzer + + - name: Restore Ccache + id: ccache-restore + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ matrix.engine }}-${{ matrix.sanitizer }}-ccache + + - name: Compile PcapPlusPlus Fuzzer application run: | export FUZZING_LANGUAGE=c export ARCHITECTURE=x86_64 export FUZZING_ENGINE=${{ matrix.engine }} export SANITIZER=${{ matrix.sanitizer }} $SRC/PcapPlusPlus/Tests/Fuzzers/ossfuzz.sh + - name: Check for regressions run: | export BINARY="$OUT/FuzzTarget" export SAMPLES="Tests/Fuzzers/RegressionTests/regression_samples" Tests/Fuzzers/RegressionTests/run_tests.sh + + - name: Save Ccache + uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache-restore.outputs.cache-primary-key }} From a4a7e89ea6257843509dceb67be616b9a437c4b8 Mon Sep 17 00:00:00 2001 From: prudens Date: Fri, 19 Jul 2024 10:51:29 +0800 Subject: [PATCH 07/35] Fix bugs in `hash5Tuple` (#1495) --- Packet++/src/PacketUtils.cpp | 7 +++---- Tests/Packet++Test/Tests/PacketUtilsTests.cpp | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Packet++/src/PacketUtils.cpp b/Packet++/src/PacketUtils.cpp index 01ea361303..c75d4b74d5 100644 --- a/Packet++/src/PacketUtils.cpp +++ b/Packet++/src/PacketUtils.cpp @@ -181,7 +181,7 @@ uint32_t hash5Tuple(Packet* packet, bool const& directionUnique) IPv4Layer* ipv4Layer = packet->getLayerOfType(); if (ipv4Layer != nullptr) { - if (portSrc == portDst && ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc) + if (!directionUnique && portSrc == portDst && ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc) srcPosition = 1; vec[2 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; @@ -194,7 +194,7 @@ uint32_t hash5Tuple(Packet* packet, bool const& directionUnique) else { IPv6Layer* ipv6Layer = packet->getLayerOfType(); - if (portSrc == portDst && (uint64_t)ipv6Layer->getIPv6Header()->ipDst < (uint64_t)ipv6Layer->getIPv6Header()->ipSrc) + if (!directionUnique && portSrc == portDst && memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0) srcPosition = 1; vec[2 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc; @@ -232,8 +232,7 @@ uint32_t hash2Tuple(Packet* packet) { IPv6Layer* ipv6Layer = packet->getLayerOfType(); int srcPosition = 0; - if ((uint64_t)ipv6Layer->getIPv6Header()->ipDst < (uint64_t)ipv6Layer->getIPv6Header()->ipSrc - && (uint64_t)(ipv6Layer->getIPv6Header()->ipDst+8) < (uint64_t)(ipv6Layer->getIPv6Header()->ipSrc+8)) + if (memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0) srcPosition = 1; vec[0 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc; diff --git a/Tests/Packet++Test/Tests/PacketUtilsTests.cpp b/Tests/Packet++Test/Tests/PacketUtilsTests.cpp index bd8ab1aaf5..70b30a7f76 100644 --- a/Tests/Packet++Test/Tests/PacketUtilsTests.cpp +++ b/Tests/Packet++Test/Tests/PacketUtilsTests.cpp @@ -97,6 +97,15 @@ PTF_TEST_CASE(PacketUtilsHash5TupleTcp) PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, false), 1576639238 ); PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, true), 1576639238 ); + tcpLayer.getTcpHeader()->portDst = 80; + tcpLayer.getTcpHeader()->portSrc = 80; + + tcpLayer2.getTcpHeader()->portDst = 80; + tcpLayer2.getTcpHeader()->portSrc = 80; + + PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&srcDstPacket), pcpp::hash5Tuple(&dstSrcPacket)); + PTF_ASSERT_NOT_EQUAL(pcpp::hash5Tuple(&srcDstPacket,true), pcpp::hash5Tuple(&dstSrcPacket,true)); + } // PacketUtilsHash5TupleTcp @@ -133,4 +142,13 @@ PTF_TEST_CASE(PacketUtilsHash5TupleIPv6) PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, false), 4288746927); PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, true), 4288746927); + udpLayer.getUdpHeader()->portDst = 80; + udpLayer.getUdpHeader()->portSrc = 80; + + udpLayer2.getUdpHeader()->portDst = 80; + udpLayer2.getUdpHeader()->portSrc = 80; + + PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&srcDstPacket), pcpp::hash5Tuple(&dstSrcPacket)); + PTF_ASSERT_NOT_EQUAL(pcpp::hash5Tuple(&srcDstPacket, true), pcpp::hash5Tuple(&dstSrcPacket, true)); + } // PacketUtilsHash5TupleIPv6 From f66ea776311803eb6f23ef7e1604f3b8d43bdcb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:46:31 -0700 Subject: [PATCH 08/35] Bump pytest (#1502) Bumps the pip-dependencies group with 1 update in the /Tests/ExamplesTest directory: [pytest](https://github.com/pytest-dev/pytest). Updates `pytest` from 8.2.1 to 8.2.2 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.2.1...8.2.2) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-patch dependency-group: pip-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Tests/ExamplesTest/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ExamplesTest/requirements.txt b/Tests/ExamplesTest/requirements.txt index 19ea22aef2..95b339fbf6 100644 --- a/Tests/ExamplesTest/requirements.txt +++ b/Tests/ExamplesTest/requirements.txt @@ -2,6 +2,6 @@ attrs==23.2.0 iniconfig==2.0.0 py==1.11.0 pyparsing==3.1.2 -pytest==8.2.1 +pytest==8.2.2 scapy==2.5.0 toml==0.10.2 From 5672654f3f3375cdad6a95c99b9e7ebb8c067a3a Mon Sep 17 00:00:00 2001 From: seladb Date: Fri, 19 Jul 2024 20:46:13 -0700 Subject: [PATCH 09/35] Update python version for FreeBSD to 3.11 (#1504) --- .github/workflows/package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 0e32c6f5ce..8c57e29370 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -95,7 +95,7 @@ jobs: envs: 'BUILD_DIR' usesh: true prepare: | - pkg install -y bash cmake git-tiny gmake gsed libpcap py39-pip + pkg install -y bash cmake git-tiny gmake gsed libpcap py311-pip run: | cmake -DPCAPPP_PACKAGE=ON -S . -B "$BUILD_DIR" cmake --build "$BUILD_DIR" -j 4 From 8841a3d294108edf965cda39e0fb53bb613176ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Jul 2024 00:44:31 -0700 Subject: [PATCH 10/35] Bump the actions-dependencies group with 3 updates (#1503) Bumps the actions-dependencies group with 3 updates: [actions/setup-python](https://github.com/actions/setup-python), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [github/codeql-action](https://github.com/github/codeql-action). Updates `actions/setup-python` from 5.1.0 to 5.1.1 - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/82c7e631bb3cdc910f68e0081d67478d79c6982d...39cd14951b08e74b54015e9e001cdefcf80e669f) Updates `actions/upload-artifact` from 4.3.3 to 4.3.4 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/65462800fd760344b1a7b4382951275a0abb4808...0b2256b8c012f0828dc542b3febcab082c67f72b) Updates `github/codeql-action` from 3.25.11 to 3.25.12 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/b611370bb5703a7efb587f9d136a52ea24c5c38c...4fa2a7953630fd2f3fb380f21be14ede0169dd4f) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-dependencies - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-dependencies - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Liu, An-Chi --- .github/workflows/auto_update.yml | 4 ++-- .github/workflows/build_and_test.yml | 6 +++--- .github/workflows/cifuzz.yml | 2 +- .github/workflows/codeql.yml | 4 ++-- .github/workflows/package.yml | 2 +- .github/workflows/scorecards.yml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/auto_update.yml b/.github/workflows/auto_update.yml index a254082adb..0f7e8cb4fe 100644 --- a/.github/workflows/auto_update.yml +++ b/.github/workflows/auto_update.yml @@ -17,7 +17,7 @@ jobs: with: ref: dev - name: Setup Python - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 with: python-version: "3.8.x" - name: Run update @@ -50,7 +50,7 @@ jobs: with: ref: dev - name: Setup Python - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 with: python-version: "3.9.x" - name: Run update diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index f41055cef2..2445f45a77 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -304,7 +304,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup Python - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 with: # support version: https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json python-version: "3.12" @@ -410,7 +410,7 @@ jobs: mingw-w64-${{matrix.env}}-make - name: Setup Python - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 with: python-version: "3.12" @@ -494,7 +494,7 @@ jobs: uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup Python - uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0 + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 with: python-version: "3.12" diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml index 84805e64a6..5666ef2852 100644 --- a/.github/workflows/cifuzz.yml +++ b/.github/workflows/cifuzz.yml @@ -31,7 +31,7 @@ jobs: dry-run: false sanitizer: ${{ matrix.sanitizer }} - name: Upload Crash - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 if: failure() && steps.build.outcome == 'success' with: name: artifacts diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3f1ff5fc9d..3890a82da0 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -29,7 +29,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 + uses: github/codeql-action/init@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3.25.12 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -44,4 +44,4 @@ jobs: cmake --build build -j - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 + uses: github/codeql-action/analyze@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3.25.12 diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 8c57e29370..4480207351 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -301,7 +301,7 @@ jobs: mkdir -p "android-package" mv "${COMBINED_PACKAGE_DIR}" "android-package" - - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: path: android-package name: android-package-${{ matrix.target }}-${{ matrix.api-version }} diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 1fd17e362c..d97b8d96fd 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -58,7 +58,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 with: name: SARIF file path: results.sarif @@ -66,6 +66,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b611370bb5703a7efb587f9d136a52ea24c5c38c # v3.25.11 + uses: github/codeql-action/upload-sarif@4fa2a7953630fd2f3fb380f21be14ede0169dd4f # v3.25.12 with: sarif_file: results.sarif From 4110f2dd444545393a6649ae1128510665a932b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 22 Jul 2024 00:57:05 +0200 Subject: [PATCH 11/35] Fix CI CMake cache (#1505) --- .github/workflows/build_and_test.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 2445f45a77..7039fe88a5 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -96,7 +96,9 @@ jobs: uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ${{ env.CCACHE_DIR }} - key: ${{ matrix.image }}-ccache + key: ${{ matrix.image }}-ccache-${{ github.run_id }} + restore-keys: | + ${{ matrix.image }}-ccache - name: Configure PcapPlusPlus run: cmake -DLIGHT_PCAPNG_ZSTD=${{ matrix.config-zstd }} -DPCAPPP_BUILD_COVERAGE=ON ${{ matrix.additional-flags }} -S . -B "$BUILD_DIR" @@ -173,7 +175,9 @@ jobs: uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ${{ env.CCACHE_DIR }} - key: ${{ matrix.image }}-ccache + key: ${{ matrix.image }}-ccache-${{ github.run_id }} + restore-keys: | + ${{ matrix.image }}-ccache - name: Configure PcapPlusPlus run: cmake -DPCAPPP_USE_DPDK=ON ${{ matrix.additional-flags }} -S . -B "$BUILD_DIR" @@ -231,7 +235,9 @@ jobs: uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ${{ env.CCACHE_DIR }} - key: ${{ matrix.image }}-ccache + key: ${{ matrix.image }}-ccache-${{ github.run_id }} + restore-keys: | + ${{ matrix.image }}-ccache - name: Configure PcapPlusPlus run: ${{ matrix.configure }} @@ -317,7 +323,9 @@ jobs: uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ${{ env.CCACHE_DIR }} - key: ${{ matrix.os-version }}-ccache + key: ${{ matrix.os-version }}-${{ matrix.arch }}-ccache-${{ github.run_id }} + restore-keys: | + ${{ matrix.os-version }}-${{ matrix.arch }}-ccache - name: Configure PcapPlusPlus # Ensure user have access to network devices instead of giving super-user right @@ -678,7 +686,9 @@ jobs: uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ${{ env.CCACHE_DIR }} - key: ${{ matrix.image }}-ccache + key: ${{ matrix.image }}-ccache-${{ github.run_id }} + restore-keys: | + ${{ matrix.image }}-ccache - name: Configure PcapPlusPlus run: cmake -DPCAPPP_USE_XDP=ON -DPCAPPP_BUILD_COVERAGE=ON -S . -B $BUILD_DIR @@ -740,7 +750,9 @@ jobs: uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ${{ env.CCACHE_DIR }} - key: ${{ matrix.engine }}-${{ matrix.sanitizer }}-ccache + key: ${{ matrix.engine }}-${{ matrix.sanitizer }}-ccache-${{ github.run_id }} + restore-keys: | + ${{ matrix.engine }}-${{ matrix.sanitizer }}-ccache - name: Compile PcapPlusPlus Fuzzer application run: | From add1746b963bc85cdb6a4699f07404d4cfc19010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 22 Jul 2024 00:58:38 +0200 Subject: [PATCH 12/35] Fix codecov for MacOS (#1506) --- .github/workflows/build_and_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 7039fe88a5..c65e561964 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -373,12 +373,14 @@ jobs: run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld - name: Create Cobertura Report + if: ${{ matrix.host-arch == matrix.arch }} run: | python3 -m pip install gcovr gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + if: ${{ matrix.host-arch == matrix.arch }} with: files: ./coverage.xml flags: ${{ matrix.os-version }},unittest From 176d3093a03b4e2482b84c8d00a650292c53cd36 Mon Sep 17 00:00:00 2001 From: seladb Date: Thu, 25 Jul 2024 00:29:00 -0700 Subject: [PATCH 13/35] Revert "Bump codecov/codecov-action from 3.1.6 to 4.5.0 (#1491)" This reverts commit 754793da5d7a7a51a57fa0dd268ceb1cb204e775. --- .github/workflows/build_and_test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index c65e561964..612cdb0e5f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -139,7 +139,7 @@ jobs: gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 with: files: ./coverage.xml flags: ${{ matrix.image }},unittest @@ -379,7 +379,7 @@ jobs: gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 if: ${{ matrix.host-arch == matrix.arch }} with: files: ./coverage.xml @@ -468,7 +468,7 @@ jobs: run: gcovr -v -g -k -r . $env:GCOVR_FLAGS.split() -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 with: files: ./coverage.xml flags: ${{ matrix.sys }},unittest @@ -559,7 +559,7 @@ jobs: python -m pytest --root-path=../../Dist/examples_bin - name: Upload Coverage Results - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 with: files: ./Tests/Pcap++Test/Pcap++Coverage.xml,./Tests/Packet++Test/Packet++Coverage.xml flags: ${{ matrix.os }},unittest,${{ matrix.pcap_lib }} @@ -710,7 +710,7 @@ jobs: gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 with: files: ./coverage.xml flags: xdp,unittest From 123994c8254f84829a5e1957b46b76395b5cdbfd Mon Sep 17 00:00:00 2001 From: "Liu, An-Chi" Date: Thu, 25 Jul 2024 22:28:34 +0900 Subject: [PATCH 14/35] apply clang-format to `Tests` (#1456) apply clang-format to `Tests` --- .clang-format | 2 +- Tests/Fuzzers/DumpToFile.h | 4 +- Tests/Fuzzers/FuzzTarget.cpp | 13 +- Tests/Fuzzers/FuzzWriter.cpp | 12 +- Tests/Fuzzers/ReadParsedPacket.h | 941 +++++++++--------- Tests/Packet++Test/Tests/Asn1Tests.cpp | 86 +- Tests/Packet++Test/Tests/BgpTests.cpp | 142 +-- Tests/Packet++Test/Tests/CotpTests.cpp | 2 +- Tests/Packet++Test/Tests/DhcpTests.cpp | 116 ++- Tests/Packet++Test/Tests/DhcpV6Tests.cpp | 48 +- Tests/Packet++Test/Tests/DnsTests.cpp | 176 ++-- Tests/Packet++Test/Tests/EthAndArpTests.cpp | 48 +- Tests/Packet++Test/Tests/FtpTests.cpp | 331 +++--- Tests/Packet++Test/Tests/GreTests.cpp | 22 +- Tests/Packet++Test/Tests/GtpTests.cpp | 43 +- Tests/Packet++Test/Tests/HttpTests.cpp | 235 +++-- Tests/Packet++Test/Tests/IPSecTests.cpp | 3 +- Tests/Packet++Test/Tests/IPv4Tests.cpp | 67 +- Tests/Packet++Test/Tests/IPv6Tests.cpp | 50 +- Tests/Packet++Test/Tests/IcmpTests.cpp | 104 +- Tests/Packet++Test/Tests/IcmpV6Tests.cpp | 167 ++-- Tests/Packet++Test/Tests/IgmpTests.cpp | 51 +- Tests/Packet++Test/Tests/LLCTests.cpp | 14 +- Tests/Packet++Test/Tests/LdapTests.cpp | 529 ++++++---- Tests/Packet++Test/Tests/NflogTests.cpp | 23 +- Tests/Packet++Test/Tests/NtpTests.cpp | 465 ++++----- Tests/Packet++Test/Tests/PPPoETests.cpp | 53 +- Tests/Packet++Test/Tests/PacketTests.cpp | 194 ++-- Tests/Packet++Test/Tests/PacketUtilsTests.cpp | 16 +- Tests/Packet++Test/Tests/RadiusTests.cpp | 34 +- Tests/Packet++Test/Tests/S7CommTests.cpp | 14 +- Tests/Packet++Test/Tests/SSHTests.cpp | 63 +- Tests/Packet++Test/Tests/SSLTests.cpp | 265 +++-- Tests/Packet++Test/Tests/SipSdpTests.cpp | 392 ++++---- Tests/Packet++Test/Tests/Sll2Tests.cpp | 10 +- .../Tests/SllNullLoopbackTests.cpp | 28 +- Tests/Packet++Test/Tests/SmtpTests.cpp | 191 ++-- Tests/Packet++Test/Tests/SomeIpSdTests.cpp | 50 +- Tests/Packet++Test/Tests/SomeIpTests.cpp | 78 +- Tests/Packet++Test/Tests/StpTests.cpp | 86 +- Tests/Packet++Test/Tests/TcpTests.cpp | 90 +- Tests/Packet++Test/Tests/TelnetTests.cpp | 249 +++-- Tests/Packet++Test/Tests/TpktTests.cpp | 2 +- Tests/Packet++Test/Tests/VlanMplsTests.cpp | 38 +- Tests/Packet++Test/Tests/VrrpTest.cpp | 41 +- Tests/Packet++Test/Tests/WakeOnLanTests.cpp | 14 +- Tests/Packet++Test/Utils/TestUtils.cpp | 165 ++- Tests/Packet++Test/Utils/TestUtils.h | 39 +- Tests/Packet++Test/main.cpp | 106 +- Tests/Pcap++Test/Common/GlobalTestArgs.h | 1 + Tests/Pcap++Test/Common/TestUtils.cpp | 25 +- Tests/Pcap++Test/Common/TestUtils.h | 44 +- Tests/Pcap++Test/Tests/DpdkTests.cpp | 213 ++-- Tests/Pcap++Test/Tests/FileTests.cpp | 125 ++- Tests/Pcap++Test/Tests/FilterTests.cpp | 131 +-- .../Pcap++Test/Tests/IPFragmentationTests.cpp | 106 +- Tests/Pcap++Test/Tests/IpMacTests.cpp | 229 +++-- Tests/Pcap++Test/Tests/KniTests.cpp | 182 ++-- Tests/Pcap++Test/Tests/LiveDeviceTests.cpp | 290 +++--- Tests/Pcap++Test/Tests/LoggerTests.cpp | 139 ++- Tests/Pcap++Test/Tests/PacketParsingTests.cpp | 80 +- Tests/Pcap++Test/Tests/PfRingTests.cpp | 146 ++- Tests/Pcap++Test/Tests/RawSocketTests.cpp | 4 +- Tests/Pcap++Test/Tests/SystemUtilsTests.cpp | 6 +- Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp | 341 ++++--- Tests/Pcap++Test/Tests/XdpTests.cpp | 75 +- Tests/Pcap++Test/main.cpp | 199 ++-- Tests/PcppTestFramework/PcppTestFramework.h | 418 ++++---- .../PcppTestFramework/PcppTestFrameworkRun.h | 161 +-- 69 files changed, 4522 insertions(+), 4305 deletions(-) mode change 100755 => 100644 Tests/Packet++Test/Tests/VrrpTest.cpp diff --git a/.clang-format b/.clang-format index eeebe47116..d8067eaade 100644 --- a/.clang-format +++ b/.clang-format @@ -11,7 +11,7 @@ PointerAlignment: Left AccessModifierOffset: -4 AlignTrailingComments: true AllowShortEnumsOnASingleLine: false -BreakStringLiterals: true +BreakStringLiterals: false AlignArrayOfStructures: Left BreakArrays: true SpacesBeforeTrailingComments: 2 diff --git a/Tests/Fuzzers/DumpToFile.h b/Tests/Fuzzers/DumpToFile.h index b67b31a42f..b54962c7df 100644 --- a/Tests/Fuzzers/DumpToFile.h +++ b/Tests/Fuzzers/DumpToFile.h @@ -4,9 +4,9 @@ // This function is created as PcapPlusPlus doesn't seem to offer a way of // parsing Pcap files directly from memory -static int dumpDataToPcapFile(const uint8_t *data, size_t size, const char* path) +static int dumpDataToPcapFile(const uint8_t* data, size_t size, const char* path) { - FILE *fd; + FILE* fd; int written = 0; fd = fopen(path, "wb"); diff --git a/Tests/Fuzzers/FuzzTarget.cpp b/Tests/Fuzzers/FuzzTarget.cpp index 293bd66252..97058e8f35 100644 --- a/Tests/Fuzzers/FuzzTarget.cpp +++ b/Tests/Fuzzers/FuzzTarget.cpp @@ -7,10 +7,10 @@ static std::string tmpName; static std::string tmpFile; -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (tmpName.empty()) - tmpName = tmpnam (NULL); + tmpName = tmpnam(NULL); if (tmpFile.empty()) tmpFile = tmpName + FILE_EXT; @@ -32,15 +32,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) pcpp::IPcapDevice::PcapStats stats; reader->getStatistics(stats); - std::cout << "Read " << stats.packetsRecv << " packets successfully and " - << stats.packetsDrop << " packets could not be read" << std::endl; + std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop + << " packets could not be read" << std::endl; if (auto ngReader = dynamic_cast(reader.get())) { std::cout << "OS is '" << ngReader->getOS() << "'; Hardware is '" << ngReader->getHardware() << "'" - << "'; CaptureApplication is '" << ngReader->getCaptureApplication() - << "'; CaptureFileComment is '" << ngReader->getCaptureFileComment() - << "'" << std::endl; + << "'; CaptureApplication is '" << ngReader->getCaptureApplication() << "'; CaptureFileComment is '" + << ngReader->getCaptureFileComment() << "'" << std::endl; } pcpp::RawPacketVector packets; diff --git a/Tests/Fuzzers/FuzzWriter.cpp b/Tests/Fuzzers/FuzzWriter.cpp index 2af45a6c42..ad591789f8 100644 --- a/Tests/Fuzzers/FuzzWriter.cpp +++ b/Tests/Fuzzers/FuzzWriter.cpp @@ -10,10 +10,10 @@ static std::string tmpFile; static std::string outPcapFile; static int writes = 0; -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (tmpName.empty()) - tmpName = tmpnam (NULL); + tmpName = tmpnam(NULL); if (tmpFile.empty()) tmpFile = tmpName + FILE_EXT; @@ -41,9 +41,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) #endif #ifdef NG_WRITER - pcpp::PcapNgFileWriterDevice pcapWriter(outPcapFile); + pcpp::PcapNgFileWriterDevice pcapWriter(outPcapFile); #else - pcpp::PcapFileWriterDevice pcapWriter(outPcapFile, pcpp::LINKTYPE_ETHERNET); + pcpp::PcapFileWriterDevice pcapWriter(outPcapFile, pcpp::LINKTYPE_ETHERNET); #endif if (writes++ == 10) { @@ -71,8 +71,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) pcpp::IPcapDevice::PcapStats stats; pcapWriter.getStatistics(stats); - std::cout << "Written " << stats.packetsRecv << " packets successfully to pcap writer and " - << stats.packetsDrop << " packets could not be written" << std::endl; + std::cout << "Written " << stats.packetsRecv << " packets successfully to pcap writer and " << stats.packetsDrop + << " packets could not be written" << std::endl; pcapWriter.close(); return 0; diff --git a/Tests/Fuzzers/ReadParsedPacket.h b/Tests/Fuzzers/ReadParsedPacket.h index 9fc0dbb326..ad17867c86 100644 --- a/Tests/Fuzzers/ReadParsedPacket.h +++ b/Tests/Fuzzers/ReadParsedPacket.h @@ -26,494 +26,497 @@ // If you made changes to PcapPlusPlus and the code doesn't compile - fix the method call as any other unit test static void readParsedPacket(pcpp::Packet parsedPacket, pcpp::Layer* layer) { - if (parsedPacket.isPacketOfType(pcpp::Telnet)) - { - if (auto telnetLayer = dynamic_cast(layer)) - { - telnetLayer->getFirstCommand(); - telnetLayer->getTotalNumberOfCommands(); + if (parsedPacket.isPacketOfType(pcpp::Telnet)) + { + if (auto telnetLayer = dynamic_cast(layer)) + { + telnetLayer->getFirstCommand(); + telnetLayer->getTotalNumberOfCommands(); - pcpp::TelnetLayer::TelnetCommand commandVal; - do - { - commandVal = telnetLayer->getNextCommand(); - std::cout << "Telnet command is '" << telnetLayer->getTelnetCommandAsString(commandVal) << "'" << std::endl; - pcpp::TelnetLayer::TelnetOption option = telnetLayer->getOption(); - std::cout << "Telnet option is '" << telnetLayer->getTelnetOptionAsString(option) << "'" << std::endl; + pcpp::TelnetLayer::TelnetCommand commandVal; + do + { + commandVal = telnetLayer->getNextCommand(); + std::cout << "Telnet command is '" << telnetLayer->getTelnetCommandAsString(commandVal) << "'" + << std::endl; + pcpp::TelnetLayer::TelnetOption option = telnetLayer->getOption(); + std::cout << "Telnet option is '" << telnetLayer->getTelnetOptionAsString(option) << "'" << std::endl; - telnetLayer->getDataAsString(true); - telnetLayer->getNumberOfCommands(commandVal); - telnetLayer->getOption(commandVal); - size_t length = 0; - telnetLayer->getOptionData(length); - telnetLayer->getOptionData(commandVal, length); - } - while (commandVal != pcpp::TelnetLayer::TelnetCommand::TelnetCommandEndOfPacket); - } - } - if (parsedPacket.isPacketOfType(pcpp::ARP)) - { - if (auto arpLayer = dynamic_cast(layer)) - { - arpLayer->isReply(); - arpLayer->isRequest(); - } - } - if (parsedPacket.isPacketOfType(pcpp::SomeIP)) - { - if (auto someipLayer = dynamic_cast(layer)) - { - auto entries = someipLayer->getEntries(); - if (!entries.empty()) - { - auto opts = someipLayer->getOptionsFromEntry(0); - for (auto opt : opts) - delete opt; - } + telnetLayer->getDataAsString(true); + telnetLayer->getNumberOfCommands(commandVal); + telnetLayer->getOption(commandVal); + size_t length = 0; + telnetLayer->getOptionData(length); + telnetLayer->getOptionData(commandVal, length); + } while (commandVal != pcpp::TelnetLayer::TelnetCommand::TelnetCommandEndOfPacket); + } + } + if (parsedPacket.isPacketOfType(pcpp::ARP)) + { + if (auto arpLayer = dynamic_cast(layer)) + { + arpLayer->isReply(); + arpLayer->isRequest(); + } + } + if (parsedPacket.isPacketOfType(pcpp::SomeIP)) + { + if (auto someipLayer = dynamic_cast(layer)) + { + auto entries = someipLayer->getEntries(); + if (!entries.empty()) + { + auto opts = someipLayer->getOptionsFromEntry(0); + for (auto opt : opts) + delete opt; + } - for (auto entry : entries) - { - entry->getNumOptions(); - entry->getServiceId(); - entry->getInstanceId(); - entry->getMajorVersion(); - entry->getMinorVersion(); - entry->getCounter(); - entry->getEventgroupId(); - delete entry; - } + for (auto entry : entries) + { + entry->getNumOptions(); + entry->getServiceId(); + entry->getInstanceId(); + entry->getMajorVersion(); + entry->getMinorVersion(); + entry->getCounter(); + entry->getEventgroupId(); + delete entry; + } - someipLayer->getFlags(); - auto opts = someipLayer->getOptions(); - for (auto opt : opts) - { - opt->getType(); - if (auto v4opt = dynamic_cast(opt)) - { - v4opt->getIpAddress(); - v4opt->getPort(); - v4opt->getProtocol(); - } - else if (auto v6opt = dynamic_cast(opt)) - { - v6opt->getIpAddress(); - v6opt->getPort(); - v6opt->getProtocol(); - } - delete opt; - } - } - } - if (parsedPacket.isPacketOfType(pcpp::GTP)) - { - if (auto gtpLayer = dynamic_cast(layer)) - { - uint16_t value16 = 0; - gtpLayer->getSequenceNumber(value16); - uint8_t value8; - gtpLayer->getNpduNumber(value8); - gtpLayer->getMessageType(); - gtpLayer->getMessageTypeAsString(); - gtpLayer->isGTPUMessage(); - gtpLayer->isGTPCMessage(); - auto ext = gtpLayer->getNextExtension(); - ext.getExtensionType(); - ext.getContent(); - ext.getContentLength(); - ext.getNextExtension(); - } - } - if (parsedPacket.isPacketOfType(pcpp::GRE)) - { - if (auto greLayer = dynamic_cast(layer)) - { - uint32_t value32 = 0; - greLayer->getSequenceNumber(value32); - } - } - if (parsedPacket.isPacketOfType(pcpp::GREv0)) - { - if (auto greLayer = dynamic_cast(layer)) - { - uint16_t value16 = 0; - greLayer->getChecksum(value16); - greLayer->getOffset(value16); - uint32_t value32 = 0; - greLayer->getKey(value32); - } - } - if (parsedPacket.isPacketOfType(pcpp::GREv1)) - { - if (auto greLayer = dynamic_cast(layer)) - { - uint32_t value32 = 0; - greLayer->getAcknowledgmentNum(value32); - } - } - if (parsedPacket.isPacketOfType(pcpp::FTP)) - { - if (auto ftpLayer = dynamic_cast(layer)) - { - ftpLayer->getCommandOption(false); - ftpLayer->getCommandOption(true); - } - else if (auto ftpLayer = dynamic_cast(layer)) - { - ftpLayer->getStatusCode(); - ftpLayer->getStatusOption(false); - ftpLayer->getStatusOption(true); - } - } - if (parsedPacket.isPacketOfType(pcpp::SLL2)) - { - if (auto sllLayer = dynamic_cast(layer)) - { - sllLayer->getLinkLayerAsMacAddress(); - sllLayer->getProtocolType(); - sllLayer->getInterfaceIndex(); - sllLayer->getArphrdType(); - sllLayer->getPacketType(); - } - } - if (parsedPacket.isPacketOfType(pcpp::VRRP)) - { - if (auto vrrpLayer = dynamic_cast(layer)) - { - vrrpLayer->getIPAddresses(); - vrrpLayer->isChecksumCorrect(); - vrrpLayer->getChecksum(); - vrrpLayer->getPriorityAsEnum(); - vrrpLayer->getPriority(); - vrrpLayer->getType(); - } - } - if (parsedPacket.isPacketOfType(pcpp::VRRPv2)) - { - if (auto vrrpLayer = dynamic_cast(layer)) - { - vrrpLayer->getAuthTypeAsEnum(); - vrrpLayer->getAdvInt(); - } - } - if (parsedPacket.isPacketOfType(pcpp::VRRPv3)) - { - if (auto vrrpLayer = dynamic_cast(layer)) - { - vrrpLayer->getMaxAdvInt(); - } - } - if (parsedPacket.isPacketOfType(pcpp::TCP)) - { - if (auto tcpLayer = dynamic_cast(layer)) - { - auto tcpLayer2 (*tcpLayer); - tcpLayer2.insertTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop), pcpp::TcpOptionEnumType::Nop); - } - } - if (parsedPacket.isPacketOfType(pcpp::SDP)) - { - if (auto sdpLayer = dynamic_cast(layer)) - { - sdpLayer->getOwnerIPv4Address(); - sdpLayer->getMediaPort("audio"); - sdpLayer->getFieldCount(); + someipLayer->getFlags(); + auto opts = someipLayer->getOptions(); + for (auto opt : opts) + { + opt->getType(); + if (auto v4opt = dynamic_cast(opt)) + { + v4opt->getIpAddress(); + v4opt->getPort(); + v4opt->getProtocol(); + } + else if (auto v6opt = dynamic_cast(opt)) + { + v6opt->getIpAddress(); + v6opt->getPort(); + v6opt->getProtocol(); + } + delete opt; + } + } + } + if (parsedPacket.isPacketOfType(pcpp::GTP)) + { + if (auto gtpLayer = dynamic_cast(layer)) + { + uint16_t value16 = 0; + gtpLayer->getSequenceNumber(value16); + uint8_t value8; + gtpLayer->getNpduNumber(value8); + gtpLayer->getMessageType(); + gtpLayer->getMessageTypeAsString(); + gtpLayer->isGTPUMessage(); + gtpLayer->isGTPCMessage(); + auto ext = gtpLayer->getNextExtension(); + ext.getExtensionType(); + ext.getContent(); + ext.getContentLength(); + ext.getNextExtension(); + } + } + if (parsedPacket.isPacketOfType(pcpp::GRE)) + { + if (auto greLayer = dynamic_cast(layer)) + { + uint32_t value32 = 0; + greLayer->getSequenceNumber(value32); + } + } + if (parsedPacket.isPacketOfType(pcpp::GREv0)) + { + if (auto greLayer = dynamic_cast(layer)) + { + uint16_t value16 = 0; + greLayer->getChecksum(value16); + greLayer->getOffset(value16); + uint32_t value32 = 0; + greLayer->getKey(value32); + } + } + if (parsedPacket.isPacketOfType(pcpp::GREv1)) + { + if (auto greLayer = dynamic_cast(layer)) + { + uint32_t value32 = 0; + greLayer->getAcknowledgmentNum(value32); + } + } + if (parsedPacket.isPacketOfType(pcpp::FTP)) + { + if (auto ftpLayer = dynamic_cast(layer)) + { + ftpLayer->getCommandOption(false); + ftpLayer->getCommandOption(true); + } + else if (auto ftpLayer = dynamic_cast(layer)) + { + ftpLayer->getStatusCode(); + ftpLayer->getStatusOption(false); + ftpLayer->getStatusOption(true); + } + } + if (parsedPacket.isPacketOfType(pcpp::SLL2)) + { + if (auto sllLayer = dynamic_cast(layer)) + { + sllLayer->getLinkLayerAsMacAddress(); + sllLayer->getProtocolType(); + sllLayer->getInterfaceIndex(); + sllLayer->getArphrdType(); + sllLayer->getPacketType(); + } + } + if (parsedPacket.isPacketOfType(pcpp::VRRP)) + { + if (auto vrrpLayer = dynamic_cast(layer)) + { + vrrpLayer->getIPAddresses(); + vrrpLayer->isChecksumCorrect(); + vrrpLayer->getChecksum(); + vrrpLayer->getPriorityAsEnum(); + vrrpLayer->getPriority(); + vrrpLayer->getType(); + } + } + if (parsedPacket.isPacketOfType(pcpp::VRRPv2)) + { + if (auto vrrpLayer = dynamic_cast(layer)) + { + vrrpLayer->getAuthTypeAsEnum(); + vrrpLayer->getAdvInt(); + } + } + if (parsedPacket.isPacketOfType(pcpp::VRRPv3)) + { + if (auto vrrpLayer = dynamic_cast(layer)) + { + vrrpLayer->getMaxAdvInt(); + } + } + if (parsedPacket.isPacketOfType(pcpp::TCP)) + { + if (auto tcpLayer = dynamic_cast(layer)) + { + auto tcpLayer2(*tcpLayer); + tcpLayer2.insertTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop), + pcpp::TcpOptionEnumType::Nop); + } + } + if (parsedPacket.isPacketOfType(pcpp::SDP)) + { + if (auto sdpLayer = dynamic_cast(layer)) + { + sdpLayer->getOwnerIPv4Address(); + sdpLayer->getMediaPort("audio"); + sdpLayer->getFieldCount(); - auto sdpLayer2 = *sdpLayer; - std::vector audioAttributes; - audioAttributes.push_back("rtpmap:8 PCMA/8000"); - sdpLayer2.addMediaDescription("audio", 6010, "RTP/AVP", "8 96", audioAttributes); - sdpLayer2.addField(PCPP_SDP_PROTOCOL_VERSION_FIELD, "0"); - sdpLayer2.removeField(PCPP_SDP_PROTOCOL_VERSION_FIELD); - } - } - if (parsedPacket.isPacketOfType(pcpp::SSL)) - { - if (auto handshakeLayer = dynamic_cast(layer)) - { - if (auto clientHelloMessage = handshakeLayer->getHandshakeMessageOfType()) - { - clientHelloMessage->getCompressionMethodsValue(); - clientHelloMessage->getSessionID(); - clientHelloMessage->getHandshakeType(); - clientHelloMessage->getHandshakeVersion(); + auto sdpLayer2 = *sdpLayer; + std::vector audioAttributes; + audioAttributes.push_back("rtpmap:8 PCMA/8000"); + sdpLayer2.addMediaDescription("audio", 6010, "RTP/AVP", "8 96", audioAttributes); + sdpLayer2.addField(PCPP_SDP_PROTOCOL_VERSION_FIELD, "0"); + sdpLayer2.removeField(PCPP_SDP_PROTOCOL_VERSION_FIELD); + } + } + if (parsedPacket.isPacketOfType(pcpp::SSL)) + { + if (auto handshakeLayer = dynamic_cast(layer)) + { + if (auto clientHelloMessage = handshakeLayer->getHandshakeMessageOfType()) + { + clientHelloMessage->getCompressionMethodsValue(); + clientHelloMessage->getSessionID(); + clientHelloMessage->getHandshakeType(); + clientHelloMessage->getHandshakeVersion(); - pcpp::SSLCipherSuite::getCipherSuiteByName("TLS_RSA_WITH_NULL_MD5"); - for (int i = 0; i < clientHelloMessage->getCipherSuiteCount(); i++) - { - clientHelloMessage->getCipherSuite(i); - bool valid; - clientHelloMessage->getCipherSuiteID(i, valid); - } - if (auto ext = clientHelloMessage->getExtensionOfType()) - ext->getHostName(); - if (auto ext = clientHelloMessage->getExtensionOfType()) - ext->getSupportedVersions(); + pcpp::SSLCipherSuite::getCipherSuiteByName("TLS_RSA_WITH_NULL_MD5"); + for (int i = 0; i < clientHelloMessage->getCipherSuiteCount(); i++) + { + clientHelloMessage->getCipherSuite(i); + bool valid; + clientHelloMessage->getCipherSuiteID(i, valid); + } + if (auto ext = clientHelloMessage->getExtensionOfType()) + ext->getHostName(); + if (auto ext = clientHelloMessage->getExtensionOfType()) + ext->getSupportedVersions(); - clientHelloMessage->getExtensionOfType(pcpp::SSL_EXT_SERVER_NAME); - clientHelloMessage->getExtensionOfType((uint16_t)0); + clientHelloMessage->getExtensionOfType(pcpp::SSL_EXT_SERVER_NAME); + clientHelloMessage->getExtensionOfType((uint16_t)0); - auto fingerprint = clientHelloMessage->generateTLSFingerprint(); - fingerprint.toMD5(); - } - if (auto serverHelloMessage = handshakeLayer->getHandshakeMessageOfType()) - { - serverHelloMessage->getCompressionMethodsValue(); - serverHelloMessage->getSessionID(); - serverHelloMessage->getCipherSuite(); + auto fingerprint = clientHelloMessage->generateTLSFingerprint(); + fingerprint.toMD5(); + } + if (auto serverHelloMessage = handshakeLayer->getHandshakeMessageOfType()) + { + serverHelloMessage->getCompressionMethodsValue(); + serverHelloMessage->getSessionID(); + serverHelloMessage->getCipherSuite(); - serverHelloMessage->getExtensionOfType(); - serverHelloMessage->getExtensionOfType(pcpp::SSL_EXT_SERVER_NAME); - serverHelloMessage->getExtensionOfType((uint16_t)0); + serverHelloMessage->getExtensionOfType(); + serverHelloMessage->getExtensionOfType(pcpp::SSL_EXT_SERVER_NAME); + serverHelloMessage->getExtensionOfType((uint16_t)0); - serverHelloMessage->getHandshakeVersion(); - auto fingerprint = serverHelloMessage->generateTLSFingerprint(); - fingerprint.toMD5(); - } - if (auto handshakeMessage = handshakeLayer->getHandshakeMessageOfType()) - { - handshakeMessage->isMessageComplete(); - } - } - } - if (parsedPacket.isPacketOfType(pcpp::NTP)) - { - if (auto ntpLayer = dynamic_cast(layer)) - { - ntpLayer->getLeapIndicator(); - ntpLayer->getMode(); - ntpLayer->getModeString(); - ntpLayer->getStratum(); - ntpLayer->getPollInterval(); - ntpLayer->getPrecision(); - ntpLayer->getRootDelay(); - ntpLayer->getRootDispersion(); - ntpLayer->getReferenceIdentifier(); - ntpLayer->getReferenceIdentifierString(); - ntpLayer->getReferenceTimestamp(); - ntpLayer->getOriginTimestamp(); - ntpLayer->getReceiveTimestamp(); - ntpLayer->getTransmitTimestamp(); + serverHelloMessage->getHandshakeVersion(); + auto fingerprint = serverHelloMessage->generateTLSFingerprint(); + fingerprint.toMD5(); + } + if (auto handshakeMessage = handshakeLayer->getHandshakeMessageOfType()) + { + handshakeMessage->isMessageComplete(); + } + } + } + if (parsedPacket.isPacketOfType(pcpp::NTP)) + { + if (auto ntpLayer = dynamic_cast(layer)) + { + ntpLayer->getLeapIndicator(); + ntpLayer->getMode(); + ntpLayer->getModeString(); + ntpLayer->getStratum(); + ntpLayer->getPollInterval(); + ntpLayer->getPrecision(); + ntpLayer->getRootDelay(); + ntpLayer->getRootDispersion(); + ntpLayer->getReferenceIdentifier(); + ntpLayer->getReferenceIdentifierString(); + ntpLayer->getReferenceTimestamp(); + ntpLayer->getOriginTimestamp(); + ntpLayer->getReceiveTimestamp(); + ntpLayer->getTransmitTimestamp(); - ntpLayer->getDigest(); - ntpLayer->getKeyID(); + ntpLayer->getDigest(); + ntpLayer->getKeyID(); - ntpLayer->getPollIntervalInSecs(); - ntpLayer->getPrecisionInSecs(); - ntpLayer->getRootDelayInSecs(); - ntpLayer->getRootDispersionInSecs(); - ntpLayer->getReferenceTimestampInSecs(); - ntpLayer->getOriginTimestampInSecs(); - ntpLayer->getReceiveTimestampInSecs(); - ntpLayer->getTransmitTimestampInSecs(); + ntpLayer->getPollIntervalInSecs(); + ntpLayer->getPrecisionInSecs(); + ntpLayer->getRootDelayInSecs(); + ntpLayer->getRootDispersionInSecs(); + ntpLayer->getReferenceTimestampInSecs(); + ntpLayer->getOriginTimestampInSecs(); + ntpLayer->getReceiveTimestampInSecs(); + ntpLayer->getTransmitTimestampInSecs(); - ntpLayer->getReferenceTimestampAsString(); - ntpLayer->getOriginTimestampAsString(); - ntpLayer->getReceiveTimestampAsString(); - ntpLayer->getTransmitTimestampAsString(); + ntpLayer->getReferenceTimestampAsString(); + ntpLayer->getOriginTimestampAsString(); + ntpLayer->getReceiveTimestampAsString(); + ntpLayer->getTransmitTimestampAsString(); - auto ntpLayer2 (*ntpLayer); - ntpLayer2.setRootDelayInSecs(0.1); - ntpLayer2.setReferenceTimestampInSecs(0.1); - } - } - if (parsedPacket.isPacketOfType(pcpp::ICMP)) - { - if (auto icmpLayer = dynamic_cast(layer)) - { - auto icmpLayer2 (*icmpLayer); + auto ntpLayer2(*ntpLayer); + ntpLayer2.setRootDelayInSecs(0.1); + ntpLayer2.setReferenceTimestampInSecs(0.1); + } + } + if (parsedPacket.isPacketOfType(pcpp::ICMP)) + { + if (auto icmpLayer = dynamic_cast(layer)) + { + auto icmpLayer2(*icmpLayer); - if (icmpLayer->isMessageOfType(pcpp::ICMP_TIMESTAMP_REPLY)) - { - icmpLayer->getTimestampReplyData(); - timeval orig = { 16131, 171000 }; - timeval recv = { 16133, 474000 }; - timeval tran = { 16133, 474000 }; - icmpLayer2.setTimestampReplyData(14640, 0, orig, recv, tran); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_ADDRESS_MASK_REQUEST)) - { - icmpLayer->getAddressMaskRequestData(); - icmpLayer2.setAddressMaskRequestData(45068, 1536, pcpp::IPv4Address::Zero); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_ADDRESS_MASK_REPLY)) - { - icmpLayer->getAddressMaskReplyData(); - icmpLayer2.setAddressMaskReplyData(45068, 1536, pcpp::IPv4Address::Zero); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_DEST_UNREACHABLE)) - { - icmpLayer->getDestUnreachableData(); - icmpLayer2.setDestUnreachableData(pcpp::IcmpHostUnreachable, 0, nullptr, nullptr); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_INFO_REPLY)) - { - auto layerData = icmpLayer->getInfoReplyData(); - icmpLayer2.setInfoReplyData(layerData->id, layerData->sequence); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_INFO_REQUEST)) - { - auto layerData = icmpLayer->getInfoRequestData(); - icmpLayer2.setInfoRequestData(layerData->id, layerData->sequence); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_PARAM_PROBLEM)) - { - auto layerData = icmpLayer->getParamProblemData(); - icmpLayer2.setParamProblemData(layerData->code, layerData->pointer, nullptr, nullptr); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_TIME_EXCEEDED)) - { - icmpLayer->getTimeExceededData(); - icmpLayer2.setTimeExceededData(1, nullptr, nullptr); - } - else if (icmpLayer->isMessageOfType(pcpp::ICMP_ROUTER_ADV)) - { - icmpLayer->getRouterAdvertisementData(); - pcpp::icmp_router_address_structure addr1; - addr1.setRouterAddress(pcpp::IPv4Address("192.168.144.2"), (uint32_t)0x08000000); - std::vector routerAddresses; - routerAddresses.push_back(addr1); - icmpLayer2.setRouterAdvertisementData(16, 200, routerAddresses); - } - } - } - if (parsedPacket.isPacketOfType(pcpp::DHCPv6)) - { - if (auto dhcpLayer = dynamic_cast(layer)) - { - dhcpLayer->getTransactionID(); - if (dhcpLayer->getOptionCount() > 0) - { - pcpp::DhcpV6Option opt = dhcpLayer->getFirstOptionData(); - opt.getType(); - opt.getTotalSize(); - opt.getValueAsHexString(); - for (size_t i = 0; i < dhcpLayer->getOptionCount(); i++) - { - opt = dhcpLayer->getNextOptionData(opt); - } - dhcpLayer->getOptionData(pcpp::DHCPV6_OPT_CLIENTID); - } - } - } - if (parsedPacket.isPacketOfType(pcpp::DHCP)) - { - if (auto dhcpLayer = dynamic_cast(layer)) - { - dhcpLayer->getOpCode(); - dhcpLayer->getDhcpHeader(); - dhcpLayer->getClientIpAddress(); - dhcpLayer->getYourIpAddress(); - dhcpLayer->getServerIpAddress(); - dhcpLayer->getGatewayIpAddress(); - dhcpLayer->getClientHardwareAddress(); - if (dhcpLayer->getOptionsCount() > 0) - { - pcpp::DhcpOption opt = dhcpLayer->getFirstOptionData(); - opt.getValueAsIpAddr(); - opt.getValueAsString(); - for (size_t i = 0; i < dhcpLayer->getOptionsCount(); i++) - { - opt = dhcpLayer->getNextOptionData(opt); - } - } - dhcpLayer->getOptionData(pcpp::DHCPOPT_SUBNET_MASK); - } - } - if (parsedPacket.isPacketOfType(pcpp::BGP)) - { - if (auto bgpLayer = dynamic_cast(layer)) - { - bgpLayer->getMessageTypeAsString(); - if (auto bgpOpenMsgLayer = dynamic_cast(bgpLayer)) - { - std::vector optionalParams; - bgpOpenMsgLayer->getOptionalParameters(optionalParams); - std::vector optionalParams2(optionalParams); - optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "010400010001")); - optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "8000")); - optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "0200")); - optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "4600")); - optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "410400000001")); - bgpOpenMsgLayer->setOptionalParameters(optionalParams2); - bgpOpenMsgLayer->clearOptionalParameters(); - bgpOpenMsgLayer->setOptionalParameters(optionalParams); - } - else if (auto bgpUpdateMsgLayer = dynamic_cast(bgpLayer)) - { - std::vector withdrawnRoutes; - bgpUpdateMsgLayer->getWithdrawnRoutes(withdrawnRoutes); - std::vector withdrawnRoutes2(withdrawnRoutes); - withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "40.1.1.0")); - withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "40.40.40.0")); - withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(16, "103.103.0.0")); - withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "103.103.40.0")); - bgpUpdateMsgLayer->setWithdrawnRoutes(withdrawnRoutes2); - bgpUpdateMsgLayer->clearWithdrawnRoutes(); - bgpUpdateMsgLayer->setWithdrawnRoutes(withdrawnRoutes); + if (icmpLayer->isMessageOfType(pcpp::ICMP_TIMESTAMP_REPLY)) + { + icmpLayer->getTimestampReplyData(); + timeval orig = { 16131, 171000 }; + timeval recv = { 16133, 474000 }; + timeval tran = { 16133, 474000 }; + icmpLayer2.setTimestampReplyData(14640, 0, orig, recv, tran); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_ADDRESS_MASK_REQUEST)) + { + icmpLayer->getAddressMaskRequestData(); + icmpLayer2.setAddressMaskRequestData(45068, 1536, pcpp::IPv4Address::Zero); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_ADDRESS_MASK_REPLY)) + { + icmpLayer->getAddressMaskReplyData(); + icmpLayer2.setAddressMaskReplyData(45068, 1536, pcpp::IPv4Address::Zero); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_DEST_UNREACHABLE)) + { + icmpLayer->getDestUnreachableData(); + icmpLayer2.setDestUnreachableData(pcpp::IcmpHostUnreachable, 0, nullptr, nullptr); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_INFO_REPLY)) + { + auto layerData = icmpLayer->getInfoReplyData(); + icmpLayer2.setInfoReplyData(layerData->id, layerData->sequence); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_INFO_REQUEST)) + { + auto layerData = icmpLayer->getInfoRequestData(); + icmpLayer2.setInfoRequestData(layerData->id, layerData->sequence); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_PARAM_PROBLEM)) + { + auto layerData = icmpLayer->getParamProblemData(); + icmpLayer2.setParamProblemData(layerData->code, layerData->pointer, nullptr, nullptr); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_TIME_EXCEEDED)) + { + icmpLayer->getTimeExceededData(); + icmpLayer2.setTimeExceededData(1, nullptr, nullptr); + } + else if (icmpLayer->isMessageOfType(pcpp::ICMP_ROUTER_ADV)) + { + icmpLayer->getRouterAdvertisementData(); + pcpp::icmp_router_address_structure addr1; + addr1.setRouterAddress(pcpp::IPv4Address("192.168.144.2"), (uint32_t)0x08000000); + std::vector routerAddresses; + routerAddresses.push_back(addr1); + icmpLayer2.setRouterAdvertisementData(16, 200, routerAddresses); + } + } + } + if (parsedPacket.isPacketOfType(pcpp::DHCPv6)) + { + if (auto dhcpLayer = dynamic_cast(layer)) + { + dhcpLayer->getTransactionID(); + if (dhcpLayer->getOptionCount() > 0) + { + pcpp::DhcpV6Option opt = dhcpLayer->getFirstOptionData(); + opt.getType(); + opt.getTotalSize(); + opt.getValueAsHexString(); + for (size_t i = 0; i < dhcpLayer->getOptionCount(); i++) + { + opt = dhcpLayer->getNextOptionData(opt); + } + dhcpLayer->getOptionData(pcpp::DHCPV6_OPT_CLIENTID); + } + } + } + if (parsedPacket.isPacketOfType(pcpp::DHCP)) + { + if (auto dhcpLayer = dynamic_cast(layer)) + { + dhcpLayer->getOpCode(); + dhcpLayer->getDhcpHeader(); + dhcpLayer->getClientIpAddress(); + dhcpLayer->getYourIpAddress(); + dhcpLayer->getServerIpAddress(); + dhcpLayer->getGatewayIpAddress(); + dhcpLayer->getClientHardwareAddress(); + if (dhcpLayer->getOptionsCount() > 0) + { + pcpp::DhcpOption opt = dhcpLayer->getFirstOptionData(); + opt.getValueAsIpAddr(); + opt.getValueAsString(); + for (size_t i = 0; i < dhcpLayer->getOptionsCount(); i++) + { + opt = dhcpLayer->getNextOptionData(opt); + } + } + dhcpLayer->getOptionData(pcpp::DHCPOPT_SUBNET_MASK); + } + } + if (parsedPacket.isPacketOfType(pcpp::BGP)) + { + if (auto bgpLayer = dynamic_cast(layer)) + { + bgpLayer->getMessageTypeAsString(); + if (auto bgpOpenMsgLayer = dynamic_cast(bgpLayer)) + { + std::vector optionalParams; + bgpOpenMsgLayer->getOptionalParameters(optionalParams); + std::vector optionalParams2(optionalParams); + optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "010400010001")); + optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "8000")); + optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "0200")); + optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "4600")); + optionalParams2.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "410400000001")); + bgpOpenMsgLayer->setOptionalParameters(optionalParams2); + bgpOpenMsgLayer->clearOptionalParameters(); + bgpOpenMsgLayer->setOptionalParameters(optionalParams); + } + else if (auto bgpUpdateMsgLayer = dynamic_cast(bgpLayer)) + { + std::vector withdrawnRoutes; + bgpUpdateMsgLayer->getWithdrawnRoutes(withdrawnRoutes); + std::vector withdrawnRoutes2(withdrawnRoutes); + withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "40.1.1.0")); + withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "40.40.40.0")); + withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(16, "103.103.0.0")); + withdrawnRoutes2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "103.103.40.0")); + bgpUpdateMsgLayer->setWithdrawnRoutes(withdrawnRoutes2); + bgpUpdateMsgLayer->clearWithdrawnRoutes(); + bgpUpdateMsgLayer->setWithdrawnRoutes(withdrawnRoutes); - std::vector nlriVec; - bgpUpdateMsgLayer->getNetworkLayerReachabilityInfo(nlriVec); - std::vector nlriVec2(nlriVec); - nlriVec2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "40.1.1.0")); - bgpUpdateMsgLayer->setNetworkLayerReachabilityInfo(nlriVec2); - bgpUpdateMsgLayer->clearNetworkLayerReachabilityInfo(); - bgpUpdateMsgLayer->setNetworkLayerReachabilityInfo(nlriVec); + std::vector nlriVec; + bgpUpdateMsgLayer->getNetworkLayerReachabilityInfo(nlriVec); + std::vector nlriVec2(nlriVec); + nlriVec2.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "40.1.1.0")); + bgpUpdateMsgLayer->setNetworkLayerReachabilityInfo(nlriVec2); + bgpUpdateMsgLayer->clearNetworkLayerReachabilityInfo(); + bgpUpdateMsgLayer->setNetworkLayerReachabilityInfo(nlriVec); - std::vector pathAttributes; - bgpUpdateMsgLayer->getPathAttributes(pathAttributes); - std::vector pathAttributes2(pathAttributes); - pathAttributes2.push_back(pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 1, "02")); - pathAttributes2.push_back(pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 2, "02030000000a0000001400000028")); - pathAttributes2.push_back(pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 3, "1e031e03")); - bgpUpdateMsgLayer->setPathAttributes(pathAttributes2); - bgpUpdateMsgLayer->clearPathAttributes(); - bgpUpdateMsgLayer->setPathAttributes(pathAttributes); - } - else if (auto bgpNotificationMsgLayer = dynamic_cast(bgpLayer)) - { - bgpNotificationMsgLayer->getNotificationDataAsHexString(); - } - } - } - if (parsedPacket.isPacketOfType(pcpp::DNS)) - { - if (auto dnsLayer = dynamic_cast(layer)) - { - dnsLayer->addQuery("mail-attachment.googleusercontent.com", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN); - dnsLayer->removeQuery("a", true); - dnsLayer->removeQuery("mail-attachment.googleusercontent.com", false); - pcpp::IPv4DnsResourceData ipv4DnsData(std::string("151.249.90.217")); - dnsLayer->addAnswer("assets.pinterest.com.cdngc.net", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 3, &ipv4DnsData); - dnsLayer->removeAnswer("a", true); - dnsLayer->removeAnswer("assets.pinterest.com.cdngc.net", false); - dnsLayer->addAuthority("Yaels-iPhone.local", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 120, &ipv4DnsData); - dnsLayer->removeAuthority("a", true); - dnsLayer->removeAuthority("Yaels-iPhone.local", false); - pcpp::GenericDnsResourceData genericData("0004000800df581faa4f3f9d"); - dnsLayer->addAdditionalRecord("abc", pcpp::DNS_TYPE_OPT, 0xa005, 0x1194, &genericData); - dnsLayer->removeAdditionalRecord("a", true); - dnsLayer->removeAdditionalRecord("abc", false); + std::vector pathAttributes; + bgpUpdateMsgLayer->getPathAttributes(pathAttributes); + std::vector pathAttributes2(pathAttributes); + pathAttributes2.push_back(pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 1, "02")); + pathAttributes2.push_back( + pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 2, "02030000000a0000001400000028")); + pathAttributes2.push_back(pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 3, "1e031e03")); + bgpUpdateMsgLayer->setPathAttributes(pathAttributes2); + bgpUpdateMsgLayer->clearPathAttributes(); + bgpUpdateMsgLayer->setPathAttributes(pathAttributes); + } + else if (auto bgpNotificationMsgLayer = dynamic_cast(bgpLayer)) + { + bgpNotificationMsgLayer->getNotificationDataAsHexString(); + } + } + } + if (parsedPacket.isPacketOfType(pcpp::DNS)) + { + if (auto dnsLayer = dynamic_cast(layer)) + { + dnsLayer->addQuery("mail-attachment.googleusercontent.com", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN); + dnsLayer->removeQuery("a", true); + dnsLayer->removeQuery("mail-attachment.googleusercontent.com", false); + pcpp::IPv4DnsResourceData ipv4DnsData(std::string("151.249.90.217")); + dnsLayer->addAnswer("assets.pinterest.com.cdngc.net", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 3, + &ipv4DnsData); + dnsLayer->removeAnswer("a", true); + dnsLayer->removeAnswer("assets.pinterest.com.cdngc.net", false); + dnsLayer->addAuthority("Yaels-iPhone.local", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 120, &ipv4DnsData); + dnsLayer->removeAuthority("a", true); + dnsLayer->removeAuthority("Yaels-iPhone.local", false); + pcpp::GenericDnsResourceData genericData("0004000800df581faa4f3f9d"); + dnsLayer->addAdditionalRecord("abc", pcpp::DNS_TYPE_OPT, 0xa005, 0x1194, &genericData); + dnsLayer->removeAdditionalRecord("a", true); + dnsLayer->removeAdditionalRecord("abc", false); - auto add = dnsLayer->getFirstAdditionalRecord(); - while (add != nullptr) - { - add = dnsLayer->getNextAdditionalRecord(add); - } + auto add = dnsLayer->getFirstAdditionalRecord(); + while (add != nullptr) + { + add = dnsLayer->getNextAdditionalRecord(add); + } - auto answer = dnsLayer->getFirstAnswer(); - while (answer != nullptr) - { - answer = dnsLayer->getNextAnswer(answer); - } + auto answer = dnsLayer->getFirstAnswer(); + while (answer != nullptr) + { + answer = dnsLayer->getNextAnswer(answer); + } - auto auth = dnsLayer->getFirstAuthority(); - while (auth != nullptr) - { - auth = dnsLayer->getNextAuthority(auth); - } + auto auth = dnsLayer->getFirstAuthority(); + while (auth != nullptr) + { + auth = dnsLayer->getNextAuthority(auth); + } - pcpp::DnsLayer other(*dnsLayer); - other = *dnsLayer; - } - } + pcpp::DnsLayer other(*dnsLayer); + other = *dnsLayer; + } + } } diff --git a/Tests/Packet++Test/Tests/Asn1Tests.cpp b/Tests/Packet++Test/Tests/Asn1Tests.cpp index 03b8d3264c..6006f3438f 100644 --- a/Tests/Packet++Test/Tests/Asn1Tests.cpp +++ b/Tests/Packet++Test/Tests/Asn1Tests.cpp @@ -21,9 +21,10 @@ PTF_TEST_CASE(Asn1DecodingTest) PTF_ASSERT_EQUAL(record->getValueLength(), 11); PTF_ASSERT_EQUAL(record->toString(), "ContextSpecific (7), Length: 2+11"); auto genericRecord = record->castAs(); - auto recordValue = std::string(genericRecord->getValue(), genericRecord->getValue() + genericRecord->getValueLength()); + auto recordValue = + std::string(genericRecord->getValue(), genericRecord->getValue() + genericRecord->getValueLength()); PTF_ASSERT_EQUAL(recordValue, "objectclass"); - } + }; // Integer 1 byte { @@ -89,7 +90,8 @@ PTF_TEST_CASE(Asn1DecodingTest) { uint8_t data[20]; auto dataLen = pcpp::hexStringToByteArray("020502540be400", data, 20); - PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, dataLen, false), std::runtime_error, "An integer ASN.1 record of more than 4 bytes is not supported"); + PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, dataLen, false), std::runtime_error, + "An integer ASN.1 record of more than 4 bytes is not supported"); } // Enumerated @@ -200,10 +202,9 @@ PTF_TEST_CASE(Asn1DecodingTest) PTF_ASSERT_EQUAL(subRecords.at(1)->castAs()->getValue(), 1000); std::ostringstream expectedString; - expectedString - << "Sequence (constructed), Length: 2+10" << std::endl - << " OctetString, Length: 2+4, Value: abcd" << std::endl - << " Integer, Length: 2+2, Value: 1000"; + expectedString << "Sequence (constructed), Length: 2+10" << std::endl + << " OctetString, Length: 2+4, Value: abcd" << std::endl + << " Integer, Length: 2+2, Value: 1000"; PTF_ASSERT_EQUAL(record->toString(), expectedString.str()); } @@ -226,10 +227,9 @@ PTF_TEST_CASE(Asn1DecodingTest) PTF_ASSERT_EQUAL(subRecords.at(1)->castAs()->getValue(), "abcd"); std::ostringstream expectedString; - expectedString - << "Set (constructed), Length: 2+10" << std::endl - << " Integer, Length: 2+2, Value: 1000" << std::endl - << " OctetString, Length: 2+4, Value: abcd"; + expectedString << "Set (constructed), Length: 2+10" << std::endl + << " Integer, Length: 2+2, Value: 1000" << std::endl + << " OctetString, Length: 2+4, Value: abcd"; PTF_ASSERT_EQUAL(record->toString(), expectedString.str()); } @@ -252,10 +252,9 @@ PTF_TEST_CASE(Asn1DecodingTest) PTF_ASSERT_EQUAL(subRecords.at(1)->castAs()->getValue(), 1000); std::ostringstream expectedString; - expectedString - << "Application (3) (constructed), Length: 2+10" << std::endl - << " OctetString, Length: 2+4, Value: abcd" << std::endl - << " Integer, Length: 2+2, Value: 1000"; + expectedString << "Application (3) (constructed), Length: 2+10" << std::endl + << " OctetString, Length: 2+4, Value: abcd" << std::endl + << " Integer, Length: 2+2, Value: 1000"; PTF_ASSERT_EQUAL(record->toString(), expectedString.str()); } @@ -273,7 +272,8 @@ PTF_TEST_CASE(Asn1DecodingTest) PTF_ASSERT_EQUAL(record->getValueLength(), 7); PTF_ASSERT_EQUAL(record->toString(), "ObjectIdentifierIRI, Length: 3+7"); auto genericRecord = record->castAs(); - auto recordValue = std::string(genericRecord->getValue(), genericRecord->getValue() + genericRecord->getValueLength()); + auto recordValue = + std::string(genericRecord->getValue(), genericRecord->getValue() + genericRecord->getValueLength()); PTF_ASSERT_EQUAL(recordValue, "myvalue"); } @@ -290,7 +290,8 @@ PTF_TEST_CASE(Asn1DecodingTest) PTF_ASSERT_EQUAL(record->getValueLength(), 7); PTF_ASSERT_EQUAL(record->toString(), "Unknown, Length: 3+7"); auto genericRecord = record->castAs(); - auto recordValue = std::string(genericRecord->getValue(), genericRecord->getValue() + genericRecord->getValueLength()); + auto recordValue = + std::string(genericRecord->getValue(), genericRecord->getValue() + genericRecord->getValueLength()); PTF_ASSERT_EQUAL(recordValue, "myvalue"); } @@ -298,7 +299,8 @@ PTF_TEST_CASE(Asn1DecodingTest) { uint8_t data[20]; auto dataLen = pcpp::hexStringToByteArray("1f8100076d7976616c7565", data, 20); - PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, dataLen), std::invalid_argument, "ASN.1 tags with value larger than 127 are not supported"); + PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, dataLen), std::invalid_argument, + "ASN.1 tags with value larger than 127 are not supported"); } // Not enough data to parse tag @@ -313,14 +315,16 @@ PTF_TEST_CASE(Asn1DecodingTest) { uint8_t data[20]; pcpp::hexStringToByteArray("0500", data, 20); - PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, 1), std::invalid_argument, "Cannot decode ASN.1 record length"); + PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, 1), std::invalid_argument, + "Cannot decode ASN.1 record length"); } // Incomplete record - doesn't contain the entire value { uint8_t data[20]; pcpp::hexStringToByteArray("0a022000", data, 20); - PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, 3), std::invalid_argument, "Cannot decode ASN.1 record, data doesn't contain the entire record"); + PTF_ASSERT_RAISES(pcpp::Asn1Record::decode(data, 3), std::invalid_argument, + "Cannot decode ASN.1 record, data doesn't contain the entire record"); } // Cast as the wrong type @@ -328,21 +332,20 @@ PTF_TEST_CASE(Asn1DecodingTest) uint8_t data[20]; auto dataLen = pcpp::hexStringToByteArray("0a022000", data, 20); auto record = pcpp::Asn1Record::decode(data, dataLen); - #ifdef _MSC_VER +#ifdef _MSC_VER auto expectedMessage = "bad cast"; - #else +#else auto expectedMessage = "std::bad_cast"; - #endif +#endif PTF_ASSERT_RAISES(record->castAs(), std::bad_cast, expectedMessage); } -}; // Asn1DecodingTest - +}; // Asn1DecodingTest PTF_TEST_CASE(Asn1EncodingTest) { // Generic record with byte array value { - uint8_t value[] = {0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73}; + uint8_t value[] = { 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73 }; pcpp::Asn1GenericRecord record(pcpp::Asn1TagClass::ContextSpecific, false, 7, value, 11); PTF_ASSERT_EQUAL(record.getTagClass(), pcpp::Asn1TagClass::ContextSpecific, enumclass); @@ -383,10 +386,17 @@ PTF_TEST_CASE(Asn1EncodingTest) // Record length > 128 { - pcpp::Asn1OctetStringRecord record("12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); + pcpp::Asn1OctetStringRecord record( + "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456" + "7890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"); uint8_t data[203]; - auto dataLen = pcpp::hexStringToByteArray("0481c83132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930", data, 203); + auto dataLen = pcpp::hexStringToByteArray( + "0481c83132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930" + "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233" + "3435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536" + "3738393031323334353637383930313233343536373839303132333435363738393031323334353637383930", + data, 203); auto encodedValue = record.encode(); PTF_ASSERT_EQUAL(encodedValue.size(), dataLen); @@ -395,10 +405,20 @@ PTF_TEST_CASE(Asn1EncodingTest) // Record length > 256 { - pcpp::Asn1OctetStringRecord record("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); + pcpp::Asn1OctetStringRecord record( + "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345" + "6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" + "2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); uint8_t data[304]; - auto dataLen = pcpp::hexStringToByteArray("0482012c303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839", data, 304); + auto dataLen = pcpp::hexStringToByteArray( + "0482012c30313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738" + "3930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031" + "3233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334" + "3536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637" + "3839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930" + "313233343536373839303132333435363738393031323334353637383930313233343536373839", + data, 304); auto encodedValue = record.encode(); PTF_ASSERT_EQUAL(encodedValue.size(), dataLen); @@ -522,7 +542,7 @@ PTF_TEST_CASE(Asn1EncodingTest) // OctetString with non-printable value { constexpr size_t valueSize = 8; - uint8_t value[valueSize] = {0x30, 0x06, 0x02, 0x02, 0x01, 0xf4, 0x04, 0x00}; + uint8_t value[valueSize] = { 0x30, 0x06, 0x02, 0x02, 0x01, 0xf4, 0x04, 0x00 }; pcpp::Asn1OctetStringRecord record(value, valueSize); PTF_ASSERT_EQUAL(record.getTagClass(), pcpp::Asn1TagClass::Universal, enumclass); @@ -593,7 +613,7 @@ PTF_TEST_CASE(Asn1EncodingTest) { pcpp::Asn1OctetStringRecord octestStringRecord("abcd"); pcpp::Asn1IntegerRecord integerRecord(1000); - pcpp::Asn1SequenceRecord record({ &octestStringRecord, &integerRecord}); + pcpp::Asn1SequenceRecord record({ &octestStringRecord, &integerRecord }); PTF_ASSERT_EQUAL(record.getTagClass(), pcpp::Asn1TagClass::Universal, enumclass); PTF_ASSERT_TRUE(record.isConstructed()); @@ -668,4 +688,4 @@ PTF_TEST_CASE(Asn1EncodingTest) PTF_ASSERT_EQUAL(encodedValue.size(), dataLen); PTF_ASSERT_BUF_COMPARE(encodedValue.data(), data, dataLen); } -} // Asn1EncodingTest +} // Asn1EncodingTest diff --git a/Tests/Packet++Test/Tests/BgpTests.cpp b/Tests/Packet++Test/Tests/BgpTests.cpp index f17f0aba25..ae047337a7 100644 --- a/Tests/Packet++Test/Tests/BgpTests.cpp +++ b/Tests/Packet++Test/Tests/BgpTests.cpp @@ -8,7 +8,6 @@ #include "BgpLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(BgpLayerParsingTest) { timeval time; @@ -41,8 +40,6 @@ PTF_TEST_CASE(BgpLayerParsingTest) } PTF_ASSERT_EQUAL(be16toh(bgpKALayer->getKeepaliveHeader()->length), 19); - - // parse BGP OPEN message pcpp::Packet bgpOpenPacket(&rawPacket2); @@ -79,14 +76,13 @@ PTF_TEST_CASE(BgpLayerParsingTest) PTF_ASSERT_EQUAL(optParam.value[optParamsDataInedx[i]], optParamsData[i]); } - - // parse BGP NOTIFICATION message pcpp::Packet bgpNotificationPacket(&rawPacket3); PTF_ASSERT_TRUE(bgpNotificationPacket.isPacketOfType(pcpp::BGP)); - pcpp::BgpNotificationMessageLayer* bgpNotificationLayer = bgpNotificationPacket.getLayerOfType(); + pcpp::BgpNotificationMessageLayer* bgpNotificationLayer = + bgpNotificationPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(bgpNotificationLayer); PTF_ASSERT_EQUAL(bgpNotificationLayer->getBgpMessageType(), pcpp::BgpLayer::Notification, enum); PTF_ASSERT_EQUAL(bgpNotificationLayer->getHeaderLen(), 146); @@ -98,7 +94,10 @@ PTF_TEST_CASE(BgpLayerParsingTest) PTF_ASSERT_EQUAL(bgpNotificationLayer->getNotificationMsgHeader()->errorSubCode, 2); PTF_ASSERT_EQUAL(bgpNotificationLayer->getNotificationDataLen(), 125); - std::string notificationDataAsHexString = "7c4e54542077696c6c20706572666f726d206d61696e74656e616e6365206f6e207468697320726f757465722e205468697320697320747261636b656420696e205449434b45542d312d32343832343239342e20436f6e74616374206e6f63406e74742e6e657420666f72206d6f726520696e666f726d6174696f6e2e"; + std::string notificationDataAsHexString = + "7c4e54542077696c6c20706572666f726d206d61696e74656e616e6365206f6e207468697320726f757465722e20546869732069732074" + "7261636b656420696e205449434b45542d312d32343832343239342e20436f6e74616374206e6f63406e74742e6e657420666f72206d6f" + "726520696e666f726d6174696f6e2e"; PTF_ASSERT_EQUAL(bgpNotificationLayer->getNotificationDataAsHexString(), notificationDataAsHexString); pcpp::Packet bgpNotificationNoDataPacket(&rawPacket4); @@ -110,8 +109,6 @@ PTF_TEST_CASE(BgpLayerParsingTest) PTF_ASSERT_NULL(bgpNotificationLayer->getNotificationData()); PTF_ASSERT_EQUAL(bgpNotificationLayer->getNotificationDataAsHexString(), ""); - - // parse BGP ROUTE-REFRESH message pcpp::Packet bgpRRPacket(&rawPacket5); @@ -125,8 +122,6 @@ PTF_TEST_CASE(BgpLayerParsingTest) PTF_ASSERT_EQUAL(bgpRRLayer->getRouteRefreshHeader()->safi, 1); PTF_ASSERT_EQUAL(bgpRRLayer->getRouteRefreshHeader()->reserved, 1); - - // parse BGP UPDATE message with Withdrawn Routes pcpp::Packet bgpUpdatePacket1(&rawPacket6); @@ -159,8 +154,6 @@ PTF_TEST_CASE(BgpLayerParsingTest) PTF_ASSERT_NOT_NULL(bgpUpdateLayer->getNextLayer()); PTF_ASSERT_EQUAL(bgpUpdateLayer->getNextLayer()->getProtocol(), pcpp::BGP, enum); - - // parse BGP UPDATE message with Path Attributes pcpp::Packet bgpUpdatePacket2(&rawPacket7); @@ -201,7 +194,7 @@ PTF_TEST_CASE(BgpLayerParsingTest) pcpp::BgpUpdateMessageLayer::prefix_and_ip nlri = nlriVec[0]; PTF_ASSERT_EQUAL(nlri.prefix, 24); PTF_ASSERT_EQUAL(nlri.ipAddr, pcpp::IPv4Address("104.104.40.0")); - size_t pathAttrSize[3] = {28, 24, 0}; + size_t pathAttrSize[3] = { 28, 24, 0 }; for (int i = 0; i < 3; i++) { PTF_ASSERT_NOT_NULL(bgpUpdateLayer->getNextLayer()); @@ -210,8 +203,7 @@ PTF_TEST_CASE(BgpLayerParsingTest) PTF_ASSERT_NOT_NULL(bgpUpdateLayer); PTF_ASSERT_EQUAL(bgpUpdateLayer->getPathAttributesLength(), pathAttrSize[i]); } -} // BgpLayerParsingTest - +} // BgpLayerParsingTest PTF_TEST_CASE(BgpLayerCreationTest) { @@ -228,13 +220,13 @@ PTF_TEST_CASE(BgpLayerCreationTest) uint8_t origBuffer[1500]; - // create BGP KEEPALIVE message memcpy(origBuffer, buffer1, bufferLength1); pcpp::BgpKeepaliveMessageLayer newKAMessage; pcpp::Packet bgpKAPacket(&rawPacket1); - pcpp::BgpKeepaliveMessageLayer* origKAMessage = dynamic_cast(bgpKAPacket.detachLayer(pcpp::BGP)); + pcpp::BgpKeepaliveMessageLayer* origKAMessage = + dynamic_cast(bgpKAPacket.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origKAMessage); PTF_ASSERT_EQUAL(newKAMessage.getDataLen(), origKAMessage->getDataLen()); PTF_ASSERT_BUF_COMPARE(newKAMessage.getData(), origKAMessage->getData(), origKAMessage->getDataLen()); @@ -244,36 +236,39 @@ PTF_TEST_CASE(BgpLayerCreationTest) PTF_ASSERT_BUF_COMPARE(bgpKAPacket.getRawPacket()->getRawData(), origBuffer, bufferLength1); delete origKAMessage; - - // create BGP ROUTE-REFRESH message memcpy(origBuffer, buffer2, bufferLength2); pcpp::BgpRouteRefreshMessageLayer newRouteRefreshMessage(1, 1); pcpp::Packet bgpRouteRefreshPacket(&rawPacket2); - pcpp::BgpRouteRefreshMessageLayer* origRouteRefreshMessage = dynamic_cast(bgpRouteRefreshPacket.detachLayer(pcpp::BGP)); + pcpp::BgpRouteRefreshMessageLayer* origRouteRefreshMessage = + dynamic_cast(bgpRouteRefreshPacket.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origRouteRefreshMessage); newRouteRefreshMessage.getRouteRefreshHeader()->reserved = 1; PTF_ASSERT_EQUAL(newRouteRefreshMessage.getDataLen(), origRouteRefreshMessage->getDataLen()); - PTF_ASSERT_BUF_COMPARE(newRouteRefreshMessage.getData(), origRouteRefreshMessage->getData(), origRouteRefreshMessage->getDataLen()); + PTF_ASSERT_BUF_COMPARE(newRouteRefreshMessage.getData(), origRouteRefreshMessage->getData(), + origRouteRefreshMessage->getDataLen()); PTF_ASSERT_TRUE(bgpRouteRefreshPacket.addLayer(&newRouteRefreshMessage)); bgpRouteRefreshPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(bgpRouteRefreshPacket.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(bgpRouteRefreshPacket.getRawPacket()->getRawData(), origBuffer, bufferLength2); delete origRouteRefreshMessage; - - // create BGP NOTIFICATION message with notification data memcpy(origBuffer, buffer3, bufferLength3); - std::string notificationData = "7c4e54542077696c6c20706572666f726d206d61696e74656e616e6365206f6e207468697320726f757465722e205468697320697320747261636b656420696e205449434b45542d312d32343832343239342e20436f6e74616374206e6f63406e74742e6e657420666f72206d6f726520696e666f726d6174696f6e2e"; + std::string notificationData = + "7c4e54542077696c6c20706572666f726d206d61696e74656e616e6365206f6e207468697320726f757465722e20546869732069732074" + "7261636b656420696e205449434b45542d312d32343832343239342e20436f6e74616374206e6f63406e74742e6e657420666f72206d6f" + "726520696e666f726d6174696f6e2e"; pcpp::BgpNotificationMessageLayer newNotificationMessage(6, 2, notificationData); pcpp::Packet bgpNotificationPacket(&rawPacket3); - pcpp::BgpNotificationMessageLayer* origNotificationMessage = dynamic_cast(bgpNotificationPacket.detachLayer(pcpp::BGP)); + pcpp::BgpNotificationMessageLayer* origNotificationMessage = + dynamic_cast(bgpNotificationPacket.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origNotificationMessage); PTF_ASSERT_EQUAL(newNotificationMessage.getDataLen(), origNotificationMessage->getDataLen()); - PTF_ASSERT_BUF_COMPARE(newNotificationMessage.getData(), origNotificationMessage->getData(), origNotificationMessage->getDataLen()); + PTF_ASSERT_BUF_COMPARE(newNotificationMessage.getData(), origNotificationMessage->getData(), + origNotificationMessage->getDataLen()); PTF_ASSERT_TRUE(bgpNotificationPacket.addLayer(&newNotificationMessage)); bgpNotificationPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(bgpNotificationPacket.getRawPacket()->getRawDataLen(), bufferLength3); @@ -285,18 +280,18 @@ PTF_TEST_CASE(BgpLayerCreationTest) memcpy(origBuffer, buffer4, bufferLength4); pcpp::BgpNotificationMessageLayer newNotificationMessage2(6, 4); pcpp::Packet bgpNotificationPacket2(&rawPacket4); - origNotificationMessage = dynamic_cast(bgpNotificationPacket2.detachLayer(pcpp::BGP)); + origNotificationMessage = + dynamic_cast(bgpNotificationPacket2.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origNotificationMessage); PTF_ASSERT_EQUAL(newNotificationMessage2.getDataLen(), origNotificationMessage->getDataLen()); - PTF_ASSERT_BUF_COMPARE(newNotificationMessage2.getData(), origNotificationMessage->getData(), origNotificationMessage->getDataLen()); + PTF_ASSERT_BUF_COMPARE(newNotificationMessage2.getData(), origNotificationMessage->getData(), + origNotificationMessage->getDataLen()); PTF_ASSERT_TRUE(bgpNotificationPacket2.addLayer(&newNotificationMessage2)); bgpNotificationPacket2.computeCalculateFields(); PTF_ASSERT_EQUAL(bgpNotificationPacket2.getRawPacket()->getRawDataLen(), bufferLength4); PTF_ASSERT_BUF_COMPARE(bgpNotificationPacket2.getRawPacket()->getRawData(), origBuffer, bufferLength4); delete origNotificationMessage; - - // create BGP UPDATE message with Withdrawn Routes memcpy(origBuffer, buffer5, bufferLength5); @@ -307,7 +302,8 @@ PTF_TEST_CASE(BgpLayerCreationTest) withdrawnRoutes.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "103.103.40.0")); pcpp::BgpUpdateMessageLayer newUpdateMessage(withdrawnRoutes); pcpp::Packet bgpUpdatePacket1(&rawPacket5); - pcpp::BgpUpdateMessageLayer* origUpdateMessage = dynamic_cast(bgpUpdatePacket1.detachLayer(pcpp::BGP)); + pcpp::BgpUpdateMessageLayer* origUpdateMessage = + dynamic_cast(bgpUpdatePacket1.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origUpdateMessage); PTF_ASSERT_EQUAL(newUpdateMessage.getDataLen(), origUpdateMessage->getDataLen()); PTF_ASSERT_BUF_COMPARE(newUpdateMessage.getData(), origUpdateMessage->getData(), origUpdateMessage->getDataLen()); @@ -326,7 +322,8 @@ PTF_TEST_CASE(BgpLayerCreationTest) pathAttributes.push_back(pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 3, "1e031e03")); std::vector nlri; nlri.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "104.104.40.0")); - pcpp::BgpUpdateMessageLayer newUpdateMessage2(std::vector(), pathAttributes, nlri); + pcpp::BgpUpdateMessageLayer newUpdateMessage2(std::vector(), + pathAttributes, nlri); pcpp::Packet bgpUpdatePacket2(&rawPacket6); origUpdateMessage = dynamic_cast(bgpUpdatePacket2.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origUpdateMessage); @@ -338,8 +335,6 @@ PTF_TEST_CASE(BgpLayerCreationTest) PTF_ASSERT_BUF_COMPARE(bgpUpdatePacket2.getRawPacket()->getRawData(), origBuffer, bufferLength6); delete origUpdateMessage; - - // create BGP OPEN message memcpy(origBuffer, buffer7, bufferLength7); @@ -351,7 +346,8 @@ PTF_TEST_CASE(BgpLayerCreationTest) optionalParams.push_back(pcpp::BgpOpenMessageLayer::optional_parameter(2, "410400000001")); pcpp::BgpOpenMessageLayer newOpenMessage(1, 180, pcpp::IPv4Address("1.1.1.1"), optionalParams); pcpp::Packet bgpOpenPacket(&rawPacket7); - pcpp::BgpOpenMessageLayer* origOpenMessage = dynamic_cast(bgpOpenPacket.detachLayer(pcpp::BGP)); + pcpp::BgpOpenMessageLayer* origOpenMessage = + dynamic_cast(bgpOpenPacket.detachLayer(pcpp::BGP)); PTF_ASSERT_NOT_NULL(origOpenMessage); PTF_ASSERT_EQUAL(newOpenMessage.getDataLen(), origOpenMessage->getDataLen()); PTF_ASSERT_BUF_COMPARE(newOpenMessage.getData(), origOpenMessage->getData(), origOpenMessage->getDataLen()); @@ -361,8 +357,6 @@ PTF_TEST_CASE(BgpLayerCreationTest) PTF_ASSERT_BUF_COMPARE(bgpOpenPacket.getRawPacket()->getRawData(), origBuffer, bufferLength7); delete origOpenMessage; - - // create packet with multiple BGP layers pcpp::EthLayer ethLayer(pcpp::MacAddress("fa:16:3e:34:89:43"), pcpp::MacAddress("fa:16:3e:22:35:cf")); @@ -373,7 +367,6 @@ PTF_TEST_CASE(BgpLayerCreationTest) ip4Layer.getIPv4Header()->timeToLive = 1; ip4Layer.getIPv4Header()->fragmentOffset = 0x40; - pcpp::TcpLayer tcpLayer(20576, 179); tcpLayer.getTcpHeader()->sequenceNumber = htobe32(3136152551); tcpLayer.getTcpHeader()->ackNumber = htobe32(4120889265); @@ -421,11 +414,13 @@ PTF_TEST_CASE(BgpLayerCreationTest) PTF_ASSERT_TRUE(newBgpMultiLayerPacket.addLayer(&newBgpUpdateMessage4)); newBgpMultiLayerPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(newBgpMultiLayerPacket.getRawPacket()->getRawDataLen(), bgpUpdatePacket2.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(newBgpMultiLayerPacket.getRawPacket()->getRawData(), bgpUpdatePacket2.getRawPacket()->getRawData(), bgpUpdatePacket2.getRawPacket()->getRawDataLen()); - -} // BgpLayerCreationTest + PTF_ASSERT_EQUAL(newBgpMultiLayerPacket.getRawPacket()->getRawDataLen(), + bgpUpdatePacket2.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(newBgpMultiLayerPacket.getRawPacket()->getRawData(), + bgpUpdatePacket2.getRawPacket()->getRawData(), + bgpUpdatePacket2.getRawPacket()->getRawDataLen()); +} // BgpLayerCreationTest PTF_TEST_CASE(BgpLayerEditTest) { @@ -441,34 +436,37 @@ PTF_TEST_CASE(BgpLayerEditTest) uint8_t origBuffer[1500]; - - // edit BGP NOTIFICATION message memcpy(origBuffer, buffer1, bufferLength1); pcpp::Packet bgpNotificationPacket1(&rawPacket1); pcpp::Packet bgpNotificationPacket2(&rawPacket2); - pcpp::BgpNotificationMessageLayer* bgpNotificationMessage1 = bgpNotificationPacket1.getLayerOfType(); + pcpp::BgpNotificationMessageLayer* bgpNotificationMessage1 = + bgpNotificationPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(bgpNotificationMessage1); PTF_ASSERT_TRUE(bgpNotificationMessage1->setNotificationData(nullptr, 0)); bgpNotificationMessage1->getNotificationMsgHeader()->errorSubCode = 4; bgpNotificationPacket1.computeCalculateFields(); - pcpp::BgpNotificationMessageLayer* bgpNotificationMessage2 = bgpNotificationPacket2.getLayerOfType(); + pcpp::BgpNotificationMessageLayer* bgpNotificationMessage2 = + bgpNotificationPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(bgpNotificationMessage2); PTF_ASSERT_EQUAL(bgpNotificationMessage1->getDataLen(), bgpNotificationMessage2->getDataLen()); - PTF_ASSERT_BUF_COMPARE(bgpNotificationMessage1->getData(), bgpNotificationMessage2->getData(), bgpNotificationMessage2->getDataLen()); + PTF_ASSERT_BUF_COMPARE(bgpNotificationMessage1->getData(), bgpNotificationMessage2->getData(), + bgpNotificationMessage2->getDataLen()); pcpp::RawPacket rawPacket1Tag(origBuffer, bufferLength1, time, false); bgpNotificationPacket1.setRawPacket(&rawPacket1Tag, false); bgpNotificationMessage1 = bgpNotificationPacket1.getLayerOfType(); - std::string notificationData = "7c4e54542077696c6c20706572666f726d206d61696e74656e616e6365206f6e207468697320726f757465722e205468697320697320747261636b656420696e205449434b45542d312d32343832343239342e20436f6e74616374206e6f63406e74742e6e657420666f72206d6f726520696e666f726d6174696f6e2e"; + std::string notificationData = + "7c4e54542077696c6c20706572666f726d206d61696e74656e616e6365206f6e207468697320726f757465722e20546869732069732074" + "7261636b656420696e205449434b45542d312d32343832343239342e20436f6e74616374206e6f63406e74742e6e657420666f72206d6f" + "726520696e666f726d6174696f6e2e"; PTF_ASSERT_TRUE(bgpNotificationMessage2->setNotificationData(notificationData)); bgpNotificationMessage2->getNotificationMsgHeader()->errorSubCode = 2; bgpNotificationPacket2.computeCalculateFields(); PTF_ASSERT_EQUAL(bgpNotificationMessage1->getDataLen(), bgpNotificationMessage2->getDataLen()); - PTF_ASSERT_BUF_COMPARE(bgpNotificationMessage1->getData(), bgpNotificationMessage2->getData(), bgpNotificationMessage2->getDataLen()); - - + PTF_ASSERT_BUF_COMPARE(bgpNotificationMessage1->getData(), bgpNotificationMessage2->getData(), + bgpNotificationMessage2->getDataLen()); // edit BGP OPEN message @@ -493,18 +491,22 @@ PTF_TEST_CASE(BgpLayerEditTest) PTF_ASSERT_EQUAL(bgpOpenMessage2->getHeaderLen(), 29); PTF_ASSERT_EQUAL(bgpOpenMessage2->getOptionalParametersLength(), 0); - - // edit BGP UPDATE message pcpp::Packet bgpUpdatePacket1(&rawPacket5); pcpp::Packet bgpUpdatePacket2(&rawPacket6); - pcpp::BgpUpdateMessageLayer* bgpUpdateMessage1Packet1 = bgpUpdatePacket1.getLayerOfType(); - pcpp::BgpUpdateMessageLayer* bgpUpdateMessage2Packet1 = bgpUpdatePacket1.getNextLayerOfType(bgpUpdateMessage1Packet1); - pcpp::BgpUpdateMessageLayer* bgpUpdateMessage1Packet2 = bgpUpdatePacket2.getLayerOfType(); - pcpp::BgpUpdateMessageLayer* bgpUpdateMessage2Packet2 = bgpUpdatePacket2.getNextLayerOfType(bgpUpdateMessage1Packet2); - pcpp::BgpUpdateMessageLayer* bgpUpdateMessage3Packet2 = bgpUpdatePacket2.getNextLayerOfType(bgpUpdateMessage2Packet2); - pcpp::BgpUpdateMessageLayer* bgpUpdateMessage4Packet2 = bgpUpdatePacket2.getNextLayerOfType(bgpUpdateMessage3Packet2); + pcpp::BgpUpdateMessageLayer* bgpUpdateMessage1Packet1 = + bgpUpdatePacket1.getLayerOfType(); + pcpp::BgpUpdateMessageLayer* bgpUpdateMessage2Packet1 = + bgpUpdatePacket1.getNextLayerOfType(bgpUpdateMessage1Packet1); + pcpp::BgpUpdateMessageLayer* bgpUpdateMessage1Packet2 = + bgpUpdatePacket2.getLayerOfType(); + pcpp::BgpUpdateMessageLayer* bgpUpdateMessage2Packet2 = + bgpUpdatePacket2.getNextLayerOfType(bgpUpdateMessage1Packet2); + pcpp::BgpUpdateMessageLayer* bgpUpdateMessage3Packet2 = + bgpUpdatePacket2.getNextLayerOfType(bgpUpdateMessage2Packet2); + pcpp::BgpUpdateMessageLayer* bgpUpdateMessage4Packet2 = + bgpUpdatePacket2.getNextLayerOfType(bgpUpdateMessage3Packet2); PTF_ASSERT_NOT_NULL(bgpUpdateMessage1Packet1); PTF_ASSERT_NOT_NULL(bgpUpdateMessage2Packet1); PTF_ASSERT_NOT_NULL(bgpUpdateMessage1Packet2); @@ -516,7 +518,8 @@ PTF_TEST_CASE(BgpLayerEditTest) withdrawnRoutes.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "104.104.40.0")); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->setWithdrawnRoutes(withdrawnRoutes)); PTF_ASSERT_EQUAL(bgpUpdateMessage1Packet1->getHeaderLen(), bgpUpdateMessage2Packet1->getHeaderLen()); - PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage2Packet1->getData(), bgpUpdateMessage2Packet1->getHeaderLen()); + PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage2Packet1->getData(), + bgpUpdateMessage2Packet1->getHeaderLen()); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->clearWithdrawnRoutes()); std::vector pathAttributes; @@ -528,7 +531,8 @@ PTF_TEST_CASE(BgpLayerEditTest) PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->setPathAttributes(pathAttributes)); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->setNetworkLayerReachabilityInfo(nlri)); PTF_ASSERT_EQUAL(bgpUpdateMessage1Packet1->getHeaderLen(), bgpUpdateMessage1Packet2->getHeaderLen()); - PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage1Packet2->getData(), bgpUpdateMessage1Packet2->getHeaderLen()); + PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage1Packet2->getData(), + bgpUpdateMessage1Packet2->getHeaderLen()); pathAttributes.erase(pathAttributes.begin()); pathAttributes.insert(pathAttributes.begin(), pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 1, "00")); @@ -540,20 +544,24 @@ PTF_TEST_CASE(BgpLayerEditTest) nlri.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(24, "103.103.40.0")); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->setNetworkLayerReachabilityInfo(nlri)); PTF_ASSERT_EQUAL(bgpUpdateMessage1Packet1->getHeaderLen(), bgpUpdateMessage2Packet2->getHeaderLen()); - PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage2Packet2->getData(), bgpUpdateMessage2Packet2->getHeaderLen()); + PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage2Packet2->getData(), + bgpUpdateMessage2Packet2->getHeaderLen()); pathAttributes.erase(pathAttributes.begin() + 1); - pathAttributes.insert(pathAttributes.begin() + 1, pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 2, "02020000000a00000014")); + pathAttributes.insert(pathAttributes.begin() + 1, + pcpp::BgpUpdateMessageLayer::path_attribute(0x40, 2, "02020000000a00000014")); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->setPathAttributes(pathAttributes)); nlri.clear(); nlri.push_back(pcpp::BgpUpdateMessageLayer::prefix_and_ip(32, "20.100.100.20")); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->setNetworkLayerReachabilityInfo(nlri)); PTF_ASSERT_EQUAL(bgpUpdateMessage1Packet1->getHeaderLen(), bgpUpdateMessage3Packet2->getHeaderLen()); - PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage3Packet2->getData(), bgpUpdateMessage3Packet2->getHeaderLen()); + PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage3Packet2->getData(), + bgpUpdateMessage3Packet2->getHeaderLen()); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->clearNetworkLayerReachabilityInfo()); PTF_ASSERT_TRUE(bgpUpdateMessage1Packet1->clearPathAttributes()); PTF_ASSERT_EQUAL(bgpUpdateMessage1Packet1->getHeaderLen(), bgpUpdateMessage4Packet2->getHeaderLen()); - PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage4Packet2->getData(), bgpUpdateMessage4Packet2->getHeaderLen()); + PTF_ASSERT_BUF_COMPARE(bgpUpdateMessage1Packet1->getData(), bgpUpdateMessage4Packet2->getData(), + bgpUpdateMessage4Packet2->getHeaderLen()); -} // BgpLayerEditTest +} // BgpLayerEditTest diff --git a/Tests/Packet++Test/Tests/CotpTests.cpp b/Tests/Packet++Test/Tests/CotpTests.cpp index 8c9e033ecc..b8f9ee8b35 100644 --- a/Tests/Packet++Test/Tests/CotpTests.cpp +++ b/Tests/Packet++Test/Tests/CotpTests.cpp @@ -37,4 +37,4 @@ PTF_TEST_CASE(CotpLayerTest) PTF_ASSERT_EQUAL(newCotpPacket.getPduType(), 0xd2); PTF_ASSERT_EQUAL(newCotpPacket.getTpduNumber(), 0x7d); -} // CotpLayerTest +} // CotpLayerTest diff --git a/Tests/Packet++Test/Tests/DhcpTests.cpp b/Tests/Packet++Test/Tests/DhcpTests.cpp index 55e4844d4b..f60071d6bb 100644 --- a/Tests/Packet++Test/Tests/DhcpTests.cpp +++ b/Tests/Packet++Test/Tests/DhcpTests.cpp @@ -8,7 +8,6 @@ #include "UdpLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(DhcpParsingTest) { timeval time; @@ -33,20 +32,18 @@ PTF_TEST_CASE(DhcpParsingTest) PTF_ASSERT_EQUAL(dhcpLayer->getOptionsCount(), 12); pcpp::DhcpOption opt = dhcpLayer->getFirstOptionData(); - pcpp::DhcpOptionTypes optTypeArr[] = { - pcpp::DHCPOPT_DHCP_MESSAGE_TYPE, - pcpp::DHCPOPT_SUBNET_MASK, - pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER, - pcpp::DHCPOPT_DHCP_LEASE_TIME, - pcpp::DHCPOPT_ROUTERS, - pcpp::DHCPOPT_DOMAIN_NAME_SERVERS, - pcpp::DHCPOPT_TFTP_SERVER_NAME, - pcpp::DHCPOPT_SIP_SERVERS, - pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER, - pcpp::DHCPOPT_AUTHENTICATION, - pcpp::DHCPOPT_DHCP_AGENT_OPTIONS, - pcpp::DHCPOPT_END - }; + pcpp::DhcpOptionTypes optTypeArr[] = { pcpp::DHCPOPT_DHCP_MESSAGE_TYPE, + pcpp::DHCPOPT_SUBNET_MASK, + pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER, + pcpp::DHCPOPT_DHCP_LEASE_TIME, + pcpp::DHCPOPT_ROUTERS, + pcpp::DHCPOPT_DOMAIN_NAME_SERVERS, + pcpp::DHCPOPT_TFTP_SERVER_NAME, + pcpp::DHCPOPT_SIP_SERVERS, + pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER, + pcpp::DHCPOPT_AUTHENTICATION, + pcpp::DHCPOPT_DHCP_AGENT_OPTIONS, + pcpp::DHCPOPT_END }; size_t optLenArr[] = { 1, 4, 4, 4, 4, 8, 14, 5, 16, 31, 22, 0 }; @@ -67,14 +64,15 @@ PTF_TEST_CASE(DhcpParsingTest) PTF_ASSERT_FALSE(dhcpLayer->getOptionData(optTypeArr[i]).isNull()); } - PTF_ASSERT_EQUAL(dhcpLayer->getOptionData(pcpp::DHCPOPT_SUBNET_MASK).getValueAsIpAddr(), pcpp::IPv4Address("255.255.255.0")); - PTF_ASSERT_EQUAL(dhcpLayer->getOptionData(pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER).getValueAsIpAddr(), pcpp::IPv4Address("172.22.178.234")); + PTF_ASSERT_EQUAL(dhcpLayer->getOptionData(pcpp::DHCPOPT_SUBNET_MASK).getValueAsIpAddr(), + pcpp::IPv4Address("255.255.255.0")); + PTF_ASSERT_EQUAL(dhcpLayer->getOptionData(pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER).getValueAsIpAddr(), + pcpp::IPv4Address("172.22.178.234")); PTF_ASSERT_EQUAL(dhcpLayer->getOptionData(pcpp::DHCPOPT_DHCP_LEASE_TIME).getValueAs(), htobe32(43200)); PTF_ASSERT_EQUAL(dhcpLayer->getOptionData(pcpp::DHCPOPT_TFTP_SERVER_NAME).getValueAsString(), "172.22.178.234"); PTF_ASSERT_EQUAL(dhcpLayer->getMessageType(), pcpp::DHCP_OFFER, enum); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/Dhcp2.dat"); pcpp::Packet dhcpPacket2(&rawPacket2); @@ -92,17 +90,15 @@ PTF_TEST_CASE(DhcpParsingTest) PTF_ASSERT_EQUAL(dhcpLayer->getOptionsCount(), 9); opt = dhcpLayer->getFirstOptionData(); - pcpp::DhcpOptionTypes optTypeArr2[] = { - pcpp::DHCPOPT_DHCP_MESSAGE_TYPE, - pcpp::DHCPOPT_DHCP_MAX_MESSAGE_SIZE, - pcpp::DHCPOPT_DHCP_PARAMETER_REQUEST_LIST, - pcpp::DHCPOPT_DHCP_LEASE_TIME, - pcpp::DHCPOPT_DHCP_OPTION_OVERLOAD, - pcpp::DHCPOPT_DHCP_MESSAGE, - pcpp::DHCPOPT_PAD, - pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER, - pcpp::DHCPOPT_END - }; + pcpp::DhcpOptionTypes optTypeArr2[] = { pcpp::DHCPOPT_DHCP_MESSAGE_TYPE, + pcpp::DHCPOPT_DHCP_MAX_MESSAGE_SIZE, + pcpp::DHCPOPT_DHCP_PARAMETER_REQUEST_LIST, + pcpp::DHCPOPT_DHCP_LEASE_TIME, + pcpp::DHCPOPT_DHCP_OPTION_OVERLOAD, + pcpp::DHCPOPT_DHCP_MESSAGE, + pcpp::DHCPOPT_PAD, + pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER, + pcpp::DHCPOPT_END }; size_t optLenArr2[] = { 1, 2, 4, 4, 1, 7, 0, 7, 0 }; @@ -126,9 +122,7 @@ PTF_TEST_CASE(DhcpParsingTest) } PTF_ASSERT_EQUAL(dhcpLayer->getMessageType(), pcpp::DHCP_DISCOVER, enum); -} // DhcpParsingTest - - +} // DhcpParsingTest PTF_TEST_CASE(DhcpCreationTest) { @@ -154,28 +148,37 @@ PTF_TEST_CASE(DhcpCreationTest) dhcpLayer.setServerIpAddress(serverIP); dhcpLayer.setGatewayIpAddress(gatewayIP); - pcpp::DhcpOption subnetMaskOpt = dhcpLayer.addOption(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_SUBNET_MASK, pcpp::IPv4Address("255.255.255.0"))); + pcpp::DhcpOption subnetMaskOpt = + dhcpLayer.addOption(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_SUBNET_MASK, pcpp::IPv4Address("255.255.255.0"))); PTF_ASSERT_FALSE(subnetMaskOpt.isNull()); uint8_t sipServersData[] = { 0x01, 0xac, 0x16, 0xb2, 0xea }; - pcpp::DhcpOption sipServersOpt = dhcpLayer.addOption(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_SIP_SERVERS, sipServersData, 5)); + pcpp::DhcpOption sipServersOpt = + dhcpLayer.addOption(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_SIP_SERVERS, sipServersData, 5)); PTF_ASSERT_FALSE(sipServersOpt.isNull()); - uint8_t agentData[] = { 0x01, 0x14, 0x20, 0x50, 0x4f, 0x4e, 0x20, 0x31, 0x2f, 0x31, 0x2f, 0x30, 0x37, 0x2f, 0x30, 0x31, 0x3a, 0x31, 0x2e, 0x30, 0x2e, 0x31 }; - pcpp::DhcpOption agentOpt = dhcpLayer.addOption(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_AGENT_OPTIONS, agentData, 22)); + uint8_t agentData[] = { 0x01, 0x14, 0x20, 0x50, 0x4f, 0x4e, 0x20, 0x31, 0x2f, 0x31, 0x2f, + 0x30, 0x37, 0x2f, 0x30, 0x31, 0x3a, 0x31, 0x2e, 0x30, 0x2e, 0x31 }; + pcpp::DhcpOption agentOpt = + dhcpLayer.addOption(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_AGENT_OPTIONS, agentData, 22)); PTF_ASSERT_FALSE(agentOpt.isNull()); - pcpp::DhcpOption clientIdOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER, nullptr, 16), pcpp::DHCPOPT_SIP_SERVERS); + pcpp::DhcpOption clientIdOpt = dhcpLayer.addOptionAfter( + pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER, nullptr, 16), pcpp::DHCPOPT_SIP_SERVERS); clientIdOpt.setValue(0); clientIdOpt.setValueString("nathan1clientid", 1); PTF_ASSERT_FALSE(clientIdOpt.isNull()); - uint8_t authOptData[] = { 0x01, 0x01, 0x00, 0xc8, 0x78, 0xc4, 0x52, 0x56, 0x40, 0x20, 0x81, 0x31, 0x32, 0x33, 0x34, 0x8f, 0xe0, 0xcc, 0xe2, 0xee, 0x85, 0x96, - 0xab, 0xb2, 0x58, 0x17, 0xc4, 0x80, 0xb2, 0xfd, 0x30}; - pcpp::DhcpOption authOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_AUTHENTICATION, authOptData, 31), pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER); + uint8_t authOptData[] = { 0x01, 0x01, 0x00, 0xc8, 0x78, 0xc4, 0x52, 0x56, 0x40, 0x20, 0x81, + 0x31, 0x32, 0x33, 0x34, 0x8f, 0xe0, 0xcc, 0xe2, 0xee, 0x85, 0x96, + 0xab, 0xb2, 0x58, 0x17, 0xc4, 0x80, 0xb2, 0xfd, 0x30 }; + pcpp::DhcpOption authOpt = dhcpLayer.addOptionAfter( + pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_AUTHENTICATION, authOptData, 31), pcpp::DHCPOPT_DHCP_CLIENT_IDENTIFIER); PTF_ASSERT_FALSE(authOpt.isNull()); - pcpp::DhcpOption dhcpServerIdOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER, pcpp::IPv4Address("172.22.178.234")), pcpp::DHCPOPT_SUBNET_MASK); + pcpp::DhcpOption dhcpServerIdOpt = dhcpLayer.addOptionAfter( + pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER, pcpp::IPv4Address("172.22.178.234")), + pcpp::DHCPOPT_SUBNET_MASK); PTF_ASSERT_FALSE(dhcpServerIdOpt.isNull()); pcpp::Packet newPacket(6); @@ -184,20 +187,25 @@ PTF_TEST_CASE(DhcpCreationTest) PTF_ASSERT_TRUE(newPacket.addLayer(&udpLayer)); PTF_ASSERT_TRUE(newPacket.addLayer(&dhcpLayer)); - pcpp::DhcpOption routerOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_ROUTERS, pcpp::IPv4Address("10.10.8.254")), pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER); + pcpp::DhcpOption routerOpt = + dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_ROUTERS, pcpp::IPv4Address("10.10.8.254")), + pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER); PTF_ASSERT_FALSE(routerOpt.isNull()); - pcpp::DhcpOption tftpServerOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_TFTP_SERVER_NAME, std::string("172.22.178.234")), pcpp::DHCPOPT_ROUTERS); + pcpp::DhcpOption tftpServerOpt = dhcpLayer.addOptionAfter( + pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_TFTP_SERVER_NAME, std::string("172.22.178.234")), pcpp::DHCPOPT_ROUTERS); PTF_ASSERT_FALSE(tftpServerOpt.isNull()); - pcpp::DhcpOption dnsOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DOMAIN_NAME_SERVERS, nullptr, 8), pcpp::DHCPOPT_ROUTERS); + pcpp::DhcpOption dnsOpt = dhcpLayer.addOptionAfter( + pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DOMAIN_NAME_SERVERS, nullptr, 8), pcpp::DHCPOPT_ROUTERS); PTF_ASSERT_FALSE(dnsOpt.isNull()); pcpp::IPv4Address dns1IP("143.209.4.1"); pcpp::IPv4Address dns2IP("143.209.5.1"); dnsOpt.setValueIpAddr(dns1IP); dnsOpt.setValueIpAddr(dns2IP, 4); - pcpp::DhcpOption leaseOpt = dhcpLayer.addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_LEASE_TIME, (uint32_t)43200), pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER); + pcpp::DhcpOption leaseOpt = dhcpLayer.addOptionAfter( + pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_LEASE_TIME, (uint32_t)43200), pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER); PTF_ASSERT_FALSE(leaseOpt.isNull()); newPacket.computeCalculateFields(); @@ -207,10 +215,8 @@ PTF_TEST_CASE(DhcpCreationTest) PTF_ASSERT_EQUAL(newPacket.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(newPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - delete [] buffer1; -} // DhcpCreationTest - - + delete[] buffer1; +} // DhcpCreationTest PTF_TEST_CASE(DhcpEditTest) { @@ -239,10 +245,12 @@ PTF_TEST_CASE(DhcpEditTest) pcpp::IPv4Address newRouter("192.168.2.1"); - opt = dhcpLayer->addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_ROUTERS, newRouter), pcpp::DHCPOPT_SUBNET_MASK); + opt = + dhcpLayer->addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_ROUTERS, newRouter), pcpp::DHCPOPT_SUBNET_MASK); PTF_ASSERT_FALSE(opt.isNull()); - opt = dhcpLayer->addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER, newRouter), pcpp::DHCPOPT_DHCP_MESSAGE_TYPE); + opt = dhcpLayer->addOptionAfter(pcpp::DhcpOptionBuilder(pcpp::DHCPOPT_DHCP_SERVER_IDENTIFIER, newRouter), + pcpp::DHCPOPT_DHCP_MESSAGE_TYPE); PTF_ASSERT_FALSE(opt.isNull()); dhcpPacket.computeCalculateFields(); @@ -252,7 +260,7 @@ PTF_TEST_CASE(DhcpEditTest) PTF_ASSERT_EQUAL(dhcpPacket.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(dhcpPacket.getRawPacket()->getRawData(), buffer2, bufferLength2); - delete [] buffer2; + delete[] buffer2; PTF_ASSERT_TRUE(dhcpLayer->removeAllOptions()); @@ -270,9 +278,9 @@ PTF_TEST_CASE(DhcpEditTest) PTF_ASSERT_EQUAL(dhcpLayer->getOptionsCount(), 2); - PTF_ASSERT_EQUAL(dhcpLayer->getDataLen(), sizeof(pcpp::dhcp_header)+4); + PTF_ASSERT_EQUAL(dhcpLayer->getDataLen(), sizeof(pcpp::dhcp_header) + 4); PTF_ASSERT_EQUAL(dhcpLayer->getMessageType(), pcpp::DHCP_DISCOVER, enum); dhcpPacket.computeCalculateFields(); -} // DhcpEditTest +} // DhcpEditTest diff --git a/Tests/Packet++Test/Tests/DhcpV6Tests.cpp b/Tests/Packet++Test/Tests/DhcpV6Tests.cpp index 0565b3ed8e..0d7ca263de 100644 --- a/Tests/Packet++Test/Tests/DhcpV6Tests.cpp +++ b/Tests/Packet++Test/Tests/DhcpV6Tests.cpp @@ -5,7 +5,6 @@ #include "DhcpV6Layer.h" #include "SystemUtils.h" - PTF_TEST_CASE(DhcpV6ParsingTest) { timeval time; @@ -22,14 +21,9 @@ PTF_TEST_CASE(DhcpV6ParsingTest) PTF_ASSERT_EQUAL(dhcpv6Layer->getOptionCount(), 6); PTF_ASSERT_EQUAL(dhcpv6Layer->toString(), "DHCPv6 Layer, Solicit message"); - pcpp::DhcpV6OptionType optTypeArr[] = { - pcpp::DHCPV6_OPT_CLIENTID, - pcpp::DHCPV6_OPT_ORO, - pcpp::DHCPV6_OPT_ELAPSED_TIME, - pcpp::DHCPV6_OPT_USER_CLASS, - pcpp::DHCPV6_OPT_VENDOR_CLASS, - pcpp::DHCPV6_OPT_IA_NA - }; + pcpp::DhcpV6OptionType optTypeArr[] = { pcpp::DHCPV6_OPT_CLIENTID, pcpp::DHCPV6_OPT_ORO, + pcpp::DHCPV6_OPT_ELAPSED_TIME, pcpp::DHCPV6_OPT_USER_CLASS, + pcpp::DHCPV6_OPT_VENDOR_CLASS, pcpp::DHCPV6_OPT_IA_NA }; size_t optDataSizeArr[] = { 18, 14, 2, 10, 51, 12 }; std::string optDataAsHexString[] = { "000200000009464745313934373134515300", @@ -50,8 +44,7 @@ PTF_TEST_CASE(DhcpV6ParsingTest) PTF_ASSERT_EQUAL(dhcpOption.getValueAsHexString(), optDataAsHexString[i]); dhcpOption = dhcpv6Layer->getNextOptionData(dhcpOption); } -} // DhcpV6ParsingTest - +} // DhcpV6ParsingTest PTF_TEST_CASE(DhcpV6CreationTest) { @@ -71,41 +64,53 @@ PTF_TEST_CASE(DhcpV6CreationTest) PTF_ASSERT_NOT_NULL(origDhcpV6Layer); // 1st option - pcpp::DhcpV6Option option = newDhcpV6Layer.addOption(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_IA_NA, "1d00fcea00000000000000000005001820010dba0100000000000000000000300000017700000258")); + pcpp::DhcpV6Option option = newDhcpV6Layer.addOption(pcpp::DhcpV6OptionBuilder( + pcpp::DHCPV6_OPT_IA_NA, "1d00fcea00000000000000000005001820010dba0100000000000000000000300000017700000258")); PTF_ASSERT_EQUAL(option.getType(), pcpp::DHCPV6_OPT_IA_NA); PTF_ASSERT_EQUAL(option.getDataSize(), 40); PTF_ASSERT_EQUAL(newDhcpV6Layer.getOptionCount(), 1); // 4th option - option = newDhcpV6Layer.addOption(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DNS_SERVERS, "20010dba010000000000000000000001")); + option = newDhcpV6Layer.addOption( + pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DNS_SERVERS, "20010dba010000000000000000000001")); PTF_ASSERT_EQUAL(option.getType(), pcpp::DHCPV6_OPT_DNS_SERVERS); PTF_ASSERT_EQUAL(option.getDataSize(), 16); PTF_ASSERT_EQUAL(newDhcpV6Layer.getOptionCount(), 2); // 3rd option - option = newDhcpV6Layer.addOptionBefore(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_SERVERID, "000100012154eee7000c29703dd8"), pcpp::DHCPV6_OPT_DNS_SERVERS); + option = newDhcpV6Layer.addOptionBefore( + pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_SERVERID, "000100012154eee7000c29703dd8"), + pcpp::DHCPV6_OPT_DNS_SERVERS); PTF_ASSERT_EQUAL(option.getType(), pcpp::DHCPV6_OPT_SERVERID); PTF_ASSERT_EQUAL(option.getDataSize(), 14); PTF_ASSERT_EQUAL(newDhcpV6Layer.getOptionCount(), 3); // 2nd option - option = newDhcpV6Layer.addOptionAfter(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_CLIENTID, "000200000009464745313934373134515300"), pcpp::DHCPV6_OPT_IA_NA); + option = newDhcpV6Layer.addOptionAfter( + pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_CLIENTID, "000200000009464745313934373134515300"), + pcpp::DHCPV6_OPT_IA_NA); PTF_ASSERT_EQUAL(option.getType(), pcpp::DHCPV6_OPT_CLIENTID); PTF_ASSERT_EQUAL(option.getDataSize(), 18); PTF_ASSERT_EQUAL(newDhcpV6Layer.getOptionCount(), 4); // 6th option - option = newDhcpV6Layer.addOption(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_BOOTFILE_URL, "687474703a2f2f5b323030313a6462613a3130303a3a315d3a393039302f657868617573746976655f7a74705f7363726970742e7079")); + option = newDhcpV6Layer.addOption(pcpp::DhcpV6OptionBuilder( + pcpp::DHCPV6_OPT_BOOTFILE_URL, + "687474703a2f2f5b323030313a6462613a3130303a3a315d3a393039302f657868617573746976655f7a74705f7363726970742e7079")); PTF_ASSERT_EQUAL(option.getType(), pcpp::DHCPV6_OPT_BOOTFILE_URL); PTF_ASSERT_EQUAL(option.getDataSize(), 54); PTF_ASSERT_EQUAL(newDhcpV6Layer.getOptionCount(), 5); // 5th option - option = newDhcpV6Layer.addOptionAfter(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DOMAIN_LIST, "05636973636f056c6f63616c00"), pcpp::DHCPV6_OPT_DNS_SERVERS); + option = newDhcpV6Layer.addOptionAfter( + pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DOMAIN_LIST, "05636973636f056c6f63616c00"), + pcpp::DHCPV6_OPT_DNS_SERVERS); PTF_ASSERT_EQUAL(option.getType(), pcpp::DHCPV6_OPT_DOMAIN_LIST); PTF_ASSERT_EQUAL(option.getDataSize(), 13); PTF_ASSERT_EQUAL(newDhcpV6Layer.getOptionCount(), 6); pcpp::Logger::getInstance().suppressLogs(); // prev/next option doesn't exist in layer - option = newDhcpV6Layer.addOptionAfter(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DOMAIN_LIST, "05"), pcpp::DHCPV6_OPT_ELAPSED_TIME); + option = newDhcpV6Layer.addOptionAfter(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DOMAIN_LIST, "05"), + pcpp::DHCPV6_OPT_ELAPSED_TIME); PTF_ASSERT_TRUE(option.isNull()); - option = newDhcpV6Layer.addOptionBefore(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DOMAIN_LIST, "05"), pcpp::DHCPV6_OPT_ELAPSED_TIME); + option = newDhcpV6Layer.addOptionBefore(pcpp::DhcpV6OptionBuilder(pcpp::DHCPV6_OPT_DOMAIN_LIST, "05"), + pcpp::DHCPV6_OPT_ELAPSED_TIME); PTF_ASSERT_TRUE(option.isNull()); // string is not a valid hex stream @@ -123,8 +128,7 @@ PTF_TEST_CASE(DhcpV6CreationTest) PTF_ASSERT_EQUAL(dhcpv6Packet.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(dhcpv6Packet.getRawPacket()->getRawData(), origBuffer, bufferLength1); delete origDhcpV6Layer; -} // DhcpV6CreationTest - +} // DhcpV6CreationTest PTF_TEST_CASE(DhcpV6EditTest) { @@ -158,4 +162,4 @@ PTF_TEST_CASE(DhcpV6EditTest) dhcpv6Layer->removeAllOptions(); PTF_ASSERT_EQUAL(dhcpv6Layer->getOptionCount(), 0); PTF_ASSERT_EQUAL(dhcpv6Layer->getDataLen(), 4); -} // DhcpV6EditTest +} // DhcpV6EditTest diff --git a/Tests/Packet++Test/Tests/DnsTests.cpp b/Tests/Packet++Test/Tests/DnsTests.cpp index 5a34fcd2af..1d0b371038 100644 --- a/Tests/Packet++Test/Tests/DnsTests.cpp +++ b/Tests/Packet++Test/Tests/DnsTests.cpp @@ -11,7 +11,6 @@ #include "DnsLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(DnsLayerParsingTest) { timeval time; @@ -57,7 +56,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(firstAuthority->getName(), "Yaels-iPhone.local"); PTF_ASSERT_EQUAL(firstAuthority->getDataLength(), 4); PTF_ASSERT_EQUAL(firstAuthority->getData()->toString(), "10.0.0.2"); - PTF_ASSERT_EQUAL(firstAuthority->getData().castAs()->getIpAddress(), pcpp::IPv4Address("10.0.0.2")); + PTF_ASSERT_EQUAL(firstAuthority->getData().castAs()->getIpAddress(), + pcpp::IPv4Address("10.0.0.2")); PTF_ASSERT_EQUAL(firstAuthority->getSize(), 16); pcpp::DnsResource* secondAuthority = dnsLayer->getNextAuthority(firstAuthority); @@ -68,7 +68,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(secondAuthority->getName(), "Yaels-iPhone.local"); PTF_ASSERT_EQUAL(secondAuthority->getDataLength(), 16); PTF_ASSERT_EQUAL(secondAuthority->getData()->toString(), "fe80::5a1f:aaff:fe4f:3f9d"); - PTF_ASSERT_EQUAL(secondAuthority->getData().castAs()->getIpAddress(), pcpp::IPv6Address("fe80::5a1f:aaff:fe4f:3f9d")); + PTF_ASSERT_EQUAL(secondAuthority->getData().castAs()->getIpAddress(), + pcpp::IPv6Address("fe80::5a1f:aaff:fe4f:3f9d")); PTF_ASSERT_EQUAL(secondAuthority->getSize(), 28); pcpp::DnsResource* thirdAuthority = dnsLayer->getNextAuthority(secondAuthority); @@ -89,9 +90,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_NULL(dnsLayer->getNextAdditionalRecord(additionalRecord)); PTF_ASSERT_EQUAL(dnsLayer->getAdditionalRecord("", true), additionalRecord, ptr); - PTF_ASSERT_EQUAL(dnsLayer->toString(), "DNS query, ID: 0; queries: 2, answers: 0, authorities: 2, additional record: 1"); - - + PTF_ASSERT_EQUAL(dnsLayer->toString(), + "DNS query, ID: 0; queries: 2, answers: 0, authorities: 2, additional record: 1"); READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/Dns1.dat"); @@ -130,7 +130,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(curAnswer->getTTL(), 117); PTF_ASSERT_EQUAL(curAnswer->getName(), "www-google-analytics.L.google.com"); PTF_ASSERT_EQUAL(curAnswer->getDataLength(), 4); - PTF_ASSERT_TRUE(curAnswer->getData().castAs()->getIpAddress().matchNetwork(std::string("212.199.219.0/255.255.255.0"))); + PTF_ASSERT_TRUE(curAnswer->getData().castAs()->getIpAddress().matchNetwork( + std::string("212.199.219.0/255.255.255.0"))); curAnswer = dnsLayer->getNextAnswer(curAnswer); answerCount++; @@ -139,11 +140,11 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(answerCount, 18); PTF_ASSERT_EQUAL(dnsLayer->getAnswer("www.google-analytics.com", false), dnsLayer->getFirstAnswer(), ptr); - PTF_ASSERT_EQUAL(dnsLayer->getAnswer("www-google-analytics.L.google.com", true), dnsLayer->getNextAnswer(dnsLayer->getFirstAnswer()), ptr); - - PTF_ASSERT_EQUAL(dnsLayer->toString(), "DNS query response, ID: 11629; queries: 1, answers: 17, authorities: 0, additional record: 0"); - + PTF_ASSERT_EQUAL(dnsLayer->getAnswer("www-google-analytics.L.google.com", true), + dnsLayer->getNextAnswer(dnsLayer->getFirstAnswer()), ptr); + PTF_ASSERT_EQUAL(dnsLayer->toString(), + "DNS query response, ID: 11629; queries: 1, answers: 17, authorities: 0, additional record: 0"); READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/Dns2.dat"); @@ -155,9 +156,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_NOT_NULL(queryByName); PTF_ASSERT_EQUAL(queryByName->getDnsClass(), pcpp::DNS_CLASS_IN_QU, enum); - PTF_ASSERT_EQUAL(dnsLayer->toString(), "DNS query, ID: 0; queries: 2, answers: 0, authorities: 2, additional record: 1"); - - + PTF_ASSERT_EQUAL(dnsLayer->toString(), + "DNS query, ID: 0; queries: 2, answers: 0, authorities: 2, additional record: 1"); READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/Dns4.dat"); @@ -171,7 +171,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(curAnswer->getDnsClass(), pcpp::DNS_CLASS_IN, enum); PTF_ASSERT_EQUAL(curAnswer->getData()->toString(), "pref: 1; mx: mta5.am0.yahoodns.net"); PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().preference, 1); - PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().mailExchange, "mta5.am0.yahoodns.net"); + PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().mailExchange, + "mta5.am0.yahoodns.net"); curAnswer = dnsLayer->getNextAnswer(curAnswer); PTF_ASSERT_NOT_NULL(curAnswer); @@ -179,7 +180,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(curAnswer->getDnsClass(), pcpp::DNS_CLASS_IN, enum); PTF_ASSERT_EQUAL(curAnswer->getData()->toString(), "pref: 1; mx: mta7.am0.yahoodns.net"); PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().preference, 1); - PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().mailExchange, "mta7.am0.yahoodns.net"); + PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().mailExchange, + "mta7.am0.yahoodns.net"); curAnswer = dnsLayer->getNextAnswer(curAnswer); PTF_ASSERT_NOT_NULL(curAnswer); @@ -187,9 +189,8 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(curAnswer->getDnsClass(), pcpp::DNS_CLASS_IN, enum); PTF_ASSERT_EQUAL(curAnswer->getData()->toString(), "pref: 1; mx: mta6.am0.yahoodns.net"); PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().preference, 1); - PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().mailExchange, "mta6.am0.yahoodns.net"); - - + PTF_ASSERT_EQUAL(curAnswer->getData()->castAs()->getMxData().mailExchange, + "mta6.am0.yahoodns.net"); READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/dns_stack_overflow.dat"); @@ -201,12 +202,12 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_EQUAL(dnsLayer->getQueryCount(), 1); firstQuery = dnsLayer->getFirstQuery(); PTF_ASSERT_NOT_NULL(firstQuery); - PTF_ASSERT_EQUAL(firstQuery->getName(), - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA."); + PTF_ASSERT_EQUAL( + firstQuery->getName(), + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA."); PTF_ASSERT_EQUAL(firstQuery->getSize(), 134); PTF_ASSERT_NULL(dnsLayer->getNextQuery(firstQuery)); - // a corner case of malformed packet where the total number of resources overflow uint16 // by less than 300. This fixes the bug: https://github.com/seladb/PcapPlusPlus/issues/441 READ_FILE_AND_CREATE_PACKET(6, "PacketExamples/DnsTooManyResources.dat"); @@ -218,9 +219,7 @@ PTF_TEST_CASE(DnsLayerParsingTest) PTF_ASSERT_NULL(dnsLayer->getFirstAnswer()); PTF_ASSERT_NULL(dnsLayer->getFirstAuthority()); PTF_ASSERT_NULL(dnsLayer->getFirstAdditionalRecord()); -} // DnsLayerParsingTest - - +} // DnsLayerParsingTest PTF_TEST_CASE(DnsLayerQueryCreationTest) { @@ -238,7 +237,8 @@ PTF_TEST_CASE(DnsLayerQueryCreationTest) pcpp::DnsLayer dns2Layer; dns2Layer.getDnsHeader()->recursionDesired = true; dns2Layer.getDnsHeader()->transactionID = htobe16(0xb179); - pcpp::DnsQuery* newQuery = dns2Layer.addQuery("mail-attachment.googleusercontent.com", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN); + pcpp::DnsQuery* newQuery = + dns2Layer.addQuery("mail-attachment.googleusercontent.com", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN); PTF_ASSERT_NOT_NULL(newQuery); PTF_ASSERT_EQUAL(dns2Layer.getQueryCount(), 1); PTF_ASSERT_EQUAL(newQuery->getName(), "mail-attachment.googleusercontent.com"); @@ -255,7 +255,6 @@ PTF_TEST_CASE(DnsLayerQueryCreationTest) PTF_ASSERT_BUF_COMPARE(dnsEdit2Packet.getRawPacket()->getRawData(), buffer2, bufferLength2); - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/DnsEdit1.dat"); pcpp::Packet dnsEdit1RefPacket(&rawPacket1); @@ -290,9 +289,7 @@ PTF_TEST_CASE(DnsLayerQueryCreationTest) PTF_ASSERT_EQUAL(dnsEdit1Packet.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(dnsEdit1Packet.getRawPacket()->getRawData(), buffer1, bufferLength1); -} // DnsLayerQueryCreationTest - - +} // DnsLayerQueryCreationTest PTF_TEST_CASE(DnsLayerResourceCreationTest) { @@ -314,7 +311,8 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) dns4Layer.getDnsHeader()->recursionAvailable = 1; pcpp::StringDnsResourceData stringDnsData("assets.pinterest.com.cdngc.net"); - pcpp::DnsResource* firstAnswer = dns4Layer.addAnswer("assets.pinterest.com", pcpp::DNS_TYPE_CNAME, pcpp::DNS_CLASS_IN, 228, &stringDnsData); + pcpp::DnsResource* firstAnswer = + dns4Layer.addAnswer("assets.pinterest.com", pcpp::DNS_TYPE_CNAME, pcpp::DNS_CLASS_IN, 228, &stringDnsData); PTF_ASSERT_NOT_NULL(firstAnswer); PTF_ASSERT_EQUAL(dns4Layer.getFirstAnswer(), firstAnswer, ptr); PTF_ASSERT_EQUAL(firstAnswer->getData()->toString(), "assets.pinterest.com.cdngc.net"); @@ -328,9 +326,11 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) PTF_ASSERT_EQUAL(dnsEdit4Packet.getLayerOfType()->getFirstAnswer(), firstAnswer, ptr); pcpp::IPv4DnsResourceData ipv4DnsData(std::string("151.249.90.217")); - pcpp::DnsResource* secondAnswer = dns4Layer.addAnswer("assets.pinterest.com.cdngc.net", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 3, &ipv4DnsData); + pcpp::DnsResource* secondAnswer = + dns4Layer.addAnswer("assets.pinterest.com.cdngc.net", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 3, &ipv4DnsData); PTF_ASSERT_NOT_NULL(secondAnswer); - PTF_ASSERT_EQUAL(secondAnswer->getData()->castAs()->getIpAddress(), ipv4DnsData.getIpAddress()); + PTF_ASSERT_EQUAL(secondAnswer->getData()->castAs()->getIpAddress(), + ipv4DnsData.getIpAddress()); pcpp::DnsQuery* query = dns4Layer.addQuery("assets.pinterest.com", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN); PTF_ASSERT_NOT_NULL(query); @@ -338,7 +338,8 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) PTF_ASSERT_EQUAL(dnsEdit4Packet.getLayerOfType()->getFirstAnswer(), firstAnswer, ptr); PTF_ASSERT_EQUAL(dnsEdit4Packet.getLayerOfType()->getNextAnswer(firstAnswer), secondAnswer, ptr); - PTF_ASSERT_RAISES(pcpp::IPv4DnsResourceData(std::string("256.249.90.238")), std::invalid_argument, "Not a valid IPv4 address: 256.249.90.238"); + PTF_ASSERT_RAISES(pcpp::IPv4DnsResourceData(std::string("256.249.90.238")), std::invalid_argument, + "Not a valid IPv4 address: 256.249.90.238"); pcpp::DnsResource* thirdAnswer = dns4Layer.addAnswer(secondAnswer); PTF_ASSERT_NOT_NULL(thirdAnswer); @@ -348,8 +349,11 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) ipv4DnsData = pcpp::IPv4DnsResourceData(std::string("151.249.90.238")); PTF_ASSERT_TRUE(thirdAnswer->setData(&ipv4DnsData)); - PTF_ASSERT_EQUAL(dns4Layer.getAnswer("assets.pinterest.com.cdngc.net", true)->getData()->toString(), "151.249.90.217"); - PTF_ASSERT_EQUAL(dns4Layer.getNextAnswer(dns4Layer.getAnswer("assets.pinterest.com.cdngc.net", false))->getData()->toString(), "151.249.90.238"); + PTF_ASSERT_EQUAL(dns4Layer.getAnswer("assets.pinterest.com.cdngc.net", true)->getData()->toString(), + "151.249.90.217"); + PTF_ASSERT_EQUAL( + dns4Layer.getNextAnswer(dns4Layer.getAnswer("assets.pinterest.com.cdngc.net", false))->getData()->toString(), + "151.249.90.238"); dnsEdit4Packet.computeCalculateFields(); @@ -357,9 +361,6 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) PTF_ASSERT_BUF_COMPARE(dnsEdit4Packet.getRawPacket()->getRawData(), buffer4, bufferLength4); - - - READ_FILE_AND_CREATE_PACKET(6, "PacketExamples/DnsEdit6.dat"); pcpp::Packet dnsEdit6RefPacket(&rawPacket6); @@ -371,7 +372,8 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) pcpp::DnsLayer dnsLayer6; ipv4DnsData = pcpp::IPv4DnsResourceData(std::string("10.0.0.2")); - pcpp::DnsResource* authority = dnsLayer6.addAuthority("Yaels-iPhone.local", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 120, &ipv4DnsData); + pcpp::DnsResource* authority = + dnsLayer6.addAuthority("Yaels-iPhone.local", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_IN, 120, &ipv4DnsData); PTF_ASSERT_NOT_NULL(authority); query = dnsLayer6.addQuery(query); @@ -387,7 +389,8 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) PTF_ASSERT_EQUAL(dnsLayer6.getAuthority("Yaels-iPhone.local", true)->getData()->toString(), "10.0.0.2"); - PTF_ASSERT_RAISES(pcpp::IPv6DnsResourceData(std::string("##80::5a1f:aaff:fe4f:3f9d")), std::invalid_argument, "Not a valid IPv6 address: ##80::5a1f:aaff:fe4f:3f9d"); + PTF_ASSERT_RAISES(pcpp::IPv6DnsResourceData(std::string("##80::5a1f:aaff:fe4f:3f9d")), std::invalid_argument, + "Not a valid IPv6 address: ##80::5a1f:aaff:fe4f:3f9d"); authority = dnsLayer6.addAuthority(authority); pcpp::Logger::getInstance().suppressLogs(); @@ -421,8 +424,6 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) PTF_ASSERT_BUF_COMPARE(dnsEdit6Packet.getRawPacket()->getRawData(), buffer6, bufferLength6); - - READ_FILE_AND_CREATE_PACKET(7, "PacketExamples/DnsEdit7.dat"); pcpp::Packet dnsEdit7RefPacket(&rawPacket7); @@ -444,7 +445,8 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) queryNameOffset << "#" << query->getNameOffset(); pcpp::MxDnsResourceData mxDnsData(1, "mta5.am0.yahoodns.net"); - pcpp::DnsResource* answer = dnsLayer7.addAnswer(queryNameOffset.str(), pcpp::DNS_TYPE_MX, pcpp::DNS_CLASS_IN, 187, &mxDnsData); + pcpp::DnsResource* answer = + dnsLayer7.addAnswer(queryNameOffset.str(), pcpp::DNS_TYPE_MX, pcpp::DNS_CLASS_IN, 187, &mxDnsData); PTF_ASSERT_NOT_NULL(answer); std::stringstream firsAnswerMxOffset; @@ -469,19 +471,21 @@ PTF_TEST_CASE(DnsLayerResourceCreationTest) PTF_ASSERT_EQUAL(dnsEdit7Packet.getRawPacket()->getRawDataLen(), bufferLength7); PTF_ASSERT_BUF_COMPARE(dnsEdit7Packet.getRawPacket()->getRawData(), buffer7, bufferLength7); -} // DnsLayerResourceCreationTest +} // DnsLayerResourceCreationTest PTF_TEST_CASE(DnsLayerAddDnsKeyTest) { // data length overflow 256 - const std::string dnskey = "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQ \ + const std::string dnskey = + "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQ \ lNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+Sr \ DK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU="; pcpp::DnsLayer dnsLayer; pcpp::GenericDnsResourceData genericData(reinterpret_cast(dnskey.c_str()), dnskey.size()); - const auto* additional = dnsLayer.addAnswer("github.com", pcpp::DNS_TYPE_DNSKEY, pcpp::DNS_CLASS_IN, 32, &genericData); + const auto* additional = + dnsLayer.addAnswer("github.com", pcpp::DNS_TYPE_DNSKEY, pcpp::DNS_CLASS_IN, 32, &genericData); PTF_ASSERT_NOT_NULL(additional); } @@ -516,9 +520,7 @@ PTF_TEST_CASE(DnsLayerEditTest) PTF_ASSERT_TRUE(dnsLayer5->getFirstQuery()->setName("assets.pinterest.com")); PTF_ASSERT_EQUAL(dnsLayer3->getHeaderLen(), dnsLayer5->getHeaderLen()); PTF_ASSERT_BUF_COMPARE(dnsLayer3->getData(), dnsLayer5->getData(), dnsLayer3->getHeaderLen()); -} // DnsLayerEditTest - - +} // DnsLayerEditTest PTF_TEST_CASE(DnsLayerRemoveResourceTest) { @@ -547,9 +549,11 @@ PTF_TEST_CASE(DnsLayerRemoveResourceTest) PTF_ASSERT_EQUAL(dnsLayer6->getFirstAuthority()->getData()->toString(), "10.0.0.2"); PTF_ASSERT_EQUAL(dnsLayer6->getFirstAdditionalRecord()->getDnsType(), pcpp::DNS_TYPE_OPT, enum); - PTF_ASSERT_EQUAL(dnsLayer6->getHeaderLen(), origDnsLayer6.getHeaderLen()-firstQuerySize); + PTF_ASSERT_EQUAL(dnsLayer6->getHeaderLen(), origDnsLayer6.getHeaderLen() - firstQuerySize); - PTF_ASSERT_BUF_COMPARE(dnsLayer6->getData() + sizeof(pcpp::dnshdr), origDnsLayer6.getData() + sizeof(pcpp::dnshdr)+firstQuerySize , dnsLayer6->getHeaderLen() - sizeof(pcpp::dnshdr)); + PTF_ASSERT_BUF_COMPARE(dnsLayer6->getData() + sizeof(pcpp::dnshdr), + origDnsLayer6.getData() + sizeof(pcpp::dnshdr) + firstQuerySize, + dnsLayer6->getHeaderLen() - sizeof(pcpp::dnshdr)); pcpp::DnsResource* firstAuthority = dnsLayer6->getFirstAuthority(); pcpp::DnsResource* secondAuthority = dnsLayer6->getNextAuthority(firstAuthority); @@ -563,7 +567,7 @@ PTF_TEST_CASE(DnsLayerRemoveResourceTest) PTF_ASSERT_EQUAL(firstAuthority->getTTL(), 120); PTF_ASSERT_EQUAL(dnsLayer6->getFirstAdditionalRecord()->getDnsType(), pcpp::DNS_TYPE_OPT, enum); PTF_ASSERT_EQUAL(dnsLayer6->getFirstAdditionalRecord()->getDataLength(), 12); - PTF_ASSERT_EQUAL(dnsLayer6->getHeaderLen(), origDnsLayer6.getHeaderLen()-firstQuerySize-secondAuthoritySize); + PTF_ASSERT_EQUAL(dnsLayer6->getHeaderLen(), origDnsLayer6.getHeaderLen() - firstQuerySize - secondAuthoritySize); PTF_ASSERT_FALSE(dnsLayer6->removeQuery("BlaBla", true)); PTF_ASSERT_FALSE(dnsLayer6->removeAuthority(secondAuthority)); @@ -574,10 +578,8 @@ PTF_TEST_CASE(DnsLayerRemoveResourceTest) PTF_ASSERT_EQUAL(dnsLayer6->getAdditionalRecordCount(), 0); PTF_ASSERT_NULL(dnsLayer6->getFirstAdditionalRecord()); PTF_ASSERT_EQUAL(dnsLayer6->getFirstAuthority()->getData()->toString(), "10.0.0.2"); - PTF_ASSERT_EQUAL(dnsLayer6->getHeaderLen(), origDnsLayer6.getHeaderLen()-firstQuerySize-secondAuthoritySize-additionalRecordSize); - - - + PTF_ASSERT_EQUAL(dnsLayer6->getHeaderLen(), + origDnsLayer6.getHeaderLen() - firstQuerySize - secondAuthoritySize - additionalRecordSize); READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/DnsEdit4.dat"); @@ -591,7 +593,7 @@ PTF_TEST_CASE(DnsLayerRemoveResourceTest) firstQuerySize = dnsLayer4->getFirstQuery()->getSize(); PTF_ASSERT_TRUE(dnsLayer4->removeQuery("pinter", false)); PTF_ASSERT_EQUAL(dnsLayer4->getQueryCount(), 0); - PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), origDnsLayer4.getHeaderLen()-firstQuerySize); + PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), origDnsLayer4.getHeaderLen() - firstQuerySize); pcpp::DnsResource* firstAnswer = dnsLayer4->getFirstAnswer(); PTF_ASSERT_NOT_NULL(firstAnswer); @@ -609,20 +611,19 @@ PTF_TEST_CASE(DnsLayerRemoveResourceTest) PTF_ASSERT_EQUAL(dnsLayer4->getAnswerCount(), 2); PTF_ASSERT_EQUAL(dnsLayer4->getFirstAnswer(), firstAnswer, ptr); PTF_ASSERT_EQUAL(dnsLayer4->getNextAnswer(dnsLayer4->getFirstAnswer()), thirdAnswer, ptr); - PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), origDnsLayer4.getHeaderLen()-firstQuerySize-secondAnswerSize); + PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), origDnsLayer4.getHeaderLen() - firstQuerySize - secondAnswerSize); PTF_ASSERT_TRUE(dnsLayer4->removeAnswer(firstAnswer)); PTF_ASSERT_EQUAL(dnsLayer4->getAnswerCount(), 1); PTF_ASSERT_EQUAL(dnsLayer4->getFirstAnswer(), thirdAnswer, ptr); PTF_ASSERT_EQUAL(dnsLayer4->getFirstAnswer()->getData()->toString(), "151.249.90.238"); - PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), origDnsLayer4.getHeaderLen()-firstQuerySize-secondAnswerSize-firstAnswerSize); + PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), + origDnsLayer4.getHeaderLen() - firstQuerySize - secondAnswerSize - firstAnswerSize); PTF_ASSERT_TRUE(dnsLayer4->removeAnswer(thirdAnswer)); PTF_ASSERT_FALSE(dnsLayer4->removeAdditionalRecord("blabla", false)); PTF_ASSERT_EQUAL(dnsLayer4->getHeaderLen(), sizeof(pcpp::dnshdr)); -} // DnsLayerRemoveResourceTest - - +} // DnsLayerRemoveResourceTest PTF_TEST_CASE(DnsOverTcpParsingTest) { @@ -652,7 +653,6 @@ PTF_TEST_CASE(DnsOverTcpParsingTest) PTF_ASSERT_EQUAL(additionalRecord->getDnsType(), pcpp::DNS_TYPE_OPT, enum); PTF_ASSERT_EQUAL(additionalRecord->getName(), ""); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/dns_over_tcp_response.dat"); pcpp::Packet dnsPacket2(&rawPacket2); @@ -666,37 +666,28 @@ PTF_TEST_CASE(DnsOverTcpParsingTest) PTF_ASSERT_EQUAL(be16toh(dnsLayer->getDnsHeader()->transactionID), 0x6165, hex); PTF_ASSERT_EQUAL(dnsOverTcpLayer->getTcpMessageLength(), 1133); - std::string expectedNames[8] = { - "net", - "net", - "A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net", - "A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net", - "QT8SCE02D5ONC5NBTQUNBEIDMFJE7GL8.net", - "QT8SCE02D5ONC5NBTQUNBEIDMFJE7GL8.net", - "EEQ3CIFFULOPN4J3E5MKEGKVDJKIGVBP.net", - "EEQ3CIFFULOPN4J3E5MKEGKVDJKIGVBP.net" - }; - - pcpp::DnsType expectedTypes[8] = { - pcpp::DNS_TYPE_SOA, - pcpp::DNS_TYPE_RRSIG, - pcpp::DNS_TYPE_NSEC3, - pcpp::DNS_TYPE_RRSIG, - pcpp::DNS_TYPE_NSEC3, - pcpp::DNS_TYPE_RRSIG, - pcpp::DNS_TYPE_NSEC3, - pcpp::DNS_TYPE_RRSIG - }; + std::string expectedNames[8] = { "net", + "net", + "A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net", + "A1RT98BS5QGC9NFI51S9HCI47ULJG6JH.net", + "QT8SCE02D5ONC5NBTQUNBEIDMFJE7GL8.net", + "QT8SCE02D5ONC5NBTQUNBEIDMFJE7GL8.net", + "EEQ3CIFFULOPN4J3E5MKEGKVDJKIGVBP.net", + "EEQ3CIFFULOPN4J3E5MKEGKVDJKIGVBP.net" }; + + pcpp::DnsType expectedTypes[8] = { pcpp::DNS_TYPE_SOA, pcpp::DNS_TYPE_RRSIG, pcpp::DNS_TYPE_NSEC3, + pcpp::DNS_TYPE_RRSIG, pcpp::DNS_TYPE_NSEC3, pcpp::DNS_TYPE_RRSIG, + pcpp::DNS_TYPE_NSEC3, pcpp::DNS_TYPE_RRSIG }; int i = 0; - for (pcpp::DnsResource* authority = dnsLayer->getFirstAuthority(); authority != nullptr; authority = dnsLayer->getNextAuthority(authority)) + for (pcpp::DnsResource* authority = dnsLayer->getFirstAuthority(); authority != nullptr; + authority = dnsLayer->getNextAuthority(authority)) { PTF_ASSERT_EQUAL(authority->getName(), expectedNames[i]); PTF_ASSERT_EQUAL(authority->getDnsType(), expectedTypes[i], enum); i++; } - READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/dns_over_tcp_answer.dat"); pcpp::Packet dnsPacket3(&rawPacket3); @@ -712,10 +703,9 @@ PTF_TEST_CASE(DnsOverTcpParsingTest) pcpp::DnsResource* answer = dnsLayer->getFirstAnswer(); PTF_ASSERT_EQUAL(answer->getName(), "github.com"); - PTF_ASSERT_EQUAL(answer->getData().castAs()->getIpAddress().toString(), "192.30.255.113"); -} // DnsOverTcpParsingTest - - + PTF_ASSERT_EQUAL(answer->getData().castAs()->getIpAddress().toString(), + "192.30.255.113"); +} // DnsOverTcpParsingTest PTF_TEST_CASE(DnsOverTcpCreationTest) { @@ -741,7 +731,7 @@ PTF_TEST_CASE(DnsOverTcpCreationTest) PTF_ASSERT_EQUAL(bufferLength1, dnsPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_BUF_COMPARE(dnsPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); -} // DnsOverTcpCreationTest +} // DnsOverTcpCreationTest PTF_TEST_CASE(DnsNXDomainTest) { @@ -754,4 +744,4 @@ PTF_TEST_CASE(DnsNXDomainTest) pcpp::DnsLayer* dnsLayer = dnsPacket.getLayerOfType(); PTF_ASSERT_EQUAL(1, dnsLayer->getDnsHeader()->queryOrResponse); -} // DnsNXDomainTest +} // DnsNXDomainTest diff --git a/Tests/Packet++Test/Tests/EthAndArpTests.cpp b/Tests/Packet++Test/Tests/EthAndArpTests.cpp index 906ad73fea..b8faea90aa 100644 --- a/Tests/Packet++Test/Tests/EthAndArpTests.cpp +++ b/Tests/Packet++Test/Tests/EthAndArpTests.cpp @@ -13,7 +13,8 @@ PTF_TEST_CASE(OUILookup) { pcpp::OUILookup lookupEngineJson; - PTF_ASSERT_GREATER_THAN(lookupEngineJson.initOUIDatabaseFromJson("../../3rdParty/OUIDataset/PCPP_OUIDataset.json"), 0); + PTF_ASSERT_GREATER_THAN(lookupEngineJson.initOUIDatabaseFromJson("../../3rdParty/OUIDataset/PCPP_OUIDataset.json"), + 0); PTF_ASSERT_EQUAL(lookupEngineJson.getVendorName("aa:aa:aa:aa:aa:aa"), "Unknown"); // CIDR 36 @@ -50,9 +51,10 @@ PTF_TEST_CASE(EthPacketCreation) PTF_ASSERT_NOT_NULL(rawPacket); PTF_ASSERT_EQUAL(rawPacket->getRawDataLen(), 18); - uint8_t expectedBuffer[18] = { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04 }; + uint8_t expectedBuffer[18] = { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04 }; PTF_ASSERT_BUF_COMPARE(rawPacket->getRawData(), expectedBuffer, 18); -} // EthPacketCreation +} // EthPacketCreation PTF_TEST_CASE(EthPacketPointerCreation) { @@ -72,17 +74,18 @@ PTF_TEST_CASE(EthPacketPointerCreation) PTF_ASSERT_EQUAL(ethPacket->getLayerOfType(), ethLayer, ptr); PTF_ASSERT_EQUAL(ethPacket->getLayerOfType()->getDestMac(), dstMac); PTF_ASSERT_EQUAL(ethPacket->getLayerOfType()->getSourceMac(), srcMac); - PTF_ASSERT_EQUAL(ethPacket->getLayerOfType()->getEthHeader()->etherType, be16toh(PCPP_ETHERTYPE_IP)); + PTF_ASSERT_EQUAL(ethPacket->getLayerOfType()->getEthHeader()->etherType, + be16toh(PCPP_ETHERTYPE_IP)); pcpp::RawPacket* rawPacket = ethPacket->getRawPacket(); PTF_ASSERT_NOT_NULL(rawPacket); PTF_ASSERT_EQUAL(rawPacket->getRawDataLen(), 18); - uint8_t expectedBuffer[18] = { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04 }; + uint8_t expectedBuffer[18] = { 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04 }; PTF_ASSERT_BUF_COMPARE(rawPacket->getRawData(), expectedBuffer, 18); - delete(ethPacket); -} // EthPacketPointerCreation - + delete (ethPacket); +} // EthPacketPointerCreation PTF_TEST_CASE(EthAndArpPacketParsing) { @@ -113,8 +116,7 @@ PTF_TEST_CASE(EthAndArpPacketParsing) PTF_ASSERT_EQUAL(arpLayer->isRequest(), false); PTF_ASSERT_EQUAL(arpLayer->getSenderIpAddr(), pcpp::IPv4Address("10.0.0.138")); PTF_ASSERT_EQUAL(arpLayer->getTargetMacAddress(), pcpp::MacAddress("6c:f0:49:b2:de:6e")); -} // EthAndArpPacketParsing - +} // EthAndArpPacketParsing PTF_TEST_CASE(ArpPacketCreation) { @@ -122,7 +124,8 @@ PTF_TEST_CASE(ArpPacketCreation) pcpp::MacAddress dstMac("ff:ff:ff:ff:ff:ff"); pcpp::EthLayer ethLayer(srcMac, dstMac, PCPP_ETHERTYPE_ARP); - pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST, srcMac, srcMac, pcpp::IPv4Address("10.0.0.1"), pcpp::IPv4Address("10.0.0.138")); + pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST, srcMac, srcMac, pcpp::IPv4Address("10.0.0.1"), + pcpp::IPv4Address("10.0.0.138")); pcpp::Packet arpRequestPacket(1); PTF_ASSERT_TRUE(arpRequestPacket.addLayer(ðLayer)); @@ -142,9 +145,8 @@ PTF_TEST_CASE(ArpPacketCreation) PTF_ASSERT_EQUAL(bufferLength1, arpRequestPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_BUF_COMPARE(arpRequestPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - delete [] buffer1; -} // ArpPacketCreation - + delete[] buffer1; +} // ArpPacketCreation PTF_TEST_CASE(EthDot3LayerParsingTest) { @@ -164,8 +166,7 @@ PTF_TEST_CASE(EthDot3LayerParsingTest) PTF_ASSERT_NOT_NULL(ethDot3Layer->getNextLayer()); PTF_ASSERT_EQUAL(ethDot3Layer->getNextLayer()->getProtocol(), pcpp::LLC, enum); -} // EthDot3LayerParsingTest - +} // EthDot3LayerParsingTest PTF_TEST_CASE(EthDot3LayerCreateEditTest) { @@ -181,7 +182,8 @@ PTF_TEST_CASE(EthDot3LayerCreateEditTest) pcpp::MacAddress dstAddr("01:80:c2:00:00:00"); pcpp::EthDot3Layer ethDot3NewLayer(srcAddr, dstAddr, 38); - pcpp::PayloadLayer newPayloadLayer("424203000000000000000013f71edff00000271080000013f7115ec0801b0100140002000f000000000000000000"); + pcpp::PayloadLayer newPayloadLayer( + "424203000000000000000013f71edff00000271080000013f7115ec0801b0100140002000f000000000000000000"); PTF_ASSERT_EQUAL(newPayloadLayer.getDataLen(), 46); pcpp::Packet newEthDot3Packet; @@ -191,15 +193,13 @@ PTF_TEST_CASE(EthDot3LayerCreateEditTest) PTF_ASSERT_BUF_COMPARE(newEthDot3Packet.getRawPacket()->getRawData(), buffer1, bufferLength1); - // edit an EthDot3 packet ethDot3NewLayer.setSourceMac(pcpp::MacAddress("00:1a:a1:97:d1:85")); ethDot3NewLayer.getEthHeader()->length = htobe16(121); - auto newPayloadLayer2 = new pcpp::PayloadLayer("424203000003027c8000000c305dd100000000008000000c305dd10080050000140002000f000000500000000" - "00000000000000000000000000000000000000000000000000000000000000055bf4e8a44b25d442868549c1bf7720f00030d408000001a" - "a197d180137c8005000c305dd10000030d40808013"); + auto newPayloadLayer2 = new pcpp::PayloadLayer( + "424203000003027c8000000c305dd100000000008000000c305dd10080050000140002000f00000050000000000000000000000000000000000000000000000000000000000000000000000055bf4e8a44b25d442868549c1bf7720f00030d408000001aa197d180137c8005000c305dd10000030d40808013"); PTF_ASSERT_TRUE(newEthDot3Packet.detachLayer(&newPayloadLayer)); PTF_ASSERT_TRUE(newEthDot3Packet.addLayer(newPayloadLayer2, true)); @@ -207,7 +207,7 @@ PTF_TEST_CASE(EthDot3LayerCreateEditTest) PTF_ASSERT_BUF_COMPARE(newEthDot3Packet.getRawPacket()->getRawData(), buffer2, bufferLength2); - delete [] buffer1; - delete [] buffer2; + delete[] buffer1; + delete[] buffer2; -} // EthDot3LayerCreateEditTest +} // EthDot3LayerCreateEditTest diff --git a/Tests/Packet++Test/Tests/FtpTests.cpp b/Tests/Packet++Test/Tests/FtpTests.cpp index 7f7612e3dd..9f243ae836 100644 --- a/Tests/Packet++Test/Tests/FtpTests.cpp +++ b/Tests/Packet++Test/Tests/FtpTests.cpp @@ -18,7 +18,7 @@ PTF_TEST_CASE(FtpParsingTests) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ftpIpv4Req.dat"); pcpp::Packet ftpPacket1(&rawPacket1); - pcpp::FtpRequestLayer *ftpLayer1 = ftpPacket1.getLayerOfType(); + pcpp::FtpRequestLayer* ftpLayer1 = ftpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer1); PTF_ASSERT_EQUAL(int(ftpLayer1->getCommand()), int(pcpp::FtpRequestLayer::FtpCommand::USER)); @@ -30,7 +30,7 @@ PTF_TEST_CASE(FtpParsingTests) READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/ftpIpv4Resp.dat"); pcpp::Packet ftpPacket2(&rawPacket2); - pcpp::FtpResponseLayer *ftpLayer2 = ftpPacket2.getLayerOfType(); + pcpp::FtpResponseLayer* ftpLayer2 = ftpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer2); PTF_ASSERT_EQUAL(int(ftpLayer2->getStatusCode()), int(pcpp::FtpResponseLayer::FtpStatusCode::REQ_FILE_OK_COMPLETE)); @@ -42,7 +42,7 @@ PTF_TEST_CASE(FtpParsingTests) READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/ftpIpv4RespHyphen.dat"); pcpp::Packet ftpPacket3(&rawPacket3); - pcpp::FtpResponseLayer *ftpLayer3 = ftpPacket3.getLayerOfType(); + pcpp::FtpResponseLayer* ftpLayer3 = ftpPacket3.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer3); PTF_ASSERT_EQUAL(int(ftpLayer3->getStatusCode()), int(pcpp::FtpResponseLayer::FtpStatusCode::SYSTEM_STATUS)); @@ -55,7 +55,7 @@ PTF_TEST_CASE(FtpParsingTests) READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/ftpIpv6Req.dat"); pcpp::Packet ftpPacket4(&rawPacket4); - pcpp::FtpRequestLayer *ftpLayer4 = ftpPacket4.getLayerOfType(); + pcpp::FtpRequestLayer* ftpLayer4 = ftpPacket4.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer4); PTF_ASSERT_EQUAL(int(ftpLayer4->getCommand()), int(pcpp::FtpRequestLayer::FtpCommand::PASS)); @@ -67,11 +67,11 @@ PTF_TEST_CASE(FtpParsingTests) READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/ftpIpv6Resp.dat"); pcpp::Packet ftpPacket5(&rawPacket5); - pcpp::FtpResponseLayer *ftpLayer5 = ftpPacket5.getLayerOfType(); + pcpp::FtpResponseLayer* ftpLayer5 = ftpPacket5.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer5); PTF_ASSERT_EQUAL(int(ftpLayer5->getStatusCode()), - int(pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED)); + int(pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED)); PTF_ASSERT_EQUAL(ftpLayer5->getStatusCodeString(), "502"); PTF_ASSERT_EQUAL(ftpLayer5->getStatusOption(), "Unknown command 'utf8'."); PTF_ASSERT_EQUAL(ftpLayer5->toString(), "FTP Response: 502"); @@ -81,7 +81,7 @@ PTF_TEST_CASE(FtpParsingTests) READ_FILE_AND_CREATE_PACKET(6, "PacketExamples/ftp-data.dat"); pcpp::Packet ftpDataPacket(&rawPacket6); - pcpp::FtpDataLayer *ftpDataLayer = ftpDataPacket.getLayerOfType(); + pcpp::FtpDataLayer* ftpDataLayer = ftpDataPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpDataLayer); @@ -89,175 +89,152 @@ PTF_TEST_CASE(FtpParsingTests) PTF_ASSERT_EQUAL(ftpDataLayer->toString(), "FTP Data"); // Command codes + // clang-format off std::vector> possibleCommandCodes = { - {static_cast(0), "Unknown command"}, - {pcpp::FtpRequestLayer::FtpCommand::ABOR, "Abort an active file transfer"}, - {pcpp::FtpRequestLayer::FtpCommand::ACCT, "Account information"}, - {pcpp::FtpRequestLayer::FtpCommand::ADAT, "Authentication/Security Data"}, - {pcpp::FtpRequestLayer::FtpCommand::ALLO, "Allocate sufficient disk space to receive a file"}, - {pcpp::FtpRequestLayer::FtpCommand::APPE, "Append (with create)"}, - {pcpp::FtpRequestLayer::FtpCommand::AUTH, "Authentication/Security Mechanism"}, - {pcpp::FtpRequestLayer::FtpCommand::AVBL, "Get the available space"}, - {pcpp::FtpRequestLayer::FtpCommand::CCC, "Clear Command Channel"}, - {pcpp::FtpRequestLayer::FtpCommand::CDUP, "Change to Parent Directory"}, - {pcpp::FtpRequestLayer::FtpCommand::CONF, "Confidentiality Protection Command"}, - {pcpp::FtpRequestLayer::FtpCommand::CSID, "Client / Server Identification"}, - {pcpp::FtpRequestLayer::FtpCommand::CWD, "Change working directory"}, - {pcpp::FtpRequestLayer::FtpCommand::DELE, "Delete file"}, - {pcpp::FtpRequestLayer::FtpCommand::DSIZ, "Get the directory size"}, - {pcpp::FtpRequestLayer::FtpCommand::ENC, "Privacy Protected Channel"}, - {pcpp::FtpRequestLayer::FtpCommand::EPRT, - "Specifies an extended address and port to which the server should connect"}, - {pcpp::FtpRequestLayer::FtpCommand::EPSV, "Enter extended passive mode"}, - {pcpp::FtpRequestLayer::FtpCommand::FEAT, "Get the feature list implemented by the server"}, - {pcpp::FtpRequestLayer::FtpCommand::HELP, - "Returns usage documentation on a command if specified, else a general help document is returned"}, - {pcpp::FtpRequestLayer::FtpCommand::HOST, "Identify desired virtual host on server, by name"}, - {pcpp::FtpRequestLayer::FtpCommand::LANG, "Language Negotiation"}, - {pcpp::FtpRequestLayer::FtpCommand::LIST, "Returns information of a file or directory if specified, else " - "information of the current working directory is returned"}, - {pcpp::FtpRequestLayer::FtpCommand::LPRT, - "Specifies a long address and port to which the server should connect"}, - {pcpp::FtpRequestLayer::FtpCommand::LPSV, "Enter long passive mode"}, - {pcpp::FtpRequestLayer::FtpCommand::MDTM, "Return the last-modified time of a specified file"}, - {pcpp::FtpRequestLayer::FtpCommand::MFCT, "Modify the creation time of a file"}, - {pcpp::FtpRequestLayer::FtpCommand::MFF, - "Modify fact (the last modification time, creation time, UNIX group/owner/mode of a file)"}, - {pcpp::FtpRequestLayer::FtpCommand::MFMT, "Modify the last modification time of a file"}, - {pcpp::FtpRequestLayer::FtpCommand::MIC, "Integrity Protected Command"}, - {pcpp::FtpRequestLayer::FtpCommand::MKD, "Make directory"}, - {pcpp::FtpRequestLayer::FtpCommand::MLSD, - "Lists the contents of a directory in a standardized machine-readable format"}, - {pcpp::FtpRequestLayer::FtpCommand::MLST, - "Provides data about exactly the object named on its command line in a standardized machine-readable format"}, - {pcpp::FtpRequestLayer::FtpCommand::MODE, "Sets the transfer mode (Stream, Block, or Compressed)"}, - {pcpp::FtpRequestLayer::FtpCommand::NLST, "Returns a list of file names in a specified directory"}, - {pcpp::FtpRequestLayer::FtpCommand::NOOP, "No operation (dummy packet; used mostly on keepalives)"}, - {pcpp::FtpRequestLayer::FtpCommand::OPTS, "Select options for a feature (for example OPTS UTF8 ON)"}, - {pcpp::FtpRequestLayer::FtpCommand::PASS, "Authentication password"}, - {pcpp::FtpRequestLayer::FtpCommand::PASV, "Enter passive mode"}, - {pcpp::FtpRequestLayer::FtpCommand::PBSZ, "Protection Buffer Size"}, - {pcpp::FtpRequestLayer::FtpCommand::PORT, "Specifies an address and port to which the server should connect"}, - {pcpp::FtpRequestLayer::FtpCommand::PROT, "Data Channel Protection Level"}, - {pcpp::FtpRequestLayer::FtpCommand::PWD, "Print working directory. Returns the current directory of the host"}, - {pcpp::FtpRequestLayer::FtpCommand::QUIT, "Disconnect"}, - {pcpp::FtpRequestLayer::FtpCommand::REIN, "Re initializes the connection"}, - {pcpp::FtpRequestLayer::FtpCommand::REST, "Restart transfer from the specified point"}, - {pcpp::FtpRequestLayer::FtpCommand::RETR, "Retrieve a copy of the file"}, - {pcpp::FtpRequestLayer::FtpCommand::RMD, "Remove a directory"}, - {pcpp::FtpRequestLayer::FtpCommand::RMDA, "Remove a directory tree"}, - {pcpp::FtpRequestLayer::FtpCommand::RNFR, "Rename from"}, - {pcpp::FtpRequestLayer::FtpCommand::RNTO, "Rename to"}, - {pcpp::FtpRequestLayer::FtpCommand::SITE, - "Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE HELP " - "output for complete list of supported commands"}, - {pcpp::FtpRequestLayer::FtpCommand::SIZE, "Return the size of a file"}, - {pcpp::FtpRequestLayer::FtpCommand::SMNT, "Mount file structure"}, - {pcpp::FtpRequestLayer::FtpCommand::SPSV, "Use single port passive mode (only one TCP port number for both " - "control connections and passive-mode data connections)"}, - {pcpp::FtpRequestLayer::FtpCommand::STAT, - "Returns information on the server status, including the status of the current connection"}, - {pcpp::FtpRequestLayer::FtpCommand::STOR, "Accept the data and to store the data as a file at the server site"}, - {pcpp::FtpRequestLayer::FtpCommand::STOU, "Store file uniquely"}, - {pcpp::FtpRequestLayer::FtpCommand::STRU, "Set file transfer structure"}, - {pcpp::FtpRequestLayer::FtpCommand::SYST, "Return system type"}, - {pcpp::FtpRequestLayer::FtpCommand::THMB, "Get a thumbnail of a remote image file"}, - {pcpp::FtpRequestLayer::FtpCommand::TYPE, "Sets the transfer mode (ASCII/Binary)"}, - {pcpp::FtpRequestLayer::FtpCommand::USER, "Authentication username"}, - {pcpp::FtpRequestLayer::FtpCommand::XCUP, "Change to the parent of the current working directory"}, - {pcpp::FtpRequestLayer::FtpCommand::XMKD, "Make a directory"}, - {pcpp::FtpRequestLayer::FtpCommand::XPWD, "Print the current working directory"}, - {pcpp::FtpRequestLayer::FtpCommand::XRCP, ""}, - {pcpp::FtpRequestLayer::FtpCommand::XRMD, "Remove the directory"}, - {pcpp::FtpRequestLayer::FtpCommand::XRSQ, ""}, - {pcpp::FtpRequestLayer::FtpCommand::XSEM, "Send, mail if cannot"}, - {pcpp::FtpRequestLayer::FtpCommand::XSEN, "Send to terminal"}}; - - for (const auto &entry : possibleCommandCodes) + { static_cast(0), "Unknown command"}, + { pcpp::FtpRequestLayer::FtpCommand::ABOR, "Abort an active file transfer"}, + { pcpp::FtpRequestLayer::FtpCommand::ACCT, "Account information"}, + { pcpp::FtpRequestLayer::FtpCommand::ADAT, "Authentication/Security Data"}, + { pcpp::FtpRequestLayer::FtpCommand::ALLO, "Allocate sufficient disk space to receive a file"}, + { pcpp::FtpRequestLayer::FtpCommand::APPE, "Append (with create)"}, + { pcpp::FtpRequestLayer::FtpCommand::AUTH, "Authentication/Security Mechanism"}, + { pcpp::FtpRequestLayer::FtpCommand::AVBL, "Get the available space"}, + { pcpp::FtpRequestLayer::FtpCommand::CCC, "Clear Command Channel"}, + { pcpp::FtpRequestLayer::FtpCommand::CDUP, "Change to Parent Directory"}, + { pcpp::FtpRequestLayer::FtpCommand::CONF, "Confidentiality Protection Command"}, + { pcpp::FtpRequestLayer::FtpCommand::CSID, "Client / Server Identification"}, + { pcpp::FtpRequestLayer::FtpCommand::CWD, "Change working directory"}, + { pcpp::FtpRequestLayer::FtpCommand::DELE, "Delete file"}, + { pcpp::FtpRequestLayer::FtpCommand::DSIZ, "Get the directory size"}, + { pcpp::FtpRequestLayer::FtpCommand::ENC, "Privacy Protected Channel"}, + { pcpp::FtpRequestLayer::FtpCommand::EPRT, "Specifies an extended address and port to which the server should connect"}, + { pcpp::FtpRequestLayer::FtpCommand::EPSV, "Enter extended passive mode"}, + { pcpp::FtpRequestLayer::FtpCommand::FEAT, "Get the feature list implemented by the server"}, + { pcpp::FtpRequestLayer::FtpCommand::HELP, "Returns usage documentation on a command if specified, else a general help document is returned"}, + { pcpp::FtpRequestLayer::FtpCommand::HOST, "Identify desired virtual host on server, by name"}, + { pcpp::FtpRequestLayer::FtpCommand::LANG, "Language Negotiation"}, + { pcpp::FtpRequestLayer::FtpCommand::LIST, "Returns information of a file or directory if specified, else information of the current working directory is returned"}, + { pcpp::FtpRequestLayer::FtpCommand::LPRT, "Specifies a long address and port to which the server should connect"}, + { pcpp::FtpRequestLayer::FtpCommand::LPSV, "Enter long passive mode"}, + { pcpp::FtpRequestLayer::FtpCommand::MDTM, "Return the last-modified time of a specified file"}, + { pcpp::FtpRequestLayer::FtpCommand::MFCT, "Modify the creation time of a file"}, + { pcpp::FtpRequestLayer::FtpCommand::MFF, "Modify fact (the last modification time, creation time, UNIX group/owner/mode of a file)"}, + { pcpp::FtpRequestLayer::FtpCommand::MFMT, "Modify the last modification time of a file"}, + { pcpp::FtpRequestLayer::FtpCommand::MIC, "Integrity Protected Command"}, + { pcpp::FtpRequestLayer::FtpCommand::MKD, "Make directory"}, + { pcpp::FtpRequestLayer::FtpCommand::MLSD, "Lists the contents of a directory in a standardized machine-readable format"}, + { pcpp::FtpRequestLayer::FtpCommand::MLST, "Provides data about exactly the object named on its command line in a standardized machine-readable format"}, + { pcpp::FtpRequestLayer::FtpCommand::MODE, "Sets the transfer mode (Stream, Block, or Compressed)"}, + { pcpp::FtpRequestLayer::FtpCommand::NLST, "Returns a list of file names in a specified directory"}, + { pcpp::FtpRequestLayer::FtpCommand::NOOP, "No operation (dummy packet; used mostly on keepalives)"}, + { pcpp::FtpRequestLayer::FtpCommand::OPTS, "Select options for a feature (for example OPTS UTF8 ON)"}, + { pcpp::FtpRequestLayer::FtpCommand::PASS, "Authentication password"}, + { pcpp::FtpRequestLayer::FtpCommand::PASV, "Enter passive mode"}, + { pcpp::FtpRequestLayer::FtpCommand::PBSZ, "Protection Buffer Size"}, + { pcpp::FtpRequestLayer::FtpCommand::PORT, "Specifies an address and port to which the server should connect"}, + { pcpp::FtpRequestLayer::FtpCommand::PROT, "Data Channel Protection Level"}, + { pcpp::FtpRequestLayer::FtpCommand::PWD, "Print working directory. Returns the current directory of the host"}, + { pcpp::FtpRequestLayer::FtpCommand::QUIT, "Disconnect"}, + { pcpp::FtpRequestLayer::FtpCommand::REIN, "Re initializes the connection"}, + { pcpp::FtpRequestLayer::FtpCommand::REST, "Restart transfer from the specified point"}, + { pcpp::FtpRequestLayer::FtpCommand::RETR, "Retrieve a copy of the file"}, + { pcpp::FtpRequestLayer::FtpCommand::RMD, "Remove a directory"}, + { pcpp::FtpRequestLayer::FtpCommand::RMDA, "Remove a directory tree"}, + { pcpp::FtpRequestLayer::FtpCommand::RNFR, "Rename from"}, + { pcpp::FtpRequestLayer::FtpCommand::RNTO, "Rename to"}, + { pcpp::FtpRequestLayer::FtpCommand::SITE, "Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE HELP output for complete list of supported commands"}, + { pcpp::FtpRequestLayer::FtpCommand::SIZE, "Return the size of a file"}, + { pcpp::FtpRequestLayer::FtpCommand::SMNT, "Mount file structure"}, + { pcpp::FtpRequestLayer::FtpCommand::SPSV, "Use single port passive mode (only one TCP port number for both control connections and passive-mode data connections)"}, + { pcpp::FtpRequestLayer::FtpCommand::STAT, "Returns information on the server status, including the status of the current connection"}, + { pcpp::FtpRequestLayer::FtpCommand::STOR, "Accept the data and to store the data as a file at the server site"}, + { pcpp::FtpRequestLayer::FtpCommand::STOU, "Store file uniquely"}, + { pcpp::FtpRequestLayer::FtpCommand::STRU, "Set file transfer structure"}, + { pcpp::FtpRequestLayer::FtpCommand::SYST, "Return system type"}, + { pcpp::FtpRequestLayer::FtpCommand::THMB, "Get a thumbnail of a remote image file"}, + { pcpp::FtpRequestLayer::FtpCommand::TYPE, "Sets the transfer mode (ASCII/Binary)"}, + { pcpp::FtpRequestLayer::FtpCommand::USER, "Authentication username"}, + { pcpp::FtpRequestLayer::FtpCommand::XCUP, "Change to the parent of the current working directory"}, + { pcpp::FtpRequestLayer::FtpCommand::XMKD, "Make a directory"}, + { pcpp::FtpRequestLayer::FtpCommand::XPWD, "Print the current working directory"}, + { pcpp::FtpRequestLayer::FtpCommand::XRCP, ""}, + { pcpp::FtpRequestLayer::FtpCommand::XRMD, "Remove the directory"}, + { pcpp::FtpRequestLayer::FtpCommand::XRSQ, ""}, + { pcpp::FtpRequestLayer::FtpCommand::XSEM, "Send, mail if cannot"}, + { pcpp::FtpRequestLayer::FtpCommand::XSEN, "Send to terminal"}, + }; + // clang-format on + + for (const auto& entry : possibleCommandCodes) { PTF_ASSERT_EQUAL(pcpp::FtpRequestLayer::getCommandInfo(entry.first), entry.second); } + // clang-format off // Status codes std::vector> possibleStatusCodes = { - {static_cast(0), "Unknown Status Code"}, - {pcpp::FtpResponseLayer::FtpStatusCode::RESTART_MARKER, "Restart marker reply"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_READY_IN_MIN, "Service ready in nnn minutes"}, - {pcpp::FtpResponseLayer::FtpStatusCode::DATA_ALREADY_OPEN_START_TRANSFER, - "Data connection already open; transfer starting"}, - {pcpp::FtpResponseLayer::FtpStatusCode::FILE_OK, "File status okay; about to open data connection"}, - {pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_OK, "Command okay"}, - {pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED_SUPERFLUOUS, - "Command not implemented, superfluous at this site"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SYSTEM_STATUS, "System status, or system help reply"}, - {pcpp::FtpResponseLayer::FtpStatusCode::DIR_STATUS, "Directory status"}, - {pcpp::FtpResponseLayer::FtpStatusCode::FILE_STATUS, "File status"}, - {pcpp::FtpResponseLayer::FtpStatusCode::HELP_MESSAGE, "Help message"}, - {pcpp::FtpResponseLayer::FtpStatusCode::NAME_SYSTEM_TYPE, "NAME system type"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_READY_FOR_USER, "Service ready for new user"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_CLOSING_CONTROL, "Service closing control connection"}, - {pcpp::FtpResponseLayer::FtpStatusCode::DATA_OPEN_NO_TRANSFER, "Data connection open; no transfer in progress"}, - {pcpp::FtpResponseLayer::FtpStatusCode::CLOSING_DATA, "Closing data connection"}, - {pcpp::FtpResponseLayer::FtpStatusCode::ENTERING_PASSIVE, "Entering Passive Mode"}, - {pcpp::FtpResponseLayer::FtpStatusCode::ENTERING_EXTENDED_PASSIVE, "Entering Extended Passive Mode"}, - {pcpp::FtpResponseLayer::FtpStatusCode::USER_LOG_IN_PROCEED, "User logged in, proceed"}, - {pcpp::FtpResponseLayer::FtpStatusCode::USER_LOG_IN_AUTHORIZED, - "User logged in, authorized by security data exchange"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SEC_DATA_EXCHANGE_COMPLETE, "Security data exchange complete"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SEC_DATA_EXCHANGE_COMPLETE_SUCCESS, - "Security data exchange completed successfully"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQ_FILE_OK_COMPLETE, "Requested file action okay, completed"}, - {pcpp::FtpResponseLayer::FtpStatusCode::PATHNAME_CREATED, "PATHNAME created"}, - {pcpp::FtpResponseLayer::FtpStatusCode::USER_OK_NEED_PASSWORD, "User name okay, need password"}, - {pcpp::FtpResponseLayer::FtpStatusCode::NEED_ACCOUNT, "Need account for login"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQ_SEC_MECHANISM_OK, "Requested security mechanism is ok"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SEC_IS_ACCEPTABLE, "Security data is acceptable, more is required"}, - {pcpp::FtpResponseLayer::FtpStatusCode::USER_OK_NEED_PASS_CHALLENGE, - "Username okay, need password. Challenge is ..."}, - {pcpp::FtpResponseLayer::FtpStatusCode::FILE_PENDING_ACTION, - "Requested file action pending further information"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_NOT_AVAILABLE, - "Service not available, closing control connection"}, - {pcpp::FtpResponseLayer::FtpStatusCode::CANT_OPEN_DATA_CONNECTION, "Can't open data connection"}, - {pcpp::FtpResponseLayer::FtpStatusCode::CONNECTION_CLOSED, "Connection closed; transfer aborted"}, - {pcpp::FtpResponseLayer::FtpStatusCode::NEED_UNAVAILABLE_RESOURCE_TO_SEC, - "Need some unavailable resource to process security"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQ_FILE_ACTION_NOT_TAKEN, "Requested file action not taken"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQ_ACTION_ABORTED, - "Requested action aborted: local error in processing"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQ_ACTION_NOT_TAKEN, - "Requested action not taken. Insufficient storage space in system"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SYNTAX_ERROR_COMMAND_UNRECOGNIZED, - "Syntax error, command unrecognized"}, - {pcpp::FtpResponseLayer::FtpStatusCode::SYNTAX_ERROR_PARAMETER_OR_ARGUMENT, - "Syntax error in parameters or arguments"}, - {pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED, "Command not implemented"}, - {pcpp::FtpResponseLayer::FtpStatusCode::BAD_SEQUENCE_COMMANDS, "Bad sequence of commands"}, - {pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER, - "Command not implemented for that parameter"}, - {pcpp::FtpResponseLayer::FtpStatusCode::NETWORK_PROTOCOL_NOT_SUPPORTED, "Network protocol not supported"}, - {pcpp::FtpResponseLayer::FtpStatusCode::NOT_LOGGED_IN, "Not logged in"}, - {pcpp::FtpResponseLayer::FtpStatusCode::NEED_ACCOUNT_FOR_STORE_FILE, "Need account for storing files"}, - {pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_PROTECTION_DENIED, - "Command protection level denied for policy reasons"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQUEST_DENIED, "Request denied for policy reasons"}, - {pcpp::FtpResponseLayer::FtpStatusCode::FAILED_SEC_CHECK, "Failed security check (hash, sequence, etc)"}, - {pcpp::FtpResponseLayer::FtpStatusCode::REQ_PROT_LEVEL_NOT_SUPPORTED, - "Requested PROT level not supported by mechanism"}, - {pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_PROTECTION_LEVEL_NOT_SUPPORTED, - "Command protection level not supported by security mechanism"}, - {pcpp::FtpResponseLayer::FtpStatusCode::FILE_UNAVAILABLE, "Requested action not taken: File unavailable"}, - {pcpp::FtpResponseLayer::FtpStatusCode::PAGE_TYPE_UNKNOWN, "Requested action aborted: page type unknown"}, - {pcpp::FtpResponseLayer::FtpStatusCode::EXCEED_STORAGE_ALLOCATION, - "Requested file action aborted: Exceeded storage allocation"}, - {pcpp::FtpResponseLayer::FtpStatusCode::FILENAME_NOT_ALLOWED, - "Requested action not taken: File name not allowed"}, - {pcpp::FtpResponseLayer::FtpStatusCode::INTEGRITY_PROTECTED, "Integrity protected reply"}, - {pcpp::FtpResponseLayer::FtpStatusCode::CONFIDENTIALITY_AND_INTEGRITY_PROTECTED, - "Confidentiality and integrity protected reply"}, - {pcpp::FtpResponseLayer::FtpStatusCode::CONFIDENTIALITY_PROTECTED, "Confidentiality protected reply"}}; - - for (const auto &entry : possibleStatusCodes) + { static_cast(0), "Unknown Status Code" }, + { pcpp::FtpResponseLayer::FtpStatusCode::RESTART_MARKER, "Restart marker reply" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_READY_IN_MIN, "Service ready in nnn minutes" }, + { pcpp::FtpResponseLayer::FtpStatusCode::DATA_ALREADY_OPEN_START_TRANSFER, "Data connection already open; transfer starting" }, + { pcpp::FtpResponseLayer::FtpStatusCode::FILE_OK, "File status okay; about to open data connection" }, + { pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_OK, "Command okay" }, + { pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED_SUPERFLUOUS, "Command not implemented, superfluous at this site" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SYSTEM_STATUS, "System status, or system help reply" }, + { pcpp::FtpResponseLayer::FtpStatusCode::DIR_STATUS, "Directory status" }, + { pcpp::FtpResponseLayer::FtpStatusCode::FILE_STATUS, "File status" }, + { pcpp::FtpResponseLayer::FtpStatusCode::HELP_MESSAGE, "Help message" }, + { pcpp::FtpResponseLayer::FtpStatusCode::NAME_SYSTEM_TYPE, "NAME system type" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_READY_FOR_USER, "Service ready for new user" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_CLOSING_CONTROL, "Service closing control connection" }, + { pcpp::FtpResponseLayer::FtpStatusCode::DATA_OPEN_NO_TRANSFER, "Data connection open; no transfer in progress" }, + { pcpp::FtpResponseLayer::FtpStatusCode::CLOSING_DATA, "Closing data connection" }, + { pcpp::FtpResponseLayer::FtpStatusCode::ENTERING_PASSIVE, "Entering Passive Mode" }, + { pcpp::FtpResponseLayer::FtpStatusCode::ENTERING_EXTENDED_PASSIVE, "Entering Extended Passive Mode" }, + { pcpp::FtpResponseLayer::FtpStatusCode::USER_LOG_IN_PROCEED, "User logged in, proceed" }, + { pcpp::FtpResponseLayer::FtpStatusCode::USER_LOG_IN_AUTHORIZED, "User logged in, authorized by security data exchange" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SEC_DATA_EXCHANGE_COMPLETE, "Security data exchange complete" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SEC_DATA_EXCHANGE_COMPLETE_SUCCESS, "Security data exchange completed successfully" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQ_FILE_OK_COMPLETE, "Requested file action okay, completed" }, + { pcpp::FtpResponseLayer::FtpStatusCode::PATHNAME_CREATED, "PATHNAME created" }, + { pcpp::FtpResponseLayer::FtpStatusCode::USER_OK_NEED_PASSWORD, "User name okay, need password" }, + { pcpp::FtpResponseLayer::FtpStatusCode::NEED_ACCOUNT, "Need account for login" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQ_SEC_MECHANISM_OK, "Requested security mechanism is ok" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SEC_IS_ACCEPTABLE, "Security data is acceptable, more is required" }, + { pcpp::FtpResponseLayer::FtpStatusCode::USER_OK_NEED_PASS_CHALLENGE, "Username okay, need password. Challenge is ..." }, + { pcpp::FtpResponseLayer::FtpStatusCode::FILE_PENDING_ACTION, "Requested file action pending further information" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SERVICE_NOT_AVAILABLE, "Service not available, closing control connection" }, + { pcpp::FtpResponseLayer::FtpStatusCode::CANT_OPEN_DATA_CONNECTION, "Can't open data connection" }, + { pcpp::FtpResponseLayer::FtpStatusCode::CONNECTION_CLOSED, "Connection closed; transfer aborted" }, + { pcpp::FtpResponseLayer::FtpStatusCode::NEED_UNAVAILABLE_RESOURCE_TO_SEC, "Need some unavailable resource to process security" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQ_FILE_ACTION_NOT_TAKEN, "Requested file action not taken" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQ_ACTION_ABORTED, "Requested action aborted: local error in processing" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQ_ACTION_NOT_TAKEN, "Requested action not taken. Insufficient storage space in system" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SYNTAX_ERROR_COMMAND_UNRECOGNIZED, "Syntax error, command unrecognized" }, + { pcpp::FtpResponseLayer::FtpStatusCode::SYNTAX_ERROR_PARAMETER_OR_ARGUMENT, "Syntax error in parameters or arguments" }, + { pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED, "Command not implemented" }, + { pcpp::FtpResponseLayer::FtpStatusCode::BAD_SEQUENCE_COMMANDS, "Bad sequence of commands" }, + { pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_NOT_IMPLEMENTED_FOR_PARAMETER, "Command not implemented for that parameter" }, + { pcpp::FtpResponseLayer::FtpStatusCode::NETWORK_PROTOCOL_NOT_SUPPORTED, "Network protocol not supported" }, + { pcpp::FtpResponseLayer::FtpStatusCode::NOT_LOGGED_IN, "Not logged in" }, + { pcpp::FtpResponseLayer::FtpStatusCode::NEED_ACCOUNT_FOR_STORE_FILE, "Need account for storing files" }, + { pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_PROTECTION_DENIED, "Command protection level denied for policy reasons" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQUEST_DENIED, "Request denied for policy reasons" }, + { pcpp::FtpResponseLayer::FtpStatusCode::FAILED_SEC_CHECK, "Failed security check (hash, sequence, etc)" }, + { pcpp::FtpResponseLayer::FtpStatusCode::REQ_PROT_LEVEL_NOT_SUPPORTED, "Requested PROT level not supported by mechanism" }, + { pcpp::FtpResponseLayer::FtpStatusCode::COMMAND_PROTECTION_LEVEL_NOT_SUPPORTED, "Command protection level not supported by security mechanism" }, + { pcpp::FtpResponseLayer::FtpStatusCode::FILE_UNAVAILABLE, "Requested action not taken: File unavailable" }, + { pcpp::FtpResponseLayer::FtpStatusCode::PAGE_TYPE_UNKNOWN, "Requested action aborted: page type unknown" }, + { pcpp::FtpResponseLayer::FtpStatusCode::EXCEED_STORAGE_ALLOCATION, "Requested file action aborted: Exceeded storage allocation" }, + { pcpp::FtpResponseLayer::FtpStatusCode::FILENAME_NOT_ALLOWED, "Requested action not taken: File name not allowed" }, + { pcpp::FtpResponseLayer::FtpStatusCode::INTEGRITY_PROTECTED, "Integrity protected reply" }, + { pcpp::FtpResponseLayer::FtpStatusCode::CONFIDENTIALITY_AND_INTEGRITY_PROTECTED, "Confidentiality and integrity protected reply" }, + { pcpp::FtpResponseLayer::FtpStatusCode::CONFIDENTIALITY_PROTECTED, "Confidentiality protected reply" } + }; + // clang-format off + + + for (const auto& entry : possibleStatusCodes) { PTF_ASSERT_EQUAL(pcpp::FtpResponseLayer::getStatusCodeAsString(entry.first), entry.second); } @@ -297,8 +274,8 @@ PTF_TEST_CASE(FtpCreationTests) pcpp::TcpLayer tcpLayer2(*ftpPacket2.getLayerOfType()); pcpp::FtpResponseLayer ftpRespLayer1( - pcpp::FtpResponseLayer::FtpStatusCode::SYSTEM_STATUS, - "Extensions supported:\r\n CLNT\r\n MDTM\r\n PASV\r\n REST STREAM\r\n SIZE\r\n211 End."); + pcpp::FtpResponseLayer::FtpStatusCode::SYSTEM_STATUS, + "Extensions supported:\r\n CLNT\r\n MDTM\r\n PASV\r\n REST STREAM\r\n SIZE\r\n211 End."); pcpp::Packet craftedPacket2; PTF_ASSERT_TRUE(craftedPacket2.addLayer(ðLayer2)); @@ -318,12 +295,12 @@ PTF_TEST_CASE(FtpEditTests) // Modify existing request packets READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ftpIpv4Req.dat"); pcpp::Packet ftpPacket1(&rawPacket1); - pcpp::FtpRequestLayer *ftpLayer1 = ftpPacket1.getLayerOfType(); + pcpp::FtpRequestLayer* ftpLayer1 = ftpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer1); READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/ftpReqEdited1.dat"); pcpp::Packet ftpReqEdited1(&rawPacket2); - pcpp::FtpRequestLayer *ftpReqEditedLayer1 = ftpReqEdited1.getLayerOfType(); + pcpp::FtpRequestLayer* ftpReqEditedLayer1 = ftpReqEdited1.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpReqEditedLayer1); ftpLayer1->setCommand(pcpp::FtpRequestLayer::FtpCommand::FEAT); @@ -332,7 +309,7 @@ PTF_TEST_CASE(FtpEditTests) READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/ftpReqEdited2.dat"); pcpp::Packet ftpReqEdited2(&rawPacket3); - pcpp::FtpRequestLayer *ftpReqEditedLayer2 = ftpReqEdited2.getLayerOfType(); + pcpp::FtpRequestLayer* ftpReqEditedLayer2 = ftpReqEdited2.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpReqEditedLayer2); ftpLayer1->setCommandOption("Test option"); @@ -342,12 +319,12 @@ PTF_TEST_CASE(FtpEditTests) // Modify existing response packets READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/ftpIpv4Resp.dat"); pcpp::Packet ftpPacket2(&rawPacket4); - pcpp::FtpResponseLayer *ftpLayer2 = ftpPacket2.getLayerOfType(); + pcpp::FtpResponseLayer* ftpLayer2 = ftpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpLayer2); READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/ftpRespEdited1.dat"); pcpp::Packet ftpRespEdited1(&rawPacket5); - pcpp::FtpResponseLayer *ftpRespEditedLayer1 = ftpRespEdited1.getLayerOfType(); + pcpp::FtpResponseLayer* ftpRespEditedLayer1 = ftpRespEdited1.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpRespEditedLayer1); ftpLayer2->setStatusCode(pcpp::FtpResponseLayer::FtpStatusCode::CLOSING_DATA); @@ -356,7 +333,7 @@ PTF_TEST_CASE(FtpEditTests) READ_FILE_AND_CREATE_PACKET(6, "PacketExamples/ftpRespEdited2.dat"); pcpp::Packet ftpRespEdited2(&rawPacket6); - pcpp::FtpResponseLayer *ftpRespEditedLayer2 = ftpRespEdited2.getLayerOfType(); + pcpp::FtpResponseLayer* ftpRespEditedLayer2 = ftpRespEdited2.getLayerOfType(); PTF_ASSERT_NOT_NULL(ftpRespEditedLayer2); ftpLayer2->setStatusOption("Test option"); diff --git a/Tests/Packet++Test/Tests/GreTests.cpp b/Tests/Packet++Test/Tests/GreTests.cpp index e359fe74ea..9c587f38c8 100644 --- a/Tests/Packet++Test/Tests/GreTests.cpp +++ b/Tests/Packet++Test/Tests/GreTests.cpp @@ -12,7 +12,6 @@ #include "Packet.h" #include "SystemUtils.h" - PTF_TEST_CASE(GreParsingTest) { timeval time; @@ -155,9 +154,7 @@ PTF_TEST_CASE(GreParsingTest) PTF_ASSERT_EQUAL(tcpLayer->getSrcPort(), 1232); grev0Layer = nullptr; tcpLayer = nullptr; -} // GreParsingTest - - +} // GreParsingTest PTF_TEST_CASE(GreCreationTest) { @@ -194,7 +191,6 @@ PTF_TEST_CASE(GreCreationTest) PTF_ASSERT_EQUAL(grev1Packet.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(grev1Packet.getRawPacket()->getRawData(), buffer1, bufferLength1); - // GREv0 packet creation pcpp::EthLayer ethLayer2(pcpp::MacAddress("00:01:01:00:00:01"), pcpp::MacAddress("00:01:01:00:00:02")); @@ -218,15 +214,12 @@ PTF_TEST_CASE(GreCreationTest) PTF_ASSERT_TRUE(grev0Packet.addLayer(&grev0Layer2)); grev0Packet.computeCalculateFields(); - PTF_ASSERT_EQUAL(grev0Packet.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(grev0Packet.getRawPacket()->getRawData(), buffer2, bufferLength2); - delete [] buffer1; - delete [] buffer2; -} // GreCreationTest - - + delete[] buffer1; + delete[] buffer2; +} // GreCreationTest PTF_TEST_CASE(GreEditTest) { @@ -246,7 +239,6 @@ PTF_TEST_CASE(GreEditTest) PTF_ASSERT_TRUE(grev0Layer->setKey(2341)); grev0Packet.computeCalculateFields(); - uint16_t value16 = 0; uint32_t value32 = 0; grev0Layer = grev0Packet.getLayerOfType(); @@ -328,7 +320,6 @@ PTF_TEST_CASE(GreEditTest) PTF_ASSERT_TRUE(grev0Layer->getChecksum(value16)); PTF_ASSERT_EQUAL(value16, 30719); - // GREv1 packet edit READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/GREv1_2.dat"); @@ -399,11 +390,12 @@ PTF_TEST_CASE(GreEditTest) PTF_ASSERT_EQUAL(pppLayer->getPPP_PPTPHeader()->protocol, 0); - auto ipv6Layer = new pcpp::IPv6Layer(pcpp::IPv6Address("2402:f000:1:8e01::5555"), pcpp::IPv6Address("2607:fcd0:100:2300::b108:2a6b")); + auto ipv6Layer = new pcpp::IPv6Layer(pcpp::IPv6Address("2402:f000:1:8e01::5555"), + pcpp::IPv6Address("2607:fcd0:100:2300::b108:2a6b")); PTF_ASSERT_TRUE(grev1Packet.addLayer(ipv6Layer, true)); grev1Packet.computeCalculateFields(); PTF_ASSERT_NOT_NULL(pppLayer->getNextLayer()); PTF_ASSERT_EQUAL(pppLayer->getNextLayer()->getProtocol(), pcpp::IPv6, enum); PTF_ASSERT_EQUAL(pppLayer->getPPP_PPTPHeader()->protocol, htobe16(PCPP_PPP_IPV6)); -} // GreEditTest +} // GreEditTest diff --git a/Tests/Packet++Test/Tests/GtpTests.cpp b/Tests/Packet++Test/Tests/GtpTests.cpp index e5cf2352d0..b167cd4bda 100644 --- a/Tests/Packet++Test/Tests/GtpTests.cpp +++ b/Tests/Packet++Test/Tests/GtpTests.cpp @@ -10,7 +10,6 @@ #include "IcmpLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(GtpLayerParsingTest) { timeval time; @@ -26,7 +25,6 @@ PTF_TEST_CASE(GtpLayerParsingTest) pcpp::Packet gtpPacket3(&rawPacket3); pcpp::Packet gtpPacket4(&rawPacket4); - // GTP-U packet 1 PTF_ASSERT_TRUE(gtpPacket1.isPacketOfType(pcpp::GTPv1)); PTF_ASSERT_TRUE(gtpPacket1.isPacketOfType(pcpp::GTP)); @@ -65,8 +63,6 @@ PTF_TEST_CASE(GtpLayerParsingTest) PTF_ASSERT_FALSE(gtpLayer->isGTPCMessage()); PTF_ASSERT_TRUE(gtpLayer->isGTPUMessage()); - - // GTP-U packet 2 (with GTP header extension) gtpLayer = gtpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(gtpLayer); @@ -108,8 +104,6 @@ PTF_TEST_CASE(GtpLayerParsingTest) PTF_ASSERT_FALSE(gtpLayer->isGTPCMessage()); PTF_ASSERT_TRUE(gtpLayer->isGTPUMessage()); - - // GTP-U IPv6 packet gtpLayer = gtpPacket4.getLayerOfType(); PTF_ASSERT_NOT_NULL(gtpLayer); @@ -137,8 +131,6 @@ PTF_TEST_CASE(GtpLayerParsingTest) PTF_ASSERT_FALSE(gtpLayer->isGTPCMessage()); PTF_ASSERT_TRUE(gtpLayer->isGTPUMessage()); - - // GTP-C packet PTF_ASSERT_TRUE(gtpPacket3.isPacketOfType(pcpp::GTP)); PTF_ASSERT_TRUE(gtpPacket3.isPacketOfType(pcpp::GTPv1)); @@ -167,9 +159,7 @@ PTF_TEST_CASE(GtpLayerParsingTest) PTF_ASSERT_TRUE(gtpLayer->isGTPCMessage()); PTF_ASSERT_FALSE(gtpLayer->isGTPUMessage()); -} // GtpLayerParsingTest - - +} // GtpLayerParsingTest PTF_TEST_CASE(GtpLayerCreationTest) { @@ -186,7 +176,8 @@ PTF_TEST_CASE(GtpLayerCreationTest) pcpp::IPv4Layer ip4Layer(*gtpPacket1.getLayerOfType()); pcpp::UdpLayer udpLayer(*gtpPacket1.getLayerOfType()); pcpp::GtpV1Layer gtpLayer(pcpp::GtpV1_GPDU, 1, true, 10461, false, 0); - pcpp::IPv4Layer ip4Layer2(*gtpPacket1.getNextLayerOfType(gtpPacket1.getLayerOfType())); + pcpp::IPv4Layer ip4Layer2( + *gtpPacket1.getNextLayerOfType(gtpPacket1.getLayerOfType())); pcpp::IcmpLayer icmpLayer(*gtpPacket1.getLayerOfType()); pcpp::Packet newGtpPacket; @@ -199,15 +190,16 @@ PTF_TEST_CASE(GtpLayerCreationTest) newGtpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(bufferLength1, newGtpPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(newGtpPacket.getRawPacket()->getRawData(), buffer1, newGtpPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(newGtpPacket.getRawPacket()->getRawData(), buffer1, + newGtpPacket.getRawPacket()->getRawDataLen()); pcpp::GtpV1Layer* newGtpLayer = newGtpPacket.getLayerOfType(); pcpp::GtpV1Layer::GtpExtension newExt1 = newGtpLayer->addExtension(0xc0, 2308); PTF_ASSERT_FALSE(newExt1.isNull()); PTF_ASSERT_EQUAL(newExt1.getExtensionType(), 0xc0); - PTF_ASSERT_EQUAL(newExt1.getTotalLength(), 4*sizeof(uint8_t)); - PTF_ASSERT_EQUAL(newExt1.getContentLength(), 2*sizeof(uint8_t)); + PTF_ASSERT_EQUAL(newExt1.getTotalLength(), 4 * sizeof(uint8_t)); + PTF_ASSERT_EQUAL(newExt1.getContentLength(), 2 * sizeof(uint8_t)); uint16_t* content = reinterpret_cast(newExt1.getContent()); PTF_ASSERT_EQUAL(be16toh(content[0]), 2308); PTF_ASSERT_TRUE(newExt1.getNextExtension().isNull()); @@ -215,13 +207,14 @@ PTF_TEST_CASE(GtpLayerCreationTest) newGtpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(bufferLength2, newGtpPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(newGtpPacket.getRawPacket()->getRawData(), buffer2, newGtpPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(newGtpPacket.getRawPacket()->getRawData(), buffer2, + newGtpPacket.getRawPacket()->getRawDataLen()); pcpp::GtpV1Layer::GtpExtension newExt2 = newGtpLayer->addExtension(0x40, 1308); PTF_ASSERT_FALSE(newExt2.isNull()); PTF_ASSERT_EQUAL(newExt2.getExtensionType(), 0x40); - PTF_ASSERT_EQUAL(newExt2.getTotalLength(), 4*sizeof(uint8_t)); - PTF_ASSERT_EQUAL(newExt2.getContentLength(), 2*sizeof(uint8_t)); + PTF_ASSERT_EQUAL(newExt2.getTotalLength(), 4 * sizeof(uint8_t)); + PTF_ASSERT_EQUAL(newExt2.getContentLength(), 2 * sizeof(uint8_t)); content = reinterpret_cast(newExt2.getContent()); PTF_ASSERT_EQUAL(be16toh(content[0]), 1308); PTF_ASSERT_TRUE(newExt2.getNextExtension().isNull()); @@ -233,10 +226,9 @@ PTF_TEST_CASE(GtpLayerCreationTest) PTF_ASSERT_EQUAL(newGtpLayer->getNextExtension().getNextExtensionHeaderType(), 0x40); PTF_ASSERT_EQUAL(bufferLength3, newGtpPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(newGtpPacket.getRawPacket()->getRawData(), buffer3, newGtpPacket.getRawPacket()->getRawDataLen()); -} // GtpLayerCreationTest - - + PTF_ASSERT_BUF_COMPARE(newGtpPacket.getRawPacket()->getRawData(), buffer3, + newGtpPacket.getRawPacket()->getRawDataLen()); +} // GtpLayerCreationTest PTF_TEST_CASE(GtpLayerEditTest) { @@ -285,7 +277,8 @@ PTF_TEST_CASE(GtpLayerEditTest) gtpPacket1.computeCalculateFields(); PTF_ASSERT_EQUAL(bufferLength2, gtpPacket1.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(gtpPacket1.getRawPacket()->getRawData(), buffer2, gtpPacket1.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(gtpPacket1.getRawPacket()->getRawData(), buffer2, + gtpPacket1.getRawPacket()->getRawDataLen()); - delete [] buffer2; -} // GtpLayerEditTest + delete[] buffer2; +} // GtpLayerEditTest diff --git a/Tests/Packet++Test/Tests/HttpTests.cpp b/Tests/Packet++Test/Tests/HttpTests.cpp index 63897c410d..6fab318743 100644 --- a/Tests/Packet++Test/Tests/HttpTests.cpp +++ b/Tests/Packet++Test/Tests/HttpTests.cpp @@ -12,33 +12,36 @@ #include PTF_TEST_CASE(HttpRequestParseMethodTest) { - PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(nullptr, 0), pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(std::string("GET").c_str(), 3), pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(nullptr, 0), + pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(std::string("GET").c_str(), 3), + pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(std::string("OPTIONS").c_str(), 7), pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(std::string("OPTIONS").c_str(), 7), + pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); std::vector> possibleMethods = { - {"GET", pcpp::HttpRequestLayer::HttpMethod::HttpGET }, - {"HEAD", pcpp::HttpRequestLayer::HttpMethod::HttpHEAD }, - {"POST", pcpp::HttpRequestLayer::HttpMethod::HttpPOST }, - {"PUT", pcpp::HttpRequestLayer::HttpMethod::HttpPUT }, - {"DELETE", pcpp::HttpRequestLayer::HttpMethod::HttpDELETE }, - {"TRACE", pcpp::HttpRequestLayer::HttpMethod::HttpTRACE }, - {"OPTIONS", pcpp::HttpRequestLayer::HttpMethod::HttpOPTIONS }, - {"CONNECT", pcpp::HttpRequestLayer::HttpMethod::HttpCONNECT }, - {"PATCH", pcpp::HttpRequestLayer::HttpMethod::HttpPATCH } + { "GET", pcpp::HttpRequestLayer::HttpMethod::HttpGET }, + { "HEAD", pcpp::HttpRequestLayer::HttpMethod::HttpHEAD }, + { "POST", pcpp::HttpRequestLayer::HttpMethod::HttpPOST }, + { "PUT", pcpp::HttpRequestLayer::HttpMethod::HttpPUT }, + { "DELETE", pcpp::HttpRequestLayer::HttpMethod::HttpDELETE }, + { "TRACE", pcpp::HttpRequestLayer::HttpMethod::HttpTRACE }, + { "OPTIONS", pcpp::HttpRequestLayer::HttpMethod::HttpOPTIONS }, + { "CONNECT", pcpp::HttpRequestLayer::HttpMethod::HttpCONNECT }, + { "PATCH", pcpp::HttpRequestLayer::HttpMethod::HttpPATCH } }; - for (const std::pair &method : possibleMethods ) + for (const std::pair& method : possibleMethods) { std::string firstLine = method.first + " "; - PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(firstLine.c_str(), firstLine.length()), method.second, enum); + PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(firstLine.c_str(), firstLine.length()), method.second, + enum); } - PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(std::string("UNKNOWN ").c_str(), 8), pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); -} // HttpRequestParseMethodTest - - + PTF_ASSERT_EQUAL(pcpp::HttpRequestFirstLine::parseMethod(std::string("UNKNOWN ").c_str(), 8), + pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown, enum); +} // HttpRequestParseMethodTest PTF_TEST_CASE(HttpRequestLayerParsingTest) { @@ -67,7 +70,6 @@ PTF_TEST_CASE(HttpRequestLayerParsingTest) PTF_ASSERT_EQUAL(requestLayer->getUrl(), "www.ynet.co.il/home/0,7340,L-8,00.html"); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/PartialHttpRequest.dat"); pcpp::Packet httpPacket2(&rawPacket2); @@ -92,9 +94,7 @@ PTF_TEST_CASE(HttpRequestLayerParsingTest) PTF_ASSERT_EQUAL(requestLayer->getFieldCount(), 8); PTF_ASSERT_FALSE(requestLayer->isHeaderComplete()); -} // HttpRequestLayerParsingTest - - +} // HttpRequestLayerParsingTest PTF_TEST_CASE(HttpRequestLayerCreationTest) { @@ -111,12 +111,15 @@ PTF_TEST_CASE(HttpRequestLayerCreationTest) pcpp::TcpLayer tcpLayer = *(sampleHttpPacket.getLayerOfType()); pcpp::HttpRequestLayer httpLayer(pcpp::HttpRequestLayer::HttpOPTIONS, "/home/0,7340,L-8,00", pcpp::OneDotOne); - PTF_ASSERT_NOT_NULL(httpLayer.addField(PCPP_HTTP_ACCEPT_FIELD, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")); + PTF_ASSERT_NOT_NULL(httpLayer.addField( + PCPP_HTTP_ACCEPT_FIELD, "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")); PTF_ASSERT_NOT_NULL(httpLayer.addField("Dummy-Field", "some value")); pcpp::HeaderField* hostField = httpLayer.insertField(nullptr, PCPP_HTTP_HOST_FIELD, "www.ynet-ynet.co.il"); PTF_ASSERT_NOT_NULL(hostField); PTF_ASSERT_NOT_NULL(httpLayer.insertField(hostField, PCPP_HTTP_CONNECTION_FIELD, "keep-alive")); - pcpp::HeaderField* userAgentField = httpLayer.addField(PCPP_HTTP_USER_AGENT_FIELD, "(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"); + pcpp::HeaderField* userAgentField = httpLayer.addField( + PCPP_HTTP_USER_AGENT_FIELD, + "(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"); httpLayer.getFirstLine()->setUri("bla.php"); PTF_ASSERT_NOT_NULL(userAgentField); PTF_ASSERT_NOT_NULL(httpLayer.addField(PCPP_HTTP_ACCEPT_LANGUAGE_FIELD, "en-US,en;q=0.8")); @@ -145,16 +148,15 @@ PTF_TEST_CASE(HttpRequestLayerCreationTest) PTF_ASSERT_EQUAL(httpLayer.getFirstLine()->getVersion(), pcpp::OneDotOne, enum); httpLayer.getFirstLine()->setUri("/home/0,7340,L-8,00.html"); PTF_ASSERT_TRUE(httpLayer.removeField("Dummy-Field2")); - userAgentField->setFieldValue("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"); + userAgentField->setFieldValue( + "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36"); httpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(bufferLength1, httpPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_BUF_COMPARE(buffer1, httpPacket.getRawPacket()->getRawData(), bufferLength1); -} // HttpRequestLayerCreationTest - - +} // HttpRequestLayerCreationTest PTF_TEST_CASE(HttpRequestLayerEditTest) { @@ -175,7 +177,8 @@ PTF_TEST_CASE(HttpRequestLayerEditTest) tcpLayer->getTcpHeader()->windowSize = htobe16(16660); pcpp::HttpRequestLayer* httpReqLayer = httpRequest.getLayerOfType(); - PTF_ASSERT_TRUE(httpReqLayer->getFirstLine()->setUri("/Common/Api/Video/CmmLightboxPlayerJs/0,14153,061014181713,00.js")); + PTF_ASSERT_TRUE( + httpReqLayer->getFirstLine()->setUri("/Common/Api/Video/CmmLightboxPlayerJs/0,14153,061014181713,00.js")); pcpp::HeaderField* acceptField = httpReqLayer->getFieldByName(PCPP_HTTP_ACCEPT_FIELD); PTF_ASSERT_NOT_NULL(acceptField); acceptField->setFieldValue("*/*"); @@ -191,16 +194,16 @@ PTF_TEST_CASE(HttpRequestLayerEditTest) PTF_ASSERT_BUF_COMPARE(buffer2, httpRequest.getRawPacket()->getRawData(), bufferLength2); - delete [] buffer2; - -} // HttpRequestLayerEditTest - + delete[] buffer2; +} // HttpRequestLayerEditTest PTF_TEST_CASE(HttpResponseParseStatusCodeTest) { - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(nullptr, 0), pcpp::HttpResponseLayer::HttpResponseStatusCode::HttpStatusCodeUnknown); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("abc").c_str(), 3), pcpp::HttpResponseLayer::HttpResponseStatusCode::HttpStatusCodeUnknown); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(nullptr, 0), + pcpp::HttpResponseLayer::HttpResponseStatusCode::HttpStatusCodeUnknown); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("abc").c_str(), 3), + pcpp::HttpResponseLayer::HttpResponseStatusCode::HttpStatusCodeUnknown); std::vector possibleStatusCodes = { pcpp::HttpResponseStatusCode::Http100Continue, @@ -288,71 +291,98 @@ PTF_TEST_CASE(HttpResponseParseStatusCodeTest) pcpp::HttpResponseStatusCode::Http599NetworkConnectTimeoutError, }; - for (const auto &statusCode : possibleStatusCodes ) + for (const auto& statusCode : possibleStatusCodes) { std::string firstLine = "HTTP/x.y " + statusCode.toString() + " " + statusCode.getMessage() + "\n"; - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(firstLine.c_str(), firstLine.length()), statusCode, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(firstLine.c_str(), firstLine.length()), + statusCode, enum); } - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 001 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 199 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatus1xxCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 299 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatus2xxCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 399 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatus3xxCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 477 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatus4xxCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 577 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatus5xxCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 600 any message\n").c_str(), 26), pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown, enum); - + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 001 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown, enum); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 199 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatus1xxCodeUnknown, enum); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 299 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatus2xxCodeUnknown, enum); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 399 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatus3xxCodeUnknown, enum); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 477 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatus4xxCodeUnknown, enum); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 577 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatus5xxCodeUnknown, enum); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 600 any message\n").c_str(), 26), + pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown, enum); // test getMessage() - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 200 OK\n").c_str(), 17).getMessage(), "OK"); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 404 Not Found\n").c_str(), 24).getMessage(), "Not Found"); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 200 OK\n").c_str(), 17).getMessage(), "OK"); + PTF_ASSERT_EQUAL( + pcpp::HttpResponseFirstLine::parseStatusCode(std::string("HTTP/x.y 404 Not Found\n").c_str(), 24).getMessage(), + "Not Found"); std::string testLine; testLine = "HTTP/x.y 404 My Not Found\r\n"; - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()).getMessage(), "My Not Found"); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()).getMessage(), + "My Not Found"); testLine = "HTTP/x.y 404 My Not Found 2\n"; - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()).getMessage(), "My Not Found 2"); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()).getMessage(), + "My Not Found 2"); testLine = "HTTP/x.y 404 Unfinished Line Here"; - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()), pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown); - - testLine = "HTTP/x.y 404\n"; // no status message - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()), pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown); - - testLine = "HTTP/x.y 404 \n"; // no status message - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()), pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown); -} // HttpResponseParseStatusCodeTest + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()), + pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown); + testLine = "HTTP/x.y 404\n"; // no status message + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()), + pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown); + testLine = "HTTP/x.y 404 \n"; // no status message + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseStatusCode(testLine.c_str(), testLine.size()), + pcpp::HttpResponseStatusCode::HttpStatusCodeUnknown); +} // HttpResponseParseStatusCodeTest PTF_TEST_CASE(HttpResponseParseVersionTest) { - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(nullptr, 0), pcpp::HttpVersion::HttpVersionUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("1.1").c_str(), 3), pcpp::HttpVersion::HttpVersionUnknown, enum); - - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("XTTP/1.1").c_str(), 8), pcpp::HttpVersion::HttpVersionUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HXTP/1.1").c_str(), 8), pcpp::HttpVersion::HttpVersionUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTXP/1.1").c_str(), 8), pcpp::HttpVersion::HttpVersionUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTTX/1.1").c_str(), 8), pcpp::HttpVersion::HttpVersionUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTTP 1.1").c_str(), 8), pcpp::HttpVersion::HttpVersionUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(nullptr, 0), pcpp::HttpVersion::HttpVersionUnknown, + enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("1.1").c_str(), 3), + pcpp::HttpVersion::HttpVersionUnknown, enum); + + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("XTTP/1.1").c_str(), 8), + pcpp::HttpVersion::HttpVersionUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HXTP/1.1").c_str(), 8), + pcpp::HttpVersion::HttpVersionUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTXP/1.1").c_str(), 8), + pcpp::HttpVersion::HttpVersionUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTTX/1.1").c_str(), 8), + pcpp::HttpVersion::HttpVersionUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTTP 1.1").c_str(), 8), + pcpp::HttpVersion::HttpVersionUnknown, enum); std::vector> possibleVersions = { { "0.9", pcpp::HttpVersion::ZeroDotNine }, - { "1.0", pcpp::HttpVersion::OneDotZero }, - { "1.1", pcpp::HttpVersion::OneDotOne } + { "1.0", pcpp::HttpVersion::OneDotZero }, + { "1.1", pcpp::HttpVersion::OneDotOne } }; - for (const std::pair &version : possibleVersions ) + for (const std::pair& version : possibleVersions) { std::string firstLine = "HTTP/" + version.first; - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(firstLine.c_str(), firstLine.length()), version.second, enum); + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(firstLine.c_str(), firstLine.length()), + version.second, enum); } - PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTTP/2.0 ").c_str(), 8), pcpp::HttpVersion::HttpVersionUnknown, enum); -} // HttpResponseParseVersionTest - - + PTF_ASSERT_EQUAL(pcpp::HttpResponseFirstLine::parseVersion(std::string("HTTP/2.0 ").c_str(), 8), + pcpp::HttpVersion::HttpVersionUnknown, enum); +} // HttpResponseParseVersionTest PTF_TEST_CASE(HttpResponseLayerParsingTest) { @@ -382,9 +412,7 @@ PTF_TEST_CASE(HttpResponseLayerParsingTest) pcpp::HeaderField* contentTypeField = responseLayer->getFieldByName(PCPP_HTTP_CONTENT_TYPE_FIELD); PTF_ASSERT_NOT_NULL(contentTypeField); PTF_ASSERT_EQUAL(contentTypeField->getFieldValue(), "application/x-javascript"); -} // HttpResponseLayerParsingTest - - +} // HttpResponseLayerParsingTest PTF_TEST_CASE(HttpResponseLayerCreationTest) { @@ -405,11 +433,15 @@ PTF_TEST_CASE(HttpResponseLayerCreationTest) PTF_ASSERT_NULL(httpResponse.addField(PCPP_HTTP_SERVER_FIELD, "Microsoft-IIS/6.0")); pcpp::Logger::getInstance().enableLogs(); PTF_ASSERT_NOT_NULL(httpResponse.addField(PCPP_HTTP_CONTENT_ENCODING_FIELD, "gzip")); - PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName(PCPP_HTTP_SERVER_FIELD), PCPP_HTTP_CONTENT_TYPE_FIELD, "application/x-javascript")); - PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName(PCPP_HTTP_CONTENT_TYPE_FIELD), "Accept-Ranges", "bytes")); + PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName(PCPP_HTTP_SERVER_FIELD), + PCPP_HTTP_CONTENT_TYPE_FIELD, "application/x-javascript")); + PTF_ASSERT_NOT_NULL( + httpResponse.insertField(httpResponse.getFieldByName(PCPP_HTTP_CONTENT_TYPE_FIELD), "Accept-Ranges", "bytes")); PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("Accept-Ranges"), "KuKu", "BlaBla")); - PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("kuku"), "Last-Modified", "Wed, 19 Dec 2012 14:06:29 GMT")); - PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("last-Modified"), "ETag", "\"3b846daf2ddcd1:e29\"")); + PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("kuku"), "Last-Modified", + "Wed, 19 Dec 2012 14:06:29 GMT")); + PTF_ASSERT_NOT_NULL( + httpResponse.insertField(httpResponse.getFieldByName("last-Modified"), "ETag", "\"3b846daf2ddcd1:e29\"")); PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("etag"), "Vary", "Accept-Encoding")); PTF_ASSERT_NOT_NULL(httpResponse.setContentLength(1616, PCPP_HTTP_CONTENT_ENCODING_FIELD)); PTF_ASSERT_NOT_NULL(httpResponse.addField("Kuku2", "blibli2")); @@ -427,26 +459,27 @@ PTF_TEST_CASE(HttpResponseLayerCreationTest) PTF_ASSERT_NOT_NULL(httpResponse.addField(PCPP_HTTP_CONNECTION_FIELD, "keep-alive")); PTF_ASSERT_NOT_NULL(httpResponse.addEndOfHeader()); - PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("Cache-Control"), "Expires", "Mon, 20 Oct 2014 13:34:26 GMT")); + PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("Cache-Control"), "Expires", + "Mon, 20 Oct 2014 13:34:26 GMT")); pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_NULL(httpResponse.addField("kuku3", "kuka")); pcpp::Logger::getInstance().enableLogs(); - PTF_ASSERT_NOT_NULL(httpResponse.insertField(httpResponse.getFieldByName("ExpIRes"), "Date", "Sun, 19 Oct 2014 19:12:09 GMT")); + PTF_ASSERT_NOT_NULL( + httpResponse.insertField(httpResponse.getFieldByName("ExpIRes"), "Date", "Sun, 19 Oct 2014 19:12:09 GMT")); pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_FALSE(httpResponse.removeField("kuku5")); pcpp::Logger::getInstance().enableLogs(); PTF_ASSERT_TRUE(httpResponse.removeField("kuku2")); - httpPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(httpResponse.getHeaderLen(), 382); - PTF_ASSERT_BUF_COMPARE(buffer1, httpPacket.getRawPacket()->getRawData(), ethLayer.getHeaderLen()+ip4Layer.getHeaderLen()+tcpLayer.getHeaderLen()+httpResponse.getHeaderLen()); - -} // HttpResponseLayerCreationTest - + PTF_ASSERT_BUF_COMPARE(buffer1, httpPacket.getRawPacket()->getRawData(), + ethLayer.getHeaderLen() + ip4Layer.getHeaderLen() + tcpLayer.getHeaderLen() + + httpResponse.getHeaderLen()); +} // HttpResponseLayerCreationTest PTF_TEST_CASE(HttpResponseLayerEditTest) { @@ -465,8 +498,10 @@ PTF_TEST_CASE(HttpResponseLayerEditTest) responseLayer->getFirstLine()->setVersion(pcpp::OneDotOne); // original status code is 404 Not Found - PTF_ASSERT_TRUE(responseLayer->getFirstLine()->setStatusCode(pcpp::HttpResponseStatusCode::Http505HTTPVersionNotSupported)); - PTF_ASSERT_EQUAL(responseLayer->getFirstLine()->getStatusCode(), pcpp::HttpResponseStatusCode::Http505HTTPVersionNotSupported, enum); + PTF_ASSERT_TRUE( + responseLayer->getFirstLine()->setStatusCode(pcpp::HttpResponseStatusCode::Http505HTTPVersionNotSupported)); + PTF_ASSERT_EQUAL(responseLayer->getFirstLine()->getStatusCode(), + pcpp::HttpResponseStatusCode::Http505HTTPVersionNotSupported, enum); PTF_ASSERT_EQUAL(responseLayer->getFirstLine()->getStatusCodeAsInt(), 505); PTF_ASSERT_EQUAL(responseLayer->getFirstLine()->getStatusCodeString(), "HTTP Version Not Supported"); @@ -476,15 +511,14 @@ PTF_TEST_CASE(HttpResponseLayerEditTest) PTF_ASSERT_BUF_COMPARE(expectedHttpResponse.c_str(), responseLayer->getData(), expectedHttpResponse.length()); - PTF_ASSERT_TRUE(responseLayer->getFirstLine()->setStatusCode(pcpp::HttpResponseStatusCode(pcpp::HttpResponseStatusCode::Http413RequestEntityTooLarge, "This is a test"))); + PTF_ASSERT_TRUE(responseLayer->getFirstLine()->setStatusCode( + pcpp::HttpResponseStatusCode(pcpp::HttpResponseStatusCode::Http413RequestEntityTooLarge, "This is a test"))); PTF_ASSERT_EQUAL(responseLayer->getFirstLine()->getStatusCodeAsInt(), 413); PTF_ASSERT_EQUAL(responseLayer->getFirstLine()->getStatusCodeString(), "This is a test"); expectedHttpResponse = "HTTP/1.1 413 This is a test\r\nContent-Length: 345\r\n"; PTF_ASSERT_BUF_COMPARE(expectedHttpResponse.c_str(), responseLayer->getData(), expectedHttpResponse.length()); -} // HttpResponseLayerEditTest - - +} // HttpResponseLayerEditTest /// In this test the first HTTP header field is malformed - it only has header name but not an header value PTF_TEST_CASE(HttpMalformedResponseTest) @@ -498,13 +532,20 @@ PTF_TEST_CASE(HttpMalformedResponseTest) pcpp::HttpResponseLayer* httpResp = httpPacket.getLayerOfType(); PTF_ASSERT_EQUAL(httpResp->getFieldCount(), 6); - std::string fieldNames[] = {"x-amz-request-id2 CA4DB8F36423461F\r\n", "x-amz-id-2", PCPP_HTTP_CONTENT_TYPE_FIELD, PCPP_HTTP_TRANSFER_ENCODING_FIELD, "Date", PCPP_HTTP_SERVER_FIELD}; - std::string fieldValues[] = {"", "xcjboWLTcibyztI2kdnRoUvPdimtSPdYQYsQ4pHAebH4miKlux4Am0SBZrvVxsHN", "application/xml", "chunked", "Thu, 21 Feb 2013 06:27:11 GMT", "AmazonS3"}; + std::string fieldNames[] = { "x-amz-request-id2 CA4DB8F36423461F\r\n", "x-amz-id-2", PCPP_HTTP_CONTENT_TYPE_FIELD, + PCPP_HTTP_TRANSFER_ENCODING_FIELD, "Date", PCPP_HTTP_SERVER_FIELD }; + std::string fieldValues[] = { "", + "xcjboWLTcibyztI2kdnRoUvPdimtSPdYQYsQ4pHAebH4miKlux4Am0SBZrvVxsHN", + "application/xml", + "chunked", + "Thu, 21 Feb 2013 06:27:11 GMT", + "AmazonS3" }; int index = 0; - for (pcpp::HeaderField* field = httpResp->getFirstField(); field != nullptr && !field->isEndOfHeader(); field = httpResp->getNextField(field)) + for (pcpp::HeaderField* field = httpResp->getFirstField(); field != nullptr && !field->isEndOfHeader(); + field = httpResp->getNextField(field)) { PTF_ASSERT_EQUAL(field->getFieldName(), fieldNames[index]); PTF_ASSERT_EQUAL(field->getFieldValue(), fieldValues[index]); index++; } -} // HttpMalformedResponseTest +} // HttpMalformedResponseTest diff --git a/Tests/Packet++Test/Tests/IPSecTests.cpp b/Tests/Packet++Test/Tests/IPSecTests.cpp index 3963449e9c..331eed8b50 100644 --- a/Tests/Packet++Test/Tests/IPSecTests.cpp +++ b/Tests/Packet++Test/Tests/IPSecTests.cpp @@ -4,7 +4,6 @@ #include "IPSecLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(IPSecParsingTest) { timeval time; @@ -58,4 +57,4 @@ PTF_TEST_CASE(IPSecParsingTest) PTF_ASSERT_NOT_NULL(espLayer); PTF_ASSERT_EQUAL(espLayer->getSPI(), 0x49507636); PTF_ASSERT_EQUAL(espLayer->getSequenceNumber(), 541414224); -} // IPSecParsingTest +} // IPSecParsingTest diff --git a/Tests/Packet++Test/Tests/IPv4Tests.cpp b/Tests/Packet++Test/Tests/IPv4Tests.cpp index 28a119be43..6d5c0c7611 100644 --- a/Tests/Packet++Test/Tests/IPv4Tests.cpp +++ b/Tests/Packet++Test/Tests/IPv4Tests.cpp @@ -23,11 +23,9 @@ PTF_TEST_CASE(IPv4PacketCreation) pcpp::IPv4Layer ip4Layer(ipSrc, ipDst); ip4Layer.getIPv4Header()->protocol = pcpp::PACKETPP_IPPROTO_TCP; - uint8_t payload[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa }; pcpp::PayloadLayer payloadLayer(payload, 10); - pcpp::Packet ip4Packet(1); PTF_ASSERT_TRUE(ip4Packet.addLayer(ðLayer)); @@ -55,9 +53,7 @@ PTF_TEST_CASE(IPv4PacketCreation) PTF_ASSERT_EQUAL(ipHeader->totalLength, htobe16(30)); PTF_ASSERT_EQUAL(ipHeader->protocol, (uint8_t)pcpp::PACKETPP_IPPROTO_TCP); PTF_ASSERT_EQUAL(ipHeader->headerChecksum, htobe16(0x90b1)); -} // Ipv4PacketCreation - - +} // Ipv4PacketCreation PTF_TEST_CASE(IPv4PacketParsing) { @@ -87,7 +83,6 @@ PTF_TEST_CASE(IPv4PacketParsing) PTF_ASSERT_TRUE(ipv4Layer->getOption(pcpp::IPV4OPT_CommercialSecurity).isNull()); PTF_ASSERT_EQUAL(ipv4Layer->getOptionCount(), 0); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/IPv4-TSO.dat"); pcpp::Packet ip4TSO(&rawPacket2); @@ -100,7 +95,6 @@ PTF_TEST_CASE(IPv4PacketParsing) PTF_ASSERT_NOT_NULL(ipv4Layer->getNextLayer()); PTF_ASSERT_EQUAL(ipv4Layer->getNextLayer()->getProtocol(), pcpp::ICMP, enum); - READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/IPv4-bad.dat"); pcpp::Packet bogusPkt(&rawPacket3, pcpp::IPv4); @@ -108,16 +102,13 @@ PTF_TEST_CASE(IPv4PacketParsing) ipv4Layer = bogusPkt.getLayerOfType(); PTF_ASSERT_NULL(ipv4Layer); - READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/IPv4-encapsulated-IPv6.dat"); pcpp::Packet encapsulatedPkt(&rawPacket4, pcpp::IPv6); - pcpp::IPv6Layer *ipv6Layer = encapsulatedPkt.getLayerOfType(); + pcpp::IPv6Layer* ipv6Layer = encapsulatedPkt.getLayerOfType(); PTF_ASSERT_NOT_NULL(ipv6Layer); -} // Ipv4PacketParsing - - +} // Ipv4PacketParsing PTF_TEST_CASE(IPv4FragmentationTest) { @@ -142,7 +133,6 @@ PTF_TEST_CASE(IPv4FragmentationTest) PTF_ASSERT_NOT_NULL(ipLayer->getNextLayer()); PTF_ASSERT_EQUAL(ipLayer->getNextLayer()->getProtocol(), pcpp::GenericPayload, enum); - ipLayer = frag2.getLayerOfType(); PTF_ASSERT_NOT_NULL(ipLayer); PTF_ASSERT_TRUE(ipLayer->isFragment()); @@ -162,9 +152,7 @@ PTF_TEST_CASE(IPv4FragmentationTest) PTF_ASSERT_EQUAL(ipLayer->getFragmentFlags(), 0); PTF_ASSERT_NOT_NULL(ipLayer->getNextLayer()) PTF_ASSERT_EQUAL(ipLayer->getNextLayer()->getProtocol(), pcpp::GenericPayload, enum); -} // Ipv4FragmentationTest - - +} // Ipv4FragmentationTest PTF_TEST_CASE(IPv4OptionsParsingTest) { @@ -319,9 +307,7 @@ PTF_TEST_CASE(IPv4OptionsParsingTest) PTF_ASSERT_TRUE(opt2 == opt); opt = ipLayer->getNextOption(opt); PTF_ASSERT_TRUE(opt.isNull()); -} // Ipv4OptionsParsingTest - - +} // Ipv4OptionsParsingTest PTF_TEST_CASE(IPv4OptionsEditTest) { @@ -352,13 +338,16 @@ PTF_TEST_CASE(IPv4OptionsEditTest) pcpp::Packet ipOpt7(&rawPacket7); pcpp::IPv4Layer* ipLayer = ipOpt1.getLayerOfType(); - uint8_t commSecOptionData[] = { 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0xef }; - PTF_ASSERT_FALSE(ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_CommercialSecurity, commSecOptionData, 20)).isNull()); + uint8_t commSecOptionData[] = { 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0xef }; + PTF_ASSERT_FALSE( + ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_CommercialSecurity, commSecOptionData, 20)).isNull()); PTF_ASSERT_FALSE(ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_EndOfOptionsList, nullptr, 0)).isNull()); + // clang-format off PTF_ASSERT_FALSE(ipLayer->addOptionAfter(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_EndOfOptionsList, nullptr, 0), pcpp::IPV4OPT_CommercialSecurity).isNull()); + // clang-format on ipOpt1.computeCalculateFields(); - PTF_ASSERT_EQUAL(ipOpt1.getRawPacket()->getRawDataLen(), bufferLength11); PTF_ASSERT_BUF_COMPARE(ipOpt1.getRawPacket()->getRawData(), buffer11, ipOpt1.getRawPacket()->getRawDataLen()); @@ -375,15 +364,14 @@ PTF_TEST_CASE(IPv4OptionsEditTest) PTF_ASSERT_EQUAL(ipOpt2.getRawPacket()->getRawDataLen(), bufferLength22); PTF_ASSERT_BUF_COMPARE(ipOpt2.getRawPacket()->getRawData(), buffer22, ipOpt2.getRawPacket()->getRawDataLen()); - ipLayer = ipOpt3.getLayerOfType(); uint16_t routerAlerVal = 0; - PTF_ASSERT_FALSE(ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_RouterAlert, (uint16_t)routerAlerVal)).isNull()); + PTF_ASSERT_FALSE( + ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_RouterAlert, (uint16_t)routerAlerVal)).isNull()); ipOpt3.computeCalculateFields(); PTF_ASSERT_EQUAL(ipOpt3.getRawPacket()->getRawDataLen(), bufferLength33); PTF_ASSERT_BUF_COMPARE(ipOpt3.getRawPacket()->getRawData(), buffer33, ipOpt3.getRawPacket()->getRawDataLen()); - ipLayer = ipOpt4.getLayerOfType(); std::vector ipListValue; ipListValue.push_back(pcpp::IPv4Address("1.2.3.4")); @@ -397,7 +385,6 @@ PTF_TEST_CASE(IPv4OptionsEditTest) PTF_ASSERT_EQUAL(ipOpt4.getRawPacket()->getRawDataLen(), bufferLength44); PTF_ASSERT_BUF_COMPARE(ipOpt4.getRawPacket()->getRawData(), buffer44, ipOpt4.getRawPacket()->getRawDataLen()); - ipLayer = ipOpt5.getLayerOfType(); tsOption.clear(); pcpp::Logger::getInstance().suppressLogs(); @@ -464,7 +451,8 @@ PTF_TEST_CASE(IPv4OptionsEditTest) tsOption.timestamps.push_back(70037668); tsOption.timestamps.push_back(70037669); PTF_ASSERT_FALSE(ipLayer->addOptionAfter(pcpp::IPv4OptionBuilder(tsOption), pcpp::IPV4OPT_NOP).isNull()); - PTF_ASSERT_FALSE(ipLayer->addOptionAfter(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_RouterAlert, (uint16_t)routerAlerVal)).isNull()); + PTF_ASSERT_FALSE( + ipLayer->addOptionAfter(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_RouterAlert, (uint16_t)routerAlerVal)).isNull()); PTF_ASSERT_EQUAL(ipLayer->getOptionCount(), 4); ipOpt7.computeCalculateFields(); tsOption.clear(); @@ -473,7 +461,8 @@ PTF_TEST_CASE(IPv4OptionsEditTest) PTF_ASSERT_FALSE(ipLayer->addOption(pcpp::IPv4OptionBuilder(tsOption)).isNull()); PTF_ASSERT_EQUAL(ipLayer->getOptionCount(), 5); pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_TRUE(ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_RouterAlert, (uint16_t)routerAlerVal)).isNull()); + PTF_ASSERT_TRUE( + ipLayer->addOption(pcpp::IPv4OptionBuilder(pcpp::IPV4OPT_RouterAlert, (uint16_t)routerAlerVal)).isNull()); pcpp::Logger::getInstance().enableLogs(); ipOpt7.computeCalculateFields(); PTF_ASSERT_EQUAL(ipLayer->getOptionCount(), 5); @@ -495,20 +484,18 @@ PTF_TEST_CASE(IPv4OptionsEditTest) ipLayer = ipOpt7.getLayerOfType(); PTF_ASSERT_EQUAL(ipLayer->getOptionCount(), 0); - delete [] buffer11; - delete [] buffer22; - delete [] buffer33; - delete [] buffer44; - delete [] buffer55; - delete [] buffer66; - delete [] buffer77; -} // Ipv4OptionsEditTest - - + delete[] buffer11; + delete[] buffer22; + delete[] buffer33; + delete[] buffer44; + delete[] buffer55; + delete[] buffer66; + delete[] buffer77; +} // Ipv4OptionsEditTest PTF_TEST_CASE(IPv4UdpChecksum) { - for (int i = 1; i<6; i++) + for (int i = 1; i < 6; i++) { std::stringstream strStream; strStream << "PacketExamples/UdpPacket4Checksum" << i << ".dat"; @@ -526,4 +513,4 @@ PTF_TEST_CASE(IPv4UdpChecksum) udpLayer->computeCalculateFields(); PTF_ASSERT_EQUAL(udpLayer->getUdpHeader()->headerChecksum, packetChecksum, hex); } -} // Ipv4UdpChecksum +} // Ipv4UdpChecksum diff --git a/Tests/Packet++Test/Tests/IPv6Tests.cpp b/Tests/Packet++Test/Tests/IPv6Tests.cpp index e019c33d65..0852c0a95c 100644 --- a/Tests/Packet++Test/Tests/IPv6Tests.cpp +++ b/Tests/Packet++Test/Tests/IPv6Tests.cpp @@ -40,7 +40,7 @@ PTF_TEST_CASE(IPv6UdpPacketParseAndCreate) PTF_ASSERT_EQUAL(pUdpLayer->getUdpHeader()->length, htobe16(154)); PTF_ASSERT_EQUAL(pUdpLayer->getUdpHeader()->headerChecksum, htobe16(0x5fea)); - pcpp::EthLayer ethLayer(pcpp::MacAddress("6c:f0:49:b2:de:6e"), pcpp::MacAddress ("33:33:00:00:00:0c")); + pcpp::EthLayer ethLayer(pcpp::MacAddress("6c:f0:49:b2:de:6e"), pcpp::MacAddress("33:33:00:00:00:0c")); pcpp::IPv6Layer ip6Layer(srcIP, dstIP); pcpp::ip6_hdr* ip6Header = ip6Layer.getIPv6Header(); @@ -72,9 +72,7 @@ PTF_TEST_CASE(IPv6UdpPacketParseAndCreate) PTF_ASSERT_EQUAL(ipv6LayerEmpty.getDstIPv6Address(), dstIP); delete[] payloadData; -} // IPv6UdpPacketParseAndCreate - - +} // IPv6UdpPacketParseAndCreate PTF_TEST_CASE(IPv6FragmentationTest) { @@ -153,10 +151,9 @@ PTF_TEST_CASE(IPv6FragmentationTest) newFrag.computeCalculateFields(); PTF_ASSERT_EQUAL(frag4.getRawPacket()->getRawDataLen(), newFrag.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(frag4.getRawPacket()->getRawData(), newFrag.getRawPacket()->getRawData(), frag4.getRawPacket()->getRawDataLen()); -} // IPv6FragmentationTest - - + PTF_ASSERT_BUF_COMPARE(frag4.getRawPacket()->getRawData(), newFrag.getRawPacket()->getRawData(), + frag4.getRawPacket()->getRawDataLen()); +} // IPv6FragmentationTest PTF_TEST_CASE(IPv6ExtensionsTest) { @@ -177,7 +174,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) pcpp::Packet ipv6AuthHdr(&rawPacket5); pcpp::Packet ipv6MultipleOptions(&rawPacket6); - // parsing of Destination extension pcpp::IPv6Layer* ipv6Layer = ipv6Dest.getLayerOfType(); PTF_ASSERT_EQUAL(ipv6Layer->getExtensionCount(), 1); @@ -207,7 +203,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) PTF_ASSERT_TRUE(destExt->getOption(12).isNull()); PTF_ASSERT_TRUE(destExt->getOption(0).isNull()); - // parsing of Hop-By-Hop extension ipv6Layer = ipv6HopByHop.getLayerOfType(); hopByHopExt = ipv6Layer->getExtensionOfType(); @@ -232,7 +227,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) option = hopByHopExt->getNextOption(option); PTF_ASSERT_TRUE(option.isNull()); - // parsing of routing extension #1 ipv6Layer = ipv6Routing1.getLayerOfType(); hopByHopExt = ipv6Layer->getExtensionOfType(); @@ -247,7 +241,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) PTF_ASSERT_EQUAL(routingExt->getRoutingAdditionalDataAsIPv6Address(4), pcpp::IPv6Address("2200::210:2:0:0:4")); PTF_ASSERT_EQUAL(routingExt->getRoutingAdditionalDataAsIPv6Address(20), pcpp::IPv6Address("2200::240:2:0:0:4")); - // parsing of routing extension #2 ipv6Layer = ipv6Routing2.getLayerOfType(); routingExt = ipv6Layer->getExtensionOfType(); @@ -259,7 +252,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) PTF_ASSERT_EQUAL(routingExt->getRoutingAdditionalDataAsIPv6Address(4), pcpp::IPv6Address("2200::210:2:0:0:4")); PTF_ASSERT_EQUAL(routingExt->getRoutingAdditionalDataAsIPv6Address(20), pcpp::IPv6Address::Zero); - // parsing of authentication header extension ipv6Layer = ipv6AuthHdr.getLayerOfType(); pcpp::IPv6AuthenticationHeader* authHdrExt = ipv6Layer->getExtensionOfType(); @@ -269,14 +261,16 @@ PTF_TEST_CASE(IPv6ExtensionsTest) PTF_ASSERT_EQUAL(authHdrExt->getAuthHeader()->sequenceNumber, htobe32(32)); PTF_ASSERT_EQUAL(authHdrExt->getIntegrityCheckValueLength(), 12); uint8_t expectedICV[12] = { 0x35, 0x48, 0x21, 0x48, 0xb2, 0x43, 0x5a, 0x23, 0xdc, 0xdd, 0x55, 0x36 }; - PTF_ASSERT_BUF_COMPARE(expectedICV, authHdrExt->getIntegrityCheckValue(), authHdrExt->getIntegrityCheckValueLength()); - + PTF_ASSERT_BUF_COMPARE(expectedICV, authHdrExt->getIntegrityCheckValue(), + authHdrExt->getIntegrityCheckValueLength()); // parsing of multiple options in one IPv6 layer ipv6Layer = ipv6MultipleOptions.getLayerOfType(); PTF_ASSERT_EQUAL(ipv6Layer->getExtensionCount(), 4); PTF_ASSERT_NOT_NULL(ipv6Layer->getExtensionOfType()); - PTF_ASSERT_EQUAL(ipv6Layer->getExtensionOfType()->getAuthHeader()->securityParametersIndex, be32toh(0x100)); + PTF_ASSERT_EQUAL( + ipv6Layer->getExtensionOfType()->getAuthHeader()->securityParametersIndex, + be32toh(0x100)); PTF_ASSERT_NOT_NULL(ipv6Layer->getExtensionOfType()); PTF_ASSERT_EQUAL(ipv6Layer->getExtensionOfType()->getFirstOption().getType(), 11); PTF_ASSERT_NOT_NULL(ipv6Layer->getExtensionOfType()); @@ -284,7 +278,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) PTF_ASSERT_NOT_NULL(ipv6Layer->getExtensionOfType()); PTF_ASSERT_EQUAL(ipv6Layer->getExtensionOfType()->getRoutingHeader()->routingType, 0); - // creation of Destination extension pcpp::EthLayer newEthLayer(*ipv6Dest.getLayerOfType()); @@ -310,8 +303,8 @@ PTF_TEST_CASE(IPv6ExtensionsTest) newPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(ipv6Dest.getRawPacket()->getRawDataLen(), newPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(ipv6Dest.getRawPacket()->getRawData(), newPacket.getRawPacket()->getRawData(), ipv6Dest.getRawPacket()->getRawDataLen()); - + PTF_ASSERT_BUF_COMPARE(ipv6Dest.getRawPacket()->getRawData(), newPacket.getRawPacket()->getRawData(), + ipv6Dest.getRawPacket()->getRawDataLen()); // creation of hop-by-hop extension pcpp::EthLayer newEthLayer2(*ipv6HopByHop.getLayerOfType()); @@ -336,8 +329,8 @@ PTF_TEST_CASE(IPv6ExtensionsTest) newPacket2.computeCalculateFields(); PTF_ASSERT_EQUAL(ipv6HopByHop.getRawPacket()->getRawDataLen(), newPacket2.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(ipv6HopByHop.getRawPacket()->getRawData(), newPacket2.getRawPacket()->getRawData(), ipv6HopByHop.getRawPacket()->getRawDataLen()); - + PTF_ASSERT_BUF_COMPARE(ipv6HopByHop.getRawPacket()->getRawData(), newPacket2.getRawPacket()->getRawData(), + ipv6HopByHop.getRawPacket()->getRawDataLen()); // creation of routing extension pcpp::EthLayer newEthLayer3(*ipv6Routing2.getLayerOfType()); @@ -353,7 +346,7 @@ PTF_TEST_CASE(IPv6ExtensionsTest) ip6Addr.copyTo(routingAdditionalData + 4); pcpp::IPv6RoutingHeader newRoutingHeader(0, 1, routingAdditionalData, 20); newIPv6Layer3.addExtension(newRoutingHeader); - delete [] routingAdditionalData; + delete[] routingAdditionalData; pcpp::UdpLayer newUdpLayer3(*ipv6Routing2.getLayerOfType()); @@ -363,8 +356,8 @@ PTF_TEST_CASE(IPv6ExtensionsTest) newPacket3.addLayer(&newUdpLayer3); PTF_ASSERT_EQUAL(ipv6Routing2.getRawPacket()->getRawDataLen(), newPacket3.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(ipv6Routing2.getRawPacket()->getRawData(), newPacket3.getRawPacket()->getRawData(), ipv6Routing2.getRawPacket()->getRawDataLen()); - + PTF_ASSERT_BUF_COMPARE(ipv6Routing2.getRawPacket()->getRawData(), newPacket3.getRawPacket()->getRawData(), + ipv6Routing2.getRawPacket()->getRawDataLen()); // creation of AH extension pcpp::EthLayer newEthLayer4(*ipv6AuthHdr.getLayerOfType()); @@ -386,8 +379,8 @@ PTF_TEST_CASE(IPv6ExtensionsTest) newPacket4.computeCalculateFields(); PTF_ASSERT_EQUAL(ipv6AuthHdr.getRawPacket()->getRawDataLen(), newPacket4.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(ipv6AuthHdr.getRawPacket()->getRawData(), newPacket4.getRawPacket()->getRawData(), ipv6AuthHdr.getRawPacket()->getRawDataLen()); - + PTF_ASSERT_BUF_COMPARE(ipv6AuthHdr.getRawPacket()->getRawData(), newPacket4.getRawPacket()->getRawData(), + ipv6AuthHdr.getRawPacket()->getRawDataLen()); // creation of packet with several extensions pcpp::EthLayer newEthLayer5(*ipv6AuthHdr.getLayerOfType()); @@ -409,5 +402,6 @@ PTF_TEST_CASE(IPv6ExtensionsTest) newPacket5.computeCalculateFields(); PTF_ASSERT_EQUAL(ipv6MultipleOptions.getRawPacket()->getRawDataLen(), newPacket5.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(ipv6MultipleOptions.getRawPacket()->getRawData(), newPacket5.getRawPacket()->getRawData(), ipv6MultipleOptions.getRawPacket()->getRawDataLen()); -} // IPv6ExtensionsTest + PTF_ASSERT_BUF_COMPARE(ipv6MultipleOptions.getRawPacket()->getRawData(), newPacket5.getRawPacket()->getRawData(), + ipv6MultipleOptions.getRawPacket()->getRawDataLen()); +} // IPv6ExtensionsTest diff --git a/Tests/Packet++Test/Tests/IcmpTests.cpp b/Tests/Packet++Test/Tests/IcmpTests.cpp index 4e75774a3b..63c810cce0 100644 --- a/Tests/Packet++Test/Tests/IcmpTests.cpp +++ b/Tests/Packet++Test/Tests/IcmpTests.cpp @@ -9,7 +9,6 @@ #include "UdpLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(IcmpParsingTest) { timeval time; @@ -65,7 +64,6 @@ PTF_TEST_CASE(IcmpParsingTest) PTF_ASSERT_TRUE(icmpAddrMaskReq.isPacketOfType(pcpp::ICMP)); PTF_ASSERT_TRUE(icmpAddrMaskRep.isPacketOfType(pcpp::ICMP)); - // Echo request icmpLayer = icmpEchoRequest.getLayerOfType(); PTF_ASSERT_NOT_NULL(icmpLayer); @@ -256,9 +254,7 @@ PTF_TEST_CASE(IcmpParsingTest) PTF_ASSERT_NOT_NULL(routerAddr); PTF_ASSERT_EQUAL(pcpp::IPv4Address(routerAddr->routerAddress), pcpp::IPv4Address("14.80.84.66")); PTF_ASSERT_EQUAL(routerAddr->preferenceLevel, 0); -} // IcmpParsingTest - - +} // IcmpParsingTest PTF_TEST_CASE(IcmpCreationTest) { @@ -285,9 +281,11 @@ PTF_TEST_CASE(IcmpCreationTest) pcpp::IPv4Layer ipLayer(pcpp::IPv4Address("1.1.1.1"), pcpp::IPv4Address("2.2.2.2")); - uint8_t data[48] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, - 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; + uint8_t data[48] = { + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; // Echo request creation pcpp::IcmpLayer echoReqLayer; @@ -298,7 +296,7 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_TRUE(echoRequestPacket.addLayer(&echoReqLayer)); echoRequestPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(echoRequestPacket.getRawPacket()->getRawDataLen(), bufferLength1); - PTF_ASSERT_BUF_COMPARE(echoRequestPacket.getRawPacket()->getRawData()+34, buffer1+34, bufferLength1-34); + PTF_ASSERT_BUF_COMPARE(echoRequestPacket.getRawPacket()->getRawData() + 34, buffer1 + 34, bufferLength1 - 34); // Echo reply creation pcpp::EthLayer ethLayer2(ethLayer); @@ -311,7 +309,7 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_NOT_NULL(echoRepLayer.setEchoReplyData(0xd73b, 0, 0xe45104007dd6a751ULL, data, 48)); echoReplyPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(echoReplyPacket.getRawPacket()->getRawDataLen(), bufferLength2); - PTF_ASSERT_BUF_COMPARE(echoReplyPacket.getRawPacket()->getRawData()+34, buffer2+34, bufferLength2-34); + PTF_ASSERT_BUF_COMPARE(echoReplyPacket.getRawPacket()->getRawData() + 34, buffer2 + 34, bufferLength2 - 34); // Time exceeded creation pcpp::EthLayer ethLayer3(ethLayer); @@ -333,7 +331,7 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_NOT_NULL(timeExceededLayer.setTimeExceededData(0, &ipLayerForTimeExceeded, &icmpLayerForTimeExceeded)); timeExceededPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(timeExceededPacket.getRawPacket()->getRawDataLen(), bufferLength11); - PTF_ASSERT_BUF_COMPARE(timeExceededPacket.getRawPacket()->getRawData()+34, buffer11+34, bufferLength11-34); + PTF_ASSERT_BUF_COMPARE(timeExceededPacket.getRawPacket()->getRawData() + 34, buffer11 + 34, bufferLength11 - 34); // Dest unreachable creation pcpp::EthLayer ethLayer4(ethLayer); @@ -350,10 +348,11 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_TRUE(destUnreachablePacket.addLayer(ðLayer4)); PTF_ASSERT_TRUE(destUnreachablePacket.addLayer(&ipLayer4)); PTF_ASSERT_TRUE(destUnreachablePacket.addLayer(&destUnreachableLayer)); - PTF_ASSERT_NOT_NULL(destUnreachableLayer.setDestUnreachableData(pcpp::IcmpPortUnreachable, 0, &ipLayerForDestUnreachable, &udpLayerForDestUnreachable)); + PTF_ASSERT_NOT_NULL(destUnreachableLayer.setDestUnreachableData( + pcpp::IcmpPortUnreachable, 0, &ipLayerForDestUnreachable, &udpLayerForDestUnreachable)); destUnreachablePacket.computeCalculateFields(); PTF_ASSERT_EQUAL(destUnreachablePacket.getRawPacket()->getRawDataLen(), bufferLength10); - PTF_ASSERT_BUF_COMPARE(destUnreachablePacket.getRawPacket()->getRawData()+34, buffer10+34, bufferLength10-34); + PTF_ASSERT_BUF_COMPARE(destUnreachablePacket.getRawPacket()->getRawData() + 34, buffer10 + 34, bufferLength10 - 34); // Timestamp reply pcpp::EthLayer ethLayer5(ethLayer); @@ -368,7 +367,7 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_TRUE(timestampReplyPacket.addLayer(&ipLayer5)); PTF_ASSERT_TRUE(timestampReplyPacket.addLayer(×tampReplyLayer)); timestampReplyPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(timestampReplyPacket.getRawPacket()->getRawDataLen(), bufferLength4-6); + PTF_ASSERT_EQUAL(timestampReplyPacket.getRawPacket()->getRawDataLen(), bufferLength4 - 6); // Address mask request pcpp::EthLayer ethLayer6(ethLayer); @@ -381,7 +380,8 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_TRUE(addressMaskRequestPacket.addLayer(&addressMaskRequestLayer)); addressMaskRequestPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(addressMaskRequestPacket.getRawPacket()->getRawDataLen(), bufferLength14 - 14); - PTF_ASSERT_BUF_COMPARE(addressMaskRequestPacket.getRawPacket()->getRawData() + 34, buffer14 + 34, bufferLength14 - 34 - 14); + PTF_ASSERT_BUF_COMPARE(addressMaskRequestPacket.getRawPacket()->getRawData() + 34, buffer14 + 34, + bufferLength14 - 34 - 14); // Redirect creation pcpp::EthLayer ethLayer7(ethLayer); @@ -399,9 +399,10 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_TRUE(redirectPacket.addLayer(ðLayer7)); PTF_ASSERT_TRUE(redirectPacket.addLayer(&ipLayer7)); PTF_ASSERT_TRUE(redirectPacket.addLayer(&redirectLayer)); - PTF_ASSERT_NOT_NULL(redirectLayer.setRedirectData(1, pcpp::IPv4Address("10.2.99.98"), &ipLayerForRedirect, &icmpLayerForRedirect)); + PTF_ASSERT_NOT_NULL( + redirectLayer.setRedirectData(1, pcpp::IPv4Address("10.2.99.98"), &ipLayerForRedirect, &icmpLayerForRedirect)); redirectPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(redirectPacket.getRawPacket()->getRawDataLen(), bufferLength5+8); + PTF_ASSERT_EQUAL(redirectPacket.getRawPacket()->getRawDataLen(), bufferLength5 + 8); // Router advertisement creation pcpp::EthLayer ethLayer8(ethLayer); @@ -424,27 +425,24 @@ PTF_TEST_CASE(IcmpCreationTest) PTF_ASSERT_NOT_NULL(routerAdvLayer.setRouterAdvertisementData(16, 200, routerAddresses)); routerAdvPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(routerAdvLayer.getHeaderLen(), 32); - PTF_ASSERT_EQUAL(routerAdvPacket.getRawPacket()->getRawDataLen(), bufferLength6-18); - - - delete [] buffer1; - delete [] buffer2; - delete [] buffer3; - delete [] buffer4; - delete [] buffer5; - delete [] buffer6; - delete [] buffer7; - delete [] buffer8; - delete [] buffer9; - delete [] buffer10; - delete [] buffer11; - delete [] buffer12; - delete [] buffer13; - delete [] buffer14; - delete [] buffer15; -} // IcmpCreationTest - - + PTF_ASSERT_EQUAL(routerAdvPacket.getRawPacket()->getRawDataLen(), bufferLength6 - 18); + + delete[] buffer1; + delete[] buffer2; + delete[] buffer3; + delete[] buffer4; + delete[] buffer5; + delete[] buffer6; + delete[] buffer7; + delete[] buffer8; + delete[] buffer9; + delete[] buffer10; + delete[] buffer11; + delete[] buffer12; + delete[] buffer13; + delete[] buffer14; + delete[] buffer15; +} // IcmpCreationTest PTF_TEST_CASE(IcmpEditTest) { @@ -464,9 +462,11 @@ PTF_TEST_CASE(IcmpEditTest) pcpp::IcmpLayer* icmpLayer = icmpRouterAdv1.getLayerOfType(); PTF_ASSERT_NOT_NULL(icmpLayer); - uint8_t data[48] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, - 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; + uint8_t data[48] = { + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 + }; PTF_ASSERT_NOT_NULL(icmpLayer->getRouterAdvertisementData()); PTF_ASSERT_NULL(icmpLayer->getEchoRequestData()); @@ -477,8 +477,7 @@ PTF_TEST_CASE(IcmpEditTest) PTF_ASSERT_EQUAL(echoReq->dataLength, 48); icmpRouterAdv1.computeCalculateFields(); PTF_ASSERT_NULL(icmpLayer->getRouterAdvertisementData()); - PTF_ASSERT_BUF_COMPARE(icmpRouterAdv1.getRawPacket()->getRawData()+34, buffer2+34, bufferLength2-34); - + PTF_ASSERT_BUF_COMPARE(icmpRouterAdv1.getRawPacket()->getRawData() + 34, buffer2 + 34, bufferLength2 - 34); // convert echo request to echo reply @@ -486,8 +485,7 @@ PTF_TEST_CASE(IcmpEditTest) PTF_ASSERT_NULL(icmpLayer->getEchoRequestData()); icmpRouterAdv1.computeCalculateFields(); PTF_ASSERT_EQUAL(echoReply->header->checksum, htobe16(0xc3b3)); - PTF_ASSERT_BUF_COMPARE(icmpRouterAdv1.getRawPacket()->getRawData()+34, buffer3+34, bufferLength3-34); - + PTF_ASSERT_BUF_COMPARE(icmpRouterAdv1.getRawPacket()->getRawData() + 34, buffer3 + 34, bufferLength3 - 34); // convert time exceeded to echo request @@ -513,12 +511,12 @@ PTF_TEST_CASE(IcmpEditTest) PTF_ASSERT_EQUAL(echoReq->header->id, htobe16(55099)); PTF_ASSERT_EQUAL(echoReq->dataLength, 48); icmpTimeExceededUdp.computeCalculateFields(); - PTF_ASSERT_BUF_COMPARE(icmpTimeExceededUdp.getRawPacket()->getRawData()+34, buffer2+34, bufferLength2-34); - + PTF_ASSERT_BUF_COMPARE(icmpTimeExceededUdp.getRawPacket()->getRawData() + 34, buffer2 + 34, bufferLength2 - 34); // convert echo request to dest unreachable - pcpp::icmp_destination_unreachable* destUnreachable = icmpLayer->setDestUnreachableData(pcpp::IcmpHostUnreachable, 0, &ipLayerForDestUnreachable, &icmpLayerForDestUnreachable); + pcpp::icmp_destination_unreachable* destUnreachable = icmpLayer->setDestUnreachableData( + pcpp::IcmpHostUnreachable, 0, &ipLayerForDestUnreachable, &icmpLayerForDestUnreachable); PTF_ASSERT_NOT_NULL(destUnreachable); PTF_ASSERT_EQUAL(icmpLayer->getHeaderLen(), 8); PTF_ASSERT_EQUAL(destUnreachable->code, (uint8_t)pcpp::IcmpHostUnreachable); @@ -534,9 +532,9 @@ PTF_TEST_CASE(IcmpEditTest) PTF_ASSERT_NOT_NULL(echoReq); PTF_ASSERT_EQUAL(echoReq->header->sequence, htobe16(4)); icmpTimeExceededUdp.computeCalculateFields(); - PTF_ASSERT_BUF_COMPARE(icmpTimeExceededUdp.getRawPacket()->getRawData()+34, buffer5+34, bufferLength5-34); + PTF_ASSERT_BUF_COMPARE(icmpTimeExceededUdp.getRawPacket()->getRawData() + 34, buffer5 + 34, bufferLength5 - 34); - delete [] buffer2; - delete [] buffer3; - delete [] buffer5; -} // IcmpEditTest + delete[] buffer2; + delete[] buffer3; + delete[] buffer5; +} // IcmpEditTest diff --git a/Tests/Packet++Test/Tests/IcmpV6Tests.cpp b/Tests/Packet++Test/Tests/IcmpV6Tests.cpp index 75c598c671..5ed38a27bb 100644 --- a/Tests/Packet++Test/Tests/IcmpV6Tests.cpp +++ b/Tests/Packet++Test/Tests/IcmpV6Tests.cpp @@ -34,7 +34,7 @@ PTF_TEST_CASE(IcmpV6ParsingTest) // Echo request PTF_ASSERT_TRUE(echoRequestPacket.isPacketOfType(pcpp::ICMPv6)); - pcpp::ICMPv6EchoLayer *echoRequestLayer = echoRequestPacket.getLayerOfType(); + pcpp::ICMPv6EchoLayer* echoRequestLayer = echoRequestPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(echoRequestLayer); PTF_ASSERT_TRUE(echoRequestLayer->isMessageOfType(pcpp::ICMPv6MessageType::ICMPv6_ECHO_REQUEST)); PTF_ASSERT_EQUAL(echoRequestLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_ECHO_REQUEST, enumclass); @@ -44,12 +44,12 @@ PTF_TEST_CASE(IcmpV6ParsingTest) PTF_ASSERT_EQUAL(echoRequestLayer->getSequenceNr(), 20); PTF_ASSERT_EQUAL(echoRequestLayer->getEchoDataLen(), 56); - uint8_t data[] = {0xbd, 0xce, 0xcb, 0x62}; + uint8_t data[] = { 0xbd, 0xce, 0xcb, 0x62 }; PTF_ASSERT_BUF_COMPARE(echoRequestLayer->getEchoDataPtr(), data, 4); // Echo reply PTF_ASSERT_TRUE(echoReplyPacket.isPacketOfType(pcpp::ICMPv6)); - pcpp::ICMPv6EchoLayer *echoReplyLayer = echoReplyPacket.getLayerOfType(); + pcpp::ICMPv6EchoLayer* echoReplyLayer = echoReplyPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(echoReplyLayer); PTF_ASSERT_TRUE(echoReplyLayer->isMessageOfType(pcpp::ICMPv6MessageType::ICMPv6_ECHO_REPLY)); PTF_ASSERT_EQUAL(echoReplyLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_ECHO_REPLY, enumclass); @@ -63,10 +63,12 @@ PTF_TEST_CASE(IcmpV6ParsingTest) // Neighbor solicitation with source link-layer option PTF_ASSERT_TRUE(neighSoliPacket.isPacketOfType(pcpp::ICMPv6)); - pcpp::NDPNeighborSolicitationLayer *neighSoliLayer = neighSoliPacket.getLayerOfType(); + pcpp::NDPNeighborSolicitationLayer* neighSoliLayer = + neighSoliPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(neighSoliLayer); PTF_ASSERT_EQUAL(neighSoliLayer->getHeaderLen(), 32); - PTF_ASSERT_EQUAL(neighSoliLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION, enumclass); + PTF_ASSERT_EQUAL(neighSoliLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION, + enumclass); PTF_ASSERT_EQUAL(neighSoliLayer->getCode(), 0); PTF_ASSERT_EQUAL(neighSoliLayer->getChecksum(), 0xfe98); PTF_ASSERT_EQUAL(neighSoliLayer->getTargetIP(), pcpp::IPv6Address("fd53:7cb8:383:2::1:117")); @@ -74,26 +76,31 @@ PTF_TEST_CASE(IcmpV6ParsingTest) PTF_ASSERT_EQUAL(neighSoliLayer->getLinkLayerAddress(), pcpp::MacAddress("00:54:af:e9:4d:80")); PTF_ASSERT_EQUAL(neighSoliLayer->getNdpOptionCount(), 1); - pcpp::NdpOption sourceLinkLayerOption = neighSoliLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); + pcpp::NdpOption sourceLinkLayerOption = + neighSoliLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); PTF_ASSERT_TRUE(sourceLinkLayerOption.isNotNull()); PTF_ASSERT_EQUAL((int)sourceLinkLayerOption.getNdpOptionType(), 1); PTF_ASSERT_EQUAL(sourceLinkLayerOption.getDataSize(), 6); PTF_ASSERT_EQUAL(sourceLinkLayerOption.getTotalSize(), 8); PTF_ASSERT_EQUAL(pcpp::MacAddress(sourceLinkLayerOption.getValue()), pcpp::MacAddress("00:54:af:e9:4d:80")); - pcpp::NdpOption targetLinkLayerOption2 = neighSoliLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + pcpp::NdpOption targetLinkLayerOption2 = + neighSoliLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); PTF_ASSERT_TRUE(targetLinkLayerOption2.isNull()); - pcpp::IcmpV6Layer *icmpNeighSoliLayer = neighSoliPacket.getLayerOfType(); + pcpp::IcmpV6Layer* icmpNeighSoliLayer = neighSoliPacket.getLayerOfType(); PTF_ASSERT_EQUAL(icmpNeighSoliLayer->getHeaderLen(), 32); - PTF_ASSERT_EQUAL(icmpNeighSoliLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION, enumclass); + PTF_ASSERT_EQUAL(icmpNeighSoliLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION, + enumclass); PTF_ASSERT_EQUAL(icmpNeighSoliLayer->getCode(), 0); PTF_ASSERT_EQUAL(icmpNeighSoliLayer->getChecksum(), 0xfe98); // Neighbor advertisement with target link-layer option PTF_ASSERT_TRUE(neighAdvPacket.isPacketOfType(pcpp::ICMPv6)); - pcpp::NDPNeighborAdvertisementLayer *neighAdvLayer = neighAdvPacket.getLayerOfType(); + pcpp::NDPNeighborAdvertisementLayer* neighAdvLayer = + neighAdvPacket.getLayerOfType(); PTF_ASSERT_EQUAL(neighAdvLayer->getHeaderLen(), 32); - PTF_ASSERT_EQUAL(neighAdvLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT, enumclass); + PTF_ASSERT_EQUAL(neighAdvLayer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT, + enumclass); PTF_ASSERT_EQUAL(neighAdvLayer->getCode(), 0); PTF_ASSERT_EQUAL(neighAdvLayer->getChecksum(), 0x9abb); PTF_ASSERT_TRUE(neighAdvLayer->getRouterFlag()); @@ -104,14 +111,15 @@ PTF_TEST_CASE(IcmpV6ParsingTest) PTF_ASSERT_EQUAL(neighAdvLayer->getTargetMac(), pcpp::MacAddress("c2:00:54:f5:00:00")); PTF_ASSERT_EQUAL(neighAdvLayer->getNdpOptionCount(), 1); - pcpp::NdpOption targetLinkLayerOption = neighAdvLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + pcpp::NdpOption targetLinkLayerOption = + neighAdvLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); PTF_ASSERT_TRUE(targetLinkLayerOption.isNotNull()); PTF_ASSERT_EQUAL((int)targetLinkLayerOption.getNdpOptionType(), 2); PTF_ASSERT_EQUAL(targetLinkLayerOption.getDataSize(), 6); PTF_ASSERT_EQUAL(targetLinkLayerOption.getTotalSize(), 8); PTF_ASSERT_EQUAL(pcpp::MacAddress(targetLinkLayerOption.getValue()), pcpp::MacAddress("c2:00:54:f5:00:00")); - pcpp::IcmpV6Layer *icmpNeighAdv = neighAdvPacket.getLayerOfType(); + pcpp::IcmpV6Layer* icmpNeighAdv = neighAdvPacket.getLayerOfType(); PTF_ASSERT_EQUAL(icmpNeighAdv->getHeaderLen(), 32); PTF_ASSERT_EQUAL(icmpNeighAdv->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT, enumclass); PTF_ASSERT_EQUAL(icmpNeighAdv->getCode(), 0); @@ -119,7 +127,8 @@ PTF_TEST_CASE(IcmpV6ParsingTest) // Neighbor advertisement without target link-layer option PTF_ASSERT_TRUE(neighAdvPacketNoOpt.isPacketOfType(pcpp::ICMPv6)); - pcpp::NDPNeighborAdvertisementLayer *neighAdvNoOptLayer = neighAdvPacketNoOpt.getLayerOfType(); + pcpp::NDPNeighborAdvertisementLayer* neighAdvNoOptLayer = + neighAdvPacketNoOpt.getLayerOfType(); PTF_ASSERT_EQUAL(neighAdvNoOptLayer->getHeaderLen(), 24); PTF_ASSERT_FALSE(neighAdvNoOptLayer->getRouterFlag()); PTF_ASSERT_TRUE(neighAdvNoOptLayer->getUnicastFlag()); @@ -128,22 +137,26 @@ PTF_TEST_CASE(IcmpV6ParsingTest) PTF_ASSERT_FALSE(neighAdvNoOptLayer->hasTargetMacInfo()); PTF_ASSERT_EQUAL(neighAdvNoOptLayer->getTargetMac(), pcpp::MacAddress()); PTF_ASSERT_EQUAL(neighAdvNoOptLayer->getNdpOptionCount(), 0); - pcpp::NdpOption targetLinkLayerNoOptOption = neighAdvNoOptLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + pcpp::NdpOption targetLinkLayerNoOptOption = + neighAdvNoOptLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); PTF_ASSERT_TRUE(targetLinkLayerNoOptOption.isNull()); // Generic ICMPv6 packet PTF_ASSERT_TRUE(icmpV6GenericPacket.isPacketOfType(pcpp::ICMPv6)); - pcpp::IcmpV6Layer *icmpV6Layer = icmpV6GenericPacket.getLayerOfType(); + pcpp::IcmpV6Layer* icmpV6Layer = icmpV6GenericPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(icmpV6Layer); PTF_ASSERT_EQUAL(icmpV6Layer->getHeaderLen(), 48); PTF_ASSERT_TRUE(icmpV6Layer->isMessageOfType(pcpp::ICMPv6MessageType::ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS)); - PTF_ASSERT_EQUAL(icmpV6Layer->getMessageType(), pcpp::ICMPv6MessageType::ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS, enumclass); + PTF_ASSERT_EQUAL(icmpV6Layer->getMessageType(), + pcpp::ICMPv6MessageType::ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS, enumclass); PTF_ASSERT_EQUAL(icmpV6Layer->getCode(), 0); PTF_ASSERT_EQUAL(icmpV6Layer->getChecksum(), 0x2b5a); PTF_ASSERT_EQUAL(icmpV6Layer->toString(), "ICMPv6 Layer, Message type: 143"); PTF_ASSERT_NULL(icmpV6Layer->getNextLayer()); - std::string expectedPayloadString = "0000000204000000ff05000000000000000000000001000304000000ff020000000000000000000000010002"; - PTF_ASSERT_EQUAL(pcpp::byteArrayToHexString(icmpV6Layer->getDataPtr(4), icmpV6Layer->getDataLen() - 4), expectedPayloadString); + std::string expectedPayloadString = + "0000000204000000ff05000000000000000000000001000304000000ff020000000000000000000000010002"; + PTF_ASSERT_EQUAL(pcpp::byteArrayToHexString(icmpV6Layer->getDataPtr(4), icmpV6Layer->getDataLen() - 4), + expectedPayloadString); } PTF_TEST_CASE(IcmpV6CreationTest) @@ -158,13 +171,14 @@ PTF_TEST_CASE(IcmpV6CreationTest) READ_FILE_INTO_BUFFER(5, "PacketExamples/IcmpV6_NeighAdvNoOption.dat"); READ_FILE_INTO_BUFFER(6, "PacketExamples/IcmpV6_Generic.dat"); - uint8_t data[56] = {0xbd, 0xce, 0xcb, 0x62, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xa1, 0x09, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}; + uint8_t data[56] = { 0xbd, 0xce, 0xcb, 0x62, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xa1, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 }; pcpp::EthLayer ethLayer(pcpp::MacAddress("11:22:33:44:55:66"), pcpp::MacAddress("66:55:44:33:22:11")); - pcpp::IPv6Layer ipv6Layer(pcpp::IPv6Address(std::string("fe80::215:5dff:fea5:c4c5")), pcpp::IPv6Address(std::string("fe80::dd05:dae0:74bc:7341"))); + pcpp::IPv6Layer ipv6Layer(pcpp::IPv6Address(std::string("fe80::215:5dff:fea5:c4c5")), + pcpp::IPv6Address(std::string("fe80::dd05:dae0:74bc:7341"))); // Create ICMPv6 layer with type, code and data pcpp::IcmpV6Layer icmpv6Layer(pcpp::ICMPv6MessageType::ICMPv6_ECHO_REQUEST, 0, data, 56); @@ -173,8 +187,11 @@ PTF_TEST_CASE(IcmpV6CreationTest) PTF_ASSERT_TRUE(icmpv6LayerPacket.addLayer(&ipv6Layer)); PTF_ASSERT_TRUE(icmpv6LayerPacket.addLayer(&icmpv6Layer)); icmpv6LayerPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(icmpv6LayerPacket.getRawPacket()->getRawDataLen(), bufferLength1-4); // comparing with IcmpV6_EchoRequest frame which has the same data but an additional echo header - PTF_ASSERT_BUF_COMPARE(icmpv6LayerPacket.getRawPacket()->getRawData()+58, buffer1+62, bufferLength1-62); + PTF_ASSERT_EQUAL( + icmpv6LayerPacket.getRawPacket()->getRawDataLen(), + bufferLength1 - + 4); // comparing with IcmpV6_EchoRequest frame which has the same data but an additional echo header + PTF_ASSERT_BUF_COMPARE(icmpv6LayerPacket.getRawPacket()->getRawData() + 58, buffer1 + 62, bufferLength1 - 62); // Echo request creation pcpp::EthLayer ethLayer1(ethLayer); @@ -186,7 +203,7 @@ PTF_TEST_CASE(IcmpV6CreationTest) PTF_ASSERT_TRUE(echoRequestPacket.addLayer(&echoReqLayer)); echoRequestPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(echoRequestPacket.getRawPacket()->getRawDataLen(), bufferLength1); - PTF_ASSERT_BUF_COMPARE(echoRequestPacket.getRawPacket()->getRawData()+54, buffer1+54, bufferLength1-54); + PTF_ASSERT_BUF_COMPARE(echoRequestPacket.getRawPacket()->getRawData() + 54, buffer1 + 54, bufferLength1 - 54); // Echo reply creation pcpp::EthLayer ethLayer2(ethLayer); @@ -198,19 +215,25 @@ PTF_TEST_CASE(IcmpV6CreationTest) PTF_ASSERT_TRUE(echoReplyPacket.addLayer(&echoRepLayer)); echoReplyPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(echoReplyPacket.getRawPacket()->getRawDataLen(), bufferLength2); - PTF_ASSERT_BUF_COMPARE(echoReplyPacket.getRawPacket()->getRawData()+54, buffer2+54, bufferLength2-54); + PTF_ASSERT_BUF_COMPARE(echoReplyPacket.getRawPacket()->getRawData() + 54, buffer2 + 54, bufferLength2 - 54); // Neighbor solicitation with source link-layer option - pcpp::IPv6Layer *ipv6SoliLayer = new pcpp::IPv6Layer(pcpp::IPv6Address("fd53:7cb8:383:4::67"), pcpp::IPv6Address("fd53:7cb8:383:2::1:117")); + pcpp::IPv6Layer* ipv6SoliLayer = + new pcpp::IPv6Layer(pcpp::IPv6Address("fd53:7cb8:383:4::67"), pcpp::IPv6Address("fd53:7cb8:383:2::1:117")); ipv6SoliLayer->getIPv6Header()->hopLimit = 255; - pcpp::NDPNeighborSolicitationLayer *ndpSoliLayer = new pcpp::NDPNeighborSolicitationLayer(0, pcpp::IPv6Address("fd53:7cb8:383:2::1:117"), pcpp::MacAddress("00:54:af:e9:4d:80")); + pcpp::NDPNeighborSolicitationLayer* ndpSoliLayer = new pcpp::NDPNeighborSolicitationLayer( + 0, pcpp::IPv6Address("fd53:7cb8:383:2::1:117"), pcpp::MacAddress("00:54:af:e9:4d:80")); pcpp::Packet neighSoliPacket(100); PTF_ASSERT_TRUE(neighSoliPacket.addLayer(ipv6SoliLayer, true)); PTF_ASSERT_TRUE(neighSoliPacket.addLayer(ndpSoliLayer, true)); neighSoliPacket.computeCalculateFields(); - PTF_ASSERT_BUF_COMPARE(neighSoliPacket.getRawPacket()->getRawData()+6, buffer3+24, bufferLength3-28); // dat file contains frame with eth + vlan layer (14 + 4 bytes) and trailing bytes (4 bytes) + PTF_ASSERT_BUF_COMPARE( + neighSoliPacket.getRawPacket()->getRawData() + 6, buffer3 + 24, + bufferLength3 - + 28); // dat file contains frame with eth + vlan layer (14 + 4 bytes) and trailing bytes (4 bytes) - pcpp::NDPNeighborSolicitationLayer *neighSoliLayer = neighSoliPacket.getLayerOfType(); + pcpp::NDPNeighborSolicitationLayer* neighSoliLayer = + neighSoliPacket.getLayerOfType(); PTF_ASSERT_EQUAL(neighSoliLayer->getHeaderLen(), 32); PTF_ASSERT_EQUAL((int)neighSoliLayer->getMessageType(), 135); PTF_ASSERT_EQUAL(neighSoliLayer->getCode(), 0); @@ -218,21 +241,25 @@ PTF_TEST_CASE(IcmpV6CreationTest) PTF_ASSERT_EQUAL(neighSoliLayer->getTargetIP(), pcpp::IPv6Address("fd53:7cb8:383:2::1:117")); PTF_ASSERT_EQUAL(neighSoliLayer->getNdpOptionCount(), 1); PTF_ASSERT_EQUAL(neighSoliLayer->getLinkLayerAddress(), pcpp::MacAddress("00:54:af:e9:4d:80")); - pcpp::NdpOption sourceLinkLayerOption = neighSoliLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); + pcpp::NdpOption sourceLinkLayerOption = + neighSoliLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); PTF_ASSERT_TRUE(sourceLinkLayerOption.isNotNull()); PTF_ASSERT_EQUAL(sourceLinkLayerOption.getDataSize(), 6); PTF_ASSERT_EQUAL(sourceLinkLayerOption.getTotalSize(), 8); // Neighbor advertisement with target link-layer option - pcpp::IPv6Layer *ipv6AdvLayer = new pcpp::IPv6Layer(pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), pcpp::IPv6Address("ff02::1")); - pcpp::NDPNeighborAdvertisementLayer *ndpAdvLayer = new pcpp::NDPNeighborAdvertisementLayer(0, pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), pcpp::MacAddress("c2:00:54:f5:00:00"), true, false, true); + pcpp::IPv6Layer* ipv6AdvLayer = + new pcpp::IPv6Layer(pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), pcpp::IPv6Address("ff02::1")); + pcpp::NDPNeighborAdvertisementLayer* ndpAdvLayer = new pcpp::NDPNeighborAdvertisementLayer( + 0, pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), pcpp::MacAddress("c2:00:54:f5:00:00"), true, false, true); pcpp::Packet neighAdvPacket(100); PTF_ASSERT_TRUE(neighAdvPacket.addLayer(ipv6AdvLayer, true)); PTF_ASSERT_TRUE(neighAdvPacket.addLayer(ndpAdvLayer, true)); neighAdvPacket.computeCalculateFields(); - PTF_ASSERT_BUF_COMPARE(neighAdvPacket.getRawPacket()->getRawData()+40, buffer4+54, bufferLength4-54); + PTF_ASSERT_BUF_COMPARE(neighAdvPacket.getRawPacket()->getRawData() + 40, buffer4 + 54, bufferLength4 - 54); - pcpp::NDPNeighborAdvertisementLayer *neighAdvLayer = neighAdvPacket.getLayerOfType(); + pcpp::NDPNeighborAdvertisementLayer* neighAdvLayer = + neighAdvPacket.getLayerOfType(); PTF_ASSERT_EQUAL(neighAdvLayer->getHeaderLen(), 32); PTF_ASSERT_EQUAL((int)neighAdvLayer->getMessageType(), 136); PTF_ASSERT_EQUAL(neighAdvLayer->getCode(), 0); @@ -243,21 +270,26 @@ PTF_TEST_CASE(IcmpV6CreationTest) PTF_ASSERT_EQUAL(neighAdvLayer->getTargetIP(), pcpp::IPv6Address("fe80::c000:54ff:fef5:0")); PTF_ASSERT_EQUAL(neighAdvLayer->getNdpOptionCount(), 1); PTF_ASSERT_EQUAL(neighAdvLayer->getTargetMac(), pcpp::MacAddress("c2:00:54:f5:00:00")); - pcpp::NdpOption targetLinkLayerOption = neighAdvLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + pcpp::NdpOption targetLinkLayerOption = + neighAdvLayer->getNdpOption(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); PTF_ASSERT_TRUE(targetLinkLayerOption.isNotNull()); PTF_ASSERT_EQUAL(targetLinkLayerOption.getDataSize(), 6); PTF_ASSERT_EQUAL(targetLinkLayerOption.getTotalSize(), 8); // Neighbor advertisement without option - pcpp::IPv6Layer *ipv6AdvLayer2 = new pcpp::IPv6Layer(pcpp::IPv6Address("fe80:ebeb:ebeb::1"), pcpp::IPv6Address("fe80:ebeb:ebeb::2")); - pcpp::NDPNeighborAdvertisementLayer *ndpAdvLayer2 = new pcpp::NDPNeighborAdvertisementLayer(0, pcpp::IPv6Address("fe80:ebeb:ebeb::1"), false, true, false); + pcpp::IPv6Layer* ipv6AdvLayer2 = + new pcpp::IPv6Layer(pcpp::IPv6Address("fe80:ebeb:ebeb::1"), pcpp::IPv6Address("fe80:ebeb:ebeb::2")); + pcpp::NDPNeighborAdvertisementLayer* ndpAdvLayer2 = + new pcpp::NDPNeighborAdvertisementLayer(0, pcpp::IPv6Address("fe80:ebeb:ebeb::1"), false, true, false); pcpp::Packet neighAdvPacket2(100); PTF_ASSERT_TRUE(neighAdvPacket2.addLayer(ipv6AdvLayer2, true)); PTF_ASSERT_TRUE(neighAdvPacket2.addLayer(ndpAdvLayer2, true)); neighAdvPacket2.computeCalculateFields(); - PTF_ASSERT_BUF_COMPARE(neighAdvPacket2.getRawPacket()->getRawData()+40, buffer5+54, bufferLength5-58); // dat file contains eth layer (14 bytes) and trailing bytes (4 bytes) + PTF_ASSERT_BUF_COMPARE(neighAdvPacket2.getRawPacket()->getRawData() + 40, buffer5 + 54, + bufferLength5 - 58); // dat file contains eth layer (14 bytes) and trailing bytes (4 bytes) - pcpp::NDPNeighborAdvertisementLayer *neighAdvLayer2 = neighAdvPacket2.getLayerOfType(); + pcpp::NDPNeighborAdvertisementLayer* neighAdvLayer2 = + neighAdvPacket2.getLayerOfType(); PTF_ASSERT_EQUAL(neighAdvLayer2->getHeaderLen(), 24); PTF_ASSERT_EQUAL((int)neighAdvLayer2->getMessageType(), 136); PTF_ASSERT_EQUAL(neighAdvLayer2->getCode(), 0); @@ -271,7 +303,8 @@ PTF_TEST_CASE(IcmpV6CreationTest) PTF_ASSERT_EQUAL(neighAdvLayer2->getTargetMac(), pcpp::MacAddress()); // Generic ICMPv6 packet - pcpp::IPv6Layer *ipv6Layer2 = new pcpp::IPv6Layer(pcpp::IPv6Address("fe80::a00:27ff:fed4:10bb"), pcpp::IPv6Address("ff02::16")); + pcpp::IPv6Layer* ipv6Layer2 = + new pcpp::IPv6Layer(pcpp::IPv6Address("fe80::a00:27ff:fed4:10bb"), pcpp::IPv6Address("ff02::16")); ipv6Layer2->getIPv6Header()->hopLimit = 1; std::vector hopByHopExtOptions; @@ -281,41 +314,46 @@ PTF_TEST_CASE(IcmpV6CreationTest) ipv6Layer2->addExtension(newHopByHopHeader); ipv6Layer2->getDataPtr(40)[0] = 0x3a; - uint8_t data2[44] = {0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0xff, 0x05, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x04, 0x00, - 0x00, 0x00, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x02}; + uint8_t data2[44] = { 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0xff, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 }; - pcpp::IcmpV6Layer *icmpV6GenericLayer = new pcpp::IcmpV6Layer(pcpp::ICMPv6MessageType::ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS, 0, data2, 44); + pcpp::IcmpV6Layer* icmpV6GenericLayer = + new pcpp::IcmpV6Layer(pcpp::ICMPv6MessageType::ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS, 0, data2, 44); pcpp::Packet genericIcmpV6Packet(100); genericIcmpV6Packet.addLayer(ipv6Layer2, true); genericIcmpV6Packet.addLayer(icmpV6GenericLayer, true); genericIcmpV6Packet.computeCalculateFields(); - PTF_ASSERT_BUF_COMPARE(genericIcmpV6Packet.getRawPacket()->getRawData(), buffer6+14, bufferLength6-14); + PTF_ASSERT_BUF_COMPARE(genericIcmpV6Packet.getRawPacket()->getRawData(), buffer6 + 14, bufferLength6 - 14); - delete [] buffer1; - delete [] buffer2; - delete [] buffer3; - delete [] buffer4; - delete [] buffer5; - delete [] buffer6; + delete[] buffer1; + delete[] buffer2; + delete[] buffer3; + delete[] buffer4; + delete[] buffer5; + delete[] buffer6; } PTF_TEST_CASE(IcmpV6EditTest) { // Creates neighbor advertisement packet without option, adds two options and removes options afterwards. - // Note: This is not a real packet, because neighbor advertisement packet can only contain one target link-layer option - // but for testing NDP options and if padding bytes are handled correct (each option must be padded to 64-bit boundary) - pcpp::IPv6Layer *ipv6AdvLayer = new pcpp::IPv6Layer(pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), pcpp::IPv6Address("ff02::1")); - pcpp::NDPNeighborAdvertisementLayer *ndpAdvLayer = new pcpp::NDPNeighborAdvertisementLayer(0, pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), true, false, true); + // Note: This is not a real packet, because neighbor advertisement packet can only contain one target link-layer + // option but for testing NDP options and if padding bytes are handled correct (each option must be padded to 64-bit + // boundary) + pcpp::IPv6Layer* ipv6AdvLayer = + new pcpp::IPv6Layer(pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), pcpp::IPv6Address("ff02::1")); + pcpp::NDPNeighborAdvertisementLayer* ndpAdvLayer = + new pcpp::NDPNeighborAdvertisementLayer(0, pcpp::IPv6Address("fe80::c000:54ff:fef5:0"), true, false, true); pcpp::Packet neighAdvPacket(100); PTF_ASSERT_TRUE(neighAdvPacket.addLayer(ipv6AdvLayer, true)); PTF_ASSERT_TRUE(neighAdvPacket.addLayer(ndpAdvLayer, true)); - pcpp::NDPNeighborAdvertisementLayer *neighAdvLayer = neighAdvPacket.getLayerOfType(); + pcpp::NDPNeighborAdvertisementLayer* neighAdvLayer = + neighAdvPacket.getLayerOfType(); - uint8_t dataOption1[6] = {0xc2, 0x00, 0x54, 0xf5, 0x01, 0x02}; - neighAdvLayer->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER, dataOption1, 4)); // datalen is set to 4 -> for testing padding + uint8_t dataOption1[6] = { 0xc2, 0x00, 0x54, 0xf5, 0x01, 0x02 }; + neighAdvLayer->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER, + dataOption1, 4)); // datalen is set to 4 -> for testing padding PTF_ASSERT_EQUAL(neighAdvLayer->getNdpOptionCount(), 1); PTF_ASSERT_EQUAL(neighAdvLayer->getHeaderLen(), 32); pcpp::NdpOption option1 = neighAdvLayer->getFirstNdpOption(); @@ -327,8 +365,9 @@ PTF_TEST_CASE(IcmpV6EditTest) neighAdvPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(neighAdvLayer->getChecksum(), 0x9abb); - uint8_t dataOption2[6] = {0xc2, 0x00, 0x54, 0xf5, 0x01, 0x02}; - neighAdvLayer->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER, dataOption2, 5)); // datalen is set to 5 -> for testing padding + uint8_t dataOption2[6] = { 0xc2, 0x00, 0x54, 0xf5, 0x01, 0x02 }; + neighAdvLayer->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER, + dataOption2, 5)); // datalen is set to 5 -> for testing padding PTF_ASSERT_EQUAL(neighAdvLayer->getNdpOptionCount(), 2); PTF_ASSERT_EQUAL(neighAdvLayer->getHeaderLen(), 40); pcpp::NdpOption option2 = neighAdvLayer->getNextNdpOption(option1); diff --git a/Tests/Packet++Test/Tests/IgmpTests.cpp b/Tests/Packet++Test/Tests/IgmpTests.cpp index 5c07bbd299..d702d556d8 100644 --- a/Tests/Packet++Test/Tests/IgmpTests.cpp +++ b/Tests/Packet++Test/Tests/IgmpTests.cpp @@ -8,7 +8,6 @@ #include "IgmpLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(IgmpParsingTest) { timeval time; @@ -39,9 +38,7 @@ PTF_TEST_CASE(IgmpParsingTest) PTF_ASSERT_EQUAL(igmpv2Layer->getType(), pcpp::IgmpType_MembershipReportV2, enum); PTF_ASSERT_EQUAL(igmpv2Layer->getGroupAddress(), pcpp::IPv4Address("239.255.255.250")); PTF_ASSERT_EQUAL(igmpv2Layer->toString(), "IGMPv2 Layer, Membership Report message"); -} // IgmpParsingTest - - +} // IgmpParsingTest PTF_TEST_CASE(IgmpCreateAndEditTest) { @@ -84,11 +81,13 @@ PTF_TEST_CASE(IgmpCreateAndEditTest) READ_FILE_INTO_BUFFER(1, "PacketExamples/IGMPv1_1.dat"); READ_FILE_INTO_BUFFER(2, "PacketExamples/IGMPv2_1.dat"); - PTF_ASSERT_EQUAL(igmpv1Packet.getRawPacket()->getRawDataLen(), bufferLength1-14); - PTF_ASSERT_BUF_COMPARE(igmpv1Packet.getRawPacket()->getRawData(), buffer1, igmpv1Packet.getRawPacket()->getRawDataLen()); + PTF_ASSERT_EQUAL(igmpv1Packet.getRawPacket()->getRawDataLen(), bufferLength1 - 14); + PTF_ASSERT_BUF_COMPARE(igmpv1Packet.getRawPacket()->getRawData(), buffer1, + igmpv1Packet.getRawPacket()->getRawDataLen()); - PTF_ASSERT_EQUAL(igmpv2Packet.getRawPacket()->getRawDataLen(), bufferLength2-14); - PTF_ASSERT_BUF_COMPARE(igmpv2Packet.getRawPacket()->getRawData(), buffer2, igmpv2Packet.getRawPacket()->getRawDataLen()); + PTF_ASSERT_EQUAL(igmpv2Packet.getRawPacket()->getRawDataLen(), bufferLength2 - 14); + PTF_ASSERT_BUF_COMPARE(igmpv2Packet.getRawPacket()->getRawData(), buffer2, + igmpv2Packet.getRawPacket()->getRawDataLen()); pcpp::IgmpV1Layer* igmpLayer = igmpv1Packet.getLayerOfType(); igmpLayer->setType(pcpp::IgmpType_MembershipReportV2); @@ -97,11 +96,9 @@ PTF_TEST_CASE(IgmpCreateAndEditTest) PTF_ASSERT_BUF_COMPARE(igmpLayer->getData(), igmpV2Layer.getData(), igmpLayer->getHeaderLen()); - delete [] buffer1; - delete [] buffer2; -} // IgmpCreateAndEditTest - - + delete[] buffer1; + delete[] buffer2; +} // IgmpCreateAndEditTest PTF_TEST_CASE(Igmpv3ParsingTest) { @@ -138,7 +135,6 @@ PTF_TEST_CASE(Igmpv3ParsingTest) PTF_ASSERT_EQUAL(igmpv3QueryLayer->getSourceAddressAtIndex(50).toString(), "0.0.0.0"); PTF_ASSERT_EQUAL(igmpv3QueryLayer->getSourceAddressAtIndex(-1).toString(), "0.0.0.0"); - PTF_ASSERT_TRUE(igmpv3ReportPacket.isPacketOfType(pcpp::IGMPv3)); PTF_ASSERT_TRUE(igmpv3ReportPacket.isPacketOfType(pcpp::IGMP)); PTF_ASSERT_FALSE(igmpv3ReportPacket.isPacketOfType(pcpp::IGMPv1)); @@ -159,9 +155,7 @@ PTF_TEST_CASE(Igmpv3ParsingTest) curGroup = igmpv3ReportLayer->getNextGroupRecord(curGroup); PTF_ASSERT_NULL(curGroup); PTF_ASSERT_EQUAL(igmpv3ReportLayer->toString(), "IGMPv3 Layer, Membership Report message"); -} // Igmpv3ParsingTest - - +} // Igmpv3ParsingTest PTF_TEST_CASE(Igmpv3QueryCreateAndEditTest) { @@ -211,7 +205,8 @@ PTF_TEST_CASE(Igmpv3QueryCreateAndEditTest) READ_FILE_INTO_BUFFER(1, "PacketExamples/igmpv3_query2.dat"); PTF_ASSERT_EQUAL(igmpv3QueryPacket.getRawPacket()->getRawDataLen(), bufferLength1); - PTF_ASSERT_BUF_COMPARE(igmpv3QueryPacket.getRawPacket()->getRawData(), buffer1, igmpv3QueryPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(igmpv3QueryPacket.getRawPacket()->getRawData(), buffer1, + igmpv3QueryPacket.getRawPacket()->getRawDataLen()); delete[] buffer1; @@ -238,14 +233,13 @@ PTF_TEST_CASE(Igmpv3QueryCreateAndEditTest) READ_FILE_INTO_BUFFER(2, "PacketExamples/igmpv3_query.dat"); PTF_ASSERT_EQUAL(igmpv3QueryPacket.getRawPacket()->getRawDataLen(), bufferLength2); - PTF_ASSERT_BUF_COMPARE(igmpv3QueryPacket.getRawPacket()->getRawData(), buffer2, igmpv3QueryPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(igmpv3QueryPacket.getRawPacket()->getRawData(), buffer2, + igmpv3QueryPacket.getRawPacket()->getRawDataLen()); delete[] buffer2; PTF_ASSERT_TRUE(igmpV3QueryLayer.removeAllSourceAddresses()); -} // Igmpv3QueryCreateAndEditTest - - +} // Igmpv3QueryCreateAndEditTest PTF_TEST_CASE(Igmpv3ReportCreateAndEditTest) { @@ -262,7 +256,8 @@ PTF_TEST_CASE(Igmpv3ReportCreateAndEditTest) std::vector srcAddrVec1; srcAddrVec1.push_back(pcpp::IPv4Address("192.168.20.222")); - pcpp::igmpv3_group_record* groupRec = igmpV3ReportLayer.addGroupRecord(1, pcpp::IPv4Address("224.0.0.9"), srcAddrVec1); + pcpp::igmpv3_group_record* groupRec = + igmpV3ReportLayer.addGroupRecord(1, pcpp::IPv4Address("224.0.0.9"), srcAddrVec1); PTF_ASSERT_NOT_NULL(groupRec); PTF_ASSERT_EQUAL(groupRec->getSourceAddressAtIndex(0), pcpp::IPv4Address("192.168.20.222")); @@ -298,7 +293,6 @@ PTF_TEST_CASE(Igmpv3ReportCreateAndEditTest) groupRec = igmpV3ReportLayer.addGroupRecordAtIndex(5, pcpp::IPv4Address("2.4.6.8"), srcAddrVec4, 4); PTF_ASSERT_NOT_NULL(groupRec); - pcpp::Packet igmpv3ReportPacket; PTF_ASSERT_TRUE(igmpv3ReportPacket.addLayer(ðLayer)); PTF_ASSERT_TRUE(igmpv3ReportPacket.addLayer(&ipLayer)); @@ -309,11 +303,11 @@ PTF_TEST_CASE(Igmpv3ReportCreateAndEditTest) READ_FILE_INTO_BUFFER(1, "PacketExamples/igmpv3_report2.dat"); PTF_ASSERT_EQUAL(igmpv3ReportPacket.getRawPacket()->getRawDataLen(), bufferLength1); - PTF_ASSERT_BUF_COMPARE(igmpv3ReportPacket.getRawPacket()->getRawData(), buffer1, igmpv3ReportPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(igmpv3ReportPacket.getRawPacket()->getRawData(), buffer1, + igmpv3ReportPacket.getRawPacket()->getRawDataLen()); delete[] buffer1; - PTF_ASSERT_TRUE(igmpV3ReportLayer.removeGroupRecordAtIndex(4)); pcpp::Logger::getInstance().suppressLogs(); @@ -333,9 +327,10 @@ PTF_TEST_CASE(Igmpv3ReportCreateAndEditTest) igmpv3ReportPacket.computeCalculateFields(); ipLayer.getIPv4Header()->headerChecksum = 0x4fb6; - PTF_ASSERT_BUF_COMPARE(igmpv3ReportPacket.getRawPacket()->getRawData(), buffer2, igmpv3ReportPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(igmpv3ReportPacket.getRawPacket()->getRawData(), buffer2, + igmpv3ReportPacket.getRawPacket()->getRawDataLen()); delete[] buffer2; PTF_ASSERT_TRUE(igmpV3ReportLayer.removeAllGroupRecords()); -} // Igmpv3ReportCreateAndEditTest +} // Igmpv3ReportCreateAndEditTest diff --git a/Tests/Packet++Test/Tests/LLCTests.cpp b/Tests/Packet++Test/Tests/LLCTests.cpp index 6869ae9ea4..0d62a5c518 100644 --- a/Tests/Packet++Test/Tests/LLCTests.cpp +++ b/Tests/Packet++Test/Tests/LLCTests.cpp @@ -17,10 +17,10 @@ PTF_TEST_CASE(LLCParsingTests) pcpp::Packet llcPacket1(&rawPacket1); PTF_ASSERT_TRUE(llcPacket1.isPacketOfType(pcpp::LLC)); - pcpp::LLCLayer *llcLayer1 = llcPacket1.getLayerOfType(); + pcpp::LLCLayer* llcLayer1 = llcPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(llcLayer1); - pcpp::llc_header *header1 = llcLayer1->getLlcHeader(); + pcpp::llc_header* header1 = llcLayer1->getLlcHeader(); PTF_ASSERT_EQUAL(header1->dsap, 0x42); PTF_ASSERT_EQUAL(header1->ssap, 0x42); PTF_ASSERT_EQUAL(header1->control, 0x3); @@ -32,15 +32,15 @@ PTF_TEST_CASE(LLCParsingTests) READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/llc_vlan.dat"); pcpp::Packet llcPacket2(&rawPacket2); - pcpp::LLCLayer *llcLayer2 = llcPacket2.getLayerOfType(); + pcpp::LLCLayer* llcLayer2 = llcPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(llcLayer2); - pcpp::llc_header *header2 = llcLayer2->getLlcHeader(); + pcpp::llc_header* header2 = llcLayer2->getLlcHeader(); PTF_ASSERT_EQUAL(header2->dsap, 0xaa); PTF_ASSERT_EQUAL(header2->ssap, 0xaa); PTF_ASSERT_EQUAL(header2->control, 0x3); -} // LLCParsingTests +} // LLCParsingTests PTF_TEST_CASE(LLCCreationTests) { @@ -52,9 +52,9 @@ PTF_TEST_CASE(LLCCreationTests) pcpp::Packet llcPacket1(&rawPacket1); PTF_ASSERT_TRUE(llcPacket1.isPacketOfType(pcpp::LLC)); - pcpp::LLCLayer *llcLayer1 = llcPacket1.getLayerOfType(); + pcpp::LLCLayer* llcLayer1 = llcPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(llcLayer1); pcpp::LLCLayer craftedLayer1(0x42, 0x42, 0x3); PTF_ASSERT_BUF_COMPARE(llcLayer1->getData(), craftedLayer1.getData(), craftedLayer1.getDataLen()); -} // LLCCreationTests +} // LLCCreationTests diff --git a/Tests/Packet++Test/Tests/LdapTests.cpp b/Tests/Packet++Test/Tests/LdapTests.cpp index e57f5b2aab..75545c6996 100644 --- a/Tests/Packet++Test/Tests/LdapTests.cpp +++ b/Tests/Packet++Test/Tests/LdapTests.cpp @@ -31,9 +31,10 @@ PTF_TEST_CASE(LdapParsingTest) pcpp::Asn1EnumeratedRecord enumeratedRecord(0); pcpp::Asn1OctetStringRecord stringRecord1(""); pcpp::Asn1OctetStringRecord stringRecord2(""); - pcpp::Asn1ConstructedRecord expectedOperationRecord(pcpp::Asn1TagClass::Application, 9, {&enumeratedRecord, &stringRecord1, &stringRecord2}); + pcpp::Asn1ConstructedRecord expectedOperationRecord(pcpp::Asn1TagClass::Application, 9, + { &enumeratedRecord, &stringRecord1, &stringRecord2 }); - pcpp::Asn1SequenceRecord expectedRootRecord({&messageIdRecord, &expectedOperationRecord}); + pcpp::Asn1SequenceRecord expectedRootRecord({ &messageIdRecord, &expectedOperationRecord }); PTF_ASSERT_EQUAL(ldapLayer->getRootAsn1Record()->toString(), expectedRootRecord.toString()); PTF_ASSERT_EQUAL(ldapLayer->getLdapOperationAsn1Record()->toString(), expectedOperationRecord.toString()); @@ -48,10 +49,12 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_NOT_NULL(ldapLayer); auto controls = ldapLayer->getControls(); + // clang-format off std::vector expectedControls = { - {"1.2.840.113556.1.4.801", "3003020107"}, - {"1.2.840.113556.1.4.319", "3006020201f40400"} + { "1.2.840.113556.1.4.801", "3003020107" }, + { "1.2.840.113556.1.4.319", "3006020201f40400" } }; + // clang-format on PTF_ASSERT_VECTORS_EQUAL(controls, expectedControls); } @@ -64,7 +67,7 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_NOT_NULL(ldapLayer); auto controls = ldapLayer->getControls(); - std::vector expectedControls = {{"1.3.6.1.4.1.42.2.27.8.5.1"}}; + std::vector expectedControls = { { "1.3.6.1.4.1.42.2.27.8.5.1" } }; PTF_ASSERT_VECTORS_EQUAL(controls, expectedControls); } @@ -82,7 +85,7 @@ PTF_TEST_CASE(LdapParsingTest) std::vector controls; PTF_ASSERT_TRUE(malformedLdapLayer->tryGet(&pcpp::LdapLayer::getControls, controls)); - std::vector expectedControls = {{"1.3.6.1.4.1.42.2.27.8.5.1"}}; + std::vector expectedControls = { { "1.3.6.1.4.1.42.2.27.8.5.1" } }; PTF_ASSERT_VECTORS_EQUAL(controls, expectedControls); } @@ -116,11 +119,14 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_EQUAL(bindRequestLayer->getLdapOperationType(), pcpp::LdapOperationType::BindRequest, enum); PTF_ASSERT_EQUAL(bindRequestLayer->getVersion(), 3); PTF_ASSERT_EQUAL(bindRequestLayer->getName(), "cn=Administrator,cn=Users,dc=cloudshark-a,dc=example,dc=com"); - PTF_ASSERT_EQUAL(bindRequestLayer->getAuthenticationType(), pcpp::LdapBindRequestLayer::AuthenticationType::Simple, enumclass); + PTF_ASSERT_EQUAL(bindRequestLayer->getAuthenticationType(), + pcpp::LdapBindRequestLayer::AuthenticationType::Simple, enumclass); PTF_ASSERT_EQUAL(bindRequestLayer->getSimpleAuthentication(), "cloudshark123!"); - PTF_ASSERT_RAISES(bindRequestLayer->getSaslAuthentication(), std::invalid_argument, "Authentication type is not sasl"); + PTF_ASSERT_RAISES(bindRequestLayer->getSaslAuthentication(), std::invalid_argument, + "Authentication type is not sasl"); pcpp::LdapBindRequestLayer::SaslAuthentication saslAuthentication; - PTF_ASSERT_FALSE(bindRequestLayer->tryGet(&pcpp::LdapBindRequestLayer::getSaslAuthentication, saslAuthentication)); + PTF_ASSERT_FALSE( + bindRequestLayer->tryGet(&pcpp::LdapBindRequestLayer::getSaslAuthentication, saslAuthentication)); PTF_ASSERT_EQUAL(bindRequestLayer->toString(), "LDAP Layer, BindRequest, simple"); } @@ -135,49 +141,95 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_EQUAL(bindRequestLayer->getLdapOperationType(), pcpp::LdapOperationType::BindRequest, enum); PTF_ASSERT_EQUAL(bindRequestLayer->getVersion(), 3); PTF_ASSERT_EQUAL(bindRequestLayer->getName(), ""); - PTF_ASSERT_EQUAL(bindRequestLayer->getAuthenticationType(), pcpp::LdapBindRequestLayer::AuthenticationType::Sasl, enumclass); - pcpp::LdapBindRequestLayer::SaslAuthentication expectedSaslAuthentication { + PTF_ASSERT_EQUAL(bindRequestLayer->getAuthenticationType(), + pcpp::LdapBindRequestLayer::AuthenticationType::Sasl, enumclass); + pcpp::LdapBindRequestLayer::SaslAuthentication expectedSaslAuthentication{ "GSS-SPNEGO", - {0x60, 0x82, 0x05, 0x1a, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02, 0xa0, 0x82, 0x05, 0x0e, 0x30, 0x82, 0x05, 0x0a, 0xa0, 0x24, 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x82, 0x04, 0xe0, 0x04, 0x82, 0x04, 0xdc, 0x60, 0x82, 0x04, 0xd8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x12, 0x01, 0x02, 0x02, 0x01, 0x00, 0x6e, 0x82, 0x04, 0xc7, 0x30, 0x82, 0x04, 0xc3, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0e, 0xa2, 0x07, 0x03, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa3, 0x82, 0x03, 0xe0, - 0x61, 0x82, 0x03, 0xdc, 0x30, 0x82, 0x03, 0xd8, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x15, 0x1b, 0x13, 0x57, 0x32, 0x4b, 0x33, 0x2e, 0x56, 0x4d, 0x4e, 0x45, 0x54, 0x31, 0x2e, 0x56, 0x4d, 0x2e, 0x42, 0x41, 0x53, 0x45, 0xa2, 0x2f, - 0x30, 0x2d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x26, 0x30, 0x24, 0x1b, 0x04, 0x6c, 0x64, 0x61, 0x70, 0x1b, 0x1c, 0x77, 0x32, 0x6b, 0x33, 0x2d, 0x31, 0x30, 0x31, 0x2e, 0x77, 0x32, 0x6b, 0x33, 0x2e, 0x76, 0x6d, 0x6e, 0x65, 0x74, - 0x31, 0x2e, 0x76, 0x6d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0xa3, 0x82, 0x03, 0x87, 0x30, 0x82, 0x03, 0x83, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa1, 0x03, 0x02, 0x01, 0x07, 0xa2, 0x82, 0x03, 0x75, 0x04, 0x82, 0x03, 0x71, 0x6a, 0x61, 0xc8, - 0x86, 0xba, 0x58, 0xd1, 0x62, 0x11, 0x3d, 0xb4, 0x26, 0x8f, 0x77, 0x43, 0xa1, 0x7e, 0xb4, 0x76, 0x18, 0x3b, 0xc0, 0xc5, 0x19, 0xad, 0xde, 0xa7, 0x65, 0x56, 0xa3, 0x70, 0x1d, 0xe3, 0x49, 0x03, 0xe6, 0xbd, 0x3f, 0x3f, 0xdc, 0xa0, - 0xb0, 0x1b, 0xbc, 0xcb, 0x9a, 0x86, 0x93, 0xb2, 0x3f, 0xa8, 0xd1, 0x98, 0x5e, 0x14, 0x92, 0x2e, 0x4c, 0xa1, 0x9b, 0x05, 0xa9, 0x07, 0x69, 0x84, 0x5a, 0x58, 0x58, 0x51, 0x5b, 0xba, 0x4a, 0xf2, 0xd7, 0xe5, 0x9b, 0xfa, 0x86, 0x34, - 0x28, 0x5a, 0x2e, 0x95, 0x4f, 0xb5, 0x18, 0x37, 0x8b, 0x8d, 0x3f, 0x27, 0x44, 0xb9, 0xbb, 0xf8, 0x84, 0x2b, 0x48, 0x07, 0x87, 0x9f, 0xf2, 0x8e, 0x55, 0xbf, 0xba, 0x49, 0x67, 0xe8, 0xc1, 0xd3, 0xb6, 0xc4, 0xe3, 0x58, 0xa5, 0x61, - 0xc5, 0x4a, 0xbb, 0xc1, 0xcb, 0x7c, 0x97, 0xb6, 0x50, 0x3f, 0xe5, 0x9b, 0x7f, 0xee, 0x64, 0x23, 0xdf, 0xfe, 0x66, 0xfe, 0x6d, 0xcb, 0x8a, 0xf0, 0x0e, 0x69, 0xc5, 0x3d, 0x6b, 0x57, 0x6f, 0x55, 0x06, 0x99, 0x04, 0x38, 0x31, 0x0f, - 0xb7, 0xdd, 0x14, 0x68, 0xa3, 0x2f, 0xd8, 0xe0, 0xde, 0xab, 0x40, 0xb1, 0x5e, 0xcf, 0xd4, 0x38, 0x56, 0x83, 0x70, 0x14, 0x0a, 0x1e, 0xda, 0xfe, 0xe7, 0x01, 0xa4, 0xa4, 0xb4, 0xe7, 0xb3, 0xaa, 0xef, 0xdc, 0x4b, 0x1a, 0xff, 0x58, - 0x68, 0xae, 0xfe, 0x5a, 0x36, 0x29, 0x4d, 0x5d, 0xd6, 0x87, 0xd5, 0xa6, 0x49, 0x31, 0x43, 0xd3, 0xad, 0xe8, 0x03, 0x1c, 0x98, 0xd2, 0x8f, 0x6c, 0x7f, 0x3d, 0xce, 0xa4, 0x14, 0x35, 0x13, 0x2f, 0x67, 0x5f, 0x26, 0x94, 0x0d, 0x1f, - 0x69, 0xe5, 0x73, 0xe5, 0xec, 0xe6, 0xed, 0x5a, 0x66, 0x11, 0x1f, 0xf9, 0xf4, 0xb0, 0x2a, 0x8d, 0xdd, 0x19, 0x08, 0x6e, 0x5b, 0x9d, 0xc0, 0xad, 0xc8, 0x6a, 0x0b, 0xc1, 0x23, 0x0f, 0x1b, 0x71, 0x5f, 0xfc, 0x40, 0x04, 0xdf, 0xc4, - 0xa7, 0xd5, 0xf7, 0x8a, 0x4d, 0xc3, 0x1a, 0xbf, 0x83, 0x0a, 0xe6, 0xe3, 0xbf, 0xd2, 0x1c, 0x87, 0xfa, 0x51, 0x96, 0x54, 0x9e, 0x13, 0x0f, 0x6a, 0x08, 0x1b, 0xaf, 0xcf, 0x41, 0x70, 0xae, 0x20, 0x1c, 0x78, 0xa3, 0x82, 0x9a, 0x01, - 0xdb, 0xa5, 0x78, 0xa2, 0xef, 0x96, 0x8f, 0x2a, 0xb6, 0x66, 0x8d, 0x81, 0x14, 0xdf, 0xcc, 0x65, 0xd7, 0x03, 0x8f, 0x55, 0x58, 0xbe, 0x7c, 0xdd, 0x92, 0x46, 0xd5, 0x22, 0x47, 0x91, 0x52, 0x60, 0xa4, 0x0e, 0x59, 0xc4, 0x8b, 0x08, - 0xa1, 0xed, 0x61, 0x42, 0x7f, 0xd3, 0x03, 0x91, 0x7c, 0x6b, 0x34, 0xb7, 0x01, 0xa4, 0xba, 0x9a, 0x38, 0x15, 0xd4, 0x82, 0x8a, 0x22, 0x8c, 0xd2, 0x09, 0xda, 0x13, 0x76, 0x26, 0xe2, 0x02, 0x9a, 0xab, 0xf6, 0xc2, 0x00, 0xbf, 0x7f, - 0xd6, 0x3c, 0xf6, 0xd4, 0x3b, 0xb6, 0x18, 0xb3, 0x1a, 0xc4, 0x8e, 0x09, 0x61, 0x35, 0x89, 0xd7, 0x4a, 0x69, 0x54, 0x2e, 0x90, 0x9c, 0xe0, 0xdc, 0x9c, 0x57, 0xc7, 0x7f, 0x7d, 0x89, 0xb9, 0x66, 0xde, 0x20, 0x00, 0x53, 0xa5, 0x8e, - 0xa5, 0x8f, 0x23, 0x74, 0x51, 0x39, 0x61, 0x63, 0x8a, 0x30, 0xca, 0x49, 0xef, 0x0e, 0xec, 0x67, 0x9d, 0x92, 0x7e, 0x38, 0x5b, 0x5d, 0xa7, 0xd4, 0xd3, 0xc1, 0xa5, 0x91, 0x69, 0xb4, 0x63, 0x0b, 0x87, 0x4a, 0x1d, 0x96, 0x9e, 0x45, - 0xd1, 0xfe, 0x37, 0x82, 0x08, 0x9f, 0x43, 0x85, 0x02, 0x49, 0x55, 0x09, 0x3b, 0x30, 0x8e, 0x19, 0x64, 0xd3, 0x07, 0x91, 0x52, 0x71, 0xaa, 0x88, 0x6c, 0x3d, 0x9b, 0x64, 0xd8, 0x46, 0xc8, 0x8c, 0xa1, 0x34, 0x1f, 0xd2, 0xf7, 0x2b, - 0x76, 0x67, 0x9d, 0x4f, 0x25, 0x8f, 0x64, 0x7b, 0xc0, 0x48, 0x20, 0xe4, 0x27, 0x76, 0xc9, 0xec, 0x0d, 0x01, 0x46, 0x46, 0x52, 0x76, 0x3a, 0x49, 0xd8, 0x22, 0xc9, 0xd2, 0x5b, 0x60, 0x39, 0x03, 0xeb, 0xd6, 0x33, 0x89, 0x52, 0x25, - 0x9b, 0x83, 0xa7, 0x40, 0xa4, 0x20, 0xd6, 0x9d, 0x23, 0xae, 0xbb, 0xdf, 0x06, 0xa9, 0x2d, 0x88, 0xa4, 0x6f, 0xfc, 0xd8, 0xd8, 0x1a, 0x47, 0xb6, 0xec, 0x99, 0xb6, 0xce, 0xa0, 0x48, 0x9c, 0xc8, 0x3e, 0xf1, 0x57, 0x57, 0xc4, 0x05, - 0x3d, 0x53, 0x84, 0x46, 0xf2, 0xe6, 0xb9, 0xeb, 0xa1, 0x2c, 0xe4, 0x96, 0x9b, 0x8d, 0x6d, 0xf9, 0xb3, 0xef, 0x57, 0x4b, 0x7d, 0x40, 0x13, 0x41, 0xc2, 0xf5, 0x55, 0xa0, 0x0f, 0x02, 0x91, 0x64, 0xe5, 0xd3, 0x87, 0x28, 0x2c, 0x0c, - 0x87, 0x91, 0xba, 0x8c, 0x69, 0x81, 0x62, 0x48, 0xe2, 0xe5, 0x44, 0xa9, 0xc1, 0x2b, 0x7a, 0xeb, 0xa6, 0x29, 0xfd, 0xee, 0xa2, 0xe1, 0x11, 0x65, 0x5e, 0x44, 0xb9, 0xc2, 0x15, 0x92, 0x4c, 0x54, 0x55, 0xea, 0xa4, 0xab, 0x32, 0xae, - 0xa1, 0xd9, 0xce, 0xf1, 0xd8, 0x6e, 0x8a, 0xcf, 0x6b, 0x0f, 0xf4, 0xdc, 0xab, 0xaf, 0x4f, 0x0e, 0x2d, 0x9a, 0xe6, 0x5c, 0x8b, 0xb1, 0x06, 0x5e, 0x04, 0x18, 0xff, 0x12, 0xd4, 0x62, 0x69, 0x30, 0x31, 0x59, 0x38, 0xbf, 0xe0, 0x0a, - 0x8d, 0x03, 0xe8, 0xe7, 0x0e, 0x9d, 0xea, 0x9d, 0xc9, 0xff, 0x74, 0x85, 0x4c, 0xbb, 0x4d, 0xbd, 0xf7, 0x00, 0xa6, 0x2e, 0x77, 0xb2, 0x6e, 0x50, 0xb1, 0x3e, 0x2d, 0x39, 0x60, 0xc9, 0x13, 0x36, 0x0c, 0x84, 0xc8, 0x7e, 0x80, 0x1e, - 0xd3, 0xdf, 0x3d, 0xb0, 0xe2, 0x76, 0x04, 0x50, 0x8c, 0xb7, 0x30, 0xc5, 0xa0, 0x52, 0xc0, 0x68, 0xab, 0xe5, 0x82, 0x6b, 0x01, 0xbe, 0x9f, 0x62, 0xe3, 0x3b, 0x9a, 0xf8, 0xed, 0xb6, 0x66, 0x7c, 0x57, 0xcb, 0x1a, 0xa8, 0x79, 0x74, - 0x3b, 0x77, 0xa7, 0x43, 0x2f, 0x75, 0xfe, 0x3a, 0xe2, 0x11, 0xf9, 0x6a, 0xf4, 0x1a, 0xde, 0xf1, 0xe1, 0xc5, 0x07, 0x25, 0x6f, 0xe5, 0xfa, 0x2b, 0xcc, 0xab, 0xe5, 0x2c, 0xf8, 0x21, 0x6d, 0x34, 0x10, 0xe6, 0x37, 0x85, 0x06, 0xd4, - 0x27, 0x34, 0x34, 0x58, 0x33, 0x2d, 0x15, 0x3a, 0x77, 0xa1, 0x62, 0xc4, 0xc5, 0xf1, 0x8d, 0x9f, 0x31, 0xb0, 0xc1, 0x42, 0x88, 0x0c, 0xad, 0x22, 0x29, 0x98, 0x17, 0x20, 0x61, 0x5a, 0xb2, 0x6b, 0x7c, 0x13, 0x44, 0x2e, 0x43, 0x17, - 0x8a, 0xad, 0xee, 0x43, 0x65, 0x10, 0xc9, 0x1b, 0xc9, 0xd5, 0xd7, 0x35, 0xeb, 0x94, 0x53, 0xcf, 0x39, 0xce, 0xf5, 0x12, 0x0e, 0x28, 0x60, 0x37, 0x75, 0xf0, 0x48, 0x3f, 0x01, 0xc3, 0xc4, 0x8b, 0x5b, 0x06, 0x0c, 0xa7, 0xf3, 0xa5, - 0x4d, 0x7c, 0x7c, 0x99, 0xa4, 0x81, 0xc9, 0x30, 0x81, 0xc6, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa2, 0x81, 0xbe, 0x04, 0x81, 0xbb, 0x03, 0xab, 0x65, 0x67, 0x60, 0xa3, 0x51, 0x2f, 0xec, 0xc7, 0x03, 0x2d, 0xa8, 0xb2, 0x01, 0x46, 0x59, - 0xf0, 0xfb, 0x34, 0xeb, 0x76, 0xb4, 0x61, 0xe4, 0x04, 0x4d, 0xa2, 0x4d, 0x16, 0xd4, 0x58, 0xe3, 0xe1, 0xc5, 0x89, 0x19, 0xc7, 0x4c, 0x4c, 0x07, 0x20, 0xaa, 0xfb, 0x87, 0xa9, 0x48, 0x15, 0x23, 0x72, 0xa2, 0x48, 0x3a, 0x4d, 0x1a, - 0xe9, 0xb9, 0x5b, 0x85, 0x8a, 0x52, 0xab, 0xaa, 0x94, 0xe7, 0xaa, 0x64, 0x1a, 0x8b, 0x99, 0x7d, 0x7e, 0x6c, 0x6e, 0x57, 0x0b, 0x59, 0x08, 0xcc, 0x54, 0x91, 0x55, 0xf5, 0xe6, 0xf1, 0x10, 0xc9, 0x8d, 0x64, 0x89, 0x78, 0x72, 0x7a, - 0xba, 0xe3, 0x92, 0x1d, 0xa5, 0x2a, 0x4c, 0x1f, 0xd7, 0x6b, 0xeb, 0x12, 0x1b, 0xf3, 0x39, 0x6b, 0xe8, 0xf9, 0x8e, 0x4a, 0xcf, 0x1e, 0xbf, 0xc3, 0xb6, 0xfb, 0x7a, 0x13, 0x54, 0xc1, 0x21, 0x87, 0x3e, 0x59, 0x18, 0x5d, 0xb9, 0x00, - 0x30, 0x08, 0x4d, 0x97, 0x86, 0x47, 0x98, 0xd7, 0x9e, 0xb9, 0xdf, 0x30, 0x75, 0x6c, 0xa1, 0xfa, 0xa7, 0xa8, 0x08, 0x80, 0xf7, 0x4f, 0x7d, 0x93, 0x64, 0x2d, 0x9c, 0xeb, 0x5e, 0x01, 0x28, 0xce, 0xd6, 0xab, 0x09, 0x6a, 0x4f, 0x01, - 0x5e, 0x5a, 0x03, 0x2b, 0x42, 0x70, 0x23, 0x1e, 0x7f, 0xf1, 0xbc, 0xd0, 0x87, 0xe8, 0xb5, 0x27, 0x02, 0x7d} + { 0x60, 0x82, 0x05, 0x1a, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02, 0xa0, 0x82, 0x05, 0x0e, 0x30, + 0x82, 0x05, 0x0a, 0xa0, 0x24, 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, + 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x0a, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x82, 0x04, 0xe0, 0x04, 0x82, 0x04, 0xdc, 0x60, 0x82, + 0x04, 0xd8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x01, 0x00, 0x6e, 0x82, + 0x04, 0xc7, 0x30, 0x82, 0x04, 0xc3, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0e, 0xa2, + 0x07, 0x03, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa3, 0x82, 0x03, 0xe0, 0x61, 0x82, 0x03, 0xdc, 0x30, + 0x82, 0x03, 0xd8, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x15, 0x1b, 0x13, 0x57, 0x32, 0x4b, 0x33, 0x2e, + 0x56, 0x4d, 0x4e, 0x45, 0x54, 0x31, 0x2e, 0x56, 0x4d, 0x2e, 0x42, 0x41, 0x53, 0x45, 0xa2, 0x2f, 0x30, + 0x2d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x26, 0x30, 0x24, 0x1b, 0x04, 0x6c, 0x64, 0x61, 0x70, 0x1b, + 0x1c, 0x77, 0x32, 0x6b, 0x33, 0x2d, 0x31, 0x30, 0x31, 0x2e, 0x77, 0x32, 0x6b, 0x33, 0x2e, 0x76, 0x6d, + 0x6e, 0x65, 0x74, 0x31, 0x2e, 0x76, 0x6d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0xa3, 0x82, 0x03, 0x87, 0x30, + 0x82, 0x03, 0x83, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa1, 0x03, 0x02, 0x01, 0x07, 0xa2, 0x82, 0x03, 0x75, + 0x04, 0x82, 0x03, 0x71, 0x6a, 0x61, 0xc8, 0x86, 0xba, 0x58, 0xd1, 0x62, 0x11, 0x3d, 0xb4, 0x26, 0x8f, + 0x77, 0x43, 0xa1, 0x7e, 0xb4, 0x76, 0x18, 0x3b, 0xc0, 0xc5, 0x19, 0xad, 0xde, 0xa7, 0x65, 0x56, 0xa3, + 0x70, 0x1d, 0xe3, 0x49, 0x03, 0xe6, 0xbd, 0x3f, 0x3f, 0xdc, 0xa0, 0xb0, 0x1b, 0xbc, 0xcb, 0x9a, 0x86, + 0x93, 0xb2, 0x3f, 0xa8, 0xd1, 0x98, 0x5e, 0x14, 0x92, 0x2e, 0x4c, 0xa1, 0x9b, 0x05, 0xa9, 0x07, 0x69, + 0x84, 0x5a, 0x58, 0x58, 0x51, 0x5b, 0xba, 0x4a, 0xf2, 0xd7, 0xe5, 0x9b, 0xfa, 0x86, 0x34, 0x28, 0x5a, + 0x2e, 0x95, 0x4f, 0xb5, 0x18, 0x37, 0x8b, 0x8d, 0x3f, 0x27, 0x44, 0xb9, 0xbb, 0xf8, 0x84, 0x2b, 0x48, + 0x07, 0x87, 0x9f, 0xf2, 0x8e, 0x55, 0xbf, 0xba, 0x49, 0x67, 0xe8, 0xc1, 0xd3, 0xb6, 0xc4, 0xe3, 0x58, + 0xa5, 0x61, 0xc5, 0x4a, 0xbb, 0xc1, 0xcb, 0x7c, 0x97, 0xb6, 0x50, 0x3f, 0xe5, 0x9b, 0x7f, 0xee, 0x64, + 0x23, 0xdf, 0xfe, 0x66, 0xfe, 0x6d, 0xcb, 0x8a, 0xf0, 0x0e, 0x69, 0xc5, 0x3d, 0x6b, 0x57, 0x6f, 0x55, + 0x06, 0x99, 0x04, 0x38, 0x31, 0x0f, 0xb7, 0xdd, 0x14, 0x68, 0xa3, 0x2f, 0xd8, 0xe0, 0xde, 0xab, 0x40, + 0xb1, 0x5e, 0xcf, 0xd4, 0x38, 0x56, 0x83, 0x70, 0x14, 0x0a, 0x1e, 0xda, 0xfe, 0xe7, 0x01, 0xa4, 0xa4, + 0xb4, 0xe7, 0xb3, 0xaa, 0xef, 0xdc, 0x4b, 0x1a, 0xff, 0x58, 0x68, 0xae, 0xfe, 0x5a, 0x36, 0x29, 0x4d, + 0x5d, 0xd6, 0x87, 0xd5, 0xa6, 0x49, 0x31, 0x43, 0xd3, 0xad, 0xe8, 0x03, 0x1c, 0x98, 0xd2, 0x8f, 0x6c, + 0x7f, 0x3d, 0xce, 0xa4, 0x14, 0x35, 0x13, 0x2f, 0x67, 0x5f, 0x26, 0x94, 0x0d, 0x1f, 0x69, 0xe5, 0x73, + 0xe5, 0xec, 0xe6, 0xed, 0x5a, 0x66, 0x11, 0x1f, 0xf9, 0xf4, 0xb0, 0x2a, 0x8d, 0xdd, 0x19, 0x08, 0x6e, + 0x5b, 0x9d, 0xc0, 0xad, 0xc8, 0x6a, 0x0b, 0xc1, 0x23, 0x0f, 0x1b, 0x71, 0x5f, 0xfc, 0x40, 0x04, 0xdf, + 0xc4, 0xa7, 0xd5, 0xf7, 0x8a, 0x4d, 0xc3, 0x1a, 0xbf, 0x83, 0x0a, 0xe6, 0xe3, 0xbf, 0xd2, 0x1c, 0x87, + 0xfa, 0x51, 0x96, 0x54, 0x9e, 0x13, 0x0f, 0x6a, 0x08, 0x1b, 0xaf, 0xcf, 0x41, 0x70, 0xae, 0x20, 0x1c, + 0x78, 0xa3, 0x82, 0x9a, 0x01, 0xdb, 0xa5, 0x78, 0xa2, 0xef, 0x96, 0x8f, 0x2a, 0xb6, 0x66, 0x8d, 0x81, + 0x14, 0xdf, 0xcc, 0x65, 0xd7, 0x03, 0x8f, 0x55, 0x58, 0xbe, 0x7c, 0xdd, 0x92, 0x46, 0xd5, 0x22, 0x47, + 0x91, 0x52, 0x60, 0xa4, 0x0e, 0x59, 0xc4, 0x8b, 0x08, 0xa1, 0xed, 0x61, 0x42, 0x7f, 0xd3, 0x03, 0x91, + 0x7c, 0x6b, 0x34, 0xb7, 0x01, 0xa4, 0xba, 0x9a, 0x38, 0x15, 0xd4, 0x82, 0x8a, 0x22, 0x8c, 0xd2, 0x09, + 0xda, 0x13, 0x76, 0x26, 0xe2, 0x02, 0x9a, 0xab, 0xf6, 0xc2, 0x00, 0xbf, 0x7f, 0xd6, 0x3c, 0xf6, 0xd4, + 0x3b, 0xb6, 0x18, 0xb3, 0x1a, 0xc4, 0x8e, 0x09, 0x61, 0x35, 0x89, 0xd7, 0x4a, 0x69, 0x54, 0x2e, 0x90, + 0x9c, 0xe0, 0xdc, 0x9c, 0x57, 0xc7, 0x7f, 0x7d, 0x89, 0xb9, 0x66, 0xde, 0x20, 0x00, 0x53, 0xa5, 0x8e, + 0xa5, 0x8f, 0x23, 0x74, 0x51, 0x39, 0x61, 0x63, 0x8a, 0x30, 0xca, 0x49, 0xef, 0x0e, 0xec, 0x67, 0x9d, + 0x92, 0x7e, 0x38, 0x5b, 0x5d, 0xa7, 0xd4, 0xd3, 0xc1, 0xa5, 0x91, 0x69, 0xb4, 0x63, 0x0b, 0x87, 0x4a, + 0x1d, 0x96, 0x9e, 0x45, 0xd1, 0xfe, 0x37, 0x82, 0x08, 0x9f, 0x43, 0x85, 0x02, 0x49, 0x55, 0x09, 0x3b, + 0x30, 0x8e, 0x19, 0x64, 0xd3, 0x07, 0x91, 0x52, 0x71, 0xaa, 0x88, 0x6c, 0x3d, 0x9b, 0x64, 0xd8, 0x46, + 0xc8, 0x8c, 0xa1, 0x34, 0x1f, 0xd2, 0xf7, 0x2b, 0x76, 0x67, 0x9d, 0x4f, 0x25, 0x8f, 0x64, 0x7b, 0xc0, + 0x48, 0x20, 0xe4, 0x27, 0x76, 0xc9, 0xec, 0x0d, 0x01, 0x46, 0x46, 0x52, 0x76, 0x3a, 0x49, 0xd8, 0x22, + 0xc9, 0xd2, 0x5b, 0x60, 0x39, 0x03, 0xeb, 0xd6, 0x33, 0x89, 0x52, 0x25, 0x9b, 0x83, 0xa7, 0x40, 0xa4, + 0x20, 0xd6, 0x9d, 0x23, 0xae, 0xbb, 0xdf, 0x06, 0xa9, 0x2d, 0x88, 0xa4, 0x6f, 0xfc, 0xd8, 0xd8, 0x1a, + 0x47, 0xb6, 0xec, 0x99, 0xb6, 0xce, 0xa0, 0x48, 0x9c, 0xc8, 0x3e, 0xf1, 0x57, 0x57, 0xc4, 0x05, 0x3d, + 0x53, 0x84, 0x46, 0xf2, 0xe6, 0xb9, 0xeb, 0xa1, 0x2c, 0xe4, 0x96, 0x9b, 0x8d, 0x6d, 0xf9, 0xb3, 0xef, + 0x57, 0x4b, 0x7d, 0x40, 0x13, 0x41, 0xc2, 0xf5, 0x55, 0xa0, 0x0f, 0x02, 0x91, 0x64, 0xe5, 0xd3, 0x87, + 0x28, 0x2c, 0x0c, 0x87, 0x91, 0xba, 0x8c, 0x69, 0x81, 0x62, 0x48, 0xe2, 0xe5, 0x44, 0xa9, 0xc1, 0x2b, + 0x7a, 0xeb, 0xa6, 0x29, 0xfd, 0xee, 0xa2, 0xe1, 0x11, 0x65, 0x5e, 0x44, 0xb9, 0xc2, 0x15, 0x92, 0x4c, + 0x54, 0x55, 0xea, 0xa4, 0xab, 0x32, 0xae, 0xa1, 0xd9, 0xce, 0xf1, 0xd8, 0x6e, 0x8a, 0xcf, 0x6b, 0x0f, + 0xf4, 0xdc, 0xab, 0xaf, 0x4f, 0x0e, 0x2d, 0x9a, 0xe6, 0x5c, 0x8b, 0xb1, 0x06, 0x5e, 0x04, 0x18, 0xff, + 0x12, 0xd4, 0x62, 0x69, 0x30, 0x31, 0x59, 0x38, 0xbf, 0xe0, 0x0a, 0x8d, 0x03, 0xe8, 0xe7, 0x0e, 0x9d, + 0xea, 0x9d, 0xc9, 0xff, 0x74, 0x85, 0x4c, 0xbb, 0x4d, 0xbd, 0xf7, 0x00, 0xa6, 0x2e, 0x77, 0xb2, 0x6e, + 0x50, 0xb1, 0x3e, 0x2d, 0x39, 0x60, 0xc9, 0x13, 0x36, 0x0c, 0x84, 0xc8, 0x7e, 0x80, 0x1e, 0xd3, 0xdf, + 0x3d, 0xb0, 0xe2, 0x76, 0x04, 0x50, 0x8c, 0xb7, 0x30, 0xc5, 0xa0, 0x52, 0xc0, 0x68, 0xab, 0xe5, 0x82, + 0x6b, 0x01, 0xbe, 0x9f, 0x62, 0xe3, 0x3b, 0x9a, 0xf8, 0xed, 0xb6, 0x66, 0x7c, 0x57, 0xcb, 0x1a, 0xa8, + 0x79, 0x74, 0x3b, 0x77, 0xa7, 0x43, 0x2f, 0x75, 0xfe, 0x3a, 0xe2, 0x11, 0xf9, 0x6a, 0xf4, 0x1a, 0xde, + 0xf1, 0xe1, 0xc5, 0x07, 0x25, 0x6f, 0xe5, 0xfa, 0x2b, 0xcc, 0xab, 0xe5, 0x2c, 0xf8, 0x21, 0x6d, 0x34, + 0x10, 0xe6, 0x37, 0x85, 0x06, 0xd4, 0x27, 0x34, 0x34, 0x58, 0x33, 0x2d, 0x15, 0x3a, 0x77, 0xa1, 0x62, + 0xc4, 0xc5, 0xf1, 0x8d, 0x9f, 0x31, 0xb0, 0xc1, 0x42, 0x88, 0x0c, 0xad, 0x22, 0x29, 0x98, 0x17, 0x20, + 0x61, 0x5a, 0xb2, 0x6b, 0x7c, 0x13, 0x44, 0x2e, 0x43, 0x17, 0x8a, 0xad, 0xee, 0x43, 0x65, 0x10, 0xc9, + 0x1b, 0xc9, 0xd5, 0xd7, 0x35, 0xeb, 0x94, 0x53, 0xcf, 0x39, 0xce, 0xf5, 0x12, 0x0e, 0x28, 0x60, 0x37, + 0x75, 0xf0, 0x48, 0x3f, 0x01, 0xc3, 0xc4, 0x8b, 0x5b, 0x06, 0x0c, 0xa7, 0xf3, 0xa5, 0x4d, 0x7c, 0x7c, + 0x99, 0xa4, 0x81, 0xc9, 0x30, 0x81, 0xc6, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa2, 0x81, 0xbe, 0x04, 0x81, + 0xbb, 0x03, 0xab, 0x65, 0x67, 0x60, 0xa3, 0x51, 0x2f, 0xec, 0xc7, 0x03, 0x2d, 0xa8, 0xb2, 0x01, 0x46, + 0x59, 0xf0, 0xfb, 0x34, 0xeb, 0x76, 0xb4, 0x61, 0xe4, 0x04, 0x4d, 0xa2, 0x4d, 0x16, 0xd4, 0x58, 0xe3, + 0xe1, 0xc5, 0x89, 0x19, 0xc7, 0x4c, 0x4c, 0x07, 0x20, 0xaa, 0xfb, 0x87, 0xa9, 0x48, 0x15, 0x23, 0x72, + 0xa2, 0x48, 0x3a, 0x4d, 0x1a, 0xe9, 0xb9, 0x5b, 0x85, 0x8a, 0x52, 0xab, 0xaa, 0x94, 0xe7, 0xaa, 0x64, + 0x1a, 0x8b, 0x99, 0x7d, 0x7e, 0x6c, 0x6e, 0x57, 0x0b, 0x59, 0x08, 0xcc, 0x54, 0x91, 0x55, 0xf5, 0xe6, + 0xf1, 0x10, 0xc9, 0x8d, 0x64, 0x89, 0x78, 0x72, 0x7a, 0xba, 0xe3, 0x92, 0x1d, 0xa5, 0x2a, 0x4c, 0x1f, + 0xd7, 0x6b, 0xeb, 0x12, 0x1b, 0xf3, 0x39, 0x6b, 0xe8, 0xf9, 0x8e, 0x4a, 0xcf, 0x1e, 0xbf, 0xc3, 0xb6, + 0xfb, 0x7a, 0x13, 0x54, 0xc1, 0x21, 0x87, 0x3e, 0x59, 0x18, 0x5d, 0xb9, 0x00, 0x30, 0x08, 0x4d, 0x97, + 0x86, 0x47, 0x98, 0xd7, 0x9e, 0xb9, 0xdf, 0x30, 0x75, 0x6c, 0xa1, 0xfa, 0xa7, 0xa8, 0x08, 0x80, 0xf7, + 0x4f, 0x7d, 0x93, 0x64, 0x2d, 0x9c, 0xeb, 0x5e, 0x01, 0x28, 0xce, 0xd6, 0xab, 0x09, 0x6a, 0x4f, 0x01, + 0x5e, 0x5a, 0x03, 0x2b, 0x42, 0x70, 0x23, 0x1e, 0x7f, 0xf1, 0xbc, 0xd0, 0x87, 0xe8, 0xb5, 0x27, 0x02, + 0x7d } }; PTF_ASSERT_EQUAL(bindRequestLayer->getSaslAuthentication(), expectedSaslAuthentication); - PTF_ASSERT_RAISES(bindRequestLayer->getSimpleAuthentication(), std::invalid_argument, "Authentication type is not simple"); + PTF_ASSERT_RAISES(bindRequestLayer->getSimpleAuthentication(), std::invalid_argument, + "Authentication type is not simple"); std::string simpleAuthentication; - PTF_ASSERT_FALSE(bindRequestLayer->tryGet(&pcpp::LdapBindRequestLayer::getSimpleAuthentication, simpleAuthentication)); + PTF_ASSERT_FALSE( + bindRequestLayer->tryGet(&pcpp::LdapBindRequestLayer::getSimpleAuthentication, simpleAuthentication)); PTF_ASSERT_EQUAL(bindRequestLayer->toString(), "LDAP Layer, BindRequest, sasl"); } @@ -195,11 +247,17 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_EQUAL(bindResponseLayer->getDiagnosticMessage(), ""); PTF_ASSERT_VECTORS_EQUAL(bindResponseLayer->getReferral(), std::vector()); std::vector expectedServerSaslCredentials = { - 0xa1, 0x81, 0xa1, 0x30, 0x81, 0x9e, 0xa0, 0x03, 0x0a, 0x01, 0x00, 0xa1, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, 0xa2, 0x81, 0x89, 0x04, 0x81, 0x86, 0x60, 0x81, 0x83, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x02, 0x00, 0x6f, 0x74, 0x30, 0x72, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0f, 0xa2, 0x66, 0x30, 0x64, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa2, 0x5d, 0x04, 0x5b, 0x4a, 0x9f, 0x10, - 0xab, 0x89, 0x96, 0xfa, 0x43, 0xf2, 0xfb, 0x40, 0x92, 0xa7, 0x6c, 0xc3, 0xfa, 0x6c, 0x1f, 0x00, 0x11, 0x67, 0xfa, 0xc9, 0x04, 0xda, 0xb0, 0x67, 0xf5, 0xf2, 0xda, 0x59, 0xa7, 0x54, 0x90, 0x57, 0xbd, 0x3e, 0xb4, 0x6c, 0xb4, 0x67, - 0xfd, 0x3b, 0x01, 0xd7, 0x3f, 0x50, 0x51, 0xaa, 0x63, 0x2e, 0xd8, 0xd6, 0xa6, 0xe5, 0x81, 0xbb, 0xab, 0x17, 0x80, 0xfa, 0xab, 0xac, 0x51, 0x52, 0x84, 0x13, 0x9c, 0xfb, 0x44, 0xc2, 0x04, 0xae, 0x1e, 0xc2, 0x5a, 0x2d, 0x58, 0x90, - 0x9d, 0x22, 0xff, 0x52, 0x34, 0x9e, 0x6d, 0x2e, 0x4d, 0x83, 0x5b, 0x98}; + 0xa1, 0x81, 0xa1, 0x30, 0x81, 0x9e, 0xa0, 0x03, 0x0a, 0x01, 0x00, 0xa1, 0x0b, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, 0xa2, 0x81, 0x89, 0x04, 0x81, 0x86, 0x60, 0x81, 0x83, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x02, 0x00, 0x6f, 0x74, 0x30, 0x72, 0xa0, + 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0f, 0xa2, 0x66, 0x30, 0x64, 0xa0, 0x03, 0x02, 0x01, + 0x17, 0xa2, 0x5d, 0x04, 0x5b, 0x4a, 0x9f, 0x10, 0xab, 0x89, 0x96, 0xfa, 0x43, 0xf2, 0xfb, 0x40, 0x92, + 0xa7, 0x6c, 0xc3, 0xfa, 0x6c, 0x1f, 0x00, 0x11, 0x67, 0xfa, 0xc9, 0x04, 0xda, 0xb0, 0x67, 0xf5, 0xf2, + 0xda, 0x59, 0xa7, 0x54, 0x90, 0x57, 0xbd, 0x3e, 0xb4, 0x6c, 0xb4, 0x67, 0xfd, 0x3b, 0x01, 0xd7, 0x3f, + 0x50, 0x51, 0xaa, 0x63, 0x2e, 0xd8, 0xd6, 0xa6, 0xe5, 0x81, 0xbb, 0xab, 0x17, 0x80, 0xfa, 0xab, 0xac, + 0x51, 0x52, 0x84, 0x13, 0x9c, 0xfb, 0x44, 0xc2, 0x04, 0xae, 0x1e, 0xc2, 0x5a, 0x2d, 0x58, 0x90, 0x9d, + 0x22, 0xff, 0x52, 0x34, 0x9e, 0x6d, 0x2e, 0x4d, 0x83, 0x5b, 0x98 + }; PTF_ASSERT_VECTORS_EQUAL(bindResponseLayer->getServerSaslCredentials(), expectedServerSaslCredentials); } @@ -241,33 +299,32 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_EQUAL(searchRequestLayer->getMessageID(), 9); PTF_ASSERT_EQUAL(searchRequestLayer->getLdapOperationType(), pcpp::LdapOperationType::SearchRequest, enum); PTF_ASSERT_EQUAL(searchRequestLayer->getBaseObject(), "cn=schema"); - PTF_ASSERT_EQUAL(searchRequestLayer->getScope(), pcpp::LdapSearchRequestLayer::SearchRequestScope::BaseObject, enum); - PTF_ASSERT_EQUAL(searchRequestLayer->getDerefAlias(), pcpp::LdapSearchRequestLayer::DerefAliases::DerefAlways, enum); + PTF_ASSERT_EQUAL(searchRequestLayer->getScope(), pcpp::LdapSearchRequestLayer::SearchRequestScope::BaseObject, + enum); + PTF_ASSERT_EQUAL(searchRequestLayer->getDerefAlias(), pcpp::LdapSearchRequestLayer::DerefAliases::DerefAlways, + enum); PTF_ASSERT_EQUAL(searchRequestLayer->getSizeLimit(), 0); PTF_ASSERT_EQUAL(searchRequestLayer->getTimeLimit(), 0); PTF_ASSERT_FALSE(searchRequestLayer->getTypesOnly()); std::ostringstream expectedFilter; - expectedFilter - << "ContextSpecific (3) (constructed), Length: 2+24" << std::endl - << " OctetString, Length: 2+11, Value: objectClass" << std::endl - << " OctetString, Length: 2+9, Value: subschema"; + expectedFilter << "ContextSpecific (3) (constructed), Length: 2+24" << std::endl + << " OctetString, Length: 2+11, Value: objectClass" << std::endl + << " OctetString, Length: 2+9, Value: subschema"; PTF_ASSERT_EQUAL(searchRequestLayer->getFilter()->toString(), expectedFilter.str()); PTF_ASSERT_EQUAL(searchRequestLayer->toString(), "LDAP Layer, SearchRequest, \"cn=schema\", BaseObject"); auto attributes = searchRequestLayer->getAttributes(); - std::vector expectedAttributes = { - "objectClasses", - "attributeTypes", - "ldapSyntaxes", - "matchingRules", - "matchingRuleUse", - "dITContentRules", - "dITStructureRules", - "nameForms", - "createTimestamp", - "modifyTimestamp", - "*", - "+" - }; + std::vector expectedAttributes = { "objectClasses", + "attributeTypes", + "ldapSyntaxes", + "matchingRules", + "matchingRuleUse", + "dITContentRules", + "dITStructureRules", + "nameForms", + "createTimestamp", + "modifyTimestamp", + "*", + "+" }; PTF_ASSERT_VECTORS_EQUAL(attributes, expectedAttributes); } @@ -279,14 +336,18 @@ PTF_TEST_CASE(LdapParsingTest) auto searchResultEntryLayer = searchResEntryPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(searchResultEntryLayer); PTF_ASSERT_EQUAL(searchResultEntryLayer->getMessageID(), 16); - PTF_ASSERT_EQUAL(searchResultEntryLayer->getLdapOperationType(), pcpp::LdapOperationType::SearchResultEntry, enum); - PTF_ASSERT_EQUAL(searchResultEntryLayer->getObjectName(), "cn=b.smith,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org"); + PTF_ASSERT_EQUAL(searchResultEntryLayer->getLdapOperationType(), pcpp::LdapOperationType::SearchResultEntry, + enum); + PTF_ASSERT_EQUAL(searchResultEntryLayer->getObjectName(), + "cn=b.smith,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org"); + // clang-format off std::vector expectedAttributes = { - {"objectclass", {"inetOrgPerson", "organizationalPerson", "person", "top"}}, - {"sn", {"Young"}}, - {"cn", {"b.smith"}}, - {"givenname", {"Beatrix"}} + { "objectclass", { "inetOrgPerson", "organizationalPerson", "person", "top" } }, + { "sn", { "Young" } }, + { "cn", { "b.smith" } }, + { "givenname", { "Beatrix" } } }; + // clang-format on PTF_ASSERT_VECTORS_EQUAL(searchResultEntryLayer->getAttributes(), expectedAttributes); } @@ -298,7 +359,8 @@ PTF_TEST_CASE(LdapParsingTest) auto searchResultDoneLayer = searchResultDonePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(searchResultDoneLayer); PTF_ASSERT_EQUAL(searchResultDoneLayer->getMessageID(), 8); - PTF_ASSERT_EQUAL(searchResultDoneLayer->getLdapOperationType(), pcpp::LdapOperationType::SearchResultDone, enum); + PTF_ASSERT_EQUAL(searchResultDoneLayer->getLdapOperationType(), pcpp::LdapOperationType::SearchResultDone, + enum); PTF_ASSERT_EQUAL(searchResultDoneLayer->getResultCode(), pcpp::LdapResultCode::Success, enum); PTF_ASSERT_EQUAL(searchResultDoneLayer->getMatchedDN(), ""); PTF_ASSERT_EQUAL(searchResultDoneLayer->getDiagnosticMessage(), ""); @@ -351,10 +413,8 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_EQUAL(deleteResponseLayer->getMatchedDN(), "ou=People,dc=example,dc=com"); PTF_ASSERT_EQUAL(deleteResponseLayer->getDiagnosticMessage(), "LDAP: error code 32 - No such object"); - std::vector expectedReferral = { - "ldap://ldap.example.com/dc=example,dc=com", - "ldap://ldap.example.com/dc=example,dc=com?objectClass?one" - }; + std::vector expectedReferral = { "ldap://ldap.example.com/dc=example,dc=com", + "ldap://ldap.example.com/dc=example,dc=com?objectClass?one" }; PTF_ASSERT_VECTORS_EQUAL(deleteResponseLayer->getReferral(), expectedReferral); PTF_ASSERT_EQUAL(deleteResponseLayer->toString(), "LDAP Layer, DeleteResponse, NoSuchObject"); } @@ -367,7 +427,8 @@ PTF_TEST_CASE(LdapParsingTest) auto modifyDNResponseLayer = modifyDNResponsePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(modifyDNResponseLayer); PTF_ASSERT_EQUAL(modifyDNResponseLayer->getMessageID(), 15); - PTF_ASSERT_EQUAL(modifyDNResponseLayer->getLdapOperationType(), pcpp::LdapOperationType::ModifyDNResponse, enum); + PTF_ASSERT_EQUAL(modifyDNResponseLayer->getLdapOperationType(), pcpp::LdapOperationType::ModifyDNResponse, + enum); PTF_ASSERT_EQUAL(modifyDNResponseLayer->getResultCode(), pcpp::LdapResultCode::NoSuchObject, enum); PTF_ASSERT_EQUAL(modifyDNResponseLayer->getMatchedDN(), "ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org"); PTF_ASSERT_EQUAL(modifyDNResponseLayer->getDiagnosticMessage(), ""); @@ -390,8 +451,7 @@ PTF_TEST_CASE(LdapParsingTest) PTF_ASSERT_VECTORS_EQUAL(compareResponseLayer->getReferral(), std::vector()); PTF_ASSERT_EQUAL(compareResponseLayer->toString(), "LDAP Layer, CompareResponse, CompareFalse"); } -} // LdapParsingTest - +} // LdapParsingTest PTF_TEST_CASE(LdapCreationTest) { @@ -410,23 +470,28 @@ PTF_TEST_CASE(LdapCreationTest) pcpp::Asn1IntegerRecord integerRecord2(0); pcpp::Asn1BooleanRecord booleanRecord(false); - pcpp::Asn1GenericRecord subRecord1(pcpp::Asn1TagClass::ContextSpecific, false, 1, "2.16.840.1.113730.3.3.2.46.1"); + pcpp::Asn1GenericRecord subRecord1(pcpp::Asn1TagClass::ContextSpecific, false, 1, + "2.16.840.1.113730.3.3.2.46.1"); pcpp::Asn1GenericRecord subRecord2(pcpp::Asn1TagClass::ContextSpecific, false, 2, "departmentNumber"); pcpp::Asn1GenericRecord subRecord3(pcpp::Asn1TagClass::ContextSpecific, false, 3, ">=N4709"); - pcpp::Asn1ConstructedRecord constructedRecord1(pcpp::Asn1TagClass::ContextSpecific, 9, {&subRecord1, &subRecord2, &subRecord3}); + pcpp::Asn1ConstructedRecord constructedRecord1(pcpp::Asn1TagClass::ContextSpecific, 9, + { &subRecord1, &subRecord2, &subRecord3 }); pcpp::Asn1OctetStringRecord stringSubRecord1("*"); pcpp::Asn1OctetStringRecord stringSubRecord2("ntsecuritydescriptor"); - pcpp::Asn1SequenceRecord sequenceRecord({&stringSubRecord1, &stringSubRecord2}); + pcpp::Asn1SequenceRecord sequenceRecord({ &stringSubRecord1, &stringSubRecord2 }); + // clang-format off std::vector controls = { - {"1.2.840.113556.1.4.801", "3003020107"}, - {"1.2.840.113556.1.4.319", "3006020201f40400"} + { "1.2.840.113556.1.4.801", "3003020107" }, + { "1.2.840.113556.1.4.319", "3006020201f40400" } }; + // clang-format on pcpp::LdapLayer ldapLayer(6, pcpp::LdapOperationType::SearchRequest, - {&stringRecord, &enumeratedRecord1, &enumeratedRecord2, &integerRecord1, &integerRecord2, &booleanRecord, &constructedRecord1, &sequenceRecord}, - controls); + { &stringRecord, &enumeratedRecord1, &enumeratedRecord2, &integerRecord1, + &integerRecord2, &booleanRecord, &constructedRecord1, &sequenceRecord }, + controls); auto expectedLdapLayer = ldapPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedLdapLayer); @@ -441,11 +506,14 @@ PTF_TEST_CASE(LdapCreationTest) pcpp::Asn1IntegerRecord integerRecord(3); pcpp::Asn1OctetStringRecord stringRecord("cn=Administrator,cn=Users,dc=cloudshark-a,dc=example,dc=com"); - uint8_t contextSpecificData[14] = {0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x68, 0x61, 0x72, 0x6b, 0x31, 0x32, 0x33, 0x21}; - pcpp::Asn1GenericRecord contextSpecificRecord(pcpp::Asn1TagClass::ContextSpecific, false, 0, contextSpecificData, 14); - std::vector controls = {{"1.3.6.1.4.1.42.2.27.8.5.1"}}; + uint8_t contextSpecificData[14] = { 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x68, + 0x61, 0x72, 0x6b, 0x31, 0x32, 0x33, 0x21 }; + pcpp::Asn1GenericRecord contextSpecificRecord(pcpp::Asn1TagClass::ContextSpecific, false, 0, + contextSpecificData, 14); + std::vector controls = { { "1.3.6.1.4.1.42.2.27.8.5.1" } }; - pcpp::LdapLayer ldapLayer(2, pcpp::LdapOperationType::BindRequest, {&integerRecord, &stringRecord, &contextSpecificRecord}, controls); + pcpp::LdapLayer ldapLayer(2, pcpp::LdapOperationType::BindRequest, + { &integerRecord, &stringRecord, &contextSpecificRecord }, controls); auto expectedLdapLayer = ldapPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedLdapLayer); @@ -459,13 +527,13 @@ PTF_TEST_CASE(LdapCreationTest) pcpp::Packet bindRequestPacket(&rawPacket1); pcpp::LdapBindRequestLayer bindRequestLayer(2, 3, "cn=Administrator,cn=Users,dc=cloudshark-a,dc=example,dc=com", - "cloudshark123!", {{"1.3.6.1.4.1.42.2.27.8.5.1"}}); + "cloudshark123!", { { "1.3.6.1.4.1.42.2.27.8.5.1" } }); auto expectedBindRequestLayer = bindRequestPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedBindRequestLayer); PTF_ASSERT_BUF_COMPARE(bindRequestLayer.getData(), expectedBindRequestLayer->getData(), - expectedBindRequestLayer->getDataLen()); + expectedBindRequestLayer->getDataLen()); } // BindRequest with sasl authentication @@ -473,54 +541,99 @@ PTF_TEST_CASE(LdapCreationTest) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ldap_bind_request2.dat"); pcpp::Packet bindRequestPacket(&rawPacket1); - pcpp::LdapBindRequestLayer::SaslAuthentication saslAuthentication { + pcpp::LdapBindRequestLayer::SaslAuthentication saslAuthentication{ "GSS-SPNEGO", - {0x60, 0x82, 0x05, 0x1a, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02, 0xa0, 0x82, 0x05, 0x0e, 0x30, 0x82, 0x05, 0x0a, 0xa0, 0x24, 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x82, 0x04, 0xe0, 0x04, 0x82, 0x04, 0xdc, 0x60, 0x82, 0x04, 0xd8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x12, 0x01, 0x02, 0x02, 0x01, 0x00, 0x6e, 0x82, 0x04, 0xc7, 0x30, 0x82, 0x04, 0xc3, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0e, 0xa2, 0x07, 0x03, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa3, 0x82, 0x03, 0xe0, - 0x61, 0x82, 0x03, 0xdc, 0x30, 0x82, 0x03, 0xd8, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x15, 0x1b, 0x13, 0x57, 0x32, 0x4b, 0x33, 0x2e, 0x56, 0x4d, 0x4e, 0x45, 0x54, 0x31, 0x2e, 0x56, 0x4d, 0x2e, 0x42, 0x41, 0x53, 0x45, 0xa2, 0x2f, - 0x30, 0x2d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x26, 0x30, 0x24, 0x1b, 0x04, 0x6c, 0x64, 0x61, 0x70, 0x1b, 0x1c, 0x77, 0x32, 0x6b, 0x33, 0x2d, 0x31, 0x30, 0x31, 0x2e, 0x77, 0x32, 0x6b, 0x33, 0x2e, 0x76, 0x6d, 0x6e, 0x65, 0x74, - 0x31, 0x2e, 0x76, 0x6d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0xa3, 0x82, 0x03, 0x87, 0x30, 0x82, 0x03, 0x83, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa1, 0x03, 0x02, 0x01, 0x07, 0xa2, 0x82, 0x03, 0x75, 0x04, 0x82, 0x03, 0x71, 0x6a, 0x61, 0xc8, - 0x86, 0xba, 0x58, 0xd1, 0x62, 0x11, 0x3d, 0xb4, 0x26, 0x8f, 0x77, 0x43, 0xa1, 0x7e, 0xb4, 0x76, 0x18, 0x3b, 0xc0, 0xc5, 0x19, 0xad, 0xde, 0xa7, 0x65, 0x56, 0xa3, 0x70, 0x1d, 0xe3, 0x49, 0x03, 0xe6, 0xbd, 0x3f, 0x3f, 0xdc, 0xa0, - 0xb0, 0x1b, 0xbc, 0xcb, 0x9a, 0x86, 0x93, 0xb2, 0x3f, 0xa8, 0xd1, 0x98, 0x5e, 0x14, 0x92, 0x2e, 0x4c, 0xa1, 0x9b, 0x05, 0xa9, 0x07, 0x69, 0x84, 0x5a, 0x58, 0x58, 0x51, 0x5b, 0xba, 0x4a, 0xf2, 0xd7, 0xe5, 0x9b, 0xfa, 0x86, 0x34, - 0x28, 0x5a, 0x2e, 0x95, 0x4f, 0xb5, 0x18, 0x37, 0x8b, 0x8d, 0x3f, 0x27, 0x44, 0xb9, 0xbb, 0xf8, 0x84, 0x2b, 0x48, 0x07, 0x87, 0x9f, 0xf2, 0x8e, 0x55, 0xbf, 0xba, 0x49, 0x67, 0xe8, 0xc1, 0xd3, 0xb6, 0xc4, 0xe3, 0x58, 0xa5, 0x61, - 0xc5, 0x4a, 0xbb, 0xc1, 0xcb, 0x7c, 0x97, 0xb6, 0x50, 0x3f, 0xe5, 0x9b, 0x7f, 0xee, 0x64, 0x23, 0xdf, 0xfe, 0x66, 0xfe, 0x6d, 0xcb, 0x8a, 0xf0, 0x0e, 0x69, 0xc5, 0x3d, 0x6b, 0x57, 0x6f, 0x55, 0x06, 0x99, 0x04, 0x38, 0x31, 0x0f, - 0xb7, 0xdd, 0x14, 0x68, 0xa3, 0x2f, 0xd8, 0xe0, 0xde, 0xab, 0x40, 0xb1, 0x5e, 0xcf, 0xd4, 0x38, 0x56, 0x83, 0x70, 0x14, 0x0a, 0x1e, 0xda, 0xfe, 0xe7, 0x01, 0xa4, 0xa4, 0xb4, 0xe7, 0xb3, 0xaa, 0xef, 0xdc, 0x4b, 0x1a, 0xff, 0x58, - 0x68, 0xae, 0xfe, 0x5a, 0x36, 0x29, 0x4d, 0x5d, 0xd6, 0x87, 0xd5, 0xa6, 0x49, 0x31, 0x43, 0xd3, 0xad, 0xe8, 0x03, 0x1c, 0x98, 0xd2, 0x8f, 0x6c, 0x7f, 0x3d, 0xce, 0xa4, 0x14, 0x35, 0x13, 0x2f, 0x67, 0x5f, 0x26, 0x94, 0x0d, 0x1f, - 0x69, 0xe5, 0x73, 0xe5, 0xec, 0xe6, 0xed, 0x5a, 0x66, 0x11, 0x1f, 0xf9, 0xf4, 0xb0, 0x2a, 0x8d, 0xdd, 0x19, 0x08, 0x6e, 0x5b, 0x9d, 0xc0, 0xad, 0xc8, 0x6a, 0x0b, 0xc1, 0x23, 0x0f, 0x1b, 0x71, 0x5f, 0xfc, 0x40, 0x04, 0xdf, 0xc4, - 0xa7, 0xd5, 0xf7, 0x8a, 0x4d, 0xc3, 0x1a, 0xbf, 0x83, 0x0a, 0xe6, 0xe3, 0xbf, 0xd2, 0x1c, 0x87, 0xfa, 0x51, 0x96, 0x54, 0x9e, 0x13, 0x0f, 0x6a, 0x08, 0x1b, 0xaf, 0xcf, 0x41, 0x70, 0xae, 0x20, 0x1c, 0x78, 0xa3, 0x82, 0x9a, 0x01, - 0xdb, 0xa5, 0x78, 0xa2, 0xef, 0x96, 0x8f, 0x2a, 0xb6, 0x66, 0x8d, 0x81, 0x14, 0xdf, 0xcc, 0x65, 0xd7, 0x03, 0x8f, 0x55, 0x58, 0xbe, 0x7c, 0xdd, 0x92, 0x46, 0xd5, 0x22, 0x47, 0x91, 0x52, 0x60, 0xa4, 0x0e, 0x59, 0xc4, 0x8b, 0x08, - 0xa1, 0xed, 0x61, 0x42, 0x7f, 0xd3, 0x03, 0x91, 0x7c, 0x6b, 0x34, 0xb7, 0x01, 0xa4, 0xba, 0x9a, 0x38, 0x15, 0xd4, 0x82, 0x8a, 0x22, 0x8c, 0xd2, 0x09, 0xda, 0x13, 0x76, 0x26, 0xe2, 0x02, 0x9a, 0xab, 0xf6, 0xc2, 0x00, 0xbf, 0x7f, - 0xd6, 0x3c, 0xf6, 0xd4, 0x3b, 0xb6, 0x18, 0xb3, 0x1a, 0xc4, 0x8e, 0x09, 0x61, 0x35, 0x89, 0xd7, 0x4a, 0x69, 0x54, 0x2e, 0x90, 0x9c, 0xe0, 0xdc, 0x9c, 0x57, 0xc7, 0x7f, 0x7d, 0x89, 0xb9, 0x66, 0xde, 0x20, 0x00, 0x53, 0xa5, 0x8e, - 0xa5, 0x8f, 0x23, 0x74, 0x51, 0x39, 0x61, 0x63, 0x8a, 0x30, 0xca, 0x49, 0xef, 0x0e, 0xec, 0x67, 0x9d, 0x92, 0x7e, 0x38, 0x5b, 0x5d, 0xa7, 0xd4, 0xd3, 0xc1, 0xa5, 0x91, 0x69, 0xb4, 0x63, 0x0b, 0x87, 0x4a, 0x1d, 0x96, 0x9e, 0x45, - 0xd1, 0xfe, 0x37, 0x82, 0x08, 0x9f, 0x43, 0x85, 0x02, 0x49, 0x55, 0x09, 0x3b, 0x30, 0x8e, 0x19, 0x64, 0xd3, 0x07, 0x91, 0x52, 0x71, 0xaa, 0x88, 0x6c, 0x3d, 0x9b, 0x64, 0xd8, 0x46, 0xc8, 0x8c, 0xa1, 0x34, 0x1f, 0xd2, 0xf7, 0x2b, - 0x76, 0x67, 0x9d, 0x4f, 0x25, 0x8f, 0x64, 0x7b, 0xc0, 0x48, 0x20, 0xe4, 0x27, 0x76, 0xc9, 0xec, 0x0d, 0x01, 0x46, 0x46, 0x52, 0x76, 0x3a, 0x49, 0xd8, 0x22, 0xc9, 0xd2, 0x5b, 0x60, 0x39, 0x03, 0xeb, 0xd6, 0x33, 0x89, 0x52, 0x25, - 0x9b, 0x83, 0xa7, 0x40, 0xa4, 0x20, 0xd6, 0x9d, 0x23, 0xae, 0xbb, 0xdf, 0x06, 0xa9, 0x2d, 0x88, 0xa4, 0x6f, 0xfc, 0xd8, 0xd8, 0x1a, 0x47, 0xb6, 0xec, 0x99, 0xb6, 0xce, 0xa0, 0x48, 0x9c, 0xc8, 0x3e, 0xf1, 0x57, 0x57, 0xc4, 0x05, - 0x3d, 0x53, 0x84, 0x46, 0xf2, 0xe6, 0xb9, 0xeb, 0xa1, 0x2c, 0xe4, 0x96, 0x9b, 0x8d, 0x6d, 0xf9, 0xb3, 0xef, 0x57, 0x4b, 0x7d, 0x40, 0x13, 0x41, 0xc2, 0xf5, 0x55, 0xa0, 0x0f, 0x02, 0x91, 0x64, 0xe5, 0xd3, 0x87, 0x28, 0x2c, 0x0c, - 0x87, 0x91, 0xba, 0x8c, 0x69, 0x81, 0x62, 0x48, 0xe2, 0xe5, 0x44, 0xa9, 0xc1, 0x2b, 0x7a, 0xeb, 0xa6, 0x29, 0xfd, 0xee, 0xa2, 0xe1, 0x11, 0x65, 0x5e, 0x44, 0xb9, 0xc2, 0x15, 0x92, 0x4c, 0x54, 0x55, 0xea, 0xa4, 0xab, 0x32, 0xae, - 0xa1, 0xd9, 0xce, 0xf1, 0xd8, 0x6e, 0x8a, 0xcf, 0x6b, 0x0f, 0xf4, 0xdc, 0xab, 0xaf, 0x4f, 0x0e, 0x2d, 0x9a, 0xe6, 0x5c, 0x8b, 0xb1, 0x06, 0x5e, 0x04, 0x18, 0xff, 0x12, 0xd4, 0x62, 0x69, 0x30, 0x31, 0x59, 0x38, 0xbf, 0xe0, 0x0a, - 0x8d, 0x03, 0xe8, 0xe7, 0x0e, 0x9d, 0xea, 0x9d, 0xc9, 0xff, 0x74, 0x85, 0x4c, 0xbb, 0x4d, 0xbd, 0xf7, 0x00, 0xa6, 0x2e, 0x77, 0xb2, 0x6e, 0x50, 0xb1, 0x3e, 0x2d, 0x39, 0x60, 0xc9, 0x13, 0x36, 0x0c, 0x84, 0xc8, 0x7e, 0x80, 0x1e, - 0xd3, 0xdf, 0x3d, 0xb0, 0xe2, 0x76, 0x04, 0x50, 0x8c, 0xb7, 0x30, 0xc5, 0xa0, 0x52, 0xc0, 0x68, 0xab, 0xe5, 0x82, 0x6b, 0x01, 0xbe, 0x9f, 0x62, 0xe3, 0x3b, 0x9a, 0xf8, 0xed, 0xb6, 0x66, 0x7c, 0x57, 0xcb, 0x1a, 0xa8, 0x79, 0x74, - 0x3b, 0x77, 0xa7, 0x43, 0x2f, 0x75, 0xfe, 0x3a, 0xe2, 0x11, 0xf9, 0x6a, 0xf4, 0x1a, 0xde, 0xf1, 0xe1, 0xc5, 0x07, 0x25, 0x6f, 0xe5, 0xfa, 0x2b, 0xcc, 0xab, 0xe5, 0x2c, 0xf8, 0x21, 0x6d, 0x34, 0x10, 0xe6, 0x37, 0x85, 0x06, 0xd4, - 0x27, 0x34, 0x34, 0x58, 0x33, 0x2d, 0x15, 0x3a, 0x77, 0xa1, 0x62, 0xc4, 0xc5, 0xf1, 0x8d, 0x9f, 0x31, 0xb0, 0xc1, 0x42, 0x88, 0x0c, 0xad, 0x22, 0x29, 0x98, 0x17, 0x20, 0x61, 0x5a, 0xb2, 0x6b, 0x7c, 0x13, 0x44, 0x2e, 0x43, 0x17, - 0x8a, 0xad, 0xee, 0x43, 0x65, 0x10, 0xc9, 0x1b, 0xc9, 0xd5, 0xd7, 0x35, 0xeb, 0x94, 0x53, 0xcf, 0x39, 0xce, 0xf5, 0x12, 0x0e, 0x28, 0x60, 0x37, 0x75, 0xf0, 0x48, 0x3f, 0x01, 0xc3, 0xc4, 0x8b, 0x5b, 0x06, 0x0c, 0xa7, 0xf3, 0xa5, - 0x4d, 0x7c, 0x7c, 0x99, 0xa4, 0x81, 0xc9, 0x30, 0x81, 0xc6, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa2, 0x81, 0xbe, 0x04, 0x81, 0xbb, 0x03, 0xab, 0x65, 0x67, 0x60, 0xa3, 0x51, 0x2f, 0xec, 0xc7, 0x03, 0x2d, 0xa8, 0xb2, 0x01, 0x46, 0x59, - 0xf0, 0xfb, 0x34, 0xeb, 0x76, 0xb4, 0x61, 0xe4, 0x04, 0x4d, 0xa2, 0x4d, 0x16, 0xd4, 0x58, 0xe3, 0xe1, 0xc5, 0x89, 0x19, 0xc7, 0x4c, 0x4c, 0x07, 0x20, 0xaa, 0xfb, 0x87, 0xa9, 0x48, 0x15, 0x23, 0x72, 0xa2, 0x48, 0x3a, 0x4d, 0x1a, - 0xe9, 0xb9, 0x5b, 0x85, 0x8a, 0x52, 0xab, 0xaa, 0x94, 0xe7, 0xaa, 0x64, 0x1a, 0x8b, 0x99, 0x7d, 0x7e, 0x6c, 0x6e, 0x57, 0x0b, 0x59, 0x08, 0xcc, 0x54, 0x91, 0x55, 0xf5, 0xe6, 0xf1, 0x10, 0xc9, 0x8d, 0x64, 0x89, 0x78, 0x72, 0x7a, - 0xba, 0xe3, 0x92, 0x1d, 0xa5, 0x2a, 0x4c, 0x1f, 0xd7, 0x6b, 0xeb, 0x12, 0x1b, 0xf3, 0x39, 0x6b, 0xe8, 0xf9, 0x8e, 0x4a, 0xcf, 0x1e, 0xbf, 0xc3, 0xb6, 0xfb, 0x7a, 0x13, 0x54, 0xc1, 0x21, 0x87, 0x3e, 0x59, 0x18, 0x5d, 0xb9, 0x00, - 0x30, 0x08, 0x4d, 0x97, 0x86, 0x47, 0x98, 0xd7, 0x9e, 0xb9, 0xdf, 0x30, 0x75, 0x6c, 0xa1, 0xfa, 0xa7, 0xa8, 0x08, 0x80, 0xf7, 0x4f, 0x7d, 0x93, 0x64, 0x2d, 0x9c, 0xeb, 0x5e, 0x01, 0x28, 0xce, 0xd6, 0xab, 0x09, 0x6a, 0x4f, 0x01, - 0x5e, 0x5a, 0x03, 0x2b, 0x42, 0x70, 0x23, 0x1e, 0x7f, 0xf1, 0xbc, 0xd0, 0x87, 0xe8, 0xb5, 0x27, 0x02, 0x7d} + { 0x60, 0x82, 0x05, 0x1a, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02, 0xa0, 0x82, 0x05, 0x0e, 0x30, + 0x82, 0x05, 0x0a, 0xa0, 0x24, 0x30, 0x22, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, + 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x06, 0x0a, 0x2b, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, 0xa2, 0x82, 0x04, 0xe0, 0x04, 0x82, 0x04, 0xdc, 0x60, 0x82, + 0x04, 0xd8, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x01, 0x00, 0x6e, 0x82, + 0x04, 0xc7, 0x30, 0x82, 0x04, 0xc3, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0e, 0xa2, + 0x07, 0x03, 0x05, 0x00, 0x20, 0x00, 0x00, 0x00, 0xa3, 0x82, 0x03, 0xe0, 0x61, 0x82, 0x03, 0xdc, 0x30, + 0x82, 0x03, 0xd8, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x15, 0x1b, 0x13, 0x57, 0x32, 0x4b, 0x33, 0x2e, + 0x56, 0x4d, 0x4e, 0x45, 0x54, 0x31, 0x2e, 0x56, 0x4d, 0x2e, 0x42, 0x41, 0x53, 0x45, 0xa2, 0x2f, 0x30, + 0x2d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0xa1, 0x26, 0x30, 0x24, 0x1b, 0x04, 0x6c, 0x64, 0x61, 0x70, 0x1b, + 0x1c, 0x77, 0x32, 0x6b, 0x33, 0x2d, 0x31, 0x30, 0x31, 0x2e, 0x77, 0x32, 0x6b, 0x33, 0x2e, 0x76, 0x6d, + 0x6e, 0x65, 0x74, 0x31, 0x2e, 0x76, 0x6d, 0x2e, 0x62, 0x61, 0x73, 0x65, 0xa3, 0x82, 0x03, 0x87, 0x30, + 0x82, 0x03, 0x83, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa1, 0x03, 0x02, 0x01, 0x07, 0xa2, 0x82, 0x03, 0x75, + 0x04, 0x82, 0x03, 0x71, 0x6a, 0x61, 0xc8, 0x86, 0xba, 0x58, 0xd1, 0x62, 0x11, 0x3d, 0xb4, 0x26, 0x8f, + 0x77, 0x43, 0xa1, 0x7e, 0xb4, 0x76, 0x18, 0x3b, 0xc0, 0xc5, 0x19, 0xad, 0xde, 0xa7, 0x65, 0x56, 0xa3, + 0x70, 0x1d, 0xe3, 0x49, 0x03, 0xe6, 0xbd, 0x3f, 0x3f, 0xdc, 0xa0, 0xb0, 0x1b, 0xbc, 0xcb, 0x9a, 0x86, + 0x93, 0xb2, 0x3f, 0xa8, 0xd1, 0x98, 0x5e, 0x14, 0x92, 0x2e, 0x4c, 0xa1, 0x9b, 0x05, 0xa9, 0x07, 0x69, + 0x84, 0x5a, 0x58, 0x58, 0x51, 0x5b, 0xba, 0x4a, 0xf2, 0xd7, 0xe5, 0x9b, 0xfa, 0x86, 0x34, 0x28, 0x5a, + 0x2e, 0x95, 0x4f, 0xb5, 0x18, 0x37, 0x8b, 0x8d, 0x3f, 0x27, 0x44, 0xb9, 0xbb, 0xf8, 0x84, 0x2b, 0x48, + 0x07, 0x87, 0x9f, 0xf2, 0x8e, 0x55, 0xbf, 0xba, 0x49, 0x67, 0xe8, 0xc1, 0xd3, 0xb6, 0xc4, 0xe3, 0x58, + 0xa5, 0x61, 0xc5, 0x4a, 0xbb, 0xc1, 0xcb, 0x7c, 0x97, 0xb6, 0x50, 0x3f, 0xe5, 0x9b, 0x7f, 0xee, 0x64, + 0x23, 0xdf, 0xfe, 0x66, 0xfe, 0x6d, 0xcb, 0x8a, 0xf0, 0x0e, 0x69, 0xc5, 0x3d, 0x6b, 0x57, 0x6f, 0x55, + 0x06, 0x99, 0x04, 0x38, 0x31, 0x0f, 0xb7, 0xdd, 0x14, 0x68, 0xa3, 0x2f, 0xd8, 0xe0, 0xde, 0xab, 0x40, + 0xb1, 0x5e, 0xcf, 0xd4, 0x38, 0x56, 0x83, 0x70, 0x14, 0x0a, 0x1e, 0xda, 0xfe, 0xe7, 0x01, 0xa4, 0xa4, + 0xb4, 0xe7, 0xb3, 0xaa, 0xef, 0xdc, 0x4b, 0x1a, 0xff, 0x58, 0x68, 0xae, 0xfe, 0x5a, 0x36, 0x29, 0x4d, + 0x5d, 0xd6, 0x87, 0xd5, 0xa6, 0x49, 0x31, 0x43, 0xd3, 0xad, 0xe8, 0x03, 0x1c, 0x98, 0xd2, 0x8f, 0x6c, + 0x7f, 0x3d, 0xce, 0xa4, 0x14, 0x35, 0x13, 0x2f, 0x67, 0x5f, 0x26, 0x94, 0x0d, 0x1f, 0x69, 0xe5, 0x73, + 0xe5, 0xec, 0xe6, 0xed, 0x5a, 0x66, 0x11, 0x1f, 0xf9, 0xf4, 0xb0, 0x2a, 0x8d, 0xdd, 0x19, 0x08, 0x6e, + 0x5b, 0x9d, 0xc0, 0xad, 0xc8, 0x6a, 0x0b, 0xc1, 0x23, 0x0f, 0x1b, 0x71, 0x5f, 0xfc, 0x40, 0x04, 0xdf, + 0xc4, 0xa7, 0xd5, 0xf7, 0x8a, 0x4d, 0xc3, 0x1a, 0xbf, 0x83, 0x0a, 0xe6, 0xe3, 0xbf, 0xd2, 0x1c, 0x87, + 0xfa, 0x51, 0x96, 0x54, 0x9e, 0x13, 0x0f, 0x6a, 0x08, 0x1b, 0xaf, 0xcf, 0x41, 0x70, 0xae, 0x20, 0x1c, + 0x78, 0xa3, 0x82, 0x9a, 0x01, 0xdb, 0xa5, 0x78, 0xa2, 0xef, 0x96, 0x8f, 0x2a, 0xb6, 0x66, 0x8d, 0x81, + 0x14, 0xdf, 0xcc, 0x65, 0xd7, 0x03, 0x8f, 0x55, 0x58, 0xbe, 0x7c, 0xdd, 0x92, 0x46, 0xd5, 0x22, 0x47, + 0x91, 0x52, 0x60, 0xa4, 0x0e, 0x59, 0xc4, 0x8b, 0x08, 0xa1, 0xed, 0x61, 0x42, 0x7f, 0xd3, 0x03, 0x91, + 0x7c, 0x6b, 0x34, 0xb7, 0x01, 0xa4, 0xba, 0x9a, 0x38, 0x15, 0xd4, 0x82, 0x8a, 0x22, 0x8c, 0xd2, 0x09, + 0xda, 0x13, 0x76, 0x26, 0xe2, 0x02, 0x9a, 0xab, 0xf6, 0xc2, 0x00, 0xbf, 0x7f, 0xd6, 0x3c, 0xf6, 0xd4, + 0x3b, 0xb6, 0x18, 0xb3, 0x1a, 0xc4, 0x8e, 0x09, 0x61, 0x35, 0x89, 0xd7, 0x4a, 0x69, 0x54, 0x2e, 0x90, + 0x9c, 0xe0, 0xdc, 0x9c, 0x57, 0xc7, 0x7f, 0x7d, 0x89, 0xb9, 0x66, 0xde, 0x20, 0x00, 0x53, 0xa5, 0x8e, + 0xa5, 0x8f, 0x23, 0x74, 0x51, 0x39, 0x61, 0x63, 0x8a, 0x30, 0xca, 0x49, 0xef, 0x0e, 0xec, 0x67, 0x9d, + 0x92, 0x7e, 0x38, 0x5b, 0x5d, 0xa7, 0xd4, 0xd3, 0xc1, 0xa5, 0x91, 0x69, 0xb4, 0x63, 0x0b, 0x87, 0x4a, + 0x1d, 0x96, 0x9e, 0x45, 0xd1, 0xfe, 0x37, 0x82, 0x08, 0x9f, 0x43, 0x85, 0x02, 0x49, 0x55, 0x09, 0x3b, + 0x30, 0x8e, 0x19, 0x64, 0xd3, 0x07, 0x91, 0x52, 0x71, 0xaa, 0x88, 0x6c, 0x3d, 0x9b, 0x64, 0xd8, 0x46, + 0xc8, 0x8c, 0xa1, 0x34, 0x1f, 0xd2, 0xf7, 0x2b, 0x76, 0x67, 0x9d, 0x4f, 0x25, 0x8f, 0x64, 0x7b, 0xc0, + 0x48, 0x20, 0xe4, 0x27, 0x76, 0xc9, 0xec, 0x0d, 0x01, 0x46, 0x46, 0x52, 0x76, 0x3a, 0x49, 0xd8, 0x22, + 0xc9, 0xd2, 0x5b, 0x60, 0x39, 0x03, 0xeb, 0xd6, 0x33, 0x89, 0x52, 0x25, 0x9b, 0x83, 0xa7, 0x40, 0xa4, + 0x20, 0xd6, 0x9d, 0x23, 0xae, 0xbb, 0xdf, 0x06, 0xa9, 0x2d, 0x88, 0xa4, 0x6f, 0xfc, 0xd8, 0xd8, 0x1a, + 0x47, 0xb6, 0xec, 0x99, 0xb6, 0xce, 0xa0, 0x48, 0x9c, 0xc8, 0x3e, 0xf1, 0x57, 0x57, 0xc4, 0x05, 0x3d, + 0x53, 0x84, 0x46, 0xf2, 0xe6, 0xb9, 0xeb, 0xa1, 0x2c, 0xe4, 0x96, 0x9b, 0x8d, 0x6d, 0xf9, 0xb3, 0xef, + 0x57, 0x4b, 0x7d, 0x40, 0x13, 0x41, 0xc2, 0xf5, 0x55, 0xa0, 0x0f, 0x02, 0x91, 0x64, 0xe5, 0xd3, 0x87, + 0x28, 0x2c, 0x0c, 0x87, 0x91, 0xba, 0x8c, 0x69, 0x81, 0x62, 0x48, 0xe2, 0xe5, 0x44, 0xa9, 0xc1, 0x2b, + 0x7a, 0xeb, 0xa6, 0x29, 0xfd, 0xee, 0xa2, 0xe1, 0x11, 0x65, 0x5e, 0x44, 0xb9, 0xc2, 0x15, 0x92, 0x4c, + 0x54, 0x55, 0xea, 0xa4, 0xab, 0x32, 0xae, 0xa1, 0xd9, 0xce, 0xf1, 0xd8, 0x6e, 0x8a, 0xcf, 0x6b, 0x0f, + 0xf4, 0xdc, 0xab, 0xaf, 0x4f, 0x0e, 0x2d, 0x9a, 0xe6, 0x5c, 0x8b, 0xb1, 0x06, 0x5e, 0x04, 0x18, 0xff, + 0x12, 0xd4, 0x62, 0x69, 0x30, 0x31, 0x59, 0x38, 0xbf, 0xe0, 0x0a, 0x8d, 0x03, 0xe8, 0xe7, 0x0e, 0x9d, + 0xea, 0x9d, 0xc9, 0xff, 0x74, 0x85, 0x4c, 0xbb, 0x4d, 0xbd, 0xf7, 0x00, 0xa6, 0x2e, 0x77, 0xb2, 0x6e, + 0x50, 0xb1, 0x3e, 0x2d, 0x39, 0x60, 0xc9, 0x13, 0x36, 0x0c, 0x84, 0xc8, 0x7e, 0x80, 0x1e, 0xd3, 0xdf, + 0x3d, 0xb0, 0xe2, 0x76, 0x04, 0x50, 0x8c, 0xb7, 0x30, 0xc5, 0xa0, 0x52, 0xc0, 0x68, 0xab, 0xe5, 0x82, + 0x6b, 0x01, 0xbe, 0x9f, 0x62, 0xe3, 0x3b, 0x9a, 0xf8, 0xed, 0xb6, 0x66, 0x7c, 0x57, 0xcb, 0x1a, 0xa8, + 0x79, 0x74, 0x3b, 0x77, 0xa7, 0x43, 0x2f, 0x75, 0xfe, 0x3a, 0xe2, 0x11, 0xf9, 0x6a, 0xf4, 0x1a, 0xde, + 0xf1, 0xe1, 0xc5, 0x07, 0x25, 0x6f, 0xe5, 0xfa, 0x2b, 0xcc, 0xab, 0xe5, 0x2c, 0xf8, 0x21, 0x6d, 0x34, + 0x10, 0xe6, 0x37, 0x85, 0x06, 0xd4, 0x27, 0x34, 0x34, 0x58, 0x33, 0x2d, 0x15, 0x3a, 0x77, 0xa1, 0x62, + 0xc4, 0xc5, 0xf1, 0x8d, 0x9f, 0x31, 0xb0, 0xc1, 0x42, 0x88, 0x0c, 0xad, 0x22, 0x29, 0x98, 0x17, 0x20, + 0x61, 0x5a, 0xb2, 0x6b, 0x7c, 0x13, 0x44, 0x2e, 0x43, 0x17, 0x8a, 0xad, 0xee, 0x43, 0x65, 0x10, 0xc9, + 0x1b, 0xc9, 0xd5, 0xd7, 0x35, 0xeb, 0x94, 0x53, 0xcf, 0x39, 0xce, 0xf5, 0x12, 0x0e, 0x28, 0x60, 0x37, + 0x75, 0xf0, 0x48, 0x3f, 0x01, 0xc3, 0xc4, 0x8b, 0x5b, 0x06, 0x0c, 0xa7, 0xf3, 0xa5, 0x4d, 0x7c, 0x7c, + 0x99, 0xa4, 0x81, 0xc9, 0x30, 0x81, 0xc6, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa2, 0x81, 0xbe, 0x04, 0x81, + 0xbb, 0x03, 0xab, 0x65, 0x67, 0x60, 0xa3, 0x51, 0x2f, 0xec, 0xc7, 0x03, 0x2d, 0xa8, 0xb2, 0x01, 0x46, + 0x59, 0xf0, 0xfb, 0x34, 0xeb, 0x76, 0xb4, 0x61, 0xe4, 0x04, 0x4d, 0xa2, 0x4d, 0x16, 0xd4, 0x58, 0xe3, + 0xe1, 0xc5, 0x89, 0x19, 0xc7, 0x4c, 0x4c, 0x07, 0x20, 0xaa, 0xfb, 0x87, 0xa9, 0x48, 0x15, 0x23, 0x72, + 0xa2, 0x48, 0x3a, 0x4d, 0x1a, 0xe9, 0xb9, 0x5b, 0x85, 0x8a, 0x52, 0xab, 0xaa, 0x94, 0xe7, 0xaa, 0x64, + 0x1a, 0x8b, 0x99, 0x7d, 0x7e, 0x6c, 0x6e, 0x57, 0x0b, 0x59, 0x08, 0xcc, 0x54, 0x91, 0x55, 0xf5, 0xe6, + 0xf1, 0x10, 0xc9, 0x8d, 0x64, 0x89, 0x78, 0x72, 0x7a, 0xba, 0xe3, 0x92, 0x1d, 0xa5, 0x2a, 0x4c, 0x1f, + 0xd7, 0x6b, 0xeb, 0x12, 0x1b, 0xf3, 0x39, 0x6b, 0xe8, 0xf9, 0x8e, 0x4a, 0xcf, 0x1e, 0xbf, 0xc3, 0xb6, + 0xfb, 0x7a, 0x13, 0x54, 0xc1, 0x21, 0x87, 0x3e, 0x59, 0x18, 0x5d, 0xb9, 0x00, 0x30, 0x08, 0x4d, 0x97, + 0x86, 0x47, 0x98, 0xd7, 0x9e, 0xb9, 0xdf, 0x30, 0x75, 0x6c, 0xa1, 0xfa, 0xa7, 0xa8, 0x08, 0x80, 0xf7, + 0x4f, 0x7d, 0x93, 0x64, 0x2d, 0x9c, 0xeb, 0x5e, 0x01, 0x28, 0xce, 0xd6, 0xab, 0x09, 0x6a, 0x4f, 0x01, + 0x5e, 0x5a, 0x03, 0x2b, 0x42, 0x70, 0x23, 0x1e, 0x7f, 0xf1, 0xbc, 0xd0, 0x87, 0xe8, 0xb5, 0x27, 0x02, + 0x7d } }; pcpp::LdapBindRequestLayer bindRequestLayer(2, 3, "", saslAuthentication); auto expectedBindRequestLayer = bindRequestPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedBindRequestLayer); - PTF_ASSERT_EQUAL(bindRequestLayer.getLdapOperationAsn1Record()->getSubRecords().size(), expectedBindRequestLayer->getLdapOperationAsn1Record()->getSubRecords().size()); - PTF_ASSERT_TRUE(std::equal(bindRequestLayer.getLdapOperationAsn1Record()->getSubRecords().begin(), - bindRequestLayer.getLdapOperationAsn1Record()->getSubRecords().end(), - expectedBindRequestLayer->getLdapOperationAsn1Record()->getSubRecords().begin(), - [](pcpp::Asn1Record* elem1, pcpp::Asn1Record* elem2) { return elem1->encode() == elem2->encode();})); + PTF_ASSERT_EQUAL(bindRequestLayer.getLdapOperationAsn1Record()->getSubRecords().size(), + expectedBindRequestLayer->getLdapOperationAsn1Record()->getSubRecords().size()); + PTF_ASSERT_TRUE(std::equal( + bindRequestLayer.getLdapOperationAsn1Record()->getSubRecords().begin(), + bindRequestLayer.getLdapOperationAsn1Record()->getSubRecords().end(), + expectedBindRequestLayer->getLdapOperationAsn1Record()->getSubRecords().begin(), + [](pcpp::Asn1Record* elem1, pcpp::Asn1Record* elem2) { return elem1->encode() == elem2->encode(); })); } // BindResponse with server sasl credentials @@ -529,28 +642,42 @@ PTF_TEST_CASE(LdapCreationTest) pcpp::Packet bindResponsePacket(&rawPacket1); std::vector serverSaslCredentials = { - 0xa1, 0x81, 0xa1, 0x30, 0x81, 0x9e, 0xa0, 0x03, 0x0a, 0x01, 0x00, 0xa1, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, 0xa2, 0x81, 0x89, 0x04, 0x81, 0x86, 0x60, 0x81, 0x83, 0x06, 0x09, 0x2a, 0x86, 0x48, - 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x02, 0x00, 0x6f, 0x74, 0x30, 0x72, 0xa0, 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0f, 0xa2, 0x66, 0x30, 0x64, 0xa0, 0x03, 0x02, 0x01, 0x17, 0xa2, 0x5d, 0x04, 0x5b, 0x4a, 0x9f, 0x10, - 0xab, 0x89, 0x96, 0xfa, 0x43, 0xf2, 0xfb, 0x40, 0x92, 0xa7, 0x6c, 0xc3, 0xfa, 0x6c, 0x1f, 0x00, 0x11, 0x67, 0xfa, 0xc9, 0x04, 0xda, 0xb0, 0x67, 0xf5, 0xf2, 0xda, 0x59, 0xa7, 0x54, 0x90, 0x57, 0xbd, 0x3e, 0xb4, 0x6c, 0xb4, 0x67, - 0xfd, 0x3b, 0x01, 0xd7, 0x3f, 0x50, 0x51, 0xaa, 0x63, 0x2e, 0xd8, 0xd6, 0xa6, 0xe5, 0x81, 0xbb, 0xab, 0x17, 0x80, 0xfa, 0xab, 0xac, 0x51, 0x52, 0x84, 0x13, 0x9c, 0xfb, 0x44, 0xc2, 0x04, 0xae, 0x1e, 0xc2, 0x5a, 0x2d, 0x58, 0x90, - 0x9d, 0x22, 0xff, 0x52, 0x34, 0x9e, 0x6d, 0x2e, 0x4d, 0x83, 0x5b, 0x98}; + 0xa1, 0x81, 0xa1, 0x30, 0x81, 0x9e, 0xa0, 0x03, 0x0a, 0x01, 0x00, 0xa1, 0x0b, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02, 0xa2, 0x81, 0x89, 0x04, 0x81, 0x86, 0x60, 0x81, 0x83, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, 0x02, 0x00, 0x6f, 0x74, 0x30, 0x72, 0xa0, + 0x03, 0x02, 0x01, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x0f, 0xa2, 0x66, 0x30, 0x64, 0xa0, 0x03, 0x02, 0x01, + 0x17, 0xa2, 0x5d, 0x04, 0x5b, 0x4a, 0x9f, 0x10, 0xab, 0x89, 0x96, 0xfa, 0x43, 0xf2, 0xfb, 0x40, 0x92, + 0xa7, 0x6c, 0xc3, 0xfa, 0x6c, 0x1f, 0x00, 0x11, 0x67, 0xfa, 0xc9, 0x04, 0xda, 0xb0, 0x67, 0xf5, 0xf2, + 0xda, 0x59, 0xa7, 0x54, 0x90, 0x57, 0xbd, 0x3e, 0xb4, 0x6c, 0xb4, 0x67, 0xfd, 0x3b, 0x01, 0xd7, 0x3f, + 0x50, 0x51, 0xaa, 0x63, 0x2e, 0xd8, 0xd6, 0xa6, 0xe5, 0x81, 0xbb, 0xab, 0x17, 0x80, 0xfa, 0xab, 0xac, + 0x51, 0x52, 0x84, 0x13, 0x9c, 0xfb, 0x44, 0xc2, 0x04, 0xae, 0x1e, 0xc2, 0x5a, 0x2d, 0x58, 0x90, 0x9d, + 0x22, 0xff, 0x52, 0x34, 0x9e, 0x6d, 0x2e, 0x4d, 0x83, 0x5b, 0x98 + }; - pcpp::LdapBindResponseLayer bindResponseLayer(215, pcpp::LdapResultCode::Success, "", "", {}, serverSaslCredentials); + pcpp::LdapBindResponseLayer bindResponseLayer(215, pcpp::LdapResultCode::Success, "", "", {}, + serverSaslCredentials); auto expectedBindResponseLayer = bindResponsePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedBindResponseLayer); - PTF_ASSERT_EQUAL(bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().size(), expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().size()); + PTF_ASSERT_EQUAL(bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().size(), + expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().size()); for (int i = 0; i < 3; i++) { - PTF_ASSERT_EQUAL(bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().at(i)->toString(), - expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().at(i)->toString()); + PTF_ASSERT_EQUAL( + bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().at(i)->toString(), + expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().at(i)->toString()); } - auto actualServerSaslCredentialsRecord = bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().at(3)->castAs(); + auto actualServerSaslCredentialsRecord = + bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().at(3)->castAs(); + // clang-format off auto expectedServerSaslCredentialsRecord = expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().at(3)->castAs(); - PTF_ASSERT_BUF_COMPARE(actualServerSaslCredentialsRecord->getValue(), expectedServerSaslCredentialsRecord->getValue(), expectedServerSaslCredentialsRecord->getValueLength()) + // clang-format on + PTF_ASSERT_BUF_COMPARE(actualServerSaslCredentialsRecord->getValue(), + expectedServerSaslCredentialsRecord->getValue(), + expectedServerSaslCredentialsRecord->getValueLength()) } // BindResponse without server sasl credentials @@ -563,11 +690,13 @@ PTF_TEST_CASE(LdapCreationTest) auto expectedBindResponseLayer = bindResponsePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedBindResponseLayer); - PTF_ASSERT_EQUAL(bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().size(), expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().size()); - PTF_ASSERT_TRUE(std::equal(bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().begin(), - bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().end(), - expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().begin(), - [](pcpp::Asn1Record* elem1, pcpp::Asn1Record* elem2) { return elem1->encode() == elem2->encode();})); + PTF_ASSERT_EQUAL(bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().size(), + expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().size()); + PTF_ASSERT_TRUE(std::equal( + bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().begin(), + bindResponseLayer.getLdapOperationAsn1Record()->getSubRecords().end(), + expectedBindResponseLayer->getLdapOperationAsn1Record()->getSubRecords().begin(), + [](pcpp::Asn1Record* elem1, pcpp::Asn1Record* elem2) { return elem1->encode() == elem2->encode(); })); } // UnbindRequest @@ -581,7 +710,7 @@ PTF_TEST_CASE(LdapCreationTest) PTF_ASSERT_NOT_NULL(expectedUnbindRequestLayer); PTF_ASSERT_BUF_COMPARE(unbindRequestLayer.getData(), expectedUnbindRequestLayer->getData(), - expectedUnbindRequestLayer->getDataLen()); + expectedUnbindRequestLayer->getDataLen()); } // SearchRequest @@ -591,33 +720,31 @@ PTF_TEST_CASE(LdapCreationTest) pcpp::Asn1OctetStringRecord filterSubRecord1("objectClass"); pcpp::Asn1OctetStringRecord filterSubRecord2("subschema"); - pcpp::Asn1ConstructedRecord filterRecord(pcpp::Asn1TagClass::ContextSpecific, 3, {&filterSubRecord1, &filterSubRecord2}); - - std::vector attributes = { - "objectClasses", - "attributeTypes", - "ldapSyntaxes", - "matchingRules", - "matchingRuleUse", - "dITContentRules", - "dITStructureRules", - "nameForms", - "createTimestamp", - "modifyTimestamp", - "*", - "+" - }; + pcpp::Asn1ConstructedRecord filterRecord(pcpp::Asn1TagClass::ContextSpecific, 3, + { &filterSubRecord1, &filterSubRecord2 }); + + std::vector attributes = { "objectClasses", + "attributeTypes", + "ldapSyntaxes", + "matchingRules", + "matchingRuleUse", + "dITContentRules", + "dITStructureRules", + "nameForms", + "createTimestamp", + "modifyTimestamp", + "*", + "+" }; pcpp::LdapSearchRequestLayer searchRequestLayer( - 9, "cn=schema", pcpp::LdapSearchRequestLayer::SearchRequestScope::BaseObject, - pcpp::LdapSearchRequestLayer::DerefAliases::DerefAlways, - 0, 0, false, &filterRecord, attributes); + 9, "cn=schema", pcpp::LdapSearchRequestLayer::SearchRequestScope::BaseObject, + pcpp::LdapSearchRequestLayer::DerefAliases::DerefAlways, 0, 0, false, &filterRecord, attributes); auto expectedSearchRequestLayer = searchRequestPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedSearchRequestLayer); PTF_ASSERT_BUF_COMPARE(searchRequestLayer.getData(), expectedSearchRequestLayer->getData(), - expectedSearchRequestLayer->getDataLen()); + expectedSearchRequestLayer->getDataLen()); } // SearchResultEntry @@ -625,20 +752,24 @@ PTF_TEST_CASE(LdapCreationTest) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ldap_search_result_entry.dat"); pcpp::Packet searchResultEntryPacket(&rawPacket1); + // clang-format off std::vector attributes = { - {"objectclass", {"inetOrgPerson", "organizationalPerson", "person", "top"}}, - {"sn", {"Young"}}, - {"cn", {"b.smith"}}, - {"givenname", {"Beatrix"}} + { "objectclass", { "inetOrgPerson", "organizationalPerson", "person", "top" } }, + { "sn", { "Young" } }, + { "cn", { "b.smith" } }, + { "givenname", { "Beatrix" } } }; + // clang-format on - pcpp::LdapSearchResultEntryLayer searchResultEntryLayer(16, "cn=b.smith,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org", attributes); + pcpp::LdapSearchResultEntryLayer searchResultEntryLayer( + 16, "cn=b.smith,ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org", attributes); - auto expectedSearchResultEntryLayer = searchResultEntryPacket.getLayerOfType(); + auto expectedSearchResultEntryLayer = + searchResultEntryPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedSearchResultEntryLayer); PTF_ASSERT_BUF_COMPARE(searchResultEntryLayer.getData(), expectedSearchResultEntryLayer->getData(), - expectedSearchResultEntryLayer->getDataLen()); + expectedSearchResultEntryLayer->getDataLen()); } // LdapSearchResultDoneLayer @@ -652,7 +783,7 @@ PTF_TEST_CASE(LdapCreationTest) PTF_ASSERT_NOT_NULL(expectedSearchResultDoneLayer); PTF_ASSERT_BUF_COMPARE(searchResultDoneLayer.getData(), expectedSearchResultDoneLayer->getData(), - expectedSearchResultDoneLayer->getDataLen()); + expectedSearchResultDoneLayer->getDataLen()); } // LdapModifyResponseLayer @@ -666,7 +797,7 @@ PTF_TEST_CASE(LdapCreationTest) PTF_ASSERT_NOT_NULL(expectedModifyResponseLayer); PTF_ASSERT_BUF_COMPARE(modifyResponseLayer.getData(), expectedModifyResponseLayer->getData(), - expectedModifyResponseLayer->getDataLen()); + expectedModifyResponseLayer->getDataLen()); } // LdapAddResponseLayer @@ -680,7 +811,7 @@ PTF_TEST_CASE(LdapCreationTest) PTF_ASSERT_NOT_NULL(expectedAddResponseLayer); PTF_ASSERT_BUF_COMPARE(addResponseLayer.getData(), expectedAddResponseLayer->getData(), - expectedAddResponseLayer->getDataLen()); + expectedAddResponseLayer->getDataLen()); } // LdapDeleteResponseLayer @@ -688,19 +819,18 @@ PTF_TEST_CASE(LdapCreationTest) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ldap_delete_response.dat"); pcpp::Packet deleteResponsePacket(&rawPacket1); - std::vector referral = { - "ldap://ldap.example.com/dc=example,dc=com", - "ldap://ldap.example.com/dc=example,dc=com?objectClass?one" - }; + std::vector referral = { "ldap://ldap.example.com/dc=example,dc=com", + "ldap://ldap.example.com/dc=example,dc=com?objectClass?one" }; - pcpp::LdapDeleteResponseLayer deleteResponseLayer(27, pcpp::LdapResultCode::NoSuchObject, "ou=People,dc=example,dc=com", - "LDAP: error code 32 - No such object", referral); + pcpp::LdapDeleteResponseLayer deleteResponseLayer(27, pcpp::LdapResultCode::NoSuchObject, + "ou=People,dc=example,dc=com", + "LDAP: error code 32 - No such object", referral); auto expectedDeleteResponseLayer = deleteResponsePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedDeleteResponseLayer); PTF_ASSERT_BUF_COMPARE(deleteResponseLayer.getData(), expectedDeleteResponseLayer->getData(), - expectedDeleteResponseLayer->getDataLen()); + expectedDeleteResponseLayer->getDataLen()); } // LdapModifyDNResponseLayer @@ -708,13 +838,14 @@ PTF_TEST_CASE(LdapCreationTest) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ldap_modify_dn_response.dat"); pcpp::Packet modifyDNResponsePacket(&rawPacket1); - pcpp::LdapModifyDNResponseLayer modifyDNResponseLayer(15, pcpp::LdapResultCode::NoSuchObject, "ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org", ""); + pcpp::LdapModifyDNResponseLayer modifyDNResponseLayer(15, pcpp::LdapResultCode::NoSuchObject, + "ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org", ""); auto expectedModifyDNResponseLayer = modifyDNResponsePacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(expectedModifyDNResponseLayer); PTF_ASSERT_BUF_COMPARE(modifyDNResponseLayer.getData(), expectedModifyDNResponseLayer->getData(), - expectedModifyDNResponseLayer->getDataLen()); + expectedModifyDNResponseLayer->getDataLen()); } // LdapCompareResponseLayer @@ -728,6 +859,6 @@ PTF_TEST_CASE(LdapCreationTest) PTF_ASSERT_NOT_NULL(expectedCompareResponseLayer); PTF_ASSERT_BUF_COMPARE(compareResponseLayer.getData(), expectedCompareResponseLayer->getData(), - expectedCompareResponseLayer->getDataLen()); + expectedCompareResponseLayer->getDataLen()); } -} // LdapCreationTest +} // LdapCreationTest diff --git a/Tests/Packet++Test/Tests/NflogTests.cpp b/Tests/Packet++Test/Tests/NflogTests.cpp index ec8a5fb1df..646697b479 100644 --- a/Tests/Packet++Test/Tests/NflogTests.cpp +++ b/Tests/Packet++Test/Tests/NflogTests.cpp @@ -8,7 +8,6 @@ #include "SystemUtils.h" #include "GeneralUtils.h" - PTF_TEST_CASE(NflogPacketParsingTest) { timeval time; @@ -29,16 +28,14 @@ PTF_TEST_CASE(NflogPacketParsingTest) PTF_ASSERT_EQUAL(nflogLayer->getNextLayer()->getProtocol(), pcpp::IPv4, enum); - pcpp::NflogTlvType expectedTypes[6] = { - pcpp::NflogTlvType::NFULA_PACKET_HDR, - pcpp::NflogTlvType::NFULA_PREFIX, - pcpp::NflogTlvType::NFULA_IFINDEX_OUTDEV, - pcpp::NflogTlvType::NFULA_UID, - pcpp::NflogTlvType::NFULA_GID, - pcpp::NflogTlvType::NFULA_PAYLOAD - }; + pcpp::NflogTlvType expectedTypes[6] = { pcpp::NflogTlvType::NFULA_PACKET_HDR, + pcpp::NflogTlvType::NFULA_PREFIX, + pcpp::NflogTlvType::NFULA_IFINDEX_OUTDEV, + pcpp::NflogTlvType::NFULA_UID, + pcpp::NflogTlvType::NFULA_GID, + pcpp::NflogTlvType::NFULA_PAYLOAD }; - int optSizes[6] = {8, 8, 8, 8, 8, 68}; + int optSizes[6] = { 8, 8, 8, 8, 8, 68 }; std::string optDataAsHexString[6] = { "0800010000000300", "05000a0000000000", @@ -48,13 +45,15 @@ PTF_TEST_CASE(NflogPacketParsingTest) "410009004500003d021040004011208f0a00020f0a000203a542003500294156c04e0100000100000000000003777777076578616d706c65036e657400000100012f0a31" }; - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 6; i++) + { pcpp::NflogTlv tlv = nflogLayer->getTlvByType(expectedTypes[i]); PTF_ASSERT_EQUAL(tlv.getTotalSize(), optSizes[i]); PTF_ASSERT_EQUAL(pcpp::byteArrayToHexString(tlv.getRecordBasePtr(), optSizes[i]), optDataAsHexString[i]); } - /// sum of all TLVs before payload + size of nflog_header + size of (recordLength + recordType) variables of payload TLV + /// sum of all TLVs before payload + size of nflog_header + size of (recordLength + recordType) variables of payload + /// TLV PTF_ASSERT_EQUAL(nflogLayer->getHeaderLen(), 48); } diff --git a/Tests/Packet++Test/Tests/NtpTests.cpp b/Tests/Packet++Test/Tests/NtpTests.cpp index 06cf056036..3373968e3c 100644 --- a/Tests/Packet++Test/Tests/NtpTests.cpp +++ b/Tests/Packet++Test/Tests/NtpTests.cpp @@ -16,276 +16,277 @@ PTF_TEST_CASE(NtpMethodsTests) { - double val = 12345.125; - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertFromTimestampFormat(pcpp::NtpLayer::convertToTimestampFormat(val)), val); - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertFromShortFormat(pcpp::NtpLayer::convertToShortFormat(val)), val); + double val = 12345.125; + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertFromTimestampFormat(pcpp::NtpLayer::convertToTimestampFormat(val)), val); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertFromShortFormat(pcpp::NtpLayer::convertToShortFormat(val)), val); - // First check the epoch is correct + // First check the epoch is correct #if defined(_WIN32) - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(0.0), std::string("1970-01-01T00:00:00.0000Z")); - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(uint64_t(0)), std::string("1970-01-01T00:00:00.0000Z")); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(0.0), std::string("1970-01-01T00:00:00.0000Z")); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(uint64_t(0)), std::string("1970-01-01T00:00:00.0000Z")); #else - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(0.0), std::string("1970-01-01T00:00:00.0000Z")); - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(uint64_t(0)), std::string("1900-01-01T00:00:00.0000Z")); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(0.0), std::string("1970-01-01T00:00:00.0000Z")); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(uint64_t(0)), std::string("1900-01-01T00:00:00.0000Z")); #endif - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(1642879410.0), "2022-01-22T19:23:30.0000Z"); - PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(pcpp::NtpLayer::convertToTimestampFormat(1642879410.0)), "2022-01-22T19:23:30.0000Z"); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(1642879410.0), "2022-01-22T19:23:30.0000Z"); + PTF_ASSERT_EQUAL(pcpp::NtpLayer::convertToIsoFormat(pcpp::NtpLayer::convertToTimestampFormat(1642879410.0)), + "2022-01-22T19:23:30.0000Z"); -} // NtpMethodsTests +} // NtpMethodsTests PTF_TEST_CASE(NtpParsingV3Tests) { - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ntpv3.dat"); - - pcpp::Packet ntpPacket(&rawPacket1); - pcpp::NtpLayer *ntpLayer = ntpPacket.getLayerOfType(); - - PTF_ASSERT_NOT_NULL(ntpLayer); - PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 3); - PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); - PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Server); - PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Server"); - PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 4); - PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(-6)); - // NTPv3 pcap is a bit useless, too many zeros but these fields same with v4 - PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), be64toh(0xd94f4f1100000000)); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xd94f4f1100000000)); - PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v3, Mode: Server"); - - // Since they are double it may or may not equal - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 16), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.015625), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - 1436864657.0), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1436864657.0), EPSILON); + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ntpv3.dat"); + + pcpp::Packet ntpPacket(&rawPacket1); + pcpp::NtpLayer* ntpLayer = ntpPacket.getLayerOfType(); + + PTF_ASSERT_NOT_NULL(ntpLayer); + PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 3); + PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); + PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Server); + PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Server"); + PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 4); + PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(-6)); + // NTPv3 pcap is a bit useless, too many zeros but these fields same with v4 + PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), be64toh(0xd94f4f1100000000)); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xd94f4f1100000000)); + PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v3, Mode: Server"); + + // Since they are double it may or may not equal + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 16), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.015625), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - 1436864657.0), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1436864657.0), EPSILON); #if defined(_WIN32) - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "1970-01-01T00:00:00.0000Z"); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1970-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "1970-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1970-01-01T00:00:00.0000Z"); #else - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "1900-01-01T00:00:00.0000Z"); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1900-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "1900-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1900-01-01T00:00:00.0000Z"); #endif - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "2015-07-14T09:04:17.0000Z"); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2015-07-14T09:04:17.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "2015-07-14T09:04:17.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2015-07-14T09:04:17.0000Z"); -} // NtpParsingV3Tests +} // NtpParsingV3Tests PTF_TEST_CASE(NtpParsingV4Tests) { - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ntpv4.dat"); - - // Test Ipv4 - pcpp::Packet ntpPacket(&rawPacket1); - pcpp::NtpLayer *ntpLayer = ntpPacket.getLayerOfType(); - - PTF_ASSERT_NOT_NULL(ntpLayer); - PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 4); - PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); - PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Client); - PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Client"); - PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 2); - PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 7); - PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(0xeb)); - PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), be32toh(0x450)); - PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), be32toh(0x3ab)); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), be32toh(0x83bc03df)); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifierString(), "131.188.3.223"); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), be64toh(0xd94f51c33165b860)); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), be64toh(0xd944575530336fd0)); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), be64toh(0xd944575531b4e978)); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xd94f51f42d26e2f4)); - PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v4, Mode: Client"); - - // Since they are double it may or may not equal - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 128), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.0000004), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0.0168457), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0.014328), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - 1436865347.192958377), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - 1436145877.188284862), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - 1436145877.194166747), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1436865396.176374611), EPSILON); - - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "2015-07-14T09:15:47.1930Z"); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "2015-07-06T01:24:37.1883Z"); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "2015-07-06T01:24:37.1942Z"); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2015-07-14T09:16:36.1764Z"); - - // Test Ipv6 - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/ntpv4Ipv6_withAuth.dat"); - - ntpPacket = pcpp::Packet(&rawPacket2); - ntpLayer = ntpPacket.getLayerOfType(); - - PTF_ASSERT_NOT_NULL(ntpLayer); - PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 4); - PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); - PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Client); - PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Client"); - PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 2); - PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 6); - PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(0xe8)); - PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), be32toh(0x91)); - PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), be32toh(0x6b7)); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), be32toh(0xb6a580db)); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifierString(), "182.165.128.219"); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), be64toh(0xdcd2a7d77a05d46a)); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xdcd2aa817b9f9bdc)); - PTF_ASSERT_EQUAL(ntpLayer->getKeyID(), be32toh(1)); - PTF_ASSERT_EQUAL(ntpLayer->getDigest(), "ac017b69915ce5a7a9fb73ac8bd1603b"); // MD5 - PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v4, Mode: Client"); - - // Since they are double it may or may not equal - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 64), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.000000059), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0.002213), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0.02623), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - 1495804247.476651454), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1495804929.482904187), EPSILON); - - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "2017-05-26T13:10:47.4767Z"); + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ntpv4.dat"); + + // Test Ipv4 + pcpp::Packet ntpPacket(&rawPacket1); + pcpp::NtpLayer* ntpLayer = ntpPacket.getLayerOfType(); + + PTF_ASSERT_NOT_NULL(ntpLayer); + PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 4); + PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); + PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Client); + PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Client"); + PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 2); + PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 7); + PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(0xeb)); + PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), be32toh(0x450)); + PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), be32toh(0x3ab)); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), be32toh(0x83bc03df)); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifierString(), "131.188.3.223"); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), be64toh(0xd94f51c33165b860)); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), be64toh(0xd944575530336fd0)); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), be64toh(0xd944575531b4e978)); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xd94f51f42d26e2f4)); + PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v4, Mode: Client"); + + // Since they are double it may or may not equal + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 128), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.0000004), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0.0168457), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0.014328), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - 1436865347.192958377), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - 1436145877.188284862), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - 1436145877.194166747), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1436865396.176374611), EPSILON); + + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "2015-07-14T09:15:47.1930Z"); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "2015-07-06T01:24:37.1883Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "2015-07-06T01:24:37.1942Z"); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2015-07-14T09:16:36.1764Z"); + + // Test Ipv6 + READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/ntpv4Ipv6_withAuth.dat"); + + ntpPacket = pcpp::Packet(&rawPacket2); + ntpLayer = ntpPacket.getLayerOfType(); + + PTF_ASSERT_NOT_NULL(ntpLayer); + PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 4); + PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); + PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Client); + PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Client"); + PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 2); + PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 6); + PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(0xe8)); + PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), be32toh(0x91)); + PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), be32toh(0x6b7)); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), be32toh(0xb6a580db)); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifierString(), "182.165.128.219"); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), be64toh(0xdcd2a7d77a05d46a)); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xdcd2aa817b9f9bdc)); + PTF_ASSERT_EQUAL(ntpLayer->getKeyID(), be32toh(1)); + PTF_ASSERT_EQUAL(ntpLayer->getDigest(), "ac017b69915ce5a7a9fb73ac8bd1603b"); // MD5 + PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v4, Mode: Client"); + + // Since they are double it may or may not equal + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 64), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.000000059), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0.002213), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0.02623), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - 1495804247.476651454), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - -double(EPOCH_OFFSET)), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1495804929.482904187), EPSILON); + + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "2017-05-26T13:10:47.4767Z"); #if defined(_WIN32) - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1970-01-01T00:00:00.0000Z"); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "1970-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1970-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "1970-01-01T00:00:00.0000Z"); #else - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1900-01-01T00:00:00.0000Z"); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "1900-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "1900-01-01T00:00:00.0000Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "1900-01-01T00:00:00.0000Z"); #endif - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2017-05-26T13:22:09.4829Z"); - - READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/ntpv4Ipv6_withAuth2.dat"); - - ntpPacket = pcpp::Packet(&rawPacket3); - ntpLayer = ntpPacket.getLayerOfType(); - - PTF_ASSERT_NOT_NULL(ntpLayer); - PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 4); - PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); - PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Server); - PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Server"); - PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 1); - PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 10); - PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(0xee)); - PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), 0); - PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), be32toh(0xfb)); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), static_cast(pcpp::NtpLayer::ClockSource::DCFa)); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifierString(), "Meinberg DCF77 with amplitude modulation"); - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), be64toh(0xdcd2aabfe3771e96)); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), be64toh(0xdcd2aae48e835d2a)); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), be64toh(0xdcd2aae48e9f4d3c)); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xdcd2aae48ece4367)); - PTF_ASSERT_EQUAL(ntpLayer->getKeyID(), be32toh(0xb)); - PTF_ASSERT_EQUAL(ntpLayer->getDigest(), "ece2d5b07e9fc63279aa2322b76038e53cd0ecc6"); // SHA1 - PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v4, Mode: Server"); - - // Since they are double it may or may not equal - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 1024), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.0000038), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0.0), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0.00383), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - 1495804991.888536368), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - 1495805028.556691954), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - 1495805028.55711825), EPSILON); - PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1495805028.557834828), EPSILON); - - PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "2017-05-26T13:23:11.8885Z"); - PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "2017-05-26T13:23:48.5567Z"); - PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "2017-05-26T13:23:48.5571Z"); - PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2017-05-26T13:23:48.5578Z"); -} // NtpParsingV4Tests + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2017-05-26T13:22:09.4829Z"); + + READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/ntpv4Ipv6_withAuth2.dat"); + + ntpPacket = pcpp::Packet(&rawPacket3); + ntpLayer = ntpPacket.getLayerOfType(); + + PTF_ASSERT_NOT_NULL(ntpLayer); + PTF_ASSERT_EQUAL(ntpLayer->getVersion(), 4); + PTF_ASSERT_EQUAL(ntpLayer->getLeapIndicator(), pcpp::NtpLayer::NoWarning); + PTF_ASSERT_EQUAL(ntpLayer->getMode(), pcpp::NtpLayer::Server); + PTF_ASSERT_EQUAL(ntpLayer->getModeString(), "Server"); + PTF_ASSERT_EQUAL(ntpLayer->getStratum(), 1); + PTF_ASSERT_EQUAL(ntpLayer->getPollInterval(), 10); + PTF_ASSERT_EQUAL(ntpLayer->getPrecision(), int8_t(0xee)); + PTF_ASSERT_EQUAL(ntpLayer->getRootDelay(), 0); + PTF_ASSERT_EQUAL(ntpLayer->getRootDispersion(), be32toh(0xfb)); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifier(), static_cast(pcpp::NtpLayer::ClockSource::DCFa)); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceIdentifierString(), "Meinberg DCF77 with amplitude modulation"); + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestamp(), be64toh(0xdcd2aabfe3771e96)); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestamp(), be64toh(0xdcd2aae48e835d2a)); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestamp(), be64toh(0xdcd2aae48e9f4d3c)); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestamp(), be64toh(0xdcd2aae48ece4367)); + PTF_ASSERT_EQUAL(ntpLayer->getKeyID(), be32toh(0xb)); + PTF_ASSERT_EQUAL(ntpLayer->getDigest(), "ece2d5b07e9fc63279aa2322b76038e53cd0ecc6"); // SHA1 + PTF_ASSERT_EQUAL(ntpLayer->toString(), "NTP Layer v4, Mode: Server"); + + // Since they are double it may or may not equal + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPollIntervalInSecs() - 1024), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getPrecisionInSecs() - 0.0000038), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDelayInSecs() - 0.0), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getRootDispersionInSecs() - 0.00383), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReferenceTimestampInSecs() - 1495804991.888536368), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getOriginTimestampInSecs() - 1495805028.556691954), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getReceiveTimestampInSecs() - 1495805028.55711825), EPSILON); + PTF_ASSERT_LOWER_THAN(fabs(ntpLayer->getTransmitTimestampInSecs() - 1495805028.557834828), EPSILON); + + PTF_ASSERT_EQUAL(ntpLayer->getReferenceTimestampAsString(), "2017-05-26T13:23:11.8885Z"); + PTF_ASSERT_EQUAL(ntpLayer->getOriginTimestampAsString(), "2017-05-26T13:23:48.5567Z"); + PTF_ASSERT_EQUAL(ntpLayer->getReceiveTimestampAsString(), "2017-05-26T13:23:48.5571Z"); + PTF_ASSERT_EQUAL(ntpLayer->getTransmitTimestampAsString(), "2017-05-26T13:23:48.5578Z"); +} // NtpParsingV4Tests PTF_TEST_CASE(NtpCreationTests) { - timeval time; - gettimeofday(&time, nullptr); - - READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ntpv4.dat"); - - pcpp::Packet ntpPacket(&rawPacket1); - - pcpp::EthLayer ethLayer(*ntpPacket.getLayerOfType()); - pcpp::IPv4Layer ipv4Layer(*ntpPacket.getLayerOfType()); - pcpp::UdpLayer udpLayer(*ntpPacket.getLayerOfType()); - - pcpp::NtpLayer ntpLayer; - - // Set the values - ntpLayer.setVersion(4); - ntpLayer.setLeapIndicator(pcpp::NtpLayer::NoWarning); - ntpLayer.setMode(pcpp::NtpLayer::Client); - ntpLayer.setStratum(2); - ntpLayer.setPollInterval(7); - ntpLayer.setPrecision(int8_t(0xeb)); - ntpLayer.setRootDelay(be32toh(0x450)); - ntpLayer.setRootDispersion(be32toh(0x3ab)); - ntpLayer.setReferenceIdentifier(pcpp::IPv4Address("131.188.3.223")); - ntpLayer.setReferenceTimestamp(be64toh(0xd94f51c33165b860)); - ntpLayer.setOriginTimestamp(be64toh(0xd944575530336fd0)); - ntpLayer.setReceiveTimestamp(be64toh(0xd944575531b4e978)); - ntpLayer.setTransmitTimestamp(be64toh(0xd94f51f42d26e2f4)); + timeval time; + gettimeofday(&time, nullptr); + + READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/ntpv4.dat"); + + pcpp::Packet ntpPacket(&rawPacket1); + + pcpp::EthLayer ethLayer(*ntpPacket.getLayerOfType()); + pcpp::IPv4Layer ipv4Layer(*ntpPacket.getLayerOfType()); + pcpp::UdpLayer udpLayer(*ntpPacket.getLayerOfType()); + + pcpp::NtpLayer ntpLayer; + + // Set the values + ntpLayer.setVersion(4); + ntpLayer.setLeapIndicator(pcpp::NtpLayer::NoWarning); + ntpLayer.setMode(pcpp::NtpLayer::Client); + ntpLayer.setStratum(2); + ntpLayer.setPollInterval(7); + ntpLayer.setPrecision(int8_t(0xeb)); + ntpLayer.setRootDelay(be32toh(0x450)); + ntpLayer.setRootDispersion(be32toh(0x3ab)); + ntpLayer.setReferenceIdentifier(pcpp::IPv4Address("131.188.3.223")); + ntpLayer.setReferenceTimestamp(be64toh(0xd94f51c33165b860)); + ntpLayer.setOriginTimestamp(be64toh(0xd944575530336fd0)); + ntpLayer.setReceiveTimestamp(be64toh(0xd944575531b4e978)); + ntpLayer.setTransmitTimestamp(be64toh(0xd94f51f42d26e2f4)); pcpp::Packet craftedPacket; PTF_ASSERT_TRUE(craftedPacket.addLayer(ðLayer)); PTF_ASSERT_TRUE(craftedPacket.addLayer(&ipv4Layer)); PTF_ASSERT_TRUE(craftedPacket.addLayer(&udpLayer)); - craftedPacket.addLayer(&ntpLayer); + craftedPacket.addLayer(&ntpLayer); - PTF_ASSERT_EQUAL(bufferLength1, craftedPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(buffer1, craftedPacket.getRawPacket()->getRawData(), bufferLength1); + PTF_ASSERT_EQUAL(bufferLength1, craftedPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(buffer1, craftedPacket.getRawPacket()->getRawData(), bufferLength1); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/ntpv3crafting.dat"); + READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/ntpv3crafting.dat"); - pcpp::Packet ntpPacket2(&rawPacket2); + pcpp::Packet ntpPacket2(&rawPacket2); - pcpp::EthLayer ethLayer2(*ntpPacket2.getLayerOfType()); - pcpp::IPv4Layer ipv4Layer2(*ntpPacket2.getLayerOfType()); - pcpp::UdpLayer udpLayer2(*ntpPacket2.getLayerOfType()); + pcpp::EthLayer ethLayer2(*ntpPacket2.getLayerOfType()); + pcpp::IPv4Layer ipv4Layer2(*ntpPacket2.getLayerOfType()); + pcpp::UdpLayer udpLayer2(*ntpPacket2.getLayerOfType()); - pcpp::NtpLayer ntpLayer2; + pcpp::NtpLayer ntpLayer2; - // Set the values - ntpLayer2.setVersion(3); - ntpLayer2.setLeapIndicator(pcpp::NtpLayer::NoWarning); - ntpLayer2.setMode(pcpp::NtpLayer::Server); - ntpLayer2.setStratum(1); - ntpLayer2.setPollInterval(10); - ntpLayer2.setPrecision(int8_t(0xfa)); - ntpLayer2.setRootDelayInSecs(0.031250); - ntpLayer2.setRootDispersionInSecs(0.125); - ntpLayer2.setReferenceIdentifier(pcpp::NtpLayer::ClockSource::DCFa); - ntpLayer2.setReferenceTimestampInSecs(1121509470.0); - ntpLayer2.setOriginTimestampInSecs(1121509866.0); - ntpLayer2.setReceiveTimestampInSecs(1121509865.0); - ntpLayer2.setTransmitTimestampInSecs(1121509865.0); + // Set the values + ntpLayer2.setVersion(3); + ntpLayer2.setLeapIndicator(pcpp::NtpLayer::NoWarning); + ntpLayer2.setMode(pcpp::NtpLayer::Server); + ntpLayer2.setStratum(1); + ntpLayer2.setPollInterval(10); + ntpLayer2.setPrecision(int8_t(0xfa)); + ntpLayer2.setRootDelayInSecs(0.031250); + ntpLayer2.setRootDispersionInSecs(0.125); + ntpLayer2.setReferenceIdentifier(pcpp::NtpLayer::ClockSource::DCFa); + ntpLayer2.setReferenceTimestampInSecs(1121509470.0); + ntpLayer2.setOriginTimestampInSecs(1121509866.0); + ntpLayer2.setReceiveTimestampInSecs(1121509865.0); + ntpLayer2.setTransmitTimestampInSecs(1121509865.0); pcpp::Packet craftedPacket2; PTF_ASSERT_TRUE(craftedPacket2.addLayer(ðLayer2)); PTF_ASSERT_TRUE(craftedPacket2.addLayer(&ipv4Layer2)); PTF_ASSERT_TRUE(craftedPacket2.addLayer(&udpLayer2)); - craftedPacket2.addLayer(&ntpLayer2); + craftedPacket2.addLayer(&ntpLayer2); - PTF_ASSERT_EQUAL(bufferLength2, craftedPacket2.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(buffer2, craftedPacket2.getRawPacket()->getRawData(), bufferLength2); -} // NtpCraftingTests + PTF_ASSERT_EQUAL(bufferLength2, craftedPacket2.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(buffer2, craftedPacket2.getRawPacket()->getRawData(), bufferLength2); +} // NtpCraftingTests diff --git a/Tests/Packet++Test/Tests/PPPoETests.cpp b/Tests/Packet++Test/Tests/PPPoETests.cpp index 5fdbed4b91..ef805ca193 100644 --- a/Tests/Packet++Test/Tests/PPPoETests.cpp +++ b/Tests/Packet++Test/Tests/PPPoETests.cpp @@ -10,7 +10,6 @@ #include "DhcpV6Layer.h" #include "SystemUtils.h" - PTF_TEST_CASE(PPPoESessionLayerParsingTest) { timeval time; @@ -37,10 +36,9 @@ PTF_TEST_CASE(PPPoESessionLayerParsingTest) PTF_ASSERT_EQUAL(pppoeSessionLayer->getPPPoEHeader()->payloadLength, htobe16(20)); PTF_ASSERT_EQUAL(pppoeSessionLayer->getPPPNextProtocol(), PCPP_PPP_LCP); - PTF_ASSERT_EQUAL(pppoeSessionLayer->toString(), std::string("PPP-over-Ethernet Session (followed by 'Link Control Protocol')")); -} // PPPoESessionLayerParsingTest - - + PTF_ASSERT_EQUAL(pppoeSessionLayer->toString(), + std::string("PPP-over-Ethernet Session (followed by 'Link Control Protocol')")); +} // PPPoESessionLayerParsingTest PTF_TEST_CASE(PPPoESessionLayerCreationTest) { @@ -68,9 +66,7 @@ PTF_TEST_CASE(PPPoESessionLayerCreationTest) PTF_ASSERT_EQUAL(bufferLength1, pppoesPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_BUF_COMPARE(pppoesPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); -} // PPPoESessionLayerCreationTest - - +} // PPPoESessionLayerCreationTest PTF_TEST_CASE(PPPoEDiscoveryLayerParsingTest) { @@ -108,14 +104,16 @@ PTF_TEST_CASE(PPPoEDiscoveryLayerParsingTest) PTF_ASSERT_EQUAL(secondTag.getDataSize(), 4); PTF_ASSERT_EQUAL(be32toh(secondTag.getValueAs()), 0x64138518); - pcpp::PPPoEDiscoveryLayer::PPPoETag thirdTag = pppoeDiscoveryLayer->getTag(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME); + pcpp::PPPoEDiscoveryLayer::PPPoETag thirdTag = + pppoeDiscoveryLayer->getTag(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME); PTF_ASSERT_FALSE(thirdTag.isNull()); PTF_ASSERT_TRUE(thirdTag == pppoeDiscoveryLayer->getNextTag(secondTag)); PTF_ASSERT_EQUAL(thirdTag.getType(), pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME, enum); PTF_ASSERT_EQUAL(thirdTag.getDataSize(), 4); PTF_ASSERT_EQUAL(thirdTag.getValueAsString(), "BRAS"); - pcpp::PPPoEDiscoveryLayer::PPPoETag fourthTag = pppoeDiscoveryLayer->getTag(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_COOKIE); + pcpp::PPPoEDiscoveryLayer::PPPoETag fourthTag = + pppoeDiscoveryLayer->getTag(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_COOKIE); PTF_ASSERT_FALSE(fourthTag.isNull()); PTF_ASSERT_TRUE(fourthTag == pppoeDiscoveryLayer->getNextTag(thirdTag)); PTF_ASSERT_EQUAL(fourthTag.getType(), pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_COOKIE, enum); @@ -127,9 +125,7 @@ PTF_TEST_CASE(PPPoEDiscoveryLayerParsingTest) PTF_ASSERT_EQUAL(pppoeDiscoveryLayer->getTagCount(), 4); PTF_ASSERT_EQUAL(pppoeDiscoveryLayer->toString(), std::string("PPP-over-Ethernet Discovery (PADS)")); -} // PPPoEDiscoveryLayerParsingTest - - +} // PPPoEDiscoveryLayerParsingTest PTF_TEST_CASE(PPPoEDiscoveryLayerCreateTest) { @@ -143,12 +139,15 @@ PTF_TEST_CASE(PPPoEDiscoveryLayerCreateTest) pcpp::EthLayer ethLayer(*samplePacket.getLayerOfType()); pcpp::PPPoEDiscoveryLayer pppoedLayer(1, 1, pcpp::PPPoELayer::PPPOE_CODE_PADI, 0); - pcpp::PPPoEDiscoveryLayer::PPPoETag svcNameTag = pppoedLayer.addTag(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_SVC_NAME)); + pcpp::PPPoEDiscoveryLayer::PPPoETag svcNameTag = + pppoedLayer.addTag(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_SVC_NAME)); PTF_ASSERT_EQUAL(pppoedLayer.getTagCount(), 1); PTF_ASSERT_EQUAL(pppoedLayer.getPPPoEHeader()->payloadLength, htobe16(4)); uint32_t hostUniqData = 0x64138518; - pppoedLayer.addTagAfter(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_HOST_UNIQ, hostUniqData), svcNameTag.getType()); + pppoedLayer.addTagAfter( + pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_HOST_UNIQ, hostUniqData), + svcNameTag.getType()); PTF_ASSERT_EQUAL(pppoedLayer.getTagCount(), 2); PTF_ASSERT_EQUAL(pppoedLayer.getPPPoEHeader()->payloadLength, htobe16(12)); @@ -161,7 +160,6 @@ PTF_TEST_CASE(PPPoEDiscoveryLayerCreateTest) PTF_ASSERT_EQUAL(pppoedPacket.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(pppoedPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - READ_FILE_INTO_BUFFER(2, "PacketExamples/PPPoEDiscovery2.dat"); pcpp::EthLayer* ethLayerPtr = pppoedPacket.getLayerOfType(); @@ -172,20 +170,25 @@ PTF_TEST_CASE(PPPoEDiscoveryLayerCreateTest) pppoedLayer.getPPPoEHeader()->code = pcpp::PPPoELayer::PPPOE_CODE_PADS; pppoedLayer.getPPPoEHeader()->sessionId = htobe16(0x11); - - uint8_t acCookieValue[16] = {0x3d, 0x0f, 0x05, 0x87, 0x06, 0x24, 0x84, 0xf2, 0xdf, 0x32, 0xb9, 0xdd, 0xfd, 0x77, 0xbd, 0x5b}; - pcpp::PPPoEDiscoveryLayer::PPPoETag acCookieTag = pppoedLayer.addTag(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_COOKIE, acCookieValue, 16)); + uint8_t acCookieValue[16] = { 0x3d, 0x0f, 0x05, 0x87, 0x06, 0x24, 0x84, 0xf2, + 0xdf, 0x32, 0xb9, 0xdd, 0xfd, 0x77, 0xbd, 0x5b }; + pcpp::PPPoEDiscoveryLayer::PPPoETag acCookieTag = pppoedLayer.addTag( + pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_COOKIE, acCookieValue, 16)); PTF_ASSERT_EQUAL(pppoedLayer.getTagCount(), 3); PTF_ASSERT_EQUAL(pppoedLayer.getPPPoEHeader()->payloadLength, htobe16(32)); - pppoedLayer.addTagAfter(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_HURL, hostUniqData), acCookieTag.getType()); + pppoedLayer.addTagAfter( + pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_HURL, hostUniqData), + acCookieTag.getType()); PTF_ASSERT_EQUAL(pppoedLayer.getTagCount(), 4); PTF_ASSERT_EQUAL(pppoedLayer.getPPPoEHeader()->payloadLength, htobe16(40)); - - pcpp::PPPoEDiscoveryLayer::PPPoETag hostUniqTag = pppoedLayer.getTag(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_HOST_UNIQ); + pcpp::PPPoEDiscoveryLayer::PPPoETag hostUniqTag = + pppoedLayer.getTag(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_HOST_UNIQ); PTF_ASSERT_FALSE(hostUniqTag.isNull()); - pppoedLayer.addTagAfter(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME, 0x42524153), hostUniqTag.getType()); + pppoedLayer.addTagAfter( + pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME, 0x42524153), + hostUniqTag.getType()); PTF_ASSERT_EQUAL(pppoedLayer.getTagCount(), 5); PTF_ASSERT_EQUAL(pppoedLayer.getPPPoEHeader()->payloadLength, htobe16(48)); @@ -204,11 +207,11 @@ PTF_TEST_CASE(PPPoEDiscoveryLayerCreateTest) PTF_ASSERT_EQUAL(pppoedPacket.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(pppoedPacket.getRawPacket()->getRawData(), buffer2, bufferLength2); - delete [] buffer2; + delete[] buffer2; PTF_ASSERT_TRUE(pppoedLayer.removeAllTags()); pppoedPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(pppoedLayer.getHeaderLen(), sizeof(pcpp::pppoe_header)); PTF_ASSERT_EQUAL(pppoedLayer.getPPPoEHeader()->payloadLength, 0); -} // PPPoEDiscoveryLayerCreateTest +} // PPPoEDiscoveryLayerCreateTest diff --git a/Tests/Packet++Test/Tests/PacketTests.cpp b/Tests/Packet++Test/Tests/PacketTests.cpp index cea40f0502..ee1fc217ef 100644 --- a/Tests/Packet++Test/Tests/PacketTests.cpp +++ b/Tests/Packet++Test/Tests/PacketTests.cpp @@ -58,7 +58,6 @@ PTF_TEST_CASE(InsertDataToPacket) PTF_ASSERT_EQUAL(ip4Layer.getSrcIPAddress(), ipSrc); PTF_ASSERT_EQUAL(payloadLayer.getPayload()[3], 0x04); - // Adding another Eth layer at the beginning of the packet // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -76,26 +75,23 @@ PTF_TEST_CASE(InsertDataToPacket) PTF_ASSERT_EQUAL(ip4Layer.getSrcIPAddress(), ipSrc); PTF_ASSERT_EQUAL(payloadLayer.getPayload()[3], 0x04); - // Adding a TCP layer at the end of the packet // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ auto tcpLayer = new pcpp::TcpLayer((uint16_t)12345, (uint16_t)80); PTF_ASSERT_TRUE(ip4Packet.insertLayer(&payloadLayer, tcpLayer, true)); - // Create a new packet and use insertLayer for the first layer in packet // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pcpp::EthLayer ethLayer3(srcMac2, dstMac2, PCPP_ETHERTYPE_IP); - pcpp::Packet testPacket(1); + pcpp::Packet testPacket(1); PTF_ASSERT_TRUE(testPacket.insertLayer(nullptr, ðLayer3)); PTF_ASSERT_EQUAL(testPacket.getFirstLayer(), ðLayer3, ptr); PTF_ASSERT_NULL(testPacket.getFirstLayer()->getNextLayer()); PTF_ASSERT_EQUAL(ethLayer3.getDestMac(), dstMac2); -} // InsertDataToPacket - +} // InsertDataToPacket PTF_TEST_CASE(CreatePacketFromBuffer) { @@ -139,13 +135,13 @@ PTF_TEST_CASE(CreatePacketFromBuffer) // Delete the packet - the buffer should not be freed delete newPacket; - std::string expectedHexString = "bbbbbbbbbbbbaaaaaaaaaaaa08004500001e00000000000690b101010101141414140102030405060708090a0000"; + std::string expectedHexString = + "bbbbbbbbbbbbaaaaaaaaaaaa08004500001e00000000000690b101010101141414140102030405060708090a0000"; PTF_ASSERT_EQUAL(pcpp::byteArrayToHexString(buffer, bufferSize), expectedHexString); - delete [] buffer; - -} // CreatePacketFromBuffer + delete[] buffer; +} // CreatePacketFromBuffer PTF_TEST_CASE(InsertVlanToPacket) { @@ -164,8 +160,7 @@ PTF_TEST_CASE(InsertVlanToPacket) PTF_ASSERT_EQUAL(tcpPacket.getFirstLayer()->getNextLayer(), &vlanLayer, ptr); PTF_ASSERT_NOT_NULL(vlanLayer.getNextLayer()); PTF_ASSERT_EQUAL(vlanLayer.getNextLayer()->getProtocol(), pcpp::IPv4, enum); -} // InsertVlanToPacket - +} // InsertVlanToPacket PTF_TEST_CASE(RemoveLayerTest) { @@ -179,7 +174,6 @@ PTF_TEST_CASE(RemoveLayerTest) pcpp::Packet tcpPacket(&rawPacket1); - // a. Remove layer from the middle // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -190,7 +184,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_EQUAL(tcpPacket.getFirstLayer()->getNextLayer()->getProtocol(), pcpp::TCP, enum); PTF_ASSERT_EQUAL(tcpPacket.getRawPacket()->getRawDataLen(), 271); - // b. Remove first layer // ~~~~~~~~~~~~~~~~~~~~~ @@ -201,7 +194,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_NULL(tcpPacket.getFirstLayer()->getNextLayer()->getNextLayer()); PTF_ASSERT_EQUAL(tcpPacket.getRawPacket()->getRawDataLen(), 257); - // c. Remove last layer // ~~~~~~~~~~~~~~~~~~~~ PTF_ASSERT_TRUE(tcpPacket.removeLastLayer()); @@ -211,7 +203,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_EQUAL(tcpPacket.getFirstLayer()->getProtocol(), pcpp::TCP, enum); PTF_ASSERT_EQUAL(tcpPacket.getRawPacket()->getRawDataLen(), 20); - // d. Remove a second layer of the same type // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -229,7 +220,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_TRUE(vxlanPacket.isPacketOfType(pcpp::VXLAN)); PTF_ASSERT_EQUAL(vxlanPacket.getRawPacket()->getRawDataLen(), 50); - // e. Remove a layer that doesn't exist // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -238,7 +228,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_FALSE(vxlanPacket.removeLayer(pcpp::Ethernet, 1)); pcpp::Logger::getInstance().enableLogs(); - // create packet and remove layers // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -259,7 +248,6 @@ PTF_TEST_CASE(RemoveLayerTest) pcpp::PayloadLayer payloadLayer(payload, 10); PTF_ASSERT_TRUE(testPacket.addLayer(&payloadLayer)); - // a. remove first layer // ~~~~~~~~~~~~~~~~~~~~~ @@ -270,7 +258,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_TRUE(testPacket.isPacketOfType(pcpp::IPv4)); PTF_ASSERT_EQUAL(testPacket.getRawPacket()->getRawDataLen(), 30); - // b. remove last layer // ~~~~~~~~~~~~~~~~~~~~ @@ -281,7 +268,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_FALSE(testPacket.isPacketOfType(pcpp::Ethernet)); PTF_ASSERT_EQUAL(testPacket.getRawPacket()->getRawDataLen(), 20); - // c. insert a layer // ~~~~~~~~~~~~~~~~~ @@ -292,7 +278,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_TRUE(testPacket.isPacketOfType(pcpp::VLAN)); PTF_ASSERT_EQUAL(testPacket.getRawPacket()->getRawDataLen(), 24); - // d. remove the remaining layers (packet remains empty!) // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -305,7 +290,6 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_FALSE(testPacket.isPacketOfType(pcpp::VLAN)); PTF_ASSERT_EQUAL(testPacket.getRawPacket()->getRawDataLen(), 0); - // Detach layer and add it to another packet // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -356,10 +340,9 @@ PTF_TEST_CASE(RemoveLayerTest) PTF_ASSERT_EQUAL(packetWithoutTunnel.getRawPacket()->getRawDataLen(), bufferLength4); PTF_ASSERT_BUF_COMPARE(packetWithoutTunnel.getRawPacket()->getRawData(), buffer4, bufferLength4); - delete [] buffer4; - -} // RemoveLayerTest + delete[] buffer4; +} // RemoveLayerTest PTF_TEST_CASE(CopyLayerAndPacketTest) { @@ -370,7 +353,7 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) pcpp::Packet sampleHttpPacket(&rawPacket1); - //RawPacket copy c'tor / assignment operator test + // RawPacket copy c'tor / assignment operator test //----------------------------------------------- pcpp::RawPacket copyRawPacket; copyRawPacket = rawPacket1; @@ -378,33 +361,40 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_TRUE(copyRawPacket.getRawData() != rawPacket1.getRawData()); PTF_ASSERT_BUF_COMPARE(copyRawPacket.getRawData(), rawPacket1.getRawData(), rawPacket1.getRawDataLen()); - //EthLayer copy c'tor test + // EthLayer copy c'tor test //------------------------ pcpp::EthLayer ethLayer = *sampleHttpPacket.getLayerOfType(); PTF_ASSERT_TRUE(sampleHttpPacket.getLayerOfType()->getLayerPayload() != ethLayer.getLayerPayload()); - PTF_ASSERT_BUF_COMPARE(ethLayer.getLayerPayload(), sampleHttpPacket.getLayerOfType()->getLayerPayload(), sampleHttpPacket.getLayerOfType()->getLayerPayloadSize()); - + PTF_ASSERT_BUF_COMPARE(ethLayer.getLayerPayload(), + sampleHttpPacket.getLayerOfType()->getLayerPayload(), + sampleHttpPacket.getLayerOfType()->getLayerPayloadSize()); - //TcpLayer copy c'tor test + // TcpLayer copy c'tor test //------------------------ READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/TcpPacketWithOptions2.dat"); pcpp::Packet sampleTcpPacketWithOptions(&rawPacket2); pcpp::TcpLayer tcpLayer = *sampleTcpPacketWithOptions.getLayerOfType(); PTF_ASSERT_TRUE(sampleTcpPacketWithOptions.getLayerOfType()->getData() != tcpLayer.getData()); - PTF_ASSERT_BUF_COMPARE(sampleTcpPacketWithOptions.getLayerOfType()->getData(), tcpLayer.getData(), sampleTcpPacketWithOptions.getLayerOfType()->getDataLen()); - PTF_ASSERT_EQUAL(tcpLayer.getTcpOptionCount(), sampleTcpPacketWithOptions.getLayerOfType()->getTcpOptionCount()); + PTF_ASSERT_BUF_COMPARE(sampleTcpPacketWithOptions.getLayerOfType()->getData(), tcpLayer.getData(), + sampleTcpPacketWithOptions.getLayerOfType()->getDataLen()); + PTF_ASSERT_EQUAL(tcpLayer.getTcpOptionCount(), + sampleTcpPacketWithOptions.getLayerOfType()->getTcpOptionCount()); + // clang-format off PTF_ASSERT_TRUE(sampleTcpPacketWithOptions.getLayerOfType()->getTcpOption(pcpp::TcpOptionEnumType::Timestamp).getRecordBasePtr() != tcpLayer.getTcpOption(pcpp::TcpOptionEnumType::Timestamp).getRecordBasePtr()); - PTF_ASSERT_TRUE(sampleTcpPacketWithOptions.getLayerOfType()->getTcpOption(pcpp::TcpOptionEnumType::Timestamp) == tcpLayer.getTcpOption(pcpp::TcpOptionEnumType::Timestamp)); + // clang-format on + PTF_ASSERT_TRUE( + sampleTcpPacketWithOptions.getLayerOfType()->getTcpOption(pcpp::TcpOptionEnumType::Timestamp) == + tcpLayer.getTcpOption(pcpp::TcpOptionEnumType::Timestamp)); - - //HttpLayer copy c'tor test + // HttpLayer copy c'tor test //-------------------------- pcpp::HttpResponseLayer* sampleHttpLayer = sampleHttpPacket.getLayerOfType(); pcpp::HttpResponseLayer httpResLayer = *sampleHttpPacket.getLayerOfType(); PTF_ASSERT_TRUE(sampleHttpLayer->getFirstLine() != httpResLayer.getFirstLine()); - PTF_ASSERT_EQUAL(sampleHttpLayer->getFirstLine()->getStatusCode(), httpResLayer.getFirstLine()->getStatusCode(), enum); + PTF_ASSERT_EQUAL(sampleHttpLayer->getFirstLine()->getStatusCode(), httpResLayer.getFirstLine()->getStatusCode(), + enum); PTF_ASSERT_EQUAL(sampleHttpLayer->getFirstLine()->getSize(), httpResLayer.getFirstLine()->getSize()); PTF_ASSERT_EQUAL(sampleHttpLayer->getFirstLine()->getVersion(), httpResLayer.getFirstLine()->getVersion(), enum); @@ -424,16 +414,17 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_NULL(curFieldInSample); PTF_ASSERT_NULL(curFieldInCopy); - - //Packet copy c'tor test - Ethernet + // Packet copy c'tor test - Ethernet //--------------------------------- pcpp::Packet samplePacketCopy(sampleHttpPacket); PTF_ASSERT_TRUE(samplePacketCopy.getFirstLayer() != sampleHttpPacket.getFirstLayer()); PTF_ASSERT_TRUE(samplePacketCopy.getLastLayer() != sampleHttpPacket.getLastLayer()); PTF_ASSERT_TRUE(samplePacketCopy.getRawPacket() != sampleHttpPacket.getRawPacket()); - PTF_ASSERT_EQUAL(samplePacketCopy.getRawPacket()->getRawDataLen(), sampleHttpPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(samplePacketCopy.getRawPacket()->getRawData(), sampleHttpPacket.getRawPacket()->getRawData(), sampleHttpPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_EQUAL(samplePacketCopy.getRawPacket()->getRawDataLen(), + sampleHttpPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(samplePacketCopy.getRawPacket()->getRawData(), sampleHttpPacket.getRawPacket()->getRawData(), + sampleHttpPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_TRUE(samplePacketCopy.isPacketOfType(pcpp::Ethernet)); PTF_ASSERT_TRUE(samplePacketCopy.isPacketOfType(pcpp::IPv4)); PTF_ASSERT_TRUE(samplePacketCopy.isPacketOfType(pcpp::TCP)); @@ -446,25 +437,26 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_EQUAL(curSamplePacketLayer->getHeaderLen(), curPacketCopyLayer->getHeaderLen()); PTF_ASSERT_EQUAL(curSamplePacketLayer->getLayerPayloadSize(), curPacketCopyLayer->getLayerPayloadSize()); PTF_ASSERT_EQUAL(curSamplePacketLayer->getDataLen(), curPacketCopyLayer->getDataLen()); - PTF_ASSERT_BUF_COMPARE(curSamplePacketLayer->getData(), curPacketCopyLayer->getData(), curSamplePacketLayer->getDataLen()); + PTF_ASSERT_BUF_COMPARE(curSamplePacketLayer->getData(), curPacketCopyLayer->getData(), + curSamplePacketLayer->getDataLen()); curSamplePacketLayer = curSamplePacketLayer->getNextLayer(); curPacketCopyLayer = curPacketCopyLayer->getNextLayer(); } auto samplePacketCopyHttpResponseLayer = samplePacketCopy.getLayerOfType(); auto contentTypeField = samplePacketCopyHttpResponseLayer->getFieldByName(PCPP_HTTP_CONTENT_TYPE_FIELD); - PTF_ASSERT_NOT_NULL(samplePacketCopyHttpResponseLayer->insertField(contentTypeField, "X-Forwarded-For", "10.20.30.40")); + PTF_ASSERT_NOT_NULL( + samplePacketCopyHttpResponseLayer->insertField(contentTypeField, "X-Forwarded-For", "10.20.30.40")); samplePacketCopy = sampleHttpPacket; samplePacketCopyHttpResponseLayer = samplePacketCopy.getLayerOfType(); contentTypeField = samplePacketCopyHttpResponseLayer->getFieldByName(PCPP_HTTP_CONTENT_TYPE_FIELD); - PTF_ASSERT_NOT_NULL(samplePacketCopyHttpResponseLayer->insertField(contentTypeField, "X-Forwarded-For", "10.20.30.40")); - + PTF_ASSERT_NOT_NULL( + samplePacketCopyHttpResponseLayer->insertField(contentTypeField, "X-Forwarded-For", "10.20.30.40")); PTF_ASSERT_NULL(curSamplePacketLayer); PTF_ASSERT_NULL(curPacketCopyLayer); - - //Packet copy c'tor test - Null/Loopback + // Packet copy c'tor test - Null/Loopback //-------------------------------------- READ_FILE_AND_CREATE_PACKET_LINKTYPE(3, "PacketExamples/NullLoopback1.dat", pcpp::LINKTYPE_NULL); @@ -476,8 +468,11 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_TRUE(nullLoopbackPacketCopy.getFirstLayer() != nullLoopbackPacket.getFirstLayer()); PTF_ASSERT_TRUE(nullLoopbackPacketCopy.getLastLayer() != nullLoopbackPacket.getLastLayer()); PTF_ASSERT_TRUE(nullLoopbackPacketCopy.getRawPacket() != nullLoopbackPacket.getRawPacket()); - PTF_ASSERT_EQUAL(nullLoopbackPacketCopy.getRawPacket()->getRawDataLen(), nullLoopbackPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(nullLoopbackPacketCopy.getRawPacket()->getRawData(), nullLoopbackPacket.getRawPacket()->getRawData(), nullLoopbackPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_EQUAL(nullLoopbackPacketCopy.getRawPacket()->getRawDataLen(), + nullLoopbackPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(nullLoopbackPacketCopy.getRawPacket()->getRawData(), + nullLoopbackPacket.getRawPacket()->getRawData(), + nullLoopbackPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_EQUAL(nullLoopbackPacketCopy.getRawPacket()->getLinkLayerType(), pcpp::LINKTYPE_NULL, enum); PTF_ASSERT_EQUAL(nullLoopbackPacketCopy.getFirstLayer()->getProtocol(), pcpp::NULL_LOOPBACK, enum); @@ -493,8 +488,7 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) curPacketCopyLayer = curPacketCopyLayer->getNextLayer(); } - - //Packet copy c'tor test - SLL + // Packet copy c'tor test - SLL //---------------------------- READ_FILE_AND_CREATE_PACKET_LINKTYPE(4, "PacketExamples/SllPacket2.dat", pcpp::LINKTYPE_LINUX_SLL); @@ -507,7 +501,8 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_TRUE(sllPacketCopy.getLastLayer() != sllPacket.getLastLayer()); PTF_ASSERT_TRUE(sllPacketCopy.getRawPacket() != sllPacket.getRawPacket()); PTF_ASSERT_EQUAL(sllPacketCopy.getRawPacket()->getRawDataLen(), sllPacket.getRawPacket()->getRawDataLen()); - PTF_ASSERT_BUF_COMPARE(sllPacketCopy.getRawPacket()->getRawData(), sllPacket.getRawPacket()->getRawData(), sllPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(sllPacketCopy.getRawPacket()->getRawData(), sllPacket.getRawPacket()->getRawData(), + sllPacket.getRawPacket()->getRawDataLen()); PTF_ASSERT_EQUAL(sllPacketCopy.getRawPacket()->getLinkLayerType(), pcpp::LINKTYPE_LINUX_SLL, enum); PTF_ASSERT_EQUAL(sllPacketCopy.getFirstLayer()->getProtocol(), pcpp::SLL, enum); @@ -523,8 +518,7 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) curPacketCopyLayer = curPacketCopyLayer->getNextLayer(); } - - //DnsLayer copy c'tor and operator= test + // DnsLayer copy c'tor and operator= test //-------------------------------------- READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/Dns2.dat"); @@ -539,9 +533,11 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_EQUAL(copyDnsLayer.getFirstQuery()->getDnsType(), origDnsLayer->getFirstQuery()->getDnsType(), enum); PTF_ASSERT_EQUAL(copyDnsLayer.getAuthorityCount(), origDnsLayer->getAuthorityCount()); - PTF_ASSERT_EQUAL(copyDnsLayer.getAuthority("Yaels-iPhone.local", true)->getData()->toString(), origDnsLayer->getAuthority("Yaels-iPhone.local", true)->getData()->toString()); + PTF_ASSERT_EQUAL(copyDnsLayer.getAuthority("Yaels-iPhone.local", true)->getData()->toString(), + origDnsLayer->getAuthority("Yaels-iPhone.local", true)->getData()->toString()); - PTF_ASSERT_EQUAL(copyDnsLayer.getAdditionalRecord("", true)->getData()->toString(), origDnsLayer->getAdditionalRecord("", true)->getData()->toString()); + PTF_ASSERT_EQUAL(copyDnsLayer.getAdditionalRecord("", true)->getData()->toString(), + origDnsLayer->getAdditionalRecord("", true)->getData()->toString()); copyDnsLayer.addQuery("bla", pcpp::DNS_TYPE_A, pcpp::DNS_CLASS_ANY); pcpp::IPv4DnsResourceData ipv4DnsData(std::string("1.1.1.1")); @@ -554,14 +550,15 @@ PTF_TEST_CASE(CopyLayerAndPacketTest) PTF_ASSERT_EQUAL(copyDnsLayer.getFirstQuery()->getDnsType(), origDnsLayer->getFirstQuery()->getDnsType(), enum); PTF_ASSERT_EQUAL(copyDnsLayer.getAuthorityCount(), origDnsLayer->getAuthorityCount()); - PTF_ASSERT_EQUAL(copyDnsLayer.getAuthority(".local", false)->getData()->toString(), origDnsLayer->getAuthority("iPhone.local", false)->getData()->toString()); + PTF_ASSERT_EQUAL(copyDnsLayer.getAuthority(".local", false)->getData()->toString(), + origDnsLayer->getAuthority("iPhone.local", false)->getData()->toString()); PTF_ASSERT_EQUAL(copyDnsLayer.getAnswerCount(), origDnsLayer->getAnswerCount()); - PTF_ASSERT_EQUAL(copyDnsLayer.getAdditionalRecord("", true)->getData()->toString(), origDnsLayer->getAdditionalRecord("", true)->getData()->toString()); - -} // CopyLayerAndPacketTest + PTF_ASSERT_EQUAL(copyDnsLayer.getAdditionalRecord("", true)->getData()->toString(), + origDnsLayer->getAdditionalRecord("", true)->getData()->toString()); +} // CopyLayerAndPacketTest PTF_TEST_CASE(PacketLayerLookupTest) { @@ -613,8 +610,7 @@ PTF_TEST_CASE(PacketLayerLookupTest) // try to get nonexistent layer PTF_ASSERT_NULL(vxlanPacket.getLayerOfType(true)); } -} // PacketLayerLookupTest - +} // PacketLayerLookupTest PTF_TEST_CASE(RawPacketTimeStampSetterTest) { @@ -627,8 +623,8 @@ PTF_TEST_CASE(RawPacketTimeStampSetterTest) timespec nsec_test_time; timespec expected_ts; - //test usec-precision setter - usec_test_time.tv_sec = 1583840642; //10.03.2020 15:44 + // test usec-precision setter + usec_test_time.tv_sec = 1583840642; // 10.03.2020 15:44 usec_test_time.tv_usec = 111222; expected_ts.tv_sec = usec_test_time.tv_sec; expected_ts.tv_nsec = usec_test_time.tv_usec * 1000; @@ -637,16 +633,15 @@ PTF_TEST_CASE(RawPacketTimeStampSetterTest) PTF_ASSERT_EQUAL(rawPacket1.getPacketTimeStamp().tv_sec, expected_ts.tv_sec); PTF_ASSERT_EQUAL(rawPacket1.getPacketTimeStamp().tv_nsec, expected_ts.tv_nsec); - //test nsec-precision setter - nsec_test_time.tv_sec = 1583842105; //10.03.2020 16:08 + // test nsec-precision setter + nsec_test_time.tv_sec = 1583842105; // 10.03.2020 16:08 nsec_test_time.tv_nsec = 111222987; expected_ts = nsec_test_time; PTF_ASSERT_TRUE(rawPacket1.setPacketTimeStamp(nsec_test_time)); PTF_ASSERT_EQUAL(rawPacket1.getPacketTimeStamp().tv_sec, expected_ts.tv_sec); PTF_ASSERT_EQUAL(rawPacket1.getPacketTimeStamp().tv_nsec, expected_ts.tv_nsec); -} // RawPacketTimeStampSetterTest - +} // RawPacketTimeStampSetterTest PTF_TEST_CASE(ParsePartialPacketTest) { @@ -739,8 +734,7 @@ PTF_TEST_CASE(ParsePartialPacketTest) PTF_ASSERT_EQUAL(curLayer->getProtocol(), pcpp::GREv0, enum); curLayer = curLayer->getNextLayer(); PTF_ASSERT_NULL(curLayer); -} // ParsePartialPacketTest - +} // ParsePartialPacketTest PTF_TEST_CASE(PacketTrailerTest) { @@ -769,10 +763,14 @@ PTF_TEST_CASE(PacketTrailerTest) PTF_ASSERT_EQUAL(trailerIPv6Packet.getLayerOfType()->getTrailerLen(), 4); PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getTrailerLen(), 28); - PTF_ASSERT_EQUAL(trailerArpPacket.getLayerOfType()->getTrailerDataAsHexString(), "742066726f6d2062726964676500203d3d20"); - PTF_ASSERT_EQUAL(trailerIPv4Packet.getLayerOfType()->getTrailerDataAsHexString(), "0101080a0000"); - PTF_ASSERT_EQUAL(trailerIPv6Packet.getLayerOfType()->getTrailerDataAsHexString(), "cdfcf105"); - PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getTrailerDataAsHexString(), "00000000000000000000000000000000000000000000000000000000"); + PTF_ASSERT_EQUAL(trailerArpPacket.getLayerOfType()->getTrailerDataAsHexString(), + "742066726f6d2062726964676500203d3d20"); + PTF_ASSERT_EQUAL(trailerIPv4Packet.getLayerOfType()->getTrailerDataAsHexString(), + "0101080a0000"); + PTF_ASSERT_EQUAL(trailerIPv6Packet.getLayerOfType()->getTrailerDataAsHexString(), + "cdfcf105"); + PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getTrailerDataAsHexString(), + "00000000000000000000000000000000000000000000000000000000"); PTF_ASSERT_EQUAL(trailerArpPacket.getLayerOfType()->getTrailerData()[3], 0x72, hex); PTF_ASSERT_EQUAL(trailerIPv4Packet.getLayerOfType()->getTrailerData()[2], 0x8, hex); @@ -791,7 +789,8 @@ PTF_TEST_CASE(PacketTrailerTest) PTF_ASSERT_NOT_NULL(ethLayer); PTF_ASSERT_NOT_NULL(ip6Layer); PTF_ASSERT_GREATER_THAN(ethLayer->getDataLen() - ethLayer->getHeaderLen(), ip6Layer->getDataLen()); - PTF_ASSERT_EQUAL(ip6Layer->getDataLen(), be16toh(ip6Layer->getIPv6Header()->payloadLength) + ip6Layer->getHeaderLen()); + PTF_ASSERT_EQUAL(ip6Layer->getDataLen(), + be16toh(ip6Layer->getIPv6Header()->payloadLength) + ip6Layer->getHeaderLen()); // add layer before trailer auto newVlanLayer = new pcpp::VlanLayer(123, true, 1, PCPP_ETHERTYPE_IPV6); @@ -860,7 +859,8 @@ PTF_TEST_CASE(PacketTrailerTest) PTF_ASSERT_EQUAL(trailerIPv4Packet.getLayerOfType()->getDataLen(), 6); // rebuild packet starting from trailer - auto newEthLayer = new pcpp::EthLayer(pcpp::MacAddress("30:46:9a:23:fb:fa"), pcpp::MacAddress("6c:f0:49:b2:de:6e"), PCPP_ETHERTYPE_IP); + auto newEthLayer = new pcpp::EthLayer(pcpp::MacAddress("30:46:9a:23:fb:fa"), pcpp::MacAddress("6c:f0:49:b2:de:6e"), + PCPP_ETHERTYPE_IP); PTF_ASSERT_TRUE(trailerIPv4Packet.insertLayer(nullptr, newEthLayer, true)); auto newIp4Layer = new pcpp::IPv4Layer(pcpp::IPv4Address("173.194.78.104"), pcpp::IPv4Address("10.0.0.1")); newIp4Layer->getIPv4Header()->ipId = htobe16(40382); @@ -893,7 +893,9 @@ PTF_TEST_CASE(PacketTrailerTest) // extend layer just before trailer pcpp::PPPoEDiscoveryLayer* pppoeDiscovery = trailerPPPoEDPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(pppoeDiscovery); + // clang-format off PTF_ASSERT_FALSE(pppoeDiscovery->addTag(pcpp::PPPoEDiscoveryLayer::PPPoETagBuilder(pcpp::PPPoEDiscoveryLayer::PPPOE_TAG_AC_NAME, 0x42524153)).isNull()); + // clang-format on trailerPPPoEDPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getDataLen(), 68); PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getDataLen(), 26); @@ -917,20 +919,19 @@ PTF_TEST_CASE(PacketTrailerTest) PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getDataLen(), 48); PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getDataLen(), 6); PTF_ASSERT_EQUAL(trailerPPPoEDPacket.getLayerOfType()->getDataLen(), 28); -} // PacketTrailerTest - +} // PacketTrailerTest PTF_TEST_CASE(ResizeLayerTest) { uint8_t payload[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa }; pcpp::PayloadLayer payloadLayer(payload, 10); - // Creating a packet - pcpp::Packet packet(1500); - PTF_ASSERT_TRUE(packet.addLayer(&payloadLayer)); + // Creating a packet + pcpp::Packet packet(1500); + PTF_ASSERT_TRUE(packet.addLayer(&payloadLayer)); // Starting Resize testing - PTF_ASSERT_EQUAL(packet.getRawPacket()->getRawDataLen(), 10); // Size of packet before resizing is not correct + PTF_ASSERT_EQUAL(packet.getRawPacket()->getRawDataLen(), 10); // Size of packet before resizing is not correct // // test shortening of packet and layer @@ -940,11 +941,13 @@ PTF_TEST_CASE(ResizeLayerTest) payloadLayer.setPayload(payload2, payload2_size); // check that resizing worked in terms of data length - PTF_ASSERT_EQUAL(packet.getRawPacket()->getRawDataLen(), (int)payload2_size); // Size of packet after first resizing (shortening) is not correct + PTF_ASSERT_EQUAL(packet.getRawPacket()->getRawDataLen(), + (int)payload2_size); // Size of packet after first resizing (shortening) is not correct // confirm that data has been correctly written to raw packet - const uint8_t* rawData = packet.getRawPacket()->getRawData() + (packet.getRawPacket()->getRawDataLen() - payload2_size); - PTF_ASSERT_EQUAL(rawData[0], 0x05); // Setting payload to new payload has failed. + const uint8_t* rawData = + packet.getRawPacket()->getRawData() + (packet.getRawPacket()->getRawDataLen() - payload2_size); + PTF_ASSERT_EQUAL(rawData[0], 0x05); // Setting payload to new payload has failed. PTF_ASSERT_EQUAL(rawData[1], 0x04); PTF_ASSERT_EQUAL(rawData[2], 0x03); PTF_ASSERT_EQUAL(rawData[3], 0x02); @@ -958,11 +961,13 @@ PTF_TEST_CASE(ResizeLayerTest) payloadLayer.setPayload(payload3, payload3_size); // check that resizing worked in terms of data length - PTF_ASSERT_EQUAL(packet.getRawPacket()->getRawDataLen(), (int)payload3_size); // Size of packet after second resizing (extension) is not correct + PTF_ASSERT_EQUAL(packet.getRawPacket()->getRawDataLen(), + (int)payload3_size); // Size of packet after second resizing (extension) is not correct // confirm that data has been correctly written to raw packet - const uint8_t* rawData2 = packet.getRawPacket()->getRawData() + (packet.getRawPacket()->getRawDataLen() - payload3_size); - PTF_ASSERT_EQUAL(rawData2[0], 0xDE); // Setting payload to new payload has failed. + const uint8_t* rawData2 = + packet.getRawPacket()->getRawData() + (packet.getRawPacket()->getRawDataLen() - payload3_size); + PTF_ASSERT_EQUAL(rawData2[0], 0xDE); // Setting payload to new payload has failed. PTF_ASSERT_EQUAL(rawData2[1], 0xAD); PTF_ASSERT_EQUAL(rawData2[2], 0xBE); PTF_ASSERT_EQUAL(rawData2[3], 0xEF); @@ -970,8 +975,7 @@ PTF_TEST_CASE(ResizeLayerTest) PTF_ASSERT_EQUAL(rawData2[5], 0xAD); PTF_ASSERT_EQUAL(rawData2[6], 0xBE); PTF_ASSERT_EQUAL(rawData2[7], 0xEF); -} // ResizeLayerTest - +} // ResizeLayerTest PTF_TEST_CASE(PrintPacketAndLayersTest) { @@ -981,9 +985,9 @@ PTF_TEST_CASE(PrintPacketAndLayersTest) // convert the timestamp to a printable format time_t nowtime = time.tv_sec; - struct tm *nowtm = nullptr; + struct tm* nowtm = nullptr; #if __cplusplus > 199711L && !defined(_WIN32) - // localtime_r is a thread-safe versions of localtime, + // localtime_r is a thread-safe versions of localtime, // but they're defined only in newer compilers (>= C++0x). // on Windows localtime is already thread-safe so there is not need // to use localtime_r @@ -1001,7 +1005,8 @@ PTF_TEST_CASE(PrintPacketAndLayersTest) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/MplsPackets1.dat"); pcpp::Packet packet(&rawPacket1); - std::string expectedPacketHeaderString = "Packet length: 361 [Bytes], Arrival time: " + std::string(tmbuf) + ".000000000"; + std::string expectedPacketHeaderString = + "Packet length: 361 [Bytes], Arrival time: " + std::string(tmbuf) + ".000000000"; std::vector expectedLayerStrings; expectedLayerStrings.push_back("Ethernet II Layer, Src: 50:81:89:f9:d5:7b, Dst: 28:c2:ce:ba:97:e8"); expectedLayerStrings.push_back("VLAN Layer, Priority: 0, Vlan ID: 215, CFI: 0"); @@ -1040,8 +1045,7 @@ PTF_TEST_CASE(PrintPacketAndLayersTest) std::vector packetAsStringList; packet.toStringList(packetAsStringList); PTF_ASSERT_TRUE(packetAsStringList == expectedLayerStrings); -} // PrintPacketAndLayer - +} // PrintPacketAndLayer PTF_TEST_CASE(ProtocolFamilyMembershipTest) { diff --git a/Tests/Packet++Test/Tests/PacketUtilsTests.cpp b/Tests/Packet++Test/Tests/PacketUtilsTests.cpp index 70b30a7f76..16d1e1bb2e 100644 --- a/Tests/Packet++Test/Tests/PacketUtilsTests.cpp +++ b/Tests/Packet++Test/Tests/PacketUtilsTests.cpp @@ -25,7 +25,6 @@ PTF_TEST_CASE(PacketUtilsHash5TupleUdp) srcDstPacket.addLayer(&udpLayer); srcDstPacket.computeCalculateFields(); - pcpp::IPv4Layer ipLayer2(dstIP, srcIP); ipLayer2.getIPv4Header()->ipId = htobe16(20300); ipLayer2.getIPv4Header()->fragmentOffset = htobe16(0x4000); @@ -48,7 +47,7 @@ PTF_TEST_CASE(PacketUtilsHash5TupleUdp) PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, false), 683027169); PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, true), 683027169); -} // PacketUtilsHash5TupleUdp +} // PacketUtilsHash5TupleUdp PTF_TEST_CASE(PacketUtilsHash5TupleTcp) { @@ -70,7 +69,6 @@ PTF_TEST_CASE(PacketUtilsHash5TupleTcp) srcDstPacket.addLayer(&tcpLayer); srcDstPacket.computeCalculateFields(); - pcpp::IPv4Layer ipLayer2(dstIP, srcIP); ipLayer2.getIPv4Header()->ipId = htobe16(20300); ipLayer2.getIPv4Header()->fragmentOffset = htobe16(0x4000); @@ -94,8 +92,8 @@ PTF_TEST_CASE(PacketUtilsHash5TupleTcp) PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&srcDstPacket, false), 1576639238); PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&srcDstPacket, true), 2243556734); - PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, false), 1576639238 ); - PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, true), 1576639238 ); + PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, false), 1576639238); + PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&dstSrcPacket, true), 1576639238); tcpLayer.getTcpHeader()->portDst = 80; tcpLayer.getTcpHeader()->portSrc = 80; @@ -104,10 +102,9 @@ PTF_TEST_CASE(PacketUtilsHash5TupleTcp) tcpLayer2.getTcpHeader()->portSrc = 80; PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&srcDstPacket), pcpp::hash5Tuple(&dstSrcPacket)); - PTF_ASSERT_NOT_EQUAL(pcpp::hash5Tuple(&srcDstPacket,true), pcpp::hash5Tuple(&dstSrcPacket,true)); - -} // PacketUtilsHash5TupleTcp + PTF_ASSERT_NOT_EQUAL(pcpp::hash5Tuple(&srcDstPacket, true), pcpp::hash5Tuple(&dstSrcPacket, true)); +} // PacketUtilsHash5TupleTcp PTF_TEST_CASE(PacketUtilsHash5TupleIPv6) { @@ -122,7 +119,6 @@ PTF_TEST_CASE(PacketUtilsHash5TupleIPv6) srcDstPacket.addLayer(&udpLayer); srcDstPacket.computeCalculateFields(); - pcpp::IPv6Layer ipLayer2(dstIP, srcIP); pcpp::UdpLayer udpLayer2(1900, 63628); @@ -151,4 +147,4 @@ PTF_TEST_CASE(PacketUtilsHash5TupleIPv6) PTF_ASSERT_EQUAL(pcpp::hash5Tuple(&srcDstPacket), pcpp::hash5Tuple(&dstSrcPacket)); PTF_ASSERT_NOT_EQUAL(pcpp::hash5Tuple(&srcDstPacket, true), pcpp::hash5Tuple(&dstSrcPacket, true)); -} // PacketUtilsHash5TupleIPv6 +} // PacketUtilsHash5TupleIPv6 diff --git a/Tests/Packet++Test/Tests/RadiusTests.cpp b/Tests/Packet++Test/Tests/RadiusTests.cpp index 01339f8ae8..c213b2ccb9 100644 --- a/Tests/Packet++Test/Tests/RadiusTests.cpp +++ b/Tests/Packet++Test/Tests/RadiusTests.cpp @@ -8,7 +8,6 @@ #include "RadiusLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(RadiusLayerParsingTest) { timeval time; @@ -30,7 +29,7 @@ PTF_TEST_CASE(RadiusLayerParsingTest) size_t attrDataSize[10] = { 4, 4, 4, 12, 17, 17, 4, 4, 17, 16 }; pcpp::RadiusAttribute radiusAttr = radiusLayer->getFirstAttribute(); PTF_PRINT_VERBOSE("Iterating over RADIUS attributes"); - for (int i=0; i<10; i++) + for (int i = 0; i < 10; i++) { PTF_PRINT_VERBOSE("Iteration #" << i); PTF_ASSERT_EQUAL(radiusAttr.getType(), attrTypes[i]); @@ -63,7 +62,7 @@ PTF_TEST_CASE(RadiusLayerParsingTest) size_t attrDataSize2[2] = { 4, 16 }; radiusAttr = radiusLayer->getFirstAttribute(); PTF_PRINT_VERBOSE("Iterating over RADIUS attributes"); - for (int i=0; i<2; i++) + for (int i = 0; i < 2; i++) { PTF_PRINT_VERBOSE("Iteration #" << i); PTF_ASSERT_EQUAL(radiusAttr.getType(), attrTypes2[i]); @@ -78,9 +77,7 @@ PTF_TEST_CASE(RadiusLayerParsingTest) radiusLayer = radiusPacket3.getLayerOfType(); PTF_ASSERT_NULL(radiusLayer); -} // RadiusLayerParsingTest - - +} // RadiusLayerParsingTest PTF_TEST_CASE(RadiusLayerCreationTest) { @@ -97,7 +94,8 @@ PTF_TEST_CASE(RadiusLayerCreationTest) pcpp::UdpLayer udpLayer(*radiusPacket.getLayerOfType()); pcpp::RadiusLayer radiusLayer(11, 5, "f050649184625d36f14c9075b7a48b83"); - pcpp::RadiusAttribute radiusNewAttr = radiusLayer.addAttribute(pcpp::RadiusAttributeBuilder(8, pcpp::IPv4Address("255.255.255.254"))); + pcpp::RadiusAttribute radiusNewAttr = + radiusLayer.addAttribute(pcpp::RadiusAttributeBuilder(8, pcpp::IPv4Address("255.255.255.254"))); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); PTF_ASSERT_EQUAL(radiusNewAttr.getType(), 8); PTF_ASSERT_EQUAL(radiusNewAttr.getDataSize(), 4); @@ -124,17 +122,20 @@ PTF_TEST_CASE(RadiusLayerCreationTest) PTF_ASSERT_EQUAL(radiusNewAttr.getType(), 6); PTF_ASSERT_EQUAL(radiusNewAttr.getDataSize(), 4); - uint8_t attrValue1[] = { 0xc6, 0xd1, 0x95, 0x03, 0x2f, 0xdc, 0x30, 0x24, 0x0f, 0x73, 0x13, 0xb2, 0x31, 0xef, 0x1d, 0x77 }; + uint8_t attrValue1[] = { 0xc6, 0xd1, 0x95, 0x03, 0x2f, 0xdc, 0x30, 0x24, + 0x0f, 0x73, 0x13, 0xb2, 0x31, 0xef, 0x1d, 0x77 }; uint8_t attrValue1Len = 16; radiusNewAttr = radiusLayer.addAttribute(pcpp::RadiusAttributeBuilder(24, attrValue1, attrValue1Len)); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); - uint8_t attrValue2[] = { 0x01, 0x01, 0x00, 0x16, 0x04, 0x10, 0x26, 0x6b, 0x0e, 0x9a, 0x58, 0x32, 0x2f, 0x4d, 0x01, 0xab, 0x25, 0xb3, 0x5f, 0x87, 0x94, 0x64 }; + uint8_t attrValue2[] = { 0x01, 0x01, 0x00, 0x16, 0x04, 0x10, 0x26, 0x6b, 0x0e, 0x9a, 0x58, + 0x32, 0x2f, 0x4d, 0x01, 0xab, 0x25, 0xb3, 0x5f, 0x87, 0x94, 0x64 }; uint8_t attrValue2Len = 22; radiusNewAttr = radiusLayer.addAttributeAfter(pcpp::RadiusAttributeBuilder(79, attrValue2, attrValue2Len), 18); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); - uint8_t attrValue3[] = { 0x11, 0xb5, 0x04, 0x3c, 0x8a, 0x28, 0x87, 0x58, 0x17, 0x31, 0x33, 0xa5, 0xe0, 0x74, 0x34, 0xcf }; + uint8_t attrValue3[] = { 0x11, 0xb5, 0x04, 0x3c, 0x8a, 0x28, 0x87, 0x58, + 0x17, 0x31, 0x33, 0xa5, 0xe0, 0x74, 0x34, 0xcf }; uint8_t attrValue3Len = 16; radiusNewAttr = radiusLayer.addAttributeAfter(pcpp::RadiusAttributeBuilder(80, attrValue3, attrValue3Len), 79); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); @@ -145,9 +146,7 @@ PTF_TEST_CASE(RadiusLayerCreationTest) pcpp::RadiusLayer* newRadiusLayer = newRadiusPacket.getLayerOfType(); PTF_ASSERT_EQUAL(origRadiusLayer->getDataLen(), newRadiusLayer->getDataLen()); PTF_ASSERT_BUF_COMPARE(origRadiusLayer->getData(), newRadiusLayer->getData(), origRadiusLayer->getDataLen()); -} // RadiusLayerCreationTest - - +} // RadiusLayerCreationTest PTF_TEST_CASE(RadiusLayerEditTest) { @@ -171,7 +170,8 @@ PTF_TEST_CASE(RadiusLayerEditTest) PTF_ASSERT_TRUE(radiusLayer->removeAttribute(80)); PTF_ASSERT_TRUE(radiusLayer->removeAttribute(24)); - pcpp::RadiusAttribute radiusNewAttr = radiusLayer->addAttributeAfter(pcpp::RadiusAttributeBuilder(18, std::string("Hello, John.McGuirk")), 6); + pcpp::RadiusAttribute radiusNewAttr = + radiusLayer->addAttributeAfter(pcpp::RadiusAttributeBuilder(18, std::string("Hello, John.McGuirk")), 6); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); uint8_t attrValue1[] = { 0x03, 0x01, 0x00, 0x04 }; @@ -179,7 +179,8 @@ PTF_TEST_CASE(RadiusLayerEditTest) radiusNewAttr = radiusLayer->addAttributeAfter(pcpp::RadiusAttributeBuilder(79, attrValue1, attrValue1Len), 18); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); - uint8_t attrValue2[] = { 0xb9, 0xc4, 0xae, 0x62, 0x13, 0xa7, 0x1d, 0x32, 0x12, 0x5e, 0xf7, 0xca, 0x4e, 0x4c, 0x63, 0x60 }; + uint8_t attrValue2[] = { 0xb9, 0xc4, 0xae, 0x62, 0x13, 0xa7, 0x1d, 0x32, + 0x12, 0x5e, 0xf7, 0xca, 0x4e, 0x4c, 0x63, 0x60 }; uint8_t attrValue2Len = 16; radiusNewAttr = radiusLayer->addAttributeAfter(pcpp::RadiusAttributeBuilder(80, attrValue2, attrValue2Len), 79); PTF_ASSERT_FALSE(radiusNewAttr.isNull()); @@ -193,7 +194,6 @@ PTF_TEST_CASE(RadiusLayerEditTest) PTF_ASSERT_EQUAL(msg2OrigRadiusLayer->getDataLen(), radiusLayer->getDataLen()); PTF_ASSERT_BUF_COMPARE(msg2OrigRadiusLayer->getData(), radiusLayer->getData(), msg2OrigRadiusLayer->getDataLen()); - // remove all attributes test PTF_ASSERT_TRUE(msg2OrigRadiusLayer->removeAllAttributes()); @@ -203,4 +203,4 @@ PTF_TEST_CASE(RadiusLayerEditTest) PTF_ASSERT_TRUE(msg2OrigRadiusLayer->getFirstAttribute().isNull()); PTF_ASSERT_TRUE(msg2OrigRadiusLayer->getAttribute(6).isNull()); PTF_ASSERT_TRUE(msg2OrigRadiusLayer->getAttribute(80).isNull()); -} // RadiusLayerEditTest +} // RadiusLayerEditTest diff --git a/Tests/Packet++Test/Tests/S7CommTests.cpp b/Tests/Packet++Test/Tests/S7CommTests.cpp index b644ed51fa..e7bc2267a4 100644 --- a/Tests/Packet++Test/Tests/S7CommTests.cpp +++ b/Tests/Packet++Test/Tests/S7CommTests.cpp @@ -5,7 +5,6 @@ #include "S7CommLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(S7CommLayerParsingTest) { timeval time; @@ -14,7 +13,7 @@ PTF_TEST_CASE(S7CommLayerParsingTest) pcpp::Packet s7CommLayerTest(&rawPacket1); PTF_ASSERT_TRUE(s7CommLayerTest.isPacketOfType(pcpp::S7COMM)); - auto *S7CommLayer = s7CommLayerTest.getLayerOfType(); + auto* S7CommLayer = s7CommLayerTest.getLayerOfType(); PTF_ASSERT_NOT_NULL(S7CommLayer); PTF_ASSERT_EQUAL(S7CommLayer->getProtocolId(), 50); @@ -26,14 +25,14 @@ PTF_TEST_CASE(S7CommLayerParsingTest) PTF_ASSERT_EQUAL(S7CommLayer->toString(), "S7Comm Layer, Userdata"); PTF_ASSERT_EQUAL(S7CommLayer->getParameter()->getDataLength(), 12); - uint8_t expectedParameterData[] = {0, 1, 18, 8, 18, 132, 1, 1, 0, 0, 0, 0}; + uint8_t expectedParameterData[] = { 0, 1, 18, 8, 18, 132, 1, 1, 0, 0, 0, 0 }; PTF_ASSERT_BUF_COMPARE(S7CommLayer->getParameter()->getData(), expectedParameterData, 12); READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/s7comm_ack_data.dat"); pcpp::Packet s7CommLayerTest2(&rawPacket2); PTF_ASSERT_TRUE(s7CommLayerTest2.isPacketOfType(pcpp::S7COMM)); - auto *s7commLayer = s7CommLayerTest2.getLayerOfType(); + auto* s7commLayer = s7CommLayerTest2.getLayerOfType(); PTF_ASSERT_NOT_NULL(s7commLayer); PTF_ASSERT_EQUAL(s7commLayer->getProtocolId(), 50); PTF_ASSERT_EQUAL(s7commLayer->getMsgType(), 3); @@ -51,10 +50,9 @@ PTF_TEST_CASE(S7CommLayerParsingTest) PTF_ASSERT_EQUAL(s7commLayer->getErrorClass(), 7); PTF_ASSERT_EQUAL(s7commLayer->getErrorCode(), 6); PTF_ASSERT_EQUAL(s7commLayer->getParameter()->getDataLength(), 2); - uint8_t expectedErrorParameterData[] = {4, 1}; + uint8_t expectedErrorParameterData[] = { 4, 1 }; PTF_ASSERT_BUF_COMPARE(s7commLayer->getParameter()->getData(), expectedErrorParameterData, 2); -} // S7CommLayerParsingTest - +} // S7CommLayerParsingTest PTF_TEST_CASE(S7CommLayerCreationTest) { @@ -84,4 +82,4 @@ PTF_TEST_CASE(S7CommLayerCreationTest) PTF_ASSERT_EQUAL(newS7commLayer2.getErrorCode(), 2); PTF_ASSERT_EQUAL(newS7commLayer2.getHeaderLen(), 82); PTF_ASSERT_EQUAL(newS7commLayer2.toString(), "S7Comm Layer, Ack-Data"); -} // S7CommLayerCreationTest +} // S7CommLayerCreationTest diff --git a/Tests/Packet++Test/Tests/SSHTests.cpp b/Tests/Packet++Test/Tests/SSHTests.cpp index d7e7a19b83..c048451e76 100644 --- a/Tests/Packet++Test/Tests/SSHTests.cpp +++ b/Tests/Packet++Test/Tests/SSHTests.cpp @@ -14,16 +14,17 @@ PTF_TEST_CASE(SSHParsingTest) // SSH Identification PTF_ASSERT_TRUE(sshIdentificationPacket.isPacketOfType(pcpp::SSH)); - pcpp::SSHIdentificationMessage* sshIdentLayer = sshIdentificationPacket.getLayerOfType(); + pcpp::SSHIdentificationMessage* sshIdentLayer = + sshIdentificationPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(sshIdentLayer); PTF_ASSERT_EQUAL(sshIdentLayer->getIdentificationMessage(), "SSH-2.0-OpenSSH_5.3"); - // SSH Key Exchange Init READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/SSHKexInit.dat"); pcpp::Packet sshKexInitPacket(&rawPacket2); PTF_ASSERT_TRUE(sshKexInitPacket.isPacketOfType(pcpp::SSH)); - pcpp::SSHKeyExchangeInitMessage* sshKexInitLayer = sshKexInitPacket.getLayerOfType(); + pcpp::SSHKeyExchangeInitMessage* sshKexInitLayer = + sshKexInitPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(sshKexInitLayer); PTF_ASSERT_EQUAL(sshKexInitLayer->getHeaderLen(), 904); PTF_ASSERT_EQUAL(sshKexInitLayer->getPaddingLength(), 4); @@ -32,19 +33,30 @@ PTF_TEST_CASE(SSHParsingTest) PTF_ASSERT_EQUAL(sshKexInitLayer->getMessageTypeStr(), "Key Exchange Init"); PTF_ASSERT_EQUAL(sshKexInitLayer->toString(), "SSH Layer, Handshake Message: Key Exchange Init"); PTF_ASSERT_EQUAL(sshKexInitLayer->getCookieAsHexStream(), "0e7b9a0807ea71e0945dd1fdbfa41929"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getKeyExchangeAlgorithms(), "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getServerHostKeyAlgorithms(), "ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getEncryptionAlgorithmsClientToServer(), "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getEncryptionAlgorithmsServerToClient(), "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getMacAlgorithmsClientToServer(), "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getMacAlgorithmsServerToClient(), "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getKeyExchangeAlgorithms(), + "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getServerHostKeyAlgorithms(), + "ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getEncryptionAlgorithmsClientToServer(), + "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getEncryptionAlgorithmsServerToClient(), + "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getMacAlgorithmsClientToServer(), + "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getMacAlgorithmsServerToClient(), + "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"); PTF_ASSERT_EQUAL(sshKexInitLayer->getCompressionAlgorithmsClientToServer(), "none,zlib@openssh.com,zlib"); PTF_ASSERT_EQUAL(sshKexInitLayer->getCompressionAlgorithmsServerToClient(), "none,zlib@openssh.com,zlib"); PTF_ASSERT_EQUAL(sshKexInitLayer->getLanguagesClientToServer(), ""); PTF_ASSERT_EQUAL(sshKexInitLayer->getLanguagesServerToClient(), ""); PTF_ASSERT_FALSE(sshKexInitLayer->isFirstKexPacketFollows()); - READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/SSHNewKeysAndKexDH.dat"); pcpp::Packet sshNewKeysKexDHPacket(&rawPacket3); PTF_ASSERT_TRUE(sshNewKeysKexDHPacket.isPacketOfType(pcpp::SSH)); @@ -56,7 +68,8 @@ PTF_TEST_CASE(SSHParsingTest) PTF_ASSERT_EQUAL(sshHandshakeMessage->getSSHHandshakeMessageLength(), 691); PTF_ASSERT_EQUAL(sshHandshakeMessage->getMessageType(), pcpp::SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_REPLY, enum); PTF_ASSERT_EQUAL(sshHandshakeMessage->getMessageTypeStr(), "Diffie-Hellman Group Exchange Reply"); - PTF_ASSERT_EQUAL(sshHandshakeMessage->toString(), "SSH Layer, Handshake Message: Diffie-Hellman Group Exchange Reply"); + PTF_ASSERT_EQUAL(sshHandshakeMessage->toString(), + "SSH Layer, Handshake Message: Diffie-Hellman Group Exchange Reply"); // SSH New Keys sshHandshakeMessage = sshNewKeysKexDHPacket.getNextLayerOfType(sshHandshakeMessage); @@ -68,7 +81,6 @@ PTF_TEST_CASE(SSHParsingTest) PTF_ASSERT_EQUAL(sshHandshakeMessage->getMessageTypeStr(), "New Keys"); PTF_ASSERT_EQUAL(sshHandshakeMessage->toString(), "SSH Layer, Handshake Message: New Keys"); - // SSH DH Group Exchange Init READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/SSHDHGexInit.dat"); pcpp::Packet sshDHGexInit(&rawPacket4); @@ -80,8 +92,8 @@ PTF_TEST_CASE(SSHParsingTest) PTF_ASSERT_EQUAL(sshHandshakeMessage->getSSHHandshakeMessageLength(), 133); PTF_ASSERT_EQUAL(sshHandshakeMessage->getMessageType(), pcpp::SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_INIT, enum); PTF_ASSERT_EQUAL(sshHandshakeMessage->getMessageTypeStr(), "Diffie-Hellman Group Exchange Init"); - PTF_ASSERT_EQUAL(sshHandshakeMessage->toString(), "SSH Layer, Handshake Message: Diffie-Hellman Group Exchange Init"); - + PTF_ASSERT_EQUAL(sshHandshakeMessage->toString(), + "SSH Layer, Handshake Message: Diffie-Hellman Group Exchange Init"); // SSH Encrypted Message READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/SSHEncryptedMessage.dat"); @@ -93,7 +105,6 @@ PTF_TEST_CASE(SSHParsingTest) PTF_ASSERT_EQUAL(sshEncryptedMsgLayer->toString(), "SSH Layer, Encrypted Message"); } - PTF_TEST_CASE(SSHMalformedParsingTest) { timeval time; @@ -127,21 +138,31 @@ PTF_TEST_CASE(SSHMalformedParsingTest) PTF_ASSERT_NULL(sshMessageMalformedTypePacket.getLayerOfType()); PTF_ASSERT_NOT_NULL(sshMessageMalformedTypePacket.getLayerOfType()); - //KexInit with malformed size of MacAlgorithmsClientToServer (size is greater than the size of the rest of the layer) + // KexInit with malformed size of MacAlgorithmsClientToServer (size is greater than the size of the rest of the + // layer) READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/SSHKexInit_Malformed.dat"); pcpp::Packet sshKexInitMalformedPacket(&rawPacket5); PTF_ASSERT_TRUE(sshKexInitMalformedPacket.isPacketOfType(pcpp::SSH)); - pcpp::SSHKeyExchangeInitMessage* sshKexInitLayer = sshKexInitMalformedPacket.getLayerOfType(); + pcpp::SSHKeyExchangeInitMessage* sshKexInitLayer = + sshKexInitMalformedPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(sshKexInitLayer); PTF_ASSERT_EQUAL(sshKexInitLayer->getHeaderLen(), 904); PTF_ASSERT_EQUAL(sshKexInitLayer->getPaddingLength(), 4); PTF_ASSERT_EQUAL(sshKexInitLayer->getSSHHandshakeMessageLength(), 894); PTF_ASSERT_EQUAL(sshKexInitLayer->getMessageType(), pcpp::SSHHandshakeMessage::SSH_MSG_KEX_INIT, enum); PTF_ASSERT_EQUAL(sshKexInitLayer->getCookieAsHexStream(), "0e7b9a0807ea71e0945dd1fdbfa41929"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getKeyExchangeAlgorithms(), "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getServerHostKeyAlgorithms(), "ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getEncryptionAlgorithmsClientToServer(), "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); - PTF_ASSERT_EQUAL(sshKexInitLayer->getEncryptionAlgorithmsServerToClient(), "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getKeyExchangeAlgorithms(), + "diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getServerHostKeyAlgorithms(), + "ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getEncryptionAlgorithmsClientToServer(), + "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); + PTF_ASSERT_EQUAL( + sshKexInitLayer->getEncryptionAlgorithmsServerToClient(), + "aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"); PTF_ASSERT_EQUAL(sshKexInitLayer->getMacAlgorithmsClientToServer(), ""); PTF_ASSERT_EQUAL(sshKexInitLayer->getMacAlgorithmsServerToClient(), ""); PTF_ASSERT_EQUAL(sshKexInitLayer->getCompressionAlgorithmsClientToServer(), ""); diff --git a/Tests/Packet++Test/Tests/SSLTests.cpp b/Tests/Packet++Test/Tests/SSLTests.cpp index 1ca311bcea..98d6681c5f 100644 --- a/Tests/Packet++Test/Tests/SSLTests.cpp +++ b/Tests/Packet++Test/Tests/SSLTests.cpp @@ -7,7 +7,6 @@ #include #include - PTF_TEST_CASE(SSLClientHelloParsingTest) { timeval time; @@ -20,7 +19,8 @@ PTF_TEST_CASE(SSLClientHelloParsingTest) pcpp::SSLHandshakeLayer* handshakeLayer = clientHelloPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessagesCount(), 1); - pcpp::SSLClientHelloMessage* clientHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessageAt(0), clientHelloMessage, ptr); PTF_ASSERT_NOT_NULL(clientHelloMessage); PTF_ASSERT_EQUAL(handshakeLayer->getRecordType(), pcpp::SSL_HANDSHAKE, enum); @@ -35,75 +35,41 @@ PTF_TEST_CASE(SSLClientHelloParsingTest) PTF_ASSERT_NULL(clientHelloMessage->getSessionID()); PTF_ASSERT_EQUAL(clientHelloMessage->getCipherSuiteCount(), 11); - uint16_t cipherSuiteIDs[11] = { 0xc02b, 0xc02f, 0xc00a, 0xc009, 0xc013, 0xc014, 0x0033, 0x0039, 0x002f, 0x0035, 0x000a }; - std::string cipherSuiteNames[11] = { - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", - "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", - "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", - "TLS_RSA_WITH_AES_128_CBC_SHA", - "TLS_RSA_WITH_AES_256_CBC_SHA", - "TLS_RSA_WITH_3DES_EDE_CBC_SHA" - }; + uint16_t cipherSuiteIDs[11] = { 0xc02b, 0xc02f, 0xc00a, 0xc009, 0xc013, 0xc014, + 0x0033, 0x0039, 0x002f, 0x0035, 0x000a }; + std::string cipherSuiteNames[11] = { "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_AES_128_CBC_SHA", + "TLS_RSA_WITH_AES_256_CBC_SHA", + "TLS_RSA_WITH_3DES_EDE_CBC_SHA" }; pcpp::SSLKeyExchangeAlgorithm cipherSuiteKey[11] = { - pcpp::SSL_KEYX_ECDHE, - pcpp::SSL_KEYX_ECDHE, - pcpp::SSL_KEYX_ECDHE, - pcpp::SSL_KEYX_ECDHE, - pcpp::SSL_KEYX_ECDHE, - pcpp::SSL_KEYX_ECDHE, - pcpp::SSL_KEYX_DHE, - pcpp::SSL_KEYX_DHE, - pcpp::SSL_KEYX_RSA, - pcpp::SSL_KEYX_RSA, - pcpp::SSL_KEYX_RSA + pcpp::SSL_KEYX_ECDHE, pcpp::SSL_KEYX_ECDHE, pcpp::SSL_KEYX_ECDHE, pcpp::SSL_KEYX_ECDHE, + pcpp::SSL_KEYX_ECDHE, pcpp::SSL_KEYX_ECDHE, pcpp::SSL_KEYX_DHE, pcpp::SSL_KEYX_DHE, + pcpp::SSL_KEYX_RSA, pcpp::SSL_KEYX_RSA, pcpp::SSL_KEYX_RSA }; pcpp::SSLAuthenticationAlgorithm cipherSuiteAuth[11] = { - pcpp::SSL_AUTH_ECDSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_ECDSA, - pcpp::SSL_AUTH_ECDSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_RSA, - pcpp::SSL_AUTH_RSA + pcpp::SSL_AUTH_ECDSA, pcpp::SSL_AUTH_RSA, pcpp::SSL_AUTH_ECDSA, pcpp::SSL_AUTH_ECDSA, + pcpp::SSL_AUTH_RSA, pcpp::SSL_AUTH_RSA, pcpp::SSL_AUTH_RSA, pcpp::SSL_AUTH_RSA, + pcpp::SSL_AUTH_RSA, pcpp::SSL_AUTH_RSA, pcpp::SSL_AUTH_RSA }; pcpp::SSLSymetricEncryptionAlgorithm cipherSuiteSym[11] = { - pcpp::SSL_SYM_AES_128_GCM, - pcpp::SSL_SYM_AES_128_GCM, - pcpp::SSL_SYM_AES_256_CBC, - pcpp::SSL_SYM_AES_128_CBC, - pcpp::SSL_SYM_AES_128_CBC, - pcpp::SSL_SYM_AES_256_CBC, - pcpp::SSL_SYM_AES_128_CBC, - pcpp::SSL_SYM_AES_256_CBC, - pcpp::SSL_SYM_AES_128_CBC, - pcpp::SSL_SYM_AES_256_CBC, - pcpp::SSL_SYM_3DES_EDE_CBC + pcpp::SSL_SYM_AES_128_GCM, pcpp::SSL_SYM_AES_128_GCM, pcpp::SSL_SYM_AES_256_CBC, pcpp::SSL_SYM_AES_128_CBC, + pcpp::SSL_SYM_AES_128_CBC, pcpp::SSL_SYM_AES_256_CBC, pcpp::SSL_SYM_AES_128_CBC, pcpp::SSL_SYM_AES_256_CBC, + pcpp::SSL_SYM_AES_128_CBC, pcpp::SSL_SYM_AES_256_CBC, pcpp::SSL_SYM_3DES_EDE_CBC }; - pcpp::SSLHashingAlgorithm cipherSuiteHash[11] = { - pcpp::SSL_HASH_SHA256, - pcpp::SSL_HASH_SHA256, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA, - pcpp::SSL_HASH_SHA - }; + pcpp::SSLHashingAlgorithm cipherSuiteHash[11] = { pcpp::SSL_HASH_SHA256, pcpp::SSL_HASH_SHA256, pcpp::SSL_HASH_SHA, + pcpp::SSL_HASH_SHA, pcpp::SSL_HASH_SHA, pcpp::SSL_HASH_SHA, + pcpp::SSL_HASH_SHA, pcpp::SSL_HASH_SHA, pcpp::SSL_HASH_SHA, + pcpp::SSL_HASH_SHA, pcpp::SSL_HASH_SHA }; PTF_PRINT_VERBOSE("Iterating over cipher suites"); for (int i = 0; i < clientHelloMessage->getCipherSuiteCount(); i++) @@ -128,17 +94,20 @@ PTF_TEST_CASE(SSLClientHelloParsingTest) pcpp::SSLExtension* ext = clientHelloMessage->getExtension(0); PTF_ASSERT_EQUAL(ext->getType(), pcpp::SSL_EXT_SERVER_NAME, enum); - pcpp::SSLServerNameIndicationExtension* serverNameExt = clientHelloMessage->getExtensionOfType(); + pcpp::SSLServerNameIndicationExtension* serverNameExt = + clientHelloMessage->getExtensionOfType(); PTF_ASSERT_NOT_NULL(serverNameExt); PTF_ASSERT_EQUAL(serverNameExt->getHostName(), "www.google.com"); - pcpp::TLSECPointFormatExtension* ecPointFormatExt = clientHelloMessage->getExtensionOfType(); + pcpp::TLSECPointFormatExtension* ecPointFormatExt = + clientHelloMessage->getExtensionOfType(); PTF_ASSERT_NOT_NULL(ecPointFormatExt); std::vector ecPointFormatList = ecPointFormatExt->getECPointFormatList(); PTF_ASSERT_EQUAL(ecPointFormatList.size(), 1); PTF_ASSERT_EQUAL(ecPointFormatList.at(0), 0); - pcpp::TLSSupportedGroupsExtension* supportedGroupsExt = clientHelloMessage->getExtensionOfType(); + pcpp::TLSSupportedGroupsExtension* supportedGroupsExt = + clientHelloMessage->getExtensionOfType(); PTF_ASSERT_NOT_NULL(supportedGroupsExt); std::vector supportedGroups = supportedGroupsExt->getSupportedGroups(); PTF_ASSERT_EQUAL(supportedGroups.size(), 3); @@ -146,9 +115,15 @@ PTF_TEST_CASE(SSLClientHelloParsingTest) PTF_ASSERT_EQUAL(supportedGroups.at(1), 24); PTF_ASSERT_EQUAL(supportedGroups.at(2), 25); - pcpp::SSLExtensionType extTypes[9] = { pcpp::SSL_EXT_SERVER_NAME, pcpp::SSL_EXT_RENEGOTIATION_INFO, pcpp::SSL_EXT_SUPPORTED_GROUPS, pcpp::SSL_EXT_EC_POINT_FORMATS, - pcpp::SSL_EXT_SESSIONTICKET_TLS, pcpp::SSL_EXT_Unknown, pcpp::SSL_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION, pcpp::SSL_EXT_STATUS_REQUEST, - pcpp::SSL_EXT_SIGNATURE_ALGORITHMS }; + pcpp::SSLExtensionType extTypes[9] = { pcpp::SSL_EXT_SERVER_NAME, + pcpp::SSL_EXT_RENEGOTIATION_INFO, + pcpp::SSL_EXT_SUPPORTED_GROUPS, + pcpp::SSL_EXT_EC_POINT_FORMATS, + pcpp::SSL_EXT_SESSIONTICKET_TLS, + pcpp::SSL_EXT_Unknown, + pcpp::SSL_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION, + pcpp::SSL_EXT_STATUS_REQUEST, + pcpp::SSL_EXT_SIGNATURE_ALGORITHMS }; uint16_t extLength[9] = { 19, 1, 8, 2, 0, 0, 23, 5, 22 }; @@ -161,9 +136,7 @@ PTF_TEST_CASE(SSLClientHelloParsingTest) PTF_ASSERT_EQUAL(curExt->getLength(), extLength[i]); PTF_ASSERT_EQUAL(clientHelloMessage->getExtensionOfType(extTypes[i]), curExt, ptr); } -} // SSLClientHelloParsingTest - - +} // SSLClientHelloParsingTest PTF_TEST_CASE(SSLExtensionWithZeroSizeTest) { @@ -175,7 +148,8 @@ PTF_TEST_CASE(SSLExtensionWithZeroSizeTest) pcpp::SSLHandshakeLayer* handshakeLayer = clientHelloPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); - pcpp::SSLClientHelloMessage* clientHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(clientHelloMessage); PTF_ASSERT_EQUAL(clientHelloMessage->getExtensionCount(), 7); @@ -186,8 +160,7 @@ PTF_TEST_CASE(SSLExtensionWithZeroSizeTest) PTF_ASSERT_EQUAL(zeroSizeExt->getTotalLength(), 4); PTF_ASSERT_NULL(zeroSizeExt->getData()); -} // SSLExtensionWithZeroSizeTest - +} // SSLExtensionWithZeroSizeTest PTF_TEST_CASE(SSLAppDataParsingTest) { @@ -222,9 +195,7 @@ PTF_TEST_CASE(SSLAppDataParsingTest) PTF_ASSERT_EQUAL(appDataLayer->getEncryptedData()[40], 0xec, hex); PTF_ASSERT_NULL(appDataLayer->getNextLayer()); -} // SSLAppDataParsingTest - - +} // SSLAppDataParsingTest PTF_TEST_CASE(SSLAlertParsingTest) { @@ -255,9 +226,7 @@ PTF_TEST_CASE(SSLAlertParsingTest) PTF_ASSERT_EQUAL(encAlertLayer->getAlertDescription(), pcpp::SSL_ALERT_ENCRYPTED, enum); PTF_ASSERT_EQUAL(encAlertLayer->getRecordLayer()->length, be16toh(26)); PTF_ASSERT_EQUAL(encAlertLayer->getHeaderLen(), 31); -} // SSLAlertParsingTest - - +} // SSLAlertParsingTest /** * Testing: server-hello, change-cipher-spec, encrypted handshake message @@ -274,7 +243,8 @@ PTF_TEST_CASE(SSLMultipleRecordParsingTest) pcpp::SSLHandshakeLayer* handshakeLayer = multipleRecordsPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessagesCount(), 1); - pcpp::SSLServerHelloMessage* serverHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerHelloMessage* serverHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(serverHelloMessage); PTF_ASSERT_EQUAL(serverHelloMessage->getSessionIDLength(), 32); PTF_ASSERT_EQUAL(serverHelloMessage->getSessionID()[0], 0xbf, hex); @@ -285,7 +255,9 @@ PTF_TEST_CASE(SSLMultipleRecordParsingTest) PTF_ASSERT_EQUAL(serverHelloMessage->getExtensionCount(), 3); uint16_t extensionsLength[3] = { 1, 5, 2 }; uint16_t totalExtensionsLength[3] = { 5, 9, 6 }; - pcpp::SSLExtensionType extensionTypes[3] = { pcpp::SSL_EXT_RENEGOTIATION_INFO, pcpp::SSL_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION, pcpp::SSL_EXT_EC_POINT_FORMATS }; + pcpp::SSLExtensionType extensionTypes[3] = { pcpp::SSL_EXT_RENEGOTIATION_INFO, + pcpp::SSL_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION, + pcpp::SSL_EXT_EC_POINT_FORMATS }; uint8_t extensionDataFirstByte[3] = { 0, 0, 1 }; PTF_PRINT_VERBOSE("iterating over SSL extensions"); for (int i = 0; i < 3; i++) @@ -297,7 +269,8 @@ PTF_TEST_CASE(SSLMultipleRecordParsingTest) PTF_ASSERT_EQUAL(curExt->getType(), extensionTypes[i], enum); PTF_ASSERT_EQUAL(curExt->getData()[0], extensionDataFirstByte[i]); } - pcpp::TLSECPointFormatExtension* ecPointFormatExt = serverHelloMessage->getExtensionOfType(); + pcpp::TLSECPointFormatExtension* ecPointFormatExt = + serverHelloMessage->getExtensionOfType(); PTF_ASSERT_NOT_NULL(ecPointFormatExt); std::vector ecPointFormatList = ecPointFormatExt->getECPointFormatList(); PTF_ASSERT_EQUAL(ecPointFormatList.size(), 1); @@ -316,9 +289,7 @@ PTF_TEST_CASE(SSLMultipleRecordParsingTest) PTF_ASSERT_NOT_NULL(unknownMessage); PTF_ASSERT_EQUAL(unknownMessage->getHandshakeType(), pcpp::SSL_HANDSHAKE_UNKNOWN, enum); PTF_ASSERT_EQUAL(unknownMessage->getMessageLength(), 40); -} // SSLMultipleRecordParsingTest - - +} // SSLMultipleRecordParsingTest /** * Testing: client-key-exchange @@ -337,7 +308,8 @@ PTF_TEST_CASE(SSLMultipleRecordParsing2Test) PTF_ASSERT_NOT_NULL(handshakeLayer); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessagesCount(), 1); - pcpp::SSLClientKeyExchangeMessage* clientKeyExMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientKeyExchangeMessage* clientKeyExMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(clientKeyExMsg); PTF_ASSERT_EQUAL(clientKeyExMsg->getHandshakeType(), pcpp::SSL_CLIENT_KEY_EXCHANGE, enum); PTF_ASSERT_EQUAL(clientKeyExMsg->getMessageLength(), 70); @@ -345,9 +317,7 @@ PTF_TEST_CASE(SSLMultipleRecordParsing2Test) PTF_ASSERT_EQUAL(clientKeyExMsg->getClientKeyExchangeParams()[0], 0x41, hex); PTF_ASSERT_EQUAL(clientKeyExMsg->getClientKeyExchangeParams()[10], 0xf2, hex); PTF_ASSERT_EQUAL(clientKeyExMsg->getClientKeyExchangeParams()[65], 0xdc, hex); -} // SSLMultipleRecordParsing2Test - - +} // SSLMultipleRecordParsing2Test /** * Testing - certificate, certificate-request @@ -378,7 +348,7 @@ PTF_TEST_CASE(SSLMultipleRecordParsing3Test) PTF_ASSERT_NOT_NULL(cert); PTF_ASSERT_TRUE(cert->allDataExists()); PTF_ASSERT_EQUAL(cert->getDataLength(), 1509); - std::string certBuffer(cert->getData(), cert->getData()+cert->getDataLength()); + std::string certBuffer(cert->getData(), cert->getData() + cert->getDataLength()); std::size_t pos = certBuffer.find("LDAP Intermediate CA"); PTF_ASSERT_TRUE(pos != std::string::npos); pos = certBuffer.find("Internal Development CA"); @@ -387,18 +357,19 @@ PTF_TEST_CASE(SSLMultipleRecordParsing3Test) PTF_ASSERT_NOT_NULL(cert); PTF_ASSERT_TRUE(cert->allDataExists()); PTF_ASSERT_EQUAL(cert->getDataLength(), 1728); - certBuffer = std::string(cert->getData(), cert->getData()+cert->getDataLength()); + certBuffer = std::string(cert->getData(), cert->getData() + cert->getDataLength()); pos = certBuffer.find("Internal Development CA"); PTF_ASSERT_TRUE(pos != std::string::npos); cert = certMsg->getCertificate(2); PTF_ASSERT_NOT_NULL(cert); PTF_ASSERT_TRUE(cert->allDataExists()); PTF_ASSERT_EQUAL(cert->getDataLength(), 1713); - certBuffer = std::string(cert->getData(), cert->getData()+cert->getDataLength()); + certBuffer = std::string(cert->getData(), cert->getData() + cert->getDataLength()); pos = certBuffer.find("Internal Development CA"); PTF_ASSERT_TRUE(pos != std::string::npos); - pcpp::SSLCertificateRequestMessage* certReqMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLCertificateRequestMessage* certReqMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_TRUE(certReqMsg->isMessageComplete()); PTF_ASSERT_EQUAL(certReqMsg->getHandshakeType(), pcpp::SSL_CERTIFICATE_REQUEST, enum); PTF_ASSERT_EQUAL(certReqMsg->getCertificateTypes().size(), 2); @@ -409,9 +380,7 @@ PTF_TEST_CASE(SSLMultipleRecordParsing3Test) PTF_ASSERT_EQUAL(certReqMsg->getCertificateAuthorityData()[1], 0x6c, hex); PTF_ASSERT_EQUAL(certReqMsg->getCertificateAuthorityData()[14], 0x2, hex); PTF_ASSERT_EQUAL(certReqMsg->getCertificateAuthorityData()[47], 0x13, hex); -} // SSLMultipleRecordParsing3Test - - +} // SSLMultipleRecordParsing3Test /** * Testing: server-key-exchange, server-hello-done @@ -430,7 +399,8 @@ PTF_TEST_CASE(SSLMultipleRecordParsing4Test) PTF_ASSERT_NOT_NULL(handshakeLayer); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessagesCount(), 1); - pcpp::SSLServerKeyExchangeMessage* serverKeyExMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerKeyExchangeMessage* serverKeyExMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(serverKeyExMsg); PTF_ASSERT_EQUAL(serverKeyExMsg->getHandshakeType(), pcpp::SSL_SERVER_KEY_EXCHANGE, enum); PTF_ASSERT_EQUAL(serverKeyExMsg->getMessageLength(), 333); @@ -442,14 +412,13 @@ PTF_TEST_CASE(SSLMultipleRecordParsing4Test) handshakeLayer = multipleRecordsPacket.getNextLayerOfType(handshakeLayer); PTF_ASSERT_NOT_NULL(handshakeLayer); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessagesCount(), 1); - pcpp::SSLServerHelloDoneMessage* serverHelloDoneMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerHelloDoneMessage* serverHelloDoneMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(serverHelloDoneMsg); PTF_ASSERT_EQUAL(serverHelloDoneMsg->getHandshakeType(), pcpp::SSL_SERVER_DONE, enum); PTF_ASSERT_EQUAL(serverHelloDoneMsg->getMessageLength(), 4); PTF_ASSERT_EQUAL(serverHelloDoneMsg, handshakeLayer->getHandshakeMessageAt(0), ptr); -} // SSLMultipleRecordParsing4Test - - +} // SSLMultipleRecordParsing4Test /** * Testing: change-cipher-spec, encrypted-handshake-message, application-data @@ -485,9 +454,7 @@ PTF_TEST_CASE(SSLMultipleRecordParsing5Test) PTF_ASSERT_EQUAL(appDataLayer->getEncryptedData()[16], 0x07, hex); PTF_ASSERT_EQUAL(appDataLayer->getEncryptedData()[61], 0x92, hex); PTF_ASSERT_NULL(appDataLayer->getNextLayer()); -} // SSLMultipleRecordParsing5Test - - +} // SSLMultipleRecordParsing5Test PTF_TEST_CASE(SSLPartialCertificateParseTest) { @@ -527,9 +494,7 @@ PTF_TEST_CASE(SSLPartialCertificateParseTest) cert = certMsg->getCertificate(0); PTF_ASSERT_FALSE(cert->allDataExists()); PTF_ASSERT_EQUAL(cert->getDataLength(), 1268); -} // SSLPartialCertificateParseTest - - +} // SSLPartialCertificateParseTest PTF_TEST_CASE(SSLNewSessionTicketParseTest) { @@ -545,7 +510,8 @@ PTF_TEST_CASE(SSLNewSessionTicketParseTest) PTF_ASSERT_NOT_NULL(handshakeLayer); PTF_ASSERT_EQUAL(handshakeLayer->getHandshakeMessagesCount(), 1); - pcpp::SSLNewSessionTicketMessage* newSessionTicketMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLNewSessionTicketMessage* newSessionTicketMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(newSessionTicketMsg); PTF_ASSERT_TRUE(newSessionTicketMsg->isMessageComplete()); PTF_ASSERT_EQUAL(newSessionTicketMsg->getHandshakeType(), pcpp::SSL_NEW_SESSION_TICKET, enum); @@ -553,8 +519,7 @@ PTF_TEST_CASE(SSLNewSessionTicketParseTest) PTF_ASSERT_EQUAL(newSessionTicketMsg->getSessionTicketData()[0], 0, hex); PTF_ASSERT_EQUAL(newSessionTicketMsg->getSessionTicketData()[16], 0xf9, hex); PTF_ASSERT_EQUAL(newSessionTicketMsg->getSessionTicketData()[213], 0x75, hex); -} // SSLNewSessionTicketParseTest - +} // SSLNewSessionTicketParseTest PTF_TEST_CASE(SSLMalformedPacketParsing) { @@ -567,11 +532,11 @@ PTF_TEST_CASE(SSLMalformedPacketParsing) pcpp::SSLHandshakeLayer* handshakeLayer = badSSLPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); - pcpp::SSLClientHelloMessage* clientHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(clientHelloMessage); PTF_ASSERT_EQUAL(clientHelloMessage->getExtensionCount(), 1); -} // SSLMalformedPacketParsing - +} // SSLMalformedPacketParsing PTF_TEST_CASE(TLS1_3ParsingTest) { @@ -585,29 +550,19 @@ PTF_TEST_CASE(TLS1_3ParsingTest) pcpp::Packet tls13ClientHello2(&rawPacket2); uint16_t cipherSuiteIDs[3] = { 0x1302, 0x1303, 0x1301 }; - std::string cipherSuiteNames[3] = - { - "TLS_AES_256_GCM_SHA384", - "TLS_CHACHA20_POLY1305_SHA256", - "TLS_AES_128_GCM_SHA256" - }; - pcpp::SSLSymetricEncryptionAlgorithm cipherSuiteSym[3] = - { - pcpp::SSL_SYM_AES_256_GCM, - pcpp::SSL_SYM_CHACHA20_POLY1305, - pcpp::SSL_SYM_AES_128_GCM - }; + std::string cipherSuiteNames[3] = { "TLS_AES_256_GCM_SHA384", "TLS_CHACHA20_POLY1305_SHA256", + "TLS_AES_128_GCM_SHA256" }; + pcpp::SSLSymetricEncryptionAlgorithm cipherSuiteSym[3] = { pcpp::SSL_SYM_AES_256_GCM, + pcpp::SSL_SYM_CHACHA20_POLY1305, + pcpp::SSL_SYM_AES_128_GCM }; - pcpp::SSLHashingAlgorithm cipherSuiteHash[3] = - { - pcpp::SSL_HASH_SHA384, - pcpp::SSL_HASH_SHA256, - pcpp::SSL_HASH_SHA256 - }; + pcpp::SSLHashingAlgorithm cipherSuiteHash[3] = { pcpp::SSL_HASH_SHA384, pcpp::SSL_HASH_SHA256, + pcpp::SSL_HASH_SHA256 }; pcpp::SSLHandshakeLayer* handshakeLayer = tls13ClientHello1.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); - pcpp::SSLClientHelloMessage* clientHelloMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(clientHelloMsg); PTF_ASSERT_EQUAL(clientHelloMsg->getCipherSuiteCount(), 4); for (int i = 0; i < 3; i++) @@ -620,7 +575,8 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(clientHelloMsg->getCipherSuite(i)->getAuthAlg(), pcpp::SSL_AUTH_NULL, enum); } - pcpp::SSLSupportedVersionsExtension* supportedVersionsExt = clientHelloMsg->getExtensionOfType(); + pcpp::SSLSupportedVersionsExtension* supportedVersionsExt = + clientHelloMsg->getExtensionOfType(); PTF_ASSERT_NOT_NULL(supportedVersionsExt); std::vector versionVec = supportedVersionsExt->getSupportedVersions(); PTF_ASSERT_EQUAL(versionVec.size(), 3); @@ -629,7 +585,8 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(versionVec[2].asEnum(), pcpp::SSLVersion::TLS1_3_D26, enum); PTF_ASSERT_EQUAL(versionVec[0].asEnum(true), pcpp::SSLVersion::TLS1_3, enum); - pcpp::TLSECPointFormatExtension* ecPointFormatExt = clientHelloMsg->getExtensionOfType(); + pcpp::TLSECPointFormatExtension* ecPointFormatExt = + clientHelloMsg->getExtensionOfType(); PTF_ASSERT_NOT_NULL(ecPointFormatExt); std::vector ecPointFormatList = ecPointFormatExt->getECPointFormatList(); PTF_ASSERT_EQUAL(ecPointFormatList.size(), 3); @@ -637,7 +594,8 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(ecPointFormatList.at(1), 1); PTF_ASSERT_EQUAL(ecPointFormatList.at(2), 2); - pcpp::TLSSupportedGroupsExtension* supportedGroupsExt = clientHelloMsg->getExtensionOfType(); + pcpp::TLSSupportedGroupsExtension* supportedGroupsExt = + clientHelloMsg->getExtensionOfType(); PTF_ASSERT_NOT_NULL(supportedGroupsExt); std::vector supportedGroups = supportedGroupsExt->getSupportedGroups(); PTF_ASSERT_EQUAL(supportedGroups.size(), 5); @@ -647,7 +605,6 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(supportedGroups.at(3), 25); PTF_ASSERT_EQUAL(supportedGroups.at(4), 24); - handshakeLayer = tls13ClientHello2.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); clientHelloMsg = handshakeLayer->getHandshakeMessageOfType(); @@ -665,7 +622,6 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(versionVec[0].asEnum(), pcpp::SSLVersion::TLS1_3, enum); PTF_ASSERT_EQUAL(versionVec[1].asEnum(), pcpp::SSLVersion::TLS1_2, enum); - READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/tls1_3_server_hello1.dat"); READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/tls1_3_server_hello2.dat"); @@ -674,7 +630,8 @@ PTF_TEST_CASE(TLS1_3ParsingTest) handshakeLayer = tls13ServerHello1.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); - pcpp::SSLServerHelloMessage* serverHelloMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerHelloMessage* serverHelloMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(serverHelloMsg); PTF_ASSERT_EQUAL(serverHelloMsg->getCipherSuite()->asString(), cipherSuiteNames[0]); @@ -686,7 +643,6 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(versionVec[0].asEnum(), pcpp::SSLVersion::TLS1_3_D28, enum); PTF_ASSERT_EQUAL(serverHelloMsg->getHandshakeVersion().asEnum(true), pcpp::SSLVersion::TLS1_3, enum); - handshakeLayer = tls13ServerHello2.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); serverHelloMsg = handshakeLayer->getHandshakeMessageOfType(); @@ -700,8 +656,7 @@ PTF_TEST_CASE(TLS1_3ParsingTest) PTF_ASSERT_EQUAL(versionVec.size(), 1); PTF_ASSERT_EQUAL(versionVec[0].asEnum(), pcpp::SSLVersion::TLS1_3, enum); PTF_ASSERT_EQUAL(serverHelloMsg->getHandshakeVersion().asEnum(true), pcpp::SSLVersion::TLS1_3, enum); -} // TLS1_3ParsingTest - +} // TLS1_3ParsingTest PTF_TEST_CASE(TLSCipherSuiteTest) { @@ -724,8 +679,7 @@ PTF_TEST_CASE(TLSCipherSuiteTest) PTF_ASSERT_EQUAL(cipherSuiteByID->getID(), cipherSuiteID); PTF_ASSERT_EQUAL(cipherSuiteByName, cipherSuiteByID, ptr); } -} // TLSCipherSuiteTest - +} // TLSCipherSuiteTest PTF_TEST_CASE(ClientHelloTLSFingerprintTest) { @@ -737,14 +691,15 @@ PTF_TEST_CASE(ClientHelloTLSFingerprintTest) pcpp::SSLHandshakeLayer* handshakeLayer = tls13ClientHello1.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); - pcpp::SSLClientHelloMessage* clientHelloMsg = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMsg = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(clientHelloMsg); pcpp::SSLClientHelloMessage::ClientHelloTLSFingerprint tlsFingerprint = clientHelloMsg->generateTLSFingerprint(); - PTF_ASSERT_EQUAL(tlsFingerprint.toString(), "771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2"); + PTF_ASSERT_EQUAL(tlsFingerprint.toString(), + "771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2"); PTF_ASSERT_EQUAL(tlsFingerprint.toMD5(), "a66e498c488aa0523759691248cdfb01"); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/tls_grease.dat"); pcpp::Packet tlsGreaseClientHello(&rawPacket2); @@ -754,10 +709,11 @@ PTF_TEST_CASE(ClientHelloTLSFingerprintTest) PTF_ASSERT_NOT_NULL(clientHelloMsg); tlsFingerprint = clientHelloMsg->generateTLSFingerprint(); - PTF_ASSERT_EQUAL(tlsFingerprint.toString(), "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-13-18-51-45-43-27-21,29-23-24,0"); + PTF_ASSERT_EQUAL(tlsFingerprint.toString(), + "771,4865-4866-4867-49195-49199-49196-49200-52393-52392-49171-49172-156-157-47-53,0-23-65281-10-" + "11-35-16-5-13-18-51-45-43-27-21,29-23-24,0"); PTF_ASSERT_EQUAL(tlsFingerprint.toMD5(), "b32309a26951912be7dba376398abc3b"); -} // ClientHelloTLSFingerprintTest - +} // ClientHelloTLSFingerprintTest PTF_TEST_CASE(ServerHelloTLSFingerprintTest) { @@ -770,14 +726,15 @@ PTF_TEST_CASE(ServerHelloTLSFingerprintTest) pcpp::SSLHandshakeLayer* handshakeLayer = multipleRecordsPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(handshakeLayer); - pcpp::SSLServerHelloMessage* serverHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerHelloMessage* serverHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); PTF_ASSERT_NOT_NULL(serverHelloMessage); - pcpp::SSLServerHelloMessage::ServerHelloTLSFingerprint tlsFingerprint = serverHelloMessage->generateTLSFingerprint(); + pcpp::SSLServerHelloMessage::ServerHelloTLSFingerprint tlsFingerprint = + serverHelloMessage->generateTLSFingerprint(); PTF_ASSERT_EQUAL(tlsFingerprint.toString(), "771,49195,65281-16-11"); PTF_ASSERT_EQUAL(tlsFingerprint.toMD5(), "554786d4c84f8a7953b7e453c6371067"); - READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/tls_server_hello.dat"); pcpp::Packet serverHelloPacket(&rawPacket2); @@ -790,4 +747,4 @@ PTF_TEST_CASE(ServerHelloTLSFingerprintTest) tlsFingerprint = serverHelloMessage->generateTLSFingerprint(); PTF_ASSERT_EQUAL(tlsFingerprint.toString(), "771,49195,23-65281-11-35-16"); PTF_ASSERT_EQUAL(tlsFingerprint.toMD5(), "eca9b8f0f3eae50309eaf901cb822d9b"); -} // ServerHelloTLSFingerprintTest +} // ServerHelloTLSFingerprintTest diff --git a/Tests/Packet++Test/Tests/SipSdpTests.cpp b/Tests/Packet++Test/Tests/SipSdpTests.cpp index 27ba32a4b1..06256efd6e 100644 --- a/Tests/Packet++Test/Tests/SipSdpTests.cpp +++ b/Tests/Packet++Test/Tests/SipSdpTests.cpp @@ -10,42 +10,44 @@ #include "PayloadLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(SipRequestParseMethodTest) { - PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(nullptr, 0), pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(std::string("ACK").c_str(), 3), pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(nullptr, 0), + pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(std::string("ACK").c_str(), 3), + pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(std::string("CANCEL").c_str(), 6), pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(std::string("CANCEL").c_str(), 6), + pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); std::vector> possibleMethods = { - {"INVITE", pcpp::SipRequestLayer::SipMethod::SipINVITE }, - {"ACK", pcpp::SipRequestLayer::SipMethod::SipACK }, - {"BYE", pcpp::SipRequestLayer::SipMethod::SipBYE }, - {"CANCEL", pcpp::SipRequestLayer::SipMethod::SipCANCEL }, - {"REGISTER", pcpp::SipRequestLayer::SipMethod::SipREGISTER }, - {"PRACK", pcpp::SipRequestLayer::SipMethod::SipPRACK }, - {"OPTIONS", pcpp::SipRequestLayer::SipMethod::SipOPTIONS }, - {"SUBSCRIBE", pcpp::SipRequestLayer::SipMethod::SipSUBSCRIBE }, - {"NOTIFY", pcpp::SipRequestLayer::SipMethod::SipNOTIFY }, - {"PUBLISH", pcpp::SipRequestLayer::SipMethod::SipPUBLISH }, - {"INFO", pcpp::SipRequestLayer::SipMethod::SipINFO }, - {"REFER", pcpp::SipRequestLayer::SipMethod::SipREFER }, - {"MESSAGE", pcpp::SipRequestLayer::SipMethod::SipMESSAGE }, - {"UPDATE", pcpp::SipRequestLayer::SipMethod::SipUPDATE }, - {"UPDATE", pcpp::SipRequestLayer::SipMethod::SipUPDATE }, + { "INVITE", pcpp::SipRequestLayer::SipMethod::SipINVITE }, + { "ACK", pcpp::SipRequestLayer::SipMethod::SipACK }, + { "BYE", pcpp::SipRequestLayer::SipMethod::SipBYE }, + { "CANCEL", pcpp::SipRequestLayer::SipMethod::SipCANCEL }, + { "REGISTER", pcpp::SipRequestLayer::SipMethod::SipREGISTER }, + { "PRACK", pcpp::SipRequestLayer::SipMethod::SipPRACK }, + { "OPTIONS", pcpp::SipRequestLayer::SipMethod::SipOPTIONS }, + { "SUBSCRIBE", pcpp::SipRequestLayer::SipMethod::SipSUBSCRIBE }, + { "NOTIFY", pcpp::SipRequestLayer::SipMethod::SipNOTIFY }, + { "PUBLISH", pcpp::SipRequestLayer::SipMethod::SipPUBLISH }, + { "INFO", pcpp::SipRequestLayer::SipMethod::SipINFO }, + { "REFER", pcpp::SipRequestLayer::SipMethod::SipREFER }, + { "MESSAGE", pcpp::SipRequestLayer::SipMethod::SipMESSAGE }, + { "UPDATE", pcpp::SipRequestLayer::SipMethod::SipUPDATE }, + { "UPDATE", pcpp::SipRequestLayer::SipMethod::SipUPDATE }, }; - for (const std::pair &method : possibleMethods ) + for (const std::pair& method : possibleMethods) { std::string firstLine = method.first + " "; - PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(firstLine.c_str(), firstLine.length()), method.second, enum); + PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(firstLine.c_str(), firstLine.length()), method.second, + enum); } - PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(std::string("UNKNOWN ").c_str(), 8), pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); -} // SipRequestParseMethodTest - - + PTF_ASSERT_EQUAL(pcpp::SipRequestFirstLine::parseMethod(std::string("UNKNOWN ").c_str(), 8), + pcpp::SipRequestLayer::SipMethod::SipMethodUnknown, enum); +} // SipRequestParseMethodTest PTF_TEST_CASE(SipRequestLayerParsingTest) { @@ -82,14 +84,17 @@ PTF_TEST_CASE(SipRequestLayerParsingTest) PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getSize(), 47); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_FROM_FIELD)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->getFieldValue(), ";tag=GR52RWG346-34"); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->getFieldValue(), + ";tag=GR52RWG346-34"); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_CONTACT_FIELD)); PTF_ASSERT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_CONTACT_FIELD, 1)); PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_CONTACT_FIELD)->getFieldValue(), ""); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD)->getFieldValue(), "SIP/2.0/UDP 200.57.7.195;branch=z9hG4bKff9b46fb055c0521cc24024da96cd290"); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD)->getFieldValue(), + "SIP/2.0/UDP 200.57.7.195;branch=z9hG4bKff9b46fb055c0521cc24024da96cd290"); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)->getFieldValue(), "SIP/2.0/UDP 200.57.7.195:55061;branch=z9hG4bK291d90e31a47b225bd0ddff4353e9cc0"); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)->getFieldValue(), + "SIP/2.0/UDP 200.57.7.195:55061;branch=z9hG4bK291d90e31a47b225bd0ddff4353e9cc0"); PTF_ASSERT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 2)); PTF_ASSERT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 100)); PTF_ASSERT_NULL(sipReqLayer->getFieldByName("BlaBla")); @@ -101,7 +106,6 @@ PTF_TEST_CASE(SipRequestLayerParsingTest) PTF_ASSERT_EQUAL(sipReqLayer->getLayerPayloadSize(), 229); PTF_ASSERT_EQUAL(sipReqLayer->getContentLength(), 229); - sipReqLayer = sipReqPacket2.getLayerOfType(); PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getMethod(), pcpp::SipRequestLayer::SipCANCEL, enum); @@ -110,7 +114,8 @@ PTF_TEST_CASE(SipRequestLayerParsingTest) PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_MAX_FORWARDS_FIELD)); PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_MAX_FORWARDS_FIELD)->getFieldValue(), "70"); - PTF_ASSERT_TRUE(sipReqLayer->getNextField(sipReqLayer->getFieldByName(PCPP_SIP_MAX_FORWARDS_FIELD))->isEndOfHeader()); + PTF_ASSERT_TRUE( + sipReqLayer->getNextField(sipReqLayer->getFieldByName(PCPP_SIP_MAX_FORWARDS_FIELD))->isEndOfHeader()); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_CSEQ_FIELD)); PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_CSEQ_FIELD)->getFieldValue(), "2 CANCEL"); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_TO_FIELD)); @@ -118,7 +123,6 @@ PTF_TEST_CASE(SipRequestLayerParsingTest) PTF_ASSERT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_TO_FIELD, 2)); PTF_ASSERT_TRUE(sipReqLayer->isHeaderComplete()); - sipReqLayer = sipReqPacket3.getLayerOfType(); PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getMethod(), pcpp::SipRequestLayer::SipACK, enum); @@ -127,16 +131,17 @@ PTF_TEST_CASE(SipRequestLayerParsingTest) PTF_ASSERT_FALSE(sipReqLayer->isHeaderComplete()); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)->getFieldValue(), "SIP/2.0/UDP 213.192.59.78:5080;rport=5080;branch=z9hG4bKjBiNGaOX"); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)->getFieldValue(), + "SIP/2.0/UDP 213.192.59.78:5080;rport=5080;branch=z9hG4bKjBiNGaOX"); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_CALL_ID_FIELD)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_CALL_ID_FIELD)->getFieldValue(), "2091060b-146f-e011-809a-0019cb53db77@admind-desktop"); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_CALL_ID_FIELD)->getFieldValue(), + "2091060b-146f-e011-809a-0019cb53db77@admind-desktop"); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName("P-hint")); PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName("P-hint")->getFieldValue(), "rr-enforced"); PTF_ASSERT_NULL(sipReqLayer->getNextField(sipReqLayer->getFieldByName("P-hint"))); PTF_ASSERT_EQUAL(sipReqLayer->getContentLength(), 0); PTF_ASSERT_EQUAL(sipReqLayer->getFieldCount(), 9); - sipReqLayer = sipReqPacket4.getLayerOfType(); PTF_ASSERT_EQUAL(sipReqLayer->getFirstLine()->getMethod(), pcpp::SipRequestLayer::SipBYE, enum); @@ -145,16 +150,18 @@ PTF_TEST_CASE(SipRequestLayerParsingTest) PTF_ASSERT_FALSE(sipReqLayer->isHeaderComplete()); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_USER_AGENT_FIELD)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_USER_AGENT_FIELD)->getFieldValue(), "FreeSWITCH-mod_sofia/1.6.12-20-b91a0a6~64bit"); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_USER_AGENT_FIELD)->getFieldValue(), + "FreeSWITCH-mod_sofia/1.6.12-20-b91a0a6~64bit"); PTF_ASSERT_NOT_NULL(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD)); - PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD)->getFieldValue(), "Q.850;cause=16;text=\"NORMAL_CLEARING\""); - PTF_ASSERT_EQUAL(sipReqLayer->getNextField(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD))->getFieldName(), "Content-Lengt"); - PTF_ASSERT_EQUAL(sipReqLayer->getNextField(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD))->getFieldValue(), ""); + PTF_ASSERT_EQUAL(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD)->getFieldValue(), + "Q.850;cause=16;text=\"NORMAL_CLEARING\""); + PTF_ASSERT_EQUAL(sipReqLayer->getNextField(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD))->getFieldName(), + "Content-Lengt"); + PTF_ASSERT_EQUAL(sipReqLayer->getNextField(sipReqLayer->getFieldByName(PCPP_SIP_REASON_FIELD))->getFieldValue(), + ""); PTF_ASSERT_EQUAL(sipReqLayer->getFieldCount(), 11); -} // SipRequestLayerParsingTest - - +} // SipRequestLayerParsingTest PTF_TEST_CASE(SipRequestLayerCreationTest) { @@ -175,8 +182,10 @@ PTF_TEST_CASE(SipRequestLayerCreationTest) PTF_ASSERT_NOT_NULL(sipReqLayer.addField(PCPP_SIP_CALL_ID_FIELD, "12013223@200.57.7.195")); PTF_ASSERT_NOT_NULL(sipReqLayer.addField(PCPP_SIP_CONTENT_TYPE_FIELD, "application/sdp")); PTF_ASSERT_TRUE(sipReqLayer.addEndOfHeader()); - PTF_ASSERT_NOT_NULL(sipReqLayer.insertField(nullptr, PCPP_SIP_VIA_FIELD, "SIP/2.0/UDP 200.57.7.195:55061;branch=z9hG4bK291d90e31a47b225bd0ddff4353e9cc0")); - PTF_ASSERT_NOT_NULL(sipReqLayer.insertField(nullptr, PCPP_SIP_VIA_FIELD, "SIP/2.0/UDP 200.57.7.195;branch=z9hG4bKff9b46fb055c0521cc24024da96cd290")); + PTF_ASSERT_NOT_NULL(sipReqLayer.insertField( + nullptr, PCPP_SIP_VIA_FIELD, "SIP/2.0/UDP 200.57.7.195:55061;branch=z9hG4bK291d90e31a47b225bd0ddff4353e9cc0")); + PTF_ASSERT_NOT_NULL(sipReqLayer.insertField( + nullptr, PCPP_SIP_VIA_FIELD, "SIP/2.0/UDP 200.57.7.195;branch=z9hG4bKff9b46fb055c0521cc24024da96cd290")); pcpp::HeaderField* callIDField = sipReqLayer.getFieldByName(PCPP_SIP_CALL_ID_FIELD); PTF_ASSERT_NOT_NULL(callIDField); pcpp::HeaderField* newField = sipReqLayer.insertField(callIDField, PCPP_SIP_CSEQ_FIELD, "1 INVITE"); @@ -185,15 +194,16 @@ PTF_TEST_CASE(SipRequestLayerCreationTest) PTF_ASSERT_NOT_NULL(newField); pcpp::HeaderField* secondViaField = sipReqLayer.getFieldByName(PCPP_SIP_VIA_FIELD, 0); PTF_ASSERT_NOT_NULL(secondViaField); - newField = sipReqLayer.insertField(secondViaField, PCPP_SIP_FROM_FIELD, ";tag=GR52RWG346-34"); + newField = sipReqLayer.insertField(secondViaField, PCPP_SIP_FROM_FIELD, + ";tag=GR52RWG346-34"); PTF_ASSERT_NOT_NULL(newField); - newField = sipReqLayer.insertField(newField, PCPP_SIP_TO_FIELD, "\"francisco@bestel.com\" "); + newField = sipReqLayer.insertField(newField, PCPP_SIP_TO_FIELD, + "\"francisco@bestel.com\" "); PTF_ASSERT_NOT_NULL(newField); pcpp::HeaderField* contentLengthField = sipReqLayer.setContentLength(229, PCPP_SIP_CONTENT_TYPE_FIELD); PTF_ASSERT_NOT_NULL(contentLengthField); contentLengthField->setFieldValue(" 229"); - pcpp::Packet newSipPacket; PTF_ASSERT_TRUE(newSipPacket.addLayer(ðLayer)); PTF_ASSERT_TRUE(newSipPacket.addLayer(&ip4Layer)); @@ -201,16 +211,16 @@ PTF_TEST_CASE(SipRequestLayerCreationTest) PTF_ASSERT_TRUE(newSipPacket.addLayer(&sipReqLayer)); pcpp::SipRequestLayer* samplePacketSipLayer = sipReqSamplePacket.getLayerOfType(); - auto payloadLayer = new pcpp::PayloadLayer(samplePacketSipLayer->getLayerPayload(), samplePacketSipLayer->getLayerPayloadSize()); + auto payloadLayer = + new pcpp::PayloadLayer(samplePacketSipLayer->getLayerPayload(), samplePacketSipLayer->getLayerPayloadSize()); PTF_ASSERT_TRUE(newSipPacket.addLayer(payloadLayer, true)); newSipPacket.computeCalculateFields(); PTF_ASSERT_EQUAL(newSipPacket.getRawPacket()->getRawDataLen(), bufferLength1); - PTF_ASSERT_BUF_COMPARE(newSipPacket.getRawPacket()->getRawData(), buffer1, newSipPacket.getRawPacket()->getRawDataLen()); -} // SipRequestLayerCreationTest - - + PTF_ASSERT_BUF_COMPARE(newSipPacket.getRawPacket()->getRawData(), buffer1, + newSipPacket.getRawPacket()->getRawDataLen()); +} // SipRequestLayerCreationTest PTF_TEST_CASE(SipRequestLayerEditTest) { @@ -238,7 +248,9 @@ PTF_TEST_CASE(SipRequestLayerEditTest) PTF_ASSERT_FALSE(sipReqLayer->getFirstLine()->setUri("")); pcpp::Logger::getInstance().enableLogs(); - PTF_ASSERT_TRUE(sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1)->setFieldValue("SIP/2.0/UDP 178.45.73.241:5060;branch=z9hG4bKb26f2c0b-146f-e011-809a-0019cb53db77;rport")); + PTF_ASSERT_TRUE( + sipReqLayer->getFieldByName(PCPP_SIP_VIA_FIELD, 1) + ->setFieldValue("SIP/2.0/UDP 178.45.73.241:5060;branch=z9hG4bKb26f2c0b-146f-e011-809a-0019cb53db77;rport")); PTF_ASSERT_TRUE(sipReqLayer->getFieldByName(PCPP_SIP_MAX_FORWARDS_FIELD)->setFieldValue("70")); PTF_ASSERT_TRUE(sipReqLayer->removeField(PCPP_SIP_VIA_FIELD, 0)); PTF_ASSERT_TRUE(sipReqLayer->removeField(PCPP_SIP_RECORD_ROUTE_FIELD)); @@ -247,9 +259,12 @@ PTF_TEST_CASE(SipRequestLayerEditTest) PTF_ASSERT_NOT_NULL(sipReqLayer->setContentLength(0, PCPP_SIP_TO_FIELD)); PTF_ASSERT_TRUE(sipReqLayer->removeField(PCPP_SIP_CALL_ID_FIELD)); PTF_ASSERT_TRUE(sipReqLayer->removeField(PCPP_SIP_CSEQ_FIELD)); - PTF_ASSERT_NOT_NULL(sipReqLayer->insertField(PCPP_SIP_FROM_FIELD, PCPP_SIP_CALL_ID_FIELD, "2091060b-146f-e011-809a-0019cb53db77@admind-desktop")); + PTF_ASSERT_NOT_NULL(sipReqLayer->insertField(PCPP_SIP_FROM_FIELD, PCPP_SIP_CALL_ID_FIELD, + "2091060b-146f-e011-809a-0019cb53db77@admind-desktop")); PTF_ASSERT_NOT_NULL(sipReqLayer->insertField("", PCPP_SIP_CSEQ_FIELD, "2 CANCEL")); - PTF_ASSERT_TRUE(sipReqLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->setFieldValue("\"sam netmon \" ;tag=bc86060b-146f-e011-809a-0019cb53db77")); + PTF_ASSERT_TRUE( + sipReqLayer->getFieldByName(PCPP_SIP_FROM_FIELD) + ->setFieldValue("\"sam netmon \" ;tag=bc86060b-146f-e011-809a-0019cb53db77")); PTF_ASSERT_TRUE(sipReqLayer->getFieldByName(PCPP_SIP_TO_FIELD)->setFieldValue("")); editedPacket.computeCalculateFields(); @@ -264,106 +279,107 @@ PTF_TEST_CASE(SipRequestLayerEditTest) PTF_ASSERT_EQUAL(secondSipReqLayer->getFirstLine()->getVersion(), sipReqLayer->getFirstLine()->getVersion()); PTF_ASSERT_EQUAL(secondSipReqLayer->getFieldCount(), sipReqLayer->getFieldCount()); PTF_ASSERT_BUF_COMPARE(secondSipReqLayer->getData(), sipReqLayer->getData(), secondSipReqLayer->getHeaderLen()); -} // SipRequestLayerEditTest - - +} // SipRequestLayerEditTest PTF_TEST_CASE(SipResponseParseStatusCodeTest) { - PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(nullptr, 0), pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(std::string("abc").c_str(), 3), pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); - PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(std::string("SIP/x.y200 ").c_str(), 12), pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(nullptr, 0), + pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(std::string("abc").c_str(), 3), + pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); + PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(std::string("SIP/x.y200 ").c_str(), 12), + pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); std::vector> possibleStatusCodes = { - {"100", pcpp::SipResponseLayer::SipResponseStatusCode::Sip100Trying }, - {"180", pcpp::SipResponseLayer::SipResponseStatusCode::Sip180Ringing }, - {"181", pcpp::SipResponseLayer::SipResponseStatusCode::Sip181CallisBeingForwarded }, - {"182", pcpp::SipResponseLayer::SipResponseStatusCode::Sip182Queued }, - {"183", pcpp::SipResponseLayer::SipResponseStatusCode::Sip183SessioninProgress }, - {"199", pcpp::SipResponseLayer::SipResponseStatusCode::Sip199EarlyDialogTerminated }, - {"200", pcpp::SipResponseLayer::SipResponseStatusCode::Sip200OK }, - {"202", pcpp::SipResponseLayer::SipResponseStatusCode::Sip202Accepted }, - {"204", pcpp::SipResponseLayer::SipResponseStatusCode::Sip204NoNotification }, - {"300", pcpp::SipResponseLayer::SipResponseStatusCode::Sip300MultipleChoices }, - {"301", pcpp::SipResponseLayer::SipResponseStatusCode::Sip301MovedPermanently }, - {"302", pcpp::SipResponseLayer::SipResponseStatusCode::Sip302MovedTemporarily }, - {"305", pcpp::SipResponseLayer::SipResponseStatusCode::Sip305UseProxy }, - {"380", pcpp::SipResponseLayer::SipResponseStatusCode::Sip380AlternativeService }, - {"400", pcpp::SipResponseLayer::SipResponseStatusCode::Sip400BadRequest }, - {"401", pcpp::SipResponseLayer::SipResponseStatusCode::Sip401Unauthorized }, - {"402", pcpp::SipResponseLayer::SipResponseStatusCode::Sip402PaymentRequired }, - {"403", pcpp::SipResponseLayer::SipResponseStatusCode::Sip403Forbidden }, - {"404", pcpp::SipResponseLayer::SipResponseStatusCode::Sip404NotFound }, - {"405", pcpp::SipResponseLayer::SipResponseStatusCode::Sip405MethodNotAllowed }, - {"406", pcpp::SipResponseLayer::SipResponseStatusCode::Sip406NotAcceptable }, - {"407", pcpp::SipResponseLayer::SipResponseStatusCode::Sip407ProxyAuthenticationRequired }, - {"408", pcpp::SipResponseLayer::SipResponseStatusCode::Sip408RequestTimeout }, - {"409", pcpp::SipResponseLayer::SipResponseStatusCode::Sip409Conflict }, - {"410", pcpp::SipResponseLayer::SipResponseStatusCode::Sip410Gone }, - {"411", pcpp::SipResponseLayer::SipResponseStatusCode::Sip411LengthRequired }, - {"412", pcpp::SipResponseLayer::SipResponseStatusCode::Sip412ConditionalRequestFailed }, - {"413", pcpp::SipResponseLayer::SipResponseStatusCode::Sip413RequestEntityTooLarge }, - {"414", pcpp::SipResponseLayer::SipResponseStatusCode::Sip414RequestURITooLong }, - {"415", pcpp::SipResponseLayer::SipResponseStatusCode::Sip415UnsupportedMediaType }, - {"416", pcpp::SipResponseLayer::SipResponseStatusCode::Sip416UnsupportedURIScheme }, - {"417", pcpp::SipResponseLayer::SipResponseStatusCode::Sip417UnknownResourcePriority }, - {"420", pcpp::SipResponseLayer::SipResponseStatusCode::Sip420BadExtension }, - {"421", pcpp::SipResponseLayer::SipResponseStatusCode::Sip421ExtensionRequired }, - {"422", pcpp::SipResponseLayer::SipResponseStatusCode::Sip422SessionIntervalTooSmall }, - {"423", pcpp::SipResponseLayer::SipResponseStatusCode::Sip423IntervalTooBrief }, - {"424", pcpp::SipResponseLayer::SipResponseStatusCode::Sip424BadLocationInformation }, - {"425", pcpp::SipResponseLayer::SipResponseStatusCode::Sip425BadAlertMessage }, - {"428", pcpp::SipResponseLayer::SipResponseStatusCode::Sip428UseIdentityHeader }, - {"429", pcpp::SipResponseLayer::SipResponseStatusCode::Sip429ProvideReferrerIdentity }, - {"430", pcpp::SipResponseLayer::SipResponseStatusCode::Sip430FlowFailed }, - {"433", pcpp::SipResponseLayer::SipResponseStatusCode::Sip433AnonymityDisallowed }, - {"436", pcpp::SipResponseLayer::SipResponseStatusCode::Sip436BadIdentityInfo }, - {"437", pcpp::SipResponseLayer::SipResponseStatusCode::Sip437UnsupportedCertificate }, - {"438", pcpp::SipResponseLayer::SipResponseStatusCode::Sip438InvalidIdentityHeader }, - {"439", pcpp::SipResponseLayer::SipResponseStatusCode::Sip439FirstHopLacksOutboundSupport }, - {"440", pcpp::SipResponseLayer::SipResponseStatusCode::Sip440MaxBreadthExceeded }, - {"469", pcpp::SipResponseLayer::SipResponseStatusCode::Sip469BadInfoPackage }, - {"470", pcpp::SipResponseLayer::SipResponseStatusCode::Sip470ConsentNeeded }, - {"480", pcpp::SipResponseLayer::SipResponseStatusCode::Sip480TemporarilyUnavailable }, - {"481", pcpp::SipResponseLayer::SipResponseStatusCode::Sip481Call_TransactionDoesNotExist }, - {"482", pcpp::SipResponseLayer::SipResponseStatusCode::Sip482LoopDetected }, - {"483", pcpp::SipResponseLayer::SipResponseStatusCode::Sip483TooManyHops }, - {"484", pcpp::SipResponseLayer::SipResponseStatusCode::Sip484AddressIncomplete }, - {"485", pcpp::SipResponseLayer::SipResponseStatusCode::Sip485Ambiguous }, - {"486", pcpp::SipResponseLayer::SipResponseStatusCode::Sip486BusyHere }, - {"487", pcpp::SipResponseLayer::SipResponseStatusCode::Sip487RequestTerminated }, - {"488", pcpp::SipResponseLayer::SipResponseStatusCode::Sip488NotAcceptableHere }, - {"489", pcpp::SipResponseLayer::SipResponseStatusCode::Sip489BadEvent }, - {"491", pcpp::SipResponseLayer::SipResponseStatusCode::Sip491RequestPending }, - {"493", pcpp::SipResponseLayer::SipResponseStatusCode::Sip493Undecipherable }, - {"494", pcpp::SipResponseLayer::SipResponseStatusCode::Sip494SecurityAgreementRequired }, - {"500", pcpp::SipResponseLayer::SipResponseStatusCode::Sip500ServerInternalError }, - {"501", pcpp::SipResponseLayer::SipResponseStatusCode::Sip501NotImplemented }, - {"502", pcpp::SipResponseLayer::SipResponseStatusCode::Sip502BadGateway }, - {"503", pcpp::SipResponseLayer::SipResponseStatusCode::Sip503ServiceUnavailable }, - {"504", pcpp::SipResponseLayer::SipResponseStatusCode::Sip504ServerTimeout }, - {"505", pcpp::SipResponseLayer::SipResponseStatusCode::Sip505VersionNotSupported }, - {"513", pcpp::SipResponseLayer::SipResponseStatusCode::Sip513MessageTooLarge }, - {"555", pcpp::SipResponseLayer::SipResponseStatusCode::Sip555PushNotificationServiceNotSupported }, - {"580", pcpp::SipResponseLayer::SipResponseStatusCode::Sip580PreconditionFailure }, - {"600", pcpp::SipResponseLayer::SipResponseStatusCode::Sip600BusyEverywhere }, - {"603", pcpp::SipResponseLayer::SipResponseStatusCode::Sip603Decline }, - {"604", pcpp::SipResponseLayer::SipResponseStatusCode::Sip604DoesNotExistAnywhere }, - {"606", pcpp::SipResponseLayer::SipResponseStatusCode::Sip606NotAcceptable }, - {"607", pcpp::SipResponseLayer::SipResponseStatusCode::Sip607Unwanted }, - {"608", pcpp::SipResponseLayer::SipResponseStatusCode::Sip608Rejected } + { "100", pcpp::SipResponseLayer::SipResponseStatusCode::Sip100Trying }, + { "180", pcpp::SipResponseLayer::SipResponseStatusCode::Sip180Ringing }, + { "181", pcpp::SipResponseLayer::SipResponseStatusCode::Sip181CallisBeingForwarded }, + { "182", pcpp::SipResponseLayer::SipResponseStatusCode::Sip182Queued }, + { "183", pcpp::SipResponseLayer::SipResponseStatusCode::Sip183SessioninProgress }, + { "199", pcpp::SipResponseLayer::SipResponseStatusCode::Sip199EarlyDialogTerminated }, + { "200", pcpp::SipResponseLayer::SipResponseStatusCode::Sip200OK }, + { "202", pcpp::SipResponseLayer::SipResponseStatusCode::Sip202Accepted }, + { "204", pcpp::SipResponseLayer::SipResponseStatusCode::Sip204NoNotification }, + { "300", pcpp::SipResponseLayer::SipResponseStatusCode::Sip300MultipleChoices }, + { "301", pcpp::SipResponseLayer::SipResponseStatusCode::Sip301MovedPermanently }, + { "302", pcpp::SipResponseLayer::SipResponseStatusCode::Sip302MovedTemporarily }, + { "305", pcpp::SipResponseLayer::SipResponseStatusCode::Sip305UseProxy }, + { "380", pcpp::SipResponseLayer::SipResponseStatusCode::Sip380AlternativeService }, + { "400", pcpp::SipResponseLayer::SipResponseStatusCode::Sip400BadRequest }, + { "401", pcpp::SipResponseLayer::SipResponseStatusCode::Sip401Unauthorized }, + { "402", pcpp::SipResponseLayer::SipResponseStatusCode::Sip402PaymentRequired }, + { "403", pcpp::SipResponseLayer::SipResponseStatusCode::Sip403Forbidden }, + { "404", pcpp::SipResponseLayer::SipResponseStatusCode::Sip404NotFound }, + { "405", pcpp::SipResponseLayer::SipResponseStatusCode::Sip405MethodNotAllowed }, + { "406", pcpp::SipResponseLayer::SipResponseStatusCode::Sip406NotAcceptable }, + { "407", pcpp::SipResponseLayer::SipResponseStatusCode::Sip407ProxyAuthenticationRequired }, + { "408", pcpp::SipResponseLayer::SipResponseStatusCode::Sip408RequestTimeout }, + { "409", pcpp::SipResponseLayer::SipResponseStatusCode::Sip409Conflict }, + { "410", pcpp::SipResponseLayer::SipResponseStatusCode::Sip410Gone }, + { "411", pcpp::SipResponseLayer::SipResponseStatusCode::Sip411LengthRequired }, + { "412", pcpp::SipResponseLayer::SipResponseStatusCode::Sip412ConditionalRequestFailed }, + { "413", pcpp::SipResponseLayer::SipResponseStatusCode::Sip413RequestEntityTooLarge }, + { "414", pcpp::SipResponseLayer::SipResponseStatusCode::Sip414RequestURITooLong }, + { "415", pcpp::SipResponseLayer::SipResponseStatusCode::Sip415UnsupportedMediaType }, + { "416", pcpp::SipResponseLayer::SipResponseStatusCode::Sip416UnsupportedURIScheme }, + { "417", pcpp::SipResponseLayer::SipResponseStatusCode::Sip417UnknownResourcePriority }, + { "420", pcpp::SipResponseLayer::SipResponseStatusCode::Sip420BadExtension }, + { "421", pcpp::SipResponseLayer::SipResponseStatusCode::Sip421ExtensionRequired }, + { "422", pcpp::SipResponseLayer::SipResponseStatusCode::Sip422SessionIntervalTooSmall }, + { "423", pcpp::SipResponseLayer::SipResponseStatusCode::Sip423IntervalTooBrief }, + { "424", pcpp::SipResponseLayer::SipResponseStatusCode::Sip424BadLocationInformation }, + { "425", pcpp::SipResponseLayer::SipResponseStatusCode::Sip425BadAlertMessage }, + { "428", pcpp::SipResponseLayer::SipResponseStatusCode::Sip428UseIdentityHeader }, + { "429", pcpp::SipResponseLayer::SipResponseStatusCode::Sip429ProvideReferrerIdentity }, + { "430", pcpp::SipResponseLayer::SipResponseStatusCode::Sip430FlowFailed }, + { "433", pcpp::SipResponseLayer::SipResponseStatusCode::Sip433AnonymityDisallowed }, + { "436", pcpp::SipResponseLayer::SipResponseStatusCode::Sip436BadIdentityInfo }, + { "437", pcpp::SipResponseLayer::SipResponseStatusCode::Sip437UnsupportedCertificate }, + { "438", pcpp::SipResponseLayer::SipResponseStatusCode::Sip438InvalidIdentityHeader }, + { "439", pcpp::SipResponseLayer::SipResponseStatusCode::Sip439FirstHopLacksOutboundSupport }, + { "440", pcpp::SipResponseLayer::SipResponseStatusCode::Sip440MaxBreadthExceeded }, + { "469", pcpp::SipResponseLayer::SipResponseStatusCode::Sip469BadInfoPackage }, + { "470", pcpp::SipResponseLayer::SipResponseStatusCode::Sip470ConsentNeeded }, + { "480", pcpp::SipResponseLayer::SipResponseStatusCode::Sip480TemporarilyUnavailable }, + { "481", pcpp::SipResponseLayer::SipResponseStatusCode::Sip481Call_TransactionDoesNotExist }, + { "482", pcpp::SipResponseLayer::SipResponseStatusCode::Sip482LoopDetected }, + { "483", pcpp::SipResponseLayer::SipResponseStatusCode::Sip483TooManyHops }, + { "484", pcpp::SipResponseLayer::SipResponseStatusCode::Sip484AddressIncomplete }, + { "485", pcpp::SipResponseLayer::SipResponseStatusCode::Sip485Ambiguous }, + { "486", pcpp::SipResponseLayer::SipResponseStatusCode::Sip486BusyHere }, + { "487", pcpp::SipResponseLayer::SipResponseStatusCode::Sip487RequestTerminated }, + { "488", pcpp::SipResponseLayer::SipResponseStatusCode::Sip488NotAcceptableHere }, + { "489", pcpp::SipResponseLayer::SipResponseStatusCode::Sip489BadEvent }, + { "491", pcpp::SipResponseLayer::SipResponseStatusCode::Sip491RequestPending }, + { "493", pcpp::SipResponseLayer::SipResponseStatusCode::Sip493Undecipherable }, + { "494", pcpp::SipResponseLayer::SipResponseStatusCode::Sip494SecurityAgreementRequired }, + { "500", pcpp::SipResponseLayer::SipResponseStatusCode::Sip500ServerInternalError }, + { "501", pcpp::SipResponseLayer::SipResponseStatusCode::Sip501NotImplemented }, + { "502", pcpp::SipResponseLayer::SipResponseStatusCode::Sip502BadGateway }, + { "503", pcpp::SipResponseLayer::SipResponseStatusCode::Sip503ServiceUnavailable }, + { "504", pcpp::SipResponseLayer::SipResponseStatusCode::Sip504ServerTimeout }, + { "505", pcpp::SipResponseLayer::SipResponseStatusCode::Sip505VersionNotSupported }, + { "513", pcpp::SipResponseLayer::SipResponseStatusCode::Sip513MessageTooLarge }, + { "555", pcpp::SipResponseLayer::SipResponseStatusCode::Sip555PushNotificationServiceNotSupported }, + { "580", pcpp::SipResponseLayer::SipResponseStatusCode::Sip580PreconditionFailure }, + { "600", pcpp::SipResponseLayer::SipResponseStatusCode::Sip600BusyEverywhere }, + { "603", pcpp::SipResponseLayer::SipResponseStatusCode::Sip603Decline }, + { "604", pcpp::SipResponseLayer::SipResponseStatusCode::Sip604DoesNotExistAnywhere }, + { "606", pcpp::SipResponseLayer::SipResponseStatusCode::Sip606NotAcceptable }, + { "607", pcpp::SipResponseLayer::SipResponseStatusCode::Sip607Unwanted }, + { "608", pcpp::SipResponseLayer::SipResponseStatusCode::Sip608Rejected } }; - for (const std::pair &statusCode : possibleStatusCodes ) + for (const std::pair& statusCode : possibleStatusCodes) { std::string firstLine = "SIP/x.y " + statusCode.first + " "; - PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(firstLine.c_str(), firstLine.length()), statusCode.second, enum); + PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(firstLine.c_str(), firstLine.length()), + statusCode.second, enum); } - PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(std::string("SIP/x.y 999 ").c_str(), 12), pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); -} // SipResponseParseStatusCodeTest - - + PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseStatusCode(std::string("SIP/x.y 999 ").c_str(), 12), + pcpp::SipResponseLayer::SipResponseStatusCode::SipStatusCodeUnknown, enum); +} // SipResponseParseStatusCodeTest PTF_TEST_CASE(SipResponseParseVersionCodeTest) { @@ -378,9 +394,7 @@ PTF_TEST_CASE(SipResponseParseVersionCodeTest) PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseVersion(std::string("SIP/2.01").c_str(), 8), ""); PTF_ASSERT_EQUAL(pcpp::SipResponseFirstLine::parseVersion(std::string("SIP/2.0 ").c_str(), 8), "SIP/2.0"); -} // SipResponseParseVersionCodeTest - - +} // SipResponseParseVersionCodeTest PTF_TEST_CASE(SipResponseLayerParsingTest) { @@ -423,7 +437,8 @@ PTF_TEST_CASE(SipResponseLayerParsingTest) PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getSize(), 20); PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_FROM_FIELD)); - PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->getFieldValue(), ";tag=GR52RWG346-34"); + PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->getFieldValue(), + ";tag=GR52RWG346-34"); PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_CALL_ID_FIELD)); PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_CALL_ID_FIELD)->getFieldValue(), "12013223@200.57.7.195"); PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_SERVER_FIELD)); @@ -432,7 +447,6 @@ PTF_TEST_CASE(SipResponseLayerParsingTest) PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_CONTENT_LENGTH_FIELD)->getFieldValue(), "0"); PTF_ASSERT_EQUAL(sipRespLayer->getContentLength(), 0); - sipRespLayer = sipRespPacket2.getLayerOfType(); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip180Ringing, enum); @@ -443,12 +457,12 @@ PTF_TEST_CASE(SipResponseLayerParsingTest) PTF_ASSERT_EQUAL(sipRespLayer->getFirstField()->getFieldName(), PCPP_SIP_VIA_FIELD); PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_VIA_FIELD)); - PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_VIA_FIELD)->getFieldValue(), "SIP/2.0/UDP 200.57.7.195;branch=z9hG4bKff9b46fb055c0521cc24024da96cd290"); + PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_VIA_FIELD)->getFieldValue(), + "SIP/2.0/UDP 200.57.7.195;branch=z9hG4bKff9b46fb055c0521cc24024da96cd290"); PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_CSEQ_FIELD)); PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_CSEQ_FIELD)->getFieldValue(), "1 INVITE"); PTF_ASSERT_EQUAL(sipRespLayer->getContentLength(), 0); - sipRespLayer = sipRespPacket3.getLayerOfType(); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip200OK, enum); @@ -461,7 +475,6 @@ PTF_TEST_CASE(SipResponseLayerParsingTest) PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_CONTENT_TYPE_FIELD)->getFieldValue(), "application/sdp"); PTF_ASSERT_EQUAL(sipRespLayer->getContentLength(), 298); - sipRespLayer = sipRespPacket4.getLayerOfType(); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip401Unauthorized, enum); @@ -471,13 +484,15 @@ PTF_TEST_CASE(SipResponseLayerParsingTest) PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getSize(), 26); PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_WWW_AUTHENTICATE_FIELD)); - PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_WWW_AUTHENTICATE_FIELD)->getFieldValue(), "Digest realm=\"ims.hom\",nonce=\"021fa2db5ff06518\",opaque=\"627f7bb95d5e2dcd\",algorithm=MD5,qop=\"auth\""); + PTF_ASSERT_EQUAL( + sipRespLayer->getFieldByName(PCPP_SIP_WWW_AUTHENTICATE_FIELD)->getFieldValue(), + "Digest realm=\"ims.hom\",nonce=\"021fa2db5ff06518\",opaque=\"627f7bb95d5e2dcd\",algorithm=MD5,qop=\"auth\""); PTF_ASSERT_EQUAL(sipRespLayer->getContentLength(), 0); - sipRespLayer = sipRespPacket7.getLayerOfType(); - PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip503ServiceUnavailable, enum); + PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip503ServiceUnavailable, + enum); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCodeAsInt(), 503); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCodeString(), "Service Unavailable"); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getVersion(), "SIP/2.0"); @@ -486,9 +501,7 @@ PTF_TEST_CASE(SipResponseLayerParsingTest) PTF_ASSERT_NOT_NULL(sipRespLayer->getFieldByName(PCPP_SIP_RETRY_AFTER_FIELD)); PTF_ASSERT_EQUAL(sipRespLayer->getFieldByName(PCPP_SIP_RETRY_AFTER_FIELD)->getFieldValue(), "0"); PTF_ASSERT_EQUAL(sipRespLayer->getContentLength(), 0); -} // SipResponseLayerParsingTest - - +} // SipResponseLayerParsingTest PTF_TEST_CASE(SipResponseLayerCreationTest) { @@ -513,10 +526,13 @@ PTF_TEST_CASE(SipResponseLayerCreationTest) contentLengthField->setFieldValue(" 0"); PTF_ASSERT_NOT_NULL(sipRespLayer.addEndOfHeader()); PTF_ASSERT_NOT_NULL(sipRespLayer.insertField(nullptr, PCPP_SIP_CALL_ID_FIELD, "93803593")); - PTF_ASSERT_NOT_NULL(sipRespLayer.insertField(nullptr, PCPP_SIP_VIA_FIELD, "SIP/2.0/UDP 10.3.160.214:5060;rport=5060;received=10.3.160.214;branch=z9hG4bK19266132")); + PTF_ASSERT_NOT_NULL(sipRespLayer.insertField( + nullptr, PCPP_SIP_VIA_FIELD, + "SIP/2.0/UDP 10.3.160.214:5060;rport=5060;received=10.3.160.214;branch=z9hG4bK19266132")); pcpp::HeaderField* fromField = sipRespLayer.getFieldByName(PCPP_SIP_FROM_FIELD); PTF_ASSERT_NOT_NULL(fromField); - PTF_ASSERT_NOT_NULL(sipRespLayer.insertField(fromField, PCPP_SIP_TO_FIELD, ";tag=z9hG4bKPjoKb0QlsN0Z-v4iW63WRm5UfjLn.Gm81V")); + PTF_ASSERT_NOT_NULL(sipRespLayer.insertField( + fromField, PCPP_SIP_TO_FIELD, ";tag=z9hG4bKPjoKb0QlsN0Z-v4iW63WRm5UfjLn.Gm81V")); pcpp::Packet newSipPacket; PTF_ASSERT_TRUE(newSipPacket.addLayer(ðLayer)); @@ -529,10 +545,9 @@ PTF_TEST_CASE(SipResponseLayerCreationTest) newSipPacket.getLayerOfType()->getUdpHeader()->headerChecksum = 0xced8; PTF_ASSERT_EQUAL(newSipPacket.getRawPacket()->getRawDataLen(), bufferLength6); - PTF_ASSERT_BUF_COMPARE(newSipPacket.getRawPacket()->getRawData(), buffer6, newSipPacket.getRawPacket()->getRawDataLen()); -} // SipResponseLayerCreationTest - - + PTF_ASSERT_BUF_COMPARE(newSipPacket.getRawPacket()->getRawData(), buffer6, + newSipPacket.getRawPacket()->getRawDataLen()); +} // SipResponseLayerCreationTest PTF_TEST_CASE(SipResponseLayerEditTest) { @@ -553,12 +568,14 @@ PTF_TEST_CASE(SipResponseLayerEditTest) PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip202Accepted, enum); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getSize(), 22); PTF_ASSERT_TRUE(sipRespLayer->getFirstLine()->setStatusCode(pcpp::SipResponseLayer::Sip415UnsupportedMediaType)); - PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip415UnsupportedMediaType, enum); + PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip415UnsupportedMediaType, + enum); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getSize(), 36); PTF_ASSERT_TRUE(sipRespLayer->getFirstLine()->setStatusCode(pcpp::SipResponseLayer::Sip603Decline)); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip603Decline, enum); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getSize(), 21); - PTF_ASSERT_TRUE(sipRespLayer->getFirstLine()->setStatusCode(pcpp::SipResponseLayer::Sip603Decline, "Some other string")); + PTF_ASSERT_TRUE( + sipRespLayer->getFirstLine()->setStatusCode(pcpp::SipResponseLayer::Sip603Decline, "Some other string")); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getStatusCode(), pcpp::SipResponseLayer::Sip603Decline, enum); PTF_ASSERT_EQUAL(sipRespLayer->getFirstLine()->getSize(), 31); PTF_ASSERT_TRUE(sipRespLayer->getFirstLine()->setStatusCode(pcpp::SipResponseLayer::Sip401Unauthorized)); @@ -572,15 +589,20 @@ PTF_TEST_CASE(SipResponseLayerEditTest) PTF_ASSERT_TRUE(sipRespLayer->removeField(PCPP_SIP_VIA_FIELD, 1)); PTF_ASSERT_TRUE(sipRespLayer->removeField(PCPP_SIP_CONTACT_FIELD)); PTF_ASSERT_TRUE(sipRespLayer->removeField(PCPP_SIP_CALL_ID_FIELD)); - PTF_ASSERT_TRUE(sipRespLayer->getFieldByName(PCPP_SIP_VIA_FIELD)->setFieldValue("SIP/2.0/UDP 10.3.160.214:5060;rport=5060;received=10.3.160.214;branch=z9hG4bK758266975")); + PTF_ASSERT_TRUE( + sipRespLayer->getFieldByName(PCPP_SIP_VIA_FIELD) + ->setFieldValue("SIP/2.0/UDP 10.3.160.214:5060;rport=5060;received=10.3.160.214;branch=z9hG4bK758266975")); PTF_ASSERT_TRUE(sipRespLayer->removeField(PCPP_SIP_CONTENT_TYPE_FIELD)); PTF_ASSERT_TRUE(sipRespLayer->removeField(PCPP_SIP_SERVER_FIELD)); PTF_ASSERT_NOT_NULL(sipRespLayer->setContentLength(0)); - PTF_ASSERT_TRUE(sipRespLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->setFieldValue(";tag=1597735002")); - PTF_ASSERT_TRUE(sipRespLayer->getFieldByName(PCPP_SIP_TO_FIELD)->setFieldValue(";tag=z9hG4bKPjNwtzXu2EwWIjxR8qftv00jzO9arV-iyh")); + PTF_ASSERT_TRUE( + sipRespLayer->getFieldByName(PCPP_SIP_FROM_FIELD)->setFieldValue(";tag=1597735002")); + PTF_ASSERT_TRUE(sipRespLayer->getFieldByName(PCPP_SIP_TO_FIELD) + ->setFieldValue(";tag=z9hG4bKPjNwtzXu2EwWIjxR8qftv00jzO9arV-iyh")); PTF_ASSERT_TRUE(sipRespLayer->getFieldByName(PCPP_SIP_CSEQ_FIELD)->setFieldValue("1 REGISTER")); - PTF_ASSERT_NOT_NULL(sipRespLayer->insertField(PCPP_SIP_CSEQ_FIELD, PCPP_SIP_WWW_AUTHENTICATE_FIELD, - "Digest realm=\"ims.hom\",nonce=\"021fa2db5ff06518\",opaque=\"627f7bb95d5e2dcd\",algorithm=MD5,qop=\"auth\"")); + PTF_ASSERT_NOT_NULL(sipRespLayer->insertField( + PCPP_SIP_CSEQ_FIELD, PCPP_SIP_WWW_AUTHENTICATE_FIELD, + "Digest realm=\"ims.hom\",nonce=\"021fa2db5ff06518\",opaque=\"627f7bb95d5e2dcd\",algorithm=MD5,qop=\"auth\"")); PTF_ASSERT_NOT_NULL(sipRespLayer->insertField(PCPP_SIP_VIA_FIELD, PCPP_SIP_CALL_ID_FIELD, "434981653")); PTF_ASSERT_TRUE(sipRespLayer->getFieldByName(PCPP_SIP_CONTENT_LENGTH_FIELD)->setFieldValue(" 0")); @@ -588,12 +610,11 @@ PTF_TEST_CASE(SipResponseLayerEditTest) PTF_ASSERT_EQUAL(secondSipRespLayer->getHeaderLen(), sipRespLayer->getHeaderLen()); PTF_ASSERT_EQUAL(secondSipRespLayer->getFirstLine()->getSize(), sipRespLayer->getFirstLine()->getSize()); - PTF_ASSERT_EQUAL(secondSipRespLayer->getFirstLine()->getStatusCode(), sipRespLayer->getFirstLine()->getStatusCode(), enum); + PTF_ASSERT_EQUAL(secondSipRespLayer->getFirstLine()->getStatusCode(), sipRespLayer->getFirstLine()->getStatusCode(), + enum); PTF_ASSERT_EQUAL(secondSipRespLayer->getFieldCount(), sipRespLayer->getFieldCount()); PTF_ASSERT_BUF_COMPARE(secondSipRespLayer->getData(), sipRespLayer->getData(), secondSipRespLayer->getHeaderLen()); -} // SipResponseLayerEditTest - - +} // SipResponseLayerEditTest PTF_TEST_CASE(SdpLayerParsingTest) { @@ -615,13 +636,16 @@ PTF_TEST_CASE(SdpLayerParsingTest) PTF_ASSERT_NOT_NULL(sdpLayer->getFieldByName(PCPP_SDP_PROTOCOL_VERSION_FIELD)); PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_PROTOCOL_VERSION_FIELD)->getFieldValue(), "0"); PTF_ASSERT_NOT_NULL(sdpLayer->getFieldByName(PCPP_SDP_ORIGINATOR_FIELD)); - PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_ORIGINATOR_FIELD)->getFieldValue(), "Clarent 120386 120387 IN IP4 200.57.7.196"); + PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_ORIGINATOR_FIELD)->getFieldValue(), + "Clarent 120386 120387 IN IP4 200.57.7.196"); PTF_ASSERT_NOT_NULL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD)); - PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD)->getFieldValue(), "audio 40376 RTP/AVP 8 18 4 0"); + PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD)->getFieldValue(), + "audio 40376 RTP/AVP 8 18 4 0"); PTF_ASSERT_NOT_NULL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD)); PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD)->getFieldValue(), "rtpmap:8 PCMA/8000"); PTF_ASSERT_NOT_NULL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, 2)); - PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, 2)->getFieldValue(), "rtpmap:4 G723/8000"); + PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, 2)->getFieldValue(), + "rtpmap:4 G723/8000"); PTF_ASSERT_NOT_NULL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, 4)); PTF_ASSERT_EQUAL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, 4)->getFieldValue(), "SendRecv"); PTF_ASSERT_NULL(sdpLayer->getFieldByName(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, 5)); @@ -645,8 +669,7 @@ PTF_TEST_CASE(SdpLayerParsingTest) PTF_ASSERT_EQUAL(sdpLayer->getOwnerIPv4Address(), pcpp::IPv4Address("10.33.6.100")); PTF_ASSERT_EQUAL(sdpLayer->getMediaPort("audio"), 6010); PTF_ASSERT_EQUAL(sdpLayer->getMediaPort("image"), 6012); -} // SdpLayerParsingTest - +} // SdpLayerParsingTest PTF_TEST_CASE(SipNotSdpLayerParsingTest) { @@ -665,7 +688,7 @@ PTF_TEST_CASE(SipNotSdpLayerParsingTest) PTF_ASSERT_EQUAL(nextLayer->getProtocol(), pcpp::GenericPayload); PTF_ASSERT_FALSE(notSdpPacket.isPacketOfType(pcpp::SDP)); -} // SipNotSdpLayerParsingTest +} // SipNotSdpLayerParsingTest PTF_TEST_CASE(SdpLayerCreationTest) { @@ -725,9 +748,7 @@ PTF_TEST_CASE(SdpLayerCreationTest) PTF_ASSERT_EQUAL(copiedSdpLayer.getFieldCount(), 18); PTF_ASSERT_EQUAL(copiedSdpLayer.getHeaderLen(), 406); PTF_ASSERT_BUF_COMPARE(copiedSdpLayer.getData(), sdpLayerPtr->getData(), sdpLayerPtr->getHeaderLen()); -} // SdpLayerCreationTest - - +} // SdpLayerCreationTest PTF_TEST_CASE(SdpLayerEditTest) { @@ -743,7 +764,8 @@ PTF_TEST_CASE(SdpLayerEditTest) pcpp::SdpLayer* sdpLayer = sourceSdpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(sdpLayer); - PTF_ASSERT_TRUE(sdpLayer->getFieldByName(PCPP_SDP_ORIGINATOR_FIELD)->setFieldValue("IPP 782647527 782647407 IN IP4 10.33.6.100")); + PTF_ASSERT_TRUE(sdpLayer->getFieldByName(PCPP_SDP_ORIGINATOR_FIELD) + ->setFieldValue("IPP 782647527 782647407 IN IP4 10.33.6.100")); PTF_ASSERT_TRUE(sdpLayer->getFieldByName(PCPP_SDP_SESSION_NAME_FIELD)->setFieldValue("Phone-Call")); PTF_ASSERT_TRUE(sdpLayer->getFieldByName(PCPP_SDP_CONNECTION_INFO_FIELD)->setFieldValue("IN IP4 10.33.6.100")); PTF_ASSERT_TRUE(sdpLayer->removeField(PCPP_SDP_MEDIA_NAME_FIELD)); @@ -779,4 +801,4 @@ PTF_TEST_CASE(SdpLayerEditTest) PTF_ASSERT_EQUAL(sdpLayer->getMediaPort("audio"), targetSdpLayer->getMediaPort("audio")); PTF_ASSERT_EQUAL(sdpLayer->getMediaPort("image"), targetSdpLayer->getMediaPort("image")); PTF_ASSERT_BUF_COMPARE(sdpLayer->getData(), targetSdpLayer->getData(), targetSdpLayer->getHeaderLen()); -} // SdpLayerEditTest +} // SdpLayerEditTest diff --git a/Tests/Packet++Test/Tests/Sll2Tests.cpp b/Tests/Packet++Test/Tests/Sll2Tests.cpp index 052de8daba..64e6b417b7 100644 --- a/Tests/Packet++Test/Tests/Sll2Tests.cpp +++ b/Tests/Packet++Test/Tests/Sll2Tests.cpp @@ -37,8 +37,7 @@ PTF_TEST_CASE(Sll2PacketParsingTest) pcpp::MacAddress macAddrRef("d2:cf:c2:50:15:ea"); PTF_ASSERT_EQUAL(macAddrRef, macAddrFromPacket); PTF_ASSERT_EQUAL(macAddrRef, sll2Layer->getLinkLayerAsMacAddress()); -} // Sll2PacketParsingTest - +} // Sll2PacketParsingTest PTF_TEST_CASE(Sll2PacketCreationTest) { @@ -46,8 +45,7 @@ PTF_TEST_CASE(Sll2PacketCreationTest) sll2Layer.setProtocolType(PCPP_ETHERTYPE_IP); sll2Layer.setMacAddressAsLinkLayer(pcpp::MacAddress("d2:cf:c2:50:15:ea")); - pcpp::IPv4Layer ipLayer(pcpp::IPv4Address(std::string("7.249.151.114")), - pcpp::IPv4Address("116.63.66.108")); + pcpp::IPv4Layer ipLayer(pcpp::IPv4Address(std::string("7.249.151.114")), pcpp::IPv4Address("116.63.66.108")); ipLayer.getIPv4Header()->fragmentOffset = 0x40; ipLayer.getIPv4Header()->ipId = htobe16(35618); ipLayer.getIPv4Header()->timeToLive = 64; @@ -74,5 +72,5 @@ PTF_TEST_CASE(Sll2PacketCreationTest) PTF_ASSERT_FALSE(sll2Layer.setLinkLayerAddr(tempBuf, 9)); pcpp::Logger::getInstance().enableLogs(); - delete [] buffer1; -} // Sll2PacketCreationTest + delete[] buffer1; +} // Sll2PacketCreationTest diff --git a/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp b/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp index 3cca58180d..e9f7283d65 100644 --- a/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp +++ b/Tests/Packet++Test/Tests/SllNullLoopbackTests.cpp @@ -12,7 +12,6 @@ #include "PayloadLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(SllPacketParsingTest) { timeval time; @@ -37,9 +36,7 @@ PTF_TEST_CASE(SllPacketParsingTest) pcpp::MacAddress macAddrRef("00:12:44:1e:74:00"); PTF_ASSERT_EQUAL(macAddrRef, macAddrFromPacket); PTF_ASSERT_EQUAL(sllLayer->getSllHeader()->protocol_type, htobe16(PCPP_ETHERTYPE_IPV6)); -} // SllPacketParsingTest - - +} // SllPacketParsingTest PTF_TEST_CASE(SllPacketCreationTest) { @@ -58,9 +55,12 @@ PTF_TEST_CASE(SllPacketCreationTest) tcpLayer.getTcpHeader()->ackNumber = htobe32(0x7633e977); tcpLayer.getTcpHeader()->ackFlag = 1; tcpLayer.getTcpHeader()->windowSize = htobe16(4098); - PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop)).isNotNull()); - PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop)).isNotNull()); - pcpp::TcpOption tsOption = tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionEnumType::Timestamp, nullptr, PCPP_TCPOLEN_TIMESTAMP-2)); + PTF_ASSERT_TRUE( + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop)).isNotNull()); + PTF_ASSERT_TRUE( + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop)).isNotNull()); + pcpp::TcpOption tsOption = tcpLayer.addTcpOption( + pcpp::TcpOptionBuilder(pcpp::TcpOptionEnumType::Timestamp, nullptr, PCPP_TCPOLEN_TIMESTAMP - 2)); PTF_ASSERT_TRUE(tsOption.isNotNull()); tsOption.setValue(htobe32(0x0402383b)); tsOption.setValue(htobe32(0x03ff37f5), 4); @@ -72,16 +72,13 @@ PTF_TEST_CASE(SllPacketCreationTest) sllPacket.computeCalculateFields(); - READ_FILE_INTO_BUFFER(1, "PacketExamples/SllPacket2.dat"); PTF_ASSERT_EQUAL(sllPacket.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(sllPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - delete [] buffer1; -} // SllPacketCreationTest - - + delete[] buffer1; +} // SllPacketCreationTest PTF_TEST_CASE(NullLoopbackTest) { @@ -92,7 +89,6 @@ PTF_TEST_CASE(NullLoopbackTest) READ_FILE_AND_CREATE_PACKET_LINKTYPE(2, "PacketExamples/NullLoopback2.dat", pcpp::LINKTYPE_NULL); READ_FILE_AND_CREATE_PACKET_LINKTYPE(3, "PacketExamples/NullLoopback3.dat", pcpp::LINKTYPE_NULL); - pcpp::Packet nullPacket1(&rawPacket1); pcpp::Packet nullPacket2(&rawPacket2); pcpp::Packet nullPacket3(&rawPacket3); @@ -132,7 +128,9 @@ PTF_TEST_CASE(NullLoopbackTest) pcpp::UdpLayer newUdpLayer(55369, 8612); - uint8_t payload[] = { 0x42, 0x4a, 0x4e, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t payload[] = { + 0x42, 0x4a, 0x4e, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; pcpp::PayloadLayer newPayloadLayer(payload, 16); pcpp::Packet newNullPacket(1); @@ -145,4 +143,4 @@ PTF_TEST_CASE(NullLoopbackTest) PTF_ASSERT_EQUAL(newNullPacket.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(newNullPacket.getRawPacket()->getRawData(), buffer2, bufferLength2); -} // NullLoopbackTest +} // NullLoopbackTest diff --git a/Tests/Packet++Test/Tests/SmtpTests.cpp b/Tests/Packet++Test/Tests/SmtpTests.cpp index 9912daf195..c8e0cfc416 100644 --- a/Tests/Packet++Test/Tests/SmtpTests.cpp +++ b/Tests/Packet++Test/Tests/SmtpTests.cpp @@ -17,7 +17,7 @@ PTF_TEST_CASE(SmtpParsingTests) // Command READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/smtpCommand.dat"); pcpp::Packet smtpPacket1(&rawPacket1); - auto *smtpLayer1 = smtpPacket1.getLayerOfType(); + auto* smtpLayer1 = smtpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(smtpLayer1); PTF_ASSERT_EQUAL(smtpLayer1->getHeaderLen(), 12); @@ -31,7 +31,7 @@ PTF_TEST_CASE(SmtpParsingTests) // Response packet READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/smtpResponse.dat"); pcpp::Packet smtpPacket2(&rawPacket2); - auto *smtpLayer2 = smtpPacket2.getLayerOfType(); + auto* smtpLayer2 = smtpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(smtpLayer2); PTF_ASSERT_EQUAL(smtpLayer2->getHeaderLen(), 18); @@ -45,28 +45,25 @@ PTF_TEST_CASE(SmtpParsingTests) // Multiline READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/smtpMultiLine.dat"); pcpp::Packet smtpPacket3(&rawPacket3); - auto *smtpLayer3 = smtpPacket3.getLayerOfType(); + auto* smtpLayer3 = smtpPacket3.getLayerOfType(); PTF_ASSERT_NOT_NULL(smtpLayer3); PTF_ASSERT_EQUAL(smtpLayer3->getHeaderLen(), 181); PTF_ASSERT_EQUAL(smtpLayer3->getStatusCode(), pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_READY, enumclass); PTF_ASSERT_EQUAL(smtpLayer3->getStatusCodeString(), "220"); - PTF_ASSERT_EQUAL( - smtpLayer3->getStatusOption(), - "xc90.websitewelcome.com ESMTP Exim 4.69 #1 Mon, 05 Oct 2009 01:05:54 -0500 We do not authorize " - "the use of this system to transport unsolicited, and/or bulk e-mail."); - PTF_ASSERT_EQUAL( - smtpLayer3->getStatusOption(false), - "xc90.websitewelcome.com ESMTP Exim 4.69 #1 Mon, 05 Oct 2009 01:05:54 -0500 \r\n" - "We do not authorize the use of this system to transport unsolicited, \r\nand/or bulk e-mail." - ) + PTF_ASSERT_EQUAL(smtpLayer3->getStatusOption(), + "xc90.websitewelcome.com ESMTP Exim 4.69 #1 Mon, 05 Oct 2009 01:05:54 -0500 We do not authorize " + "the use of this system to transport unsolicited, and/or bulk e-mail."); + PTF_ASSERT_EQUAL(smtpLayer3->getStatusOption(false), + "xc90.websitewelcome.com ESMTP Exim 4.69 #1 Mon, 05 Oct 2009 01:05:54 -0500 \r\n" + "We do not authorize the use of this system to transport unsolicited, \r\nand/or bulk e-mail.") PTF_ASSERT_EQUAL(smtpLayer3->toString(), "SMTP response layer, status code: Service ready"); PTF_ASSERT_TRUE(smtpLayer3->isMultiLine()); // IPv6 READ_FILE_AND_CREATE_PACKET(4, "PacketExamples/smtpIpv6.dat"); pcpp::Packet smtpPacket4(&rawPacket4); - auto *smtpLayer4 = smtpPacket4.getLayerOfType(); + auto* smtpLayer4 = smtpPacket4.getLayerOfType(); PTF_ASSERT_NOT_NULL(smtpLayer4); PTF_ASSERT_EQUAL(smtpLayer4->getHeaderLen(), 51); @@ -80,7 +77,7 @@ PTF_TEST_CASE(SmtpParsingTests) // Username and Password packets. They should return Unknown since there is no command in packets READ_FILE_AND_CREATE_PACKET(5, "PacketExamples/smtpUser.dat"); pcpp::Packet smtpPacket5(&rawPacket5); - auto *smtpLayer5 = smtpPacket5.getLayerOfType(); + auto* smtpLayer5 = smtpPacket5.getLayerOfType(); PTF_ASSERT_EQUAL(smtpLayer5->getHeaderLen(), 30); PTF_ASSERT_EQUAL(smtpLayer5->getCommand(), pcpp::SmtpRequestLayer::SmtpCommand::UNK, enumclass); @@ -92,7 +89,7 @@ PTF_TEST_CASE(SmtpParsingTests) READ_FILE_AND_CREATE_PACKET(6, "PacketExamples/smtpPassword.dat"); pcpp::Packet smtpPacket6(&rawPacket6); - auto *smtpLayer6 = smtpPacket6.getLayerOfType(); + auto* smtpLayer6 = smtpPacket6.getLayerOfType(); PTF_ASSERT_EQUAL(smtpLayer6->getHeaderLen(), 18); PTF_ASSERT_EQUAL(smtpLayer6->getCommand(), pcpp::SmtpRequestLayer::SmtpCommand::UNK, enumclass); @@ -104,86 +101,88 @@ PTF_TEST_CASE(SmtpParsingTests) // Command descriptions std::vector> possibleCommandCodes = { - {static_cast(0), "Unknown command"}, - {pcpp::SmtpRequestLayer::SmtpCommand::DATA, "Starting mail body"}, - {pcpp::SmtpRequestLayer::SmtpCommand::EHLO, "Initiate conversation"}, - {pcpp::SmtpRequestLayer::SmtpCommand::EXPN, "Expand the mailing list"}, - {pcpp::SmtpRequestLayer::SmtpCommand::HELO, "Initiate conversation"}, - {pcpp::SmtpRequestLayer::SmtpCommand::HELP, "Ask information"}, - {pcpp::SmtpRequestLayer::SmtpCommand::MAIL, "Sender indication"}, - {pcpp::SmtpRequestLayer::SmtpCommand::NOOP, "No operation"}, - {pcpp::SmtpRequestLayer::SmtpCommand::QUIT, "Close conversation"}, - {pcpp::SmtpRequestLayer::SmtpCommand::RCPT, "Receiver indication"}, - {pcpp::SmtpRequestLayer::SmtpCommand::RSET, "Abort transaction"}, - {pcpp::SmtpRequestLayer::SmtpCommand::VRFY, "Identify user"}, - {pcpp::SmtpRequestLayer::SmtpCommand::STARTTLS, "Start TLS handshake"}, - {pcpp::SmtpRequestLayer::SmtpCommand::TURN, "Reverse the role of sender and receiver"}, - {pcpp::SmtpRequestLayer::SmtpCommand::SEND, "Send mail to terminal"}, - {pcpp::SmtpRequestLayer::SmtpCommand::SOML, "Send mail to terminal or to mailbox"}, - {pcpp::SmtpRequestLayer::SmtpCommand::SAML, "Send mail to terminal and mailbox"}, - {pcpp::SmtpRequestLayer::SmtpCommand::AUTH, "Authenticate client and server"}, - {pcpp::SmtpRequestLayer::SmtpCommand::ATRN, "Reverse the role of sender and receiver"}, - {pcpp::SmtpRequestLayer::SmtpCommand::BDAT, "Submit mail contents"}, - {pcpp::SmtpRequestLayer::SmtpCommand::ETRN, "Request to start SMTP queue processing"}, - {pcpp::SmtpRequestLayer::SmtpCommand::XADR, "Release status of the channel"}, - {pcpp::SmtpRequestLayer::SmtpCommand::XCIR, "Release status of the circuit checking facility"}, - {pcpp::SmtpRequestLayer::SmtpCommand::XSTA, "Release status of the number of messages in channel queues"}, - {pcpp::SmtpRequestLayer::SmtpCommand::XGEN, - "Release status of whether a compiled configuration and character set are in use"}}; - - for (const auto &entry : possibleCommandCodes) + { static_cast(0), "Unknown command" }, + { pcpp::SmtpRequestLayer::SmtpCommand::DATA, "Starting mail body" }, + { pcpp::SmtpRequestLayer::SmtpCommand::EHLO, "Initiate conversation" }, + { pcpp::SmtpRequestLayer::SmtpCommand::EXPN, "Expand the mailing list" }, + { pcpp::SmtpRequestLayer::SmtpCommand::HELO, "Initiate conversation" }, + { pcpp::SmtpRequestLayer::SmtpCommand::HELP, "Ask information" }, + { pcpp::SmtpRequestLayer::SmtpCommand::MAIL, "Sender indication" }, + { pcpp::SmtpRequestLayer::SmtpCommand::NOOP, "No operation" }, + { pcpp::SmtpRequestLayer::SmtpCommand::QUIT, "Close conversation" }, + { pcpp::SmtpRequestLayer::SmtpCommand::RCPT, "Receiver indication" }, + { pcpp::SmtpRequestLayer::SmtpCommand::RSET, "Abort transaction" }, + { pcpp::SmtpRequestLayer::SmtpCommand::VRFY, "Identify user" }, + { pcpp::SmtpRequestLayer::SmtpCommand::STARTTLS, "Start TLS handshake" }, + { pcpp::SmtpRequestLayer::SmtpCommand::TURN, "Reverse the role of sender and receiver" }, + { pcpp::SmtpRequestLayer::SmtpCommand::SEND, "Send mail to terminal" }, + { pcpp::SmtpRequestLayer::SmtpCommand::SOML, "Send mail to terminal or to mailbox" }, + { pcpp::SmtpRequestLayer::SmtpCommand::SAML, "Send mail to terminal and mailbox" }, + { pcpp::SmtpRequestLayer::SmtpCommand::AUTH, "Authenticate client and server" }, + { pcpp::SmtpRequestLayer::SmtpCommand::ATRN, "Reverse the role of sender and receiver" }, + { pcpp::SmtpRequestLayer::SmtpCommand::BDAT, "Submit mail contents" }, + { pcpp::SmtpRequestLayer::SmtpCommand::ETRN, "Request to start SMTP queue processing" }, + { pcpp::SmtpRequestLayer::SmtpCommand::XADR, "Release status of the channel" }, + { pcpp::SmtpRequestLayer::SmtpCommand::XCIR, "Release status of the circuit checking facility" }, + { pcpp::SmtpRequestLayer::SmtpCommand::XSTA, "Release status of the number of messages in channel queues" }, + { pcpp::SmtpRequestLayer::SmtpCommand::XGEN, + "Release status of whether a compiled configuration and character set are in use" } + }; + + for (const auto& entry : possibleCommandCodes) { PTF_ASSERT_EQUAL(pcpp::SmtpRequestLayer::getCommandInfo(entry.first), entry.second); } // Status descriptions std::vector> possibleStatusCodes = { - {static_cast(0), "Unknown status code"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::SYSTEM_STATUS, "System status, or system help reply"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::HELP_MESSAGE, "Help message"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_READY, "Service ready"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_CLOSE, "Service closing transmission channel"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_SUCCESS, "Authentication successful"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::COMPLETED, "Requested mail action okay, completed"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::WILL_FORWARD, "User not local; will forward to "}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::CANNOT_VERIFY, - "Cannot VRFY user, but will accept message and attempt delivery"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_INPUT, "AUTH input"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::MAIL_INPUT, "Start mail input; end with ."}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_UNAVAILABLE, - "Service not available, closing transmission channel"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::PASS_NEEDED, "A password transition is needed"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::MAILBOX_UNAVAILABLE_TEMP, - "Requested mail action not taken: mailbox unavailable (mail busy or temporarily blocked)"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::ABORT_LOCAL_ERROR, - "Requested action aborted: local error in processing"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::INSUFFICIENT_STORAGE, - "Requested action not taken: insufficient system storage"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::TEMP_AUTH_FAILED, "Temporary authentication failed"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::PARAM_NOT_ACCOMMODATED, "Server unable to accommodate parameters"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::CMD_NOT_RECOGNIZED, "Syntax error, command unrecognized"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::SYNTAX_ERROR_PARAM, "Syntax error in parameters or arguments"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::CMD_NOT_IMPLEMENTED, "Command not implemented"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::CMD_BAD_SEQUENCE, "Bad sequence of commands"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::PARAM_NOT_IMPLEMENTED, "Command parameter not implemented"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::MAIL_NOT_ACCEPTED, "Server does not accept mail"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::ENCRYPT_NEED, "Encryption needed"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_REQUIRED, "Authentication required"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_TOO_WEAK, "Authentication mechanism is too weak"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_CRED_INVALID, "Authentication credentials invalid"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::ENCRYPT_REQUIRED, - "Encryption required for requested authentication mechanism"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::MAILBOX_UNAVAILABLE, - "Requested action not taken: mailbox unavailable"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::USER_NOT_LOCAL, "User not local; please try "}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::EXCEED_STORAGE, - "Requested mail action aborted: exceeded storage allocation"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::NAME_NOT_ALLOWED, - "Requested action not taken: mailbox name not allowed"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::TRANSACTION_FAIL, "Transaction failed"}, - {pcpp::SmtpResponseLayer::SmtpStatusCode::DOMAIN_NOT_ACCEPT, "Domain does not accept mail"}}; - - for (const auto &entry : possibleStatusCodes) + { static_cast(0), "Unknown status code" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::SYSTEM_STATUS, "System status, or system help reply" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::HELP_MESSAGE, "Help message" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_READY, "Service ready" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_CLOSE, "Service closing transmission channel" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_SUCCESS, "Authentication successful" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::COMPLETED, "Requested mail action okay, completed" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::WILL_FORWARD, "User not local; will forward to " }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::CANNOT_VERIFY, + "Cannot VRFY user, but will accept message and attempt delivery" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_INPUT, "AUTH input" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::MAIL_INPUT, "Start mail input; end with ." }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_UNAVAILABLE, + "Service not available, closing transmission channel" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::PASS_NEEDED, "A password transition is needed" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::MAILBOX_UNAVAILABLE_TEMP, + "Requested mail action not taken: mailbox unavailable (mail busy or temporarily blocked)" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::ABORT_LOCAL_ERROR, + "Requested action aborted: local error in processing" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::INSUFFICIENT_STORAGE, + "Requested action not taken: insufficient system storage" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::TEMP_AUTH_FAILED, "Temporary authentication failed" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::PARAM_NOT_ACCOMMODATED, "Server unable to accommodate parameters" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::CMD_NOT_RECOGNIZED, "Syntax error, command unrecognized" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::SYNTAX_ERROR_PARAM, "Syntax error in parameters or arguments" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::CMD_NOT_IMPLEMENTED, "Command not implemented" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::CMD_BAD_SEQUENCE, "Bad sequence of commands" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::PARAM_NOT_IMPLEMENTED, "Command parameter not implemented" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::MAIL_NOT_ACCEPTED, "Server does not accept mail" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::ENCRYPT_NEED, "Encryption needed" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_REQUIRED, "Authentication required" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_TOO_WEAK, "Authentication mechanism is too weak" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::AUTH_CRED_INVALID, "Authentication credentials invalid" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::ENCRYPT_REQUIRED, + "Encryption required for requested authentication mechanism" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::MAILBOX_UNAVAILABLE, + "Requested action not taken: mailbox unavailable" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::USER_NOT_LOCAL, "User not local; please try " }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::EXCEED_STORAGE, + "Requested mail action aborted: exceeded storage allocation" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::NAME_NOT_ALLOWED, + "Requested action not taken: mailbox name not allowed" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::TRANSACTION_FAIL, "Transaction failed" }, + { pcpp::SmtpResponseLayer::SmtpStatusCode::DOMAIN_NOT_ACCEPT, "Domain does not accept mail" } + }; + + for (const auto& entry : possibleStatusCodes) { PTF_ASSERT_EQUAL(pcpp::SmtpResponseLayer::getStatusCodeAsString(entry.first), entry.second); } @@ -222,9 +221,9 @@ PTF_TEST_CASE(SmtpCreationTests) pcpp::TcpLayer tcpLayer2(*smtpPacket2.getLayerOfType()); pcpp::SmtpResponseLayer smtpRespLayer1( - pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_READY, - "xc90.websitewelcome.com ESMTP Exim 4.69 #1 Mon, 05 Oct 2009 01:05:54 -0500 \r\n220-We do not authorize the " - "use of this system to transport unsolicited, \r\n220 and/or bulk e-mail."); + pcpp::SmtpResponseLayer::SmtpStatusCode::SERVICE_READY, + "xc90.websitewelcome.com ESMTP Exim 4.69 #1 Mon, 05 Oct 2009 01:05:54 -0500 \r\n220-We do not authorize the " + "use of this system to transport unsolicited, \r\n220 and/or bulk e-mail."); pcpp::Packet craftedPacket2; PTF_ASSERT_TRUE(craftedPacket2.addLayer(ðLayer2)); @@ -246,7 +245,7 @@ PTF_TEST_CASE(SmtpEditTests) READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/smtpCommandEdited.dat"); pcpp::Packet smtpPacket1(&rawPacket1); - auto *smtpLayer1 = smtpPacket1.getLayerOfType(); + auto* smtpLayer1 = smtpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(smtpLayer1); smtpLayer1->setCommand(pcpp::SmtpRequestLayer::SmtpCommand::EHLO); @@ -256,13 +255,13 @@ PTF_TEST_CASE(SmtpEditTests) pcpp::Packet smtpEditedPacket1(&rawPacket2); PTF_ASSERT_EQUAL(smtpPacket1.getRawPacket()->getRawDataLen(), smtpEditedPacket1.getRawPacket()->getRawDataLen()); PTF_ASSERT_BUF_COMPARE(smtpPacket1.getRawPacket()->getRawData(), smtpEditedPacket1.getRawPacket()->getRawData(), - smtpPacket1.getRawPacket()->getRawDataLen()); + smtpPacket1.getRawPacket()->getRawDataLen()); // Response multiline READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/smtpMultiLine.dat"); pcpp::Packet smtpPacket2(&rawPacket3); - auto *smtpLayer2 = smtpPacket2.getLayerOfType(); + auto* smtpLayer2 = smtpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(smtpLayer2); smtpLayer2->setStatusCode(pcpp::SmtpResponseLayer::SmtpStatusCode::ABORT_LOCAL_ERROR); smtpLayer2->setStatusOption("Test Option Line 1\r\n451 Test Option Line 2"); @@ -273,5 +272,5 @@ PTF_TEST_CASE(SmtpEditTests) PTF_ASSERT_EQUAL(smtpPacket2.getRawPacket()->getRawDataLen(), smtpEditedPacket2.getRawPacket()->getRawDataLen()); PTF_ASSERT_BUF_COMPARE(smtpPacket2.getRawPacket()->getRawData(), smtpEditedPacket2.getRawPacket()->getRawData(), - smtpPacket2.getRawPacket()->getRawDataLen()); + smtpPacket2.getRawPacket()->getRawDataLen()); } diff --git a/Tests/Packet++Test/Tests/SomeIpSdTests.cpp b/Tests/Packet++Test/Tests/SomeIpSdTests.cpp index 50254bbe18..8f7227d53c 100644 --- a/Tests/Packet++Test/Tests/SomeIpSdTests.cpp +++ b/Tests/Packet++Test/Tests/SomeIpSdTests.cpp @@ -62,7 +62,7 @@ PTF_TEST_CASE(SomeIpSdParsingTest) PTF_ASSERT_EQUAL((uint8_t)option->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv4Endpoint); PTF_ASSERT_EQUAL(option->getDataPtr()[1], 0x09); - pcpp::SomeIpSdIPv4Option* ipv4Option = (pcpp::SomeIpSdIPv4Option*) option; + pcpp::SomeIpSdIPv4Option* ipv4Option = (pcpp::SomeIpSdIPv4Option*)option; PTF_ASSERT_EQUAL(ipv4Option->getIpAddress(), pcpp::IPv4Address("160.48.199.28")); PTF_ASSERT_EQUAL(ipv4Option->getProtocol(), pcpp::SomeIpSdProtocolType::SD_UDP); PTF_ASSERT_EQUAL(ipv4Option->getPort(), 30502); @@ -110,19 +110,21 @@ PTF_TEST_CASE(SomeIpSdParsingTest) PTF_ASSERT_EQUAL((uint8_t)option2_1->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv6Endpoint); PTF_ASSERT_EQUAL(option2_1->getDataPtr()[1], 0x15); - pcpp::SomeIpSdIPv6Option* ipv6Option2_1 = (pcpp::SomeIpSdIPv6Option*) option2_1; + pcpp::SomeIpSdIPv6Option* ipv6Option2_1 = (pcpp::SomeIpSdIPv6Option*)option2_1; PTF_ASSERT_EQUAL(ipv6Option2_1->getIpAddress(), pcpp::IPv6Address("fd53:7cb8:383:4::1:1e5")); PTF_ASSERT_EQUAL(ipv6Option2_1->getProtocol(), pcpp::SomeIpSdProtocolType::SD_TCP); PTF_ASSERT_EQUAL(ipv6Option2_1->getPort(), 29769); - pcpp::SomeIpSdOption* option2_2 = *(options2.begin()+1); + pcpp::SomeIpSdOption* option2_2 = *(options2.begin() + 1); PTF_ASSERT_EQUAL(option2_2->getLength(), 93); PTF_ASSERT_EQUAL((uint8_t)option2_2->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::ConfigurationString); PTF_ASSERT_EQUAL(option2_2->getDataPtr()[5], 0x63); - pcpp::SomeIpSdConfigurationOption* configurationOption = (pcpp::SomeIpSdConfigurationOption*) option2_2; - for(int i = 0; i < 89; i++){ - PTF_ASSERT_EQUAL(configurationOption->getConfigurationString()[i], someIpSdPacket2.getRawPacket()->getRawData()[138+i]); + pcpp::SomeIpSdConfigurationOption* configurationOption = (pcpp::SomeIpSdConfigurationOption*)option2_2; + for (int i = 0; i < 89; i++) + { + PTF_ASSERT_EQUAL(configurationOption->getConfigurationString()[i], + someIpSdPacket2.getRawPacket()->getRawData()[138 + i]); } pcpp::SomeIpSdLayer::OptionsVec options2Entry0 = someIpSdLayer2->getOptionsFromEntry(0); @@ -133,9 +135,10 @@ PTF_TEST_CASE(SomeIpSdParsingTest) PTF_ASSERT_EQUAL((uint8_t)options2Entry0_1->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::IPv6Endpoint); PTF_ASSERT_EQUAL(options2Entry0_1->getDataPtr()[1], 0x15); - pcpp::SomeIpSdOption* options2Entry0_2 = *(options2Entry0.begin()+1); + pcpp::SomeIpSdOption* options2Entry0_2 = *(options2Entry0.begin() + 1); PTF_ASSERT_EQUAL(options2Entry0_2->getLength(), 93); - PTF_ASSERT_EQUAL((uint8_t)options2Entry0_2->getType(), (uint8_t)pcpp::SomeIpSdOption::OptionType::ConfigurationString); + PTF_ASSERT_EQUAL((uint8_t)options2Entry0_2->getType(), + (uint8_t)pcpp::SomeIpSdOption::OptionType::ConfigurationString); PTF_ASSERT_EQUAL(options2Entry0_2->getDataPtr()[5], 0x63); pcpp::SomeIpSdLayer::OptionsVec options2Entry1 = someIpSdLayer2->getOptionsFromEntry(1); @@ -177,7 +180,7 @@ PTF_TEST_CASE(SomeIpSdParsingTest) PTF_ASSERT_EQUAL(entry3_1->getEventgroupId(), 1); PTF_ASSERT_EQUAL(entry3_1->getDataPtr()[0], 0x06); - pcpp::SomeIpSdEntry* entry3_2 = *(entries3.begin()+1); + pcpp::SomeIpSdEntry* entry3_2 = *(entries3.begin() + 1); PTF_ASSERT_EQUAL(entry3_2->getLength(), 16); PTF_ASSERT_EQUAL(entry3_2->getNumOptions(), 1); PTF_ASSERT_EQUAL((uint8_t)entry3_2->getType(), (uint8_t)pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup); @@ -228,8 +231,11 @@ PTF_TEST_CASE(SomeIpSdCreationTest) // OfferService (Entry: OfferService, Option: IPv4Endpoint) pcpp::SomeIpSdLayer someIpSdLayer(0xffff, 0x8100, 0, 0x2, 0x1, pcpp::SomeIpLayer::MsgType::NOTIFICATION, 0, 0xc0); - auto pEntry = std::unique_ptr(new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::OfferService, 0xd05f, 2, 1, 3, 0)); - auto pOption = std::unique_ptr(new pcpp::SomeIpSdIPv4Option(pcpp::SomeIpSdIPv4Option::IPv4OptionType::IPv4Endpoint, pcpp::IPv4Address("160.48.199.28"), 30502, pcpp::SomeIpSdProtocolType::SD_UDP)); + auto pEntry = std::unique_ptr( + new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::OfferService, 0xd05f, 2, 1, 3, 0)); + auto pOption = std::unique_ptr( + new pcpp::SomeIpSdIPv4Option(pcpp::SomeIpSdIPv4Option::IPv4OptionType::IPv4Endpoint, + pcpp::IPv4Address("160.48.199.28"), 30502, pcpp::SomeIpSdProtocolType::SD_UDP)); auto offsetEntry = someIpSdLayer.addEntry(*pEntry); someIpSdLayer.addOptionTo(offsetEntry, *pOption); @@ -237,14 +243,18 @@ PTF_TEST_CASE(SomeIpSdCreationTest) PTF_ASSERT_TRUE(someIpSdPacket.addLayer(&someIpSdLayer)); someIpSdPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(someIpSdPacket.getRawPacket()->getRawDataLen(), bufferLength1-46); - PTF_ASSERT_BUF_COMPARE(someIpSdPacket.getRawPacket()->getRawData(), buffer1+46, bufferLength1-46); + PTF_ASSERT_EQUAL(someIpSdPacket.getRawPacket()->getRawDataLen(), bufferLength1 - 46); + PTF_ASSERT_BUF_COMPARE(someIpSdPacket.getRawPacket()->getRawData(), buffer1 + 46, bufferLength1 - 46); // Subscribe (Entry: 2xSubscribeEventgroup, Option: IPv4Endpoint) pcpp::SomeIpSdLayer someIpSdLayer2(0xffff, 0x8100, 0, 0x3, 0x1, pcpp::SomeIpLayer::MsgType::NOTIFICATION, 0, 0xc0); - auto pEntry2_1 = std::unique_ptr(new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup, 0xd063, 1, 1, 3, 0, 1)); - auto pEntry2_2 = std::unique_ptr(new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup, 0xd066, 1, 1, 3, 0, 1)); - auto pOption2 = std::unique_ptr(new pcpp::SomeIpSdIPv4Option(pcpp::SomeIpSdIPv4Option::IPv4OptionType::IPv4Endpoint, pcpp::IPv4Address("160.48.199.101"), 58358, pcpp::SomeIpSdProtocolType::SD_UDP)); + auto pEntry2_1 = std::unique_ptr( + new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup, 0xd063, 1, 1, 3, 0, 1)); + auto pEntry2_2 = std::unique_ptr( + new pcpp::SomeIpSdEntry(pcpp::SomeIpSdEntry::EntryType::SubscribeEventgroup, 0xd066, 1, 1, 3, 0, 1)); + auto pOption2 = std::unique_ptr( + new pcpp::SomeIpSdIPv4Option(pcpp::SomeIpSdIPv4Option::IPv4OptionType::IPv4Endpoint, + pcpp::IPv4Address("160.48.199.101"), 58358, pcpp::SomeIpSdProtocolType::SD_UDP)); auto offsetEntry2_1 = someIpSdLayer2.addEntry(*pEntry2_1); someIpSdLayer2.addOptionTo(offsetEntry2_1, *pOption2); auto offsetEntry2_2 = someIpSdLayer2.addEntry(*pEntry2_2); @@ -254,9 +264,9 @@ PTF_TEST_CASE(SomeIpSdCreationTest) PTF_ASSERT_TRUE(someIpSdPacket2.addLayer(&someIpSdLayer2)); someIpSdPacket2.computeCalculateFields(); - PTF_ASSERT_EQUAL(someIpSdPacket2.getRawPacket()->getRawDataLen(), bufferLength2-46); - PTF_ASSERT_BUF_COMPARE(someIpSdPacket2.getRawPacket()->getRawData(), buffer2+46, bufferLength2-46); + PTF_ASSERT_EQUAL(someIpSdPacket2.getRawPacket()->getRawDataLen(), bufferLength2 - 46); + PTF_ASSERT_BUF_COMPARE(someIpSdPacket2.getRawPacket()->getRawData(), buffer2 + 46, bufferLength2 - 46); - delete [] buffer1; - delete [] buffer2; + delete[] buffer1; + delete[] buffer2; } diff --git a/Tests/Packet++Test/Tests/SomeIpTests.cpp b/Tests/Packet++Test/Tests/SomeIpTests.cpp index 53433ab158..216b9b34b0 100644 --- a/Tests/Packet++Test/Tests/SomeIpTests.cpp +++ b/Tests/Packet++Test/Tests/SomeIpTests.cpp @@ -14,8 +14,12 @@ class SomeIpTeardown { public: - SomeIpTeardown() {} - ~SomeIpTeardown() { pcpp::SomeIpLayer::removeAllSomeIpPorts(); } + SomeIpTeardown() + {} + ~SomeIpTeardown() + { + pcpp::SomeIpLayer::removeAllSomeIpPorts(); + } }; PTF_TEST_CASE(SomeIpPortTest) @@ -55,7 +59,7 @@ PTF_TEST_CASE(SomeIpParsingTest) // Test with one SOME/IP layer PTF_ASSERT_TRUE(someIpPacket.isPacketOfType(pcpp::SomeIP)); - pcpp::SomeIpLayer *someIpLayer = someIpPacket.getLayerOfType(); + pcpp::SomeIpLayer* someIpLayer = someIpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(someIpLayer); PTF_ASSERT_EQUAL(someIpLayer->getHeaderLen(), 38); PTF_ASSERT_EQUAL(someIpLayer->getMessageID(), 0x6059410c); @@ -77,7 +81,7 @@ PTF_TEST_CASE(SomeIpParsingTest) PTF_ASSERT_NULL(someIpLayer->getNextLayer()); // Test with two SOME/IP layers - pcpp::SomeIpLayer *someIpLayer2_1 = someIpPacket2.getLayerOfType(); + pcpp::SomeIpLayer* someIpLayer2_1 = someIpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(someIpLayer2_1); PTF_ASSERT_EQUAL(someIpLayer2_1->getHeaderLen(), 38); PTF_ASSERT_EQUAL(someIpLayer2_1->getMessageID(), 0x6059410c); @@ -98,7 +102,7 @@ PTF_TEST_CASE(SomeIpParsingTest) PTF_ASSERT_EQUAL(someIpLayer2_1->toString(), "SOME/IP Layer, Service ID: 0x6059, Method ID: 0x410c, Length: 30"); PTF_ASSERT_NOT_NULL(someIpLayer2_1->getNextLayer()); - pcpp::SomeIpLayer *someIpLayer2_2 = someIpPacket2.getNextLayerOfType(someIpLayer2_1); + pcpp::SomeIpLayer* someIpLayer2_2 = someIpPacket2.getNextLayerOfType(someIpLayer2_1); PTF_ASSERT_NOT_NULL(someIpLayer2_2); PTF_ASSERT_EQUAL(someIpLayer2_2->getHeaderLen(), 36); PTF_ASSERT_EQUAL(someIpLayer2_2->getMessageID(), 0x6060410d); @@ -128,28 +132,33 @@ PTF_TEST_CASE(SomeIpCreationTest) READ_FILE_INTO_BUFFER(1, "PacketExamples/someip.dat"); READ_FILE_INTO_BUFFER(2, "PacketExamples/someip2.dat"); - std::array data1{0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00}; + std::array data1{ 0x40, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00 }; - std::array data2{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; + std::array data2{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14 }; // Test with one SOME/IP layer - pcpp::SomeIpLayer someipLayer1(0x6059, 0x410c, 0x3, 0xa, 0x5, pcpp::SomeIpLayer::MsgType::REQUEST, 0, data1.data(), data1.size()); + pcpp::SomeIpLayer someipLayer1(0x6059, 0x410c, 0x3, 0xa, 0x5, pcpp::SomeIpLayer::MsgType::REQUEST, 0, data1.data(), + data1.size()); pcpp::Packet someIpPacket(100); PTF_ASSERT_TRUE(someIpPacket.addLayer(&someipLayer1)); someIpPacket.computeCalculateFields(); - PTF_ASSERT_EQUAL(someIpPacket.getRawPacket()->getRawDataLen(), bufferLength1-78); - PTF_ASSERT_BUF_COMPARE(someIpPacket.getRawPacket()->getRawData(), buffer1+78, bufferLength1-78); + PTF_ASSERT_EQUAL(someIpPacket.getRawPacket()->getRawDataLen(), bufferLength1 - 78); + PTF_ASSERT_BUF_COMPARE(someIpPacket.getRawPacket()->getRawData(), buffer1 + 78, bufferLength1 - 78); // Test with two SOME/IP layers - pcpp::EthLayer ethLayer2(pcpp::MacAddress("02:7d:fa:01:17:40"), pcpp::MacAddress("02:7d:fa:00:10:01"), PCPP_ETHERTYPE_VLAN); + pcpp::EthLayer ethLayer2(pcpp::MacAddress("02:7d:fa:01:17:40"), pcpp::MacAddress("02:7d:fa:00:10:01"), + PCPP_ETHERTYPE_VLAN); pcpp::VlanLayer vlanLayer2(2, false, 0, PCPP_ETHERTYPE_IP); - pcpp::IPv6Layer ip6Layer2(pcpp::IPv6Address("fd53:7cb8:0383:0002::0001:0117"), pcpp::IPv6Address("fd53:7cb8:0383:000e::0014")); + pcpp::IPv6Layer ip6Layer2(pcpp::IPv6Address("fd53:7cb8:0383:0002::0001:0117"), + pcpp::IPv6Address("fd53:7cb8:0383:000e::0014")); pcpp::UdpLayer udpLayer2(29300, 29180); - pcpp::SomeIpLayer someipLayer2_1(0x6059, 0x410c, 0x3, 0xa, 0x5, pcpp::SomeIpLayer::MsgType::REQUEST, 0, data1.data(), data1.size()); - pcpp::SomeIpLayer someipLayer2_2(0x6060, 0x410d, 0x4, 0xb, 0x6, pcpp::SomeIpLayer::MsgType::REQUEST, 0, data2.data(), data2.size()); + pcpp::SomeIpLayer someipLayer2_1(0x6059, 0x410c, 0x3, 0xa, 0x5, pcpp::SomeIpLayer::MsgType::REQUEST, 0, + data1.data(), data1.size()); + pcpp::SomeIpLayer someipLayer2_2(0x6060, 0x410d, 0x4, 0xb, 0x6, pcpp::SomeIpLayer::MsgType::REQUEST, 0, + data2.data(), data2.size()); pcpp::Packet someIpPacket2(100); PTF_ASSERT_TRUE(someIpPacket2.addLayer(ðLayer2)); @@ -163,8 +172,8 @@ PTF_TEST_CASE(SomeIpCreationTest) PTF_ASSERT_EQUAL(someIpPacket2.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(someIpPacket2.getRawPacket()->getRawData(), buffer2, bufferLength2); - delete [] buffer1; - delete [] buffer2; + delete[] buffer1; + delete[] buffer2; } PTF_TEST_CASE(SomeIpTpParsingTest) @@ -184,7 +193,7 @@ PTF_TEST_CASE(SomeIpTpParsingTest) // Test SOME/IP-TP start packet PTF_ASSERT_TRUE(someIpTpPacket1.isPacketOfType(pcpp::SomeIP)); - pcpp::SomeIpTpLayer *someIpTpLayer1 = someIpTpPacket1.getLayerOfType(); + pcpp::SomeIpTpLayer* someIpTpLayer1 = someIpTpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(someIpTpLayer1); PTF_ASSERT_EQUAL(someIpTpLayer1->getHeaderLen(), 1412); PTF_ASSERT_EQUAL(someIpTpLayer1->getMessageID(), 0xd05f8001); @@ -204,11 +213,12 @@ PTF_TEST_CASE(SomeIpTpParsingTest) PTF_ASSERT_EQUAL(someIpTpLayer1->getPduPayloadSize(), 1392); PTF_ASSERT_EQUAL(someIpTpLayer1->getPduPayload()[0], 0x12); PTF_ASSERT_EQUAL(someIpTpLayer1->getPduPayload()[1391], 0x34); - PTF_ASSERT_EQUAL(someIpTpLayer1->toString(), "SOME/IP-TP Layer, Service ID: 0xd05f, Method ID: 0x8001, Length: 1404"); + PTF_ASSERT_EQUAL(someIpTpLayer1->toString(), + "SOME/IP-TP Layer, Service ID: 0xd05f, Method ID: 0x8001, Length: 1404"); // Test SOME/IP-TP end packet PTF_ASSERT_TRUE(someIpTpPacket2.isPacketOfType(pcpp::SomeIP)); - pcpp::SomeIpTpLayer *someIpTpLayer2 = someIpTpPacket2.getLayerOfType(); + pcpp::SomeIpTpLayer* someIpTpLayer2 = someIpTpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(someIpTpLayer2); PTF_ASSERT_EQUAL(someIpTpLayer2->getHeaderLen(), 245); PTF_ASSERT_EQUAL(someIpTpLayer2->getMessageID(), 0xd05f8001); @@ -228,7 +238,8 @@ PTF_TEST_CASE(SomeIpTpParsingTest) PTF_ASSERT_EQUAL(someIpTpLayer2->getPduPayloadSize(), 225); PTF_ASSERT_EQUAL(someIpTpLayer2->getPduPayload()[0], 0xab); PTF_ASSERT_EQUAL(someIpTpLayer2->getPduPayload()[224], 0xcd); - PTF_ASSERT_EQUAL(someIpTpLayer2->toString(), "SOME/IP-TP Layer, Service ID: 0xd05f, Method ID: 0x8001, Length: 237"); + PTF_ASSERT_EQUAL(someIpTpLayer2->toString(), + "SOME/IP-TP Layer, Service ID: 0xd05f, Method ID: 0x8001, Length: 237"); } PTF_TEST_CASE(SomeIpTpCreationTest) @@ -240,23 +251,24 @@ PTF_TEST_CASE(SomeIpTpCreationTest) READ_FILE_INTO_BUFFER(2, "PacketExamples/SomeIpTp2.dat"); const size_t dataLen1 = 1392; - uint8_t data1[dataLen1] = {0}; + uint8_t data1[dataLen1] = { 0 }; data1[0] = 0x12; - data1[dataLen1-1] = 0x34; + data1[dataLen1 - 1] = 0x34; const size_t dataLen2 = 225; - uint8_t data2[dataLen2] = {0}; + uint8_t data2[dataLen2] = { 0 }; data2[0] = 0xab; - data2[dataLen2-1] = 0xcd; + data2[dataLen2 - 1] = 0xcd; - pcpp::EthLayer ethLayer1(pcpp::MacAddress("02:7d:fa:01:17:40"), pcpp::MacAddress("02:7d:fa:00:10:01"), PCPP_ETHERTYPE_IP); + pcpp::EthLayer ethLayer1(pcpp::MacAddress("02:7d:fa:01:17:40"), pcpp::MacAddress("02:7d:fa:00:10:01"), + PCPP_ETHERTYPE_IP); pcpp::IPv4Layer ipLayer1(pcpp::IPv4Address("192.168.0.1"), pcpp::IPv4Address("192.168.0.2")); ipLayer1.getIPv4Header()->timeToLive = 20; pcpp::UdpLayer udpLayer1(30502, 16832); // Test SOME/IP-TP start packet pcpp::SomeIpTpLayer someIpTpLayer1(0xd05f, 0x8001, 0, 0, 1, pcpp::SomeIpLayer::MsgType::REQUEST_NO_RETURN, 0, 0, - true, data1, dataLen1); + true, data1, dataLen1); pcpp::Packet someIpTpPacket1(500); PTF_ASSERT_TRUE(someIpTpPacket1.addLayer(ðLayer1)); @@ -273,7 +285,7 @@ PTF_TEST_CASE(SomeIpTpCreationTest) pcpp::IPv4Layer ipLayer2(ipLayer1); pcpp::UdpLayer udpLayer2(udpLayer1); pcpp::SomeIpTpLayer someIpTpLayer2(0xd05f, 0x8001, 0, 0, 1, pcpp::SomeIpLayer::MsgType::REQUEST_NO_RETURN, 0, - 91872 / 16, false, data2, dataLen2); + 91872 / 16, false, data2, dataLen2); pcpp::Packet someIpTpPacket2(500); PTF_ASSERT_TRUE(someIpTpPacket2.addLayer(ðLayer2)); @@ -285,17 +297,17 @@ PTF_TEST_CASE(SomeIpTpCreationTest) PTF_ASSERT_EQUAL(someIpTpPacket2.getRawPacket()->getRawDataLen(), bufferLength2); PTF_ASSERT_BUF_COMPARE(someIpTpPacket2.getRawPacket()->getRawData(), buffer2, bufferLength2); - delete [] buffer1; - delete [] buffer2; + delete[] buffer1; + delete[] buffer2; } PTF_TEST_CASE(SomeIpTpEditTest) { const size_t dataLen2 = 225; - uint8_t data2[dataLen2] = {0}; + uint8_t data2[dataLen2] = { 0 }; pcpp::SomeIpTpLayer someIpTpLayer(0x6059, 0x410c, 0x3, 0xa, 0x5, pcpp::SomeIpLayer::MsgType::REQUEST, 0, 91872 / 16, - true, data2, dataLen2); + true, data2, dataLen2); someIpTpLayer.setOffset(123); PTF_ASSERT_EQUAL(someIpTpLayer.getOffset(), 123); diff --git a/Tests/Packet++Test/Tests/StpTests.cpp b/Tests/Packet++Test/Tests/StpTests.cpp index aa281c3efd..409d9c43f0 100644 --- a/Tests/Packet++Test/Tests/StpTests.cpp +++ b/Tests/Packet++Test/Tests/StpTests.cpp @@ -16,7 +16,7 @@ PTF_TEST_CASE(StpConfigurationParsingTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::StpConfigurationBPDULayer *stpConfLayer = stpPacket.getLayerOfType(); + pcpp::StpConfigurationBPDULayer* stpConfLayer = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpConfLayer); PTF_ASSERT_NOT_NULL(stpConfLayer->getNextLayer()); @@ -41,8 +41,7 @@ PTF_TEST_CASE(StpConfigurationParsingTests) PTF_ASSERT_EQUAL(stpConfLayer->getForwardDelay(), 15); PTF_ASSERT_EQUAL(stpConfLayer->toString(), "Spanning Tree Configuration"); -} // StpConfigurationParsingTests - +} // StpConfigurationParsingTests PTF_TEST_CASE(StpConfigurationCreationTests) { @@ -54,7 +53,7 @@ PTF_TEST_CASE(StpConfigurationCreationTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::StpConfigurationBPDULayer *stpConfLayerTgt = stpPacket.getLayerOfType(); + pcpp::StpConfigurationBPDULayer* stpConfLayerTgt = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpConfLayerTgt); pcpp::StpConfigurationBPDULayer stpConfLayer; @@ -73,8 +72,7 @@ PTF_TEST_CASE(StpConfigurationCreationTests) stpConfLayer.setForwardDelay(15); PTF_ASSERT_BUF_COMPARE(stpConfLayer.getData(), stpConfLayerTgt->getData(), stpConfLayer.getHeaderLen()); -} // StpConfigurationCreationTests - +} // StpConfigurationCreationTests PTF_TEST_CASE(StpConfigurationEditTests) { @@ -86,7 +84,7 @@ PTF_TEST_CASE(StpConfigurationEditTests) pcpp::Packet stpPacket1(&rawPacket1); PTF_ASSERT_TRUE(stpPacket1.isPacketOfType(pcpp::STP)); - pcpp::StpConfigurationBPDULayer *stpConfLayerOrig = stpPacket1.getLayerOfType(); + pcpp::StpConfigurationBPDULayer* stpConfLayerOrig = stpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpConfLayerOrig); // Read target packet @@ -94,7 +92,7 @@ PTF_TEST_CASE(StpConfigurationEditTests) pcpp::Packet stpPacket2(&rawPacket2); PTF_ASSERT_TRUE(stpPacket2.isPacketOfType(pcpp::STP)); - pcpp::StpConfigurationBPDULayer *stpConfLayerTgt1 = stpPacket2.getLayerOfType(); + pcpp::StpConfigurationBPDULayer* stpConfLayerTgt1 = stpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpConfLayerTgt1); // Set fields @@ -114,7 +112,7 @@ PTF_TEST_CASE(StpConfigurationEditTests) pcpp::Packet stpPacket3(&rawPacket3); PTF_ASSERT_TRUE(stpPacket3.isPacketOfType(pcpp::STP)); - pcpp::StpConfigurationBPDULayer *stpConfLayerTgt2 = stpPacket3.getLayerOfType(); + pcpp::StpConfigurationBPDULayer* stpConfLayerTgt2 = stpPacket3.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpConfLayerTgt2); // Set fields @@ -127,8 +125,7 @@ PTF_TEST_CASE(StpConfigurationEditTests) stpConfLayerOrig->setBridgeSystemID("FF:EE:DD:CC:BB:AA"); PTF_ASSERT_BUF_COMPARE(stpConfLayerOrig->getData(), stpConfLayerTgt2->getData(), stpConfLayerOrig->getHeaderLen()); -} // StpConfigurationEditTests - +} // StpConfigurationEditTests PTF_TEST_CASE(StpTopologyChangeParsingTests) { @@ -140,7 +137,7 @@ PTF_TEST_CASE(StpTopologyChangeParsingTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::StpTopologyChangeBPDULayer *stpTopologyLayer = stpPacket.getLayerOfType(); + pcpp::StpTopologyChangeBPDULayer* stpTopologyLayer = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpTopologyLayer); PTF_ASSERT_NOT_NULL(stpTopologyLayer->getNextLayer()); @@ -150,8 +147,7 @@ PTF_TEST_CASE(StpTopologyChangeParsingTests) PTF_ASSERT_EQUAL(stpTopologyLayer->getType(), 0x80); PTF_ASSERT_EQUAL(stpTopologyLayer->toString(), "Spanning Tree Topology Change Notification"); -} // StpTopologyChangeParsingTests - +} // StpTopologyChangeParsingTests PTF_TEST_CASE(StpTopologyChangeCreationTests) { @@ -163,14 +159,14 @@ PTF_TEST_CASE(StpTopologyChangeCreationTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::StpTopologyChangeBPDULayer *stpTopologyLayerTgt = stpPacket.getLayerOfType(); + pcpp::StpTopologyChangeBPDULayer* stpTopologyLayerTgt = + stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpTopologyLayerTgt); pcpp::StpTopologyChangeBPDULayer stpTopologyLayer; PTF_ASSERT_BUF_COMPARE(stpTopologyLayer.getData(), stpTopologyLayerTgt->getData(), stpTopologyLayer.getHeaderLen()); -} // StpTopologyChangeCreationTests - +} // StpTopologyChangeCreationTests PTF_TEST_CASE(StpTopologyChangeEditTests) { @@ -182,7 +178,8 @@ PTF_TEST_CASE(StpTopologyChangeEditTests) pcpp::Packet stpPacket1(&rawPacket1); PTF_ASSERT_TRUE(stpPacket1.isPacketOfType(pcpp::STP)); - pcpp::StpTopologyChangeBPDULayer *stpTopologyLayerOrig = stpPacket1.getLayerOfType(); + pcpp::StpTopologyChangeBPDULayer* stpTopologyLayerOrig = + stpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpTopologyLayerOrig); // Read target packet @@ -190,16 +187,17 @@ PTF_TEST_CASE(StpTopologyChangeEditTests) pcpp::Packet stpPacket2(&rawPacket2); PTF_ASSERT_TRUE(stpPacket2.isPacketOfType(pcpp::STP)); - pcpp::StpTopologyChangeBPDULayer *stpTopologyLayerTgt = stpPacket2.getLayerOfType(); + pcpp::StpTopologyChangeBPDULayer* stpTopologyLayerTgt = + stpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpTopologyLayerTgt); // Set fields stpTopologyLayerOrig->setProtoId(0xaa); stpTopologyLayerOrig->setVersion(0x13); - PTF_ASSERT_BUF_COMPARE(stpTopologyLayerOrig->getData(), stpTopologyLayerTgt->getData(), stpTopologyLayerOrig->getHeaderLen()); -} // StpTopologyChangeEditTests - + PTF_ASSERT_BUF_COMPARE(stpTopologyLayerOrig->getData(), stpTopologyLayerTgt->getData(), + stpTopologyLayerOrig->getHeaderLen()); +} // StpTopologyChangeEditTests PTF_TEST_CASE(RapidStpParsingTests) { @@ -211,7 +209,7 @@ PTF_TEST_CASE(RapidStpParsingTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::RapidStpLayer *stpRapidLayer = stpPacket.getLayerOfType(); + pcpp::RapidStpLayer* stpRapidLayer = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpRapidLayer); PTF_ASSERT_NULL(stpRapidLayer->getNextLayer()); @@ -237,8 +235,7 @@ PTF_TEST_CASE(RapidStpParsingTests) PTF_ASSERT_EQUAL(stpRapidLayer->getVersion1Len(), 0); PTF_ASSERT_EQUAL(stpRapidLayer->toString(), "Rapid Spanning Tree"); -} // RapidStpParsingTests - +} // RapidStpParsingTests PTF_TEST_CASE(RapidStpCreationTests) { @@ -250,7 +247,7 @@ PTF_TEST_CASE(RapidStpCreationTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::RapidStpLayer *stpRapidLayerTgt = stpPacket.getLayerOfType(); + pcpp::RapidStpLayer* stpRapidLayerTgt = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpRapidLayerTgt); pcpp::RapidStpLayer stpRapidLayer; @@ -270,8 +267,7 @@ PTF_TEST_CASE(RapidStpCreationTests) stpRapidLayer.setVersion1Len(0); PTF_ASSERT_BUF_COMPARE(stpRapidLayer.getData(), stpRapidLayerTgt->getData(), stpRapidLayer.getHeaderLen()); -} // RapidStpCreationTests - +} // RapidStpCreationTests PTF_TEST_CASE(RapidStpEditTests) { @@ -282,7 +278,7 @@ PTF_TEST_CASE(RapidStpEditTests) pcpp::Packet stpPacket1(&rawPacket1); PTF_ASSERT_TRUE(stpPacket1.isPacketOfType(pcpp::STP)); - pcpp::RapidStpLayer *stpRapidLayerOrig = stpPacket1.getLayerOfType(); + pcpp::RapidStpLayer* stpRapidLayerOrig = stpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpRapidLayerOrig); // Read target packet @@ -290,7 +286,7 @@ PTF_TEST_CASE(RapidStpEditTests) pcpp::Packet stpPacket2(&rawPacket2); PTF_ASSERT_TRUE(stpPacket2.isPacketOfType(pcpp::STP)); - pcpp::RapidStpLayer *stpRapidLayerTgt = stpPacket2.getLayerOfType(); + pcpp::RapidStpLayer* stpRapidLayerTgt = stpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpRapidLayerTgt); // Set fields @@ -302,8 +298,7 @@ PTF_TEST_CASE(RapidStpEditTests) stpRapidLayerOrig->setVersion1Len(2); PTF_ASSERT_BUF_COMPARE(stpRapidLayerOrig->getData(), stpRapidLayerTgt->getData(), stpRapidLayerTgt->getHeaderLen()); -} // RapidStpEditTests - +} // RapidStpEditTests PTF_TEST_CASE(MultipleStpParsingTests) { @@ -315,7 +310,7 @@ PTF_TEST_CASE(MultipleStpParsingTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::MultipleStpLayer *stpMultipleLayer = stpPacket.getLayerOfType(); + pcpp::MultipleStpLayer* stpMultipleLayer = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpMultipleLayer); PTF_ASSERT_NULL(stpMultipleLayer->getNextLayer()); @@ -353,7 +348,7 @@ PTF_TEST_CASE(MultipleStpParsingTests) PTF_ASSERT_EQUAL(stpMultipleLayer->getNumberOfMSTIConfMessages(), 1); - pcpp::msti_conf_msg *ptrExtension = stpMultipleLayer->getMstiConfMessages(); + pcpp::msti_conf_msg* ptrExtension = stpMultipleLayer->getMstiConfMessages(); PTF_ASSERT_NOT_NULL(ptrExtension); PTF_ASSERT_EQUAL(ptrExtension->flags, 0x7c); @@ -364,8 +359,7 @@ PTF_TEST_CASE(MultipleStpParsingTests) PTF_ASSERT_EQUAL(ptrExtension->remainingHops, 19); PTF_ASSERT_EQUAL(stpMultipleLayer->toString(), "Multiple Spanning Tree"); -} // MultipleStpParsingTests - +} // MultipleStpParsingTests PTF_TEST_CASE(MultipleStpCreationTests) { @@ -377,7 +371,7 @@ PTF_TEST_CASE(MultipleStpCreationTests) pcpp::Packet stpPacket(&rawPacket1); PTF_ASSERT_TRUE(stpPacket.isPacketOfType(pcpp::STP)); - pcpp::MultipleStpLayer *stpMultipleLayerTgt = stpPacket.getLayerOfType(); + pcpp::MultipleStpLayer* stpMultipleLayerTgt = stpPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpMultipleLayerTgt); pcpp::MultipleStpLayer stpMultipleLayer; @@ -406,8 +400,7 @@ PTF_TEST_CASE(MultipleStpCreationTests) PTF_ASSERT_EQUAL(stpMultipleLayer.getDataLen(), stpMultipleLayerTgt->getDataLen()); PTF_ASSERT_BUF_COMPARE(stpMultipleLayer.getData(), stpMultipleLayerTgt->getData(), stpMultipleLayer.getDataLen()); -} // MultipleStpParsingTests - +} // MultipleStpParsingTests PTF_TEST_CASE(MultipleStpEditTests) { @@ -423,10 +416,10 @@ PTF_TEST_CASE(MultipleStpEditTests) pcpp::Packet stpPacket2(&rawPacket2); PTF_ASSERT_TRUE(stpPacket2.isPacketOfType(pcpp::STP)); - pcpp::RapidStpLayer *stpMultipleLayerTgt = stpPacket2.getLayerOfType(); + pcpp::RapidStpLayer* stpMultipleLayerTgt = stpPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpMultipleLayerTgt); - pcpp::MultipleStpLayer *stpMultipleLayerOrig = stpPacket1.getLayerOfType(); + pcpp::MultipleStpLayer* stpMultipleLayerOrig = stpPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpMultipleLayerOrig); // Set fields @@ -440,13 +433,15 @@ PTF_TEST_CASE(MultipleStpEditTests) stpMultipleLayerOrig->setRemainingHopCount(17); PTF_ASSERT_EQUAL(stpMultipleLayerOrig->getDataLen(), stpMultipleLayerTgt->getDataLen()); - PTF_ASSERT_BUF_COMPARE(stpMultipleLayerOrig->getData(), stpMultipleLayerTgt->getData(), stpMultipleLayerTgt->getDataLen()); + PTF_ASSERT_BUF_COMPARE(stpMultipleLayerOrig->getData(), stpMultipleLayerTgt->getData(), + stpMultipleLayerTgt->getDataLen()); READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/StpMultipleEdit2.dat"); pcpp::Packet stpPacket3(&rawPacket3); PTF_ASSERT_TRUE(stpPacket3.isPacketOfType(pcpp::STP)); - pcpp::StpConfigurationBPDULayer *stpMultipleLayerTgt2 = stpPacket3.getLayerOfType(); + pcpp::StpConfigurationBPDULayer* stpMultipleLayerTgt2 = + stpPacket3.getLayerOfType(); PTF_ASSERT_NOT_NULL(stpMultipleLayerTgt2); stpMultipleLayerOrig->setCISTBridgePriority(24576); @@ -454,5 +449,6 @@ PTF_TEST_CASE(MultipleStpEditTests) stpMultipleLayerOrig->setCISTBridgeSystemID("FF:EE:DD:CC:BB:AA"); PTF_ASSERT_EQUAL(stpMultipleLayerOrig->getDataLen(), stpMultipleLayerTgt2->getDataLen()); - PTF_ASSERT_BUF_COMPARE(stpMultipleLayerOrig->getData(), stpMultipleLayerTgt2->getData(), stpMultipleLayerTgt2->getDataLen()); -} // MultipleStpEditTests + PTF_ASSERT_BUF_COMPARE(stpMultipleLayerOrig->getData(), stpMultipleLayerTgt2->getData(), + stpMultipleLayerTgt2->getDataLen()); +} // MultipleStpEditTests diff --git a/Tests/Packet++Test/Tests/TcpTests.cpp b/Tests/Packet++Test/Tests/TcpTests.cpp index f50e28cd12..d95029268a 100644 --- a/Tests/Packet++Test/Tests/TcpTests.cpp +++ b/Tests/Packet++Test/Tests/TcpTests.cpp @@ -14,7 +14,6 @@ DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED - PTF_TEST_CASE(TcpPacketNoOptionsParsing) { timeval time; @@ -51,10 +50,10 @@ PTF_TEST_CASE(TcpPacketNoOptionsParsing) // TCP options PTF_ASSERT_EQUAL(tcpLayer->getTcpOptionCount(), 0); - //TODO: remove deprecated + // TODO: remove deprecated PTF_ASSERT_TRUE(tcpLayer->getTcpOption(pcpp::PCPP_TCPOPT_NOP).isNull()); PTF_ASSERT_TRUE(tcpLayer->getTcpOption(pcpp::PCPP_TCPOPT_TIMESTAMP).isNull()); - //end deprecated + // end deprecated PTF_ASSERT_TRUE(tcpLayer->getTcpOption(pcpp::TcpOptionEnumType::Nop).isNull()); PTF_ASSERT_TRUE(tcpLayer->getTcpOption(pcpp::TcpOptionEnumType::Timestamp).isNull()); @@ -62,9 +61,7 @@ PTF_TEST_CASE(TcpPacketNoOptionsParsing) pcpp::Layer* afterTcpLayer = tcpLayer->getNextLayer(); PTF_ASSERT_NOT_NULL(afterTcpLayer); PTF_ASSERT_EQUAL(afterTcpLayer->getProtocol(), pcpp::HTTPResponse, enum); -} // TcpPacketNoOptionsParsing - - +} // TcpPacketNoOptionsParsing PTF_TEST_CASE(TcpPacketWithOptionsParsing) { @@ -90,7 +87,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing) // TCP options PTF_ASSERT_EQUAL(tcpLayer->getTcpOptionCount(), 3); - //TODO: remove deprecated + // TODO: remove deprecated PTF_ASSERT_TRUE(!tcpLayer->getTcpOption(pcpp::PCPP_TCPOPT_NOP).isNull()); pcpp::TcpOption timestampOptionData = tcpLayer->getTcpOption(pcpp::PCPP_TCPOPT_TIMESTAMP); PTF_ASSERT_TRUE(!timestampOptionData.isNull()); @@ -99,7 +96,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing) uint32_t tsEchoReply = timestampOptionData.getValueAs(4); PTF_ASSERT_EQUAL(tsValue, htobe32(195102)); PTF_ASSERT_EQUAL(tsEchoReply, htobe32(3555729271UL)); - //end deprecated + // end deprecated PTF_ASSERT_TRUE(!tcpLayer->getTcpOption(pcpp::TcpOptionEnumType::Nop).isNull()); pcpp::TcpOption timestampOptionData2 = tcpLayer->getTcpOption(pcpp::TcpOptionEnumType::Timestamp); @@ -109,7 +106,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing) uint32_t tsEchoReply2 = timestampOptionData2.getValueAs(4); PTF_ASSERT_EQUAL(tsValue2, htobe32(195102)); PTF_ASSERT_EQUAL(tsEchoReply2, htobe32(3555729271UL)); -} // TcpPacketWithOptionsParsing +} // TcpPacketWithOptionsParsing PTF_TEST_CASE(TcpPacketWithOptionsParsing2) { @@ -125,7 +122,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing2) PTF_ASSERT_EQUAL(tcpLayer->getTcpOptionCount(), 5); - //TODO: remove deprecated + // TODO: remove deprecated pcpp::TcpOption mssOption = tcpLayer->getTcpOption(pcpp::TCPOPT_MSS); pcpp::TcpOption sackPermOption = tcpLayer->getTcpOption(pcpp::TCPOPT_SACK_PERM); pcpp::TcpOption windowScaleOption = tcpLayer->getTcpOption(pcpp::PCPP_TCPOPT_WINDOW); @@ -146,7 +143,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing2) PTF_ASSERT_EQUAL(sackPermOption.getValueAs(), 0); PTF_ASSERT_EQUAL(mssOption.getValueAs(), 0); PTF_ASSERT_EQUAL(mssOption.getValueAs(1), 0); - //end deprecated + // end deprecated pcpp::TcpOption mssOption2 = tcpLayer->getTcpOption(pcpp::TcpOptionEnumType::Mss); pcpp::TcpOption sackPermOption2 = tcpLayer->getTcpOption(pcpp::TcpOptionEnumType::SackPerm); @@ -169,7 +166,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing2) PTF_ASSERT_EQUAL(mssOption2.getValueAs(), 0); PTF_ASSERT_EQUAL(mssOption2.getValueAs(1), 0); - //TODO: remove deprecated + // TODO: remove deprecated pcpp::TcpOption curOpt = tcpLayer->getFirstTcpOption(); PTF_ASSERT_TRUE(curOpt.isNotNull() && curOpt.getTcpOptionType() == pcpp::TCPOPT_MSS); curOpt = tcpLayer->getNextTcpOption(curOpt); @@ -180,7 +177,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing2) PTF_ASSERT_TRUE(curOpt.isNotNull() && curOpt.getTcpOptionType() == pcpp::PCPP_TCPOPT_NOP); curOpt = tcpLayer->getNextTcpOption(curOpt); PTF_ASSERT_TRUE(curOpt.isNotNull() && curOpt.getTcpOptionType() == pcpp::PCPP_TCPOPT_WINDOW); - //end deprecated + // end deprecated curOpt = tcpLayer->getFirstTcpOption(); PTF_ASSERT_TRUE(curOpt.isNotNull() && curOpt.getTcpOptionEnumType() == pcpp::TcpOptionEnumType::Mss); @@ -194,9 +191,7 @@ PTF_TEST_CASE(TcpPacketWithOptionsParsing2) PTF_ASSERT_TRUE(curOpt.isNotNull() && curOpt.getTcpOptionEnumType() == pcpp::TcpOptionEnumType::Window); curOpt = tcpLayer->getNextTcpOption(curOpt); PTF_ASSERT_TRUE(curOpt.isNull()); -} // TcpPacketWithOptionsParsing2 - - +} // TcpPacketWithOptionsParsing2 PTF_TEST_CASE(TcpMalformedPacketParsing) { @@ -209,7 +204,7 @@ PTF_TEST_CASE(TcpMalformedPacketParsing) PTF_ASSERT_NOT_NULL(badTcpPacket.getLayerOfType()); PTF_ASSERT_NULL(badTcpPacket.getLayerOfType()); -} // TcpMalformedPacketParsing +} // TcpMalformedPacketParsing PTF_TEST_CASE(TcpPacketCreation) { @@ -232,11 +227,16 @@ PTF_TEST_CASE(TcpPacketCreation) PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 24); PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NOP)).isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 24); - PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::PCPP_TCPOPT_TIMESTAMP, nullptr, PCPP_TCPOLEN_TIMESTAMP-2)).isNotNull()); + PTF_ASSERT_TRUE( + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::PCPP_TCPOPT_TIMESTAMP, nullptr, PCPP_TCPOLEN_TIMESTAMP - 2)) + .isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 32); - PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop)).isNotNull()); - PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionEnumType::Window, nullptr, PCPP_TCPOLEN_WINDOW-2)).isNotNull()); + PTF_ASSERT_TRUE( + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop)).isNotNull()); + PTF_ASSERT_TRUE( + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionEnumType::Window, nullptr, PCPP_TCPOLEN_WINDOW - 2)) + .isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 36); PTF_ASSERT_EQUAL(tcpLayer.getTcpOptionCount(), 5); @@ -269,10 +269,8 @@ PTF_TEST_CASE(TcpPacketCreation) PTF_ASSERT_BUF_COMPARE(tcpPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - delete [] buffer1; -} // TcpPacketCreation - - + delete[] buffer1; +} // TcpPacketCreation PTF_TEST_CASE(TcpPacketCreation2) { @@ -297,17 +295,21 @@ PTF_TEST_CASE(TcpPacketCreation2) PTF_ASSERT_TRUE(tcpLayer.addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TCPOPT_MSS, (uint16_t)1460)).isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 28); - pcpp::TcpOption tsOption = tcpLayer.addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::PCPP_TCPOPT_TIMESTAMP, nullptr, PCPP_TCPOLEN_TIMESTAMP-2), pcpp::TCPOPT_MSS); + pcpp::TcpOption tsOption = tcpLayer.addTcpOptionAfter( + pcpp::TcpOptionBuilder(pcpp::PCPP_TCPOPT_TIMESTAMP, nullptr, PCPP_TCPOLEN_TIMESTAMP - 2), pcpp::TCPOPT_MSS); PTF_ASSERT_TRUE(tsOption.isNotNull()); tsOption.setValue(htobe32(197364)); tsOption.setValue(0, 4); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 36); - pcpp::TcpOption winScaleOption = tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::PCPP_TCPOPT_WINDOW, (uint8_t)4)); + pcpp::TcpOption winScaleOption = + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::PCPP_TCPOPT_WINDOW, (uint8_t)4)); PTF_ASSERT_TRUE(winScaleOption.isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 40); - PTF_ASSERT_TRUE(tcpLayer.addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TCPOPT_SACK_PERM, nullptr, 0), pcpp::TCPOPT_MSS).isNotNull()); + PTF_ASSERT_TRUE( + tcpLayer.addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TCPOPT_SACK_PERM, nullptr, 0), pcpp::TCPOPT_MSS) + .isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 40); PTF_ASSERT_EQUAL(tcpLayer.getTcpOptionCount(), 5); @@ -325,11 +327,18 @@ PTF_TEST_CASE(TcpPacketCreation2) PTF_ASSERT_BUF_COMPARE(tcpPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - pcpp::TcpOption qsOption = tcpLayer.addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TCPOPT_QS, nullptr, PCPP_TCPOLEN_QS), pcpp::TCPOPT_MSS); + pcpp::TcpOption qsOption = + tcpLayer.addTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TCPOPT_QS, nullptr, PCPP_TCPOLEN_QS), pcpp::TCPOPT_MSS); PTF_ASSERT_TRUE(qsOption.isNotNull()); PTF_ASSERT_TRUE(qsOption.setValue(htobe32(9999))); - PTF_ASSERT_TRUE(tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionEnumType::Snack, static_cast(htobe32(1000)))).isNotNull()); - PTF_ASSERT_TRUE(tcpLayer.insertTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop), pcpp::TcpOptionEnumType::Timestamp).isNotNull()); + PTF_ASSERT_TRUE( + tcpLayer + .addTcpOption(pcpp::TcpOptionBuilder(pcpp::TcpOptionEnumType::Snack, static_cast(htobe32(1000)))) + .isNotNull()); + PTF_ASSERT_TRUE(tcpLayer + .insertTcpOptionAfter(pcpp::TcpOptionBuilder(pcpp::TcpOptionBuilder::NopEolOptionEnumType::Nop), + pcpp::TcpOptionEnumType::Timestamp) + .isNotNull()); PTF_ASSERT_EQUAL(tcpLayer.getTcpOptionCount(), 8); @@ -341,7 +350,7 @@ PTF_TEST_CASE(TcpPacketCreation2) PTF_ASSERT_BUF_COMPARE(tcpPacket.getRawPacket()->getRawData(), buffer1, bufferLength1); - delete [] buffer1; + delete[] buffer1; PTF_ASSERT_TRUE(tcpLayer.removeAllTcpOptions()); PTF_ASSERT_EQUAL(tcpLayer.getTcpOptionCount(), 0); @@ -349,14 +358,15 @@ PTF_TEST_CASE(TcpPacketCreation2) PTF_ASSERT_EQUAL(tcpLayer.getHeaderLen(), 20); PTF_ASSERT_TRUE(tcpLayer.getTcpOption(pcpp::PCPP_TCPOPT_TIMESTAMP).isNull()); - pcpp::TcpOption tcpSnackOption = tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TCPOPT_SNACK, nullptr, PCPP_TCPOLEN_SNACK)); + pcpp::TcpOption tcpSnackOption = + tcpLayer.addTcpOption(pcpp::TcpOptionBuilder(pcpp::TCPOPT_SNACK, nullptr, PCPP_TCPOLEN_SNACK)); PTF_ASSERT_TRUE(tcpSnackOption.isNotNull()); PTF_ASSERT_TRUE(tcpSnackOption.setValue(htobe32(1000))); -} // TcpPacketCreation2 +} // TcpPacketCreation2 PTF_TEST_CASE(TcpChecksumInvalidRead) { - uint8_t *m = new uint8_t[3]; + uint8_t* m = new uint8_t[3]; m[0] = 0x01; m[1] = 0x12; m[2] = 0xF3; @@ -368,15 +378,15 @@ PTF_TEST_CASE(TcpChecksumInvalidRead) uint16_t c = pcpp::computeChecksum(vec, 1); PTF_ASSERT_EQUAL(c, 0xbedU); - delete [] m; -} // TcpChecksumInvalidRead + delete[] m; +} // TcpChecksumInvalidRead PTF_TEST_CASE(TcpChecksumMultiBuffer) { // Taken from https://en.wikipedia.org/wiki/IPv4_header_checksum#Calculating_the_IPv4_header_checksum - uint16_t m[4] = {0x4500, 0x0073, 0x0000, 0x4000}; - uint16_t n[3] = {0x4011, 0xc0a8, 0x0001}; - uint16_t o[2] = {0xc0a8, 0x00c7}; + uint16_t m[4] = { 0x4500, 0x0073, 0x0000, 0x4000 }; + uint16_t n[3] = { 0x4011, 0xc0a8, 0x0001 }; + uint16_t o[2] = { 0xc0a8, 0x00c7 }; uint16_t checksum_expected = 0xb861; pcpp::ScalarBuffer vec[4]; @@ -396,5 +406,5 @@ PTF_TEST_CASE(TcpChecksumMultiBuffer) // Adding the checksum should be equal to 0x0 c = pcpp::computeChecksum(vec, 4); PTF_ASSERT_EQUAL(c, 0); -} // TcpChecksumInvalidRead +} // TcpChecksumInvalidRead DISABLE_WARNING_POP diff --git a/Tests/Packet++Test/Tests/TelnetTests.cpp b/Tests/Packet++Test/Tests/TelnetTests.cpp index 58b95fe24e..b60f16a6ba 100644 --- a/Tests/Packet++Test/Tests/TelnetTests.cpp +++ b/Tests/Packet++Test/Tests/TelnetTests.cpp @@ -17,7 +17,7 @@ PTF_TEST_CASE(TelnetCommandParsingTests) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/telnetCommand.dat"); pcpp::Packet telnetPacket(&rawPacket1); - pcpp::TelnetLayer *telnetLayer = telnetPacket.getLayerOfType(); + pcpp::TelnetLayer* telnetLayer = telnetPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(telnetLayer); @@ -31,38 +31,35 @@ PTF_TEST_CASE(TelnetCommandParsingTests) PTF_ASSERT_EQUAL(telnetLayer->getFirstCommand(), pcpp::TelnetLayer::TelnetCommand::WillPerform, enumclass); PTF_ASSERT_EQUAL(telnetLayer->getOption(pcpp::TelnetLayer::TelnetCommand::WillPerform), - pcpp::TelnetLayer::TelnetOption::SuppressGoAhead, enumclass); + pcpp::TelnetLayer::TelnetOption::SuppressGoAhead, enumclass); PTF_ASSERT_EQUAL(telnetLayer->getOption(pcpp::TelnetLayer::TelnetCommand::DoPerform), - pcpp::TelnetLayer::TelnetOption::TerminalType, enumclass); + pcpp::TelnetLayer::TelnetOption::TerminalType, enumclass); PTF_ASSERT_EQUAL(telnetLayer->getOption(pcpp::TelnetLayer::TelnetCommand::AreYouThere), - pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, enumclass); + pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, enumclass); // Check iteration std::vector vCommand = { - pcpp::TelnetLayer::TelnetCommand::WillPerform, - pcpp::TelnetLayer::TelnetCommand::DoPerform, - pcpp::TelnetLayer::TelnetCommand::DoPerform, - pcpp::TelnetLayer::TelnetCommand::DoPerform, - pcpp::TelnetLayer::TelnetCommand::DoPerform, - pcpp::TelnetLayer::TelnetCommand::DoPerform, - pcpp::TelnetLayer::TelnetCommand::Subnegotiation, - pcpp::TelnetLayer::TelnetCommand::SubnegotiationEnd}; - - std::vector vOptions = { - pcpp::TelnetLayer::TelnetOption::SuppressGoAhead, - pcpp::TelnetLayer::TelnetOption::TerminalType, - pcpp::TelnetLayer::TelnetOption::NegotiateAboutWindowSize, - pcpp::TelnetLayer::TelnetOption::TerminalSpeed, - pcpp::TelnetLayer::TelnetOption::RemoteFlowControl, - pcpp::TelnetLayer::TelnetOption::Linemode, - pcpp::TelnetLayer::TelnetOption::Linemode, - pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption}; - - std::vector vCommandString = {"Will Perform", "Do Perform", "Do Perform", "Do Perform", - "Do Perform", "Do Perform", "Subnegotiation", "Subnegotiation End"}; + pcpp::TelnetLayer::TelnetCommand::WillPerform, pcpp::TelnetLayer::TelnetCommand::DoPerform, + pcpp::TelnetLayer::TelnetCommand::DoPerform, pcpp::TelnetLayer::TelnetCommand::DoPerform, + pcpp::TelnetLayer::TelnetCommand::DoPerform, pcpp::TelnetLayer::TelnetCommand::DoPerform, + pcpp::TelnetLayer::TelnetCommand::Subnegotiation, pcpp::TelnetLayer::TelnetCommand::SubnegotiationEnd + }; + + std::vector vOptions = { pcpp::TelnetLayer::TelnetOption::SuppressGoAhead, + pcpp::TelnetLayer::TelnetOption::TerminalType, + pcpp::TelnetLayer::TelnetOption::NegotiateAboutWindowSize, + pcpp::TelnetLayer::TelnetOption::TerminalSpeed, + pcpp::TelnetLayer::TelnetOption::RemoteFlowControl, + pcpp::TelnetLayer::TelnetOption::Linemode, + pcpp::TelnetLayer::TelnetOption::Linemode, + pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption }; + + std::vector vCommandString = { "Will Perform", "Do Perform", "Do Perform", "Do Perform", + "Do Perform", "Do Perform", "Subnegotiation", "Subnegotiation End" }; std::vector vOptionString = { "Suppress Go Ahead", "Terminal Type", "Negotiate About Window Size", "Terminal Speed", "Remote Flow Control", - "Line mode", "Line mode", "No option for this command"}; + "Line mode", "Line mode", "No option for this command" + }; size_t ctr = 0; size_t length = 0; @@ -100,7 +97,7 @@ PTF_TEST_CASE(TelnetCommandParsingTests) READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/telnetTN3270.dat"); pcpp::Packet telnetPacket2(&rawPacket2); - pcpp::TelnetLayer *telnetLayer2 = telnetPacket2.getLayerOfType(); + pcpp::TelnetLayer* telnetLayer2 = telnetPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(telnetLayer2); @@ -108,15 +105,13 @@ PTF_TEST_CASE(TelnetCommandParsingTests) PTF_ASSERT_EQUAL(telnetLayer2->getDataAsString(), "@"); PTF_ASSERT_EQUAL(telnetLayer2->getTotalNumberOfCommands(), 3); - std::vector vCommand2 = { - pcpp::TelnetLayer::TelnetCommand::DoPerform, - pcpp::TelnetLayer::TelnetCommand::WillPerform, - pcpp::TelnetLayer::TelnetCommand::EndOfRecordCommand}; + std::vector vCommand2 = { pcpp::TelnetLayer::TelnetCommand::DoPerform, + pcpp::TelnetLayer::TelnetCommand::WillPerform, + pcpp::TelnetLayer::TelnetCommand::EndOfRecordCommand }; - std::vector vOptions2 = { - pcpp::TelnetLayer::TelnetOption::TransmitBinary, - pcpp::TelnetLayer::TelnetOption::TransmitBinary, - pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption}; + std::vector vOptions2 = { pcpp::TelnetLayer::TelnetOption::TransmitBinary, + pcpp::TelnetLayer::TelnetOption::TransmitBinary, + pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption }; size_t ctr2 = 0; size_t length2 = 0; @@ -140,117 +135,119 @@ PTF_TEST_CASE(TelnetCommandParsingTests) READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/telnetCommandWithData.dat"); pcpp::Packet telnetPacket3(&rawPacket3); - pcpp::TelnetLayer *telnetLayer3 = telnetPacket3.getLayerOfType(); + pcpp::TelnetLayer* telnetLayer3 = telnetPacket3.getLayerOfType(); PTF_ASSERT_NOT_NULL(telnetLayer3); PTF_ASSERT_EQUAL(telnetLayer3->getDataAsString(), - "Telnet server could not log you in using NTLM authentication.Your password may have " - "expired.Login using username and passwordWelcome to Microsoft Telnet Service login: "); + "Telnet server could not log you in using NTLM authentication.Your password may have " + "expired.Login using username and passwordWelcome to Microsoft Telnet Service login: "); PTF_ASSERT_EQUAL(telnetLayer3->getTotalNumberOfCommands(), 2); PTF_ASSERT_EQUAL(telnetLayer3->getNumberOfCommands(pcpp::TelnetLayer::TelnetCommand::Subnegotiation), 1); PTF_ASSERT_EQUAL(telnetLayer3->getNumberOfCommands(pcpp::TelnetLayer::TelnetCommand::SubnegotiationEnd), 1); PTF_ASSERT_EQUAL(telnetLayer3->getOption(pcpp::TelnetLayer::TelnetCommand::Subnegotiation), - pcpp::TelnetLayer::TelnetOption::AuthenticationOption, enumclass); + pcpp::TelnetLayer::TelnetOption::AuthenticationOption, enumclass); PTF_ASSERT_EQUAL(telnetLayer3->getOption(pcpp::TelnetLayer::TelnetCommand::SubnegotiationEnd), - pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, enumclass); + pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, enumclass); PTF_ASSERT_EQUAL(telnetLayer3->toString(), "Telnet Control"); // Commands std::vector> possibleCommands = { - {static_cast(0), "Unknown Command"}, - {pcpp::TelnetLayer::TelnetCommand::TelnetCommandEndOfPacket, "Reached end of packet while parsing"}, - {pcpp::TelnetLayer::TelnetCommand::EndOfFile, "End of File"}, - {pcpp::TelnetLayer::TelnetCommand::Suspend, "Suspend current process"}, - {pcpp::TelnetLayer::TelnetCommand::Abort, "Abort Process"}, - {pcpp::TelnetLayer::TelnetCommand::EndOfRecordCommand, "End of Record"}, - {pcpp::TelnetLayer::TelnetCommand::SubnegotiationEnd, "Subnegotiation End"}, - {pcpp::TelnetLayer::TelnetCommand::NoOperation, "No Operation"}, - {pcpp::TelnetLayer::TelnetCommand::DataMark, "Data Mark"}, - {pcpp::TelnetLayer::TelnetCommand::Break, "Break"}, - {pcpp::TelnetLayer::TelnetCommand::InterruptProcess, "Interrupt Process"}, - {pcpp::TelnetLayer::TelnetCommand::AbortOutput, "Abort Output"}, - {pcpp::TelnetLayer::TelnetCommand::AreYouThere, "Are You There"}, - {pcpp::TelnetLayer::TelnetCommand::EraseCharacter, "Erase Character"}, - {pcpp::TelnetLayer::TelnetCommand::EraseLine, "Erase Line"}, - {pcpp::TelnetLayer::TelnetCommand::GoAhead, "Go Ahead"}, - {pcpp::TelnetLayer::TelnetCommand::Subnegotiation, "Subnegotiation"}, - {pcpp::TelnetLayer::TelnetCommand::WillPerform, "Will Perform"}, - {pcpp::TelnetLayer::TelnetCommand::WontPerform, "Wont Perform"}, - {pcpp::TelnetLayer::TelnetCommand::DoPerform, "Do Perform"}, - {pcpp::TelnetLayer::TelnetCommand::DontPerform, "Dont Perform"}, - {pcpp::TelnetLayer::TelnetCommand::InterpretAsCommand, "Interpret As Command"}}; - - for (const auto &entry : possibleCommands) + { static_cast(0), "Unknown Command" }, + { pcpp::TelnetLayer::TelnetCommand::TelnetCommandEndOfPacket, "Reached end of packet while parsing" }, + { pcpp::TelnetLayer::TelnetCommand::EndOfFile, "End of File" }, + { pcpp::TelnetLayer::TelnetCommand::Suspend, "Suspend current process" }, + { pcpp::TelnetLayer::TelnetCommand::Abort, "Abort Process" }, + { pcpp::TelnetLayer::TelnetCommand::EndOfRecordCommand, "End of Record" }, + { pcpp::TelnetLayer::TelnetCommand::SubnegotiationEnd, "Subnegotiation End" }, + { pcpp::TelnetLayer::TelnetCommand::NoOperation, "No Operation" }, + { pcpp::TelnetLayer::TelnetCommand::DataMark, "Data Mark" }, + { pcpp::TelnetLayer::TelnetCommand::Break, "Break" }, + { pcpp::TelnetLayer::TelnetCommand::InterruptProcess, "Interrupt Process" }, + { pcpp::TelnetLayer::TelnetCommand::AbortOutput, "Abort Output" }, + { pcpp::TelnetLayer::TelnetCommand::AreYouThere, "Are You There" }, + { pcpp::TelnetLayer::TelnetCommand::EraseCharacter, "Erase Character" }, + { pcpp::TelnetLayer::TelnetCommand::EraseLine, "Erase Line" }, + { pcpp::TelnetLayer::TelnetCommand::GoAhead, "Go Ahead" }, + { pcpp::TelnetLayer::TelnetCommand::Subnegotiation, "Subnegotiation" }, + { pcpp::TelnetLayer::TelnetCommand::WillPerform, "Will Perform" }, + { pcpp::TelnetLayer::TelnetCommand::WontPerform, "Wont Perform" }, + { pcpp::TelnetLayer::TelnetCommand::DoPerform, "Do Perform" }, + { pcpp::TelnetLayer::TelnetCommand::DontPerform, "Dont Perform" }, + { pcpp::TelnetLayer::TelnetCommand::InterpretAsCommand, "Interpret As Command" } + }; + + for (const auto& entry : possibleCommands) { PTF_ASSERT_EQUAL(pcpp::TelnetLayer::getTelnetCommandAsString(entry.first), entry.second); } // Options std::vector> possibleOptions = { - {static_cast(-10), "Unknown Option"}, - {pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, "No option for this command"}, - {pcpp::TelnetLayer::TelnetOption::TransmitBinary, "Binary Transmission"}, - {pcpp::TelnetLayer::TelnetOption::Echo, "Echo"}, - {pcpp::TelnetLayer::TelnetOption::Reconnection, "Reconnection"}, - {pcpp::TelnetLayer::TelnetOption::SuppressGoAhead, "Suppress Go Ahead"}, - {pcpp::TelnetLayer::TelnetOption::ApproxMsgSizeNegotiation, "Negotiate approximate message size"}, - {pcpp::TelnetLayer::TelnetOption::Status, "Status"}, - {pcpp::TelnetLayer::TelnetOption::TimingMark, "Timing Mark"}, - {pcpp::TelnetLayer::TelnetOption::RemoteControlledTransAndEcho, "Remote Controlled Transmission and Echo"}, - {pcpp::TelnetLayer::TelnetOption::OutputLineWidth, "Output Line Width"}, - {pcpp::TelnetLayer::TelnetOption::OutputPageSize, "Output Page Size"}, - {pcpp::TelnetLayer::TelnetOption::OutputCarriageReturnDisposition, - "Negotiate About Output Carriage-Return Disposition"}, - {pcpp::TelnetLayer::TelnetOption::OutputHorizontalTabStops, "Negotiate About Output Horizontal Tabstops"}, - {pcpp::TelnetLayer::TelnetOption::OutputHorizontalTabDisposition, - "Negotiate About Output Horizontal Tab Disposition"}, - {pcpp::TelnetLayer::TelnetOption::OutputFormfeedDisposition, "Negotiate About Output Formfeed Disposition"}, - {pcpp::TelnetLayer::TelnetOption::OutputVerticalTabStops, "Negotiate About Vertical Tabstops"}, - {pcpp::TelnetLayer::TelnetOption::OutputVerticalTabDisposition, - "Negotiate About Output Vertcial Tab Disposition"}, - {pcpp::TelnetLayer::TelnetOption::OutputLinefeedDisposition, "Negotiate About Output Linefeed Disposition"}, - {pcpp::TelnetLayer::TelnetOption::ExtendedASCII, "Extended ASCII"}, - {pcpp::TelnetLayer::TelnetOption::Logout, "Logout"}, - {pcpp::TelnetLayer::TelnetOption::ByteMacro, "Byte Macro"}, - {pcpp::TelnetLayer::TelnetOption::DataEntryTerminal, "Data Entry Terminal"}, - {pcpp::TelnetLayer::TelnetOption::SUPDUP, "SUPDUP"}, - {pcpp::TelnetLayer::TelnetOption::SUPDUPOutput, "SUPDUP Output"}, - {pcpp::TelnetLayer::TelnetOption::SendLocation, "Send Location"}, - {pcpp::TelnetLayer::TelnetOption::TerminalType, "Terminal Type"}, - {pcpp::TelnetLayer::TelnetOption::EndOfRecordOption, "End Of Record"}, - {pcpp::TelnetLayer::TelnetOption::TACACSUserIdentification, "TACACS User Identification"}, - {pcpp::TelnetLayer::TelnetOption::OutputMarking, "Output Marking"}, - {pcpp::TelnetLayer::TelnetOption::TerminalLocationNumber, "Terminal Location Number"}, - {pcpp::TelnetLayer::TelnetOption::Telnet3270Regime, "Telnet 3270 Regime"}, - {pcpp::TelnetLayer::TelnetOption::X3Pad, "X3 Pad"}, - {pcpp::TelnetLayer::TelnetOption::NegotiateAboutWindowSize, "Negotiate About Window Size"}, - {pcpp::TelnetLayer::TelnetOption::TerminalSpeed, "Terminal Speed"}, - {pcpp::TelnetLayer::TelnetOption::RemoteFlowControl, "Remote Flow Control"}, - {pcpp::TelnetLayer::TelnetOption::Linemode, "Line mode"}, - {pcpp::TelnetLayer::TelnetOption::XDisplayLocation, "X Display Location"}, - {pcpp::TelnetLayer::TelnetOption::EnvironmentOption, "Environment Option"}, - {pcpp::TelnetLayer::TelnetOption::AuthenticationOption, "Authentication Option"}, - {pcpp::TelnetLayer::TelnetOption::EncryptionOption, "Encryption Option"}, - {pcpp::TelnetLayer::TelnetOption::NewEnvironmentOption, "New Environment Option"}, - {pcpp::TelnetLayer::TelnetOption::TN3270E, "TN3270E"}, - {pcpp::TelnetLayer::TelnetOption::XAuth, "X Server Authentication"}, - {pcpp::TelnetLayer::TelnetOption::Charset, "Charset"}, - {pcpp::TelnetLayer::TelnetOption::TelnetRemoteSerialPort, "Telnet Remote Serial Port"}, - {pcpp::TelnetLayer::TelnetOption::ComPortControlOption, "Com Port Control Option"}, - {pcpp::TelnetLayer::TelnetOption::TelnetSuppressLocalEcho, "Telnet Suppress Local Echo"}, - {pcpp::TelnetLayer::TelnetOption::TelnetStartTLS, "Telnet Start TLS"}, - {pcpp::TelnetLayer::TelnetOption::Kermit, "Kermit"}, - {pcpp::TelnetLayer::TelnetOption::SendURL, "Send URL"}, - {pcpp::TelnetLayer::TelnetOption::ForwardX, "Forward X Server"}, - {pcpp::TelnetLayer::TelnetOption::TelOptPragmaLogon, "Telnet Option Pragma Logon"}, - {pcpp::TelnetLayer::TelnetOption::TelOptSSPILogon, "Telnet Option SSPI Logon"}, - {pcpp::TelnetLayer::TelnetOption::TelOptPragmaHeartbeat, "Telnet Option Pragma Heartbeat"}, - {pcpp::TelnetLayer::TelnetOption::ExtendedOptions, "Extended option list"}}; - - for (const auto &entry : possibleOptions) + { static_cast(-10), "Unknown Option" }, + { pcpp::TelnetLayer::TelnetOption::TelnetOptionNoOption, "No option for this command" }, + { pcpp::TelnetLayer::TelnetOption::TransmitBinary, "Binary Transmission" }, + { pcpp::TelnetLayer::TelnetOption::Echo, "Echo" }, + { pcpp::TelnetLayer::TelnetOption::Reconnection, "Reconnection" }, + { pcpp::TelnetLayer::TelnetOption::SuppressGoAhead, "Suppress Go Ahead" }, + { pcpp::TelnetLayer::TelnetOption::ApproxMsgSizeNegotiation, "Negotiate approximate message size" }, + { pcpp::TelnetLayer::TelnetOption::Status, "Status" }, + { pcpp::TelnetLayer::TelnetOption::TimingMark, "Timing Mark" }, + { pcpp::TelnetLayer::TelnetOption::RemoteControlledTransAndEcho, "Remote Controlled Transmission and Echo" }, + { pcpp::TelnetLayer::TelnetOption::OutputLineWidth, "Output Line Width" }, + { pcpp::TelnetLayer::TelnetOption::OutputPageSize, "Output Page Size" }, + { pcpp::TelnetLayer::TelnetOption::OutputCarriageReturnDisposition, + "Negotiate About Output Carriage-Return Disposition" }, + { pcpp::TelnetLayer::TelnetOption::OutputHorizontalTabStops, "Negotiate About Output Horizontal Tabstops" }, + { pcpp::TelnetLayer::TelnetOption::OutputHorizontalTabDisposition, + "Negotiate About Output Horizontal Tab Disposition" }, + { pcpp::TelnetLayer::TelnetOption::OutputFormfeedDisposition, "Negotiate About Output Formfeed Disposition" }, + { pcpp::TelnetLayer::TelnetOption::OutputVerticalTabStops, "Negotiate About Vertical Tabstops" }, + { pcpp::TelnetLayer::TelnetOption::OutputVerticalTabDisposition, + "Negotiate About Output Vertcial Tab Disposition" }, + { pcpp::TelnetLayer::TelnetOption::OutputLinefeedDisposition, "Negotiate About Output Linefeed Disposition" }, + { pcpp::TelnetLayer::TelnetOption::ExtendedASCII, "Extended ASCII" }, + { pcpp::TelnetLayer::TelnetOption::Logout, "Logout" }, + { pcpp::TelnetLayer::TelnetOption::ByteMacro, "Byte Macro" }, + { pcpp::TelnetLayer::TelnetOption::DataEntryTerminal, "Data Entry Terminal" }, + { pcpp::TelnetLayer::TelnetOption::SUPDUP, "SUPDUP" }, + { pcpp::TelnetLayer::TelnetOption::SUPDUPOutput, "SUPDUP Output" }, + { pcpp::TelnetLayer::TelnetOption::SendLocation, "Send Location" }, + { pcpp::TelnetLayer::TelnetOption::TerminalType, "Terminal Type" }, + { pcpp::TelnetLayer::TelnetOption::EndOfRecordOption, "End Of Record" }, + { pcpp::TelnetLayer::TelnetOption::TACACSUserIdentification, "TACACS User Identification" }, + { pcpp::TelnetLayer::TelnetOption::OutputMarking, "Output Marking" }, + { pcpp::TelnetLayer::TelnetOption::TerminalLocationNumber, "Terminal Location Number" }, + { pcpp::TelnetLayer::TelnetOption::Telnet3270Regime, "Telnet 3270 Regime" }, + { pcpp::TelnetLayer::TelnetOption::X3Pad, "X3 Pad" }, + { pcpp::TelnetLayer::TelnetOption::NegotiateAboutWindowSize, "Negotiate About Window Size" }, + { pcpp::TelnetLayer::TelnetOption::TerminalSpeed, "Terminal Speed" }, + { pcpp::TelnetLayer::TelnetOption::RemoteFlowControl, "Remote Flow Control" }, + { pcpp::TelnetLayer::TelnetOption::Linemode, "Line mode" }, + { pcpp::TelnetLayer::TelnetOption::XDisplayLocation, "X Display Location" }, + { pcpp::TelnetLayer::TelnetOption::EnvironmentOption, "Environment Option" }, + { pcpp::TelnetLayer::TelnetOption::AuthenticationOption, "Authentication Option" }, + { pcpp::TelnetLayer::TelnetOption::EncryptionOption, "Encryption Option" }, + { pcpp::TelnetLayer::TelnetOption::NewEnvironmentOption, "New Environment Option" }, + { pcpp::TelnetLayer::TelnetOption::TN3270E, "TN3270E" }, + { pcpp::TelnetLayer::TelnetOption::XAuth, "X Server Authentication" }, + { pcpp::TelnetLayer::TelnetOption::Charset, "Charset" }, + { pcpp::TelnetLayer::TelnetOption::TelnetRemoteSerialPort, "Telnet Remote Serial Port" }, + { pcpp::TelnetLayer::TelnetOption::ComPortControlOption, "Com Port Control Option" }, + { pcpp::TelnetLayer::TelnetOption::TelnetSuppressLocalEcho, "Telnet Suppress Local Echo" }, + { pcpp::TelnetLayer::TelnetOption::TelnetStartTLS, "Telnet Start TLS" }, + { pcpp::TelnetLayer::TelnetOption::Kermit, "Kermit" }, + { pcpp::TelnetLayer::TelnetOption::SendURL, "Send URL" }, + { pcpp::TelnetLayer::TelnetOption::ForwardX, "Forward X Server" }, + { pcpp::TelnetLayer::TelnetOption::TelOptPragmaLogon, "Telnet Option Pragma Logon" }, + { pcpp::TelnetLayer::TelnetOption::TelOptSSPILogon, "Telnet Option SSPI Logon" }, + { pcpp::TelnetLayer::TelnetOption::TelOptPragmaHeartbeat, "Telnet Option Pragma Heartbeat" }, + { pcpp::TelnetLayer::TelnetOption::ExtendedOptions, "Extended option list" } + }; + + for (const auto& entry : possibleOptions) { PTF_ASSERT_EQUAL(pcpp::TelnetLayer::getTelnetOptionAsString(entry.first), entry.second); } @@ -265,7 +262,7 @@ PTF_TEST_CASE(TelnetDataParsingTests) READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/telnetData.dat"); pcpp::Packet telnetPacket(&rawPacket1); - pcpp::TelnetLayer *telnetLayer = telnetPacket.getLayerOfType(); + pcpp::TelnetLayer* telnetLayer = telnetPacket.getLayerOfType(); PTF_ASSERT_NOT_NULL(telnetLayer); diff --git a/Tests/Packet++Test/Tests/TpktTests.cpp b/Tests/Packet++Test/Tests/TpktTests.cpp index 45777ed6a5..ad80dbdeb0 100644 --- a/Tests/Packet++Test/Tests/TpktTests.cpp +++ b/Tests/Packet++Test/Tests/TpktTests.cpp @@ -35,4 +35,4 @@ PTF_TEST_CASE(TpktLayerTest) PTF_ASSERT_EQUAL(tpktLayerTest.getLength(), 602); PTF_ASSERT_EQUAL(tpktLayerTest.toString(), "TPKT Layer, version: 10, length: 602"); -} // TpktLayerTest +} // TpktLayerTest diff --git a/Tests/Packet++Test/Tests/VlanMplsTests.cpp b/Tests/Packet++Test/Tests/VlanMplsTests.cpp index 5a9b412bec..44ab437489 100644 --- a/Tests/Packet++Test/Tests/VlanMplsTests.cpp +++ b/Tests/Packet++Test/Tests/VlanMplsTests.cpp @@ -11,14 +11,13 @@ #include "UdpLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(VlanParseAndCreation) { - for(int vid = 0; vid < 4096 * 2; vid++) + for (int vid = 0; vid < 4096 * 2; vid++) { - for(int prio = 0; prio < 8 * 2; prio ++) + for (int prio = 0; prio < 8 * 2; prio++) { - for(int cfi = 0; cfi < 2 * 2; cfi++) //true or false + for (int cfi = 0; cfi < 2 * 2; cfi++) // true or false { pcpp::VlanLayer testVlanLayer(vid, cfi, prio, PCPP_ETHERTYPE_VLAN); PTF_ASSERT_EQUAL(testVlanLayer.getVlanID(), (vid & 0xFFF)); @@ -53,8 +52,9 @@ PTF_TEST_CASE(VlanParseAndCreation) pcpp::EthLayer ethLayer(macSrc, macDest); pcpp::VlanLayer firstVlanLayer(666, 1, 5); pcpp::VlanLayer secondVlanLayer(200, 0, 2, PCPP_ETHERTYPE_ARP); - pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST, macSrc, pcpp::MacAddress("00:00:00:00:00:00"), pcpp::IPv4Address("192.168.2.200"), pcpp::IPv4Address("192.168.2.254")); - pcpp::Packet arpWithVlanNew(1); + pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST, macSrc, pcpp::MacAddress("00:00:00:00:00:00"), + pcpp::IPv4Address("192.168.2.200"), pcpp::IPv4Address("192.168.2.254")); + pcpp::Packet arpWithVlanNew(1); PTF_ASSERT_TRUE(arpWithVlanNew.addLayer(ðLayer)); PTF_ASSERT_TRUE(arpWithVlanNew.addLayer(&firstVlanLayer)); PTF_ASSERT_TRUE(arpWithVlanNew.addLayer(&secondVlanLayer)); @@ -64,9 +64,7 @@ PTF_TEST_CASE(VlanParseAndCreation) PTF_ASSERT_EQUAL(arpWithVlanNew.getRawPacket()->getRawDataLen(), bufferLength1); PTF_ASSERT_BUF_COMPARE(arpWithVlanNew.getRawPacket()->getRawData(), buffer1, bufferLength1); -} // VlanParseAndCreation - - +} // VlanParseAndCreation PTF_TEST_CASE(QinQ802_1adParse) { @@ -88,9 +86,7 @@ PTF_TEST_CASE(QinQ802_1adParse) PTF_ASSERT_EQUAL(secondVlanLayerPtr->getPriority(), 0); PTF_ASSERT_NOT_NULL(secondVlanLayerPtr->getNextLayer()); PTF_ASSERT_EQUAL(secondVlanLayerPtr->getNextLayer()->getProtocol(), pcpp::IPv4, enum); -} // QinQ802_1adParse - - +} // QinQ802_1adParse PTF_TEST_CASE(MplsLayerTest) { @@ -138,7 +134,7 @@ PTF_TEST_CASE(MplsLayerTest) mplsLayer->setTTL(111); PTF_ASSERT_TRUE(mplsLayer->setMplsLabel(100000)); uint8_t expectedResult[4] = { 0x18, 0x6A, 0x0d, 0x6f }; - PTF_ASSERT_BUF_COMPARE(mplsLayer->getData(), expectedResult , 4); + PTF_ASSERT_BUF_COMPARE(mplsLayer->getData(), expectedResult, 4); PTF_ASSERT_EQUAL(mplsLayer->getTTL(), 111); PTF_ASSERT_EQUAL(mplsLayer->getMplsLabel(), 100000); PTF_ASSERT_EQUAL(mplsLayer->getExperimentalUseValue(), 6); @@ -146,7 +142,7 @@ PTF_TEST_CASE(MplsLayerTest) pcpp::MplsLayer mplsLayer2(0xdff0f, 20, 7, false); uint8_t expectedResult2[4] = { 0xdf, 0xf0, 0xfe, 0x14 }; - PTF_ASSERT_BUF_COMPARE(mplsLayer2.getData(), expectedResult2 , 4); + PTF_ASSERT_BUF_COMPARE(mplsLayer2.getData(), expectedResult2, 4); pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_FALSE(mplsLayer->setMplsLabel(0xFFFFFF)); @@ -173,9 +169,7 @@ PTF_TEST_CASE(MplsLayerTest) PTF_ASSERT_EQUAL(mplsLayer->getMplsLabel(), 18); PTF_ASSERT_EQUAL(mplsLayer->getExperimentalUseValue(), 0); PTF_ASSERT_TRUE(mplsLayer->isBottomOfStack()); -} // MplsLayerTest - - +} // MplsLayerTest PTF_TEST_CASE(VxlanParsingAndCreationTest) { @@ -209,7 +203,8 @@ PTF_TEST_CASE(VxlanParsingAndCreationTest) // verify edited fields PTF_ASSERT_EQUAL(vxlanPacket.getRawPacket()->getRawDataLen(), bufferLength2); - PTF_ASSERT_BUF_COMPARE(vxlanPacket.getRawPacket()->getRawData(), buffer2, vxlanPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(vxlanPacket.getRawPacket()->getRawData(), buffer2, + vxlanPacket.getRawPacket()->getRawDataLen()); // remove vxlan layer PTF_ASSERT_TRUE(vxlanPacket.removeLayer(pcpp::VXLAN)); @@ -221,7 +216,8 @@ PTF_TEST_CASE(VxlanParsingAndCreationTest) // verify new vxlan layer PTF_ASSERT_EQUAL(vxlanPacket.getRawPacket()->getRawDataLen(), bufferLength1); - PTF_ASSERT_BUF_COMPARE(vxlanPacket.getRawPacket()->getRawData(), buffer1, vxlanPacket.getRawPacket()->getRawDataLen()); + PTF_ASSERT_BUF_COMPARE(vxlanPacket.getRawPacket()->getRawData(), buffer1, + vxlanPacket.getRawPacket()->getRawDataLen()); - delete [] buffer2; -} // VxlanParsingAndCreationTest + delete[] buffer2; +} // VxlanParsingAndCreationTest diff --git a/Tests/Packet++Test/Tests/VrrpTest.cpp b/Tests/Packet++Test/Tests/VrrpTest.cpp old mode 100755 new mode 100644 index a30e39cafb..c38fadbd39 --- a/Tests/Packet++Test/Tests/VrrpTest.cpp +++ b/Tests/Packet++Test/Tests/VrrpTest.cpp @@ -11,14 +11,13 @@ #include "PayloadLayer.h" #include "SystemUtils.h" - PTF_TEST_CASE(VrrpParsingTest) { timeval time = {}; gettimeofday(&time, nullptr); PTF_ASSERT_EQUAL(pcpp::VrrpLayer::getVersionFromData(nullptr, 0), pcpp::UnknownProtocol); - uint8_t fakeBuffer[10] = {0xb4,0xaf,0x98,0x1a, 0xb4,0xaf,0x98,0x1a, 0x98,0x1a}; + uint8_t fakeBuffer[10] = { 0xb4, 0xaf, 0x98, 0x1a, 0xb4, 0xaf, 0x98, 0x1a, 0x98, 0x1a }; PTF_ASSERT_EQUAL(pcpp::VrrpLayer::getVersionFromData(fakeBuffer, 10), pcpp::UnknownProtocol); READ_FILE_AND_CREATE_PACKET(1, "PacketExamples/VRRP-V2.dat"); @@ -47,14 +46,11 @@ PTF_TEST_CASE(VrrpParsingTest) PTF_ASSERT_EQUAL(vrrpV2Layer->toString(), "VRRP v2 Layer, virtual router ID: 1, IP address count: 3") PTF_ASSERT_EQUAL(vrrpV2Layer->getIPAddressesCount(), 3) auto ipAddressVec = vrrpV2Layer->getIPAddresses(); - std::vector expectedIpAddressVec = { - pcpp::IPAddress("192.168.0.1"), - pcpp::IPAddress("192.168.0.2"), - pcpp::IPAddress("192.168.0.3") - }; + std::vector expectedIpAddressVec = { pcpp::IPAddress("192.168.0.1"), + pcpp::IPAddress("192.168.0.2"), + pcpp::IPAddress("192.168.0.3") }; PTF_ASSERT_TRUE(ipAddressVec == expectedIpAddressVec) - PTF_ASSERT_TRUE(vrrpv3IPv4Packet.isPacketOfType(pcpp::VRRP)) PTF_ASSERT_FALSE(vrrpv3IPv4Packet.isPacketOfType(pcpp::VRRPv2)) PTF_ASSERT_TRUE(vrrpv3IPv4Packet.isPacketOfType(pcpp::VRRPv3)) @@ -71,10 +67,7 @@ PTF_TEST_CASE(VrrpParsingTest) PTF_ASSERT_EQUAL(vrrpV3IPv4Layer->toString(), "VRRP v3 Layer, virtual router ID: 1, IP address count: 2") PTF_ASSERT_EQUAL(vrrpV3IPv4Layer->getIPAddressesCount(), 2) ipAddressVec = vrrpV3IPv4Layer->getIPAddresses(); - expectedIpAddressVec = { - pcpp::IPAddress("192.168.0.1"), - pcpp::IPAddress("192.168.0.2") - }; + expectedIpAddressVec = { pcpp::IPAddress("192.168.0.1"), pcpp::IPAddress("192.168.0.2") }; PTF_ASSERT_TRUE(ipAddressVec == expectedIpAddressVec) PTF_ASSERT_TRUE(vrrpv3IPv6Packet.isPacketOfType(pcpp::VRRP)) @@ -93,15 +86,10 @@ PTF_TEST_CASE(VrrpParsingTest) PTF_ASSERT_TRUE(vrrpV3IPv6Layer->isChecksumCorrect()) PTF_ASSERT_EQUAL(vrrpV3IPv6Layer->toString(), "VRRP v3 Layer, virtual router ID: 1, IP address count: 3") ipAddressVec = vrrpV3IPv6Layer->getIPAddresses(); - expectedIpAddressVec = { - pcpp::IPAddress("fe80::254"), - pcpp::IPAddress("2001:db8::1"), - pcpp::IPAddress("2001:db8::2") - }; + expectedIpAddressVec = { pcpp::IPAddress("fe80::254"), pcpp::IPAddress("2001:db8::1"), + pcpp::IPAddress("2001:db8::2") }; PTF_ASSERT_TRUE(ipAddressVec == expectedIpAddressVec) -} // VrrpParsingTest - - +} // VrrpParsingTest PTF_TEST_CASE(VrrpCreateAndEditTest) { @@ -188,14 +176,13 @@ PTF_TEST_CASE(VrrpCreateAndEditTest) vrrpv2Layer.setAuthType(10); PTF_ASSERT_EQUAL(vrrpv2Layer.getAuthTypeAsEnum(), pcpp::VrrpV2Layer::VrrpAuthType::Other, enumclass) - - //VRRPv3 IPv4 Packet + // VRRPv3 IPv4 Packet pcpp::EthLayer ethLayer2(pcpp::MacAddress("00:00:5e:00:01:01"), pcpp::MacAddress("01:00:5e:00:00:12")); pcpp::IPv4Layer ipv4Layer(pcpp::IPv4Address("192.168.0.30"), pcpp::IPv4Address("224.0.0.18")); ipv4Layer.getIPv4Header()->timeToLive = 255; pcpp::Packet vrrpv3IPv4Packet(1); - pcpp::VrrpV3Layer vrrpv3IPv4Layer(pcpp::IPAddress::IPv4AddressType, 1 ,100, 1); + pcpp::VrrpV3Layer vrrpv3IPv4Layer(pcpp::IPAddress::IPv4AddressType, 1, 100, 1); vrrpv3IPv4Layer.addIPAddress(ipv4Address1); vrrpv3IPv4Layer.addIPAddress(ipv4Address2); @@ -221,10 +208,10 @@ PTF_TEST_CASE(VrrpCreateAndEditTest) vrrpv3IPv4Layer.getData()[0] = 0x55; PTF_ASSERT_EQUAL(vrrpv3IPv4Layer.getType(), pcpp::VrrpLayer::VrrpType::VrrpType_Unknown) - PTF_ASSERT_RAISES(vrrpv3IPv4Layer.setMaxAdvInt(0x1234), std::invalid_argument, "maxAdvInt must not exceed 12 bits length") - + PTF_ASSERT_RAISES(vrrpv3IPv4Layer.setMaxAdvInt(0x1234), std::invalid_argument, + "maxAdvInt must not exceed 12 bits length") - //VRRPv3 IPv6 Packet + // VRRPv3 IPv6 Packet pcpp::EthLayer ethLayer3(pcpp::MacAddress("00:00:5e:00:01:01"), pcpp::MacAddress("01:00:5e:00:00:12")); pcpp::IPv6Layer ipv6Layer(pcpp::IPv6Address("fe80::1"), pcpp::IPv6Address("ff02::12")); ipv6Layer.getIPv6Header()->hopLimit = 255; @@ -249,4 +236,4 @@ PTF_TEST_CASE(VrrpCreateAndEditTest) FREE_FILE_INTO_BUFFER(2) FREE_FILE_INTO_BUFFER(3) -} // VrrpCreateAndEditTest +} // VrrpCreateAndEditTest diff --git a/Tests/Packet++Test/Tests/WakeOnLanTests.cpp b/Tests/Packet++Test/Tests/WakeOnLanTests.cpp index 26a935ad1d..aaf233346a 100644 --- a/Tests/Packet++Test/Tests/WakeOnLanTests.cpp +++ b/Tests/Packet++Test/Tests/WakeOnLanTests.cpp @@ -15,7 +15,7 @@ PTF_TEST_CASE(WakeOnLanParsingTests) pcpp::Packet wolPacket1(&rawPacket1); PTF_ASSERT_TRUE(wolPacket1.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer1 = wolPacket1.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer1 = wolPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer1); PTF_ASSERT_NOT_NULL(wolLayer1->getWakeOnLanHeader()); @@ -27,7 +27,7 @@ PTF_TEST_CASE(WakeOnLanParsingTests) pcpp::Packet wolPacket2(&rawPacket2); PTF_ASSERT_TRUE(wolPacket2.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer2 = wolPacket2.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer2 = wolPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer2); PTF_ASSERT_NOT_NULL(wolLayer2->getWakeOnLanHeader()); @@ -45,7 +45,7 @@ PTF_TEST_CASE(WakeOnLanCreationTests) pcpp::Packet wolPacket1(&rawPacket1); PTF_ASSERT_TRUE(wolPacket1.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer1 = wolPacket1.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer1 = wolPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer1); pcpp::WakeOnLanLayer wolcraftedLayer1(pcpp::MacAddress("00:0d:56:dc:9e:35")); @@ -62,7 +62,7 @@ PTF_TEST_CASE(WakeOnLanCreationTests) pcpp::Packet wolPacket2(&rawPacket2); PTF_ASSERT_TRUE(wolPacket2.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer2 = wolPacket2.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer2 = wolPacket2.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer2); pcpp::WakeOnLanLayer wolcraftedLayer2(pcpp::MacAddress("00:90:27:85:cf:01")); @@ -79,14 +79,14 @@ PTF_TEST_CASE(WakeOnLanEditTests) pcpp::Packet wolPacket1(&rawPacket1); PTF_ASSERT_TRUE(wolPacket1.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer1 = wolPacket1.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer1 = wolPacket1.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer1); // Edit password READ_FILE_AND_CREATE_PACKET(2, "PacketExamples/WoL_ether_edited1.dat"); pcpp::Packet wolPacketEdited1(&rawPacket2); PTF_ASSERT_TRUE(wolPacketEdited1.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer2 = wolPacketEdited1.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer2 = wolPacketEdited1.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer2); wolLayer1->setPassword(pcpp::IPv4Address("172.0.0.2")); @@ -97,7 +97,7 @@ PTF_TEST_CASE(WakeOnLanEditTests) READ_FILE_AND_CREATE_PACKET(3, "PacketExamples/WoL_ether_edited2.dat"); pcpp::Packet wolPacketEdited2(&rawPacket3); PTF_ASSERT_TRUE(wolPacketEdited2.isPacketOfType(pcpp::WakeOnLan)); - pcpp::WakeOnLanLayer *wolLayer3 = wolPacketEdited2.getLayerOfType(); + pcpp::WakeOnLanLayer* wolLayer3 = wolPacketEdited2.getLayerOfType(); PTF_ASSERT_NOT_NULL(wolLayer3); wolLayer1->setTargetAddr("00:90:27:85:cf:01"); diff --git a/Tests/Packet++Test/Utils/TestUtils.cpp b/Tests/Packet++Test/Utils/TestUtils.cpp index 03b98b21aa..ed30c46c0b 100644 --- a/Tests/Packet++Test/Utils/TestUtils.cpp +++ b/Tests/Packet++Test/Utils/TestUtils.cpp @@ -5,110 +5,109 @@ #include #include #include - namespace pcpp_tests { -int getFileLength(const char* filename) -{ - std::ifstream infile(filename, std::ifstream::binary); - if (!infile) - return -1; - infile.seekg(0, infile.end); - int length = infile.tellg(); - infile.close(); - return length; -} - -uint8_t* readFileIntoBuffer(const char* filename, int& bufferLength) -{ - int fileLength = getFileLength(filename); - if (fileLength == -1) - return nullptr; - - std::ifstream infile(filename); - if (!infile) - return nullptr; - - bufferLength = fileLength/2 + 2; - uint8_t* result = new uint8_t[bufferLength]; - int i = 0; - while (!infile.eof()) + int getFileLength(const char* filename) { - char byte[3]; - memset(byte, 0, 3); - infile.read(byte, 2); - result[i] = (uint8_t)strtol(byte, nullptr, 16); - i++; + std::ifstream infile(filename, std::ifstream::binary); + if (!infile) + return -1; + infile.seekg(0, infile.end); + int length = infile.tellg(); + infile.close(); + return length; } - infile.close(); - bufferLength -= 2; - return result; -} -void printBufferDifferences(const uint8_t* buffer1, size_t buffer1Len, const uint8_t* buffer2, size_t buffer2Len) -{ - std::cout << "First buffer (" << std::dec << buffer1Len << " bytes):\n\n"; - for(int i = 0; i<(int)buffer1Len; i++) + uint8_t* readFileIntoBuffer(const char* filename, int& bufferLength) { - std::cout << " 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buffer1[i] << " "; - if ((i+1) % 16 == 0) + int fileLength = getFileLength(filename); + if (fileLength == -1) + return nullptr; + + std::ifstream infile(filename); + if (!infile) + return nullptr; + + bufferLength = fileLength / 2 + 2; + uint8_t* result = new uint8_t[bufferLength]; + int i = 0; + while (!infile.eof()) { - std::cout << std::endl; + char byte[3]; + memset(byte, 0, 3); + infile.read(byte, 2); + result[i] = (uint8_t)strtol(byte, nullptr, 16); + i++; } + infile.close(); + bufferLength -= 2; + return result; } - std::cout << "\n\n" - << "Second buffer (" << std::dec << buffer2Len << " bytes):\n\n"; - int differenceCount = 0; - for(int i = 0; i<(int)buffer2Len; i++) + void printBufferDifferences(const uint8_t* buffer1, size_t buffer1Len, const uint8_t* buffer2, size_t buffer2Len) { - std::string starOrSpace = (buffer2[i] != buffer1[i] ? "*" : " "); - differenceCount += (buffer2[i] != buffer1[i] ? 1 : 0); - std::cout << starOrSpace << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buffer2[i] << " "; - if ((i+1) % 16 == 0) + std::cout << "First buffer (" << std::dec << buffer1Len << " bytes):\n\n"; + for (int i = 0; i < (int)buffer1Len; i++) + { + std::cout << " 0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buffer1[i] << " "; + if ((i + 1) % 16 == 0) + { + std::cout << std::endl; + } + } + std::cout << "\n\n" + << "Second buffer (" << std::dec << buffer2Len << " bytes):\n\n"; + + int differenceCount = 0; + for (int i = 0; i < (int)buffer2Len; i++) { - std::cout << std::endl; + std::string starOrSpace = (buffer2[i] != buffer1[i] ? "*" : " "); + differenceCount += (buffer2[i] != buffer1[i] ? 1 : 0); + std::cout << starOrSpace << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)buffer2[i] << " "; + if ((i + 1) % 16 == 0) + { + std::cout << std::endl; + } } + std::cout << "\n\n" << std::dec << differenceCount << " bytes differ\n\n"; } - std::cout << "\n\n" << std::dec << differenceCount << " bytes differ\n\n"; -} -void testSetUp() -{ - pcpp::SomeIpLayer::addSomeIpPort(1); - pcpp::SomeIpLayer::removeSomeIpPort(1); -} + void testSetUp() + { + pcpp::SomeIpLayer::addSomeIpPort(1); + pcpp::SomeIpLayer::removeSomeIpPort(1); + } #ifdef PCPP_TESTS_DEBUG -#include "pcap.h" +# include "pcap.h" -void savePacketToPcap(pcpp::Packet& packet, const std::string &fileName) -{ - pcap_t* pcap; - pcap = pcap_open_dead(1, 65565); - - pcap_dumper_t* d; - /* open output file */ - d = pcap_dump_open(pcap, fileName.c_str()); - if (d == NULL) + void savePacketToPcap(pcpp::Packet& packet, const std::string& fileName) { - pcap_perror(pcap, "pcap_dump_fopen"); - return; - } + pcap_t* pcap; + pcap = pcap_open_dead(1, 65565); + + pcap_dumper_t* d; + /* open output file */ + d = pcap_dump_open(pcap, fileName.c_str()); + if (d == NULL) + { + pcap_perror(pcap, "pcap_dump_fopen"); + return; + } - /* prepare for writing */ - struct pcap_pkthdr hdr; - hdr.ts.tv_sec = 0; /* sec */ - hdr.ts.tv_usec = 0; /* ms */ - hdr.caplen = hdr.len = packet.getRawPacket()->getRawDataLen(); - /* write single IP packet */ - pcap_dump(static_cast(d), &hdr, packet.getRawPacketReadOnly()->getRawData()); + /* prepare for writing */ + struct pcap_pkthdr hdr; + hdr.ts.tv_sec = 0; /* sec */ + hdr.ts.tv_usec = 0; /* ms */ + hdr.caplen = hdr.len = packet.getRawPacket()->getRawDataLen(); + /* write single IP packet */ + pcap_dump(static_cast(d), &hdr, packet.getRawPacketReadOnly()->getRawData()); - /* finish up */ - pcap_dump_close(d); - return; -} + /* finish up */ + pcap_dump_close(d); + return; + } #endif -} +} // namespace pcpp_tests diff --git a/Tests/Packet++Test/Utils/TestUtils.h b/Tests/Packet++Test/Utils/TestUtils.h index a763ca6163..6599d7690b 100644 --- a/Tests/Packet++Test/Utils/TestUtils.h +++ b/Tests/Packet++Test/Utils/TestUtils.h @@ -1,46 +1,45 @@ #pragma once +// clang-format off #ifdef PCPP_TESTS_DEBUG #include "Packet.h" #endif +// clang-format on #include #include namespace pcpp_tests { -int getFileLength(const char* filename); + int getFileLength(const char* filename); -uint8_t* readFileIntoBuffer(const char* filename, int& bufferLength); + uint8_t* readFileIntoBuffer(const char* filename, int& bufferLength); -void printBufferDifferences(const uint8_t* buffer1, size_t buffer1Len, const uint8_t* buffer2, size_t buffer2Len); + void printBufferDifferences(const uint8_t* buffer1, size_t buffer1Len, const uint8_t* buffer2, size_t buffer2Len); -void testSetUp(); + void testSetUp(); -#define READ_FILE_INTO_BUFFER(num, filename) \ - int bufferLength##num = 0; \ - uint8_t* buffer##num = pcpp_tests::readFileIntoBuffer(filename, bufferLength##num); \ - PTF_ASSERT_NOT_NULL(buffer##num) \ +#define READ_FILE_INTO_BUFFER(num, filename) \ + int bufferLength##num = 0; \ + uint8_t* buffer##num = pcpp_tests::readFileIntoBuffer(filename, bufferLength##num); \ + PTF_ASSERT_NOT_NULL(buffer##num) -#define FREE_FILE_INTO_BUFFER(num) \ - delete[] buffer##num; +#define FREE_FILE_INTO_BUFFER(num) delete[] buffer##num; -#define FILE_INTO_BUFFER_LENGTH(num) \ - bufferLength##num +#define FILE_INTO_BUFFER_LENGTH(num) bufferLength##num -#define FILE_INTO_BUFFER(num) \ - buffer##num +#define FILE_INTO_BUFFER(num) buffer##num -#define READ_FILE_AND_CREATE_PACKET(num, filename) \ - READ_FILE_INTO_BUFFER(num, filename); \ +#define READ_FILE_AND_CREATE_PACKET(num, filename) \ + READ_FILE_INTO_BUFFER(num, filename); \ pcpp::RawPacket rawPacket##num(static_cast(buffer##num), bufferLength##num, time, true) -#define READ_FILE_AND_CREATE_PACKET_LINKTYPE(num, filename, linktype) \ - READ_FILE_INTO_BUFFER(num, filename); \ +#define READ_FILE_AND_CREATE_PACKET_LINKTYPE(num, filename, linktype) \ + READ_FILE_INTO_BUFFER(num, filename); \ pcpp::RawPacket rawPacket##num(static_cast(buffer##num), bufferLength##num, time, true, linktype) #ifdef PCPP_TESTS_DEBUG -void savePacketToPcap(pcpp::Packet& packet, const std::string &fileName); + void savePacketToPcap(pcpp::Packet& packet, const std::string& fileName); #endif -} +} // namespace pcpp_tests diff --git a/Tests/Packet++Test/main.cpp b/Tests/Packet++Test/main.cpp index 937bf62707..d235f69f41 100644 --- a/Tests/Packet++Test/main.cpp +++ b/Tests/Packet++Test/main.cpp @@ -7,32 +7,32 @@ #include "Logger.h" #include "../../Tests/Packet++Test/Utils/TestUtils.h" -static struct option PacketTestOptions[] = -{ - {"include-tags", required_argument, nullptr, 't'}, - {"exclude-tags", required_argument, nullptr, 'x'}, - {"show-skipped-tests", no_argument, nullptr, 'w' }, - {"mem-verbose", no_argument, nullptr, 'm' }, - {"verbose", no_argument, nullptr, 'v' }, - {"skip-mem-leak-check", no_argument, nullptr, 's' }, - {"help", no_argument, nullptr, 'h' }, - {nullptr, 0, nullptr, 0} +static struct option PacketTestOptions[] = { + { "include-tags", required_argument, nullptr, 't' }, + { "exclude-tags", required_argument, nullptr, 'x' }, + { "show-skipped-tests", no_argument, nullptr, 'w' }, + { "mem-verbose", no_argument, nullptr, 'm' }, + { "verbose", no_argument, nullptr, 'v' }, + { "skip-mem-leak-check", no_argument, nullptr, 's' }, + // clang-format off + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 } + // clang-format on }; void printUsage() { std::cout << "Usage: Packet++Test [-t tags] [-m] [-s] [-v] [-h]\n\n" - << "Flags:\n" - << "-t --include-tags A list of semicolon separated tags for tests to run\n" - << "-x --exclude-tags A list of semicolon separated tags for tests to exclude\n" - << "-w --show-skipped-tests Show tests that are skipped. Default is to hide them in tests results\n" - << "-v --verbose Run in verbose mode (emits more output in several tests)\n" - << "-m --mem-verbose Output information about each memory allocation and deallocation\n" - << "-s --skip-mem-leak-check Skip memory leak check\n" - << "-h --help Display this help message and exit\n"; + << "Flags:\n" + << "-t --include-tags A list of semicolon separated tags for tests to run\n" + << "-x --exclude-tags A list of semicolon separated tags for tests to exclude\n" + << "-w --show-skipped-tests Show tests that are skipped. Default is to hide them in tests results\n" + << "-v --verbose Run in verbose mode (emits more output in several tests)\n" + << "-m --mem-verbose Output information about each memory allocation and deallocation\n" + << "-s --skip-mem-leak-check Skip memory leak check\n" + << "-h --help Display this help message and exit\n"; } - int main(int argc, char* argv[]) { int optionIndex = 0; @@ -41,48 +41,50 @@ int main(int argc, char* argv[]) bool memVerbose = false; bool skipMemLeakCheck = false; - while((opt = getopt_long(argc, argv, "msvwht:x:", PacketTestOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "msvwht:x:", PacketTestOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 't': - userTagsInclude = optarg; - break; - case 'x': - userTagsExclude = optarg; - break; - case 's': - skipMemLeakCheck = true; - break; - case 'm': - memVerbose = true; - break; - case 'w': - PTF_SHOW_SKIPPED_TESTS(true); - break; - case 'v': - PTF_SET_VERBOSE_MODE(true); - break; - case 'h': - printUsage(); - exit(0); - default: - printUsage(); - exit(-1); + case 0: + break; + case 't': + userTagsInclude = optarg; + break; + case 'x': + userTagsExclude = optarg; + break; + case 's': + skipMemLeakCheck = true; + break; + case 'm': + memVerbose = true; + break; + case 'w': + PTF_SHOW_SKIPPED_TESTS(true); + break; + case 'v': + PTF_SET_VERBOSE_MODE(true); + break; + case 'h': + printUsage(); + exit(0); + default: + printUsage(); + exit(-1); } } std::cout << "PcapPlusPlus version: " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; - #ifdef NDEBUG +#ifdef NDEBUG skipMemLeakCheck = true; - std::cout << "Disabling memory leak check in MSVC Release builds due to caching logic in stream objects that looks like a memory leak:" << std::endl - << " https://github.com/cpputest/cpputest/issues/786#issuecomment-148921958" << std::endl; - #endif + std::cout + << "Disabling memory leak check in MSVC Release builds due to caching logic in stream objects that looks like a memory leak:" + << std::endl + << " 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(); diff --git a/Tests/Pcap++Test/Common/GlobalTestArgs.h b/Tests/Pcap++Test/Common/GlobalTestArgs.h index 9df487020c..f94c99179d 100644 --- a/Tests/Pcap++Test/Common/GlobalTestArgs.h +++ b/Tests/Pcap++Test/Common/GlobalTestArgs.h @@ -1,6 +1,7 @@ #pragma once #include +#include struct PcapTestArgs { diff --git a/Tests/Pcap++Test/Common/TestUtils.cpp b/Tests/Pcap++Test/Common/TestUtils.cpp index 131b24d757..c55d736ef8 100644 --- a/Tests/Pcap++Test/Common/TestUtils.cpp +++ b/Tests/Pcap++Test/Common/TestUtils.cpp @@ -4,16 +4,18 @@ #include "GlobalTestArgs.h" #include "PcapFileDevice.h" #include "PcapLiveDeviceList.h" +// clang-format off #ifdef USE_PF_RING #include "PfRingDeviceList.h" #endif #ifdef USE_DPDK #include "DpdkDeviceList.h" #endif +// clang-format on extern PcapTestArgs PcapTestGlobalArgs; -bool sendURLRequest(const std::string &url) +bool sendURLRequest(const std::string& url) { #if defined(_WIN32) std::string cmd = "cUrl\\curl_win32.exe -s -o cUrl\\curl_output.txt"; @@ -29,8 +31,8 @@ bool sendURLRequest(const std::string &url) return true; } - -bool readPcapIntoPacketVec(const std::string& pcapFileName, std::vector& packetStream, std::string& errMsg) +bool readPcapIntoPacketVec(const std::string& pcapFileName, std::vector& packetStream, + std::string& errMsg) { errMsg = ""; packetStream.clear(); @@ -51,8 +53,7 @@ bool readPcapIntoPacketVec(const std::string& pcapFileName, std::vector -1) { pcpp::CoreMask coreMask = 0; @@ -109,5 +108,5 @@ void testSetUp() } pcpp::DpdkDeviceList::initDpdk(coreMask, 16383); } - #endif +#endif } diff --git a/Tests/Pcap++Test/Common/TestUtils.h b/Tests/Pcap++Test/Common/TestUtils.h index 94625923ba..9e90883fe7 100644 --- a/Tests/Pcap++Test/Common/TestUtils.h +++ b/Tests/Pcap++Test/Common/TestUtils.h @@ -9,14 +9,14 @@ class DeviceTeardown { private: - pcpp::IDevice* m_Device; bool m_CancelTeardown; bool m_DeleteDevice; public: - - explicit DeviceTeardown(pcpp::IDevice* device, bool deleteDevice = false) : m_Device(device), m_CancelTeardown(false), m_DeleteDevice(deleteDevice) {} + explicit DeviceTeardown(pcpp::IDevice* device, bool deleteDevice = false) + : m_Device(device), m_CancelTeardown(false), m_DeleteDevice(deleteDevice) + {} ~DeviceTeardown() { @@ -36,34 +36,34 @@ class DeviceTeardown } }; -bool sendURLRequest(const std::string &url); +bool sendURLRequest(const std::string& url); -bool readPcapIntoPacketVec(const std::string& pcapFileName, std::vector& packetStream, std::string& errMsg); +bool readPcapIntoPacketVec(const std::string& pcapFileName, std::vector& packetStream, + std::string& errMsg); -int getFileLength(const std::string &filename); +int getFileLength(const std::string& filename); -uint8_t* readFileIntoBuffer(const std::string &filename, int& bufferLength); +uint8_t* readFileIntoBuffer(const std::string& filename, int& bufferLength); -template -void intersectMaps( - const std::unordered_map & left, - const std::unordered_map & right, - std::unordered_map >& result) +template +void intersectMaps(const std::unordered_map& left, + const std::unordered_map& right, + std::unordered_map>& result) { typename std::unordered_map::const_iterator il = left.begin(); typename std::unordered_map::const_iterator ir = right.begin(); while (il != left.end() && ir != right.end()) { - if (il->first < ir->first) - ++il; - else if (ir->first < il->first) - ++ir; - else - { - result.insert(std::make_pair(il->first, std::make_pair(il->second, ir->second))); - ++il; - ++ir; - } + if (il->first < ir->first) + ++il; + else if (ir->first < il->first) + ++ir; + else + { + result.insert(std::make_pair(il->first, std::make_pair(il->second, ir->second))); + ++il; + ++ir; + } } } diff --git a/Tests/Pcap++Test/Tests/DpdkTests.cpp b/Tests/Pcap++Test/Tests/DpdkTests.cpp index 50afd7b03e..3da94d97f8 100644 --- a/Tests/Pcap++Test/Tests/DpdkTests.cpp +++ b/Tests/Pcap++Test/Tests/DpdkTests.cpp @@ -7,15 +7,15 @@ #include #ifdef USE_DPDK -#include -#include "Logger.h" -#include "PacketUtils.h" -#include "IPv4Layer.h" -#include "TcpLayer.h" -#include "UdpLayer.h" -#include "DnsLayer.h" -#include "DpdkDeviceList.h" -#include "PcapFileDevice.h" +# include +# include "Logger.h" +# include "PacketUtils.h" +# include "IPv4Layer.h" +# include "TcpLayer.h" +# include "UdpLayer.h" +# include "DnsLayer.h" +# include "DpdkDeviceList.h" +# include "PcapFileDevice.h" #endif extern PcapTestArgs PcapTestGlobalArgs; @@ -35,8 +35,23 @@ struct DpdkPacketData std::unordered_map FlowKeys; - DpdkPacketData() : ThreadId(-1), PacketCount(0), EthCount(0), ArpCount(0), Ip4Count(0), Ip6Count(0), TcpCount(0), UdpCount(0), HttpCount(0) {} - void clear() { ThreadId = -1; PacketCount = 0; EthCount = 0; ArpCount = 0; Ip4Count = 0; Ip6Count = 0; TcpCount = 0; UdpCount = 0; HttpCount = 0; FlowKeys.clear(); } + DpdkPacketData() + : ThreadId(-1), PacketCount(0), EthCount(0), ArpCount(0), Ip4Count(0), Ip6Count(0), TcpCount(0), UdpCount(0), + HttpCount(0) + {} + void clear() + { + ThreadId = -1; + PacketCount = 0; + EthCount = 0; + ArpCount = 0; + Ip4Count = 0; + Ip6Count = 0; + TcpCount = 0; + UdpCount = 0; + HttpCount = 0; + FlowKeys.clear(); + } }; int incSleep(int maxSleepTime, int minPacketCount, const DpdkPacketData& packetData) @@ -53,7 +68,8 @@ int incSleep(int maxSleepTime, int minPacketCount, const DpdkPacketData& packetD return totalSleepTime; } -int incSleepMultiThread(int maxSleepTime, DpdkPacketData packetData[], int totalNumOfCores, int numOfCoresInUse, pcpp::CoreMask coreMask) +int incSleepMultiThread(int maxSleepTime, DpdkPacketData packetData[], int totalNumOfCores, int numOfCoresInUse, + pcpp::CoreMask coreMask) { int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) @@ -78,7 +94,8 @@ int incSleepMultiThread(int maxSleepTime, DpdkPacketData packetData[], int total return totalSleepTime; } -void dpdkPacketsArrive(pcpp::MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::DpdkDevice* device, void* userCookie) +void dpdkPacketsArrive(pcpp::MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::DpdkDevice* device, + void* userCookie) { DpdkPacketData* data = (DpdkPacketData*)userCookie; @@ -102,11 +119,11 @@ void dpdkPacketsArrive(pcpp::MBufRawPacket* packets, uint32_t numOfPackets, uint data->UdpCount++; if (packet.isPacketOfType(pcpp::HTTP)) data->HttpCount++; - } } -void dpdkPacketsArriveMultiThread(pcpp::MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::DpdkDevice* device, void* userCookie) +void dpdkPacketsArriveMultiThread(pcpp::MBufRawPacket* packets, uint32_t numOfPackets, uint8_t threadId, + pcpp::DpdkDevice* device, void* userCookie) { DpdkPacketData* data = (DpdkPacketData*)userCookie; @@ -144,8 +161,6 @@ void dpdkPacketsArriveMultiThread(pcpp::MBufRawPacket* packets, uint32_t numOfPa } if (packet.isPacketOfType(pcpp::HTTP)) data[threadId].HttpCount++; - - } } @@ -160,6 +175,7 @@ class DpdkTestWorkerThread : public pcpp::DpdkWorkerThread int m_PacketCount; bool m_Initialized; bool m_RanAndStopped; + public: DpdkTestWorkerThread() { @@ -225,20 +241,28 @@ class DpdkTestWorkerThread : public pcpp::DpdkWorkerThread return true; } - void stop() { m_Stop = true; } + void stop() + { + m_Stop = true; + } - uint32_t getCoreId() const { return m_CoreId; } + uint32_t getCoreId() const + { + return m_CoreId; + } - int getPacketCount() const { return m_PacketCount; } + int getPacketCount() const + { + return m_PacketCount; + } - bool threadRanAndStopped() { return m_RanAndStopped; } + bool threadRanAndStopped() + { + return m_RanAndStopped; + } }; -#endif // USE_DPDK - - - - +#endif // USE_DPDK PTF_TEST_CASE(TestDpdkInitDevice) { @@ -253,10 +277,7 @@ PTF_TEST_CASE(TestDpdkInitDevice) #else PTF_SKIP_TEST("DPDK not configured"); #endif -} // TestDpdkInitDevice - - - +} // TestDpdkInitDevice PTF_TEST_CASE(TestDpdkDevice) { @@ -287,10 +308,8 @@ PTF_TEST_CASE(TestDpdkDevice) } else if (dev->getPMDName() == "net_vmxnet3") { - uint64_t rssHF = pcpp::DpdkDevice::RSS_IPV4 | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV4_TCP | \ - pcpp::DpdkDevice::RSS_IPV6 | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV6_TCP; + uint64_t rssHF = pcpp::DpdkDevice::RSS_IPV4 | pcpp::DpdkDevice::RSS_NONFRAG_IPV4_TCP | + pcpp::DpdkDevice::RSS_IPV6 | pcpp::DpdkDevice::RSS_NONFRAG_IPV6_TCP; PTF_ASSERT_TRUE(dev->isDeviceSupportRssHashFunction(rssHF)); PTF_ASSERT_EQUAL(dev->getSupportedRssHashFunctions(), rssHF); @@ -299,14 +318,10 @@ PTF_TEST_CASE(TestDpdkDevice) uint64_t configuredRssHF = pcpp::DpdkDevice::RSS_IPV4 | pcpp::DpdkDevice::RSS_IPV6; if (dev->getPMDType() == pcpp::PMD_I40E || dev->getPMDType() == pcpp::PMD_I40EVF) { - configuredRssHF = pcpp::DpdkDevice::RSS_NONFRAG_IPV4_TCP | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV4_UDP | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV4_OTHER | \ - pcpp::DpdkDevice::RSS_FRAG_IPV4 | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV6_TCP | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV6_UDP | \ - pcpp::DpdkDevice::RSS_NONFRAG_IPV6_OTHER | \ - pcpp::DpdkDevice::RSS_FRAG_IPV6; + configuredRssHF = pcpp::DpdkDevice::RSS_NONFRAG_IPV4_TCP | pcpp::DpdkDevice::RSS_NONFRAG_IPV4_UDP | + pcpp::DpdkDevice::RSS_NONFRAG_IPV4_OTHER | pcpp::DpdkDevice::RSS_FRAG_IPV4 | + pcpp::DpdkDevice::RSS_NONFRAG_IPV6_TCP | pcpp::DpdkDevice::RSS_NONFRAG_IPV6_UDP | + pcpp::DpdkDevice::RSS_NONFRAG_IPV6_OTHER | pcpp::DpdkDevice::RSS_FRAG_IPV6; } PTF_ASSERT_EQUAL(dev->getConfiguredRssHashFunction(), configuredRssHF); @@ -353,7 +368,9 @@ PTF_TEST_CASE(TestDpdkDevice) PTF_ASSERT_GREATER_THAN(packetData.PacketCount, 0); PTF_ASSERT_NOT_EQUAL(packetData.ThreadId, -1); - int statsVsPacketCount = stats.aggregatedRxStats.packets > (uint64_t)packetData.PacketCount ? stats.aggregatedRxStats.packets-(uint64_t)packetData.PacketCount : (uint64_t)packetData.PacketCount-stats.aggregatedRxStats.packets; + int statsVsPacketCount = stats.aggregatedRxStats.packets > (uint64_t)packetData.PacketCount + ? stats.aggregatedRxStats.packets - (uint64_t)packetData.PacketCount + : (uint64_t)packetData.PacketCount - stats.aggregatedRxStats.packets; PTF_ASSERT_LOWER_OR_EQUAL_THAN(statsVsPacketCount, 20); dev->close(); @@ -361,10 +378,7 @@ PTF_TEST_CASE(TestDpdkDevice) #else PTF_SKIP_TEST("DPDK not configured"); #endif -} // TestDpdkDevice - - - +} // TestDpdkDevice PTF_TEST_CASE(TestDpdkMultiThread) { @@ -376,7 +390,8 @@ PTF_TEST_CASE(TestDpdkMultiThread) DeviceTeardown devTeardown(dev); // take min value between number of cores and number of available RX queues - int numOfRxQueuesToOpen = pcpp::getNumOfCores()-1; //using num of cores minus one since 1 core is the master core and cannot be used + int numOfRxQueuesToOpen = + pcpp::getNumOfCores() - 1; // using num of cores minus one since 1 core is the master core and cannot be used if (dev->getTotalNumOfRxQueues() < numOfRxQueuesToOpen) numOfRxQueuesToOpen = dev->getTotalNumOfRxQueues(); @@ -391,7 +406,7 @@ PTF_TEST_CASE(TestDpdkMultiThread) if (dev->getTotalNumOfRxQueues() > 1) { pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_FALSE(dev->openMultiQueues(numOfRxQueuesToOpen+1, 1)); + PTF_ASSERT_FALSE(dev->openMultiQueues(numOfRxQueuesToOpen + 1, 1)); pcpp::Logger::getInstance().enableLogs(); } @@ -430,7 +445,8 @@ PTF_TEST_CASE(TestDpdkMultiThread) } PTF_ASSERT_TRUE(dev->startCaptureMultiThreads(dpdkPacketsArriveMultiThread, packetDataMultiThread, coreMask)); - int totalSleepTime = incSleepMultiThread(20, packetDataMultiThread, pcpp::getNumOfCores(), numOfCoresInUse, coreMask); + int totalSleepTime = + incSleepMultiThread(20, packetDataMultiThread, pcpp::getNumOfCores(), numOfCoresInUse, coreMask); dev->stopCapture(); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); uint64_t packetCount = 0; @@ -463,7 +479,6 @@ PTF_TEST_CASE(TestDpdkMultiThread) { PTF_PRINT_VERBOSE("Packets captured on RX queue #" << i << " according to stats: " << stats.rxStats[i].packets); PTF_PRINT_VERBOSE("Bytes captured on RX queue #" << i << " according to stats: " << stats.rxStats[i].bytes); - } PTF_ASSERT_GREATER_OR_EQUAL_THAN(stats.aggregatedRxStats.packets, packetCount); PTF_ASSERT_EQUAL(stats.rxPacketsDroppedByHW, 0); @@ -473,19 +488,21 @@ PTF_TEST_CASE(TestDpdkMultiThread) if ((pcpp::SystemCores::IdToSystemCore[firstCoreId].Mask & coreMask) == 0) continue; - for (int secondCoreId = firstCoreId+1; secondCoreId < pcpp::getNumOfCores(); secondCoreId++) + for (int secondCoreId = firstCoreId + 1; secondCoreId < pcpp::getNumOfCores(); secondCoreId++) { if ((pcpp::SystemCores::IdToSystemCore[secondCoreId].Mask & coreMask) == 0) continue; - std::unordered_map > res; - intersectMaps(packetDataMultiThread[firstCoreId].FlowKeys, packetDataMultiThread[secondCoreId].FlowKeys, res); + std::unordered_map> res; + intersectMaps( + packetDataMultiThread[firstCoreId].FlowKeys, packetDataMultiThread[secondCoreId].FlowKeys, res); PTF_ASSERT_EQUAL(res.size(), 0); if (PTF_IS_VERBOSE_MODE) { - for (auto &iter : res) + for (auto& iter : res) { - PTF_PRINT_VERBOSE("Same flow exists in core " << firstCoreId << " and core " << secondCoreId << ". Flow key = " << iter.first); + PTF_PRINT_VERBOSE("Same flow exists in core " << firstCoreId << " and core " << secondCoreId + << ". Flow key = " << iter.first); std::ostringstream stream; stream << "Core" << firstCoreId << "_Flow_" << std::hex << iter.first << ".pcap"; pcpp::PcapFileWriterDevice writerDev(stream.str()); @@ -502,16 +519,15 @@ PTF_TEST_CASE(TestDpdkMultiThread) iter.second.first.clear(); iter.second.second.clear(); - } } } - PTF_PRINT_VERBOSE("____Core " << firstCoreId << "____"); + PTF_PRINT_VERBOSE("____Core " << firstCoreId << "____"); PTF_PRINT_VERBOSE("Total flows: " << packetDataMultiThread[firstCoreId].FlowKeys.size()); if (PTF_IS_VERBOSE_MODE) { - for(auto &iter : packetDataMultiThread[firstCoreId].FlowKeys) + for (auto& iter : packetDataMultiThread[firstCoreId].FlowKeys) { PTF_PRINT_VERBOSE("Key=0x" << std::hex << iter.first << "; Value=" << std::dec << iter.second.size()); iter.second.clear(); @@ -526,10 +542,7 @@ PTF_TEST_CASE(TestDpdkMultiThread) #else PTF_SKIP_TEST("DPDK not configured"); #endif -} // TestDpdkMultiThread - - - +} // TestDpdkMultiThread PTF_TEST_CASE(TestDpdkDeviceSendPackets) { @@ -557,7 +570,7 @@ PTF_TEST_CASE(TestDpdkDeviceSendPackets) pcpp::Packet* packetArr[10000]; uint16_t packetsRead = 0; pcpp::RawPacket rawPacket; - while(fileReaderDev.getNextPacket(rawPacket)) + while (fileReaderDev.getNextPacket(rawPacket)) { if (packetsRead == 100) break; @@ -571,28 +584,28 @@ PTF_TEST_CASE(TestDpdkDeviceSendPackets) packetsRead++; } - //send packets as parsed EthPacekt array + // send packets as parsed EthPacekt array uint16_t packetsSentAsParsed = dev->sendPackets(packetArr, packetsRead, 0, false); PTF_ASSERT_EQUAL(packetsSentAsParsed, packetsRead); - //send packets are RawPacketVector + // send packets are RawPacketVector uint16_t packetsSentAsRawVector = dev->sendPackets(rawPacketVec); PTF_ASSERT_EQUAL(packetsSentAsRawVector, packetsRead); if (txQueues > 1) { - packetsSentAsParsed = dev->sendPackets(packetArr, packetsRead, txQueues-1); - packetsSentAsRawVector = dev->sendPackets(rawPacketVec, txQueues-1); + packetsSentAsParsed = dev->sendPackets(packetArr, packetsRead, txQueues - 1); + packetsSentAsRawVector = dev->sendPackets(rawPacketVec, txQueues - 1); PTF_ASSERT_EQUAL(packetsSentAsParsed, packetsRead); PTF_ASSERT_EQUAL(packetsSentAsRawVector, packetsRead); } pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_EQUAL(dev->sendPackets(rawPacketVec, txQueues+1), 0); + PTF_ASSERT_EQUAL(dev->sendPackets(rawPacketVec, txQueues + 1), 0); pcpp::Logger::getInstance().enableLogs(); - PTF_ASSERT_TRUE(dev->sendPacket(*(rawPacketVec.at(packetsRead/3)), 0)); - PTF_ASSERT_TRUE(dev->sendPacket(*(packetArr[packetsRead/2]), 0)); + PTF_ASSERT_TRUE(dev->sendPacket(*(rawPacketVec.at(packetsRead / 3)), 0)); + PTF_ASSERT_TRUE(dev->sendPacket(*(packetArr[packetsRead / 2]), 0)); dev->close(); fileReaderDev.close(); @@ -600,10 +613,7 @@ PTF_TEST_CASE(TestDpdkDeviceSendPackets) #else PTF_SKIP_TEST("DPDK not configured"); #endif -} // TestDpdkDeviceSendPackets - - - +} // TestDpdkDeviceSendPackets PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) { @@ -628,9 +638,9 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) PTF_ASSERT_EQUAL(dev->receivePackets(mBufRawPacketArr, mBufRawPacketArrLen, 0), 0); PTF_ASSERT_TRUE(dev->open()); - PTF_ASSERT_EQUAL(dev->receivePackets(rawPacketVec, dev->getTotalNumOfRxQueues()+1), 0); - PTF_ASSERT_EQUAL(dev->receivePackets(packetArr, packetArrLen, dev->getTotalNumOfRxQueues()+1), 0); - PTF_ASSERT_EQUAL(dev->receivePackets(mBufRawPacketArr, mBufRawPacketArrLen, dev->getTotalNumOfRxQueues()+1), 0); + PTF_ASSERT_EQUAL(dev->receivePackets(rawPacketVec, dev->getTotalNumOfRxQueues() + 1), 0); + PTF_ASSERT_EQUAL(dev->receivePackets(packetArr, packetArrLen, dev->getTotalNumOfRxQueues() + 1), 0); + PTF_ASSERT_EQUAL(dev->receivePackets(mBufRawPacketArr, mBufRawPacketArrLen, dev->getTotalNumOfRxQueues() + 1), 0); DpdkPacketData packetData; mBufRawPacketArrLen = 32; @@ -672,7 +682,8 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) } PTF_ASSERT_LOWER_THAN(numOfAttempts, 20); - PTF_PRINT_VERBOSE("Captured " << rawPacketVec.size() << " packets in " << numOfAttempts << " attempts using RawPacketVector"); + PTF_PRINT_VERBOSE("Captured " << rawPacketVec.size() << " packets in " << numOfAttempts + << " attempts using RawPacketVector"); // receive packets to mbuf array // ----------------------------- @@ -698,7 +709,8 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) } PTF_ASSERT_LOWER_THAN(numOfAttempts, 20); - PTF_PRINT_VERBOSE("Captured " << mBufRawPacketArrLen << " packets in " << numOfAttempts << " attempts using mBuf raw packet arr"); + PTF_PRINT_VERBOSE("Captured " << mBufRawPacketArrLen << " packets in " << numOfAttempts + << " attempts using mBuf raw packet arr"); for (int i = 0; i < 32; i++) { @@ -776,15 +788,15 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) dev->getStatistics(stats); PTF_PRINT_VERBOSE("Packets captured : " << stats.aggregatedRxStats.packets); PTF_PRINT_VERBOSE("Bytes captured : " << stats.aggregatedRxStats.bytes); - PTF_PRINT_VERBOSE("Bits per second : " << stats.aggregatedRxStats.bytesPerSec*8); + PTF_PRINT_VERBOSE("Bits per second : " << stats.aggregatedRxStats.bytesPerSec * 8); PTF_PRINT_VERBOSE("Packets per second : " << stats.aggregatedRxStats.packetsPerSec); PTF_PRINT_VERBOSE("Packets dropped : " << stats.rxPacketsDroppedByHW); PTF_PRINT_VERBOSE("Erroneous packets : " << stats.rxErroneousPackets); for (int i = 0; i < DPDK_MAX_RX_QUEUES; i++) { - PTF_PRINT_VERBOSE("Packets captured on RX queue #" << i << " according to stats: " << stats.rxStats[i].packets); + PTF_PRINT_VERBOSE("Packets captured on RX queue #" << i + << " according to stats: " << stats.rxStats[i].packets); PTF_PRINT_VERBOSE("Bytes captured on RX queue #" << i << " according to stats: " << stats.rxStats[i].bytes); - } pcpp::multiPlatformSleep(1); @@ -798,16 +810,17 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) pcpp::DpdkDeviceList::getInstance().stopDpdkWorkerThreads(); PTF_PRINT_VERBOSE("Worker threads stopped"); - // we can't guarantee all threads receive packets, it depends on the NIC load balancing and the traffic. So we check that all threads were run and - // that total amount of packets received by all threads is greater than zero + // we can't guarantee all threads receive packets, it depends on the NIC load balancing and the traffic. So we check + // that all threads were run and that total amount of packets received by all threads is greater than zero int packetCount = 0; - for (auto &iter : workerThreadVec) + for (auto& iter : workerThreadVec) { DpdkTestWorkerThread* thread = (DpdkTestWorkerThread*)iter; PTF_ASSERT_TRUE(thread->threadRanAndStopped()); packetCount += thread->getPacketCount(); - PTF_PRINT_VERBOSE("Worker thread on core " << thread->getCoreId() << " captured " << thread->getPacketCount() << " packets"); + PTF_PRINT_VERBOSE("Worker thread on core " << thread->getCoreId() << " captured " << thread->getPacketCount() + << " packets"); delete thread; } @@ -820,10 +833,7 @@ PTF_TEST_CASE(TestDpdkDeviceWorkerThreads) #else PTF_SKIP_TEST("DPDK not configured"); #endif -} // TestDpdkDeviceWorkerThreads - - - +} // TestDpdkDeviceWorkerThreads PTF_TEST_CASE(TestDpdkMbufRawPacket) { @@ -839,7 +849,6 @@ PTF_TEST_CASE(TestDpdkMbufRawPacket) PTF_ASSERT_TRUE(dev->openMultiQueues(numOfRxQueues, numOfTxQueues)); DeviceTeardown devTeardown(dev); - // Test load from PCAP to MBufRawPacket // ------------------------------------ pcpp::PcapFileReaderDevice reader(EXAMPLE2_PCAP_PATH); @@ -894,10 +903,12 @@ PTF_TEST_CASE(TestDpdkMbufRawPacket) { dev->receivePackets(rawPacketVec, i); pcpp::multiPlatformSleep(1); - for (pcpp::MBufRawPacketVector::VectorIterator iter = rawPacketVec.begin(); iter != rawPacketVec.end(); iter++) + for (pcpp::MBufRawPacketVector::VectorIterator iter = rawPacketVec.begin(); iter != rawPacketVec.end(); + iter++) { pcpp::Packet packet(*iter); - if ((packet.isPacketOfType(pcpp::TCP) || packet.isPacketOfType(pcpp::UDP)) && packet.isPacketOfType(pcpp::IPv4)) + if ((packet.isPacketOfType(pcpp::TCP) || packet.isPacketOfType(pcpp::UDP)) && + packet.isPacketOfType(pcpp::IPv4)) { foundTcpOrUdpPacket = true; break; @@ -987,25 +998,25 @@ PTF_TEST_CASE(TestDpdkMbufRawPacket) for (int i = 0; i < 10; i++) { // generate random string with random length < 40 - int nameLength = rand()%60; - char name[nameLength+1]; + int nameLength = rand() % 60; + char name[nameLength + 1]; for (int j = 0; j < nameLength; ++j) { - int randomChar = rand()%(26+26+10); + int randomChar = rand() % (26 + 26 + 10); if (randomChar < 26) name[j] = 'a' + randomChar; - else if (randomChar < 26+26) + else if (randomChar < 26 + 26) name[j] = 'A' + randomChar - 26; else name[j] = '0' + randomChar - 26 - 26; } name[nameLength] = 0; - //set name for query + // set name for query newQuery->setName(std::string(name)); packetToManipulate.computeCalculateFields(); - //transmit packet + // transmit packet PTF_ASSERT_TRUE(dev->sendPacket(packetToManipulate, 0)); } @@ -1014,4 +1025,4 @@ PTF_TEST_CASE(TestDpdkMbufRawPacket) #else PTF_SKIP_TEST("DPDK not configured"); #endif -} // TestDpdkMbufRawPacket +} // TestDpdkMbufRawPacket diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 0647c714f8..9403b73b1b 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -6,7 +6,6 @@ #include #include - class FileReaderTeardown { private: @@ -27,9 +26,6 @@ class FileReaderTeardown } }; - - - PTF_TEST_CASE(TestPcapFileReadWrite) { pcpp::PcapFileReaderDevice readerDev(EXAMPLE_PCAP_PATH); @@ -66,7 +62,6 @@ PTF_TEST_CASE(TestPcapFileReadWrite) PTF_ASSERT_TRUE(writerDev.writePacket(rawPacket)); } - pcpp::IPcapDevice::PcapStats readerStatistics; pcpp::IPcapDevice::PcapStats writerStatistics; @@ -102,26 +97,32 @@ PTF_TEST_CASE(TestPcapFileReadWrite) readerDev2.close(); PTF_ASSERT_FALSE(readerDev2.isOpened()); -} // TestPcapFileReadWrite +} // TestPcapFileReadWrite PTF_TEST_CASE(TestPcapFilePrecision) { - std::array testPayload = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; - pcpp::RawPacket rawPacketNano(testPayload.data(), testPayload.size(), timespec({1, 1234}), false); // 1.000001234 - pcpp::RawPacket rawPacketMicro(testPayload.data(), testPayload.size(), timeval({1, 2}), false); // 1.000002000 + std::array testPayload = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + pcpp::RawPacket rawPacketNano(testPayload.data(), testPayload.size(), timespec({ 1, 1234 }), false); // 1.000001234 + pcpp::RawPacket rawPacketMicro(testPayload.data(), testPayload.size(), timeval({ 1, 2 }), false); // 1.000002000 // Writer precision support should equal to reader precision support - PTF_ASSERT_EQUAL(pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported(), pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported()); + PTF_ASSERT_EQUAL(pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported(), + pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported()); // Write nano precision file pcpp::PcapFileWriterDevice writerDevNano(EXAMPLE_PCAP_NANO_PATH, pcpp::LINKTYPE_ETHERNET, true); - PTF_ASSERT_EQUAL(writerDevNano.getTimestampPrecision(), pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported() - ? pcpp::FileTimestampPrecision::Nanoseconds - : pcpp::FileTimestampPrecision::Microseconds, enumclass); + PTF_ASSERT_EQUAL(writerDevNano.getTimestampPrecision(), + pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported() + ? pcpp::FileTimestampPrecision::Nanoseconds + : pcpp::FileTimestampPrecision::Microseconds, + enumclass); PTF_ASSERT_TRUE(writerDevNano.open()); - PTF_ASSERT_EQUAL(writerDevNano.getTimestampPrecision(), pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported() - ? pcpp::FileTimestampPrecision::Nanoseconds - : pcpp::FileTimestampPrecision::Microseconds, enumclass); + PTF_ASSERT_EQUAL(writerDevNano.getTimestampPrecision(), + pcpp::PcapFileWriterDevice::isNanoSecondPrecisionSupported() + ? pcpp::FileTimestampPrecision::Nanoseconds + : pcpp::FileTimestampPrecision::Microseconds, + enumclass); PTF_ASSERT_TRUE(writerDevNano.writePacket(rawPacketMicro)); PTF_ASSERT_TRUE(writerDevNano.writePacket(rawPacketNano)); writerDevNano.close(); @@ -140,10 +141,10 @@ PTF_TEST_CASE(TestPcapFilePrecision) PTF_ASSERT_EQUAL(readerDevNano.getTimestampPrecision(), pcpp::FileTimestampPrecision::Unknown, enumclass); PTF_ASSERT_TRUE(readerDevNano.open()); PTF_ASSERT_EQUAL(readerDevNano.getTimestampPrecision(), - pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported() - ? pcpp::FileTimestampPrecision::Nanoseconds - : pcpp::FileTimestampPrecision::Microseconds, - enumclass); + pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported() + ? pcpp::FileTimestampPrecision::Nanoseconds + : pcpp::FileTimestampPrecision::Microseconds, + enumclass); pcpp::RawPacket readPacketNano, readPacketMicro; PTF_ASSERT_TRUE(readerDevNano.getNextPacket(readPacketMicro)); @@ -152,7 +153,8 @@ PTF_TEST_CASE(TestPcapFilePrecision) PTF_ASSERT_TRUE(readerDevNano.getNextPacket(readPacketNano)); PTF_ASSERT_EQUAL(readPacketNano.getPacketTimeStamp().tv_sec, 1); - PTF_ASSERT_EQUAL(readPacketNano.getPacketTimeStamp().tv_nsec, pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported() ? 1234 : 1000); + PTF_ASSERT_EQUAL(readPacketNano.getPacketTimeStamp().tv_nsec, + pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported() ? 1234 : 1000); readerDevNano.close(); @@ -161,10 +163,10 @@ PTF_TEST_CASE(TestPcapFilePrecision) PTF_ASSERT_EQUAL(readerDevMicro.getTimestampPrecision(), pcpp::FileTimestampPrecision::Unknown, enumclass); PTF_ASSERT_TRUE(readerDevMicro.open()); PTF_ASSERT_EQUAL(readerDevMicro.getTimestampPrecision(), - pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported() - ? pcpp::FileTimestampPrecision::Nanoseconds - : pcpp::FileTimestampPrecision::Microseconds, - enumclass); + pcpp::PcapFileReaderDevice::isNanoSecondPrecisionSupported() + ? pcpp::FileTimestampPrecision::Nanoseconds + : pcpp::FileTimestampPrecision::Microseconds, + enumclass); pcpp::RawPacket readPacketNano2, readPacketMicro2; PTF_ASSERT_TRUE(readerDevMicro.getNextPacket(readPacketMicro2)); @@ -176,8 +178,7 @@ PTF_TEST_CASE(TestPcapFilePrecision) PTF_ASSERT_EQUAL(readPacketNano2.getPacketTimeStamp().tv_nsec, 1000); readerDevMicro.close(); -} // TestPcapFilePrecision - +} // TestPcapFilePrecision PTF_TEST_CASE(TestPcapSllFileReadWrite) { @@ -230,9 +231,7 @@ PTF_TEST_CASE(TestPcapSllFileReadWrite) readerDev.close(); writerDev.close(); -} // TestPcapSllFileReadWrite - - +} // TestPcapSllFileReadWrite PTF_TEST_CASE(TestPcapSll2FileReadWrite) { @@ -281,9 +280,7 @@ PTF_TEST_CASE(TestPcapSll2FileReadWrite) PTF_ASSERT_EQUAL(ipCount, 3); readerDev.close(); -} // TestPcapSll2FileReadWrite - - +} // TestPcapSll2FileReadWrite PTF_TEST_CASE(TestPcapRawIPFileReadWrite) { @@ -349,9 +346,7 @@ PTF_TEST_CASE(TestPcapRawIPFileReadWrite) readerDev.close(); writerDev.close(); writerNgDev.close(); -} // TestPcapRawIPFileReadWrite - - +} // TestPcapRawIPFileReadWrite PTF_TEST_CASE(TestPcapFileAppend) { @@ -384,16 +379,14 @@ PTF_TEST_CASE(TestPcapFileAppend) while (readerDev.getNextPacket(rawPacket)) counter++; - PTF_ASSERT_EQUAL(counter, (4631*5)); + PTF_ASSERT_EQUAL(counter, (4631 * 5)); pcpp::Logger::getInstance().suppressLogs(); pcpp::PcapFileWriterDevice writerDev2(EXAMPLE_PCAP_WRITE_PATH, pcpp::LINKTYPE_LINUX_SLL); PTF_ASSERT_FALSE(writerDev2.open(true)); pcpp::Logger::getInstance().enableLogs(); -} // TestPcapFileAppend - - +} // TestPcapFileAppend PTF_TEST_CASE(TestPcapNgFileReadWrite) { @@ -478,9 +471,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWrite) writerDev.close(); writerCompressDev.close(); -} // TestPcapNgFileReadWrite - - +} // TestPcapNgFileReadWrite PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) { @@ -496,10 +487,12 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) PTF_ASSERT_TRUE(readerDev.open()); PTF_ASSERT_EQUAL(readerDev.getOS(), "Linux 3.18.1-1-ARCH"); PTF_ASSERT_EQUAL(readerDev.getCaptureApplication(), "Dumpcap (Wireshark) 1.99.1 (Git Rev Unknown from unknown)"); - PTF_ASSERT_EQUAL(readerDev.getCaptureFileComment(), "CLIENT_RANDOM E39B5BF4903C68684E8512FB2F60213E9EE843A0810B4982B607914D8092D482 95A5D39B02693BC1FB39254B179E9293007F6D37C66172B1EE4EF0D5E25CE1DABE878B6143DC3B266883E51A75E99DF9 "); + PTF_ASSERT_EQUAL( + readerDev.getCaptureFileComment(), + "CLIENT_RANDOM E39B5BF4903C68684E8512FB2F60213E9EE843A0810B4982B607914D8092D482 95A5D39B02693BC1FB39254B179E9293007F6D37C66172B1EE4EF0D5E25CE1DABE878B6143DC3B266883E51A75E99DF9 "); PTF_ASSERT_EQUAL(readerDev.getHardware(), ""); - pcpp::PcapNgFileWriterDevice writerDev(EXAMPLE2_PCAPNG_WRITE_PATH); + pcpp::PcapNgFileWriterDevice writerDev(EXAMPLE2_PCAPNG_WRITE_PATH); pcpp::PcapNgFileWriterDevice writerCompressDev(EXAMPLE2_PCAPNG_ZSTD_WRITE_PATH, 5); // negative tests @@ -507,8 +500,11 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) writerCompressDev.close(); // -------------- - PTF_ASSERT_TRUE(writerDev.open(readerDev.getOS().c_str(), "My Hardware", readerDev.getCaptureApplication().c_str(), "This is a comment in a pcap-ng file")); - PTF_ASSERT_TRUE(writerCompressDev.open(readerDev.getOS().c_str(), "My Hardware", readerDev.getCaptureApplication().c_str(), "This is a comment in a pcap-ng file")); + PTF_ASSERT_TRUE(writerDev.open(readerDev.getOS().c_str(), "My Hardware", readerDev.getCaptureApplication().c_str(), + "This is a comment in a pcap-ng file")); + PTF_ASSERT_TRUE(writerCompressDev.open(readerDev.getOS().c_str(), "My Hardware", + readerDev.getCaptureApplication().c_str(), + "This is a comment in a pcap-ng file")); pcpp::RawPacket rawPacket; int packetCount = 0; @@ -593,7 +589,8 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) PTF_ASSERT_TRUE(readerDev3.open()); PTF_ASSERT_EQUAL(readerDevCompress.getOS(), "Linux 3.18.1-1-ARCH\0"); - PTF_ASSERT_EQUAL(readerDevCompress.getCaptureApplication(), "Dumpcap (Wireshark) 1.99.1 (Git Rev Unknown from unknown)"); + PTF_ASSERT_EQUAL(readerDevCompress.getCaptureApplication(), + "Dumpcap (Wireshark) 1.99.1 (Git Rev Unknown from unknown)"); PTF_ASSERT_EQUAL(readerDevCompress.getCaptureFileComment(), "This is a comment in a pcap-ng file"); PTF_ASSERT_EQUAL(readerDevCompress.getHardware(), "My Hardware"); @@ -612,8 +609,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) httpCount = 0; commentCount = 0; - - pcpp::RawPacket rawPacket2,rawPacketCompress; + pcpp::RawPacket rawPacket2, rawPacketCompress; while (readerDev2.getNextPacket(rawPacket, pktComment)) { @@ -680,7 +676,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) if (packet1_timestamp.tv_sec < packetCompress_timestamp.tv_sec) { uint64_t timeDiff = (uint64_t)(packetCompress_timestamp.tv_sec - packet1_timestamp.tv_sec); - PTF_ASSERT_LOWER_THAN(timeDiff,2); + PTF_ASSERT_LOWER_THAN(timeDiff, 2); } else { @@ -714,7 +710,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) readerDev2.close(); readerDev3.close(); - //For now appends are not fully supported with compressed pcapng files + // For now appends are not fully supported with compressed pcapng files pcpp::PcapNgFileWriterDevice appendDev(EXAMPLE2_PCAPNG_WRITE_PATH); PTF_ASSERT_TRUE(appendDev.open(true)); @@ -723,7 +719,6 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) appendDev.close(); - pcpp::PcapNgFileReaderDevice readerDev4(EXAMPLE2_PCAPNG_WRITE_PATH); PTF_ASSERT_TRUE(readerDev4.open()); @@ -739,8 +734,8 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) // ------- // copy the .zstd file to a similar file with .zst extension - std::ifstream zstdFile(EXAMPLE2_PCAPNG_ZSTD_WRITE_PATH, std::ios::binary); - std::ofstream zstFile(EXAMPLE2_PCAPNG_ZST_WRITE_PATH, std::ios::binary); + std::ifstream zstdFile(EXAMPLE2_PCAPNG_ZSTD_WRITE_PATH, std::ios::binary); + std::ofstream zstFile(EXAMPLE2_PCAPNG_ZST_WRITE_PATH, std::ios::binary); zstFile << zstdFile.rdbuf(); zstdFile.close(); zstFile.close(); @@ -779,7 +774,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) PTF_ASSERT_TRUE(writerDev2.setFilter("dst port 35938")); pcpp::PcapNgFileWriterDevice writerCompressDev2(EXAMPLE2_PCAPNG_ZSTD_WRITE_PATH, 5); - PTF_ASSERT_TRUE(writerCompressDev2.open()); //Do not try append mode on compressed files!!! + PTF_ASSERT_TRUE(writerCompressDev2.open()); // Do not try append mode on compressed files!!! PTF_ASSERT_FALSE(writerCompressDev2.setFilter("bla bla bla")); PTF_ASSERT_TRUE(writerCompressDev2.setFilter("dst port 35938")); @@ -789,7 +784,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) while (readerDev5.getNextPacket(rawPacket, pktComment)) { filteredReadPacketCount++; - if(writerDev2.writePacket(rawPacket)) + if (writerDev2.writePacket(rawPacket)) filteredWritePacketCount++; if (writerCompressDev2.writePacket(rawPacket)) filteredCompressWritePacketCount++; @@ -802,9 +797,7 @@ PTF_TEST_CASE(TestPcapNgFileReadWriteAdv) writerCompressDev2.close(); readerDev5.close(); writerDev2.close(); -} // TestPcapNgFileReadWriteAdv - - +} // TestPcapNgFileReadWriteAdv PTF_TEST_CASE(TestPcapNgFileTooManyInterfaces) { @@ -824,9 +817,7 @@ PTF_TEST_CASE(TestPcapNgFileTooManyInterfaces) } PTF_ASSERT_EQUAL(packetCount, 1); readerDev.close(); -} // TestPcapNgFileTooManyInterfaces - - +} // TestPcapNgFileTooManyInterfaces PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv6) { @@ -854,7 +845,6 @@ PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv6) udpCount++; } - pcpp::IPcapDevice::PcapStats readerStatistics; readerDev.getStatistics(readerStatistics); @@ -870,7 +860,7 @@ PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv6) readerDev.close(); PTF_ASSERT_FALSE(readerDev.isOpened()); -} // TestPcapFileReadLinkTypeIPv6 +} // TestPcapFileReadLinkTypeIPv6 PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv4) { @@ -898,7 +888,6 @@ PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv4) udpCount++; } - pcpp::IPcapDevice::PcapStats readerStatistics; readerDev.getStatistics(readerStatistics); @@ -914,7 +903,7 @@ PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv4) readerDev.close(); PTF_ASSERT_FALSE(readerDev.isOpened()); -} // TestPcapFileReadLinkTypeIPv4 +} // TestPcapFileReadLinkTypeIPv4 PTF_TEST_CASE(TestSolarisSnoopFileRead) { @@ -963,4 +952,4 @@ PTF_TEST_CASE(TestSolarisSnoopFileRead) PTF_ASSERT_EQUAL(timeStamps[249].tv_nsec, 499893000); readerDev.close(); -} // TestSolarisSnoopFileRead +} // TestSolarisSnoopFileRead diff --git a/Tests/Pcap++Test/Tests/FilterTests.cpp b/Tests/Pcap++Test/Tests/FilterTests.cpp index ac22767762..13f656fbb0 100644 --- a/Tests/Pcap++Test/Tests/FilterTests.cpp +++ b/Tests/Pcap++Test/Tests/FilterTests.cpp @@ -15,7 +15,6 @@ extern PcapTestArgs PcapTestGlobalArgs; - static int incSleep(const pcpp::RawPacketVector& capturedPackets, size_t expectedPacketCount, int maxTimeToSleep) { int totalSleepTime = 0; @@ -33,8 +32,6 @@ static int incSleep(const pcpp::RawPacketVector& capturedPackets, size_t expecte return totalSleepTime; } - - PTF_TEST_CASE(TestPcapFiltersLive) { pcpp::PcapLiveDevice* liveDev = nullptr; @@ -48,7 +45,7 @@ PTF_TEST_CASE(TestPcapFiltersLive) pcpp::RawPacketVector capturedPackets; //----------- - //IP filter + // IP filter //----------- PTF_PRINT_VERBOSE("Testing IPFilter"); std::string filterAddrAsString(PcapTestGlobalArgs.ipToSendReceivePackets); @@ -57,13 +54,12 @@ PTF_TEST_CASE(TestPcapFiltersLive) PTF_ASSERT_TRUE(liveDev->setFilter(ipFilter)); PTF_ASSERT_TRUE(liveDev->startCapture(capturedPackets)); PTF_ASSERT_TRUE(sendURLRequest("www.google.com")); - //let the capture work for couple of seconds + // let the capture work for couple of seconds int totalSleepTime = incSleep(capturedPackets, 2, 7); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); liveDev->stopCapture(); PTF_ASSERT_GREATER_OR_EQUAL_THAN(capturedPackets.size(), 2); - for (pcpp::RawPacketVector::VectorIterator iter = capturedPackets.begin(); iter != capturedPackets.end(); iter++) { pcpp::Packet packet(*iter); @@ -73,9 +69,8 @@ PTF_TEST_CASE(TestPcapFiltersLive) } capturedPackets.clear(); - //------------ - //Port filter + // Port filter //------------ PTF_PRINT_VERBOSE("Testing PortFilter"); uint16_t filterPort = 80; @@ -84,7 +79,7 @@ PTF_TEST_CASE(TestPcapFiltersLive) PTF_ASSERT_TRUE(liveDev->setFilter(portFilter)); PTF_ASSERT_TRUE(liveDev->startCapture(capturedPackets)); PTF_ASSERT_TRUE(sendURLRequest("www.yahoo.com")); - //let the capture work for couple of seconds + // let the capture work for couple of seconds totalSleepTime = incSleep(capturedPackets, 2, 7); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); liveDev->stopCapture(); @@ -98,9 +93,8 @@ PTF_TEST_CASE(TestPcapFiltersLive) } capturedPackets.clear(); - //---------------- - //IP & Port filter + // IP & Port filter //---------------- PTF_PRINT_VERBOSE("Testing IP and Port Filter"); std::vector andFilterFilters; @@ -111,7 +105,7 @@ PTF_TEST_CASE(TestPcapFiltersLive) PTF_ASSERT_TRUE(liveDev->setFilter(andFilter)); PTF_ASSERT_TRUE(liveDev->startCapture(capturedPackets)); PTF_ASSERT_TRUE(sendURLRequest("www.walla.co.il")); - //let the capture work for couple of seconds + // let the capture work for couple of seconds totalSleepTime = incSleep(capturedPackets, 2, 7); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); liveDev->stopCapture(); @@ -128,9 +122,8 @@ PTF_TEST_CASE(TestPcapFiltersLive) } capturedPackets.clear(); - //----------------- - //IP || Port filter + // IP || Port filter //----------------- PTF_PRINT_VERBOSE("Testing IP or Port Filter"); std::vector orFilterFilters; @@ -142,7 +135,7 @@ PTF_TEST_CASE(TestPcapFiltersLive) PTF_ASSERT_TRUE(liveDev->setFilter(orFilter)); PTF_ASSERT_TRUE(liveDev->startCapture(capturedPackets)); PTF_ASSERT_TRUE(sendURLRequest("www.youtube.com")); - //let the capture work for couple of seconds + // let the capture work for couple of seconds totalSleepTime = incSleep(capturedPackets, 2, 7); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); liveDev->stopCapture(); @@ -171,9 +164,8 @@ PTF_TEST_CASE(TestPcapFiltersLive) } capturedPackets.clear(); - //---------- - //Not filter + // Not filter //---------- PTF_PRINT_VERBOSE("Testing Not IP Filter"); ipFilter.setDirection(pcpp::SRC); @@ -182,7 +174,7 @@ PTF_TEST_CASE(TestPcapFiltersLive) PTF_ASSERT_TRUE(liveDev->setFilter(notFilter)); PTF_ASSERT_TRUE(liveDev->startCapture(capturedPackets)); PTF_ASSERT_TRUE(sendURLRequest("www.ebay.com")); - //let the capture work for couple of seconds + // let the capture work for couple of seconds totalSleepTime = incSleep(capturedPackets, 2, 7); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); liveDev->stopCapture(); @@ -198,13 +190,9 @@ PTF_TEST_CASE(TestPcapFiltersLive) } capturedPackets.clear(); - liveDev->close(); -} // TestPcapFiltersLive - - - +} // TestPcapFiltersLive PTF_TEST_CASE(TestPcapFilters_General_BPFStr) { @@ -214,14 +202,14 @@ PTF_TEST_CASE(TestPcapFilters_General_BPFStr) pcpp::PcapFileReaderDevice fileReaderDev(EXAMPLE_PCAP_VLAN); //------------------------------------ - //Test GeneralFilter + BPFStringFilter + // Test GeneralFilter + BPFStringFilter //------------------------------------ - //Try to make an invalid filter + // Try to make an invalid filter pcpp::BPFStringFilter badFilter("This is not a valid filter"); PTF_ASSERT_FALSE(badFilter.verifyFilter()); - //Test stolen from MacAddress test below + // Test stolen from MacAddress test below pcpp::MacAddress macAddr("00:13:c3:df:ae:18"); pcpp::BPFStringFilter bpfStringFilter("ether dst " + macAddr.toString()); PTF_ASSERT_TRUE(bpfStringFilter.verifyFilter()); @@ -247,10 +235,7 @@ PTF_TEST_CASE(TestPcapFilters_General_BPFStr) PTF_ASSERT_EQUAL(validCounter, 5); rawPacketVec.clear(); -} // TestPcapFilters_General_BPFStr - - - +} // TestPcapFilters_General_BPFStr PTF_TEST_CASE(TestPcapFilters_MatchStatic) { @@ -270,10 +255,7 @@ PTF_TEST_CASE(TestPcapFilters_MatchStatic) } rawPacketVec.clear(); -} // TestPcapFilters_MatchStatic - - - +} // TestPcapFilters_MatchStatic PTF_TEST_CASE(TestPcapFiltersOffline) { @@ -286,7 +268,7 @@ PTF_TEST_CASE(TestPcapFiltersOffline) pcpp::PcapFileReaderDevice fileReaderDev4(EXAMPLE_PCAP_IGMP); //----------------- - //VLAN filter + // VLAN filter //----------------- pcpp::VlanFilter vlanFilter(118); @@ -308,9 +290,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //-------------------- - //MacAddress filter + // MacAddress filter //-------------------- pcpp::MacAddress macAddrToFilter("00:13:c3:df:ae:18"); pcpp::MacAddressFilter macAddrFilter(macAddrToFilter, pcpp::DST); @@ -331,9 +312,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //-------------------- - //EtherType filter + // EtherType filter //-------------------- pcpp::EtherTypeFilter ethTypeFiler(PCPP_ETHERTYPE_VLAN); ethTypeFiler.parseToString(filterAsString); @@ -352,9 +332,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //-------------------- - //IPv4 ID filter + // IPv4 ID filter //-------------------- uint16_t ipID(0x9900); pcpp::IPv4IDFilter ipIDFiler(ipID, pcpp::GREATER_THAN); @@ -376,9 +355,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //------------------------- - //IPv4 Total Length filter + // IPv4 Total Length filter //------------------------- uint16_t totalLength(576); pcpp::IPv4TotalLengthFilter ipTotalLengthFiler(totalLength, pcpp::LESS_OR_EQUAL); @@ -400,9 +378,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //------------------------- - //TCP window size filter + // TCP window size filter //------------------------- uint16_t windowSize(8312); pcpp::TcpWindowSizeFilter tcpWindowSizeFilter(windowSize, pcpp::NOT_EQUALS); @@ -424,9 +401,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //------------------------- - //UDP length filter + // UDP length filter //------------------------- uint16_t udpLength(46); pcpp::UdpLengthFilter udpLengthFilter(udpLength, pcpp::EQUALS); @@ -448,15 +424,15 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //------------------------- - //IP filter with mask + // IP filter with mask //------------------------- pcpp::IPFilter ipFilterWithMask("212.199.202.9", pcpp::SRC, "255.255.255.0"); ipFilterWithMask.parseToString(filterAsString); PTF_ASSERT_EQUAL(filterAsString, "ip and src net 212.199.202.0/24"); - PTF_ASSERT_RAISES(ipFilterWithMask.setAddr("BogusIPAddressString"), std::invalid_argument, "Not a valid IP address: BogusIPAddressString"); + PTF_ASSERT_RAISES(ipFilterWithMask.setAddr("BogusIPAddressString"), std::invalid_argument, + "Not a valid IP address: BogusIPAddressString"); PTF_ASSERT_TRUE(fileReaderDev2.open()); PTF_ASSERT_TRUE(fileReaderDev2.setFilter(ipFilterWithMask)); @@ -518,7 +494,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) ipFilterWithMask.parseToString(filterAsString); PTF_ASSERT_EQUAL(filterAsString, "ip6 and src net 2001:db8:3333:4444:cccc:dddd:eeee:ffff/128"); - PTF_ASSERT_RAISES(ipFilterWithMask.setMask("255.255.255.255"), std::invalid_argument, "Netmask is not valid IPv6 format: 255.255.255.255"); + PTF_ASSERT_RAISES(ipFilterWithMask.setMask("255.255.255.255"), std::invalid_argument, + "Netmask is not valid IPv6 format: 255.255.255.255"); ipFilterWithMask.setMask("ffff:ffff:ffff::"); ipFilterWithMask.parseToString(filterAsString); PTF_ASSERT_EQUAL(filterAsString, "ip6 and src net 2001:db8:3333::/48"); @@ -546,7 +523,7 @@ PTF_TEST_CASE(TestPcapFiltersOffline) { pcpp::Packet packet(*iter); PTF_ASSERT_TRUE(packet.isPacketOfType(pcpp::IPv6)); - pcpp::IPv6Layer *ipLayer = packet.getLayerOfType(); + pcpp::IPv6Layer* ipLayer = packet.getLayerOfType(); // This is essentially matching the host address, but it will have to do for the current sample. PTF_ASSERT_TRUE(ipLayer->getSrcIPv6Address().matchNetwork("2001:db8:0:12::1/128")); } @@ -563,13 +540,13 @@ PTF_TEST_CASE(TestPcapFiltersOffline) { pcpp::Packet packet(*iter); PTF_ASSERT_TRUE(packet.isPacketOfType(pcpp::IPv6)); - pcpp::IPv6Layer *ipLayer = packet.getLayerOfType(); + pcpp::IPv6Layer* ipLayer = packet.getLayerOfType(); PTF_ASSERT_TRUE(ipLayer->getSrcIPv6Address().matchNetwork("2001:db8:0:12::/64")); } rawPacketVec.clear(); //------------- - //Port range + // Port range //------------- pcpp::PortRangeFilter portRangeFilter(40000, 50000, pcpp::SRC); portRangeFilter.parseToString(filterAsString); @@ -589,22 +566,21 @@ PTF_TEST_CASE(TestPcapFiltersOffline) { pcpp::TcpLayer* tcpLayer = packet.getLayerOfType(); uint16_t portSrc = tcpLayer->getSrcPort(); - PTF_ASSERT_TRUE(portSrc >= 40000 && portSrc <=50000); + PTF_ASSERT_TRUE(portSrc >= 40000 && portSrc <= 50000); } else if (packet.isPacketOfType(pcpp::UDP)) { pcpp::UdpLayer* udpLayer = packet.getLayerOfType(); uint16_t portSrc = udpLayer->getSrcPort(); - PTF_ASSERT_TRUE(portSrc >= 40000 && portSrc <=50000); + PTF_ASSERT_TRUE(portSrc >= 40000 && portSrc <= 50000); } } rawPacketVec.clear(); - //------------------------- - //TCP flags filter + // TCP flags filter //------------------------- - uint8_t tcpFlagsBitMask(pcpp::TcpFlagsFilter::tcpSyn|pcpp::TcpFlagsFilter::tcpAck); + uint8_t tcpFlagsBitMask(pcpp::TcpFlagsFilter::tcpSyn | pcpp::TcpFlagsFilter::tcpAck); pcpp::TcpFlagsFilter tcpFlagsFilter(tcpFlagsBitMask, pcpp::TcpFlagsFilter::MatchAll); tcpFlagsFilter.parseToString(filterAsString); @@ -643,9 +619,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //------------ - //Proto filter + // Proto filter //------------ // ARP proto @@ -734,7 +709,7 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); //----------------------- - //And filter - Proto + IP + // And filter - Proto + IP //----------------------- pcpp::IPFilter ipFilter("10.0.0.6", pcpp::SRC); @@ -785,9 +760,8 @@ PTF_TEST_CASE(TestPcapFiltersOffline) rawPacketVec.clear(); - //------------------------------------------ - //Complex filter - (Proto1 and IP) || Proto2 + // Complex filter - (Proto1 and IP) || Proto2 //------------------------------------------ protoFilter.setProto(pcpp::GRE); @@ -826,9 +800,9 @@ PTF_TEST_CASE(TestPcapFiltersOffline) PTF_ASSERT_TRUE(packet.isPacketOfType(pcpp::GRE)); PTF_ASSERT_TRUE(packet.isPacketOfType(pcpp::IPv4)); pcpp::IPv4Layer* ipv4Layer = packet.getLayerOfType(); - PTF_ASSERT_TRUE(ipv4Layer->getSrcIPAddress().toString() == "20.0.0.1" || ipv4Layer->getDstIPAddress().toString() == "20.0.0.1"); + PTF_ASSERT_TRUE(ipv4Layer->getSrcIPAddress().toString() == "20.0.0.1" || + ipv4Layer->getDstIPAddress().toString() == "20.0.0.1"); } - } rawPacketVec.clear(); } @@ -848,12 +822,13 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer) for (pcpp::RawPacketVector::VectorIterator iter = rawPacketVec.begin(); iter != rawPacketVec.end(); iter++) { pcpp::Packet packet(*iter); - if(pcpp::IPv4Layer* ip4layer = packet.getLayerOfType()) + if (pcpp::IPv4Layer* ip4layer = packet.getLayerOfType()) { - pcpp::BPFStringFilter bpfStringFilter("host " + ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter + pcpp::BPFStringFilter bpfStringFilter( + "host " + ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter if (bpfStringFilter.matchPacketWithFilter(*iter)) { - if((*iter)->getLinkLayerType() == pcpp::LINKTYPE_DLT_RAW1) + if ((*iter)->getLinkLayerType() == pcpp::LINKTYPE_DLT_RAW1) { ++validCounter; } @@ -863,7 +838,6 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer) PTF_ASSERT_EQUAL(validCounter, 50); rawPacketVec.clear(); - // pcpp::LINKTYPE_LINUX_SLL layer pcpp::PcapFileReaderDevice fileReaderDev2(SLL_PCAP_PATH); PTF_ASSERT_TRUE(fileReaderDev2.open()); @@ -874,12 +848,13 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer) for (pcpp::RawPacketVector::VectorIterator iter = rawPacketVec.begin(); iter != rawPacketVec.end(); iter++) { pcpp::Packet packet(*iter); - if(pcpp::IPv4Layer* ip4layer = packet.getLayerOfType()) + if (pcpp::IPv4Layer* ip4layer = packet.getLayerOfType()) { - pcpp::BPFStringFilter bpfStringFilter("host " + ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter + pcpp::BPFStringFilter bpfStringFilter( + "host " + ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter if (bpfStringFilter.matchPacketWithFilter(*iter)) { - if((*iter)->getLinkLayerType() == pcpp::LINKTYPE_LINUX_SLL) + if ((*iter)->getLinkLayerType() == pcpp::LINKTYPE_LINUX_SLL) { ++validCounter; } @@ -889,7 +864,6 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer) PTF_ASSERT_EQUAL(validCounter, 510); rawPacketVec.clear(); - // pcpp::LINKTYPE_ETHERNET layer pcpp::PcapNgFileReaderDevice fileReaderDev3(EXAMPLE_PCAPNG_PATH); PTF_ASSERT_TRUE(fileReaderDev3.open()); @@ -900,12 +874,13 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer) for (pcpp::RawPacketVector::VectorIterator iter = rawPacketVec.begin(); iter != rawPacketVec.end(); iter++) { pcpp::Packet packet(*iter); - if(pcpp::IPv4Layer* ip4layer = packet.getLayerOfType()) + if (pcpp::IPv4Layer* ip4layer = packet.getLayerOfType()) { - pcpp::BPFStringFilter bpfStringFilter("host " + ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter + pcpp::BPFStringFilter bpfStringFilter( + "host " + ip4layer->getDstIPAddress().toString()); // checking against real filter, not the "" filter if (bpfStringFilter.matchPacketWithFilter(*iter)) { - if((*iter)->getLinkLayerType() == pcpp::LINKTYPE_ETHERNET) + if ((*iter)->getLinkLayerType() == pcpp::LINKTYPE_ETHERNET) { ++validCounter; } @@ -914,4 +889,4 @@ PTF_TEST_CASE(TestPcapFilters_LinkLayer) } PTF_ASSERT_EQUAL(validCounter, 62); rawPacketVec.clear(); -} // TestPcapFilters_LinkLayer +} // TestPcapFilters_LinkLayer diff --git a/Tests/Pcap++Test/Tests/IPFragmentationTests.cpp b/Tests/Pcap++Test/Tests/IPFragmentationTests.cpp index b7c3fae859..fcacbb6888 100644 --- a/Tests/Pcap++Test/Tests/IPFragmentationTests.cpp +++ b/Tests/Pcap++Test/Tests/IPFragmentationTests.cpp @@ -6,14 +6,13 @@ #include "PcapFileDevice.h" #include "EndianPortable.h" - static void ipReassemblyOnFragmentsClean(const pcpp::IPReassembly::PacketKey* key, void* userCookie) { - pcpp::PointerVector* packetsRemoved = (pcpp::PointerVector*)userCookie; + pcpp::PointerVector* packetsRemoved = + (pcpp::PointerVector*)userCookie; packetsRemoved->pushBack(key->clone()); } - PTF_TEST_CASE(TestIPFragmentationSanity) { std::vector packetStream; @@ -75,8 +74,7 @@ PTF_TEST_CASE(TestIPFragmentationSanity) PTF_ASSERT_BUF_COMPARE(result->getRawPacket()->getRawData(), buffer, bufferLength); delete result; - delete [] buffer; - + delete[] buffer; // basic IPv6 reassembly test // ========================== @@ -129,8 +127,7 @@ PTF_TEST_CASE(TestIPFragmentationSanity) PTF_ASSERT_BUF_COMPARE(result->getRawPacket()->getRawData(), buffer, bufferLength); delete result; - delete [] buffer; - + delete[] buffer; // non-fragment test // ================== @@ -149,7 +146,6 @@ PTF_TEST_CASE(TestIPFragmentationSanity) PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::NON_FRAGMENT, enum); } - // non-IP test // ================== @@ -163,8 +159,7 @@ PTF_TEST_CASE(TestIPFragmentationSanity) PTF_ASSERT_EQUAL(result, &packet, ptr); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::NON_IP_PACKET, enum); } -} // TestIPFragmentationSanity - +} // TestIPFragmentationSanity PTF_TEST_CASE(TestIPFragOutOfOrder) { @@ -179,7 +174,6 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) int bufferLength = 0; uint8_t* buffer = readFileIntoBuffer("PcapExamples/frag_http_req_reassembled.txt", bufferLength); - // First use-case: first and second fragments are swapped // ====================================================== @@ -203,7 +197,7 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) { PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FIRST_FRAGMENT, enum); } - else if (i < (packetStream.size()-1)) + else if (i < (packetStream.size() - 1)) { PTF_ASSERT_NULL(result); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); @@ -224,16 +218,15 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) packetStream.clear(); - // Second use-case: 6th and 10th fragments are swapped, as well as 3rd and 7th // =========================================================================== PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/frag_http_req.pcap", packetStream, errMsg)); - //swap 6th and 10th fragments + // swap 6th and 10th fragments std::swap(packetStream[5], packetStream[9]); - //swap 3rd and 7th fragments + // swap 3rd and 7th fragments std::swap(packetStream[2], packetStream[6]); PTF_PRINT_VERBOSE("Second use-case: iterating over packet stream"); @@ -252,7 +245,7 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) { PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FIRST_FRAGMENT, enum); } - else if (i < (packetStream.size()-1)) + else if (i < (packetStream.size() - 1)) { PTF_ASSERT_NULL(result); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); @@ -273,13 +266,12 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) packetStream.clear(); - // Third use-case: last fragment comes before the end // ================================================== PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/frag_http_req.pcap", packetStream, errMsg)); - //swap 6th and last fragments + // swap 6th and last fragments std::swap(packetStream[5], packetStream[10]); PTF_PRINT_VERBOSE("Third use-case: iterating over packet stream"); @@ -289,7 +281,7 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) pcpp::Packet packet(&packetStream.at(i)); result = ipReassembly.processPacket(&packet, status); - if (i >= 5 && i < (packetStream.size()-1)) + if (i >= 5 && i < (packetStream.size() - 1)) { PTF_ASSERT_NULL(result); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::OUT_OF_ORDER_FRAGMENT, enum); @@ -319,7 +311,6 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) packetStream.clear(); - // Fourth use-case: last fragment comes first // ========================================== @@ -346,7 +337,7 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) { PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FIRST_FRAGMENT, enum); } - else if (i < (packetStream.size()-1)) + else if (i < (packetStream.size() - 1)) { PTF_ASSERT_NULL(result); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); @@ -367,7 +358,6 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) packetStream.clear(); - // Fifth use-case: fragments come in reverse order // =============================================== @@ -388,7 +378,7 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) pcpp::Packet packet(&packetStream.at(i)); result = ipReassembly.processPacket(&packet, status); - if (i < (packetStream.size()-1)) + if (i < (packetStream.size() - 1)) { PTF_ASSERT_NULL(result); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::OUT_OF_ORDER_FRAGMENT, enum); @@ -408,8 +398,7 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) packetStream.clear(); - delete [] buffer; - + delete[] buffer; // Sixth use-case: IPv6: fragments 1 and 3 are swapped, as well as fragments 6 and 7 // ================================================================================= @@ -457,9 +446,8 @@ PTF_TEST_CASE(TestIPFragOutOfOrder) delete result; - delete [] buffer2; -} // TestIPFragOutOfOrder - + delete[] buffer2; +} // TestIPFragOutOfOrder PTF_TEST_CASE(TestIPFragPartialData) { @@ -483,7 +471,8 @@ PTF_TEST_CASE(TestIPFragPartialData) ipReassembly.processPacket(&packet, status); } - pcpp::IPReassembly::IPv4PacketKey ip4Key(16991, pcpp::IPv4Address(std::string("172.16.133.54")), pcpp::IPv4Address(std::string("216.137.33.81"))); + pcpp::IPReassembly::IPv4PacketKey ip4Key(16991, pcpp::IPv4Address(std::string("172.16.133.54")), + pcpp::IPv4Address(std::string("216.137.33.81"))); pcpp::Packet* partialPacket = ipReassembly.getCurrentPacket(ip4Key); PTF_ASSERT_NOT_NULL(partialPacket); @@ -491,8 +480,7 @@ PTF_TEST_CASE(TestIPFragPartialData) PTF_ASSERT_BUF_COMPARE(partialPacket->getRawPacket()->getRawData(), buffer, bufferLength); delete partialPacket; - delete [] buffer; - + delete[] buffer; // IPv6 partial data // ~~~~~~~~~~~~~~~~~ @@ -515,7 +503,8 @@ PTF_TEST_CASE(TestIPFragPartialData) ipReassembly.processPacket(&packet, status); } - pcpp::IPReassembly::IPv6PacketKey ip6Key(0x2c5323, pcpp::IPv6Address(std::string("fe80::21f:f3ff:fecd:f617")), pcpp::IPv6Address(std::string("ff02::fb"))); + pcpp::IPReassembly::IPv6PacketKey ip6Key(0x2c5323, pcpp::IPv6Address(std::string("fe80::21f:f3ff:fecd:f617")), + pcpp::IPv6Address(std::string("ff02::fb"))); partialPacket = ipReassembly.getCurrentPacket(ip6Key); PTF_ASSERT_EQUAL(partialPacket->getRawPacket()->getRawDataLen(), bufferLength); PTF_ASSERT_BUF_COMPARE(partialPacket->getRawPacket()->getRawData(), buffer, bufferLength); @@ -523,9 +512,8 @@ PTF_TEST_CASE(TestIPFragPartialData) PTF_ASSERT_NOT_NULL(partialPacket); delete partialPacket; - delete [] buffer; -} // TestIPFragPartialData - + delete[] buffer; +} // TestIPFragPartialData PTF_TEST_CASE(TestIPFragMultipleFrags) { @@ -549,7 +537,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) pcpp::RawPacketVector ip6Packet3Frags; pcpp::RawPacketVector ip6Packet4Frags; - PTF_ASSERT_EQUAL(reader.getNextPackets(ip4Packet1Frags, 6), 6); PTF_ASSERT_EQUAL(reader.getNextPackets(ip4Packet2Frags, 6), 6); PTF_ASSERT_EQUAL(reader.getNextPackets(ip4Packet3Frags, 6), 6); @@ -585,7 +572,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) pcpp::Packet* ip6Packet3; pcpp::Packet* ip6Packet4; - pcpp::IPReassembly ipReassembly; pcpp::IPReassembly::ReassemblyStatus status; @@ -628,13 +614,12 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 10); - // read 2nd - 5th frag in each packet PTF_PRINT_VERBOSE("read 2nd - 5th frag in each packet"); for (int i = 1; i < 5; i++) { - PTF_PRINT_VERBOSE("Frag#" << i+1); + PTF_PRINT_VERBOSE("Frag#" << i + 1); ip4Packet1 = ipReassembly.processPacket(ip4Packet1Frags.at(i), status); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); @@ -670,7 +655,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 10); - // read 6th frag in IPv4 packets 1,2,3 ip4Packet1 = ipReassembly.processPacket(ip4Packet1Frags.at(5), status); @@ -685,7 +669,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 7); - // read IPv4 packet5 ip4Packet5 = ipReassembly.processPacket(ip4Packet5Vec.at(0), status); @@ -693,7 +676,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_NOT_NULL(ip4Packet5); PTF_ASSERT_EQUAL(ip4Packet5->getRawPacket(), ip4Packet5Vec.at(0), ptr); - // read 6th - 7th frag in IPv6 packets 1,4 ip6Packet1 = ipReassembly.processPacket(ip6Packet1Frags.at(5), status); @@ -711,13 +693,12 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 5); - // read 6th - 9th frag in IPv4 packets 4,6,8 and IPv6 packet 2 PTF_PRINT_VERBOSE("read 6th - 9th frag in IPv4 packets 4,6,8 and IPv6 packet 2"); for (int i = 5; i < 9; i++) { - PTF_PRINT_VERBOSE("Frag#" << i+1); + PTF_PRINT_VERBOSE("Frag#" << i + 1); ip4Packet4 = ipReassembly.processPacket(ip4Packet4Frags.at(i), status); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); @@ -733,13 +714,12 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_NULL(ip6Packet2); } - // read 6th - 9th frag in IPv6 packet 3 PTF_PRINT_VERBOSE("read 6th - 8th frag in IPv6 packet 3"); for (int i = 5; i < 8; i++) { - PTF_PRINT_VERBOSE("Frag#" << i+1); + PTF_PRINT_VERBOSE("Frag#" << i + 1); ip6Packet3 = ipReassembly.processPacket(ip6Packet3Frags.at(i), status); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); PTF_ASSERT_NULL(ip6Packet3); @@ -751,7 +731,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 4, enum); - // read IPv4 packet7 ip4Packet7 = ipReassembly.processPacket(ip4Packet7Vec.at(0), status); @@ -759,7 +738,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_NOT_NULL(ip4Packet7); PTF_ASSERT_EQUAL(ip4Packet7->getRawPacket(), ip4Packet7Vec.at(0), ptr); - // read 10th frag in IPv4 packets 4,6,8 ip4Packet4 = ipReassembly.processPacket(ip4Packet4Frags.at(9), status); @@ -774,7 +752,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 1); - // read IPv4 packet 9 ip4Packet9 = ipReassembly.processPacket(ip4Packet9Vec.at(0), status); @@ -782,7 +759,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_NOT_NULL(ip4Packet9); PTF_ASSERT_EQUAL(ip4Packet9->getRawPacket(), ip4Packet9Vec.at(0), ptr); - // read 11th frag in IPv4 packets 4,6 (duplicated last frag) PTF_ASSERT_NULL(ipReassembly.processPacket(ip4Packet4Frags.at(10), status)); @@ -790,13 +766,12 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_NULL(ipReassembly.processPacket(ip4Packet6Frags.at(10), status)); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::OUT_OF_ORDER_FRAGMENT, enum); - // read 10th - 13th frag in IPv6 packet 2 PTF_PRINT_VERBOSE("read 10th - 12th frag in IPv6 packet 2"); for (int i = 9; i < 12; i++) { - PTF_PRINT_VERBOSE("Frag#" << i+1); + PTF_PRINT_VERBOSE("Frag#" << i + 1); ip6Packet2 = ipReassembly.processPacket(ip6Packet2Frags.at(i), status); PTF_ASSERT_EQUAL(status, pcpp::IPReassembly::FRAGMENT, enum); PTF_ASSERT_NULL(ip6Packet2); @@ -808,7 +783,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 2); - int buffer1Length = 0; uint8_t* buffer1 = readFileIntoBuffer("PcapExamples/ip4_fragments_packet1.txt", buffer1Length); PTF_ASSERT_EQUAL(ip4Packet1->getRawPacket()->getRawDataLen(), buffer1Length); @@ -838,7 +812,6 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) PTF_ASSERT_EQUAL(ip6Packet2->getRawPacket()->getRawDataLen(), buffer62Length); PTF_ASSERT_BUF_COMPARE(ip6Packet2->getRawPacket()->getRawData(), buffer62, buffer62Length); - delete ip4Packet1; delete ip4Packet2; delete ip4Packet3; @@ -853,13 +826,12 @@ PTF_TEST_CASE(TestIPFragMultipleFrags) delete ip6Packet3; delete ip6Packet4; - delete [] buffer1; - delete [] buffer4; - delete [] buffer6; - delete [] buffer61; - delete [] buffer62; -} // TestIPFragMultipleFrags - + delete[] buffer1; + delete[] buffer4; + delete[] buffer6; + delete[] buffer61; + delete[] buffer62; +} // TestIPFragMultipleFrags PTF_TEST_CASE(TestIPFragMapOverflow) { @@ -901,7 +873,6 @@ PTF_TEST_CASE(TestIPFragMapOverflow) PTF_ASSERT_EQUAL(reader2.getNextPackets(ip6Packet3Frags, 9), 9); PTF_ASSERT_EQUAL(reader2.getNextPackets(ip6Packet4Frags, 7), 7); - pcpp::PointerVector packetsRemovedFromIPReassemblyEngine; pcpp::IPReassembly ipReassembly(ipReassemblyOnFragmentsClean, &packetsRemovedFromIPReassemblyEngine, 3); @@ -909,7 +880,6 @@ PTF_TEST_CASE(TestIPFragMapOverflow) PTF_ASSERT_EQUAL(ipReassembly.getMaxCapacity(), 3); PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 0); - pcpp::IPReassembly::ReassemblyStatus status; ipReassembly.processPacket(ip6Packet1Frags.at(0), status); @@ -967,8 +937,7 @@ PTF_TEST_CASE(TestIPFragMapOverflow) PTF_ASSERT_EQUAL(ip4Key->getIpID(), 0x1ea3); PTF_ASSERT_EQUAL(ip4Key->getSrcIP(), pcpp::IPv4Address(std::string("10.118.213.212"))); PTF_ASSERT_EQUAL(ip4Key->getDstIP(), pcpp::IPv4Address(std::string("10.118.213.211"))); -} // TestIPFragMapOverflow - +} // TestIPFragMapOverflow PTF_TEST_CASE(TestIPFragRemove) { @@ -1071,8 +1040,7 @@ PTF_TEST_CASE(TestIPFragRemove) ipReassembly.processPacket(ip4Packet8Frags.at(0), status); PTF_ASSERT_EQUAL(ipReassembly.getCurrentCapacity(), 6); -} // TestIPFragRemove - +} // TestIPFragRemove PTF_TEST_CASE(TestIPFragWithPadding) { @@ -1103,5 +1071,5 @@ PTF_TEST_CASE(TestIPFragWithPadding) PTF_ASSERT_BUF_COMPARE(result->getRawPacket()->getRawData(), buffer, bufferLength); delete result; - delete [] buffer; -} // TestIPFragWithPadding + delete[] buffer; +} // TestIPFragWithPadding diff --git a/Tests/Pcap++Test/Tests/IpMacTests.cpp b/Tests/Pcap++Test/Tests/IpMacTests.cpp index 88a09a4760..7fa15a470f 100644 --- a/Tests/Pcap++Test/Tests/IpMacTests.cpp +++ b/Tests/Pcap++Test/Tests/IpMacTests.cpp @@ -17,7 +17,6 @@ #include "PcapLiveDeviceList.h" #include "SystemUtils.h" - extern PcapTestArgs PcapTestGlobalArgs; PTF_TEST_CASE(TestIPAddress) @@ -64,7 +63,7 @@ PTF_TEST_CASE(TestIPAddress) PTF_ASSERT_TRUE(ip4AddrFromIpAddr != inAddr_v4); PTF_ASSERT_TRUE(inAddr_v4 != ip4AddrFromIpAddr); - // Equality between different in_addr and IPAddress. + // Equality between different in_addr and IPAddress. PTF_ASSERT_FALSE(ip4Addr == inAddr_v4); PTF_ASSERT_FALSE(inAddr_v4 == ip4Addr); PTF_ASSERT_TRUE(ip4Addr != inAddr_v4); @@ -74,8 +73,8 @@ PTF_TEST_CASE(TestIPAddress) // networks pcpp::IPv4Address ipv4Addr("10.0.0.4"); auto networks = std::vector>{ - std::tuple{"10.8.0.0", "8", "255.0.0.0"}, - std::tuple{"10.0.0.0", "24", "255.255.255.0"} + std::tuple{ "10.8.0.0", "8", "255.0.0.0" }, + std::tuple{ "10.0.0.0", "24", "255.255.255.0" } }; for (const auto& network : networks) { @@ -87,7 +86,8 @@ PTF_TEST_CASE(TestIPAddress) } pcpp::Logger::getInstance().suppressLogs(); - auto invalidMasks = std::vector{"aaaa", "10.0.0.0", "10.0.0.0/aa", "10.0.0.0/33", "999.999.1.1/24", "10.10.10.10/99.99.99"}; + auto invalidMasks = std::vector{ "aaaa", "10.0.0.0", "10.0.0.0/aa", + "10.0.0.0/33", "999.999.1.1/24", "10.10.10.10/99.99.99" }; for (const auto& invalidMask : invalidMasks) { PTF_ASSERT_FALSE(ipv4Addr.matchNetwork(invalidMask)); @@ -95,7 +95,8 @@ PTF_TEST_CASE(TestIPAddress) pcpp::Logger::getInstance().enableLogs(); PTF_ASSERT_RAISES(pcpp::IPv4Address("invalid"), std::invalid_argument, "Not a valid IPv4 address: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv4Address("321.123.1000.1"), std::invalid_argument, "Not a valid IPv4 address: 321.123.1000.1"); + PTF_ASSERT_RAISES(pcpp::IPv4Address("321.123.1000.1"), std::invalid_argument, + "Not a valid IPv4 address: 321.123.1000.1"); std::string ip6AddrString("2607:f0d0:1002:51::4"); pcpp::IPAddress ip6Addr = pcpp::IPAddress(ip6AddrString); @@ -114,7 +115,8 @@ PTF_TEST_CASE(TestIPAddress) } uint8_t addrAsByteArray[16]; ip6AddrFromIpAddr.copyTo(addrAsByteArray); - uint8_t expectedByteArray[16] = { 0x26, 0x07, 0xF0, 0xD0, 0x10, 0x02, 0x00, 0x51, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }; + uint8_t expectedByteArray[16] = { 0x26, 0x07, 0xF0, 0xD0, 0x10, 0x02, 0x00, 0x51, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 }; for (int i = 0; i < 16; i++) { PTF_ASSERT_EQUAL(addrAsByteArray[i], expectedByteArray[i]); @@ -158,16 +160,17 @@ PTF_TEST_CASE(TestIPAddress) PTF_ASSERT_EQUAL(ip6AddrFromIpAddr, secondIPv6Address); PTF_ASSERT_RAISES(pcpp::IPv6Address("invalid"), std::invalid_argument, "Not a valid IPv6 address: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv6Address("zzzz:2222:1002:0051:0000:0000:0000:0004"), std::invalid_argument, "Not a valid IPv6 address: zzzz:2222:1002:0051:0000:0000:0000:0004"); + PTF_ASSERT_RAISES(pcpp::IPv6Address("zzzz:2222:1002:0051:0000:0000:0000:0004"), std::invalid_argument, + "Not a valid IPv6 address: zzzz:2222:1002:0051:0000:0000:0000:0004"); // networks pcpp::IPv6Address ip6Addr2("2607:f0d0:1002:0051:ffff::0004"); pcpp::IPv6Address ipv6NetworkPrefix("2607:f0d0:1002:0051:fffe::"); auto ipv6Networks = std::vector>{ - std::tuple{64, "64", "ffff:ffff:ffff:ffff::"}, - std::tuple{32, "32", "ffff:ffff::"}, - std::tuple{79, "79", "ffff:ffff:ffff:ffff:fffe::"}, - std::tuple{0, "0", "::"} + std::tuple{ 64, "64", "ffff:ffff:ffff:ffff::" }, + std::tuple{ 32, "32", "ffff:ffff::" }, + std::tuple{ 79, "79", "ffff:ffff:ffff:ffff:fffe::" }, + std::tuple{ 0, "0", "::" } }; for (const auto& ipv6Network : ipv6Networks) @@ -181,8 +184,8 @@ PTF_TEST_CASE(TestIPAddress) } auto ipv6NetworksNotMatch = std::vector>{ - std::tuple{80, "80", "ffff:ffff:ffff:ffff:ffff::"}, - std::tuple{128, "128", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"} + std::tuple{ 80, "80", "ffff:ffff:ffff:ffff:ffff::" }, + std::tuple{ 128, "128", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" } }; for (const auto& ipv6Network : ipv6NetworksNotMatch) @@ -242,13 +245,12 @@ PTF_TEST_CASE(TestIPAddress) PTF_ASSERT_FALSE(baseIPv6_2 < baseIpv4_1); PTF_ASSERT_FALSE(baseIPv6_1 < baseIpv4_2); PTF_ASSERT_FALSE(baseIPv6_2 < baseIpv4_2); -} // TestIPAddress - +} // TestIPAddress PTF_TEST_CASE(TestMacAddress) { - pcpp::MacAddress macAddr1(0x11,0x2,0x33,0x4,0x55,0x6); - pcpp::MacAddress macAddr2(0x11,0x2,0x33,0x4,0x55,0x6); + pcpp::MacAddress macAddr1(0x11, 0x2, 0x33, 0x4, 0x55, 0x6); + pcpp::MacAddress macAddr2(0x11, 0x2, 0x33, 0x4, 0x55, 0x6); PTF_ASSERT_EQUAL(macAddr1, macAddr2); pcpp::MacAddress macAddr3(std::string("11:02:33:04:55:06")); @@ -260,7 +262,8 @@ PTF_TEST_CASE(TestMacAddress) // verify if some one try to use char[6] or char* to express MAC address in bytes char invalidCharArrayAddress[6] = { 0x11, 0x2, 0x33, 0x4, 0x55, 0x6 }; - PTF_ASSERT_RAISES(pcpp::MacAddress{invalidCharArrayAddress}, std::invalid_argument, "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); + PTF_ASSERT_RAISES(pcpp::MacAddress{ invalidCharArrayAddress }, std::invalid_argument, + "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); PTF_ASSERT_EQUAL(macAddr1.toString(), "11:02:33:04:55:06"); std::ostringstream oss; @@ -275,29 +278,33 @@ PTF_TEST_CASE(TestMacAddress) PTF_ASSERT_EQUAL(arrToCopyTo[3], 0x04, hex); PTF_ASSERT_EQUAL(arrToCopyTo[4], 0x55, hex); PTF_ASSERT_EQUAL(arrToCopyTo[5], 0x06, hex); - delete [] arrToCopyTo; + delete[] arrToCopyTo; uint8_t macBytes[6]; macAddr3.copyTo(macBytes); PTF_ASSERT_BUF_COMPARE(macBytes, addrAsArr, 6); - #if __cplusplus > 199711L || _MSC_VER >= 1800 - pcpp::MacAddress macCpp11Valid { 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }; - PTF_ASSERT_RAISES(pcpp::MacAddress({ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }), std::invalid_argument, "Invalid initializer list size, should be 6"); - #endif +#if __cplusplus > 199711L || _MSC_VER >= 1800 + pcpp::MacAddress macCpp11Valid{ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }; + PTF_ASSERT_RAISES(pcpp::MacAddress({ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB }), std::invalid_argument, + "Invalid initializer list size, should be 6"); +#endif pcpp::MacAddress mac6(macAddr1); PTF_ASSERT_EQUAL(mac6, macAddr1); mac6 = macAddr2; PTF_ASSERT_EQUAL(mac6, macAddr2); - pcpp::MacAddress macWithZero("aa:aa:00:aa:00:aa"); // valid - PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa:aa:aa:aa:bb:bb:bb:bb"), std::invalid_argument, "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); - PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa"), std::invalid_argument, "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); - PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa:ZZ:aa:aa"), std::invalid_argument, "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); - PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa:aa:aa:aa:"), std::invalid_argument, "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); -} // TestMacAddress - + pcpp::MacAddress macWithZero("aa:aa:00:aa:00:aa"); // valid + PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa:aa:aa:aa:bb:bb:bb:bb"), std::invalid_argument, + "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); + PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa"), std::invalid_argument, + "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); + PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa:ZZ:aa:aa"), std::invalid_argument, + "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); + PTF_ASSERT_RAISES(pcpp::MacAddress("aa:aa:aa:aa:aa:aa:"), std::invalid_argument, + "Invalid MAC address format, should be xx:xx:xx:xx:xx:xx"); +} // TestMacAddress PTF_TEST_CASE(TestLRUList) { @@ -316,8 +323,7 @@ PTF_TEST_CASE(TestLRUList) lruList.eraseElement(2); lruList.eraseElement(3); PTF_ASSERT_EQUAL(lruList.getSize(), 0); -} // TestLRUList - +} // TestLRUList PTF_TEST_CASE(TestGeneralUtils) { @@ -343,8 +349,7 @@ PTF_TEST_CASE(TestGeneralUtils) result = pcpp::hexStringToByteArray("0102030405", resultArr, sizeof(resultArr)); PTF_ASSERT_EQUAL(result, 4); PTF_ASSERT_BUF_COMPARE(resultArr, expectedBytes2, result); -} // TestGeneralUtils - +} // TestGeneralUtils PTF_TEST_CASE(TestGetMacAddress) { @@ -355,11 +360,13 @@ PTF_TEST_CASE(TestGetMacAddress) PTF_ASSERT_TRUE(liveDev->open()); DeviceTeardown devTeardown(liveDev); - //fetch all IP addresses from arp table + // fetch all IP addresses from arp table std::string ipsInArpTableAsString; #ifdef _WIN32 - ipsInArpTableAsString = pcpp::executeShellCommand("arp -a | for /f \"tokens=1\" \%i in ('findstr dynamic') do @echo \%i"); - ipsInArpTableAsString.erase(std::remove(ipsInArpTableAsString.begin(), ipsInArpTableAsString.end(), ' '), ipsInArpTableAsString.end() ) ; + ipsInArpTableAsString = + pcpp::executeShellCommand("arp -a | for /f \"tokens=1\" \%i in ('findstr dynamic') do @echo \%i"); + ipsInArpTableAsString.erase(std::remove(ipsInArpTableAsString.begin(), ipsInArpTableAsString.end(), ' '), + ipsInArpTableAsString.end()); #else ipsInArpTableAsString = pcpp::executeShellCommand("arp -a | awk '{print $2}' | sed 's/.$//; s/^.//'"); #endif @@ -406,38 +413,55 @@ PTF_TEST_CASE(TestGetMacAddress) { PTF_ASSERT_NOT_EQUAL(result, pcpp::MacAddress::Zero); } -} // TestGetMacAddress - +} // TestGetMacAddress PTF_TEST_CASE(TestIPv4Network) { // Invalid c'tor: IPv4 address + prefix len - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), -1), std::invalid_argument, "prefixLen must be an integer between 0 and 32"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), 33), std::invalid_argument, "prefixLen must be an integer between 0 and 32"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), -1), std::invalid_argument, + "prefixLen must be an integer between 0 and 32"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), 33), std::invalid_argument, + "prefixLen must be an integer between 0 and 32"); // Invalid c'tor: IPv4 address + netmask - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "invalid"), std::invalid_argument, "Netmask is not valid IPv4 format: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "999.999.999.999"), std::invalid_argument, "Netmask is not valid IPv4 format: 999.999.999.999"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "255.255.0.255"), std::invalid_argument, "Netmask is not valid IPv4 format: 255.255.0.255"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "10.10.10.10"), std::invalid_argument, "Netmask is not valid IPv4 format: 10.10.10.10"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "0.255.255.255"), std::invalid_argument, "Netmask is not valid IPv4 format: 0.255.255.255"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "127.255.255.255"), std::invalid_argument, "Netmask is not valid IPv4 format: 127.255.255.255"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "invalid"), std::invalid_argument, + "Netmask is not valid IPv4 format: invalid"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "999.999.999.999"), std::invalid_argument, + "Netmask is not valid IPv4 format: 999.999.999.999"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "255.255.0.255"), std::invalid_argument, + "Netmask is not valid IPv4 format: 255.255.0.255"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "10.10.10.10"), std::invalid_argument, + "Netmask is not valid IPv4 format: 10.10.10.10"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "0.255.255.255"), std::invalid_argument, + "Netmask is not valid IPv4 format: 0.255.255.255"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(pcpp::IPv4Address("1.1.1.1"), "127.255.255.255"), std::invalid_argument, + "Netmask is not valid IPv4 format: 127.255.255.255"); // Invalid c'tor: address + netmask in one string - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("invalid")), std::invalid_argument, "The input should be in the format of
/ or
/"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("invalid/255.255.255.0")), std::invalid_argument, "The input doesn't contain a valid IPv4 network prefix: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/255.255.255.0/24")), std::invalid_argument, "Netmask is not valid IPv4 format: 255.255.255.0/24"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/33")), std::invalid_argument, "Prefix length must be an integer between 0 and 32"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/-1")), std::invalid_argument, "Netmask is not valid IPv4 format: -1"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/invalid")), std::invalid_argument, "Netmask is not valid IPv4 format: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/999.999.999.999")), std::invalid_argument, "Netmask is not valid IPv4 format: 999.999.999.999"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/255.255.0.1")), std::invalid_argument, "Netmask is not valid IPv4 format: 255.255.0.1"); - PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/0.0.255.255")), std::invalid_argument, "Netmask is not valid IPv4 format: 0.0.255.255"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("invalid")), std::invalid_argument, + "The input should be in the format of
/ or
/"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("invalid/255.255.255.0")), std::invalid_argument, + "The input doesn't contain a valid IPv4 network prefix: invalid"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/255.255.255.0/24")), std::invalid_argument, + "Netmask is not valid IPv4 format: 255.255.255.0/24"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/33")), std::invalid_argument, + "Prefix length must be an integer between 0 and 32"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/-1")), std::invalid_argument, + "Netmask is not valid IPv4 format: -1"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/invalid")), std::invalid_argument, + "Netmask is not valid IPv4 format: invalid"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/999.999.999.999")), std::invalid_argument, + "Netmask is not valid IPv4 format: 999.999.999.999"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/255.255.0.1")), std::invalid_argument, + "Netmask is not valid IPv4 format: 255.255.0.1"); + PTF_ASSERT_RAISES(pcpp::IPv4Network(std::string("1.1.1.1/0.0.255.255")), std::invalid_argument, + "Netmask is not valid IPv4 format: 0.0.255.255"); // Valid c'tor auto addressAsStr = std::string("192.168.10.100"); auto address = pcpp::IPv4Address(addressAsStr); + // clang-format off auto networksPrefixLensAndNetPrefix = std::vector> { std::tuple{"255.255.255.255", 32, "192.168.10.100", "192.168.10.100", "192.168.10.100", 1}, std::tuple{"255.255.255.0", 24, "192.168.10.0", "192.168.10.1", "192.168.10.254", 256}, @@ -448,6 +472,7 @@ PTF_TEST_CASE(TestIPv4Network) std::tuple{"128.0.0.0", 1, "128.0.0.0", "128.0.0.1", "255.255.255.254", 2147483648}, std::tuple{"0.0.0.0", 0, "0.0.0.0", "0.0.0.1", "255.255.255.254", 4294967296} }; + // clang-format on for (auto networkPrefixLenAndNetPrefix : networksPrefixLensAndNetPrefix) { @@ -468,13 +493,15 @@ PTF_TEST_CASE(TestIPv4Network) PTF_ASSERT_EQUAL(iPv4NetworkA.getNetworkPrefix(), std::get<2>(networkPrefixLenAndNetPrefix)); // Valid c'tor: address + prefix len in one string - std::string addressAndPrefixLen = addressAsStr + "/" + std::to_string(std::get<1>(networkPrefixLenAndNetPrefix)); + std::string addressAndPrefixLen = + addressAsStr + "/" + std::to_string(std::get<1>(networkPrefixLenAndNetPrefix)); pcpp::IPv4Network iPv4NetworkD(addressAndPrefixLen); PTF_ASSERT_EQUAL(iPv4NetworkA.getNetmask(), std::get<0>(networkPrefixLenAndNetPrefix)); PTF_ASSERT_EQUAL(iPv4NetworkA.getNetworkPrefix(), std::get<2>(networkPrefixLenAndNetPrefix)); PTF_ASSERT_EQUAL(iPv4NetworkD.getLowestAddress(), pcpp::IPv4Address(std::get<3>(networkPrefixLenAndNetPrefix))); - PTF_ASSERT_EQUAL(iPv4NetworkD.getHighestAddress(), pcpp::IPv4Address(std::get<4>(networkPrefixLenAndNetPrefix))); + PTF_ASSERT_EQUAL(iPv4NetworkD.getHighestAddress(), + pcpp::IPv4Address(std::get<4>(networkPrefixLenAndNetPrefix))); PTF_ASSERT_EQUAL(iPv4NetworkD.getTotalAddressCount(), std::get<5>(networkPrefixLenAndNetPrefix)); } @@ -503,38 +530,55 @@ PTF_TEST_CASE(TestIPv4Network) std::stringstream stream; stream << ipv4Network; PTF_ASSERT_EQUAL(stream.str(), "172.16.0.0/16"); -} // TestIPv4Network - +} // TestIPv4Network PTF_TEST_CASE(TestIPv6Network) { // Invalid c'tor: IPv6 address + prefix len - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), 129), std::invalid_argument, "prefixLen must be an integer between 0 and 128"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), 129), std::invalid_argument, + "prefixLen must be an integer between 0 and 128"); // Invalid c'tor: IPv6 address + netmask - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "invalid"), std::invalid_argument, "Netmask is not valid IPv6 format: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "ffff:ff10::"), std::invalid_argument, "Netmask is not valid IPv6 format: ffff:ff10::"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "ffff:ee00::"), std::invalid_argument, "Netmask is not valid IPv6 format: ffff:ee00::"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "7f00::"), std::invalid_argument, "Netmask is not valid IPv6 format: 7f00::"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "ffff::ffff"), std::invalid_argument, "Netmask is not valid IPv6 format: ffff::ffff"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "f000::0001"), std::invalid_argument, "Netmask is not valid IPv6 format: f000::0001"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "invalid"), std::invalid_argument, + "Netmask is not valid IPv6 format: invalid"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "ffff:ff10::"), std::invalid_argument, + "Netmask is not valid IPv6 format: ffff:ff10::"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "ffff:ee00::"), std::invalid_argument, + "Netmask is not valid IPv6 format: ffff:ee00::"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "7f00::"), std::invalid_argument, + "Netmask is not valid IPv6 format: 7f00::"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "ffff::ffff"), std::invalid_argument, + "Netmask is not valid IPv6 format: ffff::ffff"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(pcpp::IPv6Address("2001:db8::"), "f000::0001"), std::invalid_argument, + "Netmask is not valid IPv6 format: f000::0001"); // Invalid c'tor: address + netmask in one string - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("invalid")), std::invalid_argument, "The input should be in the format of
/ or
/"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("invalid/32")), std::invalid_argument, "The input doesn't contain a valid IPv6 network prefix: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/32/24")), std::invalid_argument, "Netmask is not valid IPv6 format: 32/24"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/255.255.0.0")), std::invalid_argument, "Netmask is not valid IPv6 format: 255.255.0.0"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/130")), std::invalid_argument, "Prefix length must be an integer between 0 and 128"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/-1")), std::invalid_argument, "Netmask is not valid IPv6 format: -1"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/invalid")), std::invalid_argument, "Netmask is not valid IPv6 format: invalid"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/a2cb:d625::")), std::invalid_argument, "Netmask is not valid IPv6 format: a2cb:d625::"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/ffff::0001")), std::invalid_argument, "Netmask is not valid IPv6 format: ffff::0001"); - PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/0fff::")), std::invalid_argument, "Netmask is not valid IPv6 format: 0fff::"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("invalid")), std::invalid_argument, + "The input should be in the format of
/ or
/"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("invalid/32")), std::invalid_argument, + "The input doesn't contain a valid IPv6 network prefix: invalid"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/32/24")), std::invalid_argument, + "Netmask is not valid IPv6 format: 32/24"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/255.255.0.0")), std::invalid_argument, + "Netmask is not valid IPv6 format: 255.255.0.0"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/130")), std::invalid_argument, + "Prefix length must be an integer between 0 and 128"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/-1")), std::invalid_argument, + "Netmask is not valid IPv6 format: -1"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/invalid")), std::invalid_argument, + "Netmask is not valid IPv6 format: invalid"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/a2cb:d625::")), std::invalid_argument, + "Netmask is not valid IPv6 format: a2cb:d625::"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/ffff::0001")), std::invalid_argument, + "Netmask is not valid IPv6 format: ffff::0001"); + PTF_ASSERT_RAISES(pcpp::IPv6Network(std::string("ef3c:7157:a084:23c0::/0fff::")), std::invalid_argument, + "Netmask is not valid IPv6 format: 0fff::"); // Valid c'tor auto addressAsStr = std::string("39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5746"); auto address = pcpp::IPv6Address(addressAsStr); + // clang-format off auto netmasksPrefixLensAndNetPrefix = std::vector> { std::tuple{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5746", "39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5746", "39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5746", 1}, std::tuple{"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8", 125, "39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5740", "39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5741", "39e1:f90e:14dd:f9a1:4d0a:7f9f:da18:5747", 8}, @@ -550,6 +594,7 @@ PTF_TEST_CASE(TestIPv6Network) std::tuple{"c000::", 2, "00::", "00::1", "3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0}, std::tuple{"::", 0, "::", "::1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0} }; + // clang-format on for (auto netmaskPrefixLenAndNetPrefix : netmasksPrefixLensAndNetPrefix) { @@ -570,13 +615,15 @@ PTF_TEST_CASE(TestIPv6Network) PTF_ASSERT_EQUAL(iPv6NetworkC.getNetworkPrefix(), std::get<2>(netmaskPrefixLenAndNetPrefix)); // Valid c'tor: address + prefix len in one string - std::string addressAndPrefixLen = addressAsStr + "/" + std::to_string(std::get<1>(netmaskPrefixLenAndNetPrefix)); + std::string addressAndPrefixLen = + addressAsStr + "/" + std::to_string(std::get<1>(netmaskPrefixLenAndNetPrefix)); pcpp::IPv6Network iPv6NetworkD(addressAndPrefixLen); PTF_ASSERT_EQUAL(iPv6NetworkD.getNetmask(), std::get<0>(netmaskPrefixLenAndNetPrefix)); PTF_ASSERT_EQUAL(iPv6NetworkD.getNetworkPrefix(), std::get<2>(netmaskPrefixLenAndNetPrefix)); PTF_ASSERT_EQUAL(iPv6NetworkD.getLowestAddress(), pcpp::IPv6Address(std::get<3>(netmaskPrefixLenAndNetPrefix))); - PTF_ASSERT_EQUAL(iPv6NetworkD.getHighestAddress(), pcpp::IPv6Address(std::get<4>(netmaskPrefixLenAndNetPrefix))); + PTF_ASSERT_EQUAL(iPv6NetworkD.getHighestAddress(), + pcpp::IPv6Address(std::get<4>(netmaskPrefixLenAndNetPrefix))); auto expectedNumOfAddresses = std::get<5>(netmaskPrefixLenAndNetPrefix); if (expectedNumOfAddresses != 0) { @@ -584,7 +631,8 @@ PTF_TEST_CASE(TestIPv6Network) } else { - PTF_ASSERT_RAISES(iPv6NetworkD.getTotalAddressCount(), std::out_of_range, "Number of addresses exceeds uint64_t"); + PTF_ASSERT_RAISES(iPv6NetworkD.getTotalAddressCount(), std::out_of_range, + "Number of addresses exceeds uint64_t"); } } @@ -599,30 +647,34 @@ PTF_TEST_CASE(TestIPv6Network) for (auto prefixLen = 0; prefixLen < 64; prefixLen++) { - PTF_ASSERT_FALSE(ipv6Network.includes(pcpp::IPv6Network(pcpp::IPv6Address("a88e:2765:5349:01f9:9a9a:a444:2739:2f4a"), prefixLen))); + PTF_ASSERT_FALSE(ipv6Network.includes( + pcpp::IPv6Network(pcpp::IPv6Address("a88e:2765:5349:01f9:9a9a:a444:2739:2f4a"), prefixLen))); } for (auto prefixLen = 64; prefixLen <= 128; prefixLen++) { - PTF_ASSERT_TRUE(ipv6Network.includes(pcpp::IPv6Network(pcpp::IPv6Address("a88e:2765:5349:01f9:9a9a:a444:2739:2f4a"), prefixLen))); + PTF_ASSERT_TRUE(ipv6Network.includes( + pcpp::IPv6Network(pcpp::IPv6Address("a88e:2765:5349:01f9:9a9a:a444:2739:2f4a"), prefixLen))); } - PTF_ASSERT_FALSE(ipv6Network.includes(pcpp::IPv6Network(pcpp::IPv6Address("4447:3c98:ee01:fd0a:bf73:ad00:89ac:1a89"), 64))); + PTF_ASSERT_FALSE( + ipv6Network.includes(pcpp::IPv6Network(pcpp::IPv6Address("4447:3c98:ee01:fd0a:bf73:ad00:89ac:1a89"), 64))); // to string PTF_ASSERT_EQUAL(ipv6Network.toString(), "a88e:2765:5349:1f9::/64"); std::stringstream stream; stream << ipv6Network; PTF_ASSERT_EQUAL(stream.str(), "a88e:2765:5349:1f9::/64"); -} // TestIPv6Network - +} // TestIPv6Network PTF_TEST_CASE(TestIPNetwork) { + // clang-format off auto networkInfos = std::vector> { std::tuple{"192.168.1.1", pcpp::IPv4Address("192.168.1.1"), 16, "255.255.0.0", pcpp::IPv4Address("192.168.0.0"), 4, pcpp::IPv4Address("192.168.0.1"), pcpp::IPv4Address("192.168.255.254"), 65536}, std::tuple{"fe26:d0a1:beb6:5957:e77a:9983:ec84:b23e", pcpp::IPv6Address("fe26:d0a1:beb6:5957:e77a:9983:ec84:b23e"), 64, "ffff:ffff:ffff:ffff::", pcpp::IPv6Address("fe26:d0a1:beb6:5957::"), 6, pcpp::IPv6Address("fe26:d0a1:beb6:5957::1"), pcpp::IPv6Address("fe26:d0a1:beb6:5957:ffff:ffff:ffff:ffff"), 0} }; + // clang-format on for (auto networkInfo : networkInfos) { @@ -666,7 +718,8 @@ PTF_TEST_CASE(TestIPNetwork) } else { - PTF_ASSERT_RAISES(networkD.getTotalAddressCount(), std::out_of_range, "Number of addresses exceeds uint64_t"); + PTF_ASSERT_RAISES(networkD.getTotalAddressCount(), std::out_of_range, + "Number of addresses exceeds uint64_t"); } } @@ -719,4 +772,4 @@ PTF_TEST_CASE(TestIPNetwork) PTF_ASSERT_EQUAL(ipv4Network.toString(), "10.1.2.0/24"); ipv6Network = ipv4NetworkCopy; PTF_ASSERT_EQUAL(ipv6Network.toString(), "4348:58d6::/32"); -} // TestIPNetwork +} // TestIPNetwork diff --git a/Tests/Pcap++Test/Tests/KniTests.cpp b/Tests/Pcap++Test/Tests/KniTests.cpp index 09563619f2..07bb1383ba 100644 --- a/Tests/Pcap++Test/Tests/KniTests.cpp +++ b/Tests/Pcap++Test/Tests/KniTests.cpp @@ -3,25 +3,44 @@ #include "../Common/PcapFileNamesDef.h" #ifdef USE_DPDK_KNI -#include "KniDeviceList.h" -#include "PcapFileDevice.h" -#include "RawSocketDevice.h" -#include "SystemUtils.h" +# include "KniDeviceList.h" +# include "PcapFileDevice.h" +# include "RawSocketDevice.h" +# include "SystemUtils.h" extern PcapTestArgs PcapTestGlobalArgs; -#define KNI_TEST_NAME "tkni" +# define KNI_TEST_NAME "tkni" struct KniRequestsCallbacksMock { - static int change_mtu_new(uint16_t, unsigned int) { return 0; } - static int change_mtu_old(uint8_t, unsigned int) { return 0; } - static int config_network_if_new(uint16_t, uint8_t) { return 0; } - static int config_network_if_old(uint8_t, uint8_t) { return 0; } - static int config_mac_address(uint16_t, uint8_t[]) { return 0; } - static int config_promiscusity(uint16_t, uint8_t) { return 0; } - - static bool onPacketsCallbackSingleBurst(pcpp::MBufRawPacket*, uint32_t numOfPackets, pcpp::KniDevice*, void* userCookie) + static int change_mtu_new(uint16_t, unsigned int) + { + return 0; + } + static int change_mtu_old(uint8_t, unsigned int) + { + return 0; + } + static int config_network_if_new(uint16_t, uint8_t) + { + return 0; + } + static int config_network_if_old(uint8_t, uint8_t) + { + return 0; + } + static int config_mac_address(uint16_t, uint8_t[]) + { + return 0; + } + static int config_promiscusity(uint16_t, uint8_t) + { + return 0; + } + + static bool onPacketsCallbackSingleBurst(pcpp::MBufRawPacket*, uint32_t numOfPackets, pcpp::KniDevice*, + void* userCookie) { unsigned int* counter = static_cast(userCookie); *counter = numOfPackets; @@ -77,28 +96,26 @@ static bool setKniDeviceIp(const pcpp::IPAddress& ip, int kniDeviceId) class KniDeviceTeardown { - private: - pcpp::KniDevice* m_KniDevice; - - public: +private: + pcpp::KniDevice* m_KniDevice; - explicit KniDeviceTeardown(pcpp::KniDevice* dev) - { - m_KniDevice = dev; - } +public: + explicit KniDeviceTeardown(pcpp::KniDevice* dev) + { + m_KniDevice = dev; + } - ~KniDeviceTeardown() + ~KniDeviceTeardown() + { + if (m_KniDevice != NULL && m_KniDevice->isInitialized() && m_KniDevice->isOpened()) { - if (m_KniDevice != NULL && m_KniDevice->isInitialized() && m_KniDevice->isOpened()) - { - m_KniDevice->stopRequestHandlerThread(); - m_KniDevice->close(); - } + m_KniDevice->stopRequestHandlerThread(); + m_KniDevice->close(); } + } }; -#endif // USE_DPDK_KNI - +#endif // USE_DPDK_KNI PTF_TEST_CASE(TestKniDevice) { @@ -176,7 +193,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 + pcpp::multiPlatformSleep(2); // Wait for thread to start if (pcpp::KniDeviceList::isCallbackSupported(pcpp::KniDeviceList::CALLBACK_PROMISC)) { bool modeSet = device->setPromiscuous(pcpp::KniDevice::PROMISC_ENABLE); @@ -239,37 +256,40 @@ PTF_TEST_CASE(TestKniDevice) } } { - pcpp::KniDevice::KniLinkState ls = device->updateLinkState(isLinkUp ? pcpp::KniDevice::LINK_DOWN : pcpp::KniDevice::LINK_UP); + pcpp::KniDevice::KniLinkState ls = + device->updateLinkState(isLinkUp ? pcpp::KniDevice::LINK_DOWN : pcpp::KniDevice::LINK_UP); switch (ls) { - case pcpp::KniDevice::LINK_NOT_SUPPORTED: - { - PTF_PRINT_VERBOSE("KNI updateLinkState not supported"); - } break; - case pcpp::KniDevice::LINK_ERROR: - { - PTF_PRINT_VERBOSE("KNI updateLinkState have failed with LINK_ERROR"); - } break; - case pcpp::KniDevice::LINK_DOWN: - { // If previous known state was UP -> yield an error - PTF_ASSERT_FALSE(isLinkUp); - } break; - case pcpp::KniDevice::LINK_UP: - { // If previous known state was DOWN -> yield an error - PTF_ASSERT_TRUE(isLinkUp); - } break; + case pcpp::KniDevice::LINK_NOT_SUPPORTED: + { + PTF_PRINT_VERBOSE("KNI updateLinkState not supported"); + break; + } + case pcpp::KniDevice::LINK_ERROR: + { + PTF_PRINT_VERBOSE("KNI updateLinkState have failed with LINK_ERROR"); + break; + } + case pcpp::KniDevice::LINK_DOWN: + { // If previous known state was UP -> yield an error + PTF_ASSERT_FALSE(isLinkUp); + break; + } + case pcpp::KniDevice::LINK_UP: + { // If previous known state was DOWN -> yield an error + PTF_ASSERT_TRUE(isLinkUp); + break; + } } } device->stopRequestHandlerThread(); device->close(); // Device will be destroyed later - #else PTF_SKIP_TEST("DPDK and DPDK_KNI not configured"); #endif -} // TestKniDevice - +} // TestKniDevice PTF_TEST_CASE(TestKniDeviceSendReceive) { @@ -281,7 +301,11 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) } // Assume that DPDK was initialized correctly in DpdkDevice tests - enum { KNI_MTU = 1500, BLOCK_TIMEOUT = 3 }; + enum + { + KNI_MTU = 1500, + BLOCK_TIMEOUT = 3 + }; pcpp::KniDevice* device = NULL; unsigned int counter = 0; pcpp::KniDevice::KniDeviceConfiguration devConfig; @@ -313,7 +337,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) PTF_ASSERT_TRUE(device->startRequestHandlerThread(0, 250000000)); KniDeviceTeardown devTeardown(device); - pcpp::multiPlatformSleep(1); // Wait for thread to start + pcpp::multiPlatformSleep(1); // Wait for thread to start // KNI device management PTF_ASSERT_TRUE(setKniDeviceIp(kniIp, KNI_DEVICE1)); @@ -325,7 +349,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) pcpp::PcapFileReaderDevice fileReaderDev(EXAMPLE_PCAP_PATH); PTF_ASSERT_TRUE(rsdevice.open()); - { // Receive test part + { // Receive test part pcpp::RawPacket rawPacket; pcpp::RawPacketVector rawPacketVec; pcpp::MBufRawPacketVector mbufRawPacketVec; @@ -339,7 +363,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 + pcpp::multiPlatformSleep(1); // Give some time to start capture thread for (int i = 0; i < 10; ++i) { fileReaderDev.getNextPacket(rawPacket); @@ -350,12 +374,12 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) rsdevice.sendPackets(rawPacketVec); pcpp::Logger::getInstance().enableLogs(); rawPacketVec.clear(); - pcpp::multiPlatformSleep(1); // Give some time to receive packets + pcpp::multiPlatformSleep(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 + pcpp::multiPlatformSleep(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); @@ -371,7 +395,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) rsdevice.sendPackets(rawPacketVec); pcpp::Logger::getInstance().enableLogs(); rawPacketVec.clear(); - pcpp::multiPlatformSleep(1); // Give some time to receive packets + pcpp::multiPlatformSleep(1); // Give some time to receive packets device->stopCapture(); PTF_PRINT_VERBOSE("KNI have captured " << counter << " packets on device " << KNI_DEVICE1); counter = 0; @@ -386,21 +410,25 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) rawPacketVec.clear(); //? Note(echo-Mike): Some amount of packets are always queued inside kernel //? so blocking mode has a slight chance to obtain this packets - int blockResult = device->startCaptureBlockingMode(KniRequestsCallbacksMock::onPacketsCallbackSingleBurst, &counter, BLOCK_TIMEOUT); + int blockResult = device->startCaptureBlockingMode(KniRequestsCallbacksMock::onPacketsCallbackSingleBurst, + &counter, BLOCK_TIMEOUT); switch (blockResult) { - case -1: - { - PTF_PRINT_VERBOSE("KNI startCaptureBlockingMode have exited by timeout"); - } break; - case 0: - { - PTF_PRINT_VERBOSE("KNI startCaptureBlockingMode have exited by an ERROR"); - } break; - case 1: - { - PTF_PRINT_VERBOSE("KNI have captured " << counter << " packets (blocking mode) on device " << KNI_DEVICE1); - } break; + case -1: + { + PTF_PRINT_VERBOSE("KNI startCaptureBlockingMode have exited by timeout"); + break; + } + case 0: + { + PTF_PRINT_VERBOSE("KNI startCaptureBlockingMode have exited by an ERROR"); + break; + } + case 1: + { + PTF_PRINT_VERBOSE("KNI have captured " << counter << " packets (blocking mode) on device " << KNI_DEVICE1); + break; + } } } @@ -409,7 +437,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) pcpp::Logger::getInstance().enableLogs(); PTF_ASSERT_TRUE(fileReaderDev.open()); - { // Send test part + { // Send test part pcpp::PointerVector packetVec; pcpp::RawPacketVector sendRawPacketVec; pcpp::RawPacketVector receiveRawPacketVec; @@ -417,7 +445,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) uint16_t packetsRead = 0; int packetsReceived = 0; pcpp::RawPacket rawPacket; - while(fileReaderDev.getNextPacket(rawPacket)) + while (fileReaderDev.getNextPacket(rawPacket)) { if (packetsRead == 100) break; @@ -430,7 +458,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) packetsRead++; } - //send packets as parsed EthPacekt array + // send packets as parsed EthPacekt array uint16_t packetsSentAsParsed = device->sendPackets(packetArr, packetsRead); PTF_ASSERT_EQUAL(packetsSentAsParsed, packetsRead); @@ -443,7 +471,7 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) PTF_ASSERT_NOT_EQUAL(packetsReceived, 0); packetsReceived = 0; - //send packets are RawPacketVector + // send packets are RawPacketVector uint16_t packetsSentAsRawVector = device->sendPackets(sendRawPacketVec); PTF_ASSERT_EQUAL(packetsSentAsRawVector, packetsRead); @@ -458,8 +486,8 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) //? Note (echo-Mike): this will not be checked by raw socket because there is //? a chance that packets will be thrown away before we can receive them - PTF_ASSERT_TRUE(device->sendPacket(*(sendRawPacketVec.at(packetsRead/3)))); - PTF_ASSERT_TRUE(device->sendPacket(*(packetArr[packetsRead/2]))); + PTF_ASSERT_TRUE(device->sendPacket(*(sendRawPacketVec.at(packetsRead / 3)))); + PTF_ASSERT_TRUE(device->sendPacket(*(packetArr[packetsRead / 2]))); } //! Note(echo-Mike): RawSocket device must be closed before KNI @@ -472,4 +500,4 @@ PTF_TEST_CASE(TestKniDeviceSendReceive) PTF_SKIP_TEST("DPDK and DPDK_KNI not configured"); #endif -} // TestKniDeviceSendReceive +} // TestKniDeviceSendReceive diff --git a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp index 9918945f75..6cabae8912 100644 --- a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp +++ b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp @@ -13,10 +13,10 @@ #include #include #if defined(_WIN32) -#include "PcapRemoteDevice.h" -#include "PcapRemoteDeviceList.h" -#include "WinPcapLiveDevice.h" -#include +# include "PcapRemoteDevice.h" +# include "PcapRemoteDeviceList.h" +# include "WinPcapLiveDevice.h" +# include #endif extern PcapTestArgs PcapTestGlobalArgs; @@ -46,7 +46,8 @@ static bool packetArrivesBlockingModeNoTimeout(pcpp::RawPacket* rawPacket, pcpp: return false; } -static bool packetArrivesBlockingModeStartCapture(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* userCookie) +static bool packetArrivesBlockingModeStartCapture(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, + void* userCookie) { pcpp::Logger::getInstance().suppressLogs(); if (dev->startCaptureBlockingMode(packetArrivesBlockingModeTimeout, nullptr, 5) != 0) @@ -66,7 +67,8 @@ static bool packetArrivesBlockingModeStartCapture(pcpp::RawPacket* rawPacket, pc return false; } -static bool packetArrivesBlockingModeStopCapture(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* userCookie) +static bool packetArrivesBlockingModeStopCapture(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, + void* userCookie) { // shouldn't do anything dev->stopCapture(); @@ -79,14 +81,16 @@ static bool packetArrivesBlockingModeStopCapture(pcpp::RawPacket* rawPacket, pcp return false; } -static bool packetArrivesBlockingModeNoTimeoutPacketCount(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* userCookie) +static bool packetArrivesBlockingModeNoTimeoutPacketCount(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, + void* userCookie) { int* packetCount = static_cast(userCookie); (*packetCount)++; return false; } -static bool packetArrivesBlockingModeWithSnaplen(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* userCookie) +static bool packetArrivesBlockingModeWithSnaplen(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, + void* userCookie) { int snaplen = *static_cast(userCookie); return rawPacket->getRawDataLen() > snaplen; @@ -115,9 +119,10 @@ class RpcapdServerInitializer m_JobHandle = nullptr; } } + public: RpcapdServerInitializer(bool activateRemoteDevice, const std::string& ip, uint16_t port) - : m_ProcessHandle(nullptr), m_JobHandle(nullptr) + : m_ProcessHandle(nullptr), m_JobHandle(nullptr) { if (!activateRemoteDevice) return; @@ -138,37 +143,35 @@ class RpcapdServerInitializer m_JobHandle = CreateJobObject(nullptr, nullptr); if (m_JobHandle == nullptr) { - throw std::runtime_error("Failed to create a job object with error code: " + std::to_string(GetLastError())); + throw std::runtime_error("Failed to create a job object with error code: " + + std::to_string(GetLastError())); } // Sets up the job limits so closing the job will automatically kill all processes assigned to the job. - // This will prevent the subprocess continuing to live if the current process is killed without unwinding the stack (i.e. std::terminate is called), - // as the OS itself will kill the subprocesses when the last job handle is closed. + // This will prevent the subprocess continuing to live if the current process is killed without unwinding the + // stack (i.e. std::terminate is called), as the OS itself will kill the subprocesses when the last job handle + // is closed. JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobLimitInfo{}; jobLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; - if (!SetInformationJobObject(m_JobHandle, JobObjectExtendedLimitInformation, &jobLimitInfo, sizeof(jobLimitInfo))) + if (!SetInformationJobObject(m_JobHandle, JobObjectExtendedLimitInformation, &jobLimitInfo, + sizeof(jobLimitInfo))) { DWORD errCode = GetLastError(); CloseHandle(m_JobHandle); - throw std::runtime_error("Failed to set settings to job object with error code: " + std::to_string(errCode)); + throw std::runtime_error("Failed to set settings to job object with error code: " + + std::to_string(errCode)); } STARTUPINFO si; PROCESS_INFORMATION pi; - ZeroMemory( &si, sizeof(si) ); + ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); - ZeroMemory( &pi, sizeof(pi) ); - if (!CreateProcess ( - TEXT(cmd.c_str()), - // CreateProcessW (Unicode version) modifies the argument string inplace during internal processing. - TEXT(args.data()), - nullptr, nullptr, false, - CREATE_NEW_CONSOLE, - nullptr, nullptr, - &si, - &pi - )) + ZeroMemory(&pi, sizeof(pi)); + if (!CreateProcess( + TEXT(cmd.c_str()), + // CreateProcessW (Unicode version) modifies the argument string inplace during internal processing. + TEXT(args.data()), nullptr, nullptr, false, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi)) { DWORD errCode = GetLastError(); CloseHandle(m_JobHandle); @@ -176,7 +179,7 @@ class RpcapdServerInitializer } m_ProcessHandle = pi.hProcess; - CloseHandle(pi.hThread); // We don't need the thread handle, so we can close it. + CloseHandle(pi.hThread); // We don't need the thread handle, so we can close it. if (!AssignProcessToJobObject(m_JobHandle, m_ProcessHandle)) { @@ -188,7 +191,7 @@ class RpcapdServerInitializer RpcapdServerInitializer(const RpcapdServerInitializer&) = delete; RpcapdServerInitializer(RpcapdServerInitializer&& other) noexcept - : m_ProcessHandle(other.m_ProcessHandle), m_JobHandle(other.m_JobHandle) + : m_ProcessHandle(other.m_ProcessHandle), m_JobHandle(other.m_JobHandle) { other.m_ProcessHandle = nullptr; other.m_JobHandle = nullptr; @@ -204,12 +207,18 @@ class RpcapdServerInitializer return *this; } - ~RpcapdServerInitializer() { killProcessAndCloseHandles(); } + ~RpcapdServerInitializer() + { + killProcessAndCloseHandles(); + } - HANDLE getHandle() const { return m_ProcessHandle; } + HANDLE getHandle() const + { + return m_ProcessHandle; + } }; -#endif // defined(_WIN32) +#endif // defined(_WIN32) PTF_TEST_CASE(TestPcapLiveDeviceList) { @@ -217,7 +226,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceList) PTF_ASSERT_FALSE(devList.empty()); pcpp::IPv4Address defaultGateway = pcpp::IPv4Address::Zero; - for(const auto &iter : devList) + for (const auto& iter : devList) { PTF_ASSERT_FALSE(iter->getName().empty()); if (defaultGateway == pcpp::IPv4Address::Zero) @@ -235,33 +244,32 @@ PTF_TEST_CASE(TestPcapLiveDeviceList) devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); PTF_ASSERT_FALSE(devList.empty()); - for(const auto &iter : devList) + for (const auto& iter : devList) { PTF_ASSERT_FALSE(iter->getName().empty()); } - pcpp::PcapLiveDeviceList *clonedDevList = pcpp::PcapLiveDeviceList::getInstance().clone(); + pcpp::PcapLiveDeviceList* clonedDevList = pcpp::PcapLiveDeviceList::getInstance().clone(); PTF_ASSERT_NOT_NULL(clonedDevList); std::vector clonedDevListVector = clonedDevList->getPcapLiveDevicesList(); PTF_ASSERT_EQUAL(clonedDevListVector.size(), devList.size()); auto iterCloned = clonedDevListVector.begin(); - for(auto iter = devList.begin(); iter != devList.end(); ++iter, ++iterCloned) + for (auto iter = devList.begin(); iter != devList.end(); ++iter, ++iterCloned) { PTF_ASSERT_EQUAL((*iter)->getName(), (*iterCloned)->getName()); } delete clonedDevList; PTF_ASSERT_EQUAL(pcpp::PcapLiveDeviceList::getInstance().getDnsServers().size(), dnsServerCount); -} // TestPcapLiveDeviceList - - +} // TestPcapLiveDeviceList PTF_TEST_CASE(TestPcapLiveDeviceListSearch) { pcpp::PcapLiveDevice* liveDev = nullptr; - liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); std::string devName(liveDev->getName()); @@ -272,14 +280,13 @@ PTF_TEST_CASE(TestPcapLiveDeviceListSearch) pcpp::PcapLiveDevice* liveDev3 = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(devName); PTF_ASSERT_EQUAL(liveDev3, liveDev2, ptr); - liveDev3 = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(PcapTestGlobalArgs.ipToSendReceivePackets); + liveDev3 = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(PcapTestGlobalArgs.ipToSendReceivePackets); PTF_ASSERT_EQUAL(liveDev3, liveDev, ptr); liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp("255.255.255.250"); PTF_ASSERT_NULL(liveDev); -} // TestPcapLiveDeviceListSearch - - +} // TestPcapLiveDeviceListSearch PTF_TEST_CASE(TestPcapLiveDevice) { @@ -292,7 +299,8 @@ PTF_TEST_CASE(TestPcapLiveDevice) DeviceTeardown devTeardown(liveDev); int packetCount = 0; int numOfTimeStatsWereInvoked = 0; - PTF_ASSERT_TRUE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_TRUE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, + static_cast(&numOfTimeStatsWereInvoked))); int totalSleepTime = 0; while (totalSleepTime <= 20) { @@ -306,22 +314,21 @@ PTF_TEST_CASE(TestPcapLiveDevice) liveDev->stopCapture(); PTF_ASSERT_GREATER_THAN(packetCount, 0); - PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime-2); + PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime - 2); pcpp::IPcapDevice::PcapStats statistics; liveDev->getStatistics(statistics); - //Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets - //PTF_ASSERT_EQUALS((uint32_t)statistics.ps_drop, 0); + // Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets + // PTF_ASSERT_EQUALS((uint32_t)statistics.ps_drop, 0); liveDev->close(); PTF_ASSERT_FALSE(liveDev->isOpened()); // a negative test pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_FALSE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_FALSE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, + static_cast(&numOfTimeStatsWereInvoked))); pcpp::Logger::getInstance().enableLogs(); -} // TestPcapLiveDevice - - +} // TestPcapLiveDevice PTF_TEST_CASE(TestPcapLiveDeviceClone) { @@ -336,7 +343,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceClone) #ifdef _WIN32 // Tests if device pointer points to a Windows Live Device on a Windows machine. PTF_ASSERT_NOT_NULL(dynamic_cast(originalDev)); -#endif // _WIN32 +#endif // _WIN32 liveDev = originalDev->clone(); } @@ -346,14 +353,15 @@ PTF_TEST_CASE(TestPcapLiveDeviceClone) #ifdef _WIN32 // Tests if the clone is correctly returns a Windows Live Device on Windows systems. PTF_ASSERT_NOT_NULL(dynamic_cast(liveDev)); -#endif // _WIN32 +#endif // _WIN32 PTF_ASSERT_GREATER_THAN(liveDev->getMtu(), 0); PTF_ASSERT_TRUE(liveDev->open()); DeviceTeardown devTeardown(liveDev, true); int packetCount = 0; int numOfTimeStatsWereInvoked = 0; - PTF_ASSERT_TRUE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_TRUE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, + static_cast(&numOfTimeStatsWereInvoked))); int totalSleepTime = 0; while (totalSleepTime <= 20) { @@ -367,22 +375,21 @@ PTF_TEST_CASE(TestPcapLiveDeviceClone) liveDev->stopCapture(); PTF_ASSERT_GREATER_THAN(packetCount, 0); - PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime-1); + PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime - 1); pcpp::IPcapDevice::PcapStats statistics; liveDev->getStatistics(statistics); - //Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets - //PTF_ASSERT_EQUALS((uint32_t)statistics.ps_drop, 0); + // Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets + // PTF_ASSERT_EQUALS((uint32_t)statistics.ps_drop, 0); liveDev->close(); PTF_ASSERT_FALSE(liveDev->isOpened()); // a negative test pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_FALSE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_FALSE(liveDev->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, + static_cast(&numOfTimeStatsWereInvoked))); pcpp::Logger::getInstance().enableLogs(); -} // TestPcapLiveDeviceClone - - +} // TestPcapLiveDeviceClone PTF_TEST_CASE(TestPcapLiveDeviceNoNetworking) { @@ -393,7 +400,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceNoNetworking) std::vector devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); PTF_ASSERT_FALSE(devList.empty()); - auto iter = std::find_if(devList.begin(), devList.end(), [](const pcpp::PcapLiveDevice *dev) { + auto iter = std::find_if(devList.begin(), devList.end(), [](const pcpp::PcapLiveDevice* dev) { return !dev->getLoopback() && dev->getIPv4Address() != pcpp::IPv4Address::Zero; }); if (iter != devList.end()) @@ -413,13 +420,12 @@ PTF_TEST_CASE(TestPcapLiveDeviceNoNetworking) pcpp::Logger::getInstance().enableLogs(); PTF_ASSERT_NULL(liveDev); -} // TestPcapLiveDeviceNoNetworking - - +} // TestPcapLiveDeviceNoNetworking PTF_TEST_CASE(TestPcapLiveDeviceStatsMode) { - pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); PTF_ASSERT_TRUE(liveDev->open()); DeviceTeardown devTeardown(liveDev); @@ -430,7 +436,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceStatsMode) while (totalSleepTime <= 6) { pcpp::multiPlatformSleep(2); - totalSleepTime +=2; + totalSleepTime += 2; pcpp::IPcapDevice::PcapStats statistics; liveDev->getStatistics(statistics); if (statistics.packetsRecv > 2) @@ -440,12 +446,12 @@ PTF_TEST_CASE(TestPcapLiveDeviceStatsMode) PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime << " secs"); liveDev->stopCapture(); - PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime-1); + PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime - 1); pcpp::IPcapDevice::PcapStats statistics; liveDev->getStatistics(statistics); PTF_ASSERT_GREATER_THAN((uint32_t)statistics.packetsRecv, 2); - //Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets - //PTF_ASSERT_EQUAL((uint32_t)statistics.ps_drop, 0); + // Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets + // PTF_ASSERT_EQUAL((uint32_t)statistics.ps_drop, 0); liveDev->close(); PTF_ASSERT_FALSE(liveDev->isOpened()); @@ -453,25 +459,24 @@ PTF_TEST_CASE(TestPcapLiveDeviceStatsMode) pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_FALSE(liveDev->startCapture(1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); pcpp::Logger::getInstance().enableLogs(); -} // TestPcapLiveDeviceStatsMode - - +} // TestPcapLiveDeviceStatsMode PTF_TEST_CASE(TestPcapLiveDeviceBlockingMode) { std::vector configs; - configs.emplace_back(); // the default config + configs.emplace_back(); // the default config #if !defined(_WIN32) - configs.emplace_back(); // the config used poll + configs.emplace_back(); // the config used poll configs[1].usePoll = true; #endif // test the common behaviour for all configs - for(const auto & config: configs) + for (const auto& config : configs) { // open device - pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); PTF_ASSERT_TRUE(liveDev->open(config)); DeviceTeardown devTeardown(liveDev); @@ -555,8 +560,7 @@ PTF_TEST_CASE(TestPcapLiveDeviceBlockingMode) PTF_ASSERT_FALSE(liveDev->startCapture(packetArrives, &packetCount)); pcpp::Logger::getInstance().enableLogs(); } -} // TestPcapLiveDeviceBlockingMode - +} // TestPcapLiveDeviceBlockingMode PTF_TEST_CASE(TestPcapLiveDeviceWithLambda) { @@ -570,17 +574,16 @@ PTF_TEST_CASE(TestPcapLiveDeviceWithLambda) int packetCount = 0; int numOfTimeStatsWereInvoked = 0; - auto packetArrivesLambda = [](pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* pDevice, void* userCookie) - { + auto packetArrivesLambda = [](pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* pDevice, void* userCookie) { (*static_cast(userCookie))++; }; - auto statsUpdateLambda = [](pcpp::IPcapDevice::PcapStats& stats, void* userCookie) - { + auto statsUpdateLambda = [](pcpp::IPcapDevice::PcapStats& stats, void* userCookie) { (*static_cast(userCookie))++; }; - PTF_ASSERT_TRUE(liveDev->startCapture(packetArrivesLambda , static_cast(&packetCount), 1, statsUpdateLambda, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_TRUE(liveDev->startCapture(packetArrivesLambda, static_cast(&packetCount), 1, statsUpdateLambda, + static_cast(&numOfTimeStatsWereInvoked))); int totalSleepTime = 0; while (totalSleepTime <= 20) { @@ -594,17 +597,14 @@ PTF_TEST_CASE(TestPcapLiveDeviceWithLambda) liveDev->stopCapture(); PTF_ASSERT_GREATER_THAN(packetCount, 0); - PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime-2); -} // TestPcapLiveDeviceWithLambda - - + PTF_ASSERT_GREATER_OR_EQUAL_THAN(numOfTimeStatsWereInvoked, totalSleepTime - 2); +} // TestPcapLiveDeviceWithLambda PTF_TEST_CASE(TestPcapLiveDeviceBlockingModeWithLambda) { - auto packetArrivesBlockingModeNoTimeoutLambda = []( - pcpp::RawPacket *rawPacket, pcpp::PcapLiveDevice *dev, void *userCookie) - { - int *packetCount = static_cast(userCookie); + auto packetArrivesBlockingModeNoTimeoutLambda = [](pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, + void* userCookie) { + int* packetCount = static_cast(userCookie); if ((*packetCount) == 5) return true; @@ -613,7 +613,8 @@ PTF_TEST_CASE(TestPcapLiveDeviceBlockingModeWithLambda) }; // open device - pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); PTF_ASSERT_TRUE(liveDev->open()); DeviceTeardown devTeardown(liveDev); @@ -628,13 +629,12 @@ PTF_TEST_CASE(TestPcapLiveDeviceBlockingModeWithLambda) pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_FALSE(liveDev->startCapture(packetArrives, &packetCount)); pcpp::Logger::getInstance().enableLogs(); -} // TestPcapLiveDeviceBlockingModeWithLambda - - +} // TestPcapLiveDeviceBlockingModeWithLambda PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg) { - pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); // open device in default mode @@ -643,7 +643,8 @@ PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg) // sanity test - make sure packets are captured in default mode int packetCount = 0; - PTF_ASSERT_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeNoTimeoutPacketCount, &packetCount, 7), -1); + PTF_ASSERT_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeNoTimeoutPacketCount, &packetCount, 7), + -1); liveDev->close(); PTF_ASSERT_FALSE(liveDev->isOpened()); @@ -657,7 +658,8 @@ PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg) PTF_ASSERT_TRUE(liveDev->open(devConfig)); // start capturing in non-default configuration - PTF_ASSERT_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeNoTimeoutPacketCount, &packetCount, 7), -1); + PTF_ASSERT_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeNoTimeoutPacketCount, &packetCount, 7), + -1); liveDev->close(); PTF_ASSERT_FALSE(liveDev->isOpened()); @@ -668,11 +670,13 @@ PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg) packetCount = 0; // create a non-default configuration with only capturing incoming packets and open the device again - pcpp::PcapLiveDevice::DeviceConfiguration devConfigWithDirection(pcpp::PcapLiveDevice::Promiscuous, 10, 2000000, pcpp::PcapLiveDevice::PCPP_OUT); + pcpp::PcapLiveDevice::DeviceConfiguration devConfigWithDirection(pcpp::PcapLiveDevice::Promiscuous, 10, 2000000, + pcpp::PcapLiveDevice::PCPP_OUT); PTF_ASSERT_TRUE(liveDev->open(devConfigWithDirection)); // start capturing in non-default configuration witch only captures incoming traffics - PTF_ASSERT_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeNoTimeoutPacketCount, &packetCount, 7), -1); + PTF_ASSERT_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeNoTimeoutPacketCount, &packetCount, 7), + -1); liveDev->close(); PTF_ASSERT_FALSE(liveDev->isOpened()); @@ -683,25 +687,26 @@ PTF_TEST_CASE(TestPcapLiveDeviceSpecialCfg) // create a non-default configuration with a snapshot length of 10 bytes int snaplen = 20; - pcpp::PcapLiveDevice::DeviceConfiguration devConfigWithSnaplen(pcpp::PcapLiveDevice::Promiscuous, 0, 0, pcpp::PcapLiveDevice::PCPP_INOUT, snaplen); + pcpp::PcapLiveDevice::DeviceConfiguration devConfigWithSnaplen(pcpp::PcapLiveDevice::Promiscuous, 0, 0, + pcpp::PcapLiveDevice::PCPP_INOUT, snaplen); liveDev->open(devConfigWithSnaplen); // start capturing in non-default configuration witch only captures incoming traffics - // TODO: for some reason snaplen change doesn't work in Windows (WinPcap and Npcap). Setting the check as NON_CRITICAL until we figure it out + // TODO: for some reason snaplen change doesn't work in Windows (WinPcap and Npcap). Setting the check as + // NON_CRITICAL until we figure it out PTF_NON_CRITICAL_EQUAL(liveDev->startCaptureBlockingMode(packetArrivesBlockingModeWithSnaplen, &snaplen, 3), -1); liveDev->close(); -} // TestPcapLiveDeviceSpecialCfg - - +} // TestPcapLiveDeviceSpecialCfg PTF_TEST_CASE(TestWinPcapLiveDevice) { #if defined(_WIN32) - pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); PTF_ASSERT_EQUAL(liveDev->getDeviceType(), pcpp::PcapLiveDevice::WinPcapDevice, enum); @@ -713,7 +718,8 @@ PTF_TEST_CASE(TestWinPcapLiveDevice) PTF_ASSERT_TRUE(winPcapLiveDevice->setMinAmountOfDataToCopyFromKernelToApplication(100000)); int packetCount = 0; int numOfTimeStatsWereInvoked = 0; - PTF_ASSERT_TRUE(winPcapLiveDevice->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_TRUE(winPcapLiveDevice->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, + static_cast(&numOfTimeStatsWereInvoked))); for (int i = 0; i < 5; i++) { sendURLRequest("www.ebay.com"); @@ -722,8 +728,8 @@ PTF_TEST_CASE(TestWinPcapLiveDevice) pcpp::IPcapDevice::PcapStats statistics; winPcapLiveDevice->getStatistics(statistics); PTF_ASSERT_GREATER_THAN(statistics.packetsRecv, 20); - //Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets - //PTF_ASSERT_EQUAL((uint32_t)statistics.packetsDrop, 0); + // Bad test - on high traffic libpcap/WinPcap/Npcap sometimes drop packets + // PTF_ASSERT_EQUAL((uint32_t)statistics.packetsDrop, 0); winPcapLiveDevice->stopCapture(); PTF_ASSERT_TRUE(winPcapLiveDevice->setMinAmountOfDataToCopyFromKernelToApplication(defaultDataToCopy)); winPcapLiveDevice->close(); @@ -731,18 +737,18 @@ PTF_TEST_CASE(TestWinPcapLiveDevice) // a negative test pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_FALSE(winPcapLiveDevice->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, static_cast(&numOfTimeStatsWereInvoked))); + PTF_ASSERT_FALSE(winPcapLiveDevice->startCapture(&packetArrives, static_cast(&packetCount), 1, &statsUpdate, + static_cast(&numOfTimeStatsWereInvoked))); pcpp::Logger::getInstance().enableLogs(); #else - pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* liveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(liveDev); PTF_ASSERT_EQUAL(liveDev->getDeviceType(), pcpp::PcapLiveDevice::LibPcapDevice, enum); #endif -} // TestWinPcapLiveDevice - - +} // TestWinPcapLiveDevice PTF_TEST_CASE(TestSendPacket) { @@ -758,7 +764,7 @@ PTF_TEST_CASE(TestSendPacket) PTF_ASSERT_GREATER_THAN(liveDev->getMtu(), 0); uint32_t mtu = liveDev->getMtu(); - int buffLen = mtu+1 + sizeof(pcpp::ether_header); + int buffLen = mtu + 1 + sizeof(pcpp::ether_header); uint8_t* buff = new uint8_t[buffLen]; memset(buff, 0, buffLen); pcpp::Logger::getInstance().suppressLogs(); @@ -768,17 +774,17 @@ PTF_TEST_CASE(TestSendPacket) pcpp::RawPacket rawPacket; int packetsSent = 0; int packetsRead = 0; - while(fileReaderDev.getNextPacket(rawPacket)) + while (fileReaderDev.getNextPacket(rawPacket)) { packetsRead++; - //send packet as RawPacket + // send packet as RawPacket PTF_ASSERT_TRUE(liveDev->sendPacket(rawPacket)); - //send packet as raw data + // send packet as raw data PTF_ASSERT_TRUE(liveDev->sendPacket(rawPacket.getRawData(), rawPacket.getRawDataLen())); - //send packet as parsed EthPacekt + // send packet as parsed EthPacekt pcpp::Packet packet(&rawPacket); PTF_ASSERT_TRUE(liveDev->sendPacket(&packet)); @@ -791,10 +797,7 @@ PTF_TEST_CASE(TestSendPacket) fileReaderDev.close(); delete[] buff; -} // TestSendPacket - - - +} // TestSendPacket PTF_TEST_CASE(TestSendPackets) { @@ -812,16 +815,16 @@ PTF_TEST_CASE(TestSendPackets) pcpp::PointerVector packetVec; pcpp::Packet* packetArr[10000]; int packetsRead = 0; - while(fileReaderDev.getNextPacket(rawPacketArr[packetsRead])) + while (fileReaderDev.getNextPacket(rawPacketArr[packetsRead])) { packetVec.pushBack(new pcpp::Packet(&rawPacketArr[packetsRead])); packetsRead++; } - //send packets as RawPacket array + // send packets as RawPacket array int packetsSentAsRaw = liveDev->sendPackets(rawPacketArr, packetsRead); - //send packets as parsed EthPacekt array + // send packets as parsed EthPacekt array std::copy(packetVec.begin(), packetVec.end(), packetArr); int packetsSentAsParsed = liveDev->sendPackets(packetArr, packetsRead); @@ -830,10 +833,7 @@ PTF_TEST_CASE(TestSendPackets) liveDev->close(); fileReaderDev.close(); -} // TestSendPackets - - - +} // TestSendPackets PTF_TEST_CASE(TestMtuSize) { @@ -881,9 +881,10 @@ PTF_TEST_CASE(TestMtuSize) // Try sending the packet PTF_ASSERT_TRUE(liveDev->sendPacket(&smallPacket)); pcpp::RawPacket* rawSmallPacketPtr = smallPacket.getRawPacket(); - pcpp::RawPacket &rawSmallPacketRef = *rawSmallPacketPtr; + pcpp::RawPacket& rawSmallPacketRef = *rawSmallPacketPtr; PTF_ASSERT_TRUE(liveDev->sendPacket(rawSmallPacketRef, true)); - PTF_ASSERT_TRUE(liveDev->sendPacket(rawSmallPacketPtr->getRawData(), rawSmallPacketPtr->getRawDataLen(), true, pcpp::LINKTYPE_ETHERNET)); + PTF_ASSERT_TRUE(liveDev->sendPacket(rawSmallPacketPtr->getRawData(), rawSmallPacketPtr->getRawDataLen(), true, + pcpp::LINKTYPE_ETHERNET)); delete[] smallData; @@ -914,23 +915,22 @@ PTF_TEST_CASE(TestMtuSize) PTF_ASSERT_FALSE(liveDev->sendPacket(&largePacket)); pcpp::RawPacket* rawLargePacketPtr = largePacket.getRawPacket(); - pcpp::RawPacket &rawLargePacketRef = *rawLargePacketPtr; + pcpp::RawPacket& rawLargePacketRef = *rawLargePacketPtr; PTF_ASSERT_FALSE(liveDev->sendPacket(rawLargePacketRef, true)); - PTF_ASSERT_FALSE(liveDev->sendPacket(rawLargePacketPtr->getRawData(), rawLargePacketPtr->getRawDataLen(), true, pcpp::LINKTYPE_ETHERNET)); + PTF_ASSERT_FALSE(liveDev->sendPacket(rawLargePacketPtr->getRawData(), rawLargePacketPtr->getRawDataLen(), true, + pcpp::LINKTYPE_ETHERNET)); pcpp::Logger::getInstance().enableLogs(); delete[] largeData; -} // TestMtuSize - - - +} // TestMtuSize PTF_TEST_CASE(TestRemoteCapture) { #if defined(_WIN32) bool useRemoteDevicesFromArgs = (PcapTestGlobalArgs.remoteIp != "") && (PcapTestGlobalArgs.remotePort > 0); - std::string remoteDeviceIP = (useRemoteDevicesFromArgs ? PcapTestGlobalArgs.remoteIp : PcapTestGlobalArgs.ipToSendReceivePackets); + std::string remoteDeviceIP = + (useRemoteDevicesFromArgs ? PcapTestGlobalArgs.remoteIp : PcapTestGlobalArgs.ipToSendReceivePackets); uint16_t remoteDevicePort = (useRemoteDevicesFromArgs ? PcapTestGlobalArgs.remotePort : 12321); RpcapdServerInitializer rpcapdInitializer(!useRemoteDevicesFromArgs, remoteDeviceIP, remoteDevicePort); @@ -938,9 +938,11 @@ PTF_TEST_CASE(TestRemoteCapture) PTF_ASSERT_NOT_NULL(rpcapdInitializer.getHandle()); pcpp::IPv4Address remoteDeviceIPAddr(remoteDeviceIP); - pcpp::PcapRemoteDeviceList* remoteDevices = pcpp::PcapRemoteDeviceList::getRemoteDeviceList(remoteDeviceIPAddr, remoteDevicePort); + pcpp::PcapRemoteDeviceList* remoteDevices = + pcpp::PcapRemoteDeviceList::getRemoteDeviceList(remoteDeviceIPAddr, remoteDevicePort); PTF_ASSERT_NOT_NULL(remoteDevices); - for (pcpp::PcapRemoteDeviceList::RemoteDeviceListIterator remoteDevIter = remoteDevices->begin(); remoteDevIter != remoteDevices->end(); remoteDevIter++) + for (pcpp::PcapRemoteDeviceList::RemoteDeviceListIterator remoteDevIter = remoteDevices->begin(); + remoteDevIter != remoteDevices->end(); remoteDevIter++) { PTF_ASSERT_FALSE((*remoteDevIter)->getName().empty()); } @@ -1000,7 +1002,7 @@ PTF_TEST_CASE(TestRemoteCapture) int packetsSent = remoteDevice->sendPackets(packetsToSend); PTF_ASSERT_EQUAL(packetsSent, static_cast(packetsToSend.size())); - //check statistics + // check statistics pcpp::IPcapDevice::PcapStats stats; remoteDevice->getStatistics(stats); PTF_ASSERT_EQUAL(static_cast(stats.packetsRecv), capturedPacketsSize); @@ -1015,4 +1017,4 @@ PTF_TEST_CASE(TestRemoteCapture) PTF_SKIP_TEST("This test can only run in Windows environment"); #endif -} // TestRemoteCapture +} // TestRemoteCapture diff --git a/Tests/Pcap++Test/Tests/LoggerTests.cpp b/Tests/Pcap++Test/Tests/LoggerTests.cpp index 5312ec14ce..00f06d332a 100644 --- a/Tests/Pcap++Test/Tests/LoggerTests.cpp +++ b/Tests/Pcap++Test/Tests/LoggerTests.cpp @@ -1,13 +1,13 @@ #define LOG_MODULE PacketLogModuleArpLayer #include "../TestDefinition.h" -#include "Logger.h" -#include #include #include -#include #include -#include "SystemUtils.h" +#include +#include +#include "Logger.h" +#include "SystemUtils.h" namespace pcpp { @@ -20,49 +20,49 @@ namespace pcpp { PCPP_LOG_ERROR("error log" << message); } -} - +} // namespace pcpp class LogPrinter { - public: - static int lastLogLevelSeen; - static std::string* lastLogMessageSeen; - static std::string* lastFilenameSeen; - static std::string* lastMethodSeen; - static int lastLineSeen; - - static void logPrinter(pcpp::Logger::LogLevel logLevel, const std::string& logMessage, const std::string& fileName, const std::string& method, const int line) +public: + static int lastLogLevelSeen; + static std::string* lastLogMessageSeen; + static std::string* lastFilenameSeen; + static std::string* lastMethodSeen; + static int lastLineSeen; + + static void logPrinter(pcpp::Logger::LogLevel logLevel, const std::string& logMessage, const std::string& fileName, + const std::string& method, const int line) + { + LogPrinter::clean(); + LogPrinter::lastLogLevelSeen = (int)logLevel; + LogPrinter::lastLogMessageSeen = new std::string(logMessage); + LogPrinter::lastFilenameSeen = new std::string(fileName); + LogPrinter::lastMethodSeen = new std::string(method); + LogPrinter::lastLineSeen = line; + } + + static void clean() + { + LogPrinter::lastLogLevelSeen = 999; + LogPrinter::lastLineSeen = 99999; + if (LogPrinter::lastLogMessageSeen != nullptr) + { + delete LogPrinter::lastLogMessageSeen; + LogPrinter::lastLogMessageSeen = nullptr; + } + if (LogPrinter::lastFilenameSeen != nullptr) { - LogPrinter::clean(); - LogPrinter::lastLogLevelSeen = (int)logLevel; - LogPrinter::lastLogMessageSeen = new std::string(logMessage); - LogPrinter::lastFilenameSeen = new std::string(fileName); - LogPrinter::lastMethodSeen = new std::string(method); - LogPrinter::lastLineSeen = line; + delete LogPrinter::lastFilenameSeen; + LogPrinter::lastFilenameSeen = nullptr; } - static void clean() + if (LogPrinter::lastMethodSeen != nullptr) { - LogPrinter::lastLogLevelSeen = 999; - LogPrinter::lastLineSeen = 99999; - if (LogPrinter::lastLogMessageSeen != nullptr) - { - delete LogPrinter::lastLogMessageSeen; - LogPrinter::lastLogMessageSeen = nullptr; - } - if (LogPrinter::lastFilenameSeen != nullptr) - { - delete LogPrinter::lastFilenameSeen; - LogPrinter::lastFilenameSeen = nullptr; - } - - if (LogPrinter::lastMethodSeen != nullptr) - { - delete LogPrinter::lastMethodSeen; - LogPrinter::lastMethodSeen = nullptr; - } + delete LogPrinter::lastMethodSeen; + LogPrinter::lastMethodSeen = nullptr; } + } }; int LogPrinter::lastLogLevelSeen = 999; @@ -71,28 +71,28 @@ std::string* LogPrinter::lastFilenameSeen = nullptr; std::string* LogPrinter::lastMethodSeen = nullptr; int LogPrinter::lastLineSeen = 99999; - class MultiThreadLogCounter { - public: - static const int ThreadCount = 5; - static int logMessageThreadCount[ThreadCount]; - static void logPrinter(pcpp::Logger::LogLevel logLevel, const std::string& logMessage, const std::string& fileName, const std::string& method, const int line) - { - int threadId = logMessage[logMessage.length() - 1] - '0'; - MultiThreadLogCounter::logMessageThreadCount[threadId]++; - } +public: + static const int ThreadCount = 5; + static int logMessageThreadCount[ThreadCount]; + static void logPrinter(pcpp::Logger::LogLevel logLevel, const std::string& logMessage, const std::string& fileName, + const std::string& method, const int line) + { + int threadId = logMessage[logMessage.length() - 1] - '0'; + MultiThreadLogCounter::logMessageThreadCount[threadId]++; + } }; -int MultiThreadLogCounter::logMessageThreadCount[MultiThreadLogCounter::ThreadCount] = {0, 0, 0, 0, 0}; - +int MultiThreadLogCounter::logMessageThreadCount[MultiThreadLogCounter::ThreadCount] = { 0, 0, 0, 0, 0 }; +// clang-format off #if defined(_WIN32) #define SEPARATOR '\\' #else #define SEPARATOR '/' #endif - +// clang-format on std::string getLFileName(const std::string& path) { @@ -101,18 +101,17 @@ std::string getLFileName(const std::string& path) size_t i = result.rfind('/', result.length()); if (i != std::string::npos) { - result = result.substr(i+1, result.length() - i); + result = result.substr(i + 1, result.length() - i); } // check the "\\" separator i = result.rfind('\\', result.length()); if (i != std::string::npos) { - result = result.substr(i+1, result.length() - i); + result = result.substr(i + 1, result.length() - i); } return result; } - std::string getLowerCaseFileName(const std::string& path) { std::string result = getLFileName(path); @@ -120,33 +119,30 @@ std::string getLowerCaseFileName(const std::string& path) return result; } - std::string getMethodWithoutNamespace(const std::string& method) { std::string result = method; size_t i = result.rfind(':', result.length()); if (i != std::string::npos) { - result = result.substr(i+1, result.length() - i); + result = result.substr(i + 1, result.length() - i); } return result; } - class LoggerCleaner { - public: - ~LoggerCleaner() - { - pcpp::Logger::getInstance().enableLogs(); - pcpp::Logger::getInstance().setAllModulesToLogLevel(pcpp::Logger::Info); - pcpp::Logger::getInstance().resetLogPrinter(); - std::cout.clear(); - LogPrinter::clean(); - } +public: + ~LoggerCleaner() + { + pcpp::Logger::getInstance().enableLogs(); + pcpp::Logger::getInstance().setAllModulesToLogLevel(pcpp::Logger::Info); + pcpp::Logger::getInstance().resetLogPrinter(); + std::cout.clear(); + LogPrinter::clean(); + } }; - void printLogThread(int threadId) { std::random_device rd; @@ -158,7 +154,7 @@ void printLogThread(int threadId) for (int i = 0; i < 1000; i++) { pcpp::invokeErrorLog(threadIdAsString); - int sleepTime = dist(simpleRand); + int sleepTime = dist(simpleRand); pcpp::multiPlatformMSleep(sleepTime); } } @@ -177,7 +173,7 @@ PTF_TEST_CASE(TestLoggerMultiThread) threads[i] = std::thread(printLogThread, i); } - for (auto & thread : threads) + for (auto& thread : threads) { thread.join(); } @@ -190,8 +186,7 @@ PTF_TEST_CASE(TestLoggerMultiThread) } PTF_ASSERT_EQUAL(totalLogMessages, 5000); -} // TestLoggerMultiThread - +} // TestLoggerMultiThread PTF_TEST_CASE(TestLogger) { @@ -305,4 +300,4 @@ PTF_TEST_CASE(TestLogger) pcpp::invokeErrorLog(); PTF_ASSERT_EQUAL(LogPrinter::lastLogLevelSeen, 999); PTF_ASSERT_NULL(LogPrinter::lastLogMessageSeen); -} // TestLogger +} // TestLogger diff --git a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp index 230c5393b1..a930fbdd84 100644 --- a/Tests/Pcap++Test/Tests/PacketParsingTests.cpp +++ b/Tests/Pcap++Test/Tests/PacketParsingTests.cpp @@ -8,7 +8,6 @@ #include "DnsLayer.h" #include "PcapFileDevice.h" - PTF_TEST_CASE(TestHttpRequestParsing) { pcpp::PcapFileReaderDevice readerDev(EXAMPLE_PCAP_HTTP_REQUEST); @@ -103,10 +102,10 @@ PTF_TEST_CASE(TestHttpRequestParsing) PTF_ASSERT_EQUAL(packetCount, 385); - // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || tcp contains "HEAD " || tcp contains "OPTIONS ") + // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || + // tcp contains "HEAD " || tcp contains "OPTIONS ") PTF_ASSERT_EQUAL(httpPackets, 385); - PTF_ASSERT_EQUAL(otherMethodReqs, 0); // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET ") @@ -118,8 +117,8 @@ PTF_TEST_CASE(TestHttpRequestParsing) // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "HEAD ") PTF_ASSERT_EQUAL(headReqs, 5); - - // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST ") && (tcp matches "home.*HTTP/1.1") + // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST ") && + // (tcp matches "home.*HTTP/1.1") PTF_ASSERT_EQUAL(homeReqs, 13); // Wireshark filter: http.request.full_uri contains .swf PTF_ASSERT_EQUAL(swfReqs, 4); @@ -131,17 +130,16 @@ PTF_TEST_CASE(TestHttpRequestParsing) // Wireshark filter: tcp contains "Host: www.winwin.co.il" PTF_ASSERT_EQUAL(winwinReqs, 20); - - // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || tcp contains "HEAD " || tcp contains "OPTIONS ") && (tcp contains "Firefox/33.0") + // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || + // tcp contains "HEAD " || tcp contains "OPTIONS ") && (tcp contains "Firefox/33.0") PTF_ASSERT_EQUAL(ffReqs, 233); - // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || tcp contains "HEAD " || tcp contains "OPTIONS ") && (tcp contains "Chrome/38.0") + // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || + // tcp contains "HEAD " || tcp contains "OPTIONS ") && (tcp contains "Chrome/38.0") PTF_ASSERT_EQUAL(chromeReqs, 82); - // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || tcp contains "HEAD " || tcp contains "OPTIONS ") && (tcp contains "Trident/7.0") + // Wireshark filter: (tcp.dstport == 80 || tcp.dstport == 8080) && (tcp contains "GET " || tcp contains "POST " || + // tcp contains "HEAD " || tcp contains "OPTIONS ") && (tcp contains "Trident/7.0") PTF_ASSERT_EQUAL(ieReqs, 55); -} // TestHttpRequestParsing - - - +} // TestHttpRequestParsing PTF_TEST_CASE(TestHttpResponseParsing) { @@ -175,11 +173,16 @@ PTF_TEST_CASE(TestHttpResponseParsing) pcpp::HttpResponseLayer* httpResLayer = packet.getLayerOfType(); PTF_ASSERT_NOT_NULL(httpResLayer->getFirstLine()); - if(httpResLayer->getFirstLine()->getStatusCode() == pcpp::HttpResponseStatusCode::Http200OK) { + if (httpResLayer->getFirstLine()->getStatusCode() == pcpp::HttpResponseStatusCode::Http200OK) + { http200OKCounter++; - } else if(httpResLayer->getFirstLine()->getStatusCode() == pcpp::HttpResponseStatusCode::Http302) { + } + else if (httpResLayer->getFirstLine()->getStatusCode() == pcpp::HttpResponseStatusCode::Http302) + { http302Counter++; - } else if(httpResLayer->getFirstLine()->getStatusCode() == pcpp::HttpResponseStatusCode::Http304NotModified ) { + } + else if (httpResLayer->getFirstLine()->getStatusCode() == pcpp::HttpResponseStatusCode::Http304NotModified) + { http304NotModifiedCounter++; } @@ -209,7 +212,6 @@ PTF_TEST_CASE(TestHttpResponseParsing) if (length > 100000) bigResponses++; } - } PTF_ASSERT_EQUAL(packetCount, 682); @@ -228,21 +230,22 @@ PTF_TEST_CASE(TestHttpResponseParsing) // wireshark filter: http.response && (tcp.srcport == 80 || tcp.srcport == 8080) && http.content_type == "text/html" PTF_ASSERT_EQUAL(textHtmlCount, 38); - // wireshark filter: http.response && (tcp.srcport == 80 || tcp.srcport == 8080) && http.content_type contains "image/" + // wireshark filter: http.response && (tcp.srcport == 80 || tcp.srcport == 8080) && http.content_type contains + // "image/" PTF_ASSERT_EQUAL(imageCount, 369); - // wireshark filter: (tcp.srcport == 80 || tcp.srcport == 8080) && tcp contains "HTTP/1." && (tcp contains "Transfer-Encoding: chunked" || tcp contains "Transfer-Encoding: chunked" || tcp contains "transfer-encoding: chunked") + // wireshark filter: (tcp.srcport == 80 || tcp.srcport == 8080) && tcp contains "HTTP/1." && (tcp contains + // "Transfer-Encoding: chunked" || tcp contains "Transfer-Encoding: chunked" || tcp contains "transfer-encoding: + // chunked") PTF_ASSERT_EQUAL(chunkedCount, 45); - // wireshark filter: (tcp.srcport == 80 || tcp.srcport == 8080) && tcp contains "HTTP/1." && tcp contains "Content-Encoding: gzip" + // wireshark filter: (tcp.srcport == 80 || tcp.srcport == 8080) && tcp contains "HTTP/1." && tcp contains + // "Content-Encoding: gzip" PTF_ASSERT_EQUAL(gzipCount, 148); // wireshark filter: http.content_length > 100000 PTF_ASSERT_EQUAL(bigResponses, 14); -} // TestHttpResponseParsing - - - +} // TestHttpResponseParsing PTF_TEST_CASE(TestPrintPacketAndLayers) { @@ -273,15 +276,14 @@ PTF_TEST_CASE(TestPrintPacketAndLayers) while (true) { index = referenceBufferAsString.find("\r\n", index); - if (index == std::string::npos) break; + if (index == std::string::npos) + break; referenceBufferAsString.replace(index, 2, "\n"); index += 1; } PTF_ASSERT_EQUAL(referenceBufferAsString, outputStream.str()); -} // TestPrintPacketAndLayers - - +} // TestPrintPacketAndLayers PTF_TEST_CASE(TestDnsParsing) { @@ -297,7 +299,7 @@ PTF_TEST_CASE(TestDnsParsing) int packetsContainingDnsAdditional = 0; int queriesWithNameGoogle = 0; - int queriesWithNameMozillaOrg = 0; //aus3.mozilla.org + int queriesWithNameMozillaOrg = 0; // aus3.mozilla.org int queriesWithTypeA = 0; int queriesWithTypeNotA = 0; int queriesWithClassIN = 0; @@ -334,7 +336,8 @@ PTF_TEST_CASE(TestDnsParsing) bool isTypeA = false; bool isClassIN = false; - for (pcpp::DnsQuery* query = dnsLayer->getFirstQuery(); query != nullptr; query = dnsLayer->getNextQuery(query)) + for (pcpp::DnsQuery* query = dnsLayer->getFirstQuery(); query != nullptr; + query = dnsLayer->getNextQuery(query)) { if (query->getDnsType() == pcpp::DNS_TYPE_A) isTypeA = true; @@ -361,7 +364,8 @@ PTF_TEST_CASE(TestDnsParsing) bool isTypePTR = false; bool isTtlLessThan30 = false; - for (pcpp::DnsResource* answer = dnsLayer->getFirstAnswer(); answer != nullptr; answer = dnsLayer->getNextAnswer(answer)) + for (pcpp::DnsResource* answer = dnsLayer->getFirstAnswer(); answer != nullptr; + answer = dnsLayer->getNextAnswer(answer)) { if (answer->getTTL() < 30) isTtlLessThan30 = true; @@ -388,7 +392,8 @@ PTF_TEST_CASE(TestDnsParsing) if (dnsLayer->getAuthority("Yaels-iPhone.local", true) != nullptr) authoritiesWithNameYaelPhone++; - for (pcpp::DnsResource* auth = dnsLayer->getFirstAuthority(); auth != nullptr; auth = dnsLayer->getNextAuthority(auth)) + for (pcpp::DnsResource* auth = dnsLayer->getFirstAuthority(); auth != nullptr; + auth = dnsLayer->getNextAuthority(auth)) { if (auth->getData()->toString() == "10.0.0.2") { @@ -405,12 +410,14 @@ PTF_TEST_CASE(TestDnsParsing) if (dnsLayer->getAdditionalRecord("", true) != nullptr) additionalWithEmptyName++; - if (dnsLayer->getAdditionalRecord("D.9.F.3.F.4.E.F.F.F.A.A.F.1.A.5.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa", true) != nullptr) + if (dnsLayer->getAdditionalRecord( + "D.9.F.3.F.4.E.F.F.F.A.A.F.1.A.5.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa", true) != nullptr) additionalWithLongUglyName++; bool isTypeNSEC = false; - for (pcpp::DnsResource* add = dnsLayer->getFirstAdditionalRecord(); add != nullptr; add = dnsLayer->getNextAdditionalRecord(add)) + for (pcpp::DnsResource* add = dnsLayer->getFirstAdditionalRecord(); add != nullptr; + add = dnsLayer->getNextAdditionalRecord(add)) { if (add->getDnsType() == pcpp::DNS_TYPE_NSEC) isTypeNSEC = true; @@ -461,8 +468,9 @@ PTF_TEST_CASE(TestDnsParsing) // wireshark filter: dns.count.add_rr > 0 and dns.resp.name == "" PTF_ASSERT_EQUAL(additionalWithEmptyName, 23); - // wireshark filter: dns.count.add_rr > 0 and dns.resp.name == D.9.F.3.F.4.E.F.F.F.A.A.F.1.A.5.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa + // wireshark filter: dns.count.add_rr > 0 and dns.resp.name == + // D.9.F.3.F.4.E.F.F.F.A.A.F.1.A.5.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa PTF_ASSERT_EQUAL(additionalWithLongUglyName, 12); // wireshark filter: dns.count.add_rr > 0 and dns.resp.type == 47 PTF_ASSERT_EQUAL(additionalWithTypeNSEC, 14); -} // TestDnsParsing +} // TestDnsParsing diff --git a/Tests/Pcap++Test/Tests/PfRingTests.cpp b/Tests/Pcap++Test/Tests/PfRingTests.cpp index b12828beda..b97ad500b4 100644 --- a/Tests/Pcap++Test/Tests/PfRingTests.cpp +++ b/Tests/Pcap++Test/Tests/PfRingTests.cpp @@ -5,12 +5,12 @@ #include #ifdef USE_PF_RING -#include "Logger.h" -#include "PacketUtils.h" -#include "IPv4Layer.h" -#include "PfRingDeviceList.h" -#include "PcapFileDevice.h" -#include "PcapLiveDeviceList.h" +# include "Logger.h" +# include "PacketUtils.h" +# include "IPv4Layer.h" +# include "PfRingDeviceList.h" +# include "PcapFileDevice.h" +# include "PcapLiveDeviceList.h" #endif extern PcapTestArgs PcapTestGlobalArgs; @@ -27,11 +27,20 @@ struct PfRingPacketData int UdpCount; std::unordered_map FlowKeys; - PfRingPacketData() : ThreadId(-1), PacketCount(0), EthCount(0), IpCount(0), TcpCount(0), UdpCount(0) {} - void clear() { ThreadId = -1; PacketCount = 0; EthCount = 0; IpCount = 0; TcpCount = 0; UdpCount = 0; FlowKeys.clear(); } + PfRingPacketData() : ThreadId(-1), PacketCount(0), EthCount(0), IpCount(0), TcpCount(0), UdpCount(0) + {} + void clear() + { + ThreadId = -1; + PacketCount = 0; + EthCount = 0; + IpCount = 0; + TcpCount = 0; + UdpCount = 0; + FlowKeys.clear(); + } }; - struct SetFilterInstruction { int Instruction; @@ -39,8 +48,8 @@ struct SetFilterInstruction int PacketCount; }; - -static void pfRingPacketsArrive(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* device, void* userCookie) +static void pfRingPacketsArrive(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, + pcpp::PfRingDevice* device, void* userCookie) { PfRingPacketData* data = static_cast(userCookie); @@ -61,8 +70,8 @@ static void pfRingPacketsArrive(pcpp::RawPacket* packets, uint32_t numOfPackets, } } - -static void pfRingPacketsArriveMultiThread(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* device, void* userCookie) +static void pfRingPacketsArriveMultiThread(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, + pcpp::PfRingDevice* device, void* userCookie) { PfRingPacketData* data = static_cast(userCookie); @@ -90,13 +99,13 @@ static void pfRingPacketsArriveMultiThread(pcpp::RawPacket* packets, uint32_t nu } } - -void pfRingPacketsArriveSetFilter(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* device, void* userCookie) +void pfRingPacketsArriveSetFilter(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, + pcpp::PfRingDevice* device, void* userCookie) { SetFilterInstruction* instruction = static_cast(userCookie); - switch(instruction->Instruction) + switch (instruction->Instruction) { - case 1: //verify TCP packet + case 1: // verify TCP packet for (uint32_t i = 0; i < numOfPackets; i++) { pcpp::Packet packet(&packets[i]); @@ -108,7 +117,7 @@ void pfRingPacketsArriveSetFilter(pcpp::RawPacket* packets, uint32_t numOfPacket } break; - case 2: //verify IP filter + case 2: // verify IP filter pcpp::IPv4Address addr(instruction->Data); for (uint32_t i = 0; i < numOfPackets; i++) { @@ -142,7 +151,8 @@ int incSleep(int maxSleepTime, const PfRingPacketData& packetData) return totalSleepTime; } -int incSleepMultiThread(int maxSleepTime, PfRingPacketData packetData[], int totalNumOfCores, int numOfCoresInUse, pcpp::CoreMask coreMask) +int incSleepMultiThread(int maxSleepTime, PfRingPacketData packetData[], int totalNumOfCores, int numOfCoresInUse, + pcpp::CoreMask coreMask) { int totalSleepTime = 0; while (totalSleepTime < maxSleepTime) @@ -185,9 +195,6 @@ static pcpp::CoreMask TestPfRingMultiThreadCoreMask; #endif - - - PTF_TEST_CASE(TestPfRingDevice) { #ifdef USE_PF_RING @@ -195,7 +202,8 @@ PTF_TEST_CASE(TestPfRingDevice) pcpp::PfRingDeviceList& devList = pcpp::PfRingDeviceList::getInstance(); PTF_ASSERT_GREATER_THAN(devList.getPfRingDevicesList().size(), 0); PTF_ASSERT_NOT_EQUAL(devList.getPfRingVersion(), ""); - pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(pcapLiveDev); pcpp::PfRingDevice* dev = devList.getPfRingDeviceByName(pcapLiveDev->getName()); @@ -237,26 +245,24 @@ PTF_TEST_CASE(TestPfRingDevice) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingDevice - - - +} // TestPfRingDevice PTF_TEST_CASE(TestPfRingDeviceSingleChannel) { #ifdef USE_PF_RING pcpp::PfRingDeviceList& devList = pcpp::PfRingDeviceList::getInstance(); - pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(pcapLiveDev); pcpp::PfRingDevice* dev = devList.getPfRingDeviceByName(pcapLiveDev->getName()); PTF_ASSERT_NOT_NULL(dev); PfRingPacketData packetData; pcpp::Logger::getInstance().suppressLogs(); - PTF_ASSERT_FALSE(dev->openSingleRxChannel(dev->getTotalNumOfRxChannels()+1)); + PTF_ASSERT_FALSE(dev->openSingleRxChannel(dev->getTotalNumOfRxChannels() + 1)); pcpp::Logger::getInstance().enableLogs(); - PTF_ASSERT_TRUE(dev->openSingleRxChannel(dev->getTotalNumOfRxChannels()-1)); + PTF_ASSERT_TRUE(dev->openSingleRxChannel(dev->getTotalNumOfRxChannels() - 1)); PTF_ASSERT_TRUE(dev->startCaptureSingleThread(pfRingPacketsArrive, &packetData)); int totalSleepTime = incSleep(10, packetData); dev->stopCapture(); @@ -281,22 +287,20 @@ PTF_TEST_CASE(TestPfRingDeviceSingleChannel) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingDeviceSingleChannel - - - +} // TestPfRingDeviceSingleChannel PTF_TEST_CASE(TestPfRingDeviceMultiThread) { #ifdef USE_PF_RING pcpp::PfRingDeviceList& devList = pcpp::PfRingDeviceList::getInstance(); - pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(pcapLiveDev); pcpp::PfRingDevice* dev = devList.getPfRingDeviceByName(pcapLiveDev->getName()); PTF_ASSERT_NOT_NULL(dev); uint8_t numOfChannels = dev->getTotalNumOfRxChannels(); - PTF_ASSERT_TRUE(dev->openMultiRxChannels(numOfChannels*2.5, pcpp::PfRingDevice::PerFlow)); + PTF_ASSERT_TRUE(dev->openMultiRxChannels(numOfChannels * 2.5, pcpp::PfRingDevice::PerFlow)); DeviceTeardown devTeardown(dev); dev->close(); PTF_ASSERT_EQUAL(dev->getNumOfOpenedRxChannels(), 0); @@ -315,8 +319,10 @@ PTF_TEST_CASE(TestPfRingDeviceMultiThread) PTF_ASSERT_TRUE(dev->openMultiRxChannels((uint8_t)numOfCoresInUse, pcpp::PfRingDevice::PerFlow)); PfRingPacketData packetDataMultiThread[totalnumOfCores]; - PTF_ASSERT_TRUE(dev->startCaptureMultiThread(pfRingPacketsArriveMultiThread, packetDataMultiThread, TestPfRingMultiThreadCoreMask)); - int totalSleepTime = incSleepMultiThread(15, packetDataMultiThread, totalnumOfCores, numOfCoresInUse, TestPfRingMultiThreadCoreMask); + PTF_ASSERT_TRUE(dev->startCaptureMultiThread(pfRingPacketsArriveMultiThread, packetDataMultiThread, + TestPfRingMultiThreadCoreMask)); + int totalSleepTime = + incSleepMultiThread(15, packetDataMultiThread, totalnumOfCores, numOfCoresInUse, TestPfRingMultiThreadCoreMask); dev->stopCapture(); PTF_PRINT_VERBOSE("Total sleep time: " << totalSleepTime); pcpp::PfRingDevice::PfRingStats aggrStats; @@ -344,7 +350,7 @@ PTF_TEST_CASE(TestPfRingDeviceMultiThread) PTF_PRINT_VERBOSE("Packets captured: " << stats.recv); PTF_PRINT_VERBOSE("Packets dropped: " << stats.drop); PTF_PRINT_VERBOSE("Total flows: " << packetDataMultiThread[i].FlowKeys.size()); - for(const auto &iter : packetDataMultiThread[i].FlowKeys) + for (const auto& iter : packetDataMultiThread[i].FlowKeys) { PTF_PRINT_VERBOSE("Key=0x" << std::hex << iter.first << "; Value=" << std::dec << iter.second.size()); } @@ -359,10 +365,11 @@ PTF_TEST_CASE(TestPfRingDeviceMultiThread) for (int firstCoreId = 0; firstCoreId < totalnumOfCores; firstCoreId++) { - for (int secondCoreId = firstCoreId+1; secondCoreId < totalnumOfCores; secondCoreId++) + for (int secondCoreId = firstCoreId + 1; secondCoreId < totalnumOfCores; secondCoreId++) { - std::unordered_map > res; - intersectMaps(packetDataMultiThread[firstCoreId].FlowKeys, packetDataMultiThread[secondCoreId].FlowKeys, res); + std::unordered_map> res; + intersectMaps( + packetDataMultiThread[firstCoreId].FlowKeys, packetDataMultiThread[secondCoreId].FlowKeys, res); PTF_ASSERT_EQUAL(res.size(), 0); } @@ -374,11 +381,7 @@ PTF_TEST_CASE(TestPfRingDeviceMultiThread) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingDeviceMultiThread (internal test case) - - - - +} // TestPfRingDeviceMultiThread (internal test case) PTF_TEST_CASE(TestPfRingMultiThreadAllCores) { @@ -400,10 +403,7 @@ PTF_TEST_CASE(TestPfRingMultiThreadAllCores) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingMultiThreadAllCores - - - +} // TestPfRingMultiThreadAllCores PTF_TEST_CASE(TestPfRingMultiThreadSomeCores) { @@ -428,16 +428,14 @@ PTF_TEST_CASE(TestPfRingMultiThreadSomeCores) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingMultiThreadSomeCores - - - +} // TestPfRingMultiThreadSomeCores PTF_TEST_CASE(TestPfRingSendPacket) { #ifdef USE_PF_RING pcpp::PfRingDeviceList& devList = pcpp::PfRingDeviceList::getInstance(); - pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(pcapLiveDev); pcpp::PfRingDevice* dev = devList.getPfRingDeviceByName(pcapLiveDev->getName()); PTF_ASSERT_NOT_NULL(dev); @@ -449,25 +447,25 @@ PTF_TEST_CASE(TestPfRingSendPacket) PTF_ASSERT_GREATER_THAN(dev->getMtu(), 0); uint16_t mtu = dev->getMtu(); - int buffLen = mtu+1; + int buffLen = mtu + 1; uint8_t buff[buffLen]; memset(buff, 0, buffLen); pcpp::RawPacket rawPacket; int packetsSent = 0; int packetsRead = 0; - while(fileReaderDev.getNextPacket(rawPacket)) + while (fileReaderDev.getNextPacket(rawPacket)) { packetsRead++; pcpp::RawPacket origRawPacket = rawPacket; - //send packet as RawPacket + // send packet as RawPacket PTF_ASSERT_TRUE(dev->sendPacket(rawPacket)); - //send packet as raw data + // send packet as raw data PTF_ASSERT_TRUE(dev->sendPacket(rawPacket.getRawData(), rawPacket.getRawDataLen())); - //send packet as parsed EthPacekt + // send packet as parsed EthPacekt pcpp::Packet packet(&rawPacket); PTF_ASSERT_TRUE(dev->sendPacket(packet)); @@ -483,7 +481,7 @@ PTF_TEST_CASE(TestPfRingSendPacket) // send some packets with single channel open PTF_ASSERT_TRUE(dev->openSingleRxChannel(0)); fileReaderDev.open(); - while(fileReaderDev.getNextPacket(rawPacket)) + while (fileReaderDev.getNextPacket(rawPacket)) { PTF_ASSERT_TRUE(dev->sendPacket(rawPacket)); } @@ -495,16 +493,14 @@ PTF_TEST_CASE(TestPfRingSendPacket) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingSendPacket - - - +} // TestPfRingSendPacket PTF_TEST_CASE(TestPfRingSendPackets) { #ifdef USE_PF_RING pcpp::PfRingDeviceList& devList = pcpp::PfRingDeviceList::getInstance(); - pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(pcapLiveDev); pcpp::PfRingDevice* dev = devList.getPfRingDeviceByName(pcapLiveDev->getName()); PTF_ASSERT_NOT_NULL(dev); @@ -518,16 +514,16 @@ PTF_TEST_CASE(TestPfRingSendPackets) pcpp::PointerVector packetVec; const pcpp::Packet* packetArr[10000]; int packetsRead = 0; - while(fileReaderDev.getNextPacket(rawPacketArr[packetsRead])) + while (fileReaderDev.getNextPacket(rawPacketArr[packetsRead])) { packetVec.pushBack(new pcpp::Packet(&rawPacketArr[packetsRead])); packetsRead++; } - //send packets as RawPacket array + // send packets as RawPacket array int packetsSentAsRaw = dev->sendPackets(rawPacketArr, packetsRead); - //send packets as parsed EthPacekt array + // send packets as parsed EthPacekt array std::copy(packetVec.begin(), packetVec.end(), packetArr); int packetsSentAsParsed = dev->sendPackets(packetArr, packetsRead); @@ -540,16 +536,14 @@ PTF_TEST_CASE(TestPfRingSendPackets) #else PTF_SKIP_TEST("PF_RING not configured"); #endif -} // TestPfRingSendPackets - - - +} // TestPfRingSendPackets PTF_TEST_CASE(TestPfRingFilters) { #ifdef USE_PF_RING pcpp::PfRingDeviceList& devList = pcpp::PfRingDeviceList::getInstance(); - pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + pcpp::PcapLiveDevice* pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); PTF_ASSERT_NOT_NULL(pcapLiveDev); pcpp::PfRingDevice* dev = devList.getPfRingDeviceByName(pcapLiveDev->getName()); PTF_ASSERT_NOT_NULL(dev); @@ -566,7 +560,7 @@ PTF_TEST_CASE(TestPfRingFilters) PTF_ASSERT_TRUE(dev->setFilter(protocolFilter)); // verify TCP filter - SetFilterInstruction instruction = { 1, "", 0 }; // instruction #1: verify all packets are of type TCP + SetFilterInstruction instruction = { 1, "", 0 }; // instruction #1: verify all packets are of type TCP PTF_ASSERT_TRUE(dev->startCaptureSingleThread(pfRingPacketsArriveSetFilter, &instruction)); int totalSleepTime = incSleepSetFilter(10, instruction); dev->stopCapture(); diff --git a/Tests/Pcap++Test/Tests/RawSocketTests.cpp b/Tests/Pcap++Test/Tests/RawSocketTests.cpp index 3d77179ac5..34b8c24f57 100644 --- a/Tests/Pcap++Test/Tests/RawSocketTests.cpp +++ b/Tests/Pcap++Test/Tests/RawSocketTests.cpp @@ -54,7 +54,7 @@ PTF_TEST_CASE(TestRawSockets) rawSock.receivePackets(packetVec, 2, failedRecv); if (packetVec.size() > 0) { - PTF_PRINT_VERBOSE("Total wait time: " << 2*i); + PTF_PRINT_VERBOSE("Total wait time: " << 2 * i); break; } } @@ -158,4 +158,4 @@ PTF_TEST_CASE(TestRawSockets) PTF_ASSERT_FALSE(rawSock.sendPackets(packetVec)); pcpp::Logger::getInstance().enableLogs(); } -} // TestRawSockets +} // TestRawSockets diff --git a/Tests/Pcap++Test/Tests/SystemUtilsTests.cpp b/Tests/Pcap++Test/Tests/SystemUtilsTests.cpp index e871996d0f..86f445da85 100644 --- a/Tests/Pcap++Test/Tests/SystemUtilsTests.cpp +++ b/Tests/Pcap++Test/Tests/SystemUtilsTests.cpp @@ -2,7 +2,6 @@ #include "SystemUtils.h" #include - PTF_TEST_CASE(TestSystemCoreUtils) { auto numOfCores = pcpp::getNumOfCores(); @@ -11,10 +10,11 @@ PTF_TEST_CASE(TestSystemCoreUtils) std::bitset<32> bs(pcpp::getCoreMaskForAllMachineCores()); PTF_ASSERT_EQUAL(bs.count(), numOfCores); - auto coreVector = std::vector{pcpp::SystemCores::Core0, pcpp::SystemCores::Core2, pcpp::SystemCores::Core4}; + auto coreVector = + std::vector{ pcpp::SystemCores::Core0, pcpp::SystemCores::Core2, pcpp::SystemCores::Core4 }; PTF_ASSERT_EQUAL(pcpp::createCoreMaskFromCoreVector(coreVector), 0b10101); - auto coreIdVector = std::vector{1, 3, 5}; + auto coreIdVector = std::vector{ 1, 3, 5 }; PTF_ASSERT_EQUAL(pcpp::createCoreMaskFromCoreIds(coreIdVector), 0b101010); std::vector coreVector2; diff --git a/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp b/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp index be663e0084..094f0ebdad 100644 --- a/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp +++ b/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp @@ -11,7 +11,6 @@ #include "PayloadLayer.h" #include "PcapFileDevice.h" - // ~~~~~~~~~~~~~~~~~~ // TcpReassemblyStats // ~~~~~~~~~~~~~~~~~~ @@ -28,12 +27,25 @@ struct TcpReassemblyStats size_t totalMissingBytes; pcpp::ConnectionData connData; - TcpReassemblyStats() { clear(); } + TcpReassemblyStats() + { + clear(); + } - void clear() { reassembledData = ""; numOfDataPackets = 0; curSide = -1; numOfMessagesFromSide[0] = 0; numOfMessagesFromSide[1] = 0; connectionsStarted = false; connectionsEnded = false; connectionsEndedManually = false; totalMissingBytes = 0;} + void clear() + { + reassembledData = ""; + numOfDataPackets = 0; + curSide = -1; + numOfMessagesFromSide[0] = 0; + numOfMessagesFromSide[1] = 0; + connectionsStarted = false; + connectionsEnded = false; + connectionsEndedManually = false; + totalMissingBytes = 0; + } }; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TcpReassemblyMultipleConnStats // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,22 +58,21 @@ struct TcpReassemblyMultipleConnStats Stats stats; FlowKeysList flowKeysList; - std::vectortimestamps; + std::vector timestamps; void clear() { stats.clear(); flowKeysList.clear(); } - pcpp::TcpReassembly *tcpReassmbly = nullptr; + pcpp::TcpReassembly* tcpReassmbly = nullptr; }; - // ~~~~~~~~~~~~~~~~~~~~ // readFileIntoString() // ~~~~~~~~~~~~~~~~~~~~ -static std::string readFileIntoString(const std::string &fileName) +static std::string readFileIntoString(const std::string& fileName) { std::ifstream infile(fileName.c_str(), std::ios::binary); std::ostringstream ostrm; @@ -71,7 +82,6 @@ static std::string readFileIntoString(const std::string &fileName) return res; } - // ~~~~~~~~~~~~~~~~~~~~ // getPayloadLen() // ~~~~~~~~~~~~~~~~~~~~ @@ -88,17 +98,16 @@ static size_t getPayloadLen(pcpp::RawPacket& rawPacket) if (ipLayer == nullptr) throw std::runtime_error("IPv4 Layer not found"); - return be16toh(ipLayer->getIPv4Header()->totalLength)-ipLayer->getHeaderLen()-tcpLayer->getHeaderLen(); + return be16toh(ipLayer->getIPv4Header()->totalLength) - ipLayer->getHeaderLen() - tcpLayer->getHeaderLen(); } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // tcpReassemblyMsgReadyCallback() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ static void tcpReassemblyMsgReadyCallback(int8_t sideIndex, const pcpp::TcpStreamData& tcpData, void* userCookie) { - TcpReassemblyMultipleConnStats::Stats &stats = ((TcpReassemblyMultipleConnStats*)userCookie)->stats; + TcpReassemblyMultipleConnStats::Stats& stats = ((TcpReassemblyMultipleConnStats*)userCookie)->stats; TcpReassemblyMultipleConnStats::Stats::iterator iter = stats.find(tcpData.getConnectionData().flowKey); if (iter == stats.end()) @@ -115,19 +124,19 @@ static void tcpReassemblyMsgReadyCallback(int8_t sideIndex, const pcpp::TcpStrea iter->second.curSide = sideIndex; } - ((TcpReassemblyMultipleConnStats *)userCookie)->timestamps.push_back(tcpData.getTimeStamp()); + ((TcpReassemblyMultipleConnStats*)userCookie)->timestamps.push_back(tcpData.getTimeStamp()); iter->second.numOfDataPackets++; iter->second.reassembledData += std::string((char*)tcpData.getData(), tcpData.getDataLength()); } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // tcpReassemblyManuallyCloseConnMsgReadyCallback() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -static void tcpReassemblyManuallyCloseConnMsgReadyCallback(int8_t sideIndex, const pcpp::TcpStreamData& tcpData, void* userCookie) +static void tcpReassemblyManuallyCloseConnMsgReadyCallback(int8_t sideIndex, const pcpp::TcpStreamData& tcpData, + void* userCookie) { - TcpReassemblyMultipleConnStats::Stats &stats = static_cast(userCookie)->stats; + TcpReassemblyMultipleConnStats::Stats& stats = static_cast(userCookie)->stats; auto iter = stats.find(tcpData.getConnectionData().flowKey); if (iter == stats.end()) @@ -151,7 +160,9 @@ static void tcpReassemblyManuallyCloseConnMsgReadyCallback(int8_t sideIndex, con // if numOfDataPackets hits 10, close the connection manually if (iter->second.numOfDataPackets >= 10) { + // clang-format off static_cast(userCookie)->tcpReassmbly->closeConnection(tcpData.getConnectionData().flowKey); + // clang-format on } } @@ -161,7 +172,7 @@ static void tcpReassemblyManuallyCloseConnMsgReadyCallback(int8_t sideIndex, con static void tcpReassemblyConnectionStartCallback(const pcpp::ConnectionData& connectionData, void* userCookie) { - TcpReassemblyMultipleConnStats::Stats &stats = ((TcpReassemblyMultipleConnStats*)userCookie)->stats; + TcpReassemblyMultipleConnStats::Stats& stats = ((TcpReassemblyMultipleConnStats*)userCookie)->stats; TcpReassemblyMultipleConnStats::Stats::iterator iter = stats.find(connectionData.flowKey); if (iter == stats.end()) @@ -170,22 +181,23 @@ static void tcpReassemblyConnectionStartCallback(const pcpp::ConnectionData& con iter = stats.find(connectionData.flowKey); } - TcpReassemblyMultipleConnStats::FlowKeysList &flowKeys = ((TcpReassemblyMultipleConnStats *)userCookie)->flowKeysList; - if(std::find(flowKeys.begin(), flowKeys.end(), connectionData.flowKey) == flowKeys.end()) + TcpReassemblyMultipleConnStats::FlowKeysList& flowKeys = + ((TcpReassemblyMultipleConnStats*)userCookie)->flowKeysList; + if (std::find(flowKeys.begin(), flowKeys.end(), connectionData.flowKey) == flowKeys.end()) flowKeys.push_back(connectionData.flowKey); iter->second.connectionsStarted = true; iter->second.connData = connectionData; } - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // tcpReassemblyConnectionEndCallback() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& connectionData, pcpp::TcpReassembly::ConnectionEndReason reason, void* userCookie) +static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& connectionData, + pcpp::TcpReassembly::ConnectionEndReason reason, void* userCookie) { - TcpReassemblyMultipleConnStats::Stats &stats = ((TcpReassemblyMultipleConnStats*)userCookie)->stats; + TcpReassemblyMultipleConnStats::Stats& stats = ((TcpReassemblyMultipleConnStats*)userCookie)->stats; TcpReassemblyMultipleConnStats::Stats::iterator iter = stats.find(connectionData.flowKey); if (iter == stats.end()) @@ -194,8 +206,9 @@ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& conne iter = stats.find(connectionData.flowKey); } - TcpReassemblyMultipleConnStats::FlowKeysList &flowKeys = ((TcpReassemblyMultipleConnStats *)userCookie)->flowKeysList; - if(std::find(flowKeys.begin(), flowKeys.end(), connectionData.flowKey) == flowKeys.end()) + TcpReassemblyMultipleConnStats::FlowKeysList& flowKeys = + ((TcpReassemblyMultipleConnStats*)userCookie)->flowKeysList; + if (std::find(flowKeys.begin(), flowKeys.end(), connectionData.flowKey) == flowKeys.end()) flowKeys.push_back(connectionData.flowKey); if (reason == pcpp::TcpReassembly::TcpReassemblyConnectionClosedManually) @@ -204,17 +217,19 @@ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& conne iter->second.connectionsEnded = true; } - // ~~~~~~~~~~~~~~~~~~~ // tcpReassemblyTest() // ~~~~~~~~~~~~~~~~~~~ -static bool tcpReassemblyTest(const std::vector& packetStream, TcpReassemblyMultipleConnStats& results, bool monitorOpenCloseConns, bool closeConnsManually) +static bool tcpReassemblyTest(const std::vector& packetStream, TcpReassemblyMultipleConnStats& results, + bool monitorOpenCloseConns, bool closeConnsManually) { pcpp::TcpReassembly* tcpReassembly = nullptr; if (monitorOpenCloseConns) - tcpReassembly = new pcpp::TcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback); + tcpReassembly = + new pcpp::TcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback); else tcpReassembly = new pcpp::TcpReassembly(tcpReassemblyMsgReadyCallback, &results); @@ -224,7 +239,8 @@ static bool tcpReassemblyTest(const std::vector& packetStream, tcpReassembly->reassemblePacket(packet); } - //for(TcpReassemblyMultipleConnStats::Stats::iterator iter = results.stats.begin(); iter != results.stats.end(); iter++) + // for(TcpReassemblyMultipleConnStats::Stats::iterator iter = results.stats.begin(); iter != results.stats.end(); + // iter++) //{ // // replace \r\n with \n // size_t index = 0; @@ -235,7 +251,7 @@ static bool tcpReassemblyTest(const std::vector& packetStream, // iter->second.reassembledData.replace(index, 2, "\n"); // index += 1; // } - //} + // } if (closeConnsManually) tcpReassembly->closeAllConnections(); @@ -245,14 +261,16 @@ static bool tcpReassemblyTest(const std::vector& packetStream, return true; } - // ~~~~~~~~~~~~~~~~~~~ // tcpReassemblyTestManuallyCloseConnOnMsgReady() // ~~~~~~~~~~~~~~~~~~~ -static bool tcpReassemblyTestManuallyCloseConnOnMsgReady(const std::vector& packetStream, TcpReassemblyMultipleConnStats& results) +static bool tcpReassemblyTestManuallyCloseConnOnMsgReady(const std::vector& packetStream, + TcpReassemblyMultipleConnStats& results) { - results.tcpReassmbly = new pcpp::TcpReassembly(tcpReassemblyManuallyCloseConnMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback); + results.tcpReassmbly = + new pcpp::TcpReassembly(tcpReassemblyManuallyCloseConnMsgReadyCallback, &results, + tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback); for (auto iter : packetStream) { @@ -267,7 +285,6 @@ static bool tcpReassemblyTestManuallyCloseConnOnMsgReady(const std::vectorgetIPv4Header()->totalLength)-ipLayer->getHeaderLen()-tcpLayer->getHeaderLen(); + int tcpPayloadSize = + be16toh(ipLayer->getIPv4Header()->totalLength) - ipLayer->getHeaderLen() - tcpLayer->getHeaderLen(); if (numOfBytes <= 0) - numOfBytes = tcpPayloadSize-beginning; + numOfBytes = tcpPayloadSize - beginning; uint8_t* newPayload = new uint8_t[numOfBytes]; if (beginning + numOfBytes <= tcpPayloadSize) { - memcpy(newPayload, tcpLayer->getLayerPayload()+beginning, numOfBytes); + memcpy(newPayload, tcpLayer->getLayerPayload() + beginning, numOfBytes); } else { - int bytesToCopy = tcpPayloadSize-beginning; - memcpy(newPayload, tcpLayer->getLayerPayload()+beginning, bytesToCopy); + int bytesToCopy = tcpPayloadSize - beginning; + memcpy(newPayload, tcpLayer->getLayerPayload() + beginning, bytesToCopy); for (int i = bytesToCopy; i < numOfBytes; i++) { newPayload[i] = '*'; @@ -316,20 +334,17 @@ static pcpp::RawPacket tcpReassemblyAddRetransmissions(pcpp::RawPacket rawPacket packet.computeCalculateFields(); - delete [] newPayload; + delete[] newPayload; return *(packet.getRawPacket()); } - - // ~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~ // Test Cases start here // ~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~ - PTF_TEST_CASE(TestTcpReassemblySanity) { std::string errMsg; @@ -340,7 +355,7 @@ PTF_TEST_CASE(TestTcpReassemblySanity) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 19); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 2); @@ -359,9 +374,7 @@ PTF_TEST_CASE(TestTcpReassemblySanity) std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblySanity - - +} // TestTcpReassemblySanity PTF_TEST_CASE(TestTcpReassemblyRetran) { @@ -393,16 +406,16 @@ PTF_TEST_CASE(TestTcpReassemblyRetran) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, false, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 21); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 2); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[1], 2); - std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_retransmission_output.txt")); + std::string expectedReassemblyData = + readFileIntoString(std::string("PcapExamples/one_tcp_stream_retransmission_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyRetran - +} // TestTcpReassemblyRetran PTF_TEST_CASE(TestTcpReassemblyMissingData) { @@ -433,21 +446,21 @@ PTF_TEST_CASE(TestTcpReassemblyMissingData) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, false, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.begin()->second.totalMissingBytes, expectedLoss); PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 17); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 2); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[1], 2); - std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_missing_data_output.txt")); + std::string expectedReassemblyData = + readFileIntoString(std::string("PcapExamples/one_tcp_stream_missing_data_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); packetStream.clear(); tcpReassemblyResults.clear(); expectedReassemblyData.clear(); - // test flow without SYN packet PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/one_tcp_stream.pcap", packetStream, errMsg)); @@ -464,9 +477,7 @@ PTF_TEST_CASE(TestTcpReassemblyMissingData) expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyMissingData - - +} // TestTcpReassemblyMissingData PTF_TEST_CASE(TestTcpReassemblyOutOfOrder) { @@ -494,7 +505,7 @@ PTF_TEST_CASE(TestTcpReassemblyOutOfOrder) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 19); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 2); @@ -503,14 +514,14 @@ PTF_TEST_CASE(TestTcpReassemblyOutOfOrder) PTF_ASSERT_FALSE(stats.begin()->second.connectionsEnded); PTF_ASSERT_TRUE(stats.begin()->second.connectionsEndedManually); - std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_out_of_order_output.txt")); + std::string expectedReassemblyData = + readFileIntoString(std::string("PcapExamples/one_tcp_stream_out_of_order_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); packetStream.clear(); tcpReassemblyResults.clear(); expectedReassemblyData.clear(); - // test out-of-order + missing data PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/one_tcp_stream.pcap", packetStream, errMsg)); @@ -538,9 +549,7 @@ PTF_TEST_CASE(TestTcpReassemblyOutOfOrder) expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_missing_data_output_ooo.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyOutOfOrder - - +} // TestTcpReassemblyOutOfOrder PTF_TEST_CASE(TestTcpReassemblyOOOWithManualClose) { @@ -569,7 +578,7 @@ PTF_TEST_CASE(TestTcpReassemblyOOOWithManualClose) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTestManuallyCloseConnOnMsgReady(packetStream, tcpReassemblyResults); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 13); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 2); @@ -578,7 +587,8 @@ PTF_TEST_CASE(TestTcpReassemblyOOOWithManualClose) PTF_ASSERT_FALSE(stats.begin()->second.connectionsEnded); PTF_ASSERT_TRUE(stats.begin()->second.connectionsEndedManually); - std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_out_of_order_with_manual_close_output.txt")); + std::string expectedReassemblyData = + readFileIntoString(std::string("PcapExamples/one_tcp_stream_out_of_order_with_manual_close_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); } @@ -596,7 +606,7 @@ PTF_TEST_CASE(TestTcpReassemblyOOOWithManualClose) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTestManuallyCloseConnOnMsgReady(packetStream, tcpReassemblyResults); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 10); @@ -606,13 +616,12 @@ PTF_TEST_CASE(TestTcpReassemblyOOOWithManualClose) PTF_ASSERT_FALSE(stats.begin()->second.connectionsEnded); PTF_ASSERT_TRUE(stats.begin()->second.connectionsEndedManually); - std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_missing_date_with_manual_close_output.txt")); + std::string expectedReassemblyData = + readFileIntoString(std::string("PcapExamples/one_tcp_stream_missing_date_with_manual_close_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); } -} // TestTcpReassemblyOOOWithManualClose - - +} // TestTcpReassemblyOOOWithManualClose PTF_TEST_CASE(TestTcpReassemblyWithFIN_RST) { @@ -625,7 +634,7 @@ PTF_TEST_CASE(TestTcpReassemblyWithFIN_RST) PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/one_http_stream_fin.pcap", packetStream, errMsg)); tcpReassemblyTest(packetStream, tcpReassemblyResults, true, false); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 5); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 1); @@ -674,7 +683,7 @@ PTF_TEST_CASE(TestTcpReassemblyWithFIN_RST) tcpReassemblyResults.clear(); expectedReassemblyData.clear(); - //test fin packet in end of connection that has also data + // test fin packet in end of connection that has also data PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/one_http_stream_fin2.pcap", packetStream, errMsg)); tcpReassemblyTest(packetStream, tcpReassemblyResults, true, false); @@ -711,9 +720,7 @@ PTF_TEST_CASE(TestTcpReassemblyWithFIN_RST) PTF_ASSERT_FALSE(stats.begin()->second.connectionsEndedManually); expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_http_stream_fin2_output2.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyWithFIN_RST - - +} // TestTcpReassemblyWithFIN_RST PTF_TEST_CASE(TestTcpReassemblyMalformedPkts) { @@ -733,7 +740,7 @@ PTF_TEST_CASE(TestTcpReassemblyMalformedPkts) tcpReassemblyTest(packetStream, tcpReassemblyResults, true, false); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 6); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 1); @@ -743,9 +750,7 @@ PTF_TEST_CASE(TestTcpReassemblyMalformedPkts) PTF_ASSERT_FALSE(stats.begin()->second.connectionsEndedManually); expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_http_stream_fin2_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyMalformedPkts - - +} // TestTcpReassemblyMalformedPkts PTF_TEST_CASE(TestTcpReassemblyMultipleConns) { @@ -753,7 +758,8 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) std::string errMsg; std::string expectedReassemblyData; - pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback); + pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback); std::vector packetStream; PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/three_http_streams.pcap", packetStream, errMsg)); @@ -765,32 +771,19 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) packetStream.erase(packetStream.begin() + 14); pcpp::TcpReassembly::ReassemblyStatus expectedStatuses[26] = { - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::FIN_RSTWithNoData, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::FIN_RSTWithNoData, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::TcpMessageHandled, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::FIN_RSTWithNoData, - pcpp::TcpReassembly::FIN_RSTWithNoData, - pcpp::TcpReassembly::Ignore_PacketWithNoData, - pcpp::TcpReassembly::Ignore_PacketWithNoData, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::TcpMessageHandled, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::TcpMessageHandled, + pcpp::TcpReassembly::Ignore_PacketWithNoData, pcpp::TcpReassembly::TcpMessageHandled, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::Ignore_PacketWithNoData, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::TcpMessageHandled, + pcpp::TcpReassembly::Ignore_PacketWithNoData, pcpp::TcpReassembly::TcpMessageHandled, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::Ignore_PacketWithNoData, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::FIN_RSTWithNoData, + pcpp::TcpReassembly::Ignore_PacketWithNoData, pcpp::TcpReassembly::FIN_RSTWithNoData, + pcpp::TcpReassembly::Ignore_PacketWithNoData, pcpp::TcpReassembly::Ignore_PacketWithNoData, + pcpp::TcpReassembly::TcpMessageHandled, pcpp::TcpReassembly::Ignore_PacketWithNoData, + pcpp::TcpReassembly::FIN_RSTWithNoData, pcpp::TcpReassembly::FIN_RSTWithNoData, + pcpp::TcpReassembly::Ignore_PacketWithNoData, pcpp::TcpReassembly::Ignore_PacketWithNoData, }; int statusIndex = 0; @@ -802,7 +795,7 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) PTF_ASSERT_EQUAL(status, expectedStatuses[statusIndex++], enum); } - TcpReassemblyMultipleConnStats::Stats &stats = results.stats; + TcpReassemblyMultipleConnStats::Stats& stats = results.stats; PTF_ASSERT_EQUAL(stats.size(), 3); PTF_ASSERT_EQUAL(results.flowKeysList.size(), 3); @@ -839,15 +832,17 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) expectedReassemblyData = readFileIntoString(std::string("PcapExamples/three_http_streams_conn_3_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, iter->second.reassembledData); - // test getConnectionInformation and isConnectionOpen - const pcpp::TcpReassembly::ConnectionInfoList &managedConnections = tcpReassembly.getConnectionInformation(); + const pcpp::TcpReassembly::ConnectionInfoList& managedConnections = tcpReassembly.getConnectionInformation(); PTF_ASSERT_EQUAL(managedConnections.size(), 3); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn1 = managedConnections.find(results.flowKeysList[0]); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn2 = managedConnections.find(results.flowKeysList[1]); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn3 = managedConnections.find(results.flowKeysList[2]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn1 = + managedConnections.find(results.flowKeysList[0]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn2 = + managedConnections.find(results.flowKeysList[1]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn3 = + managedConnections.find(results.flowKeysList[2]); PTF_ASSERT_TRUE(iterConn1 != managedConnections.end()); PTF_ASSERT_TRUE(iterConn2 != managedConnections.end()); PTF_ASSERT_TRUE(iterConn3 != managedConnections.end()); @@ -855,7 +850,7 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn2->second), 0); PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn3->second), 0); - //test Connection Information data + // test Connection Information data pcpp::IPv4Address expectedSrcIP("172.16.133.132"); pcpp::IPv4Address expectedDstIP("98.139.161.29"); PTF_ASSERT_EQUAL(iterConn1->second.srcIP, expectedSrcIP); @@ -873,14 +868,12 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) dummyConn.flowKey = 0x12345678; PTF_ASSERT_LOWER_THAN(tcpReassembly.isConnectionOpen(dummyConn), 0); - // close flow manually and verify it's closed tcpReassembly.closeConnection(iter->first); PTF_ASSERT_FALSE(iter->second.connectionsEnded); PTF_ASSERT_TRUE(iter->second.connectionsEndedManually); - // now send FIN packets of conn 3 and verify they are ignored pcpp::TcpReassembly::ReassemblyStatus status = tcpReassembly.reassemblePacket(&finPacket1); @@ -890,9 +883,7 @@ PTF_TEST_CASE(TestTcpReassemblyMultipleConns) PTF_ASSERT_FALSE(iter->second.connectionsEnded); PTF_ASSERT_TRUE(iter->second.connectionsEndedManually); -} // TestTcpReassemblyMultipleConns - - +} // TestTcpReassemblyMultipleConns PTF_TEST_CASE(TestTcpReassemblyIPv6) { @@ -904,7 +895,7 @@ PTF_TEST_CASE(TestTcpReassemblyIPv6) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 10); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 3); @@ -923,9 +914,7 @@ PTF_TEST_CASE(TestTcpReassemblyIPv6) std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_ipv6_http_stream.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyIPv6 - - +} // TestTcpReassemblyIPv6 PTF_TEST_CASE(TestTcpReassemblyIPv6MultConns) { @@ -938,7 +927,7 @@ PTF_TEST_CASE(TestTcpReassemblyIPv6MultConns) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 4); TcpReassemblyMultipleConnStats::Stats::iterator iter = stats.begin(); @@ -1014,9 +1003,7 @@ PTF_TEST_CASE(TestTcpReassemblyIPv6MultConns) PTF_ASSERT_EQUAL(stats.begin()->second.connData.endTime.tv_usec, 0); expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_ipv6_http_stream2.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, iter->second.reassembledData); -} // TestTcpReassemblyIPv6MultConns - - +} // TestTcpReassemblyIPv6MultConns PTF_TEST_CASE(TestTcpReassemblyIPv6_OOO) { @@ -1038,7 +1025,7 @@ PTF_TEST_CASE(TestTcpReassemblyIPv6_OOO) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 10); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 3); @@ -1057,9 +1044,7 @@ PTF_TEST_CASE(TestTcpReassemblyIPv6_OOO) std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_ipv6_http_stream.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} // TestTcpReassemblyIPv6_OOO - - +} // TestTcpReassemblyIPv6_OOO PTF_TEST_CASE(TestTcpReassemblyCleanup) { @@ -1067,7 +1052,8 @@ PTF_TEST_CASE(TestTcpReassemblyCleanup) std::string errMsg; pcpp::TcpReassemblyConfiguration config(true, 2, 1); - pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback, config); + pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback, config); std::vector packetStream; PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/three_http_streams.pcap", packetStream, errMsg)); @@ -1076,19 +1062,23 @@ PTF_TEST_CASE(TestTcpReassemblyCleanup) packetStream.pop_back(); - for(auto iter : packetStream) + for (auto iter : packetStream) { pcpp::Packet packet(&iter); tcpReassembly.reassemblePacket(packet); } - pcpp::TcpReassembly::ConnectionInfoList managedConnections = tcpReassembly.getConnectionInformation(); // make a copy of list + pcpp::TcpReassembly::ConnectionInfoList managedConnections = + tcpReassembly.getConnectionInformation(); // make a copy of list PTF_ASSERT_EQUAL(managedConnections.size(), 3); PTF_ASSERT_EQUAL(results.flowKeysList.size(), 3); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn1 = managedConnections.find(results.flowKeysList[0]); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn2 = managedConnections.find(results.flowKeysList[1]); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn3 = managedConnections.find(results.flowKeysList[2]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn1 = + managedConnections.find(results.flowKeysList[0]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn2 = + managedConnections.find(results.flowKeysList[1]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn3 = + managedConnections.find(results.flowKeysList[2]); PTF_ASSERT_TRUE(iterConn1 != managedConnections.end()); PTF_ASSERT_TRUE(iterConn2 != managedConnections.end()); PTF_ASSERT_TRUE(iterConn3 != managedConnections.end()); @@ -1098,13 +1088,13 @@ PTF_TEST_CASE(TestTcpReassemblyCleanup) pcpp::multiPlatformSleep(3); - tcpReassembly.reassemblePacket(&lastPacket); // automatic cleanup of 1 item + tcpReassembly.reassemblePacket(&lastPacket); // automatic cleanup of 1 item PTF_ASSERT_EQUAL(tcpReassembly.getConnectionInformation().size(), 2); - tcpReassembly.purgeClosedConnections(); // manually initiated cleanup of 1 item + tcpReassembly.purgeClosedConnections(); // manually initiated cleanup of 1 item PTF_ASSERT_EQUAL(tcpReassembly.getConnectionInformation().size(), 1); - tcpReassembly.purgeClosedConnections(0xFFFFFFFF); // manually initiated cleanup of all items + tcpReassembly.purgeClosedConnections(0xFFFFFFFF); // manually initiated cleanup of all items PTF_ASSERT_EQUAL(tcpReassembly.getConnectionInformation().size(), 0); const TcpReassemblyMultipleConnStats::FlowKeysList& flowKeys = results.flowKeysList; @@ -1117,9 +1107,7 @@ PTF_TEST_CASE(TestTcpReassemblyCleanup) PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn1->second), -1); PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn2->second), -1); PTF_ASSERT_EQUAL(tcpReassembly.isConnectionOpen(iterConn3->second), -1); -} // TestTcpReassemblyCleanup - - +} // TestTcpReassemblyCleanup PTF_TEST_CASE(TestTcpReassemblyMaxOOOFrags) { @@ -1128,14 +1116,18 @@ PTF_TEST_CASE(TestTcpReassemblyMaxOOOFrags) std::string errMsg; pcpp::TcpReassemblyConfiguration config1(true, 5, 30); - pcpp::TcpReassemblyConfiguration config2(true, 5, 30, 5); // the fourth argument is the max allowed out-of-order fragments, so we only allow 5 - pcpp::TcpReassembly tcpReassembly1(tcpReassemblyMsgReadyCallback, &results1, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback, config1); - pcpp::TcpReassembly tcpReassembly2(tcpReassemblyMsgReadyCallback, &results2, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback, config2); + // the fourth argument is the max allowed out-of-order fragments, so we only allow 5 + pcpp::TcpReassemblyConfiguration config2(true, 5, 30, 5); + pcpp::TcpReassembly tcpReassembly1(tcpReassemblyMsgReadyCallback, &results1, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback, config1); + pcpp::TcpReassembly tcpReassembly2(tcpReassemblyMsgReadyCallback, &results2, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback, config2); std::vector packetStream; - PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/unidirectional_tcp_stream_with_missing_packet.pcap", packetStream, errMsg)); + PTF_ASSERT_TRUE( + readPcapIntoPacketVec("PcapExamples/unidirectional_tcp_stream_with_missing_packet.pcap", packetStream, errMsg)); - for(auto iter : packetStream) + for (auto iter : packetStream) { pcpp::Packet packet(&iter); tcpReassembly1.reassemblePacket(packet); @@ -1143,20 +1135,25 @@ PTF_TEST_CASE(TestTcpReassemblyMaxOOOFrags) } pcpp::TcpReassembly::ConnectionInfoList managedConnections1 = tcpReassembly1.getConnectionInformation(); - pcpp::TcpReassembly::ConnectionInfoList managedConnections2 = tcpReassembly2.getConnectionInformation(); // make a copy of list + pcpp::TcpReassembly::ConnectionInfoList managedConnections2 = + tcpReassembly2.getConnectionInformation(); // make a copy of list PTF_ASSERT_EQUAL(managedConnections1.size(), 1); PTF_ASSERT_EQUAL(managedConnections2.size(), 1); PTF_ASSERT_EQUAL(results1.flowKeysList.size(), 1); PTF_ASSERT_EQUAL(results2.flowKeysList.size(), 1); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn1 = managedConnections1.find(results1.flowKeysList[0]); - pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn2 = managedConnections2.find(results2.flowKeysList[0]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn1 = + managedConnections1.find(results1.flowKeysList[0]); + pcpp::TcpReassembly::ConnectionInfoList::const_iterator iterConn2 = + managedConnections2.find(results2.flowKeysList[0]); PTF_ASSERT_TRUE(iterConn1 != managedConnections1.end()); PTF_ASSERT_TRUE(iterConn2 != managedConnections2.end()); PTF_ASSERT_EQUAL(tcpReassembly1.isConnectionOpen(iterConn1->second), 1); PTF_ASSERT_EQUAL(tcpReassembly2.isConnectionOpen(iterConn2->second), 1); - PTF_ASSERT_EQUAL(results1.stats.begin()->second.numOfDataPackets, 1); // The second data packet is incomplete so we stopped at one - PTF_ASSERT_EQUAL(results2.stats.begin()->second.numOfDataPackets, 7); // We hit the fragment limit so skipped the missing fragment and continued to the end + // The second data packet is incomplete so we stopped at one + PTF_ASSERT_EQUAL(results1.stats.begin()->second.numOfDataPackets, 1); + // We hit the fragment limit so skipped the missing fragment and continued to the end + PTF_ASSERT_EQUAL(results2.stats.begin()->second.numOfDataPackets, 7); // Close the connections, forcing cleanup tcpReassembly1.closeAllConnections(); @@ -1165,9 +1162,7 @@ PTF_TEST_CASE(TestTcpReassemblyMaxOOOFrags) // Everything should be processed now PTF_ASSERT_EQUAL(results1.stats.begin()->second.numOfDataPackets, 7); PTF_ASSERT_EQUAL(results2.stats.begin()->second.numOfDataPackets, 7); -} // TestTcpReassemblyCleanup - - +} // TestTcpReassemblyCleanup PTF_TEST_CASE(TestTcpReassemblyMaxSeq) { @@ -1179,7 +1174,7 @@ PTF_TEST_CASE(TestTcpReassemblyMaxSeq) TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; PTF_ASSERT_EQUAL(stats.size(), 1); PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 19); PTF_ASSERT_EQUAL(stats.begin()->second.numOfMessagesFromSide[0], 2); @@ -1198,9 +1193,9 @@ PTF_TEST_CASE(TestTcpReassemblyMaxSeq) std::string expectedReassemblyData = readFileIntoString(std::string("PcapExamples/one_tcp_stream_output.txt")); PTF_ASSERT_EQUAL(expectedReassemblyData, stats.begin()->second.reassembledData); -} //TestTcpReassemblyMaxSeq +} // TestTcpReassemblyMaxSeq -PTF_TEST_CASE(TestTcpReassemblyDisableOOOCleanup) // TestTcpReassemblyDisableBaseOutOfOrderBufferCleanupCondition +PTF_TEST_CASE(TestTcpReassemblyDisableOOOCleanup) // TestTcpReassemblyDisableBaseOutOfOrderBufferCleanupCondition { std::string errMsg; std::vector packetStream; @@ -1208,8 +1203,10 @@ PTF_TEST_CASE(TestTcpReassemblyDisableOOOCleanup) // TestTcpReassemblyDisableBas TcpReassemblyMultipleConnStats results2; pcpp::TcpReassemblyConfiguration config1(true, 5, 30, 20, true); pcpp::TcpReassemblyConfiguration config2(true, 5, 30, 20, false); - pcpp::TcpReassembly tcpReassembly1(tcpReassemblyMsgReadyCallback, &results1, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback, config1); - pcpp::TcpReassembly tcpReassembly2(tcpReassemblyMsgReadyCallback, &results2, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback, config2); + pcpp::TcpReassembly tcpReassembly1(tcpReassemblyMsgReadyCallback, &results1, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback, config1); + pcpp::TcpReassembly tcpReassembly2(tcpReassemblyMsgReadyCallback, &results2, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback, config2); PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/one_tcp_stream.pcap", packetStream, errMsg)); // unserting a data packet from reverse direction b/w swap 2 consequent data packets @@ -1227,8 +1224,8 @@ PTF_TEST_CASE(TestTcpReassemblyDisableOOOCleanup) // TestTcpReassemblyDisableBas tcpReassembly1.closeAllConnections(); tcpReassembly2.closeAllConnections(); - TcpReassemblyMultipleConnStats::Stats &stats1 = results1.stats; - TcpReassemblyMultipleConnStats::Stats &stats2 = results2.stats; + TcpReassemblyMultipleConnStats::Stats& stats1 = results1.stats; + TcpReassemblyMultipleConnStats::Stats& stats2 = results2.stats; PTF_ASSERT_EQUAL(stats1.size(), 1); PTF_ASSERT_EQUAL(stats2.size(), 1); PTF_ASSERT_EQUAL(stats1.begin()->second.numOfDataPackets, 18); @@ -1236,31 +1233,33 @@ PTF_TEST_CASE(TestTcpReassemblyDisableOOOCleanup) // TestTcpReassemblyDisableBas packetStream.clear(); tcpReassemblyResults.clear(); -} // TestTcpReassemblyDisableOOOCleanup +} // TestTcpReassemblyDisableOOOCleanup PTF_TEST_CASE(TestTcpReassemblyTimeStamps) { std::string errMsg; std::vector packetStream; - PTF_ASSERT_TRUE(readPcapIntoPacketVec("PcapExamples/unidirectional_tcp_stream_with_missing_packet.pcap", packetStream, errMsg)); + PTF_ASSERT_TRUE( + readPcapIntoPacketVec("PcapExamples/unidirectional_tcp_stream_with_missing_packet.pcap", packetStream, errMsg)); TcpReassemblyMultipleConnStats tcpReassemblyResults; tcpReassemblyTest(packetStream, tcpReassemblyResults, true, true); - TcpReassemblyMultipleConnStats::Stats &stats = tcpReassemblyResults.stats; - PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets,7); + TcpReassemblyMultipleConnStats::Stats& stats = tcpReassemblyResults.stats; + PTF_ASSERT_EQUAL(stats.begin()->second.numOfDataPackets, 7); std::ifstream expectedOutput("PcapExamples/timestamp_output.txt"); - for(long unsigned int i = 0;i>expected; - const int expUsec = std::stoll(expected)%1000000; - const int expSec = std::stoll(expected)/1000000; - PTF_ASSERT_EQUAL(t.tv_usec,expUsec); + expectedOutput >> expected; + const int expUsec = std::stoll(expected) % 1000000; + const int expSec = std::stoll(expected) / 1000000; + PTF_ASSERT_EQUAL(t.tv_usec, expUsec); PTF_ASSERT_EQUAL(t.tv_sec, expSec); } expectedOutput.close(); packetStream.clear(); tcpReassemblyResults.clear(); -} // TestTcpReassemblyTimeStamps +} // TestTcpReassemblyTimeStamps diff --git a/Tests/Pcap++Test/Tests/XdpTests.cpp b/Tests/Pcap++Test/Tests/XdpTests.cpp index 30c9cf4042..13676c3873 100644 --- a/Tests/Pcap++Test/Tests/XdpTests.cpp +++ b/Tests/Pcap++Test/Tests/XdpTests.cpp @@ -6,7 +6,6 @@ #include "Packet.h" #include "Logger.h" - extern PcapTestArgs PcapTestGlobalArgs; #ifdef USE_XDP @@ -17,34 +16,27 @@ struct XdpPacketData int byteCount; uint64_t latestTimestamp; - XdpPacketData() : packetCount(0), byteCount(0), latestTimestamp(0) {} + XdpPacketData() : packetCount(0), byteCount(0), latestTimestamp(0) + {} }; bool assertConfig(const pcpp::XdpDevice::XdpDeviceConfiguration* config, - const pcpp::XdpDevice::XdpDeviceConfiguration::AttachMode expectedAttachMode, - const uint16_t expectedUmemNumFrames, - const uint16_t expectedUmemFrameSize, - const uint32_t expectedFillRingSize, - const uint32_t expectedCompletionRingSize, - const uint32_t expectedRxSize, - const uint32_t expectedTxSize, - const uint16_t expectedRxTxBatchSize) + const pcpp::XdpDevice::XdpDeviceConfiguration::AttachMode expectedAttachMode, + const uint16_t expectedUmemNumFrames, const uint16_t expectedUmemFrameSize, + const uint32_t expectedFillRingSize, const uint32_t expectedCompletionRingSize, + const uint32_t expectedRxSize, const uint32_t expectedTxSize, const uint16_t expectedRxTxBatchSize) { - return ( - config != nullptr && - config->attachMode == expectedAttachMode && - config->umemNumFrames == expectedUmemNumFrames && - config->umemFrameSize == expectedUmemFrameSize && - config->fillRingSize == expectedFillRingSize && - config->completionRingSize == expectedCompletionRingSize && - config->rxSize == expectedRxSize && - config->txSize == expectedTxSize && - config->rxTxBatchSize == expectedRxTxBatchSize); + return (config != nullptr && config->attachMode == expectedAttachMode && + config->umemNumFrames == expectedUmemNumFrames && config->umemFrameSize == expectedUmemFrameSize && + config->fillRingSize == expectedFillRingSize && config->completionRingSize == expectedCompletionRingSize && + config->rxSize == expectedRxSize && config->txSize == expectedTxSize && + config->rxTxBatchSize == expectedRxTxBatchSize); } std::string getDeviceName() { - auto pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); + auto pcapLiveDev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp( + PcapTestGlobalArgs.ipToSendReceivePackets.c_str()); if (pcapLiveDev) { return pcapLiveDev->getName(); @@ -53,8 +45,7 @@ std::string getDeviceName() return ""; } - -#endif // USE_XDP +#endif // USE_XDP PTF_TEST_CASE(TestXdpDeviceReceivePackets) { @@ -67,14 +58,13 @@ PTF_TEST_CASE(TestXdpDeviceReceivePackets) PTF_ASSERT_TRUE(device.open()); - PTF_ASSERT_TRUE( - assertConfig(device.getConfig(), - pcpp::XdpDevice::XdpDeviceConfiguration::AutoMode, - 4096, 4096,4096,2048,2048,2048,64)); + PTF_ASSERT_TRUE(assertConfig(device.getConfig(), pcpp::XdpDevice::XdpDeviceConfiguration::AutoMode, 4096, 4096, + 4096, 2048, 2048, 2048, 64)); XdpPacketData packetData; - auto onPacketsArrive = [](pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpDevice* device, void* userCookie) -> void { + auto onPacketsArrive = [](pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpDevice* device, + void* userCookie) -> void { auto packetData = static_cast(userCookie); for (uint32_t i = 0; i < packetCount; i++) @@ -83,7 +73,8 @@ PTF_TEST_CASE(TestXdpDeviceReceivePackets) { packetData->packetCount++; packetData->byteCount += packets[i].getRawDataLen(); - packetData->latestTimestamp = 1000*1000*1000*packets[i].getPacketTimeStamp().tv_sec + packets[i].getPacketTimeStamp().tv_nsec; + packetData->latestTimestamp = 1000 * 1000 * 1000 * packets[i].getPacketTimeStamp().tv_sec + + packets[i].getPacketTimeStamp().tv_nsec; } } @@ -96,7 +87,7 @@ PTF_TEST_CASE(TestXdpDeviceReceivePackets) timespec ts; clock_gettime(CLOCK_REALTIME, &ts); - uint64_t curTimestamp = 1000*1000*1000*ts.tv_sec + ts.tv_nsec; + uint64_t curTimestamp = 1000 * 1000 * 1000 * ts.tv_sec + ts.tv_nsec; PTF_ASSERT_TRUE(device.receivePackets(onPacketsArrive, &packetData, 20000)); @@ -134,8 +125,7 @@ PTF_TEST_CASE(TestXdpDeviceReceivePackets) #else PTF_SKIP_TEST("XDP not configured"); #endif -} // TestXdpDeviceReceivePackets - +} // TestXdpDeviceReceivePackets PTF_TEST_CASE(TestXdpDeviceSendPackets) { @@ -181,8 +171,7 @@ PTF_TEST_CASE(TestXdpDeviceSendPackets) #else PTF_SKIP_TEST("XDP not configured"); #endif -} // TestXdpDeviceSendPackets - +} // TestXdpDeviceSendPackets PTF_TEST_CASE(TestXdpDeviceNonDefaultConfig) { @@ -191,18 +180,17 @@ PTF_TEST_CASE(TestXdpDeviceNonDefaultConfig) PTF_ASSERT_FALSE(devName.empty()); pcpp::XdpDevice device(devName); - auto config = pcpp::XdpDevice::XdpDeviceConfiguration(pcpp::XdpDevice::XdpDeviceConfiguration::SkbMode, - 1000, 4096, 512, 512, 512, 512, 20); + auto config = pcpp::XdpDevice::XdpDeviceConfiguration(pcpp::XdpDevice::XdpDeviceConfiguration::SkbMode, 1000, 4096, + 512, 512, 512, 512, 20); PTF_ASSERT_TRUE(device.open(config)); - PTF_ASSERT_TRUE( - assertConfig(device.getConfig(), - pcpp::XdpDevice::XdpDeviceConfiguration::SkbMode, - 1000, 4096,512,512,512,512,20)); + PTF_ASSERT_TRUE(assertConfig(device.getConfig(), pcpp::XdpDevice::XdpDeviceConfiguration::SkbMode, 1000, 4096, 512, + 512, 512, 512, 20)); int numPackets = 0; - auto onPacketsArrive = [](pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpDevice* device, void* userCookie) -> void { + auto onPacketsArrive = [](pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpDevice* device, + void* userCookie) -> void { int* totalPacketCount = static_cast(userCookie); for (uint32_t i = 0; i < packetCount; i++) @@ -225,8 +213,7 @@ PTF_TEST_CASE(TestXdpDeviceNonDefaultConfig) #else PTF_SKIP_TEST("XDP not configured"); #endif -} // TestXdpDeviceNonDefaultConfig - +} // TestXdpDeviceNonDefaultConfig PTF_TEST_CASE(TestXdpDeviceInvalidConfig) { @@ -301,4 +288,4 @@ PTF_TEST_CASE(TestXdpDeviceInvalidConfig) #else PTF_SKIP_TEST("XDP not configured"); #endif -} // TestXdpDeviceInvalidConfig +} // TestXdpDeviceInvalidConfig diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index 4c38c16223..ec159a31e2 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -8,47 +8,48 @@ #include "Common/TestUtils.h" #include -static struct option PcapTestOptions[] = -{ - {"debug-mode", no_argument, nullptr, 'b'}, - {"use-ip", required_argument, nullptr, 'i'}, - {"remote-ip", required_argument, nullptr, 'r'}, - {"remote-port", required_argument, nullptr, 'p'}, - {"dpdk-port", required_argument, nullptr, 'd' }, - {"no-networking", no_argument, nullptr, 'n' }, - {"verbose", no_argument, nullptr, 'v' }, - {"mem-verbose", no_argument, nullptr, 'm' }, - {"kni-ip", no_argument, nullptr, 'k' }, - {"skip-mem-leak-check", no_argument, nullptr, 's' }, - {"include-tags", required_argument, nullptr, 't'}, - {"exclude-tags", required_argument, nullptr, 'x'}, - {"show-skipped-tests", no_argument, nullptr, 'w' }, - {"help", no_argument, nullptr, 'h'}, - {nullptr, 0, nullptr, 0} +// clang-format off +static struct option PcapTestOptions[] = { + { "debug-mode", no_argument, nullptr, 'b' }, + { "use-ip", required_argument, nullptr, 'i' }, + { "remote-ip", required_argument, nullptr, 'r' }, + { "remote-port", required_argument, nullptr, 'p' }, + { "dpdk-port", required_argument, nullptr, 'd' }, + { "no-networking", no_argument, nullptr, 'n' }, + { "verbose", no_argument, nullptr, 'v' }, + { "mem-verbose", no_argument, nullptr, 'm' }, + { "kni-ip", no_argument, nullptr, 'k' }, + { "skip-mem-leak-check", no_argument, nullptr, 's' }, + { "include-tags", required_argument, nullptr, 't' }, + { "exclude-tags", required_argument, nullptr, 'x' }, + { "show-skipped-tests", no_argument, nullptr, 'w' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 }, }; - +// clang-format on void printUsage() { - std::cout << "Usage: Pcap++Test -i ip_to_use | [-n] [-b] [-s] [-m] [-r remote_ip_addr] [-p remote_port] [-d dpdk_port] [-k ip_addr] [-t tags] [-w] [-h]\n\n" - << "Flags:\n" - << "-i --use-ip IP to use for sending and receiving packets\n" - << "-b --debug-mode Set log level to DEBUG\n" - << "-r --remote-ip IP of remote machine running rpcapd to test remote capture\n" - << "-p --remote-port Port of remote machine running rpcapd to test remote capture\n" - << "-d --dpdk-port The DPDK NIC port to test. Required if compiling with DPDK\n" - << "-n --no-networking Do not run tests that requires networking\n" - << "-v --verbose Run in verbose mode (emits more output in several tests)\n" - << "-m --mem-verbose Output information about each memory allocation and deallocation\n" - << "-s --skip-mem-leak-check Skip memory leak check\n" - << "-k --kni-ip IP address for KNI device tests to use must not be the same\n" - << " as any of existing network interfaces in your system.\n" - << " If this parameter is omitted KNI tests will be skipped. Must be an IPv4.\n" - << " For Linux systems only\n" - << "-t --include-tags A list of semicolon separated tags for tests to run\n" - << "-x --exclude-tags A list of semicolon separated tags for tests to exclude\n" - << "-w --show-skipped-tests Show tests that are skipped. Default is to hide them in tests results\n" - << "-h --help Display this help message and exit\n"; + std::cout << "Usage: Pcap++Test -i ip_to_use | [-n] [-b] [-s] [-m] [-r remote_ip_addr] [-p remote_port] [-d " + "dpdk_port] [-k ip_addr] [-t tags] [-w] [-h]\n\n" + << "Flags:\n" + << "-i --use-ip IP to use for sending and receiving packets\n" + << "-b --debug-mode Set log level to DEBUG\n" + << "-r --remote-ip IP of remote machine running rpcapd to test remote capture\n" + << "-p --remote-port Port of remote machine running rpcapd to test remote capture\n" + << "-d --dpdk-port The DPDK NIC port to test. Required if compiling with DPDK\n" + << "-n --no-networking Do not run tests that requires networking\n" + << "-v --verbose Run in verbose mode (emits more output in several tests)\n" + << "-m --mem-verbose Output information about each memory allocation and deallocation\n" + << "-s --skip-mem-leak-check Skip memory leak check\n" + << "-k --kni-ip IP address for KNI device tests to use must not be the same\n" + << " as any of existing network interfaces in your system.\n" + << " If this parameter is omitted KNI tests will be skipped. Must be an IPv4.\n" + << " For Linux systems only\n" + << "-t --include-tags A list of semicolon separated tags for tests to run\n" + << "-x --exclude-tags A list of semicolon separated tags for tests to exclude\n" + << "-w --show-skipped-tests Show tests that are skipped. Default is to hide them in tests results\n" + << "-h --help Display this help message and exit\n"; } PcapTestArgs PcapTestGlobalArgs; @@ -67,57 +68,57 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "k:i:br:p:d:nvt:x:smw", PcapTestOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "k:i:br:p:d:nvt:x:smw", PcapTestOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'k': - PcapTestGlobalArgs.kniIp = optarg; - break; - case 'i': - PcapTestGlobalArgs.ipToSendReceivePackets = optarg; - break; - case 'b': - PcapTestGlobalArgs.debugMode = true; - break; - case 'r': - PcapTestGlobalArgs.remoteIp = optarg; - break; - case 'p': - PcapTestGlobalArgs.remotePort = (uint16_t)atoi(optarg); - break; - case 'd': - PcapTestGlobalArgs.dpdkPort = (int)atoi(optarg); - break; - case 'n': - runWithNetworking = false; - break; - case 'v': - PTF_SET_VERBOSE_MODE(true); - break; - case 't': - userTagsInclude = optarg; - break; - case 'x': - userTagsExclude = optarg; - break; - case 's': - skipMemLeakCheck = true; - break; - case 'm': - memVerbose = true; - break; - case 'w': - PTF_SHOW_SKIPPED_TESTS(true); - break; - case 'h': - printUsage(); - exit(0); - default: - printUsage(); - exit(-1); + case 0: + break; + case 'k': + PcapTestGlobalArgs.kniIp = optarg; + break; + case 'i': + PcapTestGlobalArgs.ipToSendReceivePackets = optarg; + break; + case 'b': + PcapTestGlobalArgs.debugMode = true; + break; + case 'r': + PcapTestGlobalArgs.remoteIp = optarg; + break; + case 'p': + PcapTestGlobalArgs.remotePort = (uint16_t)atoi(optarg); + break; + case 'd': + PcapTestGlobalArgs.dpdkPort = (int)atoi(optarg); + break; + case 'n': + runWithNetworking = false; + break; + case 'v': + PTF_SET_VERBOSE_MODE(true); + break; + case 't': + userTagsInclude = optarg; + break; + case 'x': + userTagsExclude = optarg; + break; + case 's': + skipMemLeakCheck = true; + break; + case 'm': + memVerbose = true; + break; + case 'w': + PTF_SHOW_SKIPPED_TESTS(true); + break; + case 'h': + printUsage(); + exit(0); + default: + printUsage(); + exit(-1); } } @@ -127,7 +128,7 @@ int main(int argc, char* argv[]) userTagsInclude += ";"; userTagsInclude += "no_network"; - std:: cout << "Running only tests that don't require network connection" << std::endl; + std::cout << "Running only tests that don't require network connection" << std::endl; } else if (PcapTestGlobalArgs.ipToSendReceivePackets == "") { @@ -136,11 +137,13 @@ int main(int argc, char* argv[]) exit(-1); } - #ifdef NDEBUG +#ifdef NDEBUG skipMemLeakCheck = true; - std:: cout << "Disabling memory leak check in MSVC Release builds due to caching logic in stream objects that looks like a memory leak:" << std::endl - << " https://github.com/cpputest/cpputest/issues/786#issuecomment-148921958" << std::endl; - #endif + std::cout << "Disabling memory leak check in MSVC Release builds due to caching logic in stream objects that looks " + "like a memory leak:" + << std::endl + << " 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(); @@ -152,7 +155,7 @@ int main(int argc, char* argv[]) configTags += ";"; configTags += "skip_mem_leak_check"; - std:: cout << "Skipping memory leak check for all test cases" << std::endl; + std::cout << "Skipping memory leak check for all test cases" << std::endl; } if (memVerbose) @@ -161,7 +164,7 @@ int main(int argc, char* argv[]) configTags += ";"; configTags += "mem_leak_check_verbose"; - std:: cout << "Turning on verbose information on memory allocations" << std::endl; + std::cout << "Turning on verbose information on memory allocations" << std::endl; } #ifdef USE_DPDK @@ -171,7 +174,7 @@ int main(int argc, char* argv[]) printUsage(); exit(-1); } -#endif // USE_DPDK +#endif // USE_DPDK if (PcapTestGlobalArgs.debugMode) { @@ -179,10 +182,10 @@ int main(int argc, char* argv[]) } std::cout << "PcapPlusPlus version: " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Git info: " << pcpp::getGitInfo() << std::endl - << "Using ip: " << PcapTestGlobalArgs.ipToSendReceivePackets << std::endl - << "Debug mode: " << (PcapTestGlobalArgs.debugMode ? "on" : "off") << std::endl; + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Git info: " << pcpp::getGitInfo() << std::endl + << "Using ip: " << PcapTestGlobalArgs.ipToSendReceivePackets << std::endl + << "Debug mode: " << (PcapTestGlobalArgs.debugMode ? "on" : "off") << std::endl; #ifdef USE_DPDK if (runWithNetworking) @@ -307,5 +310,5 @@ int main(int argc, char* argv[]) } #ifdef _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif diff --git a/Tests/PcppTestFramework/PcppTestFramework.h b/Tests/PcppTestFramework/PcppTestFramework.h index 648dceeb73..341f71d855 100644 --- a/Tests/PcppTestFramework/PcppTestFramework.h +++ b/Tests/PcppTestFramework/PcppTestFramework.h @@ -13,252 +13,270 @@ #define enum_PTF_PRINT_TYPE_EXPECTED(exp, val) exp << "[" << val << "]" #define ptr_PTF_PRINT_TYPE_ACTUAL(exp, val) exp << "[ptr: " << val << "]" #define ptr_PTF_PRINT_TYPE_EXPECTED(exp, val) exp << "[ptr: " << val << "]" -#define enumclass_PTF_PRINT_TYPE_ACTUAL(exp, val) "enum[" << +static_cast::type>(val) << "]" -#define enumclass_PTF_PRINT_TYPE_EXPECTED(exp, val) exp << "[" << +static_cast::type>(val) << "]" -#define BUFFER_PRINT(buffer, size) \ - for(size_t currentByteId = 0; currentByteId < static_cast(size); ++currentByteId) { \ - std::cout << std::setfill('0') << std::setw(2) << std::right << std::hex << static_cast(*(buffer + currentByteId)) << " "; \ - } \ - std::cout << std::setfill(' ') << std::setw(0) << std::left << std::dec; \ +#define enumclass_PTF_PRINT_TYPE_ACTUAL(exp, val) \ + "enum[" << +static_cast::type>(val) << "]" +#define enumclass_PTF_PRINT_TYPE_EXPECTED(exp, val) \ + exp << "[" << +static_cast::type>(val) << "]" +#define BUFFER_PRINT(buffer, size) \ + for (size_t currentByteId = 0; currentByteId < static_cast(size); ++currentByteId) \ + { \ + std::cout << std::setfill('0') << std::setw(2) << std::right << std::hex \ + << static_cast(*(buffer + currentByteId)) << " "; \ + } \ + std::cout << std::setfill(' ') << std::setw(0) << std::left << std::dec; \ std::cout << std::endl +#define PTF_PRINT_ASSERTION(severity, op) \ + std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " << severity << " (" << __FILE__ << ":" << __LINE__ \ + << "). " \ + << "Assert " << op << " failed:" << std::endl -#define PTF_PRINT_ASSERTION(severity, op) \ - std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ - << severity \ - << " (" << __FILE__ << ":" << __LINE__ << "). " \ - << "Assert " << op << " failed:" \ - << std::endl +#define PTF_PRINT_COMPARE_ASSERTION(severity, op, actualExp, actualVal, expectedExp, expectedVal, objType) \ + PTF_PRINT_ASSERTION(severity, op) << " Actual: " << objType##_PTF_PRINT_TYPE_ACTUAL(actualExp, actualVal) \ + << std::endl \ + << " Expected: " \ + << objType##_PTF_PRINT_TYPE_EXPECTED(expectedExp, expectedVal) << std::endl -#define PTF_PRINT_COMPARE_ASSERTION(severity, op, actualExp, actualVal, expectedExp, expectedVal, objType) \ - PTF_PRINT_ASSERTION(severity, op) \ - << " Actual: " << objType##_PTF_PRINT_TYPE_ACTUAL(actualExp, actualVal) \ - << std::endl \ - << " Expected: " << objType##_PTF_PRINT_TYPE_EXPECTED(expectedExp, expectedVal) \ - << std::endl - -#define PTF_PRINT_COMPARE_ASSERTION_FAILED(op, actualExp, actualVal, expectedExp, expectedVal, objType) \ +#define PTF_PRINT_COMPARE_ASSERTION_FAILED(op, actualExp, actualVal, expectedExp, expectedVal, objType) \ PTF_PRINT_COMPARE_ASSERTION("FAILED", op, actualExp, actualVal, expectedExp, expectedVal, objType) -#define PTF_PRINT_COMPARE_ASSERTION_NON_CRITICAL(op, actualExp, actualVal, expectedExp, expectedVal, objType) \ +#define PTF_PRINT_COMPARE_ASSERTION_NON_CRITICAL(op, actualExp, actualVal, expectedExp, expectedVal, objType) \ PTF_PRINT_COMPARE_ASSERTION("NON-CRITICAL", op, actualExp, actualVal, expectedExp, expectedVal, objType) #define PTF_TEST_CASE(TestName) void TestName(int& ptfResult, bool printVerbose, bool showSkipped) -#define PTF_INTERNAL_RUN(TestName) \ - TestName(ptfResult, printVerbose, showSkipped); \ - if (ptfResult == PTF_RESULT_FAILED) { \ - PTF_PRINT_ASSERTION("FAILED", "INTERNAL TEST") \ - << " Internal test '" << #TestName << "' failed" \ - << std::endl; \ - return; \ - } \ - else { \ - ptfResult = PTF_RESULT_PASSED; \ +#define PTF_INTERNAL_RUN(TestName) \ + TestName(ptfResult, printVerbose, showSkipped); \ + if (ptfResult == PTF_RESULT_FAILED) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "INTERNAL TEST") \ + << " Internal test '" << #TestName << "' failed" << std::endl; \ + return; \ + } \ + else \ + { \ + ptfResult = PTF_RESULT_PASSED; \ } #define PTF_IS_VERBOSE_MODE printVerbose -#define PTF_TEST_CASE_PASSED \ - ptfResult = PTF_RESULT_PASSED; \ +#define PTF_TEST_CASE_PASSED \ + ptfResult = PTF_RESULT_PASSED; \ return - -#define PTF_ASSERT_EQUAL(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual != ptfExpected) { \ - PTF_PRINT_COMPARE_ASSERTION_FAILED("EQUAL", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_EQUAL(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual != ptfExpected) \ + { \ + PTF_PRINT_COMPARE_ASSERTION_FAILED("EQUAL", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_VECTORS_EQUAL(actual, expected, ...) \ - { \ - if (actual != expected) {\ - std::ostringstream actualOss, expectedOss; \ - bool first = true; \ - for (const auto& elem : actual) { \ - if (!first) actualOss << ", "; \ - actualOss << elem; \ - first = false; \ - } \ - first = true; \ - for (const auto& elem : expected) { \ - if (!first) expectedOss << ", "; \ - expectedOss << elem; \ - first = false; \ - } \ - std::string actualValues = "[" + actualOss.str() + "]"; \ - std::string expectedValues = "[" + expectedOss.str() + "]"; \ - PTF_PRINT_COMPARE_ASSERTION_FAILED("VECTORS EQUAL", #actual, actualValues, #expected, expectedValues, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_VECTORS_EQUAL(actual, expected, ...) \ + { \ + if (actual != expected) \ + { \ + std::ostringstream actualOss, expectedOss; \ + bool first = true; \ + for (const auto& elem : actual) \ + { \ + if (!first) \ + actualOss << ", "; \ + actualOss << elem; \ + first = false; \ + } \ + first = true; \ + for (const auto& elem : expected) \ + { \ + if (!first) \ + expectedOss << ", "; \ + expectedOss << elem; \ + first = false; \ + } \ + std::string actualValues = "[" + actualOss.str() + "]"; \ + std::string expectedValues = "[" + expectedOss.str() + "]"; \ + PTF_PRINT_COMPARE_ASSERTION_FAILED("VECTORS EQUAL", #actual, actualValues, #expected, expectedValues, \ + __VA_ARGS__); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_NOT_EQUAL(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual == ptfExpected) { \ - PTF_PRINT_COMPARE_ASSERTION_FAILED("NOT EQUAL", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_NOT_EQUAL(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual == ptfExpected) \ + { \ + PTF_PRINT_COMPARE_ASSERTION_FAILED("NOT EQUAL", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_GREATER_THAN(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual <= ptfExpected) { \ - PTF_PRINT_COMPARE_ASSERTION_FAILED("GREATER THAN", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_GREATER_THAN(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual <= ptfExpected) \ + { \ + PTF_PRINT_COMPARE_ASSERTION_FAILED("GREATER THAN", #actual, ptfActual, #expected, ptfExpected, \ + __VA_ARGS__); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_GREATER_OR_EQUAL_THAN(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual < ptfExpected) { \ - PTF_PRINT_COMPARE_ASSERTION_FAILED("GREATER OR EQUAL THAN", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_GREATER_OR_EQUAL_THAN(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual < ptfExpected) \ + { \ + PTF_PRINT_COMPARE_ASSERTION_FAILED("GREATER OR EQUAL THAN", #actual, ptfActual, #expected, ptfExpected, \ + __VA_ARGS__); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_LOWER_THAN(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual >= ptfExpected) { \ +#define PTF_ASSERT_LOWER_THAN(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual >= ptfExpected) \ + { \ PTF_PRINT_COMPARE_ASSERTION_FAILED("LOWER THAN", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_LOWER_OR_EQUAL_THAN(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual > ptfExpected) { \ - PTF_PRINT_COMPARE_ASSERTION_FAILED("LOWER OR EQUAL THAN", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_LOWER_OR_EQUAL_THAN(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual > ptfExpected) \ + { \ + PTF_PRINT_COMPARE_ASSERTION_FAILED("LOWER OR EQUAL THAN", #actual, ptfActual, #expected, ptfExpected, \ + __VA_ARGS__); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_ASSERT_BUF_COMPARE(buf1, buf2, size) \ - if (memcmp(buf1, buf2, size) != 0) { \ - PTF_PRINT_ASSERTION("FAILED", "BUFFER COMPARE") \ - << " Actual " << std::endl; \ - BUFFER_PRINT(buf1, size) \ - << " Expected " << std::endl; \ - BUFFER_PRINT(buf2, size); \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ +#define PTF_ASSERT_BUF_COMPARE(buf1, buf2, size) \ + if (memcmp(buf1, buf2, size) != 0) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "BUFFER COMPARE") << " Actual " << std::endl; \ + BUFFER_PRINT(buf1, size) << " Expected " << std::endl; \ + BUFFER_PRINT(buf2, size); \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ } -#define PTF_ASSERT_TRUE(exp) \ - if (!(exp)) { \ - PTF_PRINT_ASSERTION("FAILED", "TRUE") \ - << " [" << #exp << "]" \ - << std::endl; \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ +#define PTF_ASSERT_TRUE(exp) \ + if (!(exp)) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "TRUE") << " [" << #exp << "]" << std::endl; \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ } -#define PTF_ASSERT_FALSE(exp) \ - if (exp) { \ - PTF_PRINT_ASSERTION("FAILED", "FALSE") \ - << " [" << #exp << "]" \ - << std::endl; \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ +#define PTF_ASSERT_FALSE(exp) \ + if (exp) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "FALSE") << " [" << #exp << "]" << std::endl; \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ } -#define PTF_ASSERT_NOT_NULL(exp) \ - if ((exp) == NULL) { \ - PTF_PRINT_ASSERTION("FAILED", "NOT NULL") \ - << " [" << #exp << "] is NULL" \ - << std::endl; \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ +#define PTF_ASSERT_NOT_NULL(exp) \ + if ((exp) == NULL) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "NOT NULL") << " [" << #exp << "] is NULL" << std::endl; \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ } -#define PTF_ASSERT_NULL(exp) \ - if ((exp) != NULL) { \ - PTF_PRINT_ASSERTION("FAILED", "NULL") \ - << " [" << #exp << "] is not NULL" \ - << std::endl; \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ +#define PTF_ASSERT_NULL(exp) \ + if ((exp) != NULL) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "NULL") << " [" << #exp << "] is not NULL" << std::endl; \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ } -#define PTF_ASSERT_RAISES(expression, exception_type, message) \ - { \ - auto rightExceptionCaught = false; \ - std::string messageCaught = ""; \ - try { \ - expression; \ - } \ - catch (const exception_type& e) { \ - rightExceptionCaught = true; \ - messageCaught = e.what(); \ - } \ - catch ( ... ) { /* do nothing */ } \ - if (!rightExceptionCaught) { \ - PTF_PRINT_ASSERTION("FAILED", "EXCEPTION RAISED") \ - << " " << #exception_type << " not raised" << std::endl; \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ - if (messageCaught != std::string(message)) { \ - PTF_PRINT_ASSERTION("FAILED", "EXCEPTION RAISED") \ - << " " << "Expected message: " << std::string(message) << std::endl \ - << " " << "Message caught : " << messageCaught << std::endl; \ - ptfResult = PTF_RESULT_FAILED; \ - return; \ - } \ +#define PTF_ASSERT_RAISES(expression, exception_type, message) \ + { \ + auto rightExceptionCaught = false; \ + std::string messageCaught = ""; \ + try \ + { \ + expression; \ + } \ + catch (const exception_type& e) \ + { \ + rightExceptionCaught = true; \ + messageCaught = e.what(); \ + } \ + catch (...) \ + { /* do nothing */ \ + } \ + if (!rightExceptionCaught) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "EXCEPTION RAISED") \ + << " " << #exception_type << " not raised" << std::endl; \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ + if (messageCaught != std::string(message)) \ + { \ + PTF_PRINT_ASSERTION("FAILED", "EXCEPTION RAISED") \ + << " " \ + << "Expected message: " << std::string(message) << std::endl \ + << " " \ + << "Message caught : " << messageCaught << std::endl; \ + ptfResult = PTF_RESULT_FAILED; \ + return; \ + } \ } -#define PTF_NON_CRITICAL_EQUAL(actual, expected, ...) \ - { \ - auto ptfActual = actual; \ - auto ptfExpected = static_cast(expected); \ - if (ptfActual != ptfExpected) { \ - PTF_PRINT_COMPARE_ASSERTION_NON_CRITICAL("EQUAL", #actual, ptfActual, #expected, ptfExpected, __VA_ARGS__); \ - } \ +#define PTF_NON_CRITICAL_EQUAL(actual, expected, ...) \ + { \ + auto ptfActual = actual; \ + auto ptfExpected = static_cast(expected); \ + if (ptfActual != ptfExpected) \ + { \ + PTF_PRINT_COMPARE_ASSERTION_NON_CRITICAL("EQUAL", #actual, ptfActual, #expected, ptfExpected, \ + __VA_ARGS__); \ + } \ } -#define PTF_NON_CRITICAL_TRUE(exp) \ - if (!exp) { \ - PTF_PRINT_ASSERTION("NON-CRITICAL", "TRUE") \ - << " [" << #exp << "]" \ - << std::endl; \ +#define PTF_NON_CRITICAL_TRUE(exp) \ + if (!exp) \ + { \ + PTF_PRINT_ASSERTION("NON-CRITICAL", "TRUE") << " [" << #exp << "]" << std::endl; \ } -#define PTF_PRINT_VERBOSE(data) \ - if(printVerbose) { \ - std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ - << "[VERBOSE] " \ - << data \ - << std::endl; \ - } \ +#define PTF_PRINT_VERBOSE(data) \ + if (printVerbose) \ + { \ + std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ + << "[VERBOSE] " << data << std::endl; \ + } -#define PTF_SKIP_TEST(why) \ - { \ - if (showSkipped) { \ - std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ - << "SKIPPED (" << why << ")" \ - << std::endl; \ - } \ - ptfResult = PTF_RESULT_SKIPPED; \ - return; \ +#define PTF_SKIP_TEST(why) \ + { \ + if (showSkipped) \ + { \ + std::cout << std::left << std::setw(35) << __FUNCTION__ << ": " \ + << "SKIPPED (" << why << ")" << std::endl; \ + } \ + ptfResult = PTF_RESULT_SKIPPED; \ + return; \ } diff --git a/Tests/PcppTestFramework/PcppTestFrameworkRun.h b/Tests/PcppTestFramework/PcppTestFrameworkRun.h index af77c5152f..bd5cc0d20d 100644 --- a/Tests/PcppTestFramework/PcppTestFrameworkRun.h +++ b/Tests/PcppTestFramework/PcppTestFrameworkRun.h @@ -14,13 +14,13 @@ static void __ptfSplitString(const std::string& input, std::vector& std::istringstream ss(input); std::string token; - while(std::getline(ss, token, ';')) + while (std::getline(ss, token, ';')) { result.push_back(token); } } -static bool __ptfCheckTags(const std::string &tagSet, const std::string &tagSetToCompareWith, bool emptyTagSetMeansAll) +static bool __ptfCheckTags(const std::string& tagSet, const std::string& tagSetToCompareWith, bool emptyTagSetMeansAll) { std::vector tagSetVec, tagSetToCompareWithVec; @@ -32,9 +32,10 @@ static bool __ptfCheckTags(const std::string &tagSet, const std::string &tagSetT __ptfSplitString(tagSet, tagSetVec); __ptfSplitString(tagSetToCompareWith, tagSetToCompareWithVec); - for (const auto &tagSetToCompareWithIter : tagSetToCompareWithVec) + for (const auto& tagSetToCompareWithIter : tagSetToCompareWithVec) { - if (std::any_of(tagSetVec.begin(), tagSetVec.end(), [tagSetToCompareWithIter](const std::string &val){ return val == tagSetToCompareWithIter;})) + if (std::any_of(tagSetVec.begin(), tagSetVec.end(), + [tagSetToCompareWithIter](const std::string& val) { return val == tagSetToCompareWithIter; })) { return true; } @@ -43,84 +44,88 @@ static bool __ptfCheckTags(const std::string &tagSet, const std::string &tagSetT return false; } -#define PTF_START_RUNNING_TESTS(userIncludeTags, userExcludeTags, configTags) \ - bool allTestsPassed = true; \ - int testsPassed = 0; \ - int testsFailed = 0; \ - int testsSkipped = 0; \ - std::string ptfUserIncludeTags = userIncludeTags; \ - std::string ptfUserExcludeTags = userExcludeTags; \ - std::string configTagsToRun = configTags; \ +#define PTF_START_RUNNING_TESTS(userIncludeTags, userExcludeTags, configTags) \ + bool allTestsPassed = true; \ + int testsPassed = 0; \ + int testsFailed = 0; \ + int testsSkipped = 0; \ + std::string ptfUserIncludeTags = userIncludeTags; \ + std::string ptfUserExcludeTags = userExcludeTags; \ + std::string configTagsToRun = configTags; \ std::cout << "Start running tests..." << std::endl << std::endl -#define PTF_RUN_TEST(TestName, tags) \ - std::string TestName##_tags = std::string(#TestName) + ";" + tags; \ - int TestName##_result = PTF_RESULT_PASSED; \ - if (!__ptfCheckTags(TestName##_tags, ptfUserIncludeTags, true) || __ptfCheckTags(TestName##_tags, ptfUserExcludeTags, false)) \ - { \ - if (showSkippedTests) \ - { \ - std::cout << std::left << std::setw(35) << #TestName << ": SKIPPED (tags don't match)" << std::endl; \ - } \ - TestName##_result = PTF_RESULT_SKIPPED; \ - } \ - else \ - { \ - bool runMemLeakCheck = !__ptfCheckTags("skip_mem_leak_check", configTagsToRun, false) && !__ptfCheckTags(TestName##_tags, "skip_mem_leak_check", false); \ - if (runMemLeakCheck) \ - { \ - bool memAllocVerbose = __ptfCheckTags("mem_leak_check_verbose", configTagsToRun, false); \ - MemPlumber::start(memAllocVerbose); \ - } \ - try \ - { \ - TestName(TestName##_result, verboseMode, showSkippedTests); \ - } \ - catch (std::exception const& e) \ - { \ - TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(35) << #TestName << ": FAILED. Unhandled exception occurred! " \ - << "Exception: " << e.what() << std::endl; \ - } \ - if (runMemLeakCheck) \ - { \ - if (TestName##_result != PTF_RESULT_PASSED) \ - { \ - MemPlumber::stopAndFreeAllMemory(); \ - } \ - else \ - { \ - size_t memLeakCount = 0; \ - uint64_t memLeakSize = 0; \ - MemPlumber::memLeakCheck(memLeakCount, memLeakSize, true); \ - MemPlumber::stopAndFreeAllMemory(); \ - if (memLeakCount > 0 || memLeakSize > 0) \ - { \ - TestName##_result = PTF_RESULT_FAILED; \ - std::cout << std::left << std::setw(35) << #TestName << ": FAILED. Memory leak found! " \ - << memLeakCount << " objects and " \ - << memLeakSize << "[bytes] leaked" << std::endl; \ - } \ - } \ - } \ - if (TestName##_result == PTF_RESULT_PASSED) \ - { \ - std::cout << std::left << std::setw(35) << #TestName << ": PASSED" << std::endl; \ - } \ - } \ - if (TestName##_result == PTF_RESULT_PASSED) testsPassed++; \ - if (TestName##_result == PTF_RESULT_FAILED) testsFailed++; \ - if (TestName##_result == PTF_RESULT_SKIPPED) testsSkipped++; \ +#define PTF_RUN_TEST(TestName, tags) \ + std::string TestName##_tags = std::string(#TestName) + ";" + tags; \ + int TestName##_result = PTF_RESULT_PASSED; \ + if (!__ptfCheckTags(TestName##_tags, ptfUserIncludeTags, true) || \ + __ptfCheckTags(TestName##_tags, ptfUserExcludeTags, false)) \ + { \ + if (showSkippedTests) \ + { \ + std::cout << std::left << std::setw(35) << #TestName << ": SKIPPED (tags don't match)" << std::endl; \ + } \ + TestName##_result = PTF_RESULT_SKIPPED; \ + } \ + else \ + { \ + bool runMemLeakCheck = !__ptfCheckTags("skip_mem_leak_check", configTagsToRun, false) && \ + !__ptfCheckTags(TestName##_tags, "skip_mem_leak_check", false); \ + if (runMemLeakCheck) \ + { \ + bool memAllocVerbose = __ptfCheckTags("mem_leak_check_verbose", configTagsToRun, false); \ + MemPlumber::start(memAllocVerbose); \ + } \ + try \ + { \ + TestName(TestName##_result, verboseMode, showSkippedTests); \ + } \ + catch (std::exception const& e) \ + { \ + TestName##_result = PTF_RESULT_FAILED; \ + std::cout << std::left << std::setw(35) << #TestName << ": FAILED. Unhandled exception occurred! " \ + << "Exception: " << e.what() << std::endl; \ + } \ + if (runMemLeakCheck) \ + { \ + if (TestName##_result != PTF_RESULT_PASSED) \ + { \ + MemPlumber::stopAndFreeAllMemory(); \ + } \ + else \ + { \ + size_t memLeakCount = 0; \ + uint64_t memLeakSize = 0; \ + MemPlumber::memLeakCheck(memLeakCount, memLeakSize, true); \ + MemPlumber::stopAndFreeAllMemory(); \ + if (memLeakCount > 0 || memLeakSize > 0) \ + { \ + TestName##_result = PTF_RESULT_FAILED; \ + std::cout << std::left << std::setw(35) << #TestName << ": FAILED. Memory leak found! " \ + << memLeakCount << " objects and " << memLeakSize << "[bytes] leaked" << std::endl; \ + } \ + } \ + } \ + if (TestName##_result == PTF_RESULT_PASSED) \ + { \ + std::cout << std::left << std::setw(35) << #TestName << ": PASSED" << std::endl; \ + } \ + } \ + if (TestName##_result == PTF_RESULT_PASSED) \ + testsPassed++; \ + if (TestName##_result == PTF_RESULT_FAILED) \ + testsFailed++; \ + if (TestName##_result == PTF_RESULT_SKIPPED) \ + testsSkipped++; \ allTestsPassed &= (TestName##_result != PTF_RESULT_FAILED) - -#define PTF_END_RUNNING_TESTS \ - std::string message = (allTestsPassed ? "ALL TESTS PASSED!!" : "NOT ALL TESTS PASSED!!"); \ - std::cout << std::endl << message << std::endl \ - << "Test cases: " << testsPassed + testsFailed + testsSkipped << ", " \ - << "Passed: " << testsPassed << ", " \ - << "Failed: " << testsFailed << ", " \ - << "Skipped: " << testsSkipped << std::endl; \ +#define PTF_END_RUNNING_TESTS \ + std::string message = (allTestsPassed ? "ALL TESTS PASSED!!" : "NOT ALL TESTS PASSED!!"); \ + std::cout << std::endl \ + << message << std::endl \ + << "Test cases: " << testsPassed + testsFailed + testsSkipped << ", " \ + << "Passed: " << testsPassed << ", " \ + << "Failed: " << testsFailed << ", " \ + << "Skipped: " << testsSkipped << std::endl; \ return (allTestsPassed ? 0 : 1); static bool verboseMode = false; From 7fb50c9e99178f1e1b14635008a2467c3877e4e2 Mon Sep 17 00:00:00 2001 From: "Liu, An-Chi" Date: Mon, 29 Jul 2024 09:37:13 +0900 Subject: [PATCH 15/35] Tempoararily turn off codecov on Linux (#1513) --- .github/workflows/build_and_test.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 612cdb0e5f..291ac2db33 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -138,15 +138,15 @@ jobs: ${{ matrix.python }} -m pip install gcovr gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml - - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 - with: - files: ./coverage.xml - flags: ${{ matrix.image }},unittest - fail_ci_if_error: false - verbose: true - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # - name: Upload Coverage Results + # uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + # with: + # files: ./coverage.xml + # flags: ${{ matrix.image }},unittest + # fail_ci_if_error: false + # verbose: true + # env: + # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Save Ccache uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 From ac99bbd41b0732e11250686fb074858aae8a6a76 Mon Sep 17 00:00:00 2001 From: seladb Date: Sun, 28 Jul 2024 18:23:44 -0700 Subject: [PATCH 16/35] Temporarily turn off codecov on Linux --- .github/workflows/build_and_test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 291ac2db33..5ab2308b05 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -133,10 +133,10 @@ jobs: - name: Test Tutorials run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld - - name: Create Cobertura Report - run: | - ${{ matrix.python }} -m pip install gcovr - gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml + # - name: Create Cobertura Report + # run: | + # ${{ matrix.python }} -m pip install gcovr + # gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml # - name: Upload Coverage Results # uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 From e46bf12d179cb6e50767d3c2fa6c3ffd621801c2 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 29 Jul 2024 04:57:37 +0300 Subject: [PATCH 17/35] Fix memory leak in PointerVector pushBack (#1487) --- Common++/header/PointerVector.h | 22 ++++++++++++++++++++-- Packet++/header/Asn1Codec.h | 2 +- Packet++/src/LdapLayer.cpp | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Common++/header/PointerVector.h b/Common++/header/PointerVector.h index 96638da33f..299c190033 100644 --- a/Common++/header/PointerVector.h +++ b/Common++/header/PointerVector.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -121,19 +122,36 @@ namespace pcpp m_Vector.clear(); } + /** + * Adding a nullptr to the vector is not allowed. + */ + void pushBack(std::nullptr_t element, bool freeElementOnError = true) = delete; + /** * Add a new (pointer to an) element to the vector * @param[in] element A pointer to an element to assume ownership of. + * @param[in] freeElementOnError If set to true, the element is freed if an exception is thrown during the push. * @throws std::invalid_argument The provided pointer is a nullptr. */ - void pushBack(T* element) + void pushBack(T* element, bool freeElementOnError = true) { if (element == nullptr) { throw std::invalid_argument("Element is nullptr"); } - m_Vector.push_back(element); + try + { + m_Vector.push_back(element); + } + catch (const std::exception&) + { + if (freeElementOnError) + { + delete element; + } + throw; + } } /** diff --git a/Packet++/header/Asn1Codec.h b/Packet++/header/Asn1Codec.h index 7eeb48a526..81ef57f1c2 100644 --- a/Packet++/header/Asn1Codec.h +++ b/Packet++/header/Asn1Codec.h @@ -321,7 +321,7 @@ namespace pcpp { auto encodedRecord = (*recordIter)->encode(); auto copyRecord = Asn1Record::decode(encodedRecord.data(), encodedRecord.size(), false); - m_SubRecords.pushBack(copyRecord.release()); + m_SubRecords.pushBack(std::move(copyRecord)); recordValueLength += encodedRecord.size(); } diff --git a/Packet++/src/LdapLayer.cpp b/Packet++/src/LdapLayer.cpp index 5874c2a5e5..fd2f9bd10d 100644 --- a/Packet++/src/LdapLayer.cpp +++ b/Packet++/src/LdapLayer.cpp @@ -749,7 +749,7 @@ namespace pcpp { Asn1OctetStringRecord typeRecord(attribute.type); Asn1SetRecord valuesRecord(valuesSubRecords); - attributesSubRecords.pushBack(new Asn1SequenceRecord({&typeRecord, &valuesRecord})); + attributesSubRecords.pushBack(new Asn1SequenceRecord({ &typeRecord, &valuesRecord })); } Asn1OctetStringRecord objectNameRecord(objectName); From d21c05ccf8cd039a8faef77de02e2f7d7e1549b4 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 29 Jul 2024 05:37:15 +0300 Subject: [PATCH 18/35] Add getter to fetch all IP addresses of a live device as IPAddress objects. (#1500) --- Pcap++/header/PcapLiveDevice.h | 7 +++++++ Pcap++/src/PcapLiveDevice.cpp | 23 ++++++++++++++++++++++ Tests/Pcap++Test/Tests/LiveDeviceTests.cpp | 9 +++++++++ 3 files changed, 39 insertions(+) diff --git a/Pcap++/header/PcapLiveDevice.h b/Pcap++/header/PcapLiveDevice.h index e4b88ba2f0..868af6a3a7 100644 --- a/Pcap++/header/PcapLiveDevice.h +++ b/Pcap++/header/PcapLiveDevice.h @@ -291,9 +291,16 @@ namespace pcpp /** * @return A vector containing all addresses defined for this interface, each in pcap_addr_t struct + * @deprecated This method is deprecated and will be removed in future versions. Please use getIPAddresses() instead. */ + PCPP_DEPRECATED("This method is deprecated and will be removed in future versions. Please use getIPAddresses() instead.") const std::vector& getAddresses() const { return m_Addresses; } + /** + * @return A vector containing all IP addresses defined for this interface. + */ + std::vector getIPAddresses() const; + /** * @return The MAC address for this interface */ diff --git a/Pcap++/src/PcapLiveDevice.cpp b/Pcap++/src/PcapLiveDevice.cpp index a2e1a79c8b..aeee7bb093 100644 --- a/Pcap++/src/PcapLiveDevice.cpp +++ b/Pcap++/src/PcapLiveDevice.cpp @@ -1168,6 +1168,29 @@ void PcapLiveDevice::setDefaultGateway() #endif } +std::vector PcapLiveDevice::getIPAddresses() const +{ + std::vector results; + for (const auto& address : m_Addresses) + { + in_addr* ipv4Addr = internal::try_sockaddr2in_addr(address.addr); + if (ipv4Addr != nullptr) + { + results.push_back(IPv4Address(ipv4Addr->s_addr)); + continue; + } + + in6_addr* ipv6Addr = internal::try_sockaddr2in6_addr(address.addr); + if (ipv6Addr != nullptr) + { + results.push_back(IPv6Address(ipv6Addr->s6_addr)); + continue; + } + } + + return results; +} + IPv4Address PcapLiveDevice::getIPv4Address() const { for(const auto& addrIter : m_Addresses) diff --git a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp index 6cabae8912..b93c799899 100644 --- a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp +++ b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp @@ -11,6 +11,7 @@ #include "../Common/TestUtils.h" #include "../Common/PcapFileNamesDef.h" #include +#include #include #if defined(_WIN32) # include "PcapRemoteDevice.h" @@ -296,6 +297,14 @@ PTF_TEST_CASE(TestPcapLiveDevice) PTF_ASSERT_NOT_NULL(liveDev); PTF_ASSERT_GREATER_THAN(liveDev->getMtu(), 0); PTF_ASSERT_TRUE(liveDev->open()); + + PTF_ASSERT_EQUAL(liveDev->getIPv4Address(), ipToSearch); + { + // Should probably be refactored as PTF_ASSERT_CONTAINS or similar. + auto const ipAddresses = liveDev->getIPAddresses(); + PTF_ASSERT_TRUE(std::any_of(ipAddresses.begin(), ipAddresses.end(), [ipToSearch](pcpp::IPAddress const& addr) { return addr == ipToSearch; })); + } + DeviceTeardown devTeardown(liveDev); int packetCount = 0; int numOfTimeStatsWereInvoked = 0; From 11eb010b2d5aa8776dbfb000fc626ab1925d3f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= Date: Mon, 29 Jul 2024 15:02:37 +0200 Subject: [PATCH 19/35] cmake: add reproducible build option (#1370) * cmake: add reproductible build option * fix typo + add MSVC * fix cmake format * cmake: disable incremental build in reproducible mode * fix * cmake: fix format * fix --- CMakeLists.txt | 18 ++++++++++++++++++ Common++/header/PcapPlusPlusVersion.h | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3066d9482e..e25c6c4a67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,7 @@ cmake_dependent_option( 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) +option(PCAPPP_BUILD_REPRODUCIBLE "Build a reproducible version" OFF) option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) @@ -259,6 +260,23 @@ if(PCAPPP_TARGET_COMPILER_CLANG add_compile_options(-Wall) endif() +if(PCAPPP_BUILD_REPRODUCIBLE) + add_definitions(-DPCAPPP_BUILD_REPRODUCIBLE) + if(APPLE) + if(NOT $ENV{ZERO_AR_DATE}) + message(FATAL_ERROR "You need to set `export ZERO_AR_DATE=1`") + endif() + elseif(MSVC) + message(FATAL_ERROR "Unsupported with MSVC compiler") + # Try to build a reproducible static library with MSVC doesn't work but this option should make it work for shared + # libraries or executables. add_compile_options(/Brepro) add_compile_options(/experimental:deterministic) + # add_link_options(/Brepro) add_link_options(/experimental:deterministic) add_link_options(/INCREMENTAL:NO) + else() + # We should not use __DATE__ nor __TIME__ in case of reproducible build + add_compile_options(-Wdate-time) + endif() +endif() + if(PCAPPP_BUILD_FUZZERS) add_compile_options(-w) endif() diff --git a/Common++/header/PcapPlusPlusVersion.h b/Common++/header/PcapPlusPlusVersion.h index 22edfc4a97..0f43cea2a8 100644 --- a/Common++/header/PcapPlusPlusVersion.h +++ b/Common++/header/PcapPlusPlusVersion.h @@ -37,10 +37,17 @@ namespace pcpp /** * @return The build date and time in a format of "Mmm dd yyyy hh:mm:ss" */ +#ifdef PCAPPP_BUILD_REPRODUCIBLE + inline std::string getBuildDateTime() + { + return " "; + } +#else inline std::string getBuildDateTime() { return std::string(__DATE__) + " " + std::string(__TIME__); } +#endif /** * @return The Git commit (revision) the binaries are built from From 09f479f890b8b4e2023ca5e71d3068f9fa469c84 Mon Sep 17 00:00:00 2001 From: seladb Date: Mon, 29 Jul 2024 20:07:05 -0700 Subject: [PATCH 20/35] Run `clang-format` for Examples and Tutorials (#1464) --- .pre-commit-config.yaml | 2 +- Examples/ArpSpoofing/main.cpp | 156 +- Examples/Arping/main.cpp | 232 ++- Examples/DNSResolver/main.cpp | 216 +-- Examples/DnsSpoofing/main.cpp | 269 ++-- Examples/DpdkBridge/AppWorkerThread.h | 19 +- Examples/DpdkBridge/Common.h | 32 +- Examples/DpdkBridge/main.cpp | 264 ++-- .../AppWorkerThread.h | 31 +- Examples/DpdkExample-FilterTraffic/Common.h | 43 +- .../PacketMatchingEngine.h | 15 +- Examples/DpdkExample-FilterTraffic/main.cpp | 508 +++--- Examples/ExampleApp/main.cpp | 6 +- Examples/HttpAnalyzer/HttpStatsCollector.h | 186 ++- Examples/HttpAnalyzer/main.cpp | 343 ++-- Examples/IPDefragUtil/main.cpp | 260 +-- Examples/IPFragUtil/main.cpp | 289 ++-- Examples/IcmpFileTransfer/Common.cpp | 228 ++- Examples/IcmpFileTransfer/Common.h | 62 +- .../IcmpFileTransfer-catcher.cpp | 191 +-- .../IcmpFileTransfer-pitcher.cpp | 229 ++- Examples/KniPong/main.cpp | 1189 +++++++------- Examples/PcapPlusPlus-benchmark/benchmark.cpp | 34 +- Examples/PcapPrinter/main.cpp | 140 +- .../dirent-for-Visual-Studio/include/dirent.h | 1406 +++++++++-------- Examples/PcapSearch/main.cpp | 277 ++-- Examples/PcapSplitter/ConnectionSplitters.h | 43 +- Examples/PcapSplitter/IPPortSplitters.h | 184 ++- Examples/PcapSplitter/SimpleSplitters.h | 24 +- Examples/PcapSplitter/Splitters.h | 40 +- Examples/PcapSplitter/main.cpp | 284 ++-- Examples/PfRingExample-FilterTraffic/Common.h | 52 +- .../PacketMatchingEngine.h | 15 +- Examples/PfRingExample-FilterTraffic/main.cpp | 425 ++--- Examples/SSLAnalyzer/SSLStatsCollector.h | 140 +- Examples/SSLAnalyzer/main.cpp | 265 ++-- Examples/TLSFingerprinting/main.cpp | 320 ++-- Examples/TcpReassembly/main.cpp | 337 ++-- .../Tutorial-DpdkL2Fwd/WorkerThread.cpp | 8 +- .../Tutorial-DpdkL2Fwd/WorkerThread.h | 7 +- .../Tutorials/Tutorial-DpdkL2Fwd/main.cpp | 35 +- .../Tutorials/Tutorial-HelloWorld/main.cpp | 6 +- .../Tutorials/Tutorial-LiveTraffic/main.cpp | 63 +- .../Tutorial-PacketCraftAndEdit/main.cpp | 4 +- .../Tutorials/Tutorial-PacketParsing/main.cpp | 79 +- .../Tutorials/Tutorial-PcapFiles/main.cpp | 7 +- .../PacketMatchingEngine.h | 15 +- Examples/XdpExample-FilterTraffic/main.cpp | 337 ++-- Tests/Pcap++Test/Tests/LiveDeviceTests.cpp | 3 +- 49 files changed, 4752 insertions(+), 4568 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cdbd8c581d..722288935f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: clang-format args: ["--style=file"] # Use the .clang-format file for configuration - files: ^Common\+\+/.*\.(cpp|h)$ + files: ^(Common\+\+|Tests|Examples)/.*\.(cpp|h)$ - id: cppcheck args: ["--std=c++11", "--language=c++", "--suppressions-list=cppcheckSuppressions.txt", "--inline-suppr", "--force"] - repo: https://github.com/codespell-project/codespell diff --git a/Examples/ArpSpoofing/main.cpp b/Examples/ArpSpoofing/main.cpp index 2865cd5e73..d25e1a6eb3 100644 --- a/Examples/ArpSpoofing/main.cpp +++ b/Examples/ArpSpoofing/main.cpp @@ -14,59 +14,54 @@ #include #include - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -static struct option L3FwdOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"victim", required_argument, nullptr, 'c'}, - {"gateway", required_argument, nullptr, 'g'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +static struct option L3FwdOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "victim", required_argument, nullptr, 'c' }, + { "gateway", required_argument, nullptr, 'g' }, + { "version", no_argument, nullptr, 'v' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 } }; - /** * Print application usage */ void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hv] -i interface_ip -c victim_ip -g gateway_ip" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -i interface_ip : The IPv4 address of interface to use" << std::endl - << " -c victim_ip : The IPv4 address of the victim" << std::endl - << " -g gateway_ip : The IPv4 address of the gateway" << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-hv] -i interface_ip -c victim_ip -g gateway_ip" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -i interface_ip : The IPv4 address of interface to use" << std::endl + << " -c victim_ip : The IPv4 address of the victim" << std::endl + << " -g gateway_ip : The IPv4 address of the gateway" << std::endl + << " -h : Displays this help message and exits" << std::endl + << " -v : Displays the current version and exists" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDevice* pDevice) { // Create an ARP packet and change its fields @@ -75,18 +70,14 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe pcpp::MacAddress macSrc = pDevice->getMacAddress(); pcpp::MacAddress macDst(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); pcpp::EthLayer ethLayer(macSrc, macDst, (uint16_t)PCPP_ETHERTYPE_ARP); - pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST, - pDevice->getMacAddress(), - pDevice->getMacAddress(), - pDevice->getIPv4Address(), - ipAddr); - + pcpp::ArpLayer arpLayer(pcpp::ARP_REQUEST, pDevice->getMacAddress(), pDevice->getMacAddress(), + pDevice->getIPv4Address(), ipAddr); arpRequest.addLayer(ðLayer); arpRequest.addLayer(&arpLayer); arpRequest.computeCalculateFields(); - //setup arp reply filter + // setup arp reply filter pcpp::ArpFilter arpFilter(pcpp::ARP_REPLY); if (!pDevice->setFilter(arpFilter)) { @@ -94,7 +85,7 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe return pcpp::MacAddress::Zero; } - //send the arp request and wait for arp reply + // send the arp request and wait for arp reply pDevice->sendPacket(&arpRequest); pcpp::RawPacketVector capturedPackets; pDevice->startCapture(capturedPackets); @@ -107,7 +98,7 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe return pcpp::MacAddress::Zero; } - //parse arp reply and extract the MAC address + // parse arp reply and extract the MAC address pcpp::Packet arpReply(capturedPackets.front()); if (arpReply.isPacketOfType(pcpp::ARP)) { @@ -117,8 +108,8 @@ pcpp::MacAddress getMacAddress(const pcpp::IPv4Address& ipAddr, pcpp::PcapLiveDe return pcpp::MacAddress::Zero; } - -void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatewayAddr, const pcpp::IPv4Address& victimAddr) +void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatewayAddr, + const pcpp::IPv4Address& victimAddr) { pcpp::MacAddress gatewayMacAddr; @@ -150,11 +141,7 @@ void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatew // Create ARP reply for the gateway pcpp::Packet gwArpReply(500); pcpp::EthLayer gwEthLayer(deviceMacAddress, gatewayMacAddr, (uint16_t)PCPP_ETHERTYPE_ARP); - pcpp::ArpLayer gwArpLayer(pcpp::ARP_REPLY, - pDevice->getMacAddress(), - gatewayMacAddr, - victimAddr, - gatewayAddr); + pcpp::ArpLayer gwArpLayer(pcpp::ARP_REPLY, pDevice->getMacAddress(), gatewayMacAddr, victimAddr, gatewayAddr); gwArpReply.addLayer(&gwEthLayer); gwArpReply.addLayer(&gwArpLayer); gwArpReply.computeCalculateFields(); @@ -162,72 +149,69 @@ void doArpSpoofing(pcpp::PcapLiveDevice* pDevice, const pcpp::IPv4Address& gatew // Create ARP reply for the victim pcpp::Packet victimArpReply(500); pcpp::EthLayer victimEthLayer(deviceMacAddress, victimMacAddr, (uint16_t)PCPP_ETHERTYPE_ARP); - pcpp::ArpLayer victimArpLayer(pcpp::ARP_REPLY, - pDevice->getMacAddress(), - victimMacAddr, - gatewayAddr, - victimAddr); + pcpp::ArpLayer victimArpLayer(pcpp::ARP_REPLY, pDevice->getMacAddress(), victimMacAddr, gatewayAddr, victimAddr); victimArpReply.addLayer(&victimEthLayer); victimArpReply.addLayer(&victimArpLayer); victimArpReply.computeCalculateFields(); // Send ARP replies to gateway and to victim every 5 seconds std::cout << "Sending ARP replies to victim and to gateway every 5 seconds..." << std::endl << std::endl; - while(1) + while (1) { pDevice->sendPacket(&gwArpReply); - std::cout << "Sent ARP reply: " << gatewayAddr << " [gateway] is at MAC address " << deviceMacAddress << " [me]" << std::endl; + std::cout << "Sent ARP reply: " << gatewayAddr << " [gateway] is at MAC address " << deviceMacAddress << " [me]" + << std::endl; pDevice->sendPacket(&victimArpReply); - std::cout << "Sent ARP reply: " << victimAddr << " [victim] is at MAC address " << deviceMacAddress << " [me]" << std::endl; + std::cout << "Sent ARP reply: " << victimAddr << " [victim] is at MAC address " << deviceMacAddress << " [me]" + << std::endl; pcpp::multiPlatformSleep(5); } } - int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); - //Get arguments from user for incoming interface and outgoing interface + // Get arguments from user for incoming interface and outgoing interface std::string iface = "", victim = "", gateway = ""; int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:c:g:hv", L3FwdOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:c:g:hv", L3FwdOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - iface = optarg; - break; - case 'c': - victim = optarg; - break; - case 'g': - gateway = optarg; - break; - case 'h': - printUsage(); - exit(0); - break; - case 'v': - printAppVersion(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'i': + iface = optarg; + break; + case 'c': + victim = optarg; + break; + case 'g': + gateway = optarg; + break; + case 'h': + printUsage(); + exit(0); + break; + case 'v': + printAppVersion(); + break; + default: + printUsage(); + exit(-1); } } - //Both incoming and outgoing interfaces must be provided by user - if(iface == "" || victim == "" || gateway == "") + // Both incoming and outgoing interfaces must be provided by user + if (iface == "" || victim == "" || gateway == "") { EXIT_WITH_ERROR("Please specify both interface IP, victim IP and gateway IP"); } - //Currently supports only IPv4 addresses + // Currently supports only IPv4 addresses pcpp::IPv4Address ifaceAddr; pcpp::IPv4Address victimAddr; pcpp::IPv4Address gatewayAddr; diff --git a/Examples/Arping/main.cpp b/Examples/Arping/main.cpp index 9b252de361..919e3d42f0 100644 --- a/Examples/Arping/main.cpp +++ b/Examples/Arping/main.cpp @@ -1,8 +1,8 @@ /** * Arping example application * ================================ - * This application resolves a target MAC address by its IPv4 address by sending an ARP request and translating the ARP response. - * Its basic input is the target IP address and the interface name/IP to send the ARP request from + * This application resolves a target MAC address by its IPv4 address by sending an ARP request and translating the ARP + * response. Its basic input is the target IP address and the interface name/IP to send the ARP request from */ #include @@ -17,86 +17,86 @@ #include #include - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -#define DEFAULT_MAX_TRIES 1000000 - - -static struct option ArpingOptions[] = -{ - {"interface", optional_argument, nullptr, 'i'}, - {"source-mac", optional_argument, nullptr, 's'}, - {"source-ip", optional_argument, nullptr, 'S'}, - {"target-ip", required_argument, nullptr, 'T'}, - {"count", optional_argument, nullptr, 'c'}, - {"help", optional_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {"list", optional_argument, nullptr, 'l'}, - {"timeout", optional_argument, nullptr, 'w'}, - {nullptr, 0, nullptr, 0} +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +#define DEFAULT_MAX_TRIES 1000000 + +// clang-format off +static struct option ArpingOptions[] = { + { "interface", optional_argument, nullptr, 'i' }, + { "source-mac", optional_argument, nullptr, 's' }, + { "source-ip", optional_argument, nullptr, 'S' }, + { "target-ip", required_argument, nullptr, 'T' }, + { "count", optional_argument, nullptr, 'c' }, + { "version", no_argument, nullptr, 'v' }, + { "list", optional_argument, nullptr, 'l' }, + { "timeout", optional_argument, nullptr, 'w' }, + { "help", optional_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 } }; - +// clang-format on /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvl] [-c count] [-w timeout] [-s mac_addr] [-S ip_addr] -i interface -T ip_addr" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << " -c count : Send 'count' requests" << std::endl - << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << std::endl - << " -s mac_addr : Set source MAC address" << std::endl - << " -S ip_addr : Set source IP address" << std::endl - << " -T ip_addr : Set target IP address" << std::endl - << " -w timeout : How long to wait for a reply (in seconds)" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-hvl] [-c count] [-w timeout] [-s mac_addr] [-S ip_addr] -i interface -T ip_addr" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h : Displays this help message and exits" << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -l : Print the list of interfaces and exists" << std::endl + << " -c count : Send 'count' requests" << std::endl + << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" + << std::endl + << " -s mac_addr : Set source MAC address" << std::endl + << " -S ip_addr : Set source IP address" << std::endl + << " -T ip_addr : Set target IP address" << std::endl + << " -w timeout : How long to wait for a reply (in seconds)" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for (const auto &dev : devList) + for (const auto& dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - /** * The callback to be called when application is terminated by ctrl-c. Stops the endless while loop */ @@ -106,7 +106,6 @@ void onApplicationInterrupted(void* cookie) *shouldStop = true; } - /** * main method of the application */ @@ -125,64 +124,65 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:s:S:T:c:hvlw:", ArpingOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:s:S:T:c:hvlw:", ArpingOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - ifaceNameOrIP = optarg; - ifaceNameOrIpProvided = true; - break; - case 's': - try - { - sourceMac = pcpp::MacAddress(optarg); - } - catch (std::exception&) { - EXIT_WITH_ERROR("Source MAC address is not valid"); - } - break; - case 'S': - try - { - sourceIP = pcpp::IPv4Address(static_cast(optarg)); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR("Source IP address is not valid"); - } - break; - case 'T': - try - { - targetIP = pcpp::IPv4Address(static_cast(optarg)); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR("Target IP is not valid"); - } - targetIpProvided = true; - break; - case 'c': - maxTries = atoi(optarg); - break; - case 'h': - printUsage(); - exit(0); - case 'v': - printAppVersion(); - break; - case 'l': - listInterfaces(); - break; - case 'w': - timeoutSec = atoi(optarg); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'i': + ifaceNameOrIP = optarg; + ifaceNameOrIpProvided = true; + break; + case 's': + try + { + sourceMac = pcpp::MacAddress(optarg); + } + catch (std::exception&) + { + EXIT_WITH_ERROR("Source MAC address is not valid"); + } + break; + case 'S': + try + { + sourceIP = pcpp::IPv4Address(static_cast(optarg)); + } + catch (const std::exception&) + { + EXIT_WITH_ERROR("Source IP address is not valid"); + } + break; + case 'T': + try + { + targetIP = pcpp::IPv4Address(static_cast(optarg)); + } + catch (const std::exception&) + { + EXIT_WITH_ERROR("Target IP is not valid"); + } + targetIpProvided = true; + break; + case 'c': + maxTries = atoi(optarg); + break; + case 'h': + printUsage(); + exit(0); + case 'v': + printAppVersion(); + break; + case 'l': + listInterfaces(); + break; + case 'w': + timeoutSec = atoi(optarg); + break; + default: + printUsage(); + exit(-1); } } @@ -238,7 +238,8 @@ int main(int argc, char* argv[]) while (i <= maxTries && !shouldStop) { // use the getMacAddress utility to send an ARP request and resolve the MAC address - pcpp::MacAddress result = pcpp::NetworkUtils::getInstance().getMacAddress(targetIP, dev, arpResponseTimeMS, sourceMac, sourceIP, timeoutSec); + pcpp::MacAddress result = pcpp::NetworkUtils::getInstance().getMacAddress(targetIP, dev, arpResponseTimeMS, + sourceMac, sourceIP, timeoutSec); // failed fetching MAC address if (result == pcpp::MacAddress::Zero) @@ -246,16 +247,13 @@ int main(int argc, char* argv[]) // PcapPlusPlus logger saves the last internal error message std::cout << "Arping index=" << i << " : " << pcpp::Logger::getInstance().getLastError() << std::endl; } - else // Succeeded fetching MAC address + else // Succeeded fetching MAC address { // output ARP ping data std::cout.precision(3); - std::cout - << "Reply from " << targetIP << " " - << "[" << result << "] " - << std::fixed << arpResponseTimeMS << "ms " - << "index=" << i - << std::endl; + std::cout << "Reply from " << targetIP << " " + << "[" << result << "] " << std::fixed << arpResponseTimeMS << "ms " + << "index=" << i << std::endl; } i++; diff --git a/Examples/DNSResolver/main.cpp b/Examples/DNSResolver/main.cpp index 10ce187135..f29f1e894d 100644 --- a/Examples/DNSResolver/main.cpp +++ b/Examples/DNSResolver/main.cpp @@ -8,82 +8,86 @@ #include "Logger.h" #include - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -static struct option DNSResolverOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"hostname", required_argument, nullptr, 's'}, - {"dns-server", required_argument, nullptr, 'd'}, - {"gateway", required_argument, nullptr, 'g'}, - {"timeout", optional_argument, nullptr, 't'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {"list", no_argument, nullptr, 'l'}, - {nullptr, 0, nullptr, 0} +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +static struct option DNSResolverOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "hostname", required_argument, nullptr, 's' }, + { "dns-server", required_argument, nullptr, 'd' }, + { "gateway", required_argument, nullptr, 'g' }, + { "timeout", optional_argument, nullptr, 't' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { "list", no_argument, nullptr, 'l' }, + { nullptr, 0, nullptr, 0 } }; - /** * Print application usage */ void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvl] [-t timeout] [-d dns_server] [-g gateway] [-i interface] -s hostname" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << " -s hostname : Hostname to resolve" << std::endl - << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address. If not set" << std::endl - << " one of the interfaces that has a default gateway will be used" << std::endl - << " -d dns_server: IPv4 address of DNS server to send the DNS request to. If not set the DNS request will be sent to the gateway" << std::endl - << " -g gateway : IPv4 address of the gateway to send the DNS request to. If not set the default gateway will be chosen" << std::endl - << " -t timeout : How long to wait for a reply (in seconds). Default timeout is 5 seconds" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-hvl] [-t timeout] [-d dns_server] [-g gateway] [-i interface] -s hostname" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h : Displays this help message and exits" << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -l : Print the list of interfaces and exists" << std::endl + << " -s hostname : Hostname to resolve" << std::endl + << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " + "address. If not set" + << std::endl + << " one of the interfaces that has a default gateway will be used" << std::endl + << " -d dns_server: IPv4 address of DNS server to send the DNS request to. If not set the DNS request " + "will be sent to the gateway" + << std::endl + << " -g gateway : IPv4 address of the gateway to send the DNS request to. If not set the default " + "gateway will be chosen" + << std::endl + << " -t timeout : How long to wait for a reply (in seconds). Default timeout is 5 seconds" + << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for (const auto &dev : devList) + for (const auto& dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - /** * The callback to be called when application is terminated by ctrl-c. Stops the endless while loop */ @@ -93,7 +97,6 @@ void onApplicationInterrupted(void* cookie) device->close(); } - /** * main method of the application */ @@ -112,61 +115,61 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:d:g:s:t:hvl", DNSResolverOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:d:g:s:t:hvl", DNSResolverOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'h': - { - printUsage(); - exit(0); - } - case 'v': - { - printAppVersion(); - break; - } - case 'l': - { - listInterfaces(); - exit(0); - } - case 'i': - { - interfaceNameOrIP = optarg; - interfaceNameOrIPProvided = true; - break; - } - case 'd': - { - dnsServerIP = pcpp::IPv4Address(static_cast(optarg)); - break; - } - case 'g': - { - gatewayIP = pcpp::IPv4Address(static_cast(optarg)); - break; - } - case 's': - { - hostname = optarg; - hostnameProvided = true; - break; - } - case 't': - { - timeoutSec = atoi(optarg); - break; - } - default: - { - printUsage(); - exit(1); - } + case 0: + { + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } + case 'l': + { + listInterfaces(); + exit(0); + } + case 'i': + { + interfaceNameOrIP = optarg; + interfaceNameOrIPProvided = true; + break; + } + case 'd': + { + dnsServerIP = pcpp::IPv4Address(static_cast(optarg)); + break; + } + case 'g': + { + gatewayIP = pcpp::IPv4Address(static_cast(optarg)); + break; + } + case 's': + { + hostname = optarg; + hostnameProvided = true; + break; + } + case 't': + { + timeoutSec = atoi(optarg); + break; + } + default: + { + printUsage(); + exit(1); + } } } @@ -187,10 +190,12 @@ int main(int argc, char* argv[]) // if interface name or IP was not provided - find a device that has a default gateway else { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); - auto iter = std::find_if(devList.begin(), devList.end(), - [](pcpp::PcapLiveDevice *dev) { return dev->getDefaultGateway() != pcpp::IPv4Address::Zero; }); + auto iter = std::find_if(devList.begin(), devList.end(), [](pcpp::PcapLiveDevice* dev) { + return dev->getDefaultGateway() != pcpp::IPv4Address::Zero; + }); if (iter != devList.end()) { dev = *iter; @@ -213,14 +218,17 @@ int main(int argc, char* argv[]) // find the IPv4 address for provided hostname double responseTime = 0; uint32_t dnsTTL = 0; - pcpp::IPv4Address resultIP = pcpp::NetworkUtils::getInstance().getIPv4Address(hostname, dev, responseTime, dnsTTL, timeoutSec, dnsServerIP, gatewayIP); + pcpp::IPv4Address resultIP = pcpp::NetworkUtils::getInstance().getIPv4Address( + hostname, dev, responseTime, dnsTTL, timeoutSec, dnsServerIP, gatewayIP); if (resultIP == pcpp::IPv4Address::Zero) { std::cout << std::endl << "Could not resolve hostname [" << hostname << "]" << std::endl; } else { - std::cout << std::endl << "IP address of [" << hostname << "] is: " << resultIP << " DNS-TTL=" << dnsTTL << " time=" << (int)responseTime << "ms" << std::endl; + std::cout << std::endl + << "IP address of [" << hostname << "] is: " << resultIP << " DNS-TTL=" << dnsTTL + << " time=" << (int)responseTime << "ms" << std::endl; } } catch (const std::exception&) diff --git a/Examples/DnsSpoofing/main.cpp b/Examples/DnsSpoofing/main.cpp index d19d014b24..eda9912819 100644 --- a/Examples/DnsSpoofing/main.cpp +++ b/Examples/DnsSpoofing/main.cpp @@ -1,9 +1,9 @@ /** * DNS spoofing example application * ================================ - * This application does simple DNS spoofing. It's provided with interface name or IP and starts capturing DNS requests on that - * interface. Each DNS request that matches is edited and turned into a DNS response with a user-provided IP address as the resolved IP. - * Then it's sent back on the network on the same interface + * This application does simple DNS spoofing. It's provided with interface name or IP and starts capturing DNS requests + * on that interface. Each DNS request that matches is edited and turned into a DNS response with a user-provided IP + * address as the resolved IP. Then it's sent back on the network on the same interface */ #include @@ -13,7 +13,7 @@ #include #include #if !defined(_WIN32) -#include +# include #endif #include "IpAddress.h" #include "RawPacket.h" @@ -32,27 +32,25 @@ #include "PcapPlusPlusVersion.h" #include - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -static struct option DnsSpoofingOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"spoof-dns-server", required_argument, nullptr, 'd'}, - {"client-ip", required_argument, nullptr, 'c'}, - {"host-list", required_argument, nullptr, 'o'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {"list", no_argument, nullptr, 'l'}, - {nullptr, 0, nullptr, 0} +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +static struct option DnsSpoofingOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "spoof-dns-server", required_argument, nullptr, 'd' }, + { "client-ip", required_argument, nullptr, 'c' }, + { "host-list", required_argument, nullptr, 'o' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { "list", no_argument, nullptr, 'l' }, + { nullptr, 0, nullptr, 0 } }; - /** * A struct that holds all counters that are collected during application runtime */ @@ -61,10 +59,10 @@ struct DnsSpoofStats int numOfSpoofedDnsRequests; std::unordered_map spoofedHosts; - DnsSpoofStats() : numOfSpoofedDnsRequests(0) {} + DnsSpoofStats() : numOfSpoofedDnsRequests(0) + {} }; - /** * A struct that holds all arguments passed to handleDnsRequest() */ @@ -75,70 +73,74 @@ struct DnsSpoofingArgs DnsSpoofStats stats; bool shouldStop; - DnsSpoofingArgs() : shouldStop(false) {} + DnsSpoofingArgs() : shouldStop(false) + {} }; - /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvl] [-o host1,host2,...,host_n] [-c ip_address] -i interface -d ip_address" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of available interfaces" << std::endl - << " -i interface : The interface name or interface IP address to use." << std::endl - << " Use the -l switch to see all interfaces" << std::endl - << " -d ip_address : The IP address of the spoofed DNS server. Supports both IPv4 and IPv6" << std::endl - << " (all responses will be sent with this IP address)" << std::endl - << " -c ip_address : Spoof only DNS requests coming from a specific IP address" << std::endl - << " -o host1,host2,...,host_n : A comma-separated list of hosts to spoof. If list is not given," << std::endl - << " all hosts will be spoofed. If an host contains '*' all sub-domains" << std::endl - << " will be spoofed, for example: if '*.google.com' is given" << std::endl - << " then 'mail.google.com', 'tools.google.com', etc. will be spoofed" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-hvl] [-o host1,host2,...,host_n] [-c ip_address] -i interface -d ip_address" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h : Displays this help message and exits" << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -l : Print the list of available interfaces" << std::endl + << " -i interface : The interface name or interface IP address to use." << std::endl + << " Use the -l switch to see all interfaces" << std::endl + << " -d ip_address : The IP address of the spoofed DNS server. Supports both IPv4 and IPv6" + << std::endl + << " (all responses will be sent with this IP address)" << std::endl + << " -c ip_address : Spoof only DNS requests coming from a specific IP address" << std::endl + << " -o host1,host2,...,host_n : A comma-separated list of hosts to spoof. If list is not given," + << std::endl + << " all hosts will be spoofed. If an host contains '*' all sub-domains" + << std::endl + << " will be spoofed, for example: if '*.google.com' is given" << std::endl + << " then 'mail.google.com', 'tools.google.com', etc. will be spoofed" + << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for (const auto &dev : devList) + for (const auto& dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - /** - * The method that is called each time a DNS request is received. This methods turns the DNS request into a DNS response with the - * spoofed information and sends it back to the network + * The method that is called each time a DNS request is received. This methods turns the DNS request into a DNS response + * with the spoofed information and sends it back to the network */ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* cookie) { @@ -147,7 +149,8 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* // create a parsed packet from the raw packet pcpp::Packet dnsRequest(packet); - if (!dnsRequest.isPacketOfType(pcpp::DNS) || !dnsRequest.isPacketOfType(pcpp::IP) || !dnsRequest.isPacketOfType(pcpp::UDP) || !dnsRequest.isPacketOfType(pcpp::Ethernet)) + if (!dnsRequest.isPacketOfType(pcpp::DNS) || !dnsRequest.isPacketOfType(pcpp::IP) || + !dnsRequest.isPacketOfType(pcpp::UDP) || !dnsRequest.isPacketOfType(pcpp::Ethernet)) return; // extract all packet layers @@ -161,7 +164,7 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* return; // skip DNS requests which are not of class IN and type A (IPv4) or AAAA (IPv6) - pcpp::DnsType dnsType = (args->dnsServer.isIPv4()? pcpp::DNS_TYPE_A : pcpp::DNS_TYPE_AAAA); + pcpp::DnsType dnsType = (args->dnsServer.isIPv4() ? pcpp::DNS_TYPE_A : pcpp::DNS_TYPE_AAAA); pcpp::DnsQuery* dnsQuery = dnsLayer->getFirstQuery(); if (dnsQuery->getDnsType() != dnsType || dnsQuery->getDnsClass() != pcpp::DNS_CLASS_IN) return; @@ -172,7 +175,7 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* bool hostMatch = false; // go over all hosts in dnsHostsToSpoof list and see if current query matches one of them - for (const auto &host : args->dnsHostsToSpoof) + for (const auto& host : args->dnsHostsToSpoof) { if (dnsLayer->getQuery(host, false) != nullptr) { @@ -185,7 +188,6 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* return; } - // create a response out of the request packet // reverse src and dst MAC addresses @@ -239,7 +241,6 @@ void handleDnsRequest(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* args->stats.spoofedHosts[dnsQuery->getName()]++; } - /** * An auxiliary method for sorting the string count map. Used for printing the summary of spoofed hosts */ @@ -252,7 +253,6 @@ bool stringCountComparer(const std::pair& first, const std::pa return first.second > second.second; } - /** * A callback for application interrupted event (ctrl+c): print DNS spoofing summary */ @@ -266,12 +266,12 @@ void onApplicationInterrupted(void* cookie) else { std::cout << std::endl - << "Summary of spoofed hosts:" << std::endl - << "-------------------------" << std::endl - << std::endl - << "Total spoofed: " << args->stats.numOfSpoofedDnsRequests << std::endl - << "Number of host spoofed: " << args->stats.spoofedHosts.size() << std::endl - << std::endl; + << "Summary of spoofed hosts:" << std::endl + << "-------------------------" << std::endl + << std::endl + << "Total spoofed: " << args->stats.numOfSpoofedDnsRequests << std::endl + << "Number of host spoofed: " << args->stats.spoofedHosts.size() << std::endl + << std::endl; // create a table std::vector columnNames; @@ -284,11 +284,12 @@ void onApplicationInterrupted(void* cookie) // sort the spoofed hosts map so the most spoofed hosts will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(args->stats.spoofedHosts.begin(), args->stats.spoofedHosts.end()); - std::sort(map2vec.begin(),map2vec.end(), &stringCountComparer); + std::vector> map2vec(args->stats.spoofedHosts.begin(), + args->stats.spoofedHosts.end()); + std::sort(map2vec.begin(), map2vec.end(), &stringCountComparer); // go over all items (hosts + count) in the sorted vector and print them - for(const auto &iter : map2vec) + for (const auto& iter : map2vec) { std::stringstream values; values << iter.first << "|" << iter.second; @@ -299,11 +300,11 @@ void onApplicationInterrupted(void* cookie) args->shouldStop = true; } - /** * Activate DNS spoofing: prepare the device and start capturing DNS requests */ -void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, const pcpp::IPAddress& clientIP, const std::vector &dnsHostsToSpoof) +void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, const pcpp::IPAddress& clientIP, + const std::vector& dnsHostsToSpoof) { // open device if (!dev->open()) @@ -316,7 +317,7 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, filterForAnd.push_back(&dnsPortFilter); pcpp::IPFilter clientIpFilter(clientIP.toString(), pcpp::SRC); - if(!clientIP.isZero()) + if (!clientIP.isZero()) { filterForAnd.push_back(&clientIpFilter); } @@ -335,7 +336,6 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, if (!dev->startCapture(handleDnsRequest, &args)) EXIT_WITH_ERROR("Cannot start packet capture"); - // register the on app close event to print summary stats on app termination pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &args); @@ -347,7 +347,6 @@ void doDnsSpoofing(pcpp::PcapLiveDevice* dev, const pcpp::IPAddress& dnsServer, } } - /** * main method of the application */ @@ -367,74 +366,74 @@ int main(int argc, char* argv[]) std::vector hostList; - while((opt = getopt_long(argc, argv, "i:d:c:o:hvl", DnsSpoofingOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:d:c:o:hvl", DnsSpoofingOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'h': - { - printUsage(); - exit(0); - } - case 'v': - { - printAppVersion(); - break; - } - case 'l': + case 0: + { + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } + case 'l': + { + listInterfaces(); + exit(0); + } + case 'i': + { + interfaceNameOrIP = optarg; + break; + } + case 'd': + { + try { - listInterfaces(); - exit(0); + dnsServer = pcpp::IPAddress(static_cast(optarg)); } - case 'i': + catch (const std::exception&) { - interfaceNameOrIP = optarg; - break; + EXIT_WITH_ERROR("Spoof DNS server IP provided is empty or not a valid IP address"); } - case 'd': + break; + } + case 'c': + { + try { - try - { - dnsServer = pcpp::IPAddress(static_cast(optarg)); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR("Spoof DNS server IP provided is empty or not a valid IP address"); - } - break; + clientIP = pcpp::IPAddress(static_cast(optarg)); } - case 'c': + catch (const std::exception&) { - try - { - clientIP = pcpp::IPAddress(static_cast(optarg)); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR("Client IP to spoof is invalid"); - } - clientIpSet = true; - break; + EXIT_WITH_ERROR("Client IP to spoof is invalid"); } - case 'o': - { - std::string input = optarg; - std::istringstream stream(input); - std::string token; + clientIpSet = true; + break; + } + case 'o': + { + std::string input = optarg; + std::istringstream stream(input); + std::string token; - while(std::getline(stream, token, ',')) - hostList.push_back(token); - break; - } - default: - { - printUsage(); - exit(1); - } + while (std::getline(stream, token, ',')) + hostList.push_back(token); + break; + } + default: + { + printUsage(); + exit(1); + } } } diff --git a/Examples/DpdkBridge/AppWorkerThread.h b/Examples/DpdkBridge/AppWorkerThread.h index 1b8713fcd8..84a3a83e12 100644 --- a/Examples/DpdkBridge/AppWorkerThread.h +++ b/Examples/DpdkBridge/AppWorkerThread.h @@ -7,11 +7,10 @@ #include "DpdkDeviceList.h" #include "PcapFileDevice.h" - /** - * The worker thread class which does all the work. It's initialized with pointers to the RX and TX devices, then it runs in - * an endless loop which reads packets from the RX device and sends them to the TX device. - * The endless loop is interrupted only when the thread is asked to stop (calling its stop() method) + * The worker thread class which does all the work. It's initialized with pointers to the RX and TX devices, then it + * runs in an endless loop which reads packets from the RX device and sends them to the TX device. The endless loop is + * interrupted only when the thread is asked to stop (calling its stop() method) */ class AppWorkerThread : public pcpp::DpdkWorkerThread { @@ -21,10 +20,9 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread uint32_t m_CoreId; public: - explicit AppWorkerThread(AppWorkerConfig& workerConfig) : - m_WorkerConfig(workerConfig), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES+1) - { - } + explicit AppWorkerThread(AppWorkerConfig& workerConfig) + : m_WorkerConfig(workerConfig), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES + 1) + {} virtual ~AppWorkerThread() { @@ -46,13 +44,13 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread return true; } - #define MAX_RECEIVE_BURST 64 +#define MAX_RECEIVE_BURST 64 pcpp::MBufRawPacket* packetArr[MAX_RECEIVE_BURST] = {}; // main loop, runs until be told to stop while (!m_Stop) { - for(uint16_t i = 0; i < m_WorkerConfig.RxQueues; i++) + for (uint16_t i = 0; i < m_WorkerConfig.RxQueues; i++) { // receive packets from network on the specified DPDK device uint16_t packetsReceived = rxDevice->receivePackets(packetArr, MAX_RECEIVE_BURST, i); @@ -85,5 +83,4 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread { return m_CoreId; } - }; diff --git a/Examples/DpdkBridge/Common.h b/Examples/DpdkBridge/Common.h index 77cc4a44ea..c93016b1cf 100644 --- a/Examples/DpdkBridge/Common.h +++ b/Examples/DpdkBridge/Common.h @@ -13,23 +13,24 @@ #include #include - /** * Macros for exiting the application with error */ -#define EXIT_WITH_ERROR(reason) do { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) /** * Contains all the configuration needed for the worker thread including: @@ -43,7 +44,6 @@ struct AppWorkerConfig uint16_t RxQueues; pcpp::DpdkDevice* TxDevice; - AppWorkerConfig() : CoreId(MAX_NUM_OF_CORES+1), RxDevice(NULL), RxQueues(1), TxDevice(NULL) - { - } + AppWorkerConfig() : CoreId(MAX_NUM_OF_CORES + 1), RxDevice(NULL), RxQueues(1), TxDevice(NULL) + {} }; diff --git a/Examples/DpdkBridge/main.cpp b/Examples/DpdkBridge/main.cpp index 02dec1aada..49b76652a1 100644 --- a/Examples/DpdkBridge/main.cpp +++ b/Examples/DpdkBridge/main.cpp @@ -2,20 +2,23 @@ * DPDK bridge example application * ======================================= * This application demonstrates how to create a bridge between two network devices using PcapPlusPlus DPDK APIs. - * It listens to two DPDK ports (a.k.a DPDK devices), and forwards all the traffic received on one port to the other, acting like a L2 bridge. + * It listens to two DPDK ports (a.k.a DPDK devices), and forwards all the traffic received on one port to the other, + * acting like a L2 bridge. * - * The application is very similar to [DPDK's L2 forwarding example](https://doc.dpdk.org/guides/sample_app_ug/l2_forward_real_virtual.html) - * and demonstrates how to achieve the same functionality with PcapPlusPlus using less and easier to understand C++ code. + * The application is very similar to [DPDK's L2 forwarding + * example](https://doc.dpdk.org/guides/sample_app_ug/l2_forward_real_virtual.html) and demonstrates how to achieve the + * same functionality with PcapPlusPlus using less and easier to understand C++ code. * - * The application uses the concept of worker threads. It creates 2 worker threads running in an endless loop (as long as the app is running): - * one for receiving packets on NIC#1 and sending them to NIC#2, and another for receiving packets on NIC#2 and sending them to NIC#1. + * The application uses the concept of worker threads. It creates 2 worker threads running in an endless loop (as long + * as the app is running): one for receiving packets on NIC#1 and sending them to NIC#2, and another for receiving + * packets on NIC#2 and sending them to NIC#1. * * __Important__: * - This application runs only on Linux (DPDK is not supported on Windows and Mac OS X) * - This application (like all applications using DPDK) should be run as 'sudo' - * - In order to test this application you need an envorinment where the bridge is connected directly (back-to-back) to the two machines the - * bridge wants to connect -*/ + * - In order to test this application you need an envorinment where the bridge is connected directly (back-to-back) to + * the two machines the bridge wants to connect + */ #include "Common.h" #include "AppWorkerThread.h" @@ -38,24 +41,22 @@ #include #include - #define COLLECT_STATS_EVERY_SEC 1 #define DEFAULT_MBUF_POOL_SIZE 4095 #define DEFAULT_QUEUE_QUANTITY 1 - -static struct option DpdkBridgeOptions[] = -{ - {"dpdk-ports", required_argument, 0, 'd'}, - {"core-mask", optional_argument, 0, 'c'}, - {"mbuf-pool-size", optional_argument, 0, 'm'}, - {"queue-quantity", optional_argument, 0, 'q'}, - {"help", optional_argument, 0, 'h'}, - {"list", optional_argument, 0, 'l'}, - {"version", optional_argument, 0, 'v'}, - {0, 0, 0, 0} +// clang-format off +static struct option DpdkBridgeOptions[] = { + { "dpdk-ports", required_argument, 0, 'd' }, + { "core-mask", optional_argument, 0, 'c' }, + { "mbuf-pool-size", optional_argument, 0, 'm' }, + { "queue-quantity", optional_argument, 0, 'q' }, + { "help", optional_argument, 0, 'h' }, + { "list", optional_argument, 0, 'l' }, + { "version", optional_argument, 0, 'v' }, + { 0, 0, 0, 0 } }; - +// clang-format on /** * Print application usage @@ -63,38 +64,46 @@ static struct option DpdkBridgeOptions[] = void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hlv] [-c CORE_MASK] [-m POOL_SIZE] [-q QUEUE_QTY] -d PORT_1,PORT_2" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -l|--list : Print the list of DPDK ports and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl - << " -c|--core-mask CORE_MASK : Core mask of cores to use. For example: use 7 (binary 0111) to use cores 0,1,2." << std::endl - << " Default is using all cores except management core" << std::endl - << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with. Default value is 4095\n" << std::endl - << " -d|--dpdk-ports PORT_1,PORT_2 : A comma-separated list of two DPDK port numbers to be bridged." << std::endl - << " To see all available DPDK ports use the -l switch" << std::endl - << " -q|--queue-quantity QUEUE_QTY : Quantity of RX queues to be opened for each DPDK device. Default value is 1" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-hlv] [-c CORE_MASK] [-m POOL_SIZE] [-q QUEUE_QTY] -d PORT_1,PORT_2" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h|--help : Displays this help message and exits" << std::endl + << " -l|--list : Print the list of DPDK ports and exits" << std::endl + << " -v|--version : Displays the current version and exits" << std::endl + << " -c|--core-mask CORE_MASK : Core mask of cores to use. For example: use 7 " + "(binary 0111) to use cores 0,1,2." + << std::endl + << " Default is using all cores except management core" + << std::endl + << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with. " + "Default value is 4095\n" + << std::endl + << " -d|--dpdk-ports PORT_1,PORT_2 : A comma-separated list of two DPDK port numbers to " + "be bridged." + << std::endl + << " To see all available DPDK ports use the -l switch" + << std::endl + << " -q|--queue-quantity QUEUE_QTY : Quantity of RX queues to be opened for each DPDK " + "device. Default value is 1" + << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Print to console all available DPDK ports. Used by the -l switch */ @@ -112,28 +121,26 @@ void listDpdkPorts() // go over all available DPDK devices and print info for each one std::vector deviceList = pcpp::DpdkDeviceList::getInstance().getDpdkDeviceList(); - for (const auto &iter : deviceList) + for (const auto& iter : deviceList) { pcpp::DpdkDevice* dev = iter; std::cout << " " - << " Port #" << dev->getDeviceId() << ":" - << " MAC address='" << dev->getMacAddress() << "';" - << " PCI address='" << dev->getPciAddress() << "';" - << " PMD='" << dev->getPMDName() << "'" - << std::endl; + << " Port #" << dev->getDeviceId() << ":" + << " MAC address='" << dev->getMacAddress() << "';" + << " PCI address='" << dev->getPciAddress() << "';" + << " PMD='" << dev->getPMDName() << "'" << std::endl; } } - struct DpdkBridgeArgs { bool shouldStop; std::vector* workerThreadsVector; - DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(NULL) {} + DpdkBridgeArgs() : shouldStop(false), workerThreadsVector(NULL) + {} }; - /** * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats */ @@ -141,10 +148,7 @@ void onApplicationInterrupted(void* cookie) { DpdkBridgeArgs* args = (DpdkBridgeArgs*)cookie; - std::cout - << std::endl << std::endl - << "Application stopped" - << std::endl; + std::cout << std::endl << std::endl << "Application stopped" << std::endl; // stop worker threads pcpp::DpdkDeviceList::getInstance().stopDpdkWorkerThreads(); @@ -152,7 +156,6 @@ void onApplicationInterrupted(void* cookie) args->shouldStop = true; } - /** * Extract and print traffic stats from a device */ @@ -161,7 +164,7 @@ void printStats(pcpp::DpdkDevice* device) pcpp::DpdkDevice::DpdkDeviceStats stats; device->getStatistics(stats); - std::cout << std::endl <<"Statistics for port " << device->getDeviceId() << ":" << std::endl; + std::cout << std::endl << "Statistics for port " << device->getDeviceId() << ":" << std::endl; std::vector columnNames; columnNames.push_back(" "); @@ -180,18 +183,22 @@ void printStats(pcpp::DpdkDevice* device) pcpp::TablePrinter printer(columnNames, columnLengths); std::stringstream totalRx; - totalRx << "rx" << "|" << stats.aggregatedRxStats.packets << "|" << stats.aggregatedRxStats.packetsPerSec << "|" << stats.aggregatedRxStats.bytes << "|" << stats.aggregatedRxStats.bytesPerSec; + totalRx << "rx" + << "|" << stats.aggregatedRxStats.packets << "|" << stats.aggregatedRxStats.packetsPerSec << "|" + << stats.aggregatedRxStats.bytes << "|" << stats.aggregatedRxStats.bytesPerSec; printer.printRow(totalRx.str(), '|'); std::stringstream totalTx; - totalTx << "tx" << "|" << stats.aggregatedTxStats.packets << "|" << stats.aggregatedTxStats.packetsPerSec << "|" << stats.aggregatedTxStats.bytes << "|" << stats.aggregatedTxStats.bytesPerSec; + totalTx << "tx" + << "|" << stats.aggregatedTxStats.packets << "|" << stats.aggregatedTxStats.packetsPerSec << "|" + << stats.aggregatedTxStats.bytes << "|" << stats.aggregatedTxStats.bytesPerSec; printer.printRow(totalTx.str(), '|'); } - /** - * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them. - * At program termination worker threads are stopped, statistics are collected from them and printed to console + * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating + * the worker threads and activate them. At program termination worker threads are stopped, statistics are collected + * from them and printed to console */ int main(int argc, char* argv[]) { @@ -208,75 +215,75 @@ int main(int argc, char* argv[]) uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE; uint16_t queueQuantity = DEFAULT_QUEUE_QUANTITY; - while((opt = getopt_long(argc, argv, "d:c:m:q:hvl", DpdkBridgeOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "d:c:m:q:hvl", DpdkBridgeOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'c': - { - coreMaskToUse = atoi(optarg); - break; - } - case 'd': + case 0: + { + break; + } + case 'c': + { + coreMaskToUse = atoi(optarg); + break; + } + case 'd': + { + std::string portListAsString = std::string(optarg); + std::stringstream stream(portListAsString); + std::string portAsString; + int port; + // break comma-separated string into string list + while (getline(stream, portAsString, ',')) { - std::string portListAsString = std::string(optarg); - std::stringstream stream(portListAsString); - std::string portAsString; - int port; - // break comma-separated string into string list - while(getline(stream, portAsString, ',')) + char c; + std::stringstream stream2(portAsString); + stream2 >> port; + if (stream2.fail() || stream2.get(c)) { - char c; - std::stringstream stream2(portAsString); - stream2 >> port; - if (stream2.fail() || stream2.get(c)) - { - // not an integer - EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); - } - dpdkPortVec.push_back(port); + // not an integer + EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); } - // verify list contains two ports - if(dpdkPortVec.size()!=2) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK list must contain two values"); - } - break; + dpdkPortVec.push_back(port); } - case 'm': + // verify list contains two ports + if (dpdkPortVec.size() != 2) { - mBufPoolSize = atoi(optarg); - break; - } - case 'q': - { - queueQuantity = atoi(optarg); - break; - } - case 'h': - { - printUsage(); - exit(0); - } - case 'l': - { - listDpdkPorts(); - exit(0); - } - case 'v': - { - printAppVersion(); - break; - } - default: - { - printUsage(); - exit(0); + EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK list must contain two values"); } + break; + } + case 'm': + { + mBufPoolSize = atoi(optarg); + break; + } + case 'q': + { + queueQuantity = atoi(optarg); + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'l': + { + listDpdkPorts(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } + default: + { + printUsage(); + exit(0); + } } } @@ -311,7 +318,7 @@ int main(int argc, char* argv[]) // collect the list of DPDK devices std::vector dpdkDevicesToUse; - for (const auto &port : dpdkPortVec) + for (const auto& port : dpdkPortVec) { pcpp::DpdkDevice* dev = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(port); if (dev == NULL) @@ -322,11 +329,12 @@ int main(int argc, char* argv[]) } // go over all devices and open them - for (const auto &dev : dpdkDevicesToUse) + for (const auto& dev : dpdkDevicesToUse) { if (!dev->openMultiQueues(queueQuantity, 1)) { - EXIT_WITH_ERROR("Couldn't open DPDK device #" << dev->getDeviceId() << ", PMD '" << dev->getPMDName() << "'"); + EXIT_WITH_ERROR("Couldn't open DPDK device #" << dev->getDeviceId() << ", PMD '" << dev->getPMDName() + << "'"); } } @@ -375,9 +383,7 @@ int main(int argc, char* argv[]) std::cout << "\033[2J\033[1;1H"; // Print devices traffic stats - std::cout - << "Stats #" << statsCounter++ << std::endl - << "==========" << std::endl; + std::cout << "Stats #" << statsCounter++ << std::endl << "==========" << std::endl; printStats(dpdkDevicesToUse.at(0)); printStats(dpdkDevicesToUse.at(1)); } diff --git a/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h b/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h index ec9056df18..ff7317c40e 100644 --- a/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h +++ b/Examples/DpdkExample-FilterTraffic/AppWorkerThread.h @@ -9,9 +9,10 @@ #include "PcapFileDevice.h" /** - * The worker thread class which does all the work: receive packets from relevant DPDK port(s), matched them with the packet matching engine and send them to - * TX port and/or save them to a file. In addition it collects packets statistics. - * Each core is assigned with one such worker thread, and all of them are activated using DpdkDeviceList::startDpdkWorkerThreads (see main.cpp) + * The worker thread class which does all the work: receive packets from relevant DPDK port(s), matched them with the + * packet matching engine and send them to TX port and/or save them to a file. In addition it collects packets + * statistics. Each core is assigned with one such worker thread, and all of them are activated using + * DpdkDeviceList::startDpdkWorkerThreads (see main.cpp) */ class AppWorkerThread : public pcpp::DpdkWorkerThread { @@ -24,11 +25,10 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread std::unordered_map m_FlowTable; public: - AppWorkerThread(AppWorkerConfig& workerConfig, PacketMatchingEngine& matchingEngine) : - m_WorkerConfig(workerConfig), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES+1), - m_PacketMatchingEngine(matchingEngine) - { - } + AppWorkerThread(AppWorkerConfig& workerConfig, PacketMatchingEngine& matchingEngine) + : m_WorkerConfig(workerConfig), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES + 1), + m_PacketMatchingEngine(matchingEngine) + {} virtual ~AppWorkerThread() { @@ -66,7 +66,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread return true; } - #define MAX_RECEIVE_BURST 64 +#define MAX_RECEIVE_BURST 64 pcpp::MBufRawPacket* packetArr[MAX_RECEIVE_BURST] = {}; // main loop, runs until be told to stop @@ -74,10 +74,10 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread while (!m_Stop) { // go over all DPDK devices configured for this worker/core - for (const auto &iter : m_WorkerConfig.inDataCfg) + for (const auto& iter : m_WorkerConfig.inDataCfg) { // for each DPDK device go over all RX queues configured for this worker/core - for (const auto &iter2 : iter.second) + for (const auto& iter2 : iter.second) { pcpp::DpdkDevice* dev = iter.first; @@ -94,7 +94,8 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread bool packetMatched; - // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or new flow + // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to + // an existing or new flow uint32_t hash = pcpp::hash5Tuple(&parsedPacket); auto iter3 = m_FlowTable.find(hash); @@ -103,7 +104,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread { packetMatched = true; } - else // packet belongs to a new flow + else // packet belongs to a new flow { packetMatched = m_PacketMatchingEngine.isMatched(parsedPacket); if (packetMatched) @@ -111,7 +112,7 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread // put new flow in flow table m_FlowTable[hash] = true; - //collect stats + // collect stats if (parsedPacket.isPacketOfType(pcpp::TCP)) { m_Stats.matchedTcpFlows++; @@ -120,7 +121,6 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread { m_Stats.matchedUdpFlows++; } - } } @@ -171,5 +171,4 @@ class AppWorkerThread : public pcpp::DpdkWorkerThread { return m_CoreId; } - }; diff --git a/Examples/DpdkExample-FilterTraffic/Common.h b/Examples/DpdkExample-FilterTraffic/Common.h index 15c7d6c1aa..7f032de0c6 100644 --- a/Examples/DpdkExample-FilterTraffic/Common.h +++ b/Examples/DpdkExample-FilterTraffic/Common.h @@ -13,25 +13,26 @@ #include #include - /** * Macros for exiting the application with error */ -#define EXIT_WITH_ERROR(reason) do { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) -#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - -typedef std::unordered_map > InputDataConfig; +#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) +typedef std::unordered_map> InputDataConfig; /** * Contains all the configuration needed for the worker thread including: @@ -46,11 +47,11 @@ struct AppWorkerConfig bool writeMatchedPacketsToFile; std::string pathToWritePackets; - AppWorkerConfig() : coreId(MAX_NUM_OF_CORES+1), sendPacketsTo(nullptr), - writeMatchedPacketsToFile(false), pathToWritePackets("") {} + AppWorkerConfig() + : coreId(MAX_NUM_OF_CORES + 1), sendPacketsTo(nullptr), writeMatchedPacketsToFile(false), pathToWritePackets("") + {} }; - /** * Collect and analyze packet and flow statistics */ @@ -74,9 +75,11 @@ struct PacketStats int matchedUdpFlows; int matchedPackets; - PacketStats() : workerId(MAX_NUM_OF_CORES+1), packetCount(0), ethCount(0), arpCount(0), ipv4Count(0), ipv6Count(0), - tcpCount(0), udpCount(0), httpCount(0), dnsCount(0), tlsCount(0), - matchedTcpFlows(0), matchedUdpFlows(0), matchedPackets(0) {} + PacketStats() + : workerId(MAX_NUM_OF_CORES + 1), packetCount(0), ethCount(0), arpCount(0), ipv4Count(0), ipv6Count(0), + tcpCount(0), udpCount(0), httpCount(0), dnsCount(0), tlsCount(0), matchedTcpFlows(0), matchedUdpFlows(0), + matchedPackets(0) + {} void collectStats(pcpp::Packet& packet) { @@ -121,7 +124,7 @@ struct PacketStats void clear() { - workerId = MAX_NUM_OF_CORES+1; + workerId = MAX_NUM_OF_CORES + 1; packetCount = 0; ethCount = 0; arpCount = 0; diff --git a/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h b/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h index ef249f114a..e5354898ed 100644 --- a/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h +++ b/Examples/DpdkExample-FilterTraffic/PacketMatchingEngine.h @@ -7,8 +7,9 @@ #include "SystemUtils.h" /** - * Responsible for matching packets by match criteria received from the user. Current match criteria are a combination of zero or more of the - * following parameters: source IP, dest IP, source TCP/UDP port, dest TCP/UDP port and TCP/UDP protocol. + * Responsible for matching packets by match criteria received from the user. Current match criteria are a combination + * of zero or more of the following parameters: source IP, dest IP, source TCP/UDP port, dest TCP/UDP port and TCP/UDP + * protocol. */ class PacketMatchingEngine { @@ -19,11 +20,13 @@ class PacketMatchingEngine bool m_MatchSrcIp, m_MatchDstIp; bool m_MatchSrcPort, m_MatchDstPort; bool m_MatchProtocol; + public: - PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) - : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), - m_SrcPortToMatch(srcPortToMatch), m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), - m_MatchSrcIp(false), m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) + PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, + uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) + : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), m_SrcPortToMatch(srcPortToMatch), + m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), m_MatchSrcIp(false), + m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) { if (m_SrcIpToMatch != pcpp::IPv4Address::Zero) m_MatchSrcIp = true; diff --git a/Examples/DpdkExample-FilterTraffic/main.cpp b/Examples/DpdkExample-FilterTraffic/main.cpp index 2674856a0a..3d6839c006 100644 --- a/Examples/DpdkExample-FilterTraffic/main.cpp +++ b/Examples/DpdkExample-FilterTraffic/main.cpp @@ -2,18 +2,20 @@ * Filter Traffic DPDK example application * ======================================= * An application that listens to one or more DPDK ports (a.k.a DPDK devices), captures all traffic - * and matches packets by user-defined matching criteria. Matching criteria is given on startup and can contain one or more of the following: - * source IP, destination IP, source TCP/UDP port, destination TCP/UDP port and TCP or UDP protocol. Matching is done per flow, meaning the first packet - * received on a flow is matched against the matching criteria and if it's matched then all packets of the same flow will be matched too. - * Packets that are matched can be send to a DPDK port and/or be save to a pcap file. - * In addition the application collect statistics on received and matched packets: number of packets per protocol, number of matched flows and number - * of matched packets. + * and matches packets by user-defined matching criteria. Matching criteria is given on startup and can contain one or + * more of the following: source IP, destination IP, source TCP/UDP port, destination TCP/UDP port and TCP or UDP + * protocol. Matching is done per flow, meaning the first packet received on a flow is matched against the matching + * criteria and if it's matched then all packets of the same flow will be matched too. Packets that are matched can be + * send to a DPDK port and/or be save to a pcap file. In addition the application collect statistics on received and + * matched packets: number of packets per protocol, number of matched flows and number of matched packets. * - * The application uses the concept of worker threads. Number of cores can be set by the user or set to default (default is all machine cores minus one - * management core). Each core is assigned with one worker thread. The application divides the DPDK ports and RX queues equally between worker threads. - * For example: if there are 2 DPDK ports to listen to, each one with 6 RX queues and there are 3 worker threads, then worker #1 will get RX queues - * 1-4 of port 1, worker #2 will get RX queues 5-6 of port 1 and RX queues 1-2 of port 2, and worker #3 will get RX queues 3-6 of port 2. - * Each worker thread does exactly the same work: receiving packets, collecting packet statistics, matching flows and sending/saving matched packets + * The application uses the concept of worker threads. Number of cores can be set by the user or set to default (default + * is all machine cores minus one management core). Each core is assigned with one worker thread. The application + * divides the DPDK ports and RX queues equally between worker threads. For example: if there are 2 DPDK ports to listen + * to, each one with 6 RX queues and there are 3 worker threads, then worker #1 will get RX queues 1-4 of port 1, worker + * #2 will get RX queues 5-6 of port 1 and RX queues 1-2 of port 2, and worker #3 will get RX queues 3-6 of port 2. Each + * worker thread does exactly the same work: receiving packets, collecting packet statistics, matching flows and + * sending/saving matched packets * * __Important__: this application (like all applications using DPDK) should be run as 'sudo' */ @@ -37,84 +39,96 @@ #include #include - #define DEFAULT_MBUF_POOL_SIZE 4095 #define MAX_QUEUES 64 - -static struct option FilterTrafficOptions[] = -{ - {"dpdk-ports", required_argument, 0, 'd'}, - {"send-matched-packets", optional_argument, 0, 's'}, - {"save-matched-packets", optional_argument, 0, 'f'}, - {"match-source-ip", optional_argument, 0, 'i'}, - {"match-dest-ip", optional_argument, 0, 'I'}, - {"match-source-port", optional_argument, 0, 'p'}, - {"match-dest-port", optional_argument, 0, 'P'}, - {"match-protocol", optional_argument, 0, 'o'}, - {"core-mask", optional_argument, 0, 'c'}, - {"mbuf-pool-size", optional_argument, 0, 'm'}, - {"rx-queues", optional_argument, 0, 'r'}, - {"tx-queues", optional_argument, 0, 't'}, - {"help", optional_argument, 0, 'h'}, - {"version", optional_argument, 0, 'v'}, - {"list", optional_argument, 0, 'l'}, - {0, 0, 0, 0} +// clang-format off +static struct option FilterTrafficOptions[] = { + { "dpdk-ports", required_argument, 0, 'd' }, + { "send-matched-packets", optional_argument, 0, 's' }, + { "save-matched-packets", optional_argument, 0, 'f' }, + { "match-source-ip", optional_argument, 0, 'i' }, + { "match-dest-ip", optional_argument, 0, 'I' }, + { "match-source-port", optional_argument, 0, 'p' }, + { "match-dest-port", optional_argument, 0, 'P' }, + { "match-protocol", optional_argument, 0, 'o' }, + { "core-mask", optional_argument, 0, 'c' }, + { "mbuf-pool-size", optional_argument, 0, 'm' }, + { "rx-queues", optional_argument, 0, 'r' }, + { "tx-queues", optional_argument, 0, 't' }, + { "help", optional_argument, 0, 'h' }, + { "version", optional_argument, 0, 'v' }, + { "list", optional_argument, 0, 'l' }, + { 0, 0, 0, 0 } }; - +// clang-format on /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvl] [-s PORT] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" << std::endl - << " [-c CORE_MASK] [-m POOL_SIZE] [-r NUM_QUEUES] [-t NUM_QUEUES] -d PORT_1,PORT_3,...,PORT_N" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl - << " -l|--list : Print the list of DPDK ports and exists" << std::endl - << " -d|--dpdk-ports PORT_1,PORT_3,...,PORT_N : A comma-separated list of DPDK port numbers to receive" << std::endl - << " packets from. To see all available DPDK ports use the -l switch" << std::endl - << " -s|--send-matched-packets PORT : DPDK port to send matched packets to" << std::endl - << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH. Packets" << std::endl - << " matched by core X will be saved under 'FILEPATH/CoreX.pcap'" << std::endl - << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl - << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl - << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl - << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl - << " -o|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" << std::endl - << " -c|--core-mask CORE_MASK : Core mask of cores to use." << std::endl - << " For example: use 7 (binary 0111) to use cores 0,1,2." << std::endl - << " Default is using all cores except management core" << std::endl - << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with." << std::endl - << " Default value is 4095" << std::endl - << " -r|--rx-queues NUM_QUEUES : Number of RX queues to open. Cannot exceed the max allowed by the NIC or " << MAX_QUEUES << std::endl - << " The default is 1" << std::endl - << " -t|--tx-queues NUM_QUEUES : Number of TX queues to open. Cannot exceed the max allowed by the NIC or " << MAX_QUEUES << std::endl - << " The default is 1" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() + << " [-hvl] [-s PORT] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" + << std::endl + << " [-c CORE_MASK] [-m POOL_SIZE] [-r NUM_QUEUES] [-t NUM_QUEUES] -d PORT_1,PORT_3,...,PORT_N" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h|--help : Displays this help message and exits" << std::endl + << " -v|--version : Displays the current version and exits" << std::endl + << " -l|--list : Print the list of DPDK ports and exists" << std::endl + << " -d|--dpdk-ports PORT_1,PORT_3,...,PORT_N : A comma-separated list of DPDK port numbers to receive" + << std::endl + << " packets from. To see all available DPDK ports use the -l " + "switch" + << std::endl + << " -s|--send-matched-packets PORT : DPDK port to send matched packets to" << std::endl + << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH. Packets" + << std::endl + << " matched by core X will be saved under " + "'FILEPATH/CoreX.pcap'" + << std::endl + << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl + << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl + << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl + << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl + << " -o|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" + << std::endl + << " -c|--core-mask CORE_MASK : Core mask of cores to use." << std::endl + << " For example: use 7 (binary 0111) to use cores 0,1,2." + << std::endl + << " Default is using all cores except management core" + << std::endl + << " -m|--mbuf-pool-size POOL_SIZE : DPDK mBuf pool size to initialize DPDK with." << std::endl + << " Default value is 4095" << std::endl + << " -r|--rx-queues NUM_QUEUES : Number of RX queues to open. Cannot exceed the max " + "allowed by the NIC or " + << MAX_QUEUES << std::endl + << " The default is 1" << std::endl + << " -t|--tx-queues NUM_QUEUES : Number of TX queues to open. Cannot exceed the max " + "allowed by the NIC or " + << MAX_QUEUES << std::endl + << " The default is 1" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Print to console all available DPDK ports. Used by the -l switch */ @@ -132,30 +146,29 @@ void listDpdkPorts() // go over all available DPDK devices and print info for each one std::vector deviceList = pcpp::DpdkDeviceList::getInstance().getDpdkDeviceList(); - for (const auto &dev : deviceList) + for (const auto& dev : deviceList) { std::cout << " " - << " Port #" << dev->getDeviceId() << ":" - << " MAC address='" << dev->getMacAddress() << "';" - << " PCI address='" << dev->getPciAddress() << "';" - << " PMD='" << dev->getPMDName() << "'" - << std::endl; + << " Port #" << dev->getDeviceId() << ":" + << " MAC address='" << dev->getMacAddress() << "';" + << " PCI address='" << dev->getPciAddress() << "';" + << " PMD='" << dev->getPMDName() << "'" << std::endl; } } - /** - * Prepare the configuration for each core. Configuration includes: which DpdkDevices and which RX queues to receive packets from, where to send the matched - * packets, etc. + * Prepare the configuration for each core. Configuration includes: which DpdkDevices and which RX queues to receive + * packets from, where to send the matched packets, etc. */ -void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, std::vector& coresToUse, - bool writePacketsToDisk, const std::string &packetFilePath, pcpp::DpdkDevice* sendPacketsTo, - AppWorkerConfig workerConfigArr[], int workerConfigArrLen, uint16_t rxQueues) +void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, + std::vector& coresToUse, bool writePacketsToDisk, + const std::string& packetFilePath, pcpp::DpdkDevice* sendPacketsTo, + AppWorkerConfig 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; - std::vector > deviceAndRxQVec; - for (const auto &iter : dpdkDevicesToUse) + std::vector> deviceAndRxQVec; + for (const auto& iter : dpdkDevicesToUse) { for (int rxQueueIndex = 0; rxQueueIndex < rxQueues; rxQueueIndex++) { @@ -165,14 +178,15 @@ void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, totalNumOfRxQueues += rxQueues; } - // calculate how many RX queues each core will read packets from. We divide the total number of RX queues with total number of core + // calculate how many RX queues each core will read packets from. We divide the total number of RX queues with total + // number of core int numOfRxQueuesPerCore = totalNumOfRxQueues / coresToUse.size(); int rxQueuesRemainder = totalNumOfRxQueues % coresToUse.size(); // prepare the configuration for every core: divide the devices and RX queue for each device with the various cores int i = 0; - std::vector >::iterator pairVecIter = deviceAndRxQVec.begin(); - for (const auto &core : coresToUse) + std::vector>::iterator pairVecIter = deviceAndRxQVec.begin(); + for (const auto& core : coresToUse) { std::cout << "Using core " << (int)core.Id << std::endl; workerConfigArr[i].coreId = core.Id; @@ -199,10 +213,10 @@ void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, // print configuration for core std::cout << " Core configuration:" << std::endl; - for (const auto &iter2 : workerConfigArr[i].inDataCfg) + for (const auto& iter2 : workerConfigArr[i].inDataCfg) { std::cout << " DPDK device#" << iter2.first->getDeviceId() << ": "; - for (const auto &iter3 : iter2.second) + for (const auto& iter3 : iter2.second) { std::cout << "RX-Queue#" << iter3 << "; "; } @@ -216,23 +230,22 @@ void prepareCoreConfiguration(std::vector& dpdkDevicesToUse, } } - struct FilterTrafficArgs { bool shouldStop; std::vector* workerThreadsVector; - FilterTrafficArgs() : shouldStop(false), workerThreadsVector(NULL) {} + FilterTrafficArgs() : shouldStop(false), workerThreadsVector(NULL) + {} }; - /** * Print thread stats in a table */ void printStats(const PacketStats& threadStats, const std::string& columnName) { - std::vector columnNames = {columnName, "Count"}; - std::vector columnsWidths = {21, 10}; + std::vector columnNames = { columnName, "Count" }; + std::vector columnsWidths = { 21, 10 }; pcpp::TablePrinter printer(columnNames, columnsWidths); printer.printRow("Eth count|" + std::to_string(threadStats.ethCount), '|'); @@ -252,7 +265,6 @@ void printStats(const PacketStats& threadStats, const std::string& columnName) printer.printRow("Total packet count|" + std::to_string(threadStats.packetCount), '|'); } - /** * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats */ @@ -268,7 +280,7 @@ void onApplicationInterrupted(void* cookie) // print final stats for every worker thread plus sum of all threads and free worker threads memory PacketStats aggregatedStats; std::vector threadStatsVec; - for (const auto &iter : *(args->workerThreadsVector)) + for (const auto& iter : *(args->workerThreadsVector)) { AppWorkerThread* thread = (AppWorkerThread*)(iter); PacketStats threadStats = thread->getStats(); @@ -300,10 +312,10 @@ void onApplicationInterrupted(void* cookie) args->shouldStop = true; } - /** - * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating the worker threads and activate them. - * At program termination worker threads are stopped, statistics are collected from them and printed to console + * main method of the application. Responsible for parsing user args, preparing worker thread configuration, creating + * the worker threads and activate them. At program termination worker threads are stopped, statistics are collected + * from them and printed to console */ int main(int argc, char* argv[]) { @@ -324,178 +336,178 @@ int main(int argc, char* argv[]) uint32_t mBufPoolSize = DEFAULT_MBUF_POOL_SIZE; - pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; - pcpp::IPv4Address dstIPToMatch = pcpp::IPv4Address::Zero; - uint16_t srcPortToMatch = 0; - uint16_t dstPortToMatch = 0; - pcpp::ProtocolType protocolToMatch = pcpp::UnknownProtocol; + pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; + pcpp::IPv4Address dstIPToMatch = pcpp::IPv4Address::Zero; + uint16_t srcPortToMatch = 0; + uint16_t dstPortToMatch = 0; + pcpp::ProtocolType protocolToMatch = pcpp::UnknownProtocol; uint16_t rxQueues = 1; uint16_t txQueues = 1; - while((opt = getopt_long(argc, argv, "d:c:s:f:m:i:I:p:P:o:r:t:hvl", FilterTrafficOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "d:c:s:f:m:i:I:p:P:o:r:t:hvl", FilterTrafficOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'd': + case 0: + { + break; + } + case 'd': + { + std::string portListAsString = std::string(optarg); + std::stringstream stream(portListAsString); + std::string portAsString; + int port; + // break comma-separated string into string list + while (getline(stream, portAsString, ',')) { - std::string portListAsString = std::string(optarg); - std::stringstream stream(portListAsString); - std::string portAsString; - int port; - // break comma-separated string into string list - while(getline(stream, portAsString, ',')) - { - char c; - std::stringstream stream2(portAsString); - stream2 >> port; - if (stream2.fail() || stream2.get(c)) - { - // not an integer - EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); - } - dpdkPortVec.push_back(port); - } - - // verify list is not empty - if (dpdkPortVec.empty()) + char c; + std::stringstream stream2(portAsString); + stream2 >> port; + if (stream2.fail() || stream2.get(c)) { - EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty"); + // not an integer + EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is invalid"); } - break; - } - case 's': - { - sendPacketsToPort = atoi(optarg); - break; + dpdkPortVec.push_back(port); } - case 'c': + + // verify list is not empty + if (dpdkPortVec.empty()) { - coreMaskToUse = atoi(optarg); - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("DPDK ports list is empty"); } - case 'f': + break; + } + case 's': + { + sendPacketsToPort = atoi(optarg); + break; + } + case 'c': + { + coreMaskToUse = atoi(optarg); + break; + } + case 'f': + { + packetFilePath = std::string(optarg); + writePacketsToDisk = true; + if (packetFilePath.empty()) { - packetFilePath = std::string(optarg); - writePacketsToDisk = true; - if (packetFilePath.empty()) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Filename to write packets is empty"); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Filename to write packets is empty"); } - case 'm': + break; + } + case 'm': + { + mBufPoolSize = atoi(optarg); + break; + } + case 'i': + { + try { - mBufPoolSize = atoi(optarg); - break; + srcIPToMatch = pcpp::IPv4Address(optarg); } - case 'i': + catch (const std::exception&) { - try - { - srcIPToMatch = pcpp::IPv4Address(optarg); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); } - case 'I': - { - try - { - dstIPToMatch = pcpp::IPv4Address(optarg); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); - } - break; - } - case 'p': + break; + } + case 'I': + { + try { - int ret = atoi(optarg); - if (ret <= 0 || ret > 65535) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); - } - srcPortToMatch = ret; - break; + dstIPToMatch = pcpp::IPv4Address(optarg); } - case 'P': + catch (const std::exception&) { - int ret = atoi(optarg); - if (ret <= 0 || ret > 65535) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); - } - dstPortToMatch = ret; - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); } - case 'o': + break; + } + case 'p': + { + int ret = atoi(optarg); + if (ret <= 0 || ret > 65535) { - std::string protocol = std::string(optarg); - if (protocol == "TCP") - protocolToMatch = pcpp::TCP; - else if (protocol == "UDP") - protocolToMatch = pcpp::UDP; - else - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); } - case 'r': + srcPortToMatch = ret; + break; + } + case 'P': + { + int ret = atoi(optarg); + if (ret <= 0 || ret > 65535) { - rxQueues = atoi(optarg); - if (rxQueues == 0) - { - EXIT_WITH_ERROR("Cannot open the device with 0 RX queues"); - } - if (rxQueues > MAX_QUEUES) - { - EXIT_WITH_ERROR("The number of RX queues cannot exceed " << MAX_QUEUES); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); } - case 't': + dstPortToMatch = ret; + break; + } + case 'o': + { + std::string protocol = std::string(optarg); + if (protocol == "TCP") + protocolToMatch = pcpp::TCP; + else if (protocol == "UDP") + protocolToMatch = pcpp::UDP; + else { - txQueues = atoi(optarg); - if (txQueues == 0) - { - EXIT_WITH_ERROR("Cannot open the device with 0 TX queues"); - } - if (txQueues > MAX_QUEUES) - { - EXIT_WITH_ERROR("The number of TX queues cannot exceed " << MAX_QUEUES); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); } - case 'h': + break; + } + case 'r': + { + rxQueues = atoi(optarg); + if (rxQueues == 0) { - printUsage(); - exit(0); + EXIT_WITH_ERROR("Cannot open the device with 0 RX queues"); } - case 'v': + if (rxQueues > MAX_QUEUES) { - printAppVersion(); - break; + EXIT_WITH_ERROR("The number of RX queues cannot exceed " << MAX_QUEUES); } - case 'l': + break; + } + case 't': + { + txQueues = atoi(optarg); + if (txQueues == 0) { - listDpdkPorts(); - exit(0); + EXIT_WITH_ERROR("Cannot open the device with 0 TX queues"); } - default: + if (txQueues > MAX_QUEUES) { - printUsage(); - exit(0); + EXIT_WITH_ERROR("The number of TX queues cannot exceed " << MAX_QUEUES); } + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } + case 'l': + { + listDpdkPorts(); + exit(0); + } + default: + { + printUsage(); + exit(0); + } } } @@ -530,7 +542,7 @@ int main(int argc, char* argv[]) // collect the list of DPDK devices std::vector dpdkDevicesToUse; - for (const auto &port : dpdkPortVec) + for (const auto& port : dpdkPortVec) { pcpp::DpdkDevice* dev = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(port); if (dev == NULL) @@ -541,26 +553,29 @@ int main(int argc, char* argv[]) } // go over all devices and open them - for (const auto &dev : dpdkDevicesToUse) + for (const auto& dev : dpdkDevicesToUse) { if (rxQueues > dev->getTotalNumOfRxQueues()) { - EXIT_WITH_ERROR("Number of RX errors cannot exceed the max allowed by the device which is " << dev->getTotalNumOfRxQueues()); + EXIT_WITH_ERROR("Number of RX errors cannot exceed the max allowed by the device which is " + << dev->getTotalNumOfRxQueues()); } if (txQueues > dev->getTotalNumOfTxQueues()) { - EXIT_WITH_ERROR("Number of TX errors cannot exceed the max allowed by the device which is " << dev->getTotalNumOfTxQueues()); + EXIT_WITH_ERROR("Number of TX errors cannot exceed the max allowed by the device which is " + << dev->getTotalNumOfTxQueues()); } if (!dev->openMultiQueues(rxQueues, txQueues)) { - EXIT_WITH_ERROR("Couldn't open DPDK device #" << dev->getDeviceId() << ", PMD '" << dev->getPMDName() << "'"); + EXIT_WITH_ERROR("Couldn't open DPDK device #" << dev->getDeviceId() << ", PMD '" << dev->getPMDName() + << "'"); } - std::cout - << "Opened device #" << dev->getDeviceId() - << " with " << rxQueues << " RX queues and " << txQueues << " TX queues." - << " RSS hash functions:" << std::endl; - std::vector rssHashFunctions = dev->rssHashFunctionMaskToString(dev->getConfiguredRssHashFunction()); - for(const auto &hashFunc : rssHashFunctions) + std::cout << "Opened device #" << dev->getDeviceId() << " with " << rxQueues << " RX queues and " << txQueues + << " TX queues." + << " RSS hash functions:" << std::endl; + std::vector rssHashFunctions = + dev->rssHashFunctionMaskToString(dev->getConfiguredRssHashFunction()); + for (const auto& hashFunc : rssHashFunctions) { std::cout << " " << hashFunc << std::endl; } @@ -568,14 +583,15 @@ int main(int argc, char* argv[]) // get DPDK device to send packets to (or NULL if doesn't exist) pcpp::DpdkDevice* sendPacketsTo = pcpp::DpdkDeviceList::getInstance().getDeviceByPort(sendPacketsToPort); - if (sendPacketsTo != NULL && !sendPacketsTo->isOpened() && !sendPacketsTo->open()) + if (sendPacketsTo != NULL && !sendPacketsTo->isOpened() && !sendPacketsTo->open()) { EXIT_WITH_ERROR("Could not open port#" << sendPacketsToPort << " for sending matched packets"); } // prepare configuration for every core AppWorkerConfig workerConfigArr[coresToUse.size()]; - prepareCoreConfiguration(dpdkDevicesToUse, coresToUse, writePacketsToDisk, packetFilePath, sendPacketsTo, workerConfigArr, coresToUse.size(), rxQueues); + prepareCoreConfiguration(dpdkDevicesToUse, coresToUse, writePacketsToDisk, packetFilePath, sendPacketsTo, + workerConfigArr, coresToUse.size(), rxQueues); PacketMatchingEngine matchingEngine(srcIPToMatch, dstIPToMatch, srcPortToMatch, dstPortToMatch, protocolToMatch); diff --git a/Examples/ExampleApp/main.cpp b/Examples/ExampleApp/main.cpp index fcad0e09fb..89f3bdf6d2 100644 --- a/Examples/ExampleApp/main.cpp +++ b/Examples/ExampleApp/main.cpp @@ -32,10 +32,8 @@ int main(int argc, char* argv[]) pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); // print source and dest IPs - std::cout - << "Source IP is '" << srcIP << "'; " - << "Dest IP is '" << destIP << "'" - << std::endl; + std::cout << "Source IP is '" << srcIP << "'; " + << "Dest IP is '" << destIP << "'" << std::endl; } // close the file diff --git a/Examples/HttpAnalyzer/HttpStatsCollector.h b/Examples/HttpAnalyzer/HttpStatsCollector.h index cf45af7629..445fa166cf 100644 --- a/Examples/HttpAnalyzer/HttpStatsCollector.h +++ b/Examples/HttpAnalyzer/HttpStatsCollector.h @@ -16,8 +16,8 @@ */ struct Rate { - double currentRate; // periodic rate - double totalRate; // overlal rate + double currentRate; // periodic rate + double totalRate; // overlal rate void clear() { @@ -31,19 +31,32 @@ struct Rate */ struct HttpGeneralStats { - int numOfHttpFlows; // total number of HTTP flows - Rate httpFlowRate; // rate of HTTP flows - int numOfHttpPipeliningFlows; // total number of HTTP flows that contains at least on HTTP pipelining transaction - int numOfHttpTransactions; // total number of HTTP transactions - Rate httpTransactionsRate; // rate of HTTP transactions - double averageNumOfHttpTransactionsPerFlow; // average number of HTTP transactions per flow - int numOfHttpPackets; // total number of HTTP packets - Rate httpPacketRate; // rate of HTTP packets - double averageNumOfPacketsPerFlow; // average number of HTTP packets per flow - int amountOfHttpTraffic; // total HTTP traffic in bytes - double averageAmountOfDataPerFlow; // average number of HTTP traffic per flow - Rate httpTrafficRate; // rate of HTTP traffic - double sampleTime; // total stats collection time + // total number of HTTP flows + int numOfHttpFlows; + // rate of HTTP flows + Rate httpFlowRate; + // total number of HTTP flows that contains at least on HTTP pipelining transaction + int numOfHttpPipeliningFlows; + // total number of HTTP transactions + int numOfHttpTransactions; + // rate of HTTP transactions + Rate httpTransactionsRate; + // average number of HTTP transactions per flow + double averageNumOfHttpTransactionsPerFlow; + // total number of HTTP packets + int numOfHttpPackets; + // rate of HTTP packets + Rate httpPacketRate; + // average number of HTTP packets per flow + double averageNumOfPacketsPerFlow; + // total HTTP traffic in bytes + int amountOfHttpTraffic; + // average number of HTTP traffic per flow + double averageAmountOfDataPerFlow; + // rate of HTTP traffic + Rate httpTrafficRate; + // total stats collection time + double sampleTime; void clear() { @@ -63,18 +76,22 @@ struct HttpGeneralStats } }; - /** * A base struct for collecting stats on HTTP messages */ struct HttpMessageStats { - int numOfMessages; // total number of HTTP messages of that type (request/response) - Rate messageRate; // rate of HTTP messages of that type - int totalMessageHeaderSize; // total size (in bytes) of data in headers - double averageMessageHeaderSize; // average header size - - virtual ~HttpMessageStats() {} + // total number of HTTP messages of that type (request/response) + int numOfMessages; + // rate of HTTP messages of that type + Rate messageRate; + // total size (in bytes) of data in headers + int totalMessageHeaderSize; + // average header size + double averageMessageHeaderSize; + + virtual ~HttpMessageStats() + {} virtual void clear() { @@ -85,14 +102,15 @@ struct HttpMessageStats } }; - /** * A struct for collecting stats on all HTTP requests */ struct HttpRequestStats : HttpMessageStats { - std::unordered_map > methodCount; // a map for counting the different HTTP methods seen in traffic - std::unordered_map hostnameCount; // a map for counting the hostnames seen in traffic + // a map for counting the different HTTP methods seen in traffic + std::unordered_map> methodCount; + // a map for counting the hostnames seen in traffic + std::unordered_map hostnameCount; void clear() override { @@ -102,17 +120,21 @@ struct HttpRequestStats : HttpMessageStats } }; - /** * A struct for collecting stats on all HTTP responses */ struct HttpResponseStats : HttpMessageStats { - std::unordered_map statusCodeCount; // a map for counting the different status codes seen in traffic - std::unordered_map contentTypeCount; // a map for counting the content-types seen in traffic - int numOfMessagesWithContentLength; // total number of responses containing the "content-length" field - int totalContentLengthSize; // total body size extracted by responses containing "content-length" field - double averageContentLengthSize; // average body size + // a map for counting the different status codes seen in traffic + std::unordered_map statusCodeCount; + // a map for counting the content-types seen in traffic + std::unordered_map contentTypeCount; + // total number of responses containing the "content-length" field + int numOfMessagesWithContentLength; + // total body size extracted by responses containing "content-length" field + int totalContentLengthSize; + // average body size + double averageContentLengthSize; void clear() override { @@ -125,14 +147,12 @@ struct HttpResponseStats : HttpMessageStats } }; - /** * The HTTP stats collector. Should be called for every packet arriving and also periodically to calculate rates */ class HttpStatsCollector { public: - /** * C'tor - clear all structures */ @@ -191,23 +211,29 @@ class HttpStatsCollector // getting time from last rate calculation until now double diffSec = curTime - m_LastCalcRateTime; - // calculating current rates which are the changes from last rate calculation until now divided by the time passed from - // last rate calculation until now + // calculating current rates which are the changes from last rate calculation until now divided by the time + // passed from last rate calculation until now if (diffSec != 0) { - m_GeneralStats.httpTrafficRate.currentRate = (m_GeneralStats.amountOfHttpTraffic - m_PrevGeneralStats.amountOfHttpTraffic) / diffSec; - m_GeneralStats.httpPacketRate.currentRate = (m_GeneralStats.numOfHttpPackets - m_PrevGeneralStats.numOfHttpPackets) / diffSec; - m_GeneralStats.httpFlowRate.currentRate = (m_GeneralStats.numOfHttpFlows - m_PrevGeneralStats.numOfHttpFlows) / diffSec; - m_GeneralStats.httpTransactionsRate.currentRate = (m_GeneralStats.numOfHttpTransactions - m_PrevGeneralStats.numOfHttpTransactions) / diffSec; - m_RequestStats.messageRate.currentRate = (m_RequestStats.numOfMessages - m_PrevRequestStats.numOfMessages) / diffSec; - m_ResponseStats.messageRate.currentRate = (m_ResponseStats.numOfMessages - m_PrevResponseStats.numOfMessages) / diffSec; + m_GeneralStats.httpTrafficRate.currentRate = + (m_GeneralStats.amountOfHttpTraffic - m_PrevGeneralStats.amountOfHttpTraffic) / diffSec; + m_GeneralStats.httpPacketRate.currentRate = + (m_GeneralStats.numOfHttpPackets - m_PrevGeneralStats.numOfHttpPackets) / diffSec; + m_GeneralStats.httpFlowRate.currentRate = + (m_GeneralStats.numOfHttpFlows - m_PrevGeneralStats.numOfHttpFlows) / diffSec; + m_GeneralStats.httpTransactionsRate.currentRate = + (m_GeneralStats.numOfHttpTransactions - m_PrevGeneralStats.numOfHttpTransactions) / diffSec; + m_RequestStats.messageRate.currentRate = + (m_RequestStats.numOfMessages - m_PrevRequestStats.numOfMessages) / diffSec; + m_ResponseStats.messageRate.currentRate = + (m_ResponseStats.numOfMessages - m_PrevResponseStats.numOfMessages) / diffSec; } // getting the time from the beginning of stats collection until now double diffSecTotal = curTime - m_StartTime; - // calculating total rate which is the change from beginning of stats collection until now divided by time passed from - // beginning of stats collection until now + // calculating total rate which is the change from beginning of stats collection until now divided by time + // passed from beginning of stats collection until now if (diffSecTotal != 0) { m_GeneralStats.httpTrafficRate.totalRate = m_GeneralStats.amountOfHttpTraffic / diffSecTotal; @@ -245,30 +271,44 @@ class HttpStatsCollector /** * Get HTTP general stats */ - HttpGeneralStats& getGeneralStats() { return m_GeneralStats; } + HttpGeneralStats& getGeneralStats() + { + return m_GeneralStats; + } /** * Get HTTP request stats */ - HttpRequestStats& getRequestStats() { return m_RequestStats; } + HttpRequestStats& getRequestStats() + { + return m_RequestStats; + } /** * Get HTTP response stats */ - HttpResponseStats& getResponseStats() { return m_ResponseStats; } + HttpResponseStats& getResponseStats() + { + return m_ResponseStats; + } private: - /** * Auxiliary data collected for each flow for help calculating stats on this flow */ struct HttpFlowData { - int numOfOpenTransactions; // number of transactions that were started (request has arrived) but weren't closed yet (response hasn't arrived yet) - pcpp::ProtocolType lastSeenMessage; // the last HTTP message seen on this flow (request, response or neither). Used to identify HTTP pipelining - bool httpPipeliningFlow; // was HTTP pipelining identified on this flow - uint32_t curSeqNumberRequests; // the current TCP sequence number from client to server. Used to identify TCP re-transmission - uint32_t curSeqNumberResponses; // the current TCP sequence number from server to client. Used to identify TCP re-transmission + // number of transactions that were started (request has arrived) but weren't closed yet (response hasn't + // arrived yet) + int numOfOpenTransactions; + // the last HTTP message seen on this flow (request, response or neither). Used to identify HTTP pipelining + pcpp::ProtocolType lastSeenMessage; + // was HTTP pipelining identified on this flow + bool httpPipeliningFlow; + // the current TCP sequence number from client to server. Used to identify TCP re-transmission + uint32_t curSeqNumberRequests; + // the current TCP sequence number from server to client. Used to identify TCP re-transmission + uint32_t curSeqNumberResponses; void clear() { @@ -278,7 +318,6 @@ class HttpStatsCollector } }; - /** * Collect stats relevant for every HTTP packet (request, response or any other) * This method calculates and returns the flow key for this packet @@ -307,14 +346,15 @@ class HttpStatsCollector // calculate averages if (m_FlowTable.size() != 0) { - m_GeneralStats.averageAmountOfDataPerFlow = (double)m_GeneralStats.amountOfHttpTraffic / (double)m_FlowTable.size(); - m_GeneralStats.averageNumOfPacketsPerFlow = (double)m_GeneralStats.numOfHttpPackets / (double)m_FlowTable.size(); + m_GeneralStats.averageAmountOfDataPerFlow = + (double)m_GeneralStats.amountOfHttpTraffic / (double)m_FlowTable.size(); + m_GeneralStats.averageNumOfPacketsPerFlow = + (double)m_GeneralStats.numOfHttpPackets / (double)m_FlowTable.size(); } return hashVal; } - /** * Collect stats relevant for HTTP messages (requests or responses) */ @@ -328,14 +368,15 @@ class HttpStatsCollector { // if new packet seq number is smaller than previous seen seq number current it means this packet is // a re-transmitted packet and should be ignored - if (m_FlowTable[flowKey].curSeqNumberRequests >= pcpp::netToHost32(tcpLayer->getTcpHeader()->sequenceNumber)) + if (m_FlowTable[flowKey].curSeqNumberRequests >= + pcpp::netToHost32(tcpLayer->getTcpHeader()->sequenceNumber)) return; // a new request - increase num of open transactions m_FlowTable[flowKey].numOfOpenTransactions++; - // if the previous message seen on this flow is HTTP request and if flow is not already marked as HTTP pipelining - - // mark it as so and increase number of HTTP pipelining flows + // if the previous message seen on this flow is HTTP request and if flow is not already marked as HTTP + // pipelining - mark it as so and increase number of HTTP pipelining flows if (!m_FlowTable[flowKey].httpPipeliningFlow && m_FlowTable[flowKey].lastSeenMessage == pcpp::HTTPRequest) { m_FlowTable[flowKey].httpPipeliningFlow = true; @@ -352,14 +393,15 @@ class HttpStatsCollector { // if new packet seq number is smaller than previous seen seq number current it means this packet is // a re-transmitted packet and should be ignored - if (m_FlowTable[flowKey].curSeqNumberResponses >= pcpp::netToHost32(tcpLayer->getTcpHeader()->sequenceNumber)) + if (m_FlowTable[flowKey].curSeqNumberResponses >= + pcpp::netToHost32(tcpLayer->getTcpHeader()->sequenceNumber)) return; // a response - decrease num of open transactions m_FlowTable[flowKey].numOfOpenTransactions--; - // if the previous message seen on this flow is HTTP response and if flow is not already marked as HTTP pipelining - - // mark it as so and increase number of HTTP pipelining flows + // if the previous message seen on this flow is HTTP response and if flow is not already marked as HTTP + // pipelining - mark it as so and increase number of HTTP pipelining flows if (!m_FlowTable[flowKey].httpPipeliningFlow && m_FlowTable[flowKey].lastSeenMessage == pcpp::HTTPResponse) { m_FlowTable[flowKey].httpPipeliningFlow = true; @@ -376,7 +418,8 @@ class HttpStatsCollector // calc average transactions per flow if (m_FlowTable.size() != 0) - m_GeneralStats.averageNumOfHttpTransactionsPerFlow = (double)m_GeneralStats.numOfHttpTransactions / (double)m_FlowTable.size(); + m_GeneralStats.averageNumOfHttpTransactionsPerFlow = + (double)m_GeneralStats.numOfHttpTransactions / (double)m_FlowTable.size(); } // set last seen sequence number @@ -384,7 +427,6 @@ class HttpStatsCollector } } - /** * Collect stats relevant for HTTP request messages */ @@ -393,7 +435,8 @@ class HttpStatsCollector m_RequestStats.numOfMessages++; m_RequestStats.totalMessageHeaderSize += req->getHeaderLen(); if (m_RequestStats.numOfMessages != 0) - m_RequestStats.averageMessageHeaderSize = (double)m_RequestStats.totalMessageHeaderSize / (double)m_RequestStats.numOfMessages; + m_RequestStats.averageMessageHeaderSize = + (double)m_RequestStats.totalMessageHeaderSize / (double)m_RequestStats.numOfMessages; // extract hostname and add to hostname count map pcpp::HeaderField* hostField = req->getFieldByName(PCPP_HTTP_HOST_FIELD); @@ -403,7 +446,6 @@ class HttpStatsCollector m_RequestStats.methodCount[req->getFirstLine()->getMethod()]++; } - /** * Collect stats relevant for HTTP response messages */ @@ -412,7 +454,8 @@ class HttpStatsCollector m_ResponseStats.numOfMessages++; m_ResponseStats.totalMessageHeaderSize += res->getHeaderLen(); if (m_ResponseStats.numOfMessages != 0) - m_ResponseStats.averageMessageHeaderSize = (double)m_ResponseStats.totalMessageHeaderSize / (double)m_ResponseStats.numOfMessages; + m_ResponseStats.averageMessageHeaderSize = + (double)m_ResponseStats.totalMessageHeaderSize / (double)m_ResponseStats.numOfMessages; // extract content-length (if exists) pcpp::HeaderField* contentLengthField = res->getFieldByName(PCPP_HTTP_CONTENT_LENGTH_FIELD); @@ -421,7 +464,8 @@ class HttpStatsCollector m_ResponseStats.numOfMessagesWithContentLength++; m_ResponseStats.totalContentLengthSize += atoi(contentLengthField->getFieldValue().c_str()); if (m_ResponseStats.numOfMessagesWithContentLength != 0) - m_ResponseStats.averageContentLengthSize = (double)m_ResponseStats.totalContentLengthSize / (double)m_ResponseStats.numOfMessagesWithContentLength; + m_ResponseStats.averageContentLengthSize = (double)m_ResponseStats.totalContentLengthSize / + (double)m_ResponseStats.numOfMessagesWithContentLength; } // extract content-type and add to content-type map @@ -449,11 +493,11 @@ class HttpStatsCollector double getCurTime(void) { - struct timeval tv; + struct timeval tv; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); - return (((double) tv.tv_sec) + (double) (tv.tv_usec / 1000000.0)); + return (((double)tv.tv_sec) + (double)(tv.tv_usec / 1000000.0)); } HttpGeneralStats m_GeneralStats; diff --git a/Examples/HttpAnalyzer/main.cpp b/Examples/HttpAnalyzer/main.cpp index 35a7bffaf8..b1f6803177 100644 --- a/Examples/HttpAnalyzer/main.cpp +++ b/Examples/HttpAnalyzer/main.cpp @@ -1,13 +1,14 @@ /** * HttpAnalyzer application * ======================== - * This application analyzes HTTP traffic and presents detailed and diverse information about it. It can operate in live traffic - * mode where this information is collected on live packets or in file mode where packets are being read from a pcap/pcapng file. The - * information collected by this application includes: + * This application analyzes HTTP traffic and presents detailed and diverse information about it. It can operate in live + * traffic mode where this information is collected on live packets or in file mode where packets are being read from a + * pcap/pcapng file. The information collected by this application includes: * - general data: number of packets, packet rate, amount of traffic, bandwidth * - flow data: number of flow, flow rate, average packets per flow, average data per flow * - HTTP data: number and rate of HTTP requests, number and rate of HTTP responses, transaction count and rate, - * average transactions per flow, HTTP header size (total and average), HTTP body size, number of HTTP pipelining flows + * average transactions per flow, HTTP header size (total and average), HTTP body size, number of HTTP pipelining + * flows * - hostname map * - HTTP method map * - HTTP status code map @@ -31,37 +32,35 @@ #include #include -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -#define PRINT_STAT_LINE(description, counter, measurement) \ - std::cout \ - << std::left << std::setw(40) << (std::string(description) + ":") \ - << std::right << std::setw(15) << std::fixed << std::showpoint << std::setprecision(3) << counter \ - << " [" << measurement << "]" << std::endl; +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) +#define PRINT_STAT_LINE(description, counter, measurement) \ + std::cout << std::left << std::setw(40) << (std::string(description) + ":") << std::right << std::setw(15) \ + << std::fixed << std::showpoint << std::setprecision(3) << counter << " [" << measurement << "]" \ + << std::endl; #define DEFAULT_CALC_RATES_PERIOD_SEC 2 - -static struct option HttpAnalyzerOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"dst-port", required_argument, nullptr, 'p'}, - {"input-file", required_argument, nullptr, 'f'}, - {"output-file", required_argument, nullptr, 'o'}, - {"rate-calc-period", required_argument, nullptr, 'r'}, - {"disable-rates-print", no_argument, nullptr, 'd'}, - {"list-interfaces", no_argument, nullptr, 'l'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +// clang-format off +static struct option HttpAnalyzerOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "dst-port", required_argument, nullptr, 'p' }, + { "input-file", required_argument, nullptr, 'f' }, + { "output-file", required_argument, nullptr, 'o' }, + { "rate-calc-period", required_argument, nullptr, 'r' }, + { "disable-rates-print", no_argument, nullptr, 'd' }, + { "list-interfaces", no_argument, nullptr, 'l' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { nullptr, 0, nullptr, 0 } }; - +// clang-format on struct HttpPacketArrivedData { @@ -69,75 +68,82 @@ struct HttpPacketArrivedData pcpp::PcapFileWriterDevice* pcapWriter; }; - /** * Print application usage */ void printUsage() { std::cout << std::endl - << "Usage: PCAP file mode:" << std::endl - << "----------------------" << std::endl - << pcpp::AppName::get() << " [-vh] -f input_file" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl - << "Usage: Live traffic mode:" << std::endl - << "-------------------------" << std::endl - << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] [-p dst_port] -i interface" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << std::endl - << " -p dst_port : Use the specified port (optional parameter, the default is 80)" << std::endl - << " -o output_file : Save all captured HTTP packets to a pcap file. Notice this may cause performance degradation" << std::endl - << " -r calc_period : The period in seconds to calculate rates. If not provided default is 2 seconds" << std::endl - << " -d : Disable periodic rates calculation" << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << std::endl; + << "Usage: PCAP file mode:" << std::endl + << "----------------------" << std::endl + << pcpp::AppName::get() << " [-vh] -f input_file" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" + << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -h : Displays this help message and exits" << std::endl + << std::endl + << "Usage: Live traffic mode:" << std::endl + << "-------------------------" << std::endl + << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] [-p dst_port] -i interface" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " + "address" + << std::endl + << " -p dst_port : Use the specified port (optional parameter, the default is 80)" << std::endl + << " -o output_file : Save all captured HTTP packets to a pcap file. Notice this may cause " + "performance degradation" + << std::endl + << " -r calc_period : The period in seconds to calculate rates. If not provided default is 2 seconds" + << std::endl + << " -d : Disable periodic rates calculation" << std::endl + << " -h : Displays this help message and exits" << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -l : Print the list of interfaces and exists" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& liveDevices = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& liveDevices = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for(const auto& device : liveDevices){ - std::cout << " -> Name: '" << device->getName() << "' IP address: " << device->getIPv4Address().toString() << std::endl; + for (const auto& device : liveDevices) + { + std::cout << " -> Name: '" << device->getName() << "' IP address: " << device->getIPv4Address().toString() + << std::endl; } exit(0); } - -void printStatsHeadline(const std::string &description) +void printStatsHeadline(const std::string& description) { - std::cout << std::endl << description << std::endl << std::string(description.length(),'-') << std::endl << std::endl; + std::cout << std::endl + << description << std::endl + << std::string(description.length(), '-') << std::endl + << std::endl; } - /** * packet capture callback - called whenever a packet arrives */ @@ -146,7 +152,7 @@ void httpPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* // parse the packet pcpp::Packet parsedPacket(packet); - HttpPacketArrivedData* data = (HttpPacketArrivedData*)cookie; + HttpPacketArrivedData* data = (HttpPacketArrivedData*)cookie; // give the packet to the collector data->statsCollector->collectStats(&parsedPacket); @@ -164,15 +170,17 @@ void httpPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* void printMethods(const HttpRequestStats& reqStatscollector) { // create the table - std::vector columnNames = {"Method", "Count"}; - std::vector columnsWidths = {9, 5}; + std::vector columnNames = { "Method", "Count" }; + std::vector columnsWidths = { 9, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // Copy elements to a vector - std::vector> map2vec(reqStatscollector.methodCount.begin(), reqStatscollector.methodCount.end()); - std::sort(map2vec.begin(), map2vec.end(), - [](const std::pair& left, - const std::pair& right) { return left.second > right.second; }); + std::vector> map2vec(reqStatscollector.methodCount.begin(), + reqStatscollector.methodCount.end()); + std::sort( + map2vec.begin(), map2vec.end(), + [](const std::pair& left, + const std::pair& right) { return left.second > right.second; }); // go over the method count table, print each method and the aggregated figure for (auto iter : map2vec) @@ -182,37 +190,46 @@ void printMethods(const HttpRequestStats& reqStatscollector) switch (iter.first) { case pcpp::HttpRequestLayer::HttpGET: - values << "GET" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpGET); + values << "GET" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpGET); break; case pcpp::HttpRequestLayer::HttpPOST: - values << "POST" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpPOST); + values << "POST" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpPOST); break; case pcpp::HttpRequestLayer::HttpCONNECT: - values << "CONNECT" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpCONNECT); + values << "CONNECT" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpCONNECT); break; case pcpp::HttpRequestLayer::HttpDELETE: - values << "DELETE" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpDELETE); + values << "DELETE" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpDELETE); break; case pcpp::HttpRequestLayer::HttpHEAD: - values << "HEAD" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpHEAD); + values << "HEAD" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpHEAD); break; case pcpp::HttpRequestLayer::HttpOPTIONS: - values << "OPTIONS" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpOPTIONS); + values << "OPTIONS" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpOPTIONS); break; case pcpp::HttpRequestLayer::HttpPATCH: - values << "PATCH" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpPATCH); + values << "PATCH" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpPATCH); break; case pcpp::HttpRequestLayer::HttpPUT: - values << "PUT" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpPUT); + values << "PUT" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpPUT); break; case pcpp::HttpRequestLayer::HttpTRACE: - values << "TRACE" << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpTRACE); + values << "TRACE" + << "|" << reqStatscollector.methodCount.at(pcpp::HttpRequestLayer::HttpTRACE); break; default: break; } - if(iter.first != pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown) + if (iter.first != pcpp::HttpRequestLayer::HttpMethod::HttpMethodUnknown) { printer.printRow(values.str(), '|'); } @@ -224,7 +241,8 @@ void printMethods(const HttpRequestStats& reqStatscollector) */ bool hostnameComparer(const std::pair& leftHost, const std::pair& rightHost) { - return leftHost.second > rightHost.second || (leftHost.second == rightHost.second && leftHost.first > rightHost.first); + return leftHost.second > rightHost.second || + (leftHost.second == rightHost.second && leftHost.first > rightHost.first); } /** @@ -233,18 +251,19 @@ bool hostnameComparer(const std::pair& leftHost, const std::pa void printHostnames(HttpRequestStats& reqStatscollector) { // create the table - std::vector columnNames = {"Hostname", "Count"}; - std::vector columnsWidths = {40, 5}; + std::vector columnNames = { "Hostname", "Count" }; + std::vector columnsWidths = { 40, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // sort the hostname count map so the most popular hostnames will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(reqStatscollector.hostnameCount.begin(), reqStatscollector.hostnameCount.end()); + std::vector> map2vec(reqStatscollector.hostnameCount.begin(), + reqStatscollector.hostnameCount.end()); std::sort(map2vec.begin(), map2vec.end(), &hostnameComparer); // go over all items (hostname + count) in the sorted vector and print them - for(const auto& hostname : map2vec) + for (const auto& hostname : map2vec) { std::stringstream values; values << hostname.first << "|" << hostname.second; @@ -252,21 +271,24 @@ void printHostnames(HttpRequestStats& reqStatscollector) } } - /** * Print the status code count table */ void printStatusCodes(const HttpResponseStats& resStatscollector) { // create the table - std::vector columnNames = {"Status Code", "Count"}; - std::vector columnsWidths = {28, 5}; + std::vector columnNames = { "Status Code", "Count" }; + std::vector columnsWidths = { 28, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // prints the status codes in lexical order - std::vector> map2vec(resStatscollector.statusCodeCount.begin(), resStatscollector.statusCodeCount.end()); - std::sort(map2vec.begin(), map2vec.end(), [](const std::pair& left, const std::pair& right) { return left.first < right.first; }); - for(const auto& statusCodeStat : map2vec) + std::vector> map2vec(resStatscollector.statusCodeCount.begin(), + resStatscollector.statusCodeCount.end()); + std::sort(map2vec.begin(), map2vec.end(), + [](const std::pair& left, const std::pair& right) { + return left.first < right.first; + }); + for (const auto& statusCodeStat : map2vec) { std::stringstream values; values << statusCodeStat.first << "|" << statusCodeStat.second; @@ -274,21 +296,24 @@ void printStatusCodes(const HttpResponseStats& resStatscollector) } } - /** * Print the content-type count table */ void printContentTypes(const HttpResponseStats& resStatscollector) { // create the table - std::vector columnNames = {"Content-type", "Count"}; - std::vector columnsWidths = {30, 5}; + std::vector columnNames = { "Content-type", "Count" }; + std::vector columnsWidths = { 30, 5 }; pcpp::TablePrinter printer(columnNames, columnsWidths); // prints the content-types in lexical order - std::vector> map2vec(resStatscollector.contentTypeCount.begin(), resStatscollector.contentTypeCount.end()); - std::sort(map2vec.begin(), map2vec.end(), [](const std::pair& left, const std::pair& right) { return left.first < right.first; }); - for(const auto &contentTypeStat : map2vec) + std::vector> map2vec(resStatscollector.contentTypeCount.begin(), + resStatscollector.contentTypeCount.end()); + std::sort(map2vec.begin(), map2vec.end(), + [](const std::pair& left, const std::pair& right) { + return left.first < right.first; + }); + for (const auto& contentTypeStat : map2vec) { std::stringstream values; values << contentTypeStat.first << "|" << contentTypeStat.second; @@ -296,9 +321,9 @@ void printContentTypes(const HttpResponseStats& resStatscollector) } } - /** - * Print a summary of all statistics collected by the HttpStatsCollector. Should be called when traffic capture was finished + * Print a summary of all statistics collected by the HttpStatsCollector. Should be called when traffic capture was + * finished */ void printStatsSummary(HttpStatsCollector& collector) { @@ -310,11 +335,13 @@ void printStatsSummary(HttpStatsCollector& collector) PRINT_STAT_LINE("Rate of HTTP flows", collector.getGeneralStats().httpFlowRate.totalRate, "Flows/sec"); PRINT_STAT_LINE("Number of HTTP pipelining flows", collector.getGeneralStats().numOfHttpPipeliningFlows, "Flows"); PRINT_STAT_LINE("Number of HTTP transactions", collector.getGeneralStats().numOfHttpTransactions, "Transactions"); - PRINT_STAT_LINE("Rate of HTTP transactions", collector.getGeneralStats().httpTransactionsRate.totalRate, "Transactions/sec"); + PRINT_STAT_LINE("Rate of HTTP transactions", collector.getGeneralStats().httpTransactionsRate.totalRate, + "Transactions/sec"); PRINT_STAT_LINE("Total HTTP data", collector.getGeneralStats().amountOfHttpTraffic, "Bytes"); PRINT_STAT_LINE("Rate of HTTP data", collector.getGeneralStats().httpTrafficRate.totalRate, "Bytes/sec"); PRINT_STAT_LINE("Average packets per flow", collector.getGeneralStats().averageNumOfPacketsPerFlow, "Packets"); - PRINT_STAT_LINE("Average transactions per flow", collector.getGeneralStats().averageNumOfHttpTransactionsPerFlow, "Transactions"); + PRINT_STAT_LINE("Average transactions per flow", collector.getGeneralStats().averageNumOfHttpTransactionsPerFlow, + "Transactions"); PRINT_STAT_LINE("Average data per flow", collector.getGeneralStats().averageAmountOfDataPerFlow, "Bytes"); printStatsHeadline("HTTP request stats"); @@ -328,8 +355,10 @@ void printStatsSummary(HttpStatsCollector& collector) PRINT_STAT_LINE("Rate of HTTP responses", collector.getResponseStats().messageRate.totalRate, "Responses/sec"); PRINT_STAT_LINE("Total data in headers", collector.getResponseStats().totalMessageHeaderSize, "Bytes"); PRINT_STAT_LINE("Average header size", collector.getResponseStats().averageMessageHeaderSize, "Bytes"); - PRINT_STAT_LINE("Num of responses with content-length", collector.getResponseStats().numOfMessagesWithContentLength, "Responses"); - PRINT_STAT_LINE("Total body size (may be compressed)", collector.getResponseStats().totalContentLengthSize, "Bytes"); + PRINT_STAT_LINE("Num of responses with content-length", collector.getResponseStats().numOfMessagesWithContentLength, + "Responses"); + PRINT_STAT_LINE("Total body size (may be compressed)", collector.getResponseStats().totalContentLengthSize, + "Bytes"); PRINT_STAT_LINE("Average body size", collector.getResponseStats().averageContentLengthSize, "Bytes"); printStatsHeadline("HTTP request methods"); @@ -345,7 +374,6 @@ void printStatsSummary(HttpStatsCollector& collector) printContentTypes(collector.getResponseStats()); } - /** * Print the current rates. Should be called periodically during traffic capture */ @@ -354,13 +382,13 @@ void printCurrentRates(HttpStatsCollector& collector) printStatsHeadline("Current HTTP rates"); PRINT_STAT_LINE("Rate of HTTP packets", collector.getGeneralStats().httpPacketRate.currentRate, "Packets/sec"); PRINT_STAT_LINE("Rate of HTTP flows", collector.getGeneralStats().httpFlowRate.currentRate, "Flows/sec"); - PRINT_STAT_LINE("Rate of HTTP transactions", collector.getGeneralStats().httpTransactionsRate.currentRate, "Transactions/sec"); + PRINT_STAT_LINE("Rate of HTTP transactions", collector.getGeneralStats().httpTransactionsRate.currentRate, + "Transactions/sec"); PRINT_STAT_LINE("Rate of HTTP data", collector.getGeneralStats().httpTrafficRate.currentRate, "Bytes/sec"); PRINT_STAT_LINE("Rate of HTTP requests", collector.getRequestStats().messageRate.currentRate, "Requests/sec"); PRINT_STAT_LINE("Rate of HTTP responses", collector.getResponseStats().messageRate.currentRate, "Responses/sec"); } - /** * The callback to be called when application is terminated by ctrl-c. Stops the endless while loop */ @@ -370,7 +398,6 @@ void onApplicationInterrupted(void* cookie) *shouldStop = true; } - /** * activate HTTP analysis from pcap file */ @@ -390,16 +417,14 @@ void analyzeHttpFromPcapFile(const std::string& pcapFileName, uint16_t dstPort) // read the input file packet by packet and give it to the HttpStatsCollector for collecting stats HttpStatsCollector collector(dstPort); pcpp::RawPacket rawPacket; - while(reader->getNextPacket(rawPacket)) + while (reader->getNextPacket(rawPacket)) { pcpp::Packet parsedPacket(&rawPacket); collector.collectStats(&parsedPacket); } // print stats summary - std::cout << std::endl << std::endl - << "STATS SUMMARY" << std::endl - << "=============" << std::endl; + std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; printStatsSummary(collector); // close input file @@ -409,11 +434,11 @@ void analyzeHttpFromPcapFile(const std::string& pcapFileName, uint16_t dstPort) delete reader; } - /** * activate HTTP analysis from live traffic */ -void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodically, int printRatePeriod, const std::string& savePacketsToFileName, uint16_t dstPort) +void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodically, int printRatePeriod, + const std::string& savePacketsToFileName, uint16_t dstPort) { // open the device if (!dev->open()) @@ -441,12 +466,11 @@ void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriod data.pcapWriter = pcapWriter; dev->startCapture(httpPacketArrive, &data); - // register the on app close event to print summary stats on app termination bool shouldStop = false; pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &shouldStop); - while(!shouldStop) + while (!shouldStop) { pcpp::multiPlatformSleep(printRatePeriod); @@ -466,9 +490,7 @@ void analyzeHttpFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriod collector.calcRates(); // print stats summary - std::cout << std::endl << std::endl - << "STATS SUMMARY" << std::endl - << "=============" << std::endl; + std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; printStatsSummary(collector); // close and free the writer device @@ -494,47 +516,45 @@ int main(int argc, char* argv[]) std::string readPacketsFromPcapFileName = ""; - int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:p:f:o:r:hvld", HttpAnalyzerOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:p:f:o:r:hvld", HttpAnalyzerOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - interfaceNameOrIP = optarg; - break; - case 'p': - port = optarg; - break; - case 'f': - readPacketsFromPcapFileName = optarg; - break; - case 'o': - savePacketsToFileName = optarg; - break; - case 'r': - printRatePeriod = atoi(optarg); - break; - case 'd': - printRatesPeriodically = false; - break; - case 'h': - printUsage(); - exit(0); - break; - case 'v': - printAppVersion(); - break; - case 'l': - listInterfaces(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'i': + interfaceNameOrIP = optarg; + break; + case 'p': + port = optarg; + break; + case 'f': + readPacketsFromPcapFileName = optarg; + break; + case 'o': + savePacketsToFileName = optarg; + break; + case 'r': + printRatePeriod = atoi(optarg); + break; + case 'd': + printRatesPeriodically = false; + break; + case 'h': + printUsage(); + exit(0); + case 'v': + printAppVersion(); + break; + case 'l': + listInterfaces(); + break; + default: + printUsage(); + exit(-1); } } @@ -552,9 +572,10 @@ int main(int argc, char* argv[]) { analyzeHttpFromPcapFile(readPacketsFromPcapFileName, nPort); } - else // analyze in live traffic mode + else // analyze in live traffic mode { - pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); + pcpp::PcapLiveDevice* dev = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); diff --git a/Examples/IPDefragUtil/main.cpp b/Examples/IPDefragUtil/main.cpp index 76d5ff532a..394e87ddaf 100644 --- a/Examples/IPDefragUtil/main.cpp +++ b/Examples/IPDefragUtil/main.cpp @@ -11,23 +11,22 @@ #include "SystemUtils.h" #include "getopt.h" - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -static struct option DefragUtilOptions[] = -{ - {"output-file", required_argument, nullptr, 'o'}, - {"filter-by-ipid", required_argument, nullptr, 'd'}, - {"bpf-filter", required_argument, nullptr, 'f'}, - {"copy-all-packets", no_argument, nullptr, 'a'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +static struct option DefragUtilOptions[] = { + { "output-file", required_argument, nullptr, 'o' }, + { "filter-by-ipid", required_argument, nullptr, 'd' }, + { "bpf-filter", required_argument, nullptr, 'f' }, + { "copy-all-packets", no_argument, nullptr, 'a' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { nullptr, 0, nullptr, 0 } }; /** @@ -47,58 +46,66 @@ struct DefragStats int ipv6PacketsDefragmented; int totalPacketsWritten; - void clear() { memset(this, 0, sizeof(DefragStats)); } - DefragStats() { clear(); } + void clear() + { + memset(this, 0, sizeof(DefragStats)); + } + DefragStats() + { + clear(); + } }; - /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " input_file -o output_file [-d frag_ids] [-f bpf_filter] [-a] [-h] [-v]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " input_file : Input pcap/pcapng file" << std::endl - << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" << std::endl - << " -d frag_ids : De-fragment only fragments that match this comma-separated list of IP IDs (for IPv4) or" << std::endl - << " fragment IDs (for IPv6) in decimal format" << std::endl - << " -f bpf_filter : De-fragment only fragments that match bpf_filter. Filter should be provided in Berkeley Packet Filter (BPF)" << std::endl - << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << std::endl - << " -a : Copy all packets (those who were de-fragmented and those who weren't) to output file" << std::endl - << " -v : Displays the current version and exits" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " input_file -o output_file [-d frag_ids] [-f bpf_filter] [-a] [-h] [-v]" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " input_file : Input pcap/pcapng file" << std::endl + << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" + << std::endl + << " -d frag_ids : De-fragment only fragments that match this comma-separated list of IP IDs (for IPv4) " + "or" + << std::endl + << " fragment IDs (for IPv6) in decimal format" << std::endl + << " -f bpf_filter : De-fragment only fragments that match bpf_filter. Filter should be provided in " + "Berkeley Packet Filter (BPF)" + << std::endl + << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << std::endl + << " -a : Copy all packets (those who were de-fragmented and those who weren't) to output file" + << std::endl + << " -v : Displays the current version and exits" << std::endl + << " -h : Displays this help message and exits" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** - * This method reads packets from the input file, decided which fragments pass the filters set by the user, de-fragment the fragments - * who pass them, and writes the result packets to the output file + * This method reads packets from the input file, decided which fragments pass the filters set by the user, de-fragment + * the fragments who pass them, and writes the result packets to the output file */ -void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* writer, - bool filterByBpf, const std::string& bpfFilter, - bool filterByIpID, std::unordered_map fragIDs, - bool copyAllPacketsToOutputFile, - DefragStats& stats) +void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* writer, bool filterByBpf, + const std::string& bpfFilter, bool filterByIpID, std::unordered_map fragIDs, + bool copyAllPacketsToOutputFile, DefragStats& stats) { pcpp::RawPacket rawPacket; pcpp::BPFStringFilter filter(bpfFilter); @@ -123,7 +130,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr { stats.ipPacketsMatchBpfFilter++; } - else // if not - set the packet as not marked for de-fragmentation + else // if not - set the packet as not marked for de-fragmentation { defragPacket = false; } @@ -144,7 +151,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr stats.ipv6Packets++; isIPv6Packet = true; } - else // if not - set the packet as not marked for de-fragmentation + else // if not - set the packet as not marked for de-fragmentation { defragPacket = false; } @@ -161,7 +168,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr { stats.ipv4PacketsMatchIpIDs++; } - else // if not - set the packet as not marked for de-fragmentation + else // if not - set the packet as not marked for de-fragmentation { defragPacket = false; } @@ -179,7 +186,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr { stats.ipv6PacketsMatchFragIDs++; } - else // if not - set the packet as not marked for de-fragmentation + else // if not - set the packet as not marked for de-fragmentation { defragPacket = false; } @@ -196,7 +203,8 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr // - packet is fully reassembled (status of REASSEMBLED) // - packet isn't a fragment or isn't an IP packet and the user asked to write all packets to output if (status == pcpp::IPReassembly::REASSEMBLED || - ((status == pcpp::IPReassembly::NON_IP_PACKET || status == pcpp::IPReassembly::NON_FRAGMENT) && copyAllPacketsToOutputFile)) + ((status == pcpp::IPReassembly::NON_IP_PACKET || status == pcpp::IPReassembly::NON_FRAGMENT) && + copyAllPacketsToOutputFile)) { writer->writePacket(*result->getRawPacket()); stats.totalPacketsWritten++; @@ -215,11 +223,9 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr } // update statistics if packet isn't fully reassembled - if (status == pcpp::IPReassembly::FIRST_FRAGMENT || - status == pcpp::IPReassembly::FRAGMENT || - status == pcpp::IPReassembly::OUT_OF_ORDER_FRAGMENT || - status == pcpp::IPReassembly::MALFORMED_FRAGMENT || - status == pcpp::IPReassembly::REASSEMBLED) + if (status == pcpp::IPReassembly::FIRST_FRAGMENT || status == pcpp::IPReassembly::FRAGMENT || + status == pcpp::IPReassembly::OUT_OF_ORDER_FRAGMENT || + status == pcpp::IPReassembly::MALFORMED_FRAGMENT || status == pcpp::IPReassembly::REASSEMBLED) { if (isIPv4Packet) stats.ipv4FragmentsMatched++; @@ -233,11 +239,9 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr writer->writePacket(rawPacket); stats.totalPacketsWritten++; } - } } - /** * A method for printing fragmentation process stats */ @@ -256,10 +260,12 @@ void printStats(const DefragStats& stats, bool filterByIpID, bool filterByBpf) } if (filterByBpf) stream << "IP packets match BPF filter: " << stats.ipPacketsMatchBpfFilter << std::endl; - stream << "Total fragments matched: " << (stats.ipv4FragmentsMatched + stats.ipv6FragmentsMatched) << std::endl; + stream << "Total fragments matched: " << (stats.ipv4FragmentsMatched + stats.ipv6FragmentsMatched) + << std::endl; stream << "IPv4 fragments matched: " << stats.ipv4FragmentsMatched << std::endl; stream << "IPv6 fragments matched: " << stats.ipv6FragmentsMatched << std::endl; - stream << "Total packets reassembled: " << (stats.ipv4PacketsDefragmented + stats.ipv6PacketsDefragmented) << std::endl; + stream << "Total packets reassembled: " + << (stats.ipv4PacketsDefragmented + stats.ipv6PacketsDefragmented) << std::endl; stream << "IPv4 packets reassembled: " << stats.ipv4PacketsDefragmented << std::endl; stream << "IPv6 packets reassembled: " << stats.ipv6PacketsDefragmented << std::endl; stream << "Total packets written to output file: " << stats.totalPacketsWritten << std::endl; @@ -267,7 +273,6 @@ void printStats(const DefragStats& stats, bool filterByIpID, bool filterByBpf) std::cout << stream.str(); } - /** * main method of the application */ @@ -285,68 +290,67 @@ int main(int argc, char* argv[]) std::unordered_map fragIDMap; bool copyAllPacketsToOutputFile = false; - - while((opt = getopt_long(argc, argv, "o:d:f:ahv", DefragUtilOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "o:d:f:ahv", DefragUtilOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'o': + case 0: + { + break; + } + case 'o': + { + outputFile = optarg; + break; + } + case 'd': + { + filterByFragID = true; + // read the IP ID / Frag ID list into the map + fragIDMap.clear(); + std::string ipIDsAsString = std::string(optarg); + std::stringstream stream(ipIDsAsString); + std::string ipIDStr; + // break comma-separated string into string list + while (std::getline(stream, ipIDStr, ',')) { - outputFile = optarg; - break; + // convert the IP ID to uint16_t + uint32_t fragID = (uint32_t)atoi(ipIDStr.c_str()); + // add the frag ID into the map if it doesn't already exist + fragIDMap.emplace(fragID, true); } - case 'd': - { - filterByFragID = true; - // read the IP ID / Frag ID list into the map - fragIDMap.clear(); - std::string ipIDsAsString = std::string(optarg); - std::stringstream stream(ipIDsAsString); - std::string ipIDStr; - // break comma-separated string into string list - while(std::getline(stream, ipIDStr, ',')) - { - // convert the IP ID to uint16_t - uint32_t fragID = (uint32_t)atoi(ipIDStr.c_str()); - // add the frag ID into the map if it doesn't already exist - fragIDMap.emplace(fragID, true); - } - // verify list is not empty - if (fragIDMap.empty()) - { - EXIT_WITH_ERROR("Couldn't parse fragment ID list"); - } - break; - } - case 'f': + // verify list is not empty + if (fragIDMap.empty()) { - filterByBpfFilter = true; - bpfFilter = optarg; - pcpp::BPFStringFilter filter(bpfFilter); - if (!filter.verifyFilter()) - EXIT_WITH_ERROR("Illegal BPF filter"); - break; - } - case 'a': - { - copyAllPacketsToOutputFile = true; - break; - } - case 'h': - { - printUsage(); - exit(0); - } - case 'v': - { - printAppVersion(); - break; + EXIT_WITH_ERROR("Couldn't parse fragment ID list"); } + break; + } + case 'f': + { + filterByBpfFilter = true; + bpfFilter = optarg; + pcpp::BPFStringFilter filter(bpfFilter); + if (!filter.verifyFilter()) + EXIT_WITH_ERROR("Illegal BPF filter"); + break; + } + case 'a': + { + copyAllPacketsToOutputFile = true; + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } } } @@ -363,14 +367,14 @@ int main(int argc, char* argv[]) switch (paramIndex) { - case 0: - { - inputFile = argv[i]; - break; - } + case 0: + { + inputFile = argv[i]; + break; + } - default: - EXIT_WITH_ERROR("Unexpected parameter: " << argv[i]); + default: + EXIT_WITH_ERROR("Unexpected parameter: " << argv[i]); } } @@ -392,7 +396,6 @@ int main(int argc, char* argv[]) EXIT_WITH_ERROR("Error opening input file"); } - // create a writer device for output file in the same file type as input file pcpp::IFileWriterDevice* writer = nullptr; @@ -416,7 +419,8 @@ int main(int argc, char* argv[]) // run the de-fragmentation process DefragStats stats; - processPackets(reader, writer, filterByBpfFilter, bpfFilter, filterByFragID, fragIDMap, copyAllPacketsToOutputFile, stats); + processPackets(reader, writer, filterByBpfFilter, bpfFilter, filterByFragID, fragIDMap, copyAllPacketsToOutputFile, + stats); // close files reader->close(); diff --git a/Examples/IPFragUtil/main.cpp b/Examples/IPFragUtil/main.cpp index 27ad037f97..c6151ecd1c 100644 --- a/Examples/IPFragUtil/main.cpp +++ b/Examples/IPFragUtil/main.cpp @@ -13,24 +13,23 @@ #include "SystemUtils.h" #include "getopt.h" - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -static struct option FragUtilOptions[] = -{ - {"output-file", required_argument, nullptr, 'o'}, - {"frag-size", required_argument, nullptr, 's'}, - {"filter-by-ipid", required_argument, nullptr, 'd'}, - {"bpf-filter", required_argument, nullptr, 'f'}, - {"copy-all-packets", no_argument, nullptr, 'a'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +static struct option FragUtilOptions[] = { + { "output-file", required_argument, nullptr, 'o' }, + { "frag-size", required_argument, nullptr, 's' }, + { "filter-by-ipid", required_argument, nullptr, 'd' }, + { "bpf-filter", required_argument, nullptr, 'f' }, + { "copy-all-packets", no_argument, nullptr, 'a' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { nullptr, 0, nullptr, 0 } }; /** @@ -48,56 +47,66 @@ struct FragStats int ipv6PacketsFragmented; int totalPacketsWritten; - void clear() { memset(this, 0, sizeof(FragStats)); } - FragStats() { clear(); } + void clear() + { + memset(this, 0, sizeof(FragStats)); + } + FragStats() + { + clear(); + } }; - /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " input_file -s frag_size -o output_file [-d ip_ids] [-f bpf_filter] [-a] [-h] [-v]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " input_file : Input pcap/pcapng file" << std::endl - << " -s frag_size : Size of each fragment" << std::endl - << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" << std::endl - << " -d ip_ids : Fragment only packets that match this comma-separated list of IP IDs in decimal format" << std::endl - << " -f bpf_filter : Fragment only packets that match bpf_filter. Filter should be provided in Berkeley Packet Filter (BPF)" << std::endl - << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << std::endl - << " -a : Copy all packets (those who were fragmented and those who weren't) to output file" << std::endl - << " -v : Displays the current version and exits" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " input_file -s frag_size -o output_file [-d ip_ids] [-f bpf_filter] [-a] [-h] [-v]" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " input_file : Input pcap/pcapng file" << std::endl + << " -s frag_size : Size of each fragment" << std::endl + << " -o output_file : Output file. Output file type (pcap/pcapng) will match the input file type" + << std::endl + << " -d ip_ids : Fragment only packets that match this comma-separated list of IP IDs in decimal " + "format" + << std::endl + << " -f bpf_filter : Fragment only packets that match bpf_filter. Filter should be provided in Berkeley " + "Packet Filter (BPF)" + << std::endl + << " syntax (http://biot.com/capstats/bpf.html) i.e: 'ip net 1.1.1.1'" << std::endl + << " -a : Copy all packets (those who were fragmented and those who weren't) to output file" + << std::endl + << " -v : Displays the current version and exits" << std::endl + << " -h : Displays this help message and exits" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Set fragment parameters in an IPv4 fragment packet */ void setIPv4FragmentParams(pcpp::IPv4Layer* fragIpLayer, size_t fragOffset, bool lastFrag) { // calculate the fragment offset field - uint16_t fragOffsetValue = pcpp::hostToNet16((uint16_t)(fragOffset/8)); + uint16_t fragOffsetValue = pcpp::hostToNet16((uint16_t)(fragOffset / 8)); // set the fragment flags bits to zero fragOffsetValue &= (uint16_t)0xff1f; @@ -110,7 +119,6 @@ void setIPv4FragmentParams(pcpp::IPv4Layer* fragIpLayer, size_t fragOffset, bool fragIpLayer->getIPv4Header()->fragmentOffset = fragOffsetValue; } - /** * Add IPv6 fragmentation extension to an IPv6 fragment packet and set fragmentation parameters */ @@ -120,7 +128,6 @@ void setIPv6FragmentParams(pcpp::IPv6Layer* fragIpLayer, size_t fragOffset, bool fragIpLayer->addExtension(fragHeader); } - /** * Generate a 4-byte positive random number. Used for generating IPv6 fragment ID */ @@ -141,10 +148,11 @@ uint32_t generateRandomNumber() * Fragments are written to a RawPacketVector instance supplied by the user. * The input packet isn't modified in any way. * If the packet isn't of type IPv4 or IPv6, nothing happens and the result vector remains empty. - * If the packet payload size is smaller or equal than the request fragment size the packet isn't fragmented, but the packet is copied - * and pushed into the result vector + * If the packet payload size is smaller or equal than the request fragment size the packet isn't fragmented, but the + * packet is copied and pushed into the result vector */ -void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentSize, pcpp::RawPacketVector& resultFragments) +void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentSize, + pcpp::RawPacketVector& resultFragments) { // parse raw packet pcpp::Packet packet(rawPacket); @@ -161,7 +169,7 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS pcpp::Layer* ipLayer = nullptr; if (ipProto == pcpp::IPv4) ipLayer = packet.getLayerOfType(); - else // ipProto == IPv6 + else // ipProto == IPv6 ipLayer = packet.getLayerOfType(); // if packet payload size is less than the requested fragment size, don't fragment and return @@ -182,7 +190,8 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS bool lastFrag = false; size_t curFragSize = fragmentSize; - // check if this is the last fragment by comparing the size of the rest of the payload to the requested fragment size + // check if this is the last fragment by comparing the size of the rest of the payload to the requested fragment + // size if (ipLayer->getLayerPayloadSize() - curOffset <= fragmentSize) { curFragSize = ipLayer->getLayerPayloadSize() - curOffset; @@ -198,7 +207,7 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS pcpp::Layer* fragIpLayer = nullptr; if (ipProto == pcpp::IPv4) fragIpLayer = newFrag.getLayerOfType(); - else // ipProto == IPv6 + else // ipProto == IPv6 fragIpLayer = newFrag.getLayerOfType(); // delete all layers above IP layer @@ -211,7 +220,7 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS // set fragment parameters in IPv4/6 layer if (ipProto == pcpp::IPv4) setIPv4FragmentParams((pcpp::IPv4Layer*)fragIpLayer, curOffset, lastFrag); - else // ipProto == IPv6 + else // ipProto == IPv6 setIPv6FragmentParams((pcpp::IPv6Layer*)fragIpLayer, curOffset, lastFrag, randomNum); // compute all calculated fields of the new fragment @@ -223,20 +232,15 @@ void splitIPPacketToFragmentsBySize(pcpp::RawPacket* rawPacket, size_t fragmentS // increment offset pointer curOffset += curFragSize; } - } - /** - * This method reads packets from the input file, decided which packets pass the filters set by the user, fragment packets who pass them, - * and write the result packets to the output file + * This method reads packets from the input file, decided which packets pass the filters set by the user, fragment + * packets who pass them, and write the result packets to the output file */ -void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* writer, - int fragSize, - bool filterByBpf, const std::string& bpfFilter, - bool filterByIpID, std::unordered_map ipIDs, - bool copyAllPacketsToOutputFile, - FragStats& stats) +void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* writer, int fragSize, bool filterByBpf, + const std::string& bpfFilter, bool filterByIpID, std::unordered_map ipIDs, + bool copyAllPacketsToOutputFile, FragStats& stats) { stats.clear(); @@ -259,7 +263,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr { stats.ipPacketsMatchBpfFilter++; } - else // if not - set the packet as not marked for fragmentation + else // if not - set the packet as not marked for fragmentation { fragPacket = false; } @@ -274,12 +278,12 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr ipProto = pcpp::IPv4; stats.ipv4Packets++; } - else if (parsedPacket.isPacketOfType(pcpp::IPv6)) // check if packet is of type IPv6 + else if (parsedPacket.isPacketOfType(pcpp::IPv6)) // check if packet is of type IPv6 { ipProto = pcpp::IPv6; stats.ipv6Packets++; } - else // if not - set the packet as not marked for fragmentation + else // if not - set the packet as not marked for fragmentation { fragPacket = false; } @@ -296,7 +300,7 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr { stats.ipv4PacketsMatchIpIDs++; } - else // if not - set the packet as not marked for fragmentation + else // if not - set the packet as not marked for fragmentation { fragPacket = false; } @@ -315,11 +319,11 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr { stats.ipPacketsUnderSize++; } - else if (resultFrags.size() > 1) // packet was fragmented + else if (resultFrags.size() > 1) // packet was fragmented { if (ipProto == pcpp::IPv4) stats.ipv4PacketsFragmented++; - else // ipProto == IPv6 + else // ipProto == IPv6 stats.ipv6PacketsFragmented++; } @@ -340,7 +344,6 @@ void processPackets(pcpp::IFileReaderDevice* reader, pcpp::IFileWriterDevice* wr } } - /** * A method for printing fragmentation process stats */ @@ -364,7 +367,6 @@ void printStats(const FragStats& stats, bool filterByIpID, bool filterByBpf) std::cout << stream.str(); } - /** * main method of the application */ @@ -383,76 +385,76 @@ int main(int argc, char* argv[]) std::unordered_map ipIDMap; bool copyAllPacketsToOutputFile = false; - while((opt = getopt_long(argc, argv, "o:s:d:f:ahv", FragUtilOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "o:s:d:f:ahv", FragUtilOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'o': - { - outputFile = optarg; - break; - } - case 's': + case 0: + { + break; + } + case 'o': + { + outputFile = optarg; + break; + } + case 's': + { + fragSize = atoi(optarg); + if (fragSize < 1) + EXIT_WITH_ERROR("Fragment size must be a positive integer"); + if (fragSize % 8 != 0) + EXIT_WITH_ERROR("Fragment size must divide by 8"); + break; + } + case 'd': + { + filterByIpID = true; + // read the IP ID list into the map + ipIDMap.clear(); + std::string ipIDsAsString = std::string(optarg); + std::stringstream stream(ipIDsAsString); + std::string ipIDStr; + // break comma-separated string into string list + while (std::getline(stream, ipIDStr, ',')) { - fragSize = atoi(optarg); - if (fragSize < 1) - EXIT_WITH_ERROR("Fragment size must be a positive integer"); - if (fragSize % 8 != 0) - EXIT_WITH_ERROR("Fragment size must divide by 8"); - break; + // convert the IP ID to uint16_t + uint16_t ipID = (uint16_t)atoi(ipIDStr.c_str()); + // add the IP ID into the map if it doesn't already exist + ipIDMap.emplace(ipID, true); } - case 'd': - { - filterByIpID = true; - // read the IP ID list into the map - ipIDMap.clear(); - std::string ipIDsAsString = std::string(optarg); - std::stringstream stream(ipIDsAsString); - std::string ipIDStr; - // break comma-separated string into string list - while(std::getline(stream, ipIDStr, ',')) - { - // convert the IP ID to uint16_t - uint16_t ipID = (uint16_t)atoi(ipIDStr.c_str()); - // add the IP ID into the map if it doesn't already exist - ipIDMap.emplace(ipID, true); - } - // verify list is not empty - if (ipIDMap.empty()) - { - EXIT_WITH_ERROR("Couldn't parse IP ID list"); - } - break; - } - case 'f': + // verify list is not empty + if (ipIDMap.empty()) { - filterByBpfFilter = true; - bpfFilter = optarg; - pcpp::BPFStringFilter filter(bpfFilter); - if (!filter.verifyFilter()) - EXIT_WITH_ERROR("Illegal BPF filter"); - break; - } - case 'a': - { - copyAllPacketsToOutputFile = true; - break; - } - case 'h': - { - printUsage(); - exit(0); - } - case 'v': - { - printAppVersion(); - break; + EXIT_WITH_ERROR("Couldn't parse IP ID list"); } + break; + } + case 'f': + { + filterByBpfFilter = true; + bpfFilter = optarg; + pcpp::BPFStringFilter filter(bpfFilter); + if (!filter.verifyFilter()) + EXIT_WITH_ERROR("Illegal BPF filter"); + break; + } + case 'a': + { + copyAllPacketsToOutputFile = true; + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } } } @@ -470,18 +472,17 @@ int main(int argc, char* argv[]) switch (paramIndex) { - case 0: - { - inputFile = argv[i]; - break; - } + case 0: + { + inputFile = argv[i]; + break; + } - default: - EXIT_WITH_ERROR("Unexpected parameter: " << argv[i]); + default: + EXIT_WITH_ERROR("Unexpected parameter: " << argv[i]); } } - if (inputFile == "") { EXIT_WITH_ERROR("Input file name was not given"); @@ -505,7 +506,6 @@ int main(int argc, char* argv[]) EXIT_WITH_ERROR("Error opening input file"); } - // create a writer device for output file in the same file type as input file pcpp::IFileWriterDevice* writer = nullptr; @@ -529,7 +529,8 @@ int main(int argc, char* argv[]) // run the fragmentation process FragStats stats; - processPackets(reader, writer, fragSize, filterByBpfFilter, bpfFilter, filterByIpID, ipIDMap, copyAllPacketsToOutputFile, stats); + processPackets(reader, writer, fragSize, filterByBpfFilter, bpfFilter, filterByIpID, ipIDMap, + copyAllPacketsToOutputFile, stats); // close files reader->close(); diff --git a/Examples/IcmpFileTransfer/Common.cpp b/Examples/IcmpFileTransfer/Common.cpp index 4e3037e7d3..80f080ce1d 100644 --- a/Examples/IcmpFileTransfer/Common.cpp +++ b/Examples/IcmpFileTransfer/Common.cpp @@ -10,101 +10,100 @@ #include "SystemUtils.h" #include "PcapPlusPlusVersion.h" - #if defined(_WIN32) -#define SEPARATOR '\\' +# define SEPARATOR '\\' #else -#define SEPARATOR '/' +# define SEPARATOR '/' #endif #define DEFAULT_BLOCK_SIZE 1400 -static struct option IcmpFTOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"dest-ip", required_argument, nullptr, 'd'}, - {"send-file", required_argument, nullptr, 's'}, - {"receive-file", no_argument, nullptr, 'r'}, - {"speed", required_argument, nullptr, 'p'}, - {"block-size", required_argument, nullptr, 'b'}, - {"list-interfaces", no_argument, nullptr, 'l'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, no_argument, nullptr, no_argument} +static struct option IcmpFTOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "dest-ip", required_argument, nullptr, 'd' }, + { "send-file", required_argument, nullptr, 's' }, + { "receive-file", no_argument, nullptr, 'r' }, + { "speed", required_argument, nullptr, 'p' }, + { "block-size", required_argument, nullptr, 'b' }, + { "list-interfaces", no_argument, nullptr, 'l' }, + { "version", no_argument, nullptr, 'v' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, no_argument, nullptr, no_argument } }; +#define EXIT_WITH_ERROR_PRINT_USAGE(reason) \ + do \ + { \ + printUsage(thisSide, otherSide); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) -#define EXIT_WITH_ERROR_PRINT_USAGE(reason) do { \ - printUsage(thisSide, otherSide); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -void printUsage(const std::string &thisSide, const std::string &otherSide) +void printUsage(const std::string& thisSide, const std::string& otherSide) { std::string messagesPerSecShort = (thisSide == "pitcher") ? "[-p messages_per_sec] " : ""; - std::string messagesPerSecLong = (thisSide == "pitcher") ? " -p messages_per_sec : Set number of messages to be sent per seconds. Default is max possible speed\n" : ""; + std::string messagesPerSecLong = (thisSide == "pitcher") ? " -p messages_per_sec : Set number of messages to " + "be sent per seconds. Default is max possible speed\n" + : ""; std::string thisSideInterface = thisSide + "_interface"; std::string otherSideIP = otherSide + "_ip"; - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-h] [-v] [-l] -i " << thisSideInterface << " -d " << otherSideIP << " -s file_path -r " << messagesPerSecShort << "[-b block_size]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -i " << thisSideInterface << " : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << std::endl - << " -d " << otherSideIP << " : " << otherSide << " IPv4 address" << std::endl - << " -s file_path : Send file mode: send file_path to " << otherSide << std::endl - << " -r : Receive file mode: receive file from " << otherSide << std::endl - << messagesPerSecLong - << " -b block_size : Set the size of data chunk sent in each ICMP message (in bytes). Default is " << DEFAULT_BLOCK_SIZE << " bytes. Relevant only" << std::endl - << " in send file mode (when -s is set)" << std::endl - << " -l : Print the list of interfaces and exit" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-h] [-v] [-l] -i " << thisSideInterface << " -d " << otherSideIP + << " -s file_path -r " << messagesPerSecShort << "[-b block_size]" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -i " << thisSideInterface + << " : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << std::endl + << " -d " << otherSideIP << " : " << otherSide << " IPv4 address" << std::endl + << " -s file_path : Send file mode: send file_path to " << otherSide << std::endl + << " -r : Receive file mode: receive file from " << otherSide << std::endl + << messagesPerSecLong + << " -b block_size : Set the size of data chunk sent in each ICMP message (in bytes). Default is " + << DEFAULT_BLOCK_SIZE << " bytes. Relevant only" << std::endl + << " in send file mode (when -s is set)" << std::endl + << " -l : Print the list of interfaces and exit" << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -h : Display this help message and exit" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for (const auto &dev : devList) + for (const auto& dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - -void readCommandLineArguments(int argc, char* argv[], - const std::string &thisSide, const std::string &otherSide, - bool& sender, bool& receiver, - pcpp::IPv4Address& myIP, pcpp::IPv4Address& otherSideIP, - std::string& fileNameToSend, - int& packetsPerSec, size_t& blockSize) +void readCommandLineArguments(int argc, char* argv[], const std::string& thisSide, const std::string& otherSide, + bool& sender, bool& receiver, pcpp::IPv4Address& myIP, pcpp::IPv4Address& otherSideIP, + std::string& fileNameToSend, int& packetsPerSec, size_t& blockSize) { std::string interfaceNameOrIP; std::string otherSideIPAsString; @@ -119,48 +118,48 @@ void readCommandLineArguments(int argc, char* argv[], int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:d:s:rp:b:hvl", IcmpFTOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:d:s:rp:b:hvl", IcmpFTOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - interfaceNameOrIP = optarg; - break; - case 'd': - otherSideIPAsString = optarg; - break; - case 's': - fileNameToSend = optarg; - sender = true; - break; - case 'r': - receiver = true; - break; - case 'p': - if (thisSide == "catcher") - EXIT_WITH_ERROR_PRINT_USAGE("Unknown option -p"); - packetsPerSec = atoi(optarg); - packetsPerSecSet = true; - break; - case 'b': - blockSize = atoi(optarg); - blockSizeSet = true; - break; - case 'h': - printUsage(thisSide, otherSide); - exit(0); - break; - case 'v': - printAppVersion(); - break; - case 'l': - listInterfaces(); - break; - default: - printUsage(thisSide, otherSide); - exit(-1); + case 0: + break; + case 'i': + interfaceNameOrIP = optarg; + break; + case 'd': + otherSideIPAsString = optarg; + break; + case 's': + fileNameToSend = optarg; + sender = true; + break; + case 'r': + receiver = true; + break; + case 'p': + if (thisSide == "catcher") + EXIT_WITH_ERROR_PRINT_USAGE("Unknown option -p"); + packetsPerSec = atoi(optarg); + packetsPerSecSet = true; + break; + case 'b': + blockSize = atoi(optarg); + blockSizeSet = true; + break; + case 'h': + printUsage(thisSide, otherSide); + exit(0); + break; + case 'v': + printAppVersion(); + break; + case 'l': + listInterfaces(); + break; + default: + printUsage(thisSide, otherSide); + exit(-1); } } @@ -174,7 +173,7 @@ void readCommandLineArguments(int argc, char* argv[], interfaceIP = pcpp::IPv4Address(interfaceNameOrIP); myIP = interfaceIP; } - catch(const std::exception&) + catch (const std::exception&) { pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByName(interfaceNameOrIP); if (dev == nullptr) @@ -192,7 +191,7 @@ void readCommandLineArguments(int argc, char* argv[], { tempIP = pcpp::IPv4Address(otherSideIPAsString); } - catch(const std::exception&) + catch (const std::exception&) { EXIT_WITH_ERROR_PRINT_USAGE("Invalid " << otherSide << " IP address"); } @@ -211,20 +210,17 @@ void readCommandLineArguments(int argc, char* argv[], // validate block size if (blockSize < 1 || blockSize > 1464) - EXIT_WITH_ERROR_PRINT_USAGE("Block size must be a positive integer lower or equal to 1464 bytes (which is the maximum size for a standard packet)"); + EXIT_WITH_ERROR_PRINT_USAGE("Block size must be a positive integer lower or equal to 1464 bytes (which is the " + "maximum size for a standard packet)"); // validate packets per sec if (packetsPerSecSet && packetsPerSec < 1) EXIT_WITH_ERROR_PRINT_USAGE("message_per_sec must be a positive value greater or equal to 1"); } -bool sendIcmpMessage(pcpp::PcapLiveDevice* dev, - pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, - pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, - size_t icmpMsgId, - uint64_t msgType, - uint8_t* data, size_t dataLen, - bool sendRequest) +bool sendIcmpMessage(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, + pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, size_t icmpMsgId, uint64_t msgType, + uint8_t* data, size_t dataLen, bool sendRequest) { // a static variable that holds an incrementing IP ID static uint16_t ipID = 0x1234; @@ -262,22 +258,16 @@ bool sendIcmpMessage(pcpp::PcapLiveDevice* dev, return dev->sendPacket(&packet); } -bool sendIcmpRequest(pcpp::PcapLiveDevice* dev, - pcpp::MacAddress srcMacAddr, const pcpp::MacAddress dstMacAddr, - pcpp::IPv4Address srcIPAddr, const pcpp::IPv4Address dstIPAddr, - size_t icmpMsgId, - uint64_t msgType, - uint8_t* data, size_t dataLen) +bool sendIcmpRequest(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, const pcpp::MacAddress dstMacAddr, + pcpp::IPv4Address srcIPAddr, const pcpp::IPv4Address dstIPAddr, size_t icmpMsgId, uint64_t msgType, + uint8_t* data, size_t dataLen) { return sendIcmpMessage(dev, srcMacAddr, dstMacAddr, srcIPAddr, dstIPAddr, icmpMsgId, msgType, data, dataLen, true); } -bool sendIcmpResponse(pcpp::PcapLiveDevice* dev, - pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, - pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, - size_t icmpMsgId, - uint64_t msgType, - uint8_t* data, size_t dataLen) +bool sendIcmpResponse(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, + pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, size_t icmpMsgId, uint64_t msgType, + uint8_t* data, size_t dataLen) { return sendIcmpMessage(dev, srcMacAddr, dstMacAddr, srcIPAddr, dstIPAddr, icmpMsgId, msgType, data, dataLen, false); } diff --git a/Examples/IcmpFileTransfer/Common.h b/Examples/IcmpFileTransfer/Common.h index 2deae9f696..baf7c0d3e8 100644 --- a/Examples/IcmpFileTransfer/Common.h +++ b/Examples/IcmpFileTransfer/Common.h @@ -4,7 +4,6 @@ #include "IpAddress.h" #include "PcapLiveDevice.h" - #define ICMP_FT_WAITING_FT_START 0x345a56c8e7f3cd67ULL #define ICMP_FT_START 0xd45ae6c2e7a3cd67ULL #define ICMP_FT_WAITING_DATA 0x6d5f86c817fb5d7eULL @@ -15,17 +14,20 @@ #define ONE_MBYTE 1048576 -#define EXIT_WITH_ERROR(reason) do { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - -#define EXIT_WITH_ERROR_AND_RUN_COMMAND(reason, command) do { \ - command; \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) +#define EXIT_WITH_ERROR_AND_RUN_COMMAND(reason, command) \ + do \ + { \ + command; \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) /** * Go over all interfaces and output their names @@ -33,36 +35,28 @@ void listInterfaces(); /** - * Read and parse the command line arguments from the user. If arguments are wrong or parsing fails the method causes the program to exit + * Read and parse the command line arguments from the user. If arguments are wrong or parsing fails the method causes + * the program to exit */ -void readCommandLineArguments(int argc, char* argv[], - const std::string &thisSide, const std::string &otherSide, - bool& sender, bool& receiver, - pcpp::IPv4Address& myIP, pcpp::IPv4Address& otherSideIP, - std::string& fileNameToSend, - int& packetPerSec, size_t& blockSize); +void readCommandLineArguments(int argc, char* argv[], const std::string& thisSide, const std::string& otherSide, + bool& sender, bool& receiver, pcpp::IPv4Address& myIP, pcpp::IPv4Address& otherSideIP, + std::string& fileNameToSend, int& packetPerSec, size_t& blockSize); /** - * Send an ICMP request from source to dest with certain ICMP ID, msgType will be written in the timestamp field of the request, and data - * will be written in the data section of the request + * Send an ICMP request from source to dest with certain ICMP ID, msgType will be written in the timestamp field of the + * request, and data will be written in the data section of the request */ -bool sendIcmpRequest(pcpp::PcapLiveDevice* dev, - pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, - pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, - size_t icmpMsgId, - uint64_t msgType, - uint8_t* data, size_t dataLen); +bool sendIcmpRequest(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, + pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, size_t icmpMsgId, uint64_t msgType, + uint8_t* data, size_t dataLen); /** - * Send an ICMP reply from source to dest with certain ICMP ID, msgType will be written in the timestamp field of the request, and data - * will be written in the data section of the request + * Send an ICMP reply from source to dest with certain ICMP ID, msgType will be written in the timestamp field of the + * request, and data will be written in the data section of the request */ -bool sendIcmpResponse(pcpp::PcapLiveDevice* dev, - pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, - pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, - size_t icmpMsgId, - uint64_t msgType, - uint8_t* data, size_t dataLen); +bool sendIcmpResponse(pcpp::PcapLiveDevice* dev, pcpp::MacAddress srcMacAddr, pcpp::MacAddress dstMacAddr, + pcpp::IPv4Address srcIPAddr, pcpp::IPv4Address dstIPAddr, size_t icmpMsgId, uint64_t msgType, + uint8_t* data, size_t dataLen); /** * An auxiliary method for extracting the file name from file path, diff --git a/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp b/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp index 673bbfa6cb..a1ecd4703d 100644 --- a/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp +++ b/Examples/IcmpFileTransfer/IcmpFileTransfer-catcher.cpp @@ -18,7 +18,6 @@ #include "Common.h" #include "SystemUtils.h" - /** * A struct used for starting a file transfer, mainly sending or getting the file name */ @@ -58,10 +57,9 @@ struct IcmpFileContentDataSend char* memblock; }; - /** - * A callback used in the receiveFile() method and responsible to wait for the pitcher to send an ICMP request containing the file name - * to be received + * A callback used in the receiveFile() method and responsible to wait for the pitcher to send an ICMP request + * containing the file name to be received */ static bool waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -84,7 +82,8 @@ static bool waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveD // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpFTStart->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFTStart->catcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpFTStart->pitcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpFTStart->catcherIPAddr) return false; // check the ICMP timestamp field which contains the type of message delivered between pitcher and catcher @@ -101,26 +100,23 @@ static bool waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveD pcpp::EthLayer* ethLayer = parsedPacket.getLayerOfType(); uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); - // send the pitcher an ICMP response containing an ack message (of type ICMP_FT_ACK) so it knows the catcher has received - // the file name and it's ready to start getting the file data - if (!sendIcmpResponse(dev, - dev->getMacAddress(), ethLayer->getSourceMac(), - icmpFTStart->catcherIPAddr, icmpFTStart->pitcherIPAddr, - icmpId, ICMP_FT_ACK, - nullptr, 0)) + // send the pitcher an ICMP response containing an ack message (of type ICMP_FT_ACK) so it knows the catcher has + // received the file name and it's ready to start getting the file data + if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFTStart->catcherIPAddr, + icmpFTStart->pitcherIPAddr, icmpId, ICMP_FT_ACK, nullptr, 0)) EXIT_WITH_ERROR("Cannot send ACK message to pitcher"); - // set the current ICMP ID. It's important for the catcher to keep track of the ICMP ID to make sure it doesn't miss any message + // set the current ICMP ID. It's important for the catcher to keep track of the ICMP ID to make sure it doesn't miss + // any message icmpFTStart->icmpId = icmpId; // file name has arrived, stop receiveFile() from blocking return true; } - /** - * A callback used in the receiveFile() method and responsible to receive file data chunks arriving from the pitcher and write them to the - * local file + * A callback used in the receiveFile() method and responsible to receive file data chunks arriving from the pitcher and + * write them to the local file */ static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -143,7 +139,8 @@ static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpData->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpData->catcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpData->pitcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpData->catcherIPAddr) return false; // extract message type from the ICMP request. Message type is written in ICMP request timestamp field @@ -157,22 +154,27 @@ static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev std::cout << "."; return true; } - // if message type is not ICMP_FT_END not ICMP_FT_DATA - do nothing, it's probably an ICMP request not relevant for this file transfer + // if message type is not ICMP_FT_END not ICMP_FT_DATA - do nothing, it's probably an ICMP request not relevant for + // this file transfer else if (resMsg != ICMP_FT_DATA) return false; - // compare the ICMP ID of the request to the ICMP ID we expect to see. If it's smaller than expected it means catcher already - // saw this message so it can be ignored + // compare the ICMP ID of the request to the ICMP ID we expect to see. If it's smaller than expected it means + // catcher already saw this message so it can be ignored if (pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id) < icmpData->expectedIcmpId) return false; - // if ICMP ID is bigger than expected it probably means catcher missed one or more packets. Since a reliability mechanism isn't currently - // implemented in this program, the only thing left to do is to exit the program with an error + // if ICMP ID is bigger than expected it probably means catcher missed one or more packets. Since a reliability + // mechanism isn't currently implemented in this program, the only thing left to do is to exit the program with an + // error if (pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id) > icmpData->expectedIcmpId) { // close the file, remove it and exit the program with error icmpData->file->close(); - EXIT_WITH_ERROR_AND_RUN_COMMAND("Didn't get expected ICMP message #" << icmpData->expectedIcmpId << ", got #" << pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id), std::remove(icmpData->fileName.c_str())); + EXIT_WITH_ERROR_AND_RUN_COMMAND("Didn't get expected ICMP message #" + << icmpData->expectedIcmpId << ", got #" + << pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id), + std::remove(icmpData->fileName.c_str())); } // increment expected ICMP ID @@ -196,7 +198,6 @@ static bool getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev return false; } - /** * Receive a file from the pitcher */ @@ -218,12 +219,7 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) std::cout << "Waiting for pitcher to send a file..." << std::endl; - IcmpFileTransferStart icmpFTStart = { - pitcherIP, - catcherIP, - "", - 0 - }; + IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, "", 0 }; // wait until the pitcher sends an ICMP request with the file name in its data int res = dev->startCaptureBlockingMode(waitForFileTransferStart, &icmpFTStart, -1); @@ -231,20 +227,14 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) EXIT_WITH_ERROR("Cannot start capturing packets"); // create a new file with the name provided by the pitcher - std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out|std::ios::binary); + std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out | std::ios::binary); if (file.is_open()) { - std::cout << "Getting file from pitcher: '" << icmpFTStart.fileName << "' "; + std::cout << "Getting file from pitcher: '" << icmpFTStart.fileName << "' "; IcmpFileContentDataRecv icmpFileContentData = { - pitcherIP, - catcherIP, - &file, - icmpFTStart.fileName, - (uint16_t)(icmpFTStart.icmpId+1), - 0, - 0 + pitcherIP, catcherIP, &file, icmpFTStart.fileName, (uint16_t)(icmpFTStart.icmpId + 1), 0, 0 }; // get all file data from the pitcher. This method blocks until all file is received @@ -252,13 +242,14 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) if (!res) { file.close(); - EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", std::remove(icmpFTStart.fileName.c_str())); + EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", + std::remove(icmpFTStart.fileName.c_str())); } - std::cout << std::endl << std::endl - << "Finished getting file '" << icmpFTStart.fileName << "' " - << "[received " << icmpFileContentData.fileSize << " bytes]" - << std::endl; + std::cout << std::endl + << std::endl + << "Finished getting file '" << icmpFTStart.fileName << "' " + << "[received " << icmpFileContentData.fileSize << " bytes]" << std::endl; } else EXIT_WITH_ERROR("Cannot create file"); @@ -268,10 +259,10 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP) dev->close(); } - /** - * A callback used in the sendFile() method and responsible to wait for the pitcher to send a keep-alive ICMP request. When such message - * arrives this callback takes care of sending an ICMP response to the pitcher which is data contains the file name to send + * A callback used in the sendFile() method and responsible to wait for the pitcher to send a keep-alive ICMP request. + * When such message arrives this callback takes care of sending an ICMP response to the pitcher which is data contains + * the file name to send */ static bool startFileTransfer(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -294,11 +285,13 @@ static bool startFileTransfer(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpFTStart->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFTStart->catcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpFTStart->pitcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpFTStart->catcherIPAddr) return false; // check the ICMP timestamp field which contains the type of message delivered between pitcher and catcher - // in this case the catcher is waiting for a keep-alive message from the pitcher which is of type ICMP_FT_WAITING_FT_START + // in this case the catcher is waiting for a keep-alive message from the pitcher which is of type + // ICMP_FT_WAITING_FT_START uint64_t resMsg = icmpLayer->getEchoRequestData()->header->timestamp; if (resMsg != ICMP_FT_WAITING_FT_START) return false; @@ -308,20 +301,17 @@ static bool startFileTransfer(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* uint16_t icmpId = pcpp::netToHost16(icmpLayer->getEchoRequestData()->header->id); // send the ICMP response containing the file name back to the pitcher - if (!sendIcmpResponse(dev, - dev->getMacAddress(), ethLayer->getSourceMac(), - icmpFTStart->catcherIPAddr, icmpFTStart->pitcherIPAddr, - icmpId, ICMP_FT_START, - (uint8_t*)icmpFTStart->fileName.c_str(), icmpFTStart->fileName.length()+1)) + if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFTStart->catcherIPAddr, + icmpFTStart->pitcherIPAddr, icmpId, ICMP_FT_START, (uint8_t*)icmpFTStart->fileName.c_str(), + icmpFTStart->fileName.length() + 1)) EXIT_WITH_ERROR("Cannot send file transfer start message to pitcher"); return true; } - /** - * A callback used in the sendFile() method and responsible to wait for ICMP requests coming from the pitcher and send file data chunks as - * a reply in the ICMP response data + * A callback used in the sendFile() method and responsible to wait for ICMP requests coming from the pitcher and send + * file data chunks as a reply in the ICMP response data */ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -344,7 +334,8 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v // verify the source IP is the pitcher's IP and the dest IP is the catcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpFileContentData->pitcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFileContentData->catcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpFileContentData->pitcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpFileContentData->catcherIPAddr) return false; // check the ICMP timestamp field which contains the type of message delivered between pitcher and catcher @@ -365,12 +356,10 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v // if all file was already sent to the pitcher if (!icmpFileContentData->readingFromFile) { - // send an ICMP response with ICMP_FT_END value in the timestamp field, indicating the pitcher all file was sent to it - if (!sendIcmpResponse(dev, - dev->getMacAddress(), ethLayer->getSourceMac(), - icmpFileContentData->catcherIPAddr, icmpFileContentData->pitcherIPAddr, - icmpId, ICMP_FT_END, - nullptr, 0)) + // send an ICMP response with ICMP_FT_END value in the timestamp field, indicating the pitcher all file was sent + // to it + if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFileContentData->catcherIPAddr, + icmpFileContentData->pitcherIPAddr, icmpId, ICMP_FT_END, nullptr, 0)) EXIT_WITH_ERROR("Cannot send file transfer end message to pitcher"); // then return true so the sendFile() will stop blocking @@ -380,12 +369,11 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v // try to read another block of data from the file if (icmpFileContentData->file->read(icmpFileContentData->memblock, icmpFileContentData->blockSize)) { - // if managed to read a full block, send it via the ICMP response to the pitcher. The data chunk will be sent in the response data - if (!sendIcmpResponse(dev, - dev->getMacAddress(), ethLayer->getSourceMac(), - icmpFileContentData->catcherIPAddr, icmpFileContentData->pitcherIPAddr, - icmpId, ICMP_FT_DATA, - (uint8_t*)icmpFileContentData->memblock, icmpFileContentData->blockSize)) + // if managed to read a full block, send it via the ICMP response to the pitcher. The data chunk will be sent in + // the response data + if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFileContentData->catcherIPAddr, + icmpFileContentData->pitcherIPAddr, icmpId, ICMP_FT_DATA, + (uint8_t*)icmpFileContentData->memblock, icmpFileContentData->blockSize)) EXIT_WITH_ERROR("Cannot send file transfer data message to pitcher"); // print a dot ('.') on every 1MB sent @@ -399,12 +387,11 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v // if read only partial block, it means it's the last block else if (icmpFileContentData->file->gcount() > 0) { - // send the remaining bytes of data to the pitcher via the ICMP response. The data chunk will be sent in the response data - if (!sendIcmpResponse(dev, - dev->getMacAddress(), ethLayer->getSourceMac(), - icmpFileContentData->catcherIPAddr, icmpFileContentData->pitcherIPAddr, - icmpId, ICMP_FT_DATA, - (uint8_t*)icmpFileContentData->memblock, icmpFileContentData->file->gcount())) + // send the remaining bytes of data to the pitcher via the ICMP response. The data chunk will be sent in the + // response data + if (!sendIcmpResponse(dev, dev->getMacAddress(), ethLayer->getSourceMac(), icmpFileContentData->catcherIPAddr, + icmpFileContentData->pitcherIPAddr, icmpId, ICMP_FT_DATA, + (uint8_t*)icmpFileContentData->memblock, icmpFileContentData->file->gcount())) EXIT_WITH_ERROR("Cannot send file transfer last data message to pitcher"); // set an indication that all file was delivered to the pitcher @@ -424,11 +411,10 @@ static bool sendContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, v return false; } - /** * Send a file to the pitcher */ -void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, size_t blockSize) +void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, size_t blockSize) { // identify the interface to listen and send packets to pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(catcherIP); @@ -445,15 +431,15 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP EXIT_WITH_ERROR("Can't set ICMP filter on device"); // try the open the file for reading - std::ifstream file(filePath.c_str(), std::ios::in|std::ios::binary); + std::ifstream file(filePath.c_str(), std::ios::in | std::ios::binary); if (file.is_open()) { // extract file size file.seekg(0, std::ios_base::end); - uint32_t fileSize = file.tellg(); + uint32_t fileSize = file.tellg(); - // go back to the beginning of the file + // go back to the beginning of the file file.seekg(0, std::ios::beg); // remove the path and keep just the file name. This is the name that will be delivered to the pitcher @@ -461,32 +447,19 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP std::cout << "Waiting for pitcher to send a keep-alive signal..." << std::endl; - IcmpFileTransferStart icmpFTStart = { - pitcherIP, - catcherIP, - fileName, - 0 - }; + IcmpFileTransferStart icmpFTStart = { pitcherIP, catcherIP, fileName, 0 }; - // first, establish a connection with the pitcher and send it the file name. This method waits for the pitcher to send an ICMP - // request which indicates it's alive. The response to the request will contain the file name in the ICMP response data - int res = dev->startCaptureBlockingMode(startFileTransfer, &icmpFTStart, -1); + // first, establish a connection with the pitcher and send it the file name. This method waits for the pitcher + // to send an ICMP request which indicates it's alive. The response to the request will contain the file name in + // the ICMP response data + int res = dev->startCaptureBlockingMode(startFileTransfer, &icmpFTStart, -1); // if an error occurred if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); std::cout << "Sending file '" << fileName << "' "; - - IcmpFileContentDataSend icmpFileContentData = { - pitcherIP, - catcherIP, - &file, - true, - 0, - blockSize, - nullptr - }; + IcmpFileContentDataSend icmpFileContentData = { pitcherIP, catcherIP, &file, true, 0, blockSize, nullptr }; // create the memory block that will contain the file data chunks that will be transferred to the pitcher icmpFileContentData.memblock = new char[blockSize]; @@ -496,19 +469,19 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP res = dev->startCaptureBlockingMode(sendContent, &icmpFileContentData, -1); // free the memory block data and close the file - delete [] icmpFileContentData.memblock; + delete[] icmpFileContentData.memblock; file.close(); // if capture failed, exit the program if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); - std::cout << std::endl << std::endl - << "Finished sending '" << fileName << "' " - << "[sent " << fileSize << " bytes]" - << std::endl; + std::cout << std::endl + << std::endl + << "Finished sending '" << fileName << "' " + << "[sent " << fileSize << " bytes]" << std::endl; } - else // if file couldn't be opened + else // if file couldn't be opened EXIT_WITH_ERROR("Cannot open file '" << filePath << "'"); // close the device @@ -532,8 +505,10 @@ int main(int argc, char* argv[]) // disable stdout buffering so all std::cout command will be printed immediately setbuf(stdout, nullptr); - // read and parse command line arguments. This method also takes care of arguments correctness. If they're not correct, it'll exit the program - readCommandLineArguments(argc, argv, "catcher", "pitcher", sender, receiver, catcherIP, pitcherIP, fileNameToSend, packetsPerSec, blockSize); + // read and parse command line arguments. This method also takes care of arguments correctness. If they're not + // correct, it'll exit the program + readCommandLineArguments(argc, argv, "catcher", "pitcher", sender, receiver, catcherIP, pitcherIP, fileNameToSend, + packetsPerSec, blockSize); // send a file to the pitcher if (sender) diff --git a/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp b/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp index 82d1b5f73a..2702f3b0c0 100644 --- a/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp +++ b/Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp @@ -10,7 +10,7 @@ #include #include #ifndef _MSC_VER -#include "unistd.h" +# include "unistd.h" #endif #include "EthLayer.h" #include "IPv4Layer.h" @@ -21,21 +21,20 @@ #include "Common.h" #include "SystemUtils.h" - #define SEND_TIMEOUT_BEFORE_FT_START 3 -#define SLEEP_BETWEEN_ABORT_MESSAGES 100000 // 100 msec +#define SLEEP_BETWEEN_ABORT_MESSAGES 100000 // 100 msec #define NUM_OF_ABORT_MESSAGES_TO_SEND 5 #ifdef _MSC_VER -#include +# include void usleep(__int64 usec) { HANDLE timer; LARGE_INTEGER ft; - ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time + ft.QuadPart = -(10 * usec); // Convert to 100 nanosecond interval, negative value indicates relative time timer = CreateWaitableTimer(NULL, TRUE, NULL); SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); @@ -80,10 +79,9 @@ struct IcmpFileContentData bool fileTransferError; }; - /** - * A callback used in the receiveFile() method and responsible to wait for the catcher to send an ICMP response containing the file name - * to be received + * A callback used in the receiveFile() method and responsible to wait for the catcher to send an ICMP response + * containing the file name to be received */ static void waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -106,7 +104,8 @@ static void waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveD // verify the source IP is the catcher's IP and the dest IP is the pitcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpFTStart->catcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFTStart->pitcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpFTStart->catcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpFTStart->pitcherIPAddr) return; // extract the message type in the ICMP reply timestamp field and check if it's ICMP_FT_START @@ -125,10 +124,9 @@ static void waitForFileTransferStart(pcpp::RawPacket* rawPacket, pcpp::PcapLiveD icmpFTStart->gotFileTransferStartMsg = true; } - /** - * A callback used in the receiveFile() method and responsible to receive file data chunks arriving from the catcher and write them to the - * local file + * A callback used in the receiveFile() method and responsible to receive file data chunks arriving from the catcher and + * write them to the local file */ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -151,14 +149,16 @@ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev // verify the source IP is the catcher's IP and the dest IP is the pitcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpFileContentData->catcherIPAddr || ip4Layer->getDstIPv4Address() != icmpFileContentData->pitcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpFileContentData->catcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpFileContentData->pitcherIPAddr) return; // extract the message type from the ICMP reply timestamp field uint64_t resMsg = icmpLayer->getEchoReplyData()->header->timestamp; - // if message type is ICMP_FT_END it means all file was sent by the catcher. In that case set the icmpFileContentData->fileTransferCompleted to true - // the receiveFile() method checks that flag periodically and will stop capture packets + // if message type is ICMP_FT_END it means all file was sent by the catcher. In that case set the + // icmpFileContentData->fileTransferCompleted to true the receiveFile() method checks that flag periodically and + // will stop capture packets if (resMsg == ICMP_FT_END) { icmpFileContentData->fileTransferCompleted = true; @@ -172,15 +172,16 @@ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev // if got to here it means it's an ICMP_FT_DATA message - // verify we're not missing any message by checking the ICMP ID of the reply and compare it to the expected ICMP ID. If one or more - // message were missed, set fileTransferError flag so the main thread could abort the catcher and exit the program + // verify we're not missing any message by checking the ICMP ID of the reply and compare it to the expected ICMP ID. + // If one or more message were missed, set fileTransferError flag so the main thread could abort the catcher and + // exit the program if (pcpp::netToHost16(icmpLayer->getEchoReplyData()->header->id) != icmpFileContentData->expectedIcmpId) { icmpFileContentData->fileTransferError = true; - std::cout << std::endl << std::endl - << "Didn't get expected ICMP message #" << icmpFileContentData->expectedIcmpId - << ", got #" << pcpp::netToHost16(icmpLayer->getEchoReplyData()->header->id) - << std::endl; + std::cout << std::endl + << std::endl + << "Didn't get expected ICMP message #" << icmpFileContentData->expectedIcmpId << ", got #" + << pcpp::netToHost16(icmpLayer->getEchoReplyData()->header->id) << std::endl; return; } @@ -192,7 +193,8 @@ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev icmpFileContentData->expectedIcmpId++; // write the file data chunk in the ICMP reply data to the output file - icmpFileContentData->file->write((char*)icmpLayer->getEchoReplyData()->data, icmpLayer->getEchoReplyData()->dataLength); + icmpFileContentData->file->write((char*)icmpLayer->getEchoReplyData()->data, + icmpLayer->getEchoReplyData()->dataLength); // count the bytes received icmpFileContentData->fileSize += icmpLayer->getEchoReplyData()->dataLength; @@ -206,7 +208,6 @@ static void getFileContent(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev } } - /** * Receive a file from the catcher */ @@ -228,18 +229,14 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // discover the MAC address of the catcher by sending an ARP ping to it double arpResTO = 0; - pcpp::MacAddress catcherMacAddr = pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10); + pcpp::MacAddress catcherMacAddr = + pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10); if (catcherMacAddr == pcpp::MacAddress::Zero) EXIT_WITH_ERROR("Cannot find catcher MAC address"); uint16_t icmpId = 1; - IcmpFileTransferStartRecv icmpFTStart = { - pitcherIP, - catcherIP, - false, - "" - }; + IcmpFileTransferStartRecv icmpFTStart = { pitcherIP, catcherIP, false, "" }; std::cout << "Waiting for catcher to start sending a file..." << std::endl; @@ -250,18 +247,19 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // since it's the pitcher's job to send ICMP requests and the catcher's job to get them and send ICMP replies, // sending a file from the catcher to the pitcher is a bit more complicated - // so for start the pitcher needs the file name. It sends an ICMP request with ICMP_FT_WAITING_FT_START message in the timestamp field - // and awaits for catcher response that should include the file name + // so for start the pitcher needs the file name. It sends an ICMP request with ICMP_FT_WAITING_FT_START message in + // the timestamp field and awaits for catcher response that should include the file name - // start capturing ICMP packets. The waitForFileTransferStart callback should look for the catcher reply and set icmpFTStart.gotFileTransferStartMsg - // to true + // start capturing ICMP packets. The waitForFileTransferStart callback should look for the catcher reply and set + // icmpFTStart.gotFileTransferStartMsg to true if (!dev->startCapture(waitForFileTransferStart, &icmpFTStart)) EXIT_WITH_ERROR("Cannot start capturing packets"); // while didn't receive response from the catcher, keep sending the ICMP_FT_WAITING_FT_START message while (!icmpFTStart.gotFileTransferStartMsg) { - sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_WAITING_FT_START, nullptr, 0); + sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_WAITING_FT_START, + nullptr, 0); icmpId++; // sleep for a few seconds between sending the message pcpp::multiPlatformSleep(SEND_TIMEOUT_BEFORE_FT_START); @@ -270,51 +268,44 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // stop capturing packets dev->stopCapture(); - // create a new file with the name provided by the catcher - std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out|std::ios::binary); + std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out | std::ios::binary); if (file.is_open()) { std::cout << "Getting file from catcher: '" << icmpFTStart.fileName << "' "; - IcmpFileContentData icmpFileContentData = { - pitcherIP, - catcherIP, - &file, - icmpId, - 0, - 0, - false, - false - }; - - // the next thing to do is start getting the file data. For doing that the pitcher sends the catcher ICMP requests with message type - // ICMP_FT_WAITING_DATA in the timestamp field. The catcher should send an ICMP response for each such request with data chunk of the - // file - - // calculate how many microseconds (usec) the pitcher needs to sleep between sending the ICMP_FT_WAITING_DATA message - // (calculated from user defined packetPerSec parameter). - // The calculation is done in usec as in most cases the pitcher needs to sleep less than 1 second between chunks. However if packetPerSec - // equals to 1 it means sleeping for 1 second and in this case we can't use usleep (as it's not working for 1 sec or more) and we use - // sleep instead + IcmpFileContentData icmpFileContentData = { pitcherIP, catcherIP, &file, icmpId, 0, 0, false, false }; + + // the next thing to do is start getting the file data. For doing that the pitcher sends the catcher ICMP + // requests with message type ICMP_FT_WAITING_DATA in the timestamp field. The catcher should send an ICMP + // response for each such request with data chunk of the file + + // calculate how many microseconds (usec) the pitcher needs to sleep between sending the ICMP_FT_WAITING_DATA + // message (calculated from user defined packetPerSec parameter). The calculation is done in usec as in most + // cases the pitcher needs to sleep less than 1 second between chunks. However if packetPerSec equals to 1 it + // means sleeping for 1 second and in this case we can't use usleep (as it's not working for 1 sec or more) and + // we use sleep instead uint32_t sleepBetweenPackets = 0; if (packetPerSec > 1) sleepBetweenPackets = (uint32_t)(1000000UL / packetPerSec); - // start capturing ICMP packets. The getFileContent callback should look for the catcher replies containing data chunks of the file - // and write them to the opened file. When catcher signals the end of the file transfer, the callback will set the - // icmpFileContentData.fileTransferCompleted flag to true + // start capturing ICMP packets. The getFileContent callback should look for the catcher replies containing data + // chunks of the file and write them to the opened file. When catcher signals the end of the file transfer, the + // callback will set the icmpFileContentData.fileTransferCompleted flag to true if (!dev->startCapture(getFileContent, &icmpFileContentData)) { file.close(); - EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", std::remove(icmpFTStart.fileName.c_str())); + EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", + std::remove(icmpFTStart.fileName.c_str())); } - // keep sending ICMP requests with ICMP_FT_WAITING_DATA message in the timestamp field until all file was received or until an error occurred + // keep sending ICMP requests with ICMP_FT_WAITING_DATA message in the timestamp field until all file was + // received or until an error occurred while (!icmpFileContentData.fileTransferCompleted && !icmpFileContentData.fileTransferError) { - sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_WAITING_DATA, nullptr, 0); + sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_WAITING_DATA, + nullptr, 0); // if rate limit was set by the user, sleep between sending packets if (packetPerSec > 1) @@ -328,25 +319,27 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p // stop capturing packets dev->stopCapture(); - // if an error occurred (for example: pitcher missed some of the file content packets), send several abort message to the catcher - // so it'll stop waiting for packets, and exit the program + // if an error occurred (for example: pitcher missed some of the file content packets), send several abort + // message to the catcher so it'll stop waiting for packets, and exit the program if (icmpFileContentData.fileTransferError) { for (int i = 0; i < NUM_OF_ABORT_MESSAGES_TO_SEND; i++) { - sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_ABORT, nullptr, 0); + sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_ABORT, + nullptr, 0); usleep(SLEEP_BETWEEN_ABORT_MESSAGES); } file.close(); - EXIT_WITH_ERROR_AND_RUN_COMMAND("Sent abort message to catcher. Exiting...", std::remove(icmpFTStart.fileName.c_str())); + EXIT_WITH_ERROR_AND_RUN_COMMAND("Sent abort message to catcher. Exiting...", + std::remove(icmpFTStart.fileName.c_str())); } // file transfer was completed successfully - std::cout << std::endl << std::endl - << "Finished getting file '" << icmpFTStart.fileName << "' " - << "[received " << icmpFileContentData.fileSize << " bytes]" - << std::endl; + std::cout << std::endl + << std::endl + << "Finished getting file '" << icmpFTStart.fileName << "' " + << "[received " << icmpFileContentData.fileSize << " bytes]" << std::endl; } else EXIT_WITH_ERROR("Cannot create file"); @@ -355,10 +348,9 @@ void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int p dev->close(); } - /** - * A callback used in the sendFile() method and responsible to wait for ICMP responses coming from the catcher indicating it's alive - * and ready for file transfer to start + * A callback used in the sendFile() method and responsible to wait for ICMP responses coming from the catcher + * indicating it's alive and ready for file transfer to start */ static bool waitForFileTransferStartAck(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* dev, void* icmpVoidData) { @@ -385,7 +377,8 @@ static bool waitForFileTransferStartAck(pcpp::RawPacket* rawPacket, pcpp::PcapLi // verify the source IP is the catcher's IP and the dest IP is the pitcher's IP pcpp::IPv4Layer* ip4Layer = parsedPacket.getLayerOfType(); - if (ip4Layer->getSrcIPv4Address() != icmpData->catcherIPAddr || ip4Layer->getDstIPv4Address() != icmpData->pitcherIPAddr) + if (ip4Layer->getSrcIPv4Address() != icmpData->catcherIPAddr || + ip4Layer->getDstIPv4Address() != icmpData->pitcherIPAddr) return false; // verify the message type is ICMP_FT_ACK @@ -397,11 +390,11 @@ static bool waitForFileTransferStartAck(pcpp::RawPacket* rawPacket, pcpp::PcapLi return true; } - /** * Send a file to the catcher */ -void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, size_t blockSize, int packetPerSec) +void sendFile(const std::string& filePath, pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, size_t blockSize, + int packetPerSec) { // identify the interface to listen and send packets to pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(pitcherIP); @@ -419,7 +412,8 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // discover the MAC address of the catcher by sending an ARP ping to it double arpResTO = 0; - pcpp::MacAddress catcherMacAddr = pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10); + pcpp::MacAddress catcherMacAddr = + pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10); if (catcherMacAddr == pcpp::MacAddress::Zero) EXIT_WITH_ERROR("Cannot find catcher MAC address"); @@ -428,7 +422,7 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP memset(memblock, 0, blockSize); // try the open the file for reading - std::ifstream file(filePath.c_str(), std::ios::in|std::ios::binary); + std::ifstream file(filePath.c_str(), std::ios::in | std::ios::binary); if (file.is_open()) { @@ -443,30 +437,25 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // copy the file name to the buffer strcpy((char*)memblock, fileName.c_str()); - IcmpFileTransferStartSend ftStartData = { - icmpId, - pitcherIP, - catcherIP - }; + IcmpFileTransferStartSend ftStartData = { icmpId, pitcherIP, catcherIP }; std::cout << "Waiting for catcher..." << std::endl; - // establish connection with the catcher by sending it ICMP requests that contains the file name and wait for a response - // keep sending these requests until the catcher answers or until the program is stopped + // establish connection with the catcher by sending it ICMP requests that contains the file name and wait for a + // response keep sending these requests until the catcher answers or until the program is stopped while (1) { - // send the catcher an ICMP request that includes an special ICMP_FT_START message in the timestamp field and the filename - // in the request data. The catcher should intercept this message and send an ICMP response with an ICMP_FT_ACK message in - // the timestamp field - if (!sendIcmpRequest(dev, - pitcherMacAddr, catcherMacAddr, - pitcherIP, catcherIP, - icmpId, ICMP_FT_START, - memblock, fileName.length() + 1)) + // send the catcher an ICMP request that includes an special ICMP_FT_START message in the timestamp field + // and the filename in the request data. The catcher should intercept this message and send an ICMP response + // with an ICMP_FT_ACK message in the timestamp field + if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_START, + memblock, fileName.length() + 1)) EXIT_WITH_ERROR("Cannot send file transfer start message"); - // now wait for the catcher to answer. The timeout is SEND_TIMEOUT_BEFORE_FT_START. After that another ICMP request will be sent - int res = dev->startCaptureBlockingMode(waitForFileTransferStartAck, &ftStartData, SEND_TIMEOUT_BEFORE_FT_START); + // now wait for the catcher to answer. The timeout is SEND_TIMEOUT_BEFORE_FT_START. After that another ICMP + // request will be sent + int res = + dev->startCaptureBlockingMode(waitForFileTransferStartAck, &ftStartData, SEND_TIMEOUT_BEFORE_FT_START); if (!res) EXIT_WITH_ERROR("Cannot start capturing packets"); @@ -486,21 +475,22 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP uint32_t MBSent = 0; uint32_t sleepBetweenPackets = 0; - // calculate how many microseconds (usec) the pitcher needs to sleep between sending each file data chunk (calculated from user defined - // packetPerSec parameter). - // The calculation is done in usec as in most cases the pitcher needs to sleep less than 1 second between chunks. However if packetPerSec - // equals to 1 it means sleeping for 1 second and in this case we can't use usleep (as it's not working for 1 sec or more) and we use + // calculate how many microseconds (usec) the pitcher needs to sleep between sending each file data chunk + // (calculated from user defined packetPerSec parameter). The calculation is done in usec as in most cases the + // pitcher needs to sleep less than 1 second between chunks. However if packetPerSec equals to 1 it means + // sleeping for 1 second and in this case we can't use usleep (as it's not working for 1 sec or more) and we use // sleep instead if (packetPerSec > 1) sleepBetweenPackets = (uint32_t)(1000000UL / packetPerSec); - // read one chunk of the file and send it to catcher. This loop breaks when it is reaching the end of the file and can't read a block - // of size blockSize from the file + // read one chunk of the file and send it to catcher. This loop breaks when it is reaching the end of the file + // and can't read a block of size blockSize from the file while (file.read((char*)memblock, blockSize)) { - // send an ICMP request to the catcher containing the data chunk.The message type (set in the timestamp field) is ICMP_FT_DATA - // so the catcher knows it's a data chunk - if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_DATA, memblock, blockSize)) + // send an ICMP request to the catcher containing the data chunk.The message type (set in the timestamp + // field) is ICMP_FT_DATA so the catcher knows it's a data chunk + if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_DATA, + memblock, blockSize)) EXIT_WITH_ERROR("Cannot send file data message"); // use usleep or sleep (see comment a few lines below) @@ -522,25 +512,28 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP icmpId++; } - // after the loop above breaks there may be one more block to read (of size less than blockSize). Read it and send it to the catcher + // after the loop above breaks there may be one more block to read (of size less than blockSize). Read it and + // send it to the catcher if (file.gcount() > 0) { - if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_DATA, memblock, file.gcount())) + if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_DATA, + memblock, file.gcount())) EXIT_WITH_ERROR("Cannot send file data message"); bytesSentSoFar += file.gcount(); std::cout << "."; } - // done sending the file to the catcher, send an ICMP request with message type ICMP_FT_END (in the timestamp field) to the catcher - // to indicate all file was sent - if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_END, nullptr, 0)) + // done sending the file to the catcher, send an ICMP request with message type ICMP_FT_END (in the timestamp + // field) to the catcher to indicate all file was sent + if (!sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_END, nullptr, + 0)) EXIT_WITH_ERROR("Cannot send file transfer end message"); - std::cout << std::endl << std::endl - << "Finished sending '" << fileName << "' " - << "[sent " << bytesSentSoFar << " bytes]" - << std::endl; + std::cout << std::endl + << std::endl + << "Finished sending '" << fileName << "' " + << "[sent " << bytesSentSoFar << " bytes]" << std::endl; } else EXIT_WITH_ERROR("Cannot open file '" << filePath << "'"); @@ -548,7 +541,7 @@ void sendFile(const std::string &filePath, pcpp::IPv4Address pitcherIP, pcpp::IP // close the file and the device. Free the memory for memblock file.close(); dev->close(); - delete [] memblock; + delete[] memblock; } /** @@ -568,8 +561,10 @@ int main(int argc, char* argv[]) // disable stdout buffering so all std::cout command will be printed immediately setbuf(stdout, nullptr); - // read and parse command line arguments. This method also takes care of arguments correctness. If they're not correct, it'll exit the program - readCommandLineArguments(argc, argv, "pitcher", "catcher", sender, receiver, pitcherIP, catcherIP, fileNameToSend, packetsPerSec, blockSize); + // read and parse command line arguments. This method also takes care of arguments correctness. If they're not + // correct, it'll exit the program + readCommandLineArguments(argc, argv, "pitcher", "catcher", sender, receiver, pitcherIP, catcherIP, fileNameToSend, + packetsPerSec, blockSize); // send a file to the catcher if (sender) diff --git a/Examples/KniPong/main.cpp b/Examples/KniPong/main.cpp index c03bb187d0..919af9988e 100644 --- a/Examples/KniPong/main.cpp +++ b/Examples/KniPong/main.cpp @@ -30,12 +30,12 @@ #include #include - -#define EXIT_WITH_ERROR(reason) do { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) #define IO_BUFF_SIZE (1 << 14) #define WANT_POLLIN (-2) @@ -43,96 +43,93 @@ #define DEFAULT_KNI_NAME "pcppkni0" #define DEFAULT_PORT 62604 - namespace { -struct KniPongArgs -{ - std::string kniIp; - std::string outIp; - std::string kniName; - uint16_t kniPort; -}; - - -typedef int linuxFd; - - -struct LinuxSocket -{ - inline operator int() const { return m_Socket; } - linuxFd m_Socket; -}; - - -struct PacketStats -{ - unsigned long totalPackets; - unsigned long udpPacketsIn; - unsigned long udpPacketsOutFail; - unsigned long arpPacketsIn; - unsigned long arpPacketsOutFail; -}; - - -static bool doContinue = true; + struct KniPongArgs + { + std::string kniIp; + std::string outIp; + std::string kniName; + uint16_t kniPort; + }; + typedef int linuxFd; -/** - * Print application version - */ -void printAppVersion() -{ - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; - exit(0); -} + struct LinuxSocket + { + inline operator int() const + { + return m_Socket; + } + linuxFd m_Socket; + }; + struct PacketStats + { + unsigned long totalPackets; + unsigned long udpPacketsIn; + unsigned long udpPacketsOutFail; + unsigned long arpPacketsIn; + unsigned long arpPacketsOutFail; + }; -/** - * Print application usage - */ -inline void printUsage() -{ - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hv] [-n KNI_DEVICE_NAME] [-p PORT] -s SRC_IPV4 -d DST_IPV4" << std::endl - << std::endl - << "Options:" << std::endl - << " -s --src SRC_IPV4 : IPv4 address to assign to the created KNI device" << std::endl - << " -d --dst DST_IPV4 : Virtual IPv4 address to communicate with. Must be in /24 subnet with SRC_IPV4" << std::endl - << " -n --name KNI_DEVICE_NAME : Name for KNI device. Default: \"" << DEFAULT_KNI_NAME << "\"" << std::endl - << " -p --port PORT : Port for communication. Default: " << DEFAULT_PORT << std::endl - << " -v --version : Displays the current version and exits" << std::endl - << " -h --help : Displays this help message and exits" << std::endl - << std::endl; -} + static bool doContinue = true; + /** + * Print application version + */ + void printAppVersion() + { + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; + exit(0); + } -inline void parseArgs(int argc, char* argv[], KniPongArgs& args) -{ - struct option KniPongOptions[] = + /** + * Print application usage + */ + inline void printUsage() { - {"src", required_argument, NULL, 's'}, - {"dst", required_argument, NULL, 'd'}, - {"name", optional_argument, NULL, 'n'}, - {"port", optional_argument, NULL, 'p'}, - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'v'}, - {NULL, 0, NULL, 0} - }; - // Default port: - args.kniPort = DEFAULT_PORT; - int optionIndex = 0; - int opt = 0; - while ((opt = getopt_long(argc, argv, "s:d:n:p:hv", KniPongOptions, &optionIndex)) != -1) + std::cout << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-hv] [-n KNI_DEVICE_NAME] [-p PORT] -s SRC_IPV4 -d DST_IPV4" + << std::endl + << std::endl + << "Options:" << std::endl + << " -s --src SRC_IPV4 : IPv4 address to assign to the created KNI device" << std::endl + << " -d --dst DST_IPV4 : Virtual IPv4 address to communicate with. Must be in /24 " + "subnet with SRC_IPV4" + << std::endl + << " -n --name KNI_DEVICE_NAME : Name for KNI device. Default: \"" << DEFAULT_KNI_NAME << "\"" + << std::endl + << " -p --port PORT : Port for communication. Default: " << DEFAULT_PORT << std::endl + << " -v --version : Displays the current version and exits" << std::endl + << " -h --help : Displays this help message and exits" << std::endl + << std::endl; + } + + inline void parseArgs(int argc, char* argv[], KniPongArgs& args) { - switch (opt) + struct option KniPongOptions[] = { + { "src", required_argument, NULL, 's' }, + { "dst", required_argument, NULL, 'd' }, + { "name", optional_argument, NULL, 'n' }, + { "port", optional_argument, NULL, 'p' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } + }; + // Default port: + args.kniPort = DEFAULT_PORT; + int optionIndex = 0; + int opt = 0; + while ((opt = getopt_long(argc, argv, "s:d:n:p:hv", KniPongOptions, &optionIndex)) != -1) { + switch (opt) + { case 0: break; case 's': @@ -154,575 +151,578 @@ inline void parseArgs(int argc, char* argv[], KniPongArgs& args) { printUsage(); std::exit(0); - } break; + } + break; default: { printUsage(); exit(1); - } break; + } + break; + } + } + // Default name for KNI device: + if (args.kniName.empty()) + args.kniName = DEFAULT_KNI_NAME; + if (args.kniIp.empty()) + { + printUsage(); + EXIT_WITH_ERROR("IP for KNI device not provided"); + } + if (args.outIp.empty()) + { + printUsage(); + EXIT_WITH_ERROR("Virtual IP for communication not provided"); } - } - // Default name for KNI device: - if (args.kniName.empty()) - args.kniName = DEFAULT_KNI_NAME; - if (args.kniIp.empty()) - { - printUsage(); - EXIT_WITH_ERROR("IP for KNI device not provided"); - } - if (args.outIp.empty()) - { - printUsage(); - EXIT_WITH_ERROR("Virtual IP for communication not provided"); - } - pcpp::IPv4Address kniIp; - pcpp::IPv4Address outIp; - try - { - kniIp = pcpp::IPv4Address(args.kniIp); - } - catch (const std::exception&) - { - EXIT_WITH_ERROR("Cannot assign an invalid IPv4 address to the KNI device"); - } - try - { - outIp = pcpp::IPv4Address(args.outIp); - } - catch (const std::exception&) - { - EXIT_WITH_ERROR("Cannot assign an invalid IPv4 address as the virtual address"); - } + pcpp::IPv4Address kniIp; + pcpp::IPv4Address outIp; + try + { + kniIp = pcpp::IPv4Address(args.kniIp); + } + catch (const std::exception&) + { + EXIT_WITH_ERROR("Cannot assign an invalid IPv4 address to the KNI device"); + } + try + { + outIp = pcpp::IPv4Address(args.outIp); + } + catch (const std::exception&) + { + EXIT_WITH_ERROR("Cannot assign an invalid IPv4 address as the virtual address"); + } - if (!outIp.matchNetwork(pcpp::IPv4Network(kniIp, "255.255.255.0"))) - { - EXIT_WITH_ERROR("Provided Virtual IP '" << outIp << "' is not in same required subnet '255.255.255.0' as KNI IP '" << kniIp << "'"); + if (!outIp.matchNetwork(pcpp::IPv4Network(kniIp, "255.255.255.0"))) + { + EXIT_WITH_ERROR("Provided Virtual IP '" + << outIp << "' is not in same required subnet '255.255.255.0' as KNI IP '" << kniIp << "'"); + } } -} + /** + * Simple dummy callbacks that always yields success for Linux Kernel + */ + struct KniDummyCallbacks + { + static int changeMtuNew(uint16_t, unsigned int) + { + return 0; + } + static int changeMtuOld(uint8_t, unsigned int) + { + return 0; + } + static int configNetworkIfNew(uint16_t, uint8_t) + { + return 0; + } + static int configNetworkIfOld(uint8_t, uint8_t) + { + return 0; + } + static int configMacAddress(uint16_t, uint8_t[]) + { + return 0; + } + static int configPromiscusity(uint16_t, uint8_t) + { + return 0; + } -/** - * Simple dummy callbacks that always yields success for Linux Kernel - */ -struct KniDummyCallbacks -{ - static int changeMtuNew(uint16_t, unsigned int) { return 0; } - static int changeMtuOld(uint8_t, unsigned int) { return 0; } - static int configNetworkIfNew(uint16_t, uint8_t) { return 0; } - static int configNetworkIfOld(uint8_t, uint8_t) { return 0; } - static int configMacAddress(uint16_t, uint8_t[]) { return 0; } - static int configPromiscusity(uint16_t, uint8_t) { return 0; } + static pcpp::KniDevice::KniIoctlCallbacks cbNew; + static pcpp::KniDevice::KniOldIoctlCallbacks cbOld; - static pcpp::KniDevice::KniIoctlCallbacks cbNew; - static pcpp::KniDevice::KniOldIoctlCallbacks cbOld; + static void setCallbacks() + { + cbNew.change_mtu = changeMtuNew; + cbNew.config_network_if = configNetworkIfNew; + cbNew.config_mac_address = configMacAddress; + cbNew.config_promiscusity = configPromiscusity; + cbOld.change_mtu = changeMtuOld; + cbOld.config_network_if = configNetworkIfOld; + } + }; + pcpp::KniDevice::KniIoctlCallbacks KniDummyCallbacks::cbNew; + pcpp::KniDevice::KniOldIoctlCallbacks KniDummyCallbacks::cbOld; - static void setCallbacks() + /** + * Setup IP of net device by calling the ip unix utility + */ + inline bool setKniIp(const pcpp::IPv4Address& ip, const std::string& kniName) { - cbNew.change_mtu = changeMtuNew; - cbNew.config_network_if = configNetworkIfNew; - cbNew.config_mac_address = configMacAddress; - cbNew.config_promiscusity = configPromiscusity; - cbOld.change_mtu = changeMtuOld; - cbOld.config_network_if = configNetworkIfOld; + std::ostringstream command; + command << "ip a add " << ip << "/24 dev " << kniName; + pcpp::executeShellCommand(command.str()); + command.str(""); + command << "ip a | grep " << ip; + try + { + std::string result = pcpp::executeShellCommand(command.str()); + return result != ""; + } + catch (const std::runtime_error&) + { + return false; + } } -}; -pcpp::KniDevice::KniIoctlCallbacks KniDummyCallbacks::cbNew; -pcpp::KniDevice::KniOldIoctlCallbacks KniDummyCallbacks::cbOld; - -/** - * Setup IP of net device by calling the ip unix utility - */ -inline bool setKniIp(const pcpp::IPv4Address& ip, const std::string& kniName) -{ - std::ostringstream command; - command << "ip a add " << ip << "/24 dev " << kniName; - pcpp::executeShellCommand(command.str()); - command.str(""); - command << "ip a | grep " << ip; - try - { - std::string result = pcpp::executeShellCommand(command.str()); - return result != ""; - } - catch (const std::runtime_error&) + /** + * KNI device setup routine + */ + inline pcpp::KniDevice* setupKniDevice(const KniPongArgs& args) { - return false; + { + // Setup DPDK + pcpp::CoreMask cm = 0x3; + bool dpdkInitSuccess = pcpp::DpdkDeviceList::initDpdk(cm, 1023); + if (!dpdkInitSuccess) + EXIT_WITH_ERROR("Failed to init DPDK"); + } + pcpp::IPv4Address kniIp = args.kniIp; + // Setup device config + pcpp::KniDevice* device = NULL; + pcpp::KniDevice::KniDeviceConfiguration devConfig; + devConfig.name = args.kniName; + KniDummyCallbacks::setCallbacks(); + if (pcpp::KniDeviceList::callbackVersion() == pcpp::KniDeviceList::CALLBACKS_NEW) + { + devConfig.callbacks = &KniDummyCallbacks::cbNew; + } + else + { + devConfig.oldCallbacks = &KniDummyCallbacks::cbOld; + } + devConfig.bindKthread = false; + pcpp::KniDeviceList& kniDeviceList = pcpp::KniDeviceList::getInstance(); + if (!kniDeviceList.isInitialized()) + EXIT_WITH_ERROR("Can't initialize KNI device list"); + device = kniDeviceList.createDevice(devConfig, 1024); + if (device == NULL) + EXIT_WITH_ERROR("Can't create KNI device"); + // Check KNI device and start request thread + if (!device->isInitialized()) + EXIT_WITH_ERROR("KNI device was not initialized correctly"); + if (!device->open()) + EXIT_WITH_ERROR("Could not open KNI device"); + if (!device->startRequestHandlerThread(0, 500000000)) + EXIT_WITH_ERROR("Could not start KNI device request handler thread"); + // Assign IP + if (!setKniIp(kniIp, args.kniName)) + EXIT_WITH_ERROR("Can't set KNI device IP"); + // Turn device on for Linux Kernel + if (!device->setLinkState(pcpp::KniDevice::LINK_UP)) + EXIT_WITH_ERROR("Can't set KNI device link state to UP"); + return device; } -} + /** + * Open UDP socket for communication with KNI device + */ + inline LinuxSocket setupLinuxSocket(const KniPongArgs& args) + { // Open socket + enum + { + INVALID_FD = -1 + }; + LinuxSocket sock; + if ((sock.m_Socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_FD) + { + int old_errno = errno; + EXIT_WITH_ERROR("Could not open socket" << std::endl << "Errno: " << std::strerror(old_errno)); + } + // Bind socket to KNI device IP + struct sockaddr_in egress; + std::memset(&egress, 0, sizeof(egress)); + egress.sin_family = AF_INET; + egress.sin_addr.s_addr = inet_addr(args.kniIp.c_str()); + egress.sin_port = pcpp::hostToNet16(args.kniPort); + if (bind(sock, (struct sockaddr*)&egress, sizeof(egress)) == -1) + { + int old_errno = errno; + close(sock); + EXIT_WITH_ERROR("Could not bind socket" << std::endl << "Errno: " << std::strerror(old_errno)); + } -/** - * KNI device setup routine - */ -inline pcpp::KniDevice* setupKniDevice(const KniPongArgs& args) -{ - { - // Setup DPDK - pcpp::CoreMask cm = 0x3; - bool dpdkInitSuccess = pcpp::DpdkDeviceList::initDpdk(cm, 1023); - if (!dpdkInitSuccess) - EXIT_WITH_ERROR("Failed to init DPDK"); + return sock; } - pcpp::IPv4Address kniIp = args.kniIp; - // Setup device config - pcpp::KniDevice* device = NULL; - pcpp::KniDevice::KniDeviceConfiguration devConfig; - devConfig.name = args.kniName; - KniDummyCallbacks::setCallbacks(); - if (pcpp::KniDeviceList::callbackVersion() == pcpp::KniDeviceList::CALLBACKS_NEW) - { - devConfig.callbacks = &KniDummyCallbacks::cbNew; - } - else - { - devConfig.oldCallbacks = &KniDummyCallbacks::cbOld; - } - devConfig.bindKthread = false; - pcpp::KniDeviceList& kniDeviceList = pcpp::KniDeviceList::getInstance(); - if (!kniDeviceList.isInitialized()) - EXIT_WITH_ERROR("Can't initialize KNI device list"); - device = kniDeviceList.createDevice(devConfig, 1024); - if (device == NULL) - EXIT_WITH_ERROR("Can't create KNI device"); - // Check KNI device and start request thread - if (!device->isInitialized()) - EXIT_WITH_ERROR("KNI device was not initialized correctly"); - if (!device->open()) - EXIT_WITH_ERROR("Could not open KNI device"); - if (!device->startRequestHandlerThread(0, 500000000)) - EXIT_WITH_ERROR("Could not start KNI device request handler thread"); - // Assign IP - if (!setKniIp(kniIp, args.kniName)) - EXIT_WITH_ERROR("Can't set KNI device IP"); - // Turn device on for Linux Kernel - if (!device->setLinkState(pcpp::KniDevice::LINK_UP)) - EXIT_WITH_ERROR("Can't set KNI device link state to UP"); - return device; -} - -/** - * Open UDP socket for communication with KNI device - */ -inline LinuxSocket setupLinuxSocket(const KniPongArgs& args) -{ // Open socket - enum { INVALID_FD = -1 }; - LinuxSocket sock; - if ((sock.m_Socket = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_FD) + /** + * Handle all ARP requests on KNI interface: map all IPs to same MAC + */ + inline void processArp(pcpp::Packet& packet, pcpp::ArpLayer* arpLayer) { - int old_errno = errno; - EXIT_WITH_ERROR("Could not open socket" << std::endl << "Errno: " << std::strerror(old_errno)); + pcpp::MacAddress rndMac("00:42:43:74:11:54"); + pcpp::EthLayer* ethernetLayer = NULL; + pcpp::arphdr arpHdr; + pcpp::arphdr* origArpHdr = arpLayer->getArpHeader(); + // Copy ARP request + std::memcpy(&arpHdr, origArpHdr, sizeof(arpHdr)); + // Fill fields + arpHdr.hardwareType = pcpp::hostToNet16(0x0001); // ETHERNET + arpHdr.hardwareSize = sizeof(((pcpp::arphdr*)0)->senderMacAddr); // sizeof(MAC) + arpHdr.protocolSize = sizeof(((pcpp::arphdr*)0)->senderIpAddr); // sizeof(IPv4) + arpHdr.opcode = pcpp::hostToNet16(pcpp::ARP_REPLY); + std::memcpy(arpHdr.targetMacAddr, origArpHdr->senderMacAddr, sizeof(((pcpp::arphdr*)0)->senderMacAddr)); + std::memcpy(&arpHdr.targetIpAddr, &origArpHdr->senderIpAddr, sizeof(((pcpp::arphdr*)0)->senderIpAddr)); + std::memcpy(&arpHdr.senderIpAddr, &origArpHdr->targetIpAddr, sizeof(((pcpp::arphdr*)0)->senderIpAddr)); + // Set rnd MAC in response + rndMac.copyTo(arpHdr.senderMacAddr); + // Copy ready ARP response to packet + std::memcpy(origArpHdr, &arpHdr, sizeof(arpHdr)); + + // Setup Ethernet addresses in Ethernet layer + ethernetLayer = packet.getLayerOfType(); + pcpp::ether_header ethHdr; + pcpp::ether_header* origEthHdr = ethernetLayer->getEthHeader(); + std::memcpy(ðHdr, origEthHdr, sizeof(ethHdr)); + std::memcpy(ethHdr.dstMac, origEthHdr->srcMac, sizeof(ethHdr.dstMac)); + rndMac.copyTo(ethHdr.srcMac); + // Copy ready Ethernet layer to packet + std::memcpy(origEthHdr, ðHdr, sizeof(ethHdr)); } - // Bind socket to KNI device IP - struct sockaddr_in egress; - std::memset(&egress, 0, sizeof(egress)); - egress.sin_family = AF_INET; - egress.sin_addr.s_addr = inet_addr(args.kniIp.c_str()); - egress.sin_port = pcpp::hostToNet16(args.kniPort); - if (bind(sock, (struct sockaddr*)&egress, sizeof(egress)) == -1) + + /** + * Handle all UDP packets as a packet carying 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) { - int old_errno = errno; - close(sock); - EXIT_WITH_ERROR("Could not bind socket" << std::endl << "Errno: " << std::strerror(old_errno)); + pcpp::EthLayer* ethernetLayer = NULL; + pcpp::IPv4Layer* ipLayer = NULL; + + ethernetLayer = packet.getLayerOfType(); + pcpp::ether_header ethHdr; + pcpp::ether_header* origEthHdr = ethernetLayer->getEthHeader(); + std::memcpy(ðHdr, origEthHdr, sizeof(ethHdr)); + // Swap MACs for Ethernet layer + std::memcpy(ethHdr.dstMac, origEthHdr->srcMac, sizeof(ethHdr.dstMac)); + std::memcpy(ethHdr.srcMac, origEthHdr->dstMac, sizeof(ethHdr.srcMac)); + std::memcpy(origEthHdr, ðHdr, sizeof(ethHdr)); + + ipLayer = packet.getLayerOfType(); + if (ipLayer == NULL) // Some invalid packet + return false; + pcpp::iphdr ipHdr; + pcpp::iphdr* origIpHdr = ipLayer->getIPv4Header(); + std::memcpy(&ipHdr, origIpHdr, sizeof(ipHdr)); + if (pcpp::netToHost16(ipHdr.fragmentOffset) & 0x1FFF) // Fragmented packet + return false; + // Swap src and dst IPs + std::memcpy(&ipHdr.ipSrc, &origIpHdr->ipDst, sizeof(ipHdr.ipSrc)); + std::memcpy(&ipHdr.ipDst, &origIpHdr->ipSrc, sizeof(ipHdr.ipDst)); + // Randomize IP id + ipHdr.ipId = std::rand() & 0xFFFF; + // Set by RFC791 + ipHdr.timeToLive = 64; + std::memcpy(origIpHdr, &ipHdr, sizeof(ipHdr)); + + pcpp::udphdr udpHdr; + pcpp::udphdr* origUdpHdr = udpLayer->getUdpHeader(); + std::memcpy(&udpHdr, origUdpHdr, sizeof(udpHdr)); + // Swap src and dst ports + std::memcpy(&udpHdr.portSrc, &origUdpHdr->portDst, sizeof(udpHdr.portSrc)); + std::memcpy(&udpHdr.portDst, &origUdpHdr->portSrc, sizeof(udpHdr.portDst)); + std::memcpy(origUdpHdr, &udpHdr, sizeof(udpHdr)); + + // Calculate checksums of IP and UDP layers + packet.computeCalculateFields(); + // Packet is ready to be sent + return true; } - return sock; -} - - -/** - * Handle all ARP requests on KNI interface: map all IPs to same MAC - */ -inline void processArp(pcpp::Packet& packet, pcpp::ArpLayer* arpLayer) -{ - pcpp::MacAddress rndMac("00:42:43:74:11:54"); - pcpp::EthLayer* ethernetLayer = NULL; - pcpp::arphdr arpHdr; - pcpp::arphdr* origArpHdr = arpLayer->getArpHeader(); - // Copy ARP request - std::memcpy(&arpHdr, origArpHdr, sizeof(arpHdr)); - // Fill fields - arpHdr.hardwareType = pcpp::hostToNet16(0x0001); // ETHERNET - arpHdr.hardwareSize = sizeof(((pcpp::arphdr*)0)->senderMacAddr); // sizeof(MAC) - arpHdr.protocolSize = sizeof(((pcpp::arphdr*)0)->senderIpAddr); // sizeof(IPv4) - arpHdr.opcode = pcpp::hostToNet16(pcpp::ARP_REPLY); - std::memcpy(arpHdr.targetMacAddr, origArpHdr->senderMacAddr, sizeof(((pcpp::arphdr*)0)->senderMacAddr)); - std::memcpy(&arpHdr.targetIpAddr, &origArpHdr->senderIpAddr, sizeof(((pcpp::arphdr*)0)->senderIpAddr)); - std::memcpy(&arpHdr.senderIpAddr, &origArpHdr->targetIpAddr, sizeof(((pcpp::arphdr*)0)->senderIpAddr)); - // Set rnd MAC in response - rndMac.copyTo(arpHdr.senderMacAddr); - // Copy ready ARP response to packet - std::memcpy(origArpHdr, &arpHdr, sizeof(arpHdr)); - - // Setup Ethernet addresses in Ethernet layer - ethernetLayer = packet.getLayerOfType(); - pcpp::ether_header ethHdr; - pcpp::ether_header* origEthHdr = ethernetLayer->getEthHeader(); - std::memcpy(ðHdr, origEthHdr, sizeof(ethHdr)); - std::memcpy(ethHdr.dstMac, origEthHdr->srcMac, sizeof(ethHdr.dstMac)); - rndMac.copyTo(ethHdr.srcMac); - // Copy ready Ethernet layer to packet - std::memcpy(origEthHdr, ðHdr, sizeof(ethHdr)); -} + /** + * Process burst of packets + */ + bool processBurst(pcpp::MBufRawPacket packets[], uint32_t numOfPackets, pcpp::KniDevice* kni, void* cookie) + { + PacketStats* packetStats = (PacketStats*)cookie; + pcpp::Packet packet; + pcpp::ArpLayer* arpLayer = NULL; + pcpp::UdpLayer* udpLayer = NULL; + packetStats->totalPackets += numOfPackets; + for (uint32_t i = 0; i < numOfPackets; ++i) + { + packet.setRawPacket(packets + i, false); + if ((arpLayer = packet.getLayerOfType()) != NULL) + { + ++packetStats->arpPacketsIn; + processArp(packet, arpLayer); + // Packet is ready to be sent -> have no fields to recalculate + if (!kni->sendPacket(packet)) + ++packetStats->arpPacketsOutFail; + arpLayer = NULL; + continue; + } -/** - * Handle all UDP packets as a packet carying 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) -{ - pcpp::EthLayer* ethernetLayer = NULL; - pcpp::IPv4Layer* ipLayer = NULL; - - ethernetLayer = packet.getLayerOfType(); - pcpp::ether_header ethHdr; - pcpp::ether_header* origEthHdr = ethernetLayer->getEthHeader(); - std::memcpy(ðHdr, origEthHdr, sizeof(ethHdr)); - // Swap MACs for Ethernet layer - std::memcpy(ethHdr.dstMac, origEthHdr->srcMac, sizeof(ethHdr.dstMac)); - std::memcpy(ethHdr.srcMac, origEthHdr->dstMac, sizeof(ethHdr.srcMac)); - std::memcpy(origEthHdr, ðHdr, sizeof(ethHdr)); - - ipLayer = packet.getLayerOfType(); - if (ipLayer == NULL) // Some invalid packet - return false; - pcpp::iphdr ipHdr; - pcpp::iphdr* origIpHdr = ipLayer->getIPv4Header(); - std::memcpy(&ipHdr, origIpHdr, sizeof(ipHdr)); - if (pcpp::netToHost16(ipHdr.fragmentOffset) & 0x1FFF) // Fragmented packet - return false; - // Swap src and dst IPs - std::memcpy(&ipHdr.ipSrc, &origIpHdr->ipDst, sizeof(ipHdr.ipSrc)); - std::memcpy(&ipHdr.ipDst, &origIpHdr->ipSrc, sizeof(ipHdr.ipDst)); - // Randomize IP id - ipHdr.ipId = std::rand() & 0xFFFF; - // Set by RFC791 - ipHdr.timeToLive = 64; - std::memcpy(origIpHdr, &ipHdr, sizeof(ipHdr)); - - pcpp::udphdr udpHdr; - pcpp::udphdr* origUdpHdr = udpLayer->getUdpHeader(); - std::memcpy(&udpHdr, origUdpHdr, sizeof(udpHdr)); - // Swap src and dst ports - std::memcpy(&udpHdr.portSrc, &origUdpHdr->portDst, sizeof(udpHdr.portSrc)); - std::memcpy(&udpHdr.portDst, &origUdpHdr->portSrc, sizeof(udpHdr.portDst)); - std::memcpy(origUdpHdr, &udpHdr, sizeof(udpHdr)); - - // Calculate checksums of IP and UDP layers - packet.computeCalculateFields(); - // Packet is ready to be sent - return true; -} + if ((udpLayer = packet.getLayerOfType()) != NULL) + { + ++packetStats->udpPacketsIn; + //! Warning (echo-Mike): DO NOT normalize next logic statement it relays on short circuiting + if (!processUdp(packet, udpLayer) || !kni->sendPacket(packet)) + ++packetStats->udpPacketsOutFail; + udpLayer = NULL; + continue; + } + // Other packets are just ignored + } -/** - * Process burst of packets - */ -bool processBurst(pcpp::MBufRawPacket packets[], uint32_t numOfPackets, pcpp::KniDevice* kni, void* cookie) -{ - PacketStats* packetStats = (PacketStats*)cookie; - pcpp::Packet packet; - pcpp::ArpLayer* arpLayer = NULL; - pcpp::UdpLayer* udpLayer = NULL; + return true; + } - packetStats->totalPackets += numOfPackets; - for (uint32_t i = 0; i < numOfPackets; ++i) + /** + * Connect UDP socket to other IP:port pair derived from our args + */ + void connectUDPSocket(const LinuxSocket& sock, const KniPongArgs& args) { - packet.setRawPacket(packets + i, false); - if ((arpLayer = packet.getLayerOfType()) != NULL) + struct sockaddr_in ingress; + std::memset(&ingress, 0, sizeof(ingress)); + ingress.sin_family = AF_INET; + ingress.sin_addr.s_addr = inet_addr(args.outIp.c_str()); + ingress.sin_port = pcpp::hostToNet16(args.kniPort); + if (connect(sock, (struct sockaddr*)&ingress, sizeof(ingress)) == -1) { - ++packetStats->arpPacketsIn; - processArp(packet, arpLayer); - // Packet is ready to be sent -> have no fields to recalculate - if (!kni->sendPacket(packet)) - ++packetStats->arpPacketsOutFail; - arpLayer = NULL; - continue; - } - - if ((udpLayer = packet.getLayerOfType()) != NULL) - { - ++packetStats->udpPacketsIn; - //! Warning (echo-Mike): DO NOT normalize next logic statement it relays on short circuiting - if (!processUdp(packet, udpLayer) || !kni->sendPacket(packet)) - ++packetStats->udpPacketsOutFail; - udpLayer = NULL; - continue; + int old_errno = errno; + close(sock); + EXIT_WITH_ERROR("Could not connect socket" << std::endl << "Errno: " << std::strerror(old_errno)); } - - // Other packets are just ignored } - return true; -} - - -/** - * Connect UDP socket to other IP:port pair derived from our args - */ -void connectUDPSocket(const LinuxSocket& sock, const KniPongArgs& args) -{ - struct sockaddr_in ingress; - std::memset(&ingress, 0, sizeof(ingress)); - ingress.sin_family = AF_INET; - ingress.sin_addr.s_addr = inet_addr(args.outIp.c_str()); - ingress.sin_port = pcpp::hostToNet16(args.kniPort); - if (connect(sock, (struct sockaddr*)&ingress, sizeof(ingress)) == -1) + /** + * Reworked fillbuf from netcat. See description in pingPongProcess + */ + ssize_t fillbuf(linuxFd fd, unsigned char buff[], size_t& buffPos) { - int old_errno = errno; - close(sock); - EXIT_WITH_ERROR("Could not connect socket" << std::endl << "Errno: " << std::strerror(old_errno)); - } -} - - -/** - * Reworked fillbuf from netcat. See description in pingPongProcess - */ -ssize_t fillbuf(linuxFd fd, unsigned char buff[], size_t& buffPos) -{ - size_t num = IO_BUFF_SIZE - buffPos; - ssize_t n; - - n = read(fd, buff + buffPos, num); - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - n = WANT_POLLIN; - if (n <= 0) + size_t num = IO_BUFF_SIZE - buffPos; + ssize_t n; + + n = read(fd, buff + buffPos, num); + if (n == -1 && (errno == EAGAIN || errno == EINTR)) + n = WANT_POLLIN; + if (n <= 0) + return n; + buffPos += n; return n; - buffPos += n; - return n; -} - - -/** - * Reworked drainbuf from netcat. See description in pingPongProcess - */ -ssize_t drainbuf(linuxFd fd, unsigned char buff[], size_t& buffPos) -{ - ssize_t n; - ssize_t adjust; + } - n = write(fd, buff, buffPos); - if (n == -1 && (errno == EAGAIN || errno == EINTR)) - n = WANT_POLLOUT; - if (n <= 0) + /** + * Reworked drainbuf from netcat. See description in pingPongProcess + */ + ssize_t drainbuf(linuxFd fd, unsigned char buff[], size_t& buffPos) + { + ssize_t n; + ssize_t adjust; + + n = write(fd, buff, buffPos); + if (n == -1 && (errno == EAGAIN || errno == EINTR)) + n = WANT_POLLOUT; + if (n <= 0) + return n; + /* adjust buffer */ + adjust = buffPos - n; + if (adjust > 0) + std::memmove(buff, buff + n, adjust); + buffPos -= n; return n; - /* adjust buffer */ - adjust = buffPos - n; - if (adjust > 0) - std::memmove(buff, buff + n, adjust); - buffPos -= n; - return n; -} - - -/** - * Reworked readwrite from netcat. - * - * Note (echo-Mike): This function and fillbuf/drainbuf - * are analogous to code of NETCAT utility (OpenBSD version) - * Authors of original codebase: - * - Eric Jackson - * - Bob Beck - * - *Hobbit* - * See: http://man7.org/linux/man-pages/man1/ncat.1.html - */ -void pingPongProcess(const LinuxSocket& sock) -{ + } - struct pollfd pfd[4]; - const int POLL_STDIN = 0, POLL_NETOUT = 1, POLL_NETIN = 2, POLL_STDOUT = 3; - const int DEFAULT_POLL_TIMEOUT = 3000;//milisec - unsigned char netbuff[IO_BUFF_SIZE]; - size_t netbuffPos = 0; - unsigned char ttybuff[IO_BUFF_SIZE]; - size_t ttybuffPos = 0; - int n; - ssize_t ret; - - /* stdin */ - pfd[POLL_STDIN].fd = STDIN_FILENO; - pfd[POLL_STDIN].events = POLLIN; - /* network out */ - pfd[POLL_NETOUT].fd = sock; - pfd[POLL_NETOUT].events = 0; - /* network in */ - pfd[POLL_NETIN].fd = sock; - pfd[POLL_NETIN].events = POLLIN; - /* stdout */ - pfd[POLL_STDOUT].fd = STDOUT_FILENO; - pfd[POLL_STDOUT].events = 0; - - while (doContinue) + /** + * Reworked readwrite from netcat. + * + * Note (echo-Mike): This function and fillbuf/drainbuf + * are analogous to code of NETCAT utility (OpenBSD version) + * Authors of original codebase: + * - Eric Jackson + * - Bob Beck + * - *Hobbit* + * See: http://man7.org/linux/man-pages/man1/ncat.1.html + */ + void pingPongProcess(const LinuxSocket& sock) { - /* both inputs are gone, buffers are empty, we are done */ - if (pfd[POLL_STDIN].fd == -1 && - pfd[POLL_NETIN].fd == -1 && - ttybuffPos == 0 && - netbuffPos == 0 - ) - { - return; - } - /* both outputs are gone, we can't continue */ - if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) - return; - - /* poll */ - int num_fds = poll(pfd, 4, DEFAULT_POLL_TIMEOUT); - /* treat poll errors */ - if (num_fds == -1) + struct pollfd pfd[4]; + const int POLL_STDIN = 0, POLL_NETOUT = 1, POLL_NETIN = 2, POLL_STDOUT = 3; + const int DEFAULT_POLL_TIMEOUT = 3000; // milisec + unsigned char netbuff[IO_BUFF_SIZE]; + size_t netbuffPos = 0; + unsigned char ttybuff[IO_BUFF_SIZE]; + size_t ttybuffPos = 0; + int n; + ssize_t ret; + + /* stdin */ + pfd[POLL_STDIN].fd = STDIN_FILENO; + pfd[POLL_STDIN].events = POLLIN; + /* network out */ + pfd[POLL_NETOUT].fd = sock; + pfd[POLL_NETOUT].events = 0; + /* network in */ + pfd[POLL_NETIN].fd = sock; + pfd[POLL_NETIN].events = POLLIN; + /* stdout */ + pfd[POLL_STDOUT].fd = STDOUT_FILENO; + pfd[POLL_STDOUT].events = 0; + + while (doContinue) { - int old_errno = errno; - if (old_errno != EINTR) + /* both inputs are gone, buffers are empty, we are done */ + if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 && ttybuffPos == 0 && netbuffPos == 0) { - close(sock); - EXIT_WITH_ERROR("poll returned an error" << std::endl << "Errno: " << std::strerror(old_errno)); + return; } - continue; - } + /* both outputs are gone, we can't continue */ + if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) + return; - if (num_fds == 0) - { - continue; - } + /* poll */ + int num_fds = poll(pfd, 4, DEFAULT_POLL_TIMEOUT); - /* treat socket error conditions */ - for (n = 0; n < 4; ++n) - { - if (pfd[n].revents & (POLLERR|POLLNVAL)) + /* treat poll errors */ + if (num_fds == -1) { - pfd[n].fd = -1; + int old_errno = errno; + if (old_errno != EINTR) + { + close(sock); + EXIT_WITH_ERROR("poll returned an error" << std::endl << "Errno: " << std::strerror(old_errno)); + } + continue; } - } - /* reading is possible after HUP */ - if (pfd[POLL_STDIN].events & POLLIN && - pfd[POLL_STDIN].revents & POLLHUP && - !(pfd[POLL_STDIN].revents & POLLIN) - ) - { - pfd[POLL_STDIN].fd = -1; - } - if (pfd[POLL_NETIN].events & POLLIN && - pfd[POLL_NETIN].revents & POLLHUP && - !(pfd[POLL_NETIN].revents & POLLIN) - ) - { - pfd[POLL_NETIN].fd = -1; - } - - if (pfd[POLL_NETOUT].revents & POLLHUP) - { - pfd[POLL_NETOUT].fd = -1; - } - /* if HUP, stop watching stdout */ - if (pfd[POLL_STDOUT].revents & POLLHUP) - pfd[POLL_STDOUT].fd = -1; - /* if no net out, stop watching stdin */ - if (pfd[POLL_NETOUT].fd == -1) - pfd[POLL_STDIN].fd = -1; - /* if no stdout, stop watching net in */ - if (pfd[POLL_STDOUT].fd == -1) - { - if (pfd[POLL_NETIN].fd != -1) - shutdown(pfd[POLL_NETIN].fd, SHUT_RD); - pfd[POLL_NETIN].fd = -1; - } + if (num_fds == 0) + { + continue; + } - /* try to read from stdin */ - if (pfd[POLL_STDIN].revents & POLLIN && ttybuffPos < IO_BUFF_SIZE) - { - ret = fillbuf(pfd[POLL_STDIN].fd, ttybuff, ttybuffPos); - if (ret == WANT_POLLIN) - pfd[POLL_STDIN].events = POLLIN; - else if (ret == 0 || ret == -1) + /* treat socket error conditions */ + for (n = 0; n < 4; ++n) + { + if (pfd[n].revents & (POLLERR | POLLNVAL)) + { + pfd[n].fd = -1; + } + } + /* reading is possible after HUP */ + if (pfd[POLL_STDIN].events & POLLIN && pfd[POLL_STDIN].revents & POLLHUP && + !(pfd[POLL_STDIN].revents & POLLIN)) + { pfd[POLL_STDIN].fd = -1; - /* read something - poll net out */ - if (ttybuffPos > 0) - pfd[POLL_NETOUT].events = POLLOUT; - /* filled buffer - remove self from polling */ - if (ttybuffPos == IO_BUFF_SIZE) - pfd[POLL_STDIN].events = 0; - } - /* try to write to network */ - if (pfd[POLL_NETOUT].revents & POLLOUT && ttybuffPos > 0) - { - ret = drainbuf(pfd[POLL_NETOUT].fd, ttybuff, ttybuffPos); - if (ret == WANT_POLLOUT) - pfd[POLL_NETOUT].events = POLLOUT; - else if (ret == -1) - pfd[POLL_NETOUT].fd = -1; - /* buffer empty - remove self from polling */ - if (ttybuffPos == 0) - pfd[POLL_NETOUT].events = 0; - /* buffer no longer full - poll stdin again */ - if (ttybuffPos < IO_BUFF_SIZE) - pfd[POLL_STDIN].events = POLLIN; - } - /* try to read from network */ - if (pfd[POLL_NETIN].revents & POLLIN && netbuffPos < IO_BUFF_SIZE) - { - ret = fillbuf(pfd[POLL_NETIN].fd, netbuff, netbuffPos); - if (ret == WANT_POLLIN) - pfd[POLL_NETIN].events = POLLIN; - else if (ret == -1) - pfd[POLL_NETIN].fd = -1; - /* eof on net in - remove from pfd */ - if (ret == 0) + } + + if (pfd[POLL_NETIN].events & POLLIN && pfd[POLL_NETIN].revents & POLLHUP && + !(pfd[POLL_NETIN].revents & POLLIN)) { - shutdown(pfd[POLL_NETIN].fd, SHUT_RD); pfd[POLL_NETIN].fd = -1; } - /* read something - poll stdout */ - if (netbuffPos > 0) - pfd[POLL_STDOUT].events = POLLOUT; - /* filled buffer - remove self from polling */ - if (netbuffPos == IO_BUFF_SIZE) - pfd[POLL_NETIN].events = 0; - } - /* try to write to stdout */ - if (pfd[POLL_STDOUT].revents & POLLOUT && netbuffPos > 0) - { - ret = drainbuf(pfd[POLL_STDOUT].fd, netbuff, netbuffPos); - if (ret == WANT_POLLOUT) - pfd[POLL_STDOUT].events = POLLOUT; - else if (ret == -1) + + if (pfd[POLL_NETOUT].revents & POLLHUP) + { + pfd[POLL_NETOUT].fd = -1; + } + /* if HUP, stop watching stdout */ + if (pfd[POLL_STDOUT].revents & POLLHUP) pfd[POLL_STDOUT].fd = -1; - /* buffer empty - remove self from polling */ - if (netbuffPos == 0) - pfd[POLL_STDOUT].events = 0; - /* buffer no longer full - poll net in again */ - if (netbuffPos < IO_BUFF_SIZE) - pfd[POLL_NETIN].events = POLLIN; - } + /* if no net out, stop watching stdin */ + if (pfd[POLL_NETOUT].fd == -1) + pfd[POLL_STDIN].fd = -1; + /* if no stdout, stop watching net in */ + if (pfd[POLL_STDOUT].fd == -1) + { + if (pfd[POLL_NETIN].fd != -1) + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + } - /* stdin gone and queue empty? */ - if (pfd[POLL_STDIN].fd == -1 && ttybuffPos == 0) - { - pfd[POLL_NETOUT].fd = -1; - } - /* net in gone and queue empty? */ - if (pfd[POLL_NETIN].fd == -1 && netbuffPos == 0) - { - pfd[POLL_STDOUT].fd = -1; + /* try to read from stdin */ + if (pfd[POLL_STDIN].revents & POLLIN && ttybuffPos < IO_BUFF_SIZE) + { + ret = fillbuf(pfd[POLL_STDIN].fd, ttybuff, ttybuffPos); + if (ret == WANT_POLLIN) + pfd[POLL_STDIN].events = POLLIN; + else if (ret == 0 || ret == -1) + pfd[POLL_STDIN].fd = -1; + /* read something - poll net out */ + if (ttybuffPos > 0) + pfd[POLL_NETOUT].events = POLLOUT; + /* filled buffer - remove self from polling */ + if (ttybuffPos == IO_BUFF_SIZE) + pfd[POLL_STDIN].events = 0; + } + /* try to write to network */ + if (pfd[POLL_NETOUT].revents & POLLOUT && ttybuffPos > 0) + { + ret = drainbuf(pfd[POLL_NETOUT].fd, ttybuff, ttybuffPos); + if (ret == WANT_POLLOUT) + pfd[POLL_NETOUT].events = POLLOUT; + else if (ret == -1) + pfd[POLL_NETOUT].fd = -1; + /* buffer empty - remove self from polling */ + if (ttybuffPos == 0) + pfd[POLL_NETOUT].events = 0; + /* buffer no longer full - poll stdin again */ + if (ttybuffPos < IO_BUFF_SIZE) + pfd[POLL_STDIN].events = POLLIN; + } + /* try to read from network */ + if (pfd[POLL_NETIN].revents & POLLIN && netbuffPos < IO_BUFF_SIZE) + { + ret = fillbuf(pfd[POLL_NETIN].fd, netbuff, netbuffPos); + if (ret == WANT_POLLIN) + pfd[POLL_NETIN].events = POLLIN; + else if (ret == -1) + pfd[POLL_NETIN].fd = -1; + /* eof on net in - remove from pfd */ + if (ret == 0) + { + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + } + /* read something - poll stdout */ + if (netbuffPos > 0) + pfd[POLL_STDOUT].events = POLLOUT; + /* filled buffer - remove self from polling */ + if (netbuffPos == IO_BUFF_SIZE) + pfd[POLL_NETIN].events = 0; + } + /* try to write to stdout */ + if (pfd[POLL_STDOUT].revents & POLLOUT && netbuffPos > 0) + { + ret = drainbuf(pfd[POLL_STDOUT].fd, netbuff, netbuffPos); + if (ret == WANT_POLLOUT) + pfd[POLL_STDOUT].events = POLLOUT; + else if (ret == -1) + pfd[POLL_STDOUT].fd = -1; + /* buffer empty - remove self from polling */ + if (netbuffPos == 0) + pfd[POLL_STDOUT].events = 0; + /* buffer no longer full - poll net in again */ + if (netbuffPos < IO_BUFF_SIZE) + pfd[POLL_NETIN].events = POLLIN; + } + + /* stdin gone and queue empty? */ + if (pfd[POLL_STDIN].fd == -1 && ttybuffPos == 0) + { + pfd[POLL_NETOUT].fd = -1; + } + /* net in gone and queue empty? */ + if (pfd[POLL_NETIN].fd == -1 && netbuffPos == 0) + { + pfd[POLL_STDOUT].fd = -1; + } } } -} - -} // namespace +} // namespace extern "C" void signal_handler(int) { doContinue = false; } - /** * main method of the application */ @@ -750,13 +750,14 @@ int main(int argc, char* argv[]) device->stopCapture(); device->close(); device->stopRequestHandlerThread(); - std::cout << std::endl << std::endl - << "Packet statistics from KNI thread:" << std::endl - << " Total packets met: " << packetStats.totalPackets << std::endl - << " UDP packets met: " << packetStats.udpPacketsIn << std::endl - << " Failed PONG packets: " << packetStats.udpPacketsOutFail << std::endl - << " ARP packets met: " << packetStats.arpPacketsIn << std::endl - << " Failed ARP replay packets: " << packetStats.arpPacketsOutFail << std::endl - << std::endl; + std::cout << std::endl + << std::endl + << "Packet statistics from KNI thread:" << std::endl + << " Total packets met: " << packetStats.totalPackets << std::endl + << " UDP packets met: " << packetStats.udpPacketsIn << std::endl + << " Failed PONG packets: " << packetStats.udpPacketsOutFail << std::endl + << " ARP packets met: " << packetStats.arpPacketsIn << std::endl + << " Failed ARP replay packets: " << packetStats.arpPacketsOutFail << std::endl + << std::endl; return 0; } diff --git a/Examples/PcapPlusPlus-benchmark/benchmark.cpp b/Examples/PcapPlusPlus-benchmark/benchmark.cpp index 51708e4789..96c77ca63f 100644 --- a/Examples/PcapPlusPlus-benchmark/benchmark.cpp +++ b/Examples/PcapPlusPlus-benchmark/benchmark.cpp @@ -1,15 +1,16 @@ /** * PcapPlusPlus benchmark application * ================================== - * This application is meant to run a benchmark for PcapPlusPlus as part of the "packet-capture-benchmarks" project created by - * Matias Fontanini: https://github.com/mfontanini/packet-capture-benchmarks - * The application follows the project's convention so the benchmark code is very similar to other existing benchmarks in this project - * with minor changes necessary to test and run PcapPlusPlus. - * This application currently compiles and runs on Linux only, I didn't manage to compile it on Windows with MinGW (issues related to - * to compiling a C++11 application together with WinPcap. There's probably a solution but I didn't find it yet) - * In order to run this benchmark please download packet-capture-benchmarks and compile the existing benchmarks . Then build PcapPlusPlus - * which will also build the benchmark in `/examples_bin/benchmark`. Copy this executable to `packet-capture-benchmarks/pcapplusplus` - * Then run the `benchmark.sh` script provided in `packet-capture-benchmarks` with all benchmarks you want to run. For example: + * This application is meant to run a benchmark for PcapPlusPlus as part of the "packet-capture-benchmarks" project + * created by Matias Fontanini: https://github.com/mfontanini/packet-capture-benchmarks The application follows the + * project's convention so the benchmark code is very similar to other existing benchmarks in this project with minor + * changes necessary to test and run PcapPlusPlus. This application currently compiles and runs on Linux only, I didn't + * manage to compile it on Windows with MinGW (issues related to to compiling a C++11 application together with WinPcap. + * There's probably a solution but I didn't find it yet) In order to run this benchmark please download + * packet-capture-benchmarks and compile the existing benchmarks . Then build PcapPlusPlus which will also build the + * benchmark in `/examples_bin/benchmark`. Copy this executable to + * `packet-capture-benchmarks/pcapplusplus` Then run the `benchmark.sh` script provided in `packet-capture-benchmarks` + * with all benchmarks you want to run. For example: * `./benchmark.sh libpcap PcapPlusPlus libtins libcrafter` */ @@ -56,9 +57,9 @@ bool handle_packet(Packet& packet) return true; } -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - if(argc != 4) + if (argc != 4) { std::cout << "Usage: " << *argv << " \n"; return 1; @@ -67,13 +68,13 @@ int main(int argc, char *argv[]) int total_runs = std::stoi(argv[3]); size_t total_packets = 0; std::vector durations; - for(int i = 0; i < total_runs; ++i) + for (int i = 0; i < total_runs; ++i) { count = 0; PcapFileReaderDevice reader(argv[1]); reader.open(); std::chrono::high_resolution_clock::time_point start; - if(input_type == "dns") + if (input_type == "dns") { start = std::chrono::high_resolution_clock::now(); RawPacket rawPacket; @@ -98,11 +99,8 @@ int main(int argc, char *argv[]) total_packets += count; reader.close(); } - auto total_time = std::accumulate( - durations.begin(), - durations.end(), - std::chrono::high_resolution_clock::duration(0) - ); + auto total_time = + std::accumulate(durations.begin(), durations.end(), std::chrono::high_resolution_clock::duration(0)); using std::chrono::duration_cast; using std::chrono::milliseconds; diff --git a/Examples/PcapPrinter/main.cpp b/Examples/PcapPrinter/main.cpp index d263228474..76add37598 100644 --- a/Examples/PcapPrinter/main.cpp +++ b/Examples/PcapPrinter/main.cpp @@ -21,25 +21,23 @@ #include #include - -static struct option PcapPrinterOptions[] = -{ - {"output-file", required_argument, nullptr, 'o'}, - {"packet-count", required_argument, nullptr, 'c'}, - {"filter", required_argument, nullptr, 'i'}, - {"summary", no_argument, nullptr, 's'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +static struct option PcapPrinterOptions[] = { + { "output-file", required_argument, nullptr, 'o' }, + { "packet-count", required_argument, nullptr, 'c' }, + { "filter", required_argument, nullptr, 'i' }, + { "summary", no_argument, nullptr, 's' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { nullptr, 0, nullptr, 0 } }; - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) /** * Print application usage @@ -47,36 +45,34 @@ static struct option PcapPrinterOptions[] = void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " pcap_file [-h] [-v] [-o output_file] [-c packet_count] [-i filter] [-s]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " pcap_file : Input pcap/pcapng file name" << std::endl - << " -o output_file : Save output to text file (default output is stdout)" << std::endl - << " -c packet_count: Print only first packet_count number of packet" << std::endl - << " -i filter : Apply a BPF filter, meaning only filtered packets will be printed" << std::endl - << " -s : Print only file summary and exit" << std::endl - << " -v : Display the current version and exit" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " pcap_file [-h] [-v] [-o output_file] [-c packet_count] [-i filter] [-s]" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " pcap_file : Input pcap/pcapng file name" << std::endl + << " -o output_file : Save output to text file (default output is stdout)" << std::endl + << " -c packet_count: Print only first packet_count number of packet" << std::endl + << " -i filter : Apply a BPF filter, meaning only filtered packets will be printed" << std::endl + << " -s : Print only file summary and exit" << std::endl + << " -v : Display the current version and exit" << std::endl + << " -h : Display this help message and exit" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - std::string linkLayerToString(pcpp::LinkLayerType linkLayer) { @@ -90,7 +86,8 @@ std::string linkLayerToString(pcpp::LinkLayerType linkLayer) return "Linux cooked capture v2"; else if (linkLayer == pcpp::LINKTYPE_NULL) return "Null/Loopback"; - else if (linkLayer == pcpp::LINKTYPE_RAW || linkLayer == pcpp::LINKTYPE_DLT_RAW1 || linkLayer == pcpp::LINKTYPE_DLT_RAW2) + else if (linkLayer == pcpp::LINKTYPE_RAW || linkLayer == pcpp::LINKTYPE_DLT_RAW1 || + linkLayer == pcpp::LINKTYPE_DLT_RAW2) { std::ostringstream stream; stream << "Raw IP (" << linkLayer << ")"; @@ -102,10 +99,9 @@ std::string linkLayerToString(pcpp::LinkLayerType linkLayer) return stream.str(); } - /** -* print file summary based on the reader type -*/ + * print file summary based on the reader type + */ std::string printFileSummary(pcpp::IFileReaderDevice* reader) { std::ostringstream stream; @@ -147,10 +143,9 @@ std::string printFileSummary(pcpp::IFileReaderDevice* reader) return stream.str(); } - /** -* print all requested packets in a pcap/snoop file -*/ + * print all requested packets in a pcap/snoop file + */ int printPcapPackets(pcpp::IFileReaderDevice* reader, std::ostream* out, int packetCount) { // read packets from the file until end-of-file or until reached user requested packet count @@ -171,10 +166,9 @@ int printPcapPackets(pcpp::IFileReaderDevice* reader, std::ostream* out, int pac return packetCountSoFar; } - /** -* print all requested packets in a pcap-ng file -*/ + * print all requested packets in a pcap-ng file + */ int printPcapNgPackets(pcpp::PcapNgFileReaderDevice* reader, std::ostream* out, int packetCount) { // read packets from the file until end-of-file or until reached user requested packet count @@ -201,7 +195,6 @@ int printPcapNgPackets(pcpp::PcapNgFileReaderDevice* reader, std::ostream* out, return packetCountSoFar; } - /** * main method of this utility */ @@ -221,34 +214,34 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "o:c:i:svh", PcapPrinterOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "o:c:i:svh", PcapPrinterOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'o': - outputPcapFileName = optarg; - break; - case 'c': - packetCount = atoi(optarg); - break; - case 'i': - filter = optarg; - break; - case 's': - printOnlySummary = true; - break; - case 'h': - printUsage(); - exit(0); - break; - case 'v': - printAppVersion(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'o': + outputPcapFileName = optarg; + break; + case 'c': + packetCount = atoi(optarg); + break; + case 'i': + filter = optarg; + break; + case 's': + printOnlySummary = true; + break; + case 'h': + printUsage(); + exit(0); + break; + case 'v': + printAppVersion(); + break; + default: + printUsage(); + exit(-1); } } @@ -290,7 +283,6 @@ int main(int argc, char* argv[]) delete reader; EXIT_WITH_ERROR("Couldn't set filter '" << filter << "'"); } - } // print file summary diff --git a/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h b/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h index 833351b1da..6adbbfdfa5 100644 --- a/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h +++ b/Examples/PcapSearch/dirent-for-Visual-Studio/include/dirent.h @@ -14,7 +14,7 @@ * Windows Sockets 2.0. */ #ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN #endif #include @@ -36,123 +36,123 @@ /* Entries missing from MSVC 6.0 */ #if !defined(FILE_ATTRIBUTE_DEVICE) -# define FILE_ATTRIBUTE_DEVICE 0x40 +# define FILE_ATTRIBUTE_DEVICE 0x40 #endif /* File type and permission flags for stat(), general mask */ #if !defined(S_IFMT) -# define S_IFMT _S_IFMT +# define S_IFMT _S_IFMT #endif /* Directory bit */ #if !defined(S_IFDIR) -# define S_IFDIR _S_IFDIR +# define S_IFDIR _S_IFDIR #endif /* Character device bit */ #if !defined(S_IFCHR) -# define S_IFCHR _S_IFCHR +# define S_IFCHR _S_IFCHR #endif /* Pipe bit */ #if !defined(S_IFFIFO) -# define S_IFFIFO _S_IFFIFO +# define S_IFFIFO _S_IFFIFO #endif /* Regular file bit */ #if !defined(S_IFREG) -# define S_IFREG _S_IFREG +# define S_IFREG _S_IFREG #endif /* Read permission */ #if !defined(S_IREAD) -# define S_IREAD _S_IREAD +# define S_IREAD _S_IREAD #endif /* Write permission */ #if !defined(S_IWRITE) -# define S_IWRITE _S_IWRITE +# define S_IWRITE _S_IWRITE #endif /* Execute permission */ #if !defined(S_IEXEC) -# define S_IEXEC _S_IEXEC +# define S_IEXEC _S_IEXEC #endif /* Pipe */ #if !defined(S_IFIFO) -# define S_IFIFO _S_IFIFO +# define S_IFIFO _S_IFIFO #endif /* Block device */ #if !defined(S_IFBLK) -# define S_IFBLK 0 +# define S_IFBLK 0 #endif /* Link */ #if !defined(S_IFLNK) -# define S_IFLNK 0 +# define S_IFLNK 0 #endif /* Socket */ #if !defined(S_IFSOCK) -# define S_IFSOCK 0 +# define S_IFSOCK 0 #endif /* Read user permission */ #if !defined(S_IRUSR) -# define S_IRUSR S_IREAD +# define S_IRUSR S_IREAD #endif /* Write user permission */ #if !defined(S_IWUSR) -# define S_IWUSR S_IWRITE +# define S_IWUSR S_IWRITE #endif /* Execute user permission */ #if !defined(S_IXUSR) -# define S_IXUSR 0 +# define S_IXUSR 0 #endif /* Read group permission */ #if !defined(S_IRGRP) -# define S_IRGRP 0 +# define S_IRGRP 0 #endif /* Write group permission */ #if !defined(S_IWGRP) -# define S_IWGRP 0 +# define S_IWGRP 0 #endif /* Execute group permission */ #if !defined(S_IXGRP) -# define S_IXGRP 0 +# define S_IXGRP 0 #endif /* Read others permission */ #if !defined(S_IROTH) -# define S_IROTH 0 +# define S_IROTH 0 #endif /* Write others permission */ #if !defined(S_IWOTH) -# define S_IWOTH 0 +# define S_IWOTH 0 #endif /* Execute others permission */ #if !defined(S_IXOTH) -# define S_IXOTH 0 +# define S_IXOTH 0 #endif /* Maximum length of file name */ #if !defined(PATH_MAX) -# define PATH_MAX MAX_PATH +# define PATH_MAX MAX_PATH #endif #if !defined(FILENAME_MAX) -# define FILENAME_MAX MAX_PATH +# define FILENAME_MAX MAX_PATH #endif #if !defined(NAME_MAX) -# define NAME_MAX FILENAME_MAX +# define NAME_MAX FILENAME_MAX #endif /* File type flags for d_type */ @@ -176,25 +176,25 @@ * on Windows. */ #if !defined(S_ISFIFO) -# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) #endif #if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif #if !defined(S_ISREG) -# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif #if !defined(S_ISLNK) -# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) #endif #if !defined(S_ISSOCK) -# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) #endif #if !defined(S_ISCHR) -# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) #endif #if !defined(S_ISBLK) -# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) #endif /* Return the exact length of d_namlen without zero terminator */ @@ -203,54 +203,54 @@ /* Return number of bytes needed to store d_namlen */ #define _D_ALLOC_NAMLEN(p) (PATH_MAX) - #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif + /* Wide-character version */ + struct _wdirent + { + /* Always zero */ + long d_ino; -/* Wide-character version */ -struct _wdirent { - /* Always zero */ - long d_ino; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; + /* Structure size */ + unsigned short d_reclen; - /* File type */ - int d_type; + /* Length of name without \0 */ + size_t d_namlen; - /* File name */ - wchar_t d_name[PATH_MAX]; -}; -typedef struct _wdirent _wdirent; + /* File type */ + int d_type; -struct _WDIR { - /* Current directory entry */ - struct _wdirent ent; + /* File name */ + wchar_t d_name[PATH_MAX]; + }; + typedef struct _wdirent _wdirent; - /* Private file data */ - WIN32_FIND_DATAW data; + struct _WDIR + { + /* Current directory entry */ + struct _wdirent ent; - /* True if data is valid */ - int cached; + /* Private file data */ + WIN32_FIND_DATAW data; - /* Win32 search handle */ - HANDLE handle; + /* True if data is valid */ + int cached; - /* Initial directory name */ - wchar_t *patt; -}; -typedef struct _WDIR _WDIR; + /* Win32 search handle */ + HANDLE handle; -static _WDIR *_wopendir (const wchar_t *dirname); -static struct _wdirent *_wreaddir (_WDIR *dirp); -static int _wclosedir (_WDIR *dirp); -static void _wrewinddir (_WDIR* dirp); + /* Initial directory name */ + wchar_t* patt; + }; + typedef struct _WDIR _WDIR; + static _WDIR* _wopendir(const wchar_t* dirname); + static struct _wdirent* _wreaddir(_WDIR* dirp); + static int _wclosedir(_WDIR* dirp); + static void _wrewinddir(_WDIR* dirp); /* For compatibility with Symbian */ #define wdirent _wdirent @@ -260,666 +260,680 @@ static void _wrewinddir (_WDIR* dirp); #define wclosedir _wclosedir #define wrewinddir _wrewinddir - -/* Multi-byte character versions */ -struct dirent { - /* Always zero */ - long d_ino; - - /* Structure size */ - unsigned short d_reclen; - - /* Length of name without \0 */ - size_t d_namlen; - - /* File type */ - int d_type; - - /* File name */ - char d_name[PATH_MAX]; -}; -typedef struct dirent dirent; - -struct DIR { - struct dirent ent; - struct _WDIR *wdirp; -}; -typedef struct DIR DIR; - -static DIR *opendir (const char *dirname); -static struct dirent *readdir (DIR *dirp); -static int closedir (DIR *dirp); -static void rewinddir (DIR* dirp); - - -/* Internal utility functions */ -static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); -static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); - -static int dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count); - -static int dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, - const wchar_t *wcstr, - size_t count); - -static void dirent_set_errno (int error); - -/* - * Open directory stream DIRNAME for read and return a pointer to the - * internal working area that is used to retrieve individual directory - * entries. - */ -static _WDIR* -_wopendir( - const wchar_t *dirname) -{ - _WDIR *dirp = NULL; - int error; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno (ENOENT); - return NULL; - } - - /* Allocate new _WDIR structure */ - dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); - if (dirp != NULL) { - DWORD n; - - /* Reset _WDIR structure */ - dirp->handle = INVALID_HANDLE_VALUE; - dirp->patt = NULL; - dirp->cached = 0; - - /* Compute the length of full path plus zero terminator - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume its an absolute path. - */ -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - n = wcslen(dirname); -# else - n = GetFullPathNameW (dirname, 0, NULL, NULL); -# endif - - /* Allocate room for absolute directory name and search pattern */ - dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); - if (dirp->patt) { - - /* - * Convert relative directory name to an absolute one. This - * allows rewinddir() to function correctly even when current - * working directory is changed between opendir() and rewinddir(). - * - * Note that on WinRT there's no way to convert relative paths - * into absolute paths, so just assume its an absolute path. - */ -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - wcsncpy_s(dirp->patt, n+1, dirname, n); -# else - n = GetFullPathNameW (dirname, n, dirp->patt, NULL); -# endif - if (n > 0) { - wchar_t *p; - - /* Append search pattern \* to the directory name */ - p = dirp->patt + n; - if (dirp->patt < p) { - switch (p[-1]) { - case '\\': - case '/': - case ':': - /* Directory ends in path separator, e.g. c:\temp\ */ - /*NOP*/; - break; - - default: - /* Directory name doesn't end in path separator */ - *p++ = '\\'; - } - } - *p++ = '*'; - *p = '\0'; - - /* Open directory stream and retrieve the first entry */ - if (dirent_first (dirp)) { - /* Directory stream opened successfully */ - error = 0; - } else { - /* Cannot retrieve first entry */ - error = 1; - dirent_set_errno (ENOENT); - } - - } else { - /* Cannot retrieve full path name */ - dirent_set_errno (ENOENT); - error = 1; - } - - } else { - /* Cannot allocate memory for search pattern */ - error = 1; - } - - } else { - /* Cannot allocate _WDIR structure */ - error = 1; - } - - /* Clean up in case of error */ - if (error && dirp) { - _wclosedir (dirp); - dirp = NULL; - } - - return dirp; -} - -/* - * Read next directory entry. The directory entry is returned in dirent - * structure in the d_name field. Individual directory entries returned by - * this function include regular files, sub-directories, pseudo-directories - * "." and ".." as well as volume labels, hidden files and system files. - */ -static struct _wdirent* -_wreaddir( - _WDIR *dirp) -{ - WIN32_FIND_DATAW *datap; - struct _wdirent *entp; - - /* Read next directory entry */ - datap = dirent_next (dirp); - if (datap) { - size_t n; - DWORD attr; - - /* Pointer to directory entry to return */ - entp = &dirp->ent; - - /* - * Copy file name as wide-character string. If the file name is too - * long to fit in to the destination buffer, then truncate file name - * to PATH_MAX characters and zero-terminate the buffer. - */ - n = 0; - while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { - entp->d_name[n] = datap->cFileName[n]; - n++; - } - dirp->ent.d_name[n] = 0; - - /* Length of file name excluding zero terminator */ - entp->d_namlen = n; - - /* File type */ - attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - entp->d_type = DT_CHR; - } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - entp->d_type = DT_DIR; - } else { - entp->d_type = DT_REG; - } - - /* Reset dummy fields */ - entp->d_ino = 0; - entp->d_reclen = sizeof (struct _wdirent); - - } else { - - /* Last directory entry read */ - entp = NULL; - - } - - return entp; -} - -/* - * Close directory stream opened by opendir() function. This invalidates the - * DIR structure as well as any directory entry read previously by - * _wreaddir(). - */ -static int -_wclosedir( - _WDIR *dirp) -{ - int ok; - if (dirp) { - - /* Release search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - } - - /* Release search pattern */ - if (dirp->patt) { - free (dirp->patt); - dirp->patt = NULL; - } - - /* Release directory structure */ - free (dirp); - ok = /*success*/0; - - } else { - /* Invalid directory stream */ - dirent_set_errno (EBADF); - ok = /*failure*/-1; - } - return ok; -} - -/* - * Rewind directory stream such that _wreaddir() returns the very first - * file name again. - */ -static void -_wrewinddir( - _WDIR* dirp) -{ - if (dirp) { - /* Release existing search handle */ - if (dirp->handle != INVALID_HANDLE_VALUE) { - FindClose (dirp->handle); - } - - /* Open new search handle */ - dirent_first (dirp); - } -} - -/* Get first directory entry (internal) */ -static WIN32_FIND_DATAW* -dirent_first( - _WDIR *dirp) -{ - WIN32_FIND_DATAW *datap; - - /* Open directory and retrieve the first entry */ - dirp->handle = FindFirstFileExW( - dirp->patt, FindExInfoStandard, &dirp->data, - FindExSearchNameMatch, NULL, 0); - if (dirp->handle != INVALID_HANDLE_VALUE) { - - /* a directory entry is now waiting in memory */ - datap = &dirp->data; - dirp->cached = 1; - - } else { - - /* Failed to re-open directory: no directory entry in memory */ - dirp->cached = 0; - datap = NULL; - - } - return datap; -} - -/* Get next directory entry (internal) */ -static WIN32_FIND_DATAW* -dirent_next( - _WDIR *dirp) -{ - WIN32_FIND_DATAW *p; - - /* Get next directory entry */ - if (dirp->cached != 0) { - - /* A valid directory entry already in memory */ - p = &dirp->data; - dirp->cached = 0; - - } else if (dirp->handle != INVALID_HANDLE_VALUE) { - - /* Get the next directory entry from stream */ - if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { - /* Got a file */ - p = &dirp->data; - } else { - /* The very last entry has been processed or an error occurred */ - FindClose (dirp->handle); - dirp->handle = INVALID_HANDLE_VALUE; - p = NULL; - } - - } else { - - /* End of directory stream reached */ - p = NULL; - - } - - return p; -} - -/* - * Open directory stream using plain old C-string. - */ -static DIR* -opendir( - const char *dirname) -{ - struct DIR *dirp; - int error; - - /* Must have directory name */ - if (dirname == NULL || dirname[0] == '\0') { - dirent_set_errno (ENOENT); - return NULL; - } - - /* Allocate memory for DIR structure */ - dirp = (DIR*) malloc (sizeof (struct DIR)); - if (dirp) { - wchar_t wname[PATH_MAX]; - size_t n; - - /* Convert directory name to wide-character string */ - error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX); - if (!error) { - - /* Open directory stream using wide-character name */ - dirp->wdirp = _wopendir (wname); - if (dirp->wdirp) { - /* Directory stream opened */ - error = 0; - } else { - /* Failed to open directory stream */ - error = 1; - } - - } else { - /* - * Cannot convert file name to wide-character string. This - * occurs if the string contains invalid multi-byte sequences or - * the output buffer is too small to contain the resulting - * string. - */ - error = 1; - } - - } else { - /* Cannot allocate DIR structure */ - error = 1; - } - - /* Clean up in case of error */ - if (error && dirp) { - free (dirp); - dirp = NULL; - } - - return dirp; -} - -/* - * Read next directory entry. - * - * When working with text consoles, please note that file names returned by - * readdir() are represented in the default ANSI code page while any output to - * console is typically formatted on another code page. Thus, non-ASCII - * characters in file names will not usually display correctly on console. The - * problem can be fixed in two ways: (1) change the character set of console - * to 1252 using chcp utility and use Lucida Console font, or (2) use - * _cprintf function when writing to console. The _cprinf() will re-encode - * ANSI strings to the console code page so many non-ASCII characters will - * display correctly. - */ -static struct dirent* -readdir( - DIR *dirp) -{ - WIN32_FIND_DATAW *datap; - struct dirent *entp; - - /* Read next directory entry */ - datap = dirent_next (dirp->wdirp); - if (datap) { - size_t n; - int error; - - /* Attempt to convert file name to multi-byte string */ - error = dirent_wcstombs_s( - &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); - - /* - * If the file name cannot be represented by a multi-byte string, - * then attempt to use old 8+3 file name. This allows traditional - * Unix-code to access some file names despite of unicode - * characters, although file names may seem unfamiliar to the user. - * - * Be ware that the code below cannot come up with a short file - * name unless the file system provides one. At least - * VirtualBox shared folders fail to do this. - */ - if (error && datap->cAlternateFileName[0] != '\0') { - error = dirent_wcstombs_s( - &n, dirp->ent.d_name, PATH_MAX, - datap->cAlternateFileName, PATH_MAX); - } - - if (!error) { - DWORD attr; - - /* Initialize directory entry for return */ - entp = &dirp->ent; - - /* Length of file name excluding zero terminator */ - entp->d_namlen = n - 1; - - /* File attributes */ - attr = datap->dwFileAttributes; - if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { - entp->d_type = DT_CHR; - } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { - entp->d_type = DT_DIR; - } else { - entp->d_type = DT_REG; - } - - /* Reset dummy fields */ - entp->d_ino = 0; - entp->d_reclen = sizeof (struct dirent); - - } else { - /* - * Cannot convert file name to multi-byte string so construct - * an erroneous directory entry and return that. Note that - * we cannot return NULL as that would stop the processing - * of directory entries completely. - */ - entp = &dirp->ent; - entp->d_name[0] = '?'; - entp->d_name[1] = '\0'; - entp->d_namlen = 1; - entp->d_type = DT_UNKNOWN; - entp->d_ino = 0; - entp->d_reclen = 0; - } - - } else { - /* No more directory entries */ - entp = NULL; - } - - return entp; -} - -/* - * Close directory stream. - */ -static int -closedir( - DIR *dirp) -{ - int ok; - if (dirp) { - - /* Close wide-character directory stream */ - ok = _wclosedir (dirp->wdirp); - dirp->wdirp = NULL; - - /* Release multi-byte character version */ - free (dirp); - - } else { - - /* Invalid directory stream */ - dirent_set_errno (EBADF); - ok = /*failure*/-1; - - } - return ok; -} - -/* - * Rewind directory stream to beginning. - */ -static void -rewinddir( - DIR* dirp) -{ - /* Rewind wide-character string directory stream */ - _wrewinddir (dirp->wdirp); -} - -/* Convert multi-byte string to wide character string */ -static int -dirent_mbstowcs_s( - size_t *pReturnValue, - wchar_t *wcstr, - size_t sizeInWords, - const char *mbstr, - size_t count) -{ - int error; - -#if defined(_MSC_VER) && _MSC_VER >= 1400 - - /* Microsoft Visual Studio 2005 or later */ - error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); - + /* Multi-byte character versions */ + struct dirent + { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX]; + }; + typedef struct dirent dirent; + + struct DIR + { + struct dirent ent; + struct _WDIR* wdirp; + }; + typedef struct DIR DIR; + + static DIR* opendir(const char* dirname); + static struct dirent* readdir(DIR* dirp); + static int closedir(DIR* dirp); + static void rewinddir(DIR* dirp); + + /* Internal utility functions */ + static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp); + static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp); + + static int dirent_mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr, size_t sizeInWords, const char* mbstr, + size_t count); + + static int dirent_wcstombs_s(size_t* pReturnValue, char* mbstr, size_t sizeInBytes, const wchar_t* wcstr, + size_t count); + + static void dirent_set_errno(int error); + + /* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ + static _WDIR* _wopendir(const wchar_t* dirname) + { + _WDIR* dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') + { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*)malloc(sizeof(struct _WDIR)); + if (dirp != NULL) + { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); #else + n = GetFullPathNameW(dirname, 0, NULL, NULL); +#endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16); + if (dirp->patt) + { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + wcsncpy_s(dirp->patt, n + 1, dirname, n); +#else + n = GetFullPathNameW(dirname, n, dirp->patt, NULL); +#endif + if (n > 0) + { + wchar_t* p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) + { + switch (p[-1]) + { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first(dirp)) + { + /* Directory stream opened successfully */ + error = 0; + } + else + { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno(ENOENT); + } + } + else + { + /* Cannot retrieve full path name */ + dirent_set_errno(ENOENT); + error = 1; + } + } + else + { + /* Cannot allocate memory for search pattern */ + error = 1; + } + } + else + { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) + { + _wclosedir(dirp); + dirp = NULL; + } + + return dirp; + } + + /* + * Read next directory entry. The directory entry is returned in dirent + * structure in the d_name field. Individual directory entries returned by + * this function include regular files, sub-directories, pseudo-directories + * "." and ".." as well as volume labels, hidden files and system files. + */ + static struct _wdirent* _wreaddir(_WDIR* dirp) + { + WIN32_FIND_DATAW* datap; + struct _wdirent* entp; + + /* Read next directory entry */ + datap = dirent_next(dirp); + if (datap) + { + size_t n; + DWORD attr; + + /* Pointer to directory entry to return */ + entp = &dirp->ent; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) + { + entp->d_name[n] = datap->cFileName[n]; + n++; + } + dirp->ent.d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + { + entp->d_type = DT_CHR; + } + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + entp->d_type = DT_DIR; + } + else + { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct _wdirent); + } + else + { + + /* Last directory entry read */ + entp = NULL; + } + + return entp; + } + + /* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ + static int _wclosedir(_WDIR* dirp) + { + int ok; + if (dirp) + { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) + { + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) + { + free(dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free(dirp); + ok = /*success*/ 0; + } + else + { + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/ -1; + } + return ok; + } + + /* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ + static void _wrewinddir(_WDIR* dirp) + { + if (dirp) + { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) + { + FindClose(dirp->handle); + } + + /* Open new search handle */ + dirent_first(dirp); + } + } + + /* Get first directory entry (internal) */ + static WIN32_FIND_DATAW* dirent_first(_WDIR* dirp) + { + WIN32_FIND_DATAW* datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW(dirp->patt, FindExInfoStandard, &dirp->data, FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) + { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + } + else + { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + } + return datap; + } + + /* Get next directory entry (internal) */ + static WIN32_FIND_DATAW* dirent_next(_WDIR* dirp) + { + WIN32_FIND_DATAW* p; + + /* Get next directory entry */ + if (dirp->cached != 0) + { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + } + else if (dirp->handle != INVALID_HANDLE_VALUE) + { + + /* Get the next directory entry from stream */ + if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) + { + /* Got a file */ + p = &dirp->data; + } + else + { + /* The very last entry has been processed or an error occurred */ + FindClose(dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + } + else + { + + /* End of directory stream reached */ + p = NULL; + } + + return p; + } + + /* + * Open directory stream using plain old C-string. + */ + static DIR* opendir(const char* dirname) + { + struct DIR* dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') + { + dirent_set_errno(ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*)malloc(sizeof(struct DIR)); + if (dirp) + { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX); + if (!error) + { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir(wname); + if (dirp->wdirp) + { + /* Directory stream opened */ + error = 0; + } + else + { + /* Failed to open directory stream */ + error = 1; + } + } + else + { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + error = 1; + } + } + else + { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) + { + free(dirp); + dirp = NULL; + } + + return dirp; + } + + /* + * Read next directory entry. + * + * When working with text consoles, please note that file names returned by + * readdir() are represented in the default ANSI code page while any output to + * console is typically formatted on another code page. Thus, non-ASCII + * characters in file names will not usually display correctly on console. The + * problem can be fixed in two ways: (1) change the character set of console + * to 1252 using chcp utility and use Lucida Console font, or (2) use + * _cprintf function when writing to console. The _cprinf() will re-encode + * ANSI strings to the console code page so many non-ASCII characters will + * display correctly. + */ + static struct dirent* readdir(DIR* dirp) + { + WIN32_FIND_DATAW* datap; + struct dirent* entp; + + /* Read next directory entry */ + datap = dirent_next(dirp->wdirp); + if (datap) + { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s(&n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') + { + error = dirent_wcstombs_s(&n, dirp->ent.d_name, PATH_MAX, datap->cAlternateFileName, PATH_MAX); + } + + if (!error) + { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) + { + entp->d_type = DT_CHR; + } + else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + entp->d_type = DT_DIR; + } + else + { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof(struct dirent); + } + else + { + /* + * Cannot convert file name to multi-byte string so construct + * an erroneous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + } + else + { + /* No more directory entries */ + entp = NULL; + } + + return entp; + } + + /* + * Close directory stream. + */ + static int closedir(DIR* dirp) + { + int ok; + if (dirp) + { + + /* Close wide-character directory stream */ + ok = _wclosedir(dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free(dirp); + } + else + { + + /* Invalid directory stream */ + dirent_set_errno(EBADF); + ok = /*failure*/ -1; + } + return ok; + } + + /* + * Rewind directory stream to beginning. + */ + static void rewinddir(DIR* dirp) + { + /* Rewind wide-character string directory stream */ + _wrewinddir(dirp->wdirp); + } + + /* Convert multi-byte string to wide character string */ + static int dirent_mbstowcs_s(size_t* pReturnValue, wchar_t* wcstr, size_t sizeInWords, const char* mbstr, + size_t count) + { + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count); - /* Older Visual Studio or non-Microsoft compiler */ - size_t n; - - /* Convert to wide-character string (or count characters) */ - n = mbstowcs (wcstr, mbstr, sizeInWords); - if (!wcstr || n < count) { +#else - /* Zero-terminate output buffer */ - if (wcstr && sizeInWords) { - if (n >= sizeInWords) { - n = sizeInWords - 1; - } - wcstr[n] = 0; - } + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; - /* Length of resuting multi-byte string WITH zero terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } + /* Convert to wide-character string (or count characters) */ + n = mbstowcs(wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) + { - /* Success */ - error = 0; + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) + { + if (n >= sizeInWords) + { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } - } else { + /* Length of resuting multi-byte string WITH zero terminator */ + if (pReturnValue) + { + *pReturnValue = n + 1; + } - /* Could not convert string */ - error = 1; + /* Success */ + error = 0; + } + else + { - } + /* Could not convert string */ + error = 1; + } #endif - return error; -} + return error; + } -/* Convert wide-character string to multi-byte string */ -static int -dirent_wcstombs_s( - size_t *pReturnValue, - char *mbstr, - size_t sizeInBytes, /* max size of mbstr */ - const wchar_t *wcstr, - size_t count) -{ - int error; + /* Convert wide-character string to multi-byte string */ + static int dirent_wcstombs_s(size_t* pReturnValue, char* mbstr, size_t sizeInBytes, /* max size of mbstr */ + const wchar_t* wcstr, size_t count) + { + int error; -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(_MSC_VER) && _MSC_VER >= 1400 - /* Microsoft Visual Studio 2005 or later */ - error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count); #else - /* Older Visual Studio or non-Microsoft compiler */ - size_t n; + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; - /* Convert to multi-byte string (or count the number of bytes needed) */ - n = wcstombs (mbstr, wcstr, sizeInBytes); - if (!mbstr || n < count) { + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs(mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) + { - /* Zero-terminate output buffer */ - if (mbstr && sizeInBytes) { - if (n >= sizeInBytes) { - n = sizeInBytes - 1; - } - mbstr[n] = '\0'; - } + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) + { + if (n >= sizeInBytes) + { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } - /* Length of resulting multi-bytes string WITH zero-terminator */ - if (pReturnValue) { - *pReturnValue = n + 1; - } + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) + { + *pReturnValue = n + 1; + } - /* Success */ - error = 0; + /* Success */ + error = 0; + } + else + { - } else { - - /* Cannot convert string */ - error = 1; - - } + /* Cannot convert string */ + error = 1; + } #endif - return error; -} + return error; + } -/* Set errno variable */ -static void -dirent_set_errno( - int error) -{ -#if defined(_MSC_VER) && _MSC_VER >= 1400 + /* Set errno variable */ + static void dirent_set_errno(int error) + { +#if defined(_MSC_VER) && _MSC_VER >= 1400 - /* Microsoft Visual Studio 2005 and later */ - _set_errno (error); + /* Microsoft Visual Studio 2005 and later */ + _set_errno(error); #else - /* Non-Microsoft compiler or older Microsoft compiler */ - errno = error; + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; #endif -} - + } #ifdef __cplusplus } diff --git a/Examples/PcapSearch/main.cpp b/Examples/PcapSearch/main.cpp index 427ea27de8..397725837a 100644 --- a/Examples/PcapSearch/main.cpp +++ b/Examples/PcapSearch/main.cpp @@ -1,23 +1,30 @@ /** * PcapSearch application * ====================== - * This application searches all pcap and pcapng files in a given directory and all its sub-directories (unless stated otherwise) and outputs how many and which - * packets in those files match a certain pattern given by the user. The pattern is given in Berkeley Packet Filter (BPF) syntax - * (http://biot.com/capstats/bpf.html). For example: if running the application with the following parameters: - * PcapSearch.exe -d C:\ -s "ip net 1.1.1.1" -r C:\report.txt - * The application will search all '.pcap' files in all directories under C drive and try to match packets that matches IP 1.1.1.1. The result will be - * printed to stdout and a more detailed report will be printed to c:\report.txt + * This application searches all pcap and pcapng files in a given directory and all its sub-directories (unless stated + * otherwise) and outputs how many and which packets in those files match a certain pattern given by the user. The + * pattern is given in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html). For example: if running + * the application with the following parameters: + * + * `PcapSearch.exe -d C:\ -s "ip net 1.1.1.1" -r C:\report.txt` + * + * The application will search all '.pcap' files in all directories under C drive and try to match packets that matches + * IP 1.1.1.1. The result will be printed to stdout and a more detailed report will be printed to c:\report.txt + * * Output example: - * 1 packets found in 'C:\\path\example\Dns.pcap' - * 5 packets found in 'C:\\path\example\bla1\my_pcap2.pcap' - * 7299 packets found in 'C:\\path2\example\example2\big_pcap.pcap' - * 7435 packets found in 'C:\\path3\dir1\dir2\dir3\dir4\another.pcap' - * 435 packets found in 'C:\\path3\dirx\diry\dirz\ok.pcap' - * 4662 packets found in 'C:\\path4\gotit.pcap' - * 7299 packets found in 'C:\\enough.pcap' * - * There are switches that allows the user to search only in the provided folder (without sub-directories), search user-defined file extensions (sometimes - * pcap files have an extension which is not '.pcap'), and output or not output the detailed report + * ``` + * 1 packets found in 'C:\\path\example\Dns.pcap' + * 5 packets found in 'C:\\path\example\bla1\my_pcap2.pcap' + * 7299 packets found in 'C:\\path2\example\example2\big_pcap.pcap' + * 7435 packets found in 'C:\\path3\dir1\dir2\dir3\dir4\another.pcap' + * 435 packets found in 'C:\\path3\dirx\diry\dirz\ok.pcap' + * 4662 packets found in 'C:\\path4\gotit.pcap' 7299 packets found in 'C:\\enough.pcap' + * ``` + * + * There are switches that allows the user to search only in the provided folder (without sub-directories), search + * user-defined file extensions (sometimes pcap files have an extension which is not '.pcap'), and output or not output + * the detailed report * * For more details about modes of operation and parameters please run PcapSearch -h */ @@ -39,72 +46,75 @@ #include #include - -static struct option PcapSearchOptions[] = -{ - {"input-dir", required_argument, nullptr, 'd'}, - {"not-include-sub-dir", no_argument, nullptr, 'n'}, - {"search", required_argument, nullptr, 's'}, - {"detailed-report", required_argument, nullptr, 'r'}, - {"set-extensions", required_argument, nullptr, 'e'}, - {"version", no_argument, nullptr, 'v'}, - {"help", no_argument, nullptr, 'h'}, - {nullptr, 0, nullptr, 0} +// clang-format off +static struct option PcapSearchOptions[] = { + { "input-dir", required_argument, nullptr, 'd' }, + { "not-include-sub-dir", no_argument, nullptr, 'n' }, + { "search", required_argument, nullptr, 's' }, + { "detailed-report", required_argument, nullptr, 'r' }, + { "set-extensions", required_argument, nullptr, 'e' }, + { "version", no_argument, nullptr, 'v' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 } }; +// clang-format on - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) #if defined(_WIN32) -#define DIR_SEPARATOR "\\" +# define DIR_SEPARATOR "\\" #else -#define DIR_SEPARATOR "/" +# define DIR_SEPARATOR "/" #endif - /** * Print application usage */ void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-h] [-v] [-n] [-r file_name] [-e extension_list] -d directory -s search_criteria" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -d directory : Input directory" << std::endl - << " -n : Don't include sub-directories (default is include them)" << std::endl - << " -s search_criteria : Criteria to search in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html)" << std::endl - << " i.e: 'ip net 1.1.1.1'" << std::endl - << " -r file_name : Write a detailed search report to a file" << std::endl - << " -e extension_list : Set file extensions to search. The default is searching '.pcap' and '.pcapng' files." << std::endl - << " extension_list should be a comma-separated list of extensions, for example: pcap,net,dmp" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() + << " [-h] [-v] [-n] [-r file_name] [-e extension_list] -d directory -s search_criteria" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -d directory : Input directory" << std::endl + << " -n : Don't include sub-directories (default is include them)" << std::endl + << " -s search_criteria : Criteria to search in Berkeley Packet Filter (BPF) syntax " + "(http://biot.com/capstats/bpf.html)" + << std::endl + << " i.e: 'ip net 1.1.1.1'" << std::endl + << " -r file_name : Write a detailed search report to a file" << std::endl + << " -e extension_list : Set file extensions to search. The default is searching '.pcap' and " + "'.pcapng' files." + << std::endl + << " extension_list should be a comma-separated list of extensions, for " + "example: pcap,net,dmp" + << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -h : Displays this help message and exits" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /* * Returns the extension of a given file name */ @@ -113,9 +123,9 @@ std::string getExtension(const std::string& fileName) return fileName.substr(fileName.find_last_of(".") + 1); } - /** - * Searches all packet in a given pcap file for a certain search criteria. Returns how many packets matched the search criteria + * Searches all packet in a given pcap file for a certain search criteria. Returns how many packets matched the search + * criteria */ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std::ofstream* detailedReportFile) { @@ -166,7 +176,7 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: // print layer by layer by layer as we want to add a few spaces before each layer std::vector packetLayers; parsedPacket.toStringList(packetLayers); - for (const auto &layer : packetLayers) + for (const auto& layer : packetLayers) (*detailedReportFile) << "\n " << layer; (*detailedReportFile) << std::endl; } @@ -185,7 +195,6 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: (*detailedReportFile) << "\n"; (*detailedReportFile) << " ----> Found " << packetCount << " packets" << std::endl << std::endl; - } // free the reader memory @@ -195,23 +204,23 @@ int searchPcap(const std::string& pcapFilePath, std::string searchCriteria, std: return packetCount; } - /** - * Searches all pcap files in given directory (and sub-directories if directed by the user) and output how many packets in each file matches a given - * search criteria. This method outputs how many directories were searched, how many files were searched and how many packets were matched + * Searches all pcap files in given directory (and sub-directories if directed by the user) and output how many packets + * in each file matches a given search criteria. This method outputs how many directories were searched, how many files + * were searched and how many packets were matched */ -void searchDirectories(const std::string &directory, bool includeSubDirectories, const std::string &searchCriteria, std::ofstream* detailedReportFile, - std::unordered_map extensionsToSearch, - int& totalDirSearched, int& totalFilesSearched, int& totalPacketsFound) +void searchDirectories(const std::string& directory, bool includeSubDirectories, const std::string& searchCriteria, + std::ofstream* detailedReportFile, std::unordered_map extensionsToSearch, + int& totalDirSearched, int& totalFilesSearched, int& totalPacketsFound) { // open the directory - DIR *dir = opendir(directory.c_str()); + DIR* dir = opendir(directory.c_str()); // dir is null usually when user has no access permissions if (dir == nullptr) return; - struct dirent *entry = readdir(dir); + struct dirent* entry = readdir(dir); std::vector pcapList; @@ -223,7 +232,8 @@ void searchDirectories(const std::string &directory, bool includeSubDirectories, // construct directory full path std::string dirPath = directory; std::string dirSep = DIR_SEPARATOR; - if (0 != directory.compare(directory.length() - dirSep.length(), dirSep.length(), dirSep)) // directory doesn't contain separator in the end + if (0 != directory.compare(directory.length() - dirSep.length(), dirSep.length(), + dirSep)) // directory doesn't contain separator in the end dirPath += DIR_SEPARATOR; dirPath += name; @@ -239,8 +249,8 @@ void searchDirectories(const std::string &directory, bool includeSubDirectories, // if the file is not a directory if (!(info.st_mode & S_IFDIR)) { - // check if the file extension matches the requested extensions to search. If it does, put the file name in a list of files - // that should be searched (don't do the search just yet) + // check if the file extension matches the requested extensions to search. If it does, put the file name in + // a list of files that should be searched (don't do the search just yet) if (extensionsToSearch.find(getExtension(name)) != extensionsToSearch.end()) pcapList.push_back(dirPath); entry = readdir(dir); @@ -254,10 +264,11 @@ void searchDirectories(const std::string &directory, bool includeSubDirectories, continue; } - // if we got to here it means the file is actually a directory. If required to search sub-directories, call this method recursively to search - // inside this sub-directory + // if we got to here it means the file is actually a directory. If required to search sub-directories, call this + // method recursively to search inside this sub-directory if (includeSubDirectories) - searchDirectories(dirPath, true, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound); + searchDirectories(dirPath, true, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, + totalFilesSearched, totalPacketsFound); // move to the next file entry = readdir(dir); @@ -268,9 +279,9 @@ void searchDirectories(const std::string &directory, bool includeSubDirectories, totalDirSearched++; - // when we get to here we already covered all sub-directories and collected all the files in this directory that are required for search - // go over each such file and search its packets to find the search criteria - for (const auto &iter : pcapList) + // when we get to here we already covered all sub-directories and collected all the files in this directory that are + // required for search go over each such file and search its packets to find the search criteria + for (const auto& iter : pcapList) { // do the actual search int packetsFound = searchPcap(iter, searchCriteria, detailedReportFile); @@ -285,8 +296,6 @@ void searchDirectories(const std::string &directory, bool includeSubDirectories, } } - - /** * main method of this utility */ @@ -311,55 +320,55 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "d:s:r:e:hvn", PcapSearchOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "d:s:r:e:hvn", PcapSearchOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'd': - inputDirectory = optarg; - break; - case 'n': - includeSubDirectories = false; - break; - case 's': - searchCriteria = optarg; - break; - case 'r': - detailedReportFileName = optarg; - break; - case 'e': + case 0: + break; + case 'd': + inputDirectory = optarg; + break; + case 'n': + includeSubDirectories = false; + break; + case 's': + searchCriteria = optarg; + break; + case 'r': + detailedReportFileName = optarg; + break; + case 'e': + { + // read the extension list into the map + extensionsToSearch.clear(); + std::string extensionsListAsString = std::string(optarg); + std::stringstream stream(extensionsListAsString); + std::string extension; + // break comma-separated string into string list + while (std::getline(stream, extension, ',')) { - // read the extension list into the map - extensionsToSearch.clear(); - std::string extensionsListAsString = std::string(optarg); - std::stringstream stream(extensionsListAsString); - std::string extension; - // break comma-separated string into string list - while(std::getline(stream, extension, ',')) - { - // add the extension into the map if it doesn't already exist - if (extensionsToSearch.find(extension) == extensionsToSearch.end()) - extensionsToSearch[extension] = true; - } - - // verify list is not empty - if (extensionsToSearch.empty()) - { - EXIT_WITH_ERROR("Couldn't parse extensions list"); - } - break; + // add the extension into the map if it doesn't already exist + if (extensionsToSearch.find(extension) == extensionsToSearch.end()) + extensionsToSearch[extension] = true; } - case 'h': - printUsage(); - exit(0); - case 'v': - printAppVersion(); - break; - default: - printUsage(); - exit(-1); + + // verify list is not empty + if (extensionsToSearch.empty()) + { + EXIT_WITH_ERROR("Couldn't parse extensions list"); + } + break; + } + case 'h': + printUsage(); + exit(0); + case 'v': + printAppVersion(); + break; + default: + printUsage(); + exit(-1); } } @@ -373,7 +382,7 @@ int main(int argc, char* argv[]) EXIT_WITH_ERROR("Search criteria was not given"); } - DIR *dir = opendir(inputDirectory.c_str()); + DIR* dir = opendir(inputDirectory.c_str()); if (dir == nullptr) { EXIT_WITH_ERROR("Cannot find or open input directory"); @@ -382,7 +391,7 @@ int main(int argc, char* argv[]) // verify the search criteria is a valid BPF filter pcpp::BPFStringFilter filter(searchCriteria); - if(!filter.verifyFilter()) + if (!filter.verifyFilter()) { EXIT_WITH_ERROR("Search criteria isn't valid"); } @@ -399,22 +408,20 @@ int main(int argc, char* argv[]) } } - std::cout << "Searching..." << std::endl; int totalDirSearched = 0; int totalFilesSearched = 0; int totalPacketsFound = 0; // the main call - start searching! - searchDirectories(inputDirectory, includeSubDirectories, searchCriteria, detailedReportFile, extensionsToSearch, totalDirSearched, totalFilesSearched, totalPacketsFound); + searchDirectories(inputDirectory, includeSubDirectories, searchCriteria, detailedReportFile, extensionsToSearch, + totalDirSearched, totalFilesSearched, totalPacketsFound); // after search is done, close the report file and delete its instance - std::cout << std::endl << std::endl - << "Done! Searched " - << totalFilesSearched << " files in " - << totalDirSearched << " directories, " - << totalPacketsFound << " packets were matched to search criteria" - << std::endl; + std::cout << std::endl + << std::endl + << "Done! Searched " << totalFilesSearched << " files in " << totalDirSearched << " directories, " + << totalPacketsFound << " packets were matched to search criteria" << std::endl; if (detailedReportFile != nullptr) { diff --git a/Examples/PcapSplitter/ConnectionSplitters.h b/Examples/PcapSplitter/ConnectionSplitters.h index e241cbabc6..2924584e73 100644 --- a/Examples/PcapSplitter/ConnectionSplitters.h +++ b/Examples/PcapSplitter/ConnectionSplitters.h @@ -2,7 +2,6 @@ #include "Splitters.h" - /** * Splits a pcap file by 2-tuple (IP src and IP dst). Works for IPv4 & IPv6. * All packets that aren't IPv4 or IPv6 will be placed in one file. @@ -12,15 +11,16 @@ class TwoTupleSplitter : public ValueBasedSplitter { public: - /** * A c'tor for this class that gets the maximum number of files. If this number is lower or equal to 0 it's * considered not to have a file count limit */ - explicit TwoTupleSplitter(int maxFiles) : ValueBasedSplitter(maxFiles) {} + explicit TwoTupleSplitter(int maxFiles) : ValueBasedSplitter(maxFiles) + {} /** - * Find the 2-tuple flow for this packet and get the file number it belongs to. If flow is new, return a new file number + * Find the 2-tuple flow for this packet and get the file number it belongs to. If flow is new, return a new file + * number */ int getFileNumber(pcpp::Packet& packet, std::vector& filesToClose) { @@ -33,7 +33,7 @@ class TwoTupleSplitter : public ValueBasedSplitter // create a new entry and get a new file number for it m_FlowTable[hash] = getNextFileNumber(filesToClose); } - else // flow is found in the 2-tuple flow table + else // flow is found in the 2-tuple flow table { // indicate file is being written because this file may not be in the LRU list (and hence closed), // so we need to put it there, open it, and maybe close another file @@ -44,7 +44,6 @@ class TwoTupleSplitter : public ValueBasedSplitter } }; - /** * Splits a pcap file by connection (IP src + IP dst + port src + port dst + protocol) * Works for IPv4, IPv6, TCP and UDP. @@ -55,7 +54,6 @@ class TwoTupleSplitter : public ValueBasedSplitter class FiveTupleSplitter : public ValueBasedSplitter { private: - // a flow table for saving TCP state per flow. Currently the only data that is saved is whether // the last packet seen on the flow was a TCP SYN packet std::unordered_map m_TcpFlowTable; @@ -82,12 +80,12 @@ class FiveTupleSplitter : public ValueBasedSplitter } public: - /** * A c'tor for this class that gets the maximum number of files. If this number is lower or equal to 0 it's * considered not to have a file count limit */ - explicit FiveTupleSplitter(int maxFiles) : ValueBasedSplitter(maxFiles) {} + explicit FiveTupleSplitter(int maxFiles) : ValueBasedSplitter(maxFiles) + {} /** * Find the flow for this packet and get the file number it belongs to. If flow is new, return a new file number @@ -110,7 +108,7 @@ class FiveTupleSplitter : public ValueBasedSplitter m_TcpFlowTable[hash] = isTcpSyn(packet); } } - else // flow is found in the flow table + else // flow is found in the flow table { if (packet.isPacketOfType(pcpp::TCP)) { @@ -146,21 +144,16 @@ class FiveTupleSplitter : public ValueBasedSplitter return m_FlowTable[hash]; } - void updateStringStream(std::ostringstream & sstream, const std::string & srcIp, uint16_t srcPort, const std::string & dstIp, uint16_t dstPort) + void updateStringStream(std::ostringstream& sstream, const std::string& srcIp, uint16_t srcPort, + const std::string& dstIp, uint16_t dstPort) { - sstream << hyphenIP(srcIp) - << "_" - << srcPort - << "-" - << hyphenIP(dstIp) - << "_" - << dstPort; + sstream << hyphenIP(srcIp) << "_" << srcPort << "-" << hyphenIP(dstIp) << "_" << dstPort; } /** * Re-implement Splitter's getFileName() method, this time with the IPs/Ports/protocol value */ - std::string getFileName(pcpp::Packet& packet, const std::string &outputPcapBasePath, int fileNumber) + std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) { std::ostringstream sstream; @@ -186,12 +179,13 @@ class FiveTupleSplitter : public ValueBasedSplitter if ((tcpLayer->getTcpHeader()->synFlag == 1) && (tcpLayer->getTcpHeader()->ackFlag == 0)) { updateStringStream(sstream, getSrcIPString(packet), srcPort, getDstIPString(packet), dstPort); - } else if (((tcpLayer->getTcpHeader()->synFlag == 1) && - (tcpLayer->getTcpHeader()->ackFlag == 1) - ) || (srcPort < dstPort) ) + } + else if (((tcpLayer->getTcpHeader()->synFlag == 1) && (tcpLayer->getTcpHeader()->ackFlag == 1)) || + (srcPort < dstPort)) { updateStringStream(sstream, getDstIPString(packet), dstPort, getSrcIPString(packet), srcPort); - } else + } + else { updateStringStream(sstream, getSrcIPString(packet), srcPort, getDstIPString(packet), dstPort); } @@ -205,7 +199,8 @@ class FiveTupleSplitter : public ValueBasedSplitter if (udpLayer != nullptr) { sstream << "udp_"; - updateStringStream(sstream, getSrcIPString(packet), udpLayer->getSrcPort(), getDstIPString(packet), udpLayer->getDstPort()); + updateStringStream(sstream, getSrcIPString(packet), udpLayer->getSrcPort(), getDstIPString(packet), + udpLayer->getDstPort()); return outputPcapBasePath + sstream.str(); } } diff --git a/Examples/PcapSplitter/IPPortSplitters.h b/Examples/PcapSplitter/IPPortSplitters.h index 6a8d23d0cb..11d6b244a9 100644 --- a/Examples/PcapSplitter/IPPortSplitters.h +++ b/Examples/PcapSplitter/IPPortSplitters.h @@ -4,21 +4,20 @@ #include "PacketUtils.h" #include "SystemUtils.h" - /** - * A virtual abstract class for all splitters that split files by IP address or TCP/UDP port. Inherits from ValueBasedSplitter, - * so it already contains a mapping of IP/port to file number, a flow table, and supports max number of files or undefined - * number of files. This class arranges packets by TCP/UDP flows and for each flow lets the inherited classes determine - * to which file number this flow will be matched + * A virtual abstract class for all splitters that split files by IP address or TCP/UDP port. Inherits from + * ValueBasedSplitter, so it already contains a mapping of IP/port to file number, a flow table, and supports max number + * of files or undefined number of files. This class arranges packets by TCP/UDP flows and for each flow lets the + * inherited classes determine to which file number this flow will be matched */ class IPPortSplitter : public ValueBasedSplitter { public: - /** * C'tor for this class, does nothing but calling its ancestor */ - IPPortSplitter(int maxFiles) : ValueBasedSplitter(maxFiles) {} + IPPortSplitter(int maxFiles) : ValueBasedSplitter(maxFiles) + {} /** * Implements Splitter's abstract method. This method takes a packet and decides to which flow it belongs to (can @@ -60,20 +59,23 @@ class IPPortSplitter : public ValueBasedSplitter // SYN packet if (!tcpLayer->getTcpHeader()->ackFlag) { - m_FlowTable[hash] = getFileNumberForValue(getValue(packet, SYN, srcPort, dstPort), filesToClose); + m_FlowTable[hash] = + getFileNumberForValue(getValue(packet, SYN, srcPort, dstPort), filesToClose); return m_FlowTable[hash]; } // SYN/ACK packet else { - m_FlowTable[hash] = getFileNumberForValue(getValue(packet, SYN_ACK, srcPort, dstPort), filesToClose); + m_FlowTable[hash] = + getFileNumberForValue(getValue(packet, SYN_ACK, srcPort, dstPort), filesToClose); return m_FlowTable[hash]; } } // Other TCP packet else { - m_FlowTable[hash] = getFileNumberForValue(getValue(packet, TCP_OTHER, srcPort, dstPort), filesToClose); + m_FlowTable[hash] = + getFileNumberForValue(getValue(packet, TCP_OTHER, srcPort, dstPort), filesToClose); return m_FlowTable[hash]; } } @@ -97,11 +99,10 @@ class IPPortSplitter : public ValueBasedSplitter return 0; } - /** * Re-implement Splitter's getFileName() method, this time with the IP/port value */ - std::string getFileName(pcpp::Packet& packet, const std::string &outputPcapBasePath, int fileNumber) + std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) { // first set the base string as the outputPcapBasePath std::string result = outputPcapBasePath; @@ -159,7 +160,6 @@ class IPPortSplitter : public ValueBasedSplitter } protected: - /** * An enum for TCP/UDP packet type: can be either TCP-SYN, TCP-SYN/ACK, Other TCP packet of UDP packet */ @@ -185,7 +185,8 @@ class IPPortSplitter : public ValueBasedSplitter * packet type, src and dest ports and return the value by which the file will be split, but in its string format. * For example: if the file is split by client-ip the expected result is the client-ip string ("a.b.c.d") */ - virtual std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, uint16_t dstPort) = 0; + virtual std::string getValueString(pcpp::Packet& packet, PacketType packetType, uint16_t srcPort, + uint16_t dstPort) = 0; /** * An auxiliary method for extracting packet's IPv4/IPv6 source address hashed as 4 bytes uint32_t value @@ -234,29 +235,26 @@ class IPPortSplitter : public ValueBasedSplitter } }; - - /** * Splits a pcap file by client IP. This means that all flows with a certain client IP will be written to the same * file. The client IP for each flow is determined as follows: 1) if it's a TCP flow and we have the SYN packet - the * client IP is the source IP of the SYN packet 2) if it's a TCP flow and we only have the SYN/ACK packet - the - * client IP is the dest IP of the SYN/ACK packet 3) if it's a partial TCP flow and don't have the SYN or SYN/ACK packets, - * the client IP will be determined by the port: the higher port is considered the client side 4) if it's a UDP multicast - * flow - the client IP will be determined by the port: the port corresponding to the multicast address is the client side - * 5) If it's a non-multicast UDP flow - the client IP will be determined by the port: the higher port is considered the - * client side + * client IP is the dest IP of the SYN/ACK packet 3) if it's a partial TCP flow and don't have the SYN or SYN/ACK + * packets, the client IP will be determined by the port: the higher port is considered the client side 4) if it's a UDP + * multicast flow - the client IP will be determined by the port: the port corresponding to the multicast address is the + * client side 5) If it's a non-multicast UDP flow - the client IP will be determined by the port: the higher port is + * considered the client side */ class ClientIPSplitter : public IPPortSplitter { public: - /** * C'tor for this class, does nothing but calling its ancestor */ - explicit ClientIPSplitter(int maxFiles) : IPPortSplitter(maxFiles) {} + explicit ClientIPSplitter(int maxFiles) : IPPortSplitter(maxFiles) + {} protected: - /** * Implementation of the abstract method of IPPortSplitter. This method returns the client IP for a certain flow * by the logic written at the description of this class @@ -270,9 +268,12 @@ class ClientIPSplitter : public IPPortSplitter case SYN_ACK: return getDstIPValue(packet); case UDP: - if(isSrcIPMulticast(packet)) return getSrcIPValue(packet); - else if(isDstIPMulticast(packet)) return getDstIPValue(packet); - else return srcPort >= dstPort ? getSrcIPValue(packet) : getDstIPValue(packet); + if (isSrcIPMulticast(packet)) + return getSrcIPValue(packet); + else if (isDstIPMulticast(packet)) + return getDstIPValue(packet); + else + return srcPort >= dstPort ? getSrcIPValue(packet) : getDstIPValue(packet); // other TCP packet default: if (srcPort >= dstPort) @@ -293,9 +294,13 @@ class ClientIPSplitter : public IPPortSplitter case SYN_ACK: return prefix + hyphenIP(getDstIPString(packet)); case UDP: - if(isSrcIPMulticast(packet)) return prefix + hyphenIP(getSrcIPString(packet)); - else if(isDstIPMulticast(packet)) return prefix + hyphenIP(getDstIPString(packet)); - else return srcPort >= dstPort ? prefix + hyphenIP(getSrcIPString(packet)) : prefix + hyphenIP(getDstIPString(packet)); + if (isSrcIPMulticast(packet)) + return prefix + hyphenIP(getSrcIPString(packet)); + else if (isDstIPMulticast(packet)) + return prefix + hyphenIP(getDstIPString(packet)); + else + return srcPort >= dstPort ? prefix + hyphenIP(getSrcIPString(packet)) + : prefix + hyphenIP(getDstIPString(packet)); // other TCP packet default: if (srcPort >= dstPort) @@ -306,29 +311,26 @@ class ClientIPSplitter : public IPPortSplitter } }; - - /** * Splits a pcap file by server IP. This means that all flows with a certain server IP will be written to the same * file. The server IP for each flow is determined as follows: 1) if it's a TCP flow and we have the SYN packet - the * server IP is the dest IP of the SYN packet 2) if it's a TCP flow and we only have the SYN/ACK packet - the - * server IP is the source IP of the SYN/ACK packet 3) if it's a partial TCP flow and don't have the SYN or SYN/ACK packets, - * the server IP will be determined by the port: the lower port is considered the server side 4) if it's a multicast UDP flow - - * the server IP will be determined by the port: the port corresponding to the non-multicast address is consdered as server side - * 5) if i's a non-multicast UDP flow - the server IP will be determined by the port: the lower port is considered the - * server side + * server IP is the source IP of the SYN/ACK packet 3) if it's a partial TCP flow and don't have the SYN or SYN/ACK + * packets, the server IP will be determined by the port: the lower port is considered the server side 4) if it's a + * multicast UDP flow - the server IP will be determined by the port: the port corresponding to the non-multicast + * address is consdered as server side 5) if i's a non-multicast UDP flow - the server IP will be determined by the + * port: the lower port is considered the server side */ class ServerIPSplitter : public IPPortSplitter { public: - /** * C'tor for this class, does nothing but calling its ancestor */ - explicit ServerIPSplitter(int maxFiles) : IPPortSplitter(maxFiles) {} + explicit ServerIPSplitter(int maxFiles) : IPPortSplitter(maxFiles) + {} protected: - /** * Implementation of the abstract method of IPPortSplitter. This method returns the server IP for a certain flow * by the logic written at the description of this class @@ -342,9 +344,12 @@ class ServerIPSplitter : public IPPortSplitter case SYN_ACK: return getSrcIPValue(packet); case UDP: - if(isSrcIPMulticast(packet)) return getDstIPValue(packet); - else if(isDstIPMulticast(packet)) return getSrcIPValue(packet); - else return srcPort >= dstPort ? getDstIPValue(packet) : getSrcIPValue(packet); + if (isSrcIPMulticast(packet)) + return getDstIPValue(packet); + else if (isDstIPMulticast(packet)) + return getSrcIPValue(packet); + else + return srcPort >= dstPort ? getDstIPValue(packet) : getSrcIPValue(packet); // other TCP packet default: if (srcPort >= dstPort) @@ -365,9 +370,13 @@ class ServerIPSplitter : public IPPortSplitter case SYN_ACK: return prefix + hyphenIP(getSrcIPString(packet)); case UDP: - if(isSrcIPMulticast(packet)) return prefix + hyphenIP(getDstIPString(packet)); - else if(isDstIPMulticast(packet)) return prefix + hyphenIP(getSrcIPString(packet)); - else return srcPort >= dstPort ? prefix + hyphenIP(getDstIPString(packet)) : prefix + hyphenIP(getSrcIPString(packet)); + if (isSrcIPMulticast(packet)) + return prefix + hyphenIP(getDstIPString(packet)); + else if (isDstIPMulticast(packet)) + return prefix + hyphenIP(getSrcIPString(packet)); + else + return srcPort >= dstPort ? prefix + hyphenIP(getDstIPString(packet)) + : prefix + hyphenIP(getSrcIPString(packet)); // other TCP packet default: if (srcPort >= dstPort) @@ -376,32 +385,29 @@ class ServerIPSplitter : public IPPortSplitter return prefix + hyphenIP(getSrcIPString(packet)); } } - }; - - /** * Splits a pcap file by server port (most of the time is similar to protocol). This means that all flows with a certain - * server port will be written to the same file. The server port for each flow is determined as follows: 1) if it's a TCP - * flow and we have the SYN packet - the server port is the dest port of the SYN packet 2) if it's a TCP flow and we only - * have the SYN/ACK packet - the server port is the source port of the SYN/ACK packet 3) if it's a partial TCP flow and - * we don't have the SYN or SYN/ACK packets, the server port will be determined by the port: the lower port is considered - * the server side 4) if it's a UDP multicast flow - if the sourceIP is a multicast address, the dest port is considered - * as a server port, otherwise if the destIP is a multicast address, the source port is considered as a server port 5) if - * it's a UDP flow - the server port will be determined by the port: the lower port is considered as server port + * server port will be written to the same file. The server port for each flow is determined as follows: 1) if it's a + * TCP flow and we have the SYN packet - the server port is the dest port of the SYN packet 2) if it's a TCP flow and we + * only have the SYN/ACK packet - the server port is the source port of the SYN/ACK packet 3) if it's a partial TCP flow + * and we don't have the SYN or SYN/ACK packets, the server port will be determined by the port: the lower port is + * considered the server side 4) if it's a UDP multicast flow - if the sourceIP is a multicast address, the dest port is + * considered as a server port, otherwise if the destIP is a multicast address, the source port is considered as a + * server port 5) if it's a UDP flow - the server port will be determined by the port: the lower port is considered as + * server port */ class ServerPortSplitter : public IPPortSplitter { public: - /** * C'tor for this class, does nothing but calling its ancestor */ - explicit ServerPortSplitter(int maxFiles) : IPPortSplitter(maxFiles) {} + explicit ServerPortSplitter(int maxFiles) : IPPortSplitter(maxFiles) + {} protected: - /** * Implementation of the abstract method of IPPortSplitter. This method returns the server port for a certain flow * by the logic written at the description of this class @@ -415,9 +421,12 @@ class ServerPortSplitter : public IPPortSplitter case SYN_ACK: return srcPort; case UDP: - if(isSrcIPMulticast(packet)) return dstPort; - else if(isDstIPMulticast(packet)) return srcPort; - else return std::min(srcPort, dstPort); + if (isSrcIPMulticast(packet)) + return dstPort; + else if (isDstIPMulticast(packet)) + return srcPort; + else + return std::min(srcPort, dstPort); // other TCP packet default: return std::min(srcPort, dstPort); @@ -438,10 +447,13 @@ class ServerPortSplitter : public IPPortSplitter res = srcPort; break; case UDP: - if(isSrcIPMulticast(packet)) res = dstPort; - else if(isDstIPMulticast(packet)) res = srcPort; - else res = std::min(srcPort, dstPort); - break; + if (isSrcIPMulticast(packet)) + res = dstPort; + else if (isDstIPMulticast(packet)) + res = srcPort; + else + res = std::min(srcPort, dstPort); + break; // other TCP packet default: res = std::min(srcPort, dstPort); @@ -455,26 +467,26 @@ class ServerPortSplitter : public IPPortSplitter }; /** - * Splits a pcap file by server client (most of the time is similar to protocol). This means that all flows with a certain - * client port will be written to the same file. The client port for each flow is determined as follows: 1) if it's a TCP - * flow and we have the SYN packet - the client port is the source port of the SYN packet 2) if it's a TCP flow and we only - * have the SYN/ACK packet - the client port is the dest port of the SYN/ACK packet 3) if it's a partial TCP flow and - * we don't have the SYN or SYN/ACK packets, the server port will be determined by the port: the higher port is considered - * the client side 4) if it's a UDP multicast flow - if the sourceIP is a multicast address, the source port is considered - * as a client port, otherwise if the destIP is a multicast address, the dest port is considered as a client port 5) if - * it's a UDP flow - the client port will be determined by the port: the higher port is considered as client port + * Splits a pcap file by server client (most of the time is similar to protocol). This means that all flows with a + * certain client port will be written to the same file. The client port for each flow is determined as follows: 1) if + * it's a TCP flow and we have the SYN packet - the client port is the source port of the SYN packet 2) if it's a TCP + * flow and we only have the SYN/ACK packet - the client port is the dest port of the SYN/ACK packet 3) if it's a + * partial TCP flow and we don't have the SYN or SYN/ACK packets, the server port will be determined by the port: the + * higher port is considered the client side 4) if it's a UDP multicast flow - if the sourceIP is a multicast address, + * the source port is considered as a client port, otherwise if the destIP is a multicast address, the dest port is + * considered as a client port 5) if it's a UDP flow - the client port will be determined by the port: the higher port + * is considered as client port */ class ClientPortSplitter : public IPPortSplitter { public: - /** * C'tor for this class, does nothing but calling its ancestor */ - explicit ClientPortSplitter(int maxFiles) : IPPortSplitter(maxFiles) {} + explicit ClientPortSplitter(int maxFiles) : IPPortSplitter(maxFiles) + {} protected: - /** * Implementation of the abstract method of IPPortSplitter. This method returns the client port for a certain flow * by the logic written at the description of this class @@ -488,9 +500,12 @@ class ClientPortSplitter : public IPPortSplitter case SYN_ACK: return dstPort; case UDP: - if(isSrcIPMulticast(packet)) return srcPort; - else if(isDstIPMulticast(packet)) return dstPort; - else return std::max(srcPort, dstPort); + if (isSrcIPMulticast(packet)) + return srcPort; + else if (isDstIPMulticast(packet)) + return dstPort; + else + return std::max(srcPort, dstPort); // other TCP packet default: return std::max(srcPort, dstPort); @@ -511,9 +526,12 @@ class ClientPortSplitter : public IPPortSplitter res = dstPort; break; case UDP: - if(isSrcIPMulticast(packet)) res = srcPort; - else if(isDstIPMulticast(packet)) res = dstPort; - else res = std::max(srcPort, dstPort); + if (isSrcIPMulticast(packet)) + res = srcPort; + else if (isDstIPMulticast(packet)) + res = dstPort; + else + res = std::max(srcPort, dstPort); break; // other TCP packet default: diff --git a/Examples/PcapSplitter/SimpleSplitters.h b/Examples/PcapSplitter/SimpleSplitters.h index f69b67cd85..e05abcb575 100644 --- a/Examples/PcapSplitter/SimpleSplitters.h +++ b/Examples/PcapSplitter/SimpleSplitters.h @@ -14,7 +14,6 @@ class PacketCountSplitter : public Splitter int m_MaxPacketsPerFile; public: - /** * A c'tor for this class which gets the packet count for each split file */ @@ -57,8 +56,6 @@ class PacketCountSplitter : public Splitter } }; - - /** * Splits a pcap file by number of byte in each file */ @@ -68,11 +65,10 @@ class FileSizeSplitter : public Splitter uint64_t m_TotalSize; uint64_t m_MaxBytesPerFile; - static const int PCAP_FILE_HEADER_SIZE = 24; // == sizeof(pcap_file_header) - static const int PCAP_PACKET_HEADER_SIZE = 16; // == sizeof(pcap_pkthdr) + static const int PCAP_FILE_HEADER_SIZE = 24; // == sizeof(pcap_file_header) + static const int PCAP_PACKET_HEADER_SIZE = 16; // == sizeof(pcap_pkthdr) public: - /** * A c'tor for this class which gets the file size in bytes for each split file */ @@ -114,13 +110,11 @@ class FileSizeSplitter : public Splitter return true; } - }; - /** - * Splits a pcap file into two files: one that contains all packets matching a given BPF filter and one that contains the rest - * of the packets + * Splits a pcap file into two files: one that contains all packets matching a given BPF filter and one that contains + * the rest of the packets */ class BpfCriteriaSplitter : public Splitter { @@ -129,7 +123,8 @@ class BpfCriteriaSplitter : public Splitter pcpp::BPFStringFilter filter; public: - explicit BpfCriteriaSplitter(const std::string &bpfFilter) : m_BpfFilter(bpfFilter), filter(bpfFilter) {} + explicit BpfCriteriaSplitter(const std::string& bpfFilter) : m_BpfFilter(bpfFilter), filter(bpfFilter) + {} /** * Return file #0 if packet matches the BPF filer, and file #1 if it's not @@ -145,7 +140,7 @@ class BpfCriteriaSplitter : public Splitter * Re-implement Splitter's getFileName() method, clarifying which file was matched by the BPF * filter and which didn't */ - std::string getFileName(pcpp::Packet& packet, const std::string &outputPcapBasePath, int fileNumber) + std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) { if (fileNumber == 0) return outputPcapBasePath + "match-bpf"; @@ -164,7 +159,6 @@ class BpfCriteriaSplitter : public Splitter return false; } - pcpp::BPFStringFilter localFilter(m_BpfFilter); bool filterValid = localFilter.verifyFilter(); if (!filterValid) @@ -174,14 +168,14 @@ class BpfCriteriaSplitter : public Splitter } }; - /** * Split a pcap file to an arbitrary number of files in a round-robin manner, each read packet to the next file in line */ class RoundRobinSplitter : public SplitterWithMaxFiles { public: - explicit RoundRobinSplitter(int numOfFiles) : SplitterWithMaxFiles(numOfFiles) { } + explicit RoundRobinSplitter(int numOfFiles) : SplitterWithMaxFiles(numOfFiles) + {} /** * Get the next file number, SplitterWithMaxFiles#getNextFileNumber() takes care of the round-robin method diff --git a/Examples/PcapSplitter/Splitters.h b/Examples/PcapSplitter/Splitters.h index debaf6f2ac..c6c43c30a0 100644 --- a/Examples/PcapSplitter/Splitters.h +++ b/Examples/PcapSplitter/Splitters.h @@ -21,7 +21,6 @@ class Splitter { public: - /** * A method that gets a packet and returns: * - The file number to write the packet to @@ -42,20 +41,20 @@ class Splitter * first packet that will be written to this file. The default implementation is the following: * ' /requested-path/original-file-name-[4-digit-number-starting-at-0000].pcap' */ - virtual std::string getFileName(pcpp::Packet& packet, const std::string &outputPcapBasePath, int fileNumber) + virtual std::string getFileName(pcpp::Packet& packet, const std::string& outputPcapBasePath, int fileNumber) { - std::ostringstream sstream; - sstream << std::setw(4) << std::setfill( '0' ) << fileNumber; + std::ostringstream sstream; + sstream << std::setw(4) << std::setfill('0') << fileNumber; return outputPcapBasePath.c_str() + sstream.str(); } /** * A virtual d'tor */ - virtual ~Splitter() {} + virtual ~Splitter() + {} }; - /** * A virtual abstract splitter which represent splitters that may or may not have a limit on the number of * output files after the split @@ -91,10 +90,10 @@ class SplitterWithMaxFiles : public Splitter /** * A helper method that is called by child classes and returns the next file number. If there's no output file limit - * it just return prev_file_number+1. But if there is a file limit it return file number in cyclic manner, meaning if - * reached the max file number, the next file number will be 0. - * In addition the method puts the next file in the LRU list and if the list is full it pulls out the least recently - * used file and returns it in filesToClose vector. The application will take care of closing that file + * it just return prev_file_number+1. But if there is a file limit it return file number in cyclic manner, meaning + * if reached the max file number, the next file number will be 0. In addition the method puts the next file in the + * LRU list and if the list is full it pulls out the least recently used file and returns it in filesToClose vector. + * The application will take care of closing that file */ int getNextFileNumber(std::vector& filesToClose) { @@ -103,13 +102,12 @@ class SplitterWithMaxFiles : public Splitter // zero or negative m_MaxFiles means no limit if (m_MaxFiles <= 0) nextFile = m_NextFile++; - else // m_MaxFiles is positive, meaning there is a output file limit + else // m_MaxFiles is positive, meaning there is a output file limit { nextFile = (m_NextFile) % m_MaxFiles; m_NextFile++; } - // put the next file in the LRU list int fileToClose; if (m_LRUFileList.put(nextFile, &fileToClose) == 1) @@ -121,17 +119,17 @@ class SplitterWithMaxFiles : public Splitter } /** - * A protected c'tor for this class which gets the output file limit size. If maxFile is UNLIMITED_FILES_MAGIC_NUMBER, - * it's considered there's no output files limit + * A protected c'tor for this class which gets the output file limit size. If maxFile is + * UNLIMITED_FILES_MAGIC_NUMBER, it's considered there's no output files limit */ - explicit SplitterWithMaxFiles(int maxFiles, int firstFileNumber = 0) : m_LRUFileList(MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) + explicit SplitterWithMaxFiles(int maxFiles, int firstFileNumber = 0) + : m_LRUFileList(MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) { m_MaxFiles = maxFiles; m_NextFile = firstFileNumber; } public: - static const int UNLIMITED_FILES_MAGIC_NUMBER = -12345; /** @@ -154,13 +152,12 @@ class SplitterWithMaxFiles : public Splitter } }; - /** * An abstract virtual splitter which represent splitters that needs to keep a mapping between a certain packet value to * a certain file number the packet needs to be written to. For example: in client-ip splitter all flows with a - * certain client-ip should be written to the same file. So this class will enable it to keep a mapping between client-ips - * and file numbers. This class inherits SplitterWithMaxFiles so it supports having or not having a limit on the number - * of output files + * certain client-ip should be written to the same file. So this class will enable it to keep a mapping between + * client-ips and file numbers. This class inherits SplitterWithMaxFiles so it supports having or not having a limit on + * the number of output files */ class ValueBasedSplitter : public SplitterWithMaxFiles { @@ -173,7 +170,8 @@ class ValueBasedSplitter : public SplitterWithMaxFiles /** * A protected c'tor for this class that only propagate the maxFiles to its ancestor */ - explicit ValueBasedSplitter(int maxFiles) : SplitterWithMaxFiles(maxFiles, 1) {} + explicit ValueBasedSplitter(int maxFiles) : SplitterWithMaxFiles(maxFiles, 1) + {} /** * A helper method that gets the packet value and returns the file to write it to, and also a file to close if the diff --git a/Examples/PcapSplitter/main.cpp b/Examples/PcapSplitter/main.cpp index 858d7903ca..ae928113d4 100644 --- a/Examples/PcapSplitter/main.cpp +++ b/Examples/PcapSplitter/main.cpp @@ -23,26 +23,27 @@ * between two IP addresses. The user can limit the number of output files, in this case multiple pairs of IP source * and dest will be written to the same file. If the user doesn't set such limit - all connection of one pair of * source and dest IP will be written to each file - * 7) Connection - splits a pcap file to smaller pcap files by TCP/UDP connection meaning each connection will be written - * to a certain file. The user can limit the number of output files, in this case an equal number of connections will - * be written to the same file. If the user doesn't set such limit - each file will contain one connection - * 8) BPF filter - splits the pcap file into two files: one that contains all packets matching the input BPF filter - * and the other one with the rest of the packets + * 7) Connection - splits a pcap file to smaller pcap files by TCP/UDP connection meaning each connection will be + * written to a certain file. The user can limit the number of output files, in this case an equal number of + * connections will be written to the same file. If the user doesn't set such limit - each file will contain one + * connection + * 8) BPF filter - splits the pcap file into two files: one that contains all packets matching the input BPF filter and + * the other one with the rest of the packets * * Remarks: + * * - Options 3-7 supports both IPv4 and IPV6 * - Number of output files isn't limited, unless the user set such limit in options 3-7 * - There is no limit on the size of the input file, the number of packets it contains or the number of connections it * contains - * - The user can also set a BPF filter to instruct the application to handle only packets filtered by the filter. The rest - * of the packets in the input file will be ignored + * - The user can also set a BPF filter to instruct the application to handle only packets filtered by the filter. The + * rest of the packets in the input file will be ignored * - In options 3-5 & 7 all packets which aren't UDP or TCP (hence don't belong to any connection) will be written to * one output file, separate from the other output files (usually file#0) * - Works only on files of the pcap (TCPDUMP) format * */ - #include #include #include @@ -60,117 +61,128 @@ #include #include - -static struct option PcapSplitterOptions[] = -{ - {"input-file", required_argument, nullptr, 'f'}, - {"output-file", required_argument, nullptr, 'o'}, - {"method", required_argument, nullptr, 'm'}, - {"param", required_argument, nullptr, 'p'}, - {"filter", required_argument, nullptr, 'i'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +static struct option PcapSplitterOptions[] = { + { "input-file", required_argument, nullptr, 'f' }, + { "output-file", required_argument, nullptr, 'o' }, + { "method", required_argument, nullptr, 'm' }, + { "param", required_argument, nullptr, 'p' }, + { "filter", required_argument, nullptr, 'i' }, + { "version", no_argument, nullptr, 'v' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 } }; - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -#define SPLIT_BY_FILE_SIZE "file-size" -#define SPLIT_BY_PACKET_COUNT "packet-count" -#define SPLIT_BY_IP_CLIENT "client-ip" -#define SPLIT_BY_IP_SERVER "server-ip" -#define SPLIT_BY_SERVER_PORT "server-port" -#define SPLIT_BY_CLIENT_PORT "client-port" -#define SPLIT_BY_2_TUPLE "ip-src-dst" -#define SPLIT_BY_5_TUPLE "connection" -#define SPLIT_BY_BPF_FILTER "bpf-filter" -#define SPLIT_BY_ROUND_ROBIN "round-robin" - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) + +#define SPLIT_BY_FILE_SIZE "file-size" +#define SPLIT_BY_PACKET_COUNT "packet-count" +#define SPLIT_BY_IP_CLIENT "client-ip" +#define SPLIT_BY_IP_SERVER "server-ip" +#define SPLIT_BY_SERVER_PORT "server-port" +#define SPLIT_BY_CLIENT_PORT "client-port" +#define SPLIT_BY_2_TUPLE "ip-src-dst" +#define SPLIT_BY_5_TUPLE "connection" +#define SPLIT_BY_BPF_FILTER "bpf-filter" +#define SPLIT_BY_ROUND_ROBIN "round-robin" #if defined(_WIN32) -#define SEPARATOR '\\' +# define SEPARATOR '\\' #else -#define SEPARATOR '/' +# define SEPARATOR '/' #endif - /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-h] [-v] [-i filter] -f pcap_file -o output_dir -m split_method [-p split_param]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -f pcap_file : Input pcap file name" << std::endl - << " -o output_dir : The directory where the output files shall be written" << std::endl - << " -m split_method : The method to split with. Can take one of the following params:" << std::endl - << " 'file-size' - split files by size in bytes" << std::endl - << " 'packet-count' - split files by packet count" << std::endl - << " 'client-ip' - split files by client IP, meaning all connections with" << std::endl - << " the same client IP will be in the same file" << std::endl - << " 'server-ip' - split files by server IP, meaning all connections with" << std::endl - << " the same server IP will be in the same file" << std::endl - << " 'server-port' - split files by server port, meaning all connections with" << std::endl - << " the same server port will be in the same file" << std::endl - << " 'client-port' - split files by client port, meaning all connections with" << std::endl - << " the same client port will be in the same file" << std::endl - << " 'ip-src-dst' - split files by IP src and dst (2-tuple), meaning all connections" << std::endl - << " with the same IPs will be in the same file" << std::endl - << " 'connection' - split files by connection (5-tuple), meaning all packets" << std::endl - << " of a connection will be in the same file" << std::endl - << " 'bpf-filter' - split file into two files: one that contains all packets" << std::endl - << " matching the given BPF filter (file #0) and one that contains" << std::endl - << " the rest of the packets (file #1)" << std::endl - << " 'round-robin' - split the file in a round-robin manner - each packet to a" << std::endl - << " different file" << std::endl - << " -p split-param : The relevant parameter for the split method:" << std::endl - << " 'method = file-size' => split-param is the max size per file (in bytes)." << std::endl - << " split-param is required for this method" << std::endl - << " 'method = packet-count' => split-param is the number of packet per file." << std::endl - << " split-param is required for this method" << std::endl - << " 'method = client-ip' => split-param is max number of files to open." << std::endl - << " If not provided the default is unlimited number of files" << std::endl - << " 'method = server-ip' => split-param is max number of files to open." << std::endl - << " If not provided the default is unlimited number of files" << std::endl - << " 'method = server-port' => split-param is max number of files to open." << std::endl - << " If not provided the default is unlimited number of files" << std::endl - << " 'method = ip-src-dst' => split-param is max number of files to open." << std::endl - << " If not provided the default is unlimited number of files" << std::endl - << " 'method = connection' => split-param is max number of files to open." << std::endl - << " If not provided the default is unlimited number of files" << std::endl - << " 'method = bpf-filter' => split-param is the BPF filter to match upon" << std::endl - << " 'method = round-robin' => split-param is number of files to round-robin packets between" << std::endl - << " -i filter : Apply a BPF filter, meaning only filtered packets will be counted in the split" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() << " [-h] [-v] [-i filter] -f pcap_file -o output_dir -m split_method [-p split_param]" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -f pcap_file : Input pcap file name" << std::endl + << " -o output_dir : The directory where the output files shall be written" << std::endl + << " -m split_method : The method to split with. Can take one of the following params:" << std::endl + << " 'file-size' - split files by size in bytes" << std::endl + << " 'packet-count' - split files by packet count" << std::endl + << " 'client-ip' - split files by client IP, meaning all connections with" << std::endl + << " the same client IP will be in the same file" << std::endl + << " 'server-ip' - split files by server IP, meaning all connections with" << std::endl + << " the same server IP will be in the same file" << std::endl + << " 'server-port' - split files by server port, meaning all connections with" + << std::endl + << " the same server port will be in the same file" << std::endl + << " 'client-port' - split files by client port, meaning all connections with" + << std::endl + << " the same client port will be in the same file" << std::endl + << " 'ip-src-dst' - split files by IP src and dst (2-tuple), meaning all connections" + << std::endl + << " with the same IPs will be in the same file" << std::endl + << " 'connection' - split files by connection (5-tuple), meaning all packets" + << std::endl + << " of a connection will be in the same file" << std::endl + << " 'bpf-filter' - split file into two files: one that contains all packets" + << std::endl + << " matching the given BPF filter (file #0) and one that contains" + << std::endl + << " the rest of the packets (file #1)" << std::endl + << " 'round-robin' - split the file in a round-robin manner - each packet to a" + << std::endl + << " different file" << std::endl + << " -p split-param : The relevant parameter for the split method:" << std::endl + << " 'method = file-size' => split-param is the max size per file (in bytes)." + << std::endl + << " split-param is required for this method" << std::endl + << " 'method = packet-count' => split-param is the number of packet per file." << std::endl + << " split-param is required for this method" << std::endl + << " 'method = client-ip' => split-param is max number of files to open." << std::endl + << " If not provided the default is unlimited number of files" + << std::endl + << " 'method = server-ip' => split-param is max number of files to open." << std::endl + << " If not provided the default is unlimited number of files" + << std::endl + << " 'method = server-port' => split-param is max number of files to open." << std::endl + << " If not provided the default is unlimited number of files" + << std::endl + << " 'method = ip-src-dst' => split-param is max number of files to open." << std::endl + << " If not provided the default is unlimited number of files" + << std::endl + << " 'method = connection' => split-param is max number of files to open." << std::endl + << " If not provided the default is unlimited number of files" + << std::endl + << " 'method = bpf-filter' => split-param is the BPF filter to match upon" << std::endl + << " 'method = round-robin' => split-param is number of files to round-robin packets " + "between" + << std::endl + << " -i filter : Apply a BPF filter, meaning only filtered packets will be counted in the split" + << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -h : Displays this help message and exits" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * An auxiliary method for extracting the file name without the extension from a file path, * for example: for the input '/home/myuser/mypcap.pcap' -> return value will be 'mypcap' @@ -186,7 +198,7 @@ std::string getFileNameWithoutExtension(const std::string& path) if (i != std::string::npos) { // extract filename from path - std::string fileNameWithExtension = path.substr(i+1, path.length() - i); + std::string fileNameWithExtension = path.substr(i + 1, path.length() - i); // from the file name - remove the extension (the part after the ".") i = fileNameWithExtension.rfind('.', fileNameWithExtension.length()); @@ -207,10 +219,9 @@ std::string getFileNameWithoutExtension(const std::string& path) return path; } - return(""); + return (""); } - /** * main method of this utility */ @@ -233,37 +244,37 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "f:o:m:p:i:vh", PcapSplitterOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "f:o:m:p:i:vh", PcapSplitterOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'f': - inputPcapFileName = optarg; - break; - case 'o': - outputPcapDir = optarg; - break; - case 'm': - method = optarg; - break; - case 'p': - strncpy(param, optarg, 999); - paramWasSet = true; - break; - case 'i': - filter = optarg; - break; - case 'h': - printUsage(); - exit(0); - case 'v': - printAppVersion(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'f': + inputPcapFileName = optarg; + break; + case 'o': + outputPcapDir = optarg; + break; + case 'm': + method = optarg; + break; + case 'p': + strncpy(param, optarg, 999); + paramWasSet = true; + break; + case 'i': + filter = optarg; + break; + case 'h': + printUsage(); + exit(0); + case 'v': + printAppVersion(); + break; + default: + printUsage(); + exit(-1); } } @@ -342,7 +353,6 @@ int main(int argc, char* argv[]) else EXIT_WITH_ERROR("Unknown method '" << method << "'"); - // verify splitter param is legal, otherwise return an error std::string errorStr; if (!splitter->isSplitterParamLegal(errorStr)) @@ -352,7 +362,8 @@ int main(int argc, char* argv[]) } // prepare the output file format: /requested-path/original-file-name-[4-digit-number-starting-at-0000].pcap - std::string outputPcapFileName = outputPcapDir + std::string(1, SEPARATOR) + getFileNameWithoutExtension(inputPcapFileName) + "-"; + std::string outputPcapFileName = + outputPcapDir + std::string(1, SEPARATOR) + getFileNameWithoutExtension(inputPcapFileName) + "-"; // open a pcap file for reading pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader(inputPcapFileName); @@ -397,7 +408,8 @@ int main(int argc, char* argv[]) if (outputFiles.find(fileNum) == outputFiles.end()) { // get file name from the splitter and add the .pcap extension - std::string fileName = splitter->getFileName(parsedPacket, outputPcapFileName, fileNum) + outputFileExtenison; + std::string fileName = + splitter->getFileName(parsedPacket, outputPcapFileName, fileNum) + outputFileExtenison; // create a new IFileWriterDevice for this file if (isReaderPcapng) @@ -423,7 +435,8 @@ int main(int argc, char* argv[]) else if (outputFiles[fileNum] == nullptr) { // get file name from the splitter and add the .pcap extension - std::string fileName = splitter->getFileName(parsedPacket, outputPcapFileName, fileNum) + outputFileExtenison; + std::string fileName = + splitter->getFileName(parsedPacket, outputPcapFileName, fileNum) + outputFileExtenison; // re-create the IFileWriterDevice object if (isReaderPcapng) @@ -446,7 +459,7 @@ int main(int argc, char* argv[]) outputFiles[fileNum]->writePacket(*parsedPacket.getRawPacket()); // if splitter wants us to close files - go over the file numbers and close them - for (const auto &fileId : filesToClose) + for (const auto& fileId : filesToClose) { // check if that file number is in the map if (outputFiles.find(fileId) != outputFiles.end()) @@ -463,7 +476,8 @@ int main(int argc, char* argv[]) ++packetCountSoFar; } - std::cout << "Finished. Read and written " << packetCountSoFar << " packets to " << numOfFiles << " files" << std::endl; + std::cout << "Finished. Read and written " << packetCountSoFar << " packets to " << numOfFiles << " files" + << std::endl; // close the reader file reader->close(); @@ -473,7 +487,7 @@ int main(int argc, char* argv[]) delete splitter; // close the writer files which are still open - for(const auto &it : outputFiles) + for (const auto& it : outputFiles) { if (it.second != NULL) { diff --git a/Examples/PfRingExample-FilterTraffic/Common.h b/Examples/PfRingExample-FilterTraffic/Common.h index f54a7bc4d5..587c4916d7 100644 --- a/Examples/PfRingExample-FilterTraffic/Common.h +++ b/Examples/PfRingExample-FilterTraffic/Common.h @@ -12,20 +12,23 @@ #include #include - /** * Macros for exiting the application with error */ -#define EXIT_WITH_ERROR(reason) do { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) -#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ +#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ } while (0) /** @@ -49,7 +52,10 @@ struct PacketStats int MatchedUdpFlows; int MatchedPackets; - PacketStats() : ThreadId(MAX_NUM_OF_CORES+1), PacketCount(0), EthCount(0), ArpCount(0), Ip4Count(0), Ip6Count(0), TcpCount(0), UdpCount(0), HttpCount(0), MatchedTcpFlows(0), MatchedUdpFlows(0), MatchedPackets(0) {} + PacketStats() + : ThreadId(MAX_NUM_OF_CORES + 1), PacketCount(0), EthCount(0), ArpCount(0), Ip4Count(0), Ip6Count(0), + TcpCount(0), UdpCount(0), HttpCount(0), MatchedTcpFlows(0), MatchedUdpFlows(0), MatchedPackets(0) + {} void collectStats(pcpp::Packet& packet) { @@ -86,12 +92,26 @@ struct PacketStats MatchedPackets += stats.MatchedPackets; } - void clear() { ThreadId = MAX_NUM_OF_CORES+1; PacketCount = 0; EthCount = 0; ArpCount = 0; Ip4Count = 0; Ip6Count = 0; TcpCount = 0; UdpCount = 0; HttpCount = 0; MatchedTcpFlows = 0; MatchedUdpFlows = 0; MatchedPackets = 0; } + void clear() + { + ThreadId = MAX_NUM_OF_CORES + 1; + PacketCount = 0; + EthCount = 0; + ArpCount = 0; + Ip4Count = 0; + Ip6Count = 0; + TcpCount = 0; + UdpCount = 0; + HttpCount = 0; + MatchedTcpFlows = 0; + MatchedUdpFlows = 0; + MatchedPackets = 0; + } - std::string getStatValuesAsString(const std::string &delimiter) + std::string getStatValuesAsString(const std::string& delimiter) { std::stringstream values; - if (ThreadId == MAX_NUM_OF_CORES+1) + if (ThreadId == MAX_NUM_OF_CORES + 1) values << "Total" << delimiter; else values << (int)ThreadId << delimiter; @@ -110,14 +130,13 @@ struct PacketStats return values.str(); } - static void getStatsColumns(std::vector& columnNames, std::vector& columnWidths) { columnNames.clear(); columnWidths.clear(); - static const int narrowColumnWidth = 11; - static const int wideColumnWidth = 18; + static const int narrowColumnWidth = 11; + static const int wideColumnWidth = 18; columnNames.push_back("Core ID"); columnNames.push_back("Packet Cnt"); @@ -144,6 +163,5 @@ struct PacketStats columnWidths.push_back(wideColumnWidth); columnWidths.push_back(wideColumnWidth); columnWidths.push_back(wideColumnWidth); - } }; diff --git a/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h b/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h index c19bc2949d..1a74629640 100644 --- a/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h +++ b/Examples/PfRingExample-FilterTraffic/PacketMatchingEngine.h @@ -7,8 +7,9 @@ #include "UdpLayer.h" /** - * Responsible for matching packets by match criteria received from the user. Current match criteria are a combination of zero or more of the - * following parameters: source IP, dest IP, source TCP/UDP port, dest TCP/UDP port and TCP/UDP protocol. + * Responsible for matching packets by match criteria received from the user. Current match criteria are a combination + * of zero or more of the following parameters: source IP, dest IP, source TCP/UDP port, dest TCP/UDP port and TCP/UDP + * protocol. */ class PacketMatchingEngine { @@ -19,11 +20,13 @@ class PacketMatchingEngine bool m_MatchSrcIp, m_MatchDstIp; bool m_MatchSrcPort, m_MatchDstPort; bool m_MatchProtocol; + public: - PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) - : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), - m_SrcPortToMatch(srcPortToMatch), m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), - m_MatchSrcIp(false), m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) + PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, + uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) + : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), m_SrcPortToMatch(srcPortToMatch), + m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), m_MatchSrcIp(false), + m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) { if (m_SrcIpToMatch != pcpp::IPv4Address::Zero) m_MatchSrcIp = true; diff --git a/Examples/PfRingExample-FilterTraffic/main.cpp b/Examples/PfRingExample-FilterTraffic/main.cpp index d9b2cdbc9f..81b58c65dc 100644 --- a/Examples/PfRingExample-FilterTraffic/main.cpp +++ b/Examples/PfRingExample-FilterTraffic/main.cpp @@ -2,29 +2,31 @@ * Filter Traffic PF_RING example application * ========================================== * An application that listens to one or more PF_RING interface, captures all traffic - * and matches packets by user-defined matching criteria. Matching criteria is given on startup and can contain one or more of the following: - * source IP, destination IP, source TCP/UDP port, destination TCP/UDP port and TCP or UDP protocol. Matching is done per flow, meaning the first packet - * received on a flow is matched against the matching criteria and if it's matched then all packets of the same flow will be matched too. - * Packets that are matched can be send to another PF_RING interface and/or be save to a pcap file. - * In addition the application collect statistics on received and matched packets: number of packets per protocol, number of matched flows and number - * of matched packets. + * and matches packets by user-defined matching criteria. Matching criteria is given on startup and can contain one or + * more of the following: source IP, destination IP, source TCP/UDP port, destination TCP/UDP port and TCP or UDP + * protocol. Matching is done per flow, meaning the first packet received on a flow is matched against the matching + * criteria and if it's matched then all packets of the same flow will be matched too. Packets that are matched can be + * send to another PF_RING interface and/or be save to a pcap file. In addition the application collect statistics on + * received and matched packets: number of packets per protocol, number of matched flows and number of matched packets. * - * The application uses PfRingDevice's multi-threaded capturing. Number of capture threads can be set by the user (to the maximum of machine's core number minus 1) - * or set to default (default is all machine cores minus one management core the application runs on). Each core is assigned with one capture thread. - * PfRingDevice tries to assign one RX channel for each capturing thread (to improve performance), but if NIC doesn't enough RX channels to - * provide one for each thread, it will assign several thread with the same RX channel - * For example: if NIC supports 4 RX channels but the user asks for 6 capturing threads than 4 cores will share 2 RX channels and the 2 remaining cores will - * use RX channels of their own. - * Each capturing thread does exactly the same work: receiving packets, collecting packet statistics, matching flows and sending/saving matched packets + * The application uses PfRingDevice's multi-threaded capturing. Number of capture threads can be set by the user (to + * the maximum of machine's core number minus 1) or set to default (default is all machine cores minus one management + * core the application runs on). Each core is assigned with one capture thread. PfRingDevice tries to assign one RX + * channel for each capturing thread (to improve performance), but if NIC doesn't enough RX channels to provide one for + * each thread, it will assign several thread with the same RX channel For example: if NIC supports 4 RX channels but + * the user asks for 6 capturing threads than 4 cores will share 2 RX channels and the 2 remaining cores will use RX + * channels of their own. Each capturing thread does exactly the same work: receiving packets, collecting packet + * statistics, matching flows and sending/saving matched packets * - * Another thing shown here is getting interface capabilities such as total RX channels available, MAC address, PF_RING interface - * index, MTU, etc. + * Another thing shown here is getting interface capabilities such as total RX channels available, MAC address, PF_RING + * interface index, MTU, etc. * * __Important__: - * 1. Before compiling this application make sure you set "Compile PcapPlusPlus with PF_RING" to "y" in configure-linux.sh. Otherwise - * the application won't compile - * 2. Before running the application make sure you load the PF_RING kernel module: sudo insmod /kernel/pf_ring.ko - * Otherwise the application will exit with an error log that instructs you to load the kernel module + * 1. Before compiling this application make sure you set "Compile PcapPlusPlus with PF_RING" to "y" in + * configure-linux.sh. Otherwise the application won't compile + * 2. Before running the application make sure you load the PF_RING kernel module: sudo insmod + * /kernel/pf_ring.ko Otherwise the application will exit with an error log that instructs you to load + * the kernel module * 3. This application (like all applications using PF_RING) should be run as 'sudo' */ @@ -44,24 +46,23 @@ #include #include - -static struct option PfFilterTrafficOptions[] = -{ - {"interface-name", required_argument, 0, 'n'}, - {"send-matched-packets", required_argument, 0, 's'}, - {"save-matched-packets", required_argument, 0, 'f'}, - {"match-source-ip", required_argument, 0, 'i'}, - {"match-dest-ip", required_argument, 0, 'I'}, - {"match-source-port", required_argument, 0, 'p'}, - {"match-dest-port", required_argument, 0, 'P'}, - {"match-protocol", required_argument, 0, 'r'}, - {"num-of-threads", required_argument, 0, 't'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'v'}, - {"list", no_argument, 0, 'l'}, - {0, 0, 0, 0} +// clang-format off +static struct option PfFilterTrafficOptions[] = { + { "interface-name", required_argument, 0, 'n' }, + { "send-matched-packets", required_argument, 0, 's' }, + { "save-matched-packets", required_argument, 0, 'f' }, + { "match-source-ip", required_argument, 0, 'i' }, + { "match-dest-ip", required_argument, 0, 'I' }, + { "match-source-port", required_argument, 0, 'p' }, + { "match-dest-port", required_argument, 0, 'P' }, + { "match-protocol", required_argument, 0, 'r' }, + { "num-of-threads", required_argument, 0, 't' }, + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "list", no_argument, 0, 'l' }, + { 0, 0, 0, 0 } }; - +// clang-format on /** * A struct that holds all arguments passed to capture threads: packetArrived() @@ -74,58 +75,67 @@ struct CaptureThreadArgs pcpp::PfRingDevice* sendPacketsTo; pcpp::PcapFileWriterDevice** pcapWriters; - CaptureThreadArgs() : packetStatArr(NULL), matchingEngine(NULL), flowTables(NULL), sendPacketsTo(NULL), pcapWriters(NULL) {} + CaptureThreadArgs() + : packetStatArr(NULL), matchingEngine(NULL), flowTables(NULL), sendPacketsTo(NULL), pcapWriters(NULL) + {} }; - /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvl] [-s INTERFACE_NAME] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" << std::endl - << " [-c NUM_OF_THREADS] -n INTERFACE_NAME" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl - << " -l|--list : Print the list of PF_RING devices and exit" << std::endl - << " -n|--interface-name INTERFACE_NAME : A PF_RING interface name to receive packets from." << std::endl - << " To see all available interfaces use the -l switch" << std::endl - << " -s|--send-matched-packets INTERFACE_NAME : PF_RING interface name to send matched packets to" << std::endl - << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." << std::endl - << " Packets matched by thread X will be saved under" << std::endl - << " 'FILEPATH/ThreadX.pcap'" << std::endl - << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl - << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl - << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl - << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl - << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" << std::endl - << " -t|--num-of-threads NUM_OF_THREADS : Number of capture threads to open. Should be in" << std::endl - << " the range of 1 to NUM_OF_CORES_ON_MACHINE-1." << std::endl - << " Default is using all machine cores except the core" << std::endl - << " the application is running on" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() + << " [-hvl] [-s INTERFACE_NAME] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL]" + << std::endl + << " [-c NUM_OF_THREADS] -n INTERFACE_NAME" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h|--help : Displays this help message and exits" << std::endl + << " -v|--version : Displays the current version and exits" << std::endl + << " -l|--list : Print the list of PF_RING devices and exit" << std::endl + << " -n|--interface-name INTERFACE_NAME : A PF_RING interface name to receive packets from." + << std::endl + << " To see all available interfaces use the -l switch" + << std::endl + << " -s|--send-matched-packets INTERFACE_NAME : PF_RING interface name to send matched packets to" + << std::endl + << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." + << std::endl + << " Packets matched by thread X will be saved under" + << std::endl + << " 'FILEPATH/ThreadX.pcap'" << std::endl + << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl + << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl + << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl + << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl + << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" + << std::endl + << " -t|--num-of-threads NUM_OF_THREADS : Number of capture threads to open. Should be in" + << std::endl + << " the range of 1 to NUM_OF_CORES_ON_MACHINE-1." << std::endl + << " Default is using all machine cores except the core" + << std::endl + << " the application is running on" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Print to console all available PF_RING devices. Used by the -l switch */ @@ -135,7 +145,7 @@ void listPfRingDevices() pcpp::Logger::getInstance().suppressLogs(); const std::vector& devList = pcpp::PfRingDeviceList::getInstance().getPfRingDevicesList(); - for (const auto &dev : devList) + for (const auto& dev : devList) { std::ostringstream interfaceIndex; if (dev->getInterfaceIndex() <= 9999) @@ -147,26 +157,24 @@ void listPfRingDevices() interfaceIndex << "N/A"; } - std::cout - << " -> Name: " << std::left << std::setw(8) << dev->getDeviceName() - << " Index: " << std::setw(5) << interfaceIndex.str() - << " MAC address: " << std::setw(19) << (dev->getMacAddress() == pcpp::MacAddress::Zero ? "N/A" : dev->getMacAddress().toString()) - << " Available RX channels: " << std::setw(3) << (int)dev->getTotalNumOfRxChannels() - << " MTU: " << dev->getMtu() - << std::endl; + std::cout << " -> Name: " << std::left << std::setw(8) << dev->getDeviceName() << " Index: " << std::setw(5) + << interfaceIndex.str() << " MAC address: " << std::setw(19) + << (dev->getMacAddress() == pcpp::MacAddress::Zero ? "N/A" : dev->getMacAddress().toString()) + << " Available RX channels: " << std::setw(3) << (int)dev->getTotalNumOfRxChannels() + << " MTU: " << dev->getMtu() << std::endl; } // re-enable errors pcpp::Logger::getInstance().enableLogs(); } - /** - * The method that is called each time a packet is received on any of the threads. It collects all relevant stats for the packet and - * matches it with the matching engine. If packet is matched it sends it to the TX interface (if needed) or writes it to - * the thread's pcap file (if needed) + * The method that is called each time a packet is received on any of the threads. It collects all relevant stats for + * the packet and matches it with the matching engine. If packet is matched it sends it to the TX interface (if needed) + * or writes it to the thread's pcap file (if needed) */ -void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* device, void* userCookie) +void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, pcpp::PfRingDevice* device, + void* userCookie) { CaptureThreadArgs* args = (CaptureThreadArgs*)userCookie; for (uint32_t i = 0; i < numOfPackets; i++) @@ -179,16 +187,17 @@ void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t thre bool packetMatched = false; - // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or new flow + // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or + // new flow uint32_t hash = pcpp::hash5Tuple(&packet); std::unordered_map::const_iterator iter = args->flowTables[threadId].find(hash); // if packet belongs to an already existing flow - if (iter !=args->flowTables[threadId].end() && iter->second) + if (iter != args->flowTables[threadId].end() && iter->second) { packetMatched = true; } - else // packet belongs to a new flow + else // packet belongs to a new flow { packetMatched = args->matchingEngine->isMatched(packet); if (packetMatched) @@ -196,7 +205,7 @@ void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t thre // put new flow in flow table args->flowTables[threadId][hash] = true; - //collect stats + // collect stats if (packet.isPacketOfType(pcpp::TCP)) { args->packetStatArr[threadId].MatchedTcpFlows++; @@ -205,7 +214,6 @@ void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t thre { args->packetStatArr[threadId].MatchedUdpFlows++; } - } } @@ -228,7 +236,6 @@ void packetArrived(pcpp::RawPacket* packets, uint32_t numOfPackets, uint8_t thre } } - /** * The callback to be called when application is terminated by ctrl-c. Do cleanup and print summary stats */ @@ -239,7 +246,6 @@ void onApplicationInterrupted(void* cookie) *shouldStop = true; } - int main(int argc, char* argv[]) { pcpp::AppName::init(argc, argv); @@ -247,154 +253,156 @@ int main(int argc, char* argv[]) pcpp::PfRingDevice* dev = NULL; int totalNumOfCores = pcpp::getNumOfCores(); - int numOfCaptureThreads = totalNumOfCores-1; + int numOfCaptureThreads = totalNumOfCores - 1; pcpp::PfRingDevice* sendPacketsToIface = NULL; std::string packetFilePath = ""; bool writePacketsToDisk = true; - pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; - pcpp::IPv4Address dstIPToMatch = pcpp::IPv4Address::Zero; - uint16_t srcPortToMatch = 0; - uint16_t dstPortToMatch = 0; - pcpp::ProtocolType protocolToMatch = pcpp::UnknownProtocol; + pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; + pcpp::IPv4Address dstIPToMatch = pcpp::IPv4Address::Zero; + uint16_t srcPortToMatch = 0; + uint16_t dstPortToMatch = 0; + pcpp::ProtocolType protocolToMatch = pcpp::UnknownProtocol; int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "n:s:t:f:i:I:p:P:r:hvl", PfFilterTrafficOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "n:s:t:f:i:I:p:P:r:hvl", PfFilterTrafficOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'n': - { - std::string ifaceName = std::string(optarg); - dev = pcpp::PfRingDeviceList::getInstance().getPfRingDeviceByName(ifaceName); - if (dev == NULL) - EXIT_WITH_ERROR("Could not find PF_RING device '" << ifaceName << "'"); - break; - } - case 's': - { - std::string sendPacketsToIfaceName = std::string(optarg); - sendPacketsToIface = pcpp::PfRingDeviceList::getInstance().getPfRingDeviceByName(sendPacketsToIfaceName); - if (sendPacketsToIface == NULL) - EXIT_WITH_ERROR("Could not find PF_RING device '" << sendPacketsToIfaceName << "'"); + case 0: + { + break; + } + case 'n': + { + std::string ifaceName = std::string(optarg); + dev = pcpp::PfRingDeviceList::getInstance().getPfRingDeviceByName(ifaceName); + if (dev == NULL) + EXIT_WITH_ERROR("Could not find PF_RING device '" << ifaceName << "'"); + break; + } + case 's': + { + std::string sendPacketsToIfaceName = std::string(optarg); + sendPacketsToIface = pcpp::PfRingDeviceList::getInstance().getPfRingDeviceByName(sendPacketsToIfaceName); + if (sendPacketsToIface == NULL) + EXIT_WITH_ERROR("Could not find PF_RING device '" << sendPacketsToIfaceName << "'"); - break; - } - case 't': - { - numOfCaptureThreads = atoi(optarg); - if (numOfCaptureThreads < 1 || numOfCaptureThreads > totalNumOfCores-1) - EXIT_WITH_ERROR("Number of capture threads must be in the range of 1 to " << totalNumOfCores-1); - break; - } - case 'f': - { - packetFilePath = std::string(optarg); - // make sure the path ends with '/' - if (packetFilePath.length() > 1 && (0 != packetFilePath.compare(packetFilePath.length()-1, 1, "/"))) - packetFilePath += "/"; + break; + } + case 't': + { + numOfCaptureThreads = atoi(optarg); + if (numOfCaptureThreads < 1 || numOfCaptureThreads > totalNumOfCores - 1) + EXIT_WITH_ERROR("Number of capture threads must be in the range of 1 to " << totalNumOfCores - 1); + break; + } + case 'f': + { + packetFilePath = std::string(optarg); + // make sure the path ends with '/' + if (packetFilePath.length() > 1 && (0 != packetFilePath.compare(packetFilePath.length() - 1, 1, "/"))) + packetFilePath += "/"; - writePacketsToDisk = true; - break; - } - case 'i': - { - try - { - srcIPToMatch = pcpp::IPv4Address(optarg); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); - } - break; - } - case 'I': - { - try - { - dstIPToMatch = pcpp::IPv4Address(optarg); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); - } - break; - } - case 'p': + writePacketsToDisk = true; + break; + } + case 'i': + { + try { - int ret = atoi(optarg); - if (ret <= 0 || ret > 65535) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); - } - srcPortToMatch = ret; - break; + srcIPToMatch = pcpp::IPv4Address(optarg); } - case 'P': + catch (const std::exception&) { - int ret = atoi(optarg); - if (ret <= 0 || ret > 65535) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); - } - dstPortToMatch = ret; - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); } - case 'r': + break; + } + case 'I': + { + try { - std::string protocol = std::string(optarg); - if (protocol == "TCP") - protocolToMatch = pcpp::TCP; - else if (protocol == "UDP") - protocolToMatch = pcpp::UDP; - else - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); - } - break; + dstIPToMatch = pcpp::IPv4Address(optarg); } - case 'h': + catch (const std::exception&) { - printUsage(); - exit(0); + EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); } - case 'v': + break; + } + case 'p': + { + int ret = atoi(optarg); + if (ret <= 0 || ret > 65535) { - printAppVersion(); - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); } - case 'l': + srcPortToMatch = ret; + break; + } + case 'P': + { + int ret = atoi(optarg); + if (ret <= 0 || ret > 65535) { - listPfRingDevices(); - exit(0); + EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); } - default: + dstPortToMatch = ret; + break; + } + case 'r': + { + std::string protocol = std::string(optarg); + if (protocol == "TCP") + protocolToMatch = pcpp::TCP; + else if (protocol == "UDP") + protocolToMatch = pcpp::UDP; + else { - printUsage(); - exit(0); + EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); } + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } + case 'l': + { + listPfRingDevices(); + exit(0); + } + default: + { + printUsage(); + exit(0); + } } } if (dev == NULL) EXIT_WITH_ERROR_AND_PRINT_USAGE("Interface name was not provided"); - // open the PF_RING device in multi-thread mode. Distribution of packets between threads will be done per-flow (as opposed to - // round-robin) + // open the PF_RING device in multi-thread mode. Distribution of packets between threads will be done per-flow (as + // opposed to round-robin) if (!dev->openMultiRxChannels(numOfCaptureThreads, pcpp::PfRingDevice::PerFlow)) - EXIT_WITH_ERROR("Couldn't open " << numOfCaptureThreads << " RX channels on interface '" << dev->getDeviceName() << "'"); + EXIT_WITH_ERROR("Couldn't open " << numOfCaptureThreads << " RX channels on interface '" << dev->getDeviceName() + << "'"); if (sendPacketsToIface != NULL && !sendPacketsToIface->open()) - EXIT_WITH_ERROR("Couldn't open PF_RING device '" << sendPacketsToIface->getDeviceName() << "' for sending matched packets"); + EXIT_WITH_ERROR("Couldn't open PF_RING device '" << sendPacketsToIface->getDeviceName() + << "' for sending matched packets"); pcpp::CoreMask coreMask = 0; int threadId = 0; @@ -405,7 +413,7 @@ int main(int argc, char* argv[]) // init each packet stats instance with an illegal core ID for (int coreId = 0; coreId < totalNumOfCores; coreId++) - packetStatsArr[coreId].ThreadId = MAX_NUM_OF_CORES+1; + packetStatsArr[coreId].ThreadId = MAX_NUM_OF_CORES + 1; // mark only relevant cores by adding them to core mask // mark only relevant packet stats instances by setting their core ID @@ -453,8 +461,8 @@ int main(int argc, char* argv[]) } } - - std::cout << "Start capturing on " << numOfCaptureThreads << " threads core mask = 0x" << std::hex << coreMask << std::dec << std::endl; + std::cout << "Start capturing on " << numOfCaptureThreads << " threads core mask = 0x" << std::hex << coreMask + << std::dec << std::endl; // prepare packet capture configuration CaptureThreadArgs args; @@ -467,7 +475,8 @@ int main(int argc, char* argv[]) // start capturing packets on all threads if (!dev->startCaptureMultiThread(packetArrived, &args, coreMask)) { - EXIT_WITH_ERROR("Couldn't start capturing on core mask 0x" << std::hex << coreMask << " on interface '" << dev->getDeviceName() << "'"); + EXIT_WITH_ERROR("Couldn't start capturing on core mask 0x" << std::hex << coreMask << " on interface '" + << dev->getDeviceName() << "'"); } bool shouldStop = false; @@ -498,9 +507,7 @@ int main(int argc, char* argv[]) } } - std::cout << std::endl << std::endl - << "Application stopped" - << std::endl; + std::cout << std::endl << std::endl << "Application stopped" << std::endl; // print final stats for every capture thread plus sum of all threads and free worker threads memory PacketStats aggregatedStats; @@ -513,7 +520,7 @@ int main(int argc, char* argv[]) for (int i = 0; i < totalNumOfCores; i++) { - if (packetStatsArr[i].ThreadId == MAX_NUM_OF_CORES+1) + if (packetStatsArr[i].ThreadId == MAX_NUM_OF_CORES + 1) continue; aggregatedStats.collectStats(packetStatsArr[i]); diff --git a/Examples/SSLAnalyzer/SSLStatsCollector.h b/Examples/SSLAnalyzer/SSLStatsCollector.h index ebb036c73d..6cf55a0a87 100644 --- a/Examples/SSLAnalyzer/SSLStatsCollector.h +++ b/Examples/SSLAnalyzer/SSLStatsCollector.h @@ -9,14 +9,15 @@ #include "SSLLayer.h" #include "SystemUtils.h" - /** * An auxiliary struct for encapsulating rate stats */ struct Rate { - double currentRate; // periodic rate - double totalRate; // overall rate + // periodic rate + double currentRate; + // overall rate + double totalRate; }; /** @@ -24,19 +25,32 @@ struct Rate */ struct SSLGeneralStats { - int numOfSSLFlows; // total number of SSL flows - Rate sslFlowRate; // rate of SSL flows - int numOfSSLPackets; // total number of SSL packets - Rate sslPacketRate; // rate of SSL packets - double averageNumOfPacketsPerFlow; // average number of SSL packets per flow - int amountOfSSLTraffic; // total SSL traffic in bytes - double averageAmountOfDataPerFlow; // average number of SSL traffic per flow - Rate sslTrafficRate; // rate of SSL traffic - double sampleTime; // total stats collection time - int numOfHandshakeCompleteFlows; // number of flows which handshake was complete - int numOfFlowsWithAlerts; // number of flows that were terminated because of SSL/TLS alert - std::unordered_map sslVersionCount; // number of flows per SSL/TLS version - std::unordered_map sslPortCount; // number of flows per TCP port + // total number of SSL flows + int numOfSSLFlows; + // rate of SSL flows + Rate sslFlowRate; + // total number of SSL packets + int numOfSSLPackets; + // rate of SSL packets + Rate sslPacketRate; + // average number of SSL packets per flow + double averageNumOfPacketsPerFlow; + // total SSL traffic in bytes + int amountOfSSLTraffic; + // average number of SSL traffic per flow + double averageAmountOfDataPerFlow; + // rate of SSL traffic + Rate sslTrafficRate; + // total stats collection time + double sampleTime; + // number of flows which handshake was complete + int numOfHandshakeCompleteFlows; + // number of flows that were terminated because of SSL/TLS alert + int numOfFlowsWithAlerts; + // number of flows per SSL/TLS version + std::unordered_map sslVersionCount; + // number of flows per TCP port + std::unordered_map sslPortCount; void clear() { @@ -59,17 +73,20 @@ struct SSLGeneralStats } }; - /** * A base struct for collecting stats on client-hello messages */ struct ClientHelloStats { - int numOfMessages; // total number of client-hello messages - Rate messageRate; // rate of client-hello messages - std::unordered_map serverNameCount; // a map for counting the server names seen in traffic + // total number of client-hello messages + int numOfMessages; + // rate of client-hello messages + Rate messageRate; + // a map for counting the server names seen in traffic + std::unordered_map serverNameCount; - virtual ~ClientHelloStats() {} + virtual ~ClientHelloStats() + {} virtual void clear() { @@ -85,11 +102,15 @@ struct ClientHelloStats */ struct ServerHelloStats { - int numOfMessages; // total number of server-hello messages - Rate messageRate; // rate of server-hello messages - std::unordered_map cipherSuiteCount; // count of the different chosen cipher-suites + // total number of server-hello messages + int numOfMessages; + // rate of server-hello messages + Rate messageRate; + // count of the different chosen cipher-suites + std::unordered_map cipherSuiteCount; - virtual ~ServerHelloStats() {} + virtual ~ServerHelloStats() + {} virtual void clear() { @@ -100,14 +121,12 @@ struct ServerHelloStats } }; - /** * The SSL stats collector. Should be called for every packet arriving and also periodically to calculate rates */ class SSLStatsCollector { public: - /** * C'tor - clear all structures */ @@ -149,22 +168,27 @@ class SSLStatsCollector // getting time from last rate calculation until now double diffSec = curTime - m_LastCalcRateTime; - // calculating current rates which are the changes from last rate calculation until now divided by the time passed from - // last rate calculation until now + // calculating current rates which are the changes from last rate calculation until now divided by the time + // passed from last rate calculation until now if (diffSec != 0) { - m_GeneralStats.sslTrafficRate.currentRate = (m_GeneralStats.amountOfSSLTraffic - m_PrevGeneralStats.amountOfSSLTraffic) / diffSec; - m_GeneralStats.sslPacketRate.currentRate = (m_GeneralStats.numOfSSLPackets - m_PrevGeneralStats.numOfSSLPackets) / diffSec; - m_GeneralStats.sslFlowRate.currentRate = (m_GeneralStats.numOfSSLFlows - m_PrevGeneralStats.numOfSSLFlows) / diffSec; - m_ClientHelloStats.messageRate.currentRate = (m_ClientHelloStats.numOfMessages - m_PrevClientHelloStats.numOfMessages) / diffSec; - m_ServerHelloStats.messageRate.currentRate = (m_ServerHelloStats.numOfMessages - m_PrevServerHelloStats.numOfMessages) / diffSec; + m_GeneralStats.sslTrafficRate.currentRate = + (m_GeneralStats.amountOfSSLTraffic - m_PrevGeneralStats.amountOfSSLTraffic) / diffSec; + m_GeneralStats.sslPacketRate.currentRate = + (m_GeneralStats.numOfSSLPackets - m_PrevGeneralStats.numOfSSLPackets) / diffSec; + m_GeneralStats.sslFlowRate.currentRate = + (m_GeneralStats.numOfSSLFlows - m_PrevGeneralStats.numOfSSLFlows) / diffSec; + m_ClientHelloStats.messageRate.currentRate = + (m_ClientHelloStats.numOfMessages - m_PrevClientHelloStats.numOfMessages) / diffSec; + m_ServerHelloStats.messageRate.currentRate = + (m_ServerHelloStats.numOfMessages - m_PrevServerHelloStats.numOfMessages) / diffSec; } // getting the time from the beginning of stats collection until now double diffSecTotal = curTime - m_StartTime; - // calculating total rate which is the change from beginning of stats collection until now divided by time passed from - // beginning of stats collection until now + // calculating total rate which is the change from beginning of stats collection until now divided by time + // passed from beginning of stats collection until now if (diffSecTotal != 0) { m_GeneralStats.sslTrafficRate.totalRate = m_GeneralStats.amountOfSSLTraffic / diffSecTotal; @@ -201,27 +225,37 @@ class SSLStatsCollector /** * Get SSL general stats */ - SSLGeneralStats& getGeneralStats() { return m_GeneralStats; } + SSLGeneralStats& getGeneralStats() + { + return m_GeneralStats; + } /** * Get client-hello stats */ - ClientHelloStats& getClientHelloStats() { return m_ClientHelloStats; } + ClientHelloStats& getClientHelloStats() + { + return m_ClientHelloStats; + } /** * Get server-hello stats */ - ServerHelloStats& getServerHelloStats() { return m_ServerHelloStats; } + ServerHelloStats& getServerHelloStats() + { + return m_ServerHelloStats; + } private: - /** * Auxiliary data collected for each flow for help calculating stats on this flow */ struct SSLFlowData { - bool seenAppDataPacket; // was SSL application data seen in this flow - bool seenAlertPacket; // was SSL alert packet seen in this flow + // was SSL application data seen in this flow + bool seenAppDataPacket; + // was SSL alert packet seen in this flow + bool seenAlertPacket; void clear() { @@ -230,7 +264,6 @@ class SSLStatsCollector } }; - /** * Collect stats relevant for every SSL packet (any SSL message) * This method calculates and returns the flow key for this packet @@ -268,8 +301,10 @@ class SSLStatsCollector // calculate averages if (m_FlowTable.size() != 0) { - m_GeneralStats.averageAmountOfDataPerFlow = (double)m_GeneralStats.amountOfSSLTraffic / (double)m_FlowTable.size(); - m_GeneralStats.averageNumOfPacketsPerFlow = (double)m_GeneralStats.numOfSSLPackets / (double)m_FlowTable.size(); + m_GeneralStats.averageAmountOfDataPerFlow = + (double)m_GeneralStats.amountOfSSLTraffic / (double)m_FlowTable.size(); + m_GeneralStats.averageNumOfPacketsPerFlow = + (double)m_GeneralStats.numOfSSLPackets / (double)m_FlowTable.size(); } return hashVal; @@ -315,7 +350,8 @@ class SSLStatsCollector continue; // try to find client-hello message - pcpp::SSLClientHelloMessage* clientHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); // collect client-hello stats if (clientHelloMessage != NULL) @@ -324,7 +360,8 @@ class SSLStatsCollector } // try to find server-hello message - pcpp::SSLServerHelloMessage* serverHelloMessage = handshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerHelloMessage* serverHelloMessage = + handshakeLayer->getHandshakeMessageOfType(); // collect server-hello stats if (serverHelloMessage != NULL) @@ -345,7 +382,8 @@ class SSLStatsCollector { m_ClientHelloStats.numOfMessages++; - pcpp::SSLServerNameIndicationExtension* sniExt = clientHelloMessage->getExtensionOfType(); + pcpp::SSLServerNameIndicationExtension* sniExt = + clientHelloMessage->getExtensionOfType(); if (sniExt != NULL) m_ClientHelloStats.serverNameCount[sniExt->getHostName()]++; } @@ -364,11 +402,11 @@ class SSLStatsCollector double getCurTime(void) { - struct timeval tv; + struct timeval tv; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); - return (((double) tv.tv_sec) + (double) (tv.tv_usec / 1000000.0)); + return (((double)tv.tv_sec) + (double)(tv.tv_usec / 1000000.0)); } SSLGeneralStats m_GeneralStats; diff --git a/Examples/SSLAnalyzer/main.cpp b/Examples/SSLAnalyzer/main.cpp index 0bba4d8155..bbc6941cbe 100644 --- a/Examples/SSLAnalyzer/main.cpp +++ b/Examples/SSLAnalyzer/main.cpp @@ -1,9 +1,9 @@ /** * SSLAnalyzer application * ======================== - * This application analyzes SSL/TLS traffic and presents detailed and diverse information about it. It can operate in live traffic - * mode where this information is collected on live packets or in file mode where packets are being read from a pcap/pcapng file. The - * information collected by this application includes: + * This application analyzes SSL/TLS traffic and presents detailed and diverse information about it. It can operate in + * live traffic mode where this information is collected on live packets or in file mode where packets are being read + * from a pcap/pcapng file. The information collected by this application includes: * - general data: number of packets, packet rate, amount of traffic, bandwidth * - flow data: number of flow, flow rate, average packets per flow, average data per flow * - SSL/TLS data: number of client-hello and server-hello messages, number of flows ended with successful handshake, @@ -31,37 +31,34 @@ #include "PcapPlusPlusVersion.h" #include +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - - -#define PRINT_STAT_LINE(description, counter, measurement) \ - std::cout \ - << std::left << std::setw(46) << (std::string(description) + ":") \ - << std::right << std::setw(15) << std::fixed << std::showpoint << std::setprecision(3) << counter \ - << " [" << measurement << "]" << std::endl; - +#define PRINT_STAT_LINE(description, counter, measurement) \ + std::cout << std::left << std::setw(46) << (std::string(description) + ":") << std::right << std::setw(15) \ + << std::fixed << std::showpoint << std::setprecision(3) << counter << " [" << measurement << "]" \ + << std::endl; #define DEFAULT_CALC_RATES_PERIOD_SEC 2 - -static struct option SSLAnalyzerOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"input-file", required_argument, nullptr, 'f'}, - {"output-file", required_argument, nullptr, 'o'}, - {"rate-calc-period", required_argument, nullptr, 'r'}, - {"disable-rates-print", no_argument, nullptr, 'd'}, - {"list-interfaces", no_argument, nullptr, 'l'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +// clang-format off +static struct option SSLAnalyzerOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "input-file", required_argument, nullptr, 'f' }, + { "output-file", required_argument, nullptr, 'o' }, + { "rate-calc-period", required_argument, nullptr, 'r' }, + { "disable-rates-print", no_argument, nullptr, 'd' }, + { "list-interfaces", no_argument, nullptr, 'l' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { nullptr, 0, nullptr, 0 } }; - +// clang-format on struct SSLPacketArrivedData { @@ -69,70 +66,73 @@ struct SSLPacketArrivedData pcpp::PcapFileWriterDevice* pcapWriter; }; - /** * Print application usage */ void printUsage() { std::cout << std::endl - << "Usage: PCAP file mode:" << std::endl - << "----------------------" << std::endl - << pcpp::AppName::get() << " [-hv] -f input_file" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << std::endl - << "Usage: Live traffic mode:" << std::endl - << "-------------------------" << std::endl - << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] -i interface" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address" << std::endl - << " -o output_file : Save all captured SSL packets to a pcap file. Notice this may cause performance degradation" << std::endl - << " -r calc_period : The period in seconds to calculate rates. If not provided default is 2 seconds" << std::endl - << " -d : Disable periodic rates calculation" << std::endl - << " -v : Displays the current version and exists" << std::endl - << " -h : Displays this help message and exits" << std::endl - << " -l : Print the list of interfaces and exists" << std::endl - << std::endl; + << "Usage: PCAP file mode:" << std::endl + << "----------------------" << std::endl + << pcpp::AppName::get() << " [-hv] -f input_file" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -f : The input pcap/pcapng file to analyze. Required argument for this mode" + << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -h : Displays this help message and exits" << std::endl + << std::endl + << "Usage: Live traffic mode:" << std::endl + << "-------------------------" << std::endl + << pcpp::AppName::get() << " [-hvld] [-o output_file] [-r calc_period] -i interface" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " + "address" + << std::endl + << " -o output_file : Save all captured SSL packets to a pcap file. Notice this may cause performance " + "degradation" + << std::endl + << " -r calc_period : The period in seconds to calculate rates. If not provided default is 2 seconds" + << std::endl + << " -d : Disable periodic rates calculation" << std::endl + << " -v : Displays the current version and exists" << std::endl + << " -h : Displays this help message and exits" << std::endl + << " -l : Print the list of interfaces and exists" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for (const auto &dev : devList) + for (const auto& dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - -void printStatsHeadline(const std::string &description) +void printStatsHeadline(const std::string& description) { std::string underline; for (size_t i = 0; i < description.length(); i++) @@ -143,7 +143,6 @@ void printStatsHeadline(const std::string &description) std::cout << std::endl << description << std::endl << underline << std::endl << std::endl; } - /** * packet capture callback - called whenever a packet arrives */ @@ -152,7 +151,7 @@ void sslPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* c // parse the packet pcpp::Packet parsedPacket(packet); - SSLPacketArrivedData* data = (SSLPacketArrivedData*)cookie; + SSLPacketArrivedData* data = (SSLPacketArrivedData*)cookie; // give the packet to the collector data->statsCollector->collectStats(&parsedPacket); @@ -164,7 +163,6 @@ void sslPacketArrive(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, void* c } } - /** * An auxiliary method for sorting the string count map. Used in printServerNames() and in printCipherSuites() */ @@ -177,7 +175,6 @@ bool stringCountComparer(const std::pair& first, const std::pa return first.second > second.second; } - /** * An auxiliary method for sorting the uint16_t count map. Used in printPorts() */ @@ -190,7 +187,6 @@ bool uint16CountComparer(std::pair first, std::pair second.second; } - /** * Print the server-name count map to a table sorted by popularity (most popular names will be first) */ @@ -207,11 +203,12 @@ void printServerNames(ClientHelloStats& clientHelloStatsCollector) // sort the server-name count map so the most popular names will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(clientHelloStatsCollector.serverNameCount.begin(), clientHelloStatsCollector.serverNameCount.end()); - std::sort(map2vec.begin(),map2vec.end(), &stringCountComparer); + std::vector> map2vec(clientHelloStatsCollector.serverNameCount.begin(), + clientHelloStatsCollector.serverNameCount.end()); + std::sort(map2vec.begin(), map2vec.end(), &stringCountComparer); // go over all items (names + count) in the sorted vector and print them - for(const auto &iter : map2vec) + for (const auto& iter : map2vec) { std::stringstream values; values << iter.first << "|" << iter.second; @@ -219,7 +216,6 @@ void printServerNames(ClientHelloStats& clientHelloStatsCollector) } } - /** * Print SSL record version map */ @@ -236,11 +232,11 @@ void printVersions(std::unordered_map& versionMap, const std::str // sort the version map so the most popular version will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(versionMap.begin(), versionMap.end()); - std::sort(map2vec.begin(),map2vec.end(), &uint16CountComparer); + std::vector> map2vec(versionMap.begin(), versionMap.end()); + std::sort(map2vec.begin(), map2vec.end(), &uint16CountComparer); // go over all items (names + count) in the sorted vector and print them - for(const auto &iter : map2vec) + for (const auto& iter : map2vec) { std::stringstream values; values << pcpp::SSLVersion(iter.first).toString() << "|" << iter.second; @@ -248,7 +244,6 @@ void printVersions(std::unordered_map& versionMap, const std::str } } - /** * Print used cipher-suite map to a table sorted by popularity (most popular cipher-suite will be first) */ @@ -265,11 +260,12 @@ void printCipherSuites(ServerHelloStats& serverHelloStats) // sort the cipher-suite count map so the most popular names will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(serverHelloStats.cipherSuiteCount.begin(), serverHelloStats.cipherSuiteCount.end()); - std::sort(map2vec.begin(),map2vec.end(), &stringCountComparer); + std::vector> map2vec(serverHelloStats.cipherSuiteCount.begin(), + serverHelloStats.cipherSuiteCount.end()); + std::sort(map2vec.begin(), map2vec.end(), &stringCountComparer); // go over all items (names + count) in the sorted vector and print them - for(const auto &iter : map2vec) + for (const auto& iter : map2vec) { std::stringstream values; values << iter.first << "|" << iter.second; @@ -277,7 +273,6 @@ void printCipherSuites(ServerHelloStats& serverHelloStats) } } - void printPorts(SSLGeneralStats& stats) { // create the table @@ -291,11 +286,11 @@ void printPorts(SSLGeneralStats& stats) // sort the port count map so the most popular names will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(stats.sslPortCount.begin(), stats.sslPortCount.end()); - std::sort(map2vec.begin(),map2vec.end(), &uint16CountComparer); + std::vector> map2vec(stats.sslPortCount.begin(), stats.sslPortCount.end()); + std::sort(map2vec.begin(), map2vec.end(), &uint16CountComparer); // go over all items (names + count) in the sorted vector and print them - for(const auto &iter : map2vec) + for (const auto& iter : map2vec) { std::stringstream values; values << iter.first << "|" << iter.second; @@ -303,9 +298,9 @@ void printPorts(SSLGeneralStats& stats) } } - /** - * Print a summary of all statistics collected by the SSLStatsCollector. Should be called when traffic capture was finished + * Print a summary of all statistics collected by the SSLStatsCollector. Should be called when traffic capture was + * finished */ void printStatsSummary(SSLStatsCollector& collector) { @@ -321,7 +316,8 @@ void printStatsSummary(SSLStatsCollector& collector) PRINT_STAT_LINE("Average data per flow", collector.getGeneralStats().averageAmountOfDataPerFlow, "Bytes"); PRINT_STAT_LINE("Client-hello message", collector.getClientHelloStats().numOfMessages, "Messages"); PRINT_STAT_LINE("Server-hello message", collector.getServerHelloStats().numOfMessages, "Messages"); - PRINT_STAT_LINE("Number of SSL flows with successful handshake", collector.getGeneralStats().numOfHandshakeCompleteFlows, "Flows"); + PRINT_STAT_LINE("Number of SSL flows with successful handshake", + collector.getGeneralStats().numOfHandshakeCompleteFlows, "Flows"); PRINT_STAT_LINE("Number of SSL flows ended with alert", collector.getGeneralStats().numOfFlowsWithAlerts, "Flows"); printStatsHeadline("SSL/TLS ports count"); @@ -335,10 +331,8 @@ void printStatsSummary(SSLStatsCollector& collector) printStatsHeadline("Server-name count"); printServerNames(collector.getClientHelloStats()); - } - /** * Print the current rates. Should be called periodically during traffic capture */ @@ -352,7 +346,6 @@ void printCurrentRates(SSLStatsCollector& collector) PRINT_STAT_LINE("Rate of SSL responses", collector.getServerHelloStats().messageRate.currentRate, "Responses/sec"); } - /** * The callback to be called when application is terminated by ctrl-c. Stops the endless while loop */ @@ -362,7 +355,6 @@ void onApplicationInterrupted(void* cookie) *shouldStop = true; } - /** * activate SSL/TLS analysis from pcap file */ @@ -377,16 +369,14 @@ void analyzeSSLFromPcapFile(const std::string& pcapFileName) // read the input file packet by packet and give it to the SSLStatsCollector for collecting stats SSLStatsCollector collector; pcpp::RawPacket rawPacket; - while(reader->getNextPacket(rawPacket)) + while (reader->getNextPacket(rawPacket)) { pcpp::Packet parsedPacket(&rawPacket); collector.collectStats(&parsedPacket); } // print stats summary - std::cout << std::endl << std::endl - << "STATS SUMMARY" << std::endl - << "=============" << std::endl; + std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; printStatsSummary(collector); // close input file @@ -396,11 +386,11 @@ void analyzeSSLFromPcapFile(const std::string& pcapFileName) delete reader; } - /** * activate SSL analysis from live traffic */ -void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodically, int printRatePeriod, const std::string& savePacketsToFileName) +void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodically, int printRatePeriod, + const std::string& savePacketsToFileName) { // open the device if (!dev->open()) @@ -410,7 +400,8 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi std::vector portFilterVec; // Detect all ports considered as SSL/TLS traffic and add them to the filter. - // The check is made for well known ports because currently SSLLayer does not support customizing of ports considered as SSL/TLS. + // The check is made for well known ports because currently SSLLayer does not support customizing of ports + // considered as SSL/TLS. for (uint16_t port = 0; port < 1024; ++port) if (pcpp::SSLLayer::isSSLPort(port)) portFilterVec.push_back(new pcpp::PortFilter(port, pcpp::SRC_OR_DST)); @@ -426,7 +417,6 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi EXIT_WITH_ERROR("Couldn't set the filter '" << filterAsString << "' for the device"); } - // if needed to save the captured packets to file - open a writer device pcpp::PcapFileWriterDevice* pcapWriter = nullptr; if (savePacketsToFileName != "") @@ -445,12 +435,11 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi data.pcapWriter = pcapWriter; dev->startCapture(sslPacketArrive, &data); - // register the on app close event to print summary stats on app termination bool shouldStop = false; pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &shouldStop); - while(!shouldStop) + while (!shouldStop) { pcpp::multiPlatformSleep(printRatePeriod); @@ -470,9 +459,7 @@ void analyzeSSLFromLiveTraffic(pcpp::PcapLiveDevice* dev, bool printRatesPeriodi collector.calcRates(); // print stats summary - std::cout << std::endl << std::endl - << "STATS SUMMARY" << std::endl - << "=============" << std::endl; + std::cout << std::endl << std::endl << "STATS SUMMARY" << std::endl << "=============" << std::endl; printStatsSummary(collector); // close and free the writer device @@ -497,44 +484,43 @@ int main(int argc, char* argv[]) std::string readPacketsFromPcapFileName = ""; - int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:f:o:r:hvld", SSLAnalyzerOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:f:o:r:hvld", SSLAnalyzerOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - interfaceNameOrIP = optarg; - break; - case 'f': - readPacketsFromPcapFileName = optarg; - break; - case 'o': - savePacketsToFileName = optarg; - break; - case 'r': - printRatePeriod = atoi(optarg); - break; - case 'd': - printRatesPeriodically = false; - break; - case 'v': - printAppVersion(); - break; - case 'h': - printUsage(); - exit(0); - break; - case 'l': - listInterfaces(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'i': + interfaceNameOrIP = optarg; + break; + case 'f': + readPacketsFromPcapFileName = optarg; + break; + case 'o': + savePacketsToFileName = optarg; + break; + case 'r': + printRatePeriod = atoi(optarg); + break; + case 'd': + printRatesPeriodically = false; + break; + case 'v': + printAppVersion(); + break; + case 'h': + printUsage(); + exit(0); + break; + case 'l': + listInterfaces(); + break; + default: + printUsage(); + exit(-1); } } @@ -547,10 +533,11 @@ int main(int argc, char* argv[]) { analyzeSSLFromPcapFile(readPacketsFromPcapFileName); } - else // analyze in live traffic mode + else // analyze in live traffic mode { // extract pcap live device by interface name or IP address - pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); + pcpp::PcapLiveDevice* dev = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); diff --git a/Examples/TLSFingerprinting/main.cpp b/Examples/TLSFingerprinting/main.cpp index 683f480a2d..87acfa5af0 100644 --- a/Examples/TLSFingerprinting/main.cpp +++ b/Examples/TLSFingerprinting/main.cpp @@ -26,36 +26,36 @@ #include "PcapFileDevice.h" #include -static struct option TLSFingerprintingOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"input-file", required_argument, nullptr, 'r'}, - {"output-file", required_argument, nullptr, 'o'}, - {"separator", required_argument, nullptr, 's'}, - {"tls-fp-type", required_argument, nullptr, 't'}, - {"filter", required_argument, nullptr, 'f'}, - {"list-interfaces", no_argument, nullptr, 'l'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +static struct option TLSFingerprintingOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "input-file", required_argument, nullptr, 'r' }, + { "output-file", required_argument, nullptr, 'o' }, + { "separator", required_argument, nullptr, 's' }, + { "tls-fp-type", required_argument, nullptr, 't' }, + { "filter", required_argument, nullptr, 'f' }, + { "list-interfaces", no_argument, nullptr, 'l' }, + { "version", no_argument, nullptr, 'v' }, + { "help", no_argument, nullptr, 'h' }, + { nullptr, 0, nullptr, 0 } }; -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) -#define TLS_FP_CH_ONLY "ch" -#define TLS_FP_SH_ONLY "sh" -#define TLS_FP_CH_AND_SH "ch_sh" +#define TLS_FP_CH_ONLY "ch" +#define TLS_FP_SH_ONLY "sh" +#define TLS_FP_CH_AND_SH "ch_sh" bool isNotAlphanumeric(char c) { return std::isalnum(c) == 0; } - /** * An auxiliary method for sorting the TLS fingerprint count map. Used in printCommonTLSFingerprints() */ @@ -68,74 +68,91 @@ bool stringCountComparer(const std::pair& first, const st return first.second > second.second; } - /** * Print application usage */ void printUsage() { - std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvlcms] [-r input_file] [-i interface] [-o output_file_name] [-s separator] [-t tls_fp_type] [-f bpf_filter]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -r input_file : Input pcap/pcapng file to analyze. Required argument for reading from file" << std::endl - << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or IP address." << std::endl - << " Required argument for capturing from live interface" << std::endl - << " -o output_file_name : Output file name. This is a csv file (where 'tab' is the default separator)" << std::endl - << " which contains information about all of the TLS fingerprints found in the" << std::endl - << " capture file or live interface. It includes the TLS fingerprint itself" << std::endl - << " (raw string and MD5), IP addresses, TCP ports and SSL message type (ClientHello" << std::endl - << " or ServerHello). If this argument is not specified the output file name is the" << std::endl - << " name of capture file or the live interface and it is written to the current" << std::endl - << " directory ('.')" << std::endl - << " -s separator : The separator to use in the csv output file. Valid values are a single character" << std::endl - << " which is not alphanumeric and not one of the following: '.', ',', ':', '-'." << std::endl - << " If this argument is not specified the default separator is 'tab' ('\\t')" << std::endl - << " -t tls_fp_type : Specify whether to calculate TLS fingerprints for ClientHello packets only ('ch')," << std::endl - << " ServerHello packets only ('sh') or both ('ch_sh'). The only valid values are" << std::endl - << " 'ch', 'sh', 'ch_sh'. If this argument is not specified the default value is" << std::endl - << " ClientHello ('ch')" << std::endl - << " -f bpf_filter : Apply a BPF filter to the capture file or live interface, meaning TLS fingerprint" << std::endl - << " will only be generated for the filtered packets" << std::endl - << " -l : Print the list of interfaces and exit" << std::endl - << " -v : Display the current version and exit" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + std::cout + << std::endl + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() + << " [-hvlcms] [-r input_file] [-i interface] [-o output_file_name] [-s separator] [-t tls_fp_type] [-f " + "bpf_filter]" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -r input_file : Input pcap/pcapng file to analyze. Required argument for reading from file" + << std::endl + << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or IP address." + << std::endl + << " Required argument for capturing from live interface" << std::endl + << " -o output_file_name : Output file name. This is a csv file (where 'tab' is the default separator)" + << std::endl + << " which contains information about all of the TLS fingerprints found in the" + << std::endl + << " capture file or live interface. It includes the TLS fingerprint itself" + << std::endl + << " (raw string and MD5), IP addresses, TCP ports and SSL message type (ClientHello" + << std::endl + << " or ServerHello). If this argument is not specified the output file name is the" + << std::endl + << " name of capture file or the live interface and it is written to the current" + << std::endl + << " directory ('.')" << std::endl + << " -s separator : The separator to use in the csv output file. Valid values are a single character" + << std::endl + << " which is not alphanumeric and not one of the following: '.', ',', ':', '-'." + << std::endl + << " If this argument is not specified the default separator is 'tab' ('\\t')" + << std::endl + << " -t tls_fp_type : Specify whether to calculate TLS fingerprints for ClientHello packets only " + "('ch')," + << std::endl + << " ServerHello packets only ('sh') or both ('ch_sh'). The only valid values are" + << std::endl + << " 'ch', 'sh', 'ch_sh'. If this argument is not specified the default value is" + << std::endl + << " ClientHello ('ch')" << std::endl + << " -f bpf_filter : Apply a BPF filter to the capture file or live interface, meaning TLS fingerprint" + << std::endl + << " will only be generated for the filtered packets" << std::endl + << " -l : Print the list of interfaces and exit" << std::endl + << " -v : Display the current version and exit" << std::endl + << " -h : Display this help message and exit" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ void listInterfaces() { - const std::vector& devList = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); + const std::vector& devList = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList(); std::cout << std::endl << "Network interfaces:" << std::endl; - for (const auto &dev : devList) + for (const auto& dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - /** * The callback to be called when application is terminated by ctrl-c */ @@ -145,7 +162,6 @@ static void onApplicationInterrupted(void* cookie) *shouldStop = true; } - /** * Return a packet source and dest IP addresses */ @@ -161,7 +177,6 @@ std::pair getIPs(const pcpp::Packet& packet) return std::pair(srcIP, dstIP); } - /** * Return a packet source and dest TCP ports */ @@ -178,47 +193,36 @@ std::pair getTcpPorts(const pcpp::Packet& packet) return std::pair(srcPort, dstPort); } - /** * Write data about a single ClientHello/ServerHello packet to the output file. - * This method takes the parsed packets and the TLS fingerprint as inputs, extracts the rest of the data such as IP addresses and TCP ports, - * and writes a single row to the output file + * This method takes the parsed packets and the TLS fingerprint as inputs, extracts the rest of the data such as IP + * addresses and TCP ports, and writes a single row to the output file */ -void writeToOutputFile(std::ofstream* outputFile, const pcpp::Packet& parsedPacket, const std::string &tlsFPString, const std::string &tlsFP_MD5, const std::string &tlsFPType, const std::string &separator) +void writeToOutputFile(std::ofstream* outputFile, const pcpp::Packet& parsedPacket, const std::string& tlsFPString, + const std::string& tlsFP_MD5, const std::string& tlsFPType, const std::string& separator) { std::pair ipSrcDest = getIPs(parsedPacket); std::pair tcpPorts = getTcpPorts(parsedPacket); - *outputFile << - tlsFP_MD5 << separator << - tlsFPString << separator << - tlsFPType << separator << - ipSrcDest.first.toString() << separator << - tcpPorts.first << separator << - ipSrcDest.second.toString() << separator << - tcpPorts.second << std::endl; + *outputFile << tlsFP_MD5 << separator << tlsFPString << separator << tlsFPType << separator + << ipSrcDest.first.toString() << separator << tcpPorts.first << separator << ipSrcDest.second.toString() + << separator << tcpPorts.second << std::endl; } - /** * Write the column headers to the output file */ -void writeHeaderToOutputFile(std::ofstream& outputFile, const std::string &separator) +void writeHeaderToOutputFile(std::ofstream& outputFile, const std::string& separator) { - outputFile << - "TLS Fingerprint (MD5)" << separator << - "TLS Fingerprint" << separator << - "TLS Fingerprint type" << separator << - "IP Source" << separator << - "TCP Source Port" << separator << - "IP Dest" << separator << - "TCP Dest Port" << std::endl; + outputFile << "TLS Fingerprint (MD5)" << separator << "TLS Fingerprint" << separator << "TLS Fingerprint type" + << separator << "IP Source" << separator << "TCP Source Port" << separator << "IP Dest" << separator + << "TCP Dest Port" << std::endl; } - struct TLSFingerprintingStats { - TLSFingerprintingStats(): numOfPacketsTotal(0), numOfCHPackets(0), numOfSHPackets(0) { } + TLSFingerprintingStats() : numOfPacketsTotal(0), numOfCHPackets(0), numOfSHPackets(0) + {} uint64_t numOfPacketsTotal; uint64_t numOfCHPackets; uint64_t numOfSHPackets; @@ -235,7 +239,6 @@ struct HandlePacketData TLSFingerprintingStats* stats; }; - /** * Print cipher-suite map in a table sorted by number of occurrences (most common cipher-suite will be first) */ @@ -252,11 +255,11 @@ void printCommonTLSFingerprints(const std::unordered_map& // sort the TLS fingerprint map so the most popular will be first // since it's not possible to sort a std::unordered_map you must copy it to a std::vector and sort it then - std::vector > map2vec(tlsFingerprintMap.begin(), tlsFingerprintMap.end()); - std::sort(map2vec.begin(),map2vec.end(), &stringCountComparer); + std::vector> map2vec(tlsFingerprintMap.begin(), tlsFingerprintMap.end()); + std::sort(map2vec.begin(), map2vec.end(), &stringCountComparer); // go over all items (fingerprints + count) in the sorted vector and print them - for(auto iter = map2vec.begin(); iter != map2vec.end(); ++iter) + for (auto iter = map2vec.begin(); iter != map2vec.end(); ++iter) { if (iter - map2vec.begin() >= printCountItems) break; @@ -267,7 +270,6 @@ void printCommonTLSFingerprints(const std::unordered_map& } } - /** * Print TLS fingerprinting stats */ @@ -318,9 +320,9 @@ void printStats(const TLSFingerprintingStats& stats, bool chFP, bool shFP) } } - /** - * Handle an intercepted packet: identify if it's a ClientHello or ServerHello packets, extract the TLS fingerprint and write it to the output file + * Handle an intercepted packet: identify if it's a ClientHello or ServerHello packets, extract the TLS fingerprint and + * write it to the output file */ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) { @@ -336,17 +338,20 @@ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) if (data->chFP) { // check if the SSL/TLS handhsake layer contains a ClientHello message - pcpp::SSLClientHelloMessage* clientHelloMessage = sslHandshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLClientHelloMessage* clientHelloMessage = + sslHandshakeLayer->getHandshakeMessageOfType(); if (clientHelloMessage != nullptr) { data->stats->numOfCHPackets++; // extract the TLS fingerprint - pcpp::SSLClientHelloMessage::ClientHelloTLSFingerprint tlsFingerprint = clientHelloMessage->generateTLSFingerprint(); + pcpp::SSLClientHelloMessage::ClientHelloTLSFingerprint tlsFingerprint = + clientHelloMessage->generateTLSFingerprint(); std::pair tlsFingerprintStringAndMD5 = tlsFingerprint.toStringAndMD5(); data->stats->chFingerprints[tlsFingerprintStringAndMD5.second]++; // write data to output file - writeToOutputFile(data->outputFile, parsedPacket, tlsFingerprintStringAndMD5.first, tlsFingerprintStringAndMD5.second, "ClientHello", data->separator); + writeToOutputFile(data->outputFile, parsedPacket, tlsFingerprintStringAndMD5.first, + tlsFingerprintStringAndMD5.second, "ClientHello", data->separator); return; } } @@ -354,28 +359,31 @@ void handlePacket(pcpp::RawPacket* rawPacket, const HandlePacketData* data) if (data->shFP) { // check if the SSL/TLS handhsake layer contains a ServerHello message - pcpp::SSLServerHelloMessage* servertHelloMessage = sslHandshakeLayer->getHandshakeMessageOfType(); + pcpp::SSLServerHelloMessage* servertHelloMessage = + sslHandshakeLayer->getHandshakeMessageOfType(); if (servertHelloMessage != nullptr) { data->stats->numOfSHPackets++; // extract the TLS fingerprint - pcpp::SSLServerHelloMessage::ServerHelloTLSFingerprint tlsFingerprint = servertHelloMessage->generateTLSFingerprint(); + pcpp::SSLServerHelloMessage::ServerHelloTLSFingerprint tlsFingerprint = + servertHelloMessage->generateTLSFingerprint(); std::pair tlsFingerprintStringAndMD5 = tlsFingerprint.toStringAndMD5(); data->stats->shFingerprints[tlsFingerprintStringAndMD5.second]++; // write data to output file - writeToOutputFile(data->outputFile, parsedPacket, tlsFingerprintStringAndMD5.first, tlsFingerprintStringAndMD5.second, "ServerHello", data->separator); + writeToOutputFile(data->outputFile, parsedPacket, tlsFingerprintStringAndMD5.first, + tlsFingerprintStringAndMD5.second, "ServerHello", data->separator); } } } } } - /** * Extract TLS fingerprints from a pcap/pcapng file */ -void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::string& outputFileName, const std::string& separator, bool chFP, bool shFP, const std::string& bpfFilter) +void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::string& outputFileName, + const std::string& separator, bool chFP, bool shFP, const std::string& bpfFilter) { // open input file (pcap or pcapng file) pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader(inputPcapFileName.c_str()); @@ -389,7 +397,8 @@ void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::st { size_t fileNameOffset = inputPcapFileName.find_last_of("\\/") + 1; size_t extensionOffset = inputPcapFileName.find_last_of("."); - std::string fileNameWithoutExtension = inputPcapFileName.substr(fileNameOffset, extensionOffset - fileNameOffset); + std::string fileNameWithoutExtension = + inputPcapFileName.substr(fileNameOffset, extensionOffset - fileNameOffset); outputFileName = fileNameWithoutExtension + ".txt"; } @@ -412,7 +421,6 @@ void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::st std::cout << "Start reading '" << inputPcapFileName << "'..." << std::endl; - TLSFingerprintingStats stats; HandlePacketData data; data.chFP = chFP; @@ -438,7 +446,6 @@ void doTlsFingerprintingOnPcapFile(const std::string& inputPcapFileName, std::st std::cout << "Output file was written to: '" << outputFileName << "'" << std::endl; } - /** * packet capture callback - called whenever a packet arrives on the live interface (in live device capturing mode) */ @@ -448,11 +455,11 @@ static void onPacketArrives(pcpp::RawPacket* rawPacket, pcpp::PcapLiveDevice* de handlePacket(rawPacket, data); } - /** * Extract TLS fingerprints from a live interface */ -void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std::string& outputFileName, const std::string& separator, bool chFP, bool shFP, const std::string& bpfFilter) +void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std::string& outputFileName, + const std::string& separator, bool chFP, bool shFP, const std::string& bpfFilter) { // extract pcap live device by interface name or IP address pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); @@ -467,10 +474,8 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: { // take the device name and remove all chars which are not alphanumeric outputFileName = std::string(dev->getName()); - outputFileName.erase(remove_if( - outputFileName.begin(), - outputFileName.end(), - isNotAlphanumeric), outputFileName.end()); + outputFileName.erase(remove_if(outputFileName.begin(), outputFileName.end(), isNotAlphanumeric), + outputFileName.end()); outputFileName += ".txt"; } @@ -510,7 +515,7 @@ void doTlsFingerprintingOnLiveTraffic(const std::string& interfaceNameOrIP, std: pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &shouldStop); // run in an endless loop until the user press ctrl+c - while(!shouldStop) + while (!shouldStop) pcpp::multiPlatformSleep(1); // stop capturing and close the live device @@ -539,64 +544,71 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt = 0; - while((opt = getopt_long(argc, argv, "i:r:o:t:f:s:vhl", TLSFingerprintingOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:r:o:t:f:s:vhl", TLSFingerprintingOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - interfaceNameOrIP = optarg; - break; - case 'r': - inputPcapFileName = optarg; - break; - case 'o': - outputFileName = optarg; - break; - case 'f': - bpfFilter = optarg; - break; - case 's': - separator = optarg; - break; - case 't': - tlsFingerprintType = optarg; - break; - case 'h': - printUsage(); - exit(0); - case 'v': - printAppVersion(); - break; - case 'l': - listInterfaces(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'i': + interfaceNameOrIP = optarg; + break; + case 'r': + inputPcapFileName = optarg; + break; + case 'o': + outputFileName = optarg; + break; + case 'f': + bpfFilter = optarg; + break; + case 's': + separator = optarg; + break; + case 't': + tlsFingerprintType = optarg; + break; + case 'h': + printUsage(); + exit(0); + case 'v': + printAppVersion(); + break; + case 'l': + listInterfaces(); + break; + default: + printUsage(); + exit(-1); } } - // if no interface or input pcap file provided or both are provided- exit with error + // if no interface or input pcap file provided or both are provided - exit with error if (inputPcapFileName.empty() == interfaceNameOrIP.empty()) { EXIT_WITH_ERROR("Please provide an interface or an input pcap file"); } - // if the user chosen a separator which is not the default, check if this separator is allowed. - // allowed separators are a single character which is not alphanumeric and not one of the following: '.', ',', ':', '-' + // if the user chosen a separator which is not the default, check if this separator is allowed. Allowed separators + // are a single character which is not alphanumeric and not one of the following: '.', ',', ':', '-' static const std::string disallowedSeparatorsArr[] = { ".", ",", ":", "-" }; - std::vector disallowedSeparatorsVec(disallowedSeparatorsArr, disallowedSeparatorsArr + sizeof(disallowedSeparatorsArr) / sizeof(disallowedSeparatorsArr[0]) ); - if (separator.empty() || separator.size() > 1 || std::isalnum(separator[0]) || std::find(disallowedSeparatorsVec.begin(), disallowedSeparatorsVec.end(), separator) != disallowedSeparatorsVec.end()) + std::vector disallowedSeparatorsVec(disallowedSeparatorsArr, + disallowedSeparatorsArr + sizeof(disallowedSeparatorsArr) / + sizeof(disallowedSeparatorsArr[0])); + if (separator.empty() || separator.size() > 1 || std::isalnum(separator[0]) || + std::find(disallowedSeparatorsVec.begin(), disallowedSeparatorsVec.end(), separator) != + disallowedSeparatorsVec.end()) { - EXIT_WITH_ERROR("Allowed separators are single characters which are not alphanumeric and not ',', '.', ':', '-'"); + EXIT_WITH_ERROR( + "Allowed separators are single characters which are not alphanumeric and not ',', '.', ':', '-'"); } // validate TLS fingerprint type the user has requested - if (tlsFingerprintType != TLS_FP_CH_ONLY && tlsFingerprintType != TLS_FP_SH_ONLY && tlsFingerprintType != TLS_FP_CH_AND_SH) + if (tlsFingerprintType != TLS_FP_CH_ONLY && tlsFingerprintType != TLS_FP_SH_ONLY && + tlsFingerprintType != TLS_FP_CH_AND_SH) { - EXIT_WITH_ERROR("Possible options for TLS fingerprint types are 'ch' (Client Hello), 'sh' (Server Hello) or 'ch_sh' (Client Hello & Server Hello)\n"); + EXIT_WITH_ERROR("Possible options for TLS fingerprint types are 'ch' (Client Hello), 'sh' (Server Hello) or " + "'ch_sh' (Client Hello & Server Hello)\n"); } bool chFP = true, shFP = true; diff --git a/Examples/TcpReassembly/main.cpp b/Examples/TcpReassembly/main.cpp index d8c6e688b2..8a19f86e60 100644 --- a/Examples/TcpReassembly/main.cpp +++ b/Examples/TcpReassembly/main.cpp @@ -1,27 +1,27 @@ /** * TcpReassembly application * ========================= - * This is an application that captures data transmitted as part of TCP connections, organizes the data and stores it in a way that is convenient for protocol analysis and debugging. - * This application reconstructs the TCP data streams and stores each connection in a separate file(s). TcpReassembly understands TCP sequence numbers and will correctly reconstruct - * data streams regardless of retransmissions, out-of-order delivery or data loss. - * TcpReassembly works more or less the same like tcpflow (https://linux.die.net/man/1/tcpflow) but probably with less options. - * The main purpose of it is to demonstrate the TCP reassembly capabilities in PcapPlusPlus. - * Main features and capabilities: + * This is an application that captures data transmitted as part of TCP connections, organizes the data and stores it in + * a way that is convenient for protocol analysis and debugging. This application reconstructs the TCP data streams and + * stores each connection in a separate file(s). TcpReassembly understands TCP sequence numbers and will correctly + * reconstruct data streams regardless of retransmissions, out-of-order delivery or data loss. TcpReassembly works more + * or less the same like tcpflow (https://linux.die.net/man/1/tcpflow) but probably with less options. The main purpose + * of it is to demonstrate the TCP reassembly capabilities in PcapPlusPlus. Main features and capabilities: * - Captures packets from pcap/pcapng files or live traffic * - Handles TCP retransmission, out-of-order packets and packet loss * - Possibility to set a BPF filter to process only part of the traffic * - Write each connection to a separate file * - Write each side of each connection to a separate file - * - Limit the max number of open files in each point in time (to avoid running out of file descriptors for large files / heavy traffic) - * - Write a metadata file (txt file) for each connection with various stats on the connection: number of packets (in each side + total), number of TCP messages (in each side + total), - * number of bytes (in each side + total) + * - Limit the max number of open files in each point in time (to avoid running out of file descriptors for large + * files / heavy traffic) + * - Write a metadata file (txt file) for each connection with various stats on the connection: number of packets (in + * each side + total), number of TCP messages (in each side + total), number of bytes (in each side + total) * - Write to console only (instead of files) * - Set a directory to write files to (default is current directory) * * For more details about modes of operation and parameters run TcpReassembly -h */ - #include #include #include @@ -36,59 +36,59 @@ #include "LRUList.h" #include - -#define EXIT_WITH_ERROR(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) - +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) #if defined(_WIN32) -#define SEPARATOR '\\' +# define SEPARATOR '\\' #else -#define SEPARATOR '/' +# define SEPARATOR '/' #endif - // unless the user chooses otherwise - default number of concurrent used file descriptors is 500 constexpr int DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES = 500; -static struct option TcpAssemblyOptions[] = -{ - {"interface", required_argument, nullptr, 'i'}, - {"input-file", required_argument, nullptr, 'r'}, - {"output-dir", required_argument, nullptr, 'o'}, - {"list-interfaces", no_argument, nullptr, 'l'}, - {"filter", required_argument, nullptr, 'e'}, - {"write-metadata", no_argument, nullptr, 'm'}, - {"write-to-console", no_argument, nullptr, 'c'}, - {"separate-sides", no_argument, nullptr, 's'}, - {"max-file-desc", required_argument, nullptr, 'f'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {nullptr, 0, nullptr, 0} +static struct option TcpAssemblyOptions[] = { + { "interface", required_argument, nullptr, 'i' }, + { "input-file", required_argument, nullptr, 'r' }, + { "output-dir", required_argument, nullptr, 'o' }, + { "list-interfaces", no_argument, nullptr, 'l' }, + { "filter", required_argument, nullptr, 'e' }, + { "write-metadata", no_argument, nullptr, 'm' }, + { "write-to-console", no_argument, nullptr, 'c' }, + { "separate-sides", no_argument, nullptr, 's' }, + { "max-file-desc", required_argument, nullptr, 'f' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { nullptr, 0, nullptr, 0 } }; - /** - * A singleton class containing the configuration as requested by the user. This singleton is used throughout the application + * A singleton class containing the configuration as requested by the user. This singleton is used throughout the + * application */ class GlobalConfig { private: - /** * A private c'tor (as this is a singleton) */ - GlobalConfig() : m_RecentConnsWithActivity(nullptr), writeMetadata(false), writeToConsole(false), separateSides(false), maxOpenFiles(DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) { } - - // A least-recently-used (LRU) list of all connections seen so far. Each connection is represented by its flow key. This LRU list is used to decide which connection was seen least - // recently in case we reached max number of open file descriptors and we need to decide which files to close + GlobalConfig() + : m_RecentConnsWithActivity(nullptr), writeMetadata(false), writeToConsole(false), separateSides(false), + maxOpenFiles(DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES) + {} + + // A least-recently-used (LRU) list of all connections seen so far. Each connection is represented by its flow key. + // This LRU list is used to decide which connection was seen least recently in case we reached max number of open + // file descriptors and we need to decide which files to close pcpp::LRUList* m_RecentConnsWithActivity; public: - // a flag indicating whether to write a metadata file for each connection (containing several stats) bool writeMetadata; @@ -98,13 +98,13 @@ class GlobalConfig // a flag indicating whether to write TCP data to actual files or to console bool writeToConsole; - // a flag indicating whether to write both side of a connection to the same file (which is the default) or write each side to a separate file + // a flag indicating whether to write both side of a connection to the same file (which is the default) or write + // each side to a separate file bool separateSides; // max number of allowed open files in each point in time size_t maxOpenFiles; - /** * A method getting connection parameters as input and returns a filename and file path as output. * The filename is constructed by the IPs (src and dst) and the TCP ports (src and dst) @@ -113,7 +113,8 @@ class GlobalConfig { std::stringstream stream; - // if user chooses to write to a directory other than the current directory - add the dir path to the return value + // if user chooses to write to a directory other than the current directory - add the dir path to the return + // value if (!outputDir.empty()) stream << outputDir << SEPARATOR; @@ -127,19 +128,18 @@ class GlobalConfig // side == 0 means data is sent from client->server if (side <= 0 || !useSeparateSides) stream << sourceIP << '.' << connData.srcPort << '-' << destIP << '.' << connData.dstPort; - else // side == 1 means data is sent from server->client + else // side == 1 means data is sent from server->client stream << destIP << '.' << connData.dstPort << '-' << sourceIP << '.' << connData.srcPort; // return the file path return stream.str(); } - /** - * Open a file stream. Inputs are the filename to open and a flag indicating whether to append to an existing file or overwrite it. - * Return value is a pointer to the new file stream + * Open a file stream. Inputs are the filename to open and a flag indicating whether to append to an existing file + * or overwrite it. Return value is a pointer to the new file stream */ - std::ostream* openFileStream(const std::string &fileName, bool reopen) const + std::ostream* openFileStream(const std::string& fileName, bool reopen) const { // if the user chooses to write only to console, don't open anything and return std::cout if (writeToConsole) @@ -152,7 +152,6 @@ class GlobalConfig return new std::ofstream(fileName.c_str(), std::ios_base::binary); } - /** * Close a file stream */ @@ -170,15 +169,14 @@ class GlobalConfig } } - /** * Return a pointer to the least-recently-used (LRU) list of connections */ pcpp::LRUList* getRecentConnsWithActivity() { // This is a lazy implementation - the instance isn't created until the user requests it for the first time. - // the side of the LRU list is determined by the max number of allowed open files at any point in time. Default is DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES - // but the user can choose another number + // the side of the LRU list is determined by the max number of allowed open files at any point in time. Default + // is DEFAULT_MAX_NUMBER_OF_CONCURRENT_OPEN_FILES but the user can choose another number if (m_RecentConnsWithActivity == nullptr) m_RecentConnsWithActivity = new pcpp::LRUList(maxOpenFiles); @@ -186,7 +184,6 @@ class GlobalConfig return m_RecentConnsWithActivity; } - /** * The singleton implementation of this class */ @@ -205,16 +202,18 @@ class GlobalConfig } }; - /** - * A struct to contain all data save on a specific connection. It contains the file streams to write to and also stats data on the connection + * A struct to contain all data save on a specific connection. It contains the file streams to write to and also stats + * data on the connection */ struct TcpReassemblyData { - // pointer to 2 file stream - one for each side of the connection. If the user chooses to write both sides to the same file (which is the default), only one file stream is used (index 0) + // pointer to 2 file stream - one for each side of the connection. If the user chooses to write both sides to the + // same file (which is the default), only one file stream is used (index 0) std::ostream* fileStreams[2]; - // flags indicating whether the file in each side was already opened before. If the answer is yes, next time it'll be opened in append mode (and not in overwrite mode) + // flags indicating whether the file in each side was already opened before. If the answer is yes, next time it'll + // be opened in append mode (and not in overwrite mode) bool reopenFileStreams[2]; // a flag indicating on which side was the latest message on this connection @@ -228,7 +227,12 @@ struct TcpReassemblyData /** * the default c'tor */ - TcpReassemblyData() { fileStreams[0] = nullptr; fileStreams[1] = nullptr; clear(); } + TcpReassemblyData() + { + fileStreams[0] = nullptr; + fileStreams[1] = nullptr; + clear(); + } /** * The default d'tor @@ -273,51 +277,54 @@ struct TcpReassemblyData } }; - // typedef representing the connection manager typedef std::unordered_map TcpReassemblyConnMgr; - /** * Print application usage */ void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvlcms] [-r input_file] [-i interface] [-o output_dir] [-e bpf_filter] [-f max_files]" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -r input_file : Input pcap/pcapng file to analyze. Required argument for reading from file" << std::endl - << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 address. Required argument for capturing from live interface" << std::endl - << " -o output_dir : Specify output directory (default is '.')" << std::endl - << " -e bpf_filter : Apply a BPF filter to capture file or live interface, meaning TCP reassembly will only work on filtered packets" << std::endl - << " -f max_files : Maximum number of file descriptors to use" << std::endl - << " -c : Write all output to console (nothing will be written to files)" << std::endl - << " -m : Write a metadata file for each connection" << std::endl - << " -s : Write each side of each connection to a separate file (default is writing both sides of each connection to the same file)" << std::endl - << " -l : Print the list of interfaces and exit" << std::endl - << " -v : Display the current version and exit" << std::endl - << " -h : Display this help message and exit" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() + << " [-hvlcms] [-r input_file] [-i interface] [-o output_dir] [-e bpf_filter] [-f max_files]" << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -r input_file : Input pcap/pcapng file to analyze. Required argument for reading from file" + << std::endl + << " -i interface : Use the specified interface. Can be interface name (e.g eth0) or interface IPv4 " + "address. Required argument for capturing from live interface" + << std::endl + << " -o output_dir : Specify output directory (default is '.')" << std::endl + << " -e bpf_filter : Apply a BPF filter to capture file or live interface, meaning TCP reassembly " + "will only work on filtered packets" + << std::endl + << " -f max_files : Maximum number of file descriptors to use" << std::endl + << " -c : Write all output to console (nothing will be written to files)" << std::endl + << " -m : Write a metadata file for each connection" << std::endl + << " -s : Write each side of each connection to a separate file (default is writing both " + "sides of each connection to the same file)" + << std::endl + << " -l : Print the list of interfaces and exit" << std::endl + << " -v : Display the current version and exit" << std::endl + << " -h : Display this help message and exit" << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } - /** * Go over all interfaces and output their names */ @@ -329,12 +336,12 @@ void listInterfaces() for (auto dev : devList) { - std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << dev->getName() << "' IP address: " << dev->getIPv4Address().toString() + << std::endl; } exit(0); } - /** * The callback being called by the TCP reassembly module whenever new data arrives on a certain connection */ @@ -353,7 +360,8 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc int8_t side; - // if the user wants to write each side in a different file - set side as the sideIndex, otherwise write everything to the same file ("side 0") + // if the user wants to write each side in a different file - set side as the sideIndex, otherwise write everything + // to the same file ("side 0") if (GlobalConfig::getInstance().separateSides) side = sideIndex; else @@ -362,13 +370,15 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc // if the file stream on the relevant side isn't open yet (meaning it's the first data on this connection) if (flow->second.fileStreams[side] == nullptr) { - // add the flow key of this connection to the list of open connections. If the return value isn't nullptr it means that there are too many open files - // and we need to close the connection with least recently used file(s) in order to open a new one. - // The connection with the least recently used file is the return value + // add the flow key of this connection to the list of open connections. If the return value isn't nullptr it + // means that there are too many open files and we need to close the connection with least recently used file(s) + // in order to open a new one. The connection with the least recently used file is the return value uint32_t flowKeyToCloseFiles; - int result = GlobalConfig::getInstance().getRecentConnsWithActivity()->put(tcpData.getConnectionData().flowKey, &flowKeyToCloseFiles); + int result = GlobalConfig::getInstance().getRecentConnsWithActivity()->put(tcpData.getConnectionData().flowKey, + &flowKeyToCloseFiles); - // if result equals to 1 it means we need to close the open files in this connection (the one with the least recently used files) + // if result equals to 1 it means we need to close the open files in this connection (the one with the least + // recently used files) if (result == 1) { // find the connection from the flow key @@ -384,18 +394,24 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc GlobalConfig::getInstance().closeFileSteam(flow2->second.fileStreams[index]); flow2->second.fileStreams[index] = nullptr; - // set the reopen flag to true to indicate that next time this file will be opened it will be opened in append mode (and not overwrite mode) + // set the reopen flag to true to indicate that next time this file will be opened it will be + // opened in append mode (and not overwrite mode) flow2->second.reopenFileStreams[index] = true; } } } } + // clang-format off // get the file name according to the 5-tuple etc. - std::string fileName = GlobalConfig::getInstance().getFileName(tcpData.getConnectionData(), sideIndex, GlobalConfig::getInstance().separateSides) + ".txt"; - - // open the file in overwrite mode (if this is the first time the file is opened) or in append mode (if it was already opened before) - flow->second.fileStreams[side] = GlobalConfig::getInstance().openFileStream(fileName, flow->second.reopenFileStreams[side]); + std::string fileName = GlobalConfig::getInstance().getFileName(tcpData.getConnectionData(), sideIndex, GlobalConfig::getInstance().separateSides) + + ".txt"; + // clang-format on + + // open the file in overwrite mode (if this is the first time the file is opened) or in append mode (if it was + // already opened before) + flow->second.fileStreams[side] = + GlobalConfig::getInstance().openFileStream(fileName, flow->second.reopenFileStreams[side]); } // if this messages comes on a different side than previous message seen on this connection @@ -416,9 +432,9 @@ static void tcpReassemblyMsgReadyCallback(const int8_t sideIndex, const pcpp::Tc flow->second.fileStreams[side]->write((char*)tcpData.getData(), tcpData.getDataLength()); } - /** - * The callback being called by the TCP reassembly module whenever a new connection is found. This method adds the connection to the connection manager + * The callback being called by the TCP reassembly module whenever a new connection is found. This method adds the + * connection to the connection manager */ static void tcpReassemblyConnectionStartCallback(const pcpp::ConnectionData& connectionData, void* userCookie) { @@ -436,12 +452,12 @@ static void tcpReassemblyConnectionStartCallback(const pcpp::ConnectionData& con } } - /** - * The callback being called by the TCP reassembly module whenever a connection is ending. This method removes the connection from the connection manager and writes the metadata file if requested - * by the user + * The callback being called by the TCP reassembly module whenever a connection is ending. This method removes the + * connection from the connection manager and writes the metadata file if requested by the user */ -static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& connectionData, pcpp::TcpReassembly::ConnectionEndReason reason, void* userCookie) +static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& connectionData, + pcpp::TcpReassembly::ConnectionEndReason reason, void* userCookie) { // get a pointer to the connection manager auto connMgr = (TcpReassemblyConnMgr*)userCookie; @@ -460,14 +476,18 @@ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& conne std::ofstream metadataFile(fileName.c_str()); metadataFile << "Number of data packets in side 0: " << connection->second.numOfDataPackets[0] << std::endl; metadataFile << "Number of data packets in side 1: " << connection->second.numOfDataPackets[1] << std::endl; - metadataFile << "Total number of data packets: " << (connection->second.numOfDataPackets[0] + connection->second.numOfDataPackets[1]) << std::endl; + metadataFile << "Total number of data packets: " + << (connection->second.numOfDataPackets[0] + connection->second.numOfDataPackets[1]) << std::endl; metadataFile << std::endl; metadataFile << "Number of bytes in side 0: " << connection->second.bytesFromSide[0] << std::endl; metadataFile << "Number of bytes in side 1: " << connection->second.bytesFromSide[1] << std::endl; - metadataFile << "Total number of bytes: " << (connection->second.bytesFromSide[0] + connection->second.bytesFromSide[1]) << std::endl; + metadataFile << "Total number of bytes: " + << (connection->second.bytesFromSide[0] + connection->second.bytesFromSide[1]) << std::endl; metadataFile << std::endl; - metadataFile << "Number of messages in side 0: " << connection->second.numOfMessagesFromSide[0] << std::endl; - metadataFile << "Number of messages in side 1: " << connection->second.numOfMessagesFromSide[1] << std::endl; + metadataFile << "Number of messages in side 0: " << connection->second.numOfMessagesFromSide[0] + << std::endl; + metadataFile << "Number of messages in side 1: " << connection->second.numOfMessagesFromSide[1] + << std::endl; metadataFile.close(); } @@ -475,7 +495,6 @@ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& conne connMgr->erase(connection); } - /** * The callback to be called when application is terminated by ctrl-c. Stops the endless while loop */ @@ -485,7 +504,6 @@ static void onApplicationInterrupted(void* cookie) *shouldStop = true; } - /** * packet capture callback - called whenever a packet arrives on the live device (in live device capturing mode) */ @@ -496,11 +514,11 @@ static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, tcpReassembly->reassemblePacket(packet); } - /** * The method responsible for TCP reassembly on pcap/pcapng files */ -void doTcpReassemblyOnPcapFile(const std::string& fileName, pcpp::TcpReassembly& tcpReassembly, const std::string& bpfFilter = "") +void doTcpReassemblyOnPcapFile(const std::string& fileName, pcpp::TcpReassembly& tcpReassembly, + const std::string& bpfFilter = "") { // open input file (pcap or pcapng file) pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader(fileName); @@ -538,11 +556,11 @@ void doTcpReassemblyOnPcapFile(const std::string& fileName, pcpp::TcpReassembly& std::cout << "Done! processed " << numOfConnectionsProcessed << " connections" << std::endl; } - /** * The method responsible for TCP reassembly on live traffic */ -void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly& tcpReassembly, const std::string& bpfFilter = "") +void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly& tcpReassembly, + const std::string& bpfFilter = "") { // try to open device if (!dev->open()) @@ -565,7 +583,7 @@ void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted(onApplicationInterrupted, &shouldStop); // run in an endless loop until the user presses ctrl+c - while(!shouldStop) + while (!shouldStop) pcpp::multiPlatformSleep(1); // stop capturing and close the live device @@ -578,7 +596,6 @@ void doTcpReassemblyOnLiveTraffic(pcpp::PcapLiveDevice* dev, pcpp::TcpReassembly std::cout << "Done! processed " << tcpReassembly.getConnectionInformation().size() << " connections" << std::endl; } - /** * main method of this utility */ @@ -598,48 +615,48 @@ int main(int argc, char* argv[]) int optionIndex = 0; int opt; - while((opt = getopt_long(argc, argv, "i:r:o:e:f:mcsvhl", TcpAssemblyOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "i:r:o:e:f:mcsvhl", TcpAssemblyOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - break; - case 'i': - interfaceNameOrIP = optarg; - break; - case 'r': - inputPcapFileName = optarg; - break; - case 'o': - outputDir = optarg; - break; - case 'e': - bpfFilter = optarg; - break; - case 's': - separateSides = true; - break; - case 'm': - writeMetadata = true; - break; - case 'c': - writeToConsole = true; - break; - case 'f': - maxOpenFiles = (size_t)atoi(optarg); - break; - case 'h': - printUsage(); - exit(0); - case 'v': - printAppVersion(); - break; - case 'l': - listInterfaces(); - break; - default: - printUsage(); - exit(-1); + case 0: + break; + case 'i': + interfaceNameOrIP = optarg; + break; + case 'r': + inputPcapFileName = optarg; + break; + case 'o': + outputDir = optarg; + break; + case 'e': + bpfFilter = optarg; + break; + case 's': + separateSides = true; + break; + case 'm': + writeMetadata = true; + break; + case 'c': + writeToConsole = true; + break; + case 'f': + maxOpenFiles = (size_t)atoi(optarg); + break; + case 'h': + printUsage(); + exit(0); + case 'v': + printAppVersion(); + break; + case 'l': + listInterfaces(); + break; + default: + printUsage(); + exit(-1); } } @@ -662,17 +679,19 @@ int main(int argc, char* argv[]) TcpReassemblyConnMgr connMgr; // create the TCP reassembly instance - pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &connMgr, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback); + pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &connMgr, tcpReassemblyConnectionStartCallback, + tcpReassemblyConnectionEndCallback); // analyze in pcap file mode if (!inputPcapFileName.empty()) { doTcpReassemblyOnPcapFile(inputPcapFileName, tcpReassembly, bpfFilter); } - else // analyze in live traffic mode + else // analyze in live traffic mode { // extract pcap live device by interface name or IP address - pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); + pcpp::PcapLiveDevice* dev = + pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIpOrName(interfaceNameOrIP); if (dev == nullptr) EXIT_WITH_ERROR("Couldn't find interface by provided IP address or name"); diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp index 50417731f3..0260cd7cb1 100644 --- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp +++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.cpp @@ -1,10 +1,8 @@ #include "WorkerThread.h" - -L2FwdWorkerThread::L2FwdWorkerThread(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice) : - m_RxDevice(rxDevice), m_TxDevice(txDevice), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES+1) -{ -} +L2FwdWorkerThread::L2FwdWorkerThread(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice) + : m_RxDevice(rxDevice), m_TxDevice(txDevice), m_Stop(true), m_CoreId(MAX_NUM_OF_CORES + 1) +{} bool L2FwdWorkerThread::run(uint32_t coreId) { diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h index 3e2a7ebb40..aff9e96933 100644 --- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h +++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/WorkerThread.h @@ -5,18 +5,19 @@ class L2FwdWorkerThread : public pcpp::DpdkWorkerThread { - private: +private: pcpp::DpdkDevice* m_RxDevice; pcpp::DpdkDevice* m_TxDevice; bool m_Stop; uint32_t m_CoreId; public: - // c'tor + // c'tor L2FwdWorkerThread(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice); // d'tor (does nothing) - ~L2FwdWorkerThread() { } + ~L2FwdWorkerThread() + {} // implement abstract method diff --git a/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp b/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp index a240fde53b..2e8eb2092e 100644 --- a/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp +++ b/Examples/Tutorials/Tutorial-DpdkL2Fwd/main.cpp @@ -6,7 +6,7 @@ #include "TablePrinter.h" #include "WorkerThread.h" -#define MBUF_POOL_SIZE 16*1024-1 +#define MBUF_POOL_SIZE 16 * 1024 - 1 #define DEVICE_ID_1 0 #define DEVICE_ID_2 1 #define COLLECT_STATS_EVERY_SEC 2 @@ -20,7 +20,6 @@ void onApplicationInterrupted(void* cookie) std::cout << std::endl << "Shutting down..." << std::endl; } - void printStats(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice) { pcpp::DpdkDevice::DpdkDeviceStats rxStats; @@ -28,21 +27,24 @@ void printStats(pcpp::DpdkDevice* rxDevice, pcpp::DpdkDevice* txDevice) rxDevice->getStatistics(rxStats); txDevice->getStatistics(txStats); - std::vector columnNames = {" ", "Total Packets", "Packets/sec", "Bytes", "Bits/sec"}; - std::vector columnLengths = {10, 15, 15, 15, 15}; + std::vector columnNames = { " ", "Total Packets", "Packets/sec", "Bytes", "Bits/sec" }; + std::vector columnLengths = { 10, 15, 15, 15, 15 }; pcpp::TablePrinter printer(columnNames, columnLengths); std::stringstream totalRx; - totalRx << "rx" << "|" << rxStats.aggregatedRxStats.packets << "|" << rxStats.aggregatedRxStats.packetsPerSec << "|" << rxStats.aggregatedRxStats.bytes << "|" << rxStats.aggregatedRxStats.bytesPerSec*8; + totalRx << "rx" + << "|" << rxStats.aggregatedRxStats.packets << "|" << rxStats.aggregatedRxStats.packetsPerSec << "|" + << rxStats.aggregatedRxStats.bytes << "|" << rxStats.aggregatedRxStats.bytesPerSec * 8; printer.printRow(totalRx.str(), '|'); std::stringstream totalTx; - totalTx << "tx" << "|" << txStats.aggregatedTxStats.packets << "|" << txStats.aggregatedTxStats.packetsPerSec << "|" << txStats.aggregatedTxStats.bytes << "|" << txStats.aggregatedTxStats.bytesPerSec*8; + totalTx << "tx" + << "|" << txStats.aggregatedTxStats.packets << "|" << txStats.aggregatedTxStats.packetsPerSec << "|" + << txStats.aggregatedTxStats.bytes << "|" << txStats.aggregatedTxStats.bytesPerSec * 8; printer.printRow(totalTx.str(), '|'); } - int main(int argc, char* argv[]) { // Register the on app close event handler @@ -70,13 +72,15 @@ int main(int argc, char* argv[]) // Open DPDK devices if (!device1->openMultiQueues(1, 1)) { - std::cerr << "Couldn't open device1 #" << device1->getDeviceId() << ", PMD '" << device1->getPMDName() << "'" << std::endl; + std::cerr << "Couldn't open device1 #" << device1->getDeviceId() << ", PMD '" << device1->getPMDName() << "'" + << std::endl; return 1; } if (!device2->openMultiQueues(1, 1)) { - std::cerr << "Couldn't open device2 #" << device2->getDeviceId() << ", PMD '" << device2->getPMDName() << "'" << std::endl; + std::cerr << "Couldn't open device2 #" << device2->getDeviceId() << ", PMD '" << device2->getPMDName() << "'" + << std::endl; return 1; } @@ -115,21 +119,14 @@ int main(int argc, char* argv[]) // Clear screen and move to top left std::cout << "\033[2J\033[1;1H"; - std::cout - << "Stats #" << statsCounter++ << std::endl - << "==========" << std::endl - << std::endl; + std::cout << "Stats #" << statsCounter++ << std::endl << "==========" << std::endl << std::endl; // Print stats of traffic going from Device1 to Device2 - std::cout << std::endl - << "Device1->Device2 stats:" << std::endl - << std::endl; + std::cout << std::endl << "Device1->Device2 stats:" << std::endl << std::endl; printStats(device1, device2); // Print stats of traffic going from Device2 to Device1 - std::cout << std::endl - << "Device2->Device1 stats:" << std::endl - << std::endl; + std::cout << std::endl << "Device2->Device1 stats:" << std::endl << std::endl; printStats(device2, device1); } counter++; diff --git a/Examples/Tutorials/Tutorial-HelloWorld/main.cpp b/Examples/Tutorials/Tutorial-HelloWorld/main.cpp index fcad0e09fb..89f3bdf6d2 100644 --- a/Examples/Tutorials/Tutorial-HelloWorld/main.cpp +++ b/Examples/Tutorials/Tutorial-HelloWorld/main.cpp @@ -32,10 +32,8 @@ int main(int argc, char* argv[]) pcpp::IPv4Address destIP = parsedPacket.getLayerOfType()->getDstIPv4Address(); // print source and dest IPs - std::cout - << "Source IP is '" << srcIP << "'; " - << "Dest IP is '" << destIP << "'" - << std::endl; + std::cout << "Source IP is '" << srcIP << "'; " + << "Dest IP is '" << destIP << "'" << std::endl; } // close the file diff --git a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp index b80acf7bc9..38d0d433da 100644 --- a/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp +++ b/Examples/Tutorials/Tutorial-LiveTraffic/main.cpp @@ -17,11 +17,14 @@ struct PacketStats int httpPacketCount = 0; int sslPacketCount = 0; - /** * Clear all stats */ - void clear() { ethPacketCount = ipv4PacketCount = ipv6PacketCount = tcpPacketCount = udpPacketCount = dnsPacketCount = httpPacketCount = sslPacketCount = 0; } + void clear() + { + ethPacketCount = ipv4PacketCount = ipv6PacketCount = tcpPacketCount = udpPacketCount = dnsPacketCount = + httpPacketCount = sslPacketCount = 0; + } // Constructor is optional here since the members are already initialized PacketStats() = default; @@ -54,19 +57,17 @@ struct PacketStats */ void printToConsole() { - std::cout - << "Ethernet packet count: " << ethPacketCount << std::endl - << "IPv4 packet count: " << ipv4PacketCount << std::endl - << "IPv6 packet count: " << ipv6PacketCount << std::endl - << "TCP packet count: " << tcpPacketCount << std::endl - << "UDP packet count: " << udpPacketCount << std::endl - << "DNS packet count: " << dnsPacketCount << std::endl - << "HTTP packet count: " << httpPacketCount << std::endl - << "SSL packet count: " << sslPacketCount << std::endl; + std::cout << "Ethernet packet count: " << ethPacketCount << std::endl + << "IPv4 packet count: " << ipv4PacketCount << std::endl + << "IPv6 packet count: " << ipv6PacketCount << std::endl + << "TCP packet count: " << tcpPacketCount << std::endl + << "UDP packet count: " << udpPacketCount << std::endl + << "DNS packet count: " << dnsPacketCount << std::endl + << "HTTP packet count: " << httpPacketCount << std::endl + << "SSL packet count: " << sslPacketCount << std::endl; } }; - /** * A callback function for the async capture which is called each time a packet is captured */ @@ -82,7 +83,6 @@ static void onPacketArrives(pcpp::RawPacket* packet, pcpp::PcapLiveDevice* dev, stats->consumePacket(parsedPacket); } - /** * a callback function for the blocking mode capture which is called each time a packet is captured */ @@ -101,7 +101,6 @@ static bool onPacketArrivesBlockingMode(pcpp::RawPacket* packet, pcpp::PcapLiveD return false; } - /** * main method of the application */ @@ -122,13 +121,12 @@ int main(int argc, char* argv[]) // ~~~~~~~~~~~~~~~ // before capturing packets let's print some info about this interface - std::cout - << "Interface info:" << std::endl - << " Interface name: " << dev->getName() << std::endl // get interface name - << " Interface description: " << dev->getDesc() << std::endl // get interface description - << " MAC address: " << dev->getMacAddress() << std::endl // get interface MAC address - << " Default gateway: " << dev->getDefaultGateway() << std::endl // get default gateway - << " Interface MTU: " << dev->getMtu() << std::endl; // get interface MTU + std::cout << "Interface info:" << std::endl + << " Interface name: " << dev->getName() << std::endl // get interface name + << " Interface description: " << dev->getDesc() << std::endl // get interface description + << " MAC address: " << dev->getMacAddress() << std::endl // get interface MAC address + << " Default gateway: " << dev->getDefaultGateway() << std::endl // get default gateway + << " Interface MTU: " << dev->getMtu() << std::endl; // get interface MTU if (!dev->getDnsServers().empty()) { @@ -145,13 +143,13 @@ int main(int argc, char* argv[]) // create the stats object PacketStats stats; - // Async packet capture with a callback function // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::cout << std::endl << "Starting async capture..." << std::endl; - // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats object as the cookie + // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats + // object as the cookie dev->startCapture(onPacketArrives, &stats); // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread @@ -167,7 +165,6 @@ int main(int argc, char* argv[]) // clear stats stats.clear(); - // Capturing packets in a packet vector // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -199,13 +196,13 @@ int main(int argc, char* argv[]) // clear stats stats.clear(); - // Capturing packets in blocking mode // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ std::cout << std::endl << "Starting capture in blocking mode..." << std::endl; - // start capturing in blocking mode. Give a callback function to call to whenever a packet is captured, the stats object as the cookie and a 10 seconds timeout + // start capturing in blocking mode. Give a callback function to call to whenever a packet is captured, the stats + // object as the cookie and a 10 seconds timeout dev->startCaptureBlockingMode(onPacketArrivesBlockingMode, &stats, 10); // thread is blocked until capture is finished @@ -216,16 +213,14 @@ int main(int argc, char* argv[]) stats.clear(); - // Sending single packets // ~~~~~~~~~~~~~~~~~~~~~~ std::cout << std::endl << "Sending " << packetVec.size() << " packets one by one..." << std::endl; // go over the vector of packets and send them one by one - bool allSent = std::all_of(packetVec.begin(), packetVec.end(), [dev](pcpp::RawPacket* packet) { - return dev->sendPacket(*packet); - }); + bool allSent = std::all_of(packetVec.begin(), packetVec.end(), + [dev](pcpp::RawPacket* packet) { return dev->sendPacket(*packet); }); if (!allSent) { @@ -235,18 +230,17 @@ int main(int argc, char* argv[]) std::cout << packetVec.size() << " packets sent" << std::endl; - // Sending batch of packets // ~~~~~~~~~~~~~~~~~~~~~~~~ std::cout << std::endl << "Sending " << packetVec.size() << " packets..." << std::endl; - // send all packets in the vector. The returned number shows how many packets were actually sent (expected to be equal to vector size) + // send all packets in the vector. The returned number shows how many packets were actually sent (expected to be + // equal to vector size) int packetsSent = dev->sendPackets(packetVec); std::cout << packetsSent << " packets sent" << std::endl; - // Using filters // ~~~~~~~~~~~~~ @@ -266,7 +260,8 @@ int main(int argc, char* argv[]) std::cout << std::endl << "Starting packet capture with a filter in place..." << std::endl; - // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats object as the cookie + // start capture in async mode. Give a callback function to call to whenever a packet is captured and the stats + // object as the cookie dev->startCapture(onPacketArrives, &stats); // sleep for 10 seconds in main thread, in the meantime packets are captured in the async thread diff --git a/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp b/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp index 71823e5748..bf02192c18 100644 --- a/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp +++ b/Examples/Tutorials/Tutorial-PacketCraftAndEdit/main.cpp @@ -83,7 +83,8 @@ int main(int argc, char* argv[]) // remove cookie field httpRequestLayer->removeField(PCPP_HTTP_COOKIE_FIELD); // add x-forwarded-for field - pcpp::HeaderField* xForwardedForField = httpRequestLayer->insertField(httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD), "X-Forwarded-For", "1.1.1.1"); + pcpp::HeaderField* xForwardedForField = httpRequestLayer->insertField( + httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD), "X-Forwarded-For", "1.1.1.1"); // add cache-control field httpRequestLayer->insertField(xForwardedForField, "Cache-Control", "max-age=0"); @@ -104,7 +105,6 @@ int main(int argc, char* argv[]) writer.close(); } - // Packet Creation // ~~~~~~~~~~~~~~~ diff --git a/Examples/Tutorials/Tutorial-PacketParsing/main.cpp b/Examples/Tutorials/Tutorial-PacketParsing/main.cpp index 15999f00c4..0e437eb00b 100644 --- a/Examples/Tutorials/Tutorial-PacketParsing/main.cpp +++ b/Examples/Tutorials/Tutorial-PacketParsing/main.cpp @@ -31,14 +31,22 @@ std::string printTcpFlags(pcpp::TcpLayer* tcpLayer) { std::string result; auto* tcpHeader = tcpLayer->getTcpHeader(); - if (tcpHeader->synFlag) result += "SYN "; - if (tcpHeader->ackFlag) result += "ACK "; - if (tcpHeader->pshFlag) result += "PSH "; - if (tcpHeader->cwrFlag) result += "CWR "; - if (tcpHeader->urgFlag) result += "URG "; - if (tcpHeader->eceFlag) result += "ECE "; - if (tcpHeader->rstFlag) result += "RST "; - if (tcpHeader->finFlag) result += "FIN "; + if (tcpHeader->synFlag) + result += "SYN "; + if (tcpHeader->ackFlag) + result += "ACK "; + if (tcpHeader->pshFlag) + result += "PSH "; + if (tcpHeader->cwrFlag) + result += "CWR "; + if (tcpHeader->urgFlag) + result += "URG "; + if (tcpHeader->eceFlag) + result += "ECE "; + if (tcpHeader->rstFlag) + result += "RST "; + if (tcpHeader->finFlag) + result += "FIN "; return result; } @@ -102,15 +110,17 @@ int main(int argc, char* argv[]) // parse the raw packet into a parsed packet pcpp::Packet parsedPacket(&rawPacket); - // first let's go over the layers one by one and find out its type, its total length, its header length and its payload length + // first let's go over the layers one by one and find out its type, its total length, its header length and its + // payload length for (auto* curLayer = parsedPacket.getFirstLayer(); curLayer != nullptr; curLayer = curLayer->getNextLayer()) { - std::cout - << "Layer type: " << getProtocolTypeAsString(curLayer->getProtocol()) << "; " // get layer type - << "Total data: " << curLayer->getDataLen() << " [bytes]; " // get total length of the layer - << "Layer data: " << curLayer->getHeaderLen() << " [bytes]; " // get the header length of the layer - << "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of the layer (equals total length minus header length) - << std::endl; + std::cout << "Layer type: " << getProtocolTypeAsString(curLayer->getProtocol()) << "; " // get layer type + << "Total data: " << curLayer->getDataLen() << " [bytes]; " // get total length of the layer + << "Layer data: " << curLayer->getHeaderLen() << " [bytes]; " // get the header length of the layer + << "Layer payload: " << curLayer->getLayerPayloadSize() << " [bytes]" // get the payload length of + // the layer (equals total + // length minus header length) + << std::endl; } // now let's get the Ethernet layer @@ -123,9 +133,10 @@ int main(int argc, char* argv[]) // print the source and dest MAC addresses and the Ether type std::cout << std::endl - << "Source MAC address: " << ethernetLayer->getSourceMac() << std::endl - << "Destination MAC address: " << ethernetLayer->getDestMac() << std::endl - << "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) << std::endl; + << "Source MAC address: " << ethernetLayer->getSourceMac() << std::endl + << "Destination MAC address: " << ethernetLayer->getDestMac() << std::endl + << "Ether type = 0x" << std::hex << pcpp::netToHost16(ethernetLayer->getEthHeader()->etherType) + << std::endl; // let's get the IPv4 layer auto* ipLayer = parsedPacket.getLayerOfType(); @@ -137,10 +148,10 @@ int main(int argc, char* argv[]) // print source and dest IP addresses, IP ID and TTL std::cout << std::endl - << "Source IP address: " << ipLayer->getSrcIPAddress() << std::endl - << "Destination IP address: " << ipLayer->getDstIPAddress() << std::endl - << "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << std::endl - << "TTL: " << std::dec << (int)ipLayer->getIPv4Header()->timeToLive << std::endl; + << "Source IP address: " << ipLayer->getSrcIPAddress() << std::endl + << "Destination IP address: " << ipLayer->getDstIPAddress() << std::endl + << "IP ID: 0x" << std::hex << pcpp::netToHost16(ipLayer->getIPv4Header()->ipId) << std::endl + << "TTL: " << std::dec << (int)ipLayer->getIPv4Header()->timeToLive << std::endl; // let's get the TCP layer auto* tcpLayer = parsedPacket.getLayerOfType(); @@ -152,13 +163,14 @@ int main(int argc, char* argv[]) // print TCP source and dest ports, window size, and the TCP flags that are set in this layer std::cout << std::endl - << "Source TCP port: " << tcpLayer->getSrcPort() << std::endl - << "Destination TCP port: " << tcpLayer->getDstPort() << std::endl - << "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << std::endl - << "TCP flags: " << printTcpFlags(tcpLayer) << std::endl; + << "Source TCP port: " << tcpLayer->getSrcPort() << std::endl + << "Destination TCP port: " << tcpLayer->getDstPort() << std::endl + << "Window size: " << pcpp::netToHost16(tcpLayer->getTcpHeader()->windowSize) << std::endl + << "TCP flags: " << printTcpFlags(tcpLayer) << std::endl; std::cout << "TCP options: "; - for (pcpp::TcpOption tcpOption = tcpLayer->getFirstTcpOption(); tcpOption.isNotNull(); tcpOption = tcpLayer->getNextTcpOption(tcpOption)) + for (pcpp::TcpOption tcpOption = tcpLayer->getFirstTcpOption(); tcpOption.isNotNull(); + tcpOption = tcpLayer->getNextTcpOption(tcpOption)) { std::cout << printTcpOptionType(tcpOption.getTcpOptionEnumType()) << " "; } @@ -174,14 +186,15 @@ int main(int argc, char* argv[]) // print HTTP method and URI. Both appear in the first line of the HTTP request std::cout << std::endl - << "HTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << std::endl - << "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << std::endl; + << "HTTP method: " << printHttpMethod(httpRequestLayer->getFirstLine()->getMethod()) << std::endl + << "HTTP URI: " << httpRequestLayer->getFirstLine()->getUri() << std::endl; // print values of the following HTTP field: Host, User-Agent and Cookie - std::cout - << "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << std::endl - << "HTTP user-agent: " << httpRequestLayer->getFieldByName(PCPP_HTTP_USER_AGENT_FIELD)->getFieldValue() << std::endl - << "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() << std::endl; + std::cout << "HTTP host: " << httpRequestLayer->getFieldByName(PCPP_HTTP_HOST_FIELD)->getFieldValue() << std::endl + << "HTTP user-agent: " << httpRequestLayer->getFieldByName(PCPP_HTTP_USER_AGENT_FIELD)->getFieldValue() + << std::endl + << "HTTP cookie: " << httpRequestLayer->getFieldByName(PCPP_HTTP_COOKIE_FIELD)->getFieldValue() + << std::endl; // print the full URL of this request std::cout << "HTTP full URL: " << httpRequestLayer->getUrl() << std::endl; diff --git a/Examples/Tutorials/Tutorial-PcapFiles/main.cpp b/Examples/Tutorials/Tutorial-PcapFiles/main.cpp index eedb5a1730..739265c4d8 100644 --- a/Examples/Tutorials/Tutorial-PcapFiles/main.cpp +++ b/Examples/Tutorials/Tutorial-PcapFiles/main.cpp @@ -69,8 +69,8 @@ int main(int argc, char* argv[]) // Use lambda to simplify statistics output auto printStats = [](const std::string& writerName, const pcpp::IPcapDevice::PcapStats& stats) { - std::cout << "Written " << stats.packetsRecv << " packets successfully to " << writerName - << " and " << stats.packetsDrop << " packets could not be written" << std::endl; + std::cout << "Written " << stats.packetsRecv << " packets successfully to " << writerName << " and " + << stats.packetsDrop << " packets could not be written" << std::endl; }; // create the stats object @@ -78,7 +78,8 @@ int main(int argc, char* argv[]) // read stats from reader and print them reader->getStatistics(stats); - std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop << " packets could not be read" << std::endl; + std::cout << "Read " << stats.packetsRecv << " packets successfully and " << stats.packetsDrop + << " packets could not be read" << std::endl; // read stats from pcap writer and print them pcapWriter.getStatistics(stats); diff --git a/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h b/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h index ef249f114a..e5354898ed 100644 --- a/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h +++ b/Examples/XdpExample-FilterTraffic/PacketMatchingEngine.h @@ -7,8 +7,9 @@ #include "SystemUtils.h" /** - * Responsible for matching packets by match criteria received from the user. Current match criteria are a combination of zero or more of the - * following parameters: source IP, dest IP, source TCP/UDP port, dest TCP/UDP port and TCP/UDP protocol. + * Responsible for matching packets by match criteria received from the user. Current match criteria are a combination + * of zero or more of the following parameters: source IP, dest IP, source TCP/UDP port, dest TCP/UDP port and TCP/UDP + * protocol. */ class PacketMatchingEngine { @@ -19,11 +20,13 @@ class PacketMatchingEngine bool m_MatchSrcIp, m_MatchDstIp; bool m_MatchSrcPort, m_MatchDstPort; bool m_MatchProtocol; + public: - PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) - : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), - m_SrcPortToMatch(srcPortToMatch), m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), - m_MatchSrcIp(false), m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) + PacketMatchingEngine(const pcpp::IPv4Address& srcIpToMatch, const pcpp::IPv4Address& dstIpToMatch, + uint16_t srcPortToMatch, uint16_t dstPortToMatch, pcpp::ProtocolType protocolToMatch) + : m_SrcIpToMatch(srcIpToMatch), m_DstIpToMatch(dstIpToMatch), m_SrcPortToMatch(srcPortToMatch), + m_DstPortToMatch(dstPortToMatch), m_ProtocolToMatch(protocolToMatch), m_MatchSrcIp(false), + m_MatchDstIp(false), m_MatchSrcPort(false), m_MatchDstPort(false), m_MatchProtocol(false) { if (m_SrcIpToMatch != pcpp::IPv4Address::Zero) m_MatchSrcIp = true; diff --git a/Examples/XdpExample-FilterTraffic/main.cpp b/Examples/XdpExample-FilterTraffic/main.cpp index 747984737d..f08b180c44 100644 --- a/Examples/XdpExample-FilterTraffic/main.cpp +++ b/Examples/XdpExample-FilterTraffic/main.cpp @@ -1,12 +1,12 @@ /** -* Filter Traffic AF_XDP example application -* ========================================= -* -* This application demonstrates PcapPlusPlus AF_XDP APIs. -* Please read the README.md file for more information. -* -* You can also run `XdpTrafficFilter -h` for modes of operation and parameters. -*/ + * Filter Traffic AF_XDP example application + * ========================================= + * + * This application demonstrates PcapPlusPlus AF_XDP APIs. + * Please read the README.md file for more information. + * + * You can also run `XdpTrafficFilter -h` for modes of operation and parameters. + */ #include "PacketMatchingEngine.h" #include "SystemUtils.h" @@ -22,15 +22,19 @@ #include #include -#define EXIT_WITH_ERROR(reason) do { \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ - } while(0) +#define EXIT_WITH_ERROR(reason) \ + do \ + { \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ + } while (0) -#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) do { \ - printUsage(); \ - std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ - exit(1); \ +#define EXIT_WITH_ERROR_AND_PRINT_USAGE(reason) \ + do \ + { \ + printUsage(); \ + std::cout << std::endl << "ERROR: " << reason << std::endl << std::endl; \ + exit(1); \ } while (0) /** @@ -55,9 +59,11 @@ struct PacketStats int matchedUdpFlows; int matchedPacketCount; - PacketStats() : packetCount(0), ethCount(0), arpCount(0), ip4Count(0), ip6Count(0), tcpCount(0), udpCount(0), - httpCount(0), dnsCount(0), sslCount(0), - totalTcpFlows(0), totalUdpFlows(0), matchedTcpFlows(0), matchedUdpFlows(0), matchedPacketCount(0) {} + PacketStats() + : packetCount(0), ethCount(0), arpCount(0), ip4Count(0), ip6Count(0), tcpCount(0), udpCount(0), httpCount(0), + dnsCount(0), sslCount(0), totalTcpFlows(0), totalUdpFlows(0), matchedTcpFlows(0), matchedUdpFlows(0), + matchedPacketCount(0) + {} /** * Collect stats per packet @@ -98,22 +104,26 @@ struct PacketCaptureArgs pcpp::PcapFileWriterDevice* pcapWriter; bool stopCapture; - PacketCaptureArgs() : packetStats(nullptr), matchingEngine(nullptr), sendPacketsTo(nullptr), pcapWriter(nullptr), stopCapture(false) {} + PacketCaptureArgs() + : packetStats(nullptr), matchingEngine(nullptr), sendPacketsTo(nullptr), pcapWriter(nullptr), stopCapture(false) + {} }; +// clang-format off static struct option XdpFilterTrafficOptions[] = { - {"interface", required_argument, nullptr, 'n'}, - {"send-matched-packets", required_argument, nullptr, 's'}, - {"save-matched-packets", required_argument, nullptr, 'f'}, - {"match-source-ip", required_argument, nullptr, 'i'}, - {"match-dest-ip", required_argument, nullptr, 'I'}, - {"match-source-port", required_argument, nullptr, 'p'}, - {"match-dest-port", required_argument, nullptr, 'P'}, - {"match-protocol", required_argument, nullptr, 'r'}, - {"help", no_argument, nullptr, 'h'}, - {"version", no_argument, nullptr, 'v'}, - {"list-interfaces", no_argument, nullptr, 'l'} + { "interface", required_argument, nullptr, 'n' }, + { "send-matched-packets", required_argument, nullptr, 's' }, + { "save-matched-packets", required_argument, nullptr, 'f' }, + { "match-source-ip", required_argument, nullptr, 'i' }, + { "match-dest-ip", required_argument, nullptr, 'I' }, + { "match-source-port", required_argument, nullptr, 'p' }, + { "match-dest-port", required_argument, nullptr, 'P' }, + { "match-protocol", required_argument, nullptr, 'r' }, + { "help", no_argument, nullptr, 'h' }, + { "version", no_argument, nullptr, 'v' }, + { "list-interfaces", no_argument, nullptr, 'l' } }; +// clang-format on /** * A callback to handle packets that were received on the AF_XDP socket @@ -140,7 +150,8 @@ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpD // collect stats for packet args->packetStats->collectStats(packet); - // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or new flow + // hash the packet by 5-tuple and look in the flow table to see whether this packet belongs to an existing or + // new flow uint32_t hash = pcpp::hash5Tuple(&packet); auto iter = args->flowTable.find(hash); @@ -151,7 +162,7 @@ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpD { packetMatched = true; } - else // packet belongs to a new flow + else // packet belongs to a new flow { auto isTcpFlow = packet.isPacketOfType(pcpp::TCP); auto isUdpFlow = packet.isPacketOfType(pcpp::UDP); @@ -171,7 +182,7 @@ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpD // put new flow in flow table args->flowTable[hash] = true; - //collect stats + // collect stats if (isTcpFlow) { args->packetStats->matchedTcpFlows++; @@ -210,10 +221,11 @@ void onPacketsArrive(pcpp::RawPacket packets[], uint32_t packetCount, pcpp::XdpD /** * Print the stats in a table */ -void printStats(PacketStats* packetStats, pcpp::XdpDevice::XdpDeviceStats* rxDeviceStats, pcpp::XdpDevice::XdpDeviceStats* txDeviceStats) +void printStats(PacketStats* packetStats, pcpp::XdpDevice::XdpDeviceStats* rxDeviceStats, + pcpp::XdpDevice::XdpDeviceStats* txDeviceStats) { - std::vector columnNames = {"Stat", "Count"}; - std::vector columnsWidths = {21, 10}; + std::vector columnNames = { "Stat", "Count" }; + std::vector columnsWidths = { 21, 10 }; pcpp::TablePrinter printer(columnNames, columnsWidths); printer.printRow("Eth count|" + std::to_string(packetStats->ethCount), '|'); @@ -268,7 +280,7 @@ void collectStats(std::future futureObj, PacketStats* packetStats, pcpp::X { txStats = new pcpp::XdpDevice::XdpDeviceStats(sendDev->getStatistics()); } - else // send and receive sockets are the same + else // send and receive sockets are the same { txStats = &rxStats; } @@ -290,39 +302,51 @@ void collectStats(std::future futureObj, PacketStats* packetStats, pcpp::X void printUsage() { std::cout << std::endl - << "Usage:" << std::endl - << "------" << std::endl - << pcpp::AppName::get() << " [-hvl] [-s INTERFACE_NAME] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r PROTOCOL] -n INTERFACE_NAME" << std::endl - << std::endl - << "Options:" << std::endl - << std::endl - << " -h|--help : Displays this help message and exits" << std::endl - << " -v|--version : Displays the current version and exits" << std::endl - << " -l|--list : Print the list of network interfaces and exit" << std::endl - << " -n|--interface-name INTERFACE_NAME : An interface name to open AF_XDP socket and receive packets from." << std::endl - << " To see all available interfaces use the -l switch" << std::endl - << " -s|--send-matched-packets INTERFACE_NAME : Network interface name to send matched packets to." << std::endl - << " The app will open another AF_XDP socket for sending packets." << std::endl - << " Note: this interface can be the same one used to receive packets." << std::endl - << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." << std::endl - << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl - << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl - << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl - << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl - << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" << std::endl - << std::endl; + << "Usage:" << std::endl + << "------" << std::endl + << pcpp::AppName::get() + << " [-hvl] [-s INTERFACE_NAME] [-f FILENAME] [-i IPV4_ADDR] [-I IPV4_ADDR] [-p PORT] [-P PORT] [-r " + "PROTOCOL] -n INTERFACE_NAME" + << std::endl + << std::endl + << "Options:" << std::endl + << std::endl + << " -h|--help : Displays this help message and exits" << std::endl + << " -v|--version : Displays the current version and exits" << std::endl + << " -l|--list : Print the list of network interfaces and exit" + << std::endl + << " -n|--interface-name INTERFACE_NAME : An interface name to open AF_XDP socket and receive " + "packets from." + << std::endl + << " To see all available interfaces use the -l switch" + << std::endl + << " -s|--send-matched-packets INTERFACE_NAME : Network interface name to send matched packets to." + << std::endl + << " The app will open another AF_XDP socket for sending " + "packets." + << std::endl + << " Note: this interface can be the same one used to " + "receive packets." + << std::endl + << " -f|--save-matched-packets FILEPATH : Save matched packets to pcap files under FILEPATH." + << std::endl + << " -i|--match-source-ip IPV4_ADDR : Match source IPv4 address" << std::endl + << " -I|--match-dest-ip IPV4_ADDR : Match destination IPv4 address" << std::endl + << " -p|--match-source-port PORT : Match source TCP/UDP port" << std::endl + << " -P|--match-dest-port PORT : Match destination TCP/UDP port" << std::endl + << " -r|--match-protocol PROTOCOL : Match protocol. Valid values are 'TCP' or 'UDP'" + << std::endl + << std::endl; } - /** * Print application version */ void printAppVersion() { - std::cout - << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl - << "Built: " << pcpp::getBuildDateTime() << std::endl - << "Built from: " << pcpp::getGitInfo() << std::endl; + std::cout << pcpp::AppName::get() << " " << pcpp::getPcapPlusPlusVersionFull() << std::endl + << "Built: " << pcpp::getBuildDateTime() << std::endl + << "Built from: " << pcpp::getGitInfo() << std::endl; exit(0); } @@ -332,11 +356,12 @@ void printAppVersion() void listInterfaces() { std::cout << std::endl << "Network interfaces:" << std::endl; - for(const auto& device : pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList()) + for (const auto& device : pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDevicesList()) { if (device->getIPv4Address() != pcpp::IPv4Address::Zero) { - std::cout << " -> Name: '" << device->getName() << "' IP address: " << device->getIPv4Address().toString() << std::endl; + std::cout << " -> Name: '" << device->getName() + << "' IP address: " << device->getIPv4Address().toString() << std::endl; } } exit(0); @@ -351,119 +376,119 @@ int main(int argc, char* argv[]) std::string interfaceName; - pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; - pcpp::IPv4Address dstIPToMatch = pcpp::IPv4Address::Zero; - uint16_t srcPortToMatch = 0; - uint16_t dstPortToMatch = 0; + pcpp::IPv4Address srcIPToMatch = pcpp::IPv4Address::Zero; + pcpp::IPv4Address dstIPToMatch = pcpp::IPv4Address::Zero; + uint16_t srcPortToMatch = 0; + uint16_t dstPortToMatch = 0; pcpp::ProtocolType protocolToMatch = pcpp::UnknownProtocol; std::string writePacketsToFileName; std::string sendInterfaceName; - while((opt = getopt_long(argc, argv, "n:f:s:i:I:p:P:r:vhl", XdpFilterTrafficOptions, &optionIndex)) != -1) + while ((opt = getopt_long(argc, argv, "n:f:s:i:I:p:P:r:vhl", XdpFilterTrafficOptions, &optionIndex)) != -1) { switch (opt) { - case 0: - { - break; - } - case 'n': - { - interfaceName = std::string(optarg); - break; - } - case 'f': - { - writePacketsToFileName = std::string(optarg); - break; - } - case 's': - { - sendInterfaceName = std::string(optarg); - break; - } - case 'i': + case 0: + { + break; + } + case 'n': + { + interfaceName = std::string(optarg); + break; + } + case 'f': + { + writePacketsToFileName = std::string(optarg); + break; + } + case 's': + { + sendInterfaceName = std::string(optarg); + break; + } + case 'i': + { + try { - try - { - srcIPToMatch = pcpp::IPv4Address(optarg); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); - } - break; + srcIPToMatch = pcpp::IPv4Address(optarg); } - case 'I': + catch (const std::exception&) { - try - { - dstIPToMatch = pcpp::IPv4Address(optarg); - } - catch(const std::exception&) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Source IP to match isn't a valid IP address"); } - case 'p': + break; + } + case 'I': + { + try { - int ret = std::stoi(optarg); - if (ret <= 0 || ret > 65535) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); - } - srcPortToMatch = ret; - break; + dstIPToMatch = pcpp::IPv4Address(optarg); } - case 'P': + catch (const std::exception&) { - int ret = std::stoi(optarg); - if (ret <= 0 || ret > 65535) - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); - } - dstPortToMatch = ret; - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination IP to match isn't a valid IP address"); } - case 'r': + break; + } + case 'p': + { + int ret = std::stoi(optarg); + if (ret <= 0 || ret > 65535) { - std::string protocol = std::string(optarg); - if (protocol == "TCP") - { - protocolToMatch = pcpp::TCP; - } - else if (protocol == "UDP") - { - protocolToMatch = pcpp::UDP; - } - else - { - EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); - } - break; + EXIT_WITH_ERROR_AND_PRINT_USAGE("Source port to match isn't a valid TCP/UDP port"); } - case 'h': + srcPortToMatch = ret; + break; + } + case 'P': + { + int ret = std::stoi(optarg); + if (ret <= 0 || ret > 65535) { - printUsage(); - exit(0); + EXIT_WITH_ERROR_AND_PRINT_USAGE("Destination port to match isn't a valid TCP/UDP port"); } - case 'v': + dstPortToMatch = ret; + break; + } + case 'r': + { + std::string protocol = std::string(optarg); + if (protocol == "TCP") { - printAppVersion(); - break; + protocolToMatch = pcpp::TCP; } - case 'l': + else if (protocol == "UDP") { - listInterfaces(); - exit(0); + protocolToMatch = pcpp::UDP; } - default: + else { - printUsage(); - exit(0); + EXIT_WITH_ERROR_AND_PRINT_USAGE("Protocol to match isn't TCP or UDP"); } + break; + } + case 'h': + { + printUsage(); + exit(0); + } + case 'v': + { + printAppVersion(); + break; + } + case 'l': + { + listInterfaces(); + exit(0); + } + default: + { + printUsage(); + exit(0); + } } } @@ -532,7 +557,8 @@ int main(int argc, char* argv[]) std::thread collectStatsThread(&collectStats, std::move(futureObj), &packetStats, &dev, sendDev); // add an handler for app interrupted signal, i.e ctrl+c - pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted([](void* args){reinterpret_cast(args)->stopCapture = true;}, &args); + pcpp::ApplicationEventHandler::getInstance().onApplicationInterrupted( + [](void* args) { reinterpret_cast(args)->stopCapture = true; }, &args); // start receiving packets on the AF_XDP socket auto res = dev.receivePackets(onPacketsArrive, &args, -1); @@ -549,7 +575,8 @@ int main(int argc, char* argv[]) { pcpp::IPcapDevice::PcapStats stats; pcapWriter->getStatistics(stats); - additionalStats.push_back("Wrote " + std::to_string(stats.packetsRecv) + " packets to '" + pcapWriter->getFileName() + "'"); + additionalStats.push_back("Wrote " + std::to_string(stats.packetsRecv) + " packets to '" + + pcapWriter->getFileName() + "'"); pcapWriter->close(); delete pcapWriter; } diff --git a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp index b93c799899..1536131312 100644 --- a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp +++ b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp @@ -302,7 +302,8 @@ PTF_TEST_CASE(TestPcapLiveDevice) { // Should probably be refactored as PTF_ASSERT_CONTAINS or similar. auto const ipAddresses = liveDev->getIPAddresses(); - PTF_ASSERT_TRUE(std::any_of(ipAddresses.begin(), ipAddresses.end(), [ipToSearch](pcpp::IPAddress const& addr) { return addr == ipToSearch; })); + PTF_ASSERT_TRUE(std::any_of(ipAddresses.begin(), ipAddresses.end(), + [ipToSearch](pcpp::IPAddress const& addr) { return addr == ipToSearch; })); } DeviceTeardown devTeardown(liveDev); From 08615ee80e5ce21599fa67263e34e55f875cee2a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Tue, 30 Jul 2024 07:24:17 +0300 Subject: [PATCH 21/35] Added overload to getAndDetach that accepts a constant reference to allow usage of temporaries to point to members. (such as immediately using the result of begin()). (#1512) --- Common++/header/PointerVector.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Common++/header/PointerVector.h b/Common++/header/PointerVector.h index 299c190033..bd04b38261 100644 --- a/Common++/header/PointerVector.h +++ b/Common++/header/PointerVector.h @@ -302,6 +302,18 @@ namespace pcpp return result; } + /** + * 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 result(*position); + m_Vector.erase(position); + return result; + } + /** * Return a pointer to the element in a certain index * @param[in] index The index to retrieve the element from From aa4d7c23fc7b72591af8d9c92212a9cb9a6a9f3d Mon Sep 17 00:00:00 2001 From: seladb Date: Thu, 1 Aug 2024 06:54:29 -0700 Subject: [PATCH 22/35] Auto OUI Database Update (#1518) Co-authored-by: GitHub --- 3rdParty/OUIDataset/PCPP_OUIDataset.json | 570 ++++++++++++++++++++++- 1 file changed, 558 insertions(+), 12 deletions(-) diff --git a/3rdParty/OUIDataset/PCPP_OUIDataset.json b/3rdParty/OUIDataset/PCPP_OUIDataset.json index bdf78794cb..687289d177 100644 --- a/3rdParty/OUIDataset/PCPP_OUIDataset.json +++ b/3rdParty/OUIDataset/PCPP_OUIDataset.json @@ -8334,7 +8334,7 @@ "vendor": "Airgo Networks, Inc." }, "2806": { - "vendor": "Emerson Climate Technologies Retail Solutions, Inc." + "vendor": "Copeland LP" }, "2807": { "vendor": "Broadcom" @@ -33413,6 +33413,9 @@ "29304": { "vendor": "Cisco Systems, Inc" }, + "29422": { + "vendor": "Intel Corporate" + }, "29581": { "vendor": "Shenzhen TINNO Mobile Technology Corp." }, @@ -35924,6 +35927,9 @@ "41215": { "vendor": "Tellabs Operations, Inc." }, + "41305": { + "vendor": "LG Electronics" + }, "41438": { "vendor": "ShenZhen ShiHua Technology CO.,LTD" }, @@ -35978,6 +35984,9 @@ "42884": { "vendor": "ITX security" }, + "43293": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "43520": { "vendor": "Intel Corporation" }, @@ -38912,6 +38921,9 @@ "63601": { "vendor": "Demant A/S" }, + "63692": { + "vendor": "Sagemcom Broadband SAS" + }, "63826": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -39344,6 +39356,9 @@ "284164": { "vendor": "Gionee Communication Equipment Co.,Ltd." }, + "284261": { + "vendor": "Nokia Shanghai Bell Co., Ltd." + }, "284389": { "vendor": "Intel Corporate" }, @@ -40826,6 +40841,9 @@ "542764": { "vendor": "Raycore Taiwan Co., LTD." }, + "542807": { + "vendor": "Suteng Innovation Technology Co., Ltd." + }, "543439": { "vendor": "Guangdong Oppo Mobile Telecommunications Corp.,Ltd" }, @@ -41999,6 +42017,9 @@ "818556": { "vendor": "Kexiang Information Technology Co, Ltd." }, + "818724": { + "vendor": "Garmin International" + }, "819122": { "vendor": "ARRIS Group, Inc." }, @@ -42137,6 +42158,9 @@ "824581": { "vendor": "The Chamberlain Group, Inc" }, + "824597": { + "vendor": "Palltronics, Inc." + }, "824641": { "vendor": "Chipsea Technologies (Shenzhen) Corp." }, @@ -42299,6 +42323,9 @@ "835776": { "vendor": "Magneti Marelli Sistemas Electronicos Mexico" }, + "835865": { + "vendor": "Shenzhen Phaten Tech. LTD" + }, "836519": { "vendor": "Meritec" }, @@ -42833,6 +42860,9 @@ "1061915": { "vendor": "Spacelink" }, + "1062295": { + "vendor": "Qorvo Utrecht B.V." + }, "1062474": { "vendor": "Boston Dynamics" }, @@ -42996,7 +43026,7 @@ "vendor": "Huawei Device Co., Ltd." }, "1072898": { - "vendor": "Private" + "vendor": "Ruijie Networks Co.,LTD" }, "1072902": { "vendor": "Actiontec Electronics, Inc" @@ -43091,6 +43121,9 @@ "1078383": { "vendor": "Motorola Solutions Malaysia Sdn. Bhd." }, + "1078469": { + "vendor": "Calix Inc." + }, "1078838": { "vendor": "Earda Technologies co Ltd" }, @@ -43949,6 +43982,9 @@ "1324549": { "vendor": "Nokia Corporation" }, + "1324558": { + "vendor": "Zyxel Communications Corporation" + }, "1324742": { "vendor": "Lenovo Mobile Communication Technology Ltd." }, @@ -44105,6 +44141,9 @@ "1333765": { "vendor": "Apple, Inc." }, + "1333825": { + "vendor": "Cloud Network Technology Singapore Pte. Ltd." + }, "1333891": { "vendor": "Logi-D inc" }, @@ -44210,6 +44249,9 @@ "1342938": { "vendor": "Apple, Inc." }, + "1343001": { + "vendor": "Hewlett Packard Enterprise" + }, "1343137": { "vendor": "Britania Eletrônicos S.A." }, @@ -46226,6 +46268,9 @@ "1860020": { "vendor": "TP-Link Corporation Limited" }, + "1860222": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "1860280": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -46586,6 +46631,9 @@ "1881065": { "vendor": "Shenzhen Zhongke United Communication Technology" }, + "1881196": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "1881900": { "vendor": "ASUSTek COMPUTER INC." }, @@ -46907,6 +46955,9 @@ "2102240": { "vendor": "Samsung Electronics Co.,Ltd" }, + "2102468": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "2102658": { "vendor": "Apple, Inc." }, @@ -49028,6 +49079,9 @@ "2630645": { "vendor": "China Mobile (Hangzhou) Information Technology Co., Ltd." }, + "2630857": { + "vendor": "Amazon Technologies Inc." + }, "2630911": { "vendor": "Wistron Neweb Corporation" }, @@ -49982,6 +50036,9 @@ "2796627": { "vendor": "Wolfspyre Labs" }, + "2808791": { + "vendor": "Vesper Technologies" + }, "2812437": { "vendor": "Tibit Communications" }, @@ -50054,6 +50111,9 @@ "2886633": { "vendor": "Cisco Systems, Inc" }, + "2886951": { + "vendor": "Huawei Device Co., Ltd." + }, "2887079": { "vendor": "Intel Corporate" }, @@ -50360,6 +50420,9 @@ "2905555": { "vendor": "Huawei Technologies Co.,Ltd" }, + "2905731": { + "vendor": "China Mobile Group Device Co.,Ltd." + }, "2905820": { "vendor": "ASUSTek COMPUTER INC." }, @@ -51389,6 +51452,9 @@ "3168400": { "vendor": "Frontier Silicon Ltd" }, + "3168491": { + "vendor": "zte corporation" + }, "3168603": { "vendor": "streamnow AG" }, @@ -51452,6 +51518,9 @@ "3173566": { "vendor": "Skymotion Technology (HK) Limited" }, + "3173881": { + "vendor": "Guangdong Oppo Mobile Telecommunications Corp.,Ltd" + }, "3173980": { "vendor": "Validus Technologies" }, @@ -51884,6 +51953,9 @@ "3202279": { "vendor": "zte corporation" }, + "3202474": { + "vendor": "Zhejiang Dahua Technologyco.,Ltd" + }, "3202635": { "vendor": "TP-Link Corporation Limited" }, @@ -51917,6 +51989,9 @@ "3203990": { "vendor": "Huawei Device Co., Ltd." }, + "3204004": { + "vendor": "Intel Corporate" + }, "3204054": { "vendor": "Spotify USA Inc." }, @@ -51992,6 +52067,9 @@ "3209175": { "vendor": "Thread Technology Co., Ltd" }, + "3209543": { + "vendor": "Shenzhen Skyworth Digital Technology CO., Ltd" + }, "3209547": { "vendor": "Universal Electronics, Inc." }, @@ -52052,6 +52130,9 @@ "3409743": { "vendor": "AccelStor, Inc." }, + "3409836": { + "vendor": "Pronyx Trading Llc" + }, "3409915": { "vendor": "Ericsson AB" }, @@ -52130,6 +52211,9 @@ "3413406": { "vendor": "Apple, Inc." }, + "3413814": { + "vendor": "Shenzhen iComm Semiconductor CO.,LTD" + }, "3413995": { "vendor": "Dell Inc." }, @@ -52388,6 +52472,9 @@ "3430936": { "vendor": "Alignment Engine Inc." }, + "3431008": { + "vendor": "Micro-Star INTL CO., LTD." + }, "3431098": { "vendor": "tcloud intelligence" }, @@ -52706,6 +52793,9 @@ "3449506": { "vendor": "Huawei Technologies Co.,Ltd" }, + "3449678": { + "vendor": "NevadaNano" + }, "3449749": { "vendor": "Apple, Inc." }, @@ -53033,6 +53123,9 @@ "3466967": { "vendor": "Dell Inc." }, + "3466982": { + "vendor": "LG Innotek" + }, "3467019": { "vendor": "HAN Networks Co., Ltd" }, @@ -53189,6 +53282,9 @@ "3671732": { "vendor": "A.D.C. GmbH" }, + "3671782": { + "vendor": "Arcadyan Corporation" + }, "3671830": { "vendor": "Freebox Sas" }, @@ -53510,6 +53606,9 @@ "3691675": { "vendor": "zte corporation" }, + "3691765": { + "vendor": "AltoBeam Inc." + }, "3692048": { "vendor": "CANDY HOUSE, Inc." }, @@ -54218,6 +54317,9 @@ "3804789": { "vendor": "Kevcom Llc" }, + "3808960": { + "vendor": "Aces" + }, "3814721": { "vendor": "Raspberry Pi (Trading) Ltd" }, @@ -54584,6 +54686,9 @@ "3951250": { "vendor": "Hewlett Packard" }, + "3951305": { + "vendor": "Huawei Device Co., Ltd." + }, "3951721": { "vendor": "Infinity System S.L." }, @@ -54626,6 +54731,9 @@ "3954511": { "vendor": "China Mobile Group Device Co.,Ltd." }, + "3954533": { + "vendor": "Unionman Technology Co.,Ltd" + }, "3954540": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -55880,6 +55988,9 @@ "4231706": { "vendor": "Apple, Inc." }, + "4231753": { + "vendor": "Shanghai Baud Data Communication Co.,Ltd." + }, "4232453": { "vendor": "Acoinfo Technology Co.,Ltd" }, @@ -56399,6 +56510,9 @@ "4457791": { "vendor": "Sagemcom Broadband SAS" }, + "4457912": { + "vendor": "Huawei Device Co., Ltd." + }, "4457960": { "vendor": "twareLAB" }, @@ -56930,6 +57044,9 @@ "4491467": { "vendor": "Camco Technologies NV" }, + "4491629": { + "vendor": "Tellescom Industria E Comercio Em Telecomunicacao" + }, "4491867": { "vendor": "Micro-Star INT'L CO., LTD." }, @@ -57101,6 +57218,9 @@ "4502546": { "vendor": "Sius Ag" }, + "4502563": { + "vendor": "Hanwha Vision Vietnam Company Limited" + }, "4502579": { "vendor": "tide.co.,ltd" }, @@ -57806,6 +57926,9 @@ "4741945": { "vendor": "ASUSTek COMPUTER INC." }, + "4742188": { + "vendor": "Earda Technologies co Ltd" + }, "4742453": { "vendor": "AVM Audiovisuelles Marketing und Computersysteme GmbH" }, @@ -57824,6 +57947,9 @@ "4742920": { "vendor": "Tp-Link Technologies Co.,Ltd." }, + "4742957": { + "vendor": "Amazon Technologies Inc." + }, "4743065": { "vendor": "Cloud Network Technology (Samoa) Limited" }, @@ -58148,6 +58274,9 @@ "4761884": { "vendor": "Apple, Inc." }, + "4761956": { + "vendor": "Apexsha Smarttech Private Limited" + }, "4761994": { "vendor": "Routerboard.com" }, @@ -58178,6 +58307,9 @@ "4764707": { "vendor": "Amazon Technologies Inc." }, + "4764708": { + "vendor": "eero inc." + }, "4764867": { "vendor": "Hewlett Packard Enterprise" }, @@ -58688,6 +58820,9 @@ "4989528": { "vendor": "cozybit, Inc." }, + "4989641": { + "vendor": "zte corporation" + }, "4989683": { "vendor": "Arcadyan Corporation" }, @@ -58808,6 +58943,9 @@ "4999386": { "vendor": "Beijing Autelan Technology Co.,Ltd" }, + "4999465": { + "vendor": "TCL King Electrical Appliances(Huizhou)Co.,Ltd" + }, "4999503": { "vendor": "zte corporation" }, @@ -59045,6 +59183,9 @@ "5012040": { "vendor": "Nippon Seiki (Europe) B.V." }, + "5012277": { + "vendor": "Unionman Technology Co.,Ltd" + }, "5012575": { "vendor": "Apple, Inc." }, @@ -59516,6 +59657,9 @@ "5043291": { "vendor": "Blue Clover Devices" }, + "5043317": { + "vendor": "Huawei Device Co., Ltd." + }, "5043547": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -59561,6 +59705,9 @@ "5243020": { "vendor": "Hong Kong Telecommunications (HKT) Limited" }, + "5243104": { + "vendor": "Cisco Systems, Inc" + }, "5243243": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -59582,6 +59729,9 @@ "5244221": { "vendor": "CyWee Group Ltd" }, + "5244270": { + "vendor": "Guangdong Oppo Mobile Telecommunications Corp.,Ltd" + }, "5244420": { "vendor": "Cisco Systems, Inc" }, @@ -62336,6 +62486,9 @@ "5813811": { "vendor": "Ruckus Wireless" }, + "5814360": { + "vendor": "Sz Dji Technology Co.,Ltd" + }, "5814625": { "vendor": "SOLEM Electronique" }, @@ -62744,6 +62897,9 @@ "6035637": { "vendor": "Talon Communications" }, + "6035677": { + "vendor": "Cig Shanghai Co Ltd" + }, "6036079": { "vendor": "Cambridge Industries(Group) Co.,Ltd." }, @@ -62930,6 +63086,9 @@ "6049215": { "vendor": "zte corporation" }, + "6049518": { + "vendor": "AltoBeam Inc." + }, "6049813": { "vendor": "Cisco Systems, Inc" }, @@ -63407,12 +63566,18 @@ "6077957": { "vendor": "Ispec" }, + "6078057": { + "vendor": "Oraimo Technology Limited" + }, "6078624": { "vendor": "Huawei Technologies Co.,Ltd" }, "6078935": { "vendor": "Samsung Electronics Co.,Ltd" }, + "6078962": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "6078995": { "vendor": "Fr. Sauter AG" }, @@ -63521,6 +63686,9 @@ "6085332": { "vendor": "Murata Manufacturing Co., Ltd." }, + "6085430": { + "vendor": "Calix Inc." + }, "6085782": { "vendor": "Arcadyan Technology Corporation" }, @@ -64001,6 +64169,9 @@ "6309323": { "vendor": "ASUSTek COMPUTER INC." }, + "6309325": { + "vendor": "Sagemcom Broadband SAS" + }, "6309398": { "vendor": "Xiamen Vann Intelligent Co., Ltd" }, @@ -64064,6 +64235,9 @@ "6313625": { "vendor": "MAGNETI MARELLI S.E. S.p.A." }, + "6313649": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "6313752": { "vendor": "Intel Corporate" }, @@ -65750,6 +65924,9 @@ "6610460": { "vendor": "Kingnetic Pte Ltd" }, + "6610541": { + "vendor": "Intel Corporate" + }, "6610704": { "vendor": "JingLue Semiconductor(SH) Ltd." }, @@ -65792,6 +65969,9 @@ "6612952": { "vendor": "Samsung Electronics Co.,Ltd" }, + "6613013": { + "vendor": "Arcelik A.S" + }, "6613043": { "vendor": "Espressif Inc." }, @@ -66290,6 +66470,9 @@ "6842866": { "vendor": "ComAp s.r.o." }, + "6843242": { + "vendor": "Phytium Technology Co.,Ltd." + }, "6843622": { "vendor": "Microsoft Corporation" }, @@ -66404,6 +66587,9 @@ "6850411": { "vendor": "INQ Mobile Limited" }, + "6850493": { + "vendor": "zte corporation" + }, "6850502": { "vendor": "Cisco Systems, Inc" }, @@ -68582,6 +68768,9 @@ "7372181": { "vendor": "Shenzhen City LinwlanTechnology Co. Ltd." }, + "7372207": { + "vendor": "Plucent AB" + }, "7372217": { "vendor": "Cisco Systems, Inc" }, @@ -68702,6 +68891,9 @@ "7379467": { "vendor": "Italian Institute of Technology" }, + "7379652": { + "vendor": "Huawei Device Co., Ltd." + }, "7379877": { "vendor": "Shenzhen Y&D Electronics Co.,LTD." }, @@ -69080,6 +69272,9 @@ "7403215": { "vendor": "Relay, Inc." }, + "7403343": { + "vendor": "Robert Bosch JuP1" + }, "7403348": { "vendor": "AMPAK Technology,Inc." }, @@ -69257,6 +69452,9 @@ "7612503": { "vendor": "Mayfield Robotics" }, + "7612521": { + "vendor": "Huawei Device Co., Ltd." + }, "7612786": { "vendor": "Juniper Networks" }, @@ -69365,6 +69563,9 @@ "7617560": { "vendor": "Taicang T&W Electronics" }, + "7617572": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "7618091": { "vendor": "Ruckus Wireless" }, @@ -69614,6 +69815,9 @@ "7632200": { "vendor": "Amazon Technologies Inc." }, + "7632351": { + "vendor": "Teclink" + }, "7632475": { "vendor": "Quectel Wireless Solutions Co.,Ltd." }, @@ -70118,6 +70322,9 @@ "7660172": { "vendor": "Microsoft Corporation" }, + "7660263": { + "vendor": "Cisco Systems, Inc" + }, "7660277": { "vendor": "Apple, Inc." }, @@ -70226,6 +70433,9 @@ "7665757": { "vendor": "Berkeley Nucleonics Corp" }, + "7665935": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "7665946": { "vendor": "Onface" }, @@ -70406,6 +70616,9 @@ "7873085": { "vendor": "Affirmed Networks" }, + "7873160": { + "vendor": "Shenzhen Bilian Electronic Co.,Ltd" + }, "7873319": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -70721,6 +70934,9 @@ "7889561": { "vendor": "BITSTREAM sp. z o.o." }, + "7890080": { + "vendor": "Cisco Systems, Inc" + }, "7890112": { "vendor": "Apple, Inc." }, @@ -72611,6 +72827,9 @@ "8390111": { "vendor": "Montage Technology Group Limited" }, + "8390361": { + "vendor": "zte corporation" + }, "8390427": { "vendor": "Vsolution Telecommunication Technology Co.,Ltd." }, @@ -72866,6 +73085,9 @@ "8407084": { "vendor": "Wyze Labs Inc" }, + "8407199": { + "vendor": "Hangzhou Hikvision Digital Technology Co.,Ltd." + }, "8407205": { "vendor": "Sichuan Tianyi Comheart Telecom Co.,LTD" }, @@ -73358,6 +73580,9 @@ "8437423": { "vendor": "Hangzhou Hikvision Digital Technology Co.,Ltd." }, + "8437790": { + "vendor": "Intel Corporate" + }, "8438126": { "vendor": "Hewlett Packard" }, @@ -73469,6 +73694,9 @@ "8443045": { "vendor": "Huawei Technologies Co.,Ltd" }, + "8443180": { + "vendor": "Beijing Cheering Networks Technology Co.,Ltd." + }, "8443397": { "vendor": "Apple, Inc." }, @@ -73626,7 +73854,7 @@ "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" }, "8652740": { - "vendor": "Carrier Corporation" + "vendor": "Walter Kidde Portable Equipment, Inc." }, "8653470": { "vendor": "Nexapp Technologies Pvt Ltd" @@ -74390,6 +74618,9 @@ "8699474": { "vendor": "Huawei Technologies Co.,Ltd" }, + "8699531": { + "vendor": "Chengdu Geeker Technology Co., Ltd." + }, "8700143": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -75671,6 +75902,9 @@ "8975504": { "vendor": "Jetmobile Pte Ltd" }, + "8975578": { + "vendor": "Intel Corporate" + }, "8975726": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -75869,6 +76103,9 @@ "9181939": { "vendor": "Shenzhen Gooxi Information Security CO.,Ltd." }, + "9182549": { + "vendor": "Hanwha NxMD (Thailand) Co., Ltd." + }, "9182614": { "vendor": "Intel Corporate" }, @@ -76034,6 +76271,9 @@ "9194986": { "vendor": "Cerio Corporation" }, + "9195264": { + "vendor": "Espressif Inc." + }, "9195781": { "vendor": "Shenzhen ireadygo Information Technology CO.,LTD." }, @@ -76505,6 +76745,9 @@ "9224102": { "vendor": "Samsung Electronics Co.,Ltd" }, + "9224170": { + "vendor": "Espressif Inc." + }, "9224481": { "vendor": "Panasonic Corporation AVC Networks Company" }, @@ -78128,6 +78371,9 @@ "9712605": { "vendor": "Taco Inc" }, + "9712687": { + "vendor": "Itel Mobile Limited" + }, "9712745": { "vendor": "Silicon Laboratories" }, @@ -78692,6 +78938,9 @@ "9749181": { "vendor": "Tecnobit" }, + "9749355": { + "vendor": "DRD Automation GmbH" + }, "9749476": { "vendor": "Atlas Copco IAS GmbH" }, @@ -78740,6 +78989,9 @@ "9752113": { "vendor": "CTS Limited" }, + "9752496": { + "vendor": "Huawei Device Co., Ltd." + }, "9752589": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -78917,6 +79169,9 @@ "9759693": { "vendor": "BlackBerry RTS" }, + "9759794": { + "vendor": "Silicon Laboratories" + }, "9760415": { "vendor": "HMD Global Oy" }, @@ -79619,6 +79874,9 @@ "10002206": { "vendor": "Huawei Technologies Co.,Ltd" }, + "10002762": { + "vendor": "Quectel Wireless Solutions Co.,Ltd." + }, "10003136": { "vendor": "Cisco Systems, Inc" }, @@ -80291,6 +80549,9 @@ "10241379": { "vendor": "DIMEP Sistemas" }, + "10241520": { + "vendor": "Skylark Electronics Pvt Ltd" + }, "10242041": { "vendor": "LJU Automatisierungstechnik GmbH" }, @@ -81239,6 +81500,9 @@ "10494879": { "vendor": "Cisco Systems, Inc" }, + "10495042": { + "vendor": "Shenzhenshi Xinzhongxin Technology Co.Ltd" + }, "10495225": { "vendor": "Chengdu InnovaTest Technology Co., Ltd" }, @@ -81638,6 +81902,9 @@ "10519755": { "vendor": "SonicSensory,Inc." }, + "10520035": { + "vendor": "Espressif Inc." + }, "10520060": { "vendor": "Microsoft Corporation" }, @@ -82127,6 +82394,9 @@ "10549728": { "vendor": "Vivatel Company Limited" }, + "10549916": { + "vendor": "Weifang Goertek Electronics Co.,Ltd" + }, "10549960": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -84458,6 +84728,9 @@ "11285288": { "vendor": "Huawei Device Co., Ltd." }, + "11285329": { + "vendor": "Ericsson AB" + }, "11285707": { "vendor": "Shanhai GBCOM Communication Technology Co. Ltd" }, @@ -84650,6 +84923,9 @@ "11295788": { "vendor": "Apple, Inc." }, + "11295872": { + "vendor": "Telink Micro LLC" + }, "11296016": { "vendor": "Pace Americas" }, @@ -86546,6 +86822,9 @@ "11803947": { "vendor": "Shenzhen YOUHUA Technology Co., Ltd" }, + "11804100": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "11804143": { "vendor": "Internet Laboratories, Inc." }, @@ -86993,6 +87272,9 @@ "11837261": { "vendor": "Fiberhome Telecommunication Technologies Co.,LTD" }, + "11837706": { + "vendor": "Huawei Device Co., Ltd." + }, "11838044": { "vendor": "Cambium Networks Limited" }, @@ -87137,6 +87419,9 @@ "11844114": { "vendor": "China Mobile (Hangzhou) Information Technology Co.,Ltd." }, + "11844202": { + "vendor": "Tecno Mobile Limited" + }, "11844253": { "vendor": "Sky Uk Limited" }, @@ -87971,6 +88256,9 @@ "12095559": { "vendor": "Apple, Inc." }, + "12095845": { + "vendor": "Zhejiang Tmall Technology Co., Ltd." + }, "12095945": { "vendor": "Handreamnet" }, @@ -88277,6 +88565,9 @@ "12113084": { "vendor": "zte corporation" }, + "12113091": { + "vendor": "Huawei Technologies Co.,Ltd" + }, "12113127": { "vendor": "Hewlett Packard Enterprise" }, @@ -88520,6 +88811,9 @@ "12321703": { "vendor": "Mfp Michelin" }, + "12321845": { + "vendor": "GD Midea Air-Conditioning Equipment Co.,Ltd." + }, "12322115": { "vendor": "AVM GmbH" }, @@ -89202,7 +89496,7 @@ "vendor": "Samsung Electronics Co.,Ltd" }, "12362042": { - "vendor": "SES-imagotag" + "vendor": "VusionGroup" }, "12362623": { "vendor": "Rail-Mil Sp. z o.o. Sp. K." @@ -89348,6 +89642,9 @@ "12373317": { "vendor": "Voismart" }, + "12373375": { + "vendor": "Huawei Device Co., Ltd." + }, "12373541": { "vendor": "Nintendo Co.,Ltd" }, @@ -90261,7 +90558,7 @@ "vendor": "Ruijie Networks Co.,LTD" }, "12630758": { - "vendor": "Application Solutions (Safety and Security) Ltd" + "vendor": "Zenitel GB Ltd" }, "12631194": { "vendor": "Huawei Technologies Co.,Ltd" @@ -90893,6 +91190,9 @@ "12865430": { "vendor": "Alps Alpine" }, + "12865493": { + "vendor": "Vantiva - Connected Home" + }, "12865542": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -90962,6 +91262,9 @@ "12869212": { "vendor": "Huawei Technologies Co.,Ltd" }, + "12869642": { + "vendor": "Huaqin Technology Co.LTD" + }, "12869670": { "vendor": "Sky Uk Limited" }, @@ -91334,6 +91637,9 @@ "12891410": { "vendor": "General Electric Digital Energy" }, + "12891793": { + "vendor": "Angel Robotics" + }, "12892340": { "vendor": "Huawei Technologies Co.,Ltd" }, @@ -91466,6 +91772,9 @@ "12900349": { "vendor": "Bouffalo Lab (Nanjing) Co., Ltd." }, + "12900552": { + "vendor": "Silicon Laboratories" + }, "12900565": { "vendor": "Espressif Inc." }, @@ -91559,6 +91868,9 @@ "12905283": { "vendor": "Sagemcom Broadband SAS" }, + "12905320": { + "vendor": "VusionGroup" + }, "12905443": { "vendor": "Rrcn Sas" }, @@ -91667,6 +91979,9 @@ "13108638": { "vendor": "Hefei Symboltek Co.,Ltd" }, + "13108644": { + "vendor": "Motorola(Wuhan) Mobility Technologies Communication Co.,Ltd" + }, "13109016": { "vendor": "TDSi" }, @@ -91991,6 +92306,9 @@ "13129877": { "vendor": "Motorola Mobility LLC, a Lenovo Company" }, + "13129907": { + "vendor": "Intel Corporate" + }, "13129920": { "vendor": "Intel Corporate" }, @@ -92126,6 +92444,9 @@ "13139796": { "vendor": "ASUSTek COMPUTER INC." }, + "13140532": { + "vendor": "Cisco Systems, Inc" + }, "13140756": { "vendor": "Tempo Communications" }, @@ -92354,6 +92675,9 @@ "13153314": { "vendor": "Askey Computer Corp" }, + "13153451": { + "vendor": "Inspur Computer Technology Co.,Ltd." + }, "13153709": { "vendor": "Hewlett Packard Enterprise" }, @@ -92531,6 +92855,9 @@ "13163302": { "vendor": "Logitech" }, + "13163882": { + "vendor": "Ohsung" + }, "13163977": { "vendor": "Lenovo Mobile Communication Technology Ltd." }, @@ -93212,6 +93539,9 @@ "13396977": { "vendor": "Sound Masking Inc." }, + "13397074": { + "vendor": "DZS Inc." + }, "13397408": { "vendor": "Roku, Inc." }, @@ -93245,6 +93575,9 @@ "13399522": { "vendor": "ARRIS Group, Inc." }, + "13399610": { + "vendor": "zte corporation" + }, "13399657": { "vendor": "Seetech" }, @@ -93479,6 +93812,9 @@ "13414568": { "vendor": "Huawei Device Co., Ltd." }, + "13414579": { + "vendor": "Microsoft Corporation" + }, "13414618": { "vendor": "Liteon Technology Corporation" }, @@ -94571,6 +94907,9 @@ "13681073": { "vendor": "Samsung Electronics Co.,Ltd" }, + "13681077": { + "vendor": "Dell Inc." + }, "13681230": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -94616,6 +94955,9 @@ "13682951": { "vendor": "Private" }, + "13683677": { + "vendor": "eero inc." + }, "13684193": { "vendor": "Scientech Electronics" }, @@ -94775,12 +95117,18 @@ "13694779": { "vendor": "Helmut Mauell GmbH Werk Weida" }, + "13694830": { + "vendor": "Shenzhen YOUHUA Technology Co., Ltd" + }, "13695077": { "vendor": "Itel Mobile Limited" }, "13695116": { "vendor": "Motorola (Wuhan) Mobility Technologies Communication Co., Ltd." }, + "13695207": { + "vendor": "Shenzhen Shutong Space Technology Co., Ltd" + }, "13695272": { "vendor": "zte corporation" }, @@ -95423,6 +95771,9 @@ "13929212": { "vendor": "Espressif Inc." }, + "13929545": { + "vendor": "Espressif Inc." + }, "13929653": { "vendor": "Cisco Systems, Inc" }, @@ -96077,6 +96428,9 @@ "14164724": { "vendor": "Avnet Silica" }, + "14164960": { + "vendor": "Speedtech Corp." + }, "14165111": { "vendor": "Universal Electric Corporation" }, @@ -96098,6 +96452,9 @@ "14165689": { "vendor": "Guangdong Coagent Electronics S&T Co.,Ltd." }, + "14165754": { + "vendor": "Jiangxi Zhentian Technology CO.,LTD" + }, "14165772": { "vendor": "MaxTronic International Co., Ltd." }, @@ -96812,6 +97169,9 @@ "14208570": { "vendor": "Xiaomi Communications Co Ltd" }, + "14208865": { + "vendor": "Sagemcom Broadband SAS" + }, "14208905": { "vendor": "Beijing DoSee Science and Technology Co., Ltd." }, @@ -97259,6 +97619,9 @@ "14430364": { "vendor": "Heyrex Limited" }, + "14430512": { + "vendor": "3onedata Technology Co. Ltd." + }, "14430673": { "vendor": "vivo Mobile Communication Co., Ltd." }, @@ -98231,6 +98594,9 @@ "14688043": { "vendor": "Nokia Solutions and Networks GmbH & Co. KG" }, + "14688052": { + "vendor": "HMD Global Oy" + }, "14688106": { "vendor": "Huawei Device Co., Ltd." }, @@ -99233,6 +99599,9 @@ "14950267": { "vendor": "Cisco Systems, Inc" }, + "14950357": { + "vendor": "Intel Corporate" + }, "14950377": { "vendor": "Dunkermotoren GmbH" }, @@ -99312,7 +99681,7 @@ "vendor": "Unicore communication Inc." }, "14954530": { - "vendor": "Hanwha Techwin Security Vietnam" + "vendor": "Hanwha Vision VietNam" }, "14955211": { "vendor": "Samsung Electronics Co.,Ltd" @@ -99449,6 +99818,9 @@ "14962923": { "vendor": "Apple, Inc." }, + "14963113": { + "vendor": "Nanjing Xinlian Electronics Co., Ltd" + }, "14963230": { "vendor": "Texas Instruments" }, @@ -99848,6 +100220,9 @@ "14988056": { "vendor": "Intel Corporate" }, + "14988067": { + "vendor": "Espressif Inc." + }, "14988547": { "vendor": "Realme Chongqing Mobile Telecommunications Corp.,Ltd." }, @@ -100067,6 +100442,9 @@ "15004870": { "vendor": "Netgear" }, + "15005070": { + "vendor": "Schneider Electric USA" + }, "15005531": { "vendor": "ARRIS Group, Inc." }, @@ -100166,6 +100544,9 @@ "15206539": { "vendor": "Huawei Technologies Co.,Ltd" }, + "15206575": { + "vendor": "zte corporation" + }, "15206725": { "vendor": "Integrated Device Technology (Malaysia) Sdn. Bhd." }, @@ -100256,6 +100637,9 @@ "15211944": { "vendor": "Ruckus Wireless" }, + "15212014": { + "vendor": "i-TEK RFID" + }, "15212178": { "vendor": "Huawei Device Co., Ltd." }, @@ -100523,6 +100907,9 @@ "15229374": { "vendor": "Melec Inc." }, + "15229630": { + "vendor": "Intel Corporate" + }, "15230264": { "vendor": "Cloud Network Technology Singapore Pte. Ltd." }, @@ -101168,6 +101555,9 @@ "15267412": { "vendor": "Huawei Technologies Co.,Ltd" }, + "15267443": { + "vendor": "Microsoft Corporation" + }, "15267620": { "vendor": "Hewlett Packard Enterprise" }, @@ -101240,6 +101630,9 @@ "15360118": { "vendor": "CloudSimple, Inc." }, + "15372182": { + "vendor": "Proficium, LLC" + }, "15376305": { "vendor": "Philips International B.V." }, @@ -101345,6 +101738,9 @@ "15473241": { "vendor": "Belkin International Inc." }, + "15473503": { + "vendor": "Hewlett Packard Enterprise" + }, "15473597": { "vendor": "Silicon Laboratories" }, @@ -101540,6 +101936,9 @@ "15484528": { "vendor": "Meinberg Funkuhren GmbH & Co. KG" }, + "15484684": { + "vendor": "Universal Electronics, Inc." + }, "15484732": { "vendor": "Redwire, LLC" }, @@ -101549,6 +101948,9 @@ "15486029": { "vendor": "ZAO NPK RoTeK" }, + "15486092": { + "vendor": "Intel Corporate" + }, "15486270": { "vendor": "Beijing Xiaomi Mobile Software Co., Ltd" }, @@ -101651,6 +102053,9 @@ "15492556": { "vendor": "Panasonic Automotive Systems Company of America" }, + "15492690": { + "vendor": "Info Fiber Solutions Pvt Ltd" + }, "15492817": { "vendor": "B&W Group LTD" }, @@ -101801,6 +102206,9 @@ "15502498": { "vendor": "Ruckus Wireless" }, + "15502967": { + "vendor": "Intel Corporate" + }, "15503021": { "vendor": "Dlx" }, @@ -102230,6 +102638,9 @@ "15530740": { "vendor": "SenRa Tech Pvt. Ltd" }, + "15531055": { + "vendor": "Sagemcom Broadband SAS" + }, "15531093": { "vendor": "A. Eberle GmbH & Co. KG" }, @@ -102344,6 +102755,9 @@ "15736372": { "vendor": "ORICO Technologies Co., Ltd" }, + "15736492": { + "vendor": "Rentokil Initial" + }, "15736751": { "vendor": "Dell Inc." }, @@ -102974,6 +103388,9 @@ "15777070": { "vendor": "H+S Polatis Ltd" }, + "15777262": { + "vendor": "Huawei Device Co., Ltd." + }, "15777265": { "vendor": "Sipod Inc." }, @@ -105200,6 +105617,9 @@ "16298739": { "vendor": "Guangzhou Bosma Technology Co.,Ltd" }, + "16298935": { + "vendor": "Espressif Inc." + }, "16299114": { "vendor": "Hewlett Packard" }, @@ -105872,6 +106292,9 @@ "16531465": { "vendor": "zte corporation" }, + "16531734": { + "vendor": "Google, Inc." + }, "16531971": { "vendor": "Samsung Electronics Co.,Ltd" }, @@ -107975,15 +108398,20 @@ "mask": 28, "vendors": { "40158564974592": "Shanghai Xizhi Technology Co., Ltd.", + "40158566023168": "Shenzhen LianwangRuijie Communication Technology Co, Ltd.", "40158567071744": "Emerson Automation FCP Kft.", + "40158568120320": "ViewSec Co., Ltd.", + "40158569168896": "Codepoint Technologies, Inc.", "40158570217472": "Metro Electronics", + "40158571266048": "Adtek", "40158572314624": "Tianjin Optical Electrical Juneng Communication Co.,Ltd.", "40158573363200": "Ningbo Sigmatek Automation Co., Ltd.", "40158574411776": "Vtron Pty Ltd", "40158575460352": "Tas India Pvt Ltd", "40158576508928": "Wynd Labs", "40158577557504": "L-LIGHT Co., Ltd.", - "40158578606080": "Chengdu HOLDTECS Co.,Ltd" + "40158578606080": "Chengdu HOLDTECS Co.,Ltd", + "40158579654656": "Hangzhou UPAI Technology Co., Ltd" } } ] @@ -109291,6 +109719,31 @@ } ] }, + "4742670": { + "vendor": "", + "maskedFilters": [ + { + "mask": 28, + "vendors": { + "79568799006720": "Shenzhen C & D Electronics Co., Ltd.", + "79568800055296": "Dongguan YEHUO Technology Co.,LTD", + "79568801103872": "Shenzhen Shouchuang Micro Technology Co., Ltd", + "79568802152448": "Shenzhen Anycon Electronics Technology Co.,Ltd", + "79568803201024": "MHE Electronics", + "79568804249600": "GlobalXtreme", + "79568805298176": "Sernet (Suzhou) Technologies Corporation", + "79568806346752": "Shanghai B&A automation.net", + "79568807395328": "Itfc", + "79568808443904": "Cnergee Technologies Private Limited", + "79568809492480": "Aignep Spa", + "79568810541056": "Vital Oricraft Flows Technology Co., Ltd.", + "79568811589632": "Transom Post OpCo LLC dba Bose Professional", + "79568812638208": "Huaqin Technology Co.,Ltd", + "79568813686784": "Eloom System" + } + } + ] + }, "4744686": { "vendor": "", "maskedFilters": [ @@ -109380,6 +109833,7 @@ "80156006809600": "Annapurna labs", "80156007858176": "Moff Inc.", "80156008906752": "Macriot", + "80156009955328": "Sanwa Electronic Instrument Co.,Ltd", "80156011003904": "Takiguchi Corporation", "80156012052480": "Al Hami Information Technology - L.L.C", "80156013101056": "Q-Pac", @@ -112993,6 +113447,31 @@ } ] }, + "11306705": { + "vendor": "", + "maskedFilters": [ + { + "mask": 28, + "vendors": { + "189695032033280": "Advanced Rugged System Co., LTD", + "189695033081856": "Beijing Fantasy Mofang Technology Co.,Ltd", + "189695034130432": "Hamsa India", + "189695035179008": "Inovaxe Corporation", + "189695036227584": "RayThink Technology Co.,Ltd", + "189695037276160": "Hangzhou Lingban Technology Co., Ltd", + "189695038324736": "Adveco Technology Co., Ltd", + "189695039373312": "Quantum-Systems GmbH", + "189695040421888": "PK Sound", + "189695041470464": "Annapurna labs", + "189695042519040": "EMIT GmbH", + "189695043567616": "shenzhen ceita communications technology co.,ltd", + "189695044616192": "MOTUSTECHS(Wuhan)Co.,Ltd.", + "189695045664768": "Krixe Pte. Ltd.", + "189695046713344": "Retina Development B.V." + } + } + ] + }, "11542401": { "vendor": "", "maskedFilters": [ @@ -113724,6 +114203,29 @@ } ] }, + "12910468": { + "vendor": "", + "maskedFilters": [ + { + "mask": 28, + "vendors": { + "216601710297088": "Zhuhai Ninestar Information Technology Co., Ltd.", + "216601712394240": "ShenZhen BoQiao Technologies CO.,LTD.", + "216601713442816": "Cloudhop Inc", + "216601714491392": "Malhotra Electronics Private Limited", + "216601715539968": "Eastern Acoustic Works", + "216601716588544": "Lens Technology (Xiangtan) Co.,Ltd", + "216601717637120": "NEKMA M.Mesek P.Mesek B.Mesek", + "216601718685696": "Ibm", + "216601719734272": "Atlas Copco", + "216601720782848": "Openeye", + "216601721831424": "Elaraby Company For Engineering Industries", + "216601722880000": "KSB SE & Co. KGaA", + "216601723928576": "Aosaishi (Hong Kong) Co.,Limited" + } + } + ] + }, "12910524": { "vendor": "", "maskedFilters": [ @@ -117786,7 +118288,7 @@ "346860302336": "Ast Incorporated", "346860306432": "MoBaCon", "346860310528": "Venture Research Inc.", - "346860314624": "Lyngdorf Audio Aps", + "346860314624": "SL Audio A/S", "346860318720": "Pyrosequencing AB", "346860322816": "Fr. Sauter AG", "346860326912": "Bluebell Opticom Limited", @@ -120191,7 +120693,7 @@ "71297884377088": "Scandyna A/S", "71297884381184": "Tti Ltd", "71297884385280": "Lightstar", - "71297884389376": "Akse srl", + "71297884389376": "AKSE srl", "71297884393472": "Dsp Design", "71297884397568": "Jadpod Communication Company Limited", "71297884401664": "Mango DSP, Inc.", @@ -120545,7 +121047,7 @@ "123917675622400": "Avant Technologies", "123917675626496": "Alcodex Technologies Private Limited", "123917675630592": "Schwer+Kopka GmbH", - "123917675634688": "Akse srl", + "123917675634688": "AKSE srl", "123917675638784": "Jacarta Ltd", "123917675642880": "Cardinal Kinetic", "123917675646976": "PuS GmbH und Co. KG", @@ -120687,7 +121189,7 @@ "123917676204032": "Securolytics, Inc.", "123917676208128": "AddSecure Smart Grids", "123917676212224": "Vitec", - "123917676216320": "Akse srl", + "123917676216320": "AKSE srl", "123917676220416": "OOO \"Microlink-Svyaz\"", "123917676224512": "Elvys s.r.o", "123917676228608": "RIC Electronics", @@ -121874,7 +122376,7 @@ "123917681070080": "ICTK Holdings", "123917681074176": "ACD Elekronik GmbH", "123917681078272": "ECoCoMS Ltd.", - "123917681082368": "Akse srl", + "123917681082368": "AKSE srl", "123917681086464": "MVT Video Technologies R + H Maedler GbR", "123917681090560": "IP Devices", "123917681094656": "PROEL TSI s.r.l.", @@ -124526,6 +125028,7 @@ "154066449891328": "FieldLine Medical", "154066449895424": "Nuances Org", "154066449915904": "Auditdata", + "154066449920000": "ISILINE srl", "154066449928192": "CP contech electronic GmbH", "154066449936384": "HS.com Kft", "154066449944576": "Intercreate", @@ -124585,6 +125088,7 @@ "154066450378752": "Aurora Communication Technologies Corp.", "154066450382848": "Active Research Limited", "154066450403328": "TechnipFMC", + "154066450415616": "EA Elektro-Automatik", "154066450423808": "CLOUD TELECOM Inc.", "154066450436096": "DEUTA Werke GmbH", "154066450456576": "biosilver.co.,ltd", @@ -124594,6 +125098,7 @@ "154066450481152": "Power Electronics Espana, S.L.", "154066450509824": "Leidos", "154066450513920": "Autopharma", + "154066450534400": "Rugged Science", "154066450538496": "Cleanwatts Digital, S.A.", "154066450554880": "SmartSky Networks LLC", "154066450567168": "Saskatchewan Research Council", @@ -124667,6 +125172,7 @@ "154066451152896": "Zelp Ltd", "154066451161088": "MI Inc.", "154066451181568": "NICE Total Cash Management Co., Ltd.", + "154066451189760": "Biotage Gb Ltd", "154066451193856": "Breas Medical AB", "154066451197952": "Sicon srl", "154066451214336": "M-Pulse GmbH & Co.KG", @@ -124751,6 +125257,7 @@ "154066452078592": "R2Sonic, LLC", "154066452082688": "Acuris Inc", "154066452086784": "E-alarms", + "154066452090880": "TargaSystem S.r.L.", "154066452099072": "EPC Power Corporation", "154066452103168": "BR. Voss Ingenjörsfirma AB", "154066452115456": "Karl DUNGS GmbH & Co. KG", @@ -124781,6 +125288,7 @@ "154066452373504": "Radiation Solutions Inc.", "154066452381696": "SHALARM SECURITY Co.,LTD", "154066452385792": "Elbit Systems of America, LLC", + "154066452398080": "Dco Systems Ltd", "154066452418560": "U -Mei-Dah Int'L Enterprise Co.,Ltd.", "154066452439040": "Stercom Power Solutions GmbH", "154066452447232": "Veinland GmbH", @@ -124812,6 +125320,7 @@ "154066452684800": "Enless Wireless", "154066452697088": "Florida R&D Associates LLC", "154066452713472": "TSS COMPANY s.r.o.", + "154066452717568": "Rfengine Co., Ltd.", "154066452721664": "MB connect line GmbH Fernwartungssysteme", "154066452725760": "Unimar, Inc.", "154066452729856": "Enestone Corporation", @@ -124864,10 +125373,12 @@ "154066453155840": "Vector Technologies, Llc", "154066453159936": "MB connect line GmbH Fernwartungssysteme", "154066453164032": "LAMTEC Mess- und Regeltechnik für Feuerungen GmbH & Co. KG", + "154066453168128": "Crosstek Co., Ltd", "154066453172224": "Orbital Astronautics Ltd", "154066453176320": "INVENTIS S.r.l.", "154066453180416": "ViewSonic Corp", "154066453192704": "Abbott Diagnostics Technologies AS", + "154066453196800": "Sp Manufacturing Pte Ltd", "154066453200896": "WOLF Advanced Technology", "154066453209088": "WINK Streaming", "154066453221376": "Duevi Srl", @@ -124911,6 +125422,7 @@ "154066453508096": "Clausal Computing Oy", "154066453516288": "Oriux", "154066453532672": "Suzhou Lianshichuangzhi Technology Co., Ltd", + "154066453536768": "Samuel Cosgrove", "154066453544960": "NavSys Technology Inc.", "154066453549056": "Stratis IOT", "154066453553152": "Wavestream Corp", @@ -124981,8 +125493,10 @@ "154066454265856": "Audiobyte S.R.L.", "154066454269952": "Alpine Quantum Technologies GmbH", "154066454274048": "Clair Global Corporation", + "154066454286336": "AKSE srl", "154066454290432": "Missing Link Electronics, Inc.", "154066454302720": "Eb Neuro Spa", + "154066454306816": "Novanta IMS", "154066454319104": "VirtualV Trading Limited", "154066454343680": "TECHKON GmbH", "154066454351872": "Hupi", @@ -125008,6 +125522,7 @@ "154066454507520": "miniDSP", "154066454511616": "U -Mei-Dah Int'L Enterprise Co.,Ltd.", "154066454556672": "IWS Global Pty Ltd", + "154066454573056": "Smart Monitoring Innovations Private Limited", "154066454581248": "Clock-O-Matic", "154066454605824": "SBS SpA", "154066454614016": "Apantac LLC", @@ -125021,6 +125536,7 @@ "154066454691840": "BESO sp. z o.o.", "154066454695936": "Griffyn Robotech Private Limited", "154066454708224": "PuS GmbH und Co. KG", + "154066454720512": "Exi Flow Measurement Ltd", "154066454724608": "Nuvation Energy", "154066454728704": "Renukas Castle Hard- and Software", "154066454736896": "Circuit Solutions", @@ -125046,6 +125562,7 @@ "154066454904832": "Novanta IMS", "154066454908928": "Control Aut Tecnologia em Automação LTDA", "154066454913024": "Blik Sensing B.V.", + "154066454929408": "Tcl Operations Polska Sp. Z O.O.", "154066454933504": "Smart Radar System, Inc", "154066454937600": "Wagner Group GmbH", "154066454945792": "TELE Haase Steuergeräte Ges.m.b.H", @@ -125080,6 +125597,7 @@ "154066455191552": "BAE Systems", "154066455195648": "In-lite Design BV", "154066455199744": "Scitel", + "154066455203840": "Intozi Tech Pvt Ltd", "154066455216128": "Schildknecht AG", "154066455224320": "Hanateksystem", "154066455232512": "Dexter Laundry Inc.", @@ -125119,12 +125637,14 @@ "154066455560192": "Sonel S.A.", "154066455572480": "eumig industrie-TV GmbH.", "154066455576576": "Axion Lighting", + "154066455588864": "Vortex Sp. z o.o.", "154066455597056": "ViewSonic Corp", "154066455609344": "Heitec Ag", "154066455613440": "MPT-Service project", "154066455617536": "Benchmark Electronics BV", "154066455638016": "R3Vox Ltd", "154066455642112": "Cooltera Limited", + "154066455650304": "Systems With Intelligence Inc.", "154066455662592": "Abbott Diagnostics Technologies AS", "154066455670784": "dinosys", "154066455678976": "Mahindr & Mahindra", @@ -125211,6 +125731,7 @@ "154066456371200": "sdt.net AG", "154066456375296": "Frey S.J.", "154066456387584": "MG s.r.l.", + "154066456391680": "Wi-DAS LLC", "154066456395776": "Ensto Protrol AB", "154066456399872": "Ravi Teleinfomatics", "154066456403968": "LDA Audiotech", @@ -125247,6 +125768,7 @@ "154066456727552": "Wuhan Xingtuxinke ELectronic Co.,Ltd", "154066456735744": "Italora", "154066456739840": "Abb", + "154066456756224": "Hitachi Energy Poland sp. Z o o", "154066456760320": "HTK Hamburg GmbH", "154066456764416": "Argosdyne Co., Ltd", "154066456776704": "Khimo", @@ -125264,6 +125786,7 @@ "154066456899584": "EddyWorks Co.,Ltd", "154066456903680": "Proiker Technology Sl", "154066456907776": "Anddoro Llc", + "154066456915968": "Exatron Servers Manufacturing Pvt Ltd", "154066456920064": "HM Systems A/S", "154066456936448": "Quantaflow", "154066456944640": "AIDirections", @@ -125275,6 +125798,7 @@ "154066457010176": "Nexion Data Systems P/L", "154066457022464": "Internet Protocolo Logica Sl", "154066457034752": "Abb", + "154066457042944": "Chell Instruments Ltd", "154066457047040": "Adasky Ltd.", "154066457055232": "Epigon spol. s r.o.", "154066457071616": "M/S Milind Ramachandra Rajwade", @@ -125314,6 +125838,7 @@ "154066457362432": "mapna group", "154066457366528": "Vonamic GmbH", "154066457370624": "Dorlet Sau", + "154066457378816": "Guan Show Technologe Co., Ltd.", "154066457411584": "navXperience GmbH", "154066457415680": "Becton Dickinson", "154066457423872": "Sicon srl", @@ -125335,6 +125860,7 @@ "154066457591808": "Potter Electric Signal Co. LLC", "154066457595904": "Guardian Controls International Ltd", "154066457608192": "Hirotech inc.", + "154066457612288": "Potter Electric Signal Company", "154066457616384": "OTMetric", "154066457620480": "Timegate Instruments Ltd.", "154066457632768": "XSENSOR Technology Corp.", @@ -125348,6 +125874,7 @@ "154066457686016": "James G. Biddle dba Megger", "154066457690112": "TimeMachines Inc.", "154066457694208": "Deviceroy", + "154066457702400": "Kotsu Dengyosha Co., Ltd.", "154066457706496": "GO development GmbH", "154066457747456": "Flextronics International Kft", "154066457751552": "Ascon Tecnologic S.r.l.", @@ -125392,6 +125919,7 @@ "154066458062848": "Pribusin Inc.", "154066458079232": "nke marine electronics", "154066458091520": "Gemini Electronics B.V.", + "154066458103808": "Gogo BA", "154066458112000": "ViewSonic Corp", "154066458116096": "Tiama", "154066458136576": "MTU Aero Engines AG", @@ -125521,6 +126049,7 @@ "154066459320320": "UniJet Co., Ltd.", "154066459324416": "LLC \"TC \"Vympel\"", "154066459332608": "tickIoT Inc.", + "154066459336704": "Vision Systems Safety Tech", "154066459344896": "Bcmtech", "154066459353088": "Monnit Corporation", "154066459357184": "Förster Technik GmbH", @@ -125551,6 +126080,7 @@ "154066459611136": "Aksel sp. z o.o.", "154066459619328": "Breas Medical AB", "154066459627520": "DB Systel GmbH", + "154066459635712": "Applied Electro Magnetics Pvt. Ltd.", "154066459639808": "uHave Control, Inc", "154066459656192": "EVLO Stockage Énergie", "154066459680768": "EIDOS s.r.l.", @@ -125561,6 +126091,7 @@ "154066459713536": "Instituto De Gestão, Redes Tecnológicas E Nergias", "154066459725824": "Tiama", "154066459734016": "Dave Srl", + "154066459738112": "Hangzhou Jingtang Communication Technology Co.,Ltd.", "154066459762688": "Emerson Rosemount Analytical", "154066459766784": "Böckelt GmbH", "154066459779072": "GS Elektromedizinsiche Geräte G. Stemple GmbH", @@ -125571,6 +126102,7 @@ "154066459820032": "Header Rhyme", "154066459824128": "RealWear", "154066459832320": "Camozzi Automation SpA", + "154066459860992": "EDC Acoustics", "154066459865088": "Shanghai Sizhong Information Technology Co., Ltd", "154066459873280": "JiangYu Innovative Medical Technology", "154066459877376": "Exi Flow Measurement Ltd", @@ -125608,6 +126140,7 @@ "154066460123136": "Shanghai Wise-Tech Intelligent Technology Co.,Ltd.", "154066460135424": "Lumiplan Duhamel", "154066460139520": "Elac Americas Inc.", + "154066460143616": "Dorlet Sau", "154066460155904": "FUJIHENSOKUKI Co., Ltd.", "154066460160000": "INVENTIA Sp. z o.o.", "154066460192768": "Zilica Limited", @@ -125628,6 +126161,7 @@ "154066460352512": "Rodgers Instruments US LLC", "154066460360704": "Rapidev Pvt Ltd", "154066460372992": "Saarni Cloud Oy", + "154066460381184": "Integer.pl S.A.", "154066460393472": "Flextronics International Kft", "154066460401664": "Syscom Instruments SA", "154066460413952": "Babtel", @@ -125741,6 +126275,7 @@ "154066461421568": "Lineage Power Pvt Ltd.,", "154066461442048": "Picocom Technology Ltd", "154066461454336": "Vaunix Technology Corporation", + "154066461474816": "Framatome Inc.", "154066461478912": "Sanchar Telesystems limited", "154066461483008": "Arcvideo", "154066461499392": "YUYAMA MFG Co.,Ltd", @@ -125763,6 +126298,7 @@ "154066461671424": "SPX Flow Technology", "154066461679616": "Elektronik & Modellprodukter Gävle AB", "154066461708288": "Tongye lnnovation Science and Technology (Shenzhen) Co.,Ltd", + "154066461724672": "Clealink Technology", "154066461728768": "Neurable", "154066461749248": "Gemini Electronics B.V.", "154066461753344": "Calamity, Inc.", @@ -125772,11 +126308,14 @@ "154066461782016": "Lithion Battery Inc", "154066461798400": "DEUTA-WERKE GmbH", "154066461810688": "FMC Technologies Measurement Solutions Inc", + "154066461818880": "AvMap srlu", "154066461827072": "Mine Vision Systems", + "154066461831168": "Ycn", "154066461843456": "Tieline Research Pty Ltd", "154066461855744": "Transit Solutions, LLC.", "154066461859840": "Grupo Epelsa S.L.", "154066461863936": "Zaruc Tecnologia LTDA", + "154066461868032": "HIGH RIGHT CO.,Ltd", "154066461880320": "Jiangxi Lv C-Chong Charging Technology Co.Ltd", "154066461888512": "SmartD Technologies Inc", "154066461900800": "Liberator Pty Ltd", @@ -125857,7 +126396,9 @@ "154066462507008": "Spacee", "154066462511104": "EPC Energy Inc", "154066462515200": "Invendis Technologies India Pvt Ltd", + "154066462519296": "Clockwork Dog", "154066462523392": "First Mode", + "154066462531584": "Eridan", "154066462535680": "Strategic Robotic Systems", "154066462543872": "Tunstall A/S", "154066462560256": "Alfa Proxima d.o.o.", @@ -125886,6 +126427,7 @@ "154066462810112": "Infosoft Digital Design and Services P L", "154066462814208": "J.M. Voith SE & Co. KG", "154066462826496": "CytoTronics", + "154066462830592": "PeachCreek", "154066462838784": "Pantherun Technologies Pvt Ltd", "154066462842880": "eumig industrie-TV GmbH.", "154066462851072": "Bit Part LLC", @@ -126016,9 +126558,11 @@ "154066464014336": "Pigs Can Fly Labs LLC", "154066464022528": "Procon Electronics Pty Ltd", "154066464038912": "R&K", + "154066464043008": "Wide Swath Research, LLC", "154066464047104": "Dwdm.Ru Llc", "154066464051200": "Peter Huber Kaeltemaschinenbau SE", "154066464055296": "Porsche engineering", + "154066464075776": "Reo Ag", "154066464096256": "Midlands Technical Co., Ltd.", "154066464100352": "Cardinal Scales Manufacturing Co", "154066464108544": "KST technology", @@ -126075,6 +126619,7 @@ "154066464661504": "BRICKMAKERS GmbH", "154066464673792": "Stange Elektronik GmbH", "154066464677888": "Axcend", + "154066464681984": "Infosoft Digital Design and Services P L", "154066464686080": "Indefac company", "154066464694272": "Enless Wireless", "154066464702464": "LHA Systems (Pty) Ltd", @@ -126140,6 +126685,7 @@ "154066465398784": "CAITRON GmbH", "154066465402880": "ACS Motion Control", "154066465406976": "Elektrosil GmbH", + "154066465435648": "Nextep Co.,Ltd.", "154066465439744": "Rigel Engineering, LLC", "154066465443840": "MB connect line GmbH Fernwartungssysteme", "154066465464320": "Voyage Audio LLC", From 641e36e0eaba6c882a99b2f25519db835237e935 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 00:33:25 -0700 Subject: [PATCH 23/35] Bump pytest (#1520) Bumps the pip-dependencies group with 1 update in the /Tests/ExamplesTest directory: [pytest](https://github.com/pytest-dev/pytest). Updates `pytest` from 8.2.2 to 8.3.2 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/8.2.2...8.3.2) --- updated-dependencies: - dependency-name: pytest dependency-type: direct:production update-type: version-update:semver-minor dependency-group: pip-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Tests/ExamplesTest/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ExamplesTest/requirements.txt b/Tests/ExamplesTest/requirements.txt index 95b339fbf6..a32a4796c1 100644 --- a/Tests/ExamplesTest/requirements.txt +++ b/Tests/ExamplesTest/requirements.txt @@ -2,6 +2,6 @@ attrs==23.2.0 iniconfig==2.0.0 py==1.11.0 pyparsing==3.1.2 -pytest==8.2.2 +pytest==8.3.2 scapy==2.5.0 toml==0.10.2 From 5140b0ef3efb77daa59ebeef24d4ebf002dc5e31 Mon Sep 17 00:00:00 2001 From: seladb Date: Mon, 5 Aug 2024 09:00:12 -0700 Subject: [PATCH 24/35] Add NDK version to `app/build.gradle` in Android CI (#1526) * Test with specific NDK version * Add `ndkVersion` to `build.gradle` * Fix the script * Try to fix macOS * One more fix * Another fix * Disable upload coverage on macOS --- .github/workflows/build_and_test.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 5ab2308b05..3c23094d14 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -378,16 +378,16 @@ jobs: python3 -m pip install gcovr gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 - if: ${{ matrix.host-arch == matrix.arch }} - with: - files: ./coverage.xml - flags: ${{ matrix.os-version }},unittest - fail_ci_if_error: false - verbose: true - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # - name: Upload Coverage Results + # uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + # if: ${{ matrix.host-arch == matrix.arch }} + # with: + # files: ./coverage.xml + # flags: ${{ matrix.os-version }},unittest + # fail_ci_if_error: false + # verbose: true + # env: + # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Save Ccache uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 @@ -668,7 +668,15 @@ jobs: - name: Build ToyVpn-PcapPlusPlus working-directory: ./ToyVpn-PcapPlusPlus run: | + NDK_VERSION=$(echo "$ANDROID_NDK" | awk -F'/' '{print $NF}') sed -i.bak "s|abiFilters.*$|abiFilters '${{ matrix.target }}'|g" app/build.gradle + if [[ "${{ matrix.run-on-os }}" == "macos"* ]]; then + sed -i.bak "/defaultConfig {/a\\ + ndkVersion \"$NDK_VERSION\" + " app/build.gradle + else + sed -i "/defaultConfig {/a\\ ndkVersion \"$NDK_VERSION\"" app/build.gradle + fi chmod +x gradlew ./gradlew assembleDebug From 1f2891744c5eafb3b41fd9c20acb1c03708bdbdf Mon Sep 17 00:00:00 2001 From: seladb Date: Mon, 5 Aug 2024 21:54:42 -0700 Subject: [PATCH 25/35] Auto precommit update (#1519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Auto pre-commit update * Fix typos --------- Co-authored-by: GitHub Co-authored-by: Ege Çetin Co-authored-by: Liu, An-Chi --- .pre-commit-config.yaml | 2 +- Packet++/header/SSHLayer.h | 2 +- cmake/package/READMEs/release_notes.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 722288935f..5e9024e4db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: - id: codespell pass_filenames: false - repo: https://github.com/crate-ci/typos - rev: v1.22.9 + rev: v1.23.6 hooks: - id: typos args: ['--config=typos-config.toml'] diff --git a/Packet++/header/SSHLayer.h b/Packet++/header/SSHLayer.h index 8c88e493f2..2dfc85905d 100644 --- a/Packet++/header/SSHLayer.h +++ b/Packet++/header/SSHLayer.h @@ -410,7 +410,7 @@ namespace pcpp /** * A c'tor for this class that accepts raw message data. Please avoid using it as it's used internally - * when parsing SSH messagess in SSHLayer#createSSHMessage() + * when parsing SSH messages in SSHLayer#createSSHMessage() */ SSHEncryptedMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {} diff --git a/cmake/package/READMEs/release_notes.txt b/cmake/package/READMEs/release_notes.txt index 203cbf7a1c..6d6921b055 100644 --- a/cmake/package/READMEs/release_notes.txt +++ b/cmake/package/READMEs/release_notes.txt @@ -35,7 +35,7 @@ Release notes (changes from v22.11) - Increase test coverage - Remove deprecated methods (due to typos): - `DhcpLayer::getMesageType()` -> replaced by `DhcpLayer::getMessageType()` - - `DhcpLayer::setMesageType()` -> replaced by `DhcpLayer::setMesasgeType()` + - `DhcpLayer::setMesageType()` -> replaced by `DhcpLayer::setMessageType()` - `SSLHandshakeMessage::createHandhakeMessage()` -> replaced by `SSLHandshakeMessage::createHandshakeMessage()` - `SSLClientHelloMessage::getExtensionsLenth()` -> replaced by `SSLClientHelloMessage::getExtensionsLength()` - `SSLServerHelloMessage::getExtensionsLenth()` -> replaced by `SSLServerHelloMessage::getExtensionsLength()` From b640b4ff8ebc726ba0613baab5a12d77d572264d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20=C3=87etin?= <64282645+egecetin@users.noreply.github.com> Date: Tue, 6 Aug 2024 07:56:35 +0300 Subject: [PATCH 26/35] Pin GitHub Actions with hash instead of tag Co-authored-by: Liu, An-Chi --- .github/workflows/build_and_test.yml | 4 ++-- .github/workflows/doxygen.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 3c23094d14..1c501e9697 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -574,10 +574,10 @@ jobs: matrix: version: ["14.0", "13.2"] steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Test in FreeBSD id: test - uses: vmactions/freebsd-vm@v1 + uses: vmactions/freebsd-vm@12c207ac1ba13827f25726fe93f9c2e6f685f0f3 # v1.0.8 with: release: ${{ matrix.version }} usesh: true diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 91d4a8fd4f..857767a2c5 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -37,7 +37,7 @@ jobs: - name: Upload documentation if: github.ref == 'refs/heads/master' - uses: cpina/github-action-push-to-another-repository@main + uses: cpina/github-action-push-to-another-repository@07c4d7b3def0a8ebe788a8f2c843a4e1de4f6900 # main env: SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} with: From 316ea6e767984f75d8c97357df336d33ba45b7bc Mon Sep 17 00:00:00 2001 From: "Liu, An-Chi" Date: Wed, 7 Aug 2024 17:20:08 +0900 Subject: [PATCH 27/35] Clang-format for Packet++ (#1510) * update http comment * IP Reassembly comment * fix comment * fix more comment * fix comment for layer * pre-commit * init format * manually fix Bgp * manually fix http * manually fix Layer * fix LLC * manually fix ntp * dns cpp * Packet cpp * ssl cpp * revert ssl layer wrong format * manully fix NTP, PPPoE, SingleCommandText * manually fix SSH * SSL manual fix * TCP manual fix * fix TCPReassembly * Fix VRRP * fix dns cpp * fix ftp cpp * manually fix http cpp * fix empty line * ICMP cpp * manually fix IGMP * manually fix LDAP * NDP cpp * Nflog cpp * Ntp cpp * PPPoE cpp * SDP cpp * SomeIpSd cpp * SSL handshake cpp * tcp cpp * TestBasedProtocol cpp * change to std::unique_ptr * ndp cpp * tcp reassembly cpp * gre * update ip reassembly * update http * Fix all * remove the comment --- .pre-commit-config.yaml | 2 +- Packet++/header/ArpLayer.h | 70 +- Packet++/header/Asn1Codec.h | 90 +- Packet++/header/BgpLayer.h | 1154 +++--- Packet++/header/CotpLayer.h | 35 +- Packet++/header/DhcpLayer.h | 210 +- Packet++/header/DhcpV6Layer.h | 216 +- Packet++/header/DnsLayer.h | 328 +- Packet++/header/DnsLayerEnums.h | 4 +- Packet++/header/DnsResource.h | 149 +- Packet++/header/DnsResourceData.h | 205 +- Packet++/header/EthDot3Layer.h | 58 +- Packet++/header/EthLayer.h | 97 +- Packet++/header/FtpLayer.h | 92 +- Packet++/header/GreLayer.h | 233 +- Packet++/header/GtpLayer.h | 147 +- Packet++/header/HttpLayer.h | 372 +- Packet++/header/IPLayer.h | 9 +- Packet++/header/IPReassembly.h | 394 +- Packet++/header/IPSecLayer.h | 69 +- Packet++/header/IPv4Layer.h | 194 +- Packet++/header/IPv6Extensions.h | 282 +- Packet++/header/IPv6Layer.h | 109 +- Packet++/header/IcmpLayer.h | 226 +- Packet++/header/IcmpV6Layer.h | 516 +-- Packet++/header/IgmpLayer.h | 1035 ++--- Packet++/header/LLCLayer.h | 41 +- Packet++/header/Layer.h | 149 +- Packet++/header/LdapLayer.h | 301 +- Packet++/header/MplsLayer.h | 54 +- Packet++/header/NdpLayer.h | 686 ++-- Packet++/header/NflogLayer.h | 106 +- Packet++/header/NtpLayer.h | 1269 ++++--- Packet++/header/NullLoopbackLayer.h | 61 +- Packet++/header/PPPoELayer.h | 456 +-- Packet++/header/Packet.h | 320 +- Packet++/header/PacketTrailerLayer.h | 59 +- Packet++/header/PacketUtils.h | 12 +- Packet++/header/PayloadLayer.h | 52 +- Packet++/header/ProtocolType.h | 10 +- Packet++/header/RadiusLayer.h | 124 +- Packet++/header/RawPacket.h | 196 +- Packet++/header/S7CommLayer.h | 64 +- Packet++/header/SSHLayer.h | 190 +- Packet++/header/SSLCommon.h | 128 +- Packet++/header/SSLHandshake.h | 1887 +++++----- Packet++/header/SSLLayer.h | 217 +- Packet++/header/SdpLayer.h | 97 +- Packet++/header/SingleCommandTextProtocol.h | 14 +- Packet++/header/SipLayer.h | 425 ++- Packet++/header/Sll2Layer.h | 36 +- Packet++/header/SllLayer.h | 33 +- Packet++/header/SmtpLayer.h | 51 +- Packet++/header/SomeIpLayer.h | 895 ++--- Packet++/header/SomeIpSdLayer.h | 1425 +++---- Packet++/header/StpLayer.h | 269 +- Packet++/header/TLVData.h | 143 +- Packet++/header/TcpLayer.h | 321 +- Packet++/header/TcpReassembly.h | 831 ++-- Packet++/header/TelnetLayer.h | 676 ++-- Packet++/header/TextBasedProtocol.h | 504 +-- Packet++/header/TpktLayer.h | 41 +- Packet++/header/UdpLayer.h | 36 +- Packet++/header/VlanLayer.h | 46 +- Packet++/header/VrrpLayer.h | 239 +- Packet++/header/VxlanLayer.h | 130 +- Packet++/header/WakeOnLanLayer.h | 58 +- Packet++/src/ArpLayer.cpp | 88 +- Packet++/src/Asn1Codec.cpp | 406 +- Packet++/src/BgpLayer.cpp | 1404 +++---- Packet++/src/CotpLayer.cpp | 43 +- Packet++/src/DhcpLayer.cpp | 474 +-- Packet++/src/DhcpV6Layer.cpp | 364 +- Packet++/src/DnsLayer.cpp | 1339 ++++--- Packet++/src/DnsResource.cpp | 677 ++-- Packet++/src/DnsResourceData.cpp | 316 +- Packet++/src/EthDot3Layer.cpp | 90 +- Packet++/src/EthLayer.cpp | 205 +- Packet++/src/FtpLayer.cpp | 24 +- Packet++/src/GreLayer.cpp | 930 +++-- Packet++/src/GtpLayer.cpp | 1034 +++-- Packet++/src/HttpLayer.cpp | 1619 ++++---- Packet++/src/IPReassembly.cpp | 1014 ++--- Packet++/src/IPSecLayer.cpp | 195 +- Packet++/src/IPv4Layer.cpp | 907 ++--- Packet++/src/IPv6Extensions.cpp | 433 +-- Packet++/src/IPv6Layer.cpp | 557 +-- Packet++/src/IcmpLayer.cpp | 1104 +++--- Packet++/src/IcmpV6Layer.cpp | 263 +- Packet++/src/IgmpLayer.cpp | 822 ++-- Packet++/src/LLCLayer.cpp | 74 +- Packet++/src/Layer.cpp | 163 +- Packet++/src/LdapLayer.cpp | 562 +-- Packet++/src/MplsLayer.cpp | 216 +- Packet++/src/NdpLayer.cpp | 339 +- Packet++/src/NflogLayer.cpp | 155 +- Packet++/src/NtpLayer.cpp | 1210 +++--- Packet++/src/NullLoopbackLayer.cpp | 136 +- Packet++/src/PPPoELayer.cpp | 729 ++-- Packet++/src/Packet.cpp | 1244 +++--- Packet++/src/PacketTrailerLayer.cpp | 28 +- Packet++/src/PacketUtils.cpp | 388 +- Packet++/src/PayloadLayer.cpp | 76 +- Packet++/src/RadiusLayer.cpp | 397 +- Packet++/src/RawPacket.cpp | 343 +- Packet++/src/S7CommLayer.cpp | 69 +- Packet++/src/SSHLayer.cpp | 379 +- Packet++/src/SSLCommon.cpp | 149 +- Packet++/src/SSLHandshake.cpp | 3774 +++++++++---------- Packet++/src/SSLLayer.cpp | 368 +- Packet++/src/SdpLayer.cpp | 215 +- Packet++/src/SingleCommandTextProtocol.cpp | 31 +- Packet++/src/SipLayer.cpp | 1507 ++++---- Packet++/src/Sll2Layer.cpp | 275 +- Packet++/src/SllLayer.cpp | 165 +- Packet++/src/SmtpLayer.cpp | 29 +- Packet++/src/SomeIpLayer.cpp | 569 ++- Packet++/src/SomeIpSdLayer.cpp | 1293 +++---- Packet++/src/StpLayer.cpp | 483 ++- Packet++/src/TLVData.cpp | 167 +- Packet++/src/TcpLayer.cpp | 786 ++-- Packet++/src/TcpReassembly.cpp | 1174 +++--- Packet++/src/TelnetLayer.cpp | 788 ++-- Packet++/src/TextBasedProtocol.cpp | 1078 +++--- Packet++/src/TpktLayer.cpp | 37 +- Packet++/src/UdpLayer.cpp | 218 +- Packet++/src/VlanLayer.cpp | 233 +- Packet++/src/VrrpLayer.cpp | 122 +- Packet++/src/VxlanLayer.cpp | 101 +- Packet++/src/WakeOnLanLayer.cpp | 195 +- 130 files changed, 27890 insertions(+), 25631 deletions(-) mode change 100755 => 100644 Packet++/header/VrrpLayer.h mode change 100755 => 100644 Packet++/src/VrrpLayer.cpp diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e9024e4db..a2d6e22a2b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: clang-format args: ["--style=file"] # Use the .clang-format file for configuration - files: ^(Common\+\+|Tests|Examples)/.*\.(cpp|h)$ + files: ^(Common\+\+|Tests|Examples|Packet\+\+)/.*\.(cpp|h)$ - id: cppcheck args: ["--std=c++11", "--language=c++", "--suppressions-list=cppcheckSuppressions.txt", "--inline-suppr", "--force"] - repo: https://github.com/codespell-project/codespell diff --git a/Packet++/header/ArpLayer.h b/Packet++/header/ArpLayer.h index 63a55927a2..8cdba5cf2d 100644 --- a/Packet++/header/ArpLayer.h +++ b/Packet++/header/ArpLayer.h @@ -25,10 +25,12 @@ namespace pcpp /** Protocol type (PTYPE). The permitted PTYPE values share a numbering space with those for EtherType */ uint16_t protocolType; /** Hardware address length (HLEN). For IPv4, this has the value 0x0800 */ - uint8_t hardwareSize; - /** Protocol length (PLEN). Length (in octets) of addresses used in the upper layer protocol. (The upper layer protocol specified in PTYPE.) IPv4 address size is 4 */ - uint8_t protocolSize; - /** Specifies the operation that the sender is performing: 1 (::ARP_REQUEST) for request, 2 (::ARP_REPLY) for reply */ + uint8_t hardwareSize; + /** Protocol length (PLEN). Length (in octets) of addresses used in the upper layer protocol. (The upper layer + * protocol specified in PTYPE.) IPv4 address size is 4 */ + uint8_t protocolSize; + /** Specifies the operation that the sender is performing: 1 (::ARP_REQUEST) for request, 2 (::ARP_REPLY) for + * reply */ uint16_t opcode; /** Sender hardware address (SHA) */ uint8_t senderMacAddr[6]; @@ -46,8 +48,8 @@ namespace pcpp */ enum ArpOpcode { - ARP_REQUEST = 0x0001, ///< ARP request - ARP_REPLY = 0x0002 ///< ARP reply (response) + ARP_REQUEST = 0x0001, ///< ARP request + ARP_REPLY = 0x0002 ///< ARP reply (response) }; /** @@ -64,7 +66,12 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - ArpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ARP; m_DataLen = sizeof(arphdr); } + ArpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = ARP; + m_DataLen = sizeof(arphdr); + } /** * A constructor that allocates a new ARP header @@ -74,51 +81,73 @@ namespace pcpp * @param[in] senderIpAddr The sender IP address (will be put in arphdr#senderIpAddr) * @param[in] targetIpAddr The target IP address (will be put in arphdr#targetIpAddr) */ - ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr); + ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, + const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr); - ~ArpLayer() {} + ~ArpLayer() + {} /** - * Get a pointer to the ARP header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the ARP header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref arphdr */ - inline arphdr* getArpHeader() const { return (arphdr*)m_Data; } + inline arphdr* getArpHeader() const + { + return (arphdr*)m_Data; + } /** * Get the sender hardware address (SHA) in the form of MacAddress * @return A MacAddress containing the sender hardware address (SHA) */ - inline MacAddress getSenderMacAddress() const { return MacAddress(getArpHeader()->senderMacAddr); } + inline MacAddress getSenderMacAddress() const + { + return MacAddress(getArpHeader()->senderMacAddr); + } /** * Get the target hardware address (THA) in the form of MacAddress * @return A MacAddress containing the target hardware address (THA) */ - inline MacAddress getTargetMacAddress() const { return MacAddress(getArpHeader()->targetMacAddr); } + inline MacAddress getTargetMacAddress() const + { + return MacAddress(getArpHeader()->targetMacAddr); + } /** * Get the sender protocol address (SPA) in the form of IPv4Address * @return An IPv4Address containing the sender protocol address (SPA) */ - inline IPv4Address getSenderIpAddr() const { return getArpHeader()->senderIpAddr; } + inline IPv4Address getSenderIpAddr() const + { + return getArpHeader()->senderIpAddr; + } /** * Get the target protocol address (TPA) in the form of IPv4Address * @return An IPv4Address containing the target protocol address (TPA) */ - inline IPv4Address getTargetIpAddr() const { return getArpHeader()->targetIpAddr; } + inline IPv4Address getTargetIpAddr() const + { + return getArpHeader()->targetIpAddr; + } // implement abstract methods /** * Does nothing for this layer (ArpLayer is always last) */ - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return The size of @ref arphdr */ - size_t getHeaderLen() const { return sizeof(arphdr); } + size_t getHeaderLen() const + { + return sizeof(arphdr); + } /** * Calculate the following fields: @@ -142,7 +171,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/Asn1Codec.h b/Packet++/header/Asn1Codec.h index 81ef57f1c2..7b5bffef97 100644 --- a/Packet++/header/Asn1Codec.h +++ b/Packet++/header/Asn1Codec.h @@ -142,32 +142,48 @@ namespace pcpp /** * @return The ASN.1 tag class */ - Asn1TagClass getTagClass() const { return m_TagClass; } + Asn1TagClass getTagClass() const + { + return m_TagClass; + } /** * @return True if it's a constructed record, or false if it's a primitive record */ - bool isConstructed() const { return m_IsConstructed; } + bool isConstructed() const + { + return m_IsConstructed; + } /** - * @return The ASN.1 Universal tag type if the record is of class Universal, otherwise Asn1UniversalTagType#NotApplicable + * @return The ASN.1 Universal tag type if the record is of class Universal, otherwise + * Asn1UniversalTagType#NotApplicable */ Asn1UniversalTagType getUniversalTagType() const; /** * @return The ASN.1 tag type value */ - uint8_t getTagType() const { return m_TagType; } + uint8_t getTagType() const + { + return m_TagType; + } /** * @return The length of the record value */ - size_t getValueLength() const { return m_ValueLength; } + size_t getValueLength() const + { + return m_ValueLength; + } /** * @return The total length of the record */ - size_t getTotalLength() const { return m_TotalLength; } + size_t getTotalLength() const + { + return m_TotalLength; + } /** * @return A string representation of the record @@ -180,8 +196,7 @@ namespace pcpp * @tparam Asn1RecordType The type to cast to * @return A pointer to the type after casting */ - template - Asn1RecordType* castAs() + template Asn1RecordType* castAs() { auto result = dynamic_cast(this); if (result == nullptr) @@ -240,7 +255,8 @@ namespace pcpp * @param value A byte array of the tag value * @param valueLen The length of the value byte array */ - Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, size_t valueLen); + Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, + size_t valueLen); /** * A constructor to create a generic record @@ -256,7 +272,11 @@ namespace pcpp /** * @return A pointer to the tag value */ - const uint8_t* getValue() { decodeValueIfNeeded(); return m_Value; } + const uint8_t* getValue() + { + decodeValueIfNeeded(); + return m_Value; + } protected: Asn1GenericRecord() = default; @@ -285,7 +305,8 @@ namespace pcpp * @param tagType The record tag type value * @param subRecords A list of sub-records to assign as the record value */ - explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, const std::vector& subRecords); + explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, + const std::vector& subRecords); /** * A constructor to create a constructed record @@ -293,13 +314,18 @@ namespace pcpp * @param tagType The record tag type value * @param subRecords A PointerVector of sub-records to assign as the record value */ - explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, const PointerVector& subRecords); + explicit Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, + const PointerVector& subRecords); /** * @return A reference to the list of sub-records. It's important to note that any modifications made to * this list will directly affect the internal structure */ - PointerVector& getSubRecords() { decodeValueIfNeeded(); return m_SubRecords; }; + PointerVector& getSubRecords() + { + decodeValueIfNeeded(); + return m_SubRecords; + }; protected: Asn1ConstructedRecord() = default; @@ -309,8 +335,7 @@ namespace pcpp std::vector toStringList() override; - template - void init(Asn1TagClass tagClass, uint8_t tagType, Iterator begin, Iterator end) + template void init(Asn1TagClass tagClass, uint8_t tagType, Iterator begin, Iterator end) { m_TagType = tagType; m_TagClass = tagClass; @@ -328,6 +353,7 @@ namespace pcpp m_ValueLength = recordValueLength; m_TotalLength = recordValueLength + 1 + (m_ValueLength < 128 ? 1 : 2); } + private: PointerVector m_SubRecords; }; @@ -414,7 +440,11 @@ namespace pcpp /** * @return The integer value of this record */ - uint32_t getValue() { decodeValueIfNeeded(); return m_Value; } + uint32_t getValue() + { + decodeValueIfNeeded(); + return m_Value; + } protected: Asn1IntegerRecord() = default; @@ -463,16 +493,20 @@ namespace pcpp explicit Asn1OctetStringRecord(const std::string& value); /** - * A constructor to create a record of type Octet String from a non-printable value - * @param value A byte array to set as the record value + * A constructor to create a record of type Octet String from a non-printable value + * @param value A byte array to set as the record value * @param valueLength The length of the byte array - */ + */ explicit Asn1OctetStringRecord(const uint8_t* value, size_t valueLength); /** * @return The string value of this record */ - std::string getValue() { decodeValueIfNeeded(); return m_Value; }; + std::string getValue() + { + decodeValueIfNeeded(); + return m_Value; + }; protected: void decodeValue(uint8_t* data, bool lazy) override; @@ -505,7 +539,11 @@ namespace pcpp /** * @return The boolean value of this record */ - bool getValue() { decodeValueIfNeeded(); return m_Value; }; + bool getValue() + { + decodeValueIfNeeded(); + return m_Value; + }; protected: void decodeValue(uint8_t* data, bool lazy) override; @@ -534,7 +572,11 @@ namespace pcpp Asn1NullRecord(); protected: - void decodeValue(uint8_t* data, bool lazy) override {} - std::vector encodeValue() const override { return {}; } + void decodeValue(uint8_t* data, bool lazy) override + {} + std::vector encodeValue() const override + { + return {}; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/BgpLayer.h b/Packet++/header/BgpLayer.h index 0e874a1d39..57b30a1eb3 100644 --- a/Packet++/header/BgpLayer.h +++ b/Packet++/header/BgpLayer.h @@ -19,657 +19,709 @@ namespace pcpp { -/** - * @class BgpLayer - * Represents Border Gateway Protocol (BGP) v4 protocol layer. This is an abstract class that cannot be instantiated, - * and contains functionality which is common to all BGP message types. - */ -class BgpLayer : public Layer -{ -public: - - /** - * An enum representing BGP message types - */ - enum BgpMessageType - { - /** BGP OPEN message */ - Open = 1, - /** BGP UPDATE message */ - Update = 2, - /** BGP NOTIFICATION message */ - Notification = 3, - /** BGP KEEPALIVE message */ - Keepalive = 4, - /** BGP ROUTE-REFRESH message */ - RouteRefresh = 5, - }; - /** - * @struct bgp_common_header - * Represents the common fields of a BGP 4 message + * @class BgpLayer + * Represents Border Gateway Protocol (BGP) v4 protocol layer. This is an abstract class that cannot be + * instantiated, and contains functionality which is common to all BGP message types. */ - #pragma pack(push, 1) - struct bgp_common_header + class BgpLayer : public Layer { - /** 16-octet marker */ - uint8_t marker[16]; - /** Total length of the message, including the header */ - uint16_t length; - /** BGP message type */ - uint8_t messageType; - }; - #pragma pack(pop) - - /** - * @return BGP message type - */ - virtual BgpMessageType getBgpMessageType() const = 0; - - /** - * @return BGP message type as string. Return value can be one of the following: - * "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", "Unknown" - */ - std::string getMessageTypeAsString() const; - - /** - * A static method that checks whether a source or dest port match those associated with the BGP protocol - * @param[in] portSrc Source port number to check - * @param[in] portDst Dest port number to check - * @return True if the source or dest port match those associated with the BGP protocol - */ - static bool isBgpPort(uint16_t portSrc, uint16_t portDst) { return portSrc == 179 || portDst == 179; } - - /** - * A method that creates a BGP layer from packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored - * @return A newly allocated BGP layer of one of the following types (according to the message type): - * BgpOpenMessageLayer, BgpUpdateMessageLayer, BgpNotificationMessageLayer, BgpKeepaliveMessageLayer, - * BgpRouteRefreshMessageLayer - */ - static BgpLayer* parseBgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - - // implement abstract methods - - /** - * @return The size of the BGP message - */ - size_t getHeaderLen() const; - - /** - * Multiple BGP messages can reside in a single packet, and the only layer that can come after a BGP message - * is another BGP message. This method checks for remaining data and parses it as another BGP layer - */ - void parseNextLayer(); - - std::string toString() const; - - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + public: + /** + * An enum representing BGP message types + */ + enum BgpMessageType + { + /** BGP OPEN message */ + Open = 1, + /** BGP UPDATE message */ + Update = 2, + /** BGP NOTIFICATION message */ + Notification = 3, + /** BGP KEEPALIVE message */ + Keepalive = 4, + /** BGP ROUTE-REFRESH message */ + RouteRefresh = 5, + }; + +#pragma pack(push, 1) + /** + * @struct bgp_common_header + * Represents the common fields of a BGP 4 message + */ + struct bgp_common_header + { + /** 16-octet marker */ + uint8_t marker[16]; + /** Total length of the message, including the header */ + uint16_t length; + /** BGP message type */ + uint8_t messageType; + }; +#pragma pack(pop) - /** - * Calculates the basic BGP fields: - * - Set marker to all ones - * - Set message type value - * - Set message length - */ - void computeCalculateFields(); + /** + * @return BGP message type + */ + virtual BgpMessageType getBgpMessageType() const = 0; -protected: + /** + * @return BGP message type as string. Return value can be one of the following: + * "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH", "Unknown" + */ + std::string getMessageTypeAsString() const; - // protected c'tors, this class cannot be instantiated by users - BgpLayer() {} - BgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = BGP; } + /** + * A static method that checks whether a source or dest port match those associated with the BGP protocol + * @param[in] portSrc Source port number to check + * @param[in] portDst Dest port number to check + * @return True if the source or dest port match those associated with the BGP protocol + */ + static bool isBgpPort(uint16_t portSrc, uint16_t portDst) + { + return portSrc == 179 || portDst == 179; + } - bgp_common_header* getBasicHeader() const { return (bgp_common_header*)m_Data; } + /** + * A method that creates a BGP layer from packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored + * @return A newly allocated BGP layer of one of the following types (according to the message type): + * BgpOpenMessageLayer, BgpUpdateMessageLayer, BgpNotificationMessageLayer, BgpKeepaliveMessageLayer, + * BgpRouteRefreshMessageLayer + */ + static BgpLayer* parseBgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - void setBgpFields(size_t messageLen = 0); + // implement abstract methods -}; + /** + * @return The size of the BGP message + */ + size_t getHeaderLen() const; + /** + * Multiple BGP messages can reside in a single packet, and the only layer that can come after a BGP message + * is another BGP message. This method checks for remaining data and parses it as another BGP layer + */ + void parseNextLayer(); + std::string toString() const; -/** - * @class BgpOpenMessageLayer - * Represents a BGP v4 OPEN message - */ -class BgpOpenMessageLayer : public BgpLayer -{ -public: + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } - /** - * @struct bgp_open_message - * BGP OPEN message structure - */ - #pragma pack(push, 1) - typedef struct bgp_open_message : bgp_common_header - { - /** BGP version number */ - uint8_t version; - /** Autonomous System number of the sender */ - uint16_t myAutonomousSystem; - /** The number of seconds the sender proposes for the value of the Hold Timer */ - uint16_t holdTime; - /** BGP Identifier of the sender */ - uint32_t bgpId; - /** The total length of the Optional Parameters field */ - uint8_t optionalParameterLength; - } bgp_open_message; - #pragma pack(pop) + /** + * Calculates the basic BGP fields: + * - Set marker to all ones + * - Set message type value + * - Set message length + */ + void computeCalculateFields(); + + protected: + // protected c'tors, this class cannot be instantiated by users + BgpLayer() + {} + BgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = BGP; + } + + bgp_common_header* getBasicHeader() const + { + return (bgp_common_header*)m_Data; + } + + void setBgpFields(size_t messageLen = 0); + }; /** - * @struct optional_parameter - * A structure that represents BGP OPEN message optional parameters + * @class BgpOpenMessageLayer + * Represents a BGP v4 OPEN message */ - struct optional_parameter + class BgpOpenMessageLayer : public BgpLayer { - /** Parameter type */ - uint8_t type; - /** Parameter length */ - uint8_t length; - /** Parameter data */ - uint8_t value[32]; - + public: +#pragma pack(push, 1) /** - * A default c'tor that zeroes all data + * @struct bgp_open_message + * BGP OPEN message structure */ - optional_parameter() {} + typedef struct bgp_open_message : bgp_common_header + { + /** BGP version number */ + uint8_t version; + /** Autonomous System number of the sender */ + uint16_t myAutonomousSystem; + /** The number of seconds the sender proposes for the value of the Hold Timer */ + uint16_t holdTime; + /** BGP Identifier of the sender */ + uint32_t bgpId; + /** The total length of the Optional Parameters field */ + uint8_t optionalParameterLength; + } bgp_open_message; +#pragma pack(pop) /** - * A c'tor that initializes the values of the struct - * @param[in] typeVal Parameter type value - * @param[in] valueAsHexString Parameter data as hex string. The length field will be set accordingly. - * If this parameter is not a valid hex string the data will remain zeroed and length will be also zero + * @struct optional_parameter + * A structure that represents BGP OPEN message optional parameters */ - optional_parameter(uint8_t typeVal, const std::string& valueAsHexString); - }; - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - BgpOpenMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {} - - /** - * A c'tor that creates a new BGP OPEN message - * @param[in] myAutonomousSystem The Autonomous System number of the sender - * @param[in] holdTime The number of seconds the sender proposes for the value of the Hold Timer - * @param[in] bgpId The BGP Identifier of the sender - * @param[in] optionalParams A vector of optional parameters. This parameter is optional and if not provided no parameters will be - * set on the message - */ - BgpOpenMessageLayer(uint16_t myAutonomousSystem, uint16_t holdTime, const IPv4Address& bgpId, - const std::vector& optionalParams = std::vector()); - - /** - * Get a pointer to the open message data. Notice this points directly to the data, so any change will modify the actual packet data - * @return A pointer to a bgp_open_message structure containing the data - */ - bgp_open_message* getOpenMsgHeader() const { return (bgp_open_message*)m_Data; } + struct optional_parameter + { + /** Parameter type */ + uint8_t type; + /** Parameter length */ + uint8_t length; + /** Parameter data */ + uint8_t value[32]; + + /** + * A default c'tor that zeroes all data + */ + optional_parameter() + {} + + /** + * A c'tor that initializes the values of the struct + * @param[in] typeVal Parameter type value + * @param[in] valueAsHexString Parameter data as hex string. The length field will be set accordingly. + * If this parameter is not a valid hex string the data will remain zeroed and length will be also zero + */ + optional_parameter(uint8_t typeVal, const std::string& valueAsHexString); + }; - /** - * @return The BGP identifier as IPv4Address object - */ - IPv4Address getBgpId() const { return IPv4Address(getOpenMsgHeader()->bgpId); } - - /** - * Set the BGP identifier - * @param[in] newBgpId BGP identifier to set. If value is not a valid IPv4 address it won't be set - */ - void setBgpId(const IPv4Address& newBgpId); - - /** - * Get a vector of the optional parameters in the message - * @param[out] optionalParameters The vector where the optional parameters will be written to. This method doesn't remove any - * existing data on this vector before pushing data to it - */ - void getOptionalParameters(std::vector& optionalParameters); + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + BgpOpenMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : BgpLayer(data, dataLen, prevLayer, packet) + {} - /** - * @return The length in [bytes] of the optional parameters data in the message - */ - size_t getOptionalParametersLength(); + /** + * A c'tor that creates a new BGP OPEN message + * @param[in] myAutonomousSystem The Autonomous System number of the sender + * @param[in] holdTime The number of seconds the sender proposes for the value of the Hold Timer + * @param[in] bgpId The BGP Identifier of the sender + * @param[in] optionalParams A vector of optional parameters. This parameter is optional and if not provided no + * parameters will be set on the message + */ + BgpOpenMessageLayer(uint16_t myAutonomousSystem, uint16_t holdTime, const IPv4Address& bgpId, + const std::vector& optionalParams = std::vector()); - /** - * Set optional parameters in the message. This method will override all existing optional parameters currently in the message. - * If the input is an empty vector all optional parameters will be cleared. This method automatically sets the - * bgp_common_header#length and the bgp_open_message#optionalParameterLength fields on the message - * @param[in] optionalParameters A vector of new optional parameters to set in the message - * @return True if all optional parameters were set successfully or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool setOptionalParameters(const std::vector& optionalParameters); + /** + * Get a pointer to the open message data. Notice this points directly to the data, so any change will modify + * the actual packet data + * @return A pointer to a bgp_open_message structure containing the data + */ + bgp_open_message* getOpenMsgHeader() const + { + return (bgp_open_message*)m_Data; + } - /** - * Clear all optional parameters currently in the message. This is equivalent to calling setOptionalParameters() with an empty - * vector as a parameter - * @return True if all optional parameters were successfully cleared or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool clearOptionalParameters(); + /** + * @return The BGP identifier as IPv4Address object + */ + IPv4Address getBgpId() const + { + return IPv4Address(getOpenMsgHeader()->bgpId); + } - // implement abstract methods + /** + * Set the BGP identifier + * @param[in] newBgpId BGP identifier to set. If value is not a valid IPv4 address it won't be set + */ + void setBgpId(const IPv4Address& newBgpId); - BgpMessageType getBgpMessageType() const { return BgpLayer::Open; } + /** + * Get a vector of the optional parameters in the message + * @param[out] optionalParameters The vector where the optional parameters will be written to. This method + * doesn't remove any existing data on this vector before pushing data to it + */ + void getOptionalParameters(std::vector& optionalParameters); -private: + /** + * @return The length in [bytes] of the optional parameters data in the message + */ + size_t getOptionalParametersLength(); - size_t optionalParamsToByteArray(const std::vector& optionalParams, uint8_t* resultByteArr, size_t maxByteArrSize); + /** + * Set optional parameters in the message. This method will override all existing optional parameters currently + * in the message. If the input is an empty vector all optional parameters will be cleared. This method + * automatically sets the bgp_common_header#length and the bgp_open_message#optionalParameterLength fields on + * the message + * @param[in] optionalParameters A vector of new optional parameters to set in the message + * @return True if all optional parameters were set successfully or false otherwise. In case of an error an + * appropriate message will be printed to log + */ + bool setOptionalParameters(const std::vector& optionalParameters); -}; + /** + * Clear all optional parameters currently in the message. This is equivalent to calling setOptionalParameters() + * with an empty vector as a parameter + * @return True if all optional parameters were successfully cleared or false otherwise. In case of an error an + * appropriate message will be printed to log + */ + bool clearOptionalParameters(); + // implement abstract methods + BgpMessageType getBgpMessageType() const + { + return BgpLayer::Open; + } -/** - * @class BgpUpdateMessageLayer - * Represents a BGP v4 UPDATE message - */ -class BgpUpdateMessageLayer : public BgpLayer -{ -public: + private: + size_t optionalParamsToByteArray(const std::vector& optionalParams, uint8_t* resultByteArr, + size_t maxByteArrSize); + }; /** - * @struct prefix_and_ip - * A structure that contains IPv4 address and IP address mask (prefix) information. - * It's used to represent BGP Withdrawn Routes and Network Layer Reachability Information (NLRI) + * @class BgpUpdateMessageLayer + * Represents a BGP v4 UPDATE message */ - struct prefix_and_ip + class BgpUpdateMessageLayer : public BgpLayer { - /** IPv4 address mask, must contain one of the values: 8, 16, 24, 32 */ - uint8_t prefix; - /** IPv4 address */ - IPv4Address ipAddr; - + public: /** - * A default c'tor that zeroes all data + * @struct prefix_and_ip + * A structure that contains IPv4 address and IP address mask (prefix) information. + * It's used to represent BGP Withdrawn Routes and Network Layer Reachability Information (NLRI) */ - prefix_and_ip(): prefix(0), ipAddr(IPv4Address::Zero) {} + struct prefix_and_ip + { + /** IPv4 address mask, must contain one of the values: 8, 16, 24, 32 */ + uint8_t prefix; + /** IPv4 address */ + IPv4Address ipAddr; + + /** + * A default c'tor that zeroes all data + */ + prefix_and_ip() : prefix(0), ipAddr(IPv4Address::Zero) + {} + + /** + * A c'tor that initializes the values of the struct + * @param[in] prefixVal IPv4 address mask value + * @param[in] ipAddrVal IPv4 address + */ + prefix_and_ip(uint8_t prefixVal, const std::string& ipAddrVal) : prefix(prefixVal), ipAddr(ipAddrVal) + {} + }; /** - * A c'tor that initializes the values of the struct - * @param[in] prefixVal IPv4 address mask value - * @param[in] ipAddrVal IPv4 address + * @struct path_attribute + * A structure that represents BGP OPEN message Path Attributes information */ - prefix_and_ip(uint8_t prefixVal, const std::string& ipAddrVal): prefix(prefixVal), ipAddr(ipAddrVal) {} - }; - - - /** - * @struct path_attribute - * A structure that represents BGP OPEN message Path Attributes information - */ - struct path_attribute - { - /** Path attribute flags */ - uint8_t flags; - /** Path attribute type */ - uint8_t type; - /** Path attribute length */ - uint8_t length; - /** Path attribute data. Max supported data length is 32 bytes */ - uint8_t data[32]; + struct path_attribute + { + /** Path attribute flags */ + uint8_t flags; + /** Path attribute type */ + uint8_t type; + /** Path attribute length */ + uint8_t length; + /** Path attribute data. Max supported data length is 32 bytes */ + uint8_t data[32]; + + /** + * A default c'tor that zeroes all data + */ + path_attribute() + {} + + /** + * A c'tor that initializes the values of the struct + * @param[in] flagsVal Path attribute flags value + * @param[in] typeVal Path attribute type value + * @param[in] dataAsHexString Path attribute data as hex string. The path_attribute#length field will be set + * accordingly. If this parameter is not a valid hex string the data will remain zeroed and length will be + * also set to zero + */ + path_attribute(uint8_t flagsVal, uint8_t typeVal, const std::string& dataAsHexString); + }; /** - * A default c'tor that zeroes all data + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - path_attribute() {} + BgpUpdateMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : BgpLayer(data, dataLen, prevLayer, packet) + {} /** - * A c'tor that initializes the values of the struct - * @param[in] flagsVal Path attribute flags value - * @param[in] typeVal Path attribute type value - * @param[in] dataAsHexString Path attribute data as hex string. The path_attribute#length field will be set accordingly. - * If this parameter is not a valid hex string the data will remain zeroed and length will be also set to zero + * A static method that takes a byte array and detects whether it is a BgpUpdateMessage + * @param[in] data A byte array + * @param[in] dataSize The byte array size (in bytes) + * @return True if the data looks like a valid BgpUpdateMessage layer */ - path_attribute(uint8_t flagsVal, uint8_t typeVal, const std::string& dataAsHexString); - }; - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - BgpUpdateMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {} - - /** - * A static method that takes a byte array and detects whether it is a BgpUpdateMessage - * @param[in] data A byte array - * @param[in] dataSize The byte array size (in bytes) - * @return True if the data looks like a valid BgpUpdateMessage layer - */ - static bool isDataValid(const uint8_t *data, size_t dataSize); - - /** - * A c'tor that creates a new BGP UPDATE message - * @param[in] withdrawnRoutes A vector of withdrawn routes data. If left empty (which is the default value) no withdrawn route information will be written to the message - * @param[in] pathAttributes A vector of path attributes data. If left empty (which is the default value) no path attribute information will be written to the message - * @param[in] nlri A vector of network layer reachability data. If left empty (which is the default value) no reachability information will be written to the message - */ - explicit BgpUpdateMessageLayer( - const std::vector& withdrawnRoutes = std::vector(), - const std::vector& pathAttributes = std::vector(), - const std::vector& nlri = std::vector()); + static bool isDataValid(const uint8_t* data, size_t dataSize); - /** - * Get a pointer to the basic BGP message data. Notice this points directly to the data, so any change will modify the actual packet data - * @return A pointer to a bgp_common_header structure containing the data - */ - bgp_common_header* getBasicMsgHeader() const { return (bgp_common_header*)m_Data; } - - /** - * @return The size in [bytes] of the Withdrawn Routes data - */ - size_t getWithdrawnRoutesLength() const; - - /** - * Get a vector of the Withdrawn Routes currently in the message - * @param[out] withdrawnRoutes A reference to a vector the Withdrawn Routes data will be written to - */ - void getWithdrawnRoutes(std::vector& withdrawnRoutes); - - /** - * Set Withdrawn Routes in this message. This method will override any existing Withdrawn Routes in the message. - * If the input is an empty vector all Withdrawn Routes will be removed. This method automatically sets the - * bgp_common_header#length and the Withdrawn Routes length fields in the message - * @param[in] withdrawnRoutes New Withdrawn Routes to set in the message - * @return True if all Withdrawn Routes were set successfully or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool setWithdrawnRoutes(const std::vector& withdrawnRoutes); - - /** - * Clear all Withdrawn Routes data currently in the message. This is equivalent to calling setWithdrawnRoutes() with an empty - * vector as a parameter - * @return True if all Withdrawn Routes were successfully cleared or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool clearWithdrawnRoutes(); + /** + * A c'tor that creates a new BGP UPDATE message + * @param[in] withdrawnRoutes A vector of withdrawn routes data. If left empty (which is the default value) no + * withdrawn route information will be written to the message + * @param[in] pathAttributes A vector of path attributes data. If left empty (which is the default value) no + * path attribute information will be written to the message + * @param[in] nlri A vector of network layer reachability data. If left empty (which is the default value) no + * reachability information will be written to the message + */ + explicit BgpUpdateMessageLayer( + const std::vector& withdrawnRoutes = std::vector(), + const std::vector& pathAttributes = std::vector(), + const std::vector& nlri = std::vector()); - /** - * @return The size in [bytes] of the Path Attributes data - */ - size_t getPathAttributesLength() const; + /** + * Get a pointer to the basic BGP message data. Notice this points directly to the data, so any change will + * modify the actual packet data + * @return A pointer to a bgp_common_header structure containing the data + */ + bgp_common_header* getBasicMsgHeader() const + { + return (bgp_common_header*)m_Data; + } - /** - * Get a vector of the Path Attributes currently in the message - * @param[out] pathAttributes A reference to a vector the Path Attributes data will be written to - */ - void getPathAttributes(std::vector& pathAttributes); + /** + * @return The size in [bytes] of the Withdrawn Routes data + */ + size_t getWithdrawnRoutesLength() const; - /** - * Set Path Attributes in this message. This method will override any existing Path Attributes in the message. - * If the input is an empty vector all Path Attributes will be removed. This method automatically sets the - * bgp_common_header#length and the Path Attributes length fields in the message - * @param[in] pathAttributes New Path Attributes to set in the message - * @return True if all Path Attributes were set successfully or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool setPathAttributes(const std::vector& pathAttributes); + /** + * Get a vector of the Withdrawn Routes currently in the message + * @param[out] withdrawnRoutes A reference to a vector the Withdrawn Routes data will be written to + */ + void getWithdrawnRoutes(std::vector& withdrawnRoutes); - /** - * Clear all Path Attributes data currently in the message. This is equivalent to calling setPathAttributes() with an empty - * vector as a parameter - * @return True if all Path Attributes were successfully cleared or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool clearPathAttributes(); + /** + * Set Withdrawn Routes in this message. This method will override any existing Withdrawn Routes in the message. + * If the input is an empty vector all Withdrawn Routes will be removed. This method automatically sets the + * bgp_common_header#length and the Withdrawn Routes length fields in the message + * @param[in] withdrawnRoutes New Withdrawn Routes to set in the message + * @return True if all Withdrawn Routes were set successfully or false otherwise. In case of an error an + * appropriate message will be printed to log + */ + bool setWithdrawnRoutes(const std::vector& withdrawnRoutes); - /** - * @return The size in [bytes] of the Network Layer Reachability Info - */ - size_t getNetworkLayerReachabilityInfoLength() const; + /** + * Clear all Withdrawn Routes data currently in the message. This is equivalent to calling setWithdrawnRoutes() + * with an empty vector as a parameter + * @return True if all Withdrawn Routes were successfully cleared or false otherwise. In case of an error an + * appropriate message will be printed to log + */ + bool clearWithdrawnRoutes(); - /** - * Get a vector of the Network Layer Reachability Info currently in the message - * @param[out] nlri A reference to a vector the NLRI data will be written to - */ - void getNetworkLayerReachabilityInfo(std::vector& nlri); + /** + * @return The size in [bytes] of the Path Attributes data + */ + size_t getPathAttributesLength() const; - /** - * Set NLRI data in this message. This method will override any existing NLRI data in the message. - * If the input is an empty vector all NLRI data will be removed. This method automatically sets the - * bgp_common_header#length field in the message - * @param[in] nlri New NLRI data to set in the message - * @return True if all NLRI data was set successfully or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool setNetworkLayerReachabilityInfo(const std::vector& nlri); + /** + * Get a vector of the Path Attributes currently in the message + * @param[out] pathAttributes A reference to a vector the Path Attributes data will be written to + */ + void getPathAttributes(std::vector& pathAttributes); - /** - * Clear all NLRI data currently in the message. This is equivalent to calling setNetworkLayerReachabilityInfo() with an empty - * vector as a parameter - * @return True if all NLRI were successfully cleared or false otherwise. In case of an error an appropriate message - * will be printed to log - */ - bool clearNetworkLayerReachabilityInfo(); + /** + * Set Path Attributes in this message. This method will override any existing Path Attributes in the message. + * If the input is an empty vector all Path Attributes will be removed. This method automatically sets the + * bgp_common_header#length and the Path Attributes length fields in the message + * @param[in] pathAttributes New Path Attributes to set in the message + * @return True if all Path Attributes were set successfully or false otherwise. In case of an error an + * appropriate message will be printed to log + */ + bool setPathAttributes(const std::vector& pathAttributes); - // implement abstract methods + /** + * Clear all Path Attributes data currently in the message. This is equivalent to calling setPathAttributes() + * with an empty vector as a parameter + * @return True if all Path Attributes were successfully cleared or false otherwise. In case of an error an + * appropriate message will be printed to log + */ + bool clearPathAttributes(); - BgpMessageType getBgpMessageType() const { return BgpLayer::Update; } + /** + * @return The size in [bytes] of the Network Layer Reachability Info + */ + size_t getNetworkLayerReachabilityInfoLength() const; -private: + /** + * Get a vector of the Network Layer Reachability Info currently in the message + * @param[out] nlri A reference to a vector the NLRI data will be written to + */ + void getNetworkLayerReachabilityInfo(std::vector& nlri); - void parsePrefixAndIPData(uint8_t* dataPtr, size_t dataLen, std::vector& result); + /** + * Set NLRI data in this message. This method will override any existing NLRI data in the message. + * If the input is an empty vector all NLRI data will be removed. This method automatically sets the + * bgp_common_header#length field in the message + * @param[in] nlri New NLRI data to set in the message + * @return True if all NLRI data was set successfully or false otherwise. In case of an error an appropriate + * message will be printed to log + */ + bool setNetworkLayerReachabilityInfo(const std::vector& nlri); - size_t prefixAndIPDataToByteArray(const std::vector& prefixAndIpData, uint8_t* resultByteArr, size_t maxByteArrSize); + /** + * Clear all NLRI data currently in the message. This is equivalent to calling setNetworkLayerReachabilityInfo() + * with an empty vector as a parameter + * @return True if all NLRI were successfully cleared or false otherwise. In case of an error an appropriate + * message will be printed to log + */ + bool clearNetworkLayerReachabilityInfo(); - size_t pathAttributesToByteArray(const std::vector& pathAttributes, uint8_t* resultByteArr, size_t maxByteArrSize); + // implement abstract methods -}; + BgpMessageType getBgpMessageType() const + { + return BgpLayer::Update; + } + private: + void parsePrefixAndIPData(uint8_t* dataPtr, size_t dataLen, std::vector& result); + size_t prefixAndIPDataToByteArray(const std::vector& prefixAndIpData, uint8_t* resultByteArr, + size_t maxByteArrSize); -/** - * @class BgpNotificationMessageLayer - * Represents a BGP v4 NOTIFICATION message - */ -class BgpNotificationMessageLayer : public BgpLayer -{ -public: + size_t pathAttributesToByteArray(const std::vector& pathAttributes, uint8_t* resultByteArr, + size_t maxByteArrSize); + }; /** - * @struct bgp_notification_message - * BGP NOTIFICATION message structure + * @class BgpNotificationMessageLayer + * Represents a BGP v4 NOTIFICATION message */ - #pragma pack(push, 1) - typedef struct bgp_notification_message : bgp_common_header + class BgpNotificationMessageLayer : public BgpLayer { - /** BGP notification error code */ - uint8_t errorCode; - /** BGP notification error sub-code */ - uint8_t errorSubCode; - } bgp_notification_message; - #pragma pack(pop) - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - BgpNotificationMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {} - - /** - * A c'tor that creates a new BGP NOTIFICATION message - * @param[in] errorCode BGP notification error code - * @param[in] errorSubCode BGP notification error sub code - */ - BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode); - - /** - * A c'tor that creates a new BGP Notification message - * @param[in] errorCode BGP notification error code - * @param[in] errorSubCode BGP notification error sub code - * @param[in] notificationData A byte array that contains the notification data - * @param[in] notificationDataLen The size of the byte array that contains the notification data - */ - BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, size_t notificationDataLen); - - /** - * A c'tor that creates a new BGP Notification message - * @param[in] errorCode BGP notification error code - * @param[in] errorSubCode BGP notification error sub code - * @param[in] notificationData A hex string that contains the notification data. This string will be converted to a byte array that will be - * added to the message. If the input isn't a valid hex string notification data will remain empty and an error will be printed to log - */ - BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const std::string& notificationData); - - /** - * Get a pointer to the notification message data. Notice this points directly to the data, so any change will modify the actual packet data - * @return A pointer to a bgp_notification_message structure containing the data - */ - bgp_notification_message* getNotificationMsgHeader() const { return (bgp_notification_message*)m_Data; } - - /** - * @return The size in [bytes] of the notification data. Notification data is a variable-length field used to diagnose the reason for - * the BGP NOTIFICATION - */ - size_t getNotificationDataLen() const; - - /** - * @return A pointer to the notification data. Notification data is a variable-length field used to diagnose the reason for - * the BGP NOTIFICATION - */ - uint8_t* getNotificationData() const; - - /** - * @return A hex string which represents the notification data. Notification data is a variable-length field used to diagnose the reason for - * the BGP NOTIFICATION - */ - std::string getNotificationDataAsHexString() const; + public: +#pragma pack(push, 1) + /** + * @struct bgp_notification_message + * BGP NOTIFICATION message structure + */ + typedef struct bgp_notification_message : bgp_common_header + { + /** BGP notification error code */ + uint8_t errorCode; + /** BGP notification error sub-code */ + uint8_t errorSubCode; + } bgp_notification_message; +#pragma pack(pop) - /** - * Set the notification data. This method will extend or shorten the existing layer to include the new notification data. - * If newNotificationData is NULL or newNotificationDataLen is zero then notification data will be set to none. - * @param[in] newNotificationData A byte array containing the new notification data - * @param[in] newNotificationDataLen The size of the byte array - * @return True if notification data was set successfully or false if any error occurred. In case of an error an appropriate - * error message will be printed to log - */ - bool setNotificationData(const uint8_t* newNotificationData, size_t newNotificationDataLen); + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + BgpNotificationMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : BgpLayer(data, dataLen, prevLayer, packet) + {} - /** - * Set the notification data. This method will extend or shorten the existing layer to include the new notification data. - * If newNotificationDataAsHexString is an empty string then notification data will be set to none. - * @param[in] newNotificationDataAsHexString A hex string representing the new notification data. If the string is not a valid hex string - * no data will be changed and an error will be returned - * @return True if notification data was set successfully or false if any error occurred or if the string is not a valid hex string. - * In case of an error an appropriate error message will be printed to log - */ - bool setNotificationData(const std::string& newNotificationDataAsHexString); + /** + * A c'tor that creates a new BGP NOTIFICATION message + * @param[in] errorCode BGP notification error code + * @param[in] errorSubCode BGP notification error sub code + */ + BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode); - // implement abstract methods + /** + * A c'tor that creates a new BGP Notification message + * @param[in] errorCode BGP notification error code + * @param[in] errorSubCode BGP notification error sub code + * @param[in] notificationData A byte array that contains the notification data + * @param[in] notificationDataLen The size of the byte array that contains the notification data + */ + BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, + size_t notificationDataLen); - BgpMessageType getBgpMessageType() const { return BgpLayer::Notification; } + /** + * A c'tor that creates a new BGP Notification message + * @param[in] errorCode BGP notification error code + * @param[in] errorSubCode BGP notification error sub code + * @param[in] notificationData A hex string that contains the notification data. This string will be converted + * to a byte array that will be added to the message. If the input isn't a valid hex string notification data + * will remain empty and an error will be printed to log + */ + BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const std::string& notificationData); -private: + /** + * Get a pointer to the notification message data. Notice this points directly to the data, so any change will + * modify the actual packet data + * @return A pointer to a bgp_notification_message structure containing the data + */ + bgp_notification_message* getNotificationMsgHeader() const + { + return (bgp_notification_message*)m_Data; + } - void initMessageData(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, size_t notificationDataLen); + /** + * @return The size in [bytes] of the notification data. Notification data is a variable-length field used to + * diagnose the reason for the BGP NOTIFICATION + */ + size_t getNotificationDataLen() const; -}; + /** + * @return A pointer to the notification data. Notification data is a variable-length field used to diagnose the + * reason for the BGP NOTIFICATION + */ + uint8_t* getNotificationData() const; + /** + * @return A hex string which represents the notification data. Notification data is a variable-length field + * used to diagnose the reason for the BGP NOTIFICATION + */ + std::string getNotificationDataAsHexString() const; + /** + * Set the notification data. This method will extend or shorten the existing layer to include the new + * notification data. If newNotificationData is NULL or newNotificationDataLen is zero then notification data + * will be set to none. + * @param[in] newNotificationData A byte array containing the new notification data + * @param[in] newNotificationDataLen The size of the byte array + * @return True if notification data was set successfully or false if any error occurred. In case of an error an + * appropriate error message will be printed to log + */ + bool setNotificationData(const uint8_t* newNotificationData, size_t newNotificationDataLen); -/** - * @class BgpKeepaliveMessageLayer - * Represents a BGP v4 KEEPALIVE message - */ -class BgpKeepaliveMessageLayer : public BgpLayer -{ -public: + /** + * Set the notification data. This method will extend or shorten the existing layer to include the new + * notification data. If newNotificationDataAsHexString is an empty string then notification data will be set to + * none. + * @param[in] newNotificationDataAsHexString A hex string representing the new notification data. If the string + * is not a valid hex string no data will be changed and an error will be returned + * @return True if notification data was set successfully or false if any error occurred or if the string is not + * a valid hex string. In case of an error an appropriate error message will be printed to log + */ + bool setNotificationData(const std::string& newNotificationDataAsHexString); - /** - * @typedef bgp_keepalive_message - * BGP KEEPALIVE message structure - */ - typedef bgp_common_header bgp_keepalive_message; + // implement abstract methods - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - BgpKeepaliveMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {} + BgpMessageType getBgpMessageType() const + { + return BgpLayer::Notification; + } - /** - * A c'tor that creates a new BGP KEEPALIVE message - */ - BgpKeepaliveMessageLayer(); + private: + void initMessageData(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, + size_t notificationDataLen); + }; /** - * Get a pointer to the KeepAlive message data. Notice this points directly to the data, so any change will modify the actual packet data - * @return A pointer to a bgp_keepalive_message structure containing the data + * @class BgpKeepaliveMessageLayer + * Represents a BGP v4 KEEPALIVE message */ - bgp_keepalive_message* getKeepaliveHeader() const { return (bgp_keepalive_message*)getBasicHeader(); } - - // implement abstract methods + class BgpKeepaliveMessageLayer : public BgpLayer + { + public: + /** + * @typedef bgp_keepalive_message + * BGP KEEPALIVE message structure + */ + typedef bgp_common_header bgp_keepalive_message; - BgpMessageType getBgpMessageType() const { return BgpLayer::Keepalive; } + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + BgpKeepaliveMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : BgpLayer(data, dataLen, prevLayer, packet) + {} -}; + /** + * A c'tor that creates a new BGP KEEPALIVE message + */ + BgpKeepaliveMessageLayer(); + /** + * Get a pointer to the KeepAlive message data. Notice this points directly to the data, so any change will + * modify the actual packet data + * @return A pointer to a bgp_keepalive_message structure containing the data + */ + bgp_keepalive_message* getKeepaliveHeader() const + { + return (bgp_keepalive_message*)getBasicHeader(); + } + // implement abstract methods -/** - * @class BgpRouteRefreshMessageLayer - * Represents a BGP v4 ROUTE-REFRESH message - */ -class BgpRouteRefreshMessageLayer : public BgpLayer -{ -public: + BgpMessageType getBgpMessageType() const + { + return BgpLayer::Keepalive; + } + }; /** - * @struct bgp_route_refresh_message - * BGP ROUTE-REFRESH message structure + * @class BgpRouteRefreshMessageLayer + * Represents a BGP v4 ROUTE-REFRESH message */ - #pragma pack(push, 1) - typedef struct bgp_route_refresh_message : bgp_common_header + class BgpRouteRefreshMessageLayer : public BgpLayer { - /** Address Family Identifier */ - uint16_t afi; - /** Reserved field */ - uint8_t reserved; - /** Subsequent Address Family Identifier */ - uint8_t safi; - } bgp_route_refresh_message; - #pragma pack(pop) - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - BgpRouteRefreshMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : BgpLayer(data, dataLen, prevLayer, packet) {} + public: +#pragma pack(push, 1) + /** + * @struct bgp_route_refresh_message + * BGP ROUTE-REFRESH message structure + */ + typedef struct bgp_route_refresh_message : bgp_common_header + { + /** Address Family Identifier */ + uint16_t afi; + /** Reserved field */ + uint8_t reserved; + /** Subsequent Address Family Identifier */ + uint8_t safi; + } bgp_route_refresh_message; +#pragma pack(pop) - /** - * A c'tor that creates a new BGP ROUTE-REFRESH message - * @param[in] afi The Address Family Identifier (AFI) value to set in the message - * @param[in] safi The Subsequent Address Family Identifier (SAFI) value to set in the message - */ - BgpRouteRefreshMessageLayer(uint16_t afi, uint8_t safi); + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + BgpRouteRefreshMessageLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : BgpLayer(data, dataLen, prevLayer, packet) + {} - /** - * Get a pointer to the ROUTE-REFRESH message data. Notice this points directly to the data, so any change will modify the actual packet data - * @return A pointer to a bgp_route_refresh_message structure containing the data - */ - bgp_route_refresh_message* getRouteRefreshHeader() const { return (bgp_route_refresh_message*)getBasicHeader(); } + /** + * A c'tor that creates a new BGP ROUTE-REFRESH message + * @param[in] afi The Address Family Identifier (AFI) value to set in the message + * @param[in] safi The Subsequent Address Family Identifier (SAFI) value to set in the message + */ + BgpRouteRefreshMessageLayer(uint16_t afi, uint8_t safi); - // implement abstract methods + /** + * Get a pointer to the ROUTE-REFRESH message data. Notice this points directly to the data, so any change will + * modify the actual packet data + * @return A pointer to a bgp_route_refresh_message structure containing the data + */ + bgp_route_refresh_message* getRouteRefreshHeader() const + { + return (bgp_route_refresh_message*)getBasicHeader(); + } - BgpMessageType getBgpMessageType() const { return BgpLayer::RouteRefresh; } + // implement abstract methods -}; + BgpMessageType getBgpMessageType() const + { + return BgpLayer::RouteRefresh; + } + }; -} +} // namespace pcpp diff --git a/Packet++/header/CotpLayer.h b/Packet++/header/CotpLayer.h index 88dd207cb5..4d5544d7b2 100644 --- a/Packet++/header/CotpLayer.h +++ b/Packet++/header/CotpLayer.h @@ -16,7 +16,7 @@ namespace pcpp /** length */ uint8_t length; /** PDU type identifier */ - uint8_t pduType ; + uint8_t pduType; /** TPDU number sequence*/ uint8_t tpduNumber; } cotphdr; @@ -28,7 +28,7 @@ namespace pcpp */ class CotpLayer : public Layer { - public: + public: /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data (will be casted to @ref cotphdr) @@ -36,8 +36,8 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - CotpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) + CotpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { m_Protocol = COTP; } @@ -48,7 +48,8 @@ namespace pcpp */ explicit CotpLayer(uint8_t tpduNumber); - virtual ~CotpLayer() {} + virtual ~CotpLayer() + {} /** * @return COTP length @@ -68,7 +69,10 @@ namespace pcpp /** * @return Size of @ref cotphdr */ - size_t getHeaderLen() const override { return sizeof(cotphdr); } + size_t getHeaderLen() const override + { + return sizeof(cotphdr); + } /** * Set the value of the length @@ -91,7 +95,8 @@ namespace pcpp /** * Does nothing for this layer */ - void computeCalculateFields() override {} + void computeCalculateFields() override + {} /** * Currently parses the rest of the packet as a S7COMM or generic payload (PayloadLayer) @@ -104,14 +109,20 @@ namespace pcpp * @param[in] dataSize The byte array size (in bytes) * @return True if the data looks like a valid COTP layer */ - static bool isDataValid(const uint8_t *data, size_t dataSize); + static bool isDataValid(const uint8_t* data, size_t dataSize); std::string toString() const override; - OsiModelLayer getOsiModelLayer() const override { return OsiModelTransportLayer; } + OsiModelLayer getOsiModelLayer() const override + { + return OsiModelTransportLayer; + } - private: - cotphdr *getCotpHeader() const { return (cotphdr *)m_Data; } + private: + cotphdr* getCotpHeader() const + { + return (cotphdr*)m_Data; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/DhcpLayer.h b/Packet++/header/DhcpLayer.h index 44ceff3b13..adf9581cac 100644 --- a/Packet++/header/DhcpLayer.h +++ b/Packet++/header/DhcpLayer.h @@ -15,11 +15,11 @@ namespace pcpp { - /** - * @struct dhcp_header - * Represents a DHCP protocol header - */ - #pragma pack(push, 1) +/** + * @struct dhcp_header + * Represents a DHCP protocol header + */ +#pragma pack(push, 1) struct dhcp_header { /** BootP opcode */ @@ -53,8 +53,7 @@ namespace pcpp /** DHCP magic number (set to the default value of 0x63538263) */ uint32_t magicNumber; }; - #pragma pack(pop) - +#pragma pack(pop) /** * BootP opcodes @@ -75,21 +74,21 @@ namespace pcpp /** Unknown message type */ DHCP_UNKNOWN_MSG_TYPE = 0, /** Discover message type */ - DHCP_DISCOVER = 1, + DHCP_DISCOVER = 1, /** Offer message type */ - DHCP_OFFER = 2, + DHCP_OFFER = 2, /** Request message type */ - DHCP_REQUEST = 3, + DHCP_REQUEST = 3, /** Decline message type */ - DHCP_DECLINE = 4, + DHCP_DECLINE = 4, /** Acknowledge message type */ - DHCP_ACK = 5, + DHCP_ACK = 5, /** Non-acknowledge message type */ - DHCP_NAK = 6, + DHCP_NAK = 6, /** Release message type */ - DHCP_RELEASE = 7, + DHCP_RELEASE = 7, /** Inform message type */ - DHCP_INFORM = 8 + DHCP_INFORM = 8 }; /** @@ -388,10 +387,9 @@ namespace pcpp /** Virtual Subnet Selection (VSS) Option */ DHCPOPT_VIRTUAL_SUBNET_SELECTION = 221, /** End (last option) */ - DHCPOPT_END = 255 + DHCPOPT_END = 255 }; - /** * @class DhcpOption * A wrapper class for DHCP options. This class does not create or modify DHCP option records, but rather @@ -400,17 +398,18 @@ namespace pcpp class DhcpOption : public TLVRecord { public: - /** * A c'tor for this class that gets a pointer to the option raw data (byte array) * @param[in] optionRawData A pointer to the option raw data */ - explicit DhcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) { } + explicit DhcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) + {} /** * A d'tor for this class, currently does nothing */ - virtual ~DhcpOption() { } + virtual ~DhcpOption() + {} /** * Retrieve DHCP option data as IPv4 address. Relevant only if option value is indeed an IPv4 address @@ -424,9 +423,9 @@ namespace pcpp /** * Set DHCP option data as IPv4 address. This method copies the 4 bytes of the IP address to the option value * @param[in] addr The IPv4 address to set - * @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set to 0). For example: - * if option data is 20 bytes long and you want to set the IP address in the 4 last bytes then use this method like this: - * setValueIpAddr(your_addr, 16) + * @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set + * to 0). For example: if option data is 20 bytes long and you want to set the IP address in the 4 last bytes + * then use this method like this: setValueIpAddr(your_addr, 16) */ void setValueIpAddr(const IPv4Address& addr, int valueOffset = 0) { @@ -435,9 +434,9 @@ namespace pcpp /** * Retrieve DHCP option data as string. Relevant only if option value is indeed a string - * @param[in] valueOffset An optional parameter that specifies where to start copy the DHCP option data. For example: - * when retrieving Client FQDN option, you may ignore the flags and RCODE fields using this method like this: - * getValueAsString(3). The default is 0 - start copying from the beginning of option data + * @param[in] valueOffset An optional parameter that specifies where to start copy the DHCP option data. For + * example: when retrieving Client FQDN option, you may ignore the flags and RCODE fields using this method like + * this: getValueAsString(3). The default is 0 - start copying from the beginning of option data * @return DHCP option data as string */ std::string getValueAsString(int valueOffset = 0) const @@ -449,12 +448,12 @@ namespace pcpp } /** - * Set DHCP option data as string. This method copies the string to the option value. If the string is longer than option length - * the string is trimmed so it will fit the option length + * Set DHCP option data as string. This method copies the string to the option value. If the string is longer + * than option length the string is trimmed so it will fit the option length * @param[in] stringValue The string to set - * @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set to 0). For example: - * if option data is 20 bytes long and you want to set a 6 char-long string in the 6 last bytes then use this method like this: - * setValueString("string", 14) + * @param[in] valueOffset An optional parameter that specifies where to start set the option data (default set + * to 0). For example: if option data is 20 bytes long and you want to set a 6 char-long string in the 6 last + * bytes then use this method like this: setValueString("string", 14) */ void setValueString(const std::string& stringValue, int valueOffset = 0) { @@ -514,7 +513,6 @@ namespace pcpp } }; - /** * @class DhcpOptionBuilder * A class for building DHCP options. This builder receives the option parameters in its c'tor, @@ -523,16 +521,17 @@ namespace pcpp class DhcpOptionBuilder : public TLVRecordBuilder { public: - /** * A c'tor for building DHCP options which their value is a byte array. The DhcpOption object can later * be retrieved by calling build() * @param[in] optionType DHCP option type - * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way + * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in + * any way * @param[in] optionValueLen DHCP option value length in bytes */ - DhcpOptionBuilder(DhcpOptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) : - TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) { } + DhcpOptionBuilder(DhcpOptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) + : TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) + {} /** * A c'tor for building DHCP options which have a 1-byte value. The DhcpOption object can later be retrieved @@ -540,8 +539,9 @@ namespace pcpp * @param[in] optionType DHCP option type * @param[in] optionValue A 1-byte option value */ - DhcpOptionBuilder(DhcpOptionTypes optionType, uint8_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) { } + DhcpOptionBuilder(DhcpOptionTypes optionType, uint8_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building DHCP options which have a 2-byte value. The DhcpOption object can later be retrieved @@ -549,8 +549,9 @@ namespace pcpp * @param[in] optionType DHCP option type * @param[in] optionValue A 2-byte option value */ - DhcpOptionBuilder(DhcpOptionTypes optionType, uint16_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) { } + DhcpOptionBuilder(DhcpOptionTypes optionType, uint16_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building DHCP options which have a 4-byte value. The DhcpOption object can later be retrieved @@ -558,8 +559,9 @@ namespace pcpp * @param[in] optionType DHCP option type * @param[in] optionValue A 4-byte option value */ - DhcpOptionBuilder(DhcpOptionTypes optionType, uint32_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) { } + DhcpOptionBuilder(DhcpOptionTypes optionType, uint32_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building DHCP options which have an IPv4Address value. The DhcpOption object can later be @@ -567,8 +569,9 @@ namespace pcpp * @param[in] optionType DHCP option type * @param[in] optionValue The IPv4 address option value */ - DhcpOptionBuilder(DhcpOptionTypes optionType, const IPv4Address& optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) { } + DhcpOptionBuilder(DhcpOptionTypes optionType, const IPv4Address& optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building DHCP options which have a string value. The DhcpOption object can later be retrieved @@ -576,15 +579,16 @@ namespace pcpp * @param[in] optionType DHCP option type * @param[in] optionValue The string option value */ - DhcpOptionBuilder(DhcpOptionTypes optionType, const std::string& optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) { } + DhcpOptionBuilder(DhcpOptionTypes optionType, const std::string& optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A copy c'tor which copies all the data from another instance of DhcpOptionBuilder * @param[in] other The instance to copy from */ - DhcpOptionBuilder(const DhcpOptionBuilder& other) : - TLVRecordBuilder(other) { } + DhcpOptionBuilder(const DhcpOptionBuilder& other) : TLVRecordBuilder(other) + {} /** * Assignment operator that copies all data from another instance of DhcpOptionBuilder @@ -604,8 +608,6 @@ namespace pcpp DhcpOption build() const; }; - - /** * @class DhcpLayer * Represents a DHCP (Dynamic Host Configuration Protocol) protocol layer @@ -613,7 +615,6 @@ namespace pcpp class DhcpLayer : public Layer { public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -639,88 +640,125 @@ namespace pcpp /** * A destructor for this layer */ - virtual ~DhcpLayer() {} + virtual ~DhcpLayer() + {} /** - * Get a pointer to the DHCP header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the DHCP header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref dhcp_header */ - dhcp_header* getDhcpHeader() const { return (dhcp_header*)m_Data; } + dhcp_header* getDhcpHeader() const + { + return (dhcp_header*)m_Data; + } /** * @return The BootP opcode of this message */ - BootpOpCodes getOpCode() const { return (BootpOpCodes)getDhcpHeader()->opCode; } + BootpOpCodes getOpCode() const + { + return (BootpOpCodes)getDhcpHeader()->opCode; + } /** - * @return The client IPv4 address (as extracted from dhcp_header#clientIpAddress converted to IPv4Address object) + * @return The client IPv4 address (as extracted from dhcp_header#clientIpAddress converted to IPv4Address + * object) */ - IPv4Address getClientIpAddress() const { return getDhcpHeader()->clientIpAddress; } + IPv4Address getClientIpAddress() const + { + return getDhcpHeader()->clientIpAddress; + } /** * Set the client IPv4 address in dhcp_header#clientIpAddress * @param[in] addr The IPv4 address to set */ - void setClientIpAddress(const IPv4Address& addr) { getDhcpHeader()->clientIpAddress = addr.toInt(); } + void setClientIpAddress(const IPv4Address& addr) + { + getDhcpHeader()->clientIpAddress = addr.toInt(); + } /** - * @return The server IPv4 address (as extracted from dhcp_header#serverIpAddress converted to IPv4Address object) + * @return The server IPv4 address (as extracted from dhcp_header#serverIpAddress converted to IPv4Address + * object) */ - IPv4Address getServerIpAddress() const { return getDhcpHeader()->serverIpAddress; } + IPv4Address getServerIpAddress() const + { + return getDhcpHeader()->serverIpAddress; + } /** * Set the server IPv4 address in dhcp_header#serverIpAddress * @param[in] addr The IPv4 address to set */ - void setServerIpAddress(const IPv4Address& addr) { getDhcpHeader()->serverIpAddress = addr.toInt(); } + void setServerIpAddress(const IPv4Address& addr) + { + getDhcpHeader()->serverIpAddress = addr.toInt(); + } /** * @return Your IPv4 address (as extracted from dhcp_header#yourIpAddress converted to IPv4Address object) */ - IPv4Address getYourIpAddress() const { return getDhcpHeader()->yourIpAddress; } + IPv4Address getYourIpAddress() const + { + return getDhcpHeader()->yourIpAddress; + } /** * Set your IPv4 address in dhcp_header#yourIpAddress * @param[in] addr The IPv4 address to set */ - void setYourIpAddress(const IPv4Address& addr) { getDhcpHeader()->yourIpAddress = addr.toInt(); } + void setYourIpAddress(const IPv4Address& addr) + { + getDhcpHeader()->yourIpAddress = addr.toInt(); + } /** * @return Gateway IPv4 address (as extracted from dhcp_header#gatewayIpAddress converted to IPv4Address object) */ - IPv4Address getGatewayIpAddress() const { return getDhcpHeader()->gatewayIpAddress; } + IPv4Address getGatewayIpAddress() const + { + return getDhcpHeader()->gatewayIpAddress; + } /** * Set the gateway IPv4 address in dhcp_header#gatewayIpAddress * @param[in] addr The IPv4 address to set */ - void setGatewayIpAddress(const IPv4Address& addr) { getDhcpHeader()->gatewayIpAddress = addr.toInt(); } + void setGatewayIpAddress(const IPv4Address& addr) + { + getDhcpHeader()->gatewayIpAddress = addr.toInt(); + } /** - * @return The client MAC address as extracted from dhcp_header#clientHardwareAddress, assuming dhcp_header#hardwareType is 1 (Ethernet) - * and dhcp_header#hardwareAddressLength is 6 (MAC address length). Otherwise returns MacAddress#Zero + * @return The client MAC address as extracted from dhcp_header#clientHardwareAddress, assuming + * dhcp_header#hardwareType is 1 (Ethernet) and dhcp_header#hardwareAddressLength is 6 (MAC address length). + * Otherwise returns MacAddress#Zero */ MacAddress getClientHardwareAddress() const; /** - * Set a MAC address into the first 6 bytes of dhcp_header#clientHardwareAddress. This method also sets dhcp_header#hardwareType - * to 1 (Ethernet) and dhcp_header#hardwareAddressLength to 6 (MAC address length) + * Set a MAC address into the first 6 bytes of dhcp_header#clientHardwareAddress. This method also sets + * dhcp_header#hardwareType to 1 (Ethernet) and dhcp_header#hardwareAddressLength to 6 (MAC address length) * @param[in] addr The MAC address to set */ void setClientHardwareAddress(const MacAddress& addr); /** - * @return DHCP message type as extracted from ::DHCPOPT_DHCP_MESSAGE_TYPE option. If this option doesn't exist the value of + * @return DHCP message type as extracted from ::DHCPOPT_DHCP_MESSAGE_TYPE option. If this option doesn't exist + * the value of * ::DHCP_UNKNOWN_MSG_TYPE is returned */ DhcpMessageType getMessageType() const; /** - * Set DHCP message type. This method searches for existing ::DHCPOPT_DHCP_MESSAGE_TYPE option. If found, it sets the requested - * message type as its value. If not, it creates a ::DHCPOPT_DHCP_MESSAGE_TYPE option and sets the requested message type as its - * value + * Set DHCP message type. This method searches for existing ::DHCPOPT_DHCP_MESSAGE_TYPE option. If found, it + * sets the requested message type as its value. If not, it creates a ::DHCPOPT_DHCP_MESSAGE_TYPE option and + * sets the requested message type as its value * @param[in] msgType Message type to set - * @return True if message type was set successfully or false if msgType is ::DHCP_UNKNOWN_MSG_TYPE or if failed to add + * @return True if message type was set successfully or false if msgType is ::DHCP_UNKNOWN_MSG_TYPE or if failed + * to add * ::DHCPOPT_DHCP_MESSAGE_TYPE option */ bool setMessageType(DhcpMessageType msgType); @@ -788,17 +826,22 @@ namespace pcpp /** * Does nothing for this layer (DhcpLayer is always last) */ - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return The size of @ref dhcp_header + size of options */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /** * Calculate the following fields: * - @ref dhcp_header#magicNumber = DHCP magic number (0x63538263) - * - @ref dhcp_header#opCode = ::DHCP_BOOTREQUEST for message types: ::DHCP_DISCOVER, ::DHCP_REQUEST, ::DHCP_DECLINE, ::DHCP_RELEASE, + * - @ref dhcp_header#opCode = ::DHCP_BOOTREQUEST for message types: ::DHCP_DISCOVER, ::DHCP_REQUEST, + * ::DHCP_DECLINE, ::DHCP_RELEASE, * ::DHCP_INFORM, ::DHCP_UNKNOWN_MSG_TYPE * ::DHCP_BOOTREPLY for message types: ::DHCP_OFFER, ::DHCP_ACK, ::DHCP_NAK * - @ref dhcp_header#hardwareType = 1 (Ethernet) @@ -808,11 +851,16 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } private: - - uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(dhcp_header); } + uint8_t* getOptionsBasePtr() const + { + return m_Data + sizeof(dhcp_header); + } TLVRecordReader m_OptionReader; @@ -820,4 +868,4 @@ namespace pcpp DhcpOption addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset); }; -} +} // namespace pcpp diff --git a/Packet++/header/DhcpV6Layer.h b/Packet++/header/DhcpV6Layer.h index e967b1f3a7..d072989bb8 100644 --- a/Packet++/header/DhcpV6Layer.h +++ b/Packet++/header/DhcpV6Layer.h @@ -17,33 +17,33 @@ namespace pcpp enum DhcpV6MessageType { /** Unknown message type */ - DHCPV6_UNKNOWN_MSG_TYPE = 0, + DHCPV6_UNKNOWN_MSG_TYPE = 0, /** Solicit message type (Client to Server) */ - DHCPV6_SOLICIT = 1, + DHCPV6_SOLICIT = 1, /** Advertise message type (Server to Client) */ - DHCPV6_ADVERTISE = 2, + DHCPV6_ADVERTISE = 2, /** Request message type (Client to Server) */ - DHCPV6_REQUEST = 3, + DHCPV6_REQUEST = 3, /** Confirm message type (Client to Server) */ - DHCPV6_CONFIRM = 4, + DHCPV6_CONFIRM = 4, /** Renew message type (Client to Server) */ - DHCPV6_RENEW = 5, + DHCPV6_RENEW = 5, /** Rebind message type (Client to Server) */ - DHCPV6_REBIND = 6, + DHCPV6_REBIND = 6, /** Reply message type (Server to Client) */ - DHCPV6_REPLY = 7, + DHCPV6_REPLY = 7, /** Release message type (Client to Server) */ - DHCPV6_RELEASE = 8, + DHCPV6_RELEASE = 8, /** Decline message type (Client to Server) */ - DHCPV6_DECLINE = 9, + DHCPV6_DECLINE = 9, /** Reconfigure message type (Server to Client) */ - DHCPV6_RECONFIGURE = 10, + DHCPV6_RECONFIGURE = 10, /** Information-Request message type (Client to Server) */ DHCPV6_INFORMATION_REQUEST = 11, /** Relay-Forward message type (Relay agent to Server) */ - DHCPV6_RELAY_FORWARD = 12, + DHCPV6_RELAY_FORWARD = 12, /** Relay-Reply message type (Server to Relay agent) */ - DHCPV6_RELAY_REPLY = 13 + DHCPV6_RELAY_REPLY = 13 }; /** @@ -57,133 +57,134 @@ namespace pcpp enum DhcpV6OptionType { /** Unknown option type */ - DHCPV6_OPT_UNKNOWN = 0, + DHCPV6_OPT_UNKNOWN = 0, /** Client Identifier (DUID of client) */ - DHCPV6_OPT_CLIENTID = 1, + DHCPV6_OPT_CLIENTID = 1, /** Server Identifier (DUID of server) */ - DHCPV6_OPT_SERVERID = 2, + DHCPV6_OPT_SERVERID = 2, /** Identity Association for Non-temporary addresses */ - DHCPV6_OPT_IA_NA = 3, + DHCPV6_OPT_IA_NA = 3, /** Identity Association for Temporary addresses */ - DHCPV6_OPT_IA_TA = 4, + DHCPV6_OPT_IA_TA = 4, /** IA Address option */ - DHCPV6_OPT_IAADDR = 5, + DHCPV6_OPT_IAADDR = 5, /** Option Request Option */ - DHCPV6_OPT_ORO = 6, + DHCPV6_OPT_ORO = 6, /** Preference setting */ - DHCPV6_OPT_PREFERENCE = 7, + DHCPV6_OPT_PREFERENCE = 7, /** The amount of time since the client began the current DHCP transaction */ - DHCPV6_OPT_ELAPSED_TIME = 8, + DHCPV6_OPT_ELAPSED_TIME = 8, /** The DHCP message being relayed by a relay agent */ - DHCPV6_OPT_RELAY_MSG = 9, + DHCPV6_OPT_RELAY_MSG = 9, /** Authentication information */ - DHCPV6_OPT_AUTH = 11, + DHCPV6_OPT_AUTH = 11, /** Server unicast */ - DHCPV6_OPT_UNICAST = 12, + DHCPV6_OPT_UNICAST = 12, /** Status code */ - DHCPV6_OPT_STATUS_CODE = 13, + DHCPV6_OPT_STATUS_CODE = 13, /** Rapid commit */ - DHCPV6_OPT_RAPID_COMMIT = 14, + DHCPV6_OPT_RAPID_COMMIT = 14, /** User class */ - DHCPV6_OPT_USER_CLASS = 15, + DHCPV6_OPT_USER_CLASS = 15, /** Vendor class */ - DHCPV6_OPT_VENDOR_CLASS = 16, + DHCPV6_OPT_VENDOR_CLASS = 16, /** Vendor specific information */ - DHCPV6_OPT_VENDOR_OPTS = 17, + DHCPV6_OPT_VENDOR_OPTS = 17, /** Interface ID */ - DHCPV6_OPT_INTERFACE_ID = 18, + DHCPV6_OPT_INTERFACE_ID = 18, /** Reconfigure Message */ - DHCPV6_OPT_RECONF_MSG = 19, + DHCPV6_OPT_RECONF_MSG = 19, /** Reconfigure Accept */ - DHCPV6_OPT_RECONF_ACCEPT = 20, + DHCPV6_OPT_RECONF_ACCEPT = 20, /** SIP Servers Domain Name */ - DHCPV6_OPT_SIP_SERVERS_D = 21, + DHCPV6_OPT_SIP_SERVERS_D = 21, /** SIP Servers IPv6 Address List */ - DHCPV6_OPT_SIP_SERVERS_A = 22, + DHCPV6_OPT_SIP_SERVERS_A = 22, /** DNS Recursive Name Server */ - DHCPV6_OPT_DNS_SERVERS = 23, + DHCPV6_OPT_DNS_SERVERS = 23, /** Domain Search List */ - DHCPV6_OPT_DOMAIN_LIST = 24, + DHCPV6_OPT_DOMAIN_LIST = 24, /** Identity Association for Prefix Delegation */ - DHCPV6_OPT_IA_PD = 25, + DHCPV6_OPT_IA_PD = 25, /** IA_PD Prefix */ - DHCPV6_OPT_IAPREFIX = 26, + DHCPV6_OPT_IAPREFIX = 26, /** Network Information Service (NIS) Servers */ - DHCPV6_OPT_NIS_SERVERS = 27, + DHCPV6_OPT_NIS_SERVERS = 27, /** Network Information Service v2 (NIS+) Servers */ - DHCPV6_OPT_NISP_SERVERS = 28, + DHCPV6_OPT_NISP_SERVERS = 28, /** Network Information Service (NIS) domain name */ - DHCPV6_OPT_NIS_DOMAIN_NAME = 29, + DHCPV6_OPT_NIS_DOMAIN_NAME = 29, /** Network Information Service v2 (NIS+) domain name */ - DHCPV6_OPT_NISP_DOMAIN_NAME = 30, + DHCPV6_OPT_NISP_DOMAIN_NAME = 30, /** Simple Network Time Protocol (SNTP) servers */ - DHCPV6_OPT_SNTP_SERVERS = 31, + DHCPV6_OPT_SNTP_SERVERS = 31, /** Information Refresh */ DHCPV6_OPT_INFORMATION_REFRESH_TIME = 32, /** Broadcast and Multicast Service (BCMCS) Domain Name List */ - DHCPV6_OPT_BCMCS_SERVER_D = 33, + DHCPV6_OPT_BCMCS_SERVER_D = 33, /** Broadcast and Multicast Service (BCMCS) IPv6 Address List */ - DHCPV6_OPT_BCMCS_SERVER_A = 34, + DHCPV6_OPT_BCMCS_SERVER_A = 34, /** Geographical location in civic (e.g., postal) format */ - DHCPV6_OPT_GEOCONF_CIVIC = 36, + DHCPV6_OPT_GEOCONF_CIVIC = 36, /** Relay Agent Remote ID */ - DHCPV6_OPT_REMOTE_ID = 37, + DHCPV6_OPT_REMOTE_ID = 37, /** Relay Agent Subscriber ID */ - DHCPV6_OPT_SUBSCRIBER_ID = 38, + DHCPV6_OPT_SUBSCRIBER_ID = 38, /** FQDN */ - DHCPV6_OPT_CLIENT_FQDN = 39, - /** One or more IPv6 addresses associated with PANA (Protocol for carrying Authentication for Network Access) Authentication Agents */ - DHCPV6_OPT_PANA_AGENT = 40, + DHCPV6_OPT_CLIENT_FQDN = 39, + /** One or more IPv6 addresses associated with PANA (Protocol for carrying Authentication for Network Access) + * Authentication Agents */ + DHCPV6_OPT_PANA_AGENT = 40, /** Time zone to be used by the client in IEEE 1003.1 format */ - DHCPV6_OPT_NEW_POSIX_TIMEZONE = 41, + DHCPV6_OPT_NEW_POSIX_TIMEZONE = 41, /** Time zone (TZ) database entry referred to by entry name */ - DHCPV6_OPT_NEW_TZDB_TIMEZONE = 42, + DHCPV6_OPT_NEW_TZDB_TIMEZONE = 42, /** Relay Agent Echo Request */ - DHCPV6_OPT_ERO = 43, + DHCPV6_OPT_ERO = 43, /** Query option */ - DHCPV6_OPT_LQ_QUERY = 44, + DHCPV6_OPT_LQ_QUERY = 44, /** Client Data */ - DHCPV6_OPT_CLIENT_DATA = 45, + DHCPV6_OPT_CLIENT_DATA = 45, /** Client Last Transaction Time */ - DHCPV6_OPT_CLT_TIME = 46, + DHCPV6_OPT_CLT_TIME = 46, /** Relay data */ - DHCPV6_OPT_LQ_RELAY_DATA = 47, + DHCPV6_OPT_LQ_RELAY_DATA = 47, /** Client link */ - DHCPV6_OPT_LQ_CLIENT_LINK = 48, + DHCPV6_OPT_LQ_CLIENT_LINK = 48, /** Mobile IPv6 Home Network Information */ - DHCPV6_OPT_MIP6_HNINF = 49, + DHCPV6_OPT_MIP6_HNINF = 49, /** Mobile IPv6 Relay Agent */ - DHCPV6_OPT_MIP6_RELAY = 50, + DHCPV6_OPT_MIP6_RELAY = 50, /** Location to Service Translation (LoST) server domain name */ - DHCPV6_OPT_V6_LOST = 51, + DHCPV6_OPT_V6_LOST = 51, /** Access Points (CAPWAP) Access Controller IPv6 addresses */ - DHCPV6_OPT_CAPWAP_AC_V6 = 52, + DHCPV6_OPT_CAPWAP_AC_V6 = 52, /** DHCPv6 Bulk LeaseQuery */ - DHCPV6_OPT_RELAY_ID = 53, + DHCPV6_OPT_RELAY_ID = 53, /** List of IPv6 addresses for servers providing particular types of IEEE 802.21 Mobility Service (MoS) */ - DHCPV6_OPT_IPH6_ADDRESS_MOS = 54, + DHCPV6_OPT_IPH6_ADDRESS_MOS = 54, /** List of FQDNs for servers providing particular types of IEEE 802.21 Mobility Service (MoS) */ - DHCPV6_OPT_IPV6_FQDN_MOS = 55, + DHCPV6_OPT_IPV6_FQDN_MOS = 55, /** Network Time Protocol (NTP) or Simple NTP (SNTP) Server Location */ - DHCPV6_OPT_NTP_SERVER = 56, + DHCPV6_OPT_NTP_SERVER = 56, /** Boot File Uniform Resource Locator (URL) */ - DHCPV6_OPT_BOOTFILE_URL = 59, + DHCPV6_OPT_BOOTFILE_URL = 59, /** Boot File Parameters */ - DHCPV6_OPT_BOOTFILE_PARAM = 60, + DHCPV6_OPT_BOOTFILE_PARAM = 60, /** Client System Architecture Type */ - DHCPV6_OPT_CLIENT_ARCH_TYPE = 61, + DHCPV6_OPT_CLIENT_ARCH_TYPE = 61, /** Client Network Interface Identifier */ - DHCPV6_OPT_NII = 62, + DHCPV6_OPT_NII = 62, /** ERP Local Domain Name */ - DHCPV6_OPT_ERP_LOCAL_DOMAIN_NAME = 65, + DHCPV6_OPT_ERP_LOCAL_DOMAIN_NAME = 65, /** Relay supplied options */ - DHCPV6_OPT_RELAY_SUPPLIED_OPTIONS = 66, + DHCPV6_OPT_RELAY_SUPPLIED_OPTIONS = 66, /** Virtual Subnet Selection */ - DHCPV6_OPT_VSS = 68, + DHCPV6_OPT_VSS = 68, /** Client link layer */ - DHCPV6_OPT_CLIENT_LINKLAYER_ADDR = 79, + DHCPV6_OPT_CLIENT_LINKLAYER_ADDR = 79, /** Manufacturer Usage Description */ - DHCPV6_OPT_MUD_URL = 112 + DHCPV6_OPT_MUD_URL = 112 }; /** @@ -198,12 +199,14 @@ namespace pcpp * A c'tor for this class that gets a pointer to the option raw data (byte array) * @param[in] optionRawData A pointer to the option raw data */ - explicit DhcpV6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { } + explicit DhcpV6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) + {} /** * A d'tor for this class, currently does nothing */ - virtual ~DhcpV6Option() { } + virtual ~DhcpV6Option() + {} /** * @return The option type converted to ::DhcpV6OptionType enum @@ -235,18 +238,21 @@ namespace pcpp * @param[in] optionType DHCPv6 option type * @param[in] optionValueAsHexStream The value as a hex stream string */ - DhcpV6OptionBuilder(DhcpV6OptionType optionType, const std::string& optionValueAsHexStream) : - TLVRecordBuilder(static_cast(optionType), optionValueAsHexStream, true) { } + DhcpV6OptionBuilder(DhcpV6OptionType optionType, const std::string& optionValueAsHexStream) + : TLVRecordBuilder(static_cast(optionType), optionValueAsHexStream, true) + {} /** - * A c'tor for building DHCPv6 options from a byte array representing their value. The DhcpV6Option object can be later - * retrieved by calling build() + * A c'tor for building DHCPv6 options from a byte array representing their value. The DhcpV6Option object can + * be later retrieved by calling build() * @param[in] optionType DHCPv6 option type - * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way. + * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in + * any way. * @param[in] optionValueLen Option value length in bytes */ - DhcpV6OptionBuilder(DhcpV6OptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) : - TLVRecordBuilder(static_cast(optionType), optionValue, optionValueLen) {} + DhcpV6OptionBuilder(DhcpV6OptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) + : TLVRecordBuilder(static_cast(optionType), optionValue, optionValueLen) + {} /** * Build the DhcpV6Option object out of the parameters defined in the c'tor @@ -278,7 +284,6 @@ namespace pcpp class DhcpV6Layer : public Layer { public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -291,7 +296,8 @@ namespace pcpp /** * A constructor that creates the layer from scratch * @param[in] messageType A DHCPv6 message type to be set - * @param[in] transactionId The transaction ID to be set. Notice the transaction ID is 3-byte long so the value shouldn't exceed 0xFFFFFF + * @param[in] transactionId The transaction ID to be set. Notice the transaction ID is 3-byte long so the value + * shouldn't exceed 0xFFFFFF */ DhcpV6Layer(DhcpV6MessageType messageType, uint32_t transactionId); @@ -340,8 +346,8 @@ namespace pcpp /** * Get a DHCPv6 option by type * @param[in] option DHCPv6 option type - * @return A DhcpV6OptionType object containing the first DHCP option data that matches this type, or logical NULL - * (DhcpV6Option#isNull() == true) if no such option found + * @return A DhcpV6OptionType object containing the first DHCP option data that matches this type, or logical + * NULL (DhcpV6Option#isNull() == true) if no such option found */ DhcpV6Option getOptionData(DhcpV6OptionType option) const; @@ -409,37 +415,49 @@ namespace pcpp /** * Does nothing for this layer (DhcpV6Layer is always last) */ - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return The size of @ref dhcpv6_header + size of options */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } private: - uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(dhcpv6_header); } - dhcpv6_header* getDhcpHeader() const { return (dhcpv6_header*)m_Data; } + uint8_t* getOptionsBasePtr() const + { + return m_Data + sizeof(dhcpv6_header); + } + dhcpv6_header* getDhcpHeader() const + { + return (dhcpv6_header*)m_Data; + } DhcpV6Option addOptionAt(const DhcpV6OptionBuilder& optionBuilder, int offset); TLVRecordReader m_OptionReader; }; - // implementation of inline methods bool DhcpV6Layer::isDhcpV6Port(uint16_t port) { return (port == 546) || (port == 547); - } bool DhcpV6Layer::isDataValid(const uint8_t* data, size_t dataLen) @@ -447,4 +465,4 @@ namespace pcpp return data && dataLen >= sizeof(dhcpv6_header); } -} +} // namespace pcpp diff --git a/Packet++/header/DnsLayer.h b/Packet++/header/DnsLayer.h index 50646d8a4f..d14e769baf 100644 --- a/Packet++/header/DnsLayer.h +++ b/Packet++/header/DnsLayer.h @@ -16,8 +16,8 @@ namespace pcpp /** * @struct dnshdr - * Represents the fixed part of the DNS header, meaning the part that doesn't include the DNS data (queries, answers, authorities - * and additional records) + * Represents the fixed part of the DNS header, meaning the part that doesn't include the DNS data (queries, + * answers, authorities and additional records) */ #pragma pack(push, 1) struct dnshdr @@ -26,48 +26,48 @@ namespace pcpp uint16_t transactionID; #if (BYTE_ORDER == LITTLE_ENDIAN) uint16_t - /** Recursion desired flag */ - recursionDesired:1, - /** Truncated flag */ - truncation:1, - /** Authoritative answer flag */ - authoritativeAnswer:1, - /** Operation Code */ - opcode:4, - /** Query/Response flag */ - queryOrResponse:1, - /** Return Code */ - responseCode:4, - /** Checking disabled flag */ - checkingDisabled:1, - /** Authenticated data flag */ - authenticData:1, - /** Zero flag (Reserved) */ - zero:1, - /** Recursion available flag */ - recursionAvailable:1; + /** Recursion desired flag */ + recursionDesired : 1, + /** Truncated flag */ + truncation : 1, + /** Authoritative answer flag */ + authoritativeAnswer : 1, + /** Operation Code */ + opcode : 4, + /** Query/Response flag */ + queryOrResponse : 1, + /** Return Code */ + responseCode : 4, + /** Checking disabled flag */ + checkingDisabled : 1, + /** Authenticated data flag */ + authenticData : 1, + /** Zero flag (Reserved) */ + zero : 1, + /** Recursion available flag */ + recursionAvailable : 1; #elif (BYTE_ORDER == BIG_ENDIAN) uint16_t - /** Query/Response flag */ - queryOrResponse:1, - /** Operation Code */ - opcode:4, - /** Authoritative answer flag */ - authoritativeAnswer:1, - /** Truncated flag */ - truncation:1, - /** Recursion desired flag */ - recursionDesired:1, - /** Recursion available flag */ - recursionAvailable:1, - /** Zero flag (Reserved) */ - zero:1, - /** Authenticated data flag */ - authenticData:1, - /** Checking disabled flag */ - checkingDisabled:1, - /** Return Code */ - responseCode:4; + /** Query/Response flag */ + queryOrResponse : 1, + /** Operation Code */ + opcode : 4, + /** Authoritative answer flag */ + authoritativeAnswer : 1, + /** Truncated flag */ + truncation : 1, + /** Recursion desired flag */ + recursionDesired : 1, + /** Recursion available flag */ + recursionAvailable : 1, + /** Zero flag (Reserved) */ + zero : 1, + /** Authenticated data flag */ + authenticData : 1, + /** Checking disabled flag */ + checkingDisabled : 1, + /** Return Code */ + responseCode : 4; #endif /** Number of DNS query records in packet */ uint16_t numberOfQuestions; @@ -80,14 +80,12 @@ namespace pcpp }; #pragma pack(pop) - // forward declarations class DnsQuery; class IDnsResource; class DnsResource; class IDnsResourceData; - /** * @class DnsLayer * Represents the DNS protocol layer @@ -99,7 +97,6 @@ namespace pcpp friend class DnsResource; public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -110,7 +107,8 @@ namespace pcpp DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /** - * A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no records + * A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no + * records */ DnsLayer(); @@ -130,15 +128,17 @@ namespace pcpp virtual ~DnsLayer(); /** - * Get a pointer to the DNS header (as opposed to the DNS data which is the queries, answers, etc. Data can be retrieved through the - * other methods of this layer. Notice the return value points directly to the data, so every change will change the actual packet data + * Get a pointer to the DNS header (as opposed to the DNS data which is the queries, answers, etc. Data can be + * retrieved through the other methods of this layer. Notice the return value points directly to the data, so + * every change will change the actual packet data * @return A pointer to the @ref dnshdr */ dnshdr* getDnsHeader() const; /** - * Searches for a DNS query by its name field. Notice this method returns only a query which its name equals to the requested name. If - * several queries match the requested name, the first one will be returned. If no queries match the requested name, NULL will be returned + * Searches for a DNS query by its name field. Notice this method returns only a query which its name equals to + * the requested name. If several queries match the requested name, the first one will be returned. If no + * queries match the requested name, NULL will be returned * @param[in] name The name of the query to search * @param[in] exactMatch Indicate whether to match the whole name or just a part of it * @return The first matching DNS query or NULL if no queries were found @@ -153,7 +153,8 @@ namespace pcpp /** * Get the DNS query following a certain query * @param[in] query A pointer to a DNS query that exist in the packet - * @return The DNS query following 'query'. If 'query' is NULL or 'query' is the last query in the packet NULL will be returned + * @return The DNS query following 'query'. If 'query' is NULL or 'query' is the last query in the packet NULL + * will be returned */ DnsQuery* getNextQuery(DnsQuery* query) const; @@ -167,16 +168,17 @@ namespace pcpp * @param[in] name The value that shall be set in the name field of the query * @param[in] dnsType The value that shall be set in the DNS type field of the query * @param[in] dnsClass The value that shall be set in the DNS class field of the query - * @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error log message will be - * printed in this case) + * @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error + * log message will be printed in this case) */ DnsQuery* addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass); /** - * Add a new DNS query similar to an already existing DNS query. All query fields will be copied from the existing query + * Add a new DNS query similar to an already existing DNS query. All query fields will be copied from the + * existing query * @param[in] copyQuery The record to create the new record from. copyQuery won't be changed in any way - * @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error log message will be - * printed in this case) + * @return A pointer to the newly created DNS query or NULL if query could not be created (an appropriate error + * log message will be printed in this case) */ DnsQuery* addQuery(DnsQuery* const copyQuery); @@ -184,20 +186,23 @@ namespace pcpp * Remove an existing query by name. If several queries matches the name, the first match will be removed * @param[in] queryNameToRemove The name of the query to remove * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if query was found and successfully removed or false if query was not found or couldn't be removed + * @return True if query was found and successfully removed or false if query was not found or couldn't be + * removed */ bool removeQuery(const std::string& queryNameToRemove, bool exactMatch); /** * Remove an existing query * @param[in] queryToRemove A pointer to the query to remove - * @return True if query was found and successfully removed or false if query was not found or couldn't be removed + * @return True if query was found and successfully removed or false if query was not found or couldn't be + * removed */ bool removeQuery(DnsQuery* queryToRemove); /** - * Searches for a DNS answer by its name field. Notice this method returns only an answer which its name equals to the requested name. If - * several answers match the requested name, the first one will be returned. If no answers match the requested name, NULL will be returned + * Searches for a DNS answer by its name field. Notice this method returns only an answer which its name equals + * to the requested name. If several answers match the requested name, the first one will be returned. If no + * answers match the requested name, NULL will be returned * @param[in] name The name of the answer to search * @param[in] exactMatch Indicate whether to match the whole name or just a part of it * @return The first matching DNS answer or NULL if no answers were found @@ -212,7 +217,8 @@ namespace pcpp /** * Get the DNS answer following a certain answer * @param[in] answer A pointer to a DNS answer that exist in the packet - * @return The DNS answer following 'answer'. If 'answer' is NULL or 'answer' is the last answer in the packet NULL will be returned + * @return The DNS answer following 'answer'. If 'answer' is NULL or 'answer' is the last answer in the packet + * NULL will be returned */ DnsResource* getNextAnswer(DnsResource* answer) const; @@ -228,18 +234,20 @@ namespace pcpp * @param[in] dnsClass The value that shall be set in the DNS class field of the answer * @param[in] ttl The value that shall be set in the 'time-to-leave' field of the answer * @param[in] data The answer data to be set. The type of the data should match the type of the DNS record - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS answer or NULL if answer could not be created (an appropriate error log message will be - * printed in this case) + * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see + * DnsResource#setData() for more info on this + * @return A pointer to the newly created DNS answer or NULL if answer could not be created (an appropriate + * error log message will be printed in this case) */ - DnsResource* addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data); + DnsResource* addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, + IDnsResourceData* data); /** - * Add a new DNS answer similar to an already existing DNS answer. All answer fields will be copied from the existing answer + * Add a new DNS answer similar to an already existing DNS answer. All answer fields will be copied from the + * existing answer * @param[in] copyAnswer The record to create the new record from. copyAnswer won't be changed in any way - * @return A pointer to the newly created DNS answer or NULL if query could not be created (an appropriate error log message will be - * printed in this case) + * @return A pointer to the newly created DNS answer or NULL if query could not be created (an appropriate error + * log message will be printed in this case) */ DnsResource* addAnswer(DnsResource* const copyAnswer); @@ -247,21 +255,23 @@ namespace pcpp * Remove an existing answer by name. If several answers matches the name, the first match will be removed * @param[in] answerNameToRemove The name of the answer to remove * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if answer was found and successfully removed or false if answer was not found or couldn't be removed + * @return True if answer was found and successfully removed or false if answer was not found or couldn't be + * removed */ bool removeAnswer(const std::string& answerNameToRemove, bool exactMatch); /** * Remove an existing answer * @param[in] answerToRemove A pointer to the answer to remove - * @return True if answer was found and successfully removed or false if answer was not found or couldn't be removed + * @return True if answer was found and successfully removed or false if answer was not found or couldn't be + * removed */ bool removeAnswer(DnsResource* answerToRemove); - /** - * Searches for a DNS authority by its name field. Notice this method returns only an authority which its name equals to the requested name. If - * several authorities match the requested name, the first one will be returned. If no authorities match the requested name, NULL will be returned + * Searches for a DNS authority by its name field. Notice this method returns only an authority which its name + * equals to the requested name. If several authorities match the requested name, the first one will be + * returned. If no authorities match the requested name, NULL will be returned * @param[in] name The name of the authority to search * @param[in] exactMatch Indicate whether to match the whole name or just a part of it * @return The first matching DNS authority or NULL if no authorities were found @@ -276,7 +286,8 @@ namespace pcpp /** * Get the DNS authority following a certain authority * @param[in] authority A pointer to a DNS authority that exist in the packet - * @return The DNS authority following 'authority'. If 'authority' is NULL or 'authority' is the last authority in the packet NULL will be returned + * @return The DNS authority following 'authority'. If 'authority' is NULL or 'authority' is the last authority + * in the packet NULL will be returned */ DnsResource* getNextAuthority(DnsResource* authority) const; @@ -292,41 +303,45 @@ namespace pcpp * @param[in] dnsClass The value that shall be set in the DNS class field of the authority * @param[in] ttl The value that shall be set in the 'time-to-leave' field of the authority * @param[in] data The authority data to be set. The type of the data should match the type of the DNS record - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS authority or NULL if authority could not be created (an appropriate error log message will be - * printed in this case) + * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see + * DnsResource#setData() for more info on this + * @return A pointer to the newly created DNS authority or NULL if authority could not be created (an + * appropriate error log message will be printed in this case) */ - DnsResource* addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data); + DnsResource* addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, + IDnsResourceData* data); /** - * Add a new DNS authority similar to an already existing DNS authority. All authority fields will be copied from the existing authority + * Add a new DNS authority similar to an already existing DNS authority. All authority fields will be copied + * from the existing authority * @param[in] copyAuthority The record to create the new record from. copyAuthority won't be changed in any way - * @return A pointer to the newly created DNS authority or NULL if query could not be created (an appropriate error log message will be - * printed in this case) + * @return A pointer to the newly created DNS authority or NULL if query could not be created (an appropriate + * error log message will be printed in this case) */ DnsResource* addAuthority(DnsResource* const copyAuthority); /** - * Remove an existing authority by name. If several authorities matches the name, the first match will be removed + * Remove an existing authority by name. If several authorities matches the name, the first match will be + * removed * @param[in] authorityNameToRemove The name of the authority to remove * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if authority was found and successfully removed or false if authority was not found or couldn't be removed + * @return True if authority was found and successfully removed or false if authority was not found or couldn't + * be removed */ bool removeAuthority(const std::string& authorityNameToRemove, bool exactMatch); /** * Remove an existing authority * @param[in] authorityToRemove A pointer to the authority to remove - * @return True if authority was found and successfully removed or false if authority was not found or couldn't be removed + * @return True if authority was found and successfully removed or false if authority was not found or couldn't + * be removed */ bool removeAuthority(DnsResource* authorityToRemove); - /** - * Searches for a DNS additional record by its name field. Notice this method returns only an additional record which its name equals to - * the requested name. If several additional records match the requested name, the first one will be returned. If no additional records - * match the requested name, NULL will be returned + * Searches for a DNS additional record by its name field. Notice this method returns only an additional record + * which its name equals to the requested name. If several additional records match the requested name, the + * first one will be returned. If no additional records match the requested name, NULL will be returned * @param[in] name The name of the additional record to search * @param[in] exactMatch Indicate whether to match the whole name or just a part of it * @return The first matching DNS additional record or NULL if no additional records were found @@ -334,15 +349,16 @@ namespace pcpp DnsResource* getAdditionalRecord(const std::string& name, bool exactMatch) const; /** - * @return The first DNS additional record in the packet or NULL if packet doesn't contain any additional records + * @return The first DNS additional record in the packet or NULL if packet doesn't contain any additional + * records */ DnsResource* getFirstAdditionalRecord() const; /** * Get the DNS additional record following a certain additional record * @param[in] additionalRecord A pointer to a DNS additional record that exist in the packet - * @return The DNS additional record following 'additionalRecord'. If 'additionalRecord' is NULL or 'additionalRecord' is the - * last additional record in the packet NULL will be returned + * @return The DNS additional record following 'additionalRecord'. If 'additionalRecord' is NULL or + * 'additionalRecord' is the last additional record in the packet NULL will be returned */ DnsResource* getNextAdditionalRecord(DnsResource* additionalRecord) const; @@ -357,50 +373,59 @@ namespace pcpp * @param[in] dnsType The value that shall be set in the DNS type field of the additional record * @param[in] dnsClass The value that shall be set in the DNS class field of the additional record * @param[in] ttl The value that shall be set in the 'time-to-leave' field of the additional record - * @param[in] data The additional record data to be set. The type of the data should match the type of the DNS record - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS additional record or NULL if additional record could not be created (an appropriate error - * log message will be printed in this case) + * @param[in] data The additional record data to be set. The type of the data should match the type of the DNS + * record (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see + * DnsResource#setData() for more info on this + * @return A pointer to the newly created DNS additional record or NULL if additional record could not be + * created (an appropriate error log message will be printed in this case) */ - DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data); + DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, + IDnsResourceData* data); /** - * Add a new DNS additional record to the layer that doesn't have DNS class and TTL. Instead these bytes may contains some arbitrary - * data. In the future I may add support for these kinds of additional data records. For now, these bytes are set as raw + * Add a new DNS additional record to the layer that doesn't have DNS class and TTL. Instead these bytes may + * contains some arbitrary data. In the future I may add support for these kinds of additional data records. For + * now, these bytes are set as raw * @param[in] name The value that shall be set in the name field of the additional record * @param[in] dnsType The value that shall be set in the DNS type field of the additional record - * @param[in] customData1 Two bytes of the arbitrary data that will be set in the offset usually used for the DNS class - * @param[in] customData2 Four bytes of the arbitrary data that will be set in the offset usually used for the TTL - * @param[in] data The additional record data to be set. The type of the data should match the type of the DNS record. - * (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see DnsResource#setData() - * for more info on this - * @return A pointer to the newly created DNS additional record or NULL if additional record could not be created (an appropriate error - * log message will be printed in this case) - */ - DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, uint32_t customData2, IDnsResourceData* data); - - /** - * Add a new DNS additional record similar to an already existing DNS additional record. All additional record fields will be copied from the - * existing additional record - * @param[in] copyAdditionalRecord The record to create the new record from. copyAdditionalRecord won't be changed in any way - * @return A pointer to the newly created DNS additional record or NULL if query could not be created (an appropriate error log message will - * be printed in this case) + * @param[in] customData1 Two bytes of the arbitrary data that will be set in the offset usually used for the + * DNS class + * @param[in] customData2 Four bytes of the arbitrary data that will be set in the offset usually used for the + * TTL + * @param[in] data The additional record data to be set. The type of the data should match the type of the DNS + * record. (for example: DNS record of type A should have data of type IPv4DnsResourceData. Please see + * DnsResource#setData() for more info on this + * @return A pointer to the newly created DNS additional record or NULL if additional record could not be + * created (an appropriate error log message will be printed in this case) + */ + DnsResource* addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, + uint32_t customData2, IDnsResourceData* data); + + /** + * Add a new DNS additional record similar to an already existing DNS additional record. All additional record + * fields will be copied from the existing additional record + * @param[in] copyAdditionalRecord The record to create the new record from. copyAdditionalRecord won't be + * changed in any way + * @return A pointer to the newly created DNS additional record or NULL if query could not be created (an + * appropriate error log message will be printed in this case) */ DnsResource* addAdditionalRecord(DnsResource* const copyAdditionalRecord); /** - * Remove an existing additional record by name. If several additional records matches the name, the first match will be removed + * Remove an existing additional record by name. If several additional records matches the name, the first match + * will be removed * @param[in] additionalRecordNameToRemove The name of the additional record to remove * @param[in] exactMatch Indicate whether to match the whole name or just a part of it - * @return True if additional record was found and successfully removed or false if additional record was not found or couldn't be removed + * @return True if additional record was found and successfully removed or false if additional record was not + * found or couldn't be removed */ bool removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch); /** * Remove an existing additional record * @param[in] additionalRecordToRemove A pointer to the additional record to remove - * @return True if additional record was found and successfully removed or false if additional record was not found or couldn't be removed + * @return True if additional record was found and successfully removed or false if additional record was not + * found or couldn't be removed */ bool removeAdditionalRecord(DnsResource* additionalRecordToRemove); @@ -409,22 +434,30 @@ namespace pcpp /** * Does nothing for this layer (DnsLayer is always last) */ - void parseNextLayer() {} + void parseNextLayer() + {} /** - * @return The size of the DNS data in the packet including he DNS header and size of all queries, answers, authorities and additional - * records + * @return The size of the DNS data in the packet including he DNS header and size of all queries, answers, + * authorities and additional records */ - size_t getHeaderLen() const { return m_DataLen; } //No layer above DNS + size_t getHeaderLen() const + { + return m_DataLen; + } // No layer above DNS /** * Does nothing for this layer */ - virtual void computeCalculateFields() {} + virtual void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } /** * A static method that checks whether the port is considered as DNS @@ -449,11 +482,11 @@ namespace pcpp private: IDnsResource* m_ResourceList; - DnsQuery* m_FirstQuery; - DnsResource* m_FirstAnswer; - DnsResource* m_FirstAuthority; - DnsResource* m_FirstAdditional; - uint16_t m_OffsetAdjustment; + DnsQuery* m_FirstQuery; + DnsResource* m_FirstAnswer; + DnsResource* m_FirstAuthority; + DnsResource* m_FirstAdditional; + uint16_t m_OffsetAdjustment; size_t getBasicHeaderSize(); void init(size_t offsetAdjustment, bool callParseResource); @@ -468,33 +501,30 @@ namespace pcpp using Layer::shortenLayer; bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource); - IDnsResource* getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, bool exactMatch) const; + IDnsResource* getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, + bool exactMatch) const; void parseResources(); DnsResource* addResource(DnsResourceType resType, const std::string& name, DnsType dnsType, DnsClass dnsClass, - uint32_t ttl, IDnsResourceData* data); + uint32_t ttl, IDnsResourceData* data); bool removeResource(IDnsResource* resourceToRemove); - }; - - /** * @class DnsOverTcpLayer * Represents the DNS over TCP layer. * DNS over TCP is described here: https://tools.ietf.org/html/rfc7766 . - * It is very similar to DNS over UDP, except for one field: TCP message length which is added in the beginning of the message - * before the other DNS data properties. The rest of the data is similar. + * It is very similar to DNS over UDP, except for one field: TCP message length which is added in the beginning of + * the message before the other DNS data properties. The rest of the data is similar. * - * Note: DNS over TCP can spread over more than one packet, but this implementation doesn't support this use-case and assumes - * the whole message fits in a single packet. + * Note: DNS over TCP can spread over more than one packet, but this implementation doesn't support this use-case + * and assumes the whole message fits in a single packet. */ class DnsOverTcpLayer : public DnsLayer { public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -503,18 +533,22 @@ namespace pcpp * @param[in] packet A pointer to the Packet instance where layer will be stored in */ DnsOverTcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : DnsLayer(data, dataLen, prevLayer, packet, sizeof(uint16_t)) {} + : DnsLayer(data, dataLen, prevLayer, packet, sizeof(uint16_t)) + {} /** - * A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no records + * A constructor that creates an empty DNS layer: all members of dnshdr are set to 0 and layer will contain no + * records */ - DnsOverTcpLayer() : DnsLayer(sizeof(uint16_t)) {} + DnsOverTcpLayer() : DnsLayer(sizeof(uint16_t)) + {} /** * A copy constructor for this layer * @param[in] other The DNS over TCP layer to copy from */ - DnsOverTcpLayer(const DnsOverTcpLayer& other) : DnsLayer(other) {} + DnsOverTcpLayer(const DnsOverTcpLayer& other) : DnsLayer(other) + {} /** * @return The value of the TCP message length as described in https://tools.ietf.org/html/rfc7766#section-8 @@ -527,7 +561,6 @@ namespace pcpp */ void setTcpMessageLength(uint16_t value); - // overridden methods /** @@ -536,7 +569,6 @@ namespace pcpp void computeCalculateFields(); }; - // implementation of inline methods bool DnsLayer::isDnsPort(uint16_t port) @@ -558,4 +590,4 @@ namespace pcpp return data && dataLen >= minSize; } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/DnsLayerEnums.h b/Packet++/header/DnsLayerEnums.h index a9fff1201b..28daad1bba 100644 --- a/Packet++/header/DnsLayerEnums.h +++ b/Packet++/header/DnsLayerEnums.h @@ -119,7 +119,6 @@ namespace pcpp DNS_TYPE_ALL = 255 }; - /** * An enum for all possible DNS classes */ @@ -137,7 +136,6 @@ namespace pcpp DNS_CLASS_ANY = 255 }; - /** * An enum for representing the 4 types of possible DNS records */ @@ -153,4 +151,4 @@ namespace pcpp DnsAdditionalType = 3 }; -} +} // namespace pcpp diff --git a/Packet++/header/DnsResource.h b/Packet++/header/DnsResource.h index 45122e4368..960e1c121c 100644 --- a/Packet++/header/DnsResource.h +++ b/Packet++/header/DnsResource.h @@ -20,11 +20,11 @@ namespace pcpp class IDnsResourceData; class DnsResourceDataPtr; - /** * @class IDnsResource - * An abstract class for representing all types of DNS records. This class gives access to all available record data such as DNS type, class, - * name, type of record, etc. The DnsLayer holds an instance of (inherited type of) this class for each DNS record in the DNS packet + * An abstract class for representing all types of DNS records. This class gives access to all available record data + * such as DNS type, class, name, type of record, etc. The DnsLayer holds an instance of (inherited type of) this + * class for each DNS record in the DNS packet */ class IDnsResource { @@ -47,16 +47,22 @@ namespace pcpp size_t decodeName(const char* encodedName, char* result, int iteration = 1); void encodeName(const std::string& decodedName, char* result, size_t& resultLen); - IDnsResource* getNextResource() const { return m_NextResource; } - void setNexResource(IDnsResource* next) { m_NextResource = next; } + IDnsResource* getNextResource() const + { + return m_NextResource; + } + void setNexResource(IDnsResource* next) + { + m_NextResource = next; + } uint8_t* getRawData() const; void setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer); public: - - virtual ~IDnsResource() {} + virtual ~IDnsResource() + {} /** * @return The DNS type of this record @@ -83,29 +89,34 @@ namespace pcpp /** * @return The name of this record */ - const std::string& getName() const { return m_DecodedName; } + const std::string& getName() const + { + return m_DecodedName; + } /** * @return The record name's offset in the packet */ - size_t getNameOffset() const { return m_OffsetInLayer; } + size_t getNameOffset() const + { + return m_OffsetInLayer; + } /** * Set the name of this record. The input name can be a standard hostname (e.g 'google.com'), or it may contain * a pointer to another string in the packet (as explained here: http://www.zytrax.com/books/dns/ch15/#name). * The pointer is used to reduce the DNS packet size and avoid unnecessary duplications. In case you - * want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where '#{offset}' - * is a the offset from the start of the layer. For example: if the string 'yahoo.com' already appears in offset - * 12 in the packet and you want to set the name of the current record to 'my.subdomain.yahoo.com' you may use - * the following string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12.
- * Please notice the new name can be shorter or longer of the old name, so this method can cause the packet to be - * shorten or extended + * want to use a pointer in your string you should use the following format: 'some.domain.#{offset}' where + * '#{offset}' is a the offset from the start of the layer. For example: if the string 'yahoo.com' already + * appears in offset 12 in the packet and you want to set the name of the current record to + * 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'. This will result in writing + * 'my.subdomain' and a pointer to offset 12.
Please notice the new name can be shorter or longer of the old + * name, so this method can cause the packet to be shorten or extended * @param[in] newName The name to set * @return True if name was set successfully or false if input string is malformed or if an error occurred */ bool setName(const std::string& newName); - // abstract methods /** @@ -119,7 +130,6 @@ namespace pcpp virtual DnsResourceType getType() const = 0; }; - /** * @class DnsQuery * Representing a DNS query record @@ -129,19 +139,27 @@ namespace pcpp friend class DnsLayer; private: - DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) {} + DnsQuery(DnsLayer* dnsLayer, size_t offsetInLayer) : IDnsResource(dnsLayer, offsetInLayer) + {} - explicit DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) {} + explicit DnsQuery(uint8_t* emptyRawData) : IDnsResource(emptyRawData) + {} public: - virtual ~DnsQuery() {} + virtual ~DnsQuery() + {} // implementation of abstract methods - virtual size_t getSize() const { return m_NameLength + 2 * sizeof(uint16_t); } - virtual DnsResourceType getType() const { return DnsQueryType; } + virtual size_t getSize() const + { + return m_NameLength + 2 * sizeof(uint16_t); + } + virtual DnsResourceType getType() const + { + return DnsQueryType; + } }; - /** * @class DnsResource * Representing DNS record other than DNS query @@ -153,12 +171,19 @@ namespace pcpp private: DnsResourceType m_ResourceType; - DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) : IDnsResource(dnsLayer, offsetInLayer) { m_ResourceType = resourceType; } + DnsResource(DnsLayer* dnsLayer, size_t offsetInLayer, DnsResourceType resourceType) + : IDnsResource(dnsLayer, offsetInLayer) + { + m_ResourceType = resourceType; + } - DnsResource(uint8_t* emptyRawData, DnsResourceType resType) : IDnsResource(emptyRawData), m_ResourceType(resType) {} + DnsResource(uint8_t* emptyRawData, DnsResourceType resType) + : IDnsResource(emptyRawData), m_ResourceType(resType) + {} public: - virtual ~DnsResource() {} + virtual ~DnsResource() + {} /** * @return The time-to-leave value for this record @@ -177,15 +202,19 @@ namespace pcpp size_t getDataLength() const; /** - * @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed that the - * smart pointer will always point to an object and never to NULL. The specific object type depends on the DNS type of this record:
- * - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains the IPv4 address
- * - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that contains the IPv6 address
- * - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the return value is - * a smart pointer to StringDnsResourceData object that contains the name
- * - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains the MX data (preference and - * mail exchange name)
- * - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte array of the data + * @return A smart pointer to an IDnsResourceData object that contains the DNS resource data. It is guaranteed + * that the smart pointer will always point to an object and never to NULL. The specific object type depends on + * the DNS type of this record:
+ * - For type A (::DNS_TYPE_A): the return value is a smart pointer to IPv4DnsResourceData object that contains + * the IPv4 address
+ * - For type AAAA (::DNS_TYPE_AAAA): the return value is a smart pointer to IPv6DnsResourceData object that + * contains the IPv6 address
+ * - For types NS, CNAME, DNAME, PTR (::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR): the + * return value is a smart pointer to StringDnsResourceData object that contains the name
+ * - For type MX (::DNS_TYPE_MX): the return value is a smart pointer to MxDnsResourceData object that contains + * the MX data (preference and mail exchange name)
+ * - For all other types: the return value is a smart pointer to GenericDnsResourceData which contains a byte + * array of the data */ DnsResourceDataPtr getData() const; @@ -195,40 +224,50 @@ namespace pcpp size_t getDataOffset() const; /** - * Set resource data. The given IDnsResourceData input object is validated against the DNS type of the resource. For example: if DNS type is A - * and data isn't of type IPv4DnsResourceData (which contains the IPv4 address) a log error will be printed and the method will return false. - * This method currently supports the following DNS types:
- * - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 address - * - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 address - * - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a pointer to StringDnsResourceData - * object that contains a host name, e.g: 'www.google.com' - * - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the MX data - * - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string (valid hex string means a string - * which has an even number of characters representing a valid hex data. e.g: '0d0a45569a9b') + * Set resource data. The given IDnsResourceData input object is validated against the DNS type of the resource. + * For example: if DNS type is A and data isn't of type IPv4DnsResourceData (which contains the IPv4 address) a + * log error will be printed and the method will return false. This method currently supports the following DNS + * types:
+ * - ::DNS_TYPE_A (IPv4 address) - data is expected to be a pointer to IPv4DnsResourceData with a valid IPv4 + * address + * - ::DNS_TYPE_AAAA (IPv6 address) - data is expected to be a pointer to IPv6DnsResourceData with a valid IPv6 + * address + * - ::DNS_TYPE_NS, ::DNS_TYPE_CNAME, ::DNS_TYPE_DNAM, ::DNS_TYPE_PTR (name data) - data is expected to be a + * pointer to StringDnsResourceData object that contains a host name, e.g: 'www.google.com' + * - ::DNS_TYPE_MX (MX data) - data is expected to be a pointer to MxDnsResourceData object that contains the MX + * data + * - else: data is expected to be a pointer to GenericDnsResourceData object that contains a valid hex string + * (valid hex string means a string which has an even number of characters representing a valid hex data. e.g: + * '0d0a45569a9b') * @param[in] data The pointer to the data object, as described above - * @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the packet (appropriate error log is - * printed in all cases) + * @return True if data was properly set or false if data is illegal or method couldn't extend or shorted the + * packet (appropriate error log is printed in all cases) */ bool setData(IDnsResourceData* data); /** - * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the - * user to receive these bytes + * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. + * This method enables the user to receive these bytes * @return The value stored in this place */ uint16_t getCustomDnsClass() const; /** - * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. This method enables the - * user to set these bytes + * Some records don't have a DNS class and the bytes used for storing the DNS class are used for other purpose. + * This method enables the user to set these bytes * @param[in] customValue The value to set */ void setCustomDnsClass(uint16_t customValue); // implementation of abstract methods - virtual size_t getSize() const { return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); } - virtual DnsResourceType getType() const { return m_ResourceType; } - + virtual size_t getSize() const + { + return m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t) + getDataLength(); + } + virtual DnsResourceType getType() const + { + return m_ResourceType; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/DnsResourceData.h b/Packet++/header/DnsResourceData.h index daad2a0cfa..12677be6c9 100644 --- a/Packet++/header/DnsResourceData.h +++ b/Packet++/header/DnsResourceData.h @@ -14,60 +14,55 @@ */ namespace pcpp { - - //Visual studio has always been stupid about returning something useful for __cplusplus - //Only recently was this fixed - and even then it requires a specific hack to the command line during build - //Its easier/more consistent to test _MSC_VER in VS - //https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017 - - #if __cplusplus > 199711L || _MSC_VER >= 1800 //Maybe this can be 1600 for VS2010 - #define PCPP_SMART_PTR(T) std::unique_ptr - #else - #define PCPP_SMART_PTR(T) std::auto_ptr - #endif - // forward declarations class IDnsResource; /** * @class IDnsResourceData - * A wrapper class for storing DNS RR (resource record) data. This is the base class which introduces several abstract - * methods for derived classes to implement for setting and retrieving the stored data. Each derived class will store - * different type of DNS RR data and implement these methods accordingly (for example: IPv4/IPv6 addresses, MX data, - * hostnames, raw byte data etc.) + * A wrapper class for storing DNS RR (resource record) data. This is the base class which introduces several + * abstract methods for derived classes to implement for setting and retrieving the stored data. Each derived class + * will store different type of DNS RR data and implement these methods accordingly (for example: IPv4/IPv6 + * addresses, MX data, hostnames, raw byte data etc.) */ class IDnsResourceData { protected: - // unimplemented private copy c'tor IDnsResourceData(const IDnsResourceData& other); - IDnsResourceData() { } + IDnsResourceData() + {} size_t decodeName(const char* encodedName, char* result, IDnsResource* dnsResource) const; - void encodeName(const std::string& decodedName, char* result, size_t& resultLen, IDnsResource* dnsResource) const; + void encodeName(const std::string& decodedName, char* result, size_t& resultLen, + IDnsResource* dnsResource) const; public: /** * A virtual d'tor, does nothing */ - virtual ~IDnsResourceData() { } + virtual ~IDnsResourceData() + {} /** * A templated method which takes a class that derives from IDnsResourceData as the template argument and * checks whether this instance is of this type * @return True if this instance is of the requested type, false otherwise */ - template - bool isTypeOf() const { return dynamic_cast(this) != NULL; } + template bool isTypeOf() const + { + return dynamic_cast(this) != NULL; + } /** - * A templated method which take a class that derives from IDnsResourceData as the template argument and tries to - * cast the current instance as that type - * @return A pointer to the current instance casted as the requested type or NULL if this instance isn't of this type + * A templated method which take a class that derives from IDnsResourceData as the template argument and tries + * to cast the current instance as that type + * @return A pointer to the current instance casted as the requested type or NULL if this instance isn't of this + * type */ - template - IDnsResourceDataType* castAs() { return dynamic_cast(this); } + template IDnsResourceDataType* castAs() + { + return dynamic_cast(this); + } /** * @return A string that represents the current DNS RR data @@ -79,57 +74,51 @@ namespace pcpp * @param[out] arr A pointer to a pre-allocated byte array where the result will be written to * @param[out] arrLength A reference to a 2-byte number where the result array length will be written to * @param[in] dnsResource A pointer to a DNS resource object where this DNS RR data will be stored - * @return True if the DNS RR data was successfully converted into a byte array and written to the given array or - * false if stored DNS RR data is invalid or if it could not be written to the given array + * @return True if the DNS RR data was successfully converted into a byte array and written to the given array + * or false if stored DNS RR data is invalid or if it could not be written to the given array */ virtual bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const = 0; }; - /** * @class DnsResourceDataPtr * A smart pointer class that holds pointers of type IDnsResourceData. This object is used in DnsResource#getData() */ - class DnsResourceDataPtr : public PCPP_SMART_PTR(IDnsResourceData) + class DnsResourceDataPtr : public std::unique_ptr { public: - /** * A c'tor to this class * @param[in] ptr A pointer to IDnsResourceData */ - explicit DnsResourceDataPtr(IDnsResourceData* ptr) : PCPP_SMART_PTR(IDnsResourceData)(ptr) {} - - //Visual studio has always been stupid about returning something useful for __cplusplus - //Only recently was this fixed - and even then it requires a specific hack to the command line during build - //Its easier/more consistent to test _MSC_VER in VS - //https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017 - -#if __cplusplus <= 199711L && _MSC_VER < 1800 //Maybe this can be 1600 for VS2010 - DnsResourceDataPtr(const DnsResourceDataPtr& other) : PCPP_SMART_PTR(IDnsResourceData)((DnsResourceDataPtr&)other) {} -#endif + explicit DnsResourceDataPtr(IDnsResourceData* ptr) : std::unique_ptr(ptr) + {} /** * A templated method which takes a class that derives from IDnsResourceData as the template argument and * checks whether the pointer stored in this object is of this type * @return True if the stored pointer is of the requested type, false otherwise */ - template - bool isTypeOf() const { return get()->isTypeOf(); } + template bool isTypeOf() const + { + return get()->isTypeOf(); + } /** - * A templated method which take a class that derives from IDnsResourceData as the template argument and tries to - * cast the pointer stored in this object as that type + * A templated method which take a class that derives from IDnsResourceData as the template argument and tries + * to cast the pointer stored in this object as that type * @return A pointer to the stored pointer casted as the requested type or NULL if it isn't of this type */ - template - IDnsResourceDataType* castAs() { return get()->castAs();} + template IDnsResourceDataType* castAs() + { + return get()->castAs(); + } }; - /** * @class StringDnsResourceData - * A class that represents DNS RR string data, mainly used in DNS RRs that store hostnames (like CNAME, DNAME, NS, etc.) + * A class that represents DNS RR string data, mainly used in DNS RRs that store hostnames (like CNAME, DNAME, NS, + * etc.) */ class StringDnsResourceData : public IDnsResourceData { @@ -137,37 +126,44 @@ namespace pcpp std::string m_Data; public: - /** * A c'tor for this class * @param[in] data The string data to store in this object. If this string represents a hostname it's possible - * to include a pointer to another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). - * These pointers are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include pointers - * in a hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is the offset from the - * start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset 12 in the packet and you want - * to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'. - * This will result in writing 'my.subdomain' and a pointer to offset 12 + * to include a pointer to another string in the DNS layer (as explained here: + * http://www.zytrax.com/books/dns/ch15/#name). These pointers are often used to reduce the DNS packet size and + * avoid unnecessary duplications. The way to include pointers in a hostname string is to use the following + * format: 'some.domain.#{offset}' where '#{offset}' is the offset from the start of the DNS layer. For example: + * if the string 'yahoo.com' already appears in offset 12 in the packet and you want to set the DNS RR data as + * 'my.subdomain.yahoo.com' you may use the following string: 'my.subdomain.#12'. This will result in writing + * 'my.subdomain' and a pointer to offset 12 */ - explicit StringDnsResourceData(const std::string& data) : m_Data(data) {} + explicit StringDnsResourceData(const std::string& data) : m_Data(data) + {} StringDnsResourceData(const uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource); - ~StringDnsResourceData() {} + ~StringDnsResourceData() + {} /** * Equality operator overload for this class that compares the strings stored in each object * @param[in] other The object to compare with * @return True if the string data is the same in both objects, false otherwise */ - bool operator==(const StringDnsResourceData& other) const { return m_Data == other.m_Data; } + bool operator==(const StringDnsResourceData& other) const + { + return m_Data == other.m_Data; + } // implement abstract methods - std::string toString() const { return m_Data; } + std::string toString() const + { + return m_Data; + } bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; }; - /** * @class IPv4DnsResourceData * A class that represents DNS RR IPv4 data, mainly used in DNS RRs of type ::DNS_TYPE_A @@ -178,7 +174,6 @@ namespace pcpp IPv4Address m_Data; public: - /** * A c'tor for this class * @param[in] dataPtr A byte array of size 4 that contains an IPv4 address (each byte represents 1 octet) @@ -190,33 +185,43 @@ namespace pcpp * A c'tor for this class * @param[in] addr The IPv4 address to store in this object */ - explicit IPv4DnsResourceData(const IPv4Address& addr) : m_Data(addr) {} + explicit IPv4DnsResourceData(const IPv4Address& addr) : m_Data(addr) + {} /** * A c'tor for this class * @param[in] addrAsString A string representation of an IPv4 address to store in this object */ - explicit IPv4DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) {} + explicit IPv4DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) + {} /** * Equality operator overload for this class that compares the IPv4 addresses stored in each object * @param[in] other The object to compare with * @return True if IPv4 addresses are the same in both objects, false otherwise */ - bool operator==(const IPv4DnsResourceData& other) const { return m_Data == other.m_Data; } + bool operator==(const IPv4DnsResourceData& other) const + { + return m_Data == other.m_Data; + } /** * @return The IPv4 address stored in this object */ - IPv4Address getIpAddress() const { return m_Data; } + IPv4Address getIpAddress() const + { + return m_Data; + } // implement abstract methods - std::string toString() const { return m_Data.toString(); } + std::string toString() const + { + return m_Data.toString(); + } bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; }; - /** * @class IPv6DnsResourceData * A class that represents DNS RR IPv6 data, mainly used in DNS RRs of type ::DNS_TYPE_AAAA @@ -227,7 +232,6 @@ namespace pcpp IPv6Address m_Data; public: - /** * A c'tor for this class * @param[in] dataPtr A byte array of size 16 that contains an IPv6 address (each byte represents 1 octet) @@ -239,33 +243,43 @@ namespace pcpp * A c'tor for this class * @param[in] addr The IPv6 address to store in this object */ - explicit IPv6DnsResourceData(const IPv6Address& addr) : m_Data(addr) {} + explicit IPv6DnsResourceData(const IPv6Address& addr) : m_Data(addr) + {} /** * A c'tor for this class * @param[in] addrAsString A string representation of an IPv6 address to store in this object */ - explicit IPv6DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) {} + explicit IPv6DnsResourceData(const std::string& addrAsString) : m_Data(addrAsString) + {} /** * Equality operator overload for this class that compares the IPv6 addresses stored in each object * @param[in] other The object to compare with * @return True if IPv6 addresses are the same in both objects, false otherwise */ - bool operator==(const IPv6DnsResourceData& other) const { return m_Data == other.m_Data; } + bool operator==(const IPv6DnsResourceData& other) const + { + return m_Data == other.m_Data; + } /** * @return The IPv6 address stored in this object */ - IPv6Address getIpAddress() const { return m_Data; } + IPv6Address getIpAddress() const + { + return m_Data; + } // implement abstract methods - std::string toString() const { return m_Data.toString(); } + std::string toString() const + { + return m_Data.toString(); + } bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; }; - /** * @class MxDnsResourceData * A class that represents DNS RR mail exchange (MX) data, used in DNS RRs of type ::DNS_TYPE_MX @@ -273,7 +287,6 @@ namespace pcpp class MxDnsResourceData : public IDnsResourceData { public: - /** * A struct that represents mail exchange (MX) data */ @@ -297,16 +310,17 @@ namespace pcpp * A c'tor for this class * @param[in] preference The MX preference value to store in this object * @param[in] mailExchange The MX hostname value to store in this object. It's possible to include a pointer to - * another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). These pointers - * are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include pointers - * in the hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is the offset - * from the start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset 12 in the - * packet and you want to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following string: - * 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12 + * another string in the DNS layer (as explained here: http://www.zytrax.com/books/dns/ch15/#name). These + * pointers are often used to reduce the DNS packet size and avoid unnecessary duplications. The way to include + * pointers in the hostname string is to use the following format: 'some.domain.#{offset}' where '#{offset}' is + * the offset from the start of the DNS layer. For example: if the string 'yahoo.com' already appears in offset + * 12 in the packet and you want to set the DNS RR data as 'my.subdomain.yahoo.com' you may use the following + * string: 'my.subdomain.#12'. This will result in writing 'my.subdomain' and a pointer to offset 12 */ MxDnsResourceData(const uint16_t& preference, const std::string& mailExchange); - ~MxDnsResourceData() {} + ~MxDnsResourceData() + {} /** * Equality operator overload for this class that compares the MX data stored in each object @@ -319,7 +333,10 @@ namespace pcpp /** * @return The MX data stored in this object */ - MxData getMxData() const { return m_Data; } + MxData getMxData() const + { + return m_Data; + } /** * Set the MX data stored in this object @@ -342,11 +359,10 @@ namespace pcpp MxData m_Data; }; - /** * @class GenericDnsResourceData - * A class that represents generic DNS RR data which cannot be represented in any of the other classes. It stores the - * DNS RR data as byte array + * A class that represents generic DNS RR data which cannot be represented in any of the other classes. It stores + * the DNS RR data as byte array */ class GenericDnsResourceData : public IDnsResourceData { @@ -355,11 +371,10 @@ namespace pcpp size_t m_DataLen; public: - /** * A c'tor for this class - * @param[in] dataPtr A byte array that contains the raw data (as it written in the DNS packet). The data will be - * copied from this byte array to the object + * @param[in] dataPtr A byte array that contains the raw data (as it written in the DNS packet). The data will + * be copied from this byte array to the object * @param[in] dataLen The byte array size */ GenericDnsResourceData(const uint8_t* dataPtr, size_t dataLen); @@ -376,7 +391,11 @@ namespace pcpp */ GenericDnsResourceData(const GenericDnsResourceData& other); - ~GenericDnsResourceData() { if (m_Data != NULL) delete [] m_Data; } + ~GenericDnsResourceData() + { + if (m_Data != NULL) + delete[] m_Data; + } GenericDnsResourceData& operator=(const GenericDnsResourceData& other); @@ -393,4 +412,4 @@ namespace pcpp bool toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const; }; -} +} // namespace pcpp diff --git a/Packet++/header/EthDot3Layer.h b/Packet++/header/EthDot3Layer.h index 7952055b39..2a355bd551 100644 --- a/Packet++/header/EthDot3Layer.h +++ b/Packet++/header/EthDot3Layer.h @@ -35,14 +35,16 @@ namespace pcpp class EthDot3Layer : public Layer { public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data (will be casted to ether_dot3_header) * @param[in] dataLen Size of the data in bytes * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - EthDot3Layer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = EthernetDot3; } + EthDot3Layer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) + { + m_Protocol = EthernetDot3; + } /** * A constructor that creates the layer from an existing packet raw data @@ -51,7 +53,11 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - EthDot3Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = EthernetDot3; } + EthDot3Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = EthernetDot3; + } /** * A constructor that creates a new IEEE 802.3 Ethernet header and allocates the data @@ -61,37 +67,54 @@ namespace pcpp */ EthDot3Layer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t length); - ~EthDot3Layer() {} + ~EthDot3Layer() + {} /** - * Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change + * the actual packet data * @return A pointer to the ether_header */ - ether_dot3_header* getEthHeader() const { return (ether_dot3_header*)m_Data; } + ether_dot3_header* getEthHeader() const + { + return (ether_dot3_header*)m_Data; + } /** * Get the source MAC address * @return The source MAC address */ - MacAddress getSourceMac() const { return MacAddress(getEthHeader()->srcMac); } + MacAddress getSourceMac() const + { + return MacAddress(getEthHeader()->srcMac); + } /** * Set source MAC address * @param sourceMac Source MAC to set */ - void setSourceMac(const MacAddress& sourceMac) { sourceMac.copyTo(getEthHeader()->srcMac); } + void setSourceMac(const MacAddress& sourceMac) + { + sourceMac.copyTo(getEthHeader()->srcMac); + } /** * Get the destination MAC address * @return The destination MAC address */ - MacAddress getDestMac() const { return MacAddress(getEthHeader()->dstMac); } + MacAddress getDestMac() const + { + return MacAddress(getEthHeader()->dstMac); + } /** * Set destination MAC address * @param destMac Destination MAC to set */ - void setDestMac(const MacAddress& destMac) { destMac.copyTo(getEthHeader()->dstMac); } + void setDestMac(const MacAddress& destMac) + { + destMac.copyTo(getEthHeader()->dstMac); + } // implement abstract methods @@ -103,16 +126,23 @@ namespace pcpp /** * @return Size of ether_dot3_header */ - size_t getHeaderLen() const { return sizeof(ether_dot3_header); } + size_t getHeaderLen() const + { + return sizeof(ether_dot3_header); + } /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } /** * A static method that validates the input data @@ -123,4 +153,4 @@ namespace pcpp static bool isDataValid(const uint8_t* data, size_t dataLen); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/EthLayer.h b/Packet++/header/EthLayer.h index d585587346..0cc30760f8 100644 --- a/Packet++/header/EthLayer.h +++ b/Packet++/header/EthLayer.h @@ -31,40 +31,39 @@ namespace pcpp /* Ethernet protocol ID's */ /** IP */ -#define PCPP_ETHERTYPE_IP 0x0800 +#define PCPP_ETHERTYPE_IP 0x0800 /** Address resolution */ -#define PCPP_ETHERTYPE_ARP 0x0806 +#define PCPP_ETHERTYPE_ARP 0x0806 /** Transparent Ethernet Bridging */ -#define PCPP_ETHERTYPE_ETHBRIDGE 0x6558 +#define PCPP_ETHERTYPE_ETHBRIDGE 0x6558 /** Reverse ARP */ -#define PCPP_ETHERTYPE_REVARP 0x8035 +#define PCPP_ETHERTYPE_REVARP 0x8035 /** AppleTalk protocol */ -#define PCPP_ETHERTYPE_AT 0x809B +#define PCPP_ETHERTYPE_AT 0x809B /** AppleTalk ARP */ -#define PCPP_ETHERTYPE_AARP 0x80F3 +#define PCPP_ETHERTYPE_AARP 0x80F3 /** IEEE 802.1Q VLAN tagging */ -#define PCPP_ETHERTYPE_VLAN 0x8100 +#define PCPP_ETHERTYPE_VLAN 0x8100 /** IPX */ -#define PCPP_ETHERTYPE_IPX 0x8137 +#define PCPP_ETHERTYPE_IPX 0x8137 /** IP protocol version 6 */ -#define PCPP_ETHERTYPE_IPV6 0x86dd +#define PCPP_ETHERTYPE_IPV6 0x86dd /** used to test interfaces */ -#define PCPP_ETHERTYPE_LOOPBACK 0x9000 +#define PCPP_ETHERTYPE_LOOPBACK 0x9000 /** PPPoE discovery */ -#define PCPP_ETHERTYPE_PPPOED 0x8863 +#define PCPP_ETHERTYPE_PPPOED 0x8863 /** PPPoE session */ -#define PCPP_ETHERTYPE_PPPOES 0x8864 +#define PCPP_ETHERTYPE_PPPOES 0x8864 /** MPLS */ -#define PCPP_ETHERTYPE_MPLS 0x8847 +#define PCPP_ETHERTYPE_MPLS 0x8847 /** Point-to-point protocol (PPP) */ -#define PCPP_ETHERTYPE_PPP 0x880B +#define PCPP_ETHERTYPE_PPP 0x880B /** RDMA over Converged Ethernet (RoCEv1) */ -#define PCPP_ETHERTYPE_ROCEV1 0x8915 +#define PCPP_ETHERTYPE_ROCEV1 0x8915 /** IEEE 802.1ad Provider Bridge, Q-in-Q */ -#define PCPP_ETHERTYPE_IEEE_802_1AD 0x88A8 +#define PCPP_ETHERTYPE_IEEE_802_1AD 0x88A8 /** Wake on LAN */ -#define PCPP_ETHERTYPE_WAKE_ON_LAN 0x0842 - +#define PCPP_ETHERTYPE_WAKE_ON_LAN 0x0842 /** * @class EthLayer @@ -79,7 +78,10 @@ namespace pcpp * @param[in] dataLen Size of the data in bytes * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - EthLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = Ethernet; } + EthLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) + { + m_Protocol = Ethernet; + } /** * A constructor that creates the layer from an existing packet raw data @@ -88,61 +90,85 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - EthLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = Ethernet; } + EthLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = Ethernet; + } /** * A constructor that creates a new Ethernet header and allocates the data * @param[in] sourceMac The source MAC address * @param[in] destMac The destination MAC address - * @param[in] etherType The EtherType to be used. It's an optional parameter, a value of 0 will be set if not provided + * @param[in] etherType The EtherType to be used. It's an optional parameter, a value of 0 will be set if not + * provided */ EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType = 0); - ~EthLayer() {} + ~EthLayer() + {} /** - * Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the Ethernet header. Notice this points directly to the data, so every change will change + * the actual packet data * @return A pointer to the ether_header */ - inline ether_header* getEthHeader() const { return (ether_header*)m_Data; } + inline ether_header* getEthHeader() const + { + return (ether_header*)m_Data; + } /** * Get the source MAC address * @return The source MAC address */ - inline MacAddress getSourceMac() const { return MacAddress(getEthHeader()->srcMac); } + inline MacAddress getSourceMac() const + { + return MacAddress(getEthHeader()->srcMac); + } /** * Set source MAC address * @param sourceMac Source MAC to set */ - inline void setSourceMac(const MacAddress& sourceMac) { sourceMac.copyTo(getEthHeader()->srcMac); } + inline void setSourceMac(const MacAddress& sourceMac) + { + sourceMac.copyTo(getEthHeader()->srcMac); + } /** * Get the destination MAC address * @return The destination MAC address */ - inline MacAddress getDestMac() const { return MacAddress(getEthHeader()->dstMac); } + inline MacAddress getDestMac() const + { + return MacAddress(getEthHeader()->dstMac); + } /** * Set destination MAC address * @param destMac Destination MAC to set */ - inline void setDestMac(const MacAddress& destMac) { destMac.copyTo(getEthHeader()->dstMac); } + inline void setDestMac(const MacAddress& destMac) + { + destMac.copyTo(getEthHeader()->dstMac); + } // implement abstract methods /** - * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer, - * MplsLayer. - * Otherwise sets PayloadLayer + * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, + * PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer */ void parseNextLayer(); /** * @return Size of ether_header */ - size_t getHeaderLen() const { return sizeof(ether_header); } + size_t getHeaderLen() const + { + return sizeof(ether_header); + } /** * Calculate ether_header#etherType for known protocols: IPv4, IPv6, ARP, VLAN @@ -151,7 +177,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } /** * A static method that validates the input data @@ -162,4 +191,4 @@ namespace pcpp static bool isDataValid(const uint8_t* data, size_t dataLen); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/FtpLayer.h b/Packet++/header/FtpLayer.h index 3bb2fbfdc0..2bd5523cba 100644 --- a/Packet++/header/FtpLayer.h +++ b/Packet++/header/FtpLayer.h @@ -18,41 +18,60 @@ namespace pcpp class FtpLayer : public SingleCommandTextProtocol { protected: - FtpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : SingleCommandTextProtocol(data, dataLen, prevLayer, packet) { m_Protocol = FTP; }; - FtpLayer(const std::string &command, const std::string &option) : SingleCommandTextProtocol(command, option) { m_Protocol = FTP; }; + FtpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SingleCommandTextProtocol(data, dataLen, prevLayer, packet) + { + m_Protocol = FTP; + }; + FtpLayer(const std::string& command, const std::string& option) : SingleCommandTextProtocol(command, option) + { + m_Protocol = FTP; + }; public: - /** * A static method that checks whether the port is considered as FTP control * @param[in] port The port number to be checked */ - static bool isFtpPort(uint16_t port) { return port == 21; } + static bool isFtpPort(uint16_t port) + { + return port == 21; + } /** * A static method that checks whether the port is considered as FTP data * @param[in] port The port number to be checked */ - static bool isFtpDataPort(uint16_t port) { return port == 20; } + static bool isFtpDataPort(uint16_t port) + { + return port == 20; + } // overridden methods /// FTP is the always last so does nothing for this layer - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return Get the size of the layer */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /// Does nothing for this layer - void computeCalculateFields() {} + void computeCalculateFields() + {} /** * @return The OSI layer level of FTP (Application Layer). */ - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } - + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } }; /** @@ -61,7 +80,6 @@ namespace pcpp class FtpRequestLayer : public FtpLayer { public: - /** * Enum for FTP command codes */ @@ -92,13 +110,13 @@ namespace pcpp /// Client / Server Identification CSID = ('C') | ('S' << 8) | ('I' << 16) | ('D' << 24), /// Change working directory. - CWD = ('C') | ('W' << 8) | ('D' << 16), + CWD = ('C') | ('W' << 8) | ('D' << 16), /// Delete file. DELE = ('D') | ('E' << 8) | ('L' << 16) | ('E' << 24), /// Get the directory size DSIZ = ('D') | ('S' << 8) | ('I' << 16) | ('Z' << 24), /// Privacy Protected Channel - ENC = ('E') | ('N' << 8) | ('C' << 16), + ENC = ('E') | ('N' << 8) | ('C' << 16), /// Specifies an extended address and port to which the server should connect. EPRT = ('E') | ('P' << 8) | ('R' << 16) | ('T' << 24), /// Enter extended passive mode. @@ -111,7 +129,8 @@ namespace pcpp HOST = ('H') | ('O' << 8) | ('S' << 16) | ('T' << 24), /// Language Negotiation LANG = ('L') | ('A' << 8) | ('N' << 16) | ('G' << 24), - /// Returns information of a file or directory if specified, else information of the current working directory is returned. + /// Returns information of a file or directory if specified, else information of the current working + /// directory is returned. LIST = ('L') | ('I' << 8) | ('S' << 16) | ('T' << 24), /// Specifies a long address and port to which the server should connect. LPRT = ('L') | ('P' << 8) | ('R' << 16) | ('T' << 24), @@ -122,16 +141,17 @@ namespace pcpp /// Modify the creation time of a file. MFCT = ('M') | ('F' << 8) | ('C' << 16) | ('T' << 24), /// Modify fact (the last modification time, creation time, UNIX group/owner/mode of a file). - MFF = ('M') | ('F' << 8) | ('F' << 16), + MFF = ('M') | ('F' << 8) | ('F' << 16), /// Modify the last modification time of a file. MFMT = ('M') | ('F' << 8) | ('M' << 16) | ('T' << 24), /// Integrity Protected Command - MIC = ('M') | ('I' << 8) | ('C' << 16), + MIC = ('M') | ('I' << 8) | ('C' << 16), /// Make directory. - MKD = ('M') | ('K' << 8) | ('D' << 16), + MKD = ('M') | ('K' << 8) | ('D' << 16), /// Lists the contents of a directory in a standardized machine-readable format. MLSD = ('M') | ('L' << 8) | ('S' << 16) | ('D' << 24), - /// Provides data about exactly the object named on its command line in a standardized machine-readable format. + /// Provides data about exactly the object named on its command line in a standardized machine-readable + /// format. MLST = ('M') | ('L' << 8) | ('S' << 16) | ('T' << 24), /// Sets the transfer mode (Stream, Block, or Compressed). MODE = ('M') | ('O' << 8) | ('D' << 16) | ('E' << 24), @@ -152,7 +172,7 @@ namespace pcpp /// Data Channel Protection Level. PROT = ('P') | ('R' << 8) | ('O' << 16) | ('T' << 24), /// Print working directory. Returns the current directory of the host. - PWD = ('P') | ('W' << 8) | ('D' << 16), + PWD = ('P') | ('W' << 8) | ('D' << 16), /// Disconnect. QUIT = ('Q') | ('U' << 8) | ('I' << 16) | ('T' << 24), /// Re initializes the connection. @@ -162,20 +182,22 @@ namespace pcpp /// Retrieve a copy of the file RETR = ('R') | ('E' << 8) | ('T' << 16) | ('R' << 24), /// Remove a directory. - RMD = ('R') | ('M' << 8) | ('D' << 16), + RMD = ('R') | ('M' << 8) | ('D' << 16), /// Remove a directory tree RMDA = ('R') | ('M' << 8) | ('D' << 16) | ('A' << 24), /// Rename from. RNFR = ('R') | ('N' << 8) | ('F' << 16) | ('R' << 24), /// Rename to. RNTO = ('R') | ('N' << 8) | ('T' << 16) | ('O' << 24), - /// Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE HELP output for complete list of supported commands. + /// Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE HELP + /// output for complete list of supported commands. SITE = ('S') | ('I' << 8) | ('T' << 16) | ('E' << 24), /// Return the size of a file. SIZE = ('S') | ('I' << 8) | ('Z' << 16) | ('E' << 24), /// Mount file structure. SMNT = ('S') | ('M' << 8) | ('N' << 16) | ('T' << 24), - /// Use single port passive mode (only one TCP port number for both control connections and passive-mode data connections) + /// Use single port passive mode (only one TCP port number for both control connections and passive-mode + /// data connections) SPSV = ('S') | ('P' << 8) | ('S' << 16) | ('V' << 24), /// Returns information on the server status, including the status of the current connection STAT = ('S') | ('T' << 8) | ('A' << 16) | ('T' << 24), @@ -217,14 +239,16 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - FtpRequestLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : FtpLayer(data, dataLen, prevLayer, packet) {}; + FtpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : FtpLayer(data, dataLen, prevLayer, packet) {}; /** * A constructor that creates layer with provided input values * @param[in] command FTP command * @param[in] option Argument of the command */ - explicit FtpRequestLayer(const FtpCommand &command, const std::string &option = "") : FtpLayer(getCommandAsString(command), option) {}; + explicit FtpRequestLayer(const FtpCommand& command, const std::string& option = "") + : FtpLayer(getCommandAsString(command), option) {}; /** * Set the command of request message @@ -250,7 +274,7 @@ namespace pcpp * @param[in] value Value to set command argument * @return True if the operation is successful, false otherwise */ - bool setCommandOption(const std::string &value); + bool setCommandOption(const std::string& value); /** * Get the command argument of request message @@ -287,7 +311,6 @@ namespace pcpp class FtpResponseLayer : public FtpLayer { public: - /** * Enum for FTP response codes */ @@ -415,14 +438,16 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - FtpResponseLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : FtpLayer(data, dataLen, prevLayer, packet) {}; + FtpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : FtpLayer(data, dataLen, prevLayer, packet) {}; /** * A constructor that creates layer with provided input values * @param[in] code Status code * @param[in] option Argument of the status code */ - explicit FtpResponseLayer(const FtpStatusCode &code, const std::string &option = "") : FtpLayer(std::to_string(int(code)), option) {}; + explicit FtpResponseLayer(const FtpStatusCode& code, const std::string& option = "") + : FtpLayer(std::to_string(int(code)), option) {}; /** * Set the status code of response message @@ -448,7 +473,7 @@ namespace pcpp * @param[in] value Value to set argument * @return True if the operation is successful, false otherwise */ - bool setStatusOption(const std::string &value); + bool setStatusOption(const std::string& value); /** * Get the argument of response message @@ -478,18 +503,21 @@ namespace pcpp class FtpDataLayer : public PayloadLayer { public: - /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - FtpDataLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : PayloadLayer(data, dataLen, prevLayer, packet) { m_Protocol = FTP; }; + FtpDataLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : PayloadLayer(data, dataLen, prevLayer, packet) + { + m_Protocol = FTP; + }; /** * @return Returns the protocol info as readable string */ std::string toString() const; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/GreLayer.h b/Packet++/header/GreLayer.h index 5d1c9544e2..e5aaabaff1 100644 --- a/Packet++/header/GreLayer.h +++ b/Packet++/header/GreLayer.h @@ -4,7 +4,6 @@ /// @file - /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib @@ -21,45 +20,45 @@ namespace pcpp { #if (BYTE_ORDER == LITTLE_ENDIAN) /** Number of additional encapsulations which are permitted. 0 is the default value */ - uint8_t recursionControl:3, - /** Strict source routing bit (GRE v0 only) */ - strictSourceRouteBit:1, - /** Set if sequence number exists */ - sequenceNumBit:1, - /** Set if key exists */ - keyBit:1, - /** Set if routing exists (GRE v0 only) */ - routingBit:1, - /** Set if checksum exists (GRE v0 only) */ - checksumBit:1; + uint8_t recursionControl : 3, + /** Strict source routing bit (GRE v0 only) */ + strictSourceRouteBit : 1, + /** Set if sequence number exists */ + sequenceNumBit : 1, + /** Set if key exists */ + keyBit : 1, + /** Set if routing exists (GRE v0 only) */ + routingBit : 1, + /** Set if checksum exists (GRE v0 only) */ + checksumBit : 1; #else /** Set if checksum exists (GRE v0 only) */ - uint8_t checksumBit:1, - /** Set if routing exists (GRE v0 only) */ - routingBit:1, - /** Set if key exists */ - keyBit:1, - /** Set if sequence number exists */ - sequenceNumBit:1, - /** Strict source routing bit (GRE v0 only) */ - strictSourceRouteBit:1, - /** Number of additional encapsulations which are permitted. 0 is the default value */ - recursionControl:3; + uint8_t checksumBit : 1, + /** Set if routing exists (GRE v0 only) */ + routingBit : 1, + /** Set if key exists */ + keyBit : 1, + /** Set if sequence number exists */ + sequenceNumBit : 1, + /** Strict source routing bit (GRE v0 only) */ + strictSourceRouteBit : 1, + /** Number of additional encapsulations which are permitted. 0 is the default value */ + recursionControl : 3; #endif #if (BYTE_ORDER == LITTLE_ENDIAN) /** GRE version - can be 0 or 1 */ - uint8_t version:3, - /** Reserved */ - flags:4, - /** Set if acknowledgment number is set (GRE v1 only) */ - ackSequenceNumBit:1; + uint8_t version : 3, + /** Reserved */ + flags : 4, + /** Set if acknowledgment number is set (GRE v1 only) */ + ackSequenceNumBit : 1; #else /** Set if acknowledgment number is set (GRE v1 only) */ - uint8_t ackSequenceNumBit:1, - /** Reserved */ - flags:4, - /** GRE version - can be 0 or 1 */ - version:3; + uint8_t ackSequenceNumBit : 1, + /** Reserved */ + flags : 4, + /** GRE version - can be 0 or 1 */ + version : 3; #endif /** Protocol type of the next layer */ @@ -67,7 +66,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @struct gre1_header * Represents GREv1 protocol header @@ -82,7 +80,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @struct ppp_pptp_header * Represents PPP layer that comes after GREv1 as part of PPTP protocol @@ -99,20 +96,20 @@ namespace pcpp }; #pragma pack(pop) - /** * @class GreLayer - * Abstract base class for GRE layers (GREv0Layer and GREv1Layer). Cannot be instantiated and contains common logic for derived classes + * Abstract base class for GRE layers (GREv0Layer and GREv1Layer). Cannot be instantiated and contains common logic + * for derived classes */ class GreLayer : public Layer { public: - - virtual ~GreLayer() {} + virtual ~GreLayer() + {} /** - * A static method that determines the GRE version of GRE layer raw data by looking at the gre_basic_header#version - * field + * A static method that determines the GRE version of GRE layer raw data by looking at the + * gre_basic_header#version field * @param[in] greData GRE layer raw data * @param[in] greDataLen Size of raw data * @return ::GREv0 or ::GREv1 values if raw data is GREv0 or GREv1 (accordingly) or ::UnknownProtocol otherwise @@ -129,8 +126,8 @@ namespace pcpp /** * Set sequence number value. If field already exists (gre_basic_header#sequenceNumBit is set) then only the new - * value is set. If field doesn't exist it will be added to the layer, gre_basic_header#sequenceNumBit will be set - * and the new value will be set + * value is set. If field doesn't exist it will be added to the layer, gre_basic_header#sequenceNumBit will be + * set and the new value will be set * @param[in] seqNumber The sequence number value to set * @return True if managed to set the value successfully, or false otherwise (if couldn't extend the layer) */ @@ -138,12 +135,11 @@ namespace pcpp /** * Unset sequence number and remove it from the layer - * @return True if managed to unset successfully or false (and error log) if sequence number wasn't set in the first - * place or if didn't manage to remove it from the layer + * @return True if managed to unset successfully or false (and error log) if sequence number wasn't set in the + * first place or if didn't manage to remove it from the layer */ bool unsetSequenceNumber(); - // implement abstract methods /** @@ -158,12 +154,18 @@ namespace pcpp */ size_t getHeaderLen() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } protected: - GreLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { } + GreLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + {} - GreLayer() {} + GreLayer() + {} enum GreField { @@ -178,73 +180,81 @@ namespace pcpp void computeCalculateFieldsInner(); }; - /** * @class GREv0Layer - * Represents a GRE version 0 protocol. Limitation: currently this layer doesn't support GRE routing information parsing - * and editing. So if a GREv0 packet includes routing information it won't be parse correctly. I didn't add it because - * of lack of time, but if you need it please tell me and I'll add it + * Represents a GRE version 0 protocol. Limitation: currently this layer doesn't support GRE routing information + * parsing and editing. So if a GREv0 packet includes routing information it won't be parse correctly. I didn't add + * it because of lack of time, but if you need it please tell me and I'll add it */ class GREv0Layer : public GreLayer { public: - - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - GREv0Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : GreLayer(data, dataLen, prevLayer, packet) { m_Protocol = GREv0; } + GREv0Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : GreLayer(data, dataLen, prevLayer, packet) + { + m_Protocol = GREv0; + } /** * A constructor that creates a new GREv0 header and allocates the data */ GREv0Layer(); - virtual ~GREv0Layer() {} + virtual ~GREv0Layer() + {} /** - * Get a pointer to the basic GRE header containing only non-optional fields. Notice this points directly to the data, - * so every change will change the actual packet data. Also please notice that changing the set bits - * (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit, gre_basic_header#routingBit, - * gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using the proper set or unset methods (such - * as setChecksum(), unsetChecksum(), etc.) may result to wrong calculation of header length and really weird bugs. - * Please avoid doing so + * Get a pointer to the basic GRE header containing only non-optional fields. Notice this points directly to the + * data, so every change will change the actual packet data. Also please notice that changing the set bits + * (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit, + * gre_basic_header#routingBit, gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using + * the proper set or unset methods (such as setChecksum(), unsetChecksum(), etc.) may result to wrong + * calculation of header length and really weird bugs. Please avoid doing so * @return A pointer to the gre_basic_header */ - gre_basic_header* getGreHeader() const { return (gre_basic_header*)m_Data; } + gre_basic_header* getGreHeader() const + { + return (gre_basic_header*)m_Data; + } /** * Get checksum value if field exists in layer * @param[out] checksum The returned checksum value if exists in layer. Else remain unchanged - * @return True if checksum field exists in layer. In this case checksum parameter will be filled with the value. - * Or false if checksum field doesn't exist in layer + * @return True if checksum field exists in layer. In this case checksum parameter will be filled with the + * value. Or false if checksum field doesn't exist in layer */ bool getChecksum(uint16_t& checksum); /** - * Set checksum value. If checksum or offset fields already exist (gre_basic_header#checksumBit or gre_basic_header#routingBit are set) - * then only the new value is set. If both fields don't exist a new 4-byte value will be added to the layer, - * gre_basic_header#checksumBit will be set (gre_basic_header#routingBit will remain unset), the new checksum value - * will be set and offset value will be set to 0. The reason both fields are added is that GREv0 protocol states - * both of them or none of them should exist on packet (even if only one of the bits are set) + * Set checksum value. If checksum or offset fields already exist (gre_basic_header#checksumBit or + * gre_basic_header#routingBit are set) then only the new value is set. If both fields don't exist a new 4-byte + * value will be added to the layer, gre_basic_header#checksumBit will be set (gre_basic_header#routingBit will + * remain unset), the new checksum value will be set and offset value will be set to 0. The reason both fields + * are added is that GREv0 protocol states both of them or none of them should exist on packet (even if only one + * of the bits are set) * @param[in] checksum The checksum value to set * @return True if managed to set the value/s successfully, or false otherwise (if couldn't extend the layer) */ bool setChecksum(uint16_t checksum); /** - * Unset checksum and possibly remove it from the layer. It will be removed from the layer only if gre_basic_header#routingBit - * is not set as well. Otherwise checksum field will remain on packet with value of 0 + * Unset checksum and possibly remove it from the layer. It will be removed from the layer only if + * gre_basic_header#routingBit is not set as well. Otherwise checksum field will remain on packet with value of + * 0 * @return True if managed to unset successfully or false (and error log) if checksum wasn't set in the first * place or if didn't manage to remove it from the layer */ bool unsetChecksum(); /** - * Get offset value if field exists in layer. Notice there is no setOffset() method as GRE routing information isn't - * supported yet (see comment on class description) + * Get offset value if field exists in layer. Notice there is no setOffset() method as GRE routing information + * isn't supported yet (see comment on class description) * @param[out] offset The returned offset value if exists in layer. Else remain unchanged * @return True if offset field exists in layer. In this case offset parameter will be filled with the value. * Or false if offset field doesn't exist in layer @@ -288,7 +298,6 @@ namespace pcpp // implement abstract methods - /** * Calculate the following fields: * - gre_basic_header#protocol @@ -297,10 +306,8 @@ namespace pcpp void computeCalculateFields(); std::string toString() const; - }; - /** * @class GREv1Layer * Represents a GRE version 1 protocol @@ -308,14 +315,17 @@ namespace pcpp class GREv1Layer : public GreLayer { public: - - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - GREv1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : GreLayer(data, dataLen, prevLayer, packet) { m_Protocol = GREv1; } + GREv1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : GreLayer(data, dataLen, prevLayer, packet) + { + m_Protocol = GREv1; + } /** * A constructor that creates a new GREv1 header and allocates the data @@ -323,17 +333,23 @@ namespace pcpp */ explicit GREv1Layer(uint16_t callID); - virtual ~GREv1Layer() {} + virtual ~GREv1Layer() + {} /** - * Get a pointer to the basic GREv1 header containing all non-optional fields. Notice this points directly to the data, so every change will change the actual - * packet data. Also please notice that changing the set bits (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit, - * gre_basic_header#routingBit, gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using the proper set or unset methods - * (such as setAcknowledgmentNum(), unsetSequenceNumber(), etc.) may result to wrong calculation of header length or illegal GREv1 packet and - * to some really weird bugs. Please avoid doing so + * Get a pointer to the basic GREv1 header containing all non-optional fields. Notice this points directly to + * the data, so every change will change the actual packet data. Also please notice that changing the set bits + * (gre_basic_header#strictSourceRouteBit, gre_basic_header#sequenceNumBit, gre_basic_header#keyBit, + * gre_basic_header#routingBit, gre_basic_header#checksumBit, gre_basic_header#ackSequenceNumBit) without using + * the proper set or unset methods (such as setAcknowledgmentNum(), unsetSequenceNumber(), etc.) may result to + * wrong calculation of header length or illegal GREv1 packet and to some really weird bugs. Please avoid doing + * so * @return A pointer to the gre1_header */ - gre1_header* getGreHeader() const { return (gre1_header*)m_Data; } + gre1_header* getGreHeader() const + { + return (gre1_header*)m_Data; + } /** * Get acknowledgment (ack) number value if field exists in layer @@ -380,13 +396,12 @@ namespace pcpp void computeCalculateFields(); std::string toString() const; - }; - /** * @class PPP_PPTPLayer - * Represent a PPP (point-to-point) protocol header that comes after GREv1 header, as part of PPTP - Point-to-Point Tunneling Protocol + * Represent a PPP (point-to-point) protocol header that comes after GREv1 header, as part of PPTP - Point-to-Point + * Tunneling Protocol */ class PPP_PPTPLayer : public Layer { @@ -398,7 +413,11 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - PPP_PPTPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = PPP_PPTP; } + PPP_PPTPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = PPP_PPTP; + } /** * A constructor that allocates a new PPP-PPTP header @@ -407,14 +426,18 @@ namespace pcpp */ PPP_PPTPLayer(uint8_t address, uint8_t control); - ~PPP_PPTPLayer() {} + ~PPP_PPTPLayer() + {} /** - * Get a pointer to the PPP-PPTP header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the PPP-PPTP header. Notice this points directly to the data, so every change will change + * the actual packet data * @return A pointer to the @ref ppp_pptp_header */ - ppp_pptp_header* getPPP_PPTPHeader() const { return (ppp_pptp_header*)m_Data; } - + ppp_pptp_header* getPPP_PPTPHeader() const + { + return (ppp_pptp_header*)m_Data; + } // implement abstract methods @@ -426,7 +449,10 @@ namespace pcpp /** * @return The size of @ref ppp_pptp_header */ - size_t getHeaderLen() const { return sizeof(ppp_pptp_header); } + size_t getHeaderLen() const + { + return sizeof(ppp_pptp_header); + } /** * Calculate the following fields: @@ -434,10 +460,15 @@ namespace pcpp */ void computeCalculateFields(); - std::string toString() const { return "PPP for PPTP Layer"; } - - OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; } + std::string toString() const + { + return "PPP for PPTP Layer"; + } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelSesionLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/GtpLayer.h b/Packet++/header/GtpLayer.h index 750e08b69d..1849c42fb3 100644 --- a/Packet++/header/GtpLayer.h +++ b/Packet++/header/GtpLayer.h @@ -4,7 +4,6 @@ /// @file - /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib @@ -21,38 +20,40 @@ namespace pcpp { #if (BYTE_ORDER == LITTLE_ENDIAN) /** A 1-bit value that states whether there is a N-PDU number optional field */ - uint8_t npduNumberFlag:1, - /** A 1-bit value that states whether there is a Sequence Number optional field */ - sequenceNumberFlag:1, - /** A 1-bit value that states whether there is an extension header optional field */ - extensionHeaderFlag:1, - /** Reserved bit */ - reserved:1, - /** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */ - protocolType:1, - /** GTP version */ - version:3; + uint8_t npduNumberFlag : 1, + /** A 1-bit value that states whether there is a Sequence Number optional field */ + sequenceNumberFlag : 1, + /** A 1-bit value that states whether there is an extension header optional field */ + extensionHeaderFlag : 1, + /** Reserved bit */ + reserved : 1, + /** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */ + protocolType : 1, + /** GTP version */ + version : 3; #else /** GTP version */ - uint8_t version:3, - /** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */ - protocolType:1, - /** Reserved bit */ - reserved:1, - /** A 1-bit value that states whether there is an extension header optional field */ - extensionHeaderFlag:1, - /** A 1-bit value that states whether there is a Sequence Number optional field */ - sequenceNumberFlag:1, - /** A 1-bit value that states whether there is a N-PDU number optional field */ - npduNumberFlag:1; + uint8_t version : 3, + /** A 1-bit value that differentiates GTP (value 1) from GTP' (value 0) */ + protocolType : 1, + /** Reserved bit */ + reserved : 1, + /** A 1-bit value that states whether there is an extension header optional field */ + extensionHeaderFlag : 1, + /** A 1-bit value that states whether there is a Sequence Number optional field */ + sequenceNumberFlag : 1, + /** A 1-bit value that states whether there is a N-PDU number optional field */ + npduNumberFlag : 1; #endif /** An 8-bit field that indicates the type of GTP message */ uint8_t messageType; - /** A 16-bit field that indicates the length of the payload in bytes (rest of the packet following the mandatory 8-byte GTP header). Includes the optional fields */ + /** A 16-bit field that indicates the length of the payload in bytes (rest of the packet following the mandatory + * 8-byte GTP header). Includes the optional fields */ uint16_t messageLength; - /** Tunnel endpoint identifier - A 32-bit(4-octet) field used to multiplex different connections in the same GTP tunnel */ + /** Tunnel endpoint identifier - A 32-bit(4-octet) field used to multiplex different connections in the same GTP + * tunnel */ uint32_t teid; }; @@ -60,7 +61,8 @@ namespace pcpp /** * An enum representing the possible GTP v1 message types. - * All of the message types except for #GtpV1_GPDU are considered GTP-C messages. #GtpV1_GPDU is considered a GTP-U message + * All of the message types except for #GtpV1_GPDU are considered GTP-C messages. #GtpV1_GPDU is considered a GTP-U + * message */ enum GtpV1MessageType { @@ -204,7 +206,6 @@ namespace pcpp GtpV1_GPDU = 255 }; - /** * @class GtpV1Layer * A class representing the [GTP v1](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol) protocol. @@ -221,10 +222,10 @@ namespace pcpp gtpv1_header_extra* getHeaderExtra() const; - void init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum); + void init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, + uint8_t npduNum); public: - /** * @class GtpExtension * A class that represents [GTP header extensions](https://en.wikipedia.org/wiki/GPRS_Tunnelling_Protocol) @@ -245,7 +246,6 @@ namespace pcpp static GtpExtension createGtpExtension(uint8_t* data, size_t dataLen, uint8_t extType, uint16_t content); public: - /** * An empty c'tor that creates an empty object, meaning one that isNull() returns "true") */ @@ -282,8 +282,8 @@ namespace pcpp size_t getTotalLength() const; /** - * @return The length of the extension's content, excluding the extension length and next extension type fields. - * If the object is empty a value of zero is returned + * @return The length of the extension's content, excluding the extension length and next extension type + * fields. If the object is empty a value of zero is returned */ size_t getContentLength() const; @@ -294,28 +294,33 @@ namespace pcpp uint8_t* getContent() const; /** - * @return The extension type of the next header. If there are no more header extensions or if this object is empty - * a value of zero is returned + * @return The extension type of the next header. If there are no more header extensions or if this object + * is empty a value of zero is returned */ uint8_t getNextExtensionHeaderType() const; /** - * @return An instance of this class representing the next extension header, if exists in the message. If there are - * no more header extensions or if this object is empty an empty instance of GtpExtension is returned, meaning - * one that GtpExtension#isNull() returns "true" + * @return An instance of this class representing the next extension header, if exists in the message. If + * there are no more header extensions or if this object is empty an empty instance of GtpExtension is + * returned, meaning one that GtpExtension#isNull() returns "true" */ GtpExtension getNextExtension() const; - }; // GtpExtension + }; // GtpExtension - virtual ~GtpV1Layer() {} + virtual ~GtpV1Layer() + {} - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - GtpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = GTPv1; } + GtpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = GTPv1; + } /** * A constructor that creates a new GTPv1 layer and sets the message type and the TEID value @@ -328,12 +333,17 @@ namespace pcpp * A constructor that creates a new GTPv1 layer and sets various parameters * @param[in] messageType The GTPv1 message type to be set in the newly created layer * @param[in] teid The TEID value to be set in the newly created layer - * @param[in] setSeqNum A flag indicating whether to set a sequence number. If set to "false" then the parameter "seqNum" will be ignored - * @param[in] seqNum The sequence number to be set in the newly created later. If "setSeqNum" is set to false this parameter will be ignored - * @param[in] setNpduNum A flag indicating whether to set the N-PDU number. If set to "false" then the parameter "npduNum" will be ignored - * @param[in] npduNum The N-PDU number to be set in the newly created later. If "setNpduNum" is set to false this parameter will be ignored + * @param[in] setSeqNum A flag indicating whether to set a sequence number. If set to "false" then the parameter + * "seqNum" will be ignored + * @param[in] seqNum The sequence number to be set in the newly created later. If "setSeqNum" is set to false + * this parameter will be ignored + * @param[in] setNpduNum A flag indicating whether to set the N-PDU number. If set to "false" then the parameter + * "npduNum" will be ignored + * @param[in] npduNum The N-PDU number to be set in the newly created later. If "setNpduNum" is set to false + * this parameter will be ignored */ - GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum); + GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, + uint8_t npduNum); /** * A static method that takes a byte array and detects whether it is a GTP v1 message @@ -344,9 +354,13 @@ namespace pcpp static bool isGTPv1(const uint8_t* data, size_t dataSize); /** - * @return The GTP v1 common header structure. Notice this points directly to the data, so every change will change the actual packet data + * @return The GTP v1 common header structure. Notice this points directly to the data, so every change will + * change the actual packet data */ - gtpv1_header* getHeader() const { return (gtpv1_header*)m_Data; } + gtpv1_header* getHeader() const + { + return (gtpv1_header*)m_Data; + } /** * Get the sequence number if exists on the message (sequence number is an optional field in GTP messages) @@ -359,7 +373,8 @@ namespace pcpp /** * Set a sequence number * @param[in] seqNumber The sequence number to set - * @return True if the value was set successfully, false otherwise. In case of failure a corresponding error message will be written to log + * @return True if the value was set successfully, false otherwise. In case of failure a corresponding error + * message will be written to log */ bool setSequenceNumber(const uint16_t seqNumber); @@ -374,32 +389,35 @@ namespace pcpp /** * Set an N-PDU number * @param[in] npduNum The N-PDU number to set - * @return True if the value was set successfully, false otherwise. In case of failure a corresponding error message will be written to log + * @return True if the value was set successfully, false otherwise. In case of failure a corresponding error + * message will be written to log */ bool setNpduNumber(const uint8_t npduNum); /** * Get the type of the next header extension if exists on the message (extensions are optional in GTP messages) - * @param[out] nextExtType Set with the next header extension type if exists in layer. Otherwise remains unchanged + * @param[out] nextExtType Set with the next header extension type if exists in layer. Otherwise remains + * unchanged * @return True if the message contains header extensions, in which case nextExtType is set to the next * header extension type. If there are no header extensions false is returned and nextExtType remains unchanged */ bool getNextExtensionHeaderType(uint8_t& nextExtType) const; /** - * @return An object that represents the next extension header, if exists in the message. If there are no extensions - * an empty object is returned, meaning an object which GtpExtension#isNull() returns "true" + * @return An object that represents the next extension header, if exists in the message. If there are no + * extensions an empty object is returned, meaning an object which GtpExtension#isNull() returns "true" */ GtpExtension getNextExtension() const; /** - * Add a GTPv1 header extension. It is assumed that the extension is 4 bytes in length and its content is 2 bytes in length. - * If you need a different content size please reach out to me. This method takes care of extending the layer to make room for - * the new extension and also sets the relevant flags and fields + * Add a GTPv1 header extension. It is assumed that the extension is 4 bytes in length and its content is 2 + * bytes in length. If you need a different content size please reach out to me. This method takes care of + * extending the layer to make room for the new extension and also sets the relevant flags and fields * @param[in] extensionType The type of the new extension * @param[in] extensionContent A 2-byte long content - * @return An object representing the newly added extension. If there was an error adding the extension a null object will be - * returned (meaning GtpExtension#isNull() will return "true") and a corresponding error message will be written to log + * @return An object representing the newly added extension. If there was an error adding the extension a null + * object will be returned (meaning GtpExtension#isNull() will return "true") and a corresponding error message + * will be written to log */ GtpExtension addExtension(uint8_t extensionType, uint16_t extensionContent); @@ -428,8 +446,10 @@ namespace pcpp * @param[in] port The port number to be checked * @return True if the port matches those associated with the BGP protocol */ - static bool isGTPv1Port(uint16_t port) { return port == 2152 /* GTP-U */ || port == 2123 /* GTP-C */; } - + static bool isGTPv1Port(uint16_t port) + { + return port == 2152 /* GTP-U */ || port == 2123 /* GTP-C */; + } // implement abstract methods @@ -454,6 +474,9 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelTransportLayer; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/HttpLayer.h b/Packet++/header/HttpLayer.h index 41784e0549..a63e17dab0 100644 --- a/Packet++/header/HttpLayer.h +++ b/Packet++/header/HttpLayer.h @@ -32,98 +32,116 @@ namespace pcpp // some popular HTTP fields /** Host field */ -#define PCPP_HTTP_HOST_FIELD "Host" +#define PCPP_HTTP_HOST_FIELD "Host" /** Connection field */ -#define PCPP_HTTP_CONNECTION_FIELD "Connection" +#define PCPP_HTTP_CONNECTION_FIELD "Connection" /** User-Agent field */ -#define PCPP_HTTP_USER_AGENT_FIELD "User-Agent" +#define PCPP_HTTP_USER_AGENT_FIELD "User-Agent" /** Referer field */ -#define PCPP_HTTP_REFERER_FIELD "Referer" +#define PCPP_HTTP_REFERER_FIELD "Referer" /** Accept field */ -#define PCPP_HTTP_ACCEPT_FIELD "Accept" +#define PCPP_HTTP_ACCEPT_FIELD "Accept" /** Accept-Encoding field */ -#define PCPP_HTTP_ACCEPT_ENCODING_FIELD "Accept-Encoding" +#define PCPP_HTTP_ACCEPT_ENCODING_FIELD "Accept-Encoding" /** Accept-Language field */ -#define PCPP_HTTP_ACCEPT_LANGUAGE_FIELD "Accept-Language" +#define PCPP_HTTP_ACCEPT_LANGUAGE_FIELD "Accept-Language" /** Cookie field */ -#define PCPP_HTTP_COOKIE_FIELD "Cookie" +#define PCPP_HTTP_COOKIE_FIELD "Cookie" /** Content-Length field */ -#define PCPP_HTTP_CONTENT_LENGTH_FIELD "Content-Length" +#define PCPP_HTTP_CONTENT_LENGTH_FIELD "Content-Length" /** Content-Encoding field */ -#define PCPP_HTTP_CONTENT_ENCODING_FIELD "Content-Encoding" +#define PCPP_HTTP_CONTENT_ENCODING_FIELD "Content-Encoding" /** Content-Type field */ -#define PCPP_HTTP_CONTENT_TYPE_FIELD "Content-Type" +#define PCPP_HTTP_CONTENT_TYPE_FIELD "Content-Type" /** Transfer-Encoding field */ -#define PCPP_HTTP_TRANSFER_ENCODING_FIELD "Transfer-Encoding" +#define PCPP_HTTP_TRANSFER_ENCODING_FIELD "Transfer-Encoding" /** Server field */ -#define PCPP_HTTP_SERVER_FIELD "Server" - +#define PCPP_HTTP_SERVER_FIELD "Server" // -------- classes to be defined later ----------------- - class HttpRequestFirstLine; class HttpResponseFirstLine; - // -------- Class HttpMessage ----------------- - /** * @class HttpMessage - * Represents a general HTTP message. It's an abstract class and cannot be instantiated. It's inherited by HttpRequestLayer and HttpResponseLayer + * Represents a general HTTP message. It's an abstract class and cannot be instantiated. It's inherited by + * HttpRequestLayer and HttpResponseLayer */ class HttpMessage : public TextBasedProtocolMessage { public: - - virtual ~HttpMessage() {} + virtual ~HttpMessage() + {} /** * A static method that checks whether the port is considered as HTTP * @param[in] port The port number to be checked * @return True if the port matches those associated with the HTTP protocol */ - static bool isHttpPort(uint16_t port) { return port == 80 || port == 8080; } + static bool isHttpPort(uint16_t port) + { + return port == 80 || port == 8080; + } // overridden methods virtual HeaderField* addField(const std::string& fieldName, const std::string& fieldValue); virtual HeaderField* addField(const HeaderField& newField); - virtual HeaderField* insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue); + virtual HeaderField* insertField(HeaderField* prevField, const std::string& fieldName, + const std::string& fieldValue); virtual HeaderField* insertField(HeaderField* prevField, const HeaderField& newField); - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } protected: - HttpMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) {} - HttpMessage() : TextBasedProtocolMessage() {} - HttpMessage(const HttpMessage& other) : TextBasedProtocolMessage(other) {} - HttpMessage& operator=(const HttpMessage& other) { TextBasedProtocolMessage::operator=(other); return *this; } + HttpMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) + {} + HttpMessage() : TextBasedProtocolMessage() + {} + HttpMessage(const HttpMessage& other) : TextBasedProtocolMessage(other) + {} + HttpMessage& operator=(const HttpMessage& other) + { + TextBasedProtocolMessage::operator=(other); + return *this; + } // implementation of abstract methods - char getHeaderFieldNameValueSeparator() const { return ':'; } - bool spacesAllowedBetweenHeaderFieldNameAndValue() const { return true; } + char getHeaderFieldNameValueSeparator() const + { + return ':'; + } + bool spacesAllowedBetweenHeaderFieldNameAndValue() const + { + return true; + } }; - // -------- Class HttpRequestLayer ----------------- /** * @class HttpRequestLayer - * Represents an HTTP request header and inherits all basic functionality of HttpMessage and TextBasedProtocolMessage. - * The functionality that is added for this class is the HTTP first line concept. An HTTP request has the following first line: - * GET /bla/blabla.asp HTTP/1.1 - * Since it's not an "ordinary" HTTP field, it requires a special treatment and gets a class of it's own: HttpRequestFirstLine. - * Unlike most L2-4 protocols, an HTTP request header can spread over more than 1 packet. PcapPlusPlus currently doesn't support a header - * that is spread over more than 1 packet so in such cases: 1) only the first packet will be parsed as HttpRequestLayer (the other packets - * won't be recognized as HttpRequestLayer) and 2) the HTTP header for the first packet won't be complete (as it continues in the following - * packets), this why PcapPlusPlus can indicate that HTTP request header is complete or not(doesn't end with "\r\n\r\n" or "\n\n") using - * HttpMessage#isHeaderComplete() + * Represents an HTTP request header and inherits all basic functionality of HttpMessage and + * TextBasedProtocolMessage. The functionality that is added for this class is the HTTP first line concept. An HTTP + * request has the following first line: GET /bla/blabla.asp HTTP/1.1 Since it's not an "ordinary" HTTP + * field, it requires a special treatment and gets a class of it's own: HttpRequestFirstLine. Unlike most L2-4 + * protocols, an HTTP request header can spread over more than 1 packet. PcapPlusPlus currently doesn't support a + * header that is spread over more than 1 packet so in such cases: 1) only the first packet will be parsed as + * HttpRequestLayer (the other packets won't be recognized as HttpRequestLayer) and 2) the HTTP header for the first + * packet won't be complete (as it continues in the following packets), this why PcapPlusPlus can indicate that HTTP + * request header is complete or not(doesn't end with "\r\n\r\n" or "\n\n") using HttpMessage#isHeaderComplete() */ class HttpRequestLayer : public HttpMessage { friend class HttpRequestFirstLine; + public: /** * HTTP request methods @@ -152,7 +170,7 @@ namespace pcpp HttpMethodUnknown }; - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer @@ -161,8 +179,8 @@ namespace pcpp HttpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /** - * A constructor that allocates a new HTTP request header with only the first line filled. Object will be created without further fields. - * The user can then add fields using addField() methods + * A constructor that allocates a new HTTP request header with only the first line filled. Object will be + * created without further fields. The user can then add fields using addField() methods * @param[in] method The HTTP method used in this HTTP request * @param[in] uri The URI of the first line * @param[in] version HTTP version to be used in this request @@ -172,15 +190,15 @@ namespace pcpp virtual ~HttpRequestLayer(); /** - * A copy constructor for this layer. This copy constructor inherits base copy constructor HttpMessage#HttpMessage() and add the functionality - * of copying the first line as well + * A copy constructor for this layer. This copy constructor inherits base copy constructor + * HttpMessage#HttpMessage() and add the functionality of copying the first line as well * @param[in] other The instance to copy from */ HttpRequestLayer(const HttpRequestLayer& other); /** - * An assignment operator overload for this layer. This method inherits base assignment operator HttpMessage#operator=() and add the functionality - * of copying the first line as well + * An assignment operator overload for this layer. This method inherits base assignment operator + * HttpMessage#operator=() and add the functionality of copying the first line as well * @param[in] other The instance to copy from * @return A reference to the assignee */ @@ -189,13 +207,16 @@ namespace pcpp /** * @return A pointer to the first line instance for this message */ - HttpRequestFirstLine* getFirstLine() const { return m_FirstLine; } + HttpRequestFirstLine* getFirstLine() const + { + return m_FirstLine; + } /** - * The URL is hostname+uri. So given the following URL, for example: "www.cnn.com/main.html", the hostname is "www.cnn.com" and the URI - * is "/.main.html". URI and hostname are split to 2 different places inside the HTTP request packet: URI is in the first line and hostname - * is in "HOST" field. - * This methods concatenates the hostname and URI to the full URL + * The URL is hostname+uri. So given the following URL, for example: "www.cnn.com/main.html", the hostname is + * "www.cnn.com" and the URI is "/.main.html". URI and hostname are split to 2 different places inside the HTTP + * request packet: URI is in the first line and hostname is in "HOST" field. This methods concatenates the + * hostname and URI to the full URL * @return The URL of the HTTP request message */ std::string getUrl() const; @@ -219,7 +240,7 @@ namespace pcpp /** * @brief Define enum types and the corresponding int values */ - enum Value: int + enum Value : int { /** 100 Continue*/ Http100Continue = 100, @@ -232,7 +253,7 @@ namespace pcpp /** 104-199 Unassigned */ /** 200 OK */ - Http200OK= 200, + Http200OK = 200, /** 201 Created */ Http201Created = 201, /** 202 Accepted */ @@ -404,13 +425,15 @@ namespace pcpp /** 599 Network connect timeout error */ Http599NetworkConnectTimeoutError = 599, + // clang-format off /** Unknown status code */ HttpStatus1xxCodeUnknown = 900001, // 1xx: Informational - Request received, continuing process HttpStatus2xxCodeUnknown = 900002, // 2xx: Success - The action was successfully received, understood, and accepted HttpStatus3xxCodeUnknown = 900003, // 3xx: Redirection - Further action must be taken in order to complete the request HttpStatus4xxCodeUnknown = 900004, // 4xx: Client Error - The request contains bad syntax or cannot be fulfilled HttpStatus5xxCodeUnknown = 900005, // 5xx: Server Error - The server failed to fulfill an apparently valid request - HttpStatusCodeUnknown = 999999, // other arbitrary number + HttpStatusCodeUnknown = 999999, // other arbitrary number + // clang-format on }; HttpResponseStatusCode() = default; @@ -420,14 +443,15 @@ namespace pcpp * @brief Construct HttpResponseStatusCode from Value enum * @param[in] statusCode the status code enum */ - HttpResponseStatusCode(Value statusCode) : m_Value(statusCode) { } + HttpResponseStatusCode(Value statusCode) : m_Value(statusCode) + {} /** * @brief Construct HttpResponseStatusCode from the code number and the customized message * @param[in] statusCodeNumber the status code in number, e.g. 200, 404 * @param[in] statusMessage the status message, optional, leave empty to use a default message */ - explicit HttpResponseStatusCode(const int &statusCodeNumber, const std::string& statusMessage = ""); + explicit HttpResponseStatusCode(const int& statusCodeNumber, const std::string& statusMessage = ""); /** * @brief Construct HttpResponseStatusCode from Value enum and the customized message @@ -436,8 +460,11 @@ namespace pcpp */ explicit HttpResponseStatusCode(const Value& statusCode, const std::string& statusMessage); - // Allow switch and comparisons. - operator Value() const { return m_Value; } + // Allow switch and comparisons. + operator Value() const + { + return m_Value; + } // Prevent usage: if(httpResponseStatusCode) explicit operator bool() const = delete; @@ -471,7 +498,7 @@ namespace pcpp } private: - Value m_Value = HttpStatusCodeUnknown; + Value m_Value = HttpStatusCodeUnknown; std::string m_CustomizedMessage; }; @@ -479,24 +506,25 @@ namespace pcpp /** * @class HttpResponseLayer - * Represents an HTTP response header and inherits all basic functionality of HttpMessage and TextBasedProtocolMessage. - * The functionality that is added for this class is the HTTP first line concept. An HTTP response has the following first line: - * 200 OK HTTP/1.1 - * Since it's not an "ordinary" HTTP field, it requires a special treatment and gets a class of it's own: HttpResponseFirstLine. - * Unlike most L2-4 protocols, an HTTP response header can spread over more than 1 packet. PcapPlusPlus currently doesn't support a header - * that is spread over more than 1 packet so in such cases: 1) only the first packet will be parsed as HttpResponseLayer (the other packets - * won't be recognized as HttpResponseLayer) and 2) the HTTP header for the first packet won't be complete (as it continues in the following - * packets), this why PcapPlusPlus can indicate that HTTP response header is complete or not (doesn't end with "\r\n\r\n" or "\n\n") using - * HttpMessage#isHeaderComplete() + * Represents an HTTP response header and inherits all basic functionality of HttpMessage and + * TextBasedProtocolMessage. The functionality that is added for this class is the HTTP first line concept. An HTTP + * response has the following first line: 200 OK HTTP/1.1 Since it's not an "ordinary" HTTP field, it + * requires a special treatment and gets a class of it's own: HttpResponseFirstLine. Unlike most L2-4 protocols, an + * HTTP response header can spread over more than 1 packet. PcapPlusPlus currently doesn't support a header that is + * spread over more than 1 packet so in such cases: 1) only the first packet will be parsed as HttpResponseLayer + * (the other packets won't be recognized as HttpResponseLayer) and 2) the HTTP header for the first packet won't be + * complete (as it continues in the following packets), this why PcapPlusPlus can indicate that HTTP response header + * is complete or not (doesn't end with "\r\n\r\n" or "\n\n") using HttpMessage#isHeaderComplete() */ class HttpResponseLayer : public HttpMessage { friend class HttpResponseFirstLine; + public: // backward compatibility using HttpResponseStatusCode = pcpp::HttpResponseStatusCode; - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer @@ -505,21 +533,22 @@ namespace pcpp HttpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /** - * A constructor that allocates a new HTTP response header with only the first line filled. Object will be created without further fields. - * The user can then add fields using addField() methods + * A constructor that allocates a new HTTP response header with only the first line filled. Object will be + * created without further fields. The user can then add fields using addField() methods * @param[in] version HTTP version to be used * @param[in] statusCode Status code to be used - * @param[in] statusCodeString Most status codes have their default string, e.g 200 is usually "OK", 404 is usually "Not Found", etc. - * But the user can set a non-default status code string and it will be written in the header first line. Empty string ("") means using the - * default status code string + * @param[in] statusCodeString Most status codes have their default string, e.g 200 is usually "OK", 404 is + * usually "Not Found", etc. But the user can set a non-default status code string and it will be written in the + * header first line. Empty string ("") means using the default status code string * @deprecated Use other constructors instead. */ PCPP_DEPRECATED("Use other constructors instead") - explicit HttpResponseLayer(HttpVersion version, const HttpResponseStatusCode& statusCode, const std::string& statusCodeString); + explicit HttpResponseLayer(HttpVersion version, const HttpResponseStatusCode& statusCode, + const std::string& statusCodeString); /** - * A constructor that allocates a new HTTP response header with only the first line filled. Object will be created without further fields. - * The user can then add fields using addField() methods + * A constructor that allocates a new HTTP response header with only the first line filled. Object will be + * created without further fields. The user can then add fields using addField() methods * @param[in] version HTTP version to be used * @param[in] statusCode Status code to be used */ @@ -528,15 +557,15 @@ namespace pcpp virtual ~HttpResponseLayer(); /** - * A copy constructor for this layer. This copy constructor inherits base copy constructor HttpMessage#HttpMessage() and adds the functionality - * of copying the first line as well + * A copy constructor for this layer. This copy constructor inherits base copy constructor + * HttpMessage#HttpMessage() and adds the functionality of copying the first line as well * @param[in] other The instance to copy from */ HttpResponseLayer(const HttpResponseLayer& other); /** - * An assignment operator overload for this layer. This method inherits base assignment operator HttpMessage#operator=() and adds the functionality - * of copying the first line as well + * An assignment operator overload for this layer. This method inherits base assignment operator + * HttpMessage#operator=() and adds the functionality of copying the first line as well * @param[in] other The instance to copy from * @return A reference to the assignee */ @@ -545,26 +574,32 @@ namespace pcpp /** * @return A pointer to the first line instance for this message */ - HttpResponseFirstLine* getFirstLine() const { return m_FirstLine; } + HttpResponseFirstLine* getFirstLine() const + { + return m_FirstLine; + } /** - * The length of the body of many HTTP response messages is determined by a HTTP header field called "Content-Length". This method sets - * The content-length field value. The method supports several cases: - * - If the "Content-Length" field exists - the method will only replace the existing value with the new value - * - If the "Content-Length" field doesn't exist - the method will create this field and put the value in it. Here are also 2 cases: + * The length of the body of many HTTP response messages is determined by a HTTP header field called + * "Content-Length". This method sets The content-length field value. The method supports several cases: + * - If the "Content-Length" field exists - the method will only replace the existing value with the new value + * - If the "Content-Length" field doesn't exist - the method will create this field and put the value in it. + * Here are also 2 cases: * - If prevFieldName is specified - the new "Content-Length" field will be created after it - * - If prevFieldName isn't specified or doesn't exist - the new "Content-Length" field will be created as the last field before - * end-of-header field + * - If prevFieldName isn't specified or doesn't exist - the new "Content-Length" field will be created as the + * last field before end-of-header field * * @param[in] contentLength The content length value to set - * @param[in] prevFieldName Optional field, if specified and "Content-Length" field doesn't exist, it will be created after it + * @param[in] prevFieldName Optional field, if specified and "Content-Length" field doesn't exist, it will be + * created after it * @return A pointer to the "Content-Length" field, or NULL if creation failed for some reason */ - HeaderField* setContentLength(int contentLength, const std::string &prevFieldName = ""); + HeaderField* setContentLength(int contentLength, const std::string& prevFieldName = ""); /** - * The length of the body of many HTTP response messages is determined by a HTTP header field called "Content-Length". This method - * parses this field, extracts its value and return it. If this field doesn't exist the method will return 0 + * The length of the body of many HTTP response messages is determined by a HTTP header field called + * "Content-Length". This method parses this field, extracts its value and return it. If this field doesn't + * exist the method will return 0 * @return HTTP response body length determined by "Content-Length" field */ int getContentLength() const; @@ -575,44 +610,45 @@ namespace pcpp private: HttpResponseFirstLine* m_FirstLine; - }; - - - - // -------- Class HttpRequestFirstLine ----------------- /** * @class HttpRequestFirstLine - * Represents an HTTP request header first line. The first line includes 3 parameters: HTTP method (e.g GET, POST, etc.), - * URI (e.g /main/index.html) and HTTP version (e.g HTTP/1.1). All these parameters are included in this class, and the user - * can retrieve or set them. - * This class cannot be instantiated by users, it's created inside HttpRequestLayer and user can get a pointer to an instance of it. All "get" - * methods of this class will retrieve the actual data of the HTTP request and the "set" methods will change the packet data. - * Since HTTP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "set" methods - * of this class need in most cases to shorten or extend the data in HttpRequestLayer. These methods will return a false value if this - * action failed + * Represents an HTTP request header first line. The first line includes 3 parameters: HTTP method (e.g GET, POST, + * etc.), URI (e.g /main/index.html) and HTTP version (e.g HTTP/1.1). All these parameters are included in this + * class, and the user can retrieve or set them. This class cannot be instantiated by users, it's created inside + * HttpRequestLayer and user can get a pointer to an instance of it. All "get" methods of this class will retrieve + * the actual data of the HTTP request and the "set" methods will change the packet data. Since HTTP is a textual + * protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "set" + * methods of this class need in most cases to shorten or extend the data in HttpRequestLayer. These methods will + * return a false value if this action failed */ class HttpRequestFirstLine { friend class HttpRequestLayer; + public: /** * @return The HTTP method */ - HttpRequestLayer::HttpMethod getMethod() const { return m_Method; } + HttpRequestLayer::HttpMethod getMethod() const + { + return m_Method; + } /** * Set the HTTP method * @param[in] newMethod The method to set - * @return False if newMethod is HttpRequestLayer#HttpMethodUnknown or if shortening/extending the HttpRequestLayer data failed. True otherwise + * @return False if newMethod is HttpRequestLayer#HttpMethodUnknown or if shortening/extending the + * HttpRequestLayer data failed. True otherwise */ bool setMethod(HttpRequestLayer::HttpMethod newMethod); /** - * @return A copied version of the URI (notice changing the return value won't change the actual data of the packet) + * @return A copied version of the URI (notice changing the return value won't change the actual data of the + * packet) */ std::string getUri() const; @@ -626,11 +662,14 @@ namespace pcpp /** * @return The HTTP version */ - HttpVersion getVersion() const { return m_Version; } + HttpVersion getVersion() const + { + return m_Version; + } /** - * Set the HTTP version. This method doesn't return a value since all supported HTTP versions are of the same size - * (HTTP/0.9, HTTP/1.0, HTTP/1.1) + * Set the HTTP version. This method doesn't return a value since all supported HTTP versions are of the same + * size (HTTP/0.9, HTTP/1.0, HTTP/1.1) * @param[in] newVersion The HTTP version to set */ void setVersion(HttpVersion newVersion); @@ -646,37 +685,50 @@ namespace pcpp /** * @return The size in bytes of the HTTP first line */ - int getSize() const { return m_FirstLineEndOffset; } + int getSize() const + { + return m_FirstLineEndOffset; + } /** - * As explained in HttpRequestLayer, an HTTP header can spread over more than 1 packet, so when looking at a single packet - * the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication - * whether the first line is partial + * As explained in HttpRequestLayer, an HTTP header can spread over more than 1 packet, so when looking at a + * single packet the header can be partial. Same goes for the first line - it can spread over more than 1 + * packet. This method returns an indication whether the first line is partial * @return False if the first line is partial, true if it's complete */ - bool isComplete() const { return m_IsComplete; } + bool isComplete() const + { + return m_IsComplete; + } /** * @class HttpRequestFirstLineException - * This exception can be thrown while constructing HttpRequestFirstLine (the constructor is private, so the construction happens - * only in HttpRequestLayer). This kind of exception will be thrown if trying to construct with HTTP method of - * HttpRequestLayer#HttpMethodUnknown or with undefined HTTP version ::HttpVersionUnknown + * This exception can be thrown while constructing HttpRequestFirstLine (the constructor is private, so the + * construction happens only in HttpRequestLayer). This kind of exception will be thrown if trying to construct + * with HTTP method of HttpRequestLayer#HttpMethodUnknown or with undefined HTTP version ::HttpVersionUnknown */ class HttpRequestFirstLineException : public std::exception { public: - ~HttpRequestFirstLineException() throw() {} - void setMessage(const std::string &message) { m_Message = message; } + ~HttpRequestFirstLineException() throw() + {} + void setMessage(const std::string& message) + { + m_Message = message; + } virtual const char* what() const throw() { return m_Message.c_str(); } + private: std::string m_Message; }; + private: HttpRequestFirstLine(HttpRequestLayer* httpRequest); - HttpRequestFirstLine(HttpRequestLayer* httpRequest, HttpRequestLayer::HttpMethod method, HttpVersion version, const std::string& uri = "/"); + HttpRequestFirstLine(HttpRequestLayer* httpRequest, HttpRequestLayer::HttpMethod method, HttpVersion version, + const std::string& uri = "/"); void parseVersion(); @@ -690,30 +742,31 @@ namespace pcpp HttpRequestFirstLineException m_Exception; }; - - - - // -------- Class HttpResponseFirstLine ----------------- /** * @class HttpResponseFirstLine - * Represents an HTTP response header first line. The first line includes 2 parameters: status code (e.g 200 OK, 404 Not Found, etc.), - * and HTTP version (e.g HTTP/1.1). These 2 parameters are included in this class, and the user can retrieve or set them. - * This class cannot be instantiated by users, it's created inside HttpResponseLayer and user can get a pointer to an instance of it. The "get" - * methods of this class will retrieve the actual data of the HTTP response and the "set" methods will change the packet data. - * Since HTTP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "set" methods - * of this class need in most cases to shorten or extend the data in HttpResponseLayer. These methods will return a false value if this + * Represents an HTTP response header first line. The first line includes 2 parameters: status code (e.g 200 OK, 404 + * Not Found, etc.), and HTTP version (e.g HTTP/1.1). These 2 parameters are included in this class, and the user + * can retrieve or set them. This class cannot be instantiated by users, it's created inside HttpResponseLayer and + * user can get a pointer to an instance of it. The "get" methods of this class will retrieve the actual data of the + * HTTP response and the "set" methods will change the packet data. Since HTTP is a textual protocol, most fields + * aren't of fixed size and this also applies to the first line parameters. So most "set" methods of this class need + * in most cases to shorten or extend the data in HttpResponseLayer. These methods will return a false value if this * action failed */ class HttpResponseFirstLine { friend class HttpResponseLayer; + public: /** * @return The status code as HttpResponseStatusCode enum */ - HttpResponseStatusCode getStatusCode() const { return m_StatusCode; } + HttpResponseStatusCode getStatusCode() const + { + return m_StatusCode; + } /** * @return The status code number as integer (e.g 200, 404, etc.) @@ -728,10 +781,11 @@ namespace pcpp /** * Set the status code * @param[in] newStatusCode The new status code to set - * @param[in] statusCodeString An optional parameter: set a non-default status code message (e.g "Bla Bla" instead of "Not Found"). If - * this parameter isn't supplied or supplied as empty string (""), the default message for the status code will be set + * @param[in] statusCodeString An optional parameter: set a non-default status code message (e.g "Bla Bla" + * instead of "Not Found"). If this parameter isn't supplied or supplied as empty string (""), the default + * message for the status code will be set * @return True if setting the status code was completed successfully, false otherwise - * @deprecated Use the other overload instead. + * @deprecated Use the other overload instead. */ PCPP_DEPRECATED("Use the other overload instead") bool setStatusCode(const HttpResponseStatusCode& newStatusCode, const std::string& statusCodeString); @@ -746,11 +800,14 @@ namespace pcpp /** * @return The HTTP version */ - HttpVersion getVersion() const { return m_Version; } + HttpVersion getVersion() const + { + return m_Version; + } /** - * Set the HTTP version. This method doesn't return a value since all supported HTTP versions are of the same size - * (HTTP/0.9, HTTP/1.0, HTTP/1.1) + * Set the HTTP version. This method doesn't return a value since all supported HTTP versions are of the same + * size (HTTP/0.9, HTTP/1.0, HTTP/1.1) * @param[in] newVersion The HTTP version to set */ void setVersion(HttpVersion newVersion); @@ -774,38 +831,51 @@ namespace pcpp /** * @return The size in bytes of the HTTP first line */ - int getSize() const { return m_FirstLineEndOffset; } + int getSize() const + { + return m_FirstLineEndOffset; + } /** - * As explained in HttpResponseLayer, an HTTP header can spread over more than 1 packet, so when looking at a single packet - * the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication - * whether the first line is partial + * As explained in HttpResponseLayer, an HTTP header can spread over more than 1 packet, so when looking at a + * single packet the header can be partial. Same goes for the first line - it can spread over more than 1 + * packet. This method returns an indication whether the first line is partial * @return False if the first line is partial, true if it's complete */ - bool isComplete() const { return m_IsComplete; } + bool isComplete() const + { + return m_IsComplete; + } /** * @class HttpResponseFirstLineException - * This exception can be thrown while constructing HttpResponseFirstLine (the constructor is private, so the construction happens - * only in HttpResponseLayer). This kind of exception will be thrown if trying to construct with a HTTP status code that is not in - * HttpResponseStatusCode or with undefined HTTP version ::HttpVersionUnknown + * This exception can be thrown while constructing HttpResponseFirstLine (the constructor is private, so the + * construction happens only in HttpResponseLayer). This kind of exception will be thrown if trying to construct + * with a HTTP status code that is not in HttpResponseStatusCode or with undefined HTTP version + * ::HttpVersionUnknown */ class HttpResponseFirstLineException : public std::exception { public: - ~HttpResponseFirstLineException() throw() {} - void setMessage(const std::string &message) { m_Message = message; } + ~HttpResponseFirstLineException() throw() + {} + void setMessage(const std::string& message) + { + m_Message = message; + } virtual const char* what() const throw() { return m_Message.c_str(); } + private: std::string m_Message; }; private: HttpResponseFirstLine(HttpResponseLayer* httpResponse); - HttpResponseFirstLine(HttpResponseLayer* httpResponse, HttpVersion version, const HttpResponseStatusCode& statusCode); + HttpResponseFirstLine(HttpResponseLayer* httpResponse, HttpVersion version, + const HttpResponseStatusCode& statusCode); HttpResponseLayer* m_HttpResponse; HttpVersion m_Version; @@ -815,4 +885,4 @@ namespace pcpp HttpResponseFirstLineException m_Exception; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/IPLayer.h b/Packet++/header/IPLayer.h index 51d4670f31..b65f4217a7 100644 --- a/Packet++/header/IPLayer.h +++ b/Packet++/header/IPLayer.h @@ -21,7 +21,9 @@ namespace pcpp class IPLayer { protected: - IPLayer() {} + IPLayer() + {} + public: /** * An abstract method to get the source IP address @@ -38,6 +40,7 @@ namespace pcpp /** * An empty destructor */ - virtual ~IPLayer() {} + virtual ~IPLayer() + {} }; -} +} // namespace pcpp diff --git a/Packet++/header/IPReassembly.h b/Packet++/header/IPReassembly.h index a666464e72..0d64299229 100644 --- a/Packet++/header/IPReassembly.h +++ b/Packet++/header/IPReassembly.h @@ -8,32 +8,36 @@ /** * @file - * This file includes an implementation of IP reassembly mechanism (a.k.a IP de-fragmentation), which is the mechanism of assembling IPv4 or IPv6 - * fragments back into one whole packet. As the previous sentence imply, this module supports both IPv4 and IPv6 reassembly which means - * the same pcpp#IPReassembly instance can reassemble both IPv4 and IPv6 fragments. You can read more about IP fragmentation here: - * https://en.wikipedia.org/wiki/IP_fragmentation.
- * The API is rather simple and contains one main method: pcpp#IPReassembly#processPacket() which gets a fragment packet as a parameter, does the - * reassembly and returns a fully reassembled packet when done.
+ * This file includes an implementation of IP reassembly mechanism (a.k.a IP de-fragmentation), which is the mechanism + * of assembling IPv4 or IPv6 fragments back into one whole packet. As the previous sentence imply, this module supports + * both IPv4 and IPv6 reassembly which means the same pcpp#IPReassembly instance can reassemble both IPv4 and IPv6 + * fragments. You can read more about IP fragmentation here: https://en.wikipedia.org/wiki/IP_fragmentation.
The API + * is rather simple and contains one main method: pcpp#IPReassembly#processPacket() which gets a fragment packet as a + * parameter, does the reassembly and returns a fully reassembled packet when done.
* * The logic works as follows: - * - There is an internal map that stores the reassembly data for each packet. The key to this map, meaning the way to uniquely associate a - * fragment to a (reassembled) packet is the triplet of source IP, destination IP and IP ID (for IPv4) or Fragment ID (for IPv6) + * - There is an internal map that stores the reassembly data for each packet. The key to this map, meaning the way to + * uniquely associate a fragment to a (reassembled) packet is the triplet of source IP, destination IP and IP ID (for + * IPv4) or Fragment ID (for IPv6) * - When the first fragment arrives a new record is created in the map and the fragment data is copied - * - With each fragment arriving the fragment data is copied right after the previous fragment and the reassembled packet is gradually being built - * - When the last fragment arrives the packet is fully reassembled and returned to the user. Since all fragment data is copied, the packet pointer - * returned to the user has to be freed by the user when done using it - * - The logic supports out-of-order fragments, meaning that a fragment which arrives out-of-order, its data will be copied to a list of out-of-order - * fragments where it waits for its turn. This list is observed each time a new fragment arrives to see if the next fragment(s) wait(s) in this - * list + * - With each fragment arriving the fragment data is copied right after the previous fragment and the reassembled + * packet is gradually being built + * - When the last fragment arrives the packet is fully reassembled and returned to the user. Since all fragment data is + * copied, the packet pointer returned to the user has to be freed by the user when done using it + * - The logic supports out-of-order fragments, meaning that a fragment which arrives out-of-order, its data will be + * copied to a list of out-of-order fragments where it waits for its turn. This list is observed each time a new + * fragment arrives to see if the next fragment(s) wait(s) in this list * - If a non-IP packet arrives it's returned as is to the user * - If a non-fragment packet arrives it's returned as is to the user * - * In order to limit the amount of memory used by this mechanism there is a limit to the number of concurrent packets being reassembled. - * The default limit is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE but the user can set any value (determined in pcpp#IPReassembly - * c'tor). Once capacity (the number of concurrent reassembled packets) exceeds this number, the packet that was least recently used will be - * dropped from the map along with all the data that was reassembled so far. This means that if the next fragment from this packet suddenly - * appears it will be treated as a new reassembled packet (which will create another record in the map). The user can be notified when - * reassembled packets are removed from the map by registering to the pcpp#IPReassembly#OnFragmentsClean callback in pcpp#IPReassembly c'tor + * In order to limit the amount of memory used by this mechanism there is a limit to the number of concurrent packets + * being reassembled. The default limit is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE but the user can set any + * value (determined in pcpp#IPReassembly c'tor). Once capacity (the number of concurrent reassembled packets) exceeds + * this number, the packet that was least recently used will be dropped from the map along with all the data that was + * reassembled so far. This means that if the next fragment from this packet suddenly appears it will be treated as a + * new reassembled packet (which will create another record in the map). The user can be notified when reassembled + * packets are removed from the map by registering to the pcpp#IPReassembly#OnFragmentsClean callback in + * pcpp#IPReassembly c'tor */ /** @@ -43,35 +47,35 @@ namespace pcpp { - /** IP reassembly mechanism default capacity. If concurrent packet volume exceeds this numbers, packets will start to be dropped in - * a LRU manner - */ - #define PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE 500000 +/** IP reassembly mechanism default capacity. If concurrent packet volume exceeds this numbers, packets will start to be + * dropped in a LRU manner + */ +#define PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE 500000 /** * @class IPReassembly * Contains the IP reassembly (a.k.a IP de-fragmentation) mechanism. Encapsulates both IPv4 and IPv6 reassembly. * Please refer to the documentation at the top of IPReassembly.h * to understand how this mechanism works. The main APIs are: - * - IPReassembly#processPacket() - process a fragment. This is the main method which should be called whenever a new fragment arrives. - * This method processes the fragment, runs the reassembly logic and returns the result packet when it's fully reassembled - * - IPReassembly#getCurrentPacket() - get the reassembled data that is currently available, even if reassembly process is not yet completed - * - IPReassembly#removePacket() - remove all data that is currently stored for a packet, including the reassembled data that was gathered - * so far + * - IPReassembly#processPacket() - process a fragment. This is the main method which should be called whenever a + * new fragment arrives. This method processes the fragment, runs the reassembly logic and returns the result + * packet when it's fully reassembled + * - IPReassembly#getCurrentPacket() - get the reassembled data that is currently available, even if reassembly + * process is not yet completed + * - IPReassembly#removePacket() - remove all data that is currently stored for a packet, including the reassembled + * data that was gathered so far */ class IPReassembly { public: - /** * @class PacketKey - * An abstract class that represents a key that can uniquely identify an IP packet. This class cannot be instantiated or copied, - * only its derived classes can + * An abstract class that represents a key that can uniquely identify an IP packet. This class cannot be + * instantiated or copied, only its derived classes can */ class PacketKey { public: - /** * A default virtual d'tor */ @@ -100,19 +104,19 @@ namespace pcpp PacketKey(const PacketKey& other) = default; }; - /** * @class IPv4PacketKey - * Represents a key that can uniquely identify IPv4 packets. The key comprises of source IPv4 address, dest IPv4 address and IP ID + * Represents a key that can uniquely identify IPv4 packets. The key comprises of source IPv4 address, dest IPv4 + * address and IP ID */ class IPv4PacketKey : public PacketKey { public: - /** * A default c'tor which zeros all members */ - IPv4PacketKey() : m_IpID(0), m_SrcIP(IPv4Address::Zero), m_DstIP(IPv4Address::Zero) { } + IPv4PacketKey() : m_IpID(0), m_SrcIP(IPv4Address::Zero), m_DstIP(IPv4Address::Zero) + {} /** * A c'tor that sets values in each one of the members @@ -120,13 +124,17 @@ namespace pcpp * @param[in] srcip Source IPv4 address * @param[in] dstip Dest IPv4 address */ - IPv4PacketKey(uint16_t ipid, IPv4Address srcip, IPv4Address dstip) : m_IpID(ipid), m_SrcIP(srcip), m_DstIP(dstip) { } + IPv4PacketKey(uint16_t ipid, IPv4Address srcip, IPv4Address dstip) + : m_IpID(ipid), m_SrcIP(srcip), m_DstIP(dstip) + {} /** * A copy c'tor for this class * @param[in] other The instance to copy from */ - IPv4PacketKey(const IPv4PacketKey& other) : PacketKey(other), m_IpID(other.m_IpID), m_SrcIP(other.m_SrcIP), m_DstIP(other.m_DstIP) { } + IPv4PacketKey(const IPv4PacketKey& other) + : PacketKey(other), m_IpID(other.m_IpID), m_SrcIP(other.m_SrcIP), m_DstIP(other.m_DstIP) + {} /** * Assignment operator for this class @@ -143,36 +151,53 @@ namespace pcpp /** * @return IP ID value */ - uint16_t getIpID() const { return m_IpID; } + uint16_t getIpID() const + { + return m_IpID; + } /** * @return Source IP address */ - IPv4Address getSrcIP() const { return m_SrcIP; } + IPv4Address getSrcIP() const + { + return m_SrcIP; + } /** * @return Dest IP address */ - IPv4Address getDstIP() const { return m_DstIP; } + IPv4Address getDstIP() const + { + return m_DstIP; + } /** * Set IP ID * @param[in] ipID IP ID value to set */ - void setIpID(uint16_t ipID) { m_IpID = ipID; } + void setIpID(uint16_t ipID) + { + m_IpID = ipID; + } /** * Set source IPv4 address * @param[in] srcIP Source IP to set */ - void setSrcIP(const IPv4Address& srcIP) { m_SrcIP = srcIP; } + void setSrcIP(const IPv4Address& srcIP) + { + m_SrcIP = srcIP; + } /** * Set dest IPv4 address * @param[in] dstIP Dest IP to set */ - void setDstIP(const IPv4Address& dstIP) { m_DstIP = dstIP; } - + void setDstIP(const IPv4Address& dstIP) + { + m_DstIP = dstIP; + } // implement abstract methods @@ -181,9 +206,15 @@ namespace pcpp /** * @return pcpp#IPv4 protocol */ - ProtocolType getProtocolType() const { return IPv4; } + ProtocolType getProtocolType() const + { + return IPv4; + } - PacketKey* clone() const { return new IPv4PacketKey(*this); } + PacketKey* clone() const + { + return new IPv4PacketKey(*this); + } private: uint16_t m_IpID; @@ -191,20 +222,19 @@ namespace pcpp IPv4Address m_DstIP; }; - /** * @class IPv6PacketKey - * Represents a key that can uniquely identify IPv6 fragment packets. The key comprises of source IPv6 address, dest IPv6 address - * and fragment ID (which resides in the IPv6 fragmentation extension) + * Represents a key that can uniquely identify IPv6 fragment packets. The key comprises of source IPv6 address, + * dest IPv6 address and fragment ID (which resides in the IPv6 fragmentation extension) */ class IPv6PacketKey : public PacketKey { public: - /** * A default c'tor which zeros all members */ - IPv6PacketKey() : m_FragmentID(0), m_SrcIP(IPv6Address::Zero), m_DstIP(IPv6Address::Zero) { } + IPv6PacketKey() : m_FragmentID(0), m_SrcIP(IPv6Address::Zero), m_DstIP(IPv6Address::Zero) + {} /** * A c'tor that sets values in each one of the members @@ -212,13 +242,17 @@ namespace pcpp * @param[in] srcip Source IPv6 address * @param[in] dstip Dest IPv6 address */ - IPv6PacketKey(uint32_t fragmentID, IPv6Address srcip, IPv6Address dstip) : m_FragmentID(fragmentID), m_SrcIP(srcip), m_DstIP(dstip) { } + IPv6PacketKey(uint32_t fragmentID, IPv6Address srcip, IPv6Address dstip) + : m_FragmentID(fragmentID), m_SrcIP(srcip), m_DstIP(dstip) + {} /** * A copy c'tor for this class * @param[in] other The instance to copy from */ - IPv6PacketKey(const IPv6PacketKey& other) : PacketKey(other), m_FragmentID(other.m_FragmentID), m_SrcIP(other.m_SrcIP), m_DstIP(other.m_DstIP) { } + IPv6PacketKey(const IPv6PacketKey& other) + : PacketKey(other), m_FragmentID(other.m_FragmentID), m_SrcIP(other.m_SrcIP), m_DstIP(other.m_DstIP) + {} /** * Assignment operator for this class @@ -235,36 +269,53 @@ namespace pcpp /** * @return Fragment ID value */ - uint32_t getFragmentID() const { return m_FragmentID; } + uint32_t getFragmentID() const + { + return m_FragmentID; + } /** * @return Source IP address */ - IPv6Address getSrcIP() const { return m_SrcIP; } + IPv6Address getSrcIP() const + { + return m_SrcIP; + } /** * @return Dest IP address */ - IPv6Address getDstIP() const { return m_DstIP; } + IPv6Address getDstIP() const + { + return m_DstIP; + } /** * Set fragment ID * @param[in] fragID Fragment ID value to set */ - void setFragmentID(uint32_t fragID) { m_FragmentID = fragID; } + void setFragmentID(uint32_t fragID) + { + m_FragmentID = fragID; + } /** * Set source IPv6 address * @param[in] srcIP Source IP to set */ - void setSrcIP(const IPv6Address& srcIP) { m_SrcIP = srcIP; } + void setSrcIP(const IPv6Address& srcIP) + { + m_SrcIP = srcIP; + } /** * Set dest IPv6 address * @param[in] dstIP Dest IP to set */ - void setDstIP(const IPv6Address& dstIP) { m_DstIP = dstIP; } - + void setDstIP(const IPv6Address& dstIP) + { + m_DstIP = dstIP; + } // implement abstract methods @@ -273,9 +324,15 @@ namespace pcpp /** * @return pcpp#IPv6 protocol */ - ProtocolType getProtocolType() const { return IPv6; } + ProtocolType getProtocolType() const + { + return IPv6; + } - PacketKey* clone() const { return new IPv6PacketKey(*this); } + PacketKey* clone() const + { + return new IPv6PacketKey(*this); + } private: uint32_t m_FragmentID; @@ -283,14 +340,15 @@ namespace pcpp IPv6Address m_DstIP; }; - /** * @typedef OnFragmentsClean - * The IP reassembly mechanism has a certain capacity of concurrent packets it can handle. This capacity is determined in its c'tor - * (default value is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE). When traffic volume exceeds this capacity the mechanism starts - * dropping packets in a LRU manner (least recently used are dropped first). Whenever a packet is dropped this callback is fired + * The IP reassembly mechanism has a certain capacity of concurrent packets it can handle. This capacity is + * determined in its c'tor (default value is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE). When traffic + * volume exceeds this capacity the mechanism starts dropping packets in a LRU manner (least recently used are + * dropped first). Whenever a packet is dropped this callback is fired * @param[in] key A pointer to the identifier of the packet that is being dropped - * @param[in] userCookie A pointer to the cookie provided by the user in IPReassemby c'tor (or NULL if no cookie provided) + * @param[in] userCookie A pointer to the cookie provided by the user in IPReassemby c'tor (or NULL if no cookie + * provided) */ typedef void (*OnFragmentsClean)(const PacketKey* key, void* userCookie); @@ -300,31 +358,37 @@ namespace pcpp enum ReassemblyStatus { /** The processed packet isn't of type IPv4 or IPv6 */ - NON_IP_PACKET = 0x00, + NON_IP_PACKET = 0x00, /** The processed packet isn't a fragment */ - NON_FRAGMENT = 0x01, + NON_FRAGMENT = 0x01, /** The processed fragment is the first fragment */ - FIRST_FRAGMENT = 0x02, + FIRST_FRAGMENT = 0x02, /** The processed fragment is a fragment (but not the first one) */ - FRAGMENT = 0x04, + FRAGMENT = 0x04, /** The processed fragment is not the fragment that was expected at this time */ OUT_OF_ORDER_FRAGMENT = 0x08, - /** The processed fragment is malformed, meaning a fragment which has offset of zero but isn't the first fragment */ - MALFORMED_FRAGMENT = 0x10, + /** The processed fragment is malformed, meaning a fragment which has offset of zero but isn't the first + * fragment */ + MALFORMED_FRAGMENT = 0x10, /** Packet is now fully reassembled */ - REASSEMBLED = 0x20 + REASSEMBLED = 0x20 }; /** * A c'tor for this class. * @param[in] onFragmentsCleanCallback The callback to be called when packets are dropped due to capacity limit. - * Please read more about capacity limit in IPReassembly.h file description. This parameter is optional, default value is NULL (no callback) - * @param[in] callbackUserCookie A pointer to an object provided by the user. This pointer will be returned when invoking the - * onFragmentsCleanCallback. This parameter is optional, default cookie is NULL - * @param[in] maxPacketsToStore Set the capacity limit of the IP reassembly mechanism. Default capacity is #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE + * Please read more about capacity limit in IPReassembly.h file description. This parameter is optional, default + * value is NULL (no callback) + * @param[in] callbackUserCookie A pointer to an object provided by the user. This pointer will be returned when + * invoking the onFragmentsCleanCallback. This parameter is optional, default cookie is NULL + * @param[in] maxPacketsToStore Set the capacity limit of the IP reassembly mechanism. Default capacity is + * #PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE */ - explicit IPReassembly(OnFragmentsClean onFragmentsCleanCallback = NULL, void *callbackUserCookie = NULL, size_t maxPacketsToStore = PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE) - : m_PacketLRU(maxPacketsToStore), m_OnFragmentsCleanCallback(onFragmentsCleanCallback), m_CallbackUserCookie(callbackUserCookie) {} + explicit IPReassembly(OnFragmentsClean onFragmentsCleanCallback = NULL, void* callbackUserCookie = NULL, + size_t maxPacketsToStore = PCPP_IP_REASSEMBLY_DEFAULT_MAX_PACKETS_TO_STORE) + : m_PacketLRU(maxPacketsToStore), m_OnFragmentsCleanCallback(onFragmentsCleanCallback), + m_CallbackUserCookie(callbackUserCookie) + {} /** * A d'tor for this class @@ -332,83 +396,101 @@ namespace pcpp ~IPReassembly(); /** - * The main API that drives IPReassembly. This method should be called whenever a fragment arrives. This method finds the relevant - * packet this fragment belongs to and runs the IP reassembly logic that is described in IPReassembly.h. - * @param[in] fragment The fragment to process (IPv4 or IPv6). Please notice that the reassembly logic doesn't change or manipulate - * this object in any way. All of its data is copied to internal structures and manipulated there - * @param[out] status An indication of the packet reassembly status following the processing of this fragment. Possible values are: + * The main API that drives IPReassembly. This method should be called whenever a fragment arrives. This method + * finds the relevant packet this fragment belongs to and runs the IP reassembly logic that is described in + * IPReassembly.h. + * @param[in] fragment The fragment to process (IPv4 or IPv6). Please notice that the reassembly logic doesn't + * change or manipulate this object in any way. All of its data is copied to internal structures and manipulated + * there + * @param[out] status An indication of the packet reassembly status following the processing of this fragment. + * Possible values are: * - The input fragment is not a IPv4 or IPv6 packet * - The input fragment is not a IPv4 or IPv6 fragment packet * - The input fragment is the first fragment of the packet * - The input fragment is not the first or last fragment - * - The input fragment came out-of-order, meaning that wasn't the fragment that was currently expected (it's data is copied to - * the out-of-order fragment list) + * - The input fragment came out-of-order, meaning that wasn't the fragment that was currently expected (it's + * data is copied to the out-of-order fragment list) * - The input fragment is malformed and will be ignored - * - The input fragment is the last one and the packet is now fully reassembled. In this case the return value will contain - * a pointer to the reassembled packet - * @param[in] parseUntil Optional parameter. Parse the reassembled packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a - * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Note that setting this to a protocol which doesn't - * include the IP-Layer will result in IPReassembly not finding the IP-Layer and thus failing to work properly. Default value is ::UnknownProtocol which means - * don't take this parameter into account - * @param[in] parseUntilLayer Optional parameter. Parse the reassembled packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to - * parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet. - * Note that setting this value to OsiModelPhysicalLayer will result in IPReassembly not finding the IP-layer and thus failing to work properly. - * Default value is ::OsiModelLayerUnknown which means don't take this parameter into account + * - The input fragment is the last one and the packet is now fully reassembled. In this case the return value + * will contain a pointer to the reassembled packet + * @param[in] parseUntil Optional parameter. Parse the reassembled packet until you reach a certain protocol + * (inclusive). Can be useful for cases when you need to parse only up to a certain layer and want to avoid the + * performance impact and memory consumption of parsing the whole packet. Note that setting this to a protocol + * which doesn't include the IP-Layer will result in IPReassembly not finding the IP-Layer and thus failing to + * work properly. Default value is ::UnknownProtocol which means don't take this parameter into account + * @param[in] parseUntilLayer Optional parameter. Parse the reassembled packet until you reach a certain layer + * in the OSI model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer + * (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the + * whole packet. Note that setting this value to OsiModelPhysicalLayer will result in IPReassembly not finding + * the IP-layer and thus failing to work properly. Default value is ::OsiModelLayerUnknown which means don't + * take this parameter into account * @return - * - If the input fragment isn't an IPv4/IPv6 packet or if it isn't an IPv4/IPv6 fragment, the return value is a pointer to the input fragment - * - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled packet is - * returned. Notice it's the user's responsibility to free this pointer when done using it + * - If the input fragment isn't an IPv4/IPv6 packet or if it isn't an IPv4/IPv6 fragment, the return value is a + * pointer to the input fragment + * - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled + * packet is returned. Notice it's the user's responsibility to free this pointer when done using it * - If the reassembled packet isn't ready then NULL is returned */ - Packet* processPacket(Packet* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); + Packet* processPacket(Packet* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, + OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /** - * The main API that drives IPReassembly. This method should be called whenever a fragment arrives. This method finds the relevant - * packet this fragment belongs to and runs the IPv4 reassembly logic that is described in IPReassembly.h. - * @param[in] fragment The fragment to process (IPv4 or IPv6). Please notice that the reassembly logic doesn't change or manipulate - * this object in any way. All of its data is copied to internal structures and manipulated there - * @param[out] status An indication of the packet reassembly status following the processing of this fragment. Possible values are: + * The main API that drives IPReassembly. This method should be called whenever a fragment arrives. This method + * finds the relevant packet this fragment belongs to and runs the IPv4 reassembly logic that is described in + * IPReassembly.h. + * @param[in] fragment The fragment to process (IPv4 or IPv6). Please notice that the reassembly logic doesn't + * change or manipulate this object in any way. All of its data is copied to internal structures and manipulated + * there + * @param[out] status An indication of the packet reassembly status following the processing of this fragment. + * Possible values are: * - The input fragment is not a IPv4 or IPv6 packet * - The input fragment is not a IPv4 or IPv6 fragment packet * - The input fragment is the first fragment of the packet * - The input fragment is not the first or last fragment - * - The input fragment came out-of-order, meaning that wasn't the fragment that was currently expected (it's data is copied to - * the out-of-order fragment list) + * - The input fragment came out-of-order, meaning that wasn't the fragment that was currently expected (it's + * data is copied to the out-of-order fragment list) * - The input fragment is malformed and will be ignored - * - The input fragment is the last one and the packet is now fully reassembled. In this case the return value will contain - * a pointer to the reassembled packet - * @param[in] parseUntil Optional parameter. Parse the raw and reassembled packets until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a - * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Note that setting this to a protocol which doesn't - * include the IP-Layer will result in IPReassembly not finding the IP-Layer and thus failing to work properly. Default value is ::UnknownProtocol which means - * don't take this parameter into account - * @param[in] parseUntilLayer Optional parameter. Parse the raw and reassembled packets until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to - * parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet. - * Note that setting this value to OsiModelPhysicalLayer will result in IPReassembly not finding the IP-layer and thus failing to work properly. - *Default value is ::UnknownProtocol which means don't take this parameter into account - * Default value is ::OsiModelLayerUnknown which means don't take this parameter into account + * - The input fragment is the last one and the packet is now fully reassembled. In this case the return value + * will contain a pointer to the reassembled packet + * @param[in] parseUntil Optional parameter. Parse the raw and reassembled packets until you reach a certain + * protocol (inclusive). Can be useful for cases when you need to parse only up to a certain layer and want to + * avoid the performance impact and memory consumption of parsing the whole packet. Note that setting this to a + * protocol which doesn't include the IP-Layer will result in IPReassembly not finding the IP-Layer and thus + * failing to work properly. Default value is ::UnknownProtocol which means don't take this parameter into + * account + * @param[in] parseUntilLayer Optional parameter. Parse the raw and reassembled packets until you reach a + * certain layer in the OSI model (inclusive). Can be useful for cases when you need to parse only up to a + * certain OSI layer (for example transport layer) and want to avoid the performance impact and memory + * consumption of parsing the whole packet. Note that setting this value to OsiModelPhysicalLayer will result in + * IPReassembly not finding the IP-layer and thus failing to work properly. Default value is ::UnknownProtocol + * which means don't take this parameter into account Default value is ::OsiModelLayerUnknown which means don't + * take this parameter into account * @return - * - If the input fragment isn't an IPv4/IPv6 packet or if it isn't an IPv4/IPv6 fragment, the return value is a pointer to a Packet object - * wrapping the input fragment RawPacket object. It's the user responsibility to free this instance - * - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled packet is - * returned. Notice it's the user's responsibility to free this pointer when done using it + * - If the input fragment isn't an IPv4/IPv6 packet or if it isn't an IPv4/IPv6 fragment, the return value is a + * pointer to a Packet object wrapping the input fragment RawPacket object. It's the user responsibility to + * free this instance + * - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled + * packet is returned. Notice it's the user's responsibility to free this pointer when done using it * - If the reassembled packet isn't ready then NULL is returned */ - Packet* processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); + Packet* processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, + OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /** - * Get a partially reassembled packet. This method returns all the reassembled data that was gathered so far which is obviously not - * a fully reassembled packet (otherwise it would have returned by processPacket()). Notice all data is being copied so the user is - * responsible to free the returned Packet object when done using it. Notice#2 - calling this method doesn't interfere with the - * reassembly of this packet - all internal structures and data remain + * Get a partially reassembled packet. This method returns all the reassembled data that was gathered so far + * which is obviously not a fully reassembled packet (otherwise it would have returned by processPacket()). + * Notice all data is being copied so the user is responsible to free the returned Packet object when done using + * it. Notice#2 - calling this method doesn't interfere with the reassembly of this packet - all internal + * structures and data remain * @param[in] key The identifiers of the packet to return - * @return A pointer to a Packet object containing the partially reassembled packet. Notice the user is responsible to free this - * object when done using it + * @return A pointer to a Packet object containing the partially reassembled packet. Notice the user is + * responsible to free this object when done using it */ Packet* getCurrentPacket(const PacketKey& key); /** - * Remove a partially reassembled packet from all internal structures. That means that if another fragment of this packet appears - * it will be treated as a new packet + * Remove a partially reassembled packet from all internal structures. That means that if another fragment of + * this packet appears it will be treated as a new packet * @param[in] key The identifiers of the packet to remove */ void removePacket(const PacketKey& key); @@ -416,23 +498,37 @@ namespace pcpp /** * Get the maximum capacity as determined in the c'tor */ - size_t getMaxCapacity() const { return m_PacketLRU.getMaxSize(); } + size_t getMaxCapacity() const + { + return m_PacketLRU.getMaxSize(); + } /** * Get the current number of packets being processed */ - size_t getCurrentCapacity() const { return m_FragmentMap.size(); } + size_t getCurrentCapacity() const + { + return m_FragmentMap.size(); + } private: - struct IPFragment { uint16_t fragmentOffset; bool lastFragment; uint8_t* fragmentData; size_t fragmentDataLen; - IPFragment() { fragmentOffset = 0; lastFragment = false; fragmentData = NULL; fragmentDataLen = 0; } - ~IPFragment() { delete [] fragmentData; } + IPFragment() + { + fragmentOffset = 0; + lastFragment = false; + fragmentData = NULL; + fragmentDataLen = 0; + } + ~IPFragment() + { + delete[] fragmentData; + } }; struct IPFragmentData @@ -443,8 +539,22 @@ namespace pcpp uint32_t fragmentID; PacketKey* packetKey; PointerVector outOfOrderFragments; - IPFragmentData(PacketKey* pktKey, uint32_t fragId) { currentOffset = 0; data = NULL; deleteData = true; fragmentID = fragId; packetKey = pktKey; } - ~IPFragmentData() { delete packetKey; if (deleteData && data != NULL) { delete data; } } + IPFragmentData(PacketKey* pktKey, uint32_t fragId) + { + currentOffset = 0; + data = NULL; + deleteData = true; + fragmentID = fragId; + packetKey = pktKey; + } + ~IPFragmentData() + { + delete packetKey; + if (deleteData && data != NULL) + { + delete data; + } + } }; LRUList m_PacketLRU; @@ -456,4 +566,4 @@ namespace pcpp bool matchOutOfOrderFragments(IPFragmentData* fragData); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/IPSecLayer.h b/Packet++/header/IPSecLayer.h index 4c2c3c9169..ef116654b4 100644 --- a/Packet++/header/IPSecLayer.h +++ b/Packet++/header/IPSecLayer.h @@ -51,19 +51,27 @@ namespace pcpp class AuthenticationHeaderLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - AuthenticationHeaderLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = AuthenticationHeader; } + AuthenticationHeaderLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = AuthenticationHeader; + } /** - * Get a pointer to the raw AH header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the raw AH header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the ipsec_authentication_header */ - ipsec_authentication_header* getAHHeader() const { return (ipsec_authentication_header*)m_Data; } + ipsec_authentication_header* getAHHeader() const + { + return (ipsec_authentication_header*)m_Data; + } /** * @return The Security Parameters Index (SPI) field value @@ -103,29 +111,36 @@ namespace pcpp /** * @return The size of the AH header */ - size_t getHeaderLen() const { return 4*(getAHHeader()->payloadLen + 2); } + size_t getHeaderLen() const + { + return 4 * (getAHHeader()->payloadLen + 2); + } /** - * Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. Otherwise sets PayloadLayer + * Currently identifies the following next layers: UdpLayer, TcpLayer, IPv4Layer, IPv6Layer and ESPLayer. + * Otherwise sets PayloadLayer */ void parseNextLayer(); /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } private: // this layer supports parsing only - AuthenticationHeaderLayer() {} + AuthenticationHeaderLayer() + {} }; - - /** * @class ESPLayer * Represents an IPSec Encapsulating Security Payload (ESP) layer @@ -133,15 +148,22 @@ namespace pcpp class ESPLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - ESPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ESP; } + ESPLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = ESP; + } - ipsec_esp* getESPHeader() const { return (ipsec_esp*)m_Data; } + ipsec_esp* getESPHeader() const + { + return (ipsec_esp*)m_Data; + } /** * @return The Security Parameters Index (SPI) field value @@ -166,7 +188,10 @@ namespace pcpp /** * @return The size of the ESP header (8 bytes) */ - size_t getHeaderLen() const { return sizeof(ipsec_esp); } + size_t getHeaderLen() const + { + return sizeof(ipsec_esp); + } /** * The payload of an ESP layer is encrypted, hence the next layer is always a generic payload (PayloadLayer) @@ -176,18 +201,22 @@ namespace pcpp /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelTransportLayer; + } private: // this layer supports parsing only - ESPLayer() {} + ESPLayer() + {} }; - // implementation of inline methods bool AuthenticationHeaderLayer::isDataValid(const uint8_t* data, size_t dataLen) @@ -206,4 +235,4 @@ namespace pcpp { return data && dataLen >= sizeof(ipsec_esp); } -} +} // namespace pcpp diff --git a/Packet++/header/IPv4Layer.h b/Packet++/header/IPv4Layer.h index 7e1e826333..4203992109 100644 --- a/Packet++/header/IPv4Layer.h +++ b/Packet++/header/IPv4Layer.h @@ -25,24 +25,26 @@ namespace pcpp { #if (BYTE_ORDER == LITTLE_ENDIAN) /** IP header length, has the value of 5 for IPv4 */ - uint8_t internetHeaderLength:4, - /** IP version number, has the value of 4 for IPv4 */ - ipVersion:4; + uint8_t internetHeaderLength : 4, + /** IP version number, has the value of 4 for IPv4 */ + ipVersion : 4; #else /** IP version number, has the value of 4 for IPv4 */ - uint8_t ipVersion:4, - /** IP header length, has the value of 5 for IPv4 */ - internetHeaderLength:4; + uint8_t ipVersion : 4, + /** IP header length, has the value of 5 for IPv4 */ + internetHeaderLength : 4; #endif /** type of service, same as Differentiated Services Code Point (DSCP)*/ uint8_t typeOfService; /** Entire packet (fragment) size, including header and data, in bytes */ uint16_t totalLength; - /** Identification field. Primarily used for uniquely identifying the group of fragments of a single IP datagram*/ + /** Identification field. Primarily used for uniquely identifying the group of fragments of a single IP + * datagram*/ uint16_t ipId; - /** Fragment offset field, measured in units of eight-byte blocks (64 bits) */ + /** Fragment offset field, measured in units of eight-byte blocks (64 bits) */ uint16_t fragmentOffset; - /** An eight-bit time to live field helps prevent datagrams from persisting (e.g. going in circles) on an internet. In practice, the field has become a hop count */ + /** An eight-bit time to live field helps prevent datagrams from persisting (e.g. going in circles) on an + * internet. In practice, the field has become a hop count */ uint8_t timeToLive; /** Defines the protocol used in the data portion of the IP datagram. Must be one of ::IPProtocolTypes */ uint8_t protocol; @@ -107,7 +109,6 @@ namespace pcpp PACKETPP_IPPROTO_MAX }; - /** * An enum for supported IPv4 option types */ @@ -157,12 +158,13 @@ namespace pcpp IPV4OPT_Unknown }; -#define PCPP_IP_DONT_FRAGMENT 0x40 +#define PCPP_IP_DONT_FRAGMENT 0x40 #define PCPP_IP_MORE_FRAGMENTS 0x20 /** * @struct IPv4TimestampOptionValue - * A struct representing a parsed value of the IPv4 timestamp option. This struct is used returned in IPv4OptionData#getTimestampOptionValue() method + * A struct representing a parsed value of the IPv4 timestamp option. This struct is used returned in + * IPv4OptionData#getTimestampOptionValue() method */ struct IPv4TimestampOptionValue { @@ -191,10 +193,12 @@ namespace pcpp std::vector ipAddresses; /** The default constructor */ - IPv4TimestampOptionValue() : type(IPv4TimestampOptionValue::Unknown) {} + IPv4TimestampOptionValue() : type(IPv4TimestampOptionValue::Unknown) + {} /** - * Clear the structure. Clean the timestamps and IP addresses vectors and set the type as IPv4TimestampOptionValue#Unknown + * Clear the structure. Clean the timestamps and IP addresses vectors and set the type as + * IPv4TimestampOptionValue#Unknown */ void clear() { @@ -204,7 +208,6 @@ namespace pcpp } }; - /** * @class IPv4Option * A wrapper class for IPv4 options. This class does not create or modify IPv4 option records, but rather @@ -213,22 +216,25 @@ namespace pcpp class IPv4Option : public TLVRecord { public: - /** * A c'tor for this class that gets a pointer to the option raw data (byte array) * @param[in] optionRawData A pointer to the IPv4 option raw data */ - explicit IPv4Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { } + explicit IPv4Option(uint8_t* optionRawData) : TLVRecord(optionRawData) + {} /** * A d'tor for this class, currently does nothing */ - ~IPv4Option() { } + ~IPv4Option() + {} /** - * A method for parsing the IPv4 option value as a list of IPv4 addresses. This method is relevant only for certain types of IPv4 options which their value is a list of IPv4 addresses - * such as ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute, etc. This method returns a vector of the IPv4 addresses. Blank IP addresses - * (meaning zeroed addresses - 0.0.0.0) will not be added to the returned list. If some error occurs during the parsing or the value is invalid an empty vector is returned + * A method for parsing the IPv4 option value as a list of IPv4 addresses. This method is relevant only for + * certain types of IPv4 options which their value is a list of IPv4 addresses such as ::IPV4OPT_RecordRoute, + * ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute, etc. This method returns a vector of the IPv4 + * addresses. Blank IP addresses (meaning zeroed addresses - 0.0.0.0) will not be added to the returned list. If + * some error occurs during the parsing or the value is invalid an empty vector is returned * @return A vector of IPv4 addresses parsed from the IPv4 option value */ std::vector getValueAsIpList() const @@ -260,10 +266,12 @@ namespace pcpp } /** - * A method for parsing the IPv4 timestamp option value. This method is relevant only for IPv4 timestamp option. For other option types an empty result will be returned. - * The returned structure contains the timestamp value type (timestamp only, timestamp + IP addresses, etc.) as well as 2 vectors containing the list of timestamps and the list - * of IP addresses (if applicable for the timestamp value type). Blank timestamps or IP addresses (meaning zeroed values - timestamp=0 or IP address=0.0.0.0) will not be added to - * the lists. If some error occurs during the parsing or the value is invalid an empty result is returned + * A method for parsing the IPv4 timestamp option value. This method is relevant only for IPv4 timestamp option. + * For other option types an empty result will be returned. The returned structure contains the timestamp value + * type (timestamp only, timestamp + IP addresses, etc.) as well as 2 vectors containing the list of timestamps + * and the list of IP addresses (if applicable for the timestamp value type). Blank timestamps or IP addresses + * (meaning zeroed values - timestamp=0 or IP address=0.0.0.0) will not be added to the lists. If some error + * occurs during the parsing or the value is invalid an empty result is returned * @return A structured containing the IPv4 timestamp value */ IPv4TimestampOptionValue getTimestampOptionValue() const @@ -277,7 +285,7 @@ namespace pcpp if (getIPv4OptionType() != IPV4OPT_Timestamp) return res; - size_t dataSize = getDataSize(); + size_t dataSize = getDataSize(); if (dataSize < 2) return res; @@ -330,7 +338,8 @@ namespace pcpp if (tlvDataLen < sizeof(TLVRawData::recordType)) return false; - if (getIPv4OptionType(data) == static_cast(IPV4OPT_EndOfOptionsList) || data->recordType == static_cast(IPV4OPT_NOP)) + if (getIPv4OptionType(data) == static_cast(IPV4OPT_EndOfOptionsList) || + data->recordType == static_cast(IPV4OPT_NOP)) return true; return TLVRecord::canAssign(recordRawData, tlvDataLen); @@ -343,7 +352,8 @@ namespace pcpp if (m_Data == nullptr) return 0; - if (getIPv4OptionType() == static_cast(IPV4OPT_EndOfOptionsList) || m_Data->recordType == static_cast(IPV4OPT_NOP)) + if (getIPv4OptionType() == static_cast(IPV4OPT_EndOfOptionsList) || + m_Data->recordType == static_cast(IPV4OPT_NOP)) return sizeof(uint8_t); return static_cast(m_Data->recordLen); @@ -354,10 +364,11 @@ namespace pcpp if (m_Data == nullptr) return 0; - if (getIPv4OptionType() == static_cast(IPV4OPT_EndOfOptionsList) || m_Data->recordType == static_cast(IPV4OPT_NOP)) + if (getIPv4OptionType() == static_cast(IPV4OPT_EndOfOptionsList) || + m_Data->recordType == static_cast(IPV4OPT_NOP)) return 0; - return static_cast(m_Data->recordLen) - (2*sizeof(uint8_t)); + return static_cast(m_Data->recordLen) - (2 * sizeof(uint8_t)); } private: @@ -373,7 +384,6 @@ namespace pcpp } }; - /** * @class IPv4OptionBuilder * A class for building IPv4 option records. This builder receives the IPv4 option parameters in its c'tor, @@ -385,18 +395,20 @@ namespace pcpp bool m_BuilderParamsValid; public: - /** * A c'tor for building IPv4 options which their value is a byte array. The IPv4Option object can be later * retrieved by calling build() * @param[in] optionType IPv4 option type - * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way. - * For option types ::IPV4OPT_NOP and ::IPV4OPT_EndOfOptionsList this parameter is ignored (expected to be NULL) as these - * option types don't contain any data + * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in + * any way. For option types ::IPV4OPT_NOP and ::IPV4OPT_EndOfOptionsList this parameter is ignored (expected to + * be NULL) as these option types don't contain any data * @param[in] optionValueLen Option value length in bytes */ - IPv4OptionBuilder(IPv4OptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) : - TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) { m_BuilderParamsValid = true; } + IPv4OptionBuilder(IPv4OptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) + : TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) + { + m_BuilderParamsValid = true; + } /** * A c'tor for building IPv4 options which have a 2-byte value. The IPv4Option object can be later retrieved @@ -404,20 +416,24 @@ namespace pcpp * @param[in] optionType IPv4 option type * @param[in] optionValue A 2-byte option value */ - IPv4OptionBuilder(IPv4OptionTypes optionType, uint16_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) { m_BuilderParamsValid = true; } + IPv4OptionBuilder(IPv4OptionTypes optionType, uint16_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + { + m_BuilderParamsValid = true; + } /** * A c'tor for building IPv4 options which their value is a list of IPv4 addresses, for example: - * ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute. The IPv4Option object can be later retrieved - * by calling build() + * ::IPV4OPT_RecordRoute, ::IPV4OPT_StrictSourceRoute, ::IPV4OPT_LooseSourceRoute. The IPv4Option object can be + * later retrieved by calling build() * @param[in] optionType IPv4 option type * @param[in] ipList A vector of IPv4 addresses that will be used as the option value */ IPv4OptionBuilder(IPv4OptionTypes optionType, const std::vector& ipList); /** - * A c'tor for building IPv4 timestamp option (::IPV4OPT_Timestamp). The IPv4Option object can be later retrieved by calling build() + * A c'tor for building IPv4 timestamp option (::IPV4OPT_Timestamp). The IPv4Option object can be later + * retrieved by calling build() * @param[in] timestampValue The timestamp value to build the IPv4 option with */ explicit IPv4OptionBuilder(const IPv4TimestampOptionValue& timestampValue); @@ -429,7 +445,6 @@ namespace pcpp IPv4Option build() const; }; - /** * @class IPv4Layer * Represents an IPv4 protocol layer @@ -452,14 +467,14 @@ namespace pcpp * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in - * @param[in] setTotalLenAsDataLen When setting this value to "true" or when using the other c'tor, the layer data length is calculated - * from iphdr#totalLength field. When setting to "false" the data length is set as the value of dataLen parameter. Please notice that - * if iphdr#totalLength is equal to zero (which can happen in TCP Segmentation Offloading), this flag is ignored and the layer data - * length is calculated by the actual data captured on the wire + * @param[in] setTotalLenAsDataLen When setting this value to "true" or when using the other c'tor, the layer + * data length is calculated from iphdr#totalLength field. When setting to "false" the data length is set as the + * value of dataLen parameter. Please notice that if iphdr#totalLength is equal to zero (which can happen in TCP + * Segmentation Offloading), this flag is ignored and the layer data length is calculated by the actual data + * captured on the wire */ IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen); - /** * A constructor that allocates a new IPv4 header with empty fields */ @@ -478,53 +493,76 @@ namespace pcpp IPv4Layer(const IPv4Layer& other); /** - * An assignment operator that first delete all data from current layer and then copy the entire header from the other IPv4Layer (including IPv4 options) + * An assignment operator that first delete all data from current layer and then copy the entire header from the + * other IPv4Layer (including IPv4 options) */ IPv4Layer& operator=(const IPv4Layer& other); /** - * Get a pointer to the IPv4 header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the IPv4 header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref iphdr */ - iphdr* getIPv4Header() const { return (iphdr*)m_Data; } + iphdr* getIPv4Header() const + { + return (iphdr*)m_Data; + } /** * Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv4Address(), * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses * @return An IPAddress containing the source address */ - IPAddress getSrcIPAddress() const { return getSrcIPv4Address(); } + IPAddress getSrcIPAddress() const + { + return getSrcIPv4Address(); + } /** * Get the source IP address in the form of IPv4Address * @return An IPv4Address containing the source address */ - IPv4Address getSrcIPv4Address() const { return getIPv4Header()->ipSrc; } + IPv4Address getSrcIPv4Address() const + { + return getIPv4Header()->ipSrc; + } /** * Set the source IP address * @param[in] ipAddr The IP address to set */ - void setSrcIPv4Address(const IPv4Address& ipAddr) { getIPv4Header()->ipSrc = ipAddr.toInt(); } + void setSrcIPv4Address(const IPv4Address& ipAddr) + { + getIPv4Header()->ipSrc = ipAddr.toInt(); + } /** * Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv4Address(), * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses * @return An IPAddress containing the destination address */ - IPAddress getDstIPAddress() const { return getDstIPv4Address(); } + IPAddress getDstIPAddress() const + { + return getDstIPv4Address(); + } /** * Get the destination IP address in the form of IPv4Address * @return An IPv4Address containing the destination address */ - IPv4Address getDstIPv4Address() const { return getIPv4Header()->ipDst; } + IPv4Address getDstIPv4Address() const + { + return getIPv4Header()->ipDst; + } /** * Set the dest IP address * @param[in] ipAddr The IP address to set */ - void setDstIPv4Address(const IPv4Address& ipAddr) { getIPv4Header()->ipDst = ipAddr.toInt(); } + void setDstIPv4Address(const IPv4Address& ipAddr) + { + getIPv4Header()->ipDst = ipAddr.toInt(); + } /** * @return True if this packet is a fragment (in sense of IP fragmentation), false otherwise @@ -562,8 +600,8 @@ namespace pcpp IPv4Option getOption(IPv4OptionTypes option) const; /** - * @return The first IPv4 option in the packet. If the current layer contains no options the returned value will contain - * a logical NULL (IPv4Option#isNull() == true) + * @return The first IPv4 option in the packet. If the current layer contains no options the returned value will + * contain a logical NULL (IPv4Option#isNull() == true) */ IPv4Option getFirstOption() const; @@ -593,29 +631,31 @@ namespace pcpp /** * Add a new IPv4 option after an existing one * @param[in] optionBuilder An IPv4OptionBuilder object that contains the requested IPv4 option data to be added - * @param[in] prevOptionType The IPv4 option which the newly added option should come after. This is an optional parameter which - * gets a default value of ::IPV4OPT_Unknown if omitted, which means the new option will be added as the first option in the layer + * @param[in] prevOptionType The IPv4 option which the newly added option should come after. This is an optional + * parameter which gets a default value of ::IPV4OPT_Unknown if omitted, which means the new option will be + * added as the first option in the layer * @return A IPv4Option object containing the newly added IPv4 option data or logical NULL * (IPv4Option#isNull() == true) if addition failed. In case of a failure a corresponding error message will be * printed to log */ - IPv4Option addOptionAfter(const IPv4OptionBuilder& optionBuilder, IPv4OptionTypes prevOptionType = IPV4OPT_Unknown); + IPv4Option addOptionAfter(const IPv4OptionBuilder& optionBuilder, + IPv4OptionTypes prevOptionType = IPV4OPT_Unknown); /** * Remove an IPv4 option * @param[in] option The option type to remove - * @return True if option was removed successfully or false if option type wasn't found or failed to shorten the layer. If an option appears twice in the layer, its first instance - * will be removed + * @return True if option was removed successfully or false if option type wasn't found or failed to shorten the + * layer. If an option appears twice in the layer, its first instance will be removed */ bool removeOption(IPv4OptionTypes option); /** * Remove all IPv4 options from the layer - * @return True if options removed successfully or false if some error occurred (an appropriate error message will be printed to log) + * @return True if options removed successfully or false if some error occurred (an appropriate error message + * will be printed to log) */ bool removeAllOptions(); - // implement abstract methods /** @@ -637,20 +677,28 @@ namespace pcpp /** * @return Size of IPv4 header (including IPv4 options if exist) */ - size_t getHeaderLen() const { return static_cast(static_cast(getIPv4Header()->internetHeaderLength) * 4) + m_TempHeaderExtension; } + size_t getHeaderLen() const + { + return static_cast(static_cast(getIPv4Header()->internetHeaderLength) * 4) + + m_TempHeaderExtension; + } /** * Calculate the following fields: * - iphdr#ipVersion = 4; * - iphdr#totalLength = total packet length * - iphdr#headerChecksum = calculated - * - iphdr#protocol = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP + * - iphdr#protocol = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, ::PACKETPP_IPPROTO_UDP + * for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP */ void computeCalculateFields(); std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } /** * A static method that validates the input data @@ -666,14 +714,16 @@ namespace pcpp TLVRecordReader m_OptionReader; void copyLayerData(const IPv4Layer& other); - uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(iphdr); } + uint8_t* getOptionsBasePtr() const + { + return m_Data + sizeof(iphdr); + } IPv4Option addOptionAt(const IPv4OptionBuilder& optionBuilder, int offset); void adjustOptionsTrailer(size_t totalOptSize); void initLayer(); void initLayerInPacket(bool setTotalLenAsDataLen); }; - // implementation of inline methods bool IPv4Layer::isDataValid(const uint8_t* data, size_t dataLen) @@ -682,4 +732,4 @@ namespace pcpp return dataLen >= sizeof(iphdr) && hdr->ipVersion == 4 && hdr->internetHeaderLength >= 5; } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/IPv6Extensions.h b/Packet++/header/IPv6Extensions.h index 90dd9e4bb0..ebf94eb01f 100644 --- a/Packet++/header/IPv6Extensions.h +++ b/Packet++/header/IPv6Extensions.h @@ -16,15 +16,14 @@ namespace pcpp /** * @class IPv6Extension - * A base class for all supported IPv6 extensions. This class is abstract, meaning it cannot be instantiated or copied - * (has private c'tor and copy c'tor) + * A base class for all supported IPv6 extensions. This class is abstract, meaning it cannot be instantiated or + * copied (has private c'tor and copy c'tor) */ class IPv6Extension { friend class IPv6Layer; public: - /** * An enum representing all supported IPv6 extension types */ @@ -47,12 +46,18 @@ namespace pcpp /** * @return The size of extension in bytes, meaning (for most extensions): 8 * ([headerLen field] + 1) */ - virtual size_t getExtensionLen() const { return 8 * (getBaseHeader()->headerLen+1); } + virtual size_t getExtensionLen() const + { + return 8 * (getBaseHeader()->headerLen + 1); + } /** * @return The type of the extension */ - IPv6ExtensionType getExtensionType() const { return m_ExtType; } + IPv6ExtensionType getExtensionType() const + { + return m_ExtType; + } /** * A destructor for this class @@ -62,10 +67,12 @@ namespace pcpp /** * @return A pointer to the next header or NULL if the extension is the last one */ - IPv6Extension* getNextHeader() const { return m_NextHeader; } + IPv6Extension* getNextHeader() const + { + return m_NextHeader; + } protected: - struct ipv6_ext_base_header { uint8_t nextHeader; @@ -73,12 +80,16 @@ namespace pcpp }; // protected c'tor - IPv6Extension(IDataContainer* dataContainer, size_t offset) : - m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(dataContainer), m_Offset(offset), m_ShadowData(NULL) {} + IPv6Extension(IDataContainer* dataContainer, size_t offset) + : m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(dataContainer), m_Offset(offset), + m_ShadowData(NULL) + {} // protected empty c'tor - IPv6Extension() : - m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(NULL), m_Offset(0), m_ShadowData(NULL) {} + IPv6Extension() + : m_NextHeader(NULL), m_ExtType(IPv6ExtensionUnknown), m_DataContainer(NULL), m_Offset(0), + m_ShadowData(NULL) + {} // protected assignment operator IPv6Extension& operator=(const IPv6Extension& other); @@ -87,9 +98,15 @@ namespace pcpp void initShadowPtr(size_t size); - ipv6_ext_base_header* getBaseHeader() const { return (ipv6_ext_base_header*)getDataPtr(); } + ipv6_ext_base_header* getBaseHeader() const + { + return (ipv6_ext_base_header*)getDataPtr(); + } - void setNextHeader(IPv6Extension* nextHeader) { m_NextHeader = nextHeader; } + void setNextHeader(IPv6Extension* nextHeader) + { + m_NextHeader = nextHeader; + } IPv6Extension* m_NextHeader; IPv6ExtensionType m_ExtType; @@ -98,11 +115,8 @@ namespace pcpp IDataContainer* m_DataContainer; size_t m_Offset; uint8_t* m_ShadowData; - }; - - /** * @class IPv6FragmentationHeader * Represents an IPv6 fragmentation extension header and allows easy access to all fragmentation parameters @@ -112,7 +126,6 @@ namespace pcpp friend class IPv6Layer; public: - /** * @struct ipv6_frag_header * A struct representing IPv6 fragmentation header @@ -131,8 +144,8 @@ namespace pcpp }; /** - * A c'tor for creating a new IPv6 fragmentation extension object not bounded to a packet. Useful for adding new extensions to an - * IPv6 layer with IPv6Layer#addExtension() + * A c'tor for creating a new IPv6 fragmentation extension object not bounded to a packet. Useful for adding new + * extensions to an IPv6 layer with IPv6Layer#addExtension() * @param[in] fragId Fragmentation ID * @param[in] fragOffset Fragmentation offset * @param[in] lastFragment Indicates whether this fragment is the last one @@ -140,11 +153,14 @@ namespace pcpp IPv6FragmentationHeader(uint32_t fragId, uint16_t fragOffset, bool lastFragment); /** - * Get a pointer to the fragmentation header. Notice the returned pointer points directly to the data, so every change will modify - * the actual packet data + * Get a pointer to the fragmentation header. Notice the returned pointer points directly to the data, so every + * change will modify the actual packet data * @return A pointer to the @ref ipv6_frag_header */ - ipv6_frag_header* getFragHeader() const { return (ipv6_frag_header*)getDataPtr(); } + ipv6_frag_header* getFragHeader() const + { + return (ipv6_frag_header*)getDataPtr(); + } /** * @return True if this is the first fragment (which usually contains the L4 header), false otherwise @@ -167,26 +183,22 @@ namespace pcpp uint16_t getFragmentOffset() const; private: - IPv6FragmentationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6Fragmentation; } - }; - /** - * An abstract base class for Hop-By-Hop and Destination IPv6 extensions which their structure contains Type-Length-Value (TLV) options. - * This class provides access to these options and their data as well as methods to create new options. Notice this class is abstract - * and cannot be instantiated + * An abstract base class for Hop-By-Hop and Destination IPv6 extensions which their structure contains + * Type-Length-Value (TLV) options. This class provides access to these options and their data as well as methods to + * create new options. Notice this class is abstract and cannot be instantiated */ class IPv6TLVOptionHeader : public IPv6Extension { friend class IPv6Layer; public: - /** * @class IPv6Option * A class representing a Type-Length-Value (TLV) options that are used inside Hop-By-Hop and Destinations IPv6 @@ -196,7 +208,6 @@ namespace pcpp class IPv6Option : public TLVRecord { public: - static const uint8_t Pad0OptionType = 0; static const uint8_t PadNOptionType = 1; @@ -204,12 +215,14 @@ namespace pcpp * A c'tor for this class that gets a pointer to the option raw data (byte array) * @param[in] optionRawData A pointer to the attribute raw data */ - explicit IPv6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) { } + explicit IPv6Option(uint8_t* optionRawData) : TLVRecord(optionRawData) + {} /** * A d'tor for this class, currently does nothing */ - ~IPv6Option() { } + ~IPv6Option() + {} /** * Check if a pointer can be assigned to the TLV record data @@ -254,50 +267,51 @@ namespace pcpp } }; - /** * @class IPv6TLVOptionBuilder - * A class for building IPv6 Type-Length-Value (TLV) options. This builder receives the option parameters in its c'tor, - * builds the option raw buffer and provides a method to build a IPv6Option object out of it + * A class for building IPv6 Type-Length-Value (TLV) options. This builder receives the option parameters in its + * c'tor, builds the option raw buffer and provides a method to build a IPv6Option object out of it */ class IPv6TLVOptionBuilder : public TLVRecordBuilder { public: - /** * A c'tor for building IPv6 TLV options which their value is a byte array. The IPv6Option object can later * be retrieved by calling build() * @param[in] optType IPv6 option type - * @param[in] optValue A buffer containing the option value. This buffer is read-only and isn't modified in any way + * @param[in] optValue A buffer containing the option value. This buffer is read-only and isn't modified in + * any way * @param[in] optValueLen Option value length in bytes */ - IPv6TLVOptionBuilder(uint8_t optType, const uint8_t* optValue, uint8_t optValueLen) : - TLVRecordBuilder(optType, optValue, optValueLen) { } + IPv6TLVOptionBuilder(uint8_t optType, const uint8_t* optValue, uint8_t optValueLen) + : TLVRecordBuilder(optType, optValue, optValueLen) + {} /** - * A c'tor for building IPv6 TLV options which have a 1-byte value. The IPv6Option object can later be retrieved - * by calling build() + * A c'tor for building IPv6 TLV options which have a 1-byte value. The IPv6Option object can later be + * retrieved by calling build() * @param[in] optType IPv6 option type * @param[in] optValue A 1-byte option value */ - IPv6TLVOptionBuilder(uint8_t optType, uint8_t optValue) : - TLVRecordBuilder(optType, optValue) { } + IPv6TLVOptionBuilder(uint8_t optType, uint8_t optValue) : TLVRecordBuilder(optType, optValue) + {} /** - * A c'tor for building IPv6 TLV options which have a 2-byte value. The IPv6Option object can later be retrieved - * by calling build() + * A c'tor for building IPv6 TLV options which have a 2-byte value. The IPv6Option object can later be + * retrieved by calling build() * @param[in] optType IPv6 option type * @param[in] optValue A 2-byte option value */ - IPv6TLVOptionBuilder(uint8_t optType, uint16_t optValue) : - TLVRecordBuilder(optType, optValue) { } + IPv6TLVOptionBuilder(uint8_t optType, uint16_t optValue) : TLVRecordBuilder(optType, optValue) + {} /** - * A copy c'tor that creates an instance of this class out of another instance and copies all the data from it + * A copy c'tor that creates an instance of this class out of another instance and copies all the data from + * it * @param[in] other The instance to copy data from */ - IPv6TLVOptionBuilder(const IPv6TLVOptionBuilder& other) : - TLVRecordBuilder(other) {} + IPv6TLVOptionBuilder(const IPv6TLVOptionBuilder& other) : TLVRecordBuilder(other) + {} /** * Assignment operator that copies all data from another instance of IPv6TLVOptionBuilder @@ -325,18 +339,17 @@ namespace pcpp IPv6Option getOption(uint8_t optionType) const; /** - * @return An IPv6Option that wraps the first option data or logical NULL (IPv6Option#isNull() == true) if no options exist + * @return An IPv6Option that wraps the first option data or logical NULL (IPv6Option#isNull() == true) if no + * options exist */ IPv6Option getFirstOption() const; /** * Returns a pointer to the option that comes after the option given as the parameter * @param[in] option A pointer to an option instance - * @return An IPv6Option object that wraps the option data. In the following cases logical NULL (IPv6Option#isNull() == true) - * is returned: - * (1) input parameter is out-of-bounds for this extension or - * (2) the next option doesn't exist or - * (3) the input option is NULL + * @return An IPv6Option object that wraps the option data. In the following cases logical NULL + * (IPv6Option#isNull() == true) is returned: (1) input parameter is out-of-bounds for this extension or (2) the + * next option doesn't exist or (3) the input option is NULL */ IPv6Option getNextOption(IPv6Option& option) const; @@ -346,69 +359,71 @@ namespace pcpp size_t getOptionCount() const; protected: - /** A private c'tor to keep this object from being constructed */ explicit IPv6TLVOptionHeader(const std::vector& options); IPv6TLVOptionHeader(IDataContainer* dataContainer, size_t offset); private: - TLVRecordReader m_OptionReader; }; - - /** * @class IPv6HopByHopHeader - * Represents IPv6 Hop-By-Hop extension header and allows easy access to all of its data including the TLV options stored + * Represents IPv6 Hop-By-Hop extension header and allows easy access to all of its data including the TLV options + * stored */ class IPv6HopByHopHeader : public IPv6TLVOptionHeader { friend class IPv6Layer; public: - /** - * A c'tor for creating a new IPv6 Hop-By-Hop extension object not bounded to a packet. Useful for adding new extensions to an - * IPv6 layer with IPv6Layer#addExtension() - * @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that will be stored in the - * extension data. Notice this vector is read-only and its content won't be modified + * A c'tor for creating a new IPv6 Hop-By-Hop extension object not bounded to a packet. Useful for adding new + * extensions to an IPv6 layer with IPv6Layer#addExtension() + * @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that + * will be stored in the extension data. Notice this vector is read-only and its content won't be modified */ - explicit IPv6HopByHopHeader(const std::vector& options) : IPv6TLVOptionHeader(options) { m_ExtType = IPv6HopByHop; } + explicit IPv6HopByHopHeader(const std::vector& options) : IPv6TLVOptionHeader(options) + { + m_ExtType = IPv6HopByHop; + } private: - - IPv6HopByHopHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) { m_ExtType = IPv6HopByHop; } + IPv6HopByHopHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) + { + m_ExtType = IPv6HopByHop; + } }; - - /** * @class IPv6DestinationHeader - * Represents IPv6 destination extension header and allows easy access to all of its data including the TLV options stored in it + * Represents IPv6 destination extension header and allows easy access to all of its data including the TLV options + * stored in it */ class IPv6DestinationHeader : public IPv6TLVOptionHeader { friend class IPv6Layer; public: - /** - * A c'tor for creating a new IPv6 destination extension object not bounded to a packet. Useful for adding new extensions to an - * IPv6 layer with IPv6Layer#addExtension() - * @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that will be stored in the - * extension data. Notice this vector is read-only and its content won't be modified + * A c'tor for creating a new IPv6 destination extension object not bounded to a packet. Useful for adding new + * extensions to an IPv6 layer with IPv6Layer#addExtension() + * @param[in] options A vector of IPv6TLVOptionHeader#TLVOptionBuilder instances which define the options that + * will be stored in the extension data. Notice this vector is read-only and its content won't be modified */ - explicit IPv6DestinationHeader(const std::vector& options) : IPv6TLVOptionHeader(options) { m_ExtType = IPv6Destination; } + explicit IPv6DestinationHeader(const std::vector& options) : IPv6TLVOptionHeader(options) + { + m_ExtType = IPv6Destination; + } private: - - IPv6DestinationHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) { m_ExtType = IPv6Destination; } + IPv6DestinationHeader(IDataContainer* dataContainer, size_t offset) : IPv6TLVOptionHeader(dataContainer, offset) + { + m_ExtType = IPv6Destination; + } }; - - /** * @class IPv6RoutingHeader * Represents IPv6 routing extension header and allows easy access to all of its data @@ -418,7 +433,6 @@ namespace pcpp friend class IPv6Layer; public: - /** * @struct ipv6_routing_header * A struct representing the fixed part of the IPv6 routing extension header @@ -436,26 +450,30 @@ namespace pcpp }; /** - * A c'tor for creating a new IPv6 routing extension object not bounded to a packet. Useful for adding new extensions to an - * IPv6 layer with IPv6Layer#addExtension() + * A c'tor for creating a new IPv6 routing extension object not bounded to a packet. Useful for adding new + * extensions to an IPv6 layer with IPv6Layer#addExtension() * @param[in] routingType Routing type value (will be written to ipv6_routing_header#routingType field) * @param[in] segmentsLeft Segments left value (will be written to ipv6_routing_header#segmentsLeft field) - * @param[in] additionalRoutingData A pointer to a buffer containing the additional routing data for this extension. Notice this - * buffer is read-only and its content isn't modified + * @param[in] additionalRoutingData A pointer to a buffer containing the additional routing data for this + * extension. Notice this buffer is read-only and its content isn't modified * @param[in] additionalRoutingDataLen The length of the additional routing data buffer */ - IPv6RoutingHeader(uint8_t routingType, uint8_t segmentsLeft, const uint8_t* additionalRoutingData, size_t additionalRoutingDataLen); + IPv6RoutingHeader(uint8_t routingType, uint8_t segmentsLeft, const uint8_t* additionalRoutingData, + size_t additionalRoutingDataLen); /** - * Get a pointer to the fixed part of the routing header. Notice the return pointer points directly to the data, so every change will modify - * the actual packet data + * Get a pointer to the fixed part of the routing header. Notice the return pointer points directly to the data, + * so every change will modify the actual packet data * @return A pointer to the @ref ipv6_routing_header */ - ipv6_routing_header* getRoutingHeader() const { return (ipv6_routing_header*)getDataPtr(); } + ipv6_routing_header* getRoutingHeader() const + { + return (ipv6_routing_header*)getDataPtr(); + } /** - * @return A pointer to the buffer containing the additional routing data for this extension. Notice that any change in this buffer - * will lead to a change in the extension data + * @return A pointer to the buffer containing the additional routing data for this extension. Notice that any + * change in this buffer will lead to a change in the extension data */ uint8_t* getRoutingAdditionalData() const; @@ -465,33 +483,36 @@ namespace pcpp size_t getRoutingAdditionalDataLength() const; /** - * In many cases the additional routing data is actually IPv6 address(es). This method converts the raw buffer data into an IPv6 address - * @param[in] offset An offset in the additional routing buffer pointing to where the IPv6 address begins. In some cases there are - * multiple IPv6 addresses in the additional routing data buffer so this offset points to where the request IPv6 address begins. Also, - * even if there is only one IPv6 address in this buffer, sometimes it isn't written in the beginning of the buffer, so the offset points - * to where the IPv6 address begins. This is an optional parameter and the default offset is 0 - * @return The IPv6 address stored in the additional routing data buffer from the offset defined by the user. If offset is out-of-bounds - * of the extension of doesn't have 16 bytes (== the length of IPv6 address) until the end of the buffer - IPv6Address#Zero is returned + * In many cases the additional routing data is actually IPv6 address(es). This method converts the raw buffer + * data into an IPv6 address + * @param[in] offset An offset in the additional routing buffer pointing to where the IPv6 address begins. In + * some cases there are multiple IPv6 addresses in the additional routing data buffer so this offset points to + * where the request IPv6 address begins. Also, even if there is only one IPv6 address in this buffer, sometimes + * it isn't written in the beginning of the buffer, so the offset points to where the IPv6 address begins. This + * is an optional parameter and the default offset is 0 + * @return The IPv6 address stored in the additional routing data buffer from the offset defined by the user. If + * offset is out-of-bounds of the extension of doesn't have 16 bytes (== the length of IPv6 address) until the + * end of the buffer - IPv6Address#Zero is returned */ IPv6Address getRoutingAdditionalDataAsIPv6Address(size_t offset = 0) const; private: - - IPv6RoutingHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6Routing; } - + IPv6RoutingHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) + { + m_ExtType = IPv6Routing; + } }; - /** * @class IPv6AuthenticationHeader - * Represents IPv6 authentication header extension (used in IPSec protocol) and allows easy access to all of its data + * Represents IPv6 authentication header extension (used in IPSec protocol) and allows easy access to all of its + * data */ class IPv6AuthenticationHeader : public IPv6Extension { friend class IPv6Layer; public: - /** * @struct ipv6_authentication_header * A struct representing the fixed part of the IPv6 authentication header extension @@ -501,37 +522,45 @@ namespace pcpp /** Next header type */ uint8_t nextHeader; /** The length of this Authentication Header in 4-octet units, minus 2. For example, an AH value of 4 - * equals: [ 3×(32-bit fixed-length AH fields) + 3×(32-bit ICV fields) − 2 ] and thus an AH value of 4 means 24 octets */ + * equals: [ 3×(32-bit fixed-length AH fields) + 3×(32-bit ICV fields) − 2 ] and thus an AH value of 4 means + * 24 octets */ uint8_t headerLen; /** Reserved bytes, all zeros */ uint16_t reserved; - /** Arbitrary value which is used (together with the destination IP address) to identify the security association of the receiving party */ + /** Arbitrary value which is used (together with the destination IP address) to identify the security + * association of the receiving party */ uint32_t securityParametersIndex; /** A monotonic strictly increasing sequence number (incremented by 1 for every packet sent) */ uint32_t sequenceNumber; }; /** - * A c'tor for creating a new IPv6 authentication header extension object not bounded to a packet. Useful for adding new extensions to an - * IPv6 layer with IPv6Layer#addExtension() - * @param[in] securityParametersIndex Security Parameters Index (SPI) value (will be written to ipv6_authentication_header#securityParametersIndex field) - * @param[in] sequenceNumber Sequence number value (will be written to ipv6_authentication_header#sequenceNumber field) - * @param[in] integrityCheckValue A pointer to a buffer containing the integrity check value (ICV) data for this extension. Notice this - * pointer is read-only and its content isn't modified in any way + * A c'tor for creating a new IPv6 authentication header extension object not bounded to a packet. Useful for + * adding new extensions to an IPv6 layer with IPv6Layer#addExtension() + * @param[in] securityParametersIndex Security Parameters Index (SPI) value (will be written to + * ipv6_authentication_header#securityParametersIndex field) + * @param[in] sequenceNumber Sequence number value (will be written to ipv6_authentication_header#sequenceNumber + * field) + * @param[in] integrityCheckValue A pointer to a buffer containing the integrity check value (ICV) data for this + * extension. Notice this pointer is read-only and its content isn't modified in any way * @param[in] integrityCheckValueLen The length of the integrity check value (ICV) buffer */ - IPv6AuthenticationHeader(uint32_t securityParametersIndex, uint32_t sequenceNumber, const uint8_t* integrityCheckValue, size_t integrityCheckValueLen); + IPv6AuthenticationHeader(uint32_t securityParametersIndex, uint32_t sequenceNumber, + const uint8_t* integrityCheckValue, size_t integrityCheckValueLen); /** - * Get a pointer to the fixed part of the authentication header. Notice the return pointer points directly to the data, so every change - * will modify the actual packet data + * Get a pointer to the fixed part of the authentication header. Notice the return pointer points directly to + * the data, so every change will modify the actual packet data * @return A pointer to the @ref ipv6_authentication_header */ - ipv6_authentication_header* getAuthHeader() const { return (ipv6_authentication_header*)getDataPtr(); } + ipv6_authentication_header* getAuthHeader() const + { + return (ipv6_authentication_header*)getDataPtr(); + } /** - * @return A pointer to the buffer containing the integrity check value (ICV) for this extension. Notice that any change in this buffer - * will lead to a change in the extension data + * @return A pointer to the buffer containing the integrity check value (ICV) for this extension. Notice that + * any change in this buffer will lead to a change in the extension data */ uint8_t* getIntegrityCheckValue() const; @@ -547,11 +576,16 @@ namespace pcpp * calculation is: [ 4 * (ipv6_authentication_header#headerLen + 2) ] * @return The length of this extension */ - size_t getExtensionLen() const { return 4 * (getBaseHeader()->headerLen+2); } + size_t getExtensionLen() const + { + return 4 * (getBaseHeader()->headerLen + 2); + } private: - - IPv6AuthenticationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) { m_ExtType = IPv6AuthenticationHdr; } + IPv6AuthenticationHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) + { + m_ExtType = IPv6AuthenticationHdr; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/IPv6Layer.h b/Packet++/header/IPv6Layer.h index f603083d59..fe7fc403d2 100644 --- a/Packet++/header/IPv6Layer.h +++ b/Packet++/header/IPv6Layer.h @@ -21,17 +21,17 @@ namespace pcpp #pragma pack(push, 1) struct ip6_hdr { - #if (BYTE_ORDER == LITTLE_ENDIAN) +#if (BYTE_ORDER == LITTLE_ENDIAN) /** Traffic class */ - uint8_t trafficClass:4, + uint8_t trafficClass : 4, + /** IP version number, has the value of 6 for IPv6 */ + ipVersion : 4; +#else /** IP version number, has the value of 6 for IPv6 */ - ipVersion:4; - #else - /** IP version number, has the value of 6 for IPv6 */ - uint8_t ipVersion:4, - /** Traffic class */ - trafficClass:4; - #endif + uint8_t ipVersion : 4, + /** Traffic class */ + trafficClass : 4; +#endif /** Flow label */ uint8_t flowLabel[3]; /** The size of the payload in octets, including any extension headers */ @@ -47,7 +47,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @class IPv6Layer * Represents an IPv6 protocol layer @@ -87,54 +86,76 @@ namespace pcpp ~IPv6Layer(); /** - * An assignment operator that first delete all data from current layer and then copy the entire header from the other IPv6Layer (including IPv6 extensions) + * An assignment operator that first delete all data from current layer and then copy the entire header from the + * other IPv6Layer (including IPv6 extensions) */ IPv6Layer& operator=(const IPv6Layer& other); /** - * Get a pointer to the IPv6 header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the IPv6 header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref ip6_hdr */ - ip6_hdr* getIPv6Header() const { return (ip6_hdr*)m_Data; } + ip6_hdr* getIPv6Header() const + { + return (ip6_hdr*)m_Data; + } /** * Get the source IP address in the form of IPAddress. This method is very similar to getSrcIPv6Address(), * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses * @return An IPAddress containing the source address */ - IPAddress getSrcIPAddress() const { return getSrcIPv6Address(); } + IPAddress getSrcIPAddress() const + { + return getSrcIPv6Address(); + } /** * Get the source IP address in the form of IPv6Address * @return An IPv6Address containing the source address */ - IPv6Address getSrcIPv6Address() const { return getIPv6Header()->ipSrc; } + IPv6Address getSrcIPv6Address() const + { + return getIPv6Header()->ipSrc; + } /** * Set the source IP address * @param[in] ipAddr The IP address to set */ - void setSrcIPv6Address(const IPv6Address& ipAddr) { ipAddr.copyTo(getIPv6Header()->ipSrc); } - + void setSrcIPv6Address(const IPv6Address& ipAddr) + { + ipAddr.copyTo(getIPv6Header()->ipSrc); + } /** * Set the dest IP address * @param[in] ipAddr The IP address to set */ - void setDstIPv6Address(const IPv6Address& ipAddr) { ipAddr.copyTo(getIPv6Header()->ipDst); } + void setDstIPv6Address(const IPv6Address& ipAddr) + { + ipAddr.copyTo(getIPv6Header()->ipDst); + } /** * Get the destination IP address in the form of IPAddress. This method is very similar to getDstIPv6Address(), * but adds a level of abstraction because IPAddress can be used for both IPv4 and IPv6 addresses * @return An IPAddress containing the destination address */ - IPAddress getDstIPAddress() const { return getDstIPv6Address(); } + IPAddress getDstIPAddress() const + { + return getDstIPv6Address(); + } /** * Get the destination IP address in the form of IPv6Address * @return An IPv6Address containing the destination address */ - IPv6Address getDstIPv6Address() const { return getIPv6Header()->ipDst; } + IPv6Address getDstIPv6Address() const + { + return getIPv6Header()->ipDst; + } /** * @return Number of IPv6 extensions in this layer @@ -142,24 +163,23 @@ namespace pcpp size_t getExtensionCount() const; /** - * A templated getter for an IPv6 extension of a type TIPv6Extension. TIPv6Extension has to be one of the supported IPv6 extensions, - * meaning a class that inherits IPv6Extension. If the requested extension type isn't found NULL is returned + * A templated getter for an IPv6 extension of a type TIPv6Extension. TIPv6Extension has to be one of the + * supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the requested extension type isn't + * found NULL is returned * @return A pointer to the extension instance or NULL if the requested extension type isn't found */ - template - TIPv6Extension* getExtensionOfType() const; + template TIPv6Extension* getExtensionOfType() const; /** - * Add a new extension of type TIPv6Extension to the layer. This is a templated method and TIPv6Extension has to be one of - * the supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the extension is added successfully a pointer - * to the newly added extension object is returned, otherwise NULL is returned - * @param[in] extensionHeader The extension object to add. Notice the object passed here is read-only, meaning its data is copied - * but the object itself isn't modified - * @return If the extension is added successfully a pointer to the newly added extension object is returned. Otherwise NULL is - * returned + * Add a new extension of type TIPv6Extension to the layer. This is a templated method and TIPv6Extension has to + * be one of the supported IPv6 extensions, meaning a class that inherits IPv6Extension. If the extension is + * added successfully a pointer to the newly added extension object is returned, otherwise NULL is returned + * @param[in] extensionHeader The extension object to add. Notice the object passed here is read-only, meaning + * its data is copied but the object itself isn't modified + * @return If the extension is added successfully a pointer to the newly added extension object is returned. + * Otherwise NULL is returned */ - template - TIPv6Extension* addExtension(const TIPv6Extension& extensionHeader); + template TIPv6Extension* addExtension(const TIPv6Extension& extensionHeader); /** * Remove all IPv6 extensions in this layer @@ -179,7 +199,6 @@ namespace pcpp */ static inline bool isDataValid(const uint8_t* data, size_t dataLen); - // implement abstract methods /** @@ -199,19 +218,26 @@ namespace pcpp /** * @return Size of @ref ip6_hdr */ - size_t getHeaderLen() const { return sizeof(ip6_hdr) + m_ExtensionsLen; } + size_t getHeaderLen() const + { + return sizeof(ip6_hdr) + m_ExtensionsLen; + } /** * Calculate the following fields: * - ip6_hdr#payloadLength = size of payload (all data minus header size) * - ip6_hdr#ipVersion = 6 - * - ip6_hdr#nextHeader = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP + * - ip6_hdr#nextHeader = calculated if next layer is known: ::PACKETPP_IPPROTO_TCP for TCP, + * ::PACKETPP_IPPROTO_UDP for UDP, ::PACKETPP_IPPROTO_ICMP for ICMP */ void computeCalculateFields(); std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } private: void initLayer(); @@ -223,9 +249,7 @@ namespace pcpp size_t m_ExtensionsLen; }; - - template - TIPv6Extension* IPv6Layer::getExtensionOfType() const + template TIPv6Extension* IPv6Layer::getExtensionOfType() const { IPv6Extension* curExt = m_FirstExtension; while (curExt != NULL && dynamic_cast(curExt) == NULL) @@ -234,8 +258,7 @@ namespace pcpp return static_cast(curExt); } - template - TIPv6Extension* IPv6Layer::addExtension(const TIPv6Extension& extensionHeader) + template TIPv6Extension* IPv6Layer::addExtension(const TIPv6Extension& extensionHeader) { int offsetToAddHeader = static_cast(getHeaderLen()); if (!extendLayer(offsetToAddHeader, extensionHeader.getExtensionLen())) @@ -273,4 +296,4 @@ namespace pcpp return data && dataLen >= sizeof(ip6_hdr); } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/IcmpLayer.h b/Packet++/header/IcmpLayer.h index 07b3397a62..21701ef3b4 100644 --- a/Packet++/header/IcmpLayer.h +++ b/Packet++/header/IcmpLayer.h @@ -3,13 +3,12 @@ #include "Layer.h" #include "IPv4Layer.h" #ifdef _MSC_VER -#include +# include #else -#include +# include #endif #include - /// @file /** @@ -27,9 +26,9 @@ namespace pcpp typedef struct icmphdr { /** message type */ - uint8_t type; + uint8_t type; /** message code */ - uint8_t code; + uint8_t code; /** message checksum */ uint16_t checksum; } icmphdr; @@ -41,37 +40,37 @@ namespace pcpp enum IcmpMessageType { /** ICMP echo (ping) reply message */ - ICMP_ECHO_REPLY = 0, + ICMP_ECHO_REPLY = 0, /** ICMP destination unreachable message */ - ICMP_DEST_UNREACHABLE = 3, + ICMP_DEST_UNREACHABLE = 3, /** ICMP source quench message */ - ICMP_SOURCE_QUENCH = 4, + ICMP_SOURCE_QUENCH = 4, /** ICMP redirect message */ - ICMP_REDIRECT = 5, + ICMP_REDIRECT = 5, /** ICMP echo (ping) request message */ - ICMP_ECHO_REQUEST = 8, + ICMP_ECHO_REQUEST = 8, /** ICMP router advertisement message */ - ICMP_ROUTER_ADV = 9, + ICMP_ROUTER_ADV = 9, /** ICMP router soliciatation message */ - ICMP_ROUTER_SOL = 10, + ICMP_ROUTER_SOL = 10, /** ICMP time-to-live excceded message */ - ICMP_TIME_EXCEEDED = 11, + ICMP_TIME_EXCEEDED = 11, /** ICMP parameter problem message */ - ICMP_PARAM_PROBLEM = 12, + ICMP_PARAM_PROBLEM = 12, /** ICMP timestamp request message */ - ICMP_TIMESTAMP_REQUEST = 13, + ICMP_TIMESTAMP_REQUEST = 13, /** ICMP timestamp reply message */ - ICMP_TIMESTAMP_REPLY = 14, + ICMP_TIMESTAMP_REPLY = 14, /** ICMP information request message */ - ICMP_INFO_REQUEST = 15, + ICMP_INFO_REQUEST = 15, /** ICMP information reply message */ - ICMP_INFO_REPLY = 16, + ICMP_INFO_REPLY = 16, /** ICMP address mask request message */ ICMP_ADDRESS_MASK_REQUEST = 17, /** ICMP address mask reply message */ - ICMP_ADDRESS_MASK_REPLY = 18, + ICMP_ADDRESS_MASK_REPLY = 18, /** ICMP message type unsupported by PcapPlusPlus */ - ICMP_UNSUPPORTED = 255 + ICMP_UNSUPPORTED = 255 }; /** @@ -120,7 +119,6 @@ namespace pcpp IcmpPrecedenceCutoff = 15 }; - /** * @struct icmp_echo_hdr * ICMP echo (ping) request/reply message structure @@ -137,7 +135,6 @@ namespace pcpp } icmp_echo_hdr; #pragma pack(pop) - /** * @struct icmp_echo_request * ICMP echo (ping) request/reply message structure @@ -152,14 +149,12 @@ namespace pcpp uint8_t* data; } icmp_echo_request; - /** * @typedef icmp_echo_reply * ICMP echo (ping) reply message structure, same as icmp_echo_request */ typedef icmp_echo_request icmp_echo_reply; - /** * @struct icmp_timestamp_request * ICMP timestamp request message structure @@ -180,14 +175,12 @@ namespace pcpp } icmp_timestamp_request; #pragma pack(pop) - /** * @typedef icmp_timestamp_reply * ICMP timestamp reply message structure, same as icmp_timestamp_request */ typedef icmp_timestamp_request icmp_timestamp_reply; - /** * @struct icmp_destination_unreachable * ICMP destination unreachable message structure @@ -202,7 +195,6 @@ namespace pcpp } icmp_destination_unreachable; #pragma pack(pop) - /** * @struct icmp_time_exceeded * ICMP time-to-live exceeded message structure @@ -215,14 +207,12 @@ namespace pcpp } icmp_time_exceeded; #pragma pack(pop) - /** * @typedef icmp_source_quench * ICMP source quence message structure, same as icmp_time_exceeded */ typedef icmp_time_exceeded icmp_source_quench; - /** * @struct icmp_param_problem * ICMP parameter problem message structure @@ -230,16 +220,16 @@ namespace pcpp #pragma pack(push, 1) typedef struct icmp_param_problem : icmphdr { - /** in the case of an invalid IP header (Code 0), this field indicates the byte offset of the error in the header */ - uint8_t pointer; + /** in the case of an invalid IP header (Code 0), this field indicates the byte offset of the error in the + * header */ + uint8_t pointer; /** unused 1 byte */ - uint8_t unused1; + uint8_t unused1; /** unused 2 bytes */ uint16_t unused2; } icmp_param_problem; #pragma pack(pop) - /** * @typedef icmp_router_solicitation * ICMP router solicitation message structure, same as icmphdr @@ -258,7 +248,6 @@ namespace pcpp } icmp_redirect; #pragma pack(pop) - /** * @struct icmp_router_address_structure * Router address structure, relevant for ICMP router advertisement message type (icmp_router_advertisement) @@ -283,11 +272,13 @@ namespace pcpp /** * @return The IPv4 address extracted from icmp_router_address_structure#routerAddress field */ - IPv4Address getAddress() const { return routerAddress; } + IPv4Address getAddress() const + { + return routerAddress; + } }; #pragma pack(pop) - /** * @struct icmp_router_advertisement_hdr * ICMP router advertisement message structure @@ -295,17 +286,17 @@ namespace pcpp #pragma pack(push, 1) typedef struct icmp_router_advertisement_hdr : icmphdr { - /** the number of router advertisements in this message. Each advertisement contains one router address/preference level pair */ - uint8_t advertisementCount; - /** the number of 32-bit words of information for each router address entry in the list. The value is normally set to 2 - * (router address + preference level) */ - uint8_t addressEntrySize; + /** the number of router advertisements in this message. Each advertisement contains one router + * address/preference level pair */ + uint8_t advertisementCount; + /** the number of 32-bit words of information for each router address entry in the list. The value is normally + * set to 2 (router address + preference level) */ + uint8_t addressEntrySize; /** the maximum number of seconds that the router addresses in this list may be considered valid */ uint16_t lifetime; } icmp_router_advertisement_hdr; #pragma pack(pop) - /** * @struct icmp_router_advertisement * ICMP router advertisement message structure @@ -318,13 +309,13 @@ namespace pcpp /** * Extract router advertisement at a given index * @param[in] index The index of the router advertisement - * @return A pointer to the router advertisement on the packet or null if index is out of range (less than zero or - * greater than the number of router advertisement records on this message, determined by advertisementCount field) + * @return A pointer to the router advertisement on the packet or null if index is out of range (less than zero + * or greater than the number of router advertisement records on this message, determined by advertisementCount + * field) */ icmp_router_address_structure* getRouterAddress(int index) const; }; - /** * @struct icmp_address_mask_request * ICMP address mask request message structure @@ -341,14 +332,12 @@ namespace pcpp } icmp_address_mask_request; #pragma pack(pop) - /** * @typedef icmp_address_mask_reply * ICMP address mask reply message structure, same as icmp_address_mask_request */ typedef icmp_address_mask_request icmp_address_mask_reply; - /** * @struct icmp_info_request * ICMP information request message structure @@ -363,14 +352,12 @@ namespace pcpp } icmp_info_request; #pragma pack(pop) - /** * @typedef icmp_info_reply * ICMP information reply message structure, same as icmp_info_request */ typedef icmp_info_request icmp_info_reply; - /** * @class IcmpLayer * Represents an ICMP protocol layer (for IPv4 only) @@ -383,7 +370,8 @@ namespace pcpp bool cleanIcmpLayer(); - bool setEchoData(IcmpMessageType echoType, uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen); + bool setEchoData(IcmpMessageType echoType, uint16_t id, uint16_t sequence, uint64_t timestamp, + const uint8_t* data, size_t dataLen); bool setIpAndL4Layers(IPv4Layer* ipLayer, Layer* l4Layer); @@ -396,21 +384,30 @@ namespace pcpp * @param[in] packet A pointer to the Packet instance where layer will be stored in */ // cppcheck-suppress uninitMemberVar - IcmpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ICMP; } + IcmpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = ICMP; + } /** - * An empty constructor that creates a new layer with an empty ICMP header without setting the ICMP type or ICMP data. - * Call the set*Data() methods to set ICMP type and data + * An empty constructor that creates a new layer with an empty ICMP header without setting the ICMP type or ICMP + * data. Call the set*Data() methods to set ICMP type and data */ IcmpLayer(); - virtual ~IcmpLayer() {} + virtual ~IcmpLayer() + {} /** - * Get a pointer to the basic ICMP header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the basic ICMP header. Notice this points directly to the data, so every change will change + * the actual packet data * @return A pointer to the @ref icmphdr */ - icmphdr* getIcmpHeader() const { return (icmphdr*)m_Data; } + icmphdr* getIcmpHeader() const + { + return (icmphdr*)m_Data; + } /** * @return The ICMP message type @@ -421,7 +418,10 @@ namespace pcpp * @param[in] type Type to check * @return True if the layer if of the given type, false otherwise */ - bool isMessageOfType(IcmpMessageType type) const { return getMessageType() == type; } + bool isMessageOfType(IcmpMessageType type) const + { + return getMessageType() == type; + } /** * @return ICMP echo (ping) request data. If the layer isn't of type ICMP echo request NULL is returned @@ -438,7 +438,8 @@ namespace pcpp * @return A pointer to the echo (ping) request data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) */ - icmp_echo_request* setEchoRequestData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen); + icmp_echo_request* setEchoRequestData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, + size_t dataLen); /** * @return ICMP echo reply data. If the layer isn't of type ICMP echo reply NULL is returned @@ -455,7 +456,8 @@ namespace pcpp * @return A pointer to the echo (ping) reply data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) */ - icmp_echo_reply* setEchoReplyData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen); + icmp_echo_reply* setEchoReplyData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, + size_t dataLen); /** * @return ICMP timestamp request data. If the layer isn't of type ICMP timestamp request NULL is returned @@ -487,28 +489,30 @@ namespace pcpp * @return A pointer to the timestamp reply data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) */ - icmp_timestamp_reply* setTimestampReplyData(uint16_t id, uint16_t sequence, - timeval originateTimestamp, timeval receiveTimestamp, timeval transmitTimestamp); + icmp_timestamp_reply* setTimestampReplyData(uint16_t id, uint16_t sequence, timeval originateTimestamp, + timeval receiveTimestamp, timeval transmitTimestamp); /** - * @return ICMP destination unreachable data. If the layer isn't of type ICMP destination unreachable NULL is returned. - * The IP and L4 (ICMP/TCP/UDP) headers of the destination unreachable data are parsed as separate layers and can be - * retrieved via this->getNextLayer() + * @return ICMP destination unreachable data. If the layer isn't of type ICMP destination unreachable NULL is + * returned. The IP and L4 (ICMP/TCP/UDP) headers of the destination unreachable data are parsed as separate + * layers and can be retrieved via this->getNextLayer() */ icmp_destination_unreachable* getDestUnreachableData(); /** - * Set destination unreachable message data. This method only works if IcmpLayer is already part of a packet (not - * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers - * and need a packet to be added to + * Set destination unreachable message data. This method only works if IcmpLayer is already part of a packet + * (not a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate + * layers and need a packet to be added to * @param[in] code Destination unreachable code * @param[in] nextHopMTU The MTU of the next-hop network if a code 4 error occurs - * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet + * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the + * packet * @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet * @return A pointer to the destination unreachable data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) */ - icmp_destination_unreachable* setDestUnreachableData(IcmpDestUnreachableCodes code, uint16_t nextHopMTU, IPv4Layer* ipHeader, Layer* l4Header); + icmp_destination_unreachable* setDestUnreachableData(IcmpDestUnreachableCodes code, uint16_t nextHopMTU, + IPv4Layer* ipHeader, Layer* l4Header); /** * @return ICMP source quench data. If the layer isn't of type ICMP source quench NULL is returned. @@ -519,9 +523,10 @@ namespace pcpp /** * Set source quench message data. This method only works if IcmpLayer is already part of a packet (not - * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers - * and need a packet to be added to - * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet + * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate + * layers and need a packet to be added to + * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the + * packet * @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet * @return A pointer to the source quench data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) @@ -537,11 +542,13 @@ namespace pcpp /** * Set redirect message data. This method only works if IcmpLayer is already part of a packet (not - * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers - * and need a packet to be added to - * @param[in] code The redirect message code. Only values between 0 and 3 are legal, the rest will cause the method to fail + * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate + * layers and need a packet to be added to + * @param[in] code The redirect message code. Only values between 0 and 3 are legal, the rest will cause the + * method to fail * @param[in] gatewayAddress An IPv4 address of the gateway to which the redirection should be sent - * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet + * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the + * packet * @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet * @return A pointer to the redirect data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) @@ -555,13 +562,17 @@ namespace pcpp /** * Set router advertisement message data - * @param[in] code The router advertisement message code. Only codes 0 or 16 are legal, the rest will fail the method - * @param[in] lifetimeInSeconds The maximum number of seconds that the router addresses in this list may be considered valid + * @param[in] code The router advertisement message code. Only codes 0 or 16 are legal, the rest will fail the + * method + * @param[in] lifetimeInSeconds The maximum number of seconds that the router addresses in this list may be + * considered valid * @param[in] routerAddresses A vector of router advertisements to set * @return A pointer to the router advertisement data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) */ - icmp_router_advertisement* setRouterAdvertisementData(uint8_t code, uint16_t lifetimeInSeconds, const std::vector& routerAddresses); + icmp_router_advertisement* setRouterAdvertisementData( + uint8_t code, uint16_t lifetimeInSeconds, + const std::vector& routerAddresses); /** * @return ICMP router solicitation data. If the layer isn't of type ICMP router solicitation NULL is returned @@ -577,18 +588,20 @@ namespace pcpp icmp_router_solicitation* setRouterSolicitationData(); /** - * @return ICMP time-to-live exceeded data. If the layer isn't of type ICMP time-to-live exceeded NULL is returned. - * The IP and L4 (ICMP/TCP/UDP) headers of the time exceeded data are parsed as separate layers and can be - * retrieved via this->getNextLayer() + * @return ICMP time-to-live exceeded data. If the layer isn't of type ICMP time-to-live exceeded NULL is + * returned. The IP and L4 (ICMP/TCP/UDP) headers of the time exceeded data are parsed as separate layers and + * can be retrieved via this->getNextLayer() */ icmp_time_exceeded* getTimeExceededData(); /** * Set time-to-live exceeded message data. This method only works if IcmpLayer is already part of a packet (not - * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers - * and need a packet to be added to - * @param[in] code Time-to-live exceeded message code. Only codes 0 or 1 are legal, the rest will fail the method - * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet + * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate + * layers and need a packet to be added to + * @param[in] code Time-to-live exceeded message code. Only codes 0 or 1 are legal, the rest will fail the + * method + * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the + * packet * @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet * @return A pointer to the time-to-live exceeded data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) @@ -602,16 +615,20 @@ namespace pcpp /** * Set parameter problem message data. This method only works if IcmpLayer is already part of a packet (not - * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate layers - * and need a packet to be added to - * @param[in] code Parameter problem message code. Only code between 0 and 2 are legal, the rest will fail the method - * @param[in] errorOctetPointer In the case of an invalid IP header (Code 0), indicate the byte offset of the error in the header - * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the packet + * a standalone layer). The reason is the Internet and L4 headers given as parameters are added as separate + * layers and need a packet to be added to + * @param[in] code Parameter problem message code. Only code between 0 and 2 are legal, the rest will fail the + * method + * @param[in] errorOctetPointer In the case of an invalid IP header (Code 0), indicate the byte offset of the + * error in the header + * @param[in] ipHeader The Internet header of the original data. This layer is added as a separate layer on the + * packet * @param[in] l4Header The L4 header of the original data. This layer is added as a separate layer on the packet * @return A pointer to the parameter problem data that have been set or NULL if something went wrong * (an appropriate error log is printed in such cases) */ - icmp_param_problem* setParamProblemData(uint8_t code, uint8_t errorOctetPointer, IPv4Layer* ipHeader, Layer* l4Header); + icmp_param_problem* setParamProblemData(uint8_t code, uint8_t errorOctetPointer, IPv4Layer* ipHeader, + Layer* l4Header); /** * @return ICMP address mask request data. If the layer isn't of type ICMP address mask request NULL is returned @@ -644,7 +661,8 @@ namespace pcpp icmp_address_mask_reply* setAddressMaskReplyData(uint16_t id, uint16_t sequence, IPv4Address mask); /** - * @return ICMP address information request data. If the layer isn't of type ICMP information request NULL is returned + * @return ICMP address information request data. If the layer isn't of type ICMP information request NULL is + * returned */ icmp_info_request* getInfoRequestData(); @@ -658,7 +676,8 @@ namespace pcpp icmp_info_request* setInfoRequestData(uint16_t id, uint16_t sequence); /** - * @return ICMP address information reply data. If the layer isn't of type ICMP information reply NULL is returned + * @return ICMP address information reply data. If the layer isn't of type ICMP information reply NULL is + * returned */ icmp_info_reply* getInfoReplyData(); @@ -682,16 +701,16 @@ namespace pcpp // implement abstract methods /** - * ICMP messages of types: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, ICMP_REDIRECT, ICMP_PARAM_PROBLEM - * have data that contains IPv4 header and some L4 header (TCP/UDP/ICMP). This method parses these headers as separate - * layers on top of the ICMP layer + * ICMP messages of types: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, ICMP_REDIRECT, + * ICMP_PARAM_PROBLEM have data that contains IPv4 header and some L4 header (TCP/UDP/ICMP). This method parses + * these headers as separate layers on top of the ICMP layer */ void parseNextLayer(); /** - * @return The ICMP header length. This length varies according to the ICMP message type. This length doesn't include - * IPv4 and L4 headers in case ICMP message type are: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, ICMP_TIME_EXCEEDED, - * ICMP_REDIRECT, ICMP_PARAM_PROBLEM + * @return The ICMP header length. This length varies according to the ICMP message type. This length doesn't + * include IPv4 and L4 headers in case ICMP message type are: ICMP_DEST_UNREACHABLE, ICMP_SOURCE_QUENCH, + * ICMP_TIME_EXCEEDED, ICMP_REDIRECT, ICMP_PARAM_PROBLEM */ size_t getHeaderLen() const; @@ -702,7 +721,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } }; // implementation of inline methods @@ -749,4 +771,4 @@ namespace pcpp return false; } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/IcmpV6Layer.h b/Packet++/header/IcmpV6Layer.h index 87a740196a..1d834957a4 100644 --- a/Packet++/header/IcmpV6Layer.h +++ b/Packet++/header/IcmpV6Layer.h @@ -11,104 +11,104 @@ namespace pcpp { -/** - * An enum representing the available ICMPv6 message types - */ -enum class ICMPv6MessageType : int -{ - /** Unknown ICMPv6 message */ - ICMPv6_UNKNOWN_MESSAGE = 0, - /** Destination Unreachable Message */ - ICMPv6_DESTINATION_UNREACHABLE = 1, - /** Packet Too Big Message */ - ICMPv6_PACKET_TOO_BIG = 2, - /** Time Exceeded Message */ - ICMPv6_TIME_EXCEEDED = 3, - /** Parameter Problem Message */ - ICMPv6_PARAMETER_PROBLEM = 4, - /** Private Experimentation Message */ - ICMPv6_PRIVATE_EXPERIMENTATION1 = 100, - /** Private Experimentation Message */ - ICMPv6_PRIVATE_EXPERIMENTATION2 = 101, - /** Reserved for expansion of ICMPv6 error messages */ - ICMPv6_RESERVED_EXPANSION_ERROR = 127, - /** Echo Request Message */ - ICMPv6_ECHO_REQUEST = 128, - /** Echo Reply Message */ - ICMPv6_ECHO_REPLY = 129, - /** Multicast Listener Query Message */ - ICMPv6_MULTICAST_LISTENER_QUERY = 130, - /** Multicast Listener Report Message */ - ICMPv6_MULTICAST_LISTENER_REPORT = 131, - /** Multicast Listener Done Message */ - ICMPv6_MULTICAST_LISTENER_DONE = 132, - /** Router Solicitation Message */ - ICMPv6_ROUTER_SOLICITATION = 133, - /** Router Advertisement Message */ - ICMPv6_ROUTER_ADVERTISEMENT = 134, - /** Neighbor Solicitation Message */ - ICMPv6_NEIGHBOR_SOLICITATION = 135, - /** Neighbor Advertisement Message */ - ICMPv6_NEIGHBOR_ADVERTISEMENT = 136, - /** Redirect Message */ - ICMPv6_REDIRECT_MESSAGE = 137, - /** Router Renumbering Message */ - ICMPv6_ROUTER_RENUMBERING = 138, - /** Node Information Query Message */ - ICMPv6_ICMP_NODE_INFORMATION_QUERY = 139, - /** Node Information Reply Message*/ - ICMPv6_ICMP_NODE_INFORMATION_RESPONSE = 140, - /** Inverse Neighbor Discovery Solicitation Message */ - ICMPv6_INVERSE_NEIGHBOR_DISCOVERY_SOLICITATION_MESSAGE = 141, - /** Inverse Neighbor Discovery Advertisement Message */ - ICMPv6_INVERSE_NEIGHBOR_DISCOVERY_ADVERTISEMENT_MESSAGE = 142, - /** Multicast Listener Report Message */ - ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS = 143, - /** Home Agent Address Discovery Request Message */ - ICMPv6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST_MESSAGE = 144, - /** Home Agent Address Discovery Reply Message */ - ICMPv6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY_MESSAGE = 145, - /** Mobile Prefix Solicitation Message */ - ICMPv6_MOBILE_PREFIX_SOLICITATION = 146, - /** Mobile Prefix Advertisement Message */ - ICMPv6_MOBILE_PREFIX_ADVERTISEMENT = 147, - /** Certification Path Solicitation Message */ - ICMPv6_CERTIFICATION_PATH_SOLICITATION = 148, - /** Certification Path Advertisement Message */ - ICMPv6_CERTIFICATION_PATH_ADVERTISEMENT = 149, - /** ICMP Experimental Mobility Subtype Format and Registry Message */ - ICMPv6_EXPERIMENTAL_MOBILITY = 150, - /** Multicast Router Advertisement Message */ - ICMPv6_MULTICAST_ROUTER_ADVERTISEMENT = 151, - /** Multicast Router Solicitation Message */ - ICMPv6_MULTICAST_ROUTER_SOLICITATION = 152, - /** Multicast Router Termination Message*/ - ICMPv6_MULTICAST_ROUTER_TERMINATION = 153, - /** RPL Control Message */ - ICMPv6_RPL_CONTROL_MESSAGE = 155, - /** Private Experimentation Message */ - ICMPv6_PRIVATE_EXPERIMENTATION3 = 200, - /** Private Experimentation Message */ - ICMPv6_PRIVATE_EXPERIMENTATION4 = 201, - /** Reserved for expansion of ICMPv6 informational messages */ - ICMPv6_RESERVED_EXPANSION_INFORMATIONAL = 255 -}; + /** + * An enum representing the available ICMPv6 message types + */ + enum class ICMPv6MessageType : int + { + /** Unknown ICMPv6 message */ + ICMPv6_UNKNOWN_MESSAGE = 0, + /** Destination Unreachable Message */ + ICMPv6_DESTINATION_UNREACHABLE = 1, + /** Packet Too Big Message */ + ICMPv6_PACKET_TOO_BIG = 2, + /** Time Exceeded Message */ + ICMPv6_TIME_EXCEEDED = 3, + /** Parameter Problem Message */ + ICMPv6_PARAMETER_PROBLEM = 4, + /** Private Experimentation Message */ + ICMPv6_PRIVATE_EXPERIMENTATION1 = 100, + /** Private Experimentation Message */ + ICMPv6_PRIVATE_EXPERIMENTATION2 = 101, + /** Reserved for expansion of ICMPv6 error messages */ + ICMPv6_RESERVED_EXPANSION_ERROR = 127, + /** Echo Request Message */ + ICMPv6_ECHO_REQUEST = 128, + /** Echo Reply Message */ + ICMPv6_ECHO_REPLY = 129, + /** Multicast Listener Query Message */ + ICMPv6_MULTICAST_LISTENER_QUERY = 130, + /** Multicast Listener Report Message */ + ICMPv6_MULTICAST_LISTENER_REPORT = 131, + /** Multicast Listener Done Message */ + ICMPv6_MULTICAST_LISTENER_DONE = 132, + /** Router Solicitation Message */ + ICMPv6_ROUTER_SOLICITATION = 133, + /** Router Advertisement Message */ + ICMPv6_ROUTER_ADVERTISEMENT = 134, + /** Neighbor Solicitation Message */ + ICMPv6_NEIGHBOR_SOLICITATION = 135, + /** Neighbor Advertisement Message */ + ICMPv6_NEIGHBOR_ADVERTISEMENT = 136, + /** Redirect Message */ + ICMPv6_REDIRECT_MESSAGE = 137, + /** Router Renumbering Message */ + ICMPv6_ROUTER_RENUMBERING = 138, + /** Node Information Query Message */ + ICMPv6_ICMP_NODE_INFORMATION_QUERY = 139, + /** Node Information Reply Message*/ + ICMPv6_ICMP_NODE_INFORMATION_RESPONSE = 140, + /** Inverse Neighbor Discovery Solicitation Message */ + ICMPv6_INVERSE_NEIGHBOR_DISCOVERY_SOLICITATION_MESSAGE = 141, + /** Inverse Neighbor Discovery Advertisement Message */ + ICMPv6_INVERSE_NEIGHBOR_DISCOVERY_ADVERTISEMENT_MESSAGE = 142, + /** Multicast Listener Report Message */ + ICMPv6_MULTICAST_LISTENER_DISCOVERY_REPORTS = 143, + /** Home Agent Address Discovery Request Message */ + ICMPv6_HOME_AGENT_ADDRESS_DISCOVERY_REQUEST_MESSAGE = 144, + /** Home Agent Address Discovery Reply Message */ + ICMPv6_HOME_AGENT_ADDRESS_DISCOVERY_REPLY_MESSAGE = 145, + /** Mobile Prefix Solicitation Message */ + ICMPv6_MOBILE_PREFIX_SOLICITATION = 146, + /** Mobile Prefix Advertisement Message */ + ICMPv6_MOBILE_PREFIX_ADVERTISEMENT = 147, + /** Certification Path Solicitation Message */ + ICMPv6_CERTIFICATION_PATH_SOLICITATION = 148, + /** Certification Path Advertisement Message */ + ICMPv6_CERTIFICATION_PATH_ADVERTISEMENT = 149, + /** ICMP Experimental Mobility Subtype Format and Registry Message */ + ICMPv6_EXPERIMENTAL_MOBILITY = 150, + /** Multicast Router Advertisement Message */ + ICMPv6_MULTICAST_ROUTER_ADVERTISEMENT = 151, + /** Multicast Router Solicitation Message */ + ICMPv6_MULTICAST_ROUTER_SOLICITATION = 152, + /** Multicast Router Termination Message*/ + ICMPv6_MULTICAST_ROUTER_TERMINATION = 153, + /** RPL Control Message */ + ICMPv6_RPL_CONTROL_MESSAGE = 155, + /** Private Experimentation Message */ + ICMPv6_PRIVATE_EXPERIMENTATION3 = 200, + /** Private Experimentation Message */ + ICMPv6_PRIVATE_EXPERIMENTATION4 = 201, + /** Reserved for expansion of ICMPv6 informational messages */ + ICMPv6_RESERVED_EXPANSION_INFORMATIONAL = 255 + }; /** * @struct icmpv6hdr * Represents an ICMPv6 protocol header */ #pragma pack(push, 1) -struct icmpv6hdr -{ - /** Type of the message. Values in the range from 0 to 127 (high-order bit is 0) indicate an error message, - while values in the range from 128 to 255 (high-order bit is 1) indicate an information message. */ - uint8_t type; - /** The code field value depends on the message type and provides an additional level of message granularity */ - uint8_t code; - /** The checksum field provides a minimal level of integrity verification for the ICMP message */ - uint16_t checksum; -}; + struct icmpv6hdr + { + /** Type of the message. Values in the range from 0 to 127 (high-order bit is 0) indicate an error message, + while values in the range from 128 to 255 (high-order bit is 1) indicate an information message. */ + uint8_t type; + /** The code field value depends on the message type and provides an additional level of message granularity */ + uint8_t code; + /** The checksum field provides a minimal level of integrity verification for the ICMP message */ + uint16_t checksum; + }; #pragma pack(pop) /** @@ -116,165 +116,193 @@ struct icmpv6hdr * ICMP echo request/reply message structure */ #pragma pack(push, 1) -typedef struct icmpv6_echo_hdr : icmpv6hdr -{ - /** the echo request identifier */ - uint16_t id; - /** the echo request sequence number */ - uint16_t sequence; -} icmpv6_echo_hdr; + typedef struct icmpv6_echo_hdr : icmpv6hdr + { + /** the echo request identifier */ + uint16_t id; + /** the echo request sequence number */ + uint16_t sequence; + } icmpv6_echo_hdr; #pragma pack(pop) -/** - * @class IcmpV6Layer - * Base class for ICMPv6 protocol layers which provides common logic for ICMPv6 messages. - */ -class IcmpV6Layer : public Layer -{ -public: - /** - * A constructor that creates the layer from an existing packet raw data - * @param data A pointer to the raw data - * @param dataLen Size of the data in bytes - * @param prevLayer A pointer to the previous layer - * @param packet A pointer to the Packet instance where layer will be stored in - */ - IcmpV6Layer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) { m_Protocol = ICMPv6; } - - /** - * A constructor that allocates a new ICMPv6 layer with type, code and data - * @param[in] msgType Message type of the ICMPv6 layer - * @param[in] code Code field of the ICMPv6 layer - * @param[in] data A pointer to the payload to set - * @param[in] dataLen The length of the payload - */ - IcmpV6Layer(ICMPv6MessageType msgType, uint8_t code, const uint8_t *data, size_t dataLen); - - virtual ~IcmpV6Layer() {} - - /** - * A static method that creates an ICMPv6 layer from packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored - * @return Layer* A newly allocated ICMPv6 layer - */ - static Layer *parseIcmpV6Layer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet); - - /** - * @param[in] type Type to check - * @return True if the layer if of the given type, false otherwise - */ - bool isMessageOfType(ICMPv6MessageType type) const { return getMessageType() == type; } - - /** - * @return Get the ICMPv6 Message Type - */ - ICMPv6MessageType getMessageType() const; - - /** - * @return Get the code header field - */ - uint8_t getCode() const; - - /** - * @return Get the checksum header field in host representation - */ - uint16_t getChecksum() const; - /** - * Does nothing for this layer. ICMPv6 is the last layer. + * @class IcmpV6Layer + * Base class for ICMPv6 protocol layers which provides common logic for ICMPv6 messages. */ - void parseNextLayer() {} - - /** - * @return The size of the ICMPv6 message - */ - size_t getHeaderLen() const { return m_DataLen; } - - /** - * Calculate ICMPv6 checksum field - */ - void computeCalculateFields(); - - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } - - std::string toString() const; - -protected: - IcmpV6Layer() = default; - -private: - void calculateChecksum(); - icmpv6hdr *getIcmpv6Header() const { return (icmpv6hdr *)m_Data; } -}; - -/** - * @class ICMPv6EchoLayer - * Represents an ICMPv6 echo request/reply protocol layer - */ -class ICMPv6EchoLayer : public IcmpV6Layer -{ -public: - /** - * An enum representing ICMPv6 echo message types - */ - enum ICMPv6EchoType + class IcmpV6Layer : public Layer { - /** Echo Request Type */ - REQUEST, - /** Echo Reply Type */ - REPLY + public: + /** + * A constructor that creates the layer from an existing packet raw data + * @param data A pointer to the raw data + * @param dataLen Size of the data in bytes + * @param prevLayer A pointer to the previous layer + * @param packet A pointer to the Packet instance where layer will be stored in + */ + IcmpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = ICMPv6; + } + + /** + * A constructor that allocates a new ICMPv6 layer with type, code and data + * @param[in] msgType Message type of the ICMPv6 layer + * @param[in] code Code field of the ICMPv6 layer + * @param[in] data A pointer to the payload to set + * @param[in] dataLen The length of the payload + */ + IcmpV6Layer(ICMPv6MessageType msgType, uint8_t code, const uint8_t* data, size_t dataLen); + + virtual ~IcmpV6Layer() + {} + + /** + * A static method that creates an ICMPv6 layer from packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored + * @return Layer* A newly allocated ICMPv6 layer + */ + static Layer* parseIcmpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /** + * @param[in] type Type to check + * @return True if the layer if of the given type, false otherwise + */ + bool isMessageOfType(ICMPv6MessageType type) const + { + return getMessageType() == type; + } + + /** + * @return Get the ICMPv6 Message Type + */ + ICMPv6MessageType getMessageType() const; + + /** + * @return Get the code header field + */ + uint8_t getCode() const; + + /** + * @return Get the checksum header field in host representation + */ + uint16_t getChecksum() const; + + /** + * Does nothing for this layer. ICMPv6 is the last layer. + */ + void parseNextLayer() + {} + + /** + * @return The size of the ICMPv6 message + */ + size_t getHeaderLen() const + { + return m_DataLen; + } + + /** + * Calculate ICMPv6 checksum field + */ + void computeCalculateFields(); + + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } + + std::string toString() const; + + protected: + IcmpV6Layer() = default; + + private: + void calculateChecksum(); + icmpv6hdr* getIcmpv6Header() const + { + return (icmpv6hdr*)m_Data; + } }; /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - ICMPv6EchoLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : IcmpV6Layer(data, dataLen, prevLayer, packet) {} - - /** - * A constructor for a new echo request/reply layer - * @param[in] echoType The type of the echo message - * @param[in] id Echo request identifier - * @param[in] sequence Echo request sequence number - * @param[in] data A pointer to echo request payload to set - * @param[in] dataLen The length of the echo request payload - */ - ICMPv6EchoLayer(ICMPv6EchoType echoType, uint16_t id, uint16_t sequence, const uint8_t *data, size_t dataLen); - - virtual ~ICMPv6EchoLayer() {} - - /** - * @return Identifier in host representation - */ - uint16_t getIdentifier() const; - - /** - * @return Sequence number in host representation - */ - uint16_t getSequenceNr() const; - - /** - * @return Size of the data in bytes - */ - size_t getEchoDataLen() const { return m_DataLen - sizeof(icmpv6_echo_hdr); } - - /** - * @return Pointer to the beginning of the data + * @class ICMPv6EchoLayer + * Represents an ICMPv6 echo request/reply protocol layer */ - uint8_t *getEchoDataPtr() const { return m_Data + sizeof(icmpv6_echo_hdr); } - - std::string toString() const; - -private: - icmpv6_echo_hdr *getEchoHeader() const { return (icmpv6_echo_hdr *)m_Data; } -}; + class ICMPv6EchoLayer : public IcmpV6Layer + { + public: + /** + * An enum representing ICMPv6 echo message types + */ + enum ICMPv6EchoType + { + /** Echo Request Type */ + REQUEST, + /** Echo Reply Type */ + REPLY + }; + + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + ICMPv6EchoLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : IcmpV6Layer(data, dataLen, prevLayer, packet) + {} + + /** + * A constructor for a new echo request/reply layer + * @param[in] echoType The type of the echo message + * @param[in] id Echo request identifier + * @param[in] sequence Echo request sequence number + * @param[in] data A pointer to echo request payload to set + * @param[in] dataLen The length of the echo request payload + */ + ICMPv6EchoLayer(ICMPv6EchoType echoType, uint16_t id, uint16_t sequence, const uint8_t* data, size_t dataLen); + + virtual ~ICMPv6EchoLayer() + {} + + /** + * @return Identifier in host representation + */ + uint16_t getIdentifier() const; + + /** + * @return Sequence number in host representation + */ + uint16_t getSequenceNr() const; + + /** + * @return Size of the data in bytes + */ + size_t getEchoDataLen() const + { + return m_DataLen - sizeof(icmpv6_echo_hdr); + } + + /** + * @return Pointer to the beginning of the data + */ + uint8_t* getEchoDataPtr() const + { + return m_Data + sizeof(icmpv6_echo_hdr); + } + + std::string toString() const; + + private: + icmpv6_echo_hdr* getEchoHeader() const + { + return (icmpv6_echo_hdr*)m_Data; + } + }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/IgmpLayer.h b/Packet++/header/IgmpLayer.h index 8178572f17..6106ecf241 100644 --- a/Packet++/header/IgmpLayer.h +++ b/Packet++/header/IgmpLayer.h @@ -13,499 +13,544 @@ namespace pcpp { -/** - * @struct igmp_header - * IGMPv1 and IGMPv2 basic protocol header - */ -struct igmp_header -{ - /** Indicates the message type. The enum for message type is pcpp::IgmpType */ - uint8_t type; - /** Specifies the time limit for the corresponding report. The field has a resolution of 100 milliseconds */ - uint8_t maxResponseTime; - /** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */ - uint16_t checksum; - /** This is the multicast address being queried when sending a Group-Specific or Group-and-Source-Specific Query */ - uint32_t groupAddress; -}; - - -/** - * @struct igmpv3_query_header - * IGMPv3 membership query basic header - */ -struct igmpv3_query_header -{ - /** IGMP message type. Should always have value of membership query (::IgmpType_MembershipQuery) */ - uint8_t type; - /** This field specifies the maximum time (in 1/10 second) allowed before sending a responding report */ - uint8_t maxResponseTime; - /** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */ - uint16_t checksum; - /** This is the multicast address being queried when sending a Group-Specific or Group-and-Source-Specific Query */ - uint32_t groupAddress; - /** Suppress Router-side Processing Flag + Querier's Robustness Variable */ - uint8_t s_qrv; - /** Querier's Query Interval Code */ - uint8_t qqic; - /** This field specifies the number of source addresses present in the Query */ - uint16_t numOfSources; -}; - - -/** - * @struct igmpv3_report_header - * IGMPv3 membership report basic header - */ -struct igmpv3_report_header -{ - /** IGMP message type. Should always have value of IGMPv3 membership report (::IgmpType_MembershipReportV3) */ - uint8_t type; - /** Unused byte */ - uint8_t reserved1; - /** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */ - uint16_t checksum; - /** Unused bytes */ - uint16_t reserved2; - /** This field specifies the number of group records present in the Report */ - uint16_t numOfGroupRecords; -}; - - -/** - * @struct igmpv3_group_record - * A block of fields containing information pertaining to the sender's membership in a single multicast group on the interface - * from which the Report is sent. Relevant only for IGMPv3 membership report messages - */ -struct igmpv3_group_record -{ - /** Group record type */ - uint8_t recordType; - /** Contains the length of the Auxiliary Data field in this Group Record. A value other than 0 isn't supported */ - uint8_t auxDataLen; - /** Specifies how many source addresses are present in this Group Record */ - uint16_t numOfSources; - /** Contains the IP multicast address to which this Group Record pertains */ - uint32_t multicastAddress; - /** A vector of n IP unicast addresses, where n is the value in this record's Number of Sources field */ - uint8_t sourceAddresses[]; - - /** - * @return The multicast address in igmpv3_group_record#multicastAddress as IPv4Address instance - */ - IPv4Address getMulticastAddress() const { return multicastAddress; } - - /** - * @return The number of source addresses in this group record - */ - uint16_t getSourceAddressCount() const; - - /** - * Get the source address at a certain index - * @param[in] index The index of the source address in the group record - * @return The source address in the requested index. If index is negative or higher than the number of source addresses in this - * group record the value if IPv4Address#Zero is returned - */ - IPv4Address getSourceAddressAtIndex(int index) const; - - /** - * @return The total size in bytes of the group record - */ - size_t getRecordLen() const; -}; - - -/** - * IGMP message types - */ -enum IgmpType -{ - /** Unknown message type */ - IgmpType_Unknown = 0, - /** IGMP Membership Query */ - IgmpType_MembershipQuery = 0x11, - /** IGMPv1 Membership Report */ - IgmpType_MembershipReportV1 = 0x12, - /** DVMRP */ - IgmpType_DVMRP = 0x13, - /** PIM version 1 */ - IgmpType_P1Mv1 = 0x14, - /** Cisco Trace Messages */ - IgmpType_CiscoTrace = 0x15, - /** IGMPv2 Membership Report */ - IgmpType_MembershipReportV2 = 0x16, - /** IGMPv2 Leave Group */ - IgmpType_LeaveGroup = 0x17, - /** Multicast Traceroute Response */ - IgmpType_MulticastTracerouteResponse = 0x1e, - /** Multicast Traceroute */ - IgmpType_MulticastTraceroute = 0x1f, - /** IGMPv3 Membership Report */ - IgmpType_MembershipReportV3 = 0x22, - /** MRD, Multicast Router Advertisement */ - IgmpType_MulticastRouterAdvertisement = 0x30, - /** MRD, Multicast Router Solicitation */ - IgmpType_MulticastRouterSolicitation = 0x31, - /** MRD, Multicast Router Termination */ - IgmpType_MulticastRouterTermination = 0x32, -}; - - -/** - * @class IgmpLayer - * A base class for all IGMP (Internet Group Management Protocol) protocol classes. This is an abstract class and cannot be instantiated, - * only its child classes can be instantiated. The inherited classes represent the different versions of the protocol: - * IGMPv1, IGMPv2 and IGMPv3 - */ -class IgmpLayer : public Layer -{ -protected: - - IgmpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType igmpVer) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = igmpVer; } - - IgmpLayer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime, ProtocolType igmpVer); - - uint16_t calculateChecksum(); - - size_t getHeaderSizeByVerAndType(ProtocolType igmpVer, IgmpType igmpType) const; -public: - - virtual ~IgmpLayer() {} - - /** - * Get a pointer to the raw IGMPv1/IGMPv2 header. Notice this points directly to the data, so every change will change the actual packet data - * @return A pointer to the @ref igmp_header - */ - igmp_header* getIgmpHeader() const { return (igmp_header*)m_Data; } - - /** - * @return The IPv4 multicast address stored igmp_header#groupAddress - */ - IPv4Address getGroupAddress() const { return getIgmpHeader()->groupAddress; } - - /** - * Set the IPv4 multicast address - * @param[in] groupAddr The IPv4 address to set - */ - void setGroupAddress(const IPv4Address& groupAddr); - - /** - * @return IGMP type set in igmp_header#type as ::IgmpType enum. Notice that if igmp_header#type contains a value - * that doesn't appear in the ::IgmpType enum, ::IgmpType_Unknown will be returned - */ - IgmpType getType() const; - - /** - * Set IGMP type (will be written to igmp_header#type field) - * @param[in] type The type to set - */ - void setType(IgmpType type); - - /** - * A static method that gets raw IGMP data (byte stream) and returns the IGMP version of this IGMP message - * @param[in] data The IGMP raw data (byte stream) - * @param[in] dataLen Raw data length - * @param[out] isQuery Return true if IGMP message type is ::IgmpType_MembershipQuery and false otherwise - * @return One of the values ::IGMPv1, ::IGMPv2, ::IGMPv3 according to detected IGMP version or ::UnknownProtocol if couldn't detect - * IGMP version - */ - static ProtocolType getIGMPVerFromData(uint8_t* data, size_t dataLen, bool& isQuery); - - - // implement abstract methods - - /** - * Does nothing for this layer (IGMP layer is always last) - */ - void parseNextLayer() {} - - /** - * @return Size of IGMP header = 8B - */ - size_t getHeaderLen() const { return sizeof(igmp_header); } - - std::string toString() const; - - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } -}; - - -/** - * @class IgmpV1Layer - * Represents IGMPv1 (Internet Group Management Protocol ver 1) layer. This class represents all the different messages of IGMPv1 - */ -class IgmpV1Layer : public IgmpLayer -{ -public: - /** A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - IgmpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv1) {} - - /** - * A constructor that allocates a new IGMPv1 header - * @param[in] type The message type to set - * @param[in] groupAddr The multicast address to set. This is an optional parameter and has a default value of IPv4Address#Zero - * if not provided - */ - explicit IgmpV1Layer(IgmpType type, const IPv4Address& groupAddr = IPv4Address()) - : IgmpLayer(type, groupAddr, 0, IGMPv1) {} - - /** - * A destructor for this layer (does nothing) - */ - ~IgmpV1Layer() {} - - - // implement abstract methods - - /** - * Calculate the IGMP checksum and set igmp_header#maxResponseTime to 0 (this field is unused in IGMPv1) - */ - void computeCalculateFields(); - -}; - - -/** - * @class IgmpV2Layer - * Represents IGMPv2 (Internet Group Management Protocol ver 2) layer. This class represents all the different messages of IGMPv2 - */ -class IgmpV2Layer : public IgmpLayer -{ -public: - /** A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - IgmpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv2) {} - - /** - * A constructor that allocates a new IGMPv2 header - * @param[in] type The message type to set - * @param[in] groupAddr The multicast address to set. This is an optional parameter and has a default value of unspecified/zero IPv4 address - * @param[in] maxResponseTime The max response time to set. This is an optional parameter and has a default value of 0 if not provided - */ - explicit IgmpV2Layer(IgmpType type, const IPv4Address& groupAddr = IPv4Address(), uint8_t maxResponseTime = 0) - : IgmpLayer(type, groupAddr, maxResponseTime, IGMPv2) {} - - /** - * A destructor for this layer (does nothing) - */ - ~IgmpV2Layer() {} - - - // implement abstract methods - - /** - * Calculate the IGMP checksum - */ - void computeCalculateFields(); -}; - - -/** - * @class IgmpV3QueryLayer - * Represents an IGMPv3 (Internet Group Management Protocol ver 3) membership query message - */ -class IgmpV3QueryLayer : public IgmpLayer -{ -public: - - /** A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - IgmpV3QueryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - - /** - * A constructor that allocates a new IGMPv3 membership query - * @param[in] multicastAddr The multicast address to set. This is an optional parameter and has a default value of unspecified/zero IPv4 address - * if not provided - * @param[in] maxResponseTime The max response time to set. This is an optional parameter and has a default value of 0 if not provided - * @param[in] s_qrv A 1-byte value representing the value in Suppress Router-side Processing Flag + Querier's Robustness Variable - * (igmpv3_query_header#s_qrv field). This is an optional parameter and has a default value of 0 if not provided - */ - explicit IgmpV3QueryLayer(const IPv4Address& multicastAddr = IPv4Address(), uint8_t maxResponseTime = 0, uint8_t s_qrv = 0); - - /** - * Get a pointer to the raw IGMPv3 membership query header. Notice this points directly to the data, so every change will change the - * actual packet data - * @return A pointer to the @ref igmpv3_query_header - */ - igmpv3_query_header* getIgmpV3QueryHeader() const { return (igmpv3_query_header*)m_Data; } - - /** - * @return The number of source addresses in this message (as extracted from the igmpv3_query_header#numOfSources field) - */ - uint16_t getSourceAddressCount() const; - - /** - * Get the IPV4 source address in a certain index - * @param[in] index The requested index of the source address - * @return The IPv4 source address, or IPv4Address#Zero if index is out of bounds (of the message or of the layer) - */ - IPv4Address getSourceAddressAtIndex(int index) const; - - /** - * Add a new source address at the end of the source address list. The igmpv3_query_header#numOfSources field will be incremented accordingly - * @param[in] addr The IPv4 source address to add - * @return True if source address was added successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log - */ - bool addSourceAddress(const IPv4Address& addr); - - /** - * Add a new source address at a certain index of the source address list. The igmpv3_query_header#numOfSources field will be incremented accordingly - * @param[in] addr The IPv4 source address to add - * @param[in] index The index to add the new source address at - * @return True if source address was added successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log - */ - bool addSourceAddressAtIndex(const IPv4Address& addr, int index); - - /** - * Remove a source address at a certain index. The igmpv3_query_header#numOfSources field will be decremented accordingly - * @param[in] index The index of the source address to be removed - * @return True if source address was removed successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log - */ - bool removeSourceAddressAtIndex(int index); - - /** - * Remove all source addresses in the message. The igmpv3_query_header#numOfSources field will be set to 0 - * @return True if all source addresses were cleared successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log - */ - bool removeAllSourceAddresses(); - - // implement abstract methods - /** - * Calculate the IGMP checksum - */ - void computeCalculateFields(); - - /** - * @return The message size in bytes which include the size of the basic header + the size of the source address list - */ - size_t getHeaderLen() const; -}; - - -/** - * @class IgmpV3ReportLayer - * Represents an IGMPv3 (Internet Group Management Protocol ver 3) membership report message - */ -class IgmpV3ReportLayer : public IgmpLayer -{ -private: - igmpv3_group_record* addGroupRecordAt(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector& sourceAddresses, int offset); - -public: - - /** A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - IgmpV3ReportLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3) {} - - /** - * A constructor that allocates a new IGMPv3 membership report with 0 group addresses - */ - IgmpV3ReportLayer() : IgmpLayer(IgmpType_MembershipReportV3, IPv4Address(), 0, IGMPv3) {} - - /** - * Get a pointer to the raw IGMPv3 membership report header. Notice this points directly to the data, so every change will change the - * actual packet data - * @return A pointer to the @ref igmpv3_report_header - */ - igmpv3_report_header* getReportHeader() const { return (igmpv3_report_header*)m_Data; } - - /** - * @return The number of group records in this message (as extracted from the igmpv3_report_header#numOfGroupRecords field) - */ - uint16_t getGroupRecordCount() const; - - /** - * @return A pointer to the first group record or NULL if no group records exist. Notice the return value is a pointer to the real data, - * so changes in the return value will affect the packet data - */ - igmpv3_group_record* getFirstGroupRecord() const; - - /** - * Get the group record that comes next to a given group record. If "groupRecord" is NULL then NULL will be returned. - * If "groupRecord" is the last group record or if it is out of layer bounds NULL will be returned also. Notice the return value is a - * pointer to the real data casted to igmpv3_group_record type (as opposed to a copy of the option data). So changes in the return - * value will affect the packet data - * @param[in] groupRecord The group record to start searching from - * @return The next group record or NULL if "groupRecord" is NULL, last or out of layer bounds - */ - igmpv3_group_record* getNextGroupRecord(igmpv3_group_record* groupRecord) const; - - /** - * Add a new group record at a the end of the group record list. The igmpv3_report_header#numOfGroupRecords field will be - * incremented accordingly - * @param[in] recordType The type of the new group record - * @param[in] multicastAddress The multicast address of the new group record - * @param[in] sourceAddresses A vector containing all the source addresses of the new group record - * @return The method constructs a new group record, adds it to the end of the group record list of IGMPv3 report message and - * returns a pointer to the new message. If something went wrong in creating or adding the new group record a NULL value is returned - * and an appropriate error message is printed to log - */ - igmpv3_group_record* addGroupRecord(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector& sourceAddresses); - - /** - * Add a new group record at a certain index of the group record list. The igmpv3_report_header#numOfGroupRecords field will be - * incremented accordingly - * @param[in] recordType The type of the new group record - * @param[in] multicastAddress The multicast address of the new group record - * @param[in] sourceAddresses A vector containing all the source addresses of the new group record - * @param[in] index The index to add the new group address at - * @return The method constructs a new group record, adds it to the IGMPv3 report message and returns a pointer to the new message. - * If something went wrong in creating or adding the new group record a NULL value is returned and an appropriate error message is - * printed to log - */ - igmpv3_group_record* addGroupRecordAtIndex(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector& sourceAddresses, int index); - - /** - * Remove a group record at a certain index. The igmpv3_report_header#numOfGroupRecords field will be decremented accordingly - * @param[in] index The index of the group record to be removed - * @return True if group record was removed successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log - */ - bool removeGroupRecordAtIndex(int index); - - /** - * Remove all group records in the message. The igmpv3_report_header#numOfGroupRecords field will be set to 0 - * @return True if all group records were cleared successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log - */ - bool removeAllGroupRecords(); - - // implement abstract methods - - /** - * Calculate the IGMP checksum - */ - void computeCalculateFields(); - - /** - * @return The message size in bytes which include the size of the basic header + the size of the group record list - */ - size_t getHeaderLen() const { return m_DataLen; } -}; - -} + * @struct igmp_header + * IGMPv1 and IGMPv2 basic protocol header + */ + struct igmp_header + { + /** Indicates the message type. The enum for message type is pcpp::IgmpType */ + uint8_t type; + /** Specifies the time limit for the corresponding report. The field has a resolution of 100 milliseconds */ + uint8_t maxResponseTime; + /** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */ + uint16_t checksum; + /** This is the multicast address being queried when sending a Group-Specific or Group-and-Source-Specific Query + */ + uint32_t groupAddress; + }; + + /** + * @struct igmpv3_query_header + * IGMPv3 membership query basic header + */ + struct igmpv3_query_header + { + /** IGMP message type. Should always have value of membership query (::IgmpType_MembershipQuery) */ + uint8_t type; + /** This field specifies the maximum time (in 1/10 second) allowed before sending a responding report */ + uint8_t maxResponseTime; + /** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */ + uint16_t checksum; + /** This is the multicast address being queried when sending a Group-Specific or Group-and-Source-Specific Query + */ + uint32_t groupAddress; + /** Suppress Router-side Processing Flag + Querier's Robustness Variable */ + uint8_t s_qrv; + /** Querier's Query Interval Code */ + uint8_t qqic; + /** This field specifies the number of source addresses present in the Query */ + uint16_t numOfSources; + }; + + /** + * @struct igmpv3_report_header + * IGMPv3 membership report basic header + */ + struct igmpv3_report_header + { + /** IGMP message type. Should always have value of IGMPv3 membership report (::IgmpType_MembershipReportV3) */ + uint8_t type; + /** Unused byte */ + uint8_t reserved1; + /** This is the 16-bit one's complement of the one's complement sum of the entire IGMP message */ + uint16_t checksum; + /** Unused bytes */ + uint16_t reserved2; + /** This field specifies the number of group records present in the Report */ + uint16_t numOfGroupRecords; + }; + + /** + * @struct igmpv3_group_record + * A block of fields containing information pertaining to the sender's membership in a single multicast group on the + * interface from which the Report is sent. Relevant only for IGMPv3 membership report messages + */ + struct igmpv3_group_record + { + /** Group record type */ + uint8_t recordType; + /** Contains the length of the Auxiliary Data field in this Group Record. A value other than 0 isn't supported + */ + uint8_t auxDataLen; + /** Specifies how many source addresses are present in this Group Record */ + uint16_t numOfSources; + /** Contains the IP multicast address to which this Group Record pertains */ + uint32_t multicastAddress; + /** A vector of n IP unicast addresses, where n is the value in this record's Number of Sources field */ + uint8_t sourceAddresses[]; + + /** + * @return The multicast address in igmpv3_group_record#multicastAddress as IPv4Address instance + */ + IPv4Address getMulticastAddress() const + { + return multicastAddress; + } + + /** + * @return The number of source addresses in this group record + */ + uint16_t getSourceAddressCount() const; + + /** + * Get the source address at a certain index + * @param[in] index The index of the source address in the group record + * @return The source address in the requested index. If index is negative or higher than the number of source + * addresses in this group record the value if IPv4Address#Zero is returned + */ + IPv4Address getSourceAddressAtIndex(int index) const; + + /** + * @return The total size in bytes of the group record + */ + size_t getRecordLen() const; + }; + + /** + * IGMP message types + */ + enum IgmpType + { + /** Unknown message type */ + IgmpType_Unknown = 0, + /** IGMP Membership Query */ + IgmpType_MembershipQuery = 0x11, + /** IGMPv1 Membership Report */ + IgmpType_MembershipReportV1 = 0x12, + /** DVMRP */ + IgmpType_DVMRP = 0x13, + /** PIM version 1 */ + IgmpType_P1Mv1 = 0x14, + /** Cisco Trace Messages */ + IgmpType_CiscoTrace = 0x15, + /** IGMPv2 Membership Report */ + IgmpType_MembershipReportV2 = 0x16, + /** IGMPv2 Leave Group */ + IgmpType_LeaveGroup = 0x17, + /** Multicast Traceroute Response */ + IgmpType_MulticastTracerouteResponse = 0x1e, + /** Multicast Traceroute */ + IgmpType_MulticastTraceroute = 0x1f, + /** IGMPv3 Membership Report */ + IgmpType_MembershipReportV3 = 0x22, + /** MRD, Multicast Router Advertisement */ + IgmpType_MulticastRouterAdvertisement = 0x30, + /** MRD, Multicast Router Solicitation */ + IgmpType_MulticastRouterSolicitation = 0x31, + /** MRD, Multicast Router Termination */ + IgmpType_MulticastRouterTermination = 0x32, + }; + + /** + * @class IgmpLayer + * A base class for all IGMP (Internet Group Management Protocol) protocol classes. This is an abstract class and + * cannot be instantiated, only its child classes can be instantiated. The inherited classes represent the different + * versions of the protocol: IGMPv1, IGMPv2 and IGMPv3 + */ + class IgmpLayer : public Layer + { + protected: + IgmpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType igmpVer) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = igmpVer; + } + + IgmpLayer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime, ProtocolType igmpVer); + + uint16_t calculateChecksum(); + + size_t getHeaderSizeByVerAndType(ProtocolType igmpVer, IgmpType igmpType) const; + + public: + virtual ~IgmpLayer() + {} + + /** + * Get a pointer to the raw IGMPv1/IGMPv2 header. Notice this points directly to the data, so every change will + * change the actual packet data + * @return A pointer to the @ref igmp_header + */ + igmp_header* getIgmpHeader() const + { + return (igmp_header*)m_Data; + } + + /** + * @return The IPv4 multicast address stored igmp_header#groupAddress + */ + IPv4Address getGroupAddress() const + { + return getIgmpHeader()->groupAddress; + } + + /** + * Set the IPv4 multicast address + * @param[in] groupAddr The IPv4 address to set + */ + void setGroupAddress(const IPv4Address& groupAddr); + + /** + * @return IGMP type set in igmp_header#type as ::IgmpType enum. Notice that if igmp_header#type contains a + * value that doesn't appear in the ::IgmpType enum, ::IgmpType_Unknown will be returned + */ + IgmpType getType() const; + + /** + * Set IGMP type (will be written to igmp_header#type field) + * @param[in] type The type to set + */ + void setType(IgmpType type); + + /** + * A static method that gets raw IGMP data (byte stream) and returns the IGMP version of this IGMP message + * @param[in] data The IGMP raw data (byte stream) + * @param[in] dataLen Raw data length + * @param[out] isQuery Return true if IGMP message type is ::IgmpType_MembershipQuery and false otherwise + * @return One of the values ::IGMPv1, ::IGMPv2, ::IGMPv3 according to detected IGMP version or + * ::UnknownProtocol if couldn't detect IGMP version + */ + static ProtocolType getIGMPVerFromData(uint8_t* data, size_t dataLen, bool& isQuery); + + // implement abstract methods + + /** + * Does nothing for this layer (IGMP layer is always last) + */ + void parseNextLayer() + {} + + /** + * @return Size of IGMP header = 8B + */ + size_t getHeaderLen() const + { + return sizeof(igmp_header); + } + + std::string toString() const; + + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } + }; + + /** + * @class IgmpV1Layer + * Represents IGMPv1 (Internet Group Management Protocol ver 1) layer. This class represents all the different + * messages of IGMPv1 + */ + class IgmpV1Layer : public IgmpLayer + { + public: + /** A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + IgmpV1Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv1) + {} + + /** + * A constructor that allocates a new IGMPv1 header + * @param[in] type The message type to set + * @param[in] groupAddr The multicast address to set. This is an optional parameter and has a default value of + * IPv4Address#Zero if not provided + */ + explicit IgmpV1Layer(IgmpType type, const IPv4Address& groupAddr = IPv4Address()) + : IgmpLayer(type, groupAddr, 0, IGMPv1) + {} + + /** + * A destructor for this layer (does nothing) + */ + ~IgmpV1Layer() + {} + + // implement abstract methods + + /** + * Calculate the IGMP checksum and set igmp_header#maxResponseTime to 0 (this field is unused in IGMPv1) + */ + void computeCalculateFields(); + }; + + /** + * @class IgmpV2Layer + * Represents IGMPv2 (Internet Group Management Protocol ver 2) layer. This class represents all the different + * messages of IGMPv2 + */ + class IgmpV2Layer : public IgmpLayer + { + public: + /** A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + IgmpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv2) + {} + + /** + * A constructor that allocates a new IGMPv2 header + * @param[in] type The message type to set + * @param[in] groupAddr The multicast address to set. This is an optional parameter and has a default value of + * unspecified/zero IPv4 address + * @param[in] maxResponseTime The max response time to set. This is an optional parameter and has a default + * value of 0 if not provided + */ + explicit IgmpV2Layer(IgmpType type, const IPv4Address& groupAddr = IPv4Address(), uint8_t maxResponseTime = 0) + : IgmpLayer(type, groupAddr, maxResponseTime, IGMPv2) + {} + + /** + * A destructor for this layer (does nothing) + */ + ~IgmpV2Layer() + {} + + // implement abstract methods + + /** + * Calculate the IGMP checksum + */ + void computeCalculateFields(); + }; + + /** + * @class IgmpV3QueryLayer + * Represents an IGMPv3 (Internet Group Management Protocol ver 3) membership query message + */ + class IgmpV3QueryLayer : public IgmpLayer + { + public: + /** A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + IgmpV3QueryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /** + * A constructor that allocates a new IGMPv3 membership query + * @param[in] multicastAddr The multicast address to set. This is an optional parameter and has a default value + * of unspecified/zero IPv4 address if not provided + * @param[in] maxResponseTime The max response time to set. This is an optional parameter and has a default + * value of 0 if not provided + * @param[in] s_qrv A 1-byte value representing the value in Suppress Router-side Processing Flag + Querier's + * Robustness Variable (igmpv3_query_header#s_qrv field). This is an optional parameter and has a default value + * of 0 if not provided + */ + explicit IgmpV3QueryLayer(const IPv4Address& multicastAddr = IPv4Address(), uint8_t maxResponseTime = 0, + uint8_t s_qrv = 0); + + /** + * Get a pointer to the raw IGMPv3 membership query header. Notice this points directly to the data, so every + * change will change the actual packet data + * @return A pointer to the @ref igmpv3_query_header + */ + igmpv3_query_header* getIgmpV3QueryHeader() const + { + return (igmpv3_query_header*)m_Data; + } + + /** + * @return The number of source addresses in this message (as extracted from the + * igmpv3_query_header#numOfSources field) + */ + uint16_t getSourceAddressCount() const; + + /** + * Get the IPV4 source address in a certain index + * @param[in] index The requested index of the source address + * @return The IPv4 source address, or IPv4Address#Zero if index is out of bounds (of the message or of the + * layer) + */ + IPv4Address getSourceAddressAtIndex(int index) const; + + /** + * Add a new source address at the end of the source address list. The igmpv3_query_header#numOfSources field + * will be incremented accordingly + * @param[in] addr The IPv4 source address to add + * @return True if source address was added successfully or false otherwise. If false is returned an appropriate + * error message will be printed to log + */ + bool addSourceAddress(const IPv4Address& addr); + + /** + * Add a new source address at a certain index of the source address list. The igmpv3_query_header#numOfSources + * field will be incremented accordingly + * @param[in] addr The IPv4 source address to add + * @param[in] index The index to add the new source address at + * @return True if source address was added successfully or false otherwise. If false is returned an appropriate + * error message will be printed to log + */ + bool addSourceAddressAtIndex(const IPv4Address& addr, int index); + + /** + * Remove a source address at a certain index. The igmpv3_query_header#numOfSources field will be decremented + * accordingly + * @param[in] index The index of the source address to be removed + * @return True if source address was removed successfully or false otherwise. If false is returned an + * appropriate error message will be printed to log + */ + bool removeSourceAddressAtIndex(int index); + + /** + * Remove all source addresses in the message. The igmpv3_query_header#numOfSources field will be set to 0 + * @return True if all source addresses were cleared successfully or false otherwise. If false is returned an + * appropriate error message will be printed to log + */ + bool removeAllSourceAddresses(); + + // implement abstract methods + + /** + * Calculate the IGMP checksum + */ + void computeCalculateFields(); + + /** + * @return The message size in bytes which include the size of the basic header + the size of the source address + * list + */ + size_t getHeaderLen() const; + }; + + /** + * @class IgmpV3ReportLayer + * Represents an IGMPv3 (Internet Group Management Protocol ver 3) membership report message + */ + class IgmpV3ReportLayer : public IgmpLayer + { + private: + igmpv3_group_record* addGroupRecordAt(uint8_t recordType, const IPv4Address& multicastAddress, + const std::vector& sourceAddresses, int offset); + + public: + /** A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + IgmpV3ReportLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3) + {} + + /** + * A constructor that allocates a new IGMPv3 membership report with 0 group addresses + */ + IgmpV3ReportLayer() : IgmpLayer(IgmpType_MembershipReportV3, IPv4Address(), 0, IGMPv3) + {} + + /** + * Get a pointer to the raw IGMPv3 membership report header. Notice this points directly to the data, so every + * change will change the actual packet data + * @return A pointer to the @ref igmpv3_report_header + */ + igmpv3_report_header* getReportHeader() const + { + return (igmpv3_report_header*)m_Data; + } + + /** + * @return The number of group records in this message (as extracted from the + * igmpv3_report_header#numOfGroupRecords field) + */ + uint16_t getGroupRecordCount() const; + + /** + * @return A pointer to the first group record or NULL if no group records exist. Notice the return value is a + * pointer to the real data, so changes in the return value will affect the packet data + */ + igmpv3_group_record* getFirstGroupRecord() const; + + /** + * Get the group record that comes next to a given group record. If "groupRecord" is NULL then NULL will be + * returned. If "groupRecord" is the last group record or if it is out of layer bounds NULL will be returned + * also. Notice the return value is a pointer to the real data casted to igmpv3_group_record type (as opposed to + * a copy of the option data). So changes in the return value will affect the packet data + * @param[in] groupRecord The group record to start searching from + * @return The next group record or NULL if "groupRecord" is NULL, last or out of layer bounds + */ + igmpv3_group_record* getNextGroupRecord(igmpv3_group_record* groupRecord) const; + + /** + * Add a new group record at a the end of the group record list. The igmpv3_report_header#numOfGroupRecords + * field will be incremented accordingly + * @param[in] recordType The type of the new group record + * @param[in] multicastAddress The multicast address of the new group record + * @param[in] sourceAddresses A vector containing all the source addresses of the new group record + * @return The method constructs a new group record, adds it to the end of the group record list of IGMPv3 + * report message and returns a pointer to the new message. If something went wrong in creating or adding the + * new group record a NULL value is returned and an appropriate error message is printed to log + */ + igmpv3_group_record* addGroupRecord(uint8_t recordType, const IPv4Address& multicastAddress, + const std::vector& sourceAddresses); + + /** + * Add a new group record at a certain index of the group record list. The + * igmpv3_report_header#numOfGroupRecords field will be incremented accordingly + * @param[in] recordType The type of the new group record + * @param[in] multicastAddress The multicast address of the new group record + * @param[in] sourceAddresses A vector containing all the source addresses of the new group record + * @param[in] index The index to add the new group address at + * @return The method constructs a new group record, adds it to the IGMPv3 report message and returns a pointer + * to the new message. If something went wrong in creating or adding the new group record a NULL value is + * returned and an appropriate error message is printed to log + */ + igmpv3_group_record* addGroupRecordAtIndex(uint8_t recordType, const IPv4Address& multicastAddress, + const std::vector& sourceAddresses, int index); + + /** + * Remove a group record at a certain index. The igmpv3_report_header#numOfGroupRecords field will be + * decremented accordingly + * @param[in] index The index of the group record to be removed + * @return True if group record was removed successfully or false otherwise. If false is returned an appropriate + * error message will be printed to log + */ + bool removeGroupRecordAtIndex(int index); + + /** + * Remove all group records in the message. The igmpv3_report_header#numOfGroupRecords field will be set to 0 + * @return True if all group records were cleared successfully or false otherwise. If false is returned an + * appropriate error message will be printed to log + */ + bool removeAllGroupRecords(); + + // implement abstract methods + + /** + * Calculate the IGMP checksum + */ + void computeCalculateFields(); + + /** + * @return The message size in bytes which include the size of the basic header + the size of the group record + * list + */ + size_t getHeaderLen() const + { + return m_DataLen; + } + }; + +} // namespace pcpp diff --git a/Packet++/header/LLCLayer.h b/Packet++/header/LLCLayer.h index 3fff4eccb0..f88eacb7c2 100644 --- a/Packet++/header/LLCLayer.h +++ b/Packet++/header/LLCLayer.h @@ -10,21 +10,21 @@ */ namespace pcpp { +#pragma pack(push, 1) /** * @struct llc_header * Logical Link Control (LLC) header */ - #pragma pack(push, 1) struct llc_header { /// Destination Service Access Point uint8_t dsap, - /// Source Service Access Point - ssap, - /// Control Field - control; + /// Source Service Access Point + ssap, + /// Control Field + control; }; - #pragma pack(pop) +#pragma pack(pop) /** * @class LLCLayer @@ -33,7 +33,6 @@ namespace pcpp class LLCLayer : public Layer { public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data (will be casted to llc_header) @@ -41,7 +40,11 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - LLCLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = LLC; } + LLCLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = LLC; + } /** * A constructor that creates the LLC layer from provided values @@ -55,7 +58,10 @@ namespace pcpp * Get a pointer to Logical Link Control (LLC) layer header * @return Pointer to LLC header */ - inline llc_header *getLlcHeader() const { return (llc_header*)m_Data; }; + inline llc_header* getLlcHeader() const + { + return (llc_header*)m_Data; + }; // overridden methods @@ -63,12 +69,16 @@ namespace pcpp void parseNextLayer(); /// Does nothing for this layer - void computeCalculateFields() {} + void computeCalculateFields() + {} /** * @return Get the size of the LLC header */ - size_t getHeaderLen() const { return sizeof(llc_header); } + size_t getHeaderLen() const + { + return sizeof(llc_header); + } /** * @return Returns the protocol info as readable string @@ -78,7 +88,10 @@ namespace pcpp /** * @return The OSI layer level of LLC (Data Link Layer). */ - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } /** * A static method that validates the input data @@ -86,7 +99,7 @@ namespace pcpp * @param[in] dataLen The length of the byte stream * @return True if the data is valid and can represent an LLC packet */ - static bool isDataValid(const uint8_t *data, size_t dataLen); + static bool isDataValid(const uint8_t* data, size_t dataLen); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/Layer.h b/Packet++/header/Layer.h index cc8abcd7f7..7f49f423ae 100644 --- a/Packet++/header/Layer.h +++ b/Packet++/header/Layer.h @@ -16,8 +16,8 @@ namespace pcpp /** * @class IDataContainer - * An interface (virtual abstract class) that indicates an object that holds a pointer to a buffer data. The Layer class is an example - * of such object, hence it inherits this interface + * An interface (virtual abstract class) that indicates an object that holds a pointer to a buffer data. The Layer + * class is an example of such object, hence it inherits this interface */ class IDataContainer { @@ -29,64 +29,77 @@ namespace pcpp */ virtual uint8_t* getDataPtr(size_t offset = 0) const = 0; - virtual ~IDataContainer() {} + virtual ~IDataContainer() + {} }; class Packet; /** * @class Layer - * Layer is the base class for all protocol layers. Each protocol supported in PcapPlusPlus has a class that inherits Layer. + * Layer is the base class for all protocol layers. Each protocol supported in PcapPlusPlus has a class that + * inherits Layer. * The protocol layer class expose all properties and methods relevant for viewing and editing protocol fields. - * For example: a pointer to a structured header (e.g tcphdr, iphdr, etc.), protocol header size, payload size, compute - * fields that can be automatically computed, print protocol data to string, etc. - * Each protocol instance is obviously part of a protocol stack (which construct a packet). This protocol stack is represented - * in PcapPlusPlus in a linked list, and each layer is an element in this list. That's why each layer has properties to the next and previous - * layer in the protocol stack - * The Layer class, as a base class, is abstract and the user can't create an instance of it (it has a private constructor) - * Each layer holds a pointer to the relevant place in the packet. The layer sees all the data from this pointer forward until the - * end of the packet. Here is an example packet showing this concept: + * For example: a pointer to a structured header (e.g tcphdr, iphdr, etc.), protocol header size, payload size, + * compute fields that can be automatically computed, print protocol data to string, etc. + * Each protocol instance is obviously part of a protocol stack (which construct a packet). This protocol stack is + * represented in PcapPlusPlus in a linked list, and each layer is an element in this list. That's why each layer + * has properties to the next and previous layer in the protocol stack. The Layer class, as a base class, is + * abstract and the user can't create an instance of it (it has a private constructor). Each layer holds a pointer + * to the relevant place in the packet. The layer sees all the data from this pointer forward until the end of the + * packet. Here is an example packet showing this concept: * - @verbatim - ==================================================== - |Eth |IPv4 |TCP |Packet | - |Header |Header |Header |Payload | - ==================================================== - - |--------------------------------------------------| - EthLayer data - |---------------------------------------| - IPv4Layer data - |---------------------------| - TcpLayer data - |----------------| - PayloadLayer data - @endverbatim + * @verbatim + * ==================================================== + * |Eth |IPv4 |TCP |Packet | + * |Header |Header |Header |Payload | + * ==================================================== * - */ + * |--------------------------------------------------| + * EthLayer data + * |---------------------------------------| + * IPv4Layer data + * |---------------------------| + * TcpLayer data + * |----------------| + * PayloadLayer data + * @endverbatim + * + */ class Layer : public IDataContainer { friend class Packet; + public: /** - * A destructor for this class. Frees the data if it was allocated by the layer constructor (see isAllocatedToPacket() for more info) + * A destructor for this class. Frees the data if it was allocated by the layer constructor (see + * isAllocatedToPacket() for more info) */ virtual ~Layer(); /** * @return A pointer to the next layer in the protocol stack or NULL if the layer is the last one */ - Layer* getNextLayer() const { return m_NextLayer; } + Layer* getNextLayer() const + { + return m_NextLayer; + } /** * @return A pointer to the previous layer in the protocol stack or NULL if the layer is the first one */ - Layer* getPrevLayer() const { return m_PrevLayer; } + Layer* getPrevLayer() const + { + return m_PrevLayer; + } /** * @return The protocol enum */ - ProtocolType getProtocol() const { return m_Protocol; } + ProtocolType getProtocol() const + { + return m_Protocol; + } /** * Check if the layer's protocol matches a protocol family @@ -98,32 +111,50 @@ namespace pcpp /** * @return A pointer to the layer raw data. In most cases it'll be a pointer to the first byte of the header */ - uint8_t* getData() const { return m_Data; } + uint8_t* getData() const + { + return m_Data; + } /** * @return The length in bytes of the data from the first byte of the header until the end of the packet */ - size_t getDataLen() const { return m_DataLen; } + size_t getDataLen() const + { + return m_DataLen; + } /** * @return A pointer for the layer payload, meaning the first byte after the header */ - uint8_t* getLayerPayload() const { return m_Data + getHeaderLen(); } + uint8_t* getLayerPayload() const + { + return m_Data + getHeaderLen(); + } /** * @return The size in bytes of the payload */ - size_t getLayerPayloadSize() const { return m_DataLen - getHeaderLen(); } + size_t getLayerPayloadSize() const + { + return m_DataLen - getHeaderLen(); + } /** * Raw data in layers can come from one of sources: - * 1. from an existing packet - this is the case when parsing packets received from files or the network. In this case the data was - * already allocated by someone else, and layer only holds the pointer to the relevant place inside this data - * 2. when creating packets, data is allocated when layer is created. In this case the layer is responsible for freeing it as well + * 1. from an existing packet - this is the case when parsing packets received from files or the network. In + * this case the data was already allocated by someone else, and layer only holds the pointer to the relevant + * place inside this data + * 2. when creating packets, data is allocated when layer is created. In this case the layer is responsible for + * freeing it as well * - * @return Returns true if the data was allocated by an external source (a packet) or false if it was allocated by the layer itself + * @return Returns true if the data was allocated by an external source (a packet) or false if it was allocated + * by the layer itself */ - bool isAllocatedToPacket() const { return m_Packet != NULL; } + bool isAllocatedToPacket() const + { + return m_Packet != NULL; + } /** * Copy the raw data of this layer to another array @@ -133,8 +164,10 @@ namespace pcpp // implement abstract methods - uint8_t* getDataPtr(size_t offset = 0) const { return (uint8_t*)(m_Data + offset); } - + uint8_t* getDataPtr(size_t offset = 0) const + { + return (uint8_t*)(m_Data + offset); + } // abstract methods @@ -154,7 +187,8 @@ namespace pcpp virtual void computeCalculateFields() = 0; /** - * @return A string representation of the layer most important data (should look like the layer description in Wireshark) + * @return A string representation of the layer most important data (should look like the layer description in + * Wireshark) */ virtual std::string toString() const = 0; @@ -172,27 +206,36 @@ namespace pcpp Layer* m_PrevLayer; bool m_IsAllocatedInPacket; - Layer() : m_Data(NULL), m_DataLen(0), m_Packet(NULL), m_Protocol(UnknownProtocol), m_NextLayer(NULL), m_PrevLayer(NULL), m_IsAllocatedInPacket(false) { } + Layer() + : m_Data(NULL), m_DataLen(0), m_Packet(NULL), m_Protocol(UnknownProtocol), m_NextLayer(NULL), + m_PrevLayer(NULL), m_IsAllocatedInPacket(false) + {} - Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : - m_Data(data), m_DataLen(dataLen), - m_Packet(packet), m_Protocol(UnknownProtocol), - m_NextLayer(NULL), m_PrevLayer(prevLayer), m_IsAllocatedInPacket(false) {} + Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : m_Data(data), m_DataLen(dataLen), m_Packet(packet), m_Protocol(UnknownProtocol), m_NextLayer(NULL), + m_PrevLayer(prevLayer), m_IsAllocatedInPacket(false) + {} // Copy c'tor Layer(const Layer& other); Layer& operator=(const Layer& other); - void setNextLayer(Layer* nextLayer) { m_NextLayer = nextLayer; } - void setPrevLayer(Layer* prevLayer) { m_PrevLayer = prevLayer; } + void setNextLayer(Layer* nextLayer) + { + m_NextLayer = nextLayer; + } + void setPrevLayer(Layer* prevLayer) + { + m_PrevLayer = prevLayer; + } virtual bool extendLayer(int offsetInLayer, size_t numOfBytesToExtend); virtual bool shortenLayer(int offsetInLayer, size_t numOfBytesToShorten); }; -} // namespace pcpp +} // namespace pcpp -inline std::ostream& operator<<(std::ostream& os, const pcpp::Layer &layer) +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 92751cecd5..c2d68a26e3 100644 --- a/Packet++/header/LdapLayer.h +++ b/Packet++/header/LdapLayer.h @@ -76,10 +76,11 @@ namespace pcpp // cppcheck-suppress noExplicitConstructor /** - * Construct LdapOperationType from Value enum - * @param[in] value the opetation type enum value - */ - constexpr LdapOperationType(Value value) : m_Value(value) {} + * Construct LdapOperationType from Value enum + * @param[in] value the opetation type enum value + */ + constexpr LdapOperationType(Value value) : m_Value(value) + {} /** * @return A string representation of the operation type @@ -95,7 +96,10 @@ namespace pcpp static LdapOperationType fromUintValue(uint8_t value); // Allow switch and comparisons. - constexpr operator Value() const { return m_Value; } + constexpr operator Value() const + { + return m_Value; + } // Prevent usage: if(LdapOperationType) explicit operator bool() const = delete; @@ -123,7 +127,7 @@ namespace pcpp /** * Indicates that there was a problem with the client’s use of the LDAP protocol */ - OperationsError= 1, + OperationsError = 1, /** * Indicates that there was a problem with the client’s use of the LDAP protocol */ @@ -312,10 +316,11 @@ namespace pcpp // cppcheck-suppress noExplicitConstructor /** - * Construct LdapResultCode from Value enum - * @param[in] value the result code enum value - */ - constexpr LdapResultCode(Value value) : m_Value(value) { } + * Construct LdapResultCode from Value enum + * @param[in] value the result code enum value + */ + constexpr LdapResultCode(Value value) : m_Value(value) + {} /** * @return A string representation of the result code @@ -331,10 +336,14 @@ namespace pcpp static LdapResultCode fromUintValue(uint8_t value); // Allow switch and comparisons - constexpr operator Value() const { return m_Value; } + constexpr operator Value() const + { + return m_Value; + } // Prevent usage: if(LdapResultCode) explicit operator bool() const = delete; + private: Value m_Value = LdapResultCode::Unknown; }; @@ -398,11 +407,11 @@ namespace pcpp * @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message * will be created without LDAP controls */ - LdapLayer(uint16_t messageId, LdapOperationType operationType, - const std::vector& messageRecords, - const std::vector& controls = std::vector()); + LdapLayer(uint16_t messageId, LdapOperationType operationType, const std::vector& messageRecords, + const std::vector& controls = std::vector()); - ~LdapLayer() {} + ~LdapLayer() + {} /** * @return The root ASN.1 record of the LDAP message. All of the message data will be under this record. @@ -428,7 +437,8 @@ namespace pcpp std::vector getControls() const; /** - * @return The LDAP operation of this message. If the Operation ASN.1 record is malformed, an exception is thrown + * @return The LDAP operation of this message. If the Operation ASN.1 record is malformed, an exception is + * thrown */ virtual LdapOperationType getLdapOperationType() const; @@ -452,8 +462,7 @@ namespace pcpp * @param[out] result An outvariable to contain the result if no exception is thrown * @return True if no exception was thrown or false otherwise */ - template - bool tryGet(Method method, ResultType& result) + template bool tryGet(Method method, ResultType& result) { return internalTryGet(this, method, result); } @@ -463,7 +472,10 @@ namespace pcpp * @param[in] port The port number to check * @return True if this is an LDAP port, false otherwise */ - static bool isLdapPort(uint16_t port) { return port == 389; } + static bool isLdapPort(uint16_t port) + { + return port == 389; + } /** * A static message to parse an LDAP message from raw data @@ -485,21 +497,33 @@ namespace pcpp /** * @return The size of the LDAP message */ - size_t getHeaderLen() const override { return m_Asn1Record->getTotalLength(); } + size_t getHeaderLen() const override + { + return m_Asn1Record->getTotalLength(); + } - void computeCalculateFields() override {} + void computeCalculateFields() override + {} - OsiModelLayer getOsiModelLayer() const override { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const override + { + return OsiModelApplicationLayer; + } std::string toString() const override; protected: std::unique_ptr m_Asn1Record; - LdapLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + LdapLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet); LdapLayer() = default; - void init(uint16_t messageId, LdapOperationType operationType, const std::vector& messageRecords, const std::vector& controls); - virtual std::string getExtendedInfoString() const { return ""; } + void init(uint16_t messageId, LdapOperationType operationType, const std::vector& messageRecords, + const std::vector& controls); + virtual std::string getExtendedInfoString() const + { + return ""; + } static constexpr int messageIdIndex = 0; static constexpr int operationTypeIndex = 1; @@ -553,6 +577,7 @@ namespace pcpp * somewhere else. If referral doesn't exist on the message, and empty vector is returned */ std::vector getReferral() const; + protected: static constexpr int resultCodeIndex = 0; static constexpr int matchedDNIndex = 1; @@ -562,19 +587,21 @@ namespace pcpp static constexpr uint8_t referralTagType = 3; LdapResponseLayer() = default; - LdapResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} LdapResponseLayer(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, - const std::string& matchedDN, const std::string& diagnosticMessage, - const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()); + const std::string& matchedDN, const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()); void init(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, - const std::string& matchedDN, const std::string& diagnosticMessage, - const std::vector& referral = std::vector(), - const std::vector& additionalRecords = std::vector(), - const std::vector& controls = std::vector()); + const std::string& matchedDN, const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& additionalRecords = std::vector(), + const std::vector& controls = std::vector()); std::string getExtendedInfoString() const override; }; @@ -640,9 +667,9 @@ namespace pcpp * @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message * will be created without LDAP controls */ - LdapBindRequestLayer( - uint16_t messageId, uint8_t version, const std::string& name, const std::string& simpleAuthentication, - const std::vector& controls = std::vector()); + LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, + const std::string& simpleAuthentication, + const std::vector& controls = std::vector()); /** * A constructor to create a new LDAP bind request message with SASL authentication @@ -653,9 +680,9 @@ namespace pcpp * @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message * will be created without LDAP controls */ - LdapBindRequestLayer( - uint16_t messageId, uint8_t version, const std::string& name, const SaslAuthentication& saslAuthentication, - const std::vector& controls = std::vector()); + LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, + const SaslAuthentication& saslAuthentication, + const std::vector& controls = std::vector()); /** * @return The LDAP protocol version that the client wants to use @@ -684,18 +711,21 @@ namespace pcpp */ SaslAuthentication getSaslAuthentication() const; - template - bool tryGet(Method method, ResultType& result) + template bool tryGet(Method method, ResultType& result) { return internalTryGet(this, method, result); } + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapBindRequestLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapBindRequestLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} std::string getExtendedInfoString() const override; + private: static constexpr int versionIndex = 0; static constexpr int nameIndex = 1; @@ -727,21 +757,25 @@ namespace pcpp * will be created without LDAP controls */ LdapBindResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& serverSaslCredentials = std::vector(), - const std::vector& controls = std::vector()); + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& serverSaslCredentials = std::vector(), + const std::vector& controls = std::vector()); /** * @return Encoded server SASL credentials for use in subsequent processing */ std::vector getServerSaslCredentials() const; + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); static constexpr int serverSaslCredentialsTagType = 7; - LdapBindResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapBindResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -757,23 +791,29 @@ namespace pcpp * @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message * will be created without LDAP controls */ - explicit LdapUnbindRequestLayer(uint16_t messageId, const std::vector& controls = std::vector()); + explicit LdapUnbindRequestLayer(uint16_t messageId, + const std::vector& controls = std::vector()); // Unbind request has no operation record Asn1ConstructedRecord* getLdapOperationAsn1Record() const = delete; - LdapOperationType getLdapOperationType() const override { return LdapOperationType::UnbindRequest; } + LdapOperationType getLdapOperationType() const override + { + return LdapOperationType::UnbindRequest; + } - template - bool tryGet(Method method, ResultType& result) + template bool tryGet(Method method, ResultType& result) { return internalTryGet(this, method, result); } + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapUnbindRequestLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapUnbindRequestLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -828,7 +868,8 @@ namespace pcpp * Construct SearchRequestScope from Value enum * @param[in] value the scope enum value */ - constexpr SearchRequestScope(Value value) : m_Value(value) {} + constexpr SearchRequestScope(Value value) : m_Value(value) + {} /** * @return A string representation of the scope value @@ -844,10 +885,14 @@ namespace pcpp static SearchRequestScope fromUintValue(uint8_t value); // Allow switch and comparisons. - constexpr operator Value() const { return m_Value; } + constexpr operator Value() const + { + return m_Value; + } // Prevent usage: if(LdapOperationType) explicit operator bool() const = delete; + private: Value m_Value = SearchRequestScope::Unknown; }; @@ -883,7 +928,8 @@ namespace pcpp * Construct DerefAliases from Value enum * @param[in] value the dereference alias enum value */ - constexpr DerefAliases(Value value) : m_Value(value) {} + constexpr DerefAliases(Value value) : m_Value(value) + {} /** * @return A string representation of the dereference alias value @@ -899,10 +945,14 @@ namespace pcpp static DerefAliases fromUintValue(uint8_t value); // Allow switch and comparisons. - constexpr operator Value() const { return m_Value; } + constexpr operator Value() const + { + return m_Value; + } // Prevent usage: if(LdapOperationType) explicit operator bool() const = delete; + private: Value m_Value = DerefAliases::Unknown; }; @@ -928,10 +978,10 @@ namespace pcpp * @param[in] controls A vector of LDAP controls. This is an optional parameter, if not provided the message * will be created without LDAP controls */ - LdapSearchRequestLayer( - uint16_t messageId, const std::string& baseObject, SearchRequestScope scope, DerefAliases derefAliases, - uint8_t sizeLimit, uint8_t timeLimit, bool typesOnly, Asn1Record* filterRecord, - const std::vector& attributes, const std::vector& controls = std::vector()); + LdapSearchRequestLayer(uint16_t messageId, const std::string& baseObject, SearchRequestScope scope, + DerefAliases derefAliases, uint8_t sizeLimit, uint8_t timeLimit, bool typesOnly, + Asn1Record* filterRecord, const std::vector& attributes, + const std::vector& controls = std::vector()); /** * @return The base object for the LDAP search request entry @@ -977,8 +1027,7 @@ namespace pcpp */ std::vector getAttributes() const; - template - bool tryGet(Method method, ResultType& result) + template bool tryGet(Method method, ResultType& result) { return internalTryGet(this, method, result); } @@ -995,9 +1044,10 @@ namespace pcpp static constexpr int filterIndex = 6; static constexpr int attributesIndex = 7; - LdapSearchRequestLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} - + LdapSearchRequestLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} std::string getExtendedInfoString() const override; }; @@ -1018,8 +1068,8 @@ namespace pcpp * will be created without LDAP controls */ LdapSearchResultEntryLayer(uint16_t messageId, const std::string& objectName, - const std::vector& attributes, - const std::vector& controls = std::vector()); + const std::vector& attributes, + const std::vector& controls = std::vector()); /** * @return The entry's DN @@ -1031,11 +1081,11 @@ namespace pcpp */ std::vector getAttributes() const; - template - bool tryGet(Method method, ResultType& result) + template bool tryGet(Method method, ResultType& result) { return internalTryGet(this, method, result); } + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); @@ -1044,8 +1094,10 @@ namespace pcpp static constexpr int attributeTypeIndex = 0; static constexpr int attributeValueIndex = 1; - LdapSearchResultEntryLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapSearchResultEntryLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) + : LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -1069,14 +1121,20 @@ namespace pcpp * will be created without LDAP controls */ LdapSearchResultDoneLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()) - : LdapResponseLayer(messageId, LdapOperationType::SearchResultDone, resultCode, matchedDN, diagnosticMessage, referral, controls) {} + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()) + : LdapResponseLayer(messageId, LdapOperationType::SearchResultDone, resultCode, matchedDN, + diagnosticMessage, referral, controls) + {} + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapSearchResultDoneLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapSearchResultDoneLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -1100,14 +1158,20 @@ namespace pcpp * will be created without LDAP controls */ LdapModifyResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()) - : LdapResponseLayer(messageId, LdapOperationType::ModifyResponse, resultCode, matchedDN, diagnosticMessage, referral, controls) {} + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()) + : LdapResponseLayer(messageId, LdapOperationType::ModifyResponse, resultCode, matchedDN, diagnosticMessage, + referral, controls) + {} + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapModifyResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapModifyResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -1131,14 +1195,20 @@ namespace pcpp * will be created without LDAP controls */ LdapAddResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()) - : LdapResponseLayer(messageId, LdapOperationType::AddResponse, resultCode, matchedDN, diagnosticMessage, referral, controls) {} + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()) + : LdapResponseLayer(messageId, LdapOperationType::AddResponse, resultCode, matchedDN, diagnosticMessage, + referral, controls) + {} + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapAddResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapAddResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -1162,14 +1232,20 @@ namespace pcpp * will be created without LDAP controls */ LdapDeleteResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()) - : LdapResponseLayer(messageId, LdapOperationType::DeleteResponse, resultCode, matchedDN, diagnosticMessage, referral, controls) {} + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()) + : LdapResponseLayer(messageId, LdapOperationType::DeleteResponse, resultCode, matchedDN, diagnosticMessage, + referral, controls) + {} + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapDeleteResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapDeleteResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -1193,14 +1269,20 @@ namespace pcpp * will be created without LDAP controls */ LdapModifyDNResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()) - : LdapResponseLayer(messageId, LdapOperationType::ModifyDNResponse, resultCode, matchedDN, diagnosticMessage, referral, controls) {} + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()) + : LdapResponseLayer(messageId, LdapOperationType::ModifyDNResponse, resultCode, matchedDN, + diagnosticMessage, referral, controls) + {} + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapModifyDNResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapModifyDNResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; /** @@ -1224,16 +1306,22 @@ namespace pcpp * will be created without LDAP controls */ LdapCompareResponseLayer(uint16_t messageId, LdapResultCode resultCode, const std::string& matchedDN, - const std::string& diagnosticMessage, const std::vector& referral = std::vector(), - const std::vector& controls = std::vector()) - : LdapResponseLayer(messageId, LdapOperationType::CompareResponse, resultCode, matchedDN, diagnosticMessage, referral, controls) {} + const std::string& diagnosticMessage, + const std::vector& referral = std::vector(), + const std::vector& controls = std::vector()) + : LdapResponseLayer(messageId, LdapOperationType::CompareResponse, resultCode, matchedDN, diagnosticMessage, + referral, controls) + {} + protected: friend LdapLayer* LdapLayer::parseLdapMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - LdapCompareResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) {} + LdapCompareResponseLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, + Layer* prevLayer, Packet* packet) + : LdapResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet) + {} }; -} // namespace pcpp +} // namespace pcpp inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapControl& control) { @@ -1259,7 +1347,8 @@ inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapAttribute& att return os; } -inline std::ostream& operator<<(std::ostream& os, const pcpp::LdapBindRequestLayer::SaslAuthentication& saslAuthentication) +inline std::ostream& operator<<(std::ostream& os, + const pcpp::LdapBindRequestLayer::SaslAuthentication& saslAuthentication) { os << "{" << saslAuthentication.mechanism << ", {"; diff --git a/Packet++/header/MplsLayer.h b/Packet++/header/MplsLayer.h index ef59a6eedc..b40f8f57a1 100644 --- a/Packet++/header/MplsLayer.h +++ b/Packet++/header/MplsLayer.h @@ -18,48 +18,62 @@ namespace pcpp class MplsLayer : public Layer { private: - - #pragma pack(push, 1) +#pragma pack(push, 1) struct mpls_header { uint16_t hiLabel; - uint8_t misc; - uint8_t ttl; + uint8_t misc; + uint8_t ttl; }; - #pragma pack(pop) +#pragma pack(pop) - mpls_header* getMplsHeader() const { return (mpls_header*)m_Data; } + mpls_header* getMplsHeader() const + { + return (mpls_header*)m_Data; + } public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - MplsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = MPLS; } + MplsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = MPLS; + } /** * A constructor that allocates a new MPLS header * @param[in] mplsLabel MPLS label * @param[in] ttl Time-to-leave value * @param[in] experimentalUseValue Experimental use value - * @param[in] bottomOfStack Bottom-of-stack value which indicate whether the next layer will also be a MPLS label or not + * @param[in] bottomOfStack Bottom-of-stack value which indicate whether the next layer will also be a MPLS + * label or not */ MplsLayer(uint32_t mplsLabel, uint8_t ttl, uint8_t experimentalUseValue, bool bottomOfStack); - virtual ~MplsLayer() {} + virtual ~MplsLayer() + {} /** * @return TTL value of the MPLS header */ - uint8_t getTTL() const { return getMplsHeader()->ttl; } + uint8_t getTTL() const + { + return getMplsHeader()->ttl; + } /** * Set the TTL value * @param[in] ttl The TTL value to set */ - void setTTL(uint8_t ttl) { getMplsHeader()->ttl = ttl; } + void setTTL(uint8_t ttl) + { + getMplsHeader()->ttl = ttl; + } /** * Get an indication whether the next layer is also be a MPLS label or not @@ -107,17 +121,23 @@ namespace pcpp /** * @return Size of MPLS header (4 bytes) */ - size_t getHeaderLen() const { return sizeof(mpls_header); } + size_t getHeaderLen() const + { + return sizeof(mpls_header); + } /** - * Set/unset the bottom-of-stack bit according to next layer: if it's a MPLS layer then bottom-of-stack will be unset. If it's not a - * MPLS layer this bit will be set + * Set/unset the bottom-of-stack bit according to next layer: if it's a MPLS layer then bottom-of-stack will be + * unset. If it's not a MPLS layer this bit will be set */ void computeCalculateFields(); std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelNetworkLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/NdpLayer.h b/Packet++/header/NdpLayer.h index 9e5df7a34b..6ff9f76b18 100644 --- a/Packet++/header/NdpLayer.h +++ b/Packet++/header/NdpLayer.h @@ -17,353 +17,395 @@ namespace pcpp { -/** - * An enum representing the available option types for Neighbor Discovery in IPv6 (see RFC 4861) - */ -enum class NDPNeighborOptionTypes : int -{ - NDP_OPTION_SOURCE_LINK_LAYER = 1, - NDP_OPTION_TARGET_LINK_LAYER = 2, - NDP_OPTION_PREFIX_INFORMATION = 3, - NDP_OPTION_REDIRECTED_HEADER = 4, - NDP_OPTION_MTU = 5, - NDP_OPTION_UNKNOWN = 255 -}; - -/** - * @class NdpOption - * A wrapper class for NDP options. This class does not create or modify NDP option records, but rather - * serves as a wrapper and provides useful methods for retrieving data from them - */ -class NdpOption : public TLVRecord -{ -public: /** - * A c'tor for this class that gets a pointer to the option raw data (byte array) - * @param[in] optionRawData A pointer to the NDP option raw data + * An enum representing the available option types for Neighbor Discovery in IPv6 (see RFC 4861) */ - explicit NdpOption(uint8_t *optionRawData) : TLVRecord(optionRawData) {} - - /** - * A d'tor for this class, currently does nothing - */ - ~NdpOption() {} - - /** - * @return NDP option type casted as pcpp::NDPNeighborOptionTypes enum. If the data is null a value - * of NDP_OPTION_UNKNOWN is returned - */ - NDPNeighborOptionTypes getNdpOptionType() const - { - if (m_Data == nullptr) - return NDPNeighborOptionTypes::NDP_OPTION_UNKNOWN; - - return static_cast(m_Data->recordType); - } - - // implement abstract methods - - size_t getTotalSize() const - { - if (m_Data == nullptr) - return (size_t)0; - - return (size_t)m_Data->recordLen * 8; - } - - size_t getDataSize() const + enum class NDPNeighborOptionTypes : int { - if (m_Data == nullptr) - return 0; - - return (size_t)m_Data->recordLen * 8 - (2 * sizeof(uint8_t)); // length value is stored in units of 8 octets - } -}; - -/** - * @class NdpOptionBuilder - * A class for building NDP option records. This builder receives the NDP option parameters in its c'tor, - * builds the NDP option raw buffer and provides a build() method to get a NdpOption object out of it - */ -class NdpOptionBuilder : public TLVRecordBuilder -{ -public: - /** - * A c'tor for building NDP options which their value is a byte array. The NdpOption object can be later - * retrieved by calling build(). Each option is padded to have a 64-bit boundary. - * @param[in] optionType NDP option type - * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any - * way. - * @param[in] optionValueLen Option value length in bytes - */ - NdpOptionBuilder(NDPNeighborOptionTypes optionType, const uint8_t *optionValue, uint8_t optionValueLen) - : TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) {} - - /** - * Build the NdpOption object out of the parameters defined in the c'tor. Padding bytes are added to the - * option for option length with 64-bit boundaries. - * @return The NdpOption object - */ - NdpOption build() const; -}; - -/** - * @class NDPLayerBase - * Represents a base for NDP packet types - */ -class NDPLayerBase : public IcmpV6Layer -{ -public: - virtual ~NDPLayerBase() {} - - /** - * @return The number of NDP options in this layer - */ - size_t getNdpOptionCount() const; - - /** - * Get a NDP option by type. - * @param[in] option NDP option type - * @return An NdpOption object that contains the first option that matches this type, or logical NULL - * (NdpOption#isNull() == true) if no such option found - */ - NdpOption getNdpOption(NDPNeighborOptionTypes option) const; - - /** - * @return The first NDP option in the packet. If the current layer contains no options the returned value will - * contain a logical NULL (NdpOption#isNull() == true) - */ - NdpOption getFirstNdpOption() const; - - /** - * Get the NDP option that comes after a given option. If the given option was the last one, the - * returned value will contain a logical NULL (IdpOption#isNull() == true) - * @param[in] option An NDP option object that exists in the current layer - * @return A NdpOption object that contains the NDP option data that comes next, or logical NULL if the given - * NDP option: (1) was the last one; or (2) contains a logical NULL; or (3) doesn't belong to this packet - */ - NdpOption getNextNdpOption(NdpOption &option) const; - - /** - * Add a new NDP option at the end of the layer (after the last NDP option) - * @param[in] optionBuilder An NdpOptionBuilder object that contains the NDP option data to be added - * @return A NdpOption object that contains the newly added NDP option data or logical NULL - * (NdpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be - * printed to log - */ - NdpOption addNdpOption(const NdpOptionBuilder &optionBuilder); + NDP_OPTION_SOURCE_LINK_LAYER = 1, + NDP_OPTION_TARGET_LINK_LAYER = 2, + NDP_OPTION_PREFIX_INFORMATION = 3, + NDP_OPTION_REDIRECTED_HEADER = 4, + NDP_OPTION_MTU = 5, + NDP_OPTION_UNKNOWN = 255 + }; /** - * Remove all NDP options from the layer - * @return True if options removed successfully or false if some error occurred (an appropriate error message will - * be printed to log) + * @class NdpOption + * A wrapper class for NDP options. This class does not create or modify NDP option records, but rather + * serves as a wrapper and provides useful methods for retrieving data from them */ - bool removeAllNdpOptions(); - -protected: - NDPLayerBase() = default; - - NDPLayerBase(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : IcmpV6Layer(data, dataLen, prevLayer, packet) {} - -private: - TLVRecordReader m_OptionReader; - - virtual size_t getNdpHeaderLen() const = 0; - virtual uint8_t *getNdpOptionsBasePtr() const { return m_Data + getNdpHeaderLen(); }; - NdpOption addNdpOptionAt(const NdpOptionBuilder &optionBuilder, int offset); -}; - -/** - * @class NDPNeighborSolicitationLayer - * Represents a NDP Neighbor Solicitation protocol layer - */ -class NDPNeighborSolicitationLayer : public NDPLayerBase -{ -public: - /** - * @struct ndpneighborsolicitationhdr - * Represents neighbor solicitation message format - */ -#pragma pack(push, 1) - struct ndpneighborsolicitationhdr : icmpv6hdr + class NdpOption : public TLVRecord { - /** Reserved */ - uint32_t reserved; - /** Target address - Target address of solicitation message */ - uint8_t targetIP[16]; + public: + /** + * A c'tor for this class that gets a pointer to the option raw data (byte array) + * @param[in] optionRawData A pointer to the NDP option raw data + */ + explicit NdpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) + {} + + /** + * A d'tor for this class, currently does nothing + */ + ~NdpOption() + {} + + /** + * @return NDP option type casted as pcpp::NDPNeighborOptionTypes enum. If the data is null a value + * of NDP_OPTION_UNKNOWN is returned + */ + NDPNeighborOptionTypes getNdpOptionType() const + { + if (m_Data == nullptr) + return NDPNeighborOptionTypes::NDP_OPTION_UNKNOWN; + + return static_cast(m_Data->recordType); + } + + // implement abstract methods + + size_t getTotalSize() const + { + if (m_Data == nullptr) + return (size_t)0; + + return (size_t)m_Data->recordLen * 8; + } + + size_t getDataSize() const + { + if (m_Data == nullptr) + { + return 0; + } + + // length value is stored in units of 8 octets + return (size_t)m_Data->recordLen * 8 - (2 * sizeof(uint8_t)); + } }; -#pragma pack(pop) - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - NDPNeighborSolicitationLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : NDPLayerBase(data, dataLen, prevLayer, packet) {} /** - * A constructor for a new NDPNeighborSolicitationLayer object - * @param[in] code Code field - * @param[in] targetIP Target IP address for which the solicitation shall be created + * @class NdpOptionBuilder + * A class for building NDP option records. This builder receives the NDP option parameters in its c'tor, + * builds the NDP option raw buffer and provides a build() method to get a NdpOption object out of it */ - NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address &targetIP); - - /** - * A constructor for a new NDPNeighborSolicitationLayer object - * @param[in] code Code field - * @param[in] targetIP Target IP address for which the solicitation shall be created - * @param[in] srcMac Mac address which shall be put in the linklayer option - */ - NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address &targetIP, const MacAddress &srcMac); - - virtual ~NDPNeighborSolicitationLayer() {} - - /** - * @return Get the IP address specified as the target IP address in the solicitation message - */ - IPv6Address getTargetIP() const { return IPv6Address(getNdpHeader()->targetIP); }; + class NdpOptionBuilder : public TLVRecordBuilder + { + public: + /** + * A c'tor for building NDP options which their value is a byte array. The NdpOption object can be later + * retrieved by calling build(). Each option is padded to have a 64-bit boundary. + * @param[in] optionType NDP option type + * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in + * any way. + * @param[in] optionValueLen Option value length in bytes + */ + NdpOptionBuilder(NDPNeighborOptionTypes optionType, const uint8_t* optionValue, uint8_t optionValueLen) + : TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) + {} + + /** + * Build the NdpOption object out of the parameters defined in the c'tor. Padding bytes are added to the + * option for option length with 64-bit boundaries. + * @return The NdpOption object + */ + NdpOption build() const; + }; /** - * Checks if the layer has a link layer address option set - * @return true if link layer address option is available, false otherwise + * @class NDPLayerBase + * Represents a base for NDP packet types */ - bool hasLinkLayerAddress() const; + class NDPLayerBase : public IcmpV6Layer + { + public: + virtual ~NDPLayerBase() + {} + + /** + * @return The number of NDP options in this layer + */ + size_t getNdpOptionCount() const; + + /** + * Get a NDP option by type. + * @param[in] option NDP option type + * @return An NdpOption object that contains the first option that matches this type, or logical NULL + * (NdpOption#isNull() == true) if no such option found + */ + NdpOption getNdpOption(NDPNeighborOptionTypes option) const; + + /** + * @return The first NDP option in the packet. If the current layer contains no options the returned value will + * contain a logical NULL (NdpOption#isNull() == true) + */ + NdpOption getFirstNdpOption() const; + + /** + * Get the NDP option that comes after a given option. If the given option was the last one, the + * returned value will contain a logical NULL (IdpOption#isNull() == true) + * @param[in] option An NDP option object that exists in the current layer + * @return A NdpOption object that contains the NDP option data that comes next, or logical NULL if the given + * NDP option: (1) was the last one; or (2) contains a logical NULL; or (3) doesn't belong to this packet + */ + NdpOption getNextNdpOption(NdpOption& option) const; + + /** + * Add a new NDP option at the end of the layer (after the last NDP option) + * @param[in] optionBuilder An NdpOptionBuilder object that contains the NDP option data to be added + * @return A NdpOption object that contains the newly added NDP option data or logical NULL + * (NdpOption#isNull() == true) if addition failed. In case of a failure a corresponding error message will be + * printed to log + */ + NdpOption addNdpOption(const NdpOptionBuilder& optionBuilder); + + /** + * Remove all NDP options from the layer + * @return True if options removed successfully or false if some error occurred (an appropriate error message + * will be printed to log) + */ + bool removeAllNdpOptions(); + + protected: + NDPLayerBase() = default; + + NDPLayerBase(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : IcmpV6Layer(data, dataLen, prevLayer, packet) + {} + + private: + TLVRecordReader m_OptionReader; + + virtual size_t getNdpHeaderLen() const = 0; + virtual uint8_t* getNdpOptionsBasePtr() const + { + return m_Data + getNdpHeaderLen(); + }; + NdpOption addNdpOptionAt(const NdpOptionBuilder& optionBuilder, int offset); + }; /** - * Get the Link Layer Address - * @return Mac address which is specified in the link layer address option + * @class NDPNeighborSolicitationLayer + * Represents a NDP Neighbor Solicitation protocol layer */ - MacAddress getLinkLayerAddress() const; - - std::string toString() const; + class NDPNeighborSolicitationLayer : public NDPLayerBase + { + public: + /** + * @struct ndpneighborsolicitationhdr + * Represents neighbor solicitation message format + */ +#pragma pack(push, 1) + struct ndpneighborsolicitationhdr : icmpv6hdr + { + /** Reserved */ + uint32_t reserved; + /** Target address - Target address of solicitation message */ + uint8_t targetIP[16]; + }; +#pragma pack(pop) -private: - void initLayer(uint8_t code, const IPv6Address &targetIP); - ndpneighborsolicitationhdr *getNdpHeader() const { return (ndpneighborsolicitationhdr *)m_Data; } - size_t getNdpHeaderLen() const { return sizeof(ndpneighborsolicitationhdr); }; -}; + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + NDPNeighborSolicitationLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : NDPLayerBase(data, dataLen, prevLayer, packet) + {} + + /** + * A constructor for a new NDPNeighborSolicitationLayer object + * @param[in] code Code field + * @param[in] targetIP Target IP address for which the solicitation shall be created + */ + NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address& targetIP); + + /** + * A constructor for a new NDPNeighborSolicitationLayer object + * @param[in] code Code field + * @param[in] targetIP Target IP address for which the solicitation shall be created + * @param[in] srcMac Mac address which shall be put in the linklayer option + */ + NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address& targetIP, const MacAddress& srcMac); + + virtual ~NDPNeighborSolicitationLayer() + {} + + /** + * @return Get the IP address specified as the target IP address in the solicitation message + */ + IPv6Address getTargetIP() const + { + return IPv6Address(getNdpHeader()->targetIP); + }; + + /** + * Checks if the layer has a link layer address option set + * @return true if link layer address option is available, false otherwise + */ + bool hasLinkLayerAddress() const; + + /** + * Get the Link Layer Address + * @return Mac address which is specified in the link layer address option + */ + MacAddress getLinkLayerAddress() const; + + std::string toString() const; + + private: + void initLayer(uint8_t code, const IPv6Address& targetIP); + ndpneighborsolicitationhdr* getNdpHeader() const + { + return (ndpneighborsolicitationhdr*)m_Data; + } + size_t getNdpHeaderLen() const + { + return sizeof(ndpneighborsolicitationhdr); + }; + }; -/** - * @class NDPNeighborAdvertisementLayer - * Represents a NDP Neighbor Advertisement protocol layer - */ -class NDPNeighborAdvertisementLayer : public NDPLayerBase -{ -public: /** - * @struct ndpneighboradvertisementhdr - * Represents neighbor advertisement message format + * @class NDPNeighborAdvertisementLayer + * Represents a NDP Neighbor Advertisement protocol layer */ -#pragma pack(push, 1) - struct ndpneighboradvertisementhdr : icmpv6hdr + class NDPNeighborAdvertisementLayer : public NDPLayerBase { + public: + /** + * @struct ndpneighboradvertisementhdr + * Represents neighbor advertisement message format + */ +#pragma pack(push, 1) + struct ndpneighboradvertisementhdr : icmpv6hdr + { #if (BYTE_ORDER == LITTLE_ENDIAN) - uint32_t - /** Unused field */ - reserved : 5, - /** Flag indicating that this entry should override the old one */ - override : 1, - /** Flag indicating that the advertisement was sent in response to a Neighbor Solicitation from the - Destination address */ - solicited : 1, - /** Flag indicating that the advertisement is sent by a router */ - router : 1, - /** Unused field */ - reserved2 : 24; + uint32_t + /** Unused field */ + reserved : 5, + /** Flag indicating that this entry should override the old one */ + override : 1, + /** Flag indicating that the advertisement was sent in response to a Neighbor Solicitation from the + Destination address */ + solicited : 1, + /** Flag indicating that the advertisement is sent by a router */ + router : 1, + /** Unused field */ + reserved2 : 24; #else - uint32_t - /** Flag indicating that the advertisement is sent by a router */ - router : 1, - /** Flag indicating that the advertisement was sent in response to a Neighbor Solicitation from the - Destination address */ - solicited : 1, - /** Flag indicating that this entry should override the old one */ - override : 1, - /** Unused field */ - reserved : 29; + uint32_t + /** Flag indicating that the advertisement is sent by a router */ + router : 1, + /** Flag indicating that the advertisement was sent in response to a Neighbor Solicitation from the + Destination address */ + solicited : 1, + /** Flag indicating that this entry should override the old one */ + override : 1, + /** Unused field */ + reserved : 29; #endif - /** Target address - Either source address of advertisement or address for requested MAC */ - uint8_t targetIP[16]; - }; + /** Target address - Either source address of advertisement or address for requested MAC */ + uint8_t targetIP[16]; + }; #pragma pack(pop) - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - NDPNeighborAdvertisementLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : NDPLayerBase(data, dataLen, prevLayer, packet) {} - - /** - * A constructor that allocates a new NDP Advertisement Layer with target link-layer address option - * @param[in] code Code field - * @param[in] targetIP The target IP address from the Neighbor Solicitation message (solicited advertisements) or - * the address whose link-layer address has changed (unsolicited advertisement) - * @param[in] targetMac Adds the target link-layer address into the option field of the layer - * @param[in] routerFlag The router flag - * @param[in] unicastFlag The solicited flag - * @param[in] overrideFlag The override flag - */ - NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address &targetIP, const MacAddress &targetMac, - bool routerFlag, bool unicastFlag, bool overrideFlag); - - /** - * A constructor that allocates a new NDP Advertisement Layer - * @param code Code field - * @param targetIP The target IP address from the Neighbor Solicitation message (solicited advertisements) or the - * address whose link-layer address has changed (unsolicited advertisement) - * @param routerFlag The router flag - * @param unicastFlag The solicited flag - * @param overrideFlag The override flag - */ - NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address &targetIP, bool routerFlag, bool unicastFlag, - bool overrideFlag); - - virtual ~NDPNeighborAdvertisementLayer() {} - - /** - * @return Get the target MAC address - */ - MacAddress getTargetMac() const; - - /** - * @return Get the target IP address - */ - IPv6Address getTargetIP() const { return IPv6Address(getNdpHeader()->targetIP); } - - /** - * @return Get information if the target link-layer address was added in the option field of the header - */ - bool hasTargetMacInfo() const; - - /** - * @return Get the router flag - */ - bool getRouterFlag() const { return getNdpHeader()->router; } - - /** - * @return Get the unicast flag - */ - bool getUnicastFlag() const { return getNdpHeader()->solicited; } - - /** - * @return Get the override flag - */ - bool getOverrideFlag() const { return getNdpHeader()->override; } - - std::string toString() const; - -private: - void initLayer(uint8_t code, const IPv6Address &targetIP, bool routerFlag, bool unicastFlag, bool overrideFlag); - ndpneighboradvertisementhdr *getNdpHeader() const { return (ndpneighboradvertisementhdr *)m_Data; } - size_t getNdpHeaderLen() const { return sizeof(ndpneighboradvertisementhdr); }; -}; + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + NDPNeighborAdvertisementLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : NDPLayerBase(data, dataLen, prevLayer, packet) + {} + + /** + * A constructor that allocates a new NDP Advertisement Layer with target link-layer address option + * @param[in] code Code field + * @param[in] targetIP The target IP address from the Neighbor Solicitation message (solicited advertisements) + * or the address whose link-layer address has changed (unsolicited advertisement) + * @param[in] targetMac Adds the target link-layer address into the option field of the layer + * @param[in] routerFlag The router flag + * @param[in] unicastFlag The solicited flag + * @param[in] overrideFlag The override flag + */ + NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, const MacAddress& targetMac, + bool routerFlag, bool unicastFlag, bool overrideFlag); + + /** + * A constructor that allocates a new NDP Advertisement Layer + * @param code Code field + * @param targetIP The target IP address from the Neighbor Solicitation message (solicited advertisements) or + * the address whose link-layer address has changed (unsolicited advertisement) + * @param routerFlag The router flag + * @param unicastFlag The solicited flag + * @param overrideFlag The override flag + */ + NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, bool routerFlag, bool unicastFlag, + bool overrideFlag); + + virtual ~NDPNeighborAdvertisementLayer() + {} + + /** + * @return Get the target MAC address + */ + MacAddress getTargetMac() const; + + /** + * @return Get the target IP address + */ + IPv6Address getTargetIP() const + { + return IPv6Address(getNdpHeader()->targetIP); + } + + /** + * @return Get information if the target link-layer address was added in the option field of the header + */ + bool hasTargetMacInfo() const; + + /** + * @return Get the router flag + */ + bool getRouterFlag() const + { + return getNdpHeader()->router; + } + + /** + * @return Get the unicast flag + */ + bool getUnicastFlag() const + { + return getNdpHeader()->solicited; + } + + /** + * @return Get the override flag + */ + bool getOverrideFlag() const + { + return getNdpHeader()->override; + } + + std::string toString() const; + + private: + void initLayer(uint8_t code, const IPv6Address& targetIP, bool routerFlag, bool unicastFlag, bool overrideFlag); + ndpneighboradvertisementhdr* getNdpHeader() const + { + return (ndpneighboradvertisementhdr*)m_Data; + } + size_t getNdpHeaderLen() const + { + return sizeof(ndpneighboradvertisementhdr); + }; + }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/NflogLayer.h b/Packet++/header/NflogLayer.h index af2ddc5106..2818035fe2 100644 --- a/Packet++/header/NflogLayer.h +++ b/Packet++/header/NflogLayer.h @@ -31,43 +31,43 @@ namespace pcpp /** * @enum NflogTlvType * Represents TLV types of NFLOG packets - */ + */ enum class NflogTlvType { /** the packet header structure */ - NFULA_PACKET_HDR = 1, + NFULA_PACKET_HDR = 1, /** packet mark from skbuff */ - NFULA_MARK = 2, + NFULA_MARK = 2, /** nflog_timestamp_t for skbuff's time stamp */ - NFULA_TIMESTAMP = 3, + NFULA_TIMESTAMP = 3, /** ifindex of device on which packet received (possibly bridge group) */ - NFULA_IFINDEX_INDEV = 4, + NFULA_IFINDEX_INDEV = 4, /** ifindex of device on which packet transmitted (possibly bridge group) */ - NFULA_IFINDEX_OUTDEV = 5, + NFULA_IFINDEX_OUTDEV = 5, /** ifindex of physical device on which packet received (not bridge group) */ - NFULA_IFINDEX_PHYSINDEV = 6, + NFULA_IFINDEX_PHYSINDEV = 6, /** ifindex of physical device on which packet transmitted (not bridge group) */ - NFULA_IFINDEX_PHYSOUTDEV = 7, + NFULA_IFINDEX_PHYSOUTDEV = 7, /** nflog_hwaddr_t for hardware address */ - NFULA_HWADDR = 8, + NFULA_HWADDR = 8, /** packet payload */ - NFULA_PAYLOAD = 9, + NFULA_PAYLOAD = 9, /** text string - null-terminated, count includes NUL */ - NFULA_PREFIX = 10, + NFULA_PREFIX = 10, /** UID owning socket on which packet was sent/received */ - NFULA_UID = 11, + NFULA_UID = 11, /** sequence number of packets on this NFLOG socket */ - NFULA_SEQ = 12, + NFULA_SEQ = 12, /** sequence number of packets on all NFLOG sockets */ - NFULA_SEQ_GLOBAL = 13, + NFULA_SEQ_GLOBAL = 13, /** GID owning socket on which packet was sent/received */ - NFULA_GID = 14, + NFULA_GID = 14, /** ARPHRD_ type of skbuff's device */ - NFULA_HWTYPE = 15, + NFULA_HWTYPE = 15, /** skbuff's MAC-layer header */ - NFULA_HWHEADER = 16, + NFULA_HWHEADER = 16, /** length of skbuff's MAC-layer header */ - NFULA_HWLEN = 17, + NFULA_HWLEN = 17, }; /** @@ -88,6 +88,7 @@ namespace pcpp uint8_t recordValue[]; }; NflogTLVRawData* m_Data; + public: /** * A c'tor for this class that gets a pointer to the option raw data (byte array) @@ -103,7 +104,8 @@ namespace pcpp */ size_t getTotalSize() const { - // as in https://github.com/the-tcpdump-group/libpcap/blob/766b607d60d8038087b49fc4cf433dac3dcdb49c/pcap-util.c#L371-L374 + // as in + // https://github.com/the-tcpdump-group/libpcap/blob/766b607d60d8038087b49fc4cf433dac3dcdb49c/pcap-util.c#L371-L374 return align<4>(m_Data->recordLen); } @@ -138,17 +140,26 @@ namespace pcpp /** * @return The type field of the record (the 'T' in __Type__-Length-Value) */ - uint16_t getType() const { return m_Data->recordType; } + uint16_t getType() const + { + return m_Data->recordType; + } /** * @return A pointer to the TLV record raw data byte stream */ - uint8_t* getRecordBasePtr() const { return (uint8_t*)m_Data; } + uint8_t* getRecordBasePtr() const + { + return (uint8_t*)m_Data; + } /** * @return A pointer to the value of the record as byte array (the 'V' in Type-Length- __Value__) */ - uint8_t* getValue() const { return m_Data->recordValue; } + uint8_t* getValue() const + { + return m_Data->recordValue; + } }; /** @@ -164,40 +175,49 @@ namespace pcpp * @param[in] dataLen Size of the data in bytes * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - NflogLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = NFLOG; } + NflogLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) + { + m_Protocol = NFLOG; + } - ~NflogLayer() {} + ~NflogLayer() + {} /** * Get a pointer to the Nflog header. * @return A pointer to the nflog_header */ - nflog_header* getNflogHeader() const { return (nflog_header*)m_Data; } + nflog_header* getNflogHeader() const + { + return (nflog_header*)m_Data; + } /** * Get address family of the packet. e.g. 2 for ipv4 and 10 for ipv6 * @return an unsigned char of address family - */ + */ uint8_t getFamily(); /** * Get Version number inside packet header * The version field is 0 for the current version of the pseudo-header * @return an unsigned char for version - */ + */ uint8_t getVersion(); /** * Get Resource Id in packet header - * On one netlink socket it's possible to listen to several nflog groups; the resource ID is the nflog group for the packet - */ + * On one netlink socket it's possible to listen to several nflog groups; the resource ID is the nflog group for + * the packet + */ uint16_t getResourceId(); /** - * Get a TLV object found with the input type. if no tlv is found, the internal value of the object will set to nullptr + * Get a TLV object found with the input type. if no tlv is found, the internal value of the object will set to + * nullptr * @param[in] type type of tlv by using enum class defined as NflogTlvType * @return NflogTlv obtained by type - */ + */ NflogTlv getTlvByType(NflogTlvType type) const; // implement abstract methods @@ -215,25 +235,31 @@ namespace pcpp /** * Does nothing for this layer - */ + */ void computeCalculateFields() {}; std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } /** - * A static method that validates the input data - * @param[in] data The pointer to the beginning of a byte stream of an NFLOG packet - * @param[in] dataLen The length of the byte stream - * @return True if the data is valid and can represent an NFLOG packet - */ + * A static method that validates the input data + * @param[in] data The pointer to the beginning of a byte stream of an NFLOG packet + * @param[in] dataLen The length of the byte stream + * @return True if the data is valid and can represent an NFLOG packet + */ static bool isDataValid(const uint8_t* data, size_t dataLen); private: - uint8_t* getTlvsBasePtr() const { return m_Data + sizeof(nflog_header); } + uint8_t* getTlvsBasePtr() const + { + return m_Data + sizeof(nflog_header); + } TLVRecordReader m_TlvReader; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/NtpLayer.h b/Packet++/header/NtpLayer.h index ef8c7256f3..8badfbc64e 100644 --- a/Packet++/header/NtpLayer.h +++ b/Packet++/header/NtpLayer.h @@ -12,663 +12,692 @@ */ namespace pcpp { - /** + /** * @class NtpLayer * Represents a NTP (Network Time Protocol) layer - * - * @brief The NTP packet consists of an integral number of 32-bit (4 octet) words in network byte order. - * The packet format consists of three components: the header itself, one or more optional extension fields (for v4), - * and an optional message authentication code (MAC). Currently the extension fields are not supported. The NTP header is: - * - * @verbatim - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |LI | VN |Mode | Stratum | Poll | Precision | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Root Delay | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Root Dispersion | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Reference ID | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + Reference Timestamp (64) + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + Origin Timestamp (64) + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + Receive Timestamp (64) + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + Transmit Timestamp (64) + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . . - . Extension Field 1 (variable, only v4) . - . . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - . . - . Extension Field 1 (variable, only v4) . - . . - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Key Identifier | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - | dgst (128 for v4, 64 for v3) | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - @endverbatim - * + * + * @brief The NTP packet consists of an integral number of 32-bit (4 octet) words in network byte order. + * The packet format consists of three components: the header itself, one or more optional extension fields (for + * v4), and an optional message authentication code (MAC). Currently the extension fields are not supported. The NTP + * header is: + * + * @verbatim + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |LI | VN |Mode | Stratum | Poll | Precision | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Root Delay | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Root Dispersion | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reference ID | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Reference Timestamp (64) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Origin Timestamp (64) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Receive Timestamp (64) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + Transmit Timestamp (64) + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Extension Field 1 (variable, only v4) . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + . . + . Extension Field 1 (variable, only v4) . + . . + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Key Identifier | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + | dgst (128 for v4, 64 for v3) | + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + @endverbatim + * */ - class NtpLayer : public Layer - { - private: + class NtpLayer : public Layer + { + private: #pragma pack(push, 1) - struct ntp_header - { + struct ntp_header + { #if (BYTE_ORDER == LITTLE_ENDIAN) - /// 3-bit integer representing the mode - uint8_t mode:3, - /// 3-bit integer representing the NTP version number - version:3, - /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in the last minute of the current month - leapIndicator:2; + /// 3-bit integer representing the mode + uint8_t mode : 3, + /// 3-bit integer representing the NTP version number + version : 3, + /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or + /// deleted in the last minute of the current month + leapIndicator : 2; #else - /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in the last minute of the current month - uint8_t leapIndicator:2, - /// 3-bit integer representing the NTP version number - version:3, - /// 3-bit integer representing the mode - mode:3; + /// LI Leap Indicator (leap): 2-bit integer warning of an impending leap second to be inserted or deleted in + /// the last minute of the current month + uint8_t leapIndicator : 2, + /// 3-bit integer representing the NTP version number + version : 3, + /// 3-bit integer representing the mode + mode : 3; #endif - /// 8-bit integer representing the stratum - uint8_t stratum; - /// Total round-trip delay to the reference clock, in log2 seconds. - int8_t pollInterval, - /// 8-bit signed integer representing the precision of the system clock, in log2 seconds. - precision; - /// Total round-trip delay to the reference clock, in NTP short format. - uint32_t rootDelay, - /// Total dispersion to the reference clock, in NTP short format. - rootDispersion, - /// 32-bit code identifying the particular server or reference clock. The interpretation depends on the value in the stratum field. - referenceIdentifier; - /// Time when the system clock was last set or corrected, in NTP timestamp format. - uint64_t referenceTimestamp, - /// Time at the client when the request departed for the server, in NTP timestamp format. - originTimestamp, - /// Time at the client when the request departed for the server, in NTP timestamp format. - receiveTimestamp, - /// Time at the server when the response left for the client, in NTP timestamp format. - transmitTimestamp; - }; + /// 8-bit integer representing the stratum + uint8_t stratum; + /// Total round-trip delay to the reference clock, in log2 seconds. + int8_t pollInterval, + /// 8-bit signed integer representing the precision of the system clock, in log2 seconds. + precision; + /// Total round-trip delay to the reference clock, in NTP short format. + uint32_t rootDelay, + /// Total dispersion to the reference clock, in NTP short format. + rootDispersion, + /// 32-bit code identifying the particular server or reference clock. The interpretation depends on the + /// value in the stratum field. + referenceIdentifier; + /// Time when the system clock was last set or corrected, in NTP timestamp format. + uint64_t referenceTimestamp, + /// Time at the client when the request departed for the server, in NTP timestamp format. + originTimestamp, + /// Time at the client when the request departed for the server, in NTP timestamp format. + receiveTimestamp, + /// Time at the server when the response left for the client, in NTP timestamp format. + transmitTimestamp; + }; #pragma pack(pop) #pragma pack(push, 1) - struct ntp_v3_auth - { - /// An integer identifying the cryptographic key used to generate the message-authentication code - uint32_t keyID; - /// This is an integer identifying the cryptographic key used to generate the message-authentication code. - uint8_t dgst[8]; // 64 bit DES based - }; + struct ntp_v3_auth + { + /// An integer identifying the cryptographic key used to generate the message-authentication code + uint32_t keyID; + /// This is an integer identifying the cryptographic key used to generate the message-authentication code. + uint8_t dgst[8]; // 64 bit DES based + }; #pragma pack(pop) #pragma pack(push, 1) - struct ntp_v4_auth_md5 - { - /// 32-bit unsigned integer used by the client and server to designate a secret 128-bit MD5 key. - uint32_t keyID; - /// 128-bit MD5 hash - uint8_t dgst[16]; - }; + struct ntp_v4_auth_md5 + { + /// 32-bit unsigned integer used by the client and server to designate a secret 128-bit MD5 key. + uint32_t keyID; + /// 128-bit MD5 hash + uint8_t dgst[16]; + }; #pragma pack(pop) #pragma pack(push, 1) - struct ntp_v4_auth_sha1 - { - /// 32-bit unsigned integer used by the client and server to designate a secret 160-bit SHA1 key. - uint32_t keyID; - /// 160-bit SHA1 hash - uint8_t dgst[20]; - }; + struct ntp_v4_auth_sha1 + { + /// 32-bit unsigned integer used by the client and server to designate a secret 160-bit SHA1 key. + uint32_t keyID; + /// 160-bit SHA1 hash + uint8_t dgst[20]; + }; #pragma pack(pop) - ntp_header *getNtpHeader() const { return (ntp_header *)m_Data; } - - public: - /** - * Warning of an impending leap second to be inserted or deleted in the last minute of the current month - */ - enum LeapIndicator - { - /// Normal, no leap second - NoWarning = 0, - /// Last minute of the day has 61 seconds - Last61Secs, - /// Last minute of the day has 59 seconds - Last59Secs, - /// Unknown (clock unsynchronized) - Unknown - }; - - /** - * Representing the NTP association modes - */ - enum Mode - { - /// Reserved variable - Reserved = 0, - /// Symmetrically active - SymActive, - /// Symmetrically passive - SymPassive, - /// Client mode - Client, - /// Server mode - Server, - /// Broadcasting mode - Broadcast, - /// NTP control messages - Control, - /// Reserved for private use - PrivateUse - }; - - /** - * 32-bit code identifying the particular server or reference clock. - * The interpretation depends on the value in the stratum field. - */ - enum class ClockSource : uint32_t - { - // NTPv4 - - /// Geosynchronous Orbit Environment Satellite - GOES = ('G') | ('O' << 8) | ('E' << 16) | ('S' << 24), - /// Global Position System - GPS = ('G') | ('P' << 8) | ('S' << 16), - /// Galileo Positioning System - GAL = ('G') | ('A' << 8) | ('L' << 16), - /// Generic pulse-per-second - PPS = ('P') | ('P' << 8) | ('S' << 16), - /// Inter-Range Instrumentation Group - IRIG = ('I') | ('R' << 8) | ('I' << 16) | ('G' << 24), - /// LF Radio WWVB Ft. Collins, CO 60 kHz - WWVB = ('W') | ('W' << 8) | ('V' << 16) | ('B' << 24), - /// LF Radio DCF77 Mainflingen, DE 77.5 kHz - DCF = ('D') | ('C' << 8) | ('F' << 16), - /// LF Radio HBG Prangins, HB 75 kHz - HBG = ('H') | ('B' << 8) | ('G' << 16), - /// LF Radio MSF Anthorn, UK 60 kHz - MSF = ('M') | ('S' << 8) | ('F' << 16), - /// LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz - JJY = ('J') | ('J' << 8) | ('Y' << 16), - /// MF Radio LORAN C station, 100 kHz - LORC = ('L') | ('O' << 8) | ('R' << 16) | ('C' << 24), - /// MF Radio Allouis, FR 162 kHz - TDF = ('T') | ('D' << 8) | ('F' << 16), - /// HF Radio CHU Ottawa, Ontario - CHU = ('C') | ('H' << 8) | ('U' << 16), - /// HF Radio WWV Ft. Collins, CO - WWV = ('W') | ('W' << 8) | ('V' << 16), - /// HF Radio WWVH Kauai, HI - WWVH = ('W') | ('W' << 8) | ('V' << 16) | ('H' << 24), - /// NIST telephone modem - NIST = ('N') | ('I' << 8) | ('S' << 16) | ('T' << 24), - /// NIST telephone modem - ACTS = ('A') | ('C' << 8) | ('T' << 16) | ('S' << 24), - /// USNO telephone modem - USNO = ('U') | ('S' << 8) | ('N' << 16) | ('O' << 24), - /// European telephone modem - PTB = ('P') | ('T' << 8) | ('B' << 16), - /// Multi Reference Sources - MRS = ('M') | ('R' << 8) | ('S' << 16), - /// Inter Face Association Changed - XFAC = ('X') | ('F' << 8) | ('A' << 16) | ('C' << 24), - /// Step time change - STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24), - /// Google Refid used by Google NTP servers as time4.google.com - GOOG = ('G') | ('O' << 8) | ('O' << 16) | ('G' << 24), - /// Meinberg DCF77 with amplitude modulation (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - DCFa = ('D') | ('C' << 8) | ('F' << 16) | ('a' << 24), - /// Meinberg DCF77 with phase modulation)/pseudo random phase modulation (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - DCFp = ('D') | ('C' << 8) | ('F' << 16) | ('p' << 24), - /// Meinberg GPS (with shared memory access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - GPSs = ('G') | ('P' << 8) | ('S' << 16) | ('s' << 24), - /// Meinberg GPS (with interrupt based access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - GPSi = ('G') | ('P' << 8) | ('S' << 16) | ('i' << 24), - /// Meinberg GPS/GLONASS (with shared memory access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - GLNs = ('G') | ('L' << 8) | ('N' << 16) | ('s' << 24), - /// Meinberg GPS/GLONASS (with interrupt based access) (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - GLNi = ('G') | ('L' << 8) | ('N' << 16) | ('i' << 24), - /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - LCL = ('L') | ('C' << 8) | ('L' << 16), - /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) - LOCL = ('L') | ('O' << 8) | ('C' << 16) | ('L' << 24), - - // NTPv3 - - /// DCN routing protocol - DCN = ('D') | ('C' << 8) | ('N' << 16), - /// TSP time protocol - TSP = ('T') | ('S' << 8) | ('P' << 16), - /// Digital Time Service - DTS = ('D') | ('T' << 8) | ('S' << 16), - /// Atomic clock (calibrated) - ATOM = ('A') | ('T' << 8) | ('O' << 16) | ('M' << 24), - /// VLF radio (OMEGA, etc.) - VLF = ('V') | ('L' << 8) | ('F' << 16) - - }; - - /** - * 32-bit Kiss of Death (KoD) codes - */ - enum class KissODeath : uint32_t - { - /// The association belongs to a anycast server - ACST = ('A') | ('C' << 8) | ('S' << 16) | ('T' << 24), - /// Server authentication failed - AUTH = ('A') | ('U' << 8) | ('T' << 16) | ('H' << 24), - /// Autokey sequence failed - AUTO = ('A') | ('U' << 8) | ('T' << 16) | ('O' << 24), - /// The association belongs to a broadcast server - BCST = ('B') | ('C' << 8) | ('S' << 16) | ('T' << 24), - /// Cryptographic authentication or identification failed - CRYP = ('C') | ('R' << 8) | ('Y' << 16) | ('P' << 24), - /// Access denied by remote server - DENY = ('D') | ('E' << 8) | ('N' << 16) | ('Y' << 24), - /// Lost peer in symmetric mode - DROP = ('D') | ('R' << 8) | ('O' << 16) | ('P' << 24), - /// Access denied due to local policy - RSTR = ('R') | ('S' << 8) | ('T' << 16) | ('R' << 24), - /// The association has not yet synchronized for the first time - INIT = ('I') | ('N' << 8) | ('I' << 16) | ('T' << 24), - /// The association belongs to a manycast server - MCST = ('M') | ('C' << 8) | ('S' << 16) | ('T' << 24), - /// No key found. Either the key was never installed or is not trusted - NKEY = ('N') | ('K' << 8) | ('E' << 16) | ('Y' << 24), - /// Rate exceeded. The server has temporarily denied access because the client exceeded the rate threshold - RATE = ('R') | ('A' << 8) | ('T' << 16) | ('E' << 24), - /// Somebody is tinkering with the association from a remote host running ntpdc. Not to worry unless some rascal has stolen your keys - RMOT = ('R') | ('M' << 8) | ('O' << 16) | ('T' << 24), - /// A step change in system time has occurred, but the association has not yet resynchronized - STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24), - }; - - /** + ntp_header* getNtpHeader() const + { + return (ntp_header*)m_Data; + } + + public: + /** + * Warning of an impending leap second to be inserted or deleted in the last minute of the current month + */ + enum LeapIndicator + { + /// Normal, no leap second + NoWarning = 0, + /// Last minute of the day has 61 seconds + Last61Secs, + /// Last minute of the day has 59 seconds + Last59Secs, + /// Unknown (clock unsynchronized) + Unknown + }; + + /** + * Representing the NTP association modes + */ + enum Mode + { + /// Reserved variable + Reserved = 0, + /// Symmetrically active + SymActive, + /// Symmetrically passive + SymPassive, + /// Client mode + Client, + /// Server mode + Server, + /// Broadcasting mode + Broadcast, + /// NTP control messages + Control, + /// Reserved for private use + PrivateUse + }; + + /** + * 32-bit code identifying the particular server or reference clock. + * The interpretation depends on the value in the stratum field. + */ + enum class ClockSource : uint32_t + { + // NTPv4 + + /// Geosynchronous Orbit Environment Satellite + GOES = ('G') | ('O' << 8) | ('E' << 16) | ('S' << 24), + /// Global Position System + GPS = ('G') | ('P' << 8) | ('S' << 16), + /// Galileo Positioning System + GAL = ('G') | ('A' << 8) | ('L' << 16), + /// Generic pulse-per-second + PPS = ('P') | ('P' << 8) | ('S' << 16), + /// Inter-Range Instrumentation Group + IRIG = ('I') | ('R' << 8) | ('I' << 16) | ('G' << 24), + /// LF Radio WWVB Ft. Collins, CO 60 kHz + WWVB = ('W') | ('W' << 8) | ('V' << 16) | ('B' << 24), + /// LF Radio DCF77 Mainflingen, DE 77.5 kHz + DCF = ('D') | ('C' << 8) | ('F' << 16), + /// LF Radio HBG Prangins, HB 75 kHz + HBG = ('H') | ('B' << 8) | ('G' << 16), + /// LF Radio MSF Anthorn, UK 60 kHz + MSF = ('M') | ('S' << 8) | ('F' << 16), + /// LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz + JJY = ('J') | ('J' << 8) | ('Y' << 16), + /// MF Radio LORAN C station, 100 kHz + LORC = ('L') | ('O' << 8) | ('R' << 16) | ('C' << 24), + /// MF Radio Allouis, FR 162 kHz + TDF = ('T') | ('D' << 8) | ('F' << 16), + /// HF Radio CHU Ottawa, Ontario + CHU = ('C') | ('H' << 8) | ('U' << 16), + /// HF Radio WWV Ft. Collins, CO + WWV = ('W') | ('W' << 8) | ('V' << 16), + /// HF Radio WWVH Kauai, HI + WWVH = ('W') | ('W' << 8) | ('V' << 16) | ('H' << 24), + /// NIST telephone modem + NIST = ('N') | ('I' << 8) | ('S' << 16) | ('T' << 24), + /// NIST telephone modem + ACTS = ('A') | ('C' << 8) | ('T' << 16) | ('S' << 24), + /// USNO telephone modem + USNO = ('U') | ('S' << 8) | ('N' << 16) | ('O' << 24), + /// European telephone modem + PTB = ('P') | ('T' << 8) | ('B' << 16), + /// Multi Reference Sources + MRS = ('M') | ('R' << 8) | ('S' << 16), + /// Inter Face Association Changed + XFAC = ('X') | ('F' << 8) | ('A' << 16) | ('C' << 24), + /// Step time change + STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24), + /// Google Refid used by Google NTP servers as time4.google.com + GOOG = ('G') | ('O' << 8) | ('O' << 16) | ('G' << 24), + /// Meinberg DCF77 with amplitude modulation (Ref: + /// https://www.meinbergglobal.com/english/info/ntp-refid.htm) + DCFa = ('D') | ('C' << 8) | ('F' << 16) | ('a' << 24), + /// Meinberg DCF77 with phase modulation)/pseudo random phase modulation (Ref: + /// https://www.meinbergglobal.com/english/info/ntp-refid.htm) + DCFp = ('D') | ('C' << 8) | ('F' << 16) | ('p' << 24), + /// Meinberg GPS (with shared memory access) (Ref: + /// https://www.meinbergglobal.com/english/info/ntp-refid.htm) + GPSs = ('G') | ('P' << 8) | ('S' << 16) | ('s' << 24), + /// Meinberg GPS (with interrupt based access) (Ref: + /// https://www.meinbergglobal.com/english/info/ntp-refid.htm) + GPSi = ('G') | ('P' << 8) | ('S' << 16) | ('i' << 24), + /// Meinberg GPS/GLONASS (with shared memory access) (Ref: + /// https://www.meinbergglobal.com/english/info/ntp-refid.htm) + GLNs = ('G') | ('L' << 8) | ('N' << 16) | ('s' << 24), + /// Meinberg GPS/GLONASS (with interrupt based access) (Ref: + /// https://www.meinbergglobal.com/english/info/ntp-refid.htm) + GLNi = ('G') | ('L' << 8) | ('N' << 16) | ('i' << 24), + /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) + LCL = ('L') | ('C' << 8) | ('L' << 16), + /// Meinberg Undisciplined local clock (Ref: https://www.meinbergglobal.com/english/info/ntp-refid.htm) + LOCL = ('L') | ('O' << 8) | ('C' << 16) | ('L' << 24), + + // NTPv3 + + /// DCN routing protocol + DCN = ('D') | ('C' << 8) | ('N' << 16), + /// TSP time protocol + TSP = ('T') | ('S' << 8) | ('P' << 16), + /// Digital Time Service + DTS = ('D') | ('T' << 8) | ('S' << 16), + /// Atomic clock (calibrated) + ATOM = ('A') | ('T' << 8) | ('O' << 16) | ('M' << 24), + /// VLF radio (OMEGA, etc.) + VLF = ('V') | ('L' << 8) | ('F' << 16) + }; + + /** + * 32-bit Kiss of Death (KoD) codes + */ + enum class KissODeath : uint32_t + { + /// The association belongs to a anycast server + ACST = ('A') | ('C' << 8) | ('S' << 16) | ('T' << 24), + /// Server authentication failed + AUTH = ('A') | ('U' << 8) | ('T' << 16) | ('H' << 24), + /// Autokey sequence failed + AUTO = ('A') | ('U' << 8) | ('T' << 16) | ('O' << 24), + /// The association belongs to a broadcast server + BCST = ('B') | ('C' << 8) | ('S' << 16) | ('T' << 24), + /// Cryptographic authentication or identification failed + CRYP = ('C') | ('R' << 8) | ('Y' << 16) | ('P' << 24), + /// Access denied by remote server + DENY = ('D') | ('E' << 8) | ('N' << 16) | ('Y' << 24), + /// Lost peer in symmetric mode + DROP = ('D') | ('R' << 8) | ('O' << 16) | ('P' << 24), + /// Access denied due to local policy + RSTR = ('R') | ('S' << 8) | ('T' << 16) | ('R' << 24), + /// The association has not yet synchronized for the first time + INIT = ('I') | ('N' << 8) | ('I' << 16) | ('T' << 24), + /// The association belongs to a manycast server + MCST = ('M') | ('C' << 8) | ('S' << 16) | ('T' << 24), + /// No key found. Either the key was never installed or is not trusted + NKEY = ('N') | ('K' << 8) | ('E' << 16) | ('Y' << 24), + /// Rate exceeded. The server has temporarily denied access because the client exceeded the rate threshold + RATE = ('R') | ('A' << 8) | ('T' << 16) | ('E' << 24), + /// Somebody is tinkering with the association from a remote host running ntpdc. Not to worry unless some + /// rascal has stolen your keys + RMOT = ('R') | ('M' << 8) | ('O' << 16) | ('T' << 24), + /// A step change in system time has occurred, but the association has not yet resynchronized + STEP = ('S') | ('T' << 8) | ('E' << 16) | ('P' << 24), + }; + + /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - NtpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = NTP; } - - /** - * Empty c'tor - */ - NtpLayer(); - - /** - * @return The leap indicator - */ - LeapIndicator getLeapIndicator() const; - - /** - * Set the leap indicator - */ - void setLeapIndicator(LeapIndicator val); - - /** - * @return The version of NTP - */ - uint8_t getVersion() const; - - /** - * Set the version of NTP - */ - void setVersion(uint8_t val); - - /** - * @return The mode value - */ - Mode getMode() const; - - /** - * @return The mode as string - */ - std::string getModeString() const; - - /** - * Set the mode - */ - void setMode(Mode val); - - /** - * @return The value of stratum - */ - uint8_t getStratum() const; - - /** - * Set the value of stratum - */ - void setStratum(uint8_t val); - - /** - * @return The value of poll interval in log2 seconds - */ - int8_t getPollInterval() const; - - /** - * Set the value of poll interval - * @param[in] val Poll interval in log2 seconds - */ - void setPollInterval(int8_t val); - - /** - * @return The value of poll interval in seconds - */ - double getPollIntervalInSecs() const; - - /** - * @return The value of precision in log2 seconds - */ - int8_t getPrecision() const; - - /** - * Set the value of precision - * @param[in] val Precision in log2 seconds - */ - void setPrecision(int8_t val); - - /** - * @return The value of precision in seconds - */ - double getPrecisionInSecs() const; - - /** - * @return The value of root delay in NTP short format - */ - uint32_t getRootDelay() const; - - /** - * Set the value of root delay - * @param[in] val Root delay in NTP short format - */ - void setRootDelay(uint32_t val); - - /** - * @return The value of root delay in seconds - */ - double getRootDelayInSecs() const; - - /** - * Set the value of root delay - * @param[in] val Root delay in seconds - */ - void setRootDelayInSecs(double val); - - /** - * @return The value of root dispersion in NTP short format - */ - uint32_t getRootDispersion() const; - - /** - * Set the value of root delay - * @param[in] val Root dispersion in NTP short format - */ - void setRootDispersion(uint32_t val); - - /** - * @return The value of root dispersion in seconds - */ - double getRootDispersionInSecs() const; - - /** - * Set the value of root dispersion - * @param[in] val Root dispersion in seconds - */ - void setRootDispersionInSecs(double val); - - /** - * @return The value of reference identifier - */ - uint32_t getReferenceIdentifier() const; - - /** - * Set the value of reference identifier - * @param[in] val Value of the reference identifier as IPv4 address - */ - void setReferenceIdentifier(IPv4Address val); - - /** - * Set the value of reference identifier - * @param[in] val Value of the reference identifier as ClockSource - */ - void setReferenceIdentifier(ClockSource val); - - /** - * Set the value of reference identifier - * @param[in] val Value of the reference identifier as Kiss-O-Death code - */ - void setReferenceIdentifier(KissODeath val); - - /** - * @return The value of reference identifier as a string. String representation of NTP clock source if stratum is 1, - * IPv4 address or MD5 hash of first four octets of IPv6 - */ - std::string getReferenceIdentifierString() const; - - /** - * @return The value of reference timestamp in NTP timestamp format - */ - uint64_t getReferenceTimestamp() const; - - /** - * Set the value of reference timestamp - * @param[in] val Timestamp in NTP timestamp format - */ - void setReferenceTimestamp(uint64_t val); - - /** - * @return The value of reference timestamp in seconds from Unix Epoch (1 Jan 1970) - */ - double getReferenceTimestampInSecs() const; - - /** - * Set the value of reference timestamp - * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) - */ - void setReferenceTimestampInSecs(double val); - - /** - * @return The reference timestamp value as readable string in ISO8601 format - */ - std::string getReferenceTimestampAsString(); - - /** - * @return The value of origin timestamp in NTP timestamp format - */ - uint64_t getOriginTimestamp() const; - - /** - * Set the value of origin timestamp - * @param[in] val Value in NTP timestamp format - */ - void setOriginTimestamp(uint64_t val); - - /** - * @return The value of origin timestamp in seconds from Unix Epoch (1 Jan 1970) - */ - double getOriginTimestampInSecs() const; - - /** - * Set the value of origin timestamp - * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) - */ - void setOriginTimestampInSecs(double val); - - /** - * @return the origin timestamp value as readable string in ISO8601 format - */ - std::string getOriginTimestampAsString(); - - /** - * @return The value of receive timestamp in NTP timestamp format - */ - uint64_t getReceiveTimestamp() const; - - /** - * Set the value of receive timestamp - * @param[in] val Value in NTP timestamp format - */ - void setReceiveTimestamp(uint64_t val); - - /** - * @return The value of receive timestampin seconds from Unix Epoch (1 Jan 1970) - */ - double getReceiveTimestampInSecs() const; - - /** - * Set the value of receive timestamp - * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) - */ - void setReceiveTimestampInSecs(double val); - - /** - * @return The receive timestamp value as readable string in ISO8601 format - */ - std::string getReceiveTimestampAsString(); - - /** - * @return The value of transmit timestamp in NTP timestamp format - */ - uint64_t getTransmitTimestamp() const; - - /** - * Set the value of transmit timestamp - * @param[in] val Value in NTP timestamp format - */ - void setTransmitTimestamp(uint64_t val); - - /** - * @return The value of transmit timestamp in seconds from Unix Epoch (1 Jan 1970) - */ - double getTransmitTimestampInSecs() const; - - /** - * Set the value of transmit timestamp - * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) - */ - void setTransmitTimestampInSecs(double val); - - /** - * @return The transmit timestamp value as readable string in ISO8601 format - */ - std::string getTransmitTimestampAsString(); - - /** - * @return Returns the key identifier if exists, returns 0 on unsupported NTP version or key identifier not found - */ - uint32_t getKeyID() const; - - /** - * @return Get the digest value as hexadecimal string, empty string on unsupported version - */ - std::string getDigest() const; - - /** - * Convert NTP short format to seconds from the Unix Epoch - * - * @param[in] val Value in NTP short format - * @return Value in seconds from Unix Epoch (1 Jan 1970) - */ - static double convertFromShortFormat(const uint32_t val); - - /** - * Convert NTP timestamp format to seconds from the Unix Epoch - * - * @param[in] val Value in NTP timestamp format - * @return Value in seconds from Unix Epoch (1 Jan 1970) - */ - static double convertFromTimestampFormat(const uint64_t val); - - /** - * Convert seconds from the Unix Epoch to NTP short format - * - * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) - * @return Value in NTP short format - */ - static uint32_t convertToShortFormat(const double val); - - /** - * Convert seconds from the Unix Epoch to NTP timestamp format - * - * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) - * @return Value in NTP timestamp format - */ - static uint64_t convertToTimestampFormat(const double val); - - /** - * A static method to convert timestamp value to ISO8601 date time format - * @param[in] timestamp Value in seconds from the Unix Epoch - * @return std::string ISO8601 formatted string - */ - static std::string convertToIsoFormat(const double timestamp); - - /** - * A static method to convert timestamp value to ISO8601 date time format - * @param[in] timestampInNTPformat Value in NTP timestamp format - * @return std::string ISO8601 formatted string - */ - static std::string convertToIsoFormat(const uint64_t timestampInNTPformat); - - /** + NtpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = NTP; + } + + /** + * Empty c'tor + */ + NtpLayer(); + + /** + * @return The leap indicator + */ + LeapIndicator getLeapIndicator() const; + + /** + * Set the leap indicator + */ + void setLeapIndicator(LeapIndicator val); + + /** + * @return The version of NTP + */ + uint8_t getVersion() const; + + /** + * Set the version of NTP + */ + void setVersion(uint8_t val); + + /** + * @return The mode value + */ + Mode getMode() const; + + /** + * @return The mode as string + */ + std::string getModeString() const; + + /** + * Set the mode + */ + void setMode(Mode val); + + /** + * @return The value of stratum + */ + uint8_t getStratum() const; + + /** + * Set the value of stratum + */ + void setStratum(uint8_t val); + + /** + * @return The value of poll interval in log2 seconds + */ + int8_t getPollInterval() const; + + /** + * Set the value of poll interval + * @param[in] val Poll interval in log2 seconds + */ + void setPollInterval(int8_t val); + + /** + * @return The value of poll interval in seconds + */ + double getPollIntervalInSecs() const; + + /** + * @return The value of precision in log2 seconds + */ + int8_t getPrecision() const; + + /** + * Set the value of precision + * @param[in] val Precision in log2 seconds + */ + void setPrecision(int8_t val); + + /** + * @return The value of precision in seconds + */ + double getPrecisionInSecs() const; + + /** + * @return The value of root delay in NTP short format + */ + uint32_t getRootDelay() const; + + /** + * Set the value of root delay + * @param[in] val Root delay in NTP short format + */ + void setRootDelay(uint32_t val); + + /** + * @return The value of root delay in seconds + */ + double getRootDelayInSecs() const; + + /** + * Set the value of root delay + * @param[in] val Root delay in seconds + */ + void setRootDelayInSecs(double val); + + /** + * @return The value of root dispersion in NTP short format + */ + uint32_t getRootDispersion() const; + + /** + * Set the value of root delay + * @param[in] val Root dispersion in NTP short format + */ + void setRootDispersion(uint32_t val); + + /** + * @return The value of root dispersion in seconds + */ + double getRootDispersionInSecs() const; + + /** + * Set the value of root dispersion + * @param[in] val Root dispersion in seconds + */ + void setRootDispersionInSecs(double val); + + /** + * @return The value of reference identifier + */ + uint32_t getReferenceIdentifier() const; + + /** + * Set the value of reference identifier + * @param[in] val Value of the reference identifier as IPv4 address + */ + void setReferenceIdentifier(IPv4Address val); + + /** + * Set the value of reference identifier + * @param[in] val Value of the reference identifier as ClockSource + */ + void setReferenceIdentifier(ClockSource val); + + /** + * Set the value of reference identifier + * @param[in] val Value of the reference identifier as Kiss-O-Death code + */ + void setReferenceIdentifier(KissODeath val); + + /** + * @return The value of reference identifier as a string. String representation of NTP clock source if stratum + * is 1, IPv4 address or MD5 hash of first four octets of IPv6 + */ + std::string getReferenceIdentifierString() const; + + /** + * @return The value of reference timestamp in NTP timestamp format + */ + uint64_t getReferenceTimestamp() const; + + /** + * Set the value of reference timestamp + * @param[in] val Timestamp in NTP timestamp format + */ + void setReferenceTimestamp(uint64_t val); + + /** + * @return The value of reference timestamp in seconds from Unix Epoch (1 Jan 1970) + */ + double getReferenceTimestampInSecs() const; + + /** + * Set the value of reference timestamp + * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) + */ + void setReferenceTimestampInSecs(double val); + + /** + * @return The reference timestamp value as readable string in ISO8601 format + */ + std::string getReferenceTimestampAsString(); + + /** + * @return The value of origin timestamp in NTP timestamp format + */ + uint64_t getOriginTimestamp() const; + + /** + * Set the value of origin timestamp + * @param[in] val Value in NTP timestamp format + */ + void setOriginTimestamp(uint64_t val); + + /** + * @return The value of origin timestamp in seconds from Unix Epoch (1 Jan 1970) + */ + double getOriginTimestampInSecs() const; + + /** + * Set the value of origin timestamp + * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) + */ + void setOriginTimestampInSecs(double val); + + /** + * @return the origin timestamp value as readable string in ISO8601 format + */ + std::string getOriginTimestampAsString(); + + /** + * @return The value of receive timestamp in NTP timestamp format + */ + uint64_t getReceiveTimestamp() const; + + /** + * Set the value of receive timestamp + * @param[in] val Value in NTP timestamp format + */ + void setReceiveTimestamp(uint64_t val); + + /** + * @return The value of receive timestampin seconds from Unix Epoch (1 Jan 1970) + */ + double getReceiveTimestampInSecs() const; + + /** + * Set the value of receive timestamp + * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) + */ + void setReceiveTimestampInSecs(double val); + + /** + * @return The receive timestamp value as readable string in ISO8601 format + */ + std::string getReceiveTimestampAsString(); + + /** + * @return The value of transmit timestamp in NTP timestamp format + */ + uint64_t getTransmitTimestamp() const; + + /** + * Set the value of transmit timestamp + * @param[in] val Value in NTP timestamp format + */ + void setTransmitTimestamp(uint64_t val); + + /** + * @return The value of transmit timestamp in seconds from Unix Epoch (1 Jan 1970) + */ + double getTransmitTimestampInSecs() const; + + /** + * Set the value of transmit timestamp + * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) + */ + void setTransmitTimestampInSecs(double val); + + /** + * @return The transmit timestamp value as readable string in ISO8601 format + */ + std::string getTransmitTimestampAsString(); + + /** + * @return Returns the key identifier if exists, returns 0 on unsupported NTP version or key identifier not + * found + */ + uint32_t getKeyID() const; + + /** + * @return Get the digest value as hexadecimal string, empty string on unsupported version + */ + std::string getDigest() const; + + /** + * Convert NTP short format to seconds from the Unix Epoch + * + * @param[in] val Value in NTP short format + * @return Value in seconds from Unix Epoch (1 Jan 1970) + */ + static double convertFromShortFormat(const uint32_t val); + + /** + * Convert NTP timestamp format to seconds from the Unix Epoch + * + * @param[in] val Value in NTP timestamp format + * @return Value in seconds from Unix Epoch (1 Jan 1970) + */ + static double convertFromTimestampFormat(const uint64_t val); + + /** + * Convert seconds from the Unix Epoch to NTP short format + * + * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) + * @return Value in NTP short format + */ + static uint32_t convertToShortFormat(const double val); + + /** + * Convert seconds from the Unix Epoch to NTP timestamp format + * + * @param[in] val Value in seconds from Unix Epoch (1 Jan 1970) + * @return Value in NTP timestamp format + */ + static uint64_t convertToTimestampFormat(const double val); + + /** + * A static method to convert timestamp value to ISO8601 date time format + * @param[in] timestamp Value in seconds from the Unix Epoch + * @return std::string ISO8601 formatted string + */ + static std::string convertToIsoFormat(const double timestamp); + + /** + * A static method to convert timestamp value to ISO8601 date time format + * @param[in] timestampInNTPformat Value in NTP timestamp format + * @return std::string ISO8601 formatted string + */ + static std::string convertToIsoFormat(const uint64_t timestampInNTPformat); + + /** * A static method that takes a byte array and detects whether it is a NTP message * @param[in] data A byte array * @param[in] dataSize The byte array size (in bytes) * @return True if the data is identified as NTP message */ - static bool isDataValid(const uint8_t *data, size_t dataSize); + static bool isDataValid(const uint8_t* data, size_t dataSize); - /** + /** * A static method that checks whether the port is considered as NTP * @param[in] port The port number to be checked */ - static bool isNTPPort(uint16_t port) { return port == 123; } + static bool isNTPPort(uint16_t port) + { + return port == 123; + } - // overridden methods + // overridden methods - /// Parses the next layer. NTP is the always last so does nothing for this layer - void parseNextLayer() {} + /// Parses the next layer. NTP is the always last so does nothing for this layer + void parseNextLayer() + {} - /** - * @return Get the size of the layer (Including the extension and authentication fields if exists) - */ - size_t getHeaderLen() const { return m_DataLen; } + /** + * @return Get the size of the layer (Including the extension and authentication fields if exists) + */ + size_t getHeaderLen() const + { + return m_DataLen; + } - /// Does nothing for this layer - void computeCalculateFields() {} + /// Does nothing for this layer + void computeCalculateFields() + {} - /** - * @return The OSI layer level of NTP (Application Layer). - */ - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + /** + * @return The OSI layer level of NTP (Application Layer). + */ + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } - /** - * @return Returns the protocol info as readable string - */ - std::string toString() const; - }; + /** + * @return Returns the protocol info as readable string + */ + std::string toString() const; + }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/NullLoopbackLayer.h b/Packet++/header/NullLoopbackLayer.h index 59156d4326..97ab944ee3 100644 --- a/Packet++/header/NullLoopbackLayer.h +++ b/Packet++/header/NullLoopbackLayer.h @@ -7,22 +7,22 @@ namespace pcpp { - /** IPv4 protocol **/ - #define PCPP_BSD_AF_INET 2 - /** XEROX NS protocols */ - #define PCPP_BSD_AF_NS 6 - /** ISO */ - #define PCPP_BSD_AF_ISO 7 - /** AppleTalk */ - #define PCPP_BSD_AF_APPLETALK 16 - /** IPX */ - #define PCPP_BSD_AF_IPX 23 - /** OpenBSD (and probably NetBSD), BSD/OS IPv6 */ - #define PCPP_BSD_AF_INET6_BSD 24 - /** FreeBSD IPv6 */ - #define PCPP_BSD_AF_INET6_FREEBSD 28 - /** Darwin IPv6 */ - #define PCPP_BSD_AF_INET6_DARWIN 30 +/** IPv4 protocol **/ +#define PCPP_BSD_AF_INET 2 +/** XEROX NS protocols */ +#define PCPP_BSD_AF_NS 6 +/** ISO */ +#define PCPP_BSD_AF_ISO 7 +/** AppleTalk */ +#define PCPP_BSD_AF_APPLETALK 16 +/** IPX */ +#define PCPP_BSD_AF_IPX 23 +/** OpenBSD (and probably NetBSD), BSD/OS IPv6 */ +#define PCPP_BSD_AF_INET6_BSD 24 +/** FreeBSD IPv6 */ +#define PCPP_BSD_AF_INET6_FREEBSD 28 +/** Darwin IPv6 */ +#define PCPP_BSD_AF_INET6_DARWIN 30 /** * @class NullLoopbackLayer @@ -31,12 +31,15 @@ namespace pcpp class NullLoopbackLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - NullLoopbackLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = NULL_LOOPBACK; } + NullLoopbackLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) + { + m_Protocol = NULL_LOOPBACK; + } /** * A constructor that allocates a new Null/Loopback header @@ -47,7 +50,8 @@ namespace pcpp /** * A destructor for this layer (does nothing) */ - ~NullLoopbackLayer() {} + ~NullLoopbackLayer() + {} /** * @return The protocol family in this layer @@ -60,13 +64,13 @@ namespace pcpp */ void setFamily(uint32_t family); - // implement abstract methods /** * Identifies the next layers by family: * - for ::PCPP_BSD_AF_INET the next layer is IPv4Layer - * - for ::PCPP_BSD_AF_INET6_BSD, ::PCPP_BSD_AF_INET6_FREEBSD, ::PCPP_BSD_AF_INET6_DARWIN the next layer is IPv6Layer + * - for ::PCPP_BSD_AF_INET6_BSD, ::PCPP_BSD_AF_INET6_FREEBSD, ::PCPP_BSD_AF_INET6_DARWIN the next layer is + * IPv6Layer * - for other values the next layer in PayloadLayer (unknown protocol) */ void parseNextLayer(); @@ -74,16 +78,23 @@ namespace pcpp /** * @return Size of Null/Loopback header = 4B */ - size_t getHeaderLen() const { return sizeof(uint32_t); } + size_t getHeaderLen() const + { + return sizeof(uint32_t); + } /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/PPPoELayer.h b/Packet++/header/PPPoELayer.h index 4ce8659109..b8722a1300 100644 --- a/Packet++/header/PPPoELayer.h +++ b/Packet++/header/PPPoELayer.h @@ -23,18 +23,18 @@ namespace pcpp { #if (BYTE_ORDER == LITTLE_ENDIAN) /** PPPoE version */ - uint8_t version:4, + uint8_t version : 4; /** PPPoE type */ - type:4; + uint8_t type : 4; /** PPPoE code */ uint8_t code; #else /** PPPoE version */ - uint16_t version:4, + uint16_t version : 4; /** PPPoE type */ - type:4, + uint16_t type : 4; /** PPPoE code */ - code:8; + uint16_t code : 8; #endif /** PPPoE session ID (relevant for PPPoE session packets only) */ uint16_t sessionId; @@ -43,11 +43,10 @@ namespace pcpp }; #pragma pack(pop) - /** * @class PPPoELayer - * An abstract class that describes the PPPoE protocol. Contains common data and logic of the two types of PPPoE packets: PPPoE session - * and PPPoE discovery + * An abstract class that describes the PPPoE protocol. Contains common data and logic of the two types of PPPoE + * packets: PPPoE session and PPPoE discovery */ class PPPoELayer : public Layer { @@ -58,36 +57,41 @@ namespace pcpp enum PPPoECode { /** PPPoE session code */ - PPPOE_CODE_SESSION = 0x00, + PPPOE_CODE_SESSION = 0x00, /** PPPoE discovery PADO */ - PPPOE_CODE_PADO = 0x07, + PPPOE_CODE_PADO = 0x07, /** PPPoE discovery PADI */ - PPPOE_CODE_PADI = 0x09, + PPPOE_CODE_PADI = 0x09, /** PPPoE discovery PADG */ - PPPOE_CODE_PADG = 0x0a, + PPPOE_CODE_PADG = 0x0a, /** PPPoE discovery PADC */ - PPPOE_CODE_PADC = 0x0b, + PPPOE_CODE_PADC = 0x0b, /** PPPoE discovery PADQ */ - PPPOE_CODE_PADQ = 0x0c, + PPPOE_CODE_PADQ = 0x0c, /** PPPoE discovery PADR */ - PPPOE_CODE_PADR = 0x19, + PPPOE_CODE_PADR = 0x19, /** PPPoE discovery PADS */ - PPPOE_CODE_PADS = 0x65, + PPPOE_CODE_PADS = 0x65, /** PPPoE discovery PADT */ - PPPOE_CODE_PADT = 0xa7, + PPPOE_CODE_PADT = 0xa7, /** PPPoE discovery PADM */ - PPPOE_CODE_PADM = 0xd3, + PPPOE_CODE_PADM = 0xd3, /** PPPoE discovery PADN */ - PPPOE_CODE_PADN = 0xd4 + PPPOE_CODE_PADN = 0xd4 }; - ~PPPoELayer() {} + ~PPPoELayer() + {} /** - * Get a pointer to the PPPoE header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the PPPoE header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the pppoe_header */ - pppoe_header* getPPPoEHeader() const { return (pppoe_header*)m_Data; } + pppoe_header* getPPPoEHeader() const + { + return (pppoe_header*)m_Data; + } // abstract methods implementation @@ -96,19 +100,22 @@ namespace pcpp */ virtual void computeCalculateFields(); - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } protected: - // protected c'tor as this class shouldn't be instantiated - PPPoELayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { } + PPPoELayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + {} // protected c'tor as this class shouldn't be instantiated - PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId, size_t additionalBytesToAllocate = 0); - + PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId, + size_t additionalBytesToAllocate = 0); }; - /** * @class PPPoESessionLayer * Describes the PPPoE session protocol @@ -116,7 +123,6 @@ namespace pcpp class PPPoESessionLayer : public PPPoELayer { public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data (will be casted to @ref pppoe_header) @@ -124,22 +130,33 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - PPPoESessionLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : PPPoELayer(data, dataLen, prevLayer, packet) { m_Protocol = PPPoESession; } + PPPoESessionLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : PPPoELayer(data, dataLen, prevLayer, packet) + { + m_Protocol = PPPoESession; + } /** * A constructor that allocates a new PPPoE Session header with version, type and session ID * @param[in] version PPPoE version * @param[in] type PPPoE type * @param[in] sessionId PPPoE session ID - * @param[in] pppNextProtocol The next protocol to come after the PPPoE session header. Should be one of the PPP_* macros listed below + * @param[in] pppNextProtocol The next protocol to come after the PPPoE session header. Should be one of the + * PPP_* macros listed below */ - PPPoESessionLayer(uint8_t version, uint8_t type, uint16_t sessionId, uint16_t pppNextProtocol) : PPPoELayer(version, type, PPPoELayer::PPPOE_CODE_SESSION, sessionId, sizeof(uint16_t)) { setPPPNextProtocol(pppNextProtocol); } + PPPoESessionLayer(uint8_t version, uint8_t type, uint16_t sessionId, uint16_t pppNextProtocol) + : PPPoELayer(version, type, PPPoELayer::PPPOE_CODE_SESSION, sessionId, sizeof(uint16_t)) + { + setPPPNextProtocol(pppNextProtocol); + } - virtual ~PPPoESessionLayer() {} + virtual ~PPPoESessionLayer() + {} /** - * @return The protocol after the PPPoE session header. The return value is one of the PPP_* macros listed below. This method is also - * used when parsing a packet (this way we know which layer comes after the PPPoE session) + * @return The protocol after the PPPoE session header. The return value is one of the PPP_* macros listed + * below. This method is also used when parsing a packet (this way we know which layer comes after the PPPoE + * session) */ uint16_t getPPPNextProtocol() const; @@ -167,13 +184,14 @@ namespace pcpp /** * @return Size of @ref pppoe_header */ - virtual size_t getHeaderLen() const { return sizeof(pppoe_header) + sizeof(uint16_t); } + virtual size_t getHeaderLen() const + { + return sizeof(pppoe_header) + sizeof(uint16_t); + } virtual std::string toString() const; }; - - /** * @class PPPoEDiscoveryLayer * Describes the PPPoE discovery protocol @@ -187,41 +205,41 @@ namespace pcpp enum PPPoETagTypes { /** End-Of-List tag type*/ - PPPOE_TAG_EOL = 0x0000, + PPPOE_TAG_EOL = 0x0000, /** Service-Name tag type*/ - PPPOE_TAG_SVC_NAME = 0x0101, + PPPOE_TAG_SVC_NAME = 0x0101, /** AC-Name tag type*/ - PPPOE_TAG_AC_NAME = 0x0102, + PPPOE_TAG_AC_NAME = 0x0102, /** Host-Uniq tag type*/ - PPPOE_TAG_HOST_UNIQ = 0x0103, + PPPOE_TAG_HOST_UNIQ = 0x0103, /** AC-Cookie tag type*/ - PPPOE_TAG_AC_COOKIE = 0x0104, + PPPOE_TAG_AC_COOKIE = 0x0104, /** Vendor-Specific tag type*/ - PPPOE_TAG_VENDOR = 0x0105, + PPPOE_TAG_VENDOR = 0x0105, /** Credits tag type*/ - PPPOE_TAG_CREDITS = 0x0106, + PPPOE_TAG_CREDITS = 0x0106, /** Metrics tag type*/ - PPPOE_TAG_METRICS = 0x0107, + PPPOE_TAG_METRICS = 0x0107, /** Sequence Number tag type */ - PPPOE_TAG_SEQ_NUM = 0x0108, + PPPOE_TAG_SEQ_NUM = 0x0108, /** Credit Scale Factor tag type */ PPPOE_TAG_CRED_SCALE = 0x0109, /** Relay-Session-Id tag type */ - PPPOE_TAG_RELAY_ID = 0x0110, + PPPOE_TAG_RELAY_ID = 0x0110, /** HURL tag type */ - PPPOE_TAG_HURL = 0x0111, + PPPOE_TAG_HURL = 0x0111, /** MOTM tag type */ - PPPOE_TAG_MOTM = 0x0112, + PPPOE_TAG_MOTM = 0x0112, /** PPP-Max-Payload tag type */ - PPPOE_TAG_MAX_PAYLD = 0x0120, + PPPOE_TAG_MAX_PAYLD = 0x0120, /** IP_Route_Add tag type */ - PPPOE_TAG_IP_RT_ADD = 0x0121, + PPPOE_TAG_IP_RT_ADD = 0x0121, /** Service-Name-Error tag type */ - PPPOE_TAG_SVC_ERR = 0x0201, + PPPOE_TAG_SVC_ERR = 0x0201, /** AC-System-Error tag type */ - PPPOE_TAG_AC_ERR = 0x0202, + PPPOE_TAG_AC_ERR = 0x0202, /** Generic-Error tag type */ - PPPOE_TAG_GENERIC_ERR= 0x0203 + PPPOE_TAG_GENERIC_ERR = 0x0203 }; /** @@ -235,12 +253,14 @@ namespace pcpp * A c'tor that gets a pointer to the tag raw data (byte array) * @param[in] tagRawData A pointer to the tag raw data */ - explicit PPPoETag(uint8_t* tagRawData) : TLVRecord(tagRawData) { } + explicit PPPoETag(uint8_t* tagRawData) : TLVRecord(tagRawData) + {} /** * A d'tor for this class, currently does nothing */ - virtual ~PPPoETag() { } + virtual ~PPPoETag() + {} /** * @return The tag type converted to PPPoEDiscoveryLayer#PPPoETagTypes enum @@ -267,7 +287,6 @@ namespace pcpp size_t getDataSize() const; }; - /** * @class PPPoETagBuilder * A class for building PPPoE Tags. This builder receives the tag parameters in its c'tor, @@ -276,14 +295,13 @@ namespace pcpp class PPPoETagBuilder : public TLVRecordBuilder { public: - /** * A c'tor for building a PPPoE Tag which has no value (tag len is zero). The PPPoETag object can later * be retrieved by calling build() * @param[in] tagType Tag type */ - explicit PPPoETagBuilder(PPPoETagTypes tagType) : - TLVRecordBuilder(static_cast(tagType), NULL, 0) { } + explicit PPPoETagBuilder(PPPoETagTypes tagType) : TLVRecordBuilder(static_cast(tagType), NULL, 0) + {} /** * A c'tor for building a PPPoE Tag which has a 4-byte value. The PPPoETag object can later @@ -291,8 +309,9 @@ namespace pcpp * @param[in] tagType Tag type * @param[in] tagValue The tag's 4-byte value */ - PPPoETagBuilder(PPPoETagTypes tagType, uint32_t tagValue) : - TLVRecordBuilder(static_cast(tagType), tagValue) { } + PPPoETagBuilder(PPPoETagTypes tagType, uint32_t tagValue) + : TLVRecordBuilder(static_cast(tagType), tagValue) + {} /** * A c'tor for building a PPPoE Tag which has some arbitrary value. The PPPoETag object can later @@ -301,8 +320,9 @@ namespace pcpp * @param[in] tagValue A byte array that contains the tag data * @param[in] tagValueLen The length of the value byte array */ - PPPoETagBuilder(PPPoETagTypes tagType, uint8_t* tagValue, uint8_t tagValueLen) : - TLVRecordBuilder(static_cast(tagType), tagValue, tagValueLen) { } + PPPoETagBuilder(PPPoETagTypes tagType, uint8_t* tagValue, uint8_t tagValueLen) + : TLVRecordBuilder(static_cast(tagType), tagValue, tagValueLen) + {} /** * Build the PPPoETag object out of the parameters defined in the c'tor @@ -318,7 +338,12 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - PPPoEDiscoveryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : PPPoELayer(data, dataLen, prevLayer, packet) { m_Protocol = PPPoEDiscovery; m_DataLen = getHeaderLen(); } + PPPoEDiscoveryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : PPPoELayer(data, dataLen, prevLayer, packet) + { + m_Protocol = PPPoEDiscovery; + m_DataLen = getHeaderLen(); + } /** * A constructor that allocates a new PPPoE Discovery header with version, type, PPPoE code and session ID @@ -327,7 +352,11 @@ namespace pcpp * @param[in] code PPPoE code enum * @param[in] sessionId PPPoE session ID */ - PPPoEDiscoveryLayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId) : PPPoELayer(version, type, code, sessionId) { m_Protocol = PPPoEDiscovery; } + PPPoEDiscoveryLayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId) + : PPPoELayer(version, type, code, sessionId) + { + m_Protocol = PPPoEDiscovery; + } /** * Get a PPPoE Tag by tag type. @@ -338,8 +367,8 @@ namespace pcpp PPPoETag getTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) const; /** - * @return The first tag in the PPPoE discovery layer. If the current layer contains no tags the returned value will contain - * a logical NULL (PPPoETag#isNull() == true) + * @return The first tag in the PPPoE discovery layer. If the current layer contains no tags the returned value + * will contain a logical NULL (PPPoETag#isNull() == true) */ PPPoETag getFirstTag() const; @@ -377,14 +406,15 @@ namespace pcpp /** * Remove an existing tag. Tag will be found by the tag type * @param[in] tagType The tag type to remove - * @return True if tag was removed or false if tag wasn't found or if tag removal failed (in each case a proper error will be written - * to log) + * @return True if tag was removed or false if tag wasn't found or if tag removal failed (in each case a proper + * error will be written to log) */ bool removeTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType); /** * Remove all tags in this layer - * @return True if all tags were successfully or false if removal failed for some reason (a proper error will be written to log) + * @return True if all tags were successfully or false if removal failed for some reason (a proper error will be + * written to log) */ bool removeAllTags(); @@ -401,26 +431,32 @@ namespace pcpp /** * Does nothing for this layer (PPPoE discovery is always the last layer) */ - virtual void parseNextLayer() {} + virtual void parseNextLayer() + {} /** * @return The header length which is size of strcut pppoe_header plus the total size of tags */ virtual size_t getHeaderLen() const; - virtual std::string toString() const { return "PPP-over-Ethernet Discovery (" + codeToString((PPPoELayer::PPPoECode)getPPPoEHeader()->code) + ")"; } + virtual std::string toString() const + { + return "PPP-over-Ethernet Discovery (" + codeToString((PPPoELayer::PPPoECode)getPPPoEHeader()->code) + ")"; + } private: TLVRecordReader m_TagReader; PPPoETag addTagAt(const PPPoETagBuilder& tagBuilder, int offset); - uint8_t* getTagBasePtr() const { return m_Data + sizeof(pppoe_header); } + uint8_t* getTagBasePtr() const + { + return m_Data + sizeof(pppoe_header); + } std::string codeToString(PPPoECode code) const; }; - // implementation of inline methods bool PPPoESessionLayer::isDataValid(const uint8_t* data, size_t dataLen) @@ -436,270 +472,270 @@ namespace pcpp // Copied from Wireshark: ppptypes.h /** Padding Protocol */ -#define PCPP_PPP_PADDING 0x1 +#define PCPP_PPP_PADDING 0x1 /** ROHC small-CID */ -#define PCPP_PPP_ROHC_SCID 0x3 +#define PCPP_PPP_ROHC_SCID 0x3 /** ROHC large-CID */ -#define PCPP_PPP_ROHC_LCID 0x5 +#define PCPP_PPP_ROHC_LCID 0x5 /** Internet Protocol version 4 */ -#define PCPP_PPP_IP 0x21 +#define PCPP_PPP_IP 0x21 /** OSI Network Layer */ -#define PCPP_PPP_OSI 0x23 +#define PCPP_PPP_OSI 0x23 /** Xerox NS IDP */ -#define PCPP_PPP_XNSIDP 0x25 +#define PCPP_PPP_XNSIDP 0x25 /** DECnet Phase IV */ -#define PCPP_PPP_DEC4 0x27 +#define PCPP_PPP_DEC4 0x27 /** AppleTalk */ -#define PCPP_PPP_AT 0x29 +#define PCPP_PPP_AT 0x29 /** Novell IPX */ -#define PCPP_PPP_IPX 0x2b +#define PCPP_PPP_IPX 0x2b /** Van Jacobson Compressed TCP/IP */ -#define PCPP_PPP_VJC_COMP 0x2d +#define PCPP_PPP_VJC_COMP 0x2d /** Van Jacobson Uncompressed TCP/IP */ -#define PCPP_PPP_VJC_UNCOMP 0x2f +#define PCPP_PPP_VJC_UNCOMP 0x2f /** Bridging PDU */ -#define PCPP_PPP_BCP 0x31 +#define PCPP_PPP_BCP 0x31 /** Stream Protocol (ST-II) */ -#define PCPP_PPP_ST 0x33 +#define PCPP_PPP_ST 0x33 /** Banyan Vines */ -#define PCPP_PPP_VINES 0x35 +#define PCPP_PPP_VINES 0x35 /** AppleTalk EDDP */ -#define PCPP_PPP_AT_EDDP 0x39 +#define PCPP_PPP_AT_EDDP 0x39 /** AppleTalk SmartBuffered */ -#define PCPP_PPP_AT_SB 0x3b +#define PCPP_PPP_AT_SB 0x3b /** Multi-Link */ -#define PCPP_PPP_MP 0x3d +#define PCPP_PPP_MP 0x3d /** NETBIOS Framing */ -#define PCPP_PPP_NB 0x3f +#define PCPP_PPP_NB 0x3f /** Cisco Systems */ -#define PCPP_PPP_CISCO 0x41 +#define PCPP_PPP_CISCO 0x41 /** Ascom Timeplex */ -#define PCPP_PPP_ASCOM 0x43 +#define PCPP_PPP_ASCOM 0x43 /** Fujitsu Link Backup and Load Balancing */ -#define PCPP_PPP_LBLB 0x45 +#define PCPP_PPP_LBLB 0x45 /** DCA Remote Lan */ -#define PCPP_PPP_RL 0x47 +#define PCPP_PPP_RL 0x47 /** Serial Data Transport Protocol */ -#define PCPP_PPP_SDTP 0x49 +#define PCPP_PPP_SDTP 0x49 /** SNA over 802.2 */ -#define PCPP_PPP_LLC 0x4b +#define PCPP_PPP_LLC 0x4b /** SNA */ -#define PCPP_PPP_SNA 0x4d +#define PCPP_PPP_SNA 0x4d /** IPv6 Header Compression */ -#define PCPP_PPP_IPV6HC 0x4f +#define PCPP_PPP_IPV6HC 0x4f /** KNX Bridging Data */ -#define PCPP_PPP_KNX 0x51 +#define PCPP_PPP_KNX 0x51 /** Encryption */ -#define PCPP_PPP_ENCRYPT 0x53 +#define PCPP_PPP_ENCRYPT 0x53 /** Individual Link Encryption */ -#define PCPP_PPP_ILE 0x55 +#define PCPP_PPP_ILE 0x55 /** Internet Protocol version 6 */ -#define PCPP_PPP_IPV6 0x57 +#define PCPP_PPP_IPV6 0x57 /** PPP Muxing */ -#define PCPP_PPP_MUX 0x59 +#define PCPP_PPP_MUX 0x59 /** Vendor-Specific Network Protocol (VSNP) */ -#define PCPP_PPP_VSNP 0x5b +#define PCPP_PPP_VSNP 0x5b /** TRILL Network Protocol (TNP) */ -#define PCPP_PPP_TNP 0x5d +#define PCPP_PPP_TNP 0x5d /** RTP IPHC Full Header */ -#define PCPP_PPP_RTP_FH 0x61 +#define PCPP_PPP_RTP_FH 0x61 /** RTP IPHC Compressed TCP */ -#define PCPP_PPP_RTP_CTCP 0x63 +#define PCPP_PPP_RTP_CTCP 0x63 /** RTP IPHC Compressed Non TCP */ -#define PCPP_PPP_RTP_CNTCP 0x65 +#define PCPP_PPP_RTP_CNTCP 0x65 /** RTP IPHC Compressed UDP 8 */ -#define PCPP_PPP_RTP_CUDP8 0x67 +#define PCPP_PPP_RTP_CUDP8 0x67 /** RTP IPHC Compressed RTP 8 */ -#define PCPP_PPP_RTP_CRTP8 0x69 +#define PCPP_PPP_RTP_CRTP8 0x69 /** Stampede Bridging */ -#define PCPP_PPP_STAMPEDE 0x6f +#define PCPP_PPP_STAMPEDE 0x6f /** MP+ Protocol */ -#define PCPP_PPP_MPPLUS 0x73 +#define PCPP_PPP_MPPLUS 0x73 /** NTCITS IPI */ -#define PCPP_PPP_NTCITS_IPI 0xc1 +#define PCPP_PPP_NTCITS_IPI 0xc1 /** Single link compression in multilink */ -#define PCPP_PPP_ML_SLCOMP 0xfb +#define PCPP_PPP_ML_SLCOMP 0xfb /** Compressed datagram */ -#define PCPP_PPP_COMP 0xfd +#define PCPP_PPP_COMP 0xfd /** 802.1d Hello Packets */ -#define PCPP_PPP_STP_HELLO 0x0201 +#define PCPP_PPP_STP_HELLO 0x0201 /** IBM Source Routing BPDU */ -#define PCPP_PPP_IBM_SR 0x0203 +#define PCPP_PPP_IBM_SR 0x0203 /** DEC LANBridge100 Spanning Tree */ -#define PCPP_PPP_DEC_LB 0x0205 +#define PCPP_PPP_DEC_LB 0x0205 /** Cisco Discovery Protocol */ -#define PCPP_PPP_CDP 0x0207 +#define PCPP_PPP_CDP 0x0207 /** Netcs Twin Routing */ -#define PCPP_PPP_NETCS 0x0209 +#define PCPP_PPP_NETCS 0x0209 /** STP - Scheduled Transfer Protocol */ -#define PCPP_PPP_STP 0x020b +#define PCPP_PPP_STP 0x020b /** EDP - Extreme Discovery Protocol */ -#define PCPP_PPP_EDP 0x020d +#define PCPP_PPP_EDP 0x020d /** Optical Supervisory Channel Protocol */ -#define PCPP_PPP_OSCP 0x0211 +#define PCPP_PPP_OSCP 0x0211 /** Optical Supervisory Channel Protocol */ -#define PCPP_PPP_OSCP2 0x0213 +#define PCPP_PPP_OSCP2 0x0213 /** Luxcom */ -#define PCPP_PPP_LUXCOM 0x0231 +#define PCPP_PPP_LUXCOM 0x0231 /** Sigma Network Systems */ -#define PCPP_PPP_SIGMA 0x0233 +#define PCPP_PPP_SIGMA 0x0233 /** Apple Client Server Protocol */ -#define PCPP_PPP_ACSP 0x0235 +#define PCPP_PPP_ACSP 0x0235 /** MPLS Unicast */ -#define PCPP_PPP_MPLS_UNI 0x0281 +#define PCPP_PPP_MPLS_UNI 0x0281 /** MPLS Multicast */ -#define PCPP_PPP_MPLS_MULTI 0x0283 +#define PCPP_PPP_MPLS_MULTI 0x0283 /** IEEE p1284.4 standard - data packets */ -#define PCPP_PPP_P12844 0x0285 +#define PCPP_PPP_P12844 0x0285 /** ETSI TETRA Network Protocol Type 1 */ -#define PCPP_PPP_TETRA 0x0287 +#define PCPP_PPP_TETRA 0x0287 /** Multichannel Flow Treatment Protocol */ -#define PCPP_PPP_MFTP 0x0289 +#define PCPP_PPP_MFTP 0x0289 /** RTP IPHC Compressed TCP No Delta */ -#define PCPP_PPP_RTP_CTCPND 0x2063 +#define PCPP_PPP_RTP_CTCPND 0x2063 /** RTP IPHC Context State */ -#define PCPP_PPP_RTP_CS 0x2065 +#define PCPP_PPP_RTP_CS 0x2065 /** RTP IPHC Compressed UDP 16 */ -#define PCPP_PPP_RTP_CUDP16 0x2067 +#define PCPP_PPP_RTP_CUDP16 0x2067 /** RTP IPHC Compressed RTP 16 */ -#define PCPP_PPP_RTP_CRDP16 0x2069 +#define PCPP_PPP_RTP_CRDP16 0x2069 /** Cray Communications Control Protocol */ -#define PCPP_PPP_CCCP 0x4001 +#define PCPP_PPP_CCCP 0x4001 /** CDPD Mobile Network Registration Protocol */ -#define PCPP_PPP_CDPD_MNRP 0x4003 +#define PCPP_PPP_CDPD_MNRP 0x4003 /** Expand accelerator protocol */ -#define PCPP_PPP_EXPANDAP 0x4005 +#define PCPP_PPP_EXPANDAP 0x4005 /** ODSICP NCP */ -#define PCPP_PPP_ODSICP 0x4007 +#define PCPP_PPP_ODSICP 0x4007 /** DOCSIS DLL */ -#define PCPP_PPP_DOCSIS 0x4009 +#define PCPP_PPP_DOCSIS 0x4009 /** Cetacean Network Detection Protocol */ -#define PCPP_PPP_CETACEANNDP 0x400b +#define PCPP_PPP_CETACEANNDP 0x400b /** Stacker LZS */ -#define PCPP_PPP_LZS 0x4021 +#define PCPP_PPP_LZS 0x4021 /** RefTek Protocol */ -#define PCPP_PPP_REFTEK 0x4023 +#define PCPP_PPP_REFTEK 0x4023 /** Fibre Channel */ -#define PCPP_PPP_FC 0x4025 +#define PCPP_PPP_FC 0x4025 /** EMIT Protocols */ -#define PCPP_PPP_EMIT 0x4027 +#define PCPP_PPP_EMIT 0x4027 /** Vendor-Specific Protocol (VSP) */ -#define PCPP_PPP_VSP 0x405b +#define PCPP_PPP_VSP 0x405b /** TRILL Link State Protocol (TLSP) */ -#define PCPP_PPP_TLSP 0x405d +#define PCPP_PPP_TLSP 0x405d /** Internet Protocol Control Protocol */ -#define PCPP_PPP_IPCP 0x8021 +#define PCPP_PPP_IPCP 0x8021 /** OSI Network Layer Control Protocol */ -#define PCPP_PPP_OSINLCP 0x8023 +#define PCPP_PPP_OSINLCP 0x8023 /** Xerox NS IDP Control Protocol */ -#define PCPP_PPP_XNSIDPCP 0x8025 +#define PCPP_PPP_XNSIDPCP 0x8025 /** DECnet Phase IV Control Protocol */ -#define PCPP_PPP_DECNETCP 0x8027 +#define PCPP_PPP_DECNETCP 0x8027 /** AppleTalk Control Protocol */ -#define PCPP_PPP_ATCP 0x8029 +#define PCPP_PPP_ATCP 0x8029 /** Novell IPX Control Protocol */ -#define PCPP_PPP_IPXCP 0x802b +#define PCPP_PPP_IPXCP 0x802b /** Bridging NCP */ -#define PCPP_PPP_BRIDGENCP 0x8031 +#define PCPP_PPP_BRIDGENCP 0x8031 /** Stream Protocol Control Protocol */ -#define PCPP_PPP_SPCP 0x8033 +#define PCPP_PPP_SPCP 0x8033 /** Banyan Vines Control Protocol */ -#define PCPP_PPP_BVCP 0x8035 +#define PCPP_PPP_BVCP 0x8035 /** Multi-Link Control Protocol */ -#define PCPP_PPP_MLCP 0x803d +#define PCPP_PPP_MLCP 0x803d /** NETBIOS Framing Control Protocol */ -#define PCPP_PPP_NBCP 0x803f +#define PCPP_PPP_NBCP 0x803f /** Cisco Systems Control Protocol */ -#define PCPP_PPP_CISCOCP 0x8041 +#define PCPP_PPP_CISCOCP 0x8041 /** Ascom Timeplex Control Protocol (?) */ -#define PCPP_PPP_ASCOMCP 0x8043 +#define PCPP_PPP_ASCOMCP 0x8043 /** Fujitsu LBLB Control Protocol */ -#define PCPP_PPP_LBLBCP 0x8045 +#define PCPP_PPP_LBLBCP 0x8045 /** DCA Remote Lan Network Control Protocol */ -#define PCPP_PPP_RLNCP 0x8047 +#define PCPP_PPP_RLNCP 0x8047 /** Serial Data Control Protocol */ -#define PCPP_PPP_SDCP 0x8049 +#define PCPP_PPP_SDCP 0x8049 /** SNA over 802.2 Control Protocol */ -#define PCPP_PPP_LLCCP 0x804b +#define PCPP_PPP_LLCCP 0x804b /** SNA Control Protocol */ -#define PCPP_PPP_SNACP 0x804d +#define PCPP_PPP_SNACP 0x804d /** IP6 Header Compression Control Protocol */ -#define PCPP_PPP_IP6HCCP 0x804f +#define PCPP_PPP_IP6HCCP 0x804f /** KNX Bridging Control Protocol */ -#define PCPP_PPP_KNXCP 0x8051 +#define PCPP_PPP_KNXCP 0x8051 /** Encryption Control Protocol */ -#define PCPP_PPP_ECP 0x8053 +#define PCPP_PPP_ECP 0x8053 /** Individual Link Encryption Control Protocol */ -#define PCPP_PPP_ILECP 0x8055 +#define PCPP_PPP_ILECP 0x8055 /** IPv6 Control Protocol */ -#define PCPP_PPP_IPV6CP 0x8057 +#define PCPP_PPP_IPV6CP 0x8057 /** PPP Muxing Control Protocol */ -#define PCPP_PPP_MUXCP 0x8059 +#define PCPP_PPP_MUXCP 0x8059 /** Vendor-Specific Network Control Protocol (VSNCP) [RFC3772] */ -#define PCPP_PPP_VSNCP 0x805b +#define PCPP_PPP_VSNCP 0x805b /** TRILL Network Control Protocol (TNCP) */ -#define PCPP_PPP_TNCP 0x805d +#define PCPP_PPP_TNCP 0x805d /** Stampede Bridging Control Protocol */ -#define PCPP_PPP_STAMPEDECP 0x806f +#define PCPP_PPP_STAMPEDECP 0x806f /** MP+ Contorol Protocol */ -#define PCPP_PPP_MPPCP 0x8073 +#define PCPP_PPP_MPPCP 0x8073 /** NTCITS IPI Control Protocol */ -#define PCPP_PPP_IPICP 0x80c1 +#define PCPP_PPP_IPICP 0x80c1 /** Single link compression in multilink control */ -#define PCPP_PPP_SLCC 0x80fb +#define PCPP_PPP_SLCC 0x80fb /** Compression Control Protocol */ -#define PCPP_PPP_CCP 0x80fd +#define PCPP_PPP_CCP 0x80fd /** Cisco Discovery Protocol Control Protocol */ -#define PCPP_PPP_CDPCP 0x8207 +#define PCPP_PPP_CDPCP 0x8207 /** Netcs Twin Routing */ -#define PCPP_PPP_NETCSCP 0x8209 +#define PCPP_PPP_NETCSCP 0x8209 /** STP - Control Protocol */ -#define PCPP_PPP_STPCP 0x820b +#define PCPP_PPP_STPCP 0x820b /** EDPCP - Extreme Discovery Protocol Control Protocol */ -#define PCPP_PPP_EDPCP 0x820d +#define PCPP_PPP_EDPCP 0x820d /** Apple Client Server Protocol Control */ -#define PCPP_PPP_ACSPC 0x8235 +#define PCPP_PPP_ACSPC 0x8235 /** MPLS Control Protocol */ -#define PCPP_PPP_MPLSCP 0x8281 +#define PCPP_PPP_MPLSCP 0x8281 /** IEEE p1284.4 standard - Protocol Control */ -#define PCPP_PPP_P12844CP 0x8285 +#define PCPP_PPP_P12844CP 0x8285 /** ETSI TETRA TNP1 Control Protocol */ -#define PCPP_PPP_TETRACP 0x8287 +#define PCPP_PPP_TETRACP 0x8287 /** Multichannel Flow Treatment Protocol */ -#define PCPP_PPP_MFTPCP 0x8289 +#define PCPP_PPP_MFTPCP 0x8289 /** Link Control Protocol */ -#define PCPP_PPP_LCP 0xc021 +#define PCPP_PPP_LCP 0xc021 /** Password Authentication Protocol */ -#define PCPP_PPP_PAP 0xc023 +#define PCPP_PPP_PAP 0xc023 /** Link Quality Report */ -#define PCPP_PPP_LQR 0xc025 +#define PCPP_PPP_LQR 0xc025 /** Shiva Password Authentication Protocol */ -#define PCPP_PPP_SPAP 0xc027 +#define PCPP_PPP_SPAP 0xc027 /** CallBack Control Protocol (CBCP) */ -#define PCPP_PPP_CBCP 0xc029 +#define PCPP_PPP_CBCP 0xc029 /** BACP Bandwidth Allocation Control Protocol */ -#define PCPP_PPP_BACP 0xc02b +#define PCPP_PPP_BACP 0xc02b /** BAP Bandwidth Allocation Protocol */ -#define PCPP_PPP_BAP 0xc02d +#define PCPP_PPP_BAP 0xc02d /** Vendor-Specific Authentication Protocol (VSAP) */ -#define PCPP_PPP_VSAP 0xc05b +#define PCPP_PPP_VSAP 0xc05b /** Container Control Protocol */ -#define PCPP_PPP_CONTCP 0xc081 +#define PCPP_PPP_CONTCP 0xc081 /** Challenge Handshake Authentication Protocol */ -#define PCPP_PPP_CHAP 0xc223 +#define PCPP_PPP_CHAP 0xc223 /** RSA Authentication Protocol */ -#define PCPP_PPP_RSAAP 0xc225 +#define PCPP_PPP_RSAAP 0xc225 /** Extensible Authentication Protocol */ -#define PCPP_PPP_EAP 0xc227 +#define PCPP_PPP_EAP 0xc227 /** Mitsubishi Security Information Exchange Protocol (SIEP) */ -#define PCPP_PPP_SIEP 0xc229 +#define PCPP_PPP_SIEP 0xc229 /** Stampede Bridging Authorization Protocol */ -#define PCPP_PPP_SBAP 0xc26f +#define PCPP_PPP_SBAP 0xc26f /** Proprietary Authentication Protocol */ -#define PCPP_PPP_PRPAP 0xc281 +#define PCPP_PPP_PRPAP 0xc281 /** Proprietary Authentication Protocol */ -#define PCPP_PPP_PRPAP2 0xc283 +#define PCPP_PPP_PRPAP2 0xc283 /** Proprietary Node ID Authentication Protocol */ -#define PCPP_PPP_PRPNIAP 0xc481 +#define PCPP_PPP_PRPNIAP 0xc481 -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/Packet.h b/Packet++/header/Packet.h index 596ea0203a..b0f2d26907 100644 --- a/Packet++/header/Packet.h +++ b/Packet++/header/Packet.h @@ -15,16 +15,18 @@ namespace pcpp /** * @class Packet - * This class represents a parsed packet. It contains the raw data (RawPacket instance), and a linked list of layers, each layer is a parsed - * protocol that this packet contains. The layers linked list is ordered where the first layer is the lowest in the packet (currently it's always - * Ethernet protocol as PcapPlusPlus supports only Ethernet packets), the next layer will be L2.5 or L3 (e.g VLAN, IPv4, IPv6, etc.), and so on. - * etc.), etc. The last layer in the linked list will be the highest in the packet. - * For example: for a standard HTTP request packet the layer will look like this: EthLayer -> IPv4Layer -> TcpLayer -> HttpRequestLayer
- * Packet instance isn't read only. The user can add or remove layers, update current layer, etc. + * This class represents a parsed packet. It contains the raw data (RawPacket instance), and a linked list of + * layers, each layer is a parsed protocol that this packet contains. The layers linked list is ordered where the + * first layer is the lowest in the packet (currently it's always Ethernet protocol as PcapPlusPlus supports only + * Ethernet packets), the next layer will be L2.5 or L3 (e.g VLAN, IPv4, IPv6, etc.), and so on. etc.), etc. The + * last layer in the linked list will be the highest in the packet. For example: for a standard HTTP request packet + * the layer will look like this: EthLayer -> IPv4Layer -> TcpLayer -> HttpRequestLayer
Packet instance isn't + * read only. The user can add or remove layers, update current layer, etc. */ class Packet { friend class Layer; + private: RawPacket* m_RawPacket; Layer* m_FirstLayer; @@ -34,93 +36,114 @@ namespace pcpp bool m_CanReallocateData; public: - /** * A constructor for creating a new packet (with no layers). - * When using this constructor an empty raw buffer is allocated (with the size of maxPacketLen) and a new RawPacket is created + * When using this constructor an empty raw buffer is allocated (with the size of maxPacketLen) and a new + * RawPacket is created * @param[in] maxPacketLen The expected packet length in bytes */ explicit Packet(size_t maxPacketLen = 1); /** * A constructor for creating a new packet with a buffer that is pre-allocated by the user. - * The packet is created empty (with no layers), which means the constructor doesn't parse the data in the buffer. - * Instead, all of the raw data of this packet it written to this buffer: whenever a layer is added, it's data is written to this buffer. - * The buffer isn't freed and it's content isn't erased when the packet object is deleted. - * This constructor is useful when you already have a memory buffer and you want to create packet data in it. + * The packet is created empty (with no layers), which means the constructor doesn't parse the data in the + * buffer. Instead, all of the raw data of this packet it written to this buffer: whenever a layer is added, + * it's data is written to this buffer. The buffer isn't freed and it's content isn't erased when the packet + * object is deleted. This constructor is useful when you already have a memory buffer and you want to create + * packet data in it. * @param[in] buffer A pointer to a pre-allocated memory buffer * @param[in] bufferSize The size of the buffer */ Packet(uint8_t* buffer, size_t bufferSize); /** - * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. - * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers - * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free - * the instance of raw packet when the Packet is free or not + * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that + * came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't copied) + * and the RawPacket is parsed, meaning all layers are created and linked to each other in the right order. In + * this overload of the constructor the user can specify whether to free the instance of raw packet when the + * Packet is free or not * @param[in] rawPacket A pointer to the raw packet - * @param[in] freeRawPacket Optional parameter. A flag indicating if the destructor should also call the raw packet destructor or not. Default value is false - * @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a - * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this - * parameter into account - * @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to - * parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet. + * @param[in] freeRawPacket Optional parameter. A flag indicating if the destructor should also call the raw + * packet destructor or not. Default value is false + * @param[in] parseUntil Optional parameter. Parse the packet until you reach a certain protocol (inclusive). + * Can be useful for cases when you need to parse only up to a certain layer and want to avoid the performance + * impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means + * don't take this parameter into account + * @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI + * model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for example + * transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet. * Default value is ::OsiModelLayerUnknown which means don't take this parameter into account */ - explicit Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); + explicit Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, + OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /** - * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. - * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers - * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free - * the instance of raw packet when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer + * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that + * came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't copied) + * and the RawPacket is parsed, meaning all layers are created and linked to each other in the right order. In + * this overload of the constructor the user can specify whether to free the instance of raw packet when the + * Packet is free or not. This constructor should be used to parse the packet up to a certain layer * @param[in] rawPacket A pointer to the raw packet - * @param[in] parseUntil Parse the packet until you reach a certain protocol (inclusive). Can be useful for cases when you need to parse only up to a - * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet + * @param[in] parseUntil Parse the packet until you reach a certain protocol (inclusive). Can be useful for + * cases when you need to parse only up to a certain layer and want to avoid the performance impact and memory + * consumption of parsing the whole packet */ explicit Packet(RawPacket* rawPacket, ProtocolType parseUntil); /** - * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. - * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers - * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free - * the instance of raw packet when the Packet is free or not. This constructor should be used to parse the packet up to a certain layer + * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that + * came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't copied) + * and the RawPacket is parsed, meaning all layers are created and linked to each other in the right order. In + * this overload of the constructor the user can specify whether to free the instance of raw packet when the + * Packet is free or not. This constructor should be used to parse the packet up to a certain layer * @param[in] rawPacket A pointer to the raw packet - * @param[in] parseUntilFamily Parse the packet until you reach a certain protocol family (inclusive). Can be useful for cases when you need to parse only up to a - * certain layer and want to avoid the performance impact and memory consumption of parsing the whole packet + * @param[in] parseUntilFamily Parse the packet until you reach a certain protocol family (inclusive). Can be + * useful for cases when you need to parse only up to a certain layer and want to avoid the performance impact + * and memory consumption of parsing the whole packet */ explicit Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily); /** - * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that came from the network. - * When using this constructor a pointer to the RawPacket is saved (data isn't copied) and the RawPacket is parsed, meaning all layers - * are created and linked to each other in the right order. In this overload of the constructor the user can specify whether to free - * the instance of raw packet when the Packet is free or not. . This constructor should be used to parse the packet up to a certain layer in the OSI model + * A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets that + * came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't copied) + * and the RawPacket is parsed, meaning all layers are created and linked to each other in the right order. In + * this overload of the constructor the user can specify whether to free the instance of raw packet when the + * Packet is free or not. This constructor should be used to parse the packet up to a certain layer in the OSI + * model * @param[in] rawPacket A pointer to the raw packet - * @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI model (inclusive). Can be useful for cases when you need to - * parse only up to a certain OSI layer (for example transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet + * @param[in] parseUntilLayer Optional parameter. Parse the packet until you reach a certain layer in the OSI + * model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for example + * transport layer) and want to avoid the performance impact and memory consumption of parsing the whole packet */ explicit Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer); /** - * A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers that weren't allocated by this - * class, for example layers that were added by addLayer() or insertLayer() ). In addition it frees the raw packet if it was allocated by - * this instance (meaning if it was allocated by this instance constructor) + * A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers that + * weren't allocated by this class, for example layers that were added by addLayer() or insertLayer() ). In + * addition it frees the raw packet if it was allocated by this instance (meaning if it was allocated by this + * instance constructor) */ - virtual ~Packet() { destructPacketData(); } + virtual ~Packet() + { + destructPacketData(); + } /** - * A copy constructor for this class. This copy constructor copies all the raw data and re-create all layers. So when the original Packet - * is being freed, no data will be lost in the copied instance + * A copy constructor for this class. This copy constructor copies all the raw data and re-create all layers. So + * when the original Packet is being freed, no data will be lost in the copied instance * @param[in] other The instance to copy from */ - Packet(const Packet& other) { copyDataFrom(other); } + Packet(const Packet& other) + { + copyDataFrom(other); + } /** - * Assignment operator overloading. It first frees all layers allocated by this instance (Notice: it doesn't free layers that weren't allocated by this - * class, for example layers that were added by addLayer() or insertLayer() ). In addition it frees the raw packet if it was allocated by - * this instance (meaning if it was allocated by this instance constructor). - * Afterwards it copies the data from the other packet in the same way used in the copy constructor. + * Assignment operator overloading. It first frees all layers allocated by this instance (Notice: it doesn't + * free layers that weren't allocated by this class, for example layers that were added by addLayer() or + * insertLayer() ). In addition it frees the raw packet if it was allocated by this instance (meaning if it was + * allocated by this instance constructor). Afterwards it copies the data from the other packet in the same way + * used in the copy constructor. * @param[in] other The instance to copy from */ Packet& operator=(const Packet& other); @@ -129,47 +152,69 @@ namespace pcpp * Get a pointer to the Packet's RawPacket * @return A pointer to the Packet's RawPacket */ - RawPacket* getRawPacket() const { return m_RawPacket; } + RawPacket* getRawPacket() const + { + return m_RawPacket; + } /** * Set a RawPacket and re-construct all packet layers * @param[in] rawPacket Raw packet to set - * @param[in] freeRawPacket A flag indicating if the destructor should also call the raw packet destructor or not - * @param[in] parseUntil Parse the packet until it reaches this protocol. Can be useful for cases when you need to parse only up to a certain layer and want to avoid the - * performance impact and memory consumption of parsing the whole packet. Default value is ::UnknownProtocol which means don't take this parameter into account - * @param[in] parseUntilLayer Parse the packet until certain layer in OSI model. Can be useful for cases when you need to parse only up to a certain layer and want to avoid the - * performance impact and memory consumption of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter into account + * @param[in] freeRawPacket A flag indicating if the destructor should also call the raw packet destructor or + * not + * @param[in] parseUntil Parse the packet until it reaches this protocol. Can be useful for cases when you need + * to parse only up to a certain layer and want to avoid the performance impact and memory consumption of + * parsing the whole packet. Default value is ::UnknownProtocol which means don't take this parameter into + * account + * @param[in] parseUntilLayer Parse the packet until certain layer in OSI model. Can be useful for cases when + * you need to parse only up to a certain layer and want to avoid the performance impact and memory consumption + * of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter + * into account */ - void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); + void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil = UnknownProtocol, + OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /** * Get a pointer to the Packet's RawPacket in a read-only manner * @return A pointer to the Packet's RawPacket */ - RawPacket* getRawPacketReadOnly() const { return m_RawPacket; } + RawPacket* getRawPacketReadOnly() const + { + return m_RawPacket; + } /** * Get a pointer to the first (lowest) layer in the packet * @return A pointer to the first (lowest) layer in the packet */ - Layer* getFirstLayer() const { return m_FirstLayer; } + Layer* getFirstLayer() const + { + return m_FirstLayer; + } /** * Get a pointer to the last (highest) layer in the packet * @return A pointer to the last (highest) layer in the packet */ - Layer* getLastLayer() const { return m_LastLayer; } + Layer* getLastLayer() const + { + return m_LastLayer; + } /** * Add a new layer as the last layer in the packet. This method gets a pointer to the new layer as a parameter * and attaches it to the packet. Notice after calling this method the input layer is attached to the packet so * every change you make in it affect the packet; Also it cannot be attached to other packets * @param[in] newLayer A pointer to the new layer to be added to the packet - * @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default is false. + * @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default + * is false. * @return True if everything went well or false otherwise (an appropriate error log message will be printed in * such cases) */ - bool addLayer(Layer* newLayer, bool ownInPacket = false) { return insertLayer(m_LastLayer, newLayer, ownInPacket); } + bool addLayer(Layer* newLayer, bool ownInPacket = false) + { + return insertLayer(m_LastLayer, newLayer, ownInPacket); + } /** * Insert a new layer after an existing layer in the packet. This method gets a pointer to the new layer as a @@ -178,85 +223,89 @@ namespace pcpp * @param[in] prevLayer A pointer to an existing layer in the packet which the new layer should followed by. If * this layer isn't attached to a packet and error will be printed to log and false will be returned * @param[in] newLayer A pointer to the new layer to be added to the packet - * @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default is false. + * @param[in] ownInPacket If true, Packet fully owns newLayer, including memory deletion upon destruct. Default + * is false. * @return True if everything went well or false otherwise (an appropriate error log message will be printed in * such cases) */ bool insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket = false); - /** * Remove an existing layer from the packet. The layer to removed is identified by its type (protocol). If the - * packet has multiple layers of the same type in the packet the user may specify the index of the layer to remove - * (the default index is 0 - remove the first layer of this type). If the layer was allocated during packet creation - * it will be deleted and any pointer to it will get invalid. However if the layer was allocated by the user and - * manually added to the packet it will simply get detached from the packet, meaning the pointer to it will stay - * valid and its data (that was removed from the packet) will be copied back to the layer. In that case it's - * the user's responsibility to delete the layer instance + * packet has multiple layers of the same type in the packet the user may specify the index of the layer to + * remove (the default index is 0 - remove the first layer of this type). If the layer was allocated during + * packet creation it will be deleted and any pointer to it will get invalid. However if the layer was allocated + * by the user and manually added to the packet it will simply get detached from the packet, meaning the pointer + * to it will stay valid and its data (that was removed from the packet) will be copied back to the layer. In + * that case it's the user's responsibility to delete the layer instance * @param[in] layerType The layer type (protocol) to remove - * @param[in] index If there are multiple layers of the same type, indicate which instance to remove. The default - * value is 0, meaning remove the first layer of this type + * @param[in] index If there are multiple layers of the same type, indicate which instance to remove. The + * default value is 0, meaning remove the first layer of this type * @return True if everything went well or false otherwise (an appropriate error log message will be printed in * such cases) */ bool removeLayer(ProtocolType layerType, int index = 0); /** - * Remove the first layer in the packet. The layer will be deleted if it was allocated during packet creation, or detached - * if was allocated outside of the packet. Please refer to removeLayer() to get more info - * @return True if layer removed successfully, or false if removing the layer failed or if there are no layers in the - * packet. In any case of failure an appropriate error log message will be printed + * Remove the first layer in the packet. The layer will be deleted if it was allocated during packet creation, + * or detached if was allocated outside of the packet. Please refer to removeLayer() to get more info + * @return True if layer removed successfully, or false if removing the layer failed or if there are no layers + * in the packet. In any case of failure an appropriate error log message will be printed */ bool removeFirstLayer(); /** - * Remove the last layer in the packet. The layer will be deleted if it was allocated during packet creation, or detached - * if was allocated outside of the packet. Please refer to removeLayer() to get more info - * @return True if layer removed successfully, or false if removing the layer failed or if there are no layers in the - * packet. In any case of failure an appropriate error log message will be printed + * Remove the last layer in the packet. The layer will be deleted if it was allocated during packet creation, or + * detached if was allocated outside of the packet. Please refer to removeLayer() to get more info + * @return True if layer removed successfully, or false if removing the layer failed or if there are no layers + * in the packet. In any case of failure an appropriate error log message will be printed */ bool removeLastLayer(); /** - * Remove all layers that come after a certain layer. All layers removed will be deleted if they were allocated during - * packet creation or detached if were allocated outside of the packet, please refer to removeLayer() to get more info - * @param[in] layer A pointer to the layer to begin removing from. Please note this layer will not be removed, only the - * layers that come after it will be removed. Also, if removal of one layer failed, the method will return immediately and - * the following layers won't be deleted - * @return True if all layers were removed successfully, or false if failed to remove at least one layer. In any case of - * failure an appropriate error log message will be printed + * Remove all layers that come after a certain layer. All layers removed will be deleted if they were allocated + * during packet creation or detached if were allocated outside of the packet, please refer to removeLayer() to + * get more info + * @param[in] layer A pointer to the layer to begin removing from. Please note this layer will not be removed, + * only the layers that come after it will be removed. Also, if removal of one layer failed, the method will + * return immediately and the following layers won't be deleted + * @return True if all layers were removed successfully, or false if failed to remove at least one layer. In any + * case of failure an appropriate error log message will be printed */ bool removeAllLayersAfter(Layer* layer); /** - * Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated from the - * packet - e.g it will be removed from the layer chain of the packet and its data will be copied from the packet buffer - * into an internal layer buffer. After a layer is detached, it can be added into another packet (but it's impossible to - * attach a layer to multiple packets in the same time). After layer is detached, it's the user's responsibility to - * delete it when it's not needed anymore + * Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated + * from the packet - e.g it will be removed from the layer chain of the packet and its data will be copied from + * the packet buffer into an internal layer buffer. After a layer is detached, it can be added into another + * packet (but it's impossible to attach a layer to multiple packets in the same time). After layer is detached, + * it's the user's responsibility to delete it when it's not needed anymore * @param[in] layerType The layer type (protocol) to detach from the packet - * @param[in] index If there are multiple layers of the same type, indicate which instance to detach. The default - * value is 0, meaning detach the first layer of this type + * @param[in] index If there are multiple layers of the same type, indicate which instance to detach. The + * default value is 0, meaning detach the first layer of this type * @return A pointer to the detached layer or NULL if detaching process failed. In any case of failure an * appropriate error log message will be printed */ Layer* detachLayer(ProtocolType layerType, int index = 0); /** - * Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated from the - * packet - e.g it will be removed from the layer chain of the packet and its data will be copied from the packet buffer - * into an internal layer buffer. After a layer is detached, it can be added into another packet (but it's impossible to - * attach a layer to multiple packets at the same time). After layer is detached, it's the user's responsibility to - * delete it when it's not needed anymore + * Detach a layer from the packet. Detaching means the layer instance will not be deleted, but rather separated + * from the packet - e.g it will be removed from the layer chain of the packet and its data will be copied from + * the packet buffer into an internal layer buffer. After a layer is detached, it can be added into another + * packet (but it's impossible to attach a layer to multiple packets at the same time). After layer is detached, + * it's the user's responsibility to delete it when it's not needed anymore * @param[in] layer A pointer to the layer to detach - * @return True if the layer was detached successfully, or false if something went wrong. In any case of failure an - * appropriate error log message will be printed + * @return True if the layer was detached successfully, or false if something went wrong. In any case of failure + * an appropriate error log message will be printed */ - bool detachLayer(Layer* layer) { return removeLayer(layer, false); } + bool detachLayer(Layer* layer) + { + return removeLayer(layer, false); + } /** - * Get a pointer to the layer of a certain type (protocol). This method goes through the layers and returns a layer - * that matches the give protocol type + * Get a pointer to the layer of a certain type (protocol). This method goes through the layers and returns a + * layer that matches the give protocol type * @param[in] layerType The layer type (protocol) to fetch * @param[in] index If there are multiple layers of the same type, indicate which instance to fetch. The default * value is 0, meaning fetch the first layer of this type @@ -265,34 +314,33 @@ namespace pcpp Layer* getLayerOfType(ProtocolType layerType, int index = 0) const; /** - * A templated method to get a layer of a certain type (protocol). If no layer of such type is found, NULL is returned - * @param[in] reverseOrder The optional parameter that indicates that the lookup should run in reverse order, the default value is false + * A templated method to get a layer of a certain type (protocol). If no layer of such type is found, NULL is + * returned + * @param[in] reverseOrder The optional parameter that indicates that the lookup should run in reverse order, + * the default value is false * @return A pointer to the layer of the requested type, NULL if not found */ - template - TLayer* getLayerOfType(bool reverseOrder = false) const; + template TLayer* getLayerOfType(bool reverseOrder = false) const; /** * A templated method to get the first layer of a certain type (protocol), start searching from a certain layer. * For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> IPv4Layer - * and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(3) will be returned - * If no layer of such type is found, NULL is returned + * and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(3) will be + * returned If no layer of such type is found, NULL is returned * @param[in] startLayer A pointer to the layer to start search from * @return A pointer to the layer of the requested type, NULL if not found */ - template - TLayer* getNextLayerOfType(Layer* startLayer) const; + template TLayer* getNextLayerOfType(Layer* startLayer) const; /** * A templated method to get the first layer of a certain type (protocol), start searching from a certain layer. * For example: if a packet looks like: EthLayer -> VlanLayer(1) -> VlanLayer(2) -> VlanLayer(3) -> IPv4Layer - * and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(1) will be returned - * If no layer of such type is found, NULL is returned + * and the user put VlanLayer(2) as a parameter and wishes to search for a VlanLayer, VlanLayer(1) will be + * returned If no layer of such type is found, NULL is returned * @param[in] startLayer A pointer to the layer to start search from * @return A pointer to the layer of the requested type, NULL if not found */ - template - TLayer* getPrevLayerOfType(Layer* startLayer) const; + template TLayer* getPrevLayerOfType(Layer* startLayer) const; /** * Check whether the packet contains a layer of a certain protocol @@ -302,30 +350,34 @@ namespace pcpp bool isPacketOfType(ProtocolType protocolType) const; /** - * Check whether the packet contains a layer of a certain protocol family - * @param[in] protocolTypeFamily The protocol type family to search + * Check whether the packet contains a layer of a certain protocol family + * @param[in] protocolTypeFamily The protocol type family to search * @return True if the packet contains a layer of a certain protocol family, false otherwise */ bool isPacketOfType(ProtocolTypeFamily protocolTypeFamily) const; /** - * Each layer can have fields that can be calculate automatically from other fields using Layer#computeCalculateFields(). This method forces all layers to calculate these - * fields values + * Each layer can have fields that can be calculate automatically from other fields using + * Layer#computeCalculateFields(). This method forces all layers to calculate these fields values */ void computeCalculateFields(); /** - * Each layer can print a string representation of the layer most important data using Layer#toString(). This method aggregates this string from all layers and - * print it to a complete string containing all packet's relevant data - * @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set to false - * @return A string containing most relevant data from all layers (looks like the packet description in Wireshark) + * Each layer can print a string representation of the layer most important data using Layer#toString(). This + * method aggregates this string from all layers and print it to a complete string containing all packet's + * relevant data + * @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set + * to false + * @return A string containing most relevant data from all layers (looks like the packet description in + * Wireshark) */ std::string toString(bool timeAsLocalTime = true) const; /** * Similar to toString(), but instead of one string it outputs a list of strings, one string for every layer * @param[out] result A string vector that will contain all strings - * @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set to false + * @param[in] timeAsLocalTime Print time as local time or GMT. Default (true value) is local time, for GMT set + * to false */ void toStringList(std::vector& result, bool timeAsLocalTime = true) const; @@ -344,13 +396,11 @@ namespace pcpp std::string printPacketInfo(bool timeAsLocalTime) const; Layer* createFirstLayer(LinkLayerType linkType); - }; // class Packet - + }; // class Packet // implementation of inline methods - template - TLayer* Packet::getLayerOfType(bool reverse) const + template TLayer* Packet::getLayerOfType(bool reverse) const { if (!reverse) { @@ -367,8 +417,7 @@ namespace pcpp return getPrevLayerOfType(getLastLayer()); } - template - TLayer* Packet::getNextLayerOfType(Layer* curLayer) const + template TLayer* Packet::getNextLayerOfType(Layer* curLayer) const { if (curLayer == NULL) return NULL; @@ -382,8 +431,7 @@ namespace pcpp return dynamic_cast(curLayer); } - template - TLayer* Packet::getPrevLayerOfType(Layer* curLayer) const + template TLayer* Packet::getPrevLayerOfType(Layer* curLayer) const { if (curLayer == NULL) return NULL; @@ -397,7 +445,7 @@ namespace pcpp return dynamic_cast(curLayer); } -} // namespace pcpp +} // namespace pcpp inline std::ostream& operator<<(std::ostream& os, const pcpp::Packet& packet) { diff --git a/Packet++/header/PacketTrailerLayer.h b/Packet++/header/PacketTrailerLayer.h index 15ebb8ff57..7dbc819626 100644 --- a/Packet++/header/PacketTrailerLayer.h +++ b/Packet++/header/PacketTrailerLayer.h @@ -8,17 +8,19 @@ namespace pcpp { /** * @class PacketTrailerLayer - * A class for representing packet tailer (a.k.a footer or padding) which refers to supplemental data placed at the end of a block of data - * being stored or transmitted, which may contain information for the handling of the data block, or just mark its end - * (taken from Wikipedia: https://en.wikipedia.org/wiki/Trailer_(computing) ) + * A class for representing packet tailer (a.k.a footer or padding) which refers to supplemental data placed at the + * end of a block of data being stored or transmitted, which may contain information for the handling of the data + * block, or just mark its end (taken from Wikipedia: https://en.wikipedia.org/wiki/Trailer_(computing) ) * - * There are various reasons for adding a packet trailer, one of the most famous is FCS (Frame check sequence) which refers to the extra - * error-detecting code added to a frame. Another usage is padding which means adding data to reach a minimum required packet length. + * There are various reasons for adding a packet trailer, one of the most famous is FCS (Frame check sequence) which + * refers to the extra error-detecting code added to a frame. Another usage is padding which means adding data to + * reach a minimum required packet length. * - * Although this layer inherits from the Layer class, it is not a standard layer in the sense that it can't be constructed by the user. - * This layer may be only be constructed in the Packet class, in the process of parsing the packet and creating the layers; if at the end - * of the parsing process there is data left that is not allocated to any layer, it's assumed to be the packet trailer and an instance of - * this class is created. This means this layer can only exist as the last layer in a packet, if a packet trailer indeed exists. + * Although this layer inherits from the Layer class, it is not a standard layer in the sense that it can't be + * constructed by the user. This layer may be only be constructed in the Packet class, in the process of parsing the + * packet and creating the layers; if at the end of the parsing process there is data left that is not allocated to + * any layer, it's assumed to be the packet trailer and an instance of this class is created. This means this layer + * can only exist as the last layer in a packet, if a packet trailer indeed exists. * * No layer can be added by the user after this layer (trying to do that will result with an error). * @@ -29,21 +31,29 @@ namespace pcpp class PacketTrailerLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - PacketTrailerLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = PacketTrailer; } + PacketTrailerLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = PacketTrailer; + } - ~PacketTrailerLayer() {} + ~PacketTrailerLayer() + {} /** * Get a pointer to the trailer data * @return A pointer to the trailer data */ - uint8_t* getTrailerData() const { return m_Data; } + uint8_t* getTrailerData() const + { + return m_Data; + } /** * @return Trailer data as hex string @@ -54,28 +64,39 @@ namespace pcpp * Get the trailer data length * @return The trailer data length in bytes */ - size_t getTrailerLen() const { return m_DataLen; } + size_t getTrailerLen() const + { + return m_DataLen; + } // implement abstract methods /** * Does nothing for this layer (PacketTrailerLayer is always last) */ - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return trailer data length in bytes */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/PacketUtils.h b/Packet++/header/PacketUtils.h index 7bfc50b402..1bf04c091a 100644 --- a/Packet++/header/PacketUtils.h +++ b/Packet++/header/PacketUtils.h @@ -14,8 +14,7 @@ namespace pcpp /** * A struct that represent a single buffer */ - template - struct ScalarBuffer + template struct ScalarBuffer { /** * The pointer to the buffer @@ -36,7 +35,7 @@ namespace pcpp */ uint16_t computeChecksum(ScalarBuffer vec[], size_t vecSize); - /** + /** * Computes the checksum for Pseudo header * @param[in] dataPtr Data pointer * @param[in] dataLen Data length @@ -46,9 +45,8 @@ namespace pcpp * @param[in] dstIPAddress Destination IP Address * @return The checksum result */ - uint16_t computePseudoHdrChecksum(uint8_t *dataPtr, size_t dataLen, - IPAddress::AddressType ipAddrType, uint8_t protocolType, - IPAddress srcIPAddress, IPAddress dstIPAddress); + uint16_t computePseudoHdrChecksum(uint8_t* dataPtr, size_t dataLen, IPAddress::AddressType ipAddrType, + uint8_t protocolType, IPAddress srcIPAddress, IPAddress dstIPAddress); /** * Computes Fowler-Noll-Vo (FNV-1) 32bit hash function on an array of byte buffers. The hash is calculated on each @@ -85,4 +83,4 @@ namespace pcpp */ uint32_t hash2Tuple(Packet* packet); -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/PayloadLayer.h b/Packet++/header/PayloadLayer.h index bed6d3f677..759a192b3a 100644 --- a/Packet++/header/PayloadLayer.h +++ b/Packet++/header/PayloadLayer.h @@ -18,13 +18,17 @@ namespace pcpp class PayloadLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - PayloadLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = GenericPayload; } + PayloadLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = GenericPayload; + } /** * A constructor that allocates a new payload @@ -35,46 +39,60 @@ namespace pcpp /** * A constructor that allocates a new payload from an hex stream - * @param[in] payloadAsHexStream A string that represents an hex stream of the payload. For example: 0001080006040002842b2b774c56c0a80078000000000000c0a8. - * In order for the hex stream to be valid it has to contain valid hex chars only (which means, for example, that it can't begin with "0x") and it also has - * to have an even number of chars (each char represents one nibble). If the string is not a valid hex stream an error will be printed to log and the payload - * layer will be empty (no data) + * @param[in] payloadAsHexStream A string that represents an hex stream of the payload. For example: + * 0001080006040002842b2b774c56c0a80078000000000000c0a8. In order for the hex stream to be valid it has to + * contain valid hex chars only (which means, for example, that it can't begin with "0x") and it also has to + * have an even number of chars (each char represents one nibble). If the string is not a valid hex stream an + * error will be printed to log and the payload layer will be empty (no data) */ explicit PayloadLayer(const std::string& payloadAsHexStream); - ~PayloadLayer() {} + ~PayloadLayer() + {} /** * Get a pointer to the payload data * @return A pointer to the payload data */ - uint8_t* getPayload() const { return m_Data; } + uint8_t* getPayload() const + { + return m_Data; + } /** * Get the payload data length * @return The payload data length in bytes */ - size_t getPayloadLen() const { return m_DataLen; } + size_t getPayloadLen() const + { + return m_DataLen; + } // implement abstract methods /** * Does nothing for this layer (PayloadLayer is always last) */ - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return Payload data length in bytes */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} /** - * Sets the payload of the PayloadLayer to the given pointer. This will resize (extend/shorten) the underlying packet respectively if there is one. + * Sets the payload of the PayloadLayer to the given pointer. This will resize (extend/shorten) the underlying + * packet respectively if there is one. * @param[in] newPayload New payload that shall be set * @param[in] newPayloadLength New length of payload */ @@ -82,8 +100,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } - + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/ProtocolType.h b/Packet++/header/ProtocolType.h index 0f7cba2bbd..ada6950c5e 100644 --- a/Packet++/header/ProtocolType.h +++ b/Packet++/header/ProtocolType.h @@ -267,8 +267,8 @@ namespace pcpp */ const ProtocolType Telnet = 40; - /** - * File Transfer (FTP) Protocol + /** + * File Transfer (FTP) Protocol */ const ProtocolType FTP = 41; @@ -318,8 +318,8 @@ namespace pcpp const ProtocolType VRRPv3 = 50; /** - * VRRP protocol family (VRRPv2 and VRRPv3 protocols) - */ + * VRRP protocol family (VRRPv2 and VRRPv3 protocols) + */ const ProtocolTypeFamily VRRP = 0x3132; /** @@ -370,4 +370,4 @@ namespace pcpp OsiModelLayerUnknown = 8 }; -} //namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/RadiusLayer.h b/Packet++/header/RadiusLayer.h index 09d0198f30..09ac76a5a0 100644 --- a/Packet++/header/RadiusLayer.h +++ b/Packet++/header/RadiusLayer.h @@ -30,7 +30,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @class RadiusAttribute * A wrapper class for RADIUS attributes. This class does not create or modify RADIUS attribute records, but rather @@ -39,17 +38,18 @@ namespace pcpp class RadiusAttribute : public TLVRecord { public: - /** * A c'tor for this class that gets a pointer to the attribute raw data (byte array) * @param[in] attrRawData A pointer to the attribute raw data */ - explicit RadiusAttribute(uint8_t* attrRawData) : TLVRecord(attrRawData) { } + explicit RadiusAttribute(uint8_t* attrRawData) : TLVRecord(attrRawData) + {} /** * A d'tor for this class, currently does nothing */ - virtual ~RadiusAttribute() { } + virtual ~RadiusAttribute() + {} // implement abstract methods @@ -66,11 +66,10 @@ namespace pcpp if (m_Data == nullptr) return 0; - return (size_t)m_Data->recordLen - 2*sizeof(uint8_t); + return (size_t)m_Data->recordLen - 2 * sizeof(uint8_t); } }; - /** * @class RadiusAttributeBuilder * A class for building RADIUS attributes. This builder receives the attribute parameters in its c'tor, @@ -79,68 +78,69 @@ namespace pcpp class RadiusAttributeBuilder : public TLVRecordBuilder { public: - /** - * A c'tor for building RADIUS attributes which their value is a byte array. The RadiusAttribute object can later - * be retrieved by calling build() + * A c'tor for building RADIUS attributes which their value is a byte array. The RadiusAttribute object can + * later be retrieved by calling build() * @param[in] attrType RADIUS attribute type - * @param[in] attrValue A buffer containing the attribute value. This buffer is read-only and isn't modified in any way + * @param[in] attrValue A buffer containing the attribute value. This buffer is read-only and isn't modified in + * any way * @param[in] attrValueLen Attribute value length in bytes */ - RadiusAttributeBuilder(uint8_t attrType, const uint8_t* attrValue, uint8_t attrValueLen) : - TLVRecordBuilder(attrType, attrValue, attrValueLen) { } + RadiusAttributeBuilder(uint8_t attrType, const uint8_t* attrValue, uint8_t attrValueLen) + : TLVRecordBuilder(attrType, attrValue, attrValueLen) + {} /** - * A c'tor for building RADIUS attributes which have a 1-byte value. The RadiusAttribute object can later be retrieved - * by calling build() + * A c'tor for building RADIUS attributes which have a 1-byte value. The RadiusAttribute object can later be + * retrieved by calling build() * @param[in] attrType RADIUS attribute type * @param[in] attrValue A 1-byte attribute value */ - RadiusAttributeBuilder(uint8_t attrType, uint8_t attrValue) : - TLVRecordBuilder(attrType, attrValue) { } + RadiusAttributeBuilder(uint8_t attrType, uint8_t attrValue) : TLVRecordBuilder(attrType, attrValue) + {} /** - * A c'tor for building RADIUS attributes which have a 2-byte value. The RadiusAttribute object can later be retrieved - * by calling build() + * A c'tor for building RADIUS attributes which have a 2-byte value. The RadiusAttribute object can later be + * retrieved by calling build() * @param[in] attrType RADIUS attribute type * @param[in] attrValue A 2-byte attribute value */ - RadiusAttributeBuilder(uint8_t attrType, uint16_t attrValue) : - TLVRecordBuilder(attrType, attrValue) { } + RadiusAttributeBuilder(uint8_t attrType, uint16_t attrValue) : TLVRecordBuilder(attrType, attrValue) + {} /** - * A c'tor for building RADIUS attributes which have a 4-byte value. The RadiusAttribute object can later be retrieved - * by calling build() + * A c'tor for building RADIUS attributes which have a 4-byte value. The RadiusAttribute object can later be + * retrieved by calling build() * @param[in] attrType RADIUS attribute type * @param[in] attrValue A 4-byte attribute value */ - RadiusAttributeBuilder(uint8_t attrType, uint32_t attrValue) : - TLVRecordBuilder(attrType, attrValue) { } + RadiusAttributeBuilder(uint8_t attrType, uint32_t attrValue) : TLVRecordBuilder(attrType, attrValue) + {} /** - * A c'tor for building RADIUS attributes which have an IPv4Address value. The RadiusAttribute object can later be - * retrieved by calling build() + * A c'tor for building RADIUS attributes which have an IPv4Address value. The RadiusAttribute object can later + * be retrieved by calling build() * @param[in] attrType RADIUS attribute type * @param[in] attrValue The IPv4 address attribute value */ - RadiusAttributeBuilder(uint8_t attrType, const IPv4Address& attrValue) : - TLVRecordBuilder(attrType, attrValue) { } + RadiusAttributeBuilder(uint8_t attrType, const IPv4Address& attrValue) : TLVRecordBuilder(attrType, attrValue) + {} /** - * A c'tor for building RADIUS attributes which have a string value. The RadiusAttribute object can later be retrieved - * by calling build() + * A c'tor for building RADIUS attributes which have a string value. The RadiusAttribute object can later be + * retrieved by calling build() * @param[in] attrType RADIUS attribute type * @param[in] attrValue The string attribute value */ - RadiusAttributeBuilder(uint8_t attrType, const std::string& attrValue) : - TLVRecordBuilder(attrType, attrValue) { } + RadiusAttributeBuilder(uint8_t attrType, const std::string& attrValue) : TLVRecordBuilder(attrType, attrValue) + {} /** * A copy c'tor which copies all the data from another instance of RadiusAttributeBuilder * @param[in] other The instance to copy from */ - RadiusAttributeBuilder(const RadiusAttributeBuilder& other) : - TLVRecordBuilder(other) { } + RadiusAttributeBuilder(const RadiusAttributeBuilder& other) : TLVRecordBuilder(other) + {} /** * Assignment operator that copies all data from another instance of RadiusAttributeBuilder @@ -159,7 +159,6 @@ namespace pcpp RadiusAttribute build() const; }; - /** * @class RadiusLayer * Represents a RADIUS (Remote Authentication Dial-In User Service) protocol layer @@ -167,15 +166,16 @@ namespace pcpp class RadiusLayer : public Layer { private: - TLVRecordReader m_AttributeReader; - uint8_t* getAttributesBasePtr() const { return m_Data + sizeof(radius_header); } + uint8_t* getAttributesBasePtr() const + { + return m_Data + sizeof(radius_header); + } RadiusAttribute addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset); public: - /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -183,9 +183,11 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - RadiusLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : - Layer(data, dataLen, prevLayer, packet) - { m_Protocol = Radius; } + RadiusLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = Radius; + } /** * A constructor that creates a new layer from scratch @@ -193,8 +195,9 @@ namespace pcpp * @param[in] id The RADIUS message ID * @param[in] authenticator A pointer to a byte array containing the authenticator value * @param[in] authenticatorArrSize The authenticator byte array size. A valid size of the authenticator field is - * 16 bytes. If the provided size is less than that then the byte array will be copied to the packet but the missing - * bytes will stay zero. If the size is more than 16 bytes, only the first 16 bytes will be copied to the packet + * 16 bytes. If the provided size is less than that then the byte array will be copied to the packet but the + * missing bytes will stay zero. If the size is more than 16 bytes, only the first 16 bytes will be copied to + * the packet */ RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize); @@ -203,22 +206,27 @@ namespace pcpp * @param[in] code The RADIUS message code * @param[in] id The RADIUS message ID * @param[in] authenticator A hex string representing the authenticator value. A valid size of the authenticator - * field is 16 bytes. If the hex string represents an array that is smaller than this then the missing bytes in the - * packet's authenticator field will stay zero. If the hex string represents an array that is larger than 16 bytes, - * only the first 16 bytes will be copied to the packet + * field is 16 bytes. If the hex string represents an array that is smaller than this then the missing bytes in + * the packet's authenticator field will stay zero. If the hex string represents an array that is larger than 16 + * bytes, only the first 16 bytes will be copied to the packet */ - RadiusLayer(uint8_t code, uint8_t id, const std::string &authenticator); + RadiusLayer(uint8_t code, uint8_t id, const std::string& authenticator); /** * A d'tor for this layer, currently does nothing */ - ~RadiusLayer() {} + ~RadiusLayer() + {} /** - * Get a pointer to the RADIUS header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the RADIUS header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the radius_header object */ - radius_header* getRadiusHeader() const { return (radius_header*)m_Data; } + radius_header* getRadiusHeader() const + { + return (radius_header*)m_Data; + } /** * @return A hex string representation of the radius_header#authenticator byte array value @@ -287,7 +295,8 @@ namespace pcpp /** * Remove an existing RADIUS attribute from the layer * @param[in] attrType The RADIUS attribute type to remove - * @return True if the RADIUS attribute was successfully removed or false if type wasn't found or if removal failed + * @return True if the RADIUS attribute was successfully removed or false if type wasn't found or if removal + * failed */ bool removeAttribute(uint8_t attrType); @@ -321,7 +330,8 @@ namespace pcpp /** * Does nothing for this layer, RADIUS is always last */ - void parseNextLayer() {} + void parseNextLayer() + {} /** * Calculate and store the value of radius_header#length according to the layer size @@ -330,10 +340,12 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } }; - // implementation of inline methods bool RadiusLayer::isRadiusPort(uint16_t port) @@ -347,6 +359,6 @@ namespace pcpp default: return false; } - } // isRadiusPort + } // isRadiusPort -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index a212b3d3c7..5cb59146bf 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -2,10 +2,10 @@ #include #ifdef _MSC_VER -#include -#include +# include +# include #else -#include +# include #endif #include @@ -43,7 +43,8 @@ namespace pcpp LINKTYPE_DLT_RAW1 = 12, /** Raw IP (OpenBSD) */ LINKTYPE_DLT_RAW2 = 14, - /** PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547 */ + /** PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547 + */ LINKTYPE_PPP_HDLC = 50, /** PPPoE */ LINKTYPE_PPP_ETHER = 51, @@ -125,7 +126,8 @@ namespace pcpp LINKTYPE_IEEE802_11_AVS = 163, /** BACnet MS/TP frames */ LINKTYPE_BACNET_MS_TP = 165, - /** PPP in HDLC-like encapsulation, like LINKTYPE_PPP_HDLC, but with the 0xff address byte replaced by a direction indication - 0x00 for incoming and 0x01 for outgoing */ + /** PPP in HDLC-like encapsulation, like LINKTYPE_PPP_HDLC, but with the 0xff address byte replaced by a + * direction indication - 0x00 for incoming and 0x01 for outgoing */ LINKTYPE_PPP_PPPD = 166, /** General Packet Radio Service Logical Link Control */ LINKTYPE_GPRS_LLC = 169, @@ -153,7 +155,8 @@ namespace pcpp LINKTYPE_AX25_KISS = 202, /** Link Access Procedures on the D Channel (LAPD) frames */ LINKTYPE_LAPD = 203, - /** PPP, as per RFC 1661 and RFC 1662, preceded with a one-byte pseudo-header with a zero value meaning "received by this host" and a non-zero value meaning "sent by this host" */ + /** PPP, as per RFC 1661 and RFC 1662, preceded with a one-byte pseudo-header with a zero value meaning + * "received by this host" and a non-zero value meaning "sent by this host" */ LINKTYPE_PPP_WITH_DIR = 204, /** Cisco PPP with HDLC framing */ LINKTYPE_C_HDLC_WITH_DIR = 205, @@ -179,27 +182,34 @@ namespace pcpp LINKTYPE_IPV6 = 229, /** IEEE 802.15.4 wireless Personal Area Network, without the FCS at the end of the frame */ LINKTYPE_IEEE802_15_4_NOFCS = 230, - /** Raw D-Bus messages, starting with the endianness flag, followed by the message type, etc., but without the authentication handshake before the message sequence */ + /** Raw D-Bus messages, starting with the endianness flag, followed by the message type, etc., but without the + * authentication handshake before the message sequence */ LINKTYPE_DBUS = 231, - /** DVB-CI (DVB Common Interface for communication between a PC Card module and a DVB receiver), with the message format specified by the PCAP format for DVB-CI specification */ + /** DVB-CI (DVB Common Interface for communication between a PC Card module and a DVB receiver), with the + * message format specified by the PCAP format for DVB-CI specification */ LINKTYPE_DVB_CI = 235, /** Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but not the same as, 27.010) */ LINKTYPE_MUX27010 = 236, - /** D_PDUs as described by NATO standard STANAG 5066, starting with the synchronization sequence, and including both header and data CRCs */ + /** D_PDUs as described by NATO standard STANAG 5066, starting with the synchronization sequence, and including + * both header and data CRCs */ LINKTYPE_STANAG_5066_D_PDU = 237, /** Linux netlink NETLINK NFLOG socket log messages */ LINKTYPE_NFLOG = 239, - /** Pseudo-header for Hilscher Gesellschaft für Systemautomation mbH netANALYZER devices, followed by an Ethernet frame, beginning with the MAC header and ending with the FCS */ + /** Pseudo-header for Hilscher Gesellschaft für Systemautomation mbH netANALYZER devices, followed by an + * Ethernet frame, beginning with the MAC header and ending with the FCS */ LINKTYPE_NETANALYZER = 240, - /** Pseudo-header for Hilscher Gesellschaft für Systemautomation mbH netANALYZER devices, followed by an Ethernet frame, beginning with the preamble, SFD, and MAC header, and ending with the FCS */ + /** Pseudo-header for Hilscher Gesellschaft für Systemautomation mbH netANALYZER devices, followed by an + * Ethernet frame, beginning with the preamble, SFD, and MAC header, and ending with the FCS */ LINKTYPE_NETANALYZER_TRANSPARENT = 241, /** IP-over-InfiniBand, as specified by RFC 4391 section 6 */ LINKTYPE_IPOIB = 242, /** MPEG-2 Transport Stream transport packets, as specified by ISO 13818-1/ITU-T Recommendation H.222.0 */ LINKTYPE_MPEG_2_TS = 243, - /** Pseudo-header for ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as used by their ng40 protocol tester */ + /** Pseudo-header for ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as used by their ng40 + * protocol tester */ LINKTYPE_NG40 = 244, - /** Pseudo-header for NFC LLCP packet captures, followed by frame data for the LLCP Protocol as specified by NFCForum-TS-LLCP_1.1 */ + /** Pseudo-header for NFC LLCP packet captures, followed by frame data for the LLCP Protocol as specified by + * NFCForum-TS-LLCP_1.1 */ LINKTYPE_NFC_LLCP = 245, /** Raw InfiniBand frames, starting with the Local Routing Header */ LINKTYPE_INFINIBAND = 247, @@ -231,9 +241,12 @@ namespace pcpp LINKTYPE_ZWAVE_R1_R2 = 261, /** Per Joshua Wright , formats for Z-Wave RF profile R3 captures */ LINKTYPE_ZWAVE_R3 = 262, - /** Formats for WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol common packet structure captures */ + /** Formats for WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol common packet + * structure captures */ LINKTYPE_WATTSTOPPER_DLM = 263, - /** Messages between ISO 14443 contactless smartcards (Proximity Integrated Circuit Card, PICC) and card readers (Proximity Coupling Device, PCD), with the message format specified by the PCAP format for ISO14443 specification */ + /** Messages between ISO 14443 contactless smartcards (Proximity Integrated Circuit Card, PICC) and card readers + * (Proximity Coupling Device, PCD), with the message format specified by the PCAP format for ISO14443 + * specification */ LINKTYPE_ISO_14443 = 264, /** Linux "cooked" capture encapsulation v2 */ LINKTYPE_LINUX_SLL2 = 276, @@ -248,9 +261,9 @@ namespace pcpp /** * @class RawPacket - * This class holds the packet as raw (not parsed) data. The data is held as byte array. In addition to the data itself - * every instance also holds a timestamp representing the time the packet was received by the NIC. - * RawPacket instance isn't read only. The user can change the packet data, add or remove data, etc. + * This class holds the packet as raw (not parsed) data. The data is held as byte array. In addition to the data + * itself every instance also holds a timestamp representing the time the packet was received by the NIC. RawPacket + * instance isn't read only. The user can change the packet data, add or remove data, etc. */ class RawPacket { @@ -264,32 +277,37 @@ namespace pcpp LinkLayerType m_LinkLayerType; void init(bool deleteRawDataAtDestructor = true); void copyDataFrom(const RawPacket& other, bool allocateData = true); + public: /** - * A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually used when packet - * is captured using a packet capturing engine (like libPcap. WinPcap, Npcap, PF_RING, etc.). The capturing engine allocates the raw data - * memory and give the user a pointer to it + a timestamp it has arrived to the device + * A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually used + * when packet is captured using a packet capturing engine (like libPcap. WinPcap, Npcap, PF_RING, etc.). The + * capturing engine allocates the raw data memory and give the user a pointer to it + a timestamp it has arrived + * to the device * @param[in] pRawData A pointer to the raw data * @param[in] rawDataLen The raw data length in bytes * @param[in] timestamp The timestamp packet was received by the NIC (in usec precision) - * @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance is freed or not. If set - * to 'true' than pRawData will be freed when instanced is being freed + * @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance + * is freed or not. If set to 'true' than pRawData will be freed when instanced is being freed * @param[in] layerType The link layer type of this raw packet. The default is Ethernet */ - RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET); + RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, + LinkLayerType layerType = LINKTYPE_ETHERNET); /** - * A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually used when packet - * is captured using a packet capturing engine (like libPcap. WinPcap, Npcap, PF_RING, etc.). The capturing engine allocates the raw data - * memory and give the user a pointer to it + a timestamp it has arrived to the device + * A constructor that receives a pointer to the raw data (allocated elsewhere). This constructor is usually used + * when packet is captured using a packet capturing engine (like libPcap. WinPcap, Npcap, PF_RING, etc.). The + * capturing engine allocates the raw data memory and give the user a pointer to it + a timestamp it has arrived + * to the device * @param[in] pRawData A pointer to the raw data * @param[in] rawDataLen The raw data length in bytes * @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision) - * @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance is freed or not. If set - * to 'true' than pRawData will be freed when instanced is being freed + * @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance + * is freed or not. If set to 'true' than pRawData will be freed when instanced is being freed * @param[in] layerType The link layer type of this raw packet. The default is Ethernet */ - RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET); + RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, + LinkLayerType layerType = LINKTYPE_ETHERNET); /** * A default constructor that initializes class'es attributes to default value: @@ -306,15 +324,16 @@ namespace pcpp virtual ~RawPacket(); /** - * A copy constructor that copies all data from another instance. Notice all raw data is copied (using memcpy), so when the original or - * the other instance are freed, the other won't be affected + * A copy constructor that copies all data from another instance. Notice all raw data is copied (using memcpy), + * so when the original or the other instance are freed, the other won't be affected * @param[in] other The instance to copy from */ RawPacket(const RawPacket& other); /** - * Assignment operator overload for this class. When using this operator on an already initialized RawPacket instance, - * the original raw data is freed first. Then the other instance is copied to this instance, the same way the copy constructor works + * Assignment operator overload for this class. When using this operator on an already initialized RawPacket + * instance, the original raw data is freed first. Then the other instance is copied to this instance, the same + * way the copy constructor works * @todo free raw data only if deleteRawDataAtDestructor was set to 'true' * @param[in] other The instance to copy from */ @@ -323,55 +342,71 @@ namespace pcpp /** * @return RawPacket object type. Each derived class should return a different value */ - virtual uint8_t getObjectType() const { return 0; } + virtual uint8_t getObjectType() const + { + return 0; + } /** - * Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be freed first + * Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be + * freed first * @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 (in usec precision) * @param[in] layerType The link layer type for this raw data - * @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 + * @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 set successfully, false otherwise */ - virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); + virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); /** - * Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be freed first + * Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be + * freed first * @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 (in nsec precision) * @param[in] layerType The link layer type for this raw data - * @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 + * @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 set successfully, false otherwise */ - virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); + virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); /** - * Initialize a raw packet with data. The main difference between this method and setRawData() is that setRawData() - * is meant for replacing the data in an existing raw packet, whereas this method is meant to be used right after - * constructing a raw packet using the default c'tor, before setting any data + * Initialize a raw packet with data. The main difference between this method and setRawData() is that + * setRawData() is meant for replacing the data in an existing raw packet, whereas this method is meant to be + * used right after constructing a raw packet using the default c'tor, before setting any data * @param pRawData A pointer to the new raw data * @param rawDataLen The new raw data length in bytes * @param timestamp The timestamp packet was received by the NIC (in nsec precision) * @param layerType The link layer type for this raw data * @return True if raw data was set successfully, false otherwise */ - bool initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET); + bool initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET); /** * Get raw data pointer * @return A read-only pointer to the raw data */ - const uint8_t* getRawData() const { return m_RawData; } + const uint8_t* getRawData() const + { + return m_RawData; + } /** * Get the link layer type * @return the type of the link layer */ - LinkLayerType getLinkLayerType() const { return m_LinkLayerType; } + LinkLayerType getLinkLayerType() const + { + return m_LinkLayerType; + } /** * This static method validates whether a link type integer value is valid @@ -384,18 +419,27 @@ namespace pcpp * Get raw data length in bytes * @return Raw data length in bytes */ - int getRawDataLen() const { return m_RawDataLen; } + int getRawDataLen() const + { + return m_RawDataLen; + } /** * Get frame length in bytes * @return frame length in bytes */ - int getFrameLength() const { return m_FrameLength; } + int getFrameLength() const + { + return m_FrameLength; + } /** * Get raw data timestamp * @return Raw data timestamp */ - timespec getPacketTimeStamp() const { return m_TimeStamp; } + timespec getPacketTimeStamp() const + { + return m_TimeStamp; + } /** * Set raw packet timestamp with usec precision @@ -413,33 +457,37 @@ namespace pcpp /** * Get an indication whether raw data was already set for this instance. - * @return True if raw data was set for this instance. Raw data can be set using the non-default constructor, using setRawData(), using - * the copy constructor or using the assignment operator. Returns false otherwise, for example: if the instance was created using the - * default constructor or clear() was called + * @return True if raw data was set for this instance. Raw data can be set using the non-default constructor, + * using setRawData(), using the copy constructor or using the assignment operator. Returns false otherwise, for + * example: if the instance was created using the default constructor or clear() was called */ - bool isPacketSet() const { return m_RawPacketSet; } + bool isPacketSet() const + { + return m_RawPacketSet; + } /** - * Clears all members of this instance, meaning setting raw data to NULL, raw data length to 0, etc. Currently raw data is always freed, - * even if deleteRawDataAtDestructor was set to 'false' + * Clears all members of this instance, meaning setting raw data to NULL, raw data length to 0, etc. Currently + * raw data is always freed, even if deleteRawDataAtDestructor was set to 'false' * @todo deleteRawDataAtDestructor was set to 'true', don't free the raw data * @todo set timestamp to a default value as well */ virtual void clear(); /** - * Append data to the end of current data. This method works without allocating more memory, it just uses memcpy() to copy dataToAppend at - * the end of the current data. This means that the method assumes this memory was already allocated by the user. If it isn't the case then - * this method will cause memory corruption + * Append data to the end of current data. This method works without allocating more memory, it just uses + * memcpy() to copy dataToAppend at the end of the current data. This means that the method assumes this memory + * was already allocated by the user. If it isn't the case then this method will cause memory corruption * @param[in] dataToAppend A pointer to the data to append to current raw data * @param[in] dataToAppendLen Length in bytes of dataToAppend */ virtual void appendData(const uint8_t* dataToAppend, size_t dataToAppendLen); /** - * Insert new data at some index of the current data and shift the remaining old data to the end. This method works without allocating more memory, - * it just copies dataToAppend at the relevant index and shifts the remaining data to the end. This means that the method assumes this memory was - * already allocated by the user. If it isn't the case then this method will cause memory corruption + * Insert new data at some index of the current data and shift the remaining old data to the end. This method + * works without allocating more memory, it just copies dataToAppend at the relevant index and shifts the + * remaining data to the end. This means that the method assumes this memory was already allocated by the user. + * If it isn't the case then this method will cause memory corruption * @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 @@ -447,22 +495,26 @@ namespace pcpp virtual 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 + * Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be shifted + * back * @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 atIndex+numOfBytesToRemove is out-of-bounds of the raw data buffer + * @return True if all bytes were removed successfully, or false if atIndex+numOfBytesToRemove is out-of-bounds + * of the raw data buffer */ virtual bool removeData(int atIndex, size_t numOfBytesToRemove); /** - * Re-allocate raw packet buffer meaning add size to it without losing the current packet data. This method allocates the required buffer size as instructed - * by the use and then copies the raw data from the current allocated buffer to the new one. This method can become useful if the user wants to insert or - * append data to the raw data, and the previous allocated buffer is too small, so the user wants to allocate a larger buffer and get RawPacket instance to - * point to it - * @param[in] newBufferLength The new buffer length as required by the user. The method is responsible to allocate the memory + * Re-allocate raw packet buffer meaning add size to it without losing the current packet data. This method + * allocates the required buffer size as instructed by the use and then copies the raw data from the current + * allocated buffer to the new one. This method can become useful if the user wants to insert or append data to + * the raw data, and the previous allocated buffer is too small, so the user wants to allocate a larger buffer + * and get RawPacket instance to point to it + * @param[in] newBufferLength The new buffer length as required by the user. The method is responsible to + * allocate the memory * @return True if data was reallocated successfully, false otherwise */ virtual bool reallocateData(size_t newBufferLength); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/S7CommLayer.h b/Packet++/header/S7CommLayer.h index 8766b95b77..01d96f6f8d 100644 --- a/Packet++/header/S7CommLayer.h +++ b/Packet++/header/S7CommLayer.h @@ -49,23 +49,32 @@ namespace pcpp { friend class S7CommLayer; - public: - S7CommParameter() {} + public: + S7CommParameter() + {} - virtual ~S7CommParameter() {} + virtual ~S7CommParameter() + {} /** * @return The data of the Parameter */ - uint8_t *getData() const { return m_Data; } + uint8_t* getData() const + { + return m_Data; + } /** * @return The length of the Parameter data */ - size_t getDataLength() const { return m_DataLen; } + size_t getDataLength() const + { + return m_DataLen; + } - private: - S7CommParameter(uint8_t *data, size_t dataLen) : m_Data(data), m_DataLen(dataLen) {} - uint8_t *m_Data; + private: + S7CommParameter(uint8_t* data, size_t dataLen) : m_Data(data), m_DataLen(dataLen) + {} + uint8_t* m_Data; size_t m_DataLen; }; /** @@ -85,7 +94,7 @@ namespace pcpp * @param[in] errorCode The value of the error code */ S7CommLayer(uint8_t msgType, uint16_t pduRef, uint16_t paramLength, uint16_t dataLength, uint8_t errorClass = 0, - uint8_t errorCode = 0); + uint8_t errorCode = 0); /** * A constructor that creates the layer from an existing packet raw data @@ -94,8 +103,8 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - S7CommLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) + S7CommLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { m_Protocol = S7COMM; m_Parameter = nullptr; @@ -145,7 +154,7 @@ namespace pcpp /** * @return S7comm parameter */ - const S7CommParameter *getParameter(); + const S7CommParameter* getParameter(); /** * Set the value of the message type @@ -173,17 +182,22 @@ namespace pcpp /** * @return Size of S7CommLayer */ - size_t getHeaderLen() const override { return m_DataLen; } + size_t getHeaderLen() const override + { + return m_DataLen; + } /** * Does nothing for this layer (S7CommLayer is always last) */ - void computeCalculateFields() override {} + void computeCalculateFields() override + {} /** * Does nothing for this layer (S7CommLayer is always last) */ - void parseNextLayer() override {} + void parseNextLayer() override + {} /** * A static method that takes a byte array and detects whether it is a S7COMM @@ -191,27 +205,33 @@ namespace pcpp * @param[in] dataSize The byte array size (in bytes) * @return True if the data looks like a valid S7COMM layer */ - static bool isDataValid(const uint8_t *data, size_t dataSize); + static bool isDataValid(const uint8_t* data, size_t dataSize); std::string toString() const override; - OsiModelLayer getOsiModelLayer() const override { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const override + { + return OsiModelApplicationLayer; + } private: - s7commhdr *getS7commHeader() const { return (s7commhdr *)m_Data; } + s7commhdr* getS7commHeader() const + { + return (s7commhdr*)m_Data; + } - s7comm_ack_data_hdr *getS7commAckDataHeader() const + s7comm_ack_data_hdr* getS7commAckDataHeader() const { if (getS7commHeader()->msgType == 0x03) { - return (s7comm_ack_data_hdr *)m_Data; + return (s7comm_ack_data_hdr*)m_Data; } return nullptr; } size_t getS7commHeaderLength() const; - S7CommParameter *m_Parameter; + S7CommParameter* m_Parameter; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SSHLayer.h b/Packet++/header/SSHLayer.h index 2dfc85905d..811aad089c 100644 --- a/Packet++/header/SSHLayer.h +++ b/Packet++/header/SSHLayer.h @@ -17,25 +17,27 @@ * PcapPlusPlus uses some heuristics to determine the type of the SSH message (which will be covered later). * If it doesn't find a match to one of the other SSH messages, it assumes it is an encrypted SSH message. * - * Following is an overview of the SSH protocol classes currently supported in PcapPlusPlus. They cover the different messages of the SSH protocol: + * Following is an overview of the SSH protocol classes currently supported in PcapPlusPlus. They cover the different + * messages of the SSH protocol: * @verbatim - +----------------------------+ SSH version identification - +---| SSHIdentificationMessage | ===> as described here: - | +----------------------------+ https://tools.ietf.org/html/rfc4253#section-4.2 - | - +------------+ | +----------------------------+ SSH handshake message - | SSHLayer |-------------+---| SSHHandshakeMessage | ===> which is typically one of the messages described here: - | (abstract) | | +----------------------------+ https://tools.ietf.org/html/rfc4253#section-12 - +------------+ | | - | | +----------------------------+ SSH Key Exchange message - | +-----| SSHKeyExchangeInitMessage | ===> as described here: - | +----------------------------+ https://tools.ietf.org/html/rfc4253#section-7 - | - | +----------------------------+ - +---| SSHEncryptedMessage | ===> An encrypted SSH message - +----------------------------+ + +----------------------------+ SSH version identification + +---| SSHIdentificationMessage | ===> as described here: + | +----------------------------+ https://tools.ietf.org/html/rfc4253#section-4.2 + | + +------------+ | +----------------------------+ SSH handshake message + | SSHLayer |---------+---| SSHHandshakeMessage | ===> which is typically one of the messages described here: + | (abstract) | | +----------------------------+ https://tools.ietf.org/html/rfc4253#section-12 + +------------+ | | + | | +----------------------------+ + | +-----| SSHKeyExchangeInitMessage | ===> SSH Key Exchange message + | +----------------------------+ as described here: + | https://tools.ietf.org/html/rfc4253#section-7 + | + | +----------------------------+ + +---| SSHEncryptedMessage | ===> An encrypted SSH message + +----------------------------+ @endverbatim @@ -43,8 +45,8 @@ * 1. If the data starts with the characters "SSH-" and ends with "\n" (or "\r\n") it's assumed the message is of type * pcpp#SSHIdentificationMessage * 2. Try to determine if this is a non-encrypted SSH handshake message: - * - Look at the first 4 bytes of the data which may contain the packet length and see if the value is smaller of equal - * than the entire layer length + * - Look at the first 4 bytes of the data which may contain the packet length and see if the value is smaller of + * equal than the entire layer length. * - The next byte contains the padding length, check if it's smaller or equal than the packet length * - The next byte contains the message type, check if the value is a valid message type as described in: * @@ -91,40 +93,50 @@ namespace pcpp * @return Currently the implementation is very simple and returns "true" if either src or dst ports * are equal to 22, "false" otherwise */ - static bool isSSHPort(uint16_t portSrc, uint16_t portDst) { return portSrc == 22 || portDst == 22; } + static bool isSSHPort(uint16_t portSrc, uint16_t portDst) + { + return portSrc == 22 || portDst == 22; + } // implement abstract methods /** - * Several SSH records can reside in a single packets. This method examins the remaining data and creates additional - * SSH records if applicable + * Several SSH records can reside in a single packets. This method examins the remaining data and creates + * additional SSH records if applicable */ void parseNextLayer(); /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } protected: // protected c'tor, this class cannot be instantiated - SSHLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = SSH; } + SSHLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = SSH; + } private: // this layer supports only parsing SSHLayer(); }; - - /** * @class SSHIdentificationMessage - * A class that represents SSH identification message as described in RFC 4253: + * A class that represents SSH identification message as described in RFC 4253: + * * - * The message content is typically a string that contains the protocol version, software version and a few more details. - * This string can be retrieved using the getIdentificationMessage() method + * The message content is typically a string that contains the protocol version, software version and a few more + * details. This string can be retrieved using the getIdentificationMessage() method */ class SSHIdentificationMessage : public SSHLayer { @@ -135,9 +147,9 @@ namespace pcpp std::string getIdentificationMessage(); /** - * A static method that takes raw data and tries to parse it as an SSH identification message using the heuristics described - * in the SSHLayer.h file description. It returns a SSHIdentificationMessage instance if such a message can be identified or NULL - * otherwise. + * A static method that takes raw data and tries to parse it as an SSH identification message using the + * heuristics described in the SSHLayer.h file description. It returns a SSHIdentificationMessage instance if + * such a message can be identified or NULL otherwise. * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer @@ -151,7 +163,10 @@ namespace pcpp /** * @return The size of the identification message */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } std::string toString() const; @@ -160,11 +175,11 @@ namespace pcpp SSHIdentificationMessage(); // private c'tor, this class cannot be instantiated - SSHIdentificationMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {} - + SSHIdentificationMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SSHLayer(data, dataLen, prevLayer, packet) + {} }; - /** * @class SSHHandshakeMessage * A class representing all of the non-encrypted SSH handshake messages. @@ -178,11 +193,13 @@ namespace pcpp +---------------------------------------+---------+---------+----------- ---------+ @endverbatim * - * The first 4 bytes hold the packet length, followed by 1 byte that holds the padding length (which comes at the end of the message), - * then 1 byte that holds the message type (which can be of type SSHHandshakeMessage#SSHHandshakeMessageType) and then the message content. - * At the end of the content there is typically padding. + * The first 4 bytes hold the packet length, followed by 1 byte that holds the padding length (which comes at the + * end of the message), then 1 byte that holds the message type (which can be of type + * SSHHandshakeMessage#SSHHandshakeMessageType) and then the message content. At the end of the content there is + * typically padding. * - * This class provides access to all of these values. The message content itself is not parse with the exception of SSHKeyExchangeInitMessage + * This class provides access to all of these values. The message content itself is not parse with the exception of + * SSHKeyExchangeInitMessage * which inherits from this class and provides parsing of the Key Exchange Init message. */ class SSHHandshakeMessage : public SSHLayer @@ -261,34 +278,37 @@ namespace pcpp std::string toString() const; protected: - +#pragma pack(push, 1) /** * An internal struct representing the SSH handshake message header */ - #pragma pack(push, 1) struct ssh_message_base { uint32_t packetLength; uint8_t paddingLength; uint8_t messageCode; }; - #pragma pack(pop) +#pragma pack(pop) // this layer supports only parsing SSHHandshakeMessage(); // private c'tor, this class cannot be instantiated - SSHHandshakeMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {} + SSHHandshakeMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SSHLayer(data, dataLen, prevLayer, packet) + {} - ssh_message_base* getMsgBaseHeader() const { return (ssh_message_base*)m_Data; } + ssh_message_base* getMsgBaseHeader() const + { + return (ssh_message_base*)m_Data; + } }; - /** * @class SSHKeyExchangeInitMessage * A class representing the SSH Key Exchange Init message. This is a non-encrypted message that contains information - * about the algorithms used for key exchange, encryption, MAC and compression. This class provides methods to access - * these details + * about the algorithms used for key exchange, encryption, MAC and compression. This class provides methods to + * access these details */ class SSHKeyExchangeInitMessage : public SSHHandshakeMessage { @@ -296,7 +316,7 @@ namespace pcpp /** * A c'tor for this class that accepts raw message data. Please avoid using it as it's used internally * when parsing SSH handshake messages in SSHHandshakeMessage#tryParse() - * @param[in] data A pointer to the raw data + * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in @@ -323,61 +343,91 @@ namespace pcpp * @return A comma-separated list of the key exchange algorithms used in this session. * Can be empty if the value is missing or the message is malformed */ - std::string getKeyExchangeAlgorithms() { return getFieldValue(0); } + std::string getKeyExchangeAlgorithms() + { + return getFieldValue(0); + } /** * @return A comma-separated list of the algorithms supported for the server host key. * Can be empty if the value is missing or the message is malformed */ - std::string getServerHostKeyAlgorithms() { return getFieldValue(1); } + std::string getServerHostKeyAlgorithms() + { + return getFieldValue(1); + } /** * @return A comma-separated list of acceptable symmetric encryption algorithms (also known as ciphers) * from the client to the server. Can be empty if the value is missing or the message is malformed */ - std::string getEncryptionAlgorithmsClientToServer() { return getFieldValue(2); } + std::string getEncryptionAlgorithmsClientToServer() + { + return getFieldValue(2); + } /** * @return A comma-separated list of acceptable symmetric encryption algorithms (also known as ciphers) * from the server to the client. Can be empty if the value is missing or the message is malformed */ - std::string getEncryptionAlgorithmsServerToClient() { return getFieldValue(3); } + std::string getEncryptionAlgorithmsServerToClient() + { + return getFieldValue(3); + } /** * @return A comma-separated list of acceptable MAC algorithms from the client to the server. * Can be empty if the value is missing or the message is malformed */ - std::string getMacAlgorithmsClientToServer() { return getFieldValue(4); } + std::string getMacAlgorithmsClientToServer() + { + return getFieldValue(4); + } /** * @return A comma-separated list of acceptable MAC algorithms from the server to the client. * Can be empty if the value is missing or the message is malformed */ - std::string getMacAlgorithmsServerToClient() { return getFieldValue(5); } + std::string getMacAlgorithmsServerToClient() + { + return getFieldValue(5); + } /** * @return A comma-separated list of acceptable compression algorithms from the client to the server. * Can be empty if the value is missing or the message is malformed */ - std::string getCompressionAlgorithmsClientToServer() { return getFieldValue(6); } + std::string getCompressionAlgorithmsClientToServer() + { + return getFieldValue(6); + } /** * @return A comma-separated list of acceptable compression algorithms from the server to the client. * Can be empty if the value is missing or the message is malformed */ - std::string getCompressionAlgorithmsServerToClient() { return getFieldValue(7); } + std::string getCompressionAlgorithmsServerToClient() + { + return getFieldValue(7); + } /** * @return A comma-separated list of language tags from the client to the server. * Can be empty if the value is missing or the message is malformed */ - std::string getLanguagesClientToServer() { return getFieldValue(8); } + std::string getLanguagesClientToServer() + { + return getFieldValue(8); + } /** * @return A comma-separated list of language tags from the server to the client. * Can be empty if the value is missing or the message is malformed */ - std::string getLanguagesServerToClient() { return getFieldValue(9); } + std::string getLanguagesServerToClient() + { + return getFieldValue(9); + } /** * @return Indicates whether a guessed key exchange packet follows. If a @@ -395,33 +445,37 @@ namespace pcpp std::string getFieldValue(int fieldOffsetIndex); }; - /** * @class SSHEncryptedMessage - * A class representing an SSH encrypted message. In such messages there is very little information to extract from the packet, - * hence this class doesn't expose any methods or getters, other than the ones inherited from parent classes. + * A class representing an SSH encrypted message. In such messages there is very little information to extract from + * the packet, hence this class doesn't expose any methods or getters, other than the ones inherited from parent + * classes. * - * It is assumed that any SSH message which does not fit to any of the other SSH message types, according to the heuristics described in - * the SSHLayer.h file description, is considered as an encrypted message. + * It is assumed that any SSH message which does not fit to any of the other SSH message types, according to the + * heuristics described in the SSHLayer.h file description, is considered as an encrypted message. */ class SSHEncryptedMessage : public SSHLayer { public: - /** * A c'tor for this class that accepts raw message data. Please avoid using it as it's used internally * when parsing SSH messages in SSHLayer#createSSHMessage() */ - SSHEncryptedMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHLayer(data, dataLen, prevLayer, packet) {} + SSHEncryptedMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SSHLayer(data, dataLen, prevLayer, packet) + {} // implement abstract methods /** * @return The size of the message which is equal to the size of the layer */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } std::string toString() const; }; -} +} // namespace pcpp diff --git a/Packet++/header/SSLCommon.h b/Packet++/header/SSLCommon.h index aefd14dcf8..19285f2520 100644 --- a/Packet++/header/SSLCommon.h +++ b/Packet++/header/SSLCommon.h @@ -31,7 +31,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @struct ssl_tls_handshake_layer * The common part of all SSL/TLS handshake message types @@ -48,7 +47,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @struct ssl_tls_client_server_hello * The common header part of client-hello and server-hello handshake messages @@ -63,7 +61,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @struct ssl_tls_change_cipher_spec * SSL/TLS change-cipher-spec message structure @@ -76,7 +73,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @struct ssl_tls_alert * SSL/TLS alert message structure @@ -91,7 +87,6 @@ namespace pcpp }; #pragma pack(pop) - /** * SSL/TLS message types */ @@ -100,14 +95,13 @@ namespace pcpp /** Change-cipher-spec message */ SSL_CHANGE_CIPHER_SPEC = 20, /** SSL alert message */ - SSL_ALERT = 21, + SSL_ALERT = 21, /** SSL handshake message */ - SSL_HANDSHAKE = 22, + SSL_HANDSHAKE = 22, /** SSL data message */ - SSL_APPLICATION_DATA = 23 + SSL_APPLICATION_DATA = 23 }; - /** * @class SSLVersion * A wrapper class for SSL/TLS versions. The SSL/TLS version is typically represented by a 2-byte number, @@ -123,9 +117,9 @@ namespace pcpp enum SSLVersionEnum { /** SSL 2.0 */ - SSL2 = 0x0200, + SSL2 = 0x0200, /** SSL 3.0 */ - SSL3 = 0x0300, + SSL3 = 0x0300, /** TLS 1.0 */ TLS1_0 = 0x0301, /** TLS 1.1 */ @@ -177,28 +171,34 @@ namespace pcpp * @param[in] sslVersionValue The numeric value representing this SSL/TLS version. For example: * for TLS 1.2 this would be 0x0303. */ - explicit SSLVersion(uint16_t sslVersionValue) { m_SSLVersionValue = sslVersionValue; } + explicit SSLVersion(uint16_t sslVersionValue) + { + m_SSLVersionValue = sslVersionValue; + } /** * @return An enum value of type SSLVersion::SSLVersionEnum representing the SSL/TLS version. * If the numeric value is an invalid SSL/TLS version SSLVersion::Unknown will be returned. - * @param[in] countTlsDraftsAs1_3 A flag indicating whether to return the enum value SSLVersion::TLS1_3 for all TLS 1.3 drafts. If set to "true" - * all TLS 1.3 draft values (i.e 0x7f0e - 0x7f1c, 0xfb17, 0xfb1a) will return SSLVersion::TLS1_3, otherwise the corresponding enum values will be - * returned. The default value is "false". + * @param[in] countTlsDraftsAs1_3 A flag indicating whether to return the enum value SSLVersion::TLS1_3 for all + * TLS 1.3 drafts. If set to "true" all TLS 1.3 draft values (i.e 0x7f0e - 0x7f1c, 0xfb17, 0xfb1a) will return + * SSLVersion::TLS1_3, otherwise the corresponding enum values will be returned. The default value is "false". */ SSLVersionEnum asEnum(bool countTlsDraftsAs1_3 = false); /** * @return The numeric value of the SSL/TLs version */ - uint16_t asUInt() { return m_SSLVersionValue; } + uint16_t asUInt() + { + return m_SSLVersionValue; + } /** - * @return A string representation of the SSL/TLS version. For example: for TLS 1.2 the string "TLS 1.2" is returned. - * If the numeric value is an invalid SSL/TLS version the string "Unknown" will be returned. - * @param[in] countTlsDraftsAs1_3 A flag indicating whether to return the string value "TLS 1.3" for all TLS 1.3 drafts. If set to "true" - * all TLS 1.3 draft values (i.e 0x7f0e - 0x7f1c, 0xfb17, 0xfb1a) will return "TLS 1.3", otherwise the corresponding string values will be - * returned. The default value is "false". + * @return A string representation of the SSL/TLS version. For example: for TLS 1.2 the string "TLS 1.2" is + * returned. If the numeric value is an invalid SSL/TLS version the string "Unknown" will be returned. + * @param[in] countTlsDraftsAs1_3 A flag indicating whether to return the string value "TLS 1.3" for all TLS 1.3 + * drafts. If set to "true" all TLS 1.3 draft values (i.e 0x7f0e - 0x7f1c, 0xfb17, 0xfb1a) will return + * "TLS 1.3", otherwise the corresponding string values will be returned. The default value is "false". */ std::string toString(bool countTlsDraftsAs1_3 = false); @@ -215,35 +215,35 @@ namespace pcpp enum SSLHandshakeType { /** Hello-request message type */ - SSL_HELLO_REQUEST = 0, + SSL_HELLO_REQUEST = 0, /** Client-hello message type */ - SSL_CLIENT_HELLO = 1, + SSL_CLIENT_HELLO = 1, /** Server-hello message type */ - SSL_SERVER_HELLO = 2, + SSL_SERVER_HELLO = 2, /** New-session-ticket message type */ - SSL_NEW_SESSION_TICKET = 4, + SSL_NEW_SESSION_TICKET = 4, /** End-of-early-data message type (TLS 1.3) */ - SSL_END_OF_EARLY_DATE = 5, + SSL_END_OF_EARLY_DATE = 5, /** Encrypted-extensions message type (TLS 1.3) */ SSL_ENCRYPTED_EXTENSIONS = 8, /** Certificate message type */ - SSL_CERTIFICATE = 11, + SSL_CERTIFICATE = 11, /** Server-key-exchange message type */ - SSL_SERVER_KEY_EXCHANGE = 12, + SSL_SERVER_KEY_EXCHANGE = 12, /** Certificate-request message type */ - SSL_CERTIFICATE_REQUEST = 13, + SSL_CERTIFICATE_REQUEST = 13, /** Server-hello-done message type */ - SSL_SERVER_DONE = 14, + SSL_SERVER_DONE = 14, /** Certificate-verify message type */ - SSL_CERTIFICATE_VERIFY = 15, + SSL_CERTIFICATE_VERIFY = 15, /** Client-key-exchange message type */ - SSL_CLIENT_KEY_EXCHANGE = 16, + SSL_CLIENT_KEY_EXCHANGE = 16, /** Finish message type */ - SSL_FINISHED = 20, + SSL_FINISHED = 20, /** Key-update message type (TLS 1.3) */ - SSL_KEY_UPDATE = 24, + SSL_KEY_UPDATE = 24, /** Unknown SSL handshake message */ - SSL_HANDSHAKE_UNKNOWN = 255 + SSL_HANDSHAKE_UNKNOWN = 255 }; /** @@ -252,11 +252,11 @@ namespace pcpp enum SSLAlertLevel { /** Warning level alert */ - SSL_ALERT_LEVEL_WARNING = 1, + SSL_ALERT_LEVEL_WARNING = 1, /** Fatal level alert */ - SSL_ALERT_LEVEL_FATAL = 2, + SSL_ALERT_LEVEL_FATAL = 2, /** For encrypted alerts the level is unknown so this type will be returned */ - SSL_ALERT_LEVEL_ENCRYPTED = 255 + SSL_ALERT_LEVEL_ENCRYPTED = 255 }; /** @@ -265,57 +265,57 @@ namespace pcpp enum SSLAlertDescription { /** Close notify alert */ - SSL_ALERT_CLOSE_NOTIFY = 0, + SSL_ALERT_CLOSE_NOTIFY = 0, /** Unexpected message alert */ - SSL_ALERT_UNEXPECTED_MESSAGE = 10, + SSL_ALERT_UNEXPECTED_MESSAGE = 10, /** Bad record MAC alert */ - SSL_ALERT_BAD_RECORD_MAC = 20, + SSL_ALERT_BAD_RECORD_MAC = 20, /** Decryption failed alert */ - SSL_ALERT_DECRYPTION_FAILED = 21, + SSL_ALERT_DECRYPTION_FAILED = 21, /** */ - SSL_ALERT_RECORD_OVERFLOW = 22, + SSL_ALERT_RECORD_OVERFLOW = 22, /** Decompression failure alert */ - SSL_ALERT_DECOMPRESSION_FAILURE = 30, + SSL_ALERT_DECOMPRESSION_FAILURE = 30, /** Handshake failure alert */ - SSL_ALERT_HANDSHAKE_FAILURE = 40, + SSL_ALERT_HANDSHAKE_FAILURE = 40, /** No certificate alert */ - SSL_ALERT_NO_CERTIFICATE = 41, + SSL_ALERT_NO_CERTIFICATE = 41, /** Bad certificate alert */ - SSL_ALERT_BAD_CERTIFICATE = 42, + SSL_ALERT_BAD_CERTIFICATE = 42, /** Unsupported certificate */ SSL_ALERT_UNSUPPORTED_CERTIFICATE = 43, /** Certificate revoked alert */ - SSL_ALERT_CERTIFICATE_REVOKED = 44, + SSL_ALERT_CERTIFICATE_REVOKED = 44, /** Certificate expired alert */ - SSL_ALERT_CERTIFICATE_EXPIRED = 45, + SSL_ALERT_CERTIFICATE_EXPIRED = 45, /** Certificate unknown alert */ - SSL_ALERT_CERTIFICATE_UNKNOWN = 46, + SSL_ALERT_CERTIFICATE_UNKNOWN = 46, /** Illegal parameter alert */ - SSL_ALERT_ILLEGAL_PARAMETER = 47, + SSL_ALERT_ILLEGAL_PARAMETER = 47, /** Unknown CA alert */ - SSL_ALERT_UNKNOWN_CA = 48, + SSL_ALERT_UNKNOWN_CA = 48, /** Access denied alert */ - SSL_ALERT_ACCESS_DENIED = 49, + SSL_ALERT_ACCESS_DENIED = 49, /** Decode error alert */ - SSL_ALERT_DECODE_ERROR = 50, + SSL_ALERT_DECODE_ERROR = 50, /** Decrypt error alert */ - SSL_ALERT_DECRYPT_ERROR = 51, + SSL_ALERT_DECRYPT_ERROR = 51, /** Export restriction alert */ - SSL_ALERT_EXPORT_RESTRICTION = 60, + SSL_ALERT_EXPORT_RESTRICTION = 60, /** Protocol version alert */ - SSL_ALERT_PROTOCOL_VERSION = 70, + SSL_ALERT_PROTOCOL_VERSION = 70, /** Insufficient security alert */ - SSL_ALERT_INSUFFICIENT_SECURITY = 71, + SSL_ALERT_INSUFFICIENT_SECURITY = 71, /** Internal error alert */ - SSL_ALERT_INTERNAL_ERROR = 80, + SSL_ALERT_INTERNAL_ERROR = 80, /** User cancelled alert */ - SSL_ALERT_USER_CANCELLED = 90, + SSL_ALERT_USER_CANCELLED = 90, /** No negotiation alert */ - SSL_ALERT_NO_RENEGOTIATION = 100, + SSL_ALERT_NO_RENEGOTIATION = 100, /** Unsupported extension alert */ - SSL_ALERT_UNSUPPORTED_EXTENSION = 110, + SSL_ALERT_UNSUPPORTED_EXTENSION = 110, /** Encrtpyed alert (cannot determine its type) */ - SSL_ALERT_ENCRYPTED = 255 + SSL_ALERT_ENCRYPTED = 255 }; /** @@ -606,4 +606,4 @@ namespace pcpp SSL_CCT_UNKNOWN }; -} //namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SSLHandshake.h b/Packet++/header/SSLHandshake.h index e26f234e59..b68154bdc7 100644 --- a/Packet++/header/SSLHandshake.h +++ b/Packet++/header/SSLHandshake.h @@ -16,1126 +16,1163 @@ namespace pcpp { - -/** - * @class SSLCipherSuite - * Represents a cipher-suite and enables access all information about it such as all algorithms it encapsulates, - * its ID (as appears in the client-hello or server-hello messages), - * its name (e.g "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA") etc. PcapPlusPlus contains static instances of this type - * for all known cipher-suites and enables access to them through name or ID (see getCipherSuiteByID() and - * getCipherSuiteByName() ). List of cipher-suite was taken from here: - * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml - */ -class SSLCipherSuite -{ -public: - /** - * A c'tor for this class, should never be used by a user - * @param[in] id Cipher-suite ID - * @param[in] keyExAlg Key-exchange algorithm used in this cipher-suite - * @param[in] authAlg Authentication algorithm used in this cipher-suite - * @param[in] symKeyAlg Symmetric key algorithm used in this cipher-suite - * @param[in] MACAlg MAC algorithm used in this cipher-suite - * @param[in] name String representation of this cipher-suite - */ - SSLCipherSuite(uint16_t id, SSLKeyExchangeAlgorithm keyExAlg, - SSLAuthenticationAlgorithm authAlg, - SSLSymetricEncryptionAlgorithm symKeyAlg, - SSLHashingAlgorithm MACAlg, - const char* name) - : m_Id(id), m_KeyExAlg(keyExAlg), m_AuthAlg(authAlg), m_SymKeyAlg(symKeyAlg), m_MACAlg(MACAlg), m_Name(name) {} - - /** - * @return Cipher-suite ID - */ - uint16_t getID() const { return m_Id; } - - /** - * @return String representation of this cipher-suite - */ - std::string asString() const { return m_Name; } - - /** - * @return Key-exchange algorithm used in this cipher-suite - */ - SSLKeyExchangeAlgorithm getKeyExchangeAlg() const { return m_KeyExAlg; } - - /** - * @return Authentication algorithm used in this cipher-suite - */ - SSLAuthenticationAlgorithm getAuthAlg() const { return m_AuthAlg; } - - /** - * @return Symmetric key algorithm used in this cipher-suite - */ - SSLSymetricEncryptionAlgorithm getSymKeyAlg() const { return m_SymKeyAlg; } - - /** - * @return MAC algorithm used in this cipher-suite - */ - SSLHashingAlgorithm getMACAlg() const { return m_MACAlg; } - - /** - * A static method that returns a cipher-suite instance by ID - * @param[in] id Cipher-suite ID - * @return A cipher-suite instance matching this ID or NULL if ID not found - */ - static SSLCipherSuite* getCipherSuiteByID(uint16_t id); - - /** - * A static method that returns a cipher-suite instance by name - * @param[in] name Cipher-suite name (e.g "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA") - * @return A cipher-suite instance matching this name or NULL if name not found - */ - static SSLCipherSuite* getCipherSuiteByName(std::string name); - -private: - uint16_t m_Id; - SSLKeyExchangeAlgorithm m_KeyExAlg; - SSLAuthenticationAlgorithm m_AuthAlg; - SSLSymetricEncryptionAlgorithm m_SymKeyAlg; - SSLHashingAlgorithm m_MACAlg; - std::string m_Name; -}; - - -/** - * @class SSLExtension - * Represents a SSL/TLS extension. This is a base class that can represent any type of extension. Inherited classes may - * contain parsing logic for specific extensions. This class provides capabilities such as getting the extension type, - * length and viewing the extension data as raw (byte array) - */ -class SSLExtension -{ -public: /** - * C'tor for this class - * @param[in] data The raw data for the extension + * @class SSLCipherSuite + * Represents a cipher-suite and enables access all information about it such as all algorithms it encapsulates, + * its ID (as appears in the client-hello or server-hello messages), + * its name (e.g "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA") etc. PcapPlusPlus contains static instances of this type + * for all known cipher-suites and enables access to them through name or ID (see getCipherSuiteByID() and + * getCipherSuiteByName() ). List of cipher-suite was taken from here: + * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml */ - explicit SSLExtension(uint8_t* data); + class SSLCipherSuite + { + public: + /** + * A c'tor for this class, should never be used by a user + * @param[in] id Cipher-suite ID + * @param[in] keyExAlg Key-exchange algorithm used in this cipher-suite + * @param[in] authAlg Authentication algorithm used in this cipher-suite + * @param[in] symKeyAlg Symmetric key algorithm used in this cipher-suite + * @param[in] MACAlg MAC algorithm used in this cipher-suite + * @param[in] name String representation of this cipher-suite + */ + SSLCipherSuite(uint16_t id, SSLKeyExchangeAlgorithm keyExAlg, SSLAuthenticationAlgorithm authAlg, + SSLSymetricEncryptionAlgorithm symKeyAlg, SSLHashingAlgorithm MACAlg, const char* name) + : m_Id(id), m_KeyExAlg(keyExAlg), m_AuthAlg(authAlg), m_SymKeyAlg(symKeyAlg), m_MACAlg(MACAlg), m_Name(name) + {} - virtual ~SSLExtension() { } + /** + * @return Cipher-suite ID + */ + uint16_t getID() const + { + return m_Id; + } - /** - * @return The type of the extension as enum - */ - SSLExtensionType getType() const; + /** + * @return String representation of this cipher-suite + */ + std::string asString() const + { + return m_Name; + } - /** - * @return The type of the extension as a numeric value - */ - uint16_t getTypeAsInt() const; + /** + * @return Key-exchange algorithm used in this cipher-suite + */ + SSLKeyExchangeAlgorithm getKeyExchangeAlg() const + { + return m_KeyExAlg; + } - /** - * @return The length of the extension data in bytes (not including the type and length fields) - */ - uint16_t getLength() const; + /** + * @return Authentication algorithm used in this cipher-suite + */ + SSLAuthenticationAlgorithm getAuthAlg() const + { + return m_AuthAlg; + } - /** - * @return The total length of the extension, including type and length fields and the extension data field - */ - uint16_t getTotalLength() const; + /** + * @return Symmetric key algorithm used in this cipher-suite + */ + SSLSymetricEncryptionAlgorithm getSymKeyAlg() const + { + return m_SymKeyAlg; + } - /** - * @return A pointer to the raw data of the extension - */ - uint8_t* getData() const; + /** + * @return MAC algorithm used in this cipher-suite + */ + SSLHashingAlgorithm getMACAlg() const + { + return m_MACAlg; + } -protected: + /** + * A static method that returns a cipher-suite instance by ID + * @param[in] id Cipher-suite ID + * @return A cipher-suite instance matching this ID or NULL if ID not found + */ + static SSLCipherSuite* getCipherSuiteByID(uint16_t id); - /** - * @struct SSLExtensionStruct - * Represents the common fields of the extension - */ - struct SSLExtensionStruct - { - /** Extension type */ - uint16_t extensionType; - /** Extension length */ - uint16_t extensionDataLength; - /** Extension data as raw (byte array) */ - uint8_t extensionData[]; + /** + * A static method that returns a cipher-suite instance by name + * @param[in] name Cipher-suite name (e.g "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA") + * @return A cipher-suite instance matching this name or NULL if name not found + */ + static SSLCipherSuite* getCipherSuiteByName(std::string name); + + private: + uint16_t m_Id; + SSLKeyExchangeAlgorithm m_KeyExAlg; + SSLAuthenticationAlgorithm m_AuthAlg; + SSLSymetricEncryptionAlgorithm m_SymKeyAlg; + SSLHashingAlgorithm m_MACAlg; + std::string m_Name; }; - uint8_t* m_RawData; - - SSLExtensionStruct* getExtensionStruct() const { return (SSLExtensionStruct*)m_RawData; } -}; - - -/** - * @class SSLServerNameIndicationExtension - * Represents SSL/TLS Server Name Indication extension. Inherits from SSLExtension and add parsing of the hostname - * written in the extension data - */ -class SSLServerNameIndicationExtension : public SSLExtension -{ -public: - /** - * C'tor for this class - * @param[in] data The raw data for the extension - */ - explicit SSLServerNameIndicationExtension(uint8_t* data) : SSLExtension(data) {} - - /** - * @return The hostname written in the extension data - */ - std::string getHostName() const; -}; - - -/** - * @class SSLSupportedVersionsExtension - * Represents TLS Supported Versions extension. Inherits from SSLExtension and adds parsing of the list - * of supported versions mentioned in the extension data - */ -class SSLSupportedVersionsExtension : public SSLExtension -{ -public: - /** - * C'tor for this class - * @param[in] data The raw data for the extension - */ - explicit SSLSupportedVersionsExtension(uint8_t* data) : SSLExtension(data) {} - /** - * @return The list of supported versions mentioned in the extension data + * @class SSLExtension + * Represents a SSL/TLS extension. This is a base class that can represent any type of extension. Inherited classes + * may contain parsing logic for specific extensions. This class provides capabilities such as getting the extension + * type, length and viewing the extension data as raw (byte array) */ - std::vector getSupportedVersions() const; -}; - - -/** - * @class TLSSupportedGroupsExtension - * Represents TLS Supported Groups extension. Inherits from SSLExtension and adds parsing of the - * supported groups (Elliptic Curves) mentioned in the extension data - */ -class TLSSupportedGroupsExtension : public SSLExtension -{ + class SSLExtension + { public: - /** - * C'tor for this class - * @param[in] data The raw data for the extension - */ - explicit TLSSupportedGroupsExtension(uint8_t* data) : SSLExtension(data) {} - - /** - * @return A vector of the supported groups (also known as "Elliptic Curves") - */ - std::vector getSupportedGroups() const; -}; - + /** + * C'tor for this class + * @param[in] data The raw data for the extension + */ + explicit SSLExtension(uint8_t* data); -/** - * @class TLSECPointFormatExtension - * Represents TLS EC (Elliptic Curves) Point Format extension. Inherits from SSLExtension and adds parsing of the - * EC point formats mentioned in the extension data - */ -class TLSECPointFormatExtension : public SSLExtension -{ - public: - /** - * C'tor for this class - * @param[in] data The raw data for the extension - */ - explicit TLSECPointFormatExtension(uint8_t* data) : SSLExtension(data) {} + virtual ~SSLExtension() + {} - /** - * @return A vector of the elliptic curves point formats - */ - std::vector getECPointFormatList() const; -}; + /** + * @return The type of the extension as enum + */ + SSLExtensionType getType() const; + /** + * @return The type of the extension as a numeric value + */ + uint16_t getTypeAsInt() const; -/** - * @class SSLx509Certificate - * Represents a x509v3 certificate. the SSLCertificateMessage class returns an instance of this class as the certificate. - * Currently this class doesn't do much as it doesn't parse the certificate. It only acts as container to the raw data - * and returns general info as data as raw, length, etc. In the future I may add full parsing of the certificate - */ -class SSLx509Certificate -{ -public: + /** + * @return The length of the extension data in bytes (not including the type and length fields) + */ + uint16_t getLength() const; - /** - * C'tor for this class - * @param[in] data The raw data of the certificate - * @param[in] dataLen The length in bytes of the raw data - * @param[in] allDataExists Certificate messages usually spread on more than 1 packet. So a certificate is likely - * to split between 2 packets or more. This field indicates whether the raw data contains all ceritificate data - * of just a part of it - */ - SSLx509Certificate(uint8_t* data, size_t dataLen, bool allDataExists) - : m_Data(data), m_DataLen(dataLen), m_AllDataExists(allDataExists) {} + /** + * @return The total length of the extension, including type and length fields and the extension data field + */ + uint16_t getTotalLength() const; - /** - * @return A pointer to the raw data - */ - uint8_t* getData() const { return m_Data; } + /** + * @return A pointer to the raw data of the extension + */ + uint8_t* getData() const; - /** - * @return Raw data length - */ - size_t getDataLength() const { return m_DataLen; } + protected: + /** + * @struct SSLExtensionStruct + * Represents the common fields of the extension + */ + struct SSLExtensionStruct + { + /** Extension type */ + uint16_t extensionType; + /** Extension length */ + uint16_t extensionDataLength; + /** Extension data as raw (byte array) */ + uint8_t extensionData[]; + }; + + uint8_t* m_RawData; + + SSLExtensionStruct* getExtensionStruct() const + { + return (SSLExtensionStruct*)m_RawData; + } + }; /** - * Certificate messages usually spread on more than 1 packet. So a certificate is likely to split between 2 packets - * or more. This method provides an indication whether all certificate data exists or only part of it - * @return True if this data contains all certificate data, false otherwise + * @class SSLServerNameIndicationExtension + * Represents SSL/TLS Server Name Indication extension. Inherits from SSLExtension and add parsing of the hostname + * written in the extension data */ - bool allDataExists() const { return m_AllDataExists; } - -private: - uint8_t* m_Data; - size_t m_DataLen; - bool m_AllDataExists; -}; - - -class SSLHandshakeLayer; - - -/** - * @class SSLHandshakeMessage - * A base class for SSL/TLS handshake messages. This is an abstract class and cannot be instantiated. SSL/TLS handshake - * messages are contained in SSLHandshakeLayer, meaning a SSLHandshakeLayer instance can contain one or more SSLHandshakeMessage - * instances. For example: one SSLHandshakeLayer may contain a server-hello, certificate, - * server-key-exchange, and server-hello-done messages (although it's not such a common case, most handshake layers - * contain 1 handshake message only) - */ -class SSLHandshakeMessage -{ -public: - - virtual ~SSLHandshakeMessage() {} + class SSLServerNameIndicationExtension : public SSLExtension + { + public: + /** + * C'tor for this class + * @param[in] data The raw data for the extension + */ + explicit SSLServerNameIndicationExtension(uint8_t* data) : SSLExtension(data) + {} - /** - * A factory method for creating instances of handshake messages from raw data - * @param[in] data The raw data containing 1 handshake message - * @param[in] dataLen Raw data length in bytes - * @param[in] container A pointer to the SSLHandshakeLayer instance which will contain the created message. - * This parameter is required because the handshake message includes a pointer to its container - */ - static SSLHandshakeMessage* createHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); + /** + * @return The hostname written in the extension data + */ + std::string getHostName() const; + }; /** - * @return The handshake message type + * @class SSLSupportedVersionsExtension + * Represents TLS Supported Versions extension. Inherits from SSLExtension and adds parsing of the list + * of supported versions mentioned in the extension data */ - virtual SSLHandshakeType getHandshakeType() const; + class SSLSupportedVersionsExtension : public SSLExtension + { + public: + /** + * C'tor for this class + * @param[in] data The raw data for the extension + */ + explicit SSLSupportedVersionsExtension(uint8_t* data) : SSLExtension(data) + {} - /** - * @return The handshake message length in bytes. Notice that sometimes the handshake message is divided between - * several packets, in this case this method will return the length of part of the message in the current packet - */ - virtual size_t getMessageLength() const; + /** + * @return The list of supported versions mentioned in the extension data + */ + std::vector getSupportedVersions() const; + }; /** - * @return True if current packet contains the entire message or false otherwise. This method is important - * because sometimes handshake messages are divided in consequent packets (happens a lot in certificate messages - * which usually contain several KB of data which is larger than standard packet size, so the message is divided between - * several packets) + * @class TLSSupportedGroupsExtension + * Represents TLS Supported Groups extension. Inherits from SSLExtension and adds parsing of the + * supported groups (Elliptic Curves) mentioned in the extension data */ - virtual bool isMessageComplete() const; + class TLSSupportedGroupsExtension : public SSLExtension + { + public: + /** + * C'tor for this class + * @param[in] data The raw data for the extension + */ + explicit TLSSupportedGroupsExtension(uint8_t* data) : SSLExtension(data) + {} - /** - * @return A pointer to the SSLHandshakeLayer instance containing this message - */ - SSLHandshakeLayer* getContainingLayer() const { return m_Container; } + /** + * @return A vector of the supported groups (also known as "Elliptic Curves") + */ + std::vector getSupportedGroups() const; + }; /** - * @return A string representation of the message type (e.g "Client Hello message") + * @class TLSECPointFormatExtension + * Represents TLS EC (Elliptic Curves) Point Format extension. Inherits from SSLExtension and adds parsing of the + * EC point formats mentioned in the extension data */ - virtual std::string toString() const = 0; - -protected: - - SSLHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - - uint8_t* m_Data; - size_t m_DataLen; - SSLHandshakeLayer* m_Container; - -}; - + class TLSECPointFormatExtension : public SSLExtension + { + public: + /** + * C'tor for this class + * @param[in] data The raw data for the extension + */ + explicit TLSECPointFormatExtension(uint8_t* data) : SSLExtension(data) + {} -/** - * @class SSLClientHelloMessage - * Represents a client-hello message (type 1). Inherits from SSLHandshakeMessage and adds parsing of all fields - * of this message including the message extensions, cipher-suite list, etc. - */ -class SSLClientHelloMessage : public SSLHandshakeMessage -{ -public: + /** + * @return A vector of the elliptic curves point formats + */ + std::vector getECPointFormatList() const; + }; /** - * @struct ClientHelloTLSFingerprint - * A struct that contains all the elements needed for creating a Client Hello TLS fingerprinting: - * TLS version, a list of Cipher Suite IDs, a list of Extensions IDs, a list of support groups and a list of - * EC point formats. - * You can read more about this in SSLClientHelloMessage#generateTLSFingerprint(). - * This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() + * @class SSLx509Certificate + * Represents a x509v3 certificate. the SSLCertificateMessage class returns an instance of this class as the + * certificate. Currently this class doesn't do much as it doesn't parse the certificate. It only acts as container + * to the raw data and returns general info as data as raw, length, etc. In the future I may add full parsing of the + * certificate */ - struct ClientHelloTLSFingerprint + class SSLx509Certificate { - /** TLS version */ - uint16_t tlsVersion; - /** A list of Cipher Suite IDs */ - std::vector cipherSuites; - /** A list of extension IDs */ - std::vector extensions; - /** A list of Suppotred Groups taken from the "supported groups" TLS extension (if exist in the message) */ - std::vector supportedGroups; - /** A list of EC point formats taken from the "EC point formats" TLS extension (if exist in the message) */ - std::vector ecPointFormats; - - /** - * @return A string representing the TLS fingerprint, for example: - * 771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2 - * - * This string has the following format: TLSVersion,CipherSuiteIDs,ExtensionIDs,SupportedGroups,ECPointFormats - * - * The extension IDs, supported groups and EC point formats are each separated by a "-". - * If the message doesn't include the "supported groups" or "EC point formats" extensions, they will be replaced - * by an empty string for example: 771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,, + public: + /** + * C'tor for this class + * @param[in] data The raw data of the certificate + * @param[in] dataLen The length in bytes of the raw data + * @param[in] allDataExists Certificate messages usually spread on more than 1 packet. So a certificate is + * likely to split between 2 packets or more. This field indicates whether the raw data contains all + * ceritificate data of just a part of it */ - std::string toString(); + SSLx509Certificate(uint8_t* data, size_t dataLen, bool allDataExists) + : m_Data(data), m_DataLen(dataLen), m_AllDataExists(allDataExists) + {} /** - * @return An MD5 hash of the string generated by toString() + * @return A pointer to the raw data */ - std::string toMD5(); + uint8_t* getData() const + { + return m_Data; + } /** - * @return A pair of the string and MD5 hash (string is first, MD5 is second). - * If you want both this method is more efficient than calling toString() and toMD5() separately + * @return Raw data length */ - std::pair toStringAndMD5(); + size_t getDataLength() const + { + return m_DataLen; + } + + /** + * Certificate messages usually spread on more than 1 packet. So a certificate is likely to split between 2 + * packets or more. This method provides an indication whether all certificate data exists or only part of it + * @return True if this data contains all certificate data, false otherwise + */ + bool allDataExists() const + { + return m_AllDataExists; + } + + private: + uint8_t* m_Data; + size_t m_DataLen; + bool m_AllDataExists; }; + class SSLHandshakeLayer; + /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message + * @class SSLHandshakeMessage + * A base class for SSL/TLS handshake messages. This is an abstract class and cannot be instantiated. SSL/TLS + * handshake messages are contained in SSLHandshakeLayer, meaning a SSLHandshakeLayer instance can contain one or + * more SSLHandshakeMessage instances. For example: one SSLHandshakeLayer may contain a server-hello, certificate, + * server-key-exchange, and server-hello-done messages (although it's not such a common case, most handshake layers + * contain 1 handshake message only) */ - SSLClientHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); + class SSLHandshakeMessage + { + public: + virtual ~SSLHandshakeMessage() + {} - virtual ~SSLClientHelloMessage() {} + /** + * A factory method for creating instances of handshake messages from raw data + * @param[in] data The raw data containing 1 handshake message + * @param[in] dataLen Raw data length in bytes + * @param[in] container A pointer to the SSLHandshakeLayer instance which will contain the created message. + * This parameter is required because the handshake message includes a pointer to its container + */ + static SSLHandshakeMessage* createHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - /** - * @return A struct containing common fields for client-hello and server-hello messages. Notice this points directly - * to the data, so every change will change the actual packet data - */ - ssl_tls_client_server_hello* getClientHelloHeader() const { return (ssl_tls_client_server_hello*)m_Data; } + /** + * @return The handshake message type + */ + virtual SSLHandshakeType getHandshakeType() const; - /** - * @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each client-hello - * or server-hello message has both record version and handshake version and they may differ from one another) - */ - SSLVersion getHandshakeVersion() const; + /** + * @return The handshake message length in bytes. Notice that sometimes the handshake message is divided between + * several packets, in this case this method will return the length of part of the message in the current packet + */ + virtual size_t getMessageLength() const; - /** - * @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned - */ - uint8_t getSessionIDLength() const; + /** + * @return True if current packet contains the entire message or false otherwise. This method is important + * because sometimes handshake messages are divided in consequent packets (happens a lot in certificate messages + * which usually contain several KB of data which is larger than standard packet size, so the message is divided + * between several packets) + */ + virtual bool isMessageComplete() const; - /** - * @return Session ID as byte array. If server-hello message doesn't include session ID NULL will be returned - */ - uint8_t* getSessionID() const; + /** + * @return A pointer to the SSLHandshakeLayer instance containing this message + */ + SSLHandshakeLayer* getContainingLayer() const + { + return m_Container; + } - /** - * @return The number of cipher-suites included in this message - */ - int getCipherSuiteCount() const; + /** + * @return A string representation of the message type (e.g "Client Hello message") + */ + virtual std::string toString() const = 0; - /** - * Get a pointer to a cipher-suite by index. The cipher-suites are numbered according to their order of appearance - * in the message. If index is out of bounds (less than 0 or larger than total amount of cipher suites) NULL will be - * returned. NULL will also be returned if the cipher-suite ID is unknown. If you still want to get the cipher-suite - * ID you can use getCipherSuiteID() - * @param[in] index The index of the cipher-suite to return - * @return The pointer to the cipher-suite object or NULL if index is out of bounds - */ - SSLCipherSuite* getCipherSuite(int index) const; + protected: + SSLHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - /** - * Get the cipher-suite ID by index. This method just parses the ID from the client-hello message and returns it. - * To get more information on the cipher-suite you can use the getCipherSuite() method - * @param[in] index The index of the cipher-suite to return - * @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" if: - * (1) the index is out-of-bounds (less than 0 or larger than total amount of cipher suites) or (2) the parsing failed. - * If the value is "false" the return value can be ignored - * @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value can be ignored - */ - uint16_t getCipherSuiteID(int index, bool& isValid) const; + uint8_t* m_Data; + size_t m_DataLen; + SSLHandshakeLayer* m_Container; + }; /** - * @return The value of the compression method byte + * @class SSLClientHelloMessage + * Represents a client-hello message (type 1). Inherits from SSLHandshakeMessage and adds parsing of all fields + * of this message including the message extensions, cipher-suite list, etc. */ - uint8_t getCompressionMethodsValue() const; + class SSLClientHelloMessage : public SSLHandshakeMessage + { + public: + /** + * @struct ClientHelloTLSFingerprint + * A struct that contains all the elements needed for creating a Client Hello TLS fingerprinting: + * TLS version, a list of Cipher Suite IDs, a list of Extensions IDs, a list of support groups and a list of + * EC point formats. + * You can read more about this in SSLClientHelloMessage#generateTLSFingerprint(). + * This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() + */ + struct ClientHelloTLSFingerprint + { + /** TLS version */ + uint16_t tlsVersion; + /** A list of Cipher Suite IDs */ + std::vector cipherSuites; + /** A list of extension IDs */ + std::vector extensions; + /** A list of Suppotred Groups taken from the "supported groups" TLS extension (if exist in the message) */ + std::vector supportedGroups; + /** A list of EC point formats taken from the "EC point formats" TLS extension (if exist in the message) */ + std::vector ecPointFormats; + + /** + * @return A string representing the TLS fingerprint, for example: + * 771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,29-23-30-25-24,0-1-2 + * + * This string has the following format: + * TLSVersion,CipherSuiteIDs,ExtensionIDs,SupportedGroups,ECPointFormats + * + * The extension IDs, supported groups and EC point formats are each separated by a "-". + * If the message doesn't include the "supported groups" or "EC point formats" extensions, they will be + * replaced by an empty string for example: 771,4866-4867-4865-255,0-11-10-35-22-23-13-43-45-51,, + */ + std::string toString(); + + /** + * @return An MD5 hash of the string generated by toString() + */ + std::string toMD5(); + + /** + * @return A pair of the string and MD5 hash (string is first, MD5 is second). + * If you want both this method is more efficient than calling toString() and toMD5() separately + */ + std::pair toStringAndMD5(); + }; - /** - * @return The number of extensions in this message - */ - int getExtensionCount() const; + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLClientHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - /** - * @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" field - */ - uint16_t getExtensionsLength() const; + virtual ~SSLClientHelloMessage() + {} - /** - * Get a pointer to an extension by index. The extensions are numbered according to their order of appearance - * in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) NULL will be - * returned - * @param[in] index The index of the extension to return - * @return The pointer to the extension or NULL if index is out of bounds - */ - SSLExtension* getExtension(int index) const; + /** + * @return A struct containing common fields for client-hello and server-hello messages. Notice this points + * directly to the data, so every change will change the actual packet data + */ + ssl_tls_client_server_hello* getClientHelloHeader() const + { + return (ssl_tls_client_server_hello*)m_Data; + } - /** - * Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing - * its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a - * pointer to the extension object - * @param[in] type The 2-byte numeric type of the extension - * @return A pointer to the extension object of NULL if this type doesn't exist in this message - */ - SSLExtension* getExtensionOfType(uint16_t type) const; + /** + * @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each + * client-hello or server-hello message has both record version and handshake version and they may differ from + * one another) + */ + SSLVersion getHandshakeVersion() const; - /** - * Get a pointer to an extension by its enum type - * @param[in] type The type of extension to return - * @return A pointer to the extension object or NULL if this type doesn't exist in this message - */ - SSLExtension* getExtensionOfType(SSLExtensionType type) const; + /** + * @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned + */ + uint8_t getSessionIDLength() const; - /** - * Get a pointer to an extension by its class type. This is a templated method that is used with the type of the - * requested extension and returns the first extension instance of this type - * @return A pointer to the extension object or NULL if this extension type doesn't exist in this message - * - */ - template - TExtension* getExtensionOfType() const; + /** + * @return Session ID as byte array. If server-hello message doesn't include session ID NULL will be returned + */ + uint8_t* getSessionID() const; - /** - * TLS fingerprinting is a way to identify client applications using the details in the TLS Client Hello packet. - * It was initially introduced by Lee Brotherston in his 2015 research: - * This implementation of TLS fingerprint is a C++ version of Salesforce's JA3 open source project (originally written in - * Python and Zeek): - * - * @return A SSLClientHelloMessage#ClientHelloTLSFingerprint struct that contains all the elements needed for - * creating a TLS fingerprint out of this Client Hello message. This struct has also methods to extract the TLS fingerprint - * itself in a string or MD5 formats - */ - ClientHelloTLSFingerprint generateTLSFingerprint() const; + /** + * @return The number of cipher-suites included in this message + */ + int getCipherSuiteCount() const; - // implement abstract methods + /** + * Get a pointer to a cipher-suite by index. The cipher-suites are numbered according to their order of + * appearance in the message. If index is out of bounds (less than 0 or larger than total amount of cipher + * suites) NULL will be returned. NULL will also be returned if the cipher-suite ID is unknown. If you still + * want to get the cipher-suite ID you can use getCipherSuiteID() + * @param[in] index The index of the cipher-suite to return + * @return The pointer to the cipher-suite object or NULL if index is out of bounds + */ + SSLCipherSuite* getCipherSuite(int index) const; - std::string toString() const; + /** + * Get the cipher-suite ID by index. This method just parses the ID from the client-hello message and returns + * it. To get more information on the cipher-suite you can use the getCipherSuite() method + * @param[in] index The index of the cipher-suite to return + * @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" if: + * (1) the index is out-of-bounds (less than 0 or larger than total amount of cipher suites) or (2) the parsing + * failed. If the value is "false" the return value can be ignored + * @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value + * can be ignored + */ + uint16_t getCipherSuiteID(int index, bool& isValid) const; -private: - PointerVector m_ExtensionList; + /** + * @return The value of the compression method byte + */ + uint8_t getCompressionMethodsValue() const; -}; + /** + * @return The number of extensions in this message + */ + int getExtensionCount() const; + /** + * @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" + * field + */ + uint16_t getExtensionsLength() const; -/** - * @class SSLServerHelloMessage - * Represents SSL/TLS server-hello message (type 2). Inherits from SSLHandshakeMessage and adds parsing of all fields - * of this message including the message extensions, cipher-suite, etc. - */ -class SSLServerHelloMessage : public SSLHandshakeMessage -{ -public: + /** + * Get a pointer to an extension by index. The extensions are numbered according to their order of appearance + * in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) NULL will + * be returned + * @param[in] index The index of the extension to return + * @return The pointer to the extension or NULL if index is out of bounds + */ + SSLExtension* getExtension(int index) const; - /** - * @struct ServerHelloTLSFingerprint - * A struct that contains all the elements needed for creating a Server Hello TLS fingerprinting: - * TLS version, Cipher Suite ID, and a list of Extensions IDs. - * You can read more about this in SSLServerHelloMessage#generateTLSFingerprint(). - * This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() - */ - struct ServerHelloTLSFingerprint - { - /** TLS version */ - uint16_t tlsVersion; - /** Cipher Suite ID */ - uint16_t cipherSuite; - /** A list of extension IDs */ - std::vector extensions; + /** + * Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing + * its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a + * pointer to the extension object + * @param[in] type The 2-byte numeric type of the extension + * @return A pointer to the extension object of NULL if this type doesn't exist in this message + */ + SSLExtension* getExtensionOfType(uint16_t type) const; /** - * @return A string representing the TLS fingerprint, for example: 771,49195,65281-16-11 - * - * This string has the following format: TLSVersion,Cipher,Extensions - * - * The extension ID are separated with a "-" + * Get a pointer to an extension by its enum type + * @param[in] type The type of extension to return + * @return A pointer to the extension object or NULL if this type doesn't exist in this message */ - std::string toString(); + SSLExtension* getExtensionOfType(SSLExtensionType type) const; /** - * @return An MD5 hash of the string generated by toString() + * Get a pointer to an extension by its class type. This is a templated method that is used with the type of the + * requested extension and returns the first extension instance of this type + * @return A pointer to the extension object or NULL if this extension type doesn't exist in this message + * */ - std::string toMD5(); + template TExtension* getExtensionOfType() const; /** - * @return A pair of the string and MD5 hash (string is first, MD5 is second). - * If you want both this method is more efficient than calling toString() and toMD5() separately + * TLS fingerprinting is a way to identify client applications using the details in the TLS Client Hello packet. + * It was initially introduced by Lee Brotherston in his 2015 research: + * This implementation of TLS fingerprint is a C++ version of + * Salesforce's JA3 open source project (originally written in Python and Zeek): + * + * @return A SSLClientHelloMessage#ClientHelloTLSFingerprint struct that contains all the elements needed for + * creating a TLS fingerprint out of this Client Hello message. This struct has also methods to extract the TLS + * fingerprint itself in a string or MD5 formats */ - std::pair toStringAndMD5(); - }; + ClientHelloTLSFingerprint generateTLSFingerprint() const; - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLServerHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); + // implement abstract methods - virtual ~SSLServerHelloMessage() {} + std::string toString() const; - /** - * @return A struct containing common fields for client-hello and server-hello messages. Notice this points directly - * to the data, so every change will change the actual packet data - */ - ssl_tls_client_server_hello* getServerHelloHeader() const { return (ssl_tls_client_server_hello*)m_Data; } + private: + PointerVector m_ExtensionList; + }; /** - * @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each client-hello - * or server-hello message has both record version and handshake version and they may differ from one another). - * - * NOTE: for TLS 1.3 the handshake version written in ssl_tls_client_server_hello::handshakeVersion is still TLS 1.2, - * so a special check is made here see if a SupportedVersions extension exists and if so extract the version from it. - * This is the most straight-forward way to detect TLS 1.3. + * @class SSLServerHelloMessage + * Represents SSL/TLS server-hello message (type 2). Inherits from SSLHandshakeMessage and adds parsing of all + * fields of this message including the message extensions, cipher-suite, etc. */ - SSLVersion getHandshakeVersion() const; + class SSLServerHelloMessage : public SSLHandshakeMessage + { + public: + /** + * @struct ServerHelloTLSFingerprint + * A struct that contains all the elements needed for creating a Server Hello TLS fingerprinting: + * TLS version, Cipher Suite ID, and a list of Extensions IDs. + * You can read more about this in SSLServerHelloMessage#generateTLSFingerprint(). + * This struct contains methods to extract the TLS fingerprint itself: toString() and toMD5() + */ + struct ServerHelloTLSFingerprint + { + /** TLS version */ + uint16_t tlsVersion; + /** Cipher Suite ID */ + uint16_t cipherSuite; + /** A list of extension IDs */ + std::vector extensions; + + /** + * @return A string representing the TLS fingerprint, for example: 771,49195,65281-16-11 + * + * This string has the following format: TLSVersion,Cipher,Extensions + * + * The extension ID are separated with a "-" + */ + std::string toString(); + + /** + * @return An MD5 hash of the string generated by toString() + */ + std::string toMD5(); + + /** + * @return A pair of the string and MD5 hash (string is first, MD5 is second). + * If you want both this method is more efficient than calling toString() and toMD5() separately + */ + std::pair toStringAndMD5(); + }; - /** - * @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned - */ - uint8_t getSessionIDLength() const; + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and shouldn't be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLServerHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - /** - * @return Session ID as byte array. If server-hello message doesn't include session ID NULL will be returned - */ - uint8_t* getSessionID() const; + virtual ~SSLServerHelloMessage() + {} - /** - * @return A pointer to the cipher suite encapsulated in this message (server-hello message contains one - * cipher-suite, the one that will be used to for encryption between client and server). May return NULL - * if the parsing of the message failed or the cipher-suite ID is unknown. If you still want to get the - * cipher-suite ID you can use the getCipherSuiteID() method - */ - SSLCipherSuite* getCipherSuite() const; + /** + * @return A struct containing common fields for client-hello and server-hello messages. Notice this points + * directly to the data, so every change will change the actual packet data + */ + ssl_tls_client_server_hello* getServerHelloHeader() const + { + return (ssl_tls_client_server_hello*)m_Data; + } - /** - * Get the cipher-suite ID. This method just parses the ID from the server-hello message and returns it. - * To get more information on the cipher-suite you can use the getCipherSuite() method - * @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" otherwise. - * If the value is "false" the return value can be ignored - * @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value can be ignored - */ - uint16_t getCipherSuiteID(bool& isValid) const; + /** + * @return Handshake SSL/TLS version (notice it may be different than SSLLayer#getRecordVersion(). Each + * client-hello or server-hello message has both record version and handshake version and they may differ from + * one another). + * + * NOTE: for TLS 1.3 the handshake version written in ssl_tls_client_server_hello::handshakeVersion is + * still TLS 1.2, so a special check is made here see if a SupportedVersions extension exists and if so extract + * the version from it. This is the most straight-forward way to detect TLS 1.3. + */ + SSLVersion getHandshakeVersion() const; - /** - * @return The value of the compression method byte - */ - uint8_t getCompressionMethodsValue() const; + /** + * @return Session ID length in bytes. If server-hello message doesn't include session ID 0 will be returned + */ + uint8_t getSessionIDLength() const; - /** - * @return The number of extensions in this message - */ - int getExtensionCount() const; + /** + * @return Session ID as byte array. If server-hello message doesn't include session ID NULL will be returned + */ + uint8_t* getSessionID() const; - /** - * @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" field - */ - uint16_t getExtensionsLength() const; + /** + * @return A pointer to the cipher suite encapsulated in this message (server-hello message contains one + * cipher-suite, the one that will be used to for encryption between client and server). May return NULL + * if the parsing of the message failed or the cipher-suite ID is unknown. If you still want to get the + * cipher-suite ID you can use the getCipherSuiteID() method + */ + SSLCipherSuite* getCipherSuite() const; - /** - * Get a pointer to an extension by index. The extensions are numbered according to their order of appearance - * in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) NULL will be - * returned - * @param[in] index The index of the extension to return - * @return The pointer to the extension or NULL if index is out of bounds - */ - SSLExtension* getExtension(int index) const; + /** + * Get the cipher-suite ID. This method just parses the ID from the server-hello message and returns it. + * To get more information on the cipher-suite you can use the getCipherSuite() method + * @param[out] isValid Set to "true" if parsing succeeded and the return value is valid or "false" otherwise. + * If the value is "false" the return value can be ignored + * @return The cipher-suite ID if "isValid" is set to "true". If "isValid" is set to "false" the return value + * can be ignored + */ + uint16_t getCipherSuiteID(bool& isValid) const; - /** - * Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing - * its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a - * pointer to the extension object - * @param[in] type The 2-byte numeric type of the extension - * @return A pointer to the extension object of NULL if this type doesn't exist in this message - */ - SSLExtension* getExtensionOfType(uint16_t type) const; + /** + * @return The value of the compression method byte + */ + uint8_t getCompressionMethodsValue() const; - /** - * Get a pointer to an extension by its enum type - * @param[in] type The type of extension to return - * @return A pointer to the extension object or NULL if this type doesn't exist in this message - */ - SSLExtension* getExtensionOfType(SSLExtensionType type) const; + /** + * @return The number of extensions in this message + */ + int getExtensionCount() const; - /** - * Get a pointer to an extension by its class type. This is a templated method that is used with the type of the - * requested extension and returns the first extension instance of this type - * @return A pointer to the extension object or NULL if this extension type doesn't exist in this message - * - */ - template - TExtension* getExtensionOfType() const; + /** + * @return The size (in bytes) of all extensions data in this message. Extracted from the "extensions length" + * field + */ + uint16_t getExtensionsLength() const; - /** - * ServerHello TLS fingerprinting is a way to fingerprint TLS Server Hello messages. In conjunction with - * ClientHello TLS fingerprinting it can assist in identifying specific client-server communication (for - * example: a malware connecting to its backend server). - * ServerHello TLS fingerprinting was introduced in Salesforce's JA3S open source project: - * - * This implementation is a C++ version of Salesforce's JAS3 (originally written in Python and Zeek) - * @return A SSLServerHelloMessage#ServerHelloTLSFingerprint struct that contains all the elements needed for - * creating a TLS fingerprint out of this Server Hello message. This struct has also methods to extract the TLS fingerprint - * itself in a string or MD5 formats - */ - ServerHelloTLSFingerprint generateTLSFingerprint() const; + /** + * Get a pointer to an extension by index. The extensions are numbered according to their order of appearance + * in the message. If index is out of bounds (less than 0 or larger than total amount of extensions) NULL will + * be returned + * @param[in] index The index of the extension to return + * @return The pointer to the extension or NULL if index is out of bounds + */ + SSLExtension* getExtension(int index) const; - // implement abstract methods + /** + * Get a pointer to an extension by numeric type field. Every extension has a 2-byte numeric value representing + * its type (for example: renegotiation info extension type is 0x1ff). This method gets the type and returns a + * pointer to the extension object + * @param[in] type The 2-byte numeric type of the extension + * @return A pointer to the extension object of NULL if this type doesn't exist in this message + */ + SSLExtension* getExtensionOfType(uint16_t type) const; - std::string toString() const; + /** + * Get a pointer to an extension by its enum type + * @param[in] type The type of extension to return + * @return A pointer to the extension object or NULL if this type doesn't exist in this message + */ + SSLExtension* getExtensionOfType(SSLExtensionType type) const; -private: - PointerVector m_ExtensionList; -}; + /** + * Get a pointer to an extension by its class type. This is a templated method that is used with the type of the + * requested extension and returns the first extension instance of this type + * @return A pointer to the extension object or NULL if this extension type doesn't exist in this message + * + */ + template TExtension* getExtensionOfType() const; + /** + * ServerHello TLS fingerprinting is a way to fingerprint TLS Server Hello messages. In conjunction with + * ClientHello TLS fingerprinting it can assist in identifying specific client-server communication (for + * example: a malware connecting to its backend server). + * ServerHello TLS fingerprinting was introduced in Salesforce's JA3S open source project: + * + * This implementation is a C++ version of Salesforce's JAS3 (originally written in Python and Zeek) + * @return A SSLServerHelloMessage#ServerHelloTLSFingerprint struct that contains all the elements needed for + * creating a TLS fingerprint out of this Server Hello message. This struct has also methods to extract the TLS + * fingerprint itself in a string or MD5 formats + */ + ServerHelloTLSFingerprint generateTLSFingerprint() const; -/** - * @class SSLCertificateMessage - * Represents SSL/TLS certificate message (type 11). Inherits from SSLHandshakeMessage and adds parsing functionality - * such as extracting the certificates data. Notice that in most cases this message is spread over more than 1 packet - * as its size is too big for a single packet. So SSLCertificateMessage instance will be created just for the first - * part of the message - the one encapsulated in the first packet. Other parts (encapsulated in the following packets) - * won't be recognized as SSLCertificateMessage messages - */ -class SSLCertificateMessage : public SSLHandshakeMessage -{ -public: + // implement abstract methods - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLCertificateMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); + std::string toString() const; - virtual ~SSLCertificateMessage() {} + private: + PointerVector m_ExtensionList; + }; /** - * @return The number of certificates encapsulated in this message (as written in the 'length' field of the - * message). Notice that because the message may spread over several packets, not all certificates will necessarily - * be in this packet. So, for example, there may be a case where this method return 3 (message contains 3 - * certificates) but this message actually contains only 1 certificate as the other 2 are spread over the other - * packets + * @class SSLCertificateMessage + * Represents SSL/TLS certificate message (type 11). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as extracting the certificates data. Notice that in most cases this message is spread over + * more than 1 packet as its size is too big for a single packet. So SSLCertificateMessage instance will be created + * just for the first part of the message - the one encapsulated in the first packet. Other parts (encapsulated in + * the following packets) won't be recognized as SSLCertificateMessage messages */ - int getNumOfCertificates() const; + class SSLCertificateMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLCertificateMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - /** - * Get a certificate by index - * @param[in] index The index of the certificate to retrieve - * @return A pointer to the certificate object. Notice that if index < 0 or index > num of certificates encapsulated - * in current packet a NULL value will be returned - */ - SSLx509Certificate* getCertificate(int index) const; + virtual ~SSLCertificateMessage() + {} - // implement abstract methods + /** + * @return The number of certificates encapsulated in this message (as written in the 'length' field of the + * message). Notice that because the message may spread over several packets, not all certificates will + * necessarily be in this packet. So, for example, there may be a case where this method return 3 (message + * contains 3 certificates) but this message actually contains only 1 certificate as the other 2 are spread over + * the other packets + */ + int getNumOfCertificates() const; - std::string toString() const; + /** + * Get a certificate by index + * @param[in] index The index of the certificate to retrieve + * @return A pointer to the certificate object. Notice that if index < 0 or index > num of certificates + * encapsulated in current packet a NULL value will be returned + */ + SSLx509Certificate* getCertificate(int index) const; -private: - PointerVector m_CertificateList; -}; + // implement abstract methods + std::string toString() const; -/** - * @class SSLHelloRequestMessage - * Represents SSL/TLS hello-request message (type 0). This message has no additional payload except for the common payload - * described in SSLHandshakeMessage - */ -class SSLHelloRequestMessage : public SSLHandshakeMessage -{ -public: + private: + PointerVector m_CertificateList; + }; /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message + * @class SSLHelloRequestMessage + * Represents SSL/TLS hello-request message (type 0). This message has no additional payload except for the common + * payload described in SSLHandshakeMessage */ - SSLHelloRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} - - virtual ~SSLHelloRequestMessage() {} - - // implement abstract methods - - std::string toString() const; -}; - - -/** - * @class SSLServerKeyExchangeMessage - * Represents SSL/TLS server-key-exchange message (type 12). Inherits from SSLHandshakeMessage and adds parsing - * functionality such as getting the server key exchange params as raw data (parsing of this may be added in the - * future) - */ -class SSLServerKeyExchangeMessage : public SSLHandshakeMessage -{ -public: + class SSLHelloRequestMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLHelloRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLServerKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} + virtual ~SSLHelloRequestMessage() + {} - ~SSLServerKeyExchangeMessage() {} + // implement abstract methods - /** - * @return A pointer to the raw data of the server key exchange params. Currently this data can only returned as - * raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in a way - * params doesn't exist in the first packet, NULL will be returned - */ - uint8_t* getServerKeyExchangeParams() const; + std::string toString() const; + }; /** - * @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way the - * ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the params - * exist in current packet (and the rest are on consequent packets), the size that will be returned is the size - * of the part that exists in the current packet (and not total size of params) + * @class SSLServerKeyExchangeMessage + * Represents SSL/TLS server-key-exchange message (type 12). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as getting the server key exchange params as raw data (parsing of this may be added in the + * future) */ - size_t getServerKeyExchangeParamsLength() const; - - // implement abstract methods - - std::string toString() const; -}; + class SSLServerKeyExchangeMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLServerKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} + ~SSLServerKeyExchangeMessage() + {} -/** - * @class SSLClientKeyExchangeMessage - * Represents SSL/TLS client-key-exchange message (type 16). Inherits from SSLHandshakeMessage and adds parsing - * functionality such as getting the server key exchange params as raw data (parsing of this may be added in the - * future) - */ -class SSLClientKeyExchangeMessage : public SSLHandshakeMessage -{ -public: + /** + * @return A pointer to the raw data of the server key exchange params. Currently this data can only returned as + * raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in a + * way params doesn't exist in the first packet, NULL will be returned + */ + uint8_t* getServerKeyExchangeParams() const; - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLClientKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} + /** + * @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way + * the ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the + * params exist in current packet (and the rest are on consequent packets), the size that will be returned is + * the size of the part that exists in the current packet (and not total size of params) + */ + size_t getServerKeyExchangeParamsLength() const; - ~SSLClientKeyExchangeMessage() {} + // implement abstract methods - /** - * @return A pointer to the raw data of the server key exchange params. Currently this data can only be returned - * as raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in - * a way params doesn't exist in the first packet, NULL will be returned - */ - uint8_t* getClientKeyExchangeParams() const; + std::string toString() const; + }; /** - * @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way the - * ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the params - * exist in current packet (and the rest are on consequent packets), the size that will be returned is the size - * of the part that exists in the current packet (and not the total size of params) + * @class SSLClientKeyExchangeMessage + * Represents SSL/TLS client-key-exchange message (type 16). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as getting the server key exchange params as raw data (parsing of this may be added in the + * future) */ - size_t getClientKeyExchangeParamsLength() const; - - // implement abstract methods + class SSLClientKeyExchangeMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLClientKeyExchangeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} - std::string toString() const; -}; + ~SSLClientKeyExchangeMessage() + {} + /** + * @return A pointer to the raw data of the server key exchange params. Currently this data can only be returned + * as raw, parsing may be added in the future. Notice that if the message is spread over more than 1 packet in + * a way params doesn't exist in the first packet, NULL will be returned + */ + uint8_t* getClientKeyExchangeParams() const; -/** - * @class SSLCertificateRequestMessage - * Represents SSL/TLS certificate-request message (type 13). Inherits from SSLHandshakeMessage and adds parsing - * functionality such as retrieving client certificate types and authority data - */ -class SSLCertificateRequestMessage : public SSLHandshakeMessage -{ -public: + /** + * @return The size of the params field. Notice that if the message is spread over more than 1 packet in a way + * the ssl_tls_handshake_layer cannot be parsed from the packet, 0 will be returned. Also, if only part of the + * params exist in current packet (and the rest are on consequent packets), the size that will be returned is + * the size of the part that exists in the current packet (and not the total size of params) + */ + size_t getClientKeyExchangeParamsLength() const; - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLCertificateRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); + // implement abstract methods - ~SSLCertificateRequestMessage() {} + std::string toString() const; + }; /** - * @return A reference to a vector containing all client certificate types exist in this message + * @class SSLCertificateRequestMessage + * Represents SSL/TLS certificate-request message (type 13). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as retrieving client certificate types and authority data */ - std::vector& getCertificateTypes(); + class SSLCertificateRequestMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLCertificateRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container); - /** - * @return A pointer to the certificate authority data as raw data (byte array). Parsing of this data may be added - * in the future. Notice that if this message is spread over several packets in a way none of the certificate - * authority data exists in this packet, NULL will be returned - */ - uint8_t* getCertificateAuthorityData() const; + ~SSLCertificateRequestMessage() + {} - /** - * @return The length of certificate authority data returned by getCertificateAuthorityData(). Notice that if - * this message is spread over several packets in a way none of certificate authority data exists in the current - * packet, 0 will be returned. Also, if some of the data exists in the consequent packets, the length that will be - * returned is the length of data exists in the current packet only (and not the total length) - */ - size_t getCertificateAuthorityLength() const; + /** + * @return A reference to a vector containing all client certificate types exist in this message + */ + std::vector& getCertificateTypes(); - // implement abstract methods + /** + * @return A pointer to the certificate authority data as raw data (byte array). Parsing of this data may be + * added in the future. Notice that if this message is spread over several packets in a way none of the + * certificate authority data exists in this packet, NULL will be returned + */ + uint8_t* getCertificateAuthorityData() const; - std::string toString() const; + /** + * @return The length of certificate authority data returned by getCertificateAuthorityData(). Notice that if + * this message is spread over several packets in a way none of certificate authority data exists in the current + * packet, 0 will be returned. Also, if some of the data exists in the consequent packets, the length that will + * be returned is the length of data exists in the current packet only (and not the total length) + */ + size_t getCertificateAuthorityLength() const; -private: - std::vector m_ClientCertificateTypes; -}; + // implement abstract methods + std::string toString() const; -/** - * @class SSLServerHelloDoneMessage - * Represents SSL/TLS server-hello-done message (type 14). This message has no additional payload except for the common - * payload described in SSLHandshakeMessage - */ -class SSLServerHelloDoneMessage : public SSLHandshakeMessage -{ -public: + private: + std::vector m_ClientCertificateTypes; + }; /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message + * @class SSLServerHelloDoneMessage + * Represents SSL/TLS server-hello-done message (type 14). This message has no additional payload except for the + * common payload described in SSLHandshakeMessage */ - SSLServerHelloDoneMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} - - virtual ~SSLServerHelloDoneMessage() {} - - // implement abstract methods - - std::string toString() const; -}; - - -/** - * @class SSLCertificateVerifyMessage - * Represents SSL/TLS certificate-verify message (type 15). Inherits from SSLHandshakeMessage and adds parsing - * functionality such as retrieving signed hash data as raw data (parsing may be added in the future) - * @todo This message type wasn't tested in unit-tests - */ -class SSLCertificateVerifyMessage : public SSLHandshakeMessage -{ -public: + class SSLServerHelloDoneMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLServerHelloDoneMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLCertificateVerifyMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} + virtual ~SSLServerHelloDoneMessage() + {} - virtual ~SSLCertificateVerifyMessage() {} + // implement abstract methods - /** - * @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added - * in the future. Notice that if this message is spread over several packets in a way none of the signed hash data - * exists in this packet, NULL will be returned - */ - uint8_t* getSignedHash() const; + std::string toString() const; + }; /** - * @return The length of signed hash data returned by getSignedHash(). Notice that if this message is spread over - * several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if some of - * the data exists in the consequent packets, the length that will be returned will be the length of data exists in - * the current packet only (and not the total length) + * @class SSLCertificateVerifyMessage + * Represents SSL/TLS certificate-verify message (type 15). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as retrieving signed hash data as raw data (parsing may be added in the future) + * @todo This message type wasn't tested in unit-tests */ - size_t getSignedHashLength() const; - - // implement abstract methods - - std::string toString() const; -}; + class SSLCertificateVerifyMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLCertificateVerifyMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} + virtual ~SSLCertificateVerifyMessage() + {} -/** - * @class SSLFinishedMessage - * Represents SSL/TLS finished message (type 20). Inherits from SSLHandshakeMessage and adds parsing - * functionality such as retrieving signed hash data as raw data (parsing may be added in the future) - * @todo This message type wasn't tested in unit-tests - */ -class SSLFinishedMessage : public SSLHandshakeMessage -{ -public: + /** + * @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added + * in the future. Notice that if this message is spread over several packets in a way none of the signed hash + * data exists in this packet, NULL will be returned + */ + uint8_t* getSignedHash() const; - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLFinishedMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} + /** + * @return The length of signed hash data returned by getSignedHash(). Notice that if this message is spread + * over several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if + * some of the data exists in the consequent packets, the length that will be returned will be the length of + * data exists in the current packet only (and not the total length) + */ + size_t getSignedHashLength() const; - virtual ~SSLFinishedMessage() {} + // implement abstract methods - /** - * @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added - * in the future. Notice that if this message is spread over several packets in a way none of the signed hash data - * exists in this packet, NULL will be returned - */ - uint8_t* getSignedHash() const; + std::string toString() const; + }; /** - * @return The length of signed hash data returned by getSignedHash(). Notice that if the message is spread over - * several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if some of - * the data exists in the consequent packets, the length that will be returned will be the length of data exists - * in the current packet only (and not the total length) + * @class SSLFinishedMessage + * Represents SSL/TLS finished message (type 20). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as retrieving signed hash data as raw data (parsing may be added in the future) + * @todo This message type wasn't tested in unit-tests */ - size_t getSignedHashLength() const; - - // implement abstract methods + class SSLFinishedMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLFinishedMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} - std::string toString() const; -}; + virtual ~SSLFinishedMessage() + {} + /** + * @return A pointer to the signed hash data as raw data (byte array). Parsing of this data may be added + * in the future. Notice that if this message is spread over several packets in a way none of the signed hash + * data exists in this packet, NULL will be returned + */ + uint8_t* getSignedHash() const; -/** - * @class SSLNewSessionTicketMessage - * Represents SSL/TLS new-session-ticket message (type 4). Inherits from SSLHandshakeMessage and adds parsing - * functionality such as retrieving session ticket data as raw data (parsing may be added in the future) - */ -class SSLNewSessionTicketMessage : public SSLHandshakeMessage -{ -public: + /** + * @return The length of signed hash data returned by getSignedHash(). Notice that if the message is spread over + * several packets in a way none of this data exists in the current packet, 0 will be returned. Also, if some of + * the data exists in the consequent packets, the length that will be returned will be the length of data exists + * in the current packet only (and not the total length) + */ + size_t getSignedHashLength() const; - /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message - */ - SSLNewSessionTicketMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} + // implement abstract methods - virtual ~SSLNewSessionTicketMessage() {} + std::string toString() const; + }; /** - * @return A pointer to the session ticket data as raw data (byte array). Parsing of this data may be added - * in the future. Notice that if this message is spread over several packets in a way none of the signed hash data - * exists in current packet, NULL will be returned + * @class SSLNewSessionTicketMessage + * Represents SSL/TLS new-session-ticket message (type 4). Inherits from SSLHandshakeMessage and adds parsing + * functionality such as retrieving session ticket data as raw data (parsing may be added in the future) */ - uint8_t* getSessionTicketData() const; + class SSLNewSessionTicketMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLNewSessionTicketMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} - /** - * @return The length of session ticket data returned by getSessionTicketData(). Notice that if this message is - * spread over several packets in a way none of this data exists in the current packet, 0 will be returned. Also, - * if some of the data exist in the consequent packets, the length that will be returned will be the length of the - * data existing in the current packet only (and not the total length) - */ - size_t getSessionTicketDataLength() const; + virtual ~SSLNewSessionTicketMessage() + {} - // implement abstract methods + /** + * @return A pointer to the session ticket data as raw data (byte array). Parsing of this data may be added + * in the future. Notice that if this message is spread over several packets in a way none of the signed hash + * data exists in current packet, NULL will be returned + */ + uint8_t* getSessionTicketData() const; - std::string toString() const; -}; + /** + * @return The length of session ticket data returned by getSessionTicketData(). Notice that if this message is + * spread over several packets in a way none of this data exists in the current packet, 0 will be returned. + * Also, if some of the data exist in the consequent packets, the length that will be returned will be the + * length of the data existing in the current packet only (and not the total length) + */ + size_t getSessionTicketDataLength() const; + // implement abstract methods -/** - * @class SSLUnknownMessage - * Represents an unknown type of message or an encrypted message that PcapPlusPlus can't determine its type. In these - * cases length can't always be determined from the message itself (especially if the message is encrypted), so - * the length of this message will always be the size counted from message start until the end of the layer - */ -class SSLUnknownMessage : public SSLHandshakeMessage -{ -public: + std::string toString() const; + }; /** - * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be used - * by a user - * @param[in] data The message as raw data - * @param[in] dataLen Message raw data length in bytes - * @param[in] container The SSL handshake layer which shall contain this message + * @class SSLUnknownMessage + * Represents an unknown type of message or an encrypted message that PcapPlusPlus can't determine its type. In + * these cases length can't always be determined from the message itself (especially if the message is encrypted), + * so the length of this message will always be the size counted from message start until the end of the layer */ - SSLUnknownMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) : SSLHandshakeMessage(data, dataLen, container) {} + class SSLUnknownMessage : public SSLHandshakeMessage + { + public: + /** + * C'tor for this class. Currently only in use in SSLHandshakeMessage::createHandshakeMessage() and should be + * used by a user + * @param[in] data The message as raw data + * @param[in] dataLen Message raw data length in bytes + * @param[in] container The SSL handshake layer which shall contain this message + */ + SSLUnknownMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + {} - virtual ~SSLUnknownMessage() {} + virtual ~SSLUnknownMessage() + {} - // implement virtual and abstract methods + // implement virtual and abstract methods - /** - * @return Always ::SSL_HANDSHAKE_UNKNOWN (overridden from SSLHandshakeMessage) - */ - SSLHandshakeType getHandshakeType() const; + /** + * @return Always ::SSL_HANDSHAKE_UNKNOWN (overridden from SSLHandshakeMessage) + */ + SSLHandshakeType getHandshakeType() const; - /** - * @return The length of the data from message start until the end of the layer. Since it's an unknown type - * or an encrypted message the length parsed from the message can't be guaranteed to be the correct length. That's - * why the length returned is the size until the end of the layer - */ - size_t getMessageLength() const; + /** + * @return The length of the data from message start until the end of the layer. Since it's an unknown type + * or an encrypted message the length parsed from the message can't be guaranteed to be the correct length. + * That's why the length returned is the size until the end of the layer + */ + size_t getMessageLength() const; - std::string toString() const; -}; + std::string toString() const; + }; -template -TExtension* SSLClientHelloMessage::getExtensionOfType() const -{ - size_t vecSize = m_ExtensionList.size(); - for (size_t i = 0; i < vecSize; i++) + template TExtension* SSLClientHelloMessage::getExtensionOfType() const { - SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); - if (dynamic_cast(curElem) != NULL) - return (TExtension*)curElem; + size_t vecSize = m_ExtensionList.size(); + for (size_t i = 0; i < vecSize; i++) + { + SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); + if (dynamic_cast(curElem) != NULL) + return (TExtension*)curElem; + } + + return NULL; } - return NULL; -} - -template -TExtension* SSLServerHelloMessage::getExtensionOfType() const -{ - size_t vecSize = m_ExtensionList.size(); - for (size_t i = 0; i < vecSize; i++) + template TExtension* SSLServerHelloMessage::getExtensionOfType() const { - SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); - if (dynamic_cast(curElem) != NULL) - return (TExtension*)curElem; + size_t vecSize = m_ExtensionList.size(); + for (size_t i = 0; i < vecSize; i++) + { + SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); + if (dynamic_cast(curElem) != NULL) + return (TExtension*)curElem; + } + + return NULL; } - return NULL; -} - -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SSLLayer.h b/Packet++/header/SSLLayer.h index 095f01acaa..33c854767b 100644 --- a/Packet++/header/SSLLayer.h +++ b/Packet++/header/SSLLayer.h @@ -91,7 +91,8 @@ * - Finished * - New-session-ticket * - * All handshake messages classes inherit from a base abstract class: pcpp::SSLHandshakeMessage which cannot be instantiated. + * All handshake messages classes inherit from a base abstract class: pcpp::SSLHandshakeMessage which cannot be + * instantiated. * Also, all of them reside in SSLHandshake.h. Following is a simple diagram of these classes: * @verbatim @@ -129,14 +130,16 @@ * * __Cipher suites:__
* - * Cipher suites are named combinations of authentication, encryption, message authentication code (MAC) and key exchange - * algorithms used to negotiate the security settings for a network connection using SSL/TLS. + * Cipher suites are named combinations of authentication, encryption, message authentication code (MAC) and key + * exchange algorithms used to negotiate the security settings for a network connection using SSL/TLS. * There are many known cipher-suites. PcapPlusPlus support above 300 of them, according to this list: * http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml - * There is a designated class in PcapPlusPlus called pcpp::SSLCipherSuite which represents the cipher-suites and provides - * access to their attributes. Then there is a static instance of this class for each one of the supported cipher-suites. - * This means there are 300+ static instances of pcpp::SSLCipherSuite representing the different cipher suites. The user can - * access them through static methods in pcpp::SSLCipherSuite or from client-hello and server-hello messages where they appear + * There is a designated class in PcapPlusPlus called pcpp::SSLCipherSuite which represents the cipher-suites and + * provides access to their attributes. Then there is a static instance of this class for each one of the supported + * cipher-suites. + * This means there are 300+ static instances of pcpp::SSLCipherSuite representing the different cipher suites. The user + * can access them through static methods in pcpp::SSLCipherSuite or from client-hello and server-hello messages where + * they appear. * *

* @@ -144,15 +147,16 @@ * * SSL/TLS handshake messages, specifically client-hello and server-hello usually include extensions. There are various * types of extensions - some are more broadly used, some are less. In PcapPlusPlus there is a base class for all - * extensions: pcpp::SSLExtension. This class is instantiable and represents a generic extension, which means extension data - * isn't parsed and given to the user as raw data. Currently there are only two extension that are fully parsed which are - * server-name-indication (pcpp::SSLServerNameIndicationExtension) and SupportedVersions (pcpp::SSLSupportedVersionsExtension). + * extensions: pcpp::SSLExtension. This class is instantiable and represents a generic extension, which means extension + * data isn't parsed and given to the user as raw data. Currently there are only two extension that are fully parsed + * which are server-name-indication (pcpp::SSLServerNameIndicationExtension) and SupportedVersions + * (pcpp::SSLSupportedVersionsExtension). * Both inherit from pcpp::SSLExtension and add additional parsing relevant for the specific extension. * All other extensions aren't parsed and are represented by instance of pcpp::SSLExtension. - * Access to extensions is done through the handshake messages classes, specifically pcpp::SSLClientHelloMessage and pcpp::SSLServerHelloMessage + * Access to extensions is done through the handshake messages classes, specifically pcpp::SSLClientHelloMessage and + * pcpp::SSLServerHelloMessage */ - /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib @@ -164,13 +168,12 @@ namespace pcpp * @class SSLLayer * The base class for the 4 record type classes. Each record type is represented as a layer. See SSLLayer.h for * detailed explanation of the TLS/SSL protocol support in PcapPlusPlus. - * This class provides the common functionality used by all record types and also contains static methods for identifying - * an creating SSL/TLS record type layers + * This class provides the common functionality used by all record types and also contains static methods for + * identifying an creating SSL/TLS record type layers */ class SSLLayer : public Layer { public: - /** * A static method that checks whether the port is considered as SSL/TLS * @param[in] port The port number to be checked @@ -178,9 +181,9 @@ namespace pcpp static inline bool isSSLPort(uint16_t port); /** - * A static methods that gets raw data of a layer and checks whether this data is a SSL/TLS record or not. This check is - * done using the source/dest port and matching of a legal record type in the raw data. The list of ports identified - * as SSL/TLS is hard-coded and includes the following ports: + * A static methods that gets raw data of a layer and checks whether this data is a SSL/TLS record or not. This + * check is done using the source/dest port and matching of a legal record type in the raw data. The list of + * ports identified as SSL/TLS is hard-coded and includes the following ports: * - Port 443 [HTTPS] * - Port 261 [NSIIOPS] * - Port 448 [DDM-SSL] @@ -200,11 +203,12 @@ namespace pcpp * criteria to identify SSL/TLS packets * @param[in] data The data to check * @param[in] dataLen Length (in bytes) of the data - * @param[in] ignorePorts SSL/TLS ports are only relevant for parsing the first SSL/TLS message, but are not relevant - * for parsing subsequent messages. This parameter can be set to "true" to skip SSL/TLS ports check. This is an - * optional parameter and its default is "false" + * @param[in] ignorePorts SSL/TLS ports are only relevant for parsing the first SSL/TLS message, but are not + * relevant for parsing subsequent messages. This parameter can be set to "true" to skip SSL/TLS ports check. + * This is an optional parameter and its default is "false" */ - static bool IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, bool ignorePorts = false); + static bool IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, + bool ignorePorts = false); /** * A static method that creates SSL/TLS layers by raw data. This method parses the raw data, finds if and which @@ -214,16 +218,20 @@ namespace pcpp * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in - * @return A pointer to the newly created record layer. If no SSL/TLS record could be identified from the raw data - * NULL is returned + * @return A pointer to the newly created record layer. If no SSL/TLS record could be identified from the raw + * data NULL is returned */ static SSLLayer* createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /** - * Get a pointer to the record header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the record header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref ssl_tls_record_layer */ - ssl_tls_record_layer* getRecordLayer() const { return (ssl_tls_record_layer*)m_Data; } + ssl_tls_record_layer* getRecordLayer() const + { + return (ssl_tls_record_layer*)m_Data; + } /** * @return The SSL/TLS version used in this record (parsed from the record) @@ -248,22 +256,31 @@ namespace pcpp */ void parseNextLayer(); - OsiModelLayer getOsiModelLayer() const { return OsiModelPresentationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelPresentationLayer; + } protected: - SSLLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = SSL; } - - }; // class SSLLayer + SSLLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = SSL; + } + }; // class SSLLayer + // The graph below will break the code formatting, so it's disabled. + // clang-format off /** * @class SSLHandshakeLayer - * Represents SSL/TLS handshake layer. This layer may contain one or more handshake messages (all of them inherit from - * the base class SSLHandshakeMessage) which are the SSL/TLS handshake message sent between a client and a server until - * they establish a secure connection (e.g client-hello, server-hello, certificate, client-key-exchange, - * server-key-exchange, etc.). Usually this layer will contain just one message (as the first example below - * demonstrates). But there are cases a layer may contain more than 1 message. To better explain this layer structure - * we'll use 2 examples. The first will be client-hello message. The layer structure will look like this: + * Represents SSL/TLS handshake layer. This layer may contain one or more handshake messages (all of them inherit + * from the base class SSLHandshakeMessage) which are the SSL/TLS handshake message sent between a client and a + * server until they establish a secure connection (e.g client-hello, server-hello, certificate, + * client-key-exchange, server-key-exchange, etc.). + * Usually this layer will contain just one message (as the first example below + * demonstrates). But there are cases a layer may contain more than 1 message. To better explain this layer + * structure. We'll use 2 examples. The first will be client-hello message. The layer structure will look like this: @verbatim |------------------- SSLHandshakeLayer ----------------------| @@ -281,8 +298,8 @@ namespace pcpp | yyy @endverbatim - * Second example is a multiple-message handshake layer comprises of server-hello, certificate and server-key-exchange - * messages: + * Second example is a multiple-message handshake layer comprises of server-hello, certificate and + * server-key-exchange messages: @verbatim @@ -299,10 +316,10 @@ namespace pcpp (22) xxx | version,length | | @endverbatim */ - class SSLHandshakeLayer: public SSLLayer + // clang-format on + class SSLHandshakeLayer : public SSLLayer { public: - /** * C'tor for this class that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -315,12 +332,15 @@ namespace pcpp /** * @return The number of messages in this layer instance */ - size_t getHandshakeMessagesCount() const { return m_MessageList.size(); } + size_t getHandshakeMessagesCount() const + { + return m_MessageList.size(); + } /** - * Get a pointer to an handshake message by index. The message are numbered according to their order of appearance - * in the layer. If index is out of bounds (less than 0 or larger than total amount of message) NULL will be - * returned + * Get a pointer to an handshake message by index. The message are numbered according to their order of + * appearance in the layer. If index is out of bounds (less than 0 or larger than total amount of message) NULL + * will be returned * @param[in] index The index of the message to return * @return The pointer to the message object or NULL if index is out of bounds */ @@ -330,8 +350,7 @@ namespace pcpp * A templated method to get a message of a certain type. If no message of such type is found, NULL is returned * @return A pointer to the message of the requested type, NULL if not found */ - template - THandshakeMessage* getHandshakeMessageOfType() const; + template THandshakeMessage* getHandshakeMessageOfType() const; /** * A templated method to get the first message of a certain type, starting to search from a certain message. @@ -342,7 +361,7 @@ namespace pcpp * @param[in] after A pointer to the message to start search from * @return A pointer to the message of the requested type, NULL if not found */ - template + template THandshakeMessage* getNextHandshakeMessageOfType(const SSLHandshakeMessage* after) const; // implement abstract methods @@ -352,22 +371,21 @@ namespace pcpp /** * There are no calculated fields for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} private: PointerVector m_MessageList; - }; // class SSLHandshakeLayer - + }; // class SSLHandshakeLayer /** * @class SSLChangeCipherSpecLayer - * Represents SSL/TLS change-cipher-spec layer. This layer has no additional fields besides common fields described in - * SSLLayer + * Represents SSL/TLS change-cipher-spec layer. This layer has no additional fields besides common fields described + * in SSLLayer */ class SSLChangeCipherSpecLayer : public SSLLayer { public: - /** * C'tor for this class that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -376,9 +394,11 @@ namespace pcpp * @param[in] packet A pointer to the Packet instance where layer will be stored in */ SSLChangeCipherSpecLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : SSLLayer(data, dataLen, prevLayer, packet) {} + : SSLLayer(data, dataLen, prevLayer, packet) + {} - ~SSLChangeCipherSpecLayer() {} + ~SSLChangeCipherSpecLayer() + {} // implement abstract methods @@ -387,19 +407,18 @@ namespace pcpp /** * There are no calculated fields for this layer */ - void computeCalculateFields() {} - }; // class SSLChangeCipherSpecLayer - + void computeCalculateFields() + {} + }; // class SSLChangeCipherSpecLayer /** * @class SSLAlertLayer - * Represents SSL/TLS alert layer. Inherits from SSLLayer and adds parsing functionality such as retrieving the alert - * level and description + * Represents SSL/TLS alert layer. Inherits from SSLLayer and adds parsing functionality such as retrieving the + * alert level and description */ class SSLAlertLayer : public SSLLayer { public: - /** * C'tor for this class that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -408,9 +427,11 @@ namespace pcpp * @param[in] packet A pointer to the Packet instance where layer will be stored in */ SSLAlertLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : SSLLayer(data, dataLen, prevLayer, packet) {} + : SSLLayer(data, dataLen, prevLayer, packet) + {} - ~SSLAlertLayer() {} + ~SSLAlertLayer() + {} /** * @return SSL/TLS alert level. Will return ::SSL_ALERT_LEVEL_ENCRYPTED if alert is encrypted @@ -429,9 +450,9 @@ namespace pcpp /** * There are no calculated fields for this layer */ - void computeCalculateFields() {} - }; // class SSLAlertLayer - + void computeCalculateFields() + {} + }; // class SSLAlertLayer /** * @class SSLApplicationDataLayer @@ -441,7 +462,6 @@ namespace pcpp class SSLApplicationDataLayer : public SSLLayer { public: - /** * C'tor for this class that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -450,9 +470,11 @@ namespace pcpp * @param[in] packet A pointer to the Packet instance where layer will be stored in */ SSLApplicationDataLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : SSLLayer(data, dataLen, prevLayer, packet) {} + : SSLLayer(data, dataLen, prevLayer, packet) + {} - ~SSLApplicationDataLayer() {} + ~SSLApplicationDataLayer() + {} /** * @return A pointer to the encrypted data. This data can be decrypted only if you have the symmetric key @@ -472,27 +494,25 @@ namespace pcpp /** * There are no calculated fields for this layer */ - void computeCalculateFields() {} - }; // class SSLApplicationDataLayer - + void computeCalculateFields() + {} + }; // class SSLApplicationDataLayer - template - THandshakeMessage* SSLHandshakeLayer::getHandshakeMessageOfType() const + template THandshakeMessage* SSLHandshakeLayer::getHandshakeMessageOfType() const { size_t vecSize = m_MessageList.size(); for (size_t i = 0; i < vecSize; i++) { SSLHandshakeMessage* curElem = const_cast(m_MessageList.at(i)); - if (dynamic_cast(curElem) != NULL) - return (THandshakeMessage*)curElem; + if (dynamic_cast(curElem) != NULL) + return (THandshakeMessage*)curElem; } // element not found return NULL; - } // getHandshakeMessageOfType + } // getHandshakeMessageOfType - - template + template THandshakeMessage* SSLHandshakeLayer::getNextHandshakeMessageOfType(const SSLHandshakeMessage* after) const { size_t vecSize = m_MessageList.size(); @@ -510,43 +530,42 @@ namespace pcpp if (afterIndex == vecSize) return NULL; - for (size_t i = afterIndex+1; i < vecSize; i++) + for (size_t i = afterIndex + 1; i < vecSize; i++) { SSLHandshakeMessage* curElem = const_cast(m_MessageList.at(i)); - if (dynamic_cast(curElem) != NULL) - return (THandshakeMessage*)curElem; + if (dynamic_cast(curElem) != NULL) + return (THandshakeMessage*)curElem; } // element not found return NULL; - } // getNextHandshakeMessageOfType - + } // getNextHandshakeMessageOfType // implementation of inline methods bool SSLLayer::isSSLPort(uint16_t port) { - if (port == 443) // HTTPS, this is likely case + if (port == 443) // HTTPS, this is likely case return true; switch (port) { - case 261: // NSIIOPS - case 448: // DDM-SSL - case 465: // SMTPS - case 563: // NNTPS - case 614: // SSHELL - case 636: // LDAPS - case 989: // FTPS - data - case 990: // FTPS - control - case 992: // Telnet over TLS/SSL - case 993: // IMAPS - case 994: // IRCS - case 995: // POP3S + case 261: // NSIIOPS + case 448: // DDM-SSL + case 465: // SMTPS + case 563: // NNTPS + case 614: // SSHELL + case 636: // LDAPS + case 989: // FTPS - data + case 990: // FTPS - control + case 992: // Telnet over TLS/SSL + case 993: // IMAPS + case 994: // IRCS + case 995: // POP3S return true; default: return false; } - } // isSSLPort + } // isSSLPort -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SdpLayer.h b/Packet++/header/SdpLayer.h index 457fab5994..067f4d8feb 100644 --- a/Packet++/header/SdpLayer.h +++ b/Packet++/header/SdpLayer.h @@ -16,50 +16,50 @@ namespace pcpp /** Protocol version (v) */ #define PCPP_SDP_PROTOCOL_VERSION_FIELD "v" /** Originator and session identifier (o) */ -#define PCPP_SDP_ORIGINATOR_FIELD "o" +#define PCPP_SDP_ORIGINATOR_FIELD "o" /** Session name (s) */ -#define PCPP_SDP_SESSION_NAME_FIELD "s" +#define PCPP_SDP_SESSION_NAME_FIELD "s" /** Session title, media title or short information (i) */ -#define PCPP_SDP_INFO_FIELD "i" +#define PCPP_SDP_INFO_FIELD "i" /** URI of description (u) */ -#define PCPP_SDP_URI_FIELD "u" +#define PCPP_SDP_URI_FIELD "u" /** Email address with optional name of contacts (e) */ -#define PCPP_SDP_EMAIL_FIELD "e" +#define PCPP_SDP_EMAIL_FIELD "e" /** Phone number with optional name of contacts (p) */ -#define PCPP_SDP_PHONE_FIELD "p" +#define PCPP_SDP_PHONE_FIELD "p" /** Connection information (c) */ -#define PCPP_SDP_CONNECTION_INFO_FIELD "c" +#define PCPP_SDP_CONNECTION_INFO_FIELD "c" /** Bandwidth information (b) */ -#define PCPP_SDP_BANDWIDTH_FIELD "b" +#define PCPP_SDP_BANDWIDTH_FIELD "b" /** Time the session is active (t) */ -#define PCPP_SDP_TIME_FIELD "t" +#define PCPP_SDP_TIME_FIELD "t" /** Repeat times (r) */ -#define PCPP_SDP_REPEAT_TIMES_FIELD "r" +#define PCPP_SDP_REPEAT_TIMES_FIELD "r" /** Time zone adjustments (z) */ -#define PCPP_SDP_TIME_ZONE_FIELD "z" +#define PCPP_SDP_TIME_ZONE_FIELD "z" /** Encryption key (k) */ -#define PCPP_SDP_ENCRYPTION_KEY_FIELD "k" +#define PCPP_SDP_ENCRYPTION_KEY_FIELD "k" /** Media attribute (a) */ -#define PCPP_SDP_MEDIA_ATTRIBUTE_FIELD "a" +#define PCPP_SDP_MEDIA_ATTRIBUTE_FIELD "a" /** Media name and transport address (m) */ -#define PCPP_SDP_MEDIA_NAME_FIELD "m" +#define PCPP_SDP_MEDIA_NAME_FIELD "m" /** * @class SdpLayer - * Represents a SDP (Session Description Protocol) message. SDP is a text-based protocol described by a series of fields, one per line (lines are separated by CRLF). - * The form of each field is as follows:
+ * Represents a SDP (Session Description Protocol) message. SDP is a text-based protocol described by a series of + * fields, one per line (lines are separated by CRLF). The form of each field is as follows:
* @code * [character]=[value] * @endcode * Each character represents a certain type of field. All field type are represented as macros in SdpLayer.h file * (for example: PCPP_SDP_ORIGINATOR_FIELD is a macro for the originator field (o=) ).
- * For more details about SDP structure please refer to its Wikipedia page: https://en.wikipedia.org/wiki/Session_Description_Protocol + * For more details about SDP structure please refer to its Wikipedia page: + * https://en.wikipedia.org/wiki/Session_Description_Protocol */ class SdpLayer : public TextBasedProtocolMessage { public: - - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer @@ -92,46 +92,57 @@ namespace pcpp * @param[in] startTime The start time of the session * @param[in] stopTime The stop time of the session */ - SdpLayer(const std::string& username, long sessionID, long sessionVersion, IPv4Address ipAddress, const std::string& sessionName, long startTime, long stopTime); + SdpLayer(const std::string& username, long sessionID, long sessionVersion, IPv4Address ipAddress, + const std::string& sessionName, long startTime, long stopTime); - ~SdpLayer() {} + ~SdpLayer() + {} /** * A copy constructor for this layer. Inherits the base copy constructor and doesn't add * anything else * @param[in] other The instance to copy from */ - SdpLayer(const SdpLayer& other) : TextBasedProtocolMessage(other) {} + SdpLayer(const SdpLayer& other) : TextBasedProtocolMessage(other) + {} /** * An assignment operator overload for this layer. Inherits the base assignment operator * and doesn't add anything else * @param[in] other The instance to copy from */ - SdpLayer& operator=(const SdpLayer& other) { TextBasedProtocolMessage::operator=(other); return *this; } + SdpLayer& operator=(const SdpLayer& other) + { + TextBasedProtocolMessage::operator=(other); + return *this; + } /** * The 'originator' field (o=) contains the IP address of the the machine from which the session is created. - * This IP address can be used to track the RTP data relevant for the call. This method extracts this IP address from the 'originator' field and returns it. - * A value of IPv4Address#Zero will be returned in the following cases: (1) if 'originator' field doesn't exist; (2) if it doesn't contain the IP address; - * (3) if it contains a non-IPv4 address + * This IP address can be used to track the RTP data relevant for the call. This method extracts this IP address + * from the 'originator' field and returns it. A value of IPv4Address#Zero will be returned in the following + * cases: (1) if 'originator' field doesn't exist; (2) if it doesn't contain the IP address; (3) if it contains + * a non-IPv4 address * @return The IP address of the the machine from which the session is created */ IPv4Address getOwnerIPv4Address() const; /** - * The 'media-description' field (m=) contains the transport port to which the media stream is sent. This port can be used to track the RTP data relevant for the call. - * This method extracts this port from the 'media-description' field and returns it. Since a SDP message can contain several 'media-description' fields, one for each media type - * (e.g audio, image, etc.), the user is required to provide the media type. A value of 0 will be returned in the following cases: (1) if 'media-description' field doesn't - * exist; (2) if provided media type was not found; (3) if 'media-description' field didn't contain a port + * The 'media-description' field (m=) contains the transport port to which the media stream is sent. This port + * can be used to track the RTP data relevant for the call. This method extracts this port from the + * 'media-description' field and returns it. Since a SDP message can contain several 'media-description' fields, + * one for each media type (e.g audio, image, etc.), the user is required to provide the media type. A value of + * 0 will be returned in the following cases: (1) if 'media-description' field doesn't exist; (2) if provided + * media type was not found; (3) if 'media-description' field didn't contain a port * @param[in] mediaType The media type to search in * @return The transport port to which the media stream is sent */ uint16_t getMediaPort(const std::string& mediaType) const; /** - * Adds a 'media-description' field (m=) with all necessary data and attribute fields (a=) with data relevant for this media.
- * After this method is run the following block of fields will be added at the end of the message: + * Adds a 'media-description' field (m=) with all necessary data and attribute fields (a=) with data relevant + * for this media.
After this method is run the following block of fields will be added at the end of the + * message: * * @code * m=[mediaType] [mediaPort] [mediaProtocol] [mediaFormat] @@ -148,19 +159,27 @@ namespace pcpp * translated into a 'media-attribute' field (a=) * @return True if all fields were added properly or false if at least one field was failed to be added */ - bool addMediaDescription(const std::string& mediaType, uint16_t mediaPort, const std::string& mediaProtocol, const std::string& mediaFormat, const std::vector &mediaAttributes); + bool addMediaDescription(const std::string& mediaType, uint16_t mediaPort, const std::string& mediaProtocol, + const std::string& mediaFormat, const std::vector& mediaAttributes); // overridden methods - OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelSesionLayer; + } std::string toString() const; protected: - // implementation of abstract methods - char getHeaderFieldNameValueSeparator() const { return '='; } - bool spacesAllowedBetweenHeaderFieldNameAndValue() const { return false; } - + char getHeaderFieldNameValueSeparator() const + { + return '='; + } + bool spacesAllowedBetweenHeaderFieldNameAndValue() const + { + return false; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/SingleCommandTextProtocol.h b/Packet++/header/SingleCommandTextProtocol.h index f437febc03..dea2af9dc9 100644 --- a/Packet++/header/SingleCommandTextProtocol.h +++ b/Packet++/header/SingleCommandTextProtocol.h @@ -23,8 +23,10 @@ namespace pcpp bool hyphenRequired(const std::string& value); protected: - SingleCommandTextProtocol(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : Layer(data, dataLen, prevLayer, packet) {}; - SingleCommandTextProtocol(const std::string &command, const std::string &option); + SingleCommandTextProtocol(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) {}; + + SingleCommandTextProtocol(const std::string& command, const std::string& option); bool setCommandInternal(std::string value); bool setCommandOptionInternal(std::string value); @@ -33,9 +35,9 @@ namespace pcpp std::string getCommandOptionInternal() const; public: - /** - * Checks if the current message is a multi-line reply. Multi-line messages are indicated with a Hyphen (-) immediately after reply code. + * Checks if the current message is a multi-line reply. Multi-line messages are indicated with a Hyphen (-) + * immediately after reply code. * @return true If this is a multi-line reply * @return false Otherwise */ @@ -48,6 +50,6 @@ namespace pcpp * @param[in] dataSize The byte array size (in bytes) * @return True if the data is identified as single command text based message */ - static bool isDataValid(const uint8_t *data, size_t dataSize); + static bool isDataValid(const uint8_t* data, size_t dataSize); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SipLayer.h b/Packet++/header/SipLayer.h index 740fcb5602..31e1f53d37 100644 --- a/Packet++/header/SipLayer.h +++ b/Packet++/header/SipLayer.h @@ -13,101 +13,108 @@ namespace pcpp // some popular SIP header fields /** From field */ -#define PCPP_SIP_FROM_FIELD "From" +#define PCPP_SIP_FROM_FIELD "From" /** To field */ -#define PCPP_SIP_TO_FIELD "To" +#define PCPP_SIP_TO_FIELD "To" /** Via field */ -#define PCPP_SIP_VIA_FIELD "Via" +#define PCPP_SIP_VIA_FIELD "Via" /** Call-ID field */ -#define PCPP_SIP_CALL_ID_FIELD "Call-ID" +#define PCPP_SIP_CALL_ID_FIELD "Call-ID" /** Content-Type field */ -#define PCPP_SIP_CONTENT_TYPE_FIELD "Content-Type" +#define PCPP_SIP_CONTENT_TYPE_FIELD "Content-Type" /** Content-Length field */ -#define PCPP_SIP_CONTENT_LENGTH_FIELD "Content-Length" +#define PCPP_SIP_CONTENT_LENGTH_FIELD "Content-Length" /** Content-Disposition field */ #define PCPP_SIP_CONTENT_DISPOSITION_FIELD "Content-Disposition" /** Content-Encoding field */ -#define PCPP_SIP_CONTENT_ENCODING_FIELD "Content-Encoding" +#define PCPP_SIP_CONTENT_ENCODING_FIELD "Content-Encoding" /** Content-Language field */ -#define PCPP_SIP_CONTENT_LANGUAGE_FIELD "Content-Language" +#define PCPP_SIP_CONTENT_LANGUAGE_FIELD "Content-Language" /** CSeq field */ -#define PCPP_SIP_CSEQ_FIELD "CSeq" +#define PCPP_SIP_CSEQ_FIELD "CSeq" /** Contact field */ -#define PCPP_SIP_CONTACT_FIELD "Contact" +#define PCPP_SIP_CONTACT_FIELD "Contact" /** Max-Forwards field */ -#define PCPP_SIP_MAX_FORWARDS_FIELD "Max-Forwards" +#define PCPP_SIP_MAX_FORWARDS_FIELD "Max-Forwards" /** User-Agent field */ -#define PCPP_SIP_USER_AGENT_FIELD "User-Agent" +#define PCPP_SIP_USER_AGENT_FIELD "User-Agent" /** Accept field */ -#define PCPP_SIP_ACCEPT_FIELD "Accept" +#define PCPP_SIP_ACCEPT_FIELD "Accept" /** Accept-Encoding field */ -#define PCPP_SIP_ACCEPT_ENCODING_FIELD "Accept-Encoding" +#define PCPP_SIP_ACCEPT_ENCODING_FIELD "Accept-Encoding" /** Accept-Language field */ -#define PCPP_SIP_ACCEPT_LANGUAGE_FIELD "Accept-Language" +#define PCPP_SIP_ACCEPT_LANGUAGE_FIELD "Accept-Language" /** Allow field */ -#define PCPP_SIP_ALLOW_FIELD "Allow" +#define PCPP_SIP_ALLOW_FIELD "Allow" /** Authorization field */ -#define PCPP_SIP_AUTHORIZATION_FIELD "Authorization" +#define PCPP_SIP_AUTHORIZATION_FIELD "Authorization" /** Date field */ -#define PCPP_SIP_DATE_FIELD "Date" +#define PCPP_SIP_DATE_FIELD "Date" /** MIME-Version field */ -#define PCPP_SIP_MIME_VERSION_FIELD "MIME-Version" +#define PCPP_SIP_MIME_VERSION_FIELD "MIME-Version" /** Reason field */ -#define PCPP_SIP_REASON_FIELD "Reason" +#define PCPP_SIP_REASON_FIELD "Reason" /** Supported field */ -#define PCPP_SIP_SUPPORTED_FIELD "Supported" +#define PCPP_SIP_SUPPORTED_FIELD "Supported" /** Server field */ -#define PCPP_SIP_SERVER_FIELD "Server" +#define PCPP_SIP_SERVER_FIELD "Server" /** WWW-Authenticate fild */ -#define PCPP_SIP_WWW_AUTHENTICATE_FIELD "WWW-Authenticate" +#define PCPP_SIP_WWW_AUTHENTICATE_FIELD "WWW-Authenticate" /** Retry-After field */ -#define PCPP_SIP_RETRY_AFTER_FIELD "Retry-After" +#define PCPP_SIP_RETRY_AFTER_FIELD "Retry-After" /** Record-Route field */ -#define PCPP_SIP_RECORD_ROUTE_FIELD "Record-Route" - +#define PCPP_SIP_RECORD_ROUTE_FIELD "Record-Route" /** * @class SipLayer - * Represents a general SIP message. It's an abstract class and cannot be instantiated. It's inherited by SipRequestLayer and SipResponseLayer + * Represents a general SIP message. It's an abstract class and cannot be instantiated. It's inherited by + * SipRequestLayer and SipResponseLayer */ class SipLayer : public TextBasedProtocolMessage { public: - /** - * The length of the body of many SIP response messages is determined by a SIP header field called "Content-Length". This method - * parses this field, extracts its value and return it. If this field doesn't exist 0 is returned + * The length of the body of many SIP response messages is determined by a SIP header field called + * "Content-Length". This method parses this field, extracts its value and return it. If this field doesn't + * exist 0 is returned * @return SIP response body length determined by "Content-Length" field */ int getContentLength() const; /** - * The length of the body of many SIP messages is determined by a header field called "Content-Length". This method sets - * The content-length field value. The method supports several cases: + * The length of the body of many SIP messages is determined by a header field called "Content-Length". This + * method sets The content-length field value. The method supports several cases: * - If the "Content-Length" field exists - the method will only replace the existing value with the new value - * - If the "Content-Length" field doesn't exist - the method will create this field and put the value in it. Here are also 2 cases: + * - If the "Content-Length" field doesn't exist - the method will create this field and put the value in it. + * Here are also 2 cases: * - If prevFieldName is specified - the new "Content-Length" field will be created after it - * - If prevFieldName isn't specified or doesn't exist - the new "Content-Length" field will be created as the last field before - * end-of-header field + * - If prevFieldName isn't specified or doesn't exist - the new "Content-Length" field will be created as the + * last field before end-of-header field * * @param[in] contentLength The content length value to set - * @param[in] prevFieldName Optional parameter, if specified and "Content-Length" field doesn't exist, it will be created after this field + * @param[in] prevFieldName Optional parameter, if specified and "Content-Length" field doesn't exist, it will + * be created after this field * @return A pointer to the "Content-Length" field, or NULL if creation failed */ - HeaderField* setContentLength(int contentLength, const std::string &prevFieldName = ""); + HeaderField* setContentLength(int contentLength, const std::string& prevFieldName = ""); // Overridden methods - OsiModelLayer getOsiModelLayer() const { return OsiModelSesionLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelSesionLayer; + } /** * Currently identifies only SDP if content-length field exists and set to a value greater than zero. - * If content-length field doesn't exist or set to zero and still there is data after this layer, a PayloadLayer will be created + * If content-length field doesn't exist or set to zero and still there is data after this layer, a PayloadLayer + * will be created */ void parseNextLayer(); /** - * Set the content-length only if a content-length field already exists and if its current value is different than the total length of the next layer(s) + * Set the content-length only if a content-length field already exists and if its current value is different + * than the total length of the next layer(s) */ void computeCalculateFields(); @@ -115,31 +122,46 @@ namespace pcpp * A static method that checks whether the port is considered as SIP * @param[in] port The port number to be checked */ - static bool isSipPort(uint16_t port) { return port == 5060 || port == 5061; } + static bool isSipPort(uint16_t port) + { + return port == 5060 || port == 5061; + } protected: - SipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) {} - SipLayer() : TextBasedProtocolMessage() {} - SipLayer(const SipLayer& other) : TextBasedProtocolMessage(other) {} - SipLayer& operator=(const SipLayer& other) { TextBasedProtocolMessage::operator=(other); return *this; } + SipLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) + {} + SipLayer() : TextBasedProtocolMessage() + {} + SipLayer(const SipLayer& other) : TextBasedProtocolMessage(other) + {} + SipLayer& operator=(const SipLayer& other) + { + TextBasedProtocolMessage::operator=(other); + return *this; + } // implementation of abstract methods - char getHeaderFieldNameValueSeparator() const { return ':'; } - bool spacesAllowedBetweenHeaderFieldNameAndValue() const { return true; } + char getHeaderFieldNameValueSeparator() const + { + return ':'; + } + bool spacesAllowedBetweenHeaderFieldNameAndValue() const + { + return true; + } }; - class SipRequestFirstLine; - /** * @class SipRequestLayer * Represents a SIP request header and inherits all basic functionality of SipLayer and TextBasedProtocolMessage. - * The functionality that is added for this class is the SIP first line concept. A SIP request has the following first line: - * INVITE sip:bla@bla.com:12345 SIP/2.0 - * Since it's not an "ordinary" header field, it requires a special treatment and gets a class of it's own: SipRequestFirstLine. - * In most cases a SIP request will be contained in a single packet but for cases it is not, only the first packet will be identified as SIP - * request layer. You can find out whether the header is complete by using SipLayer#isHeaderComplete() + * The functionality that is added for this class is the SIP first line concept. A SIP request has the following + * first line: INVITE sip:bla@bla.com:12345 SIP/2.0 Since it's not an "ordinary" header field, it requires a + * special treatment and gets a class of it's own: SipRequestFirstLine. In most cases a SIP request will be + * contained in a single packet but for cases it is not, only the first packet will be identified as SIP request + * layer. You can find out whether the header is complete by using SipLayer#isHeaderComplete() */ class SipRequestLayer : public SipLayer { @@ -183,7 +205,7 @@ namespace pcpp SipMethodUnknown }; - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer @@ -192,8 +214,8 @@ namespace pcpp SipRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /** - * A constructor that allocates a new SIP request with only the first line filled. The request will be created without further fields. - * The user can then add fields using addField() or insertField() methods + * A constructor that allocates a new SIP request with only the first line filled. The request will be created + * without further fields. The user can then add fields using addField() or insertField() methods * @param[in] method The SIP method to be used in this SIP request * @param[in] requestUri The URI of the request * @param[in] version SIP version to be used in this request. Default is "SIP/2.0" @@ -210,8 +232,8 @@ namespace pcpp SipRequestLayer(const SipRequestLayer& other); /** - * An assignment operator overload for this layer. This method inherits base assignment operator SipLayer#operator=() and adds the functionality - * of copying the first line + * An assignment operator overload for this layer. This method inherits base assignment operator + * SipLayer#operator=() and adds the functionality of copying the first line * @param[in] other The instance to copy from */ SipRequestLayer& operator=(const SipRequestLayer& other); @@ -219,7 +241,10 @@ namespace pcpp /** * @return A pointer to the first line instance for this message */ - SipRequestFirstLine* getFirstLine() const { return m_FirstLine; } + SipRequestFirstLine* getFirstLine() const + { + return m_FirstLine; + } // implement Layer's abstract methods @@ -229,54 +254,58 @@ namespace pcpp SipRequestFirstLine* m_FirstLine; }; - - - class SipResponseFirstLine; - /** * @class SipResponseLayer * Represents an SIP response message and inherits all basic functionality of SipLayer and TextBasedProtocolMessage. - * The functionality that is added for this class is the SIP first line concept. A SIP response has the following first line: - * 200 OK SIP/2.0 - * Since it's not an "ordinary" header field, it requires a special treatment and gets a class of it's own: SipResponseFirstLine. - * In most cases a SIP response will be contained in a single packet but for cases it is not, only the first packet will be identified as SIP - * response layer. You can find out whether the header is complete by using SipLayer#isHeaderComplete() + * The functionality that is added for this class is the SIP first line concept. A SIP response has the following + * first line: 200 OK SIP/2.0 Since it's not an "ordinary" header field, it requires a special treatment and + * gets a class of it's own: SipResponseFirstLine. In most cases a SIP response will be contained in a single packet + * but for cases it is not, only the first packet will be identified as SIP response layer. You can find out whether + * the header is complete by using SipLayer#isHeaderComplete() */ class SipResponseLayer : public SipLayer { friend class SipResponseFirstLine; - public: + public: /** - * Enum for SIP response status codes. List is taken from Wikipedia: https://en.wikipedia.org/wiki/List_of_SIP_response_codes + * Enum for SIP response status codes. List is taken from Wikipedia: + * https://en.wikipedia.org/wiki/List_of_SIP_response_codes */ enum SipResponseStatusCode { - /** Extended search being performed may take a significant time so a forking proxy must send a 100 Trying response */ + /** Extended search being performed may take a significant time so a forking proxy must send a 100 Trying + * response */ Sip100Trying, /** Destination user agent received INVITE, and is alerting user of call */ Sip180Ringing, /** Servers can optionally send this response to indicate a call is being forwarded */ Sip181CallisBeingForwarded, - /** Indicates that the destination was temporarily unavailable, so the server has queued the call until the destination is available. A server may send multiple 182 responses to update progress of the queue */ + /** Indicates that the destination was temporarily unavailable, so the server has queued the call until the + * destination is available. A server may send multiple 182 responses to update progress of the queue */ Sip182Queued, /** This response may be used to send extra information for a call which is still being set up */ Sip183SessioninProgress, - /** Can be used by User Agent Server to indicate to upstream SIP entities (including the User Agent Client (UAC)) that an early dialog has been terminated */ + /** Can be used by User Agent Server to indicate to upstream SIP entities (including the User Agent Client + * (UAC)) that an early dialog has been terminated */ Sip199EarlyDialogTerminated, /** Indicates the request was successful */ Sip200OK, - /** Indicates that the request has been accepted for processing, but the processing has not been completed */ + /** Indicates that the request has been accepted for processing, but the processing has not been completed + */ Sip202Accepted, /** Indicates the request was successful, but the corresponding response will not be received */ Sip204NoNotification, - /** The address resolved to one of several options for the user or client to choose between, which are listed in the message body or the message's Contact fields */ + /** The address resolved to one of several options for the user or client to choose between, which are + * listed in the message body or the message's Contact fields */ Sip300MultipleChoices, - /** The original Request-URI is no longer valid, the new address is given in the Contact header field, and the client should update any records of the original Request-URI with the new value */ + /** The original Request-URI is no longer valid, the new address is given in the Contact header field, and + * the client should update any records of the original Request-URI with the new value */ Sip301MovedPermanently, - /** The client should try at the address in the Contact field. If an Expires field is present, the client may cache the result for that period of time */ + /** The client should try at the address in the Contact field. If an Expires field is present, the client + * may cache the result for that period of time */ Sip302MovedTemporarily, /** The Contact field details a proxy that must be used to access the requested destination */ Sip305UseProxy, @@ -290,15 +319,21 @@ namespace pcpp Sip402PaymentRequired, /** The server understood the request, but is refusing to fulfill it */ Sip403Forbidden, - /** The server has definitive information that the user does not exist at the domain specified in the Request-URI. This status is also returned if the domain in the Request-URI does not match any of the domains handled by the recipient of the request */ + /** The server has definitive information that the user does not exist at the domain specified in the + * Request-URI. This status is also returned if the domain in the Request-URI does not match any of the + * domains handled by the recipient of the request */ Sip404NotFound, - /** The method specified in the Request-Line is understood, but not allowed for the address identified by the Request-URI */ + /** The method specified in the Request-Line is understood, but not allowed for the address identified by + * the Request-URI */ Sip405MethodNotAllowed, - /** The resource identified by the request is only capable of generating response entities that have content characteristics but not acceptable according to the Accept header field sent in the request */ + /** The resource identified by the request is only capable of generating response entities that have content + * characteristics but not acceptable according to the Accept header field sent in the request */ Sip406NotAcceptable, /** The request requires user authentication. This response is issued by proxies */ Sip407ProxyAuthenticationRequired, - /** Couldn't find the user in time. The server could not produce a response within a suitable amount of time, for example, if it could not determine the location of the user in time. The client MAY repeat the request without modifications at any later time */ + /** Couldn't find the user in time. The server could not produce a response within a suitable amount of + * time, for example, if it could not determine the location of the user in time. The client MAY repeat the + * request without modifications at any later time */ Sip408RequestTimeout, /** User already registered */ Sip409Conflict, @@ -310,7 +345,8 @@ namespace pcpp Sip412ConditionalRequestFailed, /** Request body too large */ Sip413RequestEntityTooLarge, - /** The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret */ + /** The server is refusing to service the request because the Request-URI is longer than the server is + * willing to interpret */ Sip414RequestURITooLong, /** Request body in a format not supported */ Sip415UnsupportedMediaType, @@ -328,13 +364,16 @@ namespace pcpp Sip423IntervalTooBrief, /** The request's location content was malformed or otherwise unsatisfactory */ Sip424BadLocationInformation, - /** The server rejected a non-interactive emergency call, indicating that the request was malformed enough that no reasonable emergency response to the alert can be determined */ + /** The server rejected a non-interactive emergency call, indicating that the request was malformed enough + * that no reasonable emergency response to the alert can be determined */ Sip425BadAlertMessage, /** The server policy requires an Identity header, and one has not been provided */ Sip428UseIdentityHeader, /** The server did not receive a valid Referred-By token on the request */ Sip429ProvideReferrerIdentity, - /** A specific flow to a user agent has failed, although other flows may succeed. This response is intended for use between proxy devices, and should not be seen by an endpoint (and if it is seen by one, should be treated as a 400 Bad Request response) */ + /** A specific flow to a user agent has failed, although other flows may succeed. This response is intended + * for use between proxy devices, and should not be seen by an endpoint (and if it is seen by one, should be + * treated as a 400 Bad Request response) */ Sip430FlowFailed, /** The request has been rejected because it was anonymous */ Sip433AnonymityDisallowed, @@ -342,13 +381,20 @@ namespace pcpp Sip436BadIdentityInfo, /** The server was unable to validate a certificate for the domain that signed the request */ Sip437UnsupportedCertificate, - /** The server obtained a valid certificate that the request claimed was used to sign the request, but was unable to verify that signature */ + /** The server obtained a valid certificate that the request claimed was used to sign the request, but was + * unable to verify that signature */ Sip438InvalidIdentityHeader, - /** The first outbound proxy the user is attempting to register through does not support the "outbound" feature of RFC 5626, although the registrar does */ + /** The first outbound proxy the user is attempting to register through does not support the "outbound" + * feature of RFC 5626, although the registrar does */ Sip439FirstHopLacksOutboundSupport, - /** If a SIP proxy determines a response context has insufficient Incoming Max-Breadth to carry out a desired parallel fork, and the proxy is unwilling/unable to compensate by forking serially or sending a redirect, that proxy MUST return a 440 response. A client receiving a 440 response can infer that its request did not reach all possible destinations */ + /** If a SIP proxy determines a response context has insufficient Incoming Max-Breadth to carry out a + * desired parallel fork, and the proxy is unwilling/unable to compensate by forking serially or sending a + * redirect, that proxy MUST return a 440 response. A client receiving a 440 response can infer that its + * request did not reach all possible destinations */ Sip440MaxBreadthExceeded, - /** If a SIP UA receives an INFO request associated with an Info Package that the UA has not indicated willingness to receive, the UA MUST send a 469 response, which contains a Recv-Info header field with Info Packages for which the UA is willing to receive INFO requests */ + /** If a SIP UA receives an INFO request associated with an Info Package that the UA has not indicated + * willingness to receive, the UA MUST send a 469 response, which contains a Recv-Info header field with + * Info Packages for which the UA is willing to receive INFO requests */ Sip469BadInfoPackage, /** The source of the request did not have the permission of the recipient to make such a request */ Sip470ConsentNeeded, @@ -376,35 +422,48 @@ namespace pcpp Sip491RequestPending, /** Request contains an encrypted MIME body, which recipient can not decrypt */ Sip493Undecipherable, - /** The server has received a request that requires a negotiated security mechanism, and the response contains a list of suitable security mechanisms for the requester to choose between, or a digest authentication challenge */ + /** The server has received a request that requires a negotiated security mechanism, and the response + * contains a list of suitable security mechanisms for the requester to choose between, or a digest + * authentication challenge */ Sip494SecurityAgreementRequired, /** The server could not fulfill the request due to some unexpected condition */ Sip500ServerInternalError, - /** The server does not have the ability to fulfill the request, such as because it does not recognize the request method. (Compare with 405 Method Not Allowed, where the server recognizes the method but does not allow or support it.) */ + /** The server does not have the ability to fulfill the request, such as because it does not recognize the + * request method. (Compare with 405 Method Not Allowed, where the server recognizes the method but does not + * allow or support it.) */ Sip501NotImplemented, - /** The server is acting as a gateway or proxy, and received an invalid response from a downstream server while attempting to fulfill the request */ + /** The server is acting as a gateway or proxy, and received an invalid response from a downstream server + * while attempting to fulfill the request */ Sip502BadGateway, - /** The server is undergoing maintenance or is temporarily overloaded and so cannot process the request. A "Retry-After" header field may specify when the client may reattempt its request */ + /** The server is undergoing maintenance or is temporarily overloaded and so cannot process the request. A + * "Retry-After" header field may specify when the client may reattempt its request */ Sip503ServiceUnavailable, - /** The server attempted to access another server in attempting to process the request, and did not receive a prompt response */ + /** The server attempted to access another server in attempting to process the request, and did not receive + * a prompt response */ Sip504ServerTimeout, /** The SIP protocol version in the request is not supported by the server */ Sip505VersionNotSupported, /** The request message length is longer than the server can process */ Sip513MessageTooLarge, - /** The server does not support the push notification service identified in a 'pn-provider' SIP URI parameter */ + /** The server does not support the push notification service identified in a 'pn-provider' SIP URI + * parameter */ Sip555PushNotificationServiceNotSupported, /** The server is unable or unwilling to meet some constraints specified in the offer */ Sip580PreconditionFailure, - /** All possible destinations are busy. Unlike the 486 response, this response indicates the destination knows there are no alternative destinations (such as a voicemail server) able to accept the call */ + /** All possible destinations are busy. Unlike the 486 response, this response indicates the destination + * knows there are no alternative destinations (such as a voicemail server) able to accept the call */ Sip600BusyEverywhere, - /** The destination does not wish to participate in the call, or cannot do so, and additionally the destination knows there are no alternative destinations (such as a voicemail server) willing to accept the call */ + /** The destination does not wish to participate in the call, or cannot do so, and additionally the + * destination knows there are no alternative destinations (such as a voicemail server) willing to accept + * the call */ Sip603Decline, /** The server has authoritative information that the requested user does not exist anywhere */ Sip604DoesNotExistAnywhere, - /** The user's agent was contacted successfully but some aspects of the session description such as the requested media, bandwidth, or addressing style were not acceptable */ + /** The user's agent was contacted successfully but some aspects of the session description such as the + * requested media, bandwidth, or addressing style were not acceptable */ Sip606NotAcceptable, - /** The called party did not want this call from the calling party. Future attempts from the calling party are likely to be similarly rejected */ + /** The called party did not want this call from the calling party. Future attempts from the calling party + * are likely to be similarly rejected */ Sip607Unwanted, /** An intermediary machine or process rejected the call attempt */ Sip608Rejected, @@ -412,7 +471,7 @@ namespace pcpp SipStatusCodeUnknown }; - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer @@ -421,29 +480,31 @@ namespace pcpp SipResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); /** - * A constructor that allocates a new SIP response with only the first line filled. The request will be created without further fields. - * The user can then add fields using addField() or insertField() methods + * A constructor that allocates a new SIP response with only the first line filled. The request will be created + * without further fields. The user can then add fields using addField() or insertField() methods * @param[in] statusCode SIP status code to set * @param[in] statusCodeString Most status codes have their default string, e.g 200 is usually "OK" etc. - * But the user can set a non-default status code string and it will be written in the header first line. Empty string ("") means using the - * default status code string. Also, the default is using the default status code string + * But the user can set a non-default status code string and it will be written in the header first line. Empty + * string ("") means using the default status code string. Also, the default is using the default status code + * string * @param[in] sipVersion SIP version to set, default is SIP/2.0 * */ - explicit SipResponseLayer(SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString = "", const std::string& sipVersion = "SIP/2.0"); + explicit SipResponseLayer(SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString = "", + const std::string& sipVersion = "SIP/2.0"); virtual ~SipResponseLayer(); /** - * A copy constructor for this layer. This copy constructor inherits base copy constructor SipLayer and adds the functionality - * of copying the first line as well + * A copy constructor for this layer. This copy constructor inherits base copy constructor SipLayer and adds the + * functionality of copying the first line as well * @param[in] other The instance to copy from */ SipResponseLayer(const SipResponseLayer& other); /** - * An assignment operator overload for this layer. This method inherits base assignment operator SipLayer#operator=() and adds the functionality - * of copying the first line as well + * An assignment operator overload for this layer. This method inherits base assignment operator + * SipLayer#operator=() and adds the functionality of copying the first line as well * @param[in] other The instance to copy from */ SipResponseLayer& operator=(const SipResponseLayer& other); @@ -451,7 +512,10 @@ namespace pcpp /** * @return A pointer to the first line instance for this message */ - SipResponseFirstLine* getFirstLine() const { return m_FirstLine; } + SipResponseFirstLine* getFirstLine() const + { + return m_FirstLine; + } // implement Layer's abstract methods @@ -461,37 +525,41 @@ namespace pcpp SipResponseFirstLine* m_FirstLine; }; - - /** * @class SipRequestFirstLine - * Represents an SIP request first line. The first line includes 3 parameters: SIP method (e.g INVITE, ACK, BYE, etc.), - * URI (e.g sip:bla@bla.com:12345) and SIP version (usually SIP/2.0). All these parameters are included in this class, and the user - * can retrieve or set them. - * This class cannot be instantiated by users, it's created inside SipRequestLayer and user can get a pointer to an instance of it. All "getters" - * of this class retrieve the actual data of the SIP request and the "setters" actually change the packet data. - * Since SIP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So many "setter" methods - * of this class may need to shorten or extend the data in SipRequestLayer. These methods will return a false value if this action failed + * Represents an SIP request first line. The first line includes 3 parameters: SIP method (e.g INVITE, ACK, BYE, + * etc.), URI (e.g sip:bla@bla.com:12345) and SIP version (usually SIP/2.0). All these parameters are included in + * this class, and the user can retrieve or set them. This class cannot be instantiated by users, it's created + * inside SipRequestLayer and user can get a pointer to an instance of it. All "getters" of this class retrieve the + * actual data of the SIP request and the "setters" actually change the packet data. Since SIP is a textual + * protocol, most fields aren't of fixed size and this also applies to the first line parameters. So many "setter" + * methods of this class may need to shorten or extend the data in SipRequestLayer. These methods will return a + * false value if this action failed */ class SipRequestFirstLine { friend class SipRequestLayer; - public: + public: /** * @return The SIP request method */ - SipRequestLayer::SipMethod getMethod() const { return m_Method; } + SipRequestLayer::SipMethod getMethod() const + { + return m_Method; + } /** * Set the SIP request method * @param[in] newMethod The method to set - * @return False if newMethod is SipRequestLayer#SipMethodUnknown or if shortening/extending the SipRequestLayer data failed. True otherwise + * @return False if newMethod is SipRequestLayer#SipMethodUnknown or if shortening/extending the SipRequestLayer + * data failed. True otherwise */ bool setMethod(SipRequestLayer::SipMethod newMethod); /** - * @return A copied version of the URI (notice changing the return value won't change the actual data of the packet) + * @return A copied version of the URI (notice changing the return value won't change the actual data of the + * packet) */ std::string getUri() const; @@ -505,7 +573,10 @@ namespace pcpp /** * @return The SIP version */ - std::string getVersion() const { return m_Version; } + std::string getVersion() const + { + return m_Version; + } /** * A static method for parsing the SIP method out of raw data @@ -518,38 +589,50 @@ namespace pcpp /** * @return The size in bytes of the SIP request first line */ - int getSize() const { return m_FirstLineEndOffset; } + int getSize() const + { + return m_FirstLineEndOffset; + } /** - * As explained in SipRequestLayer, a SIP message can sometimes spread over more than 1 packet, so when looking at a single packet - * the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication - * whether the first line is partial + * As explained in SipRequestLayer, a SIP message can sometimes spread over more than 1 packet, so when looking + * at a single packet the header can be partial. Same goes for the first line - it can spread over more than 1 + * packet. This method returns an indication whether the first line is partial * @return False if the first line is partial, true if it's complete */ - bool isComplete() const { return m_IsComplete; } + bool isComplete() const + { + return m_IsComplete; + } /** * @class SipRequestFirstLineException - * This exception can be thrown while constructing SipRequestFirstLine (the constructor is private, so the construction happens - * only in SipRequestLayer). This kind of exception is thrown if trying to construct with SIP method of - * SipRequestLayer#SipMethodUnknown or with empty SIP version + * This exception can be thrown while constructing SipRequestFirstLine (the constructor is private, so the + * construction happens only in SipRequestLayer). This kind of exception is thrown if trying to construct with + * SIP method of SipRequestLayer#SipMethodUnknown or with empty SIP version */ class SipRequestFirstLineException : public std::exception { public: - ~SipRequestFirstLineException() throw() {} - void setMessage(const std::string &message) { m_Message = message; } + ~SipRequestFirstLineException() throw() + {} + void setMessage(const std::string& message) + { + m_Message = message; + } virtual const char* what() const throw() { return m_Message.c_str(); } + private: std::string m_Message; }; private: SipRequestFirstLine(SipRequestLayer* sipRequest); - SipRequestFirstLine(SipRequestLayer* sipRequest, SipRequestLayer::SipMethod method, const std::string& version, const std::string& uri); + SipRequestFirstLine(SipRequestLayer* sipRequest, SipRequestLayer::SipMethod method, const std::string& version, + const std::string& uri); void parseVersion(); @@ -563,26 +646,29 @@ namespace pcpp SipRequestFirstLineException m_Exception; }; - - - /** * @class SipResponseFirstLine - * Represents an SIP response message first line. The first line includes 2 parameters: status code (e.g 100 Trying ,200 OK, etc.), - * and SIP version (usually SIP/2.0). These 2 parameters are included in this class, and the user can retrieve or set them. - * This class cannot be instantiated by users, it's created inside SipResponseLayer and user can get a pointer to an instance of it. The "getter" - * methods of this class will retrieve the actual data of the SIP response and the "setter" methods will change the packet data. - * Since SIP is a textual protocol, most fields aren't of fixed size and this also applies to the first line parameters. So most "setter" methods - * of this class may need to shorten or extend the data in SipResponseLayer. These methods will return a false value if this action failed + * Represents an SIP response message first line. The first line includes 2 parameters: status code (e.g 100 Trying + * ,200 OK, etc.), and SIP version (usually SIP/2.0). These 2 parameters are included in this class, and the user + * can retrieve or set them. This class cannot be instantiated by users, it's created inside SipResponseLayer and + * user can get a pointer to an instance of it. The "getter" methods of this class will retrieve the actual data of + * the SIP response and the "setter" methods will change the packet data. Since SIP is a textual protocol, most + * fields aren't of fixed size and this also applies to the first line parameters. So most "setter" methods of this + * class may need to shorten or extend the data in SipResponseLayer. These methods will return a false value if this + * action failed */ class SipResponseFirstLine { friend class SipResponseLayer; + public: /** * @return The status code as SipResponseLayer#SipResponseStatusCode enum */ - SipResponseLayer::SipResponseStatusCode getStatusCode() const { return m_StatusCode; } + SipResponseLayer::SipResponseStatusCode getStatusCode() const + { + return m_StatusCode; + } /** * @return The status code number as integer (e.g 200, 100, etc.) @@ -597,18 +683,23 @@ namespace pcpp /** * Set the status code * @param[in] newStatusCode The new status code to set - * @param[in] statusCodeString An optional parameter: set a non-default status code message (e.g "Bla Bla" instead of "Not Found"). If - * this parameter isn't supplied or supplied as empty string (""), the default message for the status code will be set + * @param[in] statusCodeString An optional parameter: set a non-default status code message (e.g "Bla Bla" + * instead of "Not Found"). If this parameter isn't supplied or supplied as empty string (""), the default + * message for the status code will be set */ bool setStatusCode(SipResponseLayer::SipResponseStatusCode newStatusCode, std::string statusCodeString = ""); /** * @return The SIP version */ - std::string getVersion() const { return m_Version; } + std::string getVersion() const + { + return m_Version; + } /** - * Set the SIP version. The version to set is expected to be in the format of SIP/x.y otherwise an error will be written to log + * Set the SIP version. The version to set is expected to be in the format of SIP/x.y otherwise an error will be + * written to log * @param[in] newVersion The SIP version to set */ void setVersion(const std::string& newVersion); @@ -632,38 +723,50 @@ namespace pcpp /** * @return The size in bytes of the SIP response first line */ - int getSize() const { return m_FirstLineEndOffset; } + int getSize() const + { + return m_FirstLineEndOffset; + } /** - * As explained in SipResponseLayer, A SIP message can sometimes spread over more than 1 packet, so when looking at a single packet - * the header can be partial. Same goes for the first line - it can spread over more than 1 packet. This method returns an indication - * whether the first line is partial + * As explained in SipResponseLayer, A SIP message can sometimes spread over more than 1 packet, so when looking + * at a single packet the header can be partial. Same goes for the first line - it can spread over more than 1 + * packet. This method returns an indication whether the first line is partial * @return False if the first line is partial, true if it's complete */ - bool isComplete() const { return m_IsComplete; } + bool isComplete() const + { + return m_IsComplete; + } /** * @class SipResponseFirstLineException - * This exception can be thrown while constructing SipResponseFirstLine (the constructor is private, so the construction happens - * only in SipResponseLayer). This kind of exception will be thrown if trying to construct with SIP status code of - * SipResponseLayer#SipStatusCodeUnknown or with an empty SIP version + * This exception can be thrown while constructing SipResponseFirstLine (the constructor is private, so the + * construction happens only in SipResponseLayer). This kind of exception will be thrown if trying to construct + * with SIP status code of SipResponseLayer#SipStatusCodeUnknown or with an empty SIP version */ class SipResponseFirstLineException : public std::exception { public: - ~SipResponseFirstLineException() throw() {} - void setMessage(const std::string &message) { m_Message = message; } + ~SipResponseFirstLineException() throw() + {} + void setMessage(const std::string& message) + { + m_Message = message; + } virtual const char* what() const throw() { return m_Message.c_str(); } + private: std::string m_Message; }; private: SipResponseFirstLine(SipResponseLayer* sipResponse); - SipResponseFirstLine(SipResponseLayer* sipResponse, const std::string& version, SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString = ""); + SipResponseFirstLine(SipResponseLayer* sipResponse, const std::string& version, + SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString = ""); SipResponseLayer* m_SipResponse; std::string m_Version; @@ -673,4 +776,4 @@ namespace pcpp SipResponseFirstLineException m_Exception; }; -} +} // namespace pcpp diff --git a/Packet++/header/Sll2Layer.h b/Packet++/header/Sll2Layer.h index c2fa047117..8ab0458e3d 100644 --- a/Packet++/header/Sll2Layer.h +++ b/Packet++/header/Sll2Layer.h @@ -55,7 +55,10 @@ namespace pcpp * @param[in] dataLen Size of the data in bytes * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - Sll2Layer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet) { m_Protocol = SLL2; } + Sll2Layer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet) + { + m_Protocol = SLL2; + } /** * A constructor that creates a new SLL2 header and allocates the data @@ -65,13 +68,18 @@ namespace pcpp */ Sll2Layer(uint32_t interfaceIndex, uint16_t ARPHRDType, uint8_t packetType); - ~Sll2Layer() {} + ~Sll2Layer() + {} /** - * Get a pointer to the Sll header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the Sll header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the sll2_header */ - sll2_header* getSll2Header() const { return (sll2_header*)m_Data; } + sll2_header* getSll2Header() const + { + return (sll2_header*)m_Data; + } /** * A static method that validates the input data @@ -151,7 +159,8 @@ namespace pcpp /** * Get a MAC address in the link layer address field - * @return return macAddress pointer was set successfully, null pointer if d MAC address isn't valid or if set failed + * @return return macAddress pointer was set successfully, null pointer if d MAC address isn't valid or if set + * failed */ MacAddress getLinkLayerAsMacAddress(); @@ -165,9 +174,8 @@ namespace pcpp // implement abstract methods /** - * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer, - * MplsLayer. - * Otherwise sets PayloadLayer + * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, + * PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer */ void parseNextLayer(); @@ -179,11 +187,17 @@ namespace pcpp /** * @return Size of sll2_header */ - size_t getHeaderLen() const { return sizeof(sll2_header); } + size_t getHeaderLen() const + { + return sizeof(sll2_header); + } std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SllLayer.h b/Packet++/header/SllLayer.h index 441ae10d50..656b90ca06 100644 --- a/Packet++/header/SllLayer.h +++ b/Packet++/header/SllLayer.h @@ -50,7 +50,10 @@ namespace pcpp * @param[in] dataLen Size of the data in bytes * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - SllLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet) { m_Protocol = SLL; } + SllLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet) + { + m_Protocol = SLL; + } /** * A constructor that creates a new SLL header and allocates the data @@ -59,13 +62,18 @@ namespace pcpp */ SllLayer(uint16_t packetType, uint16_t ARPHRDType); - ~SllLayer() {} + ~SllLayer() + {} /** - * Get a pointer to the Sll header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the Sll header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the sll_header */ - sll_header* getSllHeader() const { return (sll_header*)m_Data; } + sll_header* getSllHeader() const + { + return (sll_header*)m_Data; + } /** * A setter for the link layer address field @@ -83,16 +91,18 @@ namespace pcpp bool setMacAddressAsLinkLayer(const MacAddress& macAddr); /** - * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer, - * MplsLayer. - * Otherwise sets PayloadLayer + * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, + * PPPoEDiscoveryLayer, MplsLayer. Otherwise sets PayloadLayer */ void parseNextLayer(); /** * @return Size of sll_header */ - size_t getHeaderLen() const { return sizeof(sll_header); } + size_t getHeaderLen() const + { + return sizeof(sll_header); + } /** * Calculate the next protocol type for known protocols: IPv4, IPv6, ARP, VLAN @@ -101,7 +111,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SmtpLayer.h b/Packet++/header/SmtpLayer.h index 786a368331..fca5c6b2bb 100644 --- a/Packet++/header/SmtpLayer.h +++ b/Packet++/header/SmtpLayer.h @@ -18,13 +18,13 @@ namespace pcpp class SmtpLayer : public SingleCommandTextProtocol { protected: - SmtpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : SingleCommandTextProtocol(data, dataLen, prevLayer, packet) + SmtpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SingleCommandTextProtocol(data, dataLen, prevLayer, packet) { m_Protocol = SMTP; }; - SmtpLayer(const std::string &command, const std::string &option) : SingleCommandTextProtocol(command, option) + SmtpLayer(const std::string& command, const std::string& option) : SingleCommandTextProtocol(command, option) { m_Protocol = SMTP; }; @@ -35,25 +35,36 @@ namespace pcpp * @param[in] port The port number to be checked * @return True if this an SMTP port (25 or 587) */ - static bool isSmtpPort(uint16_t port) { return port == 25 || port == 587; } + static bool isSmtpPort(uint16_t port) + { + return port == 25 || port == 587; + } // overridden methods /// SMTP is the always last so does nothing for this layer - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return Get the size of the layer */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /// Does nothing for this layer - void computeCalculateFields() {} + void computeCalculateFields() + {} /** * @return The OSI layer level of SMTP (Application Layer). */ - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } }; /** @@ -93,7 +104,7 @@ namespace pcpp VRFY = ('V') | ('R' << 8) | ('F' << 16) | ('Y' << 24), /// Start TLS handshake STARTTLS = (('S') | ('T' << 8) | ('A' << 16) | ('R' << 24) | - static_cast(('T') | ('T' << 8) | ('L' << 16) | ('S' << 24)) << 32), + static_cast(('T') | ('T' << 8) | ('L' << 16) | ('S' << 24)) << 32), /// Reverse the role of sender and receiver TURN = ('T') | ('U' << 8) | ('R' << 16) | ('N' << 24), /// Send mail to terminal @@ -126,16 +137,16 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - SmtpRequestLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : SmtpLayer(data, dataLen, prevLayer, packet){}; + SmtpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SmtpLayer(data, dataLen, prevLayer, packet) {}; /** * A constructor that creates layer with provided input values * @param[in] command SMTP command * @param[in] option Argument of the command */ - explicit SmtpRequestLayer(const SmtpCommand &command, const std::string &option = "") - : SmtpLayer(getCommandAsString(command), option){}; + explicit SmtpRequestLayer(const SmtpCommand& command, const std::string& option = "") + : SmtpLayer(getCommandAsString(command), option) {}; /** * Set the command of request message @@ -161,7 +172,7 @@ namespace pcpp * @param[in] value Value to set command argument * @return True if the operation is successful, false otherwise */ - bool setCommandOption(const std::string &value); + bool setCommandOption(const std::string& value); /** * Get the command argument of request message @@ -279,16 +290,16 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - SmtpResponseLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : SmtpLayer(data, dataLen, prevLayer, packet){}; + SmtpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SmtpLayer(data, dataLen, prevLayer, packet) {}; /** * A constructor that creates layer with provided input values * @param[in] code Status code * @param[in] option Argument of the status code */ - explicit SmtpResponseLayer(const SmtpStatusCode &code, const std::string &option = "") - : SmtpLayer(std::to_string(int(code)), option){}; + explicit SmtpResponseLayer(const SmtpStatusCode& code, const std::string& option = "") + : SmtpLayer(std::to_string(int(code)), option) {}; /** * Set the status code of response message @@ -314,7 +325,7 @@ namespace pcpp * @param[in] value Value to set argument * @return True if the operation is successful, false otherwise */ - bool setStatusOption(const std::string &value); + bool setStatusOption(const std::string& value); /** * Get the argument of response message @@ -337,6 +348,6 @@ namespace pcpp */ std::string toString() const; }; -} // namespace pcpp +} // namespace pcpp #endif /* PACKETPP_SMTP_LAYER */ diff --git a/Packet++/header/SomeIpLayer.h b/Packet++/header/SomeIpLayer.h index f4d1ca2aa3..448964858a 100644 --- a/Packet++/header/SomeIpLayer.h +++ b/Packet++/header/SomeIpLayer.h @@ -12,448 +12,479 @@ namespace pcpp { -/** - * @class SomeIpLayer - * Represents a SOME/IP protocol layer - */ -class SomeIpLayer : public Layer -{ -public: /** - * SOME/IP message types + * @class SomeIpLayer + * Represents a SOME/IP protocol layer */ - enum class MsgType : uint8_t + class SomeIpLayer : public Layer { - /** A request expecting a response (even void) */ - REQUEST = 0x00, - /** Acknowledgment for REQUEST(optional) */ - REQUEST_ACK = 0x40, - /** A fire&forget request */ - REQUEST_NO_RETURN = 0x01, - /** Acknowledgment for REQUEST_NO_RETURN(informational) */ - REQUEST_NO_RETURN_ACK = 0x41, - /** A request of a notification expecting no response */ - NOTIFICATION = 0x02, - /** Acknowledgment for NOTIFICATION(informational) */ - NOTIFICATION_ACK = 0x42, - /** The response message */ - RESPONSE = 0x80, - /** The Acknowledgment for RESPONSE(informational) */ - RESPONSE_ACK = 0xC0, - /** The response containing an error */ - ERRORS = 0x81, - /** Acknowledgment for ERROR(informational) */ - ERROR_ACK = 0xC1, - /** A TP request expecting a response (even void) */ - TP_REQUEST = 0x20, - /** A TP fire&forget request */ - TP_REQUEST_NO_RETURN = 0x21, - /** A TP request of a notification/event callback expecting no response */ - TP_NOTIFICATION = 0x22, - /** The TP response message */ - TP_RESPONSE = 0xa0, - /** The TP response containing an error */ - TP_ERROR = 0xa1, - }; - - /** - * @struct someiphdr - * Represents a SOME/IP protocol header - */ + public: + /** + * SOME/IP message types + */ + enum class MsgType : uint8_t + { + /** A request expecting a response (even void) */ + REQUEST = 0x00, + /** Acknowledgment for REQUEST(optional) */ + REQUEST_ACK = 0x40, + /** A fire&forget request */ + REQUEST_NO_RETURN = 0x01, + /** Acknowledgment for REQUEST_NO_RETURN(informational) */ + REQUEST_NO_RETURN_ACK = 0x41, + /** A request of a notification expecting no response */ + NOTIFICATION = 0x02, + /** Acknowledgment for NOTIFICATION(informational) */ + NOTIFICATION_ACK = 0x42, + /** The response message */ + RESPONSE = 0x80, + /** The Acknowledgment for RESPONSE(informational) */ + RESPONSE_ACK = 0xC0, + /** The response containing an error */ + ERRORS = 0x81, + /** Acknowledgment for ERROR(informational) */ + ERROR_ACK = 0xC1, + /** A TP request expecting a response (even void) */ + TP_REQUEST = 0x20, + /** A TP fire&forget request */ + TP_REQUEST_NO_RETURN = 0x21, + /** A TP request of a notification/event callback expecting no response */ + TP_NOTIFICATION = 0x22, + /** The TP response message */ + TP_RESPONSE = 0xa0, + /** The TP response containing an error */ + TP_ERROR = 0xa1, + }; + + /** + * @struct someiphdr + * Represents a SOME/IP protocol header + */ #pragma pack(push, 1) - struct someiphdr - { - /** Service ID */ - uint16_t serviceID; - /** Method ID. Most significant bit 0 when E2E communication. 1 when SOME/IP event */ - uint16_t methodID; - /** Length. Also covers payload. Excludes serviceID, methodID and length field itself */ - uint32_t length; - /** Client ID */ - uint16_t clientID; - /** Session ID */ - uint16_t sessionID; - /** Protocol Version */ - uint8_t protocolVersion; - /** Interface Version */ - uint8_t interfaceVersion; - /** Message Type */ - uint8_t msgType; - /** Return Code */ - uint8_t returnCode; - }; + struct someiphdr + { + /** Service ID */ + uint16_t serviceID; + /** Method ID. Most significant bit 0 when E2E communication. 1 when SOME/IP event */ + uint16_t methodID; + /** Length. Also covers payload. Excludes serviceID, methodID and length field itself */ + uint32_t length; + /** Client ID */ + uint16_t clientID; + /** Session ID */ + uint16_t sessionID; + /** Protocol Version */ + uint8_t protocolVersion; + /** Interface Version */ + uint8_t interfaceVersion; + /** Message Type */ + uint8_t msgType; + /** Return Code */ + uint8_t returnCode; + }; #pragma pack(pop) - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data (will be casted to someiphdr) - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - SomeIpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) - { - m_Protocol = SomeIP; - } - - /** - * Construct a new layer object - * @param[in] serviceID Service ID - * @param[in] methodID Method ID - * @param[in] clientID Client ID - * @param[in] sessionID Session ID - * @param[in] interfaceVersion Interface Version - * @param[in] type Type of the message - * @param[in] returnCode Return Code - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * holds the reference to a data buffer. This option can be used to reduce the number of copies to generate packets. - */ - SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, uint8_t interfaceVersion, - MsgType type, uint8_t returnCode, const uint8_t *const data = nullptr, size_t dataLen = 0); - - /** - * Destroy the layer object - */ - ~SomeIpLayer() {} - - /** - * A static method that creates a SOME/IP or SOME/IP-TP layer from packet raw data. Returns PayloadLayer if data is - * not valid. - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored - * @return Layer* A newly allocated layer - */ - static Layer* parseSomeIpLayer(uint8_t *data, size_t dataLen, Layer* prevLayer, Packet* packet); - - /** - * Get a pointer to the basic SOME/IP header. Notice this points directly to the data, so every change will change - * the actual packet data - * @return A pointer to the someiphdr - */ - someiphdr *getSomeIpHeader() const { return (someiphdr *)m_Data; } - - /** - * Checks if given port is a SOME/IP protocol port (only Service Discovery ports are checked for now) - * @param[in] port Port to check - * @return true if SOME/IP protocol port, false if not - */ - static bool isSomeIpPort(uint16_t port); - - /** - * Adds port to a list of ports where pcap checks for SOME/IP communication. - * Each port must be removed at the end in order to have no memory leak. - * @param[in] port Port to add - */ - static void addSomeIpPort(uint16_t port); - - /** - * Removes port from a list of ports where pcap checks for SOME/IP communication. - * @param[in] port Port to remove - */ - static void removeSomeIpPort(uint16_t port); - - /** - * Removes all ports from a list of ports where pcap checks for SOME/IP communication. - */ - static void removeAllSomeIpPorts(); - - /** - * Get the messageID - * @return uint32_t returned in host endian - */ - uint32_t getMessageID() const; - - /** - * Set the Message ID - * @param[in] messageID messageID to set - */ - void setMessageID(uint32_t messageID); - - /** - * Get the serviceID - * @return uint16_t returned in host endian - */ - uint16_t getServiceID() const; - - /** - * Set the Service ID - * @param[in] serviceID serviceID to set - */ - void setServiceID(uint16_t serviceID); - - /** - * Get the methodID - * @return uint16_t returned in host endian - */ - uint16_t getMethodID() const; - - /** - * Set the Method ID - * @param[in] methodID methodID to set - */ - void setMethodID(uint16_t methodID); - - /** - * Get the Length Field of the SOME/IP header - * @return uint32_t The length field of the SOME/IP header - */ - uint32_t getLengthField() const; - - /** - * Get the requestID - * @return uint32_t returned in host endian - */ - uint32_t getRequestID() const; - - /** - * Set the Request ID - * @param[in] requestID requestID to set - */ - void setRequestID(uint32_t requestID); - - /** - * Get the sessionID - * @return uint16_t returned in host endian - */ - uint16_t getSessionID() const; - - /** - * Set the Session ID - * @param[in] sessionID sessionID to set - */ - void setSessionID(uint16_t sessionID); - - /** - * Get the clientID - * @return uint16_t returned in host endian - */ - uint16_t getClientID() const; - - /** - * Set the Client ID - * @param[in] clientID clientID to set - */ - void setClientID(uint16_t clientID); - - /** - * Get the protocolVersion - * @return uint8_t - */ - uint8_t getProtocolVersion() const; - - /** - * Set the Protocol Version - * @param[in] version version to set - */ - void setProtocolVersion(uint8_t version); - - /** - * Get the interfaceVersion - * @return uint8_t - */ - uint8_t getInterfaceVersion() const; - - /** - * Set the Interface Version - * @param[in] version version to set - */ - void setInterfaceVersion(uint8_t version); - - /** - * Get the message type - * @return uint8_t - */ - uint8_t getMessageTypeAsInt() const; - - /** - * Get the message type - * @return SomeIpLayer::MsgType - */ - SomeIpLayer::MsgType getMessageType() const; - - /** - * Set the Message Type - * @param[in] type Type to set - */ - void setMessageType(MsgType type); - - /** - * Set the Message Type - * @param[in] type Type to set - */ - void setMessageType(uint8_t type); - - /** - * Get the returnCode - * @return uint8_t - */ - uint8_t getReturnCode() const; - - /** - * Set the returnCode - * @param[in] returnCode ReturnCode to set - */ - void setReturnCode(uint8_t returnCode); - - /** - * Set the length field of the SOME/IP header - * @param[in] payloadLength Length of the payload - */ - void setPayloadLength(uint32_t payloadLength); - - /** - * @return A pointer for the layer payload, meaning the first byte after the header - */ - uint8_t *getPduPayload() const { return m_Data + getSomeIpHeaderLen(); } - - /** - * @return The size in bytes of the payload - */ - size_t getPduPayloadSize() const { return getHeaderLen() - getSomeIpHeaderLen(); } - - /** - * Get the Length of the SOME/IP header inc payload - * @return size_t - */ - size_t getHeaderLen() const { return sizeof(uint32_t) * 2 + getLengthField(); } - - /** - * Does nothing for this layer - */ - virtual void computeCalculateFields() {} - - /** - * Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer - */ - void parseNextLayer(); - - /** - * @return The string representation of the SOME/IP layer - */ - virtual std::string toString() const; - - /** - * @return The OSI model layer of this layer - */ - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } - -protected: - SomeIpLayer() {} - -private: - static const uint8_t SOMEIP_PROTOCOL_VERSION = 1; - virtual size_t getSomeIpHeaderLen() const { return sizeof(someiphdr); } - - /* Using unordered_set since insertion and search should be almost constant time */ - static std::unordered_set m_SomeIpPorts; -}; + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data (will be casted to someiphdr) + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + SomeIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = SomeIP; + } + + /** + * Construct a new layer object + * @param[in] serviceID Service ID + * @param[in] methodID Method ID + * @param[in] clientID Client ID + * @param[in] sessionID Session ID + * @param[in] interfaceVersion Interface Version + * @param[in] type Type of the message + * @param[in] returnCode Return Code + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * holds the reference to a data buffer. This option can be used to reduce the number of copies to generate + * packets. + */ + SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, const uint8_t* const data = nullptr, + size_t dataLen = 0); + + /** + * Destroy the layer object + */ + ~SomeIpLayer() + {} + + /** + * A static method that creates a SOME/IP or SOME/IP-TP layer from packet raw data. Returns PayloadLayer if data + * is not valid. + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored + * @return Layer* A newly allocated layer + */ + static Layer* parseSomeIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /** + * Get a pointer to the basic SOME/IP header. Notice this points directly to the data, so every change will + * change the actual packet data + * @return A pointer to the someiphdr + */ + someiphdr* getSomeIpHeader() const + { + return (someiphdr*)m_Data; + } + + /** + * Checks if given port is a SOME/IP protocol port (only Service Discovery ports are checked for now) + * @param[in] port Port to check + * @return true if SOME/IP protocol port, false if not + */ + static bool isSomeIpPort(uint16_t port); + + /** + * Adds port to a list of ports where pcap checks for SOME/IP communication. + * Each port must be removed at the end in order to have no memory leak. + * @param[in] port Port to add + */ + static void addSomeIpPort(uint16_t port); + + /** + * Removes port from a list of ports where pcap checks for SOME/IP communication. + * @param[in] port Port to remove + */ + static void removeSomeIpPort(uint16_t port); + + /** + * Removes all ports from a list of ports where pcap checks for SOME/IP communication. + */ + static void removeAllSomeIpPorts(); + + /** + * Get the messageID + * @return uint32_t returned in host endian + */ + uint32_t getMessageID() const; + + /** + * Set the Message ID + * @param[in] messageID messageID to set + */ + void setMessageID(uint32_t messageID); + + /** + * Get the serviceID + * @return uint16_t returned in host endian + */ + uint16_t getServiceID() const; + + /** + * Set the Service ID + * @param[in] serviceID serviceID to set + */ + void setServiceID(uint16_t serviceID); + + /** + * Get the methodID + * @return uint16_t returned in host endian + */ + uint16_t getMethodID() const; + + /** + * Set the Method ID + * @param[in] methodID methodID to set + */ + void setMethodID(uint16_t methodID); + + /** + * Get the Length Field of the SOME/IP header + * @return uint32_t The length field of the SOME/IP header + */ + uint32_t getLengthField() const; + + /** + * Get the requestID + * @return uint32_t returned in host endian + */ + uint32_t getRequestID() const; + + /** + * Set the Request ID + * @param[in] requestID requestID to set + */ + void setRequestID(uint32_t requestID); + + /** + * Get the sessionID + * @return uint16_t returned in host endian + */ + uint16_t getSessionID() const; + + /** + * Set the Session ID + * @param[in] sessionID sessionID to set + */ + void setSessionID(uint16_t sessionID); + + /** + * Get the clientID + * @return uint16_t returned in host endian + */ + uint16_t getClientID() const; + + /** + * Set the Client ID + * @param[in] clientID clientID to set + */ + void setClientID(uint16_t clientID); + + /** + * Get the protocolVersion + * @return uint8_t + */ + uint8_t getProtocolVersion() const; + + /** + * Set the Protocol Version + * @param[in] version version to set + */ + void setProtocolVersion(uint8_t version); + + /** + * Get the interfaceVersion + * @return uint8_t + */ + uint8_t getInterfaceVersion() const; + + /** + * Set the Interface Version + * @param[in] version version to set + */ + void setInterfaceVersion(uint8_t version); + + /** + * Get the message type + * @return uint8_t + */ + uint8_t getMessageTypeAsInt() const; + + /** + * Get the message type + * @return SomeIpLayer::MsgType + */ + SomeIpLayer::MsgType getMessageType() const; + + /** + * Set the Message Type + * @param[in] type Type to set + */ + void setMessageType(MsgType type); + + /** + * Set the Message Type + * @param[in] type Type to set + */ + void setMessageType(uint8_t type); + + /** + * Get the returnCode + * @return uint8_t + */ + uint8_t getReturnCode() const; + + /** + * Set the returnCode + * @param[in] returnCode ReturnCode to set + */ + void setReturnCode(uint8_t returnCode); + + /** + * Set the length field of the SOME/IP header + * @param[in] payloadLength Length of the payload + */ + void setPayloadLength(uint32_t payloadLength); + + /** + * @return A pointer for the layer payload, meaning the first byte after the header + */ + uint8_t* getPduPayload() const + { + return m_Data + getSomeIpHeaderLen(); + } + + /** + * @return The size in bytes of the payload + */ + size_t getPduPayloadSize() const + { + return getHeaderLen() - getSomeIpHeaderLen(); + } + + /** + * Get the Length of the SOME/IP header inc payload + * @return size_t + */ + size_t getHeaderLen() const + { + return sizeof(uint32_t) * 2 + getLengthField(); + } + + /** + * Does nothing for this layer + */ + virtual void computeCalculateFields() + {} + + /** + * Identifies the following next layers: SomeIpLayer, SomeIpTpLayer, SomeIpSdLayer. Otherwise sets PayloadLayer + */ + void parseNextLayer(); + + /** + * @return The string representation of the SOME/IP layer + */ + virtual std::string toString() const; + + /** + * @return The OSI model layer of this layer + */ + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } + + protected: + SomeIpLayer() + {} + + private: + static const uint8_t SOMEIP_PROTOCOL_VERSION = 1; + virtual size_t getSomeIpHeaderLen() const + { + return sizeof(someiphdr); + } + + /* Using unordered_set since insertion and search should be almost constant time */ + static std::unordered_set m_SomeIpPorts; + }; -/** - * @class SomeIpTpLayer - * Represents an SOME/IP Transport Protocol Layer - */ -class SomeIpTpLayer : public SomeIpLayer -{ -public: /** - * @struct someiptphdr - * Represents an SOME/IP-TP protocol header. + * @class SomeIpTpLayer + * Represents an SOME/IP Transport Protocol Layer */ -#pragma pack(push, 1) - struct someiptphdr : someiphdr + class SomeIpTpLayer : public SomeIpLayer { - /** Contains the offset and the more segments flag. 28 bit offset field measured in 16 bytes + 3 bit reserved + - * 1 bit more segments flag */ - uint32_t offsetAndFlag; - }; + public: + /** + * @struct someiptphdr + * Represents an SOME/IP-TP protocol header. + */ +#pragma pack(push, 1) + struct someiptphdr : someiphdr + { + /** Contains the offset and the more segments flag. 28 bit offset field measured in 16 bytes + 3 bit + * reserved + 1 bit more segments flag */ + uint32_t offsetAndFlag; + }; #pragma pack(pop) - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data (will be casted to @ref someiptphdr) - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - SomeIpTpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : SomeIpLayer(data, dataLen, prevLayer, packet) {} - - /** - * A constructor that creates empty layer and sets values - * @param[in] serviceID Service ID - * @param[in] methodID Method ID - * @param[in] clientID Client ID - * @param[in] sessionID Session ID - * @param[in] interfaceVersion Interface Version - * @param[in] type Type of the message - * @param[in] returnCode Return Code - * @param[in] offset Offset indicating the data offset in increments of 16 bytes - * @param[in] moreSegmentsFlag Flag indicating whether more SOME/IP-TP Packets will follow - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - */ - SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, - uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, bool moreSegmentsFlag, - const uint8_t *const data = nullptr, size_t dataLen = 0); - - /** - * Destroy the layer object - */ - ~SomeIpTpLayer() {} - - /** - * Get a pointer to the basic SOME/IP-TP header. Notice this points directly to the data, so every change will - * change the actual packet data - * @return A pointer to the @ref someiptphdr - */ - someiptphdr *getSomeIpTpHeader() const { return (someiptphdr *)m_Data; } - - /** - * Get the Offset. Offset is returned in multiple of 16 bytes. - * @return The offset value - */ - uint32_t getOffset() const; - - /** - * Set the Offset. Already has to be in multiples of 16 bytes. - * If 32 bytes have already been transmitted, the offset has to be set to 2. - * @param[in] offset Offset to set. Already has to be in multiples of 16 bytes. - */ - void setOffset(uint32_t offset); - - /** - * Get the More Segments Flag - * @return true if the More Segments Flag is set, false if it is not set - */ - bool getMoreSegmentsFlag() const; - - /** - * Set the More Segments Flag - * @param[in] flag True if the More Segments Flag shall be set, false for resetting - */ - void setMoreSegmentsFlag(bool flag); - - /** - * Sets the message type in this layer with enabling the TP flag - */ - void computeCalculateFields(); - - /** - * @return The string representation of the SOME/IP-TP layer - */ - std::string toString() const; - -private: - static const uint32_t SOMEIP_TP_MORE_FLAG_MASK = 0x01; - static const uint32_t SOMEIP_TP_OFFSET_MASK = 0xFFFFFFF0; - - size_t getSomeIpHeaderLen() const { return sizeof(someiptphdr); } - - static uint8_t setTpFlag(uint8_t messageType); -}; + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data (will be casted to @ref someiptphdr) + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + SomeIpTpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SomeIpLayer(data, dataLen, prevLayer, packet) + {} + + /** + * A constructor that creates empty layer and sets values + * @param[in] serviceID Service ID + * @param[in] methodID Method ID + * @param[in] clientID Client ID + * @param[in] sessionID Session ID + * @param[in] interfaceVersion Interface Version + * @param[in] type Type of the message + * @param[in] returnCode Return Code + * @param[in] offset Offset indicating the data offset in increments of 16 bytes + * @param[in] moreSegmentsFlag Flag indicating whether more SOME/IP-TP Packets will follow + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + */ + SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, + bool moreSegmentsFlag, const uint8_t* const data = nullptr, size_t dataLen = 0); + + /** + * Destroy the layer object + */ + ~SomeIpTpLayer() + {} + + /** + * Get a pointer to the basic SOME/IP-TP header. Notice this points directly to the data, so every change will + * change the actual packet data + * @return A pointer to the @ref someiptphdr + */ + someiptphdr* getSomeIpTpHeader() const + { + return (someiptphdr*)m_Data; + } + + /** + * Get the Offset. Offset is returned in multiple of 16 bytes. + * @return The offset value + */ + uint32_t getOffset() const; + + /** + * Set the Offset. Already has to be in multiples of 16 bytes. + * If 32 bytes have already been transmitted, the offset has to be set to 2. + * @param[in] offset Offset to set. Already has to be in multiples of 16 bytes. + */ + void setOffset(uint32_t offset); + + /** + * Get the More Segments Flag + * @return true if the More Segments Flag is set, false if it is not set + */ + bool getMoreSegmentsFlag() const; + + /** + * Set the More Segments Flag + * @param[in] flag True if the More Segments Flag shall be set, false for resetting + */ + void setMoreSegmentsFlag(bool flag); + + /** + * Sets the message type in this layer with enabling the TP flag + */ + void computeCalculateFields(); + + /** + * @return The string representation of the SOME/IP-TP layer + */ + std::string toString() const; + + private: + static const uint32_t SOMEIP_TP_MORE_FLAG_MASK = 0x01; + static const uint32_t SOMEIP_TP_OFFSET_MASK = 0xFFFFFFF0; + + size_t getSomeIpHeaderLen() const + { + return sizeof(someiptphdr); + } + + static uint8_t setTpFlag(uint8_t messageType); + }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/SomeIpSdLayer.h b/Packet++/header/SomeIpSdLayer.h index 2b0f49511f..b7c1bd9024 100644 --- a/Packet++/header/SomeIpSdLayer.h +++ b/Packet++/header/SomeIpSdLayer.h @@ -18,759 +18,774 @@ */ namespace pcpp { -/** - * Types of protocols that can be referenced in SOME/IP-SD - */ -enum SomeIpSdProtocolType : uint8_t -{ - /** TCP */ - SD_TCP = 0x06, - /** UDP */ - SD_UDP = 0x11 -}; - -class SomeIpSdLayer; - -/** - * @class SomeIpSdOption - * Base class of the SOME/IP-SD options. Cannot be instantiated. - */ -class SomeIpSdOption -{ -public: - friend class SomeIpSdLayer; - /** - * Types of options currently available for the SOME/IP-SD protocol + * Types of protocols that can be referenced in SOME/IP-SD */ - enum class OptionType : uint8_t + enum SomeIpSdProtocolType : uint8_t { - /** Unknown Option Type */ - Unknown = 0x00, - /** Configuration Option */ - ConfigurationString = 0x01, - /** Load Balancing Option */ - LoadBalancing = 0x02, - /** IPv4 Endpoint Option */ - IPv4Endpoint = 0x04, - /** IPv6 Endpoint Option */ - IPv6Endpoint = 0x06, - /** IPv4 Multicast Option */ - IPv4Multicast = 0x14, - /** IPv6 Multicast Option */ - IPv6Multicast = 0x16, - /** IPv4 SD Endpoint Option */ - IPv4SdEndpoint = 0x24, - /** IPv6 SD Endpoint Option */ - IPv6SdEndpoint = 0x26 + /** TCP */ + SD_TCP = 0x06, + /** UDP */ + SD_UDP = 0x11 }; - /** - * @struct someipsdhdroptionsbase - * Represents the common base for SOME/IP-SD header options - */ -#pragma pack(push, 1) - struct someipsdhdroptionsbase - { - /** Length - excluding the 16 bit Length field and the 8 bit type flag */ - uint16_t length; - /** Type */ - uint8_t type; - /** Reserved */ - uint8_t reserved; - }; -#pragma pack(pop) + class SomeIpSdLayer; /** - * Destroy the SOME/IP-SD Option object and delete allocated data if it has been allocated by a constructor + * @class SomeIpSdOption + * Base class of the SOME/IP-SD options. Cannot be instantiated. */ - virtual ~SomeIpSdOption(); - - /** - * Get the Option Type - * @return OptionType - */ - OptionType getType() const; - - /** - * Get the Length of the SOME/IP-SD option - * @return size_t - */ - size_t getLength() const { return m_DataLen; } - - /** - * Get the internal data of the SOME/IP-SD Option - * @return uint8_t* - */ - uint8_t *getDataPtr() const; - - /** - * Get a pointer to the SOME/IP-SD Option base header - * @return someipsdhdroptionsbase* - */ - someipsdhdroptionsbase *getSomeIpSdOptionHeader() const; - -protected: - const IDataContainer *m_DataContainer; - size_t m_Offset; - uint8_t *m_ShadowData; - size_t m_DataLen; - - SomeIpSdOption() : m_DataContainer(nullptr), m_Offset(0), m_ShadowData(nullptr), m_DataLen(0) {} - - SomeIpSdOption(const IDataContainer *dataContainer, size_t offset) - : m_DataContainer(dataContainer), m_Offset(offset), m_ShadowData(nullptr), m_DataLen(0) {} - - void initStdFields(OptionType type); - - SomeIpSdOption(const SomeIpSdOption &) = delete; - SomeIpSdOption &operator=(const SomeIpSdOption &) = delete; -}; - -/** - * @class SomeIpSdIPv4Option - * Implements the following SOME/IP-SD Options: IPv4 Endpoint, IPv4 Multicast, IPv4 SD Endpoint - */ -class SomeIpSdIPv4Option : public SomeIpSdOption -{ -public: - friend class SomeIpSdLayer; - - /** - * Types of options which are implemented with this class - */ - enum IPv4OptionType + class SomeIpSdOption { - /** IPv4 Endpoint Option */ - IPv4Endpoint, - /** IPv4 Multicast Option */ - IPv4Multicast, - /** IPv4 SD Endpoint Option */ - IPv4SdEndpoint, - }; - - /** - * Construct a new SomeIpSdIPv4 Option object - * @param[in] type IPv4 Option type - * @param[in] ipAddress Ipv4 address to use - * @param[in] port Port to use - * @param[in] l4Protocol Protocol to use - */ - SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port, SomeIpSdProtocolType l4Protocol); - - /** - * Construct a new SomeIpSdIPv4 Option object from already existing memory - * @param[in] dataContainer Data containing the SomeIpSdIPv4 Option object - * @param[in] offset Offset for dataContainer - */ - SomeIpSdIPv4Option(const IDataContainer *dataContainer, size_t offset); - - /** - * Get the Ip Address - * @return IPv4Address - */ - IPv4Address getIpAddress() const; - - /** - * Get the Port - * @return uint16_t - */ - uint16_t getPort() const; - - /** - * Get the Protocol - * @return SomeIpSdProtocolType - */ - SomeIpSdProtocolType getProtocol() const; - -private: - /** - * @struct someipsdhdroptionsipv4 - * Represents the IPv4 option types for the SOME/IP-SD header - */ + public: + friend class SomeIpSdLayer; + + /** + * Types of options currently available for the SOME/IP-SD protocol + */ + enum class OptionType : uint8_t + { + /** Unknown Option Type */ + Unknown = 0x00, + /** Configuration Option */ + ConfigurationString = 0x01, + /** Load Balancing Option */ + LoadBalancing = 0x02, + /** IPv4 Endpoint Option */ + IPv4Endpoint = 0x04, + /** IPv6 Endpoint Option */ + IPv6Endpoint = 0x06, + /** IPv4 Multicast Option */ + IPv4Multicast = 0x14, + /** IPv6 Multicast Option */ + IPv6Multicast = 0x16, + /** IPv4 SD Endpoint Option */ + IPv4SdEndpoint = 0x24, + /** IPv6 SD Endpoint Option */ + IPv6SdEndpoint = 0x26 + }; + + /** + * @struct someipsdhdroptionsbase + * Represents the common base for SOME/IP-SD header options + */ #pragma pack(push, 1) - struct someipsdhdroptionsipv4 : someipsdhdroptionsbase - { - /* IPv4-Address field */ - uint32_t ipv4Address; - /* Reserved */ - // cppcheck-suppress duplInheritedMember - uint8_t reserved; - /* Layer 4 Protocol field (L4-Proto) - Either UDP or TCP */ - SomeIpSdProtocolType l4Protocol; - /* Port number of UDP or TCP */ - uint16_t portNumber; - }; + struct someipsdhdroptionsbase + { + /** Length - excluding the 16 bit Length field and the 8 bit type flag */ + uint16_t length; + /** Type */ + uint8_t type; + /** Reserved */ + uint8_t reserved; + }; #pragma pack(pop) -}; -/** - * @class SomeIpSdIPv6Option - * Implements the following SOME/IP-SD Options: IPv6 Endpoint, IPv6 Multicast, IPv6 SD Endpoint - */ -class SomeIpSdIPv6Option : public SomeIpSdOption -{ -public: - friend class SomeIpSdLayer; + /** + * Destroy the SOME/IP-SD Option object and delete allocated data if it has been allocated by a constructor + */ + virtual ~SomeIpSdOption(); + + /** + * Get the Option Type + * @return OptionType + */ + OptionType getType() const; + + /** + * Get the Length of the SOME/IP-SD option + * @return size_t + */ + size_t getLength() const + { + return m_DataLen; + } + + /** + * Get the internal data of the SOME/IP-SD Option + * @return uint8_t* + */ + uint8_t* getDataPtr() const; + + /** + * Get a pointer to the SOME/IP-SD Option base header + * @return someipsdhdroptionsbase* + */ + someipsdhdroptionsbase* getSomeIpSdOptionHeader() const; + + protected: + const IDataContainer* m_DataContainer; + size_t m_Offset; + uint8_t* m_ShadowData; + size_t m_DataLen; + + SomeIpSdOption() : m_DataContainer(nullptr), m_Offset(0), m_ShadowData(nullptr), m_DataLen(0) + {} + + SomeIpSdOption(const IDataContainer* dataContainer, size_t offset) + : m_DataContainer(dataContainer), m_Offset(offset), m_ShadowData(nullptr), m_DataLen(0) + {} + + void initStdFields(OptionType type); + + SomeIpSdOption(const SomeIpSdOption&) = delete; + SomeIpSdOption& operator=(const SomeIpSdOption&) = delete; + }; /** - * Types of options which are implemented with this class + * @class SomeIpSdIPv4Option + * Implements the following SOME/IP-SD Options: IPv4 Endpoint, IPv4 Multicast, IPv4 SD Endpoint */ - enum IPv6OptionType + class SomeIpSdIPv4Option : public SomeIpSdOption { - /** IPv6 Endpoint Option */ - IPv6Endpoint, - /** IPv6 Multicast Option */ - IPv6Multicast, - /** IPv6 SD Endpoint Option */ - IPv6SdEndpoint, + public: + friend class SomeIpSdLayer; + + /** + * Types of options which are implemented with this class + */ + enum IPv4OptionType + { + /** IPv4 Endpoint Option */ + IPv4Endpoint, + /** IPv4 Multicast Option */ + IPv4Multicast, + /** IPv4 SD Endpoint Option */ + IPv4SdEndpoint, + }; + + /** + * Construct a new SomeIpSdIPv4 Option object + * @param[in] type IPv4 Option type + * @param[in] ipAddress Ipv4 address to use + * @param[in] port Port to use + * @param[in] l4Protocol Protocol to use + */ + SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port, SomeIpSdProtocolType l4Protocol); + + /** + * Construct a new SomeIpSdIPv4 Option object from already existing memory + * @param[in] dataContainer Data containing the SomeIpSdIPv4 Option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdIPv4Option(const IDataContainer* dataContainer, size_t offset); + + /** + * Get the Ip Address + * @return IPv4Address + */ + IPv4Address getIpAddress() const; + + /** + * Get the Port + * @return uint16_t + */ + uint16_t getPort() const; + + /** + * Get the Protocol + * @return SomeIpSdProtocolType + */ + SomeIpSdProtocolType getProtocol() const; + + private: + /** + * @struct someipsdhdroptionsipv4 + * Represents the IPv4 option types for the SOME/IP-SD header + */ +#pragma pack(push, 1) + struct someipsdhdroptionsipv4 : someipsdhdroptionsbase + { + /* IPv4-Address field */ + uint32_t ipv4Address; + /* Reserved */ + // cppcheck-suppress duplInheritedMember + uint8_t reserved; + /* Layer 4 Protocol field (L4-Proto) - Either UDP or TCP */ + SomeIpSdProtocolType l4Protocol; + /* Port number of UDP or TCP */ + uint16_t portNumber; + }; +#pragma pack(pop) }; /** - * Construct a new SomeIpSdIPv6 Option object - * @param[in] type IPv6 Option type - * @param[in] ipAddress Ipv6 address to use - * @param[in] port Port to use - * @param[in] l4Protocol Protocol to use - */ - SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port, SomeIpSdProtocolType l4Protocol); - - /** - * Construct a new SomeIpSdIPv6 Option object from already existing memory - * @param[in] dataContainer Data containing the SomeIpSdIPv6 Option object - * @param[in] offset Offset for dataContainer - */ - SomeIpSdIPv6Option(const IDataContainer *dataContainer, size_t offset); - - /** - * Get the Ip Address - * @return IPv6Address - */ - IPv6Address getIpAddress() const; - - /** - * Get the Port - * @return uint16_t - */ - uint16_t getPort() const; - - /** - * Get the Protocol - * @return SomeIpSdProtocolType - */ - SomeIpSdProtocolType getProtocol() const; - -private: - /** - * @struct someipsdhdroptionsipv6 - * Represents the IPv6 option types for the SOME/IP-SD header + * @class SomeIpSdIPv6Option + * Implements the following SOME/IP-SD Options: IPv6 Endpoint, IPv6 Multicast, IPv6 SD Endpoint */ -#pragma pack(push, 1) - struct someipsdhdroptionsipv6 : someipsdhdroptionsbase + class SomeIpSdIPv6Option : public SomeIpSdOption { - /* IPv6-Address field */ - uint8_t ipv6Address[16]; - /* Reserved */ - // cppcheck-suppress duplInheritedMember - uint8_t reserved; - /* Layer 4 Protocol field (L4-Proto) - Either UDP or TCP */ - SomeIpSdProtocolType l4Protocol; - /* Port number of UDP or TCP */ - uint16_t portNumber; - }; + public: + friend class SomeIpSdLayer; + + /** + * Types of options which are implemented with this class + */ + enum IPv6OptionType + { + /** IPv6 Endpoint Option */ + IPv6Endpoint, + /** IPv6 Multicast Option */ + IPv6Multicast, + /** IPv6 SD Endpoint Option */ + IPv6SdEndpoint, + }; + + /** + * Construct a new SomeIpSdIPv6 Option object + * @param[in] type IPv6 Option type + * @param[in] ipAddress Ipv6 address to use + * @param[in] port Port to use + * @param[in] l4Protocol Protocol to use + */ + SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port, SomeIpSdProtocolType l4Protocol); + + /** + * Construct a new SomeIpSdIPv6 Option object from already existing memory + * @param[in] dataContainer Data containing the SomeIpSdIPv6 Option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdIPv6Option(const IDataContainer* dataContainer, size_t offset); + + /** + * Get the Ip Address + * @return IPv6Address + */ + IPv6Address getIpAddress() const; + + /** + * Get the Port + * @return uint16_t + */ + uint16_t getPort() const; + + /** + * Get the Protocol + * @return SomeIpSdProtocolType + */ + SomeIpSdProtocolType getProtocol() const; + + private: + /** + * @struct someipsdhdroptionsipv6 + * Represents the IPv6 option types for the SOME/IP-SD header + */ +#pragma pack(push, 1) + struct someipsdhdroptionsipv6 : someipsdhdroptionsbase + { + /* IPv6-Address field */ + uint8_t ipv6Address[16]; + /* Reserved */ + // cppcheck-suppress duplInheritedMember + uint8_t reserved; + /* Layer 4 Protocol field (L4-Proto) - Either UDP or TCP */ + SomeIpSdProtocolType l4Protocol; + /* Port number of UDP or TCP */ + uint16_t portNumber; + }; #pragma pack(pop) -}; - -/** - * @class SomeIpSdConfigurationOption - * Implements the Configuration option of SOME/IP-SD protocol - */ -class SomeIpSdConfigurationOption : public SomeIpSdOption -{ -public: - friend class SomeIpSdLayer; - - /** - * Construct a new Configuration Option object - * @param[in] configurationString the configuration string - */ - explicit SomeIpSdConfigurationOption(const std::string &configurationString); - - /** - * Construct a new Configuration Option object from already existing memory - * @param[in] dataContainer Data containing the Configuration Option object - * @param[in] offset Offset for dataContainer - */ - SomeIpSdConfigurationOption(const IDataContainer *dataContainer, size_t offset); - - /** - * Get the configuration string - * @return std::string - */ - std::string getConfigurationString() const; -}; - -/** - * @class SomeIpSdLoadBalancingOption - * Implements the Load Balancing option of SOME/IP-SD protocol - */ -class SomeIpSdLoadBalancingOption : public SomeIpSdOption -{ -public: - friend class SomeIpSdLayer; - - /** - * Construct a new Load Balancing object - * @param[in] priority Priority of this instance - * @param[in] weight Weight of this instance - */ - SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight); - - /** - * Construct a new Option object from already existing memory - * @param[in] dataContainer Data containing the option object - * @param[in] offset Offset for dataContainer - */ - SomeIpSdLoadBalancingOption(const IDataContainer *dataContainer, size_t offset); - - /** - * Get the priority fild - * @return uint16_t - */ - uint16_t getPriority() const; - - /** - * Get the weight field - * @return uint16_t - */ - uint16_t getWeight() const; + }; -private: /** - * @struct someipsdhdroptionsload - * Represents the Load Balancing option header for SOME/IP-SD + * @class SomeIpSdConfigurationOption + * Implements the Configuration option of SOME/IP-SD protocol */ -#pragma pack(push, 1) - struct someipsdhdroptionsload : someipsdhdroptionsbase + class SomeIpSdConfigurationOption : public SomeIpSdOption { - /* Priority field */ - uint16_t priority; - /* Weight field */ - uint16_t weight; + public: + friend class SomeIpSdLayer; + + /** + * Construct a new Configuration Option object + * @param[in] configurationString the configuration string + */ + explicit SomeIpSdConfigurationOption(const std::string& configurationString); + + /** + * Construct a new Configuration Option object from already existing memory + * @param[in] dataContainer Data containing the Configuration Option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdConfigurationOption(const IDataContainer* dataContainer, size_t offset); + + /** + * Get the configuration string + * @return std::string + */ + std::string getConfigurationString() const; }; -#pragma pack(pop) -}; - -/** - * @class SomeIpSdEntry - * Implementation of the SOME/IP-SD Service Entry and Eventgroup Entry Type - */ -class SomeIpSdEntry -{ -public: - friend class SomeIpSdLayer; /** - * Types of entries that can occur in SOME/IP-SD + * @class SomeIpSdLoadBalancingOption + * Implements the Load Balancing option of SOME/IP-SD protocol */ - enum class EntryType : uint8_t + class SomeIpSdLoadBalancingOption : public SomeIpSdOption { - /** Find Service */ - FindService, - /** Offer Service */ - OfferService, - /** Stop Offer Service */ - StopOfferService, - /** Subscribe Eventgroup */ - SubscribeEventgroup, - /** Stop Subscribe Eventgroup */ - StopSubscribeEventgroup, - /** Subscribe Eventgroup Acknowledgment */ - SubscribeEventgroupAck, - /** Subscribe Eventgroup Negative Acknowledgement */ - SubscribeEventgroupNack, - /** Unknown Entry Type */ - UnknownEntryType + public: + friend class SomeIpSdLayer; + + /** + * Construct a new Load Balancing object + * @param[in] priority Priority of this instance + * @param[in] weight Weight of this instance + */ + SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight); + + /** + * Construct a new Option object from already existing memory + * @param[in] dataContainer Data containing the option object + * @param[in] offset Offset for dataContainer + */ + SomeIpSdLoadBalancingOption(const IDataContainer* dataContainer, size_t offset); + + /** + * Get the priority fild + * @return uint16_t + */ + uint16_t getPriority() const; + + /** + * Get the weight field + * @return uint16_t + */ + uint16_t getWeight() const; + + private: + /** + * @struct someipsdhdroptionsload + * Represents the Load Balancing option header for SOME/IP-SD + */ +#pragma pack(push, 1) + struct someipsdhdroptionsload : someipsdhdroptionsbase + { + /* Priority field */ + uint16_t priority; + /* Weight field */ + uint16_t weight; + }; +#pragma pack(pop) }; /** - * @struct someipsdhdrentry - * Represents the Service Entry Type and Eventgroup Entry Type + * @class SomeIpSdEntry + * Implementation of the SOME/IP-SD Service Entry and Eventgroup Entry Type */ -#pragma pack(push, 1) - struct someipsdhdrentry + class SomeIpSdEntry { - /** Type */ - uint8_t type; - /** Index 1st option */ - uint8_t indexFirstOption; - /** Index 2nd option */ - uint8_t indexSecondOption; + public: + friend class SomeIpSdLayer; + + /** + * Types of entries that can occur in SOME/IP-SD + */ + enum class EntryType : uint8_t + { + /** Find Service */ + FindService, + /** Offer Service */ + OfferService, + /** Stop Offer Service */ + StopOfferService, + /** Subscribe Eventgroup */ + SubscribeEventgroup, + /** Stop Subscribe Eventgroup */ + StopSubscribeEventgroup, + /** Subscribe Eventgroup Acknowledgment */ + SubscribeEventgroupAck, + /** Subscribe Eventgroup Negative Acknowledgement */ + SubscribeEventgroupNack, + /** Unknown Entry Type */ + UnknownEntryType + }; + + /** + * @struct someipsdhdrentry + * Represents the Service Entry Type and Eventgroup Entry Type + */ +#pragma pack(push, 1) + struct someipsdhdrentry + { + /** Type */ + uint8_t type; + /** Index 1st option */ + uint8_t indexFirstOption; + /** Index 2nd option */ + uint8_t indexSecondOption; #if (BYTE_ORDER == LITTLE_ENDIAN) - uint8_t - /** Numbers of Option #2 (4bit) */ - nrOpt2 : 4, - /** Numbers of Option #1 (4bit) */ - nrOpt1 : 4; + uint8_t + /** Numbers of Option #2 (4bit) */ + nrOpt2 : 4, + /** Numbers of Option #1 (4bit) */ + nrOpt1 : 4; #else - uint8_t - /** Numbers of Option #1 (4bit) */ - nrOpt1 : 4, - /** Numbers of Option #2 (4bit) */ - nrOpt2 : 4; + uint8_t + /** Numbers of Option #1 (4bit) */ + nrOpt1 : 4, + /** Numbers of Option #2 (4bit) */ + nrOpt2 : 4; #endif - /** Service ID */ - uint16_t serviceID; - /** Instance ID */ - uint16_t instanceID; - /** Major Version (8 bit) + TTL (24 bit) */ - uint32_t majorVersion_ttl; - /** Minor Version (Service Entry Type) or Counter + Eventgroup ID (Eventgroup Entry Type) */ - uint32_t data; - }; + /** Service ID */ + uint16_t serviceID; + /** Instance ID */ + uint16_t instanceID; + /** Major Version (8 bit) + TTL (24 bit) */ + uint32_t majorVersion_ttl; + /** Minor Version (Service Entry Type) or Counter + Eventgroup ID (Eventgroup Entry Type) */ + uint32_t data; + }; #pragma pack(pop) - /** - * Construct a new SOME/IP-SD Service Entry Type - * @param[in] type Type to create - * @param[in] serviceID ServiceID to use - * @param[in] instanceID InstanceID to use - * @param[in] majorVersion MajorVersion to use - * @param[in] TTL TTL to use. Has to be 0 for all Stop* entry types - * @param[in] minorVersion MinorVersion to use - */ - SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL, - uint32_t minorVersion); - - /** - * Construct a new SOME/IP-SD Eventgroup Entry Type - * @param[in] type Type to create - * @param[in] serviceID ServiceID to use - * @param[in] instanceID InstanceID to use - * @param[in] majorVersion MajorVersion to use - * @param[in] TTL TTL to use. Has to be 0 for all Stop* entry types - * @param[in] counter Counter value to use - * @param[in] eventGroupID EventgroupId to use - */ - SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL, - uint8_t counter, uint16_t eventGroupID); - - /** - * Construct a new SomeIpSdEntry object from existing data - * @param[in] pSomeIpSdLayer Layer that this entry is created for - * @param[in] offset Offset for pSomeIpSdLayer - */ - SomeIpSdEntry(const SomeIpSdLayer *pSomeIpSdLayer, size_t offset); - - /** - * Destroy the SomeIpSd Entry object and delete allocated data if it has been allocated by a constructor - */ - ~SomeIpSdEntry(); - - /** - * Get the internal data of the SOME/IP-SD Entry - * @return uint8_t* - */ - uint8_t *getDataPtr() const; - - /** - * Get a pointer to the SOME/IP-SD Entry header - * @return someipsdhdrentry* - */ - someipsdhdrentry *getSomeIpSdEntryHeader() const; - - /** - * Get the Entry Type - * @return EntryType - */ - EntryType getType() const { return m_EntryType; } - - /** - * Get the Length of the SomeIpSd Entry - * @return size_t - */ - size_t getLength() const { return sizeof(someipsdhdrentry); } - - /** - * Get the number of Options of this Entry - * @return uint32_t - */ - uint32_t getNumOptions() const; - - /** - * Get the Service Id in host endianness - * @return uint16_t - */ - uint16_t getServiceId() const; - - /** - * Set the Service Id - * @param[in] serviceId - */ - void setServiceId(uint16_t serviceId); - - /** - * Get the Instance Id in host endianness - * @return uint16_t - */ - uint16_t getInstanceId() const; - - /** - * Set the Instance Id - * @param[in] instanceId - */ - void setInstanceId(uint16_t instanceId); - - /** - * Get the Major version field in host endianness - * @return uint16_t - */ - uint8_t getMajorVersion() const; - - /** - * Set the Major Version - * @param[in] majorVersion - */ - void setMajorVersion(uint8_t majorVersion); - - /** - * Get the Ttl field - * @return uint32_t - */ - uint32_t getTtl() const; - - /** - * Set the Ttl field - * @param[in] ttl - */ - void setTtl(uint32_t ttl); - - /** - * Get the minor version - * @return uint32_t - */ - uint32_t getMinorVersion() const; - - /** - * Set the minor version - * @param[in] minorVersion - */ - void setMinorVersion(uint32_t minorVersion); - - /** - * Get the counter value - * @return uint32_t - */ - uint8_t getCounter() const; - - /** - * Set the counter value - * @param[in] counter - */ - void setCounter(uint8_t counter); - - /** - * Get the eventgroup id - * @return uint32_t - */ - uint16_t getEventgroupId() const; - - /** - * Set the eventgroup id - * @param[in] eventgroupID - */ - void setEventgroupId(uint16_t eventgroupID); - -private: - /** - * These are the entry types used by SOME/IP-SD. They cannot be used for parameter passing since the values - * are not unique. - */ - enum class TypeInternal : uint8_t - { - /** Find Service */ - FindService_Internal = 0x00, - /** Offer Service / Stop Offer Service */ - OfferService_Internal = 0x01, - /** Subscribe Eventgroup & Stop Subscribe Eventgroup */ - SubscribeEventgroup_Internal = 0x06, - /** Subscribe Eventgroup Acknowledgment / Negative Acknowledgement */ - SubscribeEventgroupAck_Internal = 0x07, + /** + * Construct a new SOME/IP-SD Service Entry Type + * @param[in] type Type to create + * @param[in] serviceID ServiceID to use + * @param[in] instanceID InstanceID to use + * @param[in] majorVersion MajorVersion to use + * @param[in] TTL TTL to use. Has to be 0 for all Stop* entry types + * @param[in] minorVersion MinorVersion to use + */ + SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL, + uint32_t minorVersion); + + /** + * Construct a new SOME/IP-SD Eventgroup Entry Type + * @param[in] type Type to create + * @param[in] serviceID ServiceID to use + * @param[in] instanceID InstanceID to use + * @param[in] majorVersion MajorVersion to use + * @param[in] TTL TTL to use. Has to be 0 for all Stop* entry types + * @param[in] counter Counter value to use + * @param[in] eventGroupID EventgroupId to use + */ + SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL, + uint8_t counter, uint16_t eventGroupID); + + /** + * Construct a new SomeIpSdEntry object from existing data + * @param[in] pSomeIpSdLayer Layer that this entry is created for + * @param[in] offset Offset for pSomeIpSdLayer + */ + SomeIpSdEntry(const SomeIpSdLayer* pSomeIpSdLayer, size_t offset); + + /** + * Destroy the SomeIpSd Entry object and delete allocated data if it has been allocated by a constructor + */ + ~SomeIpSdEntry(); + + /** + * Get the internal data of the SOME/IP-SD Entry + * @return uint8_t* + */ + uint8_t* getDataPtr() const; + + /** + * Get a pointer to the SOME/IP-SD Entry header + * @return someipsdhdrentry* + */ + someipsdhdrentry* getSomeIpSdEntryHeader() const; + + /** + * Get the Entry Type + * @return EntryType + */ + EntryType getType() const + { + return m_EntryType; + } + + /** + * Get the Length of the SomeIpSd Entry + * @return size_t + */ + size_t getLength() const + { + return sizeof(someipsdhdrentry); + } + + /** + * Get the number of Options of this Entry + * @return uint32_t + */ + uint32_t getNumOptions() const; + + /** + * Get the Service Id in host endianness + * @return uint16_t + */ + uint16_t getServiceId() const; + + /** + * Set the Service Id + * @param[in] serviceId + */ + void setServiceId(uint16_t serviceId); + + /** + * Get the Instance Id in host endianness + * @return uint16_t + */ + uint16_t getInstanceId() const; + + /** + * Set the Instance Id + * @param[in] instanceId + */ + void setInstanceId(uint16_t instanceId); + + /** + * Get the Major version field in host endianness + * @return uint16_t + */ + uint8_t getMajorVersion() const; + + /** + * Set the Major Version + * @param[in] majorVersion + */ + void setMajorVersion(uint8_t majorVersion); + + /** + * Get the Ttl field + * @return uint32_t + */ + uint32_t getTtl() const; + + /** + * Set the Ttl field + * @param[in] ttl + */ + void setTtl(uint32_t ttl); + + /** + * Get the minor version + * @return uint32_t + */ + uint32_t getMinorVersion() const; + + /** + * Set the minor version + * @param[in] minorVersion + */ + void setMinorVersion(uint32_t minorVersion); + + /** + * Get the counter value + * @return uint32_t + */ + uint8_t getCounter() const; + + /** + * Set the counter value + * @param[in] counter + */ + void setCounter(uint8_t counter); + + /** + * Get the eventgroup id + * @return uint32_t + */ + uint16_t getEventgroupId() const; + + /** + * Set the eventgroup id + * @param[in] eventgroupID + */ + void setEventgroupId(uint16_t eventgroupID); + + private: + /** + * These are the entry types used by SOME/IP-SD. They cannot be used for parameter passing since the values + * are not unique. + */ + enum class TypeInternal : uint8_t + { + /** Find Service */ + FindService_Internal = 0x00, + /** Offer Service / Stop Offer Service */ + OfferService_Internal = 0x01, + /** Subscribe Eventgroup & Stop Subscribe Eventgroup */ + SubscribeEventgroup_Internal = 0x06, + /** Subscribe Eventgroup Acknowledgment / Negative Acknowledgement */ + SubscribeEventgroupAck_Internal = 0x07, + }; + + EntryType m_EntryType; + const SomeIpSdLayer* m_Layer; + size_t m_Offset; + uint8_t* m_ShadowData; + + void initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL); + + SomeIpSdEntry(const SomeIpSdEntry&) = delete; + SomeIpSdEntry& operator=(const SomeIpSdEntry&) = delete; + + static const uint32_t SOMEIPSD_HDR_ENTRY_MASK_TTL = 0x00FFFFFF; }; - EntryType m_EntryType; - const SomeIpSdLayer *m_Layer; - size_t m_Offset; - uint8_t *m_ShadowData; - - void initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, uint32_t TTL); - - SomeIpSdEntry(const SomeIpSdEntry &) = delete; - SomeIpSdEntry &operator=(const SomeIpSdEntry &) = delete; - - static const uint32_t SOMEIPSD_HDR_ENTRY_MASK_TTL = 0x00FFFFFF; -}; - -/** - * @class SomeIpSdLayer - * Implementation of the SOME/IP-SD protocol - */ -class SomeIpSdLayer : public SomeIpLayer -{ -public: - friend class SomeIpSdEntry; - - typedef SomeIpSdEntry* EntryPtr; - typedef std::vector EntriesVec; - typedef SomeIpSdOption* OptionPtr; - typedef std::vector OptionsVec; - - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - SomeIpSdLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet); - - /** - * Construct a new SomeIpSdLayer object - * @param[in] serviceID Service ID - * @param[in] methodID Method ID - * @param[in] clientID Client ID - * @param[in] sessionID Session ID - * @param[in] interfaceVersion Interface Version - * @param[in] type Type of the message - * @param[in] returnCode Return Code - * @param[in] flags Flags that shall be used in the header - */ - SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, - uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags); - - /** - * Destroy the layer object - */ - ~SomeIpSdLayer() {} - - /** - * Checks if given port is a SOME/IP-SD protocol port - * @param[in] port Port to check - * @return true if SOME/IP-SD protocol port, false if not - */ - static bool isSomeIpSdPort(uint16_t port) { return port == 30490; } - - /** - * The static method makes validation of input data - * @param[in] data The pointer to the beginning of byte stream of IP packet - * @param[in] dataLen The length of byte stream - * @return True if the data is valid and can represent the packet - */ - static bool isDataValid(const uint8_t* data, size_t dataLen); - - /** - * Get the Flags of the layer - * @return uint8_t Flags - */ - uint8_t getFlags() const; - - /** - * Set the Flags of the layer - * @param[in] flags Flags to set - */ - void setFlags(uint8_t flags); - - /** - * Get the number of entries in this layer - * @return uint32_t - */ - uint32_t getNumEntries() const; - - /** - * Get the number of options in this layer - * @return uint32_t - */ - uint32_t getNumOptions() const; - - /** - * Get the Entries from this layer - * @return EntriesVec Vector holding pointers to the options - */ - const EntriesVec getEntries() const; - - /** - * Get the Options from this layer - * @return OptionsVec Vector holding pointers to the options - */ - const OptionsVec getOptions() const; - - /** - * Get the Options from a specific Entry - * @param[in] index Index of the Entry, starting with 0. - * @return OptionsVec Vector holding pointers to the options - */ - const OptionsVec getOptionsFromEntry(uint32_t index) const; - /** - * Adds a given entry to the layer and returns the index of the entry - * @param[in] entry Pointer to the entry that shall be added to the layer - * @return uint32_t Returns the index of the entry starting with 0 + * @class SomeIpSdLayer + * Implementation of the SOME/IP-SD protocol */ - uint32_t addEntry(const SomeIpSdEntry &entry); - - /** - * Adds an option to an entry that has already been added to the layer by using addEntry(). The option - * is also added to the layer itself. If the option cannot by assigned to the entry, the option is not - * copied into the layer. - * @param[in] indexEntry Index of the entry where the option shall be added. First Entry has index 0 - * @param[in] option Pointer to the option that shall be added - * @return True if the option could be assigned to the entry and was copied into the layer, false otherwise - */ - bool addOptionTo(uint32_t indexEntry, const SomeIpSdOption &option); - - /** - * Does nothing for this layer - */ - void computeCalculateFields() {}; - - /** - * @return The string representation of the SOME/IP-SD layer - */ - std::string toString() const; - -private: - /** - * @struct someipsdhdr - * Represents an SOME/IP-SD protocol header - */ -#pragma pack(push, 1) - struct someipsdhdr : someiphdr + class SomeIpSdLayer : public SomeIpLayer { - /** Flags (8 bit) */ - uint8_t flags; - /** Reserved1 field (Bits 0-7 of 24-bits reserved field) */ - uint8_t reserved1; - /** Reserved2 field (Bits 8-15 of 24-bits reserved field) */ - uint8_t reserved2; - /** Reserved3 field (Bits 16-23 of 24-bits reserved field) */ - uint8_t reserved3; - }; + public: + friend class SomeIpSdEntry; + + typedef SomeIpSdEntry* EntryPtr; + typedef std::vector EntriesVec; + typedef SomeIpSdOption* OptionPtr; + typedef std::vector OptionsVec; + + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + SomeIpSdLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + + /** + * Construct a new SomeIpSdLayer object + * @param[in] serviceID Service ID + * @param[in] methodID Method ID + * @param[in] clientID Client ID + * @param[in] sessionID Session ID + * @param[in] interfaceVersion Interface Version + * @param[in] type Type of the message + * @param[in] returnCode Return Code + * @param[in] flags Flags that shall be used in the header + */ + SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags); + + /** + * Destroy the layer object + */ + ~SomeIpSdLayer() + {} + + /** + * Checks if given port is a SOME/IP-SD protocol port + * @param[in] port Port to check + * @return true if SOME/IP-SD protocol port, false if not + */ + static bool isSomeIpSdPort(uint16_t port) + { + return port == 30490; + } + + /** + * The static method makes validation of input data + * @param[in] data The pointer to the beginning of byte stream of IP packet + * @param[in] dataLen The length of byte stream + * @return True if the data is valid and can represent the packet + */ + static bool isDataValid(const uint8_t* data, size_t dataLen); + + /** + * Get the Flags of the layer + * @return uint8_t Flags + */ + uint8_t getFlags() const; + + /** + * Set the Flags of the layer + * @param[in] flags Flags to set + */ + void setFlags(uint8_t flags); + + /** + * Get the number of entries in this layer + * @return uint32_t + */ + uint32_t getNumEntries() const; + + /** + * Get the number of options in this layer + * @return uint32_t + */ + uint32_t getNumOptions() const; + + /** + * Get the Entries from this layer + * @return EntriesVec Vector holding pointers to the options + */ + const EntriesVec getEntries() const; + + /** + * Get the Options from this layer + * @return OptionsVec Vector holding pointers to the options + */ + const OptionsVec getOptions() const; + + /** + * Get the Options from a specific Entry + * @param[in] index Index of the Entry, starting with 0. + * @return OptionsVec Vector holding pointers to the options + */ + const OptionsVec getOptionsFromEntry(uint32_t index) const; + + /** + * Adds a given entry to the layer and returns the index of the entry + * @param[in] entry Pointer to the entry that shall be added to the layer + * @return uint32_t Returns the index of the entry starting with 0 + */ + uint32_t addEntry(const SomeIpSdEntry& entry); + + /** + * Adds an option to an entry that has already been added to the layer by using addEntry(). The option + * is also added to the layer itself. If the option cannot by assigned to the entry, the option is not + * copied into the layer. + * @param[in] indexEntry Index of the entry where the option shall be added. First Entry has index 0 + * @param[in] option Pointer to the option that shall be added + * @return True if the option could be assigned to the entry and was copied into the layer, false otherwise + */ + bool addOptionTo(uint32_t indexEntry, const SomeIpSdOption& option); + + /** + * Does nothing for this layer + */ + void computeCalculateFields() {}; + + /** + * @return The string representation of the SOME/IP-SD layer + */ + std::string toString() const; + + private: + /** + * @struct someipsdhdr + * Represents an SOME/IP-SD protocol header + */ +#pragma pack(push, 1) + struct someipsdhdr : someiphdr + { + /** Flags (8 bit) */ + uint8_t flags; + /** Reserved1 field (Bits 0-7 of 24-bits reserved field) */ + uint8_t reserved1; + /** Reserved2 field (Bits 8-15 of 24-bits reserved field) */ + uint8_t reserved2; + /** Reserved3 field (Bits 16-23 of 24-bits reserved field) */ + uint8_t reserved3; + }; #pragma pack(pop) - uint32_t m_NumOptions; + uint32_t m_NumOptions; - static bool countOptions(uint32_t& count, const uint8_t* data); - uint32_t findOption(const SomeIpSdOption &option); - void addOption(const SomeIpSdOption &option); - bool addOptionIndex(uint32_t indexEntry, uint32_t indexOffset); - OptionPtr parseOption(SomeIpSdOption::OptionType type, size_t offset) const; + static bool countOptions(uint32_t& count, const uint8_t* data); + uint32_t findOption(const SomeIpSdOption& option); + void addOption(const SomeIpSdOption& option); + bool addOptionIndex(uint32_t indexEntry, uint32_t indexOffset); + OptionPtr parseOption(SomeIpSdOption::OptionType type, size_t offset) const; - static size_t getLenEntries(const uint8_t* data); - size_t getLenEntries() const; - static size_t getLenOptions(const uint8_t* data); - size_t getLenOptions() const; - void setLenEntries(uint32_t length); - void setLenOptions(uint32_t length); -}; + static size_t getLenEntries(const uint8_t* data); + size_t getLenEntries() const; + static size_t getLenOptions(const uint8_t* data); + size_t getLenOptions() const; + void setLenEntries(uint32_t length); + void setLenOptions(uint32_t length); + }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/StpLayer.h b/Packet++/header/StpLayer.h index ffa72b8f1e..eb84f54948 100644 --- a/Packet++/header/StpLayer.h +++ b/Packet++/header/StpLayer.h @@ -28,8 +28,8 @@ namespace pcpp }; #pragma pack(pop) -/// Spanning Tree protocol common header -typedef stp_tcn_bpdu stp_header; + /// Spanning Tree protocol common header + typedef stp_tcn_bpdu stp_header; /** * @struct stp_conf_bpdu @@ -125,9 +125,9 @@ typedef stp_tcn_bpdu stp_header; */ class StpLayer : public Layer { - protected: - StpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) + protected: + StpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { m_Protocol = STP; } @@ -141,9 +141,9 @@ typedef stp_tcn_bpdu stp_header; } static pcpp::MacAddress IDtoMacAddress(uint64_t id); - static uint64_t macAddressToID(const pcpp::MacAddress &addr); + static uint64_t macAddressToID(const pcpp::MacAddress& addr); - public: + public: /// STP protocol uses "01:80:C2:00:00:00" multicast address as destination MAC static pcpp::MacAddress StpMulticastDstMAC; /// STP Uplink Fast protocol uses "01:00:0C:CD:CD:CD" as destination MAC @@ -153,58 +153,86 @@ typedef stp_tcn_bpdu stp_header; * Get a pointer to base Spanning tree header * @return A pointer to spanning tree header */ - stp_header *getStpHeader() const { return (stp_header *)(m_Data); } + stp_header* getStpHeader() const + { + return (stp_header*)(m_Data); + } /** * Returns the protocol id. Fixed at 0x0 for STP messages which represents IEEE 802.1d * @return ID of the protocol */ - uint16_t getProtoId() const { return getStpHeader()->protoId; } + uint16_t getProtoId() const + { + return getStpHeader()->protoId; + } /** * Sets the protocol id * @param[in] value ID of the protocol */ - void setProtoId(uint16_t value) { getStpHeader()->protoId = value; } + void setProtoId(uint16_t value) + { + getStpHeader()->protoId = value; + } /** * Returns the version. Fixed at 0x0 for STP messages * @return Version number */ - uint8_t getVersion() const { return getStpHeader()->version; } + uint8_t getVersion() const + { + return getStpHeader()->version; + } /** * Sets the version * @param[in] value Version number */ - void setVersion(uint8_t value) { getStpHeader()->version = value; } + void setVersion(uint8_t value) + { + getStpHeader()->version = value; + } /** * Returns the type of configuration message. * @return Type of configuration message */ - uint8_t getType() const { return getStpHeader()->type; } + uint8_t getType() const + { + return getStpHeader()->type; + } /** * Sets the type of configuration message * @param[in] value Type of configuration message */ - void setType(uint8_t value) { getStpHeader()->type = value; } + void setType(uint8_t value) + { + getStpHeader()->type = value; + } // overridden methods /** * @return The size of STP packet */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /// Does nothing for this layer - void computeCalculateFields() {} + void computeCalculateFields() + {} /** * @return The OSI layer level of STP (Data Link Layer). */ - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } /** * A static method that validates the input data @@ -212,7 +240,7 @@ typedef stp_tcn_bpdu stp_header; * @param[in] dataLen The length of the byte stream * @return True if the data is valid and can represent an Spanning Tree packet */ - static bool isDataValid(const uint8_t *data, size_t dataLen); + static bool isDataValid(const uint8_t* data, size_t dataLen); /** * A method to create STP layer from existing packet @@ -223,7 +251,7 @@ typedef stp_tcn_bpdu stp_header; * @return A newly allocated STP layer of one of the following types (according to the message type): * StpConfigurationBPDULayer, StpTopologyChangeBPDULayer, RapidStpLayer, MultipleStpLayer */ - static StpLayer *parseStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet); + static StpLayer* parseStpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); }; /** @@ -232,10 +260,11 @@ typedef stp_tcn_bpdu stp_header; */ class StpTopologyChangeBPDULayer : public StpLayer { - protected: - explicit StpTopologyChangeBPDULayer(size_t dataLen) : StpLayer(dataLen) {} + protected: + explicit StpTopologyChangeBPDULayer(size_t dataLen) : StpLayer(dataLen) + {} - public: + public: /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -243,10 +272,9 @@ typedef stp_tcn_bpdu stp_header; * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - StpTopologyChangeBPDULayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : StpLayer(data, dataLen, prevLayer, packet) - { - } + StpTopologyChangeBPDULayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : StpLayer(data, dataLen, prevLayer, packet) + {} /** * Empty c'tor to create a new network topology change (TCN) BPDU layer. @@ -258,14 +286,20 @@ typedef stp_tcn_bpdu stp_header; * Get a pointer to network topology change (TCN) BPDU message * @return A pointer to TCN BPDU message */ - stp_tcn_bpdu* getStpTcnHeader() { return getStpHeader(); } + stp_tcn_bpdu* getStpTcnHeader() + { + return getStpHeader(); + } // overridden methods /** * @return The size of STP TCN message */ - size_t getHeaderLen() const { return sizeof(stp_tcn_bpdu); } + size_t getHeaderLen() const + { + return sizeof(stp_tcn_bpdu); + } /// Parses next layer void parseNextLayer(); @@ -273,7 +307,10 @@ typedef stp_tcn_bpdu stp_header; /** * @return Returns the protocol info as readable string */ - std::string toString() const { return "Spanning Tree Topology Change Notification"; } + std::string toString() const + { + return "Spanning Tree Topology Change Notification"; + } /** * A static method that validates the input data @@ -281,7 +318,10 @@ typedef stp_tcn_bpdu stp_header; * @param[in] dataLen The length of the byte stream * @return True if the data is valid and can represent an Spanning Tree packet */ - static bool isDataValid(const uint8_t *data, size_t dataLen) { return data && dataLen >= sizeof(stp_tcn_bpdu); } + static bool isDataValid(const uint8_t* data, size_t dataLen) + { + return data && dataLen >= sizeof(stp_tcn_bpdu); + } }; /** @@ -290,10 +330,11 @@ typedef stp_tcn_bpdu stp_header; */ class StpConfigurationBPDULayer : public StpTopologyChangeBPDULayer { - protected: - explicit StpConfigurationBPDULayer(size_t dataLen) : StpTopologyChangeBPDULayer(dataLen) {} + protected: + explicit StpConfigurationBPDULayer(size_t dataLen) : StpTopologyChangeBPDULayer(dataLen) + {} - public: + public: /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -301,10 +342,9 @@ typedef stp_tcn_bpdu stp_header; * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - StpConfigurationBPDULayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : StpTopologyChangeBPDULayer(data, dataLen, prevLayer, packet) - { - } + StpConfigurationBPDULayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : StpTopologyChangeBPDULayer(data, dataLen, prevLayer, packet) + {} /** * Empty c'tor to create a new configuration BPDU layer. @@ -316,19 +356,28 @@ typedef stp_tcn_bpdu stp_header; * Get a pointer to configuration BPDU message * @return A pointer to configuration BPDU message */ - stp_conf_bpdu *getStpConfHeader() const { return (stp_conf_bpdu *)(m_Data); } + stp_conf_bpdu* getStpConfHeader() const + { + return (stp_conf_bpdu*)(m_Data); + } /** * Returns the flags of configuration message which indicates purpose of BPDU * @return Flags of the configuration message */ - uint8_t getFlag() const { return getStpConfHeader()->flag; } + uint8_t getFlag() const + { + return getStpConfHeader()->flag; + } /** * Returns the flags of configuration message which indicates purpose of BPDU * @param[in] value Flags of the configuration message */ - void setFlag(uint8_t value) { getStpConfHeader()->flag = value; } + void setFlag(uint8_t value) + { + getStpConfHeader()->flag = value; + } /** * Returns the root bridge identifier @@ -370,13 +419,16 @@ typedef stp_tcn_bpdu stp_header; * Returns the system identifier of root bridge * @return System identifier of root bridge */ - pcpp::MacAddress getRootSystemID() const { return IDtoMacAddress(getRootId()); } + pcpp::MacAddress getRootSystemID() const + { + return IDtoMacAddress(getRootId()); + } /** * Sets the system identifier of root bridge * @param[in] value System identifier of root bridge */ - void setRootSystemID(const pcpp::MacAddress &value); + void setRootSystemID(const pcpp::MacAddress& value); /** * Returns the value of the cost of path @@ -430,13 +482,16 @@ typedef stp_tcn_bpdu stp_header; * Returns the system identifier of bridge * @return System identifier of bridge */ - pcpp::MacAddress getBridgeSystemID() const { return IDtoMacAddress(getBridgeId()); } + pcpp::MacAddress getBridgeSystemID() const + { + return IDtoMacAddress(getBridgeId()); + } /** * Sets the system identifier of bridge * @param[in] value System identifier of bridge */ - void setBridgeSystemID(const pcpp::MacAddress &value); + void setBridgeSystemID(const pcpp::MacAddress& value); /** * Returns the port identifier @@ -503,7 +558,10 @@ typedef stp_tcn_bpdu stp_header; /** * @return The size of STP configuration BPDU message */ - size_t getHeaderLen() const { return sizeof(stp_conf_bpdu); } + size_t getHeaderLen() const + { + return sizeof(stp_conf_bpdu); + } /// Parses next layer void parseNextLayer(); @@ -511,7 +569,10 @@ typedef stp_tcn_bpdu stp_header; /** * @return Returns the protocol info as readable string */ - std::string toString() const { return "Spanning Tree Configuration"; } + std::string toString() const + { + return "Spanning Tree Configuration"; + } /** * A static method that validates the input data @@ -519,7 +580,7 @@ typedef stp_tcn_bpdu stp_header; * @param[in] dataLen The length of the byte stream * @return True if the data is valid and can represent an Spanning Tree packet */ - static bool isDataValid(const uint8_t *data, size_t dataLen) + static bool isDataValid(const uint8_t* data, size_t dataLen) { return data && dataLen >= sizeof(stp_conf_bpdu); } @@ -531,10 +592,11 @@ typedef stp_tcn_bpdu stp_header; */ class RapidStpLayer : public StpConfigurationBPDULayer { - protected: - explicit RapidStpLayer(size_t dataLen) : StpConfigurationBPDULayer(dataLen) {} + protected: + explicit RapidStpLayer(size_t dataLen) : StpConfigurationBPDULayer(dataLen) + {} - public: + public: /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -542,10 +604,9 @@ typedef stp_tcn_bpdu stp_header; * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - RapidStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : StpConfigurationBPDULayer(data, dataLen, prevLayer, packet) - { - } + RapidStpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : StpConfigurationBPDULayer(data, dataLen, prevLayer, packet) + {} /** * Empty c'tor to create a new Rapid STP layer. @@ -557,26 +618,38 @@ typedef stp_tcn_bpdu stp_header; * Get a pointer to Rapid STP header * @return A pointer to Rapid STP header */ - rstp_conf_bpdu *getRstpConfHeader() const { return (rstp_conf_bpdu *)(m_Data); } + rstp_conf_bpdu* getRstpConfHeader() const + { + return (rstp_conf_bpdu*)(m_Data); + } /** * Returns the length of version1 field. Fixed at 0x0 for Rapid STP * @return Length of the version1 field */ - uint8_t getVersion1Len() const { return getRstpConfHeader()->version1Len; } + uint8_t getVersion1Len() const + { + return getRstpConfHeader()->version1Len; + } /** * Returns the length of version1 field * @param[in] value Length of the version1 field */ - void setVersion1Len(uint8_t value) { getRstpConfHeader()->version1Len = value; } + void setVersion1Len(uint8_t value) + { + getRstpConfHeader()->version1Len = value; + } // overridden methods /** * @return The size of Rapid STP message */ - size_t getHeaderLen() const { return sizeof(rstp_conf_bpdu); } + size_t getHeaderLen() const + { + return sizeof(rstp_conf_bpdu); + } /// Parses next layer void parseNextLayer(); @@ -584,7 +657,10 @@ typedef stp_tcn_bpdu stp_header; /** * @return Returns the protocol info as readable string */ - std::string toString() const { return "Rapid Spanning Tree"; } + std::string toString() const + { + return "Rapid Spanning Tree"; + } /** * A static method that validates the input data @@ -592,7 +668,7 @@ typedef stp_tcn_bpdu stp_header; * @param[in] dataLen The length of the byte stream * @return True if the data is valid and can represent an Spanning Tree packet */ - static bool isDataValid(const uint8_t *data, size_t dataLen) + static bool isDataValid(const uint8_t* data, size_t dataLen) { return data && dataLen >= sizeof(rstp_conf_bpdu); } @@ -600,11 +676,12 @@ typedef stp_tcn_bpdu stp_header; /** * @class MultipleStpLayer - * Represents Multiple Spanning Tree Protocol (MSTP). It has limited capabilities (no crafting / limited editing) over MSTI configuration + * Represents Multiple Spanning Tree Protocol (MSTP). It has limited capabilities (no crafting / limited editing) + * over MSTI configuration */ class MultipleStpLayer : public RapidStpLayer { - public: + public: /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data @@ -612,10 +689,9 @@ typedef stp_tcn_bpdu stp_header; * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - MultipleStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : RapidStpLayer(data, dataLen, prevLayer, packet) - { - } + MultipleStpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : RapidStpLayer(data, dataLen, prevLayer, packet) + {} /** * Empty c'tor to create a new Multiple STP layer. @@ -627,7 +703,10 @@ typedef stp_tcn_bpdu stp_header; * Get a pointer to Multiple STP header * @return A pointer to Multiple STP header */ - mstp_conf_bpdu *getMstpHeader() const { return (mstp_conf_bpdu *)(m_Data); } + mstp_conf_bpdu* getMstpHeader() const + { + return (mstp_conf_bpdu*)(m_Data); + } /** * @return Length of version3 field @@ -644,13 +723,19 @@ typedef stp_tcn_bpdu stp_header; * Returns the configuration ID format selector * @return Configuration ID of format selector */ - uint8_t getMstConfigurationFormatSelector() const { return getMstpHeader()->mstConfigFormatSelector; } + uint8_t getMstConfigurationFormatSelector() const + { + return getMstpHeader()->mstConfigFormatSelector; + } /** * Sets the configuration ID format selector * @param[in] value Configuration ID of format selector */ - void setMstConfigurationFormatSelector(uint8_t value) { getMstpHeader()->mstConfigFormatSelector = value; } + void setMstConfigurationFormatSelector(uint8_t value) + { + getMstpHeader()->mstConfigFormatSelector = value; + } /** * Returns the pointer to configuration name field @@ -663,7 +748,7 @@ typedef stp_tcn_bpdu stp_header; * @param[in] value Configuration name. Length should be less than 32, if longer value provided first 32 * characters are used */ - void setMstConfigurationName(const std::string &value); + void setMstConfigurationName(const std::string& value); /** * Returns the revision of configuration ID @@ -681,14 +766,17 @@ typedef stp_tcn_bpdu stp_header; * Returns the pointer to configuration message digest. The field itself always 16 bytes long. * @return A pointer to configuration digest */ - uint8_t *getMstConfigDigest() const { return getMstpHeader()->mstConfigDigest; } + uint8_t* getMstConfigDigest() const + { + return getMstpHeader()->mstConfigDigest; + } /** * Sets the pointer to configuration message digest. The field itself always 16 bytes long. * @param[in] value Pointer to digest * @param[in] len Length of the digest, should be less than 16. If longer first 16 bytes are used */ - void setMstConfigDigest(const uint8_t *value, uint8_t len); + void setMstConfigDigest(const uint8_t* value, uint8_t len); /** * Returns CIST internal root path cost @@ -742,48 +830,65 @@ typedef stp_tcn_bpdu stp_header; * Returns the system identifier of CIST bridge * @return System identifier of CIST bridge */ - pcpp::MacAddress getCISTBridgeSystemID() const { return IDtoMacAddress(getCISTBridgeId()); } + pcpp::MacAddress getCISTBridgeSystemID() const + { + return IDtoMacAddress(getCISTBridgeId()); + } /** * Sets the system identifier of CIST bridge * @param[in] value System identifier of CIST bridge */ - void setCISTBridgeSystemID(const pcpp::MacAddress &value); + void setCISTBridgeSystemID(const pcpp::MacAddress& value); /** * Returns the remaining hop count * @return Value of remaining hop count */ - uint8_t getRemainingHopCount() const { return getMstpHeader()->remainId; } + uint8_t getRemainingHopCount() const + { + return getMstpHeader()->remainId; + } /** * Returns the remaining hop count * @param[in] value Value of remaining hop count */ - void setRemainingHopCount(uint8_t value) { getMstpHeader()->remainId = value; } + void setRemainingHopCount(uint8_t value) + { + getMstpHeader()->remainId = value; + } /** * Returns the total number of MSTI configuration messages * @return Number of MSTI configuration messages. Can be between 0 and 64. */ - uint8_t getNumberOfMSTIConfMessages() const { return (getVersion3Len() - (sizeof(mstp_conf_bpdu) - sizeof(rstp_conf_bpdu) - sizeof(uint16_t))) / sizeof(msti_conf_msg); } + uint8_t getNumberOfMSTIConfMessages() const + { + return (getVersion3Len() - (sizeof(mstp_conf_bpdu) - sizeof(rstp_conf_bpdu) - sizeof(uint16_t))) / + sizeof(msti_conf_msg); + } /** * Returns a reference to MSTI configuration messages. An MSTP packet can contain between 0 to 64 MSTI messages. * The number of messages can be obtained by using getNumberOfMSTIConfMessages() * @return An array pointer to MSTI configuration messages. Returns nullptr if there is no MSTI message. */ - msti_conf_msg *getMstiConfMessages() const; + msti_conf_msg* getMstiConfMessages() const; // overridden methods /// Parses next layer - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return Returns the protocol info as readable string */ - std::string toString() const { return "Multiple Spanning Tree"; } + std::string toString() const + { + return "Multiple Spanning Tree"; + } /** * A static method that validates the input data @@ -791,9 +896,9 @@ typedef stp_tcn_bpdu stp_header; * @param[in] dataLen The length of the byte stream * @return True if the data is valid and can represent an Spanning Tree packet */ - static bool isDataValid(const uint8_t *data, size_t dataLen) + static bool isDataValid(const uint8_t* data, size_t dataLen) { return data && dataLen >= sizeof(mstp_conf_bpdu); } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/TLVData.h b/Packet++/header/TLVData.h index 7ef0cfbbc3..6b09ac8dc9 100644 --- a/Packet++/header/TLVData.h +++ b/Packet++/header/TLVData.h @@ -14,16 +14,14 @@ namespace pcpp { /** * @class TLVRecord - * A wrapper class for a Type-Length-Value (TLV) record. This class does not create or modify TLV records, but rather - * serves as a wrapper and provides useful methods for retrieving data from them. This class has several abstract methods - * that should be implemented in derived classes. These methods are for record length value calculation (the 'L' in TLV) - * which is implemented differently in different protocols + * A wrapper class for a Type-Length-Value (TLV) record. This class does not create or modify TLV records, but + * rather serves as a wrapper and provides useful methods for retrieving data from them. This class has several + * abstract methods that should be implemented in derived classes. These methods are for record length value + * calculation (the 'L' in TLV) which is implemented differently in different protocols */ - template - class TLVRecord + template class TLVRecord { protected: - /** A struct representing the TLV construct */ struct TLVRawData { @@ -38,7 +36,6 @@ namespace pcpp TLVRawData* m_Data; public: - /** * A c'tor for this class that gets a pointer to the TLV record raw data (byte array) * @param[in] recordRawData A pointer to the TLV record raw data @@ -61,7 +58,8 @@ namespace pcpp /** * A d'tor for this class, currently does nothing */ - virtual ~TLVRecord() { } + virtual ~TLVRecord() + {} /** * Assign a pointer to the TLV record raw data (byte array) @@ -80,12 +78,14 @@ namespace pcpp */ static bool canAssign(const uint8_t* recordRawData, size_t tlvDataLen) { - return recordRawData != nullptr && tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen)); + return recordRawData != nullptr && + tlvDataLen >= (sizeof(TLVRawData::recordType) + sizeof(TLVRawData::recordLen)); } /** - * Overload of the assignment operator. This operator doesn't copy the TLV data, but rather copies the pointer to it, - * which means that after calling it both the old and the new instance will point to the same TLV raw data + * Overload of the assignment operator. This operator doesn't copy the TLV data, but rather copies the pointer + * to it, which means that after calling it both the old and the new instance will point to the same TLV raw + * data * @param[in] other The TLVRecord instance to assign */ TLVRecord& operator=(const TLVRecord& other) @@ -95,8 +95,8 @@ namespace pcpp } /** - * Overload of the equality operator. Two record are equal if both of them point to the same data, or if they point - * to different data but their total size is equal and the raw data they both contain is similar. + * Overload of the equality operator. Two record are equal if both of them point to the same data, or if they + * point to different data but their total size is equal and the raw data they both contain is similar. * @param[in] rhs The object to compare to * @return True if both objects are equal, false otherwise */ @@ -127,7 +127,8 @@ namespace pcpp /** * @return The type field of the record (the 'T' in __Type__-Length-Value) */ - TRecType getType() const { + TRecType getType() const + { if (m_Data == nullptr) return 0; @@ -137,7 +138,8 @@ namespace pcpp /** * @return A pointer to the value of the record as byte array (the 'V' in Type-Length- __Value__) */ - uint8_t* getValue() const { + uint8_t* getValue() const + { if (m_Data == nullptr) return nullptr; @@ -147,17 +149,26 @@ namespace pcpp /** * @return True if the TLV record raw data is NULL, false otherwise */ - bool isNull() const { return (m_Data == nullptr); } + bool isNull() const + { + return (m_Data == nullptr); + } /** * @return True if the TLV record raw data is not NULL, false otherwise */ - bool isNotNull() const { return (m_Data != nullptr); } + bool isNotNull() const + { + return (m_Data != nullptr); + } /** * @return A pointer to the TLV record raw data byte stream */ - uint8_t* getRecordBasePtr() const { return (uint8_t*)m_Data; } + uint8_t* getRecordBasePtr() const + { + return (uint8_t*)m_Data; + } /** * Free the memory of the TLV record raw data @@ -166,22 +177,21 @@ namespace pcpp { if (!isNull()) { - delete [] m_Data; + delete[] m_Data; m_Data = nullptr; } } /** * A templated method to retrieve the record data as a certain type T. For example, if record data is 4B long - * (integer) then this method should be used as getValueAs() and it will return the record data as an integer.
- * Notice this return value is a copy of the data, not a pointer to the actual data - * @param[in] offset The offset in the record data to start reading the value from. Useful for cases when you want - * to read some of the data that doesn't start at offset 0. This is an optional parameter and the default value - * is 0, meaning start reading the value at the beginning of the record data + * (integer) then this method should be used as getValueAs() and it will return the record data as an + * integer.
Notice this return value is a copy of the data, not a pointer to the actual data + * @param[in] offset The offset in the record data to start reading the value from. Useful for cases when you + * want to read some of the data that doesn't start at offset 0. This is an optional parameter and the default + * value is 0, meaning start reading the value at the beginning of the record data * @return The record data as type T */ - template - T getValueAs(size_t offset = 0) const + template T getValueAs(size_t offset = 0) const { if (getDataSize() - offset < sizeof(T)) return 0; @@ -192,16 +202,15 @@ namespace pcpp } /** - * A templated method to copy data of type T into the TLV record data. For example: if record data is 4[Bytes] long use - * this method with \ to set an integer value into the record data: setValue(num) + * A templated method to copy data of type T into the TLV record data. For example: if record data is 4[Bytes] + * long use this method with \ to set an integer value into the record data: setValue(num) * @param[in] newValue The value of type T to copy to the record data - * @param[in] valueOffset An optional parameter that specifies where to start setting the record data (default set to 0). For example: - * if record data is 20 bytes long and you only need to set the 4 last bytes as integer then use this method like this: - * setValue(num, 16) + * @param[in] valueOffset An optional parameter that specifies where to start setting the record data (default + * set to 0). For example: if record data is 20 bytes long and you only need to set the 4 last bytes as integer + * then use this method like this: setValue(num, 16) * @return True if value was set successfully or false if the size of T is larger than the record data size */ - template - bool setValue(T newValue, int valueOffset = 0) + template bool setValue(T newValue, int valueOffset = 0) { if (getDataSize() < sizeof(T)) return false; @@ -221,24 +230,24 @@ namespace pcpp virtual size_t getDataSize() const = 0; }; - /** * @class TLVRecordReader * A class for reading TLV records data out of a byte stream. This class contains helper methods for retrieving and * counting TLV records. This is a template class that expects template argument class derived from TLVRecord. */ - template - class TLVRecordReader + template class TLVRecordReader { private: mutable size_t m_RecordCount; public: - /** * A default c'tor for this class */ - TLVRecordReader() { m_RecordCount = (size_t)-1; } + TLVRecordReader() + { + m_RecordCount = (size_t)-1; + } /** * A default copy c'tor for this class @@ -251,7 +260,8 @@ namespace pcpp /** * A d'tor for this class which currently does nothing */ - virtual ~TLVRecordReader() { } + virtual ~TLVRecordReader() + {} /** * Overload of the assignment operator for this class @@ -268,12 +278,12 @@ namespace pcpp * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream * @param[in] tlvDataLen The TLV data byte stream length * @return An instance of type TLVRecordType that contains the first TLV record. If tlvDataBasePtr is NULL or - * tlvDataLen is zero the returned TLVRecordType instance will be logically NULL, meaning TLVRecordType.isNull() will - * return true + * tlvDataLen is zero the returned TLVRecordType instance will be logically NULL, meaning TLVRecordType.isNull() + * will return true */ TLVRecordType getFirstTLVRecord(uint8_t* tlvDataBasePtr, size_t tlvDataLen) const { - TLVRecordType resRec(NULL); // for NRVO optimization + TLVRecordType resRec(NULL); // for NRVO optimization if (!TLVRecordType::canAssign(tlvDataBasePtr, tlvDataLen)) return resRec; @@ -295,17 +305,19 @@ namespace pcpp * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream * @param[in] tlvDataLen The TLV data byte stream length * @return An instance of type TLVRecordType that wraps the record following the record given as input. If the - * input record.isNull() is true or if the next record is out of bounds of the byte stream, a logical NULL instance - * of TLVRecordType will be returned, meaning TLVRecordType.isNull() will return true + * input record.isNull() is true or if the next record is out of bounds of the byte stream, a logical NULL + * instance of TLVRecordType will be returned, meaning TLVRecordType.isNull() will return true */ TLVRecordType getNextTLVRecord(TLVRecordType& record, const uint8_t* tlvDataBasePtr, size_t tlvDataLen) const { - TLVRecordType resRec(NULL); // for NRVO optimization + TLVRecordType resRec(NULL); // for NRVO optimization if (record.isNull()) return resRec; - if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - record.getTotalSize())) + if (!TLVRecordType::canAssign(record.getRecordBasePtr() + record.getTotalSize(), + tlvDataBasePtr - record.getRecordBasePtr() + tlvDataLen - + record.getTotalSize())) return resRec; resRec.assign(record.getRecordBasePtr() + record.getTotalSize()); @@ -346,14 +358,14 @@ namespace pcpp } curRec.assign(NULL); - return curRec; // for NRVO optimization + return curRec; // for NRVO optimization } /** * Get the TLV record count in a given TLV data byte stream. For efficiency purposes the count is being cached - * so only the first call to this method will go over all the TLV records, while all consequent calls will return - * the cached number. This implies that if there is a change in the number of records, it's the user's responsibility - * to call changeTLVRecordCount() with the record count change + * so only the first call to this method will go over all the TLV records, while all consequent calls will + * return the cached number. This implies that if there is a change in the number of records, it's the user's + * responsibility to call changeTLVRecordCount() with the record count change * @param[in] tlvDataBasePtr A pointer to the TLV data byte stream * @param[in] tlvDataLen The TLV data byte stream length * @return The TLV record count @@ -376,28 +388,30 @@ namespace pcpp /** * As described in getTLVRecordCount(), the TLV record count is being cached for efficiency purposes. So if the - * number of TLV records change, it's the user's responsibility to call this method with the number of TLV records - * being added or removed. If records were added the change should be a positive number, or a negative number - * if records were removed + * number of TLV records change, it's the user's responsibility to call this method with the number of TLV + * records being added or removed. If records were added the change should be a positive number, or a negative + * number if records were removed * @param[in] changedBy Number of records that were added or removed */ - void changeTLVRecordCount(int changedBy) { if (m_RecordCount != (size_t)-1) m_RecordCount += changedBy; } + void changeTLVRecordCount(int changedBy) + { + if (m_RecordCount != (size_t)-1) + m_RecordCount += changedBy; + } }; - /** * @class TLVRecordBuilder - * A base class for building Type-Length-Value (TLV) records. This builder receives the record parameters in its c'tor, - * builds the record raw buffer and provides a method to build a TLVRecord object out of it. Please notice this is - * a base class that lacks the capability of actually building TLVRecord objects and also cannot be instantiated. The - * reason for that is that different protocols build TLV records in different ways, so these missing capabilities will - * be implemented by the derived classes which are specific to each protocol. This class only provides the common - * infrastructure that will be used by them + * A base class for building Type-Length-Value (TLV) records. This builder receives the record parameters in its + * c'tor, builds the record raw buffer and provides a method to build a TLVRecord object out of it. Please notice + * this is a base class that lacks the capability of actually building TLVRecord objects and also cannot be + * instantiated. The reason for that is that different protocols build TLV records in different ways, so these + * missing capabilities will be implemented by the derived classes which are specific to each protocol. This class + * only provides the common infrastructure that will be used by them */ class TLVRecordBuilder { protected: - TLVRecordBuilder(); TLVRecordBuilder(uint32_t recType, const uint8_t* recValue, uint8_t recValueLen); @@ -425,7 +439,6 @@ namespace pcpp uint32_t m_RecType; private: - void copyData(const TLVRecordBuilder& other); }; -} +} // namespace pcpp diff --git a/Packet++/header/TcpLayer.h b/Packet++/header/TcpLayer.h index 103c373c21..3efbb2c01f 100644 --- a/Packet++/header/TcpLayer.h +++ b/Packet++/header/TcpLayer.h @@ -5,8 +5,8 @@ #include "TLVData.h" #include -#define PCPP_DEPRECATED_TCP_OPTION_TYPE PCPP_DEPRECATED("enum TcpOptionType is deprecated; " \ - "Use enum class TcpOptionEnumType instead") +#define PCPP_DEPRECATED_TCP_OPTION_TYPE \ + PCPP_DEPRECATED("enum TcpOptionType is deprecated; Use enum class TcpOptionEnumType instead") /// @file @@ -21,7 +21,7 @@ namespace pcpp * @struct tcphdr * Represents an TCP protocol header */ -#pragma pack(push,1) +#pragma pack(push, 1) struct tcphdr { /** Source TCP port */ @@ -33,113 +33,114 @@ namespace pcpp /** Acknowledgment number */ uint32_t ackNumber; #if (BYTE_ORDER == LITTLE_ENDIAN) - uint16_t reserved:4, + uint16_t reserved : 4; /** Specifies the size of the TCP header in 32-bit words */ - dataOffset:4, + uint16_t dataOffset : 4; /** FIN flag */ - finFlag:1, + uint16_t finFlag : 1; /** SYN flag */ - synFlag:1, + uint16_t synFlag : 1; /** RST flag */ - rstFlag:1, + uint16_t rstFlag : 1; /** PSH flag */ - pshFlag:1, + uint16_t pshFlag : 1; /** ACK flag */ - ackFlag:1, + uint16_t ackFlag : 1; /** URG flag */ - urgFlag:1, + uint16_t urgFlag : 1; /** ECE flag */ - eceFlag:1, + uint16_t eceFlag : 1; /** CWR flag */ - cwrFlag:1; + uint16_t cwrFlag : 1; #elif (BYTE_ORDER == BIG_ENDIAN) /** Specifies the size of the TCP header in 32-bit words */ - uint16_t dataOffset:4, - reserved:4, + uint16_t dataOffset : 4; + /** Reserved */ + uint16_t reserved : 4; /** CWR flag */ - cwrFlag:1, + uint16_t cwrFlag : 1; /** ECE flag */ - eceFlag:1, + uint16_t eceFlag : 1; /** URG flag */ - urgFlag:1, + uint16_t urgFlag : 1; /** ACK flag */ - ackFlag:1, + uint16_t ackFlag : 1; /** PSH flag */ - pshFlag:1, + uint16_t pshFlag : 1; /** RST flag */ - rstFlag:1, + uint16_t rstFlag : 1; /** SYN flag */ - synFlag:1, + uint16_t synFlag : 1; /** FIN flag */ - finFlag:1; + uint16_t finFlag : 1; #else -#error "Endian is not LE nor BE..." +# error "Endian is not LE nor BE..." #endif /** The size of the receive window, which specifies the number of window size units (by default, bytes) */ - uint16_t windowSize; + uint16_t windowSize; /** The 16-bit checksum field is used for error-checking of the header and data */ - uint16_t headerChecksum; - /** If the URG flag (@ref tcphdr#urgFlag) is set, then this 16-bit field is an offset from the sequence number indicating the last urgent data byte */ - uint16_t urgentPointer; + uint16_t headerChecksum; + /** If the URG flag (@ref tcphdr#urgFlag) is set, then this 16-bit field is an offset from the sequence number + * indicating the last urgent data byte */ + uint16_t urgentPointer; }; #pragma pack(pop) - /** * TCP options types */ enum TcpOptionType : uint8_t { /** Padding */ - PCPP_TCPOPT_NOP = 1, + PCPP_TCPOPT_NOP = 1, /** End of options */ - PCPP_TCPOPT_EOL = 0, + PCPP_TCPOPT_EOL = 0, /** Segment size negotiating */ - TCPOPT_MSS = 2, + TCPOPT_MSS = 2, /** Window scaling */ - PCPP_TCPOPT_WINDOW = 3, + PCPP_TCPOPT_WINDOW = 3, /** SACK Permitted */ - TCPOPT_SACK_PERM = 4, + TCPOPT_SACK_PERM = 4, /** SACK Block */ - PCPP_TCPOPT_SACK = 5, + PCPP_TCPOPT_SACK = 5, /** Echo (obsoleted by option TcpOptionType::PCPP_TCPOPT_TIMESTAMP) */ - TCPOPT_ECHO = 6, + TCPOPT_ECHO = 6, /** Echo Reply (obsoleted by option TcpOptionType::PCPP_TCPOPT_TIMESTAMP) */ - TCPOPT_ECHOREPLY = 7, + TCPOPT_ECHOREPLY = 7, /** TCP Timestamps */ PCPP_TCPOPT_TIMESTAMP = 8, /** CC (obsolete) */ - TCPOPT_CC = 11, + TCPOPT_CC = 11, /** CC.NEW (obsolete) */ - TCPOPT_CCNEW = 12, + TCPOPT_CCNEW = 12, /** CC.ECHO(obsolete) */ - TCPOPT_CCECHO = 13, + TCPOPT_CCECHO = 13, /** MD5 Signature Option */ - TCPOPT_MD5 = 19, + TCPOPT_MD5 = 19, /** Multipath TCP */ - TCPOPT_MPTCP = 0x1e, + TCPOPT_MPTCP = 0x1e, /** SCPS Capabilities */ - TCPOPT_SCPS = 20, + TCPOPT_SCPS = 20, /** SCPS SNACK */ - TCPOPT_SNACK = 21, + TCPOPT_SNACK = 21, /** SCPS Record Boundary */ - TCPOPT_RECBOUND = 22, + TCPOPT_RECBOUND = 22, /** SCPS Corruption Experienced */ - TCPOPT_CORREXP = 23, + TCPOPT_CORREXP = 23, /** Quick-Start Response */ - TCPOPT_QS = 27, + TCPOPT_QS = 27, /** User Timeout Option (also, other known unauthorized use) */ - TCPOPT_USER_TO = 28, + TCPOPT_USER_TO = 28, /** RFC3692-style Experiment 1 (also improperly used for shipping products) */ - TCPOPT_EXP_FD = 0xfd, + TCPOPT_EXP_FD = 0xfd, /** RFC3692-style Experiment 2 (also improperly used for shipping products) */ - TCPOPT_EXP_FE = 0xfe, + TCPOPT_EXP_FE = 0xfe, /** Riverbed probe option, non IANA registered option number */ - TCPOPT_RVBD_PROBE = 76, + TCPOPT_RVBD_PROBE = 76, /** Riverbed transparency option, non IANA registered option number */ - TCPOPT_RVBD_TRPY = 78, + TCPOPT_RVBD_TRPY = 78, /** Unknown option */ - TCPOPT_Unknown = 255 + TCPOPT_Unknown = 255 }; /** @@ -148,108 +149,105 @@ namespace pcpp enum class TcpOptionEnumType : uint8_t { /** Padding */ - Nop = 1, + Nop = 1, /** End of options */ - Eol = 0, + Eol = 0, /** Segment size negotiating */ - Mss = 2, + Mss = 2, /** Window scaling */ - Window = 3, + Window = 3, /** SACK Permitted */ - SackPerm = 4, + SackPerm = 4, /** SACK Block */ - Sack = 5, + Sack = 5, /** Echo (obsoleted by option TcpOptionEnumType::Timestamp) */ - Echo = 6, + Echo = 6, /** Echo Reply (obsoleted by option TcpOptionEnumType::Timestamp) */ - EchoReply = 7, + EchoReply = 7, /** TCP Timestamps */ - Timestamp = 8, + Timestamp = 8, /** CC (obsolete) */ - Cc = 11, + Cc = 11, /** CC.NEW (obsolete) */ - CcNew = 12, + CcNew = 12, /** CC.ECHO(obsolete) */ - CcEcho = 13, + CcEcho = 13, /** MD5 Signature Option */ - Md5 = 19, + Md5 = 19, /** Multipath TCP */ - MpTcp = 0x1e, + MpTcp = 0x1e, /** SCPS Capabilities */ - Scps = 20, + Scps = 20, /** SCPS SNACK */ - Snack = 21, + Snack = 21, /** SCPS Record Boundary */ - RecBound = 22, + RecBound = 22, /** SCPS Corruption Experienced */ - CorrExp = 23, + CorrExp = 23, /** Quick-Start Response */ - Qs = 27, + Qs = 27, /** User Timeout Option (also, other known unauthorized use) */ - UserTo = 28, + UserTo = 28, /** RFC3692-style Experiment 1 (also improperly used for shipping products) */ - ExpFd = 0xfd, + ExpFd = 0xfd, /** RFC3692-style Experiment 2 (also improperly used for shipping products) */ - ExpFe = 0xfe, + ExpFe = 0xfe, /** Riverbed probe option, non IANA registered option number */ - RvbdProbe = 76, + RvbdProbe = 76, /** Riverbed transparency option, non IANA registered option number */ - RvbdTrpy = 78, + RvbdTrpy = 78, /** Unknown option */ - Unknown = 255 + Unknown = 255 }; - // TCP option lengths /** pcpp::TcpOptionEnumType::Nop length */ -#define PCPP_TCPOLEN_NOP 1 +#define PCPP_TCPOLEN_NOP 1 /** pcpp::TcpOptionEnumType::Eol length */ -#define PCPP_TCPOLEN_EOL 1 +#define PCPP_TCPOLEN_EOL 1 /** pcpp::TcpOptionEnumType::Mss length */ -#define PCPP_TCPOLEN_MSS 4 +#define PCPP_TCPOLEN_MSS 4 /** pcpp::TcpOptionEnumType::Window length */ -#define PCPP_TCPOLEN_WINDOW 3 +#define PCPP_TCPOLEN_WINDOW 3 /** pcpp::TcpOptionEnumType::SackPerm length */ -#define PCPP_TCPOLEN_SACK_PERM 2 +#define PCPP_TCPOLEN_SACK_PERM 2 /** pcpp::TcpOptionEnumType::Sack length */ -#define PCPP_TCPOLEN_SACK_MIN 2 +#define PCPP_TCPOLEN_SACK_MIN 2 /** pcpp::TcpOptionEnumType::Echo length */ -#define PCPP_TCPOLEN_ECHO 6 +#define PCPP_TCPOLEN_ECHO 6 /** pcpp::TcpOptionEnumType::EchoReply length */ -#define PCPP_TCPOLEN_ECHOREPLY 6 +#define PCPP_TCPOLEN_ECHOREPLY 6 /** pcpp::TcpOptionEnumType::Timestamp length */ -#define PCPP_TCPOLEN_TIMESTAMP 10 +#define PCPP_TCPOLEN_TIMESTAMP 10 /** pcpp::TcpOptionEnumType::Cc length */ -#define PCPP_TCPOLEN_CC 6 +#define PCPP_TCPOLEN_CC 6 /** pcpp::TcpOptionEnumType::CcNew length */ -#define PCPP_TCPOLEN_CCNEW 6 +#define PCPP_TCPOLEN_CCNEW 6 /** pcpp::TcpOptionEnumType::CcEcho length */ -#define PCPP_TCPOLEN_CCECHO 6 +#define PCPP_TCPOLEN_CCECHO 6 /** pcpp::TcpOptionEnumType::Md5 length */ -#define PCPP_TCPOLEN_MD5 18 +#define PCPP_TCPOLEN_MD5 18 /** pcpp::TcpOptionEnumType::MpTcp length */ -#define PCPP_TCPOLEN_MPTCP_MIN 8 +#define PCPP_TCPOLEN_MPTCP_MIN 8 /** pcpp::TcpOptionEnumType::Scps length */ -#define PCPP_TCPOLEN_SCPS 4 +#define PCPP_TCPOLEN_SCPS 4 /** pcpp::TcpOptionEnumType::Snack length */ -#define PCPP_TCPOLEN_SNACK 6 +#define PCPP_TCPOLEN_SNACK 6 /** pcpp::TcpOptionEnumType::RecBound length */ -#define PCPP_TCPOLEN_RECBOUND 2 +#define PCPP_TCPOLEN_RECBOUND 2 /** pcpp::TcpOptionEnumType::CorrExp length */ -#define PCPP_TCPOLEN_CORREXP 2 +#define PCPP_TCPOLEN_CORREXP 2 /** pcpp::TcpOptionEnumType::Qs length */ -#define PCPP_TCPOLEN_QS 8 +#define PCPP_TCPOLEN_QS 8 /** pcpp::TcpOptionEnumType::UserTo length */ -#define PCPP_TCPOLEN_USER_TO 4 +#define PCPP_TCPOLEN_USER_TO 4 /** pcpp::TcpOptionEnumType::RvbdProbe length */ #define PCPP_TCPOLEN_RVBD_PROBE_MIN 3 /** pcpp::TcpOptionEnumType::RvbdTrpy length */ #define PCPP_TCPOLEN_RVBD_TRPY_MIN 16 /** pcpp::TcpOptionEnumType::ExpFd and pcpp::TcpOptionEnumType::ExpFe length */ -#define PCPP_TCPOLEN_EXP_MIN 2 - - +#define PCPP_TCPOLEN_EXP_MIN 2 /** * @class TcpOption @@ -259,12 +257,12 @@ namespace pcpp class TcpOption : public TLVRecord { public: - /** * A c'tor for this class that gets a pointer to the option raw data (byte array) * @param[in] optionRawData A pointer to the TCP option raw data */ - explicit TcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) { } + explicit TcpOption(uint8_t* optionRawData) : TLVRecord(optionRawData) + {} /** * A d'tor for this class, currently does nothing @@ -334,7 +332,7 @@ namespace pcpp if (recordType == TcpOptionEnumType::Nop || recordType == TcpOptionEnumType::Eol) return 0; - return static_cast(m_Data->recordLen) - (2*sizeof(uint8_t)); + return static_cast(m_Data->recordLen) - (2 * sizeof(uint8_t)); } private: @@ -355,7 +353,6 @@ namespace pcpp } }; - /** * @class TcpOptionBuilder * A class for building TCP option records. This builder receives the TCP option parameters in its c'tor, @@ -365,7 +362,6 @@ namespace pcpp { public: - /** * An enum to describe NOP and EOL TCP options. Used in one of this class's c'tors */ @@ -377,7 +373,7 @@ namespace pcpp EOL }; - /** + /** * An enum to describe NOP and EOL TCP options. Used in one of this class's c'tors */ enum class NopEolOptionEnumType : uint8_t @@ -392,26 +388,29 @@ namespace pcpp * @deprecated This method is deprecated, please use constructor with TcpOptionEnumType */ PCPP_DEPRECATED_TCP_OPTION_TYPE - TcpOptionBuilder(TcpOptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) : - TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) {} + TcpOptionBuilder(TcpOptionType optionType, const uint8_t* optionValue, uint8_t optionValueLen) + : TLVRecordBuilder((uint8_t)optionType, optionValue, optionValueLen) + {} /** * A c'tor for building TCP options which their value is a byte array. The TcpOption object can be later * retrieved by calling build() * @param[in] optionType TCP option type - * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in any way. + * @param[in] optionValue A buffer containing the option value. This buffer is read-only and isn't modified in + * any way. * @param[in] optionValueLen Option value length in bytes */ - TcpOptionBuilder(TcpOptionEnumType optionType, const uint8_t* optionValue, uint8_t optionValueLen) : - TLVRecordBuilder(static_cast(optionType), optionValue, optionValueLen) {} + TcpOptionBuilder(TcpOptionEnumType optionType, const uint8_t* optionValue, uint8_t optionValueLen) + : TLVRecordBuilder(static_cast(optionType), optionValue, optionValueLen) + {} /** * @deprecated This method is deprecated, please use constructor with TcpOptionEnumType */ PCPP_DEPRECATED_TCP_OPTION_TYPE - TcpOptionBuilder(TcpOptionType optionType, uint8_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) {} - + TcpOptionBuilder(TcpOptionType optionType, uint8_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building TCP options which have a 1-byte value. The TcpOption object can be later retrieved @@ -419,15 +418,17 @@ namespace pcpp * @param[in] optionType TCP option type * @param[in] optionValue A 1-byte option value */ - TcpOptionBuilder(TcpOptionEnumType optionType, uint8_t optionValue) : - TLVRecordBuilder(static_cast(optionType), optionValue) {} + TcpOptionBuilder(TcpOptionEnumType optionType, uint8_t optionValue) + : TLVRecordBuilder(static_cast(optionType), optionValue) + {} /** * @deprecated This method is deprecated, please use constructor with TcpOptionEnumType */ PCPP_DEPRECATED_TCP_OPTION_TYPE - TcpOptionBuilder(TcpOptionType optionType, uint16_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) {} + TcpOptionBuilder(TcpOptionType optionType, uint16_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building TCP options which have a 2-byte value. The TcpOption object can be later retrieved @@ -435,15 +436,17 @@ namespace pcpp * @param[in] optionType TCP option type * @param[in] optionValue A 2-byte option value */ - TcpOptionBuilder(TcpOptionEnumType optionType, uint16_t optionValue) : - TLVRecordBuilder(static_cast(optionType), optionValue) {} + TcpOptionBuilder(TcpOptionEnumType optionType, uint16_t optionValue) + : TLVRecordBuilder(static_cast(optionType), optionValue) + {} /** * @deprecated This method is deprecated, please use constructor with TcpOptionEnumType */ PCPP_DEPRECATED_TCP_OPTION_TYPE - TcpOptionBuilder(TcpOptionType optionType, uint32_t optionValue) : - TLVRecordBuilder((uint8_t)optionType, optionValue) {} + TcpOptionBuilder(TcpOptionType optionType, uint32_t optionValue) + : TLVRecordBuilder((uint8_t)optionType, optionValue) + {} /** * A c'tor for building TCP options which have a 4-byte value. The TcpOption object can be later retrieved @@ -451,8 +454,9 @@ namespace pcpp * @param[in] optionType TCP option type * @param[in] optionValue A 4-byte option value */ - TcpOptionBuilder(TcpOptionEnumType optionType, uint32_t optionValue) : - TLVRecordBuilder(static_cast(optionType), optionValue) {} + TcpOptionBuilder(TcpOptionEnumType optionType, uint32_t optionValue) + : TLVRecordBuilder(static_cast(optionType), optionValue) + {} /** * @deprecated This method is deprecated, please use constructor with NopEolOptionEnumType @@ -475,7 +479,6 @@ namespace pcpp TcpOption build() const; }; - /** * @class TcpLayer * Represents a TCP (Transmission Control Protocol) protocol layer @@ -512,15 +515,20 @@ namespace pcpp TcpLayer(const TcpLayer& other); /** - * An assignment operator that first delete all data from current layer and then copy the entire header from the other TcpLayer (including TCP options) + * An assignment operator that first delete all data from current layer and then copy the entire header from the + * other TcpLayer (including TCP options) */ TcpLayer& operator=(const TcpLayer& other); /** - * Get a pointer to the TCP header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the TCP header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref tcphdr */ - tcphdr* getTcpHeader() const { return (tcphdr*)m_Data; } + tcphdr* getTcpHeader() const + { + return (tcphdr*)m_Data; + } /** * @return TCP source port @@ -547,8 +555,8 @@ namespace pcpp TcpOption getTcpOption(TcpOptionEnumType option) const; /** - * @return The first TCP option in the packet. If the current layer contains no options the returned value will contain - * a logical NULL (TcpOption#isNull() == true) + * @return The first TCP option in the packet. If the current layer contains no options the returned value will + * contain a logical NULL (TcpOption#isNull() == true) */ TcpOption getFirstTcpOption() const; @@ -576,21 +584,25 @@ namespace pcpp TcpOption addTcpOption(const TcpOptionBuilder& optionBuilder); /** - * @deprecated This method is deprecated, please use insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionEnumType prevOptionType = TcpOptionEnumType::Unknown) + * @deprecated This method is deprecated, please use insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, + * TcpOptionEnumType prevOptionType = TcpOptionEnumType::Unknown) */ PCPP_DEPRECATED("Use insertTcpOptionAfter instead") - TcpOption addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType = TcpOptionType::TCPOPT_Unknown); + TcpOption addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, + TcpOptionType prevOptionType = TcpOptionType::TCPOPT_Unknown); /** * Insert a new TCP option after an existing one * @param[in] optionBuilder A TcpOptionBuilder object that contains the requested TCP option data to be inserted - * @param[in] prevOptionType The TCP option which the newly inserted option should come after. This is an optional parameter which - * gets a default value of TcpOptionType::Unknown if omitted, which means the new option will be inserted as the first option in the layer + * @param[in] prevOptionType The TCP option which the newly inserted option should come after. This is an + * optional parameter which gets a default value of TcpOptionType::Unknown if omitted, which means the new + * option will be inserted as the first option in the layer * @return A TcpOption object containing the newly inserted TCP option data or logical NULL * (TcpOption#isNull() == true) if insertion failed. In case of a failure a corresponding error message will be * printed to log */ - TcpOption insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionEnumType prevOptionType = TcpOptionEnumType::Unknown); + TcpOption insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, + TcpOptionEnumType prevOptionType = TcpOptionEnumType::Unknown); /** * @deprecated This method is deprecated, please use removeTcpOption(TcpOptionEnumType) @@ -601,8 +613,8 @@ namespace pcpp /** * Remove an existing TCP option from the layer. TCP option is found by type * @param[in] optionType The TCP option type to remove - * @return True if TCP option was removed or false if type wasn't found or if removal failed (in each case a proper error - * will be written to log) + * @return True if TCP option was removed or false if type wasn't found or if removal failed (in each case a + * proper error will be written to log) */ bool removeTcpOption(TcpOptionEnumType optionType); @@ -613,10 +625,10 @@ namespace pcpp */ bool removeAllTcpOptions(); - /** * Calculate the checksum from header and data and possibly write the result to @ref tcphdr#headerChecksum - * @param[in] writeResultToPacket If set to true then checksum result will be written to @ref tcphdr#headerChecksum + * @param[in] writeResultToPacket If set to true then checksum result will be written to @ref + * tcphdr#headerChecksum * @return The checksum result */ uint16_t calculateChecksum(bool writeResultToPacket); @@ -632,14 +644,18 @@ namespace pcpp // implement abstract methods /** - * Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets PayloadLayer + * Currently identifies the following next layers: HttpRequestLayer, HttpResponseLayer. Otherwise sets + * PayloadLayer */ void parseNextLayer(); /** * @return Size of @ref tcphdr + all TCP options */ - size_t getHeaderLen() const { return getTcpHeader()->dataOffset*4 ;} + size_t getHeaderLen() const + { + return getTcpHeader()->dataOffset * 4; + } /** * Calculate @ref tcphdr#headerChecksum field @@ -648,30 +664,33 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelTransportLayer; + } private: - TLVRecordReader m_OptionReader; int m_NumOfTrailingBytes; void initLayer(); - uint8_t* getOptionsBasePtr() const { return m_Data + sizeof(tcphdr); } + uint8_t* getOptionsBasePtr() const + { + return m_Data + sizeof(tcphdr); + } TcpOption addTcpOptionAt(const TcpOptionBuilder& optionBuilder, int offset); void adjustTcpOptionTrailer(size_t totalOptSize); void copyLayerData(const TcpLayer& other); }; - // implementation of inline methods bool TcpLayer::isDataValid(const uint8_t* data, size_t dataLen) { const tcphdr* hdr = reinterpret_cast(data); - return dataLen >= sizeof(tcphdr) - && hdr->dataOffset >= 5 /* the minimum TCP header size */ - && dataLen >= hdr->dataOffset * sizeof(uint32_t); + return dataLen >= sizeof(tcphdr) && hdr->dataOffset >= 5 /* the minimum TCP header size */ + && dataLen >= hdr->dataOffset * sizeof(uint32_t); } -} // namespace pcpp +} // namespace pcpp #undef PCPP_DEPRECATED_TCP_OPTION_TYPE diff --git a/Packet++/header/TcpReassembly.h b/Packet++/header/TcpReassembly.h index 78b4d2a6f5..3c48413054 100644 --- a/Packet++/header/TcpReassembly.h +++ b/Packet++/header/TcpReassembly.h @@ -8,11 +8,11 @@ #include #include - /** * @file - * This is an implementation of TCP reassembly logic, which means reassembly of TCP messages spanning multiple TCP segments (or packets).
- * This logic can be useful in analyzing messages for a large number of protocols implemented on top of TCP including HTTP, SSL/TLS, FTP and many many more. + * This is an implementation of TCP reassembly logic, which means reassembly of TCP messages spanning multiple TCP + * segments (or packets).
This logic can be useful in analyzing messages for a large number of protocols implemented + * on top of TCP including HTTP, SSL/TLS, FTP and many many more. * * __General Features:__ * - Manage multiple TCP connections under one pcpp#TcpReassembly instance @@ -25,43 +25,61 @@ * __Logic Description:__ * - The user creates an instance of the pcpp#TcpReassembly class * - Then the user starts feeding it with TCP packets - * - The pcpp#TcpReassembly instance manages all TCP connections from the packets it's being fed. For each connection it manages its 2 sides (A->B and B->A) + * - The pcpp#TcpReassembly instance manages all TCP connections from the packets it's being fed. For each connection it + * manages its 2 sides (A->B and B->A). * - When a packet arrives, it is first classified to a certain TCP connection * - Then it is classified to a certain side of the TCP connection - * - Then the pcpp#TcpReassembly logic tries to understand if the data in this packet is the expected data (sequence-wise) and if it's new (e.g isn't a retransmission) - * - If the packet data matches these criteria a callback is being invoked. This callback is supplied by the user in the creation of the pcpp#TcpReassembly instance. This callback contains - * the new data (of course), but also information about the connection (5-tuple, 4-byte hash key describing the connection, etc.) and also a pointer to a "user cookie", meaning a pointer to - * a structure provided by the user during the creation of the pcpp#TcpReassembly instance + * - Then the pcpp#TcpReassembly logic tries to understand if the data in this packet is the expected data + * (sequence-wise) and if it's new (e.g isn't a retransmission). + * - If the packet data matches these criteria a callback is being invoked. This callback is supplied by the user in the + * creation of the pcpp#TcpReassembly instance. This callback contains the new data (of course), but also information + * about the connection (5-tuple, 4-byte hash key describing the connection, etc.) and also a pointer to a "user + * cookie", meaning a pointer to a structure provided by the user during the creation of the pcpp#TcpReassembly + * instance. * - If the data in this packet isn't new, it's being ignored - * - If the data in this packet isn't expected (meaning this packet came out-of-order), then the data is being queued internally and will be sent to the user when its turn arrives - * (meaning, after the data before arrives) - * - If the missing data doesn't arrive until a new message from the other side of the connection arrives or until the connection ends - this will be considered as missing data and the - * queued data will be sent to the user, but the string "[X bytes missing]" will be added to the message sent in the callback - * - pcpp#TcpReassembly supports 2 more callbacks - one is invoked when a new TCP connection is first seen and the other when it's ended (either by a FIN/RST packet or manually by the user). - * Both of these callbacks contain data about the connection (5-tuple, 4-byte hash key describing the connection, etc.) and also a pointer to a "user cookie", meaning a pointer to a - * structure provided by the user during the creation of the pcpp#TcpReassembly instance. The end connection callback also provides the reason for closing it ("naturally" or manually) + * - If the data in this packet isn't expected (meaning this packet came out-of-order), then the data is being queued + * internally and will be sent to the user when its turn arrives (meaning, after the data before arrives). + * - If the missing data doesn't arrive until a new message from the other side of the connection arrives or until the + * connection ends - this will be considered as missing data and the queued data will be sent to the user, but the + * string "[X bytes missing]" will be added to the message sent in the callback. + * - pcpp#TcpReassembly supports 2 more callbacks - one is invoked when a new TCP connection is first seen and the other + * when it's ended (either by a FIN/RST packet or manually by the user). Both of these callbacks contain data about + * the connection (5-tuple, 4-byte hash key describing the connection, etc.) and also a pointer to a "user cookie", + * meaning a pointer to a structure provided by the user during the creation of the pcpp#TcpReassembly instance. The + * end connection callback also provides the reason for closing it ("naturally" or manually). * * __Basic Usage and APIs:__ * - pcpp#TcpReassembly c'tor - Create an instance, provide the callbacks and the user cookie to the instance * - pcpp#TcpReassembly#reassemblePacket() - Feed pcpp#TcpReassembly instance with packets * - pcpp#TcpReassembly#closeConnection() - Manually close a connection by a flow key * - pcpp#TcpReassembly#closeAllConnections() - Manually close all currently opened connections - * - pcpp#TcpReassembly#OnTcpMessageReady callback - Invoked when new data arrives on a certain connection. Contains the new data as well as connection data (5-tuple, flow key) + * - pcpp#TcpReassembly#OnTcpMessageReady callback - Invoked when new data arrives on a certain connection. Contains the + * new data as well as connection data (5-tuple, flow key). * - pcpp#TcpReassembly#OnTcpConnectionStart callback - Invoked when a new connection is identified - * - pcpp#TcpReassembly#OnTcpConnectionEnd callback - Invoked when a connection ends (either by FIN/RST or manually by the user) + * - pcpp#TcpReassembly#OnTcpConnectionEnd callback - Invoked when a connection ends (either by FIN/RST or manually by + * the user). * * __Additional information:__ - * When the connection is closed the information is not being deleted from memory immediately. There is a delay between these moments. Existence of this delay is caused by two reasons: - * - pcpp#TcpReassembly#reassemblePacket() should detect the packets that arrive after the FIN packet has been received - * - the user can use the information about connections managed by pcpp#TcpReassembly instance. Following methods are used for this purpose: pcpp#TcpReassembly#getConnectionInformation and pcpp#TcpReassembly#isConnectionOpen. - * Cleaning of memory can be performed automatically (the default behavior) by pcpp#TcpReassembly#reassemblePacket() or manually by calling pcpp#TcpReassembly#purgeClosedConnections in the user code. - * Automatic cleaning is performed once per second. + * When the connection is closed the information is not being deleted from memory immediately. There is a delay between + * these moments. Existence of this delay is caused by two reasons: + * - pcpp#TcpReassembly#reassemblePacket() should detect the packets that arrive after the FIN packet has been received. + * - The user can use the information about connections managed by pcpp#TcpReassembly instance. Following methods are + * used for this purpose: pcpp#TcpReassembly#getConnectionInformation and pcpp#TcpReassembly#isConnectionOpen. + * Cleaning of memory can be performed automatically (the default behavior) by pcpp#TcpReassembly#reassemblePacket() or + * manually by calling pcpp#TcpReassembly#purgeClosedConnections in the user code. Automatic cleaning is performed once + * per second. * - * The struct pcpp#TcpReassemblyConfiguration allows to setup the parameters of cleanup. Following parameters are supported: - * - pcpp#TcpReassemblyConfiguration#doNotRemoveConnInfo - if this member is set to false the automatic cleanup mode is applied - * - pcpp#TcpReassemblyConfiguration#closedConnectionDelay - the value of delay expressed in seconds. The minimum value is 1 - * - pcpp#TcpReassemblyConfiguration#maxNumToClean - to avoid performance overhead when the cleanup is being performed, this parameter is used. It defines the maximum number of items to be removed per one call of pcpp#TcpReassembly#purgeClosedConnections - * - pcpp#TcpReassemblyConfiguration#maxOutOfOrderFragments - the maximum number of unmatched fragments to keep per flow before missed fragments are considered lost. A value of 0 means unlimited + * The struct pcpp#TcpReassemblyConfiguration allows to setup the parameters of cleanup. Following parameters are + * supported: + * - pcpp#TcpReassemblyConfiguration#doNotRemoveConnInfo - if this member is set to false the automatic cleanup mode is + * applied. + * - pcpp#TcpReassemblyConfiguration#closedConnectionDelay - the value of delay expressed in seconds. The minimum value + * is 1. + * - pcpp#TcpReassemblyConfiguration#maxNumToClean - to avoid performance overhead when the cleanup is being performed, + * this parameter is used. It defines the maximum number of items to be removed per one call of + * pcpp#TcpReassembly#purgeClosedConnections. + * - pcpp#TcpReassemblyConfiguration#maxOutOfOrderFragments - the maximum number of unmatched fragments to keep per flow + * before missed fragments are considered lost. A value of 0 means unlimited. * */ @@ -72,408 +90,479 @@ namespace pcpp { -/** - * @struct ConnectionData - * Represents basic TCP/UDP + IP connection data - */ -struct ConnectionData -{ - /** Source IP address */ - IPAddress srcIP; - /** Destination IP address */ - IPAddress dstIP; - /** Source TCP/UDP port */ - uint16_t srcPort; - /** Destination TCP/UDP port */ - uint16_t dstPort; - /** A 4-byte hash key representing the connection */ - uint32_t flowKey; - /** Start TimeStamp of the connection */ - timeval startTime; - /** End TimeStamp of the connection */ - timeval endTime; - - /** - * A c'tor for this struct that basically zeros all members - */ - ConnectionData() : srcPort(0), dstPort(0), flowKey(0), startTime(), endTime() {} - - /** - * Set startTime of Connection - * @param[in] startTimeValue integer value - */ - void setStartTime(const timeval &startTimeValue) { startTime = startTimeValue; } - /** - * Set endTime of Connection - * @param[in] endTimeValue integer value + * @struct ConnectionData + * Represents basic TCP/UDP + IP connection data */ - void setEndTime(const timeval &endTimeValue) { endTime = endTimeValue; } -}; - - -class TcpReassembly; - - -/** - * @class TcpStreamData - * When following a TCP connection each packet may contain a piece of the data transferred between the client and the server. This class represents these pieces: each instance of it - * contains a piece of data, usually extracted from a single packet, as well as information about the connection - */ -class TcpStreamData -{ -public: - /** - * A c'tor for this class that get data from outside and set the internal members - * @param[in] tcpData A pointer to buffer containing the TCP data piece - * @param[in] tcpDataLength The length of the buffer - * @param[in] missingBytes The number of missing bytes due to packet loss. - * @param[in] connData TCP connection information for this TCP data - * @param[in] timestamp when this packet was received - */ - TcpStreamData(const uint8_t* tcpData, size_t tcpDataLength, size_t missingBytes, const ConnectionData& connData, timeval timestamp) - : m_Data(tcpData), m_DataLen(tcpDataLength), m_MissingBytes(missingBytes), m_Connection(connData), m_Timestamp(timestamp) + struct ConnectionData { - } - - /** - * A getter for the data buffer - * @return A pointer to the buffer - */ - const uint8_t* getData() const { return m_Data; } + /** Source IP address */ + IPAddress srcIP; + /** Destination IP address */ + IPAddress dstIP; + /** Source TCP/UDP port */ + uint16_t srcPort; + /** Destination TCP/UDP port */ + uint16_t dstPort; + /** A 4-byte hash key representing the connection */ + uint32_t flowKey; + /** Start TimeStamp of the connection */ + timeval startTime; + /** End TimeStamp of the connection */ + timeval endTime; - /** - * A getter for buffer length - * @return Buffer length - */ - size_t getDataLength() const { return m_DataLen; } + /** + * A c'tor for this struct that basically zeros all members + */ + ConnectionData() : srcPort(0), dstPort(0), flowKey(0), startTime(), endTime() + {} - /** - * A getter for missing byte count due to packet loss. - * @return Missing byte count - */ - size_t getMissingByteCount() const { return m_MissingBytes; } + /** + * Set startTime of Connection + * @param[in] startTimeValue integer value + */ + void setStartTime(const timeval& startTimeValue) + { + startTime = startTimeValue; + } - /** - * Determine if bytes are missing. getMissingByteCount can be called to determine the number of missing bytes. - * @return true if bytes are missing. - */ - bool isBytesMissing() const { return getMissingByteCount() > 0; } + /** + * Set endTime of Connection + * @param[in] endTimeValue integer value + */ + void setEndTime(const timeval& endTimeValue) + { + endTime = endTimeValue; + } + }; - /** - * A getter for the connection data - * @return The const reference to connection data - */ - const ConnectionData& getConnectionData() const { return m_Connection; } + class TcpReassembly; /** - * A getter for the timestamp of this packet - * @return The const timeval object with timestamp of this packet + * @class TcpStreamData + * When following a TCP connection each packet may contain a piece of the data transferred between the client and + * the server. This class represents these pieces: each instance of it contains a piece of data, usually extracted + * from a single packet, as well as information about the connection */ - timeval getTimeStamp() const { return m_Timestamp; } + class TcpStreamData + { + public: + /** + * A c'tor for this class that get data from outside and set the internal members + * @param[in] tcpData A pointer to buffer containing the TCP data piece + * @param[in] tcpDataLength The length of the buffer + * @param[in] missingBytes The number of missing bytes due to packet loss. + * @param[in] connData TCP connection information for this TCP data + * @param[in] timestamp when this packet was received + */ + TcpStreamData(const uint8_t* tcpData, size_t tcpDataLength, size_t missingBytes, const ConnectionData& connData, + timeval timestamp) + : m_Data(tcpData), m_DataLen(tcpDataLength), m_MissingBytes(missingBytes), m_Connection(connData), + m_Timestamp(timestamp) + {} -private: - const uint8_t* m_Data; - size_t m_DataLen; - size_t m_MissingBytes; - const ConnectionData& m_Connection; - timeval m_Timestamp; -}; + /** + * A getter for the data buffer + * @return A pointer to the buffer + */ + const uint8_t* getData() const + { + return m_Data; + } + /** + * A getter for buffer length + * @return Buffer length + */ + size_t getDataLength() const + { + return m_DataLen; + } -/** - * @struct TcpReassemblyConfiguration - * A structure for configuring the TcpReassembly class - */ -struct TcpReassemblyConfiguration -{ - /** The flag indicating whether to remove the connection data after a connection is closed */ - bool removeConnInfo; + /** + * A getter for missing byte count due to packet loss. + * @return Missing byte count + */ + size_t getMissingByteCount() const + { + return m_MissingBytes; + } - /** How long the closed connections will not be cleaned up. The value is expressed in seconds. If the value is set to 0 then TcpReassembly should use the default value. - * This parameter is only relevant if removeConnInfo is equal to true. - */ - uint32_t closedConnectionDelay; + /** + * Determine if bytes are missing. getMissingByteCount can be called to determine the number of missing bytes. + * @return true if bytes are missing. + */ + bool isBytesMissing() const + { + return getMissingByteCount() > 0; + } - /** The maximum number of items to be cleaned up per one call of purgeClosedConnections. If the value is set to 0 then TcpReassembly should use the default value. - * This parameter is only relevant if removeConnInfo is equal to true. - */ - uint32_t maxNumToClean; + /** + * A getter for the connection data + * @return The const reference to connection data + */ + const ConnectionData& getConnectionData() const + { + return m_Connection; + } - /** The maximum number of fragments with a non-matching sequence-number to store per connection flow before packets are assumed permanently missed. - If the value is 0, TcpReassembly should keep out of order fragments indefinitely, or until a message from the paired side is seen. - */ - uint32_t maxOutOfOrderFragments; + /** + * A getter for the timestamp of this packet + * @return The const timeval object with timestamp of this packet + */ + timeval getTimeStamp() const + { + return m_Timestamp; + } - /** To enable to clear buffer once packet contains data from a different side than the side seen before - */ - bool enableBaseBufferClearCondition; + private: + const uint8_t* m_Data; + size_t m_DataLen; + size_t m_MissingBytes; + const ConnectionData& m_Connection; + timeval m_Timestamp; + }; /** - * A c'tor for this struct - * @param[in] removeConnInfo The flag indicating whether to remove the connection data after a connection is closed. The default is true - * @param[in] closedConnectionDelay How long the closed connections will not be cleaned up. The value is expressed in seconds. If it's set to 0 the default value will be used. The default is 5. - * @param[in] maxNumToClean The maximum number of items to be cleaned up per one call of purgeClosedConnections. If it's set to 0 the default value will be used. The default is 30. - * @param[in] maxOutOfOrderFragments The maximum number of unmatched fragments to keep per flow before missed fragments are considered lost. The default is unlimited. - * @param[in] enableBaseBufferClearCondition To enable to clear buffer once packet contains data from a different side than the side seen before + * @struct TcpReassemblyConfiguration + * A structure for configuring the TcpReassembly class */ - explicit TcpReassemblyConfiguration(bool removeConnInfo = true, uint32_t closedConnectionDelay = 5, uint32_t maxNumToClean = 30, uint32_t maxOutOfOrderFragments = 0, - bool enableBaseBufferClearCondition = true) : removeConnInfo(removeConnInfo), closedConnectionDelay(closedConnectionDelay), maxNumToClean(maxNumToClean), maxOutOfOrderFragments(maxOutOfOrderFragments), enableBaseBufferClearCondition(enableBaseBufferClearCondition) + struct TcpReassemblyConfiguration { - } -}; + /** The flag indicating whether to remove the connection data after a connection is closed */ + bool removeConnInfo; + /** How long the closed connections will not be cleaned up. The value is expressed in seconds. If the value is + * set to 0 then TcpReassembly should use the default value. This parameter is only relevant if removeConnInfo + * is equal to true. + */ + uint32_t closedConnectionDelay; -/** - * @class TcpReassembly - * A class containing the TCP reassembly logic. Please refer to the documentation at the top of TcpReassembly.h for understanding how to use this class - */ -class TcpReassembly -{ -public: + /** The maximum number of items to be cleaned up per one call of purgeClosedConnections. If the value is set to + * 0 then TcpReassembly should use the default value. This parameter is only relevant if removeConnInfo is equal + * to true. + */ + uint32_t maxNumToClean; - /** - * An enum for connection end reasons - */ - enum ConnectionEndReason - { - /** Connection ended because of FIN or RST packet */ - TcpReassemblyConnectionClosedByFIN_RST, - /** Connection ended manually by the user */ - TcpReassemblyConnectionClosedManually + /** The maximum number of fragments with a non-matching sequence-number to store per connection flow before + packets are assumed permanently missed. If the value is 0, TcpReassembly should keep out of order fragments + indefinitely, or until a message from the paired side is seen. + */ + uint32_t maxOutOfOrderFragments; + + /** To enable to clear buffer once packet contains data from a different side than the side seen before + */ + bool enableBaseBufferClearCondition; + + /** + * A c'tor for this struct + * @param[in] removeConnInfo The flag indicating whether to remove the connection data after a connection is + * closed. The default is true + * @param[in] closedConnectionDelay How long the closed connections will not be cleaned up. The value is + * expressed in seconds. If it's set to 0 the default value will be used. The default is 5. + * @param[in] maxNumToClean The maximum number of items to be cleaned up per one call of purgeClosedConnections. + * If it's set to 0 the default value will be used. The default is 30. + * @param[in] maxOutOfOrderFragments The maximum number of unmatched fragments to keep per flow before missed + * fragments are considered lost. The default is unlimited. + * @param[in] enableBaseBufferClearCondition To enable to clear buffer once packet contains data from a + * different side than the side seen before + */ + explicit TcpReassemblyConfiguration(bool removeConnInfo = true, uint32_t closedConnectionDelay = 5, + uint32_t maxNumToClean = 30, uint32_t maxOutOfOrderFragments = 0, + bool enableBaseBufferClearCondition = true) + : removeConnInfo(removeConnInfo), closedConnectionDelay(closedConnectionDelay), + maxNumToClean(maxNumToClean), maxOutOfOrderFragments(maxOutOfOrderFragments), + enableBaseBufferClearCondition(enableBaseBufferClearCondition) + {} }; /** - * An enum for providing reassembly status for each processed packet + * @class TcpReassembly + * A class containing the TCP reassembly logic. Please refer to the documentation at the top of TcpReassembly.h for + * understanding how to use this class */ - enum ReassemblyStatus + class TcpReassembly { + public: /** - * The processed packet contains valid TCP payload, and its payload is processed by `OnMessageReadyCallback` callback function. - * The packet may be: - * 1. An in-order TCP packet, meaning `packet_sequence == sequence_expected`. - * Note if there's any buffered out-of-order packet waiting for this packet, their associated callbacks are called in this `reassemblePacket` call. - * 2. An out-of-order TCP packet which satisfy `packet_sequence < sequence_expected && packet_sequence + packet_payload_length > sequence_expected`. - * Note only the new data (the `[sequence_expected, packet_sequence + packet_payload_length]` part ) is processed by `OnMessageReadyCallback` callback function. + * An enum for connection end reasons */ - TcpMessageHandled, + enum ConnectionEndReason + { + /** Connection ended because of FIN or RST packet */ + TcpReassemblyConnectionClosedByFIN_RST, + /** Connection ended manually by the user */ + TcpReassemblyConnectionClosedManually + }; + /** - * The processed packet is an out-of-order TCP packet, meaning `packet_sequence > sequence_expected`. It's buffered so no `OnMessageReadyCallback` callback function is called. - * The callback function for this packet maybe called LATER, under different circumstances: - * 1. When an in-order packet which is right before this packet arrives(case 1 and case 2 described in `TcpMessageHandled` section above). - * 2. When a FIN or RST packet arrives, which will clear the buffered out-of-order packets of this side. - * If this packet contains "new data", meaning `(packet_sequence <= sequence_expected) && (packet_sequence + packet_payload_length > sequence_expected)`, the new data is processed by `OnMessageReadyCallback` callback. + * An enum for providing reassembly status for each processed packet */ - OutOfOrderTcpMessageBuffered, + enum ReassemblyStatus + { + /** + * The processed packet contains valid TCP payload, and its payload is processed by `OnMessageReadyCallback` + * callback function. The packet may be: + * 1. An in-order TCP packet, meaning `packet_sequence == sequence_expected`. + * Note if there's any buffered out-of-order packet waiting for this packet, their associated callbacks + * are called in this `reassemblePacket` call. + * 2. An out-of-order TCP packet which satisfy `packet_sequence < sequence_expected && packet_sequence + + * packet_payload_length > sequence_expected`. Note only the new data (the `[sequence_expected, + * packet_sequence + packet_payload_length]` part ) is processed by `OnMessageReadyCallback` callback + * function. + */ + TcpMessageHandled, + /** + * The processed packet is an out-of-order TCP packet, meaning `packet_sequence > sequence_expected`. It's + * buffered so no `OnMessageReadyCallback` callback function is called. The callback function for this + * packet maybe called LATER, under different circumstances: + * 1. When an in-order packet which is right before this packet arrives(case 1 and case 2 described in + * `TcpMessageHandled` section above). + * 2. When a FIN or RST packet arrives, which will clear the buffered out-of-order packets of this side. + * If this packet contains "new data", meaning `(packet_sequence <= sequence_expected) && + * (packet_sequence + packet_payload_length > sequence_expected)`, the new data is processed by + * `OnMessageReadyCallback` callback. + */ + OutOfOrderTcpMessageBuffered, + /** + * The processed packet is a FIN or RST packet with no payload. + * Buffered out-of-order packets will be cleared. + * If they contain "new data", the new data is processed by `OnMessageReadyCallback` callback. + */ + FIN_RSTWithNoData, + /** + * The processed packet is not a SYN/SYNACK/FIN/RST packet and has no payload. + * Normally it's just a bare ACK packet. + * It's ignored and no callback function is called. + */ + Ignore_PacketWithNoData, + /** + * The processed packet comes from a closed flow(an in-order FIN or RST is seen). + * It's ignored and no callback function is called. + */ + Ignore_PacketOfClosedFlow, + /** + * The processed packet is a restransmission packet with no new data, meaning the `packet_sequence + + * packet_payload_length < sequence_expected`. It's ignored and no callback function is called. + */ + Ignore_Retransimission, + /** + * The processed packet is not an IP packet. + * It's ignored and no callback function is called. + */ + NonIpPacket, + /** + * The processed packet is not a TCP packet. + * It's ignored and no callback function is called. + */ + NonTcpPacket, + /** + * The processed packet does not belong to any known TCP connection. + * It's ignored and no callback function is called. + * Normally this will be happen. + */ + Error_PacketDoesNotMatchFlow, + }; + /** - * The processed packet is a FIN or RST packet with no payload. - * Buffered out-of-order packets will be cleared. - * If they contain "new data", the new data is processed by `OnMessageReadyCallback` callback. + * The type for storing the connection information */ - FIN_RSTWithNoData, + typedef std::unordered_map ConnectionInfoList; + /** - * The processed packet is not a SYN/SYNACK/FIN/RST packet and has no payload. - * Normally it's just a bare ACK packet. - * It's ignored and no callback function is called. + * @typedef OnTcpMessageReady + * A callback invoked when new data arrives on a connection + * @param[in] side The side this data belongs to (MachineA->MachineB or vice versa). The value is 0 or 1 where 0 + * is the first side seen in the connection and 1 is the second side seen + * @param[in] tcpData The TCP data itself + connection information + * @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no + * cookie provided) */ - Ignore_PacketWithNoData, + typedef void (*OnTcpMessageReady)(int8_t side, const TcpStreamData& tcpData, void* userCookie); + /** - * The processed packet comes from a closed flow(an in-order FIN or RST is seen). - * It's ignored and no callback function is called. + * @typedef OnTcpConnectionStart + * A callback invoked when a new TCP connection is identified (whether it begins with a SYN packet or not) + * @param[in] connectionData Connection information + * @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no + * cookie provided) */ - Ignore_PacketOfClosedFlow, + typedef void (*OnTcpConnectionStart)(const ConnectionData& connectionData, void* userCookie); + /** - * The processed packet is a restransmission packet with no new data, meaning the `packet_sequence + packet_payload_length < sequence_expected`. - * It's ignored and no callback function is called. + * @typedef OnTcpConnectionEnd + * A callback invoked when a TCP connection is terminated, either by a FIN or RST packet or manually by the user + * @param[in] connectionData Connection information + * @param[in] reason The reason for connection termination: FIN/RST packet or manually by the user + * @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no + * cookie provided) */ - Ignore_Retransimission, + typedef void (*OnTcpConnectionEnd)(const ConnectionData& connectionData, ConnectionEndReason reason, + void* userCookie); + /** - * The processed packet is not an IP packet. - * It's ignored and no callback function is called. + * A c'tor for this class + * @param[in] onMessageReadyCallback The callback to be invoked when new data arrives + * @param[in] userCookie A pointer to an object provided by the user. This pointer will be returned when + * invoking the various callbacks. This parameter is optional, default cookie is NULL + * @param[in] onConnectionStartCallback The callback to be invoked when a new connection is identified. This + * parameter is optional + * @param[in] onConnectionEndCallback The callback to be invoked when a new connection is terminated (either by + * a FIN/RST packet or manually by the user). This parameter is optional + * @param[in] config Optional parameter for defining special configuration parameters. If not set the default + * parameters will be set */ - NonIpPacket, + explicit TcpReassembly(OnTcpMessageReady onMessageReadyCallback, void* userCookie = NULL, + OnTcpConnectionStart onConnectionStartCallback = NULL, + OnTcpConnectionEnd onConnectionEndCallback = NULL, + const TcpReassemblyConfiguration& config = TcpReassemblyConfiguration()); + /** - * The processed packet is not a TCP packet. - * It's ignored and no callback function is called. + * The most important method of this class which gets a packet from the user and processes it. If this packet + * opens a new connection, ends a connection or contains new data on an existing connection, the relevant + * callback will be called (TcpReassembly#OnTcpMessageReady, TcpReassembly#OnTcpConnectionStart, + * TcpReassembly#OnTcpConnectionEnd) + * @param[in] tcpData A reference to the packet to process + * @return A enum of `TcpReassembly::ReassemblyStatus`, indicating status of TCP reassembly */ - NonTcpPacket, + ReassemblyStatus reassemblePacket(Packet& tcpData); + /** - * The processed packet does not belong to any known TCP connection. - * It's ignored and no callback function is called. - * Normally this will be happen. + * The most important method of this class which gets a raw packet from the user and processes it. If this + * packet opens a new connection, ends a connection or contains new data on an existing connection, the relevant + * callback will be invoked (TcpReassembly#OnTcpMessageReady, TcpReassembly#OnTcpConnectionStart, + * TcpReassembly#OnTcpConnectionEnd) + * @param[in] tcpRawData A reference to the raw packet to process + * @return A enum of `TcpReassembly::ReassemblyStatus`, indicating status of TCP reassembly */ - Error_PacketDoesNotMatchFlow, - }; - - /** - * The type for storing the connection information - */ - typedef std::unordered_map ConnectionInfoList; - - /** - * @typedef OnTcpMessageReady - * A callback invoked when new data arrives on a connection - * @param[in] side The side this data belongs to (MachineA->MachineB or vice versa). The value is 0 or 1 where 0 is the first side seen in the connection and 1 is the second side seen - * @param[in] tcpData The TCP data itself + connection information - * @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no cookie provided) - */ - typedef void (*OnTcpMessageReady)(int8_t side, const TcpStreamData& tcpData, void* userCookie); - - /** - * @typedef OnTcpConnectionStart - * A callback invoked when a new TCP connection is identified (whether it begins with a SYN packet or not) - * @param[in] connectionData Connection information - * @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no cookie provided) - */ - typedef void (*OnTcpConnectionStart)(const ConnectionData& connectionData, void* userCookie); - - /** - * @typedef OnTcpConnectionEnd - * A callback invoked when a TCP connection is terminated, either by a FIN or RST packet or manually by the user - * @param[in] connectionData Connection information - * @param[in] reason The reason for connection termination: FIN/RST packet or manually by the user - * @param[in] userCookie A pointer to the cookie provided by the user in TcpReassembly c'tor (or NULL if no cookie provided) - */ - typedef void (*OnTcpConnectionEnd)(const ConnectionData& connectionData, ConnectionEndReason reason, void* userCookie); - - /** - * A c'tor for this class - * @param[in] onMessageReadyCallback The callback to be invoked when new data arrives - * @param[in] userCookie A pointer to an object provided by the user. This pointer will be returned when invoking the various callbacks. This parameter is optional, default cookie is NULL - * @param[in] onConnectionStartCallback The callback to be invoked when a new connection is identified. This parameter is optional - * @param[in] onConnectionEndCallback The callback to be invoked when a new connection is terminated (either by a FIN/RST packet or manually by the user). This parameter is optional - * @param[in] config Optional parameter for defining special configuration parameters. If not set the default parameters will be set - */ - explicit TcpReassembly(OnTcpMessageReady onMessageReadyCallback, void* userCookie = NULL, OnTcpConnectionStart onConnectionStartCallback = NULL, OnTcpConnectionEnd onConnectionEndCallback = NULL, const TcpReassemblyConfiguration &config = TcpReassemblyConfiguration()); - - /** - * The most important method of this class which gets a packet from the user and processes it. If this packet opens a new connection, ends a connection or contains new data on an - * existing connection, the relevant callback will be called (TcpReassembly#OnTcpMessageReady, TcpReassembly#OnTcpConnectionStart, TcpReassembly#OnTcpConnectionEnd) - * @param[in] tcpData A reference to the packet to process - * @return A enum of `TcpReassembly::ReassemblyStatus`, indicating status of TCP reassembly - */ - ReassemblyStatus reassemblePacket(Packet& tcpData); - - /** - * The most important method of this class which gets a raw packet from the user and processes it. If this packet opens a new connection, ends a connection or contains new data on an - * existing connection, the relevant callback will be invoked (TcpReassembly#OnTcpMessageReady, TcpReassembly#OnTcpConnectionStart, TcpReassembly#OnTcpConnectionEnd) - * @param[in] tcpRawData A reference to the raw packet to process - * @return A enum of `TcpReassembly::ReassemblyStatus`, indicating status of TCP reassembly - */ - ReassemblyStatus reassemblePacket(RawPacket* tcpRawData); - - /** - * Close a connection manually. If the connection doesn't exist or already closed an error log is printed. This method will cause the TcpReassembly#OnTcpConnectionEnd to be invoked with - * a reason of TcpReassembly#TcpReassemblyConnectionClosedManually - * @param[in] flowKey A 4-byte hash key representing the connection. Can be taken from a ConnectionData instance - */ - void closeConnection(uint32_t flowKey); - - /** - * Close all open connections manually. This method will cause the TcpReassembly#OnTcpConnectionEnd to be invoked for each connection with a reason of - * TcpReassembly#TcpReassemblyConnectionClosedManually - */ - void closeAllConnections(); - - /** - * Get a map of all connections managed by this TcpReassembly instance (both connections that are open and those that are already closed) - * @return A map of all connections managed. Notice this map is constant and cannot be changed by the user - */ - const ConnectionInfoList& getConnectionInformation() const { return m_ConnectionInfo; } - - /** - * Check if a certain connection managed by this TcpReassembly instance is currently opened or closed - * @param[in] connection The connection to check - * @return A positive number (> 0) if connection is opened, zero (0) if connection is closed, and a negative number (< 0) if this connection isn't managed by this TcpReassembly instance - */ - int isConnectionOpen(const ConnectionData& connection) const; - - /** - * Clean up the closed connections from the memory - * @param[in] maxNumToClean The maximum number of items to be cleaned up per one call. This parameter, when its value is not zero, overrides the value that was set by the constructor. - * @return The number of cleared items - */ - uint32_t purgeClosedConnections(uint32_t maxNumToClean = 0); + ReassemblyStatus reassemblePacket(RawPacket* tcpRawData); -private: - struct TcpFragment - { - uint32_t sequence; - size_t dataLength; - uint8_t* data; - timeval timestamp; - - TcpFragment() : sequence(0), dataLength(0), data(NULL) {} - ~TcpFragment() { delete [] data; } - }; + /** + * Close a connection manually. If the connection doesn't exist or already closed an error log is printed. This + * method will cause the TcpReassembly#OnTcpConnectionEnd to be invoked with a reason of + * TcpReassembly#TcpReassemblyConnectionClosedManually + * @param[in] flowKey A 4-byte hash key representing the connection. Can be taken from a ConnectionData instance + */ + void closeConnection(uint32_t flowKey); - struct TcpOneSideData - { - IPAddress srcIP; - uint16_t srcPort; - uint32_t sequence; - PointerVector tcpFragmentList; - bool gotFinOrRst; + /** + * Close all open connections manually. This method will cause the TcpReassembly#OnTcpConnectionEnd to be + * invoked for each connection with a reason of TcpReassembly#TcpReassemblyConnectionClosedManually + */ + void closeAllConnections(); - TcpOneSideData() : srcPort(0), sequence(0), gotFinOrRst(false) {} - }; + /** + * Get a map of all connections managed by this TcpReassembly instance (both connections that are open and those + * that are already closed) + * @return A map of all connections managed. Notice this map is constant and cannot be changed by the user + */ + const ConnectionInfoList& getConnectionInformation() const + { + return m_ConnectionInfo; + } - struct TcpReassemblyData - { - bool closed; - int8_t numOfSides; - int8_t prevSide; - TcpOneSideData twoSides[2]; - ConnectionData connData; + /** + * Check if a certain connection managed by this TcpReassembly instance is currently opened or closed + * @param[in] connection The connection to check + * @return A positive number (> 0) if connection is opened, zero (0) if connection is closed, and a negative + * number (< 0) if this connection isn't managed by this TcpReassembly instance + */ + int isConnectionOpen(const ConnectionData& connection) const; - TcpReassemblyData() : closed(false), numOfSides(0), prevSide(-1) {} - }; + /** + * Clean up the closed connections from the memory + * @param[in] maxNumToClean The maximum number of items to be cleaned up per one call. This parameter, when its + * value is not zero, overrides the value that was set by the constructor. + * @return The number of cleared items + */ + uint32_t purgeClosedConnections(uint32_t maxNumToClean = 0); - class OutOfOrderProcessingGuard - { private: - bool& m_Flag; - public: - explicit OutOfOrderProcessingGuard(bool& flag) : m_Flag(flag) + struct TcpFragment { - m_Flag = true; - } - - ~OutOfOrderProcessingGuard() + uint32_t sequence; + size_t dataLength; + uint8_t* data; + timeval timestamp; + + TcpFragment() : sequence(0), dataLength(0), data(NULL) + {} + ~TcpFragment() + { + delete[] data; + } + }; + + struct TcpOneSideData { - m_Flag = false; - } - - // Disable copy and move operations - OutOfOrderProcessingGuard(const OutOfOrderProcessingGuard&) = delete; - OutOfOrderProcessingGuard& operator=(const OutOfOrderProcessingGuard&) = delete; - }; + IPAddress srcIP; + uint16_t srcPort; + uint32_t sequence; + PointerVector tcpFragmentList; + bool gotFinOrRst; - typedef std::unordered_map ConnectionList; - typedef std::map > CleanupList; + TcpOneSideData() : srcPort(0), sequence(0), gotFinOrRst(false) + {} + }; - OnTcpMessageReady m_OnMessageReadyCallback; - OnTcpConnectionStart m_OnConnStart; - OnTcpConnectionEnd m_OnConnEnd; - void* m_UserCookie; - ConnectionList m_ConnectionList; - ConnectionInfoList m_ConnectionInfo; - CleanupList m_CleanupList; - bool m_RemoveConnInfo; - uint32_t m_ClosedConnectionDelay; - uint32_t m_MaxNumToClean; - size_t m_MaxOutOfOrderFragments; - time_t m_PurgeTimepoint; - bool m_EnableBaseBufferClearCondition; - bool m_ProcessingOutOfOrder = false; - - void checkOutOfOrderFragments(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, bool cleanWholeFragList); - - void handleFinOrRst(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, uint32_t flowKey, bool isRst); + struct TcpReassemblyData + { + bool closed; + int8_t numOfSides; + int8_t prevSide; + TcpOneSideData twoSides[2]; + ConnectionData connData; - void closeConnectionInternal(uint32_t flowKey, ConnectionEndReason reason); + TcpReassemblyData() : closed(false), numOfSides(0), prevSide(-1) + {} + }; - void insertIntoCleanupList(uint32_t flowKey); -}; + class OutOfOrderProcessingGuard + { + private: + bool& m_Flag; + + public: + explicit OutOfOrderProcessingGuard(bool& flag) : m_Flag(flag) + { + m_Flag = true; + } + + ~OutOfOrderProcessingGuard() + { + m_Flag = false; + } + + // Disable copy and move operations + OutOfOrderProcessingGuard(const OutOfOrderProcessingGuard&) = delete; + OutOfOrderProcessingGuard& operator=(const OutOfOrderProcessingGuard&) = delete; + }; + + typedef std::unordered_map ConnectionList; + typedef std::map> CleanupList; + + OnTcpMessageReady m_OnMessageReadyCallback; + OnTcpConnectionStart m_OnConnStart; + OnTcpConnectionEnd m_OnConnEnd; + void* m_UserCookie; + ConnectionList m_ConnectionList; + ConnectionInfoList m_ConnectionInfo; + CleanupList m_CleanupList; + bool m_RemoveConnInfo; + uint32_t m_ClosedConnectionDelay; + uint32_t m_MaxNumToClean; + size_t m_MaxOutOfOrderFragments; + time_t m_PurgeTimepoint; + bool m_EnableBaseBufferClearCondition; + bool m_ProcessingOutOfOrder = false; + + void checkOutOfOrderFragments(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, bool cleanWholeFragList); + + void handleFinOrRst(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, uint32_t flowKey, bool isRst); + + void closeConnectionInternal(uint32_t flowKey, ConnectionEndReason reason); + + void insertIntoCleanupList(uint32_t flowKey); + }; -} +} // namespace pcpp diff --git a/Packet++/header/TelnetLayer.h b/Packet++/header/TelnetLayer.h index 328a24ea29..0f6ca901dc 100644 --- a/Packet++/header/TelnetLayer.h +++ b/Packet++/header/TelnetLayer.h @@ -11,338 +11,354 @@ namespace pcpp { -/** - * Class for representing the Telnet Layer - */ -class TelnetLayer : public Layer -{ - private: - // Position iterator for next command - size_t lastPositionOffset; - - // Checks if position is a data field - bool isDataField(uint8_t *pos) const; - // Checks if position is a command field - bool isCommandField(uint8_t *pos) const; - // Returns distance to next IAC - size_t distanceToNextIAC(uint8_t *startPos, size_t maxLength); - // Returns length of provided field - size_t getFieldLen(uint8_t *startPos, size_t maxLength); - // Get position of next data field - uint8_t *getNextDataField(uint8_t *pos, size_t len); - // Get position of next command field - uint8_t *getNextCommandField(uint8_t *pos, size_t len); - // Get options of provided field - int16_t getSubCommand(uint8_t *pos, size_t len); - // Get data of provided field - uint8_t *getCommandData(uint8_t *pos, size_t &slen); - - public: - /** - * Telnet Command Indicator - */ - enum class TelnetCommand : int - { - /// Indicator to parser reached end of packet - TelnetCommandEndOfPacket = -1, - - /// End of file - EndOfFile = 236, - /// Suspend current process - Suspend, - /// Abort Process - Abort, - /// End of Record - EndOfRecordCommand, - /// Marks the end of a Telnet option subnegotiation, used with the SB code to specify more specific option - /// parameters. - SubnegotiationEnd, - /// Null command; does nothing. - NoOperation, - /// Used to mark the end of a sequence of data that the recipient should scan for urgent Telnet commands. - DataMark, - /// Represents the pressing of the “break” or “attention” key on the terminal. - Break, - /// Tells the recipient to interrupt, abort, suspend or terminate the process currently in use. - InterruptProcess, - /// Instructs the remote host to continue running the current process, but discard all remaining output from it. - /// This may be needed if a program starts to send unexpectedly large amounts of data to the user. - AbortOutput, - /// May be used to check that the remote host is still “alive”. When this character is sent the remote host - /// returns some type of output to indicate that it is still functioning. - AreYouThere, - /// Instructs the recipient to delete the last undeleted character from the data stream. Used to “undo” the - /// sending of a character. - EraseCharacter, - /// Tells the recipient to delete all characters from the data stream back to (but not including) the last end - /// of line (CR+LF) sequence. - EraseLine, - /// Used in Telnet half-duplex mode to signal the other device that it may transmit. - GoAhead, - /// Marks the beginning of a Telnet option subnegotiation, used when an option requires the client and server to - /// exchange parameters. - Subnegotiation, - /// Indicates that the device sending this code is willing to perform or continue performing a particular - /// option. - WillPerform, - /// Indicates that the device sending this code is either not willing to perform a particular option, or is now - /// refusing to continue to perform it. - WontPerform, - /// Requests that the other device perform a particular option or confirms the expectation that the other device - /// will perform that option. - DoPerform, - /// Specifies that the other party not perform an option, or confirms a device’s expectation that the other - /// party not perform an option. - DontPerform, - /// Precedes command values 240 through 254 as described above. A pair of IAC bytes in a row represents the data - /// value 255. - InterpretAsCommand - }; - /** - * Telnet Options + * Class for representing the Telnet Layer */ - enum class TelnetOption : int + class TelnetLayer : public Layer { - /// Internal return for no option detected - TelnetOptionNoOption = -1, - - /// Binary Transmission RFC856 https://www.iana.org/go/rfc856 - TransmitBinary = 0, - /// Echo RFC857 https://www.iana.org/go/rfc857 - Echo, - /// Reconnection - Reconnection, - /// Suppress Go Ahead RFC858 https://www.iana.org/go/rfc858 - SuppressGoAhead, - /// Negotiate approximate message size - ApproxMsgSizeNegotiation, - /// Status RFC859 https://www.iana.org/go/rfc859 - Status, - /// Timing Mark RFC860 https://www.iana.org/go/rfc860 - TimingMark, - /// RCTE, Remote Controlled Transmission and Echo RFC726 https://www.iana.org/go/rfc726 - RemoteControlledTransAndEcho, - /// Output Line Width - OutputLineWidth, - /// Output Page Size - OutputPageSize, - /// NAOCRD, Negotiate About Output Carriage-Return Disposition RFC652 https://www.iana.org/go/rfc652 - OutputCarriageReturnDisposition, - /// NAOHTS, Negotiate About Output Horizontal Tabstops RFC653 https://www.iana.org/go/rfc653 - OutputHorizontalTabStops, - /// NAOHTD, Negotiate About Output Horizontal Tab Disposition RFC654 https://www.iana.org/go/rfc654 - OutputHorizontalTabDisposition, - /// NAOFFD, Negotiate About Output Formfeed Disposition RFC655 https://www.iana.org/go/rfc655 - OutputFormfeedDisposition, - /// NAOVTS, Negotiate About Vertical Tabstops RFC656 https://www.iana.org/go/rfc656 - OutputVerticalTabStops, - /// NAOVTD, Negotiate About Output Vertcial Tab Disposition RFC657 https://www.iana.org/go/rfc657 - OutputVerticalTabDisposition, - /// NAOLFD, Negotiate About Output Linefeed Disposition RFC658 https://www.iana.org/go/rfc658 - OutputLinefeedDisposition, - /// Extended ASCII RFC698 https://www.iana.org/go/rfc698 - ExtendedASCII, - /// Logout RFC727 https://www.iana.org/go/rfc727 - Logout, - /// BM, Byte Macro RFC735 https://www.iana.org/go/rfc735 - ByteMacro, - /// Data Entry Terminal RFC1043 - RFC732 https://www.iana.org/go/rfc1043 https://www.iana.org/go/rfc732 - DataEntryTerminal, - /// SUPDUP RFC736 - RFC734 https://www.iana.org/go/rfc736 https://www.iana.org/go/rfc734 - SUPDUP, - /// SUPDUP Output RFC749 https://www.iana.org/go/rfc749 - SUPDUPOutput, - /// Send Location RFC779 https://www.iana.org/go/rfc779 - SendLocation, - /// Terminal Type RFC1091 https://www.iana.org/go/rfc1091 - TerminalType, - /// End of record RFC885 https://www.iana.org/go/rfc885 - EndOfRecordOption, - /// TUID, TACACS User Identification RFC927 https://www.iana.org/go/rfc927 - TACACSUserIdentification, - /// OUTMRK, Output Marking RFC933 https://www.iana.org/go/rfc933 - OutputMarking, - /// TTYLOC, Terminal Location Number RFC946 https://www.iana.org/go/rfc946 - TerminalLocationNumber, - /// Telnet 3270 Regime RFC1041 https://www.iana.org/go/rfc1041 - Telnet3270Regime, - /// X.3 PAD RFC1053 https://www.iana.org/go/rfc1053 - X3Pad, - /// NAWS, Negotiate About Window Size RFC1073 https://www.iana.org/go/rfc1073 - NegotiateAboutWindowSize, - /// Terminal Speed RFC1079 https://www.iana.org/go/rfc1079 - TerminalSpeed, - /// Remote Flow Control RFC1372 https://www.iana.org/go/rfc1372 - RemoteFlowControl, - /// Line Mode RFC1184 https://www.iana.org/go/rfc1184 - Linemode, - /// X Display Location RFC1096 https://www.iana.org/go/rfc1096 - XDisplayLocation, - /// Environment Option RFC1408 https://www.iana.org/go/rfc1408 - EnvironmentOption, - /// Authentication Option RFC2941 https://www.iana.org/go/rfc2941 - AuthenticationOption, - /// Encryption Option RFC2946 https://www.iana.org/go/rfc2946 - EncryptionOption, - /// New Environment Option RFC1572 https://www.iana.org/go/rfc1572 - NewEnvironmentOption, - /// TN3270E RFC2355 https://www.iana.org/go/rfc2355 - TN3270E, - /// X Server Authentication - XAuth, - /// Charset RFC2066 https://www.iana.org/go/rfc2066 - Charset, - /// RSP, Telnet Remote Serial Port - TelnetRemoteSerialPort, - /// Com Port Control Option RFC2217 https://www.iana.org/go/rfc2217 - ComPortControlOption, - /// Telnet Suppress Local Echo - TelnetSuppressLocalEcho, - /// Telnet Start TLS - TelnetStartTLS, - /// Kermit RFC2840 https://www.iana.org/go/rfc2840 - Kermit, - /// Send URL - SendURL, - /// Forward X Server - ForwardX, - - /// Telnet Option Pragma Logon - TelOptPragmaLogon = 138, - /// Telnet Option SSPI Logon - TelOptSSPILogon, - /// Telnet Option Pragma Heartbeat - TelOptPragmaHeartbeat, - - /// Extended option list - ExtendedOptions = 255 + private: + // Position iterator for next command + size_t lastPositionOffset; + + // Checks if position is a data field + bool isDataField(uint8_t* pos) const; + // Checks if position is a command field + bool isCommandField(uint8_t* pos) const; + // Returns distance to next IAC + size_t distanceToNextIAC(uint8_t* startPos, size_t maxLength); + // Returns length of provided field + size_t getFieldLen(uint8_t* startPos, size_t maxLength); + // Get position of next data field + uint8_t* getNextDataField(uint8_t* pos, size_t len); + // Get position of next command field + uint8_t* getNextCommandField(uint8_t* pos, size_t len); + // Get options of provided field + int16_t getSubCommand(uint8_t* pos, size_t len); + // Get data of provided field + uint8_t* getCommandData(uint8_t* pos, size_t& slen); + + public: + /** + * Telnet Command Indicator + */ + enum class TelnetCommand : int + { + /// Indicator to parser reached end of packet + TelnetCommandEndOfPacket = -1, + + /// End of file + EndOfFile = 236, + /// Suspend current process + Suspend, + /// Abort Process + Abort, + /// End of Record + EndOfRecordCommand, + /// Marks the end of a Telnet option subnegotiation, used with the SB code to specify more specific option + /// parameters. + SubnegotiationEnd, + /// Null command; does nothing. + NoOperation, + /// Used to mark the end of a sequence of data that the recipient should scan for urgent Telnet commands. + DataMark, + /// Represents the pressing of the “break” or “attention” key on the terminal. + Break, + /// Tells the recipient to interrupt, abort, suspend or terminate the process currently in use. + InterruptProcess, + /// Instructs the remote host to continue running the current process, but discard all remaining output from + /// it. This may be needed if a program starts to send unexpectedly large amounts of data to the user. + AbortOutput, + /// May be used to check that the remote host is still “alive”. When this character is sent the remote host + /// returns some type of output to indicate that it is still functioning. + AreYouThere, + /// Instructs the recipient to delete the last undeleted character from the data stream. Used to “undo” the + /// sending of a character. + EraseCharacter, + /// Tells the recipient to delete all characters from the data stream back to (but not including) the last + /// end of line (CR+LF) sequence. + EraseLine, + /// Used in Telnet half-duplex mode to signal the other device that it may transmit. + GoAhead, + /// Marks the beginning of a Telnet option subnegotiation, used when an option requires the client and + /// server to exchange parameters. + Subnegotiation, + /// Indicates that the device sending this code is willing to perform or continue performing a particular + /// option. + WillPerform, + /// Indicates that the device sending this code is either not willing to perform a particular option, or is + /// now refusing to continue to perform it. + WontPerform, + /// Requests that the other device perform a particular option or confirms the expectation that the other + /// device will perform that option. + DoPerform, + /// Specifies that the other party not perform an option, or confirms a device’s expectation that the other + /// party not perform an option. + DontPerform, + /// Precedes command values 240 through 254 as described above. A pair of IAC bytes in a row represents the + /// data value 255. + InterpretAsCommand + }; + + /** + * Telnet Options + */ + enum class TelnetOption : int + { + /// Internal return for no option detected + TelnetOptionNoOption = -1, + + /// Binary Transmission RFC856 https://www.iana.org/go/rfc856 + TransmitBinary = 0, + /// Echo RFC857 https://www.iana.org/go/rfc857 + Echo, + /// Reconnection + Reconnection, + /// Suppress Go Ahead RFC858 https://www.iana.org/go/rfc858 + SuppressGoAhead, + /// Negotiate approximate message size + ApproxMsgSizeNegotiation, + /// Status RFC859 https://www.iana.org/go/rfc859 + Status, + /// Timing Mark RFC860 https://www.iana.org/go/rfc860 + TimingMark, + /// RCTE, Remote Controlled Transmission and Echo RFC726 https://www.iana.org/go/rfc726 + RemoteControlledTransAndEcho, + /// Output Line Width + OutputLineWidth, + /// Output Page Size + OutputPageSize, + /// NAOCRD, Negotiate About Output Carriage-Return Disposition RFC652 https://www.iana.org/go/rfc652 + OutputCarriageReturnDisposition, + /// NAOHTS, Negotiate About Output Horizontal Tabstops RFC653 https://www.iana.org/go/rfc653 + OutputHorizontalTabStops, + /// NAOHTD, Negotiate About Output Horizontal Tab Disposition RFC654 https://www.iana.org/go/rfc654 + OutputHorizontalTabDisposition, + /// NAOFFD, Negotiate About Output Formfeed Disposition RFC655 https://www.iana.org/go/rfc655 + OutputFormfeedDisposition, + /// NAOVTS, Negotiate About Vertical Tabstops RFC656 https://www.iana.org/go/rfc656 + OutputVerticalTabStops, + /// NAOVTD, Negotiate About Output Vertcial Tab Disposition RFC657 https://www.iana.org/go/rfc657 + OutputVerticalTabDisposition, + /// NAOLFD, Negotiate About Output Linefeed Disposition RFC658 https://www.iana.org/go/rfc658 + OutputLinefeedDisposition, + /// Extended ASCII RFC698 https://www.iana.org/go/rfc698 + ExtendedASCII, + /// Logout RFC727 https://www.iana.org/go/rfc727 + Logout, + /// BM, Byte Macro RFC735 https://www.iana.org/go/rfc735 + ByteMacro, + /// Data Entry Terminal RFC1043 - RFC732 https://www.iana.org/go/rfc1043 https://www.iana.org/go/rfc732 + DataEntryTerminal, + /// SUPDUP RFC736 - RFC734 https://www.iana.org/go/rfc736 https://www.iana.org/go/rfc734 + SUPDUP, + /// SUPDUP Output RFC749 https://www.iana.org/go/rfc749 + SUPDUPOutput, + /// Send Location RFC779 https://www.iana.org/go/rfc779 + SendLocation, + /// Terminal Type RFC1091 https://www.iana.org/go/rfc1091 + TerminalType, + /// End of record RFC885 https://www.iana.org/go/rfc885 + EndOfRecordOption, + /// TUID, TACACS User Identification RFC927 https://www.iana.org/go/rfc927 + TACACSUserIdentification, + /// OUTMRK, Output Marking RFC933 https://www.iana.org/go/rfc933 + OutputMarking, + /// TTYLOC, Terminal Location Number RFC946 https://www.iana.org/go/rfc946 + TerminalLocationNumber, + /// Telnet 3270 Regime RFC1041 https://www.iana.org/go/rfc1041 + Telnet3270Regime, + /// X.3 PAD RFC1053 https://www.iana.org/go/rfc1053 + X3Pad, + /// NAWS, Negotiate About Window Size RFC1073 https://www.iana.org/go/rfc1073 + NegotiateAboutWindowSize, + /// Terminal Speed RFC1079 https://www.iana.org/go/rfc1079 + TerminalSpeed, + /// Remote Flow Control RFC1372 https://www.iana.org/go/rfc1372 + RemoteFlowControl, + /// Line Mode RFC1184 https://www.iana.org/go/rfc1184 + Linemode, + /// X Display Location RFC1096 https://www.iana.org/go/rfc1096 + XDisplayLocation, + /// Environment Option RFC1408 https://www.iana.org/go/rfc1408 + EnvironmentOption, + /// Authentication Option RFC2941 https://www.iana.org/go/rfc2941 + AuthenticationOption, + /// Encryption Option RFC2946 https://www.iana.org/go/rfc2946 + EncryptionOption, + /// New Environment Option RFC1572 https://www.iana.org/go/rfc1572 + NewEnvironmentOption, + /// TN3270E RFC2355 https://www.iana.org/go/rfc2355 + TN3270E, + /// X Server Authentication + XAuth, + /// Charset RFC2066 https://www.iana.org/go/rfc2066 + Charset, + /// RSP, Telnet Remote Serial Port + TelnetRemoteSerialPort, + /// Com Port Control Option RFC2217 https://www.iana.org/go/rfc2217 + ComPortControlOption, + /// Telnet Suppress Local Echo + TelnetSuppressLocalEcho, + /// Telnet Start TLS + TelnetStartTLS, + /// Kermit RFC2840 https://www.iana.org/go/rfc2840 + Kermit, + /// Send URL + SendURL, + /// Forward X Server + ForwardX, + + /// Telnet Option Pragma Logon + TelOptPragmaLogon = 138, + /// Telnet Option SSPI Logon + TelOptSSPILogon, + /// Telnet Option Pragma Heartbeat + TelOptPragmaHeartbeat, + + /// Extended option list + ExtendedOptions = 255 + }; + + /** + * A constructor that creates the layer from an existing packet raw data + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + TelnetLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = Telnet; + lastPositionOffset = SIZE_MAX; + }; + + /** + * Get the Telnet data as readable string + * @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not + * @return Full payload as readable string, empty if Telnet packet contains control commands/options. + */ + std::string getDataAsString(bool removeEscapeCharacters = true); + + /** + * Get the total number of detected Telnet commands + * @return size_t The number of Telnet commands + */ + size_t getTotalNumberOfCommands(); + + /** + * Returns the number of occurrences of provided command + * @param[in] command Telnet command to count + * @return size_t Number of occurrences of command + */ + size_t getNumberOfCommands(TelnetCommand command); + + /** + * Returns the first command of packet + * @return TelnetCommand First detected command value, TelnetCommandEndOfPacket if there is no command field + */ + TelnetCommand getFirstCommand(); + + /** + * Returns the next command of packet. Uses an internal iterator. The iterator resets when reached end of + * packet. + * @return TelnetCommand Detected command value, TelnetCommandEndOfPacket if reached the end of packet. + */ + TelnetCommand getNextCommand(); + + /** + * Returns the option of current command. Uses an internal iterator. Iterator can be moved with getNextCommand + * @return TelnetOption Option of current command + */ + TelnetOption getOption(); + + /** + * Returns the option of provided command. It will return option of first occurrence of the command + * @param[in] command Telnet command to search + * @return TelnetOption Option of the command. Returns TelnetOptionNoOption if the provided command not found. + */ + TelnetOption getOption(TelnetCommand command); + + /** + * Returns the data of current command. Uses an internal iterator. Iterator can be moved with getNextCommand + * @param[out] length Length of the data of current command + * @return uint8_t* Pointer to the data of current command. NULL if there is no data for this command. + */ + uint8_t* getOptionData(size_t& length); + + /** + * Returns the data of provided command. It will return data of first occurrence of the command + * @param[in] command Telnet command to search + * @param[out] length Length of the data of current command + * @return uint8_t* Pointer to the data of current command. NULL if there is no data for this command or if + * can't find the command. + */ + uint8_t* getOptionData(TelnetCommand command, size_t& length); + + /** + * Convert the Telnet Command to readable string + * @param[in] val Value of the command + * @return The Telnet Command as readable string + */ + static std::string getTelnetCommandAsString(TelnetCommand val); + + /** + * Convert the Telnet option to readable string + * @param[in] val Value of the option + * @return The Telnet Option as readable string + */ + static std::string getTelnetOptionAsString(TelnetOption val); + + /** + * A static method that checks whether the port is considered as Telnet + * @param[in] port The port number to be checked + */ + static bool isTelnetPort(uint16_t port) + { + return port == 23; + } + + /** + * A static method that takes a byte array and detects whether it is a Telnet message + * @param[in] data A byte array + * @param[in] dataSize The byte array size (in bytes) + * @return True if the data is identified as Telnet message + */ + static bool isDataValid(const uint8_t* data, size_t dataSize) + { + return data && dataSize; + } + + // overridden methods + + /// Parses the next layer. Telnet is the always last so does nothing for this layer + void parseNextLayer() + {} + + /** + * @return Get the size of the layer + */ + size_t getHeaderLen() const + { + return m_DataLen; + } + + /// Does nothing for this layer + void computeCalculateFields() + {} + + /** + * @return The OSI layer level of Telnet (Application Layer). + */ + OsiModelLayer getOsiModelLayer() const + { + return OsiModelApplicationLayer; + } + + /** + * @return Returns the protocol info as readable string + */ + std::string toString() const; }; - /** - * A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - TelnetLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) : Layer(data, dataLen, prevLayer, packet) - { - m_Protocol = Telnet; - lastPositionOffset = SIZE_MAX; - }; - - /** - * Get the Telnet data as readable string - * @param[in] removeEscapeCharacters Whether non-alphanumerical characters should be removed or not - * @return Full payload as readable string, empty if Telnet packet contains control commands/options. - */ - std::string getDataAsString(bool removeEscapeCharacters = true); - - /** - * Get the total number of detected Telnet commands - * @return size_t The number of Telnet commands - */ - size_t getTotalNumberOfCommands(); - - /** - * Returns the number of occurrences of provided command - * @param[in] command Telnet command to count - * @return size_t Number of occurrences of command - */ - size_t getNumberOfCommands(TelnetCommand command); - - /** - * Returns the first command of packet - * @return TelnetCommand First detected command value, TelnetCommandEndOfPacket if there is no command field - */ - TelnetCommand getFirstCommand(); - - /** - * Returns the next command of packet. Uses an internal iterator. The iterator resets when reached end of packet. - * @return TelnetCommand Detected command value, TelnetCommandEndOfPacket if reached the end of packet. - */ - TelnetCommand getNextCommand(); - - /** - * Returns the option of current command. Uses an internal iterator. Iterator can be moved with getNextCommand - * @return TelnetOption Option of current command - */ - TelnetOption getOption(); - - /** - * Returns the option of provided command. It will return option of first occurrence of the command - * @param[in] command Telnet command to search - * @return TelnetOption Option of the command. Returns TelnetOptionNoOption if the provided command not found. - */ - TelnetOption getOption(TelnetCommand command); - - /** - * Returns the data of current command. Uses an internal iterator. Iterator can be moved with getNextCommand - * @param[out] length Length of the data of current command - * @return uint8_t* Pointer to the data of current command. NULL if there is no data for this command. - */ - uint8_t *getOptionData(size_t &length); - - /** - * Returns the data of provided command. It will return data of first occurrence of the command - * @param[in] command Telnet command to search - * @param[out] length Length of the data of current command - * @return uint8_t* Pointer to the data of current command. NULL if there is no data for this command or if can't - * find the command. - */ - uint8_t *getOptionData(TelnetCommand command, size_t &length); - - /** - * Convert the Telnet Command to readable string - * @param[in] val Value of the command - * @return The Telnet Command as readable string - */ - static std::string getTelnetCommandAsString(TelnetCommand val); - - /** - * Convert the Telnet option to readable string - * @param[in] val Value of the option - * @return The Telnet Option as readable string - */ - static std::string getTelnetOptionAsString(TelnetOption val); - - /** - * A static method that checks whether the port is considered as Telnet - * @param[in] port The port number to be checked - */ - static bool isTelnetPort(uint16_t port) { return port == 23; } - - /** - * A static method that takes a byte array and detects whether it is a Telnet message - * @param[in] data A byte array - * @param[in] dataSize The byte array size (in bytes) - * @return True if the data is identified as Telnet message - */ - static bool isDataValid(const uint8_t *data, size_t dataSize) { return data && dataSize; } - - // overridden methods - - /// Parses the next layer. Telnet is the always last so does nothing for this layer - void parseNextLayer() {} - - /** - * @return Get the size of the layer - */ - size_t getHeaderLen() const { return m_DataLen; } - - /// Does nothing for this layer - void computeCalculateFields() {} - - /** - * @return The OSI layer level of Telnet (Application Layer). - */ - OsiModelLayer getOsiModelLayer() const { return OsiModelApplicationLayer; } - - /** - * @return Returns the protocol info as readable string - */ - std::string toString() const; -}; - -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/TextBasedProtocol.h b/Packet++/header/TextBasedProtocol.h index 276da0f348..fc727bceea 100644 --- a/Packet++/header/TextBasedProtocol.h +++ b/Packet++/header/TextBasedProtocol.h @@ -11,249 +11,275 @@ namespace pcpp /** End of header */ #define PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER "" -class TextBasedProtocolMessage; + class TextBasedProtocolMessage; - -// -------- Class HeaderField ----------------- - - -/** - * @class HeaderField - * A wrapper class for each text-based-protocol header field, e.g "Host", "Cookie", "Content-Length", "Via", "Call-ID", etc. - * Each field contains a name (e.g "Host") and a value (e.g "www.wikipedia.org"). The user can get and set both of them through dedicated methods. - * The separator between header fields is either CRLF ("\r\n\") or LF ("\n") in more rare cases, which means every HeaderField instance is - * responsible for wrapping and parsing a header field from the previous CRLF (not inclusive) until the next CRLF/LF (inclusive) - * A special case is with the end of a header, meaning 2 consecutive CRLFs ("\r\n\r\n") or consecutive LFs ("\n\n"). PcapPlusPlus treats the first - * CRLF/LF as part of the last field in the header, and the second CRLF is an HeaderField instance of its own which name and values are an empty string ("") - * or pcpp::PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER - */ -class HeaderField -{ - friend class TextBasedProtocolMessage; -public: - - ~HeaderField(); - - /** - * A copy constructor that creates a new instance out of an existing HeaderField instance. The copied instance will not have shared - * resources with the original instance, meaning all members and properties are copied - * @param[in] other The original instance to copy from - */ - HeaderField(const HeaderField& other); - - /** - * Assignment operator for this class. This method copies the data from the other instance and will not share any resources with it. - * Also, if the instance already contains data it will be deleted or zeroed - * @param[in] other The instance to assign from - * @return A reference to the assignee - */ - HeaderField& operator=(const HeaderField& other); - - /** - * @return The field length in bytes, meaning count of all characters from the previous CRLF (not inclusive) until the next CRLF (inclusive) - * For example: the field "Host: www.wikipedia.org\r\n" will have the length of 25 - */ - size_t getFieldSize() const { return m_FieldSize; } - - /** - * @return The field name as string. Notice the return data is copied data, so changing it won't change the packet data - */ - std::string getFieldName() const; - - /** - * @return The field value as string. Notice the return data is copied data, so changing it won't change the packet data - */ - std::string getFieldValue() const; - - /** - * A setter for field value - * @param[in] newValue The new value to set to the field. Old value will be deleted - * @return True if setting the value was completed successfully, false otherwise - */ - bool setFieldValue(const std::string& newValue); - - /** - * Get an indication whether the field is a field that ends the header (meaning contain only CRLF - see class explanation) - * @return True if this is a end-of-header field, false otherwise - */ - bool isEndOfHeader() const { return m_IsEndOfHeaderField; } - -private: - HeaderField(const std::string& name, const std::string& value, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue); - HeaderField(TextBasedProtocolMessage* TextBasedProtocolMessage, int offsetInMessage, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue); - - char* getData() const; - void setNextField(HeaderField* nextField); - HeaderField *getNextField() const; - void initNewField(const std::string& name, const std::string& value); - void attachToTextBasedProtocolMessage(TextBasedProtocolMessage* message, int fieldOffsetInMessage); - - uint8_t* m_NewFieldData; - TextBasedProtocolMessage* m_TextBasedProtocolMessage; - int m_NameOffsetInMessage; - size_t m_FieldNameSize; - int m_ValueOffsetInMessage; - size_t m_FieldValueSize; - size_t m_FieldSize; - HeaderField* m_NextField; - bool m_IsEndOfHeaderField; - char m_NameValueSeparator; - bool m_SpacesAllowedBetweenNameAndValue; -}; - - - - -// -------- Class TextBasedProtocolMessage ----------------- - -/** - * @class TextBasedProtocolMessage - * An abstract base class that wraps text-based-protocol header layers (both requests and responses). It is the base class for all those layers. - * This class is not meant to be instantiated, hence the protected c'tor - */ -class TextBasedProtocolMessage : public Layer -{ - friend class HeaderField; -public: - ~TextBasedProtocolMessage(); - - /** - * Get a pointer to a header field by name. The search is case insensitive, meaning if a field with name "Host" exists and the - * fieldName parameter is "host" (all letter are lower case), this method will return a pointer to "Host" field - * @param[in] fieldName The field name - * @param[in] index Optional parameter. If the field name appears more than once, this parameter will indicate which field to get. - * The default value is 0 (get the first appearance of the field name as appears on the packet) - * @return A pointer to an HeaderField instance, or NULL if field doesn't exist - */ - HeaderField* getFieldByName(std::string fieldName, int index = 0) const; - - /** - * @return A pointer to the first header field exists in this message, or NULL if no such field exists - */ - HeaderField* getFirstField() const { return m_FieldList; } - - /** - * Get the field which appears after a certain field - * @param[in] prevField A pointer to the field - * @return The field after prevField or NULL if prevField is the last field. If prevField is NULL, this method will return NULL - */ - HeaderField* getNextField(HeaderField* prevField) const { if (prevField != NULL) return prevField->getNextField(); else return NULL; } - - /** - * @return The number of header fields currently in the layer (not including CRLF at the end of the header) - */ - int getFieldCount() const; + // -------- Class HeaderField ----------------- /** - * Add a new header field to this message. This field will be added last (before the end-of-header field) - * @param[in] fieldName The field name - * @param[in] fieldValue The field value - * @return A pointer to the newly created header field, or NULL if the field could not be created + * @class HeaderField + * A wrapper class for each text-based-protocol header field, e.g "Host", "Cookie", "Content-Length", "Via", + * "Call-ID", etc. Each field contains a name (e.g "Host") and a value (e.g "www.wikipedia.org"). The user can get + * and set both of them through dedicated methods. The separator between header fields is either CRLF ("\r\n\") or + * LF ("\n") in more rare cases, which means every HeaderField instance is responsible for wrapping and parsing a + * header field from the previous CRLF (not inclusive) until the next CRLF/LF (inclusive) A special case is with the + * end of a header, meaning 2 consecutive CRLFs ("\r\n\r\n") or consecutive LFs ("\n\n"). PcapPlusPlus treats the + * first CRLF/LF as part of the last field in the header, and the second CRLF is an HeaderField instance of its own + * which name and values are an empty string ("") or pcpp::PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER */ - virtual HeaderField* addField(const std::string& fieldName, const std::string& fieldValue); + class HeaderField + { + friend class TextBasedProtocolMessage; + + public: + ~HeaderField(); + + /** + * A copy constructor that creates a new instance out of an existing HeaderField instance. The copied instance + * will not have shared resources with the original instance, meaning all members and properties are copied + * @param[in] other The original instance to copy from + */ + HeaderField(const HeaderField& other); + + /** + * Assignment operator for this class. This method copies the data from the other instance and will not share + * any resources with it. Also, if the instance already contains data it will be deleted or zeroed + * @param[in] other The instance to assign from + * @return A reference to the assignee + */ + HeaderField& operator=(const HeaderField& other); + + /** + * @return The field length in bytes, meaning count of all characters from the previous CRLF (not inclusive) + * until the next CRLF (inclusive) For example: the field "Host: www.wikipedia.org\r\n" will have the length of + * 25 + */ + size_t getFieldSize() const + { + return m_FieldSize; + } + + /** + * @return The field name as string. Notice the return data is copied data, so changing it won't change the + * packet data + */ + std::string getFieldName() const; + + /** + * @return The field value as string. Notice the return data is copied data, so changing it won't change the + * packet data + */ + std::string getFieldValue() const; + + /** + * A setter for field value + * @param[in] newValue The new value to set to the field. Old value will be deleted + * @return True if setting the value was completed successfully, false otherwise + */ + bool setFieldValue(const std::string& newValue); + + /** + * Get an indication whether the field is a field that ends the header (meaning contain only CRLF - see class + * explanation) + * @return True if this is a end-of-header field, false otherwise + */ + bool isEndOfHeader() const + { + return m_IsEndOfHeaderField; + } + + private: + HeaderField(const std::string& name, const std::string& value, char nameValueSeparator, + bool spacesAllowedBetweenNameAndValue); + HeaderField(TextBasedProtocolMessage* TextBasedProtocolMessage, int offsetInMessage, char nameValueSeparator, + bool spacesAllowedBetweenNameAndValue); + + char* getData() const; + void setNextField(HeaderField* nextField); + HeaderField* getNextField() const; + void initNewField(const std::string& name, const std::string& value); + void attachToTextBasedProtocolMessage(TextBasedProtocolMessage* message, int fieldOffsetInMessage); + + uint8_t* m_NewFieldData; + TextBasedProtocolMessage* m_TextBasedProtocolMessage; + int m_NameOffsetInMessage; + size_t m_FieldNameSize; + int m_ValueOffsetInMessage; + size_t m_FieldValueSize; + size_t m_FieldSize; + HeaderField* m_NextField; + bool m_IsEndOfHeaderField; + char m_NameValueSeparator; + bool m_SpacesAllowedBetweenNameAndValue; + }; + + // -------- Class TextBasedProtocolMessage ----------------- /** - * Add a new header field to this message. This field will be added last (before the end-of-header field) - * @param[in] newField The header field to add - * @return A pointer to the newly created header field, or NULL if the field could not be created + * @class TextBasedProtocolMessage + * An abstract base class that wraps text-based-protocol header layers (both requests and responses). It is the base + * class for all those layers. This class is not meant to be instantiated, hence the protected c'tor */ - virtual HeaderField* addField(const HeaderField& newField); - - /** - * Add the special end-of-header field (see the explanation in HeaderField) - * @return A pointer to the newly created header field, or NULL if the field could not be created - */ - HeaderField* addEndOfHeader(); - - /** - * Insert a new field after an existing field - * @param[in] prevField A pointer to the existing field. If it's NULL the new field will be added as first field - * @param[in] fieldName The field name - * @param[in] fieldValue The field value - * @return A pointer to the newly created header field, or NULL if the field could not be created - */ - virtual HeaderField* insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue); - - /** - * Insert a new field after an existing field - * @param[in] prevFieldName A name of an existing field. If the field doesn't exist NULL will be returned. - * If field name is empty ('') the new field will be added as first field - * @param[in] fieldName The field name - * @param[in] fieldValue The field value - * @return A pointer to the newly created header field, or NULL if the field could not be created - */ - virtual HeaderField* insertField(std::string prevFieldName, const std::string& fieldName, const std::string& fieldValue); - - /** - * Insert a new field after an existing field - * @param[in] prevField A pointer to the existing field - * @param[in] newField The header field to add - * @return A pointer to the newly created header field, or NULL if the field could not be created - */ - virtual HeaderField* insertField(HeaderField* prevField, const HeaderField& newField); - - /** - * Remove a field from the message - * @param[in] fieldToRemove A pointer to the field that should be removed - * @return True if the field was removed successfully, or false otherwise (for example: if fieldToRemove is NULL, if it doesn't exist - * in the message, or if the removal failed) - */ - bool removeField(HeaderField* fieldToRemove); - - /** - * Remove a field from the message - * @param[in] fieldName The name of the field that should be removed - * @param[in] index Optional parameter. If the field name appears more than once, this parameter will indicate which field to remove. - * The default value is 0 (remove the first appearance of the field name as appears on the packet) - * @return True if the field was removed successfully, or false otherwise (for example: if fieldName doesn't exist in the message, or if the removal failed) - */ - bool removeField(std::string fieldName, int index = 0); - - /** - * Indicate whether the header is complete (ending with end-of-header "\r\n\r\n" or "\n\n") or spread over more packets - * @return True if the header is complete or false if not - */ - bool isHeaderComplete() const; - - // implement Layer's abstract methods - - /** - * Currently set only PayloadLayer for the rest of the data - */ - virtual void parseNextLayer(); - - /** - * @return The message length - */ - size_t getHeaderLen() const; - - /** - * Does nothing for this class - */ - virtual void computeCalculateFields(); - -protected: - TextBasedProtocolMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); - TextBasedProtocolMessage() : m_FieldList(NULL), m_LastField(NULL), m_FieldsOffset(0) {} - - // copy c'tor - TextBasedProtocolMessage(const TextBasedProtocolMessage& other); - TextBasedProtocolMessage& operator=(const TextBasedProtocolMessage& other); - - void copyDataFrom(const TextBasedProtocolMessage& other); - - void parseFields(); - void shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift); - - // abstract methods - virtual char getHeaderFieldNameValueSeparator() const = 0; - virtual bool spacesAllowedBetweenHeaderFieldNameAndValue() const = 0; - - HeaderField* m_FieldList; - HeaderField* m_LastField; - int m_FieldsOffset; - std::multimap m_FieldNameToFieldMap; -}; - - -} + class TextBasedProtocolMessage : public Layer + { + friend class HeaderField; + + public: + ~TextBasedProtocolMessage(); + + /** + * Get a pointer to a header field by name. The search is case insensitive, meaning if a field with name "Host" + * exists and the fieldName parameter is "host" (all letter are lower case), this method will return a pointer + * to "Host" field + * @param[in] fieldName The field name + * @param[in] index Optional parameter. If the field name appears more than once, this parameter will indicate + * which field to get. The default value is 0 (get the first appearance of the field name as appears on the + * packet) + * @return A pointer to an HeaderField instance, or NULL if field doesn't exist + */ + HeaderField* getFieldByName(std::string fieldName, int index = 0) const; + + /** + * @return A pointer to the first header field exists in this message, or NULL if no such field exists + */ + HeaderField* getFirstField() const + { + return m_FieldList; + } + + /** + * Get the field which appears after a certain field + * @param[in] prevField A pointer to the field + * @return The field after prevField or NULL if prevField is the last field. If prevField is NULL, this method + * will return NULL + */ + HeaderField* getNextField(HeaderField* prevField) const + { + if (prevField != NULL) + return prevField->getNextField(); + else + return NULL; + } + + /** + * @return The number of header fields currently in the layer (not including CRLF at the end of the header) + */ + int getFieldCount() const; + + /** + * Add a new header field to this message. This field will be added last (before the end-of-header field) + * @param[in] fieldName The field name + * @param[in] fieldValue The field value + * @return A pointer to the newly created header field, or NULL if the field could not be created + */ + virtual HeaderField* addField(const std::string& fieldName, const std::string& fieldValue); + + /** + * Add a new header field to this message. This field will be added last (before the end-of-header field) + * @param[in] newField The header field to add + * @return A pointer to the newly created header field, or NULL if the field could not be created + */ + virtual HeaderField* addField(const HeaderField& newField); + + /** + * Add the special end-of-header field (see the explanation in HeaderField) + * @return A pointer to the newly created header field, or NULL if the field could not be created + */ + HeaderField* addEndOfHeader(); + + /** + * Insert a new field after an existing field + * @param[in] prevField A pointer to the existing field. If it's NULL the new field will be added as first field + * @param[in] fieldName The field name + * @param[in] fieldValue The field value + * @return A pointer to the newly created header field, or NULL if the field could not be created + */ + virtual HeaderField* insertField(HeaderField* prevField, const std::string& fieldName, + const std::string& fieldValue); + + /** + * Insert a new field after an existing field + * @param[in] prevFieldName A name of an existing field. If the field doesn't exist NULL will be returned. + * If field name is empty ('') the new field will be added as first field + * @param[in] fieldName The field name + * @param[in] fieldValue The field value + * @return A pointer to the newly created header field, or NULL if the field could not be created + */ + virtual HeaderField* insertField(std::string prevFieldName, const std::string& fieldName, + const std::string& fieldValue); + + /** + * Insert a new field after an existing field + * @param[in] prevField A pointer to the existing field + * @param[in] newField The header field to add + * @return A pointer to the newly created header field, or NULL if the field could not be created + */ + virtual HeaderField* insertField(HeaderField* prevField, const HeaderField& newField); + + /** + * Remove a field from the message + * @param[in] fieldToRemove A pointer to the field that should be removed + * @return True if the field was removed successfully, or false otherwise (for example: if fieldToRemove is + * NULL, if it doesn't exist in the message, or if the removal failed) + */ + bool removeField(HeaderField* fieldToRemove); + + /** + * Remove a field from the message + * @param[in] fieldName The name of the field that should be removed + * @param[in] index Optional parameter. If the field name appears more than once, this parameter will indicate + * which field to remove. The default value is 0 (remove the first appearance of the field name as appears on + * the packet) + * @return True if the field was removed successfully, or false otherwise (for example: if fieldName doesn't + * exist in the message, or if the removal failed) + */ + bool removeField(std::string fieldName, int index = 0); + + /** + * Indicate whether the header is complete (ending with end-of-header "\r\n\r\n" or "\n\n") or spread over more + * packets + * @return True if the header is complete or false if not + */ + bool isHeaderComplete() const; + + // implement Layer's abstract methods + + /** + * Currently set only PayloadLayer for the rest of the data + */ + virtual void parseNextLayer(); + + /** + * @return The message length + */ + size_t getHeaderLen() const; + + /** + * Does nothing for this class + */ + virtual void computeCalculateFields(); + + protected: + TextBasedProtocolMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet); + TextBasedProtocolMessage() : m_FieldList(NULL), m_LastField(NULL), m_FieldsOffset(0) + {} + + // copy c'tor + TextBasedProtocolMessage(const TextBasedProtocolMessage& other); + TextBasedProtocolMessage& operator=(const TextBasedProtocolMessage& other); + + void copyDataFrom(const TextBasedProtocolMessage& other); + + void parseFields(); + void shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift); + + // abstract methods + virtual char getHeaderFieldNameValueSeparator() const = 0; + virtual bool spacesAllowedBetweenHeaderFieldNameAndValue() const = 0; + + HeaderField* m_FieldList; + HeaderField* m_LastField; + int m_FieldsOffset; + std::multimap m_FieldNameToFieldMap; + }; + +} // namespace pcpp diff --git a/Packet++/header/TpktLayer.h b/Packet++/header/TpktLayer.h index 3cd8f9992d..e7ab49e45b 100644 --- a/Packet++/header/TpktLayer.h +++ b/Packet++/header/TpktLayer.h @@ -34,7 +34,7 @@ namespace pcpp */ class TpktLayer : public Layer { - public: + public: /** * A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data (will be casted to @ref tpkthdr) @@ -42,8 +42,8 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - TpktLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) + TpktLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { m_Protocol = TPKT; } @@ -55,7 +55,8 @@ namespace pcpp */ TpktLayer(uint8_t version, uint16_t length); - virtual ~TpktLayer() {} + virtual ~TpktLayer() + {} /** * @return TPKT reserved @@ -87,12 +88,16 @@ namespace pcpp /** * @return Size of @ref tpkthdr */ - size_t getHeaderLen() const override { return sizeof(tpkthdr); } + size_t getHeaderLen() const override + { + return sizeof(tpkthdr); + } /** * Does nothing for this layer */ - void computeCalculateFields() override {} + void computeCalculateFields() override + {} /** * Currently parses the rest of the packet as a COTP protocol or generic payload (PayloadLayer) @@ -105,7 +110,10 @@ namespace pcpp * @param[in] portDst Dest port number to check * @return True if the source or dest port match those associated with the TPKT protocol */ - static bool isTpktPort(uint16_t portSrc, uint16_t portDst) { return portSrc == 102 || portDst == 102; } + static bool isTpktPort(uint16_t portSrc, uint16_t portDst) + { + return portSrc == 102 || portDst == 102; + } /** * A static method that takes a byte array and detects whether it is a TPKT message @@ -113,20 +121,29 @@ namespace pcpp * @param[in] dataSize The byte array size (in bytes) * @return True if the data size is greater or equal than the size of tpkthdr */ - static bool isDataValid(const uint8_t *data, size_t dataSize) { return data && dataSize >= sizeof(tpkthdr); } + static bool isDataValid(const uint8_t* data, size_t dataSize) + { + return data && dataSize >= sizeof(tpkthdr); + } std::string toString() const override; - OsiModelLayer getOsiModelLayer() const override { return OsiModelTransportLayer; } + OsiModelLayer getOsiModelLayer() const override + { + return OsiModelTransportLayer; + } - private: + private: /** * Get a pointer to the TPKT header. Data can be retrieved through the * other methods of this layer. Notice the return value points directly to the data, so every change will change * the actual packet data * @return A pointer to the @ref tpkthdr */ - tpkthdr *getTpktHeader() const { return (tpkthdr *)m_Data; } + tpkthdr* getTpktHeader() const + { + return (tpkthdr*)m_Data; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/UdpLayer.h b/Packet++/header/UdpLayer.h index 9a2ab0f1bd..a325698b2c 100644 --- a/Packet++/header/UdpLayer.h +++ b/Packet++/header/UdpLayer.h @@ -15,7 +15,7 @@ namespace pcpp * @struct udphdr * Represents an UDP protocol header */ -#pragma pack(push,1) +#pragma pack(push, 1) struct udphdr { /** Source port */ @@ -29,7 +29,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @class UdpLayer * Represents an UDP (User Datagram Protocol) protocol layer @@ -44,7 +43,11 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - UdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = UDP; } + UdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = UDP; + } /** * A constructor that allocates a new UDP header with source and destination ports @@ -54,10 +57,14 @@ namespace pcpp UdpLayer(uint16_t portSrc, uint16_t portDst); /** - * Get a pointer to the UDP header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the UDP header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the @ref udphdr */ - udphdr* getUdpHeader() const { return (udphdr*)m_Data; } + udphdr* getUdpHeader() const + { + return (udphdr*)m_Data; + } /** * @return UDP source port @@ -71,7 +78,8 @@ namespace pcpp /** * Calculate the checksum from header and data and possibly write the result to @ref udphdr#headerChecksum - * @param[in] writeResultToPacket If set to true then checksum result will be written to @ref udphdr#headerChecksum + * @param[in] writeResultToPacket If set to true then checksum result will be written to @ref + * udphdr#headerChecksum * @return The checksum result */ uint16_t calculateChecksum(bool writeResultToPacket); @@ -79,15 +87,18 @@ namespace pcpp // implement abstract methods /** - * Currently identifies the following next layers: DnsLayer, DhcpLayer, VxlanLayer, SipRequestLayer, SipResponseLayer, - * RadiusLayer. Otherwise sets PayloadLayer + * Currently identifies the following next layers: DnsLayer, DhcpLayer, VxlanLayer, SipRequestLayer, + * SipResponseLayer, RadiusLayer. Otherwise sets PayloadLayer */ void parseNextLayer(); /** * @return Size of @ref udphdr */ - size_t getHeaderLen() const { return sizeof(udphdr); } + size_t getHeaderLen() const + { + return sizeof(udphdr); + } /** * Calculate @ref udphdr#headerChecksum field @@ -96,7 +107,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelTransportLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelTransportLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/VlanLayer.h b/Packet++/header/VlanLayer.h index 769c6945a2..cb46753dd8 100644 --- a/Packet++/header/VlanLayer.h +++ b/Packet++/header/VlanLayer.h @@ -34,7 +34,6 @@ namespace pcpp }; #pragma pack(pop) - /** * @class VlanLayer * Represents a VLAN tunnel layer @@ -42,34 +41,44 @@ namespace pcpp class VlanLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - VlanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = VLAN; } + VlanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = VLAN; + } /** * A constructor that allocates a new VLAN header * @param[in] vlanID VLAN ID * @param[in] cfi CFI value * @param[in] priority Priority value - * @param[in] etherType Protocol EtherType of the next layer. It's an optional parameter, a value of 0 will be set if not provided + * @param[in] etherType Protocol EtherType of the next layer. It's an optional parameter, a value of 0 will be + * set if not provided */ VlanLayer(const uint16_t vlanID, bool cfi, uint8_t priority, uint16_t etherType = 0); - ~VlanLayer() {} + ~VlanLayer() + {} /** - * Get a pointer to the VLAN header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the VLAN header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the vlan_header */ - vlan_header* getVlanHeader() const { return (vlan_header*)m_Data; } + vlan_header* getVlanHeader() const + { + return (vlan_header*)m_Data; + } /** - * Get the VLAN ID value. This method differs from vlan_header#vlanID because vlan_header#vlanID is 12 bits long in a 16 bit field. - * This methods extracts only the 12 bit relevant for the VLAN ID + * Get the VLAN ID value. This method differs from vlan_header#vlanID because vlan_header#vlanID is 12 bits long + * in a 16 bit field. This methods extracts only the 12 bit relevant for the VLAN ID * @return VLAN ID value * @todo Verify it works in big endian machines as well */ @@ -88,8 +97,8 @@ namespace pcpp uint8_t getPriority() const; /** - * Set VLAN ID. This method differs from setting vlan_header#vlanID because vlan_header#vlanID is 12 bits long in a 16 bit field. - * This methods sets only the 12 bit relevant for the VLAN ID + * Set VLAN ID. This method differs from setting vlan_header#vlanID because vlan_header#vlanID is 12 bits long + * in a 16 bit field. This methods sets only the 12 bit relevant for the VLAN ID * @param[in] id The VLAN ID to set * @todo Verify it works in big endian machines as well */ @@ -112,14 +121,18 @@ namespace pcpp // implement abstract methods /** - * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, MplsLayer. Otherwise sets PayloadLayer + * Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, MplsLayer. + * Otherwise sets PayloadLayer */ void parseNextLayer(); /** * @return Size of vlan_header */ - size_t getHeaderLen() const { return sizeof(vlan_header); } + size_t getHeaderLen() const + { + return sizeof(vlan_header); + } /** * Calculate the EtherType for known protocols: IPv4, IPv6, ARP, VLAN @@ -128,7 +141,10 @@ namespace pcpp std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/header/VrrpLayer.h b/Packet++/header/VrrpLayer.h old mode 100755 new mode 100644 index 86629e9314..39549b34e7 --- a/Packet++/header/VrrpLayer.h +++ b/Packet++/header/VrrpLayer.h @@ -14,14 +14,14 @@ namespace pcpp { /** For more info see: - https://datatracker.ietf.org/doc/html/rfc2338 - https://datatracker.ietf.org/doc/html/rfc3768 - https://datatracker.ietf.org/doc/html/rfc5798 + https://datatracker.ietf.org/doc/html/rfc2338 + https://datatracker.ietf.org/doc/html/rfc3768 + https://datatracker.ietf.org/doc/html/rfc5798 */ /* VRRPv2 Packet Format - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| Type | Virtual Rtr ID| Priority | Count IP Addrs| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -42,28 +42,28 @@ namespace pcpp */ /* VRRPv3 Packet Format - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | IPv4 Fields or IPv6 Fields | + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | IPv4 Fields or IPv6 Fields | ... ... - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr| - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |(rsvd) | Max Adver Int | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - + + - | IPvX Address(es) | - + + - + + - + + - + + - | | - + + - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr| + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |(rsvd) | Max Adver Int | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | IPvX Address(es) | + + + + + + + + + + + + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /** @@ -74,18 +74,19 @@ namespace pcpp { #if (BYTE_ORDER == LITTLE_ENDIAN) /** Type */ - uint8_t type: 4, + uint8_t type : 4; /** Version bits */ - version: 4; + uint8_t version : 4; #else /** Version bits */ - uint8_t version:4, + uint8_t version : 4; /** Type */ - type: 4; + uint8_t type : 4; #endif - /** The Virtual Router Identifier (VRID) field identifies the virtual router this packet is reporting status for*/ + /** The Virtual Router Identifier (VRID) field identifies the virtual router this packet is reporting status + * for*/ uint8_t vrId; /** This specifies the sending VRRP router's priority for the virtual router */ @@ -94,7 +95,8 @@ namespace pcpp /** Specifies how many IPvX addresses are present in this Packet */ uint8_t ipAddrCount; - /** This specifies authentication type(v2) or (Max) Advertisement interval (in seconds(v2) or centi-seconds(v3)). */ + /** This specifies authentication type(v2) or (Max) Advertisement interval (in seconds(v2) or + * centi-seconds(v3)). */ uint16_t authTypeAdvInt; /** This specifies checksum field that is used to detect data corruption in the VRRP message. @@ -102,45 +104,48 @@ namespace pcpp uint16_t checksum; /** This specifies one or more IPvX addresses that are associated with the virtual router. */ - uint8_t *ipAddresses[]; + uint8_t* ipAddresses[]; }; /** * @class VrrpLayer - * A base class for all VRRP (Virtual Router Redundancy Protocol) protocol classes. This is an abstract class and cannot be instantiated, - * only its child classes can be instantiated. The inherited classes represent the different versions of the protocol: - * VRRPv2 and VRRPv3 + * A base class for all VRRP (Virtual Router Redundancy Protocol) protocol classes. This is an abstract class and + * cannot be instantiated, only its child classes can be instantiated. The inherited classes represent the different + * versions of the protocol: VRRPv2 and VRRPv3 */ class VrrpLayer : public Layer { private: - bool addIPAddressesAt(const std::vector &ipAddresses, int offset); + bool addIPAddressesAt(const std::vector& ipAddresses, int offset); uint8_t getIPAddressLen() const; - bool isIPAddressValid(IPAddress &ipAddress) const; + bool isIPAddressValid(IPAddress& ipAddress) const; uint8_t* getFirstIPAddressPtr() const; uint8_t* getNextIPAddressPtr(uint8_t* ipAddressPtr) const; - IPAddress getIPAddressFromData(uint8_t *data) const; + IPAddress getIPAddressFromData(uint8_t* data) const; - void copyIPAddressToData(uint8_t *data, const IPAddress &ipAddress) const; + void copyIPAddressToData(uint8_t* data, const IPAddress& ipAddress) const; IPAddress::AddressType m_AddressType; protected: - VrrpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet, ProtocolType vrrpVer, - IPAddress::AddressType addressType) - : Layer(data, dataLen, prevLayer, packet), m_AddressType(addressType) + VrrpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, ProtocolType vrrpVer, + IPAddress::AddressType addressType) + : Layer(data, dataLen, prevLayer, packet), m_AddressType(addressType) { m_Protocol = vrrpVer; } explicit VrrpLayer(ProtocolType subProtocol, uint8_t virtualRouterId, uint8_t priority); - vrrp_header *getVrrpHeader() const { return (vrrp_header *) m_Data; } + vrrp_header* getVrrpHeader() const + { + return (vrrp_header*)m_Data; + } void setAddressType(IPAddress::AddressType addressType); @@ -172,25 +177,26 @@ namespace pcpp Other }; - virtual ~VrrpLayer() {} + virtual ~VrrpLayer() + {} /** - * @return The VRRP IP Address type - */ + * @return The VRRP IP Address type + */ IPAddress::AddressType getAddressType() const; /** * A static method that validates the input data * @param[in] data VRRP raw data (byte stream) * @param[in] dataLen The length of the byte stream - * @return One of the values ::VRRPv2, ::VRRPv3 according to detected VRRP version or ::UnknownProtocol if couldn't detect - * VRRP version + * @return One of the values ::VRRPv2, ::VRRPv3 according to detected VRRP version or ::UnknownProtocol if + * couldn't detect VRRP version */ - static ProtocolType getVersionFromData(uint8_t *data, size_t dataLen); + static ProtocolType getVersionFromData(uint8_t* data, size_t dataLen); /** - * @return VRRP version of this message - */ + * @return VRRP version of this message + */ uint8_t getVersion() const; /** @@ -199,8 +205,8 @@ namespace pcpp VrrpType getType() const; /** - * @return The virtual router id (vrId) in this message - */ + * @return The virtual router id (vrId) in this message + */ uint8_t getVirtualRouterID() const; /** @@ -210,13 +216,13 @@ namespace pcpp void setVirtualRouterID(uint8_t virtualRouterID); /** - * @return The priority in this message - */ + * @return The priority in this message + */ uint8_t getPriority() const; /** - * @return An enum describing VRRP priority - */ + * @return An enum describing VRRP priority + */ VrrpPriority getPriorityAsEnum() const; /** @@ -226,8 +232,8 @@ namespace pcpp void setPriority(uint8_t priority); /** - * @return VRRP checksum of this message - */ + * @return VRRP checksum of this message + */ uint16_t getChecksum() const; /** @@ -257,33 +263,34 @@ namespace pcpp std::vector getIPAddresses() const; /** - * Add a list of virtual IP addresses at a the end of the virtual IP address list. The vrrp_header#ipAddressCount field will be - * incremented accordingly + * Add a list of virtual IP addresses at a the end of the virtual IP address list. The + * vrrp_header#ipAddressCount field will be incremented accordingly * @param[in] ipAddresses A vector containing all the virtual IP address * @return true if added successfully, false otherwise */ - bool addIPAddresses(const std::vector &ipAddresses); + bool addIPAddresses(const std::vector& ipAddresses); /** - * Add a virtual IP address at a the end of the virtual IP address list. The vrrp_header#ipAddressCount field will be - * incremented accordingly + * Add a virtual IP address at a the end of the virtual IP address list. The vrrp_header#ipAddressCount field + * will be incremented accordingly * @param[in] ipAddress Virtual IP address to add * @return true if add successfully, false otherwise */ - bool addIPAddress(const IPAddress &ipAddress); + bool addIPAddress(const IPAddress& ipAddress); /** - * Remove a virtual IP address at a certain index. The vrrp_header#ipAddressCount field will be decremented accordingly + * Remove a virtual IP address at a certain index. The vrrp_header#ipAddressCount field will be decremented + * accordingly * @param[in] index The index of the virtual IP address to be removed - * @return True if virtual IP address was removed successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log + * @return True if virtual IP address was removed successfully or false otherwise. If false is returned an + * appropriate error message will be printed to log */ bool removeIPAddressAtIndex(int index); /** * Remove all virtual IP addresses in the message. The vrrp_header#ipAddressCount field will be set to 0 - * @return True if virtual IP addresses were cleared successfully or false otherwise. If false is returned an appropriate error message - * will be printed to log + * @return True if virtual IP addresses were cleared successfully or false otherwise. If false is returned an + * appropriate error message will be printed to log */ bool removeAllIPAddresses(); @@ -292,7 +299,8 @@ namespace pcpp /** * Does nothing for this layer (VRRP layer is always last) */ - void parseNextLayer() override {} + void parseNextLayer() override + {} /** * Calculate the VRRP checksum @@ -302,16 +310,23 @@ namespace pcpp /** * @return The message size in bytes which include the size of the basic header + the size of the IP address(es) */ - size_t getHeaderLen() const override { return m_DataLen; } + size_t getHeaderLen() const override + { + return m_DataLen; + } std::string toString() const override; - OsiModelLayer getOsiModelLayer() const override { return OsiModelNetworkLayer; } + OsiModelLayer getOsiModelLayer() const override + { + return OsiModelNetworkLayer; + } }; /** * @class VrrpV2Layer - * Represents VRRPv2 (Virtual Router Redundancy Protocol ver 2) layer. This class represents all the different messages of VRRPv2 + * Represents VRRPv2 (Virtual Router Redundancy Protocol ver 2) layer. This class represents all the different + * messages of VRRPv2 */ class VrrpV2Layer : public VrrpLayer { @@ -341,13 +356,14 @@ namespace pcpp }; /** A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - */ - VrrpV2Layer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : VrrpLayer(data, dataLen, prevLayer, packet, VRRPv2, IPAddress::IPv4AddressType) {} + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + */ + VrrpV2Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : VrrpLayer(data, dataLen, prevLayer, packet, VRRPv2, IPAddress::IPv4AddressType) + {} /** * A constructor that allocates a new VRRP v2 layer @@ -361,11 +377,12 @@ namespace pcpp /** * A destructor for this layer (does nothing) */ - ~VrrpV2Layer() {} + ~VrrpV2Layer() + {} /** - * @return The VRRP advertisement interval in this message - */ + * @return The VRRP advertisement interval in this message + */ uint8_t getAdvInt() const; /** @@ -375,13 +392,13 @@ namespace pcpp void setAdvInt(uint8_t advInt); /** - * @return The authentication type in this message - */ + * @return The authentication type in this message + */ uint8_t getAuthType() const; /** - * @return The VRRP authentication type as enum - */ + * @return The VRRP authentication type as enum + */ VrrpAuthType getAuthTypeAsEnum() const; /** @@ -393,15 +410,16 @@ namespace pcpp // implement abstract methods /** - * Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum - * @return The checksum result - */ + * Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum + * @return The checksum result + */ uint16_t calculateChecksum() const override; }; /** * @class VrrpV3Layer - * Represents VRRPv3 (Virtual Router Redundancy Protocol ver 3) layer. This class represents all the different messages of VRRP + * Represents VRRPv3 (Virtual Router Redundancy Protocol ver 3) layer. This class represents all the different + * messages of VRRP */ class VrrpV3Layer : public VrrpLayer { @@ -413,14 +431,15 @@ namespace pcpp public: /** A constructor that creates the layer from an existing packet raw data - * @param[in] data A pointer to the raw data - * @param[in] dataLen Size of the data in bytes - * @param[in] prevLayer A pointer to the previous layer - * @param[in] packet A pointer to the Packet instance where layer will be stored in - * @param[in] addressType The IP address type to set for this layer - */ - VrrpV3Layer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet, IPAddress::AddressType addressType) - : VrrpLayer(data, dataLen, prevLayer, packet, VRRPv3, addressType) {} + * @param[in] data A pointer to the raw data + * @param[in] dataLen Size of the data in bytes + * @param[in] prevLayer A pointer to the previous layer + * @param[in] packet A pointer to the Packet instance where layer will be stored in + * @param[in] addressType The IP address type to set for this layer + */ + VrrpV3Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, IPAddress::AddressType addressType) + : VrrpLayer(data, dataLen, prevLayer, packet, VRRPv3, addressType) + {} /** * A constructor that allocates a new VRRPv3 @@ -429,16 +448,18 @@ namespace pcpp * @param priority Priority * @param maxAdvInt Max advertisement interval */ - explicit VrrpV3Layer(IPAddress::AddressType addressType, uint8_t virtualRouterId, uint8_t priority, uint16_t maxAdvInt); + explicit VrrpV3Layer(IPAddress::AddressType addressType, uint8_t virtualRouterId, uint8_t priority, + uint16_t maxAdvInt); /** * A destructor for this layer (does nothing) */ - ~VrrpV3Layer() {} + ~VrrpV3Layer() + {} /** - * @return The maximum advertisement interval in this message - */ + * @return The maximum advertisement interval in this message + */ uint16_t getMaxAdvInt() const; /** @@ -450,9 +471,9 @@ namespace pcpp // implement abstract methods /** - * Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum - * @return The checksum result - */ + * Calculate the checksum from header and data and write the result to @ref vrrp_header#checksum + * @return The checksum result + */ uint16_t calculateChecksum() const override; }; -} +} // namespace pcpp diff --git a/Packet++/header/VxlanLayer.h b/Packet++/header/VxlanLayer.h index 0fdcda1319..c078e87121 100644 --- a/Packet++/header/VxlanLayer.h +++ b/Packet++/header/VxlanLayer.h @@ -14,57 +14,56 @@ namespace pcpp #pragma pack(push, 1) struct vxlan_header { - #if(BYTE_ORDER == LITTLE_ENDIAN) - /** Reserved bits */ - uint16_t reserved6_8:3; - /** VNI present flag */ - uint16_t vniPresentFlag:1; - /** Reserved bits */ - uint16_t reserved2_4:3; - /** GBP flag */ - uint16_t gbpFlag:1; - /** Reserved bits */ - uint16_t reserved14_16:3; - /** Policy applied flag */ - uint16_t policyAppliedFlag:1; - /** Reserved bits */ - uint16_t reserved11_12:2; - /** Don't learn flag */ - uint16_t dontLearnFlag:1; - /** Reserved bits */ - uint16_t reserved9:1; - #else - /** Reserved bits */ - uint16_t reserved9:1; - /** Don't learn flag */ - uint16_t dontLearnFlag:1; - /** Reserved bits */ - uint16_t reserved11_12:2; - /** Policy applied flag */ - uint16_t policyAppliedFlag:1; - /** Reserved bits */ - uint16_t reserved14_16:3; - /** GBP flag */ - uint16_t gbpFlag:1; - /** Reserved bits */ - uint16_t reserved2_4:3; - /** VNI present flag */ - uint16_t vniPresentFlag:1; - /** Reserved bits */ - uint16_t reserved6_8:3; - #endif +#if (BYTE_ORDER == LITTLE_ENDIAN) + /** Reserved bits */ + uint16_t reserved6_8 : 3; + /** VNI present flag */ + uint16_t vniPresentFlag : 1; + /** Reserved bits */ + uint16_t reserved2_4 : 3; + /** GBP flag */ + uint16_t gbpFlag : 1; + /** Reserved bits */ + uint16_t reserved14_16 : 3; + /** Policy applied flag */ + uint16_t policyAppliedFlag : 1; + /** Reserved bits */ + uint16_t reserved11_12 : 2; + /** Don't learn flag */ + uint16_t dontLearnFlag : 1; + /** Reserved bits */ + uint16_t reserved9 : 1; +#else + /** Reserved bits */ + uint16_t reserved9 : 1; + /** Don't learn flag */ + uint16_t dontLearnFlag : 1; + /** Reserved bits */ + uint16_t reserved11_12 : 2; + /** Policy applied flag */ + uint16_t policyAppliedFlag : 1; + /** Reserved bits */ + uint16_t reserved14_16 : 3; + /** GBP flag */ + uint16_t gbpFlag : 1; + /** Reserved bits */ + uint16_t reserved2_4 : 3; + /** VNI present flag */ + uint16_t vniPresentFlag : 1; + /** Reserved bits */ + uint16_t reserved6_8 : 3; +#endif /** Group Policy ID */ uint16_t groupPolicyID; /** VXLAN Network ID (VNI) */ - uint32_t vni:24; + uint32_t vni : 24; /** Reserved bits */ - uint32_t pad:8; + uint32_t pad : 8; }; #pragma pack(pop) - /** * @class VxlanLayer * Represents a VXLAN (Virtual eXtensible Local Area Network) protocol layer @@ -72,31 +71,42 @@ namespace pcpp class VxlanLayer : public Layer { public: - /** A constructor that creates the layer from an existing packet raw data + /** A constructor that creates the layer from an existing packet raw data * @param[in] data A pointer to the raw data * @param[in] dataLen Size of the data in bytes * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - VxlanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) { m_Protocol = VXLAN; } + VxlanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = VXLAN; + } /** - * A constructor that creates a new VXLAN header and allocates the data. Note: the VNI present flag is set automatically + * A constructor that creates a new VXLAN header and allocates the data. Note: the VNI present flag is set + * automatically * @param[in] vni VNI (VXLAN Network ID) to set. Optional parameter (default is 0) * @param[in] groupPolicyID Group Policy ID to set. Optional parameter (default is 0) * @param[in] setGbpFlag Set GBP flag. Optional parameter (default is false) * @param[in] setPolicyAppliedFlag Set Policy Applied flag. Optional parameter (default is false) * @param[in] setDontLearnFlag Set Don't Learn flag. Optional parameter (default is false) */ - explicit VxlanLayer(uint32_t vni = 0, uint16_t groupPolicyID = 0, bool setGbpFlag = false, bool setPolicyAppliedFlag = false, bool setDontLearnFlag = false); + explicit VxlanLayer(uint32_t vni = 0, uint16_t groupPolicyID = 0, bool setGbpFlag = false, + bool setPolicyAppliedFlag = false, bool setDontLearnFlag = false); - ~VxlanLayer() {} + ~VxlanLayer() + {} /** - * Get a pointer to the VXLAN header. Notice this points directly to the data, so every change will change the actual packet data + * Get a pointer to the VXLAN header. Notice this points directly to the data, so every change will change the + * actual packet data * @return A pointer to the vxlan_header */ - vxlan_header* getVxlanHeader() const { return (vxlan_header*)m_Data; } + vxlan_header* getVxlanHeader() const + { + return (vxlan_header*)m_Data; + } /** * @return The VXLAN Network ID (VNI) value @@ -113,8 +123,10 @@ namespace pcpp * A static method that checks whether the port is considered as VxLAN * @param[in] port The port number to be checked */ - static bool isVxlanPort(uint16_t port) { return port == 4789; } - + static bool isVxlanPort(uint16_t port) + { + return port == 4789; + } // implement abstract methods @@ -126,17 +138,23 @@ namespace pcpp /** * @return Size of vxlan_header */ - size_t getHeaderLen() const { return sizeof(vxlan_header); } + size_t getHeaderLen() const + { + return sizeof(vxlan_header); + } /** * Does nothing for this layer */ - void computeCalculateFields() {} + void computeCalculateFields() + {} std::string toString() const; - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } - + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } }; -} +} // namespace pcpp diff --git a/Packet++/header/WakeOnLanLayer.h b/Packet++/header/WakeOnLanLayer.h index 68d1375c79..a06d78bbc7 100644 --- a/Packet++/header/WakeOnLanLayer.h +++ b/Packet++/header/WakeOnLanLayer.h @@ -17,10 +17,10 @@ namespace pcpp */ class WakeOnLanLayer : public Layer { - private: - void init(uint16_t len); + private: + void init(uint16_t len); - public: + public: /** * @struct wol_header * Wake On LAN protocol header @@ -42,8 +42,8 @@ namespace pcpp * @param[in] prevLayer A pointer to the previous layer * @param[in] packet A pointer to the Packet instance where layer will be stored in */ - WakeOnLanLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : Layer(data, dataLen, prevLayer, packet) + WakeOnLanLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { m_Protocol = WakeOnLan; } @@ -52,7 +52,7 @@ namespace pcpp * Construct a new Wake On Lan Layer with provided values * @param[in] targetAddr Target MAC address */ - explicit WakeOnLanLayer(const pcpp::MacAddress &targetAddr); + explicit WakeOnLanLayer(const pcpp::MacAddress& targetAddr); /** * Construct a new Wake On Lan Layer with provided values @@ -60,28 +60,31 @@ namespace pcpp * @param[in] password Password as array * @param[in] len Length of the password array, length of the password should be less than 6 bytes */ - WakeOnLanLayer(const pcpp::MacAddress &targetAddr, uint8_t *password, uint8_t len); + WakeOnLanLayer(const pcpp::MacAddress& targetAddr, uint8_t* password, uint8_t len); /** * Construct a new Wake On Lan Layer with provided values * @param[in] targetAddr Target MAC address * @param[in] password Password as MAC address */ - WakeOnLanLayer(const pcpp::MacAddress &targetAddr, const pcpp::MacAddress &password); + WakeOnLanLayer(const pcpp::MacAddress& targetAddr, const pcpp::MacAddress& password); /** * Construct a new Wake On Lan Layer with provided values * @param[in] targetAddr Target MAC address * @param[in] password Password as IPv4 address */ - WakeOnLanLayer(const pcpp::MacAddress &targetAddr, const IPv4Address &password); + WakeOnLanLayer(const pcpp::MacAddress& targetAddr, const IPv4Address& password); /** * Get a pointer to the Wake On LAN header. Notice this points directly to the data, so every change will change * the actual packet data * @return A pointer to the wol_header */ - inline wol_header *getWakeOnLanHeader() const { return (wol_header *)m_Data; } + inline wol_header* getWakeOnLanHeader() const + { + return (wol_header*)m_Data; + } /** * Get the target MAC address of the command @@ -93,7 +96,7 @@ namespace pcpp * Set the target MAC address * @param[in] targetAddr MAC address of the target */ - void setTargetAddr(const pcpp::MacAddress &targetAddr); + void setTargetAddr(const pcpp::MacAddress& targetAddr); /** * Get the password of the command @@ -107,34 +110,37 @@ namespace pcpp * @param[in] len Length of the password array, length of the password should be less than 6 bytes * @return True if operation successful, false otherwise */ - bool setPassword(const uint8_t *password, uint8_t len); + bool setPassword(const uint8_t* password, uint8_t len); /** * Set the password of the command * @param[in] password Password as string. Length of the password should be less than 6 bytes * @return True if operation successful, false otherwise */ - bool setPassword(const std::string &password); + bool setPassword(const std::string& password); /** * Set the password of the command * @param[in] addr Password as MAC address * @return True if operation successful, false otherwise */ - bool setPassword(const MacAddress &addr); + bool setPassword(const MacAddress& addr); /** * Set the password of the command * @param addr Password as IPv4 address * @return True if operation successful, false otherwise */ - bool setPassword(const IPv4Address &addr); + bool setPassword(const IPv4Address& addr); /** * A static method that checks whether the port is considered as Wake on LAN * @param[in] port The port number to be checked */ - static bool isWakeOnLanPort(uint16_t port) { return (port == 0) || (port == 7) || (port == 9); } + static bool isWakeOnLanPort(uint16_t port) + { + return (port == 0) || (port == 7) || (port == 9); + } /** * A static method that takes a byte array and detects whether it is a Wake on LAN message @@ -142,29 +148,37 @@ namespace pcpp * @param[in] dataSize The byte array size (in bytes) * @return True if the data is identified as Wake on LAN message */ - static bool isDataValid(const uint8_t *data, size_t dataSize); + static bool isDataValid(const uint8_t* data, size_t dataSize); // overridden methods /// Parses the next layer. Wake on LAN is the always last so does nothing for this layer - void parseNextLayer() {} + void parseNextLayer() + {} /** * @return Get the size of the layer */ - size_t getHeaderLen() const { return m_DataLen; } + size_t getHeaderLen() const + { + return m_DataLen; + } /// Does nothing for this layer - void computeCalculateFields() {} + void computeCalculateFields() + {} /** * @return The OSI layer level of Wake on LAN (Data Link Layer) */ - OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; } + OsiModelLayer getOsiModelLayer() const + { + return OsiModelDataLinkLayer; + } /** * @return Returns the protocol info as readable string */ std::string toString() const; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/ArpLayer.cpp b/Packet++/src/ArpLayer.cpp index c821794412..0852d9bb0f 100644 --- a/Packet++/src/ArpLayer.cpp +++ b/Packet++/src/ArpLayer.cpp @@ -8,54 +8,56 @@ namespace pcpp { -ArpLayer::ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr) -{ - const size_t headerLen = sizeof(arphdr); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, sizeof(headerLen)); - m_Protocol = ARP; - - arphdr* arpHeader = getArpHeader(); - arpHeader->opcode = htobe16(static_cast(opCode)); - targetMacAddr.copyTo(arpHeader->targetMacAddr); - senderMacAddr.copyTo(arpHeader->senderMacAddr); - arpHeader->targetIpAddr = targetIpAddr.toInt(); - arpHeader->senderIpAddr = senderIpAddr.toInt(); -} - -void ArpLayer::computeCalculateFields() -{ - arphdr* arpHeader = getArpHeader(); - arpHeader->hardwareType = htobe16(1); //Ethernet - arpHeader->hardwareSize = 6; - arpHeader->protocolType = htobe16(PCPP_ETHERTYPE_IP); //assume IPv4 over ARP - arpHeader->protocolSize = 4; //assume IPv4 over ARP - if (arpHeader->opcode == htobe16(ARP_REQUEST)) - MacAddress::Zero.copyTo(arpHeader->targetMacAddr); -} - -bool ArpLayer::isRequest() const -{ - return be16toh(getArpHeader()->opcode) == pcpp::ArpOpcode::ARP_REQUEST; -} + ArpLayer::ArpLayer(ArpOpcode opCode, const MacAddress& senderMacAddr, const MacAddress& targetMacAddr, + const IPv4Address& senderIpAddr, const IPv4Address& targetIpAddr) + { + const size_t headerLen = sizeof(arphdr); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, sizeof(headerLen)); + m_Protocol = ARP; + + arphdr* arpHeader = getArpHeader(); + arpHeader->opcode = htobe16(static_cast(opCode)); + targetMacAddr.copyTo(arpHeader->targetMacAddr); + senderMacAddr.copyTo(arpHeader->senderMacAddr); + arpHeader->targetIpAddr = targetIpAddr.toInt(); + arpHeader->senderIpAddr = senderIpAddr.toInt(); + } + void ArpLayer::computeCalculateFields() + { + arphdr* arpHeader = getArpHeader(); + arpHeader->hardwareType = htobe16(1); // Ethernet + arpHeader->hardwareSize = 6; + arpHeader->protocolType = htobe16(PCPP_ETHERTYPE_IP); // assume IPv4 over ARP + arpHeader->protocolSize = 4; // assume IPv4 over ARP + if (arpHeader->opcode == htobe16(ARP_REQUEST)) + MacAddress::Zero.copyTo(arpHeader->targetMacAddr); + } -bool ArpLayer::isReply() const -{ - return be16toh(getArpHeader()->opcode) == pcpp::ArpOpcode::ARP_REPLY; -} + bool ArpLayer::isRequest() const + { + return be16toh(getArpHeader()->opcode) == pcpp::ArpOpcode::ARP_REQUEST; + } -std::string ArpLayer::toString() const -{ - if (be16toh(getArpHeader()->opcode) == ARP_REQUEST) + bool ArpLayer::isReply() const { - return "ARP Layer, ARP request, who has " + getTargetIpAddr().toString() + " ? Tell " + getSenderIpAddr().toString(); + return be16toh(getArpHeader()->opcode) == pcpp::ArpOpcode::ARP_REPLY; } - else + + std::string ArpLayer::toString() const { - return "ARP Layer, ARP reply, " + getSenderIpAddr().toString() + " is at " + getSenderMacAddress().toString(); + if (be16toh(getArpHeader()->opcode) == ARP_REQUEST) + { + return "ARP Layer, ARP request, who has " + getTargetIpAddr().toString() + " ? Tell " + + getSenderIpAddr().toString(); + } + else + { + return "ARP Layer, ARP reply, " + getSenderIpAddr().toString() + " is at " + + getSenderMacAddress().toString(); + } } -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/Asn1Codec.cpp b/Packet++/src/Asn1Codec.cpp index 555b829861..5990f70fd0 100644 --- a/Packet++/src/Asn1Codec.cpp +++ b/Packet++/src/Asn1Codec.cpp @@ -14,16 +14,16 @@ #include #if defined(_WIN32) -#undef max +# undef max #endif namespace pcpp { - const std::unordered_map> Asn1TagClassToString { - {Asn1TagClass::Universal, "Universal" }, - {Asn1TagClass::ContextSpecific, "ContextSpecific" }, - {Asn1TagClass::Application, "Application"}, - {Asn1TagClass::Private, "Private"} + const std::unordered_map> Asn1TagClassToString{ + { Asn1TagClass::Universal, "Universal" }, + { Asn1TagClass::ContextSpecific, "ContextSpecific" }, + { Asn1TagClass::Application, "Application" }, + { Asn1TagClass::Private, "Private" } }; std::string toString(Asn1TagClass tagClass) @@ -36,46 +36,47 @@ namespace pcpp return "Unknown"; } - const std::unordered_map> Asn1UniversalTagTypeToString { - {Asn1UniversalTagType::EndOfContent, "EndOfContent"}, - {Asn1UniversalTagType::Boolean, "Boolean"}, - {Asn1UniversalTagType::Integer, "Integer"}, - {Asn1UniversalTagType::BitString, "BitString"}, - {Asn1UniversalTagType::OctetString, "OctetString"}, - {Asn1UniversalTagType::Null, "Null"}, - {Asn1UniversalTagType::ObjectIdentifier, "ObjectIdentifier"}, - {Asn1UniversalTagType::ObjectDescriptor, "ObjectDescriptor"}, - {Asn1UniversalTagType::External, "External"}, - {Asn1UniversalTagType::Real, "Real"}, - {Asn1UniversalTagType::Enumerated, "Enumerated"}, - {Asn1UniversalTagType::EmbeddedPDV, "EmbeddedPDV"}, - {Asn1UniversalTagType::UTF8String, "UTF8String"}, - {Asn1UniversalTagType::RelativeObjectIdentifier, "RelativeObjectIdentifier"}, - {Asn1UniversalTagType::Time, "Time"}, - {Asn1UniversalTagType::Reserved, "Reserved"}, - {Asn1UniversalTagType::Sequence, "Sequence"}, - {Asn1UniversalTagType::Set, "Set"}, - {Asn1UniversalTagType::NumericString, "NumericString"}, - {Asn1UniversalTagType::PrintableString, "PrintableString"}, - {Asn1UniversalTagType::T61String, "T61String"}, - {Asn1UniversalTagType::VideotexString, "VideotexString"}, - {Asn1UniversalTagType::IA5String, "IA5String"}, - {Asn1UniversalTagType::UTCTime, "UTCTime"}, - {Asn1UniversalTagType::GeneralizedTime, "GeneralizedTime"}, - {Asn1UniversalTagType::GraphicString, "GraphicString"}, - {Asn1UniversalTagType::VisibleString, "VisibleString"}, - {Asn1UniversalTagType::GeneralString, "GeneralString"}, - {Asn1UniversalTagType::UniversalString, "UniversalString"}, - {Asn1UniversalTagType::CharacterString, "CharacterString"}, - {Asn1UniversalTagType::BMPString, "BMPString"}, - {Asn1UniversalTagType::Date, "Date"}, - {Asn1UniversalTagType::TimeOfDay, "TimeOfDay"}, - {Asn1UniversalTagType::DateTime, "DateTime"}, - {Asn1UniversalTagType::Duration, "Duration"}, - {Asn1UniversalTagType::ObjectIdentifierIRI, "ObjectIdentifierIRI"}, - {Asn1UniversalTagType::RelativeObjectIdentifierIRI, "RelativeObjectIdentifierIRI"}, - {Asn1UniversalTagType::NotApplicable, "Unknown"} - }; + const std::unordered_map> + Asn1UniversalTagTypeToString{ + { Asn1UniversalTagType::EndOfContent, "EndOfContent" }, + { Asn1UniversalTagType::Boolean, "Boolean" }, + { Asn1UniversalTagType::Integer, "Integer" }, + { Asn1UniversalTagType::BitString, "BitString" }, + { Asn1UniversalTagType::OctetString, "OctetString" }, + { Asn1UniversalTagType::Null, "Null" }, + { Asn1UniversalTagType::ObjectIdentifier, "ObjectIdentifier" }, + { Asn1UniversalTagType::ObjectDescriptor, "ObjectDescriptor" }, + { Asn1UniversalTagType::External, "External" }, + { Asn1UniversalTagType::Real, "Real" }, + { Asn1UniversalTagType::Enumerated, "Enumerated" }, + { Asn1UniversalTagType::EmbeddedPDV, "EmbeddedPDV" }, + { Asn1UniversalTagType::UTF8String, "UTF8String" }, + { Asn1UniversalTagType::RelativeObjectIdentifier, "RelativeObjectIdentifier" }, + { Asn1UniversalTagType::Time, "Time" }, + { Asn1UniversalTagType::Reserved, "Reserved" }, + { Asn1UniversalTagType::Sequence, "Sequence" }, + { Asn1UniversalTagType::Set, "Set" }, + { Asn1UniversalTagType::NumericString, "NumericString" }, + { Asn1UniversalTagType::PrintableString, "PrintableString" }, + { Asn1UniversalTagType::T61String, "T61String" }, + { Asn1UniversalTagType::VideotexString, "VideotexString" }, + { Asn1UniversalTagType::IA5String, "IA5String" }, + { Asn1UniversalTagType::UTCTime, "UTCTime" }, + { Asn1UniversalTagType::GeneralizedTime, "GeneralizedTime" }, + { Asn1UniversalTagType::GraphicString, "GraphicString" }, + { Asn1UniversalTagType::VisibleString, "VisibleString" }, + { Asn1UniversalTagType::GeneralString, "GeneralString" }, + { Asn1UniversalTagType::UniversalString, "UniversalString" }, + { Asn1UniversalTagType::CharacterString, "CharacterString" }, + { Asn1UniversalTagType::BMPString, "BMPString" }, + { Asn1UniversalTagType::Date, "Date" }, + { Asn1UniversalTagType::TimeOfDay, "TimeOfDay" }, + { Asn1UniversalTagType::DateTime, "DateTime" }, + { Asn1UniversalTagType::Duration, "Duration" }, + { Asn1UniversalTagType::ObjectIdentifierIRI, "ObjectIdentifierIRI" }, + { Asn1UniversalTagType::RelativeObjectIdentifierIRI, "RelativeObjectIdentifierIRI" }, + { Asn1UniversalTagType::NotApplicable, "Unknown" } + }; std::string toString(Asn1UniversalTagType tagType) { @@ -89,7 +90,7 @@ namespace pcpp std::unique_ptr Asn1Record::decode(const uint8_t* data, size_t dataLen, bool lazy) { - auto record = decodeInternal(data, dataLen ,lazy); + auto record = decodeInternal(data, dataLen, lazy); return std::unique_ptr(record); } @@ -99,26 +100,26 @@ namespace pcpp switch (m_TagClass) { - case Asn1TagClass::Private: - { - tagByte = 0xc0; - break; - } - case Asn1TagClass::ContextSpecific: - { - tagByte = 0x80; - break; - } - case Asn1TagClass::Application: - { - tagByte = 0x40; - break; - } - default: - { - tagByte = 0; - break; - } + case Asn1TagClass::Private: + { + tagByte = 0xc0; + break; + } + case Asn1TagClass::ContextSpecific: + { + tagByte = 0x80; + break; + } + case Asn1TagClass::Application: + { + tagByte = 0x40; + break; + } + default: + { + tagByte = 0; + break; + } } if (m_IsConstructed) @@ -146,7 +147,7 @@ namespace pcpp do { uint8_t byte = tempValueLength & 0xff; - result.push_back(byte); // Inserts the bytes in reverse order + result.push_back(byte); // Inserts the bytes in reverse order tempValueLength >>= 8; } while (tempValueLength != 0); @@ -209,7 +210,6 @@ namespace pcpp delete decodedRecord; throw; } - } else { @@ -289,20 +289,20 @@ namespace pcpp { switch (static_cast(tagType)) { - case Asn1UniversalTagType::Sequence: - { - newRecord = new Asn1SequenceRecord(); - break; - } - case Asn1UniversalTagType::Set: - { - newRecord = new Asn1SetRecord(); - break; - } - default: - { - newRecord = new Asn1ConstructedRecord(); - } + case Asn1UniversalTagType::Sequence: + { + newRecord = new Asn1SequenceRecord(); + break; + } + case Asn1UniversalTagType::Set: + { + newRecord = new Asn1SetRecord(); + break; + } + default: + { + newRecord = new Asn1ConstructedRecord(); + } } } else @@ -317,35 +317,35 @@ namespace pcpp auto asn1UniversalTagType = static_cast(tagType); switch (asn1UniversalTagType) { - case Asn1UniversalTagType::Integer: - { - newRecord = new Asn1IntegerRecord(); - break; - } - case Asn1UniversalTagType::Enumerated: - { - newRecord = new Asn1EnumeratedRecord(); - break; - } - case Asn1UniversalTagType::OctetString: - { - newRecord = new Asn1OctetStringRecord(); - break; - } - case Asn1UniversalTagType::Boolean: - { - newRecord = new Asn1BooleanRecord(); - break; - } - case Asn1UniversalTagType::Null: - { - newRecord = new Asn1NullRecord(); - break; - } - default: - { - newRecord = new Asn1GenericRecord(); - } + case Asn1UniversalTagType::Integer: + { + newRecord = new Asn1IntegerRecord(); + break; + } + case Asn1UniversalTagType::Enumerated: + { + newRecord = new Asn1EnumeratedRecord(); + break; + } + case Asn1UniversalTagType::OctetString: + { + newRecord = new Asn1OctetStringRecord(); + break; + } + case Asn1UniversalTagType::Boolean: + { + newRecord = new Asn1BooleanRecord(); + break; + } + case Asn1UniversalTagType::Null: + { + newRecord = new Asn1NullRecord(); + break; + } + default: + { + newRecord = new Asn1GenericRecord(); + } } } else @@ -410,8 +410,7 @@ namespace pcpp { auto lines = toStringList(); - auto commaSeparated = [](std::string str1, std::string str2) - { + auto commaSeparated = [](std::string str1, std::string str2) { return std::move(str1) + '\n' + std::move(str2); }; @@ -439,15 +438,17 @@ namespace pcpp stream << ", Length: " << m_TotalLength - m_ValueLength << "+" << m_ValueLength; - return {stream.str()}; + return { stream.str() }; } - Asn1GenericRecord::Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, size_t valueLen) + Asn1GenericRecord::Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, + const uint8_t* value, size_t valueLen) { init(tagClass, isConstructed, tagType, value, valueLen); } - Asn1GenericRecord::Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const std::string& value) + Asn1GenericRecord::Asn1GenericRecord(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, + const std::string& value) { init(tagClass, isConstructed, tagType, reinterpret_cast(value.c_str()), value.size()); } @@ -467,10 +468,11 @@ namespace pcpp std::vector Asn1GenericRecord::encodeValue() const { - return {m_Value, m_Value + m_ValueLength}; + return { m_Value, m_Value + m_ValueLength }; } - void Asn1GenericRecord::init(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, size_t valueLen) + void Asn1GenericRecord::init(Asn1TagClass tagClass, bool isConstructed, uint8_t tagType, const uint8_t* value, + size_t valueLen) { m_TagType = tagType; m_TagClass = tagClass; @@ -481,12 +483,14 @@ namespace pcpp m_TotalLength = m_ValueLength + 2; } - Asn1ConstructedRecord::Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, const std::vector& subRecords) + Asn1ConstructedRecord::Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, + const std::vector& subRecords) { init(tagClass, tagType, subRecords.begin(), subRecords.end()); } - Asn1ConstructedRecord::Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, const PointerVector& subRecords) + Asn1ConstructedRecord::Asn1ConstructedRecord(Asn1TagClass tagClass, uint8_t tagType, + const PointerVector& subRecords) { init(tagClass, tagType, subRecords.begin(), subRecords.end()); } @@ -519,7 +523,8 @@ namespace pcpp for (auto record : m_SubRecords) { auto encodedRecord = record->encode(); - result.insert(result.end(), std::make_move_iterator(encodedRecord.begin()), std::make_move_iterator(encodedRecord.end())); + result.insert(result.end(), std::make_move_iterator(encodedRecord.begin()), + std::make_move_iterator(encodedRecord.end())); } return result; } @@ -527,7 +532,7 @@ namespace pcpp std::vector Asn1ConstructedRecord::toStringList() { decodeValueIfNeeded(); - std::vector result = {Asn1Record::toStringList().front()}; + std::vector result = { Asn1Record::toStringList().front() }; for (auto subRecord : m_SubRecords) { for (const auto& line : subRecord->toStringList()) @@ -539,24 +544,26 @@ namespace pcpp } Asn1SequenceRecord::Asn1SequenceRecord(const std::vector& subRecords) - : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Sequence), subRecords) + : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Sequence), + subRecords) {} Asn1SequenceRecord::Asn1SequenceRecord(const PointerVector& subRecords) - : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Sequence), subRecords) + : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Sequence), + subRecords) {} Asn1SetRecord::Asn1SetRecord(const std::vector& subRecords) - : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Set), subRecords) + : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Set), subRecords) {} Asn1SetRecord::Asn1SetRecord(const PointerVector& subRecords) - : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Set), subRecords) + : Asn1ConstructedRecord(Asn1TagClass::Universal, static_cast(Asn1UniversalTagType::Set), subRecords) {} Asn1PrimitiveRecord::Asn1PrimitiveRecord(Asn1UniversalTagType tagType) : Asn1Record() { - m_TagType = static_cast(tagType); + m_TagType = static_cast(tagType); m_TagClass = Asn1TagClass::Universal; m_IsConstructed = false; } @@ -589,32 +596,32 @@ namespace pcpp { switch (m_ValueLength) { - case 1: - { - m_Value = *data; - break; - } - case 2: - { - m_Value = be16toh(*reinterpret_cast(data)); - break; - } - case 3: - { - uint8_t tempData[4] = {0}; - memcpy(tempData + 1, data, 3); - m_Value = be32toh(*reinterpret_cast(tempData)); - break; - } - case 4: - { - m_Value = be32toh(*reinterpret_cast(data)); - break; - } - default: - { - throw std::runtime_error("An integer ASN.1 record of more than 4 bytes is not supported"); - } + case 1: + { + m_Value = *data; + break; + } + case 2: + { + m_Value = be16toh(*reinterpret_cast(data)); + break; + } + case 3: + { + uint8_t tempData[4] = { 0 }; + memcpy(tempData + 1, data, 3); + m_Value = be32toh(*reinterpret_cast(tempData)); + break; + } + case 4: + { + m_Value = be32toh(*reinterpret_cast(data)); + break; + } + default: + { + throw std::runtime_error("An integer ASN.1 record of more than 4 bytes is not supported"); + } } } @@ -622,45 +629,45 @@ namespace pcpp { std::vector result; - #if !(defined(__MINGW64_VERSION_MAJOR) || defined(__MINGW32_MAJOR_VERSION)) +#if !(defined(__MINGW64_VERSION_MAJOR) || defined(__MINGW32_MAJOR_VERSION)) result.reserve(m_ValueLength); - #endif +#endif switch (m_ValueLength) { - case 1: - { - result.push_back(static_cast(m_Value)); - break; - } - case 2: - { - uint8_t tempArr[sizeof(uint16_t)]; - auto hostValue = htobe16(static_cast(m_Value)); - memcpy(tempArr, &hostValue, m_ValueLength); - std::copy(tempArr, tempArr + m_ValueLength, std::back_inserter(result)); - break; - } - case 3: - { - uint8_t tempArr[sizeof(uint32_t)]; - auto hostValue = htobe32(static_cast(m_Value)); - memcpy(tempArr, &hostValue, m_ValueLength + 1); - std::copy(tempArr + 1, tempArr + m_ValueLength + 1, std::back_inserter(result)); - break; - } - case 4: - { - uint8_t tempArr[sizeof(uint32_t)]; - auto hostValue = htobe32(static_cast(m_Value)); - memcpy(tempArr, &hostValue, m_ValueLength); - std::copy(tempArr, tempArr + m_ValueLength, std::back_inserter(result)); - break; - } - default: - { - throw std::runtime_error("Integer value of more than 4 bytes is not supported"); - } + case 1: + { + result.push_back(static_cast(m_Value)); + break; + } + case 2: + { + uint8_t tempArr[sizeof(uint16_t)]; + auto hostValue = htobe16(static_cast(m_Value)); + memcpy(tempArr, &hostValue, m_ValueLength); + std::copy(tempArr, tempArr + m_ValueLength, std::back_inserter(result)); + break; + } + case 3: + { + uint8_t tempArr[sizeof(uint32_t)]; + auto hostValue = htobe32(static_cast(m_Value)); + memcpy(tempArr, &hostValue, m_ValueLength + 1); + std::copy(tempArr + 1, tempArr + m_ValueLength + 1, std::back_inserter(result)); + break; + } + case 4: + { + uint8_t tempArr[sizeof(uint32_t)]; + auto hostValue = htobe32(static_cast(m_Value)); + memcpy(tempArr, &hostValue, m_ValueLength); + std::copy(tempArr, tempArr + m_ValueLength, std::back_inserter(result)); + break; + } + default: + { + throw std::runtime_error("Integer value of more than 4 bytes is not supported"); + } } return result; @@ -668,7 +675,8 @@ namespace pcpp std::vector Asn1IntegerRecord::toStringList() { - return std::vector({Asn1Record::toStringList().front() + ", Value: " + std::to_string(getValue())}); + return std::vector( + { Asn1Record::toStringList().front() + ", Value: " + std::to_string(getValue()) }); } Asn1EnumeratedRecord::Asn1EnumeratedRecord(uint32_t value) : Asn1IntegerRecord(value) @@ -676,7 +684,8 @@ namespace pcpp m_TagType = static_cast(Asn1UniversalTagType::Enumerated); } - Asn1OctetStringRecord::Asn1OctetStringRecord(const std::string& value) : Asn1PrimitiveRecord(Asn1UniversalTagType::OctetString) + Asn1OctetStringRecord::Asn1OctetStringRecord(const std::string& value) + : Asn1PrimitiveRecord(Asn1UniversalTagType::OctetString) { m_Value = value; m_ValueLength = value.size(); @@ -684,7 +693,8 @@ namespace pcpp m_IsPrintable = true; } - Asn1OctetStringRecord::Asn1OctetStringRecord(const uint8_t* value, size_t valueLength) : Asn1PrimitiveRecord(Asn1UniversalTagType::OctetString) + Asn1OctetStringRecord::Asn1OctetStringRecord(const uint8_t* value, size_t valueLength) + : Asn1PrimitiveRecord(Asn1UniversalTagType::OctetString) { m_Value = byteArrayToHexString(value, valueLength); m_ValueLength = valueLength; @@ -696,9 +706,7 @@ namespace pcpp { auto value = reinterpret_cast(data); - m_IsPrintable = std::all_of(value, value + m_ValueLength, [](char c) { - return isprint(0xff & c); - }); + m_IsPrintable = std::all_of(value, value + m_ValueLength, [](char c) { return isprint(0xff & c); }); if (m_IsPrintable) { @@ -714,7 +722,7 @@ namespace pcpp { if (m_IsPrintable) { - return {m_Value.begin(), m_Value.end()}; + return { m_Value.begin(), m_Value.end() }; } // converting the hex stream to a byte array. @@ -729,7 +737,7 @@ namespace pcpp std::vector Asn1OctetStringRecord::toStringList() { - return {Asn1Record::toStringList().front() + ", Value: " + getValue()}; + return { Asn1Record::toStringList().front() + ", Value: " + getValue() }; } Asn1BooleanRecord::Asn1BooleanRecord(bool value) : Asn1PrimitiveRecord(Asn1UniversalTagType::Boolean) @@ -752,7 +760,7 @@ namespace pcpp std::vector Asn1BooleanRecord::toStringList() { - return {Asn1Record::toStringList().front() + ", Value: " + (getValue() ? "true" : "false")}; + return { Asn1Record::toStringList().front() + ", Value: " + (getValue() ? "true" : "false") }; } Asn1NullRecord::Asn1NullRecord() : Asn1PrimitiveRecord(Asn1UniversalTagType::Null) @@ -760,4 +768,4 @@ namespace pcpp m_ValueLength = 0; m_TotalLength = 2; } -} +} // namespace pcpp diff --git a/Packet++/src/BgpLayer.cpp b/Packet++/src/BgpLayer.cpp index 791f9a07d5..e8e48320d7 100644 --- a/Packet++/src/BgpLayer.cpp +++ b/Packet++/src/BgpLayer.cpp @@ -8,59 +8,61 @@ namespace pcpp { -// ~~~~~~~~ -// BgpLayer -// ~~~~~~~~ + // ~~~~~~~~ + // BgpLayer + // ~~~~~~~~ -size_t BgpLayer::getHeaderLen() const -{ - if (m_DataLen < sizeof(bgp_common_header)) + size_t BgpLayer::getHeaderLen() const { - return m_DataLen; - } + if (m_DataLen < sizeof(bgp_common_header)) + { + return m_DataLen; + } - uint16_t messageLen = be16toh(getBasicHeader()->length); - if (m_DataLen < messageLen) - { - return m_DataLen; - } + uint16_t messageLen = be16toh(getBasicHeader()->length); + if (m_DataLen < messageLen) + { + return m_DataLen; + } - return (size_t)messageLen; -} + return (size_t)messageLen; + } -BgpLayer* BgpLayer::parseBgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - if (data == nullptr || dataLen < sizeof(bgp_common_header)) - return nullptr; + BgpLayer* BgpLayer::parseBgpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + { + if (data == nullptr || dataLen < sizeof(bgp_common_header)) + return nullptr; - bgp_common_header* bgpHeader = (bgp_common_header*)data; + bgp_common_header* bgpHeader = (bgp_common_header*)data; - // illegal header data - length is too small - uint16_t messageLen = be16toh(bgpHeader->length); - if (dataLen < messageLen || messageLen < static_cast(sizeof(bgp_common_header))) - return nullptr; + // illegal header data - length is too small + uint16_t messageLen = be16toh(bgpHeader->length); + if (dataLen < messageLen || messageLen < static_cast(sizeof(bgp_common_header))) + return nullptr; - switch (bgpHeader->messageType) - { - case 1: // OPEN - return new BgpOpenMessageLayer(data, dataLen, prevLayer, packet); - case 2: // UPDATE - return BgpUpdateMessageLayer::isDataValid(data, dataLen) ? new BgpUpdateMessageLayer(data, dataLen, prevLayer, packet) : nullptr; - case 3: // NOTIFICATION - return new BgpNotificationMessageLayer(data, dataLen, prevLayer, packet); - case 4: // KEEPALIVE - return new BgpKeepaliveMessageLayer(data, dataLen, prevLayer, packet); - case 5: // ROUTE-REFRESH - return new BgpRouteRefreshMessageLayer(data, dataLen, prevLayer, packet); - default: - return nullptr; + switch (bgpHeader->messageType) + { + case 1: // OPEN + return new BgpOpenMessageLayer(data, dataLen, prevLayer, packet); + case 2: // UPDATE + return BgpUpdateMessageLayer::isDataValid(data, dataLen) + ? new BgpUpdateMessageLayer(data, dataLen, prevLayer, packet) + : nullptr; + case 3: // NOTIFICATION + return new BgpNotificationMessageLayer(data, dataLen, prevLayer, packet); + case 4: // KEEPALIVE + return new BgpKeepaliveMessageLayer(data, dataLen, prevLayer, packet); + case 5: // ROUTE-REFRESH + return new BgpRouteRefreshMessageLayer(data, dataLen, prevLayer, packet); + default: + return nullptr; + } } -} -std::string BgpLayer::getMessageTypeAsString() const -{ - switch (getBgpMessageType()) + std::string BgpLayer::getMessageTypeAsString() const { + switch (getBgpMessageType()) + { case BgpLayer::Open: return "OPEN"; case BgpLayer::Update: @@ -73,854 +75,872 @@ std::string BgpLayer::getMessageTypeAsString() const return "ROUTE-REFRESH"; default: return "Unknown"; + } } -} - -void BgpLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen || headerLen == 0) - return; - - uint8_t* payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; - - m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, m_Packet); -} - -std::string BgpLayer::toString() const -{ - return "BGP Layer, " + getMessageTypeAsString() + " message"; -} - -void BgpLayer::computeCalculateFields() -{ - bgp_common_header* bgpHeader = getBasicHeader(); - memset(bgpHeader->marker, 0xff, 16*sizeof(uint8_t)); - bgpHeader->messageType = (uint8_t)getBgpMessageType(); - bgpHeader->length = htobe16(getHeaderLen()); -} -void BgpLayer::setBgpFields(size_t messageLen) -{ - bgp_common_header* bgpHdr = getBasicHeader(); - memset(bgpHdr->marker, 0xff, 16*sizeof(uint8_t)); - bgpHdr->messageType = (uint8_t)getBgpMessageType(); - if (messageLen != 0) + void BgpLayer::parseNextLayer() { - bgpHdr->length = htobe16((uint16_t)messageLen); - } - else - { - bgpHdr->length = m_DataLen; - } -} - + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen || headerLen == 0) + return; + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; -// ~~~~~~~~~~~~~~~~~~~~ -// BgpOpenMessageLayer -// ~~~~~~~~~~~~~~~~~~~~ - -BgpOpenMessageLayer::optional_parameter::optional_parameter(uint8_t typeVal, const std::string& valueAsHexString) -{ - type = typeVal; - length = hexStringToByteArray(valueAsHexString, value, 32); -} - -BgpOpenMessageLayer::BgpOpenMessageLayer(uint16_t myAutonomousSystem, uint16_t holdTime, const IPv4Address& bgpId, - const std::vector& optionalParams) -{ - uint8_t optionalParamsData[1500]; - size_t optionalParamsDataLen = optionalParamsToByteArray(optionalParams, optionalParamsData, 1500); - - const size_t headerLen = sizeof(bgp_open_message) + optionalParamsDataLen; - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - setBgpFields(headerLen); + m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, m_Packet); + } - bgp_open_message* msgHdr = getOpenMsgHeader(); - msgHdr->version = 4; - msgHdr->myAutonomousSystem = htobe16(myAutonomousSystem); - msgHdr->holdTime = htobe16(holdTime); - msgHdr->bgpId = bgpId.toInt(); - msgHdr->optionalParameterLength = optionalParamsDataLen; - if (optionalParamsDataLen > 0) + std::string BgpLayer::toString() const { - memcpy(m_Data + sizeof(bgp_open_message), optionalParamsData, optionalParamsDataLen); + return "BGP Layer, " + getMessageTypeAsString() + " message"; } - m_Protocol = BGP; -} - -size_t BgpOpenMessageLayer::optionalParamsToByteArray(const std::vector& optionalParams, uint8_t* resultByteArr, size_t maxByteArrSize) -{ - if (resultByteArr == nullptr || maxByteArrSize == 0) + void BgpLayer::computeCalculateFields() { - return 0; + bgp_common_header* bgpHeader = getBasicHeader(); + memset(bgpHeader->marker, 0xff, 16 * sizeof(uint8_t)); + bgpHeader->messageType = (uint8_t)getBgpMessageType(); + bgpHeader->length = htobe16(getHeaderLen()); } - size_t dataLen = 0; - - for (const auto ¶m : optionalParams) + void BgpLayer::setBgpFields(size_t messageLen) { - if (param.length > 32) - { - PCPP_LOG_ERROR("Illegal optional parameter length " << (int)param.length << ", must be 32 bytes or less"); - break; // illegal value - } - - size_t curDataSize = 2*sizeof(uint8_t) + (size_t)param.length; - - if (dataLen + curDataSize > maxByteArrSize) + bgp_common_header* bgpHdr = getBasicHeader(); + memset(bgpHdr->marker, 0xff, 16 * sizeof(uint8_t)); + bgpHdr->messageType = (uint8_t)getBgpMessageType(); + if (messageLen != 0) { - break; + bgpHdr->length = htobe16((uint16_t)messageLen); } - - resultByteArr[0] = param.type; - resultByteArr[1] = param.length; - if (param.length > 0) + else { - memcpy(resultByteArr + 2*sizeof(uint8_t), param.value, param.length); + bgpHdr->length = m_DataLen; } - - dataLen += curDataSize; - resultByteArr += curDataSize; } - return dataLen; -} + // ~~~~~~~~~~~~~~~~~~~~ + // BgpOpenMessageLayer + // ~~~~~~~~~~~~~~~~~~~~ -void BgpOpenMessageLayer::setBgpId(const IPv4Address& newBgpId) -{ - bgp_open_message* msgHdr = getOpenMsgHeader(); - if (msgHdr == nullptr) + BgpOpenMessageLayer::optional_parameter::optional_parameter(uint8_t typeVal, const std::string& valueAsHexString) { - return; + type = typeVal; + length = hexStringToByteArray(valueAsHexString, value, 32); } - msgHdr->bgpId = newBgpId.toInt(); -} - -void BgpOpenMessageLayer::getOptionalParameters(std::vector& optionalParameters) -{ - bgp_open_message* msgHdr = getOpenMsgHeader(); - if (msgHdr == nullptr || msgHdr->optionalParameterLength == 0) + BgpOpenMessageLayer::BgpOpenMessageLayer(uint16_t myAutonomousSystem, uint16_t holdTime, const IPv4Address& bgpId, + const std::vector& optionalParams) { - return; - } + uint8_t optionalParamsData[1500]; + size_t optionalParamsDataLen = optionalParamsToByteArray(optionalParams, optionalParamsData, 1500); - size_t optionalParamsLen = (size_t)be16toh(msgHdr->optionalParameterLength); + const size_t headerLen = sizeof(bgp_open_message) + optionalParamsDataLen; + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + setBgpFields(headerLen); - if (optionalParamsLen > getHeaderLen() - sizeof(bgp_open_message)) - { - optionalParamsLen = getHeaderLen() - sizeof(bgp_open_message); + bgp_open_message* msgHdr = getOpenMsgHeader(); + msgHdr->version = 4; + msgHdr->myAutonomousSystem = htobe16(myAutonomousSystem); + msgHdr->holdTime = htobe16(holdTime); + msgHdr->bgpId = bgpId.toInt(); + msgHdr->optionalParameterLength = optionalParamsDataLen; + if (optionalParamsDataLen > 0) + { + memcpy(m_Data + sizeof(bgp_open_message), optionalParamsData, optionalParamsDataLen); + } + + m_Protocol = BGP; } - uint8_t* dataPtr = m_Data + sizeof(bgp_open_message); - size_t byteCount = 0; - while (byteCount < optionalParamsLen) + size_t BgpOpenMessageLayer::optionalParamsToByteArray(const std::vector& optionalParams, + uint8_t* resultByteArr, size_t maxByteArrSize) { - optional_parameter op; - op.type = dataPtr[0]; - op.length = dataPtr[1]; - - if (op.length > optionalParamsLen - byteCount) + if (resultByteArr == nullptr || maxByteArrSize == 0) { - PCPP_LOG_ERROR("Optional parameter length is out of bounds: " << (int)op.length); - break; + return 0; } - if (op.length > 0) + size_t dataLen = 0; + + for (const auto& param : optionalParams) { - memcpy(op.value, dataPtr + 2*sizeof(uint8_t), (op.length > 32 ? 32 : op.length)); - } + if (param.length > 32) + { + PCPP_LOG_ERROR("Illegal optional parameter length " << (int)param.length + << ", must be 32 bytes or less"); + break; // illegal value + } - optionalParameters.push_back(op); - size_t totalLen = 2 + (size_t)op.length; - byteCount += totalLen; - dataPtr += totalLen; - } -} + size_t curDataSize = 2 * sizeof(uint8_t) + (size_t)param.length; -size_t BgpOpenMessageLayer::getOptionalParametersLength() -{ - bgp_open_message* msgHdr = getOpenMsgHeader(); - if (msgHdr != nullptr) - { - return (size_t)(msgHdr->optionalParameterLength); - } + if (dataLen + curDataSize > maxByteArrSize) + { + break; + } - return 0; -} + resultByteArr[0] = param.type; + resultByteArr[1] = param.length; + if (param.length > 0) + { + memcpy(resultByteArr + 2 * sizeof(uint8_t), param.value, param.length); + } -bool BgpOpenMessageLayer::setOptionalParameters(const std::vector& optionalParameters) -{ - uint8_t newOptionalParamsData[1500]; - size_t newOptionalParamsDataLen = optionalParamsToByteArray(optionalParameters, newOptionalParamsData, 1500); - size_t curOptionalParamsDataLen = getOptionalParametersLength(); - - if (newOptionalParamsDataLen > curOptionalParamsDataLen) - { - bool res = extendLayer(sizeof(bgp_open_message), newOptionalParamsDataLen - curOptionalParamsDataLen); - if (!res) - { - PCPP_LOG_ERROR("Couldn't extend BGP open layer to include the additional optional parameters"); - return res; + dataLen += curDataSize; + resultByteArr += curDataSize; } + + return dataLen; } - else if (newOptionalParamsDataLen < curOptionalParamsDataLen) + + void BgpOpenMessageLayer::setBgpId(const IPv4Address& newBgpId) { - bool res = shortenLayer(sizeof(bgp_open_message), curOptionalParamsDataLen - newOptionalParamsDataLen); - if (!res) + bgp_open_message* msgHdr = getOpenMsgHeader(); + if (msgHdr == nullptr) { - PCPP_LOG_ERROR("Couldn't shorten BGP open layer to set the right size of the optional parameters data"); - return res; + return; } - } - if (newOptionalParamsDataLen > 0) - { - memcpy(m_Data + sizeof(bgp_open_message), newOptionalParamsData, newOptionalParamsDataLen); + msgHdr->bgpId = newBgpId.toInt(); } - getOpenMsgHeader()->optionalParameterLength = (uint8_t)newOptionalParamsDataLen; - getOpenMsgHeader()->length = htobe16(sizeof(bgp_open_message) + newOptionalParamsDataLen); - - return true; -} - -bool BgpOpenMessageLayer::clearOptionalParameters() -{ - return setOptionalParameters(std::vector()); -} - + void BgpOpenMessageLayer::getOptionalParameters(std::vector& optionalParameters) + { + bgp_open_message* msgHdr = getOpenMsgHeader(); + if (msgHdr == nullptr || msgHdr->optionalParameterLength == 0) + { + return; + } + size_t optionalParamsLen = (size_t)be16toh(msgHdr->optionalParameterLength); -// ~~~~~~~~~~~~~~~~~~~~~ -// BgpUpdateMessageLayer -// ~~~~~~~~~~~~~~~~~~~~~ + if (optionalParamsLen > getHeaderLen() - sizeof(bgp_open_message)) + { + optionalParamsLen = getHeaderLen() - sizeof(bgp_open_message); + } -BgpUpdateMessageLayer::path_attribute::path_attribute(uint8_t flagsVal, uint8_t typeVal, const std::string& dataAsHexString) -{ - flags = flagsVal; - type = typeVal; - length = hexStringToByteArray(dataAsHexString, data, 32); -} - -BgpUpdateMessageLayer::BgpUpdateMessageLayer( - const std::vector& withdrawnRoutes, - const std::vector& pathAttributes, - const std::vector& nlri) -{ - uint8_t withdrawnRoutesData[1500]; - uint8_t pathAttributesData[1500]; - uint8_t nlriData[1500]; - size_t withdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, withdrawnRoutesData, 1500); - size_t pathAttributesDataLen = pathAttributesToByteArray(pathAttributes, pathAttributesData, 1500); - size_t nlriDataLen = prefixAndIPDataToByteArray(nlri, nlriData, 1500); + uint8_t* dataPtr = m_Data + sizeof(bgp_open_message); + size_t byteCount = 0; + while (byteCount < optionalParamsLen) + { + optional_parameter op; + op.type = dataPtr[0]; + op.length = dataPtr[1]; - size_t headerLen = sizeof(bgp_common_header) + 2*sizeof(uint16_t) + withdrawnRoutesDataLen + pathAttributesDataLen + nlriDataLen; - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - setBgpFields(headerLen); + if (op.length > optionalParamsLen - byteCount) + { + PCPP_LOG_ERROR("Optional parameter length is out of bounds: " << (int)op.length); + break; + } - uint8_t* dataPtr = m_Data + sizeof(bgp_common_header); + if (op.length > 0) + { + memcpy(op.value, dataPtr + 2 * sizeof(uint8_t), (op.length > 32 ? 32 : op.length)); + } - // copy withdrawn routes data - uint16_t withdrawnRoutesDataLenBE = htobe16(withdrawnRoutesDataLen); - memcpy(dataPtr, &withdrawnRoutesDataLenBE, sizeof(uint16_t)); - dataPtr += sizeof(uint16_t); - if (withdrawnRoutesDataLen > 0) - { - memcpy(dataPtr, withdrawnRoutesData, withdrawnRoutesDataLen); - dataPtr += withdrawnRoutesDataLen; + optionalParameters.push_back(op); + size_t totalLen = 2 + (size_t)op.length; + byteCount += totalLen; + dataPtr += totalLen; + } } - // copy path attributes data - uint16_t pathAttributesDataLenBE = htobe16(pathAttributesDataLen); - memcpy(dataPtr, &pathAttributesDataLenBE, sizeof(uint16_t)); - dataPtr += sizeof(uint16_t); - if (pathAttributesDataLen > 0) + size_t BgpOpenMessageLayer::getOptionalParametersLength() { - memcpy(dataPtr, pathAttributesData, pathAttributesDataLen); - dataPtr += pathAttributesDataLen; - } + bgp_open_message* msgHdr = getOpenMsgHeader(); + if (msgHdr != nullptr) + { + return (size_t)(msgHdr->optionalParameterLength); + } - // copy nlri data - if (nlriDataLen > 0) - { - memcpy(dataPtr, nlriData, nlriDataLen); + return 0; } - m_Protocol = BGP; -} - -void BgpUpdateMessageLayer::parsePrefixAndIPData(uint8_t* dataPtr, size_t dataLen, std::vector& result) -{ - size_t byteCount = 0; - while (byteCount < dataLen) + bool BgpOpenMessageLayer::setOptionalParameters(const std::vector& optionalParameters) { - prefix_and_ip wr; - wr.prefix = dataPtr[0]; - size_t curByteCount = 1; - if (wr.prefix == 32) - { - uint8_t octets[4] = { dataPtr[1], dataPtr[2], dataPtr[3], dataPtr[4] }; - wr.ipAddr = IPv4Address(octets); - curByteCount += 4; - } - else if (wr.prefix == 24) - { - uint8_t octets[4] = { dataPtr[1], dataPtr[2], dataPtr[3], 0 }; - wr.ipAddr = IPv4Address(octets); - curByteCount += 3; - } - else if (wr.prefix == 16) + uint8_t newOptionalParamsData[1500]; + size_t newOptionalParamsDataLen = optionalParamsToByteArray(optionalParameters, newOptionalParamsData, 1500); + size_t curOptionalParamsDataLen = getOptionalParametersLength(); + + if (newOptionalParamsDataLen > curOptionalParamsDataLen) { - uint8_t octets[4] = { dataPtr[1], dataPtr[2], 0, 0 }; - wr.ipAddr = IPv4Address(octets); - curByteCount += 2; + bool res = extendLayer(sizeof(bgp_open_message), newOptionalParamsDataLen - curOptionalParamsDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't extend BGP open layer to include the additional optional parameters"); + return res; + } } - else if (wr.prefix == 8) + else if (newOptionalParamsDataLen < curOptionalParamsDataLen) { - uint8_t octets[4] = { dataPtr[1], 0, 0, 0 }; - wr.ipAddr = IPv4Address(octets); - curByteCount += 1; + bool res = shortenLayer(sizeof(bgp_open_message), curOptionalParamsDataLen - newOptionalParamsDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't shorten BGP open layer to set the right size of the optional parameters data"); + return res; + } } - else + + if (newOptionalParamsDataLen > 0) { - PCPP_LOG_DEBUG("Illegal prefix value " << (int)wr.prefix); - break; // illegal value + memcpy(m_Data + sizeof(bgp_open_message), newOptionalParamsData, newOptionalParamsDataLen); } - result.push_back(wr); - dataPtr += curByteCount; - byteCount += curByteCount; + getOpenMsgHeader()->optionalParameterLength = (uint8_t)newOptionalParamsDataLen; + getOpenMsgHeader()->length = htobe16(sizeof(bgp_open_message) + newOptionalParamsDataLen); + + return true; } -} -size_t BgpUpdateMessageLayer::prefixAndIPDataToByteArray(const std::vector& prefixAndIpData, uint8_t* resultByteArr, size_t maxByteArrSize) -{ - if (resultByteArr == nullptr || maxByteArrSize == 0) + bool BgpOpenMessageLayer::clearOptionalParameters() { - return 0; + return setOptionalParameters(std::vector()); } - size_t dataLen = 0; + // ~~~~~~~~~~~~~~~~~~~~~ + // BgpUpdateMessageLayer + // ~~~~~~~~~~~~~~~~~~~~~ - for (const auto &prefixAndIp : prefixAndIpData) + BgpUpdateMessageLayer::path_attribute::path_attribute(uint8_t flagsVal, uint8_t typeVal, + const std::string& dataAsHexString) { - uint8_t curData[5]; - curData[0] = prefixAndIp.prefix; - size_t curDataSize = 1; - const uint8_t* octets = prefixAndIp.ipAddr.toBytes(); - if (prefixAndIp.prefix == 32) - { - curDataSize += 4; - curData[1] = octets[0]; - curData[2] = octets[1]; - curData[3] = octets[2]; - curData[4] = octets[3]; - } - else if (prefixAndIp.prefix == 24) - { - curDataSize += 3; - curData[1] = octets[0]; - curData[2] = octets[1]; - curData[3] = octets[2]; - } - else if (prefixAndIp.prefix == 16) - { - curDataSize += 2; - curData[1] = octets[0]; - curData[2] = octets[1]; - } - else if (prefixAndIp.prefix == 8) + flags = flagsVal; + type = typeVal; + length = hexStringToByteArray(dataAsHexString, data, 32); + } + + BgpUpdateMessageLayer::BgpUpdateMessageLayer(const std::vector& withdrawnRoutes, + const std::vector& pathAttributes, + const std::vector& nlri) + { + uint8_t withdrawnRoutesData[1500]; + uint8_t pathAttributesData[1500]; + uint8_t nlriData[1500]; + size_t withdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, withdrawnRoutesData, 1500); + size_t pathAttributesDataLen = pathAttributesToByteArray(pathAttributes, pathAttributesData, 1500); + size_t nlriDataLen = prefixAndIPDataToByteArray(nlri, nlriData, 1500); + + size_t headerLen = sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + withdrawnRoutesDataLen + + pathAttributesDataLen + nlriDataLen; + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + setBgpFields(headerLen); + + uint8_t* dataPtr = m_Data + sizeof(bgp_common_header); + + // copy withdrawn routes data + uint16_t withdrawnRoutesDataLenBE = htobe16(withdrawnRoutesDataLen); + memcpy(dataPtr, &withdrawnRoutesDataLenBE, sizeof(uint16_t)); + dataPtr += sizeof(uint16_t); + if (withdrawnRoutesDataLen > 0) { - curDataSize += 1; - curData[1] = octets[0]; + memcpy(dataPtr, withdrawnRoutesData, withdrawnRoutesDataLen); + dataPtr += withdrawnRoutesDataLen; } - else + + // copy path attributes data + uint16_t pathAttributesDataLenBE = htobe16(pathAttributesDataLen); + memcpy(dataPtr, &pathAttributesDataLenBE, sizeof(uint16_t)); + dataPtr += sizeof(uint16_t); + if (pathAttributesDataLen > 0) { - PCPP_LOG_ERROR("Illegal prefix value " << (int)prefixAndIp.prefix); - break; // illegal value + memcpy(dataPtr, pathAttributesData, pathAttributesDataLen); + dataPtr += pathAttributesDataLen; } - if (dataLen + curDataSize > maxByteArrSize) + // copy nlri data + if (nlriDataLen > 0) { - break; + memcpy(dataPtr, nlriData, nlriDataLen); } - dataLen += curDataSize; + m_Protocol = BGP; + } - memcpy(resultByteArr, curData, curDataSize); - resultByteArr += curDataSize; - } + void BgpUpdateMessageLayer::parsePrefixAndIPData(uint8_t* dataPtr, size_t dataLen, + std::vector& result) + { + size_t byteCount = 0; + while (byteCount < dataLen) + { + prefix_and_ip wr; + wr.prefix = dataPtr[0]; + size_t curByteCount = 1; + if (wr.prefix == 32) + { + uint8_t octets[4] = { dataPtr[1], dataPtr[2], dataPtr[3], dataPtr[4] }; + wr.ipAddr = IPv4Address(octets); + curByteCount += 4; + } + else if (wr.prefix == 24) + { + uint8_t octets[4] = { dataPtr[1], dataPtr[2], dataPtr[3], 0 }; + wr.ipAddr = IPv4Address(octets); + curByteCount += 3; + } + else if (wr.prefix == 16) + { + uint8_t octets[4] = { dataPtr[1], dataPtr[2], 0, 0 }; + wr.ipAddr = IPv4Address(octets); + curByteCount += 2; + } + else if (wr.prefix == 8) + { + uint8_t octets[4] = { dataPtr[1], 0, 0, 0 }; + wr.ipAddr = IPv4Address(octets); + curByteCount += 1; + } + else + { + PCPP_LOG_DEBUG("Illegal prefix value " << (int)wr.prefix); + break; // illegal value + } + + result.push_back(wr); + dataPtr += curByteCount; + byteCount += curByteCount; + } + } + + size_t BgpUpdateMessageLayer::prefixAndIPDataToByteArray(const std::vector& prefixAndIpData, + uint8_t* resultByteArr, size_t maxByteArrSize) + { + if (resultByteArr == nullptr || maxByteArrSize == 0) + { + return 0; + } - return dataLen; -} + size_t dataLen = 0; -size_t BgpUpdateMessageLayer::pathAttributesToByteArray(const std::vector& pathAttributes, uint8_t* resultByteArr, size_t maxByteArrSize) -{ - if (resultByteArr == nullptr || maxByteArrSize == 0) - { - return 0; - } + for (const auto& prefixAndIp : prefixAndIpData) + { + uint8_t curData[5]; + curData[0] = prefixAndIp.prefix; + size_t curDataSize = 1; + const uint8_t* octets = prefixAndIp.ipAddr.toBytes(); + if (prefixAndIp.prefix == 32) + { + curDataSize += 4; + curData[1] = octets[0]; + curData[2] = octets[1]; + curData[3] = octets[2]; + curData[4] = octets[3]; + } + else if (prefixAndIp.prefix == 24) + { + curDataSize += 3; + curData[1] = octets[0]; + curData[2] = octets[1]; + curData[3] = octets[2]; + } + else if (prefixAndIp.prefix == 16) + { + curDataSize += 2; + curData[1] = octets[0]; + curData[2] = octets[1]; + } + else if (prefixAndIp.prefix == 8) + { + curDataSize += 1; + curData[1] = octets[0]; + } + else + { + PCPP_LOG_ERROR("Illegal prefix value " << (int)prefixAndIp.prefix); + break; // illegal value + } - size_t dataLen = 0; + if (dataLen + curDataSize > maxByteArrSize) + { + break; + } + + dataLen += curDataSize; + + memcpy(resultByteArr, curData, curDataSize); + resultByteArr += curDataSize; + } + + return dataLen; + } + + size_t BgpUpdateMessageLayer::pathAttributesToByteArray(const std::vector& pathAttributes, + uint8_t* resultByteArr, size_t maxByteArrSize) + { + if (resultByteArr == nullptr || maxByteArrSize == 0) + { + return 0; + } + + size_t dataLen = 0; - for (const auto &attribute : pathAttributes) - { - if (attribute.length > 32) + for (const auto& attribute : pathAttributes) { - PCPP_LOG_ERROR("Illegal path attribute length " << (int)attribute.length); - break; // illegal value - } + if (attribute.length > 32) + { + PCPP_LOG_ERROR("Illegal path attribute length " << (int)attribute.length); + break; // illegal value + } - size_t curDataSize = 3*sizeof(uint8_t) + (size_t)attribute.length; + size_t curDataSize = 3 * sizeof(uint8_t) + (size_t)attribute.length; - if (dataLen + curDataSize > maxByteArrSize) - { - break; - } + if (dataLen + curDataSize > maxByteArrSize) + { + break; + } - resultByteArr[0] = attribute.flags; - resultByteArr[1] = attribute.type; - resultByteArr[2] = attribute.length; - if (attribute.length > 0) - { - memcpy(resultByteArr + 3*sizeof(uint8_t), attribute.data, attribute.length); + resultByteArr[0] = attribute.flags; + resultByteArr[1] = attribute.type; + resultByteArr[2] = attribute.length; + if (attribute.length > 0) + { + memcpy(resultByteArr + 3 * sizeof(uint8_t), attribute.data, attribute.length); + } + + dataLen += curDataSize; + resultByteArr += curDataSize; } - dataLen += curDataSize; - resultByteArr += curDataSize; + return dataLen; } - return dataLen; -} - -size_t BgpUpdateMessageLayer::getWithdrawnRoutesLength() const -{ - size_t headerLen = getHeaderLen(); - size_t minLen = sizeof(bgp_common_header) + sizeof(uint16_t); - if (headerLen >= minLen) + size_t BgpUpdateMessageLayer::getWithdrawnRoutesLength() const { - uint16_t res = be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header))); - if ((size_t)res > headerLen - minLen) + size_t headerLen = getHeaderLen(); + size_t minLen = sizeof(bgp_common_header) + sizeof(uint16_t); + if (headerLen >= minLen) { - return headerLen - minLen; - } + uint16_t res = be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header))); + if ((size_t)res > headerLen - minLen) + { + return headerLen - minLen; + } - return (size_t)res; - } - - return 0; -} + return (size_t)res; + } -void BgpUpdateMessageLayer::getWithdrawnRoutes(std::vector& withdrawnRoutes) -{ - size_t withdrawnRouteLen = getWithdrawnRoutesLength(); - if (withdrawnRouteLen == 0) - { - return; + return 0; } - uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + sizeof(uint16_t); - parsePrefixAndIPData(dataPtr, withdrawnRouteLen, withdrawnRoutes); -} - -size_t BgpUpdateMessageLayer::getPathAttributesLength() const -{ - size_t headerLen = getHeaderLen(); - size_t minLen = sizeof(bgp_common_header) + 2*sizeof(uint16_t); - if (headerLen >= minLen) + void BgpUpdateMessageLayer::getWithdrawnRoutes(std::vector& withdrawnRoutes) { size_t withdrawnRouteLen = getWithdrawnRoutesLength(); - uint16_t res = be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrawnRouteLen)); - if ((size_t)res > headerLen - minLen - withdrawnRouteLen) + if (withdrawnRouteLen == 0) { - return headerLen - minLen - withdrawnRouteLen; + return; } - return (size_t)res; + uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + sizeof(uint16_t); + parsePrefixAndIPData(dataPtr, withdrawnRouteLen, withdrawnRoutes); } - return 0; -} - -bool BgpUpdateMessageLayer::setWithdrawnRoutes(const std::vector& withdrawnRoutes) -{ - uint8_t newWithdrawnRoutesData[1500]; - size_t newWithdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, newWithdrawnRoutesData, 1500); - size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength(); - - if (newWithdrawnRoutesDataLen > curWithdrawnRoutesDataLen) + size_t BgpUpdateMessageLayer::getPathAttributesLength() const { - bool res = extendLayer(sizeof(bgp_common_header) + sizeof(uint16_t), newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen); - if (!res) + size_t headerLen = getHeaderLen(); + size_t minLen = sizeof(bgp_common_header) + 2 * sizeof(uint16_t); + if (headerLen >= minLen) { - PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional withdrawn routes"); - return res; + size_t withdrawnRouteLen = getWithdrawnRoutesLength(); + uint16_t res = + be16toh(*(uint16_t*)(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrawnRouteLen)); + if ((size_t)res > headerLen - minLen - withdrawnRouteLen) + { + return headerLen - minLen - withdrawnRouteLen; + } + + return (size_t)res; } + + return 0; } - else if (newWithdrawnRoutesDataLen < curWithdrawnRoutesDataLen) + + bool BgpUpdateMessageLayer::setWithdrawnRoutes(const std::vector& withdrawnRoutes) { - bool res = shortenLayer(sizeof(bgp_common_header) + sizeof(uint16_t), curWithdrawnRoutesDataLen - newWithdrawnRoutesDataLen); - if (!res) + uint8_t newWithdrawnRoutesData[1500]; + size_t newWithdrawnRoutesDataLen = prefixAndIPDataToByteArray(withdrawnRoutes, newWithdrawnRoutesData, 1500); + size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength(); + + if (newWithdrawnRoutesDataLen > curWithdrawnRoutesDataLen) { - PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the withdrawn routes data"); - return res; + bool res = extendLayer(sizeof(bgp_common_header) + sizeof(uint16_t), + newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional withdrawn routes"); + return res; + } + } + else if (newWithdrawnRoutesDataLen < curWithdrawnRoutesDataLen) + { + bool res = shortenLayer(sizeof(bgp_common_header) + sizeof(uint16_t), + curWithdrawnRoutesDataLen - newWithdrawnRoutesDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the withdrawn routes data"); + return res; + } } - } - - if (newWithdrawnRoutesDataLen > 0) - { - memcpy(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t), newWithdrawnRoutesData, newWithdrawnRoutesDataLen); - } - getBasicHeader()->length = htobe16(be16toh(getBasicHeader()->length) + newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen); + if (newWithdrawnRoutesDataLen > 0) + { + memcpy(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t), newWithdrawnRoutesData, + newWithdrawnRoutesDataLen); + } - uint16_t newWithdrawnRoutesDataLenBE = htobe16(newWithdrawnRoutesDataLen); - memcpy(m_Data + sizeof(bgp_common_header), &newWithdrawnRoutesDataLenBE, sizeof(uint16_t)); + getBasicHeader()->length = + htobe16(be16toh(getBasicHeader()->length) + newWithdrawnRoutesDataLen - curWithdrawnRoutesDataLen); - return true; -} + uint16_t newWithdrawnRoutesDataLenBE = htobe16(newWithdrawnRoutesDataLen); + memcpy(m_Data + sizeof(bgp_common_header), &newWithdrawnRoutesDataLenBE, sizeof(uint16_t)); -bool BgpUpdateMessageLayer::clearWithdrawnRoutes() -{ - return setWithdrawnRoutes(std::vector()); -} + return true; + } -void BgpUpdateMessageLayer::getPathAttributes(std::vector& pathAttributes) -{ - size_t pathAttrLen = getPathAttributesLength(); - if (pathAttrLen == 0) + bool BgpUpdateMessageLayer::clearWithdrawnRoutes() { - return; + return setWithdrawnRoutes(std::vector()); } - uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + 2*sizeof(uint16_t) + getWithdrawnRoutesLength(); - size_t byteCount = 0; - while (byteCount < pathAttrLen) + void BgpUpdateMessageLayer::getPathAttributes(std::vector& pathAttributes) { - path_attribute pa; - pa.flags = dataPtr[0]; - pa.type = dataPtr[1]; - pa.length = dataPtr[2]; - size_t curByteCount = 3 + pa.length; - if (pa.length > 0) + size_t pathAttrLen = getPathAttributesLength(); + if (pathAttrLen == 0) { - size_t dataLenToCopy = (pa.length <= 32 ? pa.length : 32); - memcpy(pa.data, dataPtr+3, dataLenToCopy); + return; } - pathAttributes.push_back(pa); - dataPtr += curByteCount; - byteCount += curByteCount; - } -} + uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + getWithdrawnRoutesLength(); + size_t byteCount = 0; + while (byteCount < pathAttrLen) + { + path_attribute pa; + pa.flags = dataPtr[0]; + pa.type = dataPtr[1]; + pa.length = dataPtr[2]; + size_t curByteCount = 3 + pa.length; + if (pa.length > 0) + { + size_t dataLenToCopy = (pa.length <= 32 ? pa.length : 32); + memcpy(pa.data, dataPtr + 3, dataLenToCopy); + } -bool BgpUpdateMessageLayer::setPathAttributes(const std::vector& pathAttributes) -{ - uint8_t newPathAttributesData[1500]; - size_t newPathAttributesDataLen = pathAttributesToByteArray(pathAttributes, newPathAttributesData, 1500); - size_t curPathAttributesDataLen = getPathAttributesLength(); - size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength(); + pathAttributes.push_back(pa); + dataPtr += curByteCount; + byteCount += curByteCount; + } + } - if (newPathAttributesDataLen > curPathAttributesDataLen) + bool BgpUpdateMessageLayer::setPathAttributes(const std::vector& pathAttributes) { - bool res = extendLayer(sizeof(bgp_common_header) + 2*sizeof(uint16_t) + curWithdrawnRoutesDataLen, newPathAttributesDataLen - curPathAttributesDataLen); - if (!res) + uint8_t newPathAttributesData[1500]; + size_t newPathAttributesDataLen = pathAttributesToByteArray(pathAttributes, newPathAttributesData, 1500); + size_t curPathAttributesDataLen = getPathAttributesLength(); + size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength(); + + if (newPathAttributesDataLen > curPathAttributesDataLen) { - PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional path attributes"); - return res; + bool res = extendLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen, + newPathAttributesDataLen - curPathAttributesDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional path attributes"); + return res; + } } - } - else if (newPathAttributesDataLen < curPathAttributesDataLen) - { - bool res = shortenLayer(sizeof(bgp_common_header) + 2*sizeof(uint16_t) + curWithdrawnRoutesDataLen, curPathAttributesDataLen - newPathAttributesDataLen); - if (!res) + else if (newPathAttributesDataLen < curPathAttributesDataLen) { - PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the path attributes data"); - return res; + bool res = shortenLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen, + curPathAttributesDataLen - newPathAttributesDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the path attributes data"); + return res; + } } - } - if (newPathAttributesDataLen > 0) - { - memcpy(m_Data + sizeof(bgp_common_header) + 2*sizeof(uint16_t) + curWithdrawnRoutesDataLen, newPathAttributesData, newPathAttributesDataLen); - } + if (newPathAttributesDataLen > 0) + { + memcpy(m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen, + newPathAttributesData, newPathAttributesDataLen); + } - getBasicHeader()->length = htobe16(be16toh(getBasicHeader()->length) + newPathAttributesDataLen - curPathAttributesDataLen); + getBasicHeader()->length = + htobe16(be16toh(getBasicHeader()->length) + newPathAttributesDataLen - curPathAttributesDataLen); - uint16_t newWithdrawnRoutesDataLenBE = htobe16(newPathAttributesDataLen); - memcpy(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + curWithdrawnRoutesDataLen, &newWithdrawnRoutesDataLenBE, sizeof(uint16_t)); + uint16_t newWithdrawnRoutesDataLenBE = htobe16(newPathAttributesDataLen); + memcpy(m_Data + sizeof(bgp_common_header) + sizeof(uint16_t) + curWithdrawnRoutesDataLen, + &newWithdrawnRoutesDataLenBE, sizeof(uint16_t)); - return true; -} + return true; + } -bool BgpUpdateMessageLayer::clearPathAttributes() -{ - return setPathAttributes(std::vector()); -} + bool BgpUpdateMessageLayer::clearPathAttributes() + { + return setPathAttributes(std::vector()); + } -size_t BgpUpdateMessageLayer::getNetworkLayerReachabilityInfoLength() const -{ - size_t headerLen = getHeaderLen(); - size_t minLen = sizeof(bgp_common_header) + 2*sizeof(uint16_t); - if (headerLen >= minLen) + size_t BgpUpdateMessageLayer::getNetworkLayerReachabilityInfoLength() const { - size_t withdrawnRouteLen = getWithdrawnRoutesLength(); - size_t pathAttrLen = getPathAttributesLength(); - int nlriSize = headerLen - minLen - withdrawnRouteLen - pathAttrLen; - if (nlriSize >= 0) + size_t headerLen = getHeaderLen(); + size_t minLen = sizeof(bgp_common_header) + 2 * sizeof(uint16_t); + if (headerLen >= minLen) { - return (size_t)nlriSize; + size_t withdrawnRouteLen = getWithdrawnRoutesLength(); + size_t pathAttrLen = getPathAttributesLength(); + int nlriSize = headerLen - minLen - withdrawnRouteLen - pathAttrLen; + if (nlriSize >= 0) + { + return (size_t)nlriSize; + } + + return 0; } return 0; } - return 0; -} - -void BgpUpdateMessageLayer::getNetworkLayerReachabilityInfo(std::vector& nlri) -{ - size_t nlriSize = getNetworkLayerReachabilityInfoLength(); - if (nlriSize == 0) + void BgpUpdateMessageLayer::getNetworkLayerReachabilityInfo(std::vector& nlri) { - return; - } - - uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + 2*sizeof(uint16_t) + getWithdrawnRoutesLength() + getPathAttributesLength(); - parsePrefixAndIPData(dataPtr, nlriSize, nlri); -} + size_t nlriSize = getNetworkLayerReachabilityInfoLength(); + if (nlriSize == 0) + { + return; + } -bool BgpUpdateMessageLayer::isDataValid(const uint8_t *data, size_t dataSize) -{ - if (dataSize < sizeof(bgp_common_header) + 2*sizeof(uint16_t)) - return false; + uint8_t* dataPtr = m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + getWithdrawnRoutesLength() + + getPathAttributesLength(); + parsePrefixAndIPData(dataPtr, nlriSize, nlri); + } - uint16_t withdrLen = be16toh(*(uint16_t*)(data + sizeof(bgp_common_header))); - if (dataSize < sizeof(bgp_common_header) + 2*sizeof(uint16_t) + withdrLen) - return false; + bool BgpUpdateMessageLayer::isDataValid(const uint8_t* data, size_t dataSize) + { + if (dataSize < sizeof(bgp_common_header) + 2 * sizeof(uint16_t)) + return false; - uint16_t attrLen = be16toh(*(uint16_t*)(data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrLen)); - if (dataSize < sizeof(bgp_common_header) + 2*sizeof(uint16_t) + withdrLen + attrLen) - return false; + uint16_t withdrLen = be16toh(*(uint16_t*)(data + sizeof(bgp_common_header))); + if (dataSize < sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + withdrLen) + return false; - return true; -} + uint16_t attrLen = be16toh(*(uint16_t*)(data + sizeof(bgp_common_header) + sizeof(uint16_t) + withdrLen)); + if (dataSize < sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + withdrLen + attrLen) + return false; -bool BgpUpdateMessageLayer::setNetworkLayerReachabilityInfo(const std::vector& nlri) -{ - uint8_t newNlriData[1500]; - size_t newNlriDataLen = prefixAndIPDataToByteArray(nlri, newNlriData, 1500); - size_t curNlriDataLen = getNetworkLayerReachabilityInfoLength(); - size_t curPathAttributesDataLen = getPathAttributesLength(); - size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength(); + return true; + } - if (newNlriDataLen > curNlriDataLen) + bool BgpUpdateMessageLayer::setNetworkLayerReachabilityInfo(const std::vector& nlri) { - bool res = extendLayer(sizeof(bgp_common_header) + 2*sizeof(uint16_t) + curWithdrawnRoutesDataLen + curPathAttributesDataLen, newNlriDataLen - curNlriDataLen); - if (!res) + uint8_t newNlriData[1500]; + size_t newNlriDataLen = prefixAndIPDataToByteArray(nlri, newNlriData, 1500); + size_t curNlriDataLen = getNetworkLayerReachabilityInfoLength(); + size_t curPathAttributesDataLen = getPathAttributesLength(); + size_t curWithdrawnRoutesDataLen = getWithdrawnRoutesLength(); + + if (newNlriDataLen > curNlriDataLen) { - PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional NLRI data"); - return res; + bool res = extendLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen + + curPathAttributesDataLen, + newNlriDataLen - curNlriDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't extend BGP update layer to include the additional NLRI data"); + return res; + } } - } - else if (newNlriDataLen < curNlriDataLen) - { - bool res = shortenLayer(sizeof(bgp_common_header) + 2*sizeof(uint16_t) + curWithdrawnRoutesDataLen + curPathAttributesDataLen, curNlriDataLen - newNlriDataLen); - if (!res) + else if (newNlriDataLen < curNlriDataLen) { - PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the NLRI data"); - return res; + bool res = shortenLayer(sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen + + curPathAttributesDataLen, + curNlriDataLen - newNlriDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't shorten BGP update layer to set the right size of the NLRI data"); + return res; + } } - } - if (newNlriDataLen > 0) - { - memcpy(m_Data + sizeof(bgp_common_header) + 2*sizeof(uint16_t) + curWithdrawnRoutesDataLen + curPathAttributesDataLen, newNlriData, newNlriDataLen); - } - - getBasicHeader()->length = htobe16(be16toh(getBasicHeader()->length) + newNlriDataLen - curNlriDataLen); - - return true; -} - -bool BgpUpdateMessageLayer::clearNetworkLayerReachabilityInfo() -{ - return setNetworkLayerReachabilityInfo(std::vector()); -} - - - - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// BgpNotificationMessageLayer -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if (newNlriDataLen > 0) + { + memcpy(m_Data + sizeof(bgp_common_header) + 2 * sizeof(uint16_t) + curWithdrawnRoutesDataLen + + curPathAttributesDataLen, + newNlriData, newNlriDataLen); + } -BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode) -{ - initMessageData(errorCode, errorSubCode, nullptr, 0); -} + getBasicHeader()->length = htobe16(be16toh(getBasicHeader()->length) + newNlriDataLen - curNlriDataLen); -BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, size_t notificationDataLen) -{ - initMessageData(errorCode, errorSubCode, notificationData, notificationDataLen); -} - -BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, const std::string& notificationData) -{ - uint8_t notificationDataByteArr[1500]; - size_t notificationDataLen = hexStringToByteArray(notificationData, notificationDataByteArr, 1500); - initMessageData(errorCode, errorSubCode, notificationDataByteArr, notificationDataLen); -} + return true; + } -void BgpNotificationMessageLayer::initMessageData(uint8_t errorCode, uint8_t errorSubCode, const uint8_t* notificationData, size_t notificationDataLen) -{ - size_t headerLen = sizeof(bgp_notification_message); - if (notificationData != nullptr && notificationDataLen > 0) - { - headerLen += notificationDataLen; - } - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - setBgpFields(headerLen); - bgp_notification_message* msgHdr = getNotificationMsgHeader(); - msgHdr->errorCode = errorCode; - msgHdr->errorSubCode = errorSubCode; - memcpy(m_Data + sizeof(bgp_notification_message), notificationData, notificationDataLen); - m_Protocol = BGP; -} - -size_t BgpNotificationMessageLayer::getNotificationDataLen() const -{ - size_t headerLen = getHeaderLen(); - if (headerLen > sizeof(bgp_notification_message)) + bool BgpUpdateMessageLayer::clearNetworkLayerReachabilityInfo() { - return headerLen - sizeof(bgp_notification_message); + return setNetworkLayerReachabilityInfo(std::vector()); } - return 0; -} + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // BgpNotificationMessageLayer + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -uint8_t* BgpNotificationMessageLayer::getNotificationData() const -{ - if (getNotificationDataLen() > 0) + BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode) { - return m_Data + sizeof(bgp_notification_message); + initMessageData(errorCode, errorSubCode, nullptr, 0); } - return nullptr; -} - -std::string BgpNotificationMessageLayer::getNotificationDataAsHexString() const -{ - uint8_t* notificationData = getNotificationData(); - if (notificationData == nullptr) + BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, + const uint8_t* notificationData, + size_t notificationDataLen) { - return ""; + initMessageData(errorCode, errorSubCode, notificationData, notificationDataLen); } - return byteArrayToHexString(notificationData, getNotificationDataLen()); -} - -bool BgpNotificationMessageLayer::setNotificationData(const uint8_t* newNotificationData, size_t newNotificationDataLen) -{ - if (newNotificationData == nullptr) + BgpNotificationMessageLayer::BgpNotificationMessageLayer(uint8_t errorCode, uint8_t errorSubCode, + const std::string& notificationData) { - newNotificationDataLen = 0; + uint8_t notificationDataByteArr[1500]; + size_t notificationDataLen = hexStringToByteArray(notificationData, notificationDataByteArr, 1500); + initMessageData(errorCode, errorSubCode, notificationDataByteArr, notificationDataLen); } - size_t curNotificationDataLen = getNotificationDataLen(); - - if (newNotificationDataLen > curNotificationDataLen) + void BgpNotificationMessageLayer::initMessageData(uint8_t errorCode, uint8_t errorSubCode, + const uint8_t* notificationData, size_t notificationDataLen) { - bool res = extendLayer(sizeof(bgp_notification_message), newNotificationDataLen - curNotificationDataLen); - if (!res) + size_t headerLen = sizeof(bgp_notification_message); + if (notificationData != nullptr && notificationDataLen > 0) { - PCPP_LOG_ERROR("Couldn't extend BGP notification layer to include the additional notification data"); - return res; + headerLen += notificationDataLen; } + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + setBgpFields(headerLen); + bgp_notification_message* msgHdr = getNotificationMsgHeader(); + msgHdr->errorCode = errorCode; + msgHdr->errorSubCode = errorSubCode; + memcpy(m_Data + sizeof(bgp_notification_message), notificationData, notificationDataLen); + m_Protocol = BGP; } - else if (newNotificationDataLen < curNotificationDataLen) + + size_t BgpNotificationMessageLayer::getNotificationDataLen() const { - bool res = shortenLayer(sizeof(bgp_notification_message), curNotificationDataLen - newNotificationDataLen); - if (!res) + size_t headerLen = getHeaderLen(); + if (headerLen > sizeof(bgp_notification_message)) { - PCPP_LOG_ERROR("Couldn't shorten BGP notification layer to set the right size of the notification data"); - return res; + return headerLen - sizeof(bgp_notification_message); } + + return 0; } - if (newNotificationDataLen > 0) + uint8_t* BgpNotificationMessageLayer::getNotificationData() const { - memcpy(m_Data + sizeof(bgp_notification_message), newNotificationData, newNotificationDataLen); + if (getNotificationDataLen() > 0) + { + return m_Data + sizeof(bgp_notification_message); + } + + return nullptr; } - getNotificationMsgHeader()->length = htobe16(sizeof(bgp_notification_message) + newNotificationDataLen); + std::string BgpNotificationMessageLayer::getNotificationDataAsHexString() const + { + uint8_t* notificationData = getNotificationData(); + if (notificationData == nullptr) + { + return ""; + } - return true; -} + return byteArrayToHexString(notificationData, getNotificationDataLen()); + } -bool BgpNotificationMessageLayer::setNotificationData(const std::string& newNotificationDataAsHexString) -{ - if (newNotificationDataAsHexString.empty()) + bool BgpNotificationMessageLayer::setNotificationData(const uint8_t* newNotificationData, + size_t newNotificationDataLen) { - return setNotificationData(nullptr, 0); - } + if (newNotificationData == nullptr) + { + newNotificationDataLen = 0; + } - uint8_t newNotificationData[1500]; - size_t newNotificationDataLen = hexStringToByteArray(newNotificationDataAsHexString, newNotificationData, 1500); + size_t curNotificationDataLen = getNotificationDataLen(); - if (newNotificationDataLen == 0) - { - PCPP_LOG_ERROR("newNotificationDataAsHexString is not a valid hex string"); - return false; + if (newNotificationDataLen > curNotificationDataLen) + { + bool res = extendLayer(sizeof(bgp_notification_message), newNotificationDataLen - curNotificationDataLen); + if (!res) + { + PCPP_LOG_ERROR("Couldn't extend BGP notification layer to include the additional notification data"); + return res; + } + } + else if (newNotificationDataLen < curNotificationDataLen) + { + bool res = shortenLayer(sizeof(bgp_notification_message), curNotificationDataLen - newNotificationDataLen); + if (!res) + { + PCPP_LOG_ERROR( + "Couldn't shorten BGP notification layer to set the right size of the notification data"); + return res; + } + } + + if (newNotificationDataLen > 0) + { + memcpy(m_Data + sizeof(bgp_notification_message), newNotificationData, newNotificationDataLen); + } + + getNotificationMsgHeader()->length = htobe16(sizeof(bgp_notification_message) + newNotificationDataLen); + + return true; } - return setNotificationData(newNotificationData, newNotificationDataLen); -} + bool BgpNotificationMessageLayer::setNotificationData(const std::string& newNotificationDataAsHexString) + { + if (newNotificationDataAsHexString.empty()) + { + return setNotificationData(nullptr, 0); + } + uint8_t newNotificationData[1500]; + size_t newNotificationDataLen = hexStringToByteArray(newNotificationDataAsHexString, newNotificationData, 1500); + if (newNotificationDataLen == 0) + { + PCPP_LOG_ERROR("newNotificationDataAsHexString is not a valid hex string"); + return false; + } -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// BgpKeepaliveMessageLayer -// ~~~~~~~~~~~~~~~~~~~~~~~~ + return setNotificationData(newNotificationData, newNotificationDataLen); + } -BgpKeepaliveMessageLayer::BgpKeepaliveMessageLayer() : BgpLayer() -{ - const size_t headerLen = sizeof(bgp_common_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - setBgpFields(headerLen); - m_Protocol = BGP; -} + // ~~~~~~~~~~~~~~~~~~~~~~~~ + // BgpKeepaliveMessageLayer + // ~~~~~~~~~~~~~~~~~~~~~~~~ + BgpKeepaliveMessageLayer::BgpKeepaliveMessageLayer() : BgpLayer() + { + const size_t headerLen = sizeof(bgp_common_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + setBgpFields(headerLen); + m_Protocol = BGP; + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // BgpRouteRefreshMessageLayer + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// BgpRouteRefreshMessageLayer -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + BgpRouteRefreshMessageLayer::BgpRouteRefreshMessageLayer(uint16_t afi, uint8_t safi) + { + const size_t headerLen = sizeof(bgp_route_refresh_message); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + setBgpFields(headerLen); + bgp_route_refresh_message* msgHdr = getRouteRefreshHeader(); + msgHdr->afi = htobe16(afi); + msgHdr->safi = safi; + m_Protocol = BGP; + } -BgpRouteRefreshMessageLayer::BgpRouteRefreshMessageLayer(uint16_t afi, uint8_t safi) -{ - const size_t headerLen = sizeof(bgp_route_refresh_message); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - setBgpFields(headerLen); - bgp_route_refresh_message* msgHdr = getRouteRefreshHeader(); - msgHdr->afi = htobe16(afi); - msgHdr->safi = safi; - m_Protocol = BGP; -} - -} +} // namespace pcpp diff --git a/Packet++/src/CotpLayer.cpp b/Packet++/src/CotpLayer.cpp index 353ebdfabf..f3ea7975db 100644 --- a/Packet++/src/CotpLayer.cpp +++ b/Packet++/src/CotpLayer.cpp @@ -15,28 +15,49 @@ namespace pcpp m_DataLen = headerLen; m_Data = new uint8_t[headerLen]; memset(m_Data, 0, headerLen); - cotphdr *cotpHdr = (cotphdr *)m_Data; + cotphdr* cotpHdr = (cotphdr*)m_Data; cotpHdr->length = 0x02; cotpHdr->pduType = 0x0f; cotpHdr->tpduNumber = tpduNumber; m_Protocol = COTP; } - std::string CotpLayer::toString() const { return "Cotp Layer"; } + std::string CotpLayer::toString() const + { + return "Cotp Layer"; + } - uint8_t CotpLayer::getLength() const { return getCotpHeader()->length; } + uint8_t CotpLayer::getLength() const + { + return getCotpHeader()->length; + } - uint8_t CotpLayer::getPduType() const { return getCotpHeader()->pduType; } + uint8_t CotpLayer::getPduType() const + { + return getCotpHeader()->pduType; + } - uint8_t CotpLayer::getTpduNumber() const { return getCotpHeader()->tpduNumber; } + uint8_t CotpLayer::getTpduNumber() const + { + return getCotpHeader()->tpduNumber; + } - void CotpLayer::setLength(uint8_t length) const { getCotpHeader()->length = length; } + void CotpLayer::setLength(uint8_t length) const + { + getCotpHeader()->length = length; + } - void CotpLayer::setPduType(uint8_t pduType) const { getCotpHeader()->pduType = pduType; } + void CotpLayer::setPduType(uint8_t pduType) const + { + getCotpHeader()->pduType = pduType; + } - void CotpLayer::setTpduNumber(uint8_t tpduNumber) const { getCotpHeader()->tpduNumber = tpduNumber; } + void CotpLayer::setTpduNumber(uint8_t tpduNumber) const + { + getCotpHeader()->tpduNumber = tpduNumber; + } - bool CotpLayer::isDataValid(const uint8_t *data, size_t dataSize) + bool CotpLayer::isDataValid(const uint8_t* data, size_t dataSize) { if (!data || dataSize < sizeof(cotphdr)) return false; @@ -50,7 +71,7 @@ namespace pcpp if (m_DataLen <= headerLen) return; - uint8_t *payload = m_Data + headerLen; + uint8_t* payload = m_Data + headerLen; size_t payloadLen = m_DataLen - headerLen; if (S7CommLayer::isDataValid(payload, payloadLen)) @@ -58,4 +79,4 @@ namespace pcpp else m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/DhcpLayer.cpp b/Packet++/src/DhcpLayer.cpp index c75c370a08..b75b841295 100644 --- a/Packet++/src/DhcpLayer.cpp +++ b/Packet++/src/DhcpLayer.cpp @@ -8,307 +8,307 @@ namespace pcpp #define DHCP_MAGIC_NUMBER 0x63538263 + DhcpOption DhcpOptionBuilder::build() const + { + size_t recSize = 2 * sizeof(uint8_t) + m_RecValueLen; + uint8_t recType = static_cast(m_RecType); -DhcpOption DhcpOptionBuilder::build() const -{ - size_t recSize = 2 * sizeof(uint8_t) + m_RecValueLen; - uint8_t recType = static_cast(m_RecType); + if ((recType == DHCPOPT_END || recType == DHCPOPT_PAD)) + { + if (m_RecValueLen != 0) + { + PCPP_LOG_ERROR( + "Can't set DHCP END option or DHCP PAD option with size different than 0, tried to set size " + << (int)m_RecValueLen); + return DhcpOption(nullptr); + } + + recSize = sizeof(uint8_t); + } - if ((recType == DHCPOPT_END || recType == DHCPOPT_PAD)) - { - if (m_RecValueLen != 0) + uint8_t* recordBuffer = new uint8_t[recSize]; + memset(recordBuffer, 0, recSize); + recordBuffer[0] = recType; + if (recSize > 1) { - PCPP_LOG_ERROR("Can't set DHCP END option or DHCP PAD option with size different than 0, tried to set size " << (int)m_RecValueLen); - return DhcpOption(nullptr); + recordBuffer[1] = static_cast(m_RecValueLen); + if (m_RecValue != nullptr) + memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); + else + memset(recordBuffer + 2, 0, m_RecValueLen); } - recSize = sizeof(uint8_t); + return DhcpOption(recordBuffer); } - uint8_t* recordBuffer = new uint8_t[recSize]; - memset(recordBuffer, 0, recSize); - recordBuffer[0] = recType; - if (recSize > 1) + DhcpLayer::DhcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { - recordBuffer[1] = static_cast(m_RecValueLen); - if (m_RecValue != nullptr) - memcpy(recordBuffer+2, m_RecValue, m_RecValueLen); - else - memset(recordBuffer+2, 0, m_RecValueLen); + m_Protocol = DHCP; } - return DhcpOption(recordBuffer); -} - -DhcpLayer::DhcpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) -{ - m_Protocol = DHCP; -} - -void DhcpLayer::initDhcpLayer(size_t numOfBytesToAllocate) -{ - m_DataLen = numOfBytesToAllocate; - m_Data = new uint8_t[numOfBytesToAllocate]; - memset(m_Data, 0, numOfBytesToAllocate); - m_Protocol = DHCP; -} - -DhcpLayer::DhcpLayer() : Layer() -{ - initDhcpLayer(sizeof(dhcp_header)); -} - -DhcpLayer::DhcpLayer(DhcpMessageType msgType, const MacAddress& clientMacAddr) : Layer() -{ - initDhcpLayer(sizeof(dhcp_header) + 4*sizeof(uint8_t)); - - setClientHardwareAddress(clientMacAddr); - - uint8_t* msgTypeOptionPtr = m_Data + sizeof(dhcp_header); - msgTypeOptionPtr[0] = (uint8_t)DHCPOPT_DHCP_MESSAGE_TYPE; // option code - msgTypeOptionPtr[1] = 1; // option len - msgTypeOptionPtr[2] = (uint8_t)msgType; // option data - message type - - msgTypeOptionPtr[3] = (uint8_t)DHCPOPT_END; -} - -MacAddress DhcpLayer::getClientHardwareAddress() const -{ - dhcp_header* hdr = getDhcpHeader(); - if (hdr != nullptr && hdr->hardwareType == 1 && hdr->hardwareAddressLength == 6) - return MacAddress(hdr->clientHardwareAddress); + void DhcpLayer::initDhcpLayer(size_t numOfBytesToAllocate) + { + m_DataLen = numOfBytesToAllocate; + m_Data = new uint8_t[numOfBytesToAllocate]; + memset(m_Data, 0, numOfBytesToAllocate); + m_Protocol = DHCP; + } - PCPP_LOG_DEBUG("Hardware type isn't Ethernet or hardware addr len != 6, returning MacAddress:Zero"); + DhcpLayer::DhcpLayer() : Layer() + { + initDhcpLayer(sizeof(dhcp_header)); + } - return MacAddress::Zero; -} + DhcpLayer::DhcpLayer(DhcpMessageType msgType, const MacAddress& clientMacAddr) : Layer() + { + initDhcpLayer(sizeof(dhcp_header) + 4 * sizeof(uint8_t)); -void DhcpLayer::setClientHardwareAddress(const MacAddress& addr) -{ - dhcp_header* hdr = getDhcpHeader(); - hdr->hardwareType = 1; // Ethernet - hdr->hardwareAddressLength = 6; // MAC address length - addr.copyTo(hdr->clientHardwareAddress); -} + setClientHardwareAddress(clientMacAddr); -void DhcpLayer::computeCalculateFields() -{ - dhcp_header* hdr = getDhcpHeader(); + uint8_t* msgTypeOptionPtr = m_Data + sizeof(dhcp_header); + msgTypeOptionPtr[0] = (uint8_t)DHCPOPT_DHCP_MESSAGE_TYPE; // option code + msgTypeOptionPtr[1] = 1; // option len + msgTypeOptionPtr[2] = (uint8_t)msgType; // option data - message type - hdr->magicNumber = DHCP_MAGIC_NUMBER; + msgTypeOptionPtr[3] = (uint8_t)DHCPOPT_END; + } - DhcpMessageType msgType = getMessageType(); - switch(msgType) + MacAddress DhcpLayer::getClientHardwareAddress() const { - case DHCP_DISCOVER: - case DHCP_REQUEST: - case DHCP_DECLINE: - case DHCP_RELEASE: - case DHCP_INFORM: - case DHCP_UNKNOWN_MSG_TYPE: - hdr->opCode = DHCP_BOOTREQUEST; - break; - case DHCP_OFFER: - case DHCP_ACK: - case DHCP_NAK: - hdr->opCode = DHCP_BOOTREPLY; - break; - default: - break; - } + dhcp_header* hdr = getDhcpHeader(); + if (hdr != nullptr && hdr->hardwareType == 1 && hdr->hardwareAddressLength == 6) + return MacAddress(hdr->clientHardwareAddress); - hdr->hardwareType = 1; //Ethernet - hdr->hardwareAddressLength = 6; // MAC address length -} + PCPP_LOG_DEBUG("Hardware type isn't Ethernet or hardware addr len != 6, returning MacAddress:Zero"); -std::string DhcpLayer::toString() const -{ - std::string msgType = "Unknown"; - switch (getMessageType()) - { - case DHCP_DISCOVER: - { - msgType = "Discover"; - break; + return MacAddress::Zero; } - case DHCP_OFFER: - { - msgType = "Offer"; - break; - } - case DHCP_REQUEST: - { - msgType = "Request"; - break; - } - case DHCP_DECLINE: - { - msgType = "Decline"; - break; - } - case DHCP_ACK: - { - msgType = "Acknowledge"; - break; - } - case DHCP_NAK: - { - msgType = "Negative Acknowledge"; - break; - } - case DHCP_RELEASE: + + void DhcpLayer::setClientHardwareAddress(const MacAddress& addr) { - msgType = "Release"; - break; + dhcp_header* hdr = getDhcpHeader(); + hdr->hardwareType = 1; // Ethernet + hdr->hardwareAddressLength = 6; // MAC address length + addr.copyTo(hdr->clientHardwareAddress); } - case DHCP_INFORM: + + void DhcpLayer::computeCalculateFields() { - msgType = "Inform"; - break; - } - default: - break; + dhcp_header* hdr = getDhcpHeader(); - } + hdr->magicNumber = DHCP_MAGIC_NUMBER; - return "DHCP layer (" + msgType + ")"; -} + DhcpMessageType msgType = getMessageType(); + switch (msgType) + { + case DHCP_DISCOVER: + case DHCP_REQUEST: + case DHCP_DECLINE: + case DHCP_RELEASE: + case DHCP_INFORM: + case DHCP_UNKNOWN_MSG_TYPE: + hdr->opCode = DHCP_BOOTREQUEST; + break; + case DHCP_OFFER: + case DHCP_ACK: + case DHCP_NAK: + hdr->opCode = DHCP_BOOTREPLY; + break; + default: + break; + } -DhcpMessageType DhcpLayer::getMessageType() const -{ - DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE); - if (opt.isNull()) - return DHCP_UNKNOWN_MSG_TYPE; + hdr->hardwareType = 1; // Ethernet + hdr->hardwareAddressLength = 6; // MAC address length + } - return (DhcpMessageType)opt.getValueAs(); -} + std::string DhcpLayer::toString() const + { + std::string msgType = "Unknown"; + switch (getMessageType()) + { + case DHCP_DISCOVER: + { + msgType = "Discover"; + break; + } + case DHCP_OFFER: + { + msgType = "Offer"; + break; + } + case DHCP_REQUEST: + { + msgType = "Request"; + break; + } + case DHCP_DECLINE: + { + msgType = "Decline"; + break; + } + case DHCP_ACK: + { + msgType = "Acknowledge"; + break; + } + case DHCP_NAK: + { + msgType = "Negative Acknowledge"; + break; + } + case DHCP_RELEASE: + { + msgType = "Release"; + break; + } + case DHCP_INFORM: + { + msgType = "Inform"; + break; + } + default: + break; + } -bool DhcpLayer::setMessageType(DhcpMessageType msgType) -{ - if (msgType == DHCP_UNKNOWN_MSG_TYPE) - return false; + return "DHCP layer (" + msgType + ")"; + } - DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE); - if (opt.isNull()) + DhcpMessageType DhcpLayer::getMessageType() const { - opt = addOptionAfter(DhcpOptionBuilder(DHCPOPT_DHCP_MESSAGE_TYPE, (uint8_t)msgType), DHCPOPT_UNKNOWN); + DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE); if (opt.isNull()) - return false; - } - - opt.setValue((uint8_t)msgType); - return true; -} + return DHCP_UNKNOWN_MSG_TYPE; -DhcpOption DhcpLayer::getOptionData(DhcpOptionTypes option) const -{ - return m_OptionReader.getTLVRecord((uint8_t)option, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); -} + return (DhcpMessageType)opt.getValueAs(); + } -DhcpOption DhcpLayer::getFirstOptionData() const -{ - return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); -} + bool DhcpLayer::setMessageType(DhcpMessageType msgType) + { + if (msgType == DHCP_UNKNOWN_MSG_TYPE) + return false; -DhcpOption DhcpLayer::getNextOptionData(DhcpOption dhcpOption) const -{ - return m_OptionReader.getNextTLVRecord(dhcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); -} + DhcpOption opt = getOptionData(DHCPOPT_DHCP_MESSAGE_TYPE); + if (opt.isNull()) + { + opt = addOptionAfter(DhcpOptionBuilder(DHCPOPT_DHCP_MESSAGE_TYPE, (uint8_t)msgType), DHCPOPT_UNKNOWN); + if (opt.isNull()) + return false; + } -size_t DhcpLayer::getOptionsCount() const -{ - return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); -} + opt.setValue((uint8_t)msgType); + return true; + } -DhcpOption DhcpLayer::addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset) -{ - DhcpOption newOpt = optionBuilder.build(); + DhcpOption DhcpLayer::getOptionData(DhcpOptionTypes option) const + { + return m_OptionReader.getTLVRecord((uint8_t)option, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); + } - if (newOpt.isNull()) + DhcpOption DhcpLayer::getFirstOptionData() const { - PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOpt.getType()); - return DhcpOption(nullptr); + return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); } - size_t sizeToExtend = newOpt.getTotalSize(); + DhcpOption DhcpLayer::getNextOptionData(DhcpOption dhcpOption) const + { + return m_OptionReader.getNextTLVRecord(dhcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); + } - if (!extendLayer(offset, sizeToExtend)) + size_t DhcpLayer::getOptionsCount() const { - PCPP_LOG_ERROR("Could not extend DhcpLayer in [" << newOpt.getTotalSize() << "] bytes"); - newOpt.purgeRecordData(); - return DhcpOption(nullptr); + return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcp_header)); } - memcpy(m_Data + offset, newOpt.getRecordBasePtr(), newOpt.getTotalSize()); + DhcpOption DhcpLayer::addOptionAt(const DhcpOptionBuilder& optionBuilder, int offset) + { + DhcpOption newOpt = optionBuilder.build(); - uint8_t* newOptPtr = m_Data + offset; + if (newOpt.isNull()) + { + PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOpt.getType()); + return DhcpOption(nullptr); + } - m_OptionReader.changeTLVRecordCount(1); + size_t sizeToExtend = newOpt.getTotalSize(); - newOpt.purgeRecordData(); + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend DhcpLayer in [" << newOpt.getTotalSize() << "] bytes"); + newOpt.purgeRecordData(); + return DhcpOption(nullptr); + } - return DhcpOption(newOptPtr); -} + memcpy(m_Data + offset, newOpt.getRecordBasePtr(), newOpt.getTotalSize()); -DhcpOption DhcpLayer::addOption(const DhcpOptionBuilder& optionBuilder) -{ - int offset = 0; - DhcpOption endOpt = getOptionData(DHCPOPT_END); - if (!endOpt.isNull()) - offset = endOpt.getRecordBasePtr() - m_Data; - else - offset = getHeaderLen(); + uint8_t* newOptPtr = m_Data + offset; - return addOptionAt(optionBuilder, offset); -} + m_OptionReader.changeTLVRecordCount(1); -DhcpOption DhcpLayer::addOptionAfter(const DhcpOptionBuilder& optionBuilder, DhcpOptionTypes prevOption) -{ - int offset = 0; + newOpt.purgeRecordData(); - DhcpOption prevOpt = getOptionData(prevOption); + return DhcpOption(newOptPtr); + } - if (prevOpt.isNull()) + DhcpOption DhcpLayer::addOption(const DhcpOptionBuilder& optionBuilder) { - offset = sizeof(dhcp_header); + int offset = 0; + DhcpOption endOpt = getOptionData(DHCPOPT_END); + if (!endOpt.isNull()) + offset = endOpt.getRecordBasePtr() - m_Data; + else + offset = getHeaderLen(); + + return addOptionAt(optionBuilder, offset); } - else + + DhcpOption DhcpLayer::addOptionAfter(const DhcpOptionBuilder& optionBuilder, DhcpOptionTypes prevOption) { - offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; - } + int offset = 0; - return addOptionAt(optionBuilder, offset); -} + DhcpOption prevOpt = getOptionData(prevOption); -bool DhcpLayer::removeOption(DhcpOptionTypes optionType) -{ - DhcpOption optToRemove = getOptionData(optionType); - if (optToRemove.isNull()) - { - return false; - } + if (prevOpt.isNull()) + { + offset = sizeof(dhcp_header); + } + else + { + offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + } - int offset = optToRemove.getRecordBasePtr() - m_Data; + return addOptionAt(optionBuilder, offset); + } - if (!shortenLayer(offset, optToRemove.getTotalSize())) + bool DhcpLayer::removeOption(DhcpOptionTypes optionType) { - return false; - } + DhcpOption optToRemove = getOptionData(optionType); + if (optToRemove.isNull()) + { + return false; + } - m_OptionReader.changeTLVRecordCount(-1); - return true; -} + int offset = optToRemove.getRecordBasePtr() - m_Data; -bool DhcpLayer::removeAllOptions() -{ - int offset = sizeof(dhcp_header); + if (!shortenLayer(offset, optToRemove.getTotalSize())) + { + return false; + } + + m_OptionReader.changeTLVRecordCount(-1); + return true; + } - if (!shortenLayer(offset, getHeaderLen()-offset)) - return false; + bool DhcpLayer::removeAllOptions() + { + int offset = sizeof(dhcp_header); - m_OptionReader.changeTLVRecordCount(0-getOptionsCount()); - return true; -} + if (!shortenLayer(offset, getHeaderLen() - offset)) + return false; + m_OptionReader.changeTLVRecordCount(0 - getOptionsCount()); + return true; + } -} +} // namespace pcpp diff --git a/Packet++/src/DhcpV6Layer.cpp b/Packet++/src/DhcpV6Layer.cpp index 2d7eac7a5f..ba017106ac 100644 --- a/Packet++/src/DhcpV6Layer.cpp +++ b/Packet++/src/DhcpV6Layer.cpp @@ -5,101 +5,101 @@ #include "GeneralUtils.h" #include "EndianPortable.h" - namespace pcpp { -DhcpV6OptionType DhcpV6Option::getType() const -{ - if (m_Data == nullptr) - return DhcpV6OptionType::DHCPV6_OPT_UNKNOWN; - - uint16_t optionType = be16toh(m_Data->recordType); - if (optionType <= 62 && optionType != 10 && optionType != 35 && optionType != 57 && optionType != 58) - { - return static_cast(optionType); - } - if (optionType == 65 || optionType == 66 || optionType == 68 || optionType == 79 || optionType == 112) + DhcpV6OptionType DhcpV6Option::getType() const { - return static_cast(optionType); + if (m_Data == nullptr) + return DhcpV6OptionType::DHCPV6_OPT_UNKNOWN; + + uint16_t optionType = be16toh(m_Data->recordType); + if (optionType <= 62 && optionType != 10 && optionType != 35 && optionType != 57 && optionType != 58) + { + return static_cast(optionType); + } + if (optionType == 65 || optionType == 66 || optionType == 68 || optionType == 79 || optionType == 112) + { + return static_cast(optionType); + } + + return DHCPV6_OPT_UNKNOWN; } - return DHCPV6_OPT_UNKNOWN; -} + std::string DhcpV6Option::getValueAsHexString() const + { + if (m_Data == nullptr) + return ""; -std::string DhcpV6Option::getValueAsHexString() const -{ - if (m_Data == nullptr) - return ""; + return byteArrayToHexString(m_Data->recordValue, getDataSize()); + } - return byteArrayToHexString(m_Data->recordValue, getDataSize()); -} + size_t DhcpV6Option::getTotalSize() const + { + if (m_Data == nullptr) + return 0; -size_t DhcpV6Option::getTotalSize() const -{ - if (m_Data == nullptr) - return 0; + return 2 * sizeof(uint16_t) + be16toh(m_Data->recordLen); + } - return 2*sizeof(uint16_t) + be16toh(m_Data->recordLen); -} + size_t DhcpV6Option::getDataSize() const + { + if (m_Data == nullptr) + return 0; -size_t DhcpV6Option::getDataSize() const -{ - if (m_Data == nullptr) - return 0; + return static_cast(be16toh(m_Data->recordLen)); + } - return static_cast(be16toh(m_Data->recordLen)); -} + DhcpV6Option DhcpV6OptionBuilder::build() const + { + if (m_RecType == 0) + return DhcpV6Option(nullptr); + + size_t optionSize = 2 * sizeof(uint16_t) + m_RecValueLen; + uint8_t* recordBuffer = new uint8_t[optionSize]; + uint16_t optionTypeVal = htobe16(static_cast(m_RecType)); + uint16_t optionLength = htobe16(static_cast(m_RecValueLen)); + memcpy(recordBuffer, &optionTypeVal, sizeof(uint16_t)); + memcpy(recordBuffer + sizeof(uint16_t), &optionLength, sizeof(uint16_t)); + if (optionSize > 0 && m_RecValue != nullptr) + memcpy(recordBuffer + 2 * sizeof(uint16_t), m_RecValue, m_RecValueLen); + + return DhcpV6Option(recordBuffer); + } -DhcpV6Option DhcpV6OptionBuilder::build() const -{ - if (m_RecType == 0) - return DhcpV6Option(nullptr); - - size_t optionSize = 2 * sizeof(uint16_t) + m_RecValueLen; - uint8_t* recordBuffer = new uint8_t[optionSize]; - uint16_t optionTypeVal = htobe16(static_cast(m_RecType)); - uint16_t optionLength = htobe16(static_cast(m_RecValueLen)); - memcpy(recordBuffer, &optionTypeVal, sizeof(uint16_t)); - memcpy(recordBuffer + sizeof(uint16_t), &optionLength, sizeof(uint16_t)); - if (optionSize > 0 && m_RecValue != nullptr) - memcpy(recordBuffer + 2*sizeof(uint16_t), m_RecValue, m_RecValueLen); - - return DhcpV6Option(recordBuffer); -} - -DhcpV6Layer::DhcpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) -{ - m_Protocol = DHCPv6; -} + DhcpV6Layer::DhcpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = DHCPv6; + } -DhcpV6Layer::DhcpV6Layer(DhcpV6MessageType messageType, uint32_t transactionId) -{ - m_DataLen = sizeof(dhcpv6_header); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = DHCPv6; + DhcpV6Layer::DhcpV6Layer(DhcpV6MessageType messageType, uint32_t transactionId) + { + m_DataLen = sizeof(dhcpv6_header); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = DHCPv6; - setMessageType(messageType); - setTransactionID(transactionId); -} + setMessageType(messageType); + setTransactionID(transactionId); + } -DhcpV6MessageType DhcpV6Layer::getMessageType() const -{ - uint8_t messageType = getDhcpHeader()->messageType; - if (messageType > 13) + DhcpV6MessageType DhcpV6Layer::getMessageType() const { - return DHCPV6_UNKNOWN_MSG_TYPE; - } + uint8_t messageType = getDhcpHeader()->messageType; + if (messageType > 13) + { + return DHCPV6_UNKNOWN_MSG_TYPE; + } - return static_cast(messageType); -} + return static_cast(messageType); + } -std::string DhcpV6Layer::getMessageTypeAsString() const -{ - DhcpV6MessageType messageType = getMessageType(); - switch (messageType) + std::string DhcpV6Layer::getMessageTypeAsString() const { + DhcpV6MessageType messageType = getMessageType(); + switch (messageType) + { case DHCPV6_SOLICIT: return "Solicit"; case DHCPV6_ADVERTISE: @@ -128,147 +128,149 @@ std::string DhcpV6Layer::getMessageTypeAsString() const return "Relay-Reply"; default: return "Unknown"; + } } -} - -void DhcpV6Layer::setMessageType(DhcpV6MessageType messageType) -{ - getDhcpHeader()->messageType = static_cast(messageType); -} - -uint32_t DhcpV6Layer::getTransactionID() const -{ - dhcpv6_header* hdr = getDhcpHeader(); - uint32_t result = hdr->transactionId1 << 16 | hdr->transactionId2 << 8 | hdr->transactionId3; - return result; -} - -void DhcpV6Layer::setTransactionID(uint32_t transactionId) const -{ - dhcpv6_header* hdr = getDhcpHeader(); - hdr->transactionId1 = (transactionId >> 16) & 0xff; - hdr->transactionId2 = (transactionId >> 8) & 0xff; - hdr->transactionId3 = transactionId & 0xff; -} -DhcpV6Option DhcpV6Layer::getFirstOptionData() const -{ - return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcpv6_header)); -} + void DhcpV6Layer::setMessageType(DhcpV6MessageType messageType) + { + getDhcpHeader()->messageType = static_cast(messageType); + } -DhcpV6Option DhcpV6Layer::getNextOptionData(DhcpV6Option dhcpv6Option) const -{ - return m_OptionReader.getNextTLVRecord(dhcpv6Option, getOptionsBasePtr(), getHeaderLen() - sizeof(dhcpv6_header)); -} + uint32_t DhcpV6Layer::getTransactionID() const + { + dhcpv6_header* hdr = getDhcpHeader(); + uint32_t result = hdr->transactionId1 << 16 | hdr->transactionId2 << 8 | hdr->transactionId3; + return result; + } -DhcpV6Option DhcpV6Layer::getOptionData(DhcpV6OptionType option) const -{ - return m_OptionReader.getTLVRecord(static_cast(option), getOptionsBasePtr(), getHeaderLen() - sizeof(dhcpv6_header)); -} + void DhcpV6Layer::setTransactionID(uint32_t transactionId) const + { + dhcpv6_header* hdr = getDhcpHeader(); + hdr->transactionId1 = (transactionId >> 16) & 0xff; + hdr->transactionId2 = (transactionId >> 8) & 0xff; + hdr->transactionId3 = transactionId & 0xff; + } -size_t DhcpV6Layer::getOptionCount() const -{ - return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcpv6_header)); -} + DhcpV6Option DhcpV6Layer::getFirstOptionData() const + { + return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcpv6_header)); + } -DhcpV6Option DhcpV6Layer::addOptionAt(const DhcpV6OptionBuilder& optionBuilder, int offset) -{ - DhcpV6Option newOpt = optionBuilder.build(); - if (newOpt.isNull()) + DhcpV6Option DhcpV6Layer::getNextOptionData(DhcpV6Option dhcpv6Option) const { - PCPP_LOG_ERROR("Cannot build new option"); - return DhcpV6Option(nullptr); + return m_OptionReader.getNextTLVRecord(dhcpv6Option, getOptionsBasePtr(), + getHeaderLen() - sizeof(dhcpv6_header)); } - size_t sizeToExtend = newOpt.getTotalSize(); + DhcpV6Option DhcpV6Layer::getOptionData(DhcpV6OptionType option) const + { + return m_OptionReader.getTLVRecord(static_cast(option), getOptionsBasePtr(), + getHeaderLen() - sizeof(dhcpv6_header)); + } - if (!extendLayer(offset, sizeToExtend)) + size_t DhcpV6Layer::getOptionCount() const { - PCPP_LOG_ERROR("Could not extend DhcpLayer in [" << newOpt.getTotalSize() << "] bytes"); - newOpt.purgeRecordData(); - return DhcpV6Option(nullptr); + return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(dhcpv6_header)); } - memcpy(m_Data + offset, newOpt.getRecordBasePtr(), newOpt.getTotalSize()); + DhcpV6Option DhcpV6Layer::addOptionAt(const DhcpV6OptionBuilder& optionBuilder, int offset) + { + DhcpV6Option newOpt = optionBuilder.build(); + if (newOpt.isNull()) + { + PCPP_LOG_ERROR("Cannot build new option"); + return DhcpV6Option(nullptr); + } - uint8_t* newOptPtr = m_Data + offset; + size_t sizeToExtend = newOpt.getTotalSize(); - m_OptionReader.changeTLVRecordCount(1); + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend DhcpLayer in [" << newOpt.getTotalSize() << "] bytes"); + newOpt.purgeRecordData(); + return DhcpV6Option(nullptr); + } - newOpt.purgeRecordData(); + memcpy(m_Data + offset, newOpt.getRecordBasePtr(), newOpt.getTotalSize()); - return DhcpV6Option(newOptPtr); -} + uint8_t* newOptPtr = m_Data + offset; -DhcpV6Option DhcpV6Layer::addOption(const DhcpV6OptionBuilder& optionBuilder) -{ - return addOptionAt(optionBuilder, getHeaderLen()); -} + m_OptionReader.changeTLVRecordCount(1); -DhcpV6Option DhcpV6Layer::addOptionAfter(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType) -{ - int offset = 0; + newOpt.purgeRecordData(); - DhcpV6Option prevOpt = getOptionData(optionType); + return DhcpV6Option(newOptPtr); + } - if (prevOpt.isNull()) + DhcpV6Option DhcpV6Layer::addOption(const DhcpV6OptionBuilder& optionBuilder) { - PCPP_LOG_ERROR("Option type " << optionType << " doesn't exist in layer"); - return DhcpV6Option(nullptr); + return addOptionAt(optionBuilder, getHeaderLen()); } - offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; - return addOptionAt(optionBuilder, offset); -} -DhcpV6Option DhcpV6Layer::addOptionBefore(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType) -{ - int offset = 0; + DhcpV6Option DhcpV6Layer::addOptionAfter(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType) + { + int offset = 0; - DhcpV6Option nextOpt = getOptionData(optionType); + DhcpV6Option prevOpt = getOptionData(optionType); - if (nextOpt.isNull()) - { - PCPP_LOG_ERROR("Option type " << optionType << " doesn't exist in layer"); - return DhcpV6Option(nullptr); + if (prevOpt.isNull()) + { + PCPP_LOG_ERROR("Option type " << optionType << " doesn't exist in layer"); + return DhcpV6Option(nullptr); + } + offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + return addOptionAt(optionBuilder, offset); } - offset = nextOpt.getRecordBasePtr() - m_Data; - return addOptionAt(optionBuilder, offset); -} - -bool DhcpV6Layer::removeOption(DhcpV6OptionType optionType) -{ - DhcpV6Option optToRemove = getOptionData(optionType); - if (optToRemove.isNull()) + DhcpV6Option DhcpV6Layer::addOptionBefore(const DhcpV6OptionBuilder& optionBuilder, DhcpV6OptionType optionType) { - return false; - } + int offset = 0; - int offset = optToRemove.getRecordBasePtr() - m_Data; + DhcpV6Option nextOpt = getOptionData(optionType); - if (!shortenLayer(offset, optToRemove.getTotalSize())) - { - return false; + if (nextOpt.isNull()) + { + PCPP_LOG_ERROR("Option type " << optionType << " doesn't exist in layer"); + return DhcpV6Option(nullptr); + } + + offset = nextOpt.getRecordBasePtr() - m_Data; + return addOptionAt(optionBuilder, offset); } - m_OptionReader.changeTLVRecordCount(-1); - return true; -} + bool DhcpV6Layer::removeOption(DhcpV6OptionType optionType) + { + DhcpV6Option optToRemove = getOptionData(optionType); + if (optToRemove.isNull()) + { + return false; + } -bool DhcpV6Layer::removeAllOptions() -{ - int offset = sizeof(dhcpv6_header); + int offset = optToRemove.getRecordBasePtr() - m_Data; - if (!shortenLayer(offset, getHeaderLen()-offset)) - return false; + if (!shortenLayer(offset, optToRemove.getTotalSize())) + { + return false; + } - m_OptionReader.changeTLVRecordCount(0-getOptionCount()); - return true; -} + m_OptionReader.changeTLVRecordCount(-1); + return true; + } -std::string DhcpV6Layer::toString() const -{ - return "DHCPv6 Layer, " + getMessageTypeAsString() + " message"; -} + bool DhcpV6Layer::removeAllOptions() + { + int offset = sizeof(dhcpv6_header); + + if (!shortenLayer(offset, getHeaderLen() - offset)) + return false; + + m_OptionReader.changeTLVRecordCount(0 - getOptionCount()); + return true; + } + + std::string DhcpV6Layer::toString() const + { + return "DHCPv6 Layer, " + getMessageTypeAsString() + " message"; + } -} +} // namespace pcpp diff --git a/Packet++/src/DnsLayer.cpp b/Packet++/src/DnsLayer.cpp index 3863c4a7b8..a0e73a81ba 100644 --- a/Packet++/src/DnsLayer.cpp +++ b/Packet++/src/DnsLayer.cpp @@ -12,867 +12,852 @@ namespace pcpp { -// ~~~~~~~~ -// DnsLayer -// ~~~~~~~~ + // ~~~~~~~~ + // DnsLayer + // ~~~~~~~~ -DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : Layer(data, dataLen, prevLayer, packet) -{ - init(0, true); -} - -DnsLayer::DnsLayer() -{ - initNewLayer(0); -} - -DnsLayer::DnsLayer(const DnsLayer& other) : Layer(other) -{ - init(other.m_OffsetAdjustment, true); -} - -DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, size_t offsetAdjustment) - : Layer(data, dataLen, prevLayer, packet) -{ - init(offsetAdjustment, true); -} - -DnsLayer::DnsLayer(size_t offsetAdjustment) -{ - initNewLayer(offsetAdjustment); -} - -DnsLayer& DnsLayer::operator=(const DnsLayer& other) -{ - Layer::operator=(other); - - IDnsResource* curResource = m_ResourceList; - while (curResource != nullptr) + DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { - IDnsResource* temp = curResource->getNextResource(); - delete curResource; - curResource = temp; + init(0, true); } - init(other.m_OffsetAdjustment, true); - - return (*this); -} - -DnsLayer::~DnsLayer() -{ - IDnsResource* curResource = m_ResourceList; - while (curResource != nullptr) + DnsLayer::DnsLayer() { - IDnsResource* nextResource = curResource->getNextResource(); - delete curResource; - curResource = nextResource; + initNewLayer(0); } -} - -void DnsLayer::init(size_t offsetAdjustment, bool callParseResource) -{ - m_OffsetAdjustment = offsetAdjustment; - m_Protocol = DNS; - m_ResourceList = nullptr; - - m_FirstQuery = nullptr; - m_FirstAnswer = nullptr; - m_FirstAuthority = nullptr; - m_FirstAdditional = nullptr; - if (callParseResource) - parseResources(); -} + DnsLayer::DnsLayer(const DnsLayer& other) : Layer(other) + { + init(other.m_OffsetAdjustment, true); + } + DnsLayer::DnsLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, size_t offsetAdjustment) + : Layer(data, dataLen, prevLayer, packet) + { + init(offsetAdjustment, true); + } -void DnsLayer::initNewLayer(size_t offsetAdjustment) -{ - m_OffsetAdjustment = offsetAdjustment; - const size_t headerLen = getBasicHeaderSize(); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); + DnsLayer::DnsLayer(size_t offsetAdjustment) + { + initNewLayer(offsetAdjustment); + } - init(m_OffsetAdjustment, false); -} + DnsLayer& DnsLayer::operator=(const DnsLayer& other) + { + Layer::operator=(other); -size_t DnsLayer::getBasicHeaderSize() -{ - return sizeof(dnshdr) + m_OffsetAdjustment; -} + IDnsResource* curResource = m_ResourceList; + while (curResource != nullptr) + { + IDnsResource* temp = curResource->getNextResource(); + delete curResource; + curResource = temp; + } -dnshdr* DnsLayer::getDnsHeader() const -{ - uint8_t* ptr = m_Data + m_OffsetAdjustment; - return (dnshdr*)ptr; -} + init(other.m_OffsetAdjustment, true); -bool DnsLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource* resource) -{ - if (!Layer::extendLayer(offsetInLayer, numOfBytesToExtend)) - return false; + return (*this); + } - IDnsResource* curResource = resource->getNextResource(); - while (curResource != nullptr) + DnsLayer::~DnsLayer() { - curResource->m_OffsetInLayer += numOfBytesToExtend; - curResource = curResource->getNextResource(); + IDnsResource* curResource = m_ResourceList; + while (curResource != nullptr) + { + IDnsResource* nextResource = curResource->getNextResource(); + delete curResource; + curResource = nextResource; + } } - return true; -} + void DnsLayer::init(size_t offsetAdjustment, bool callParseResource) + { + m_OffsetAdjustment = offsetAdjustment; + m_Protocol = DNS; + m_ResourceList = nullptr; -bool DnsLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource) -{ - if (!Layer::shortenLayer(offsetInLayer, numOfBytesToShorten)) - return false; + m_FirstQuery = nullptr; + m_FirstAnswer = nullptr; + m_FirstAuthority = nullptr; + m_FirstAdditional = nullptr; - IDnsResource* curResource = resource->getNextResource(); - while (curResource != nullptr) - { - curResource->m_OffsetInLayer -= numOfBytesToShorten; - curResource = curResource->getNextResource(); + if (callParseResource) + parseResources(); } - return true; -} + void DnsLayer::initNewLayer(size_t offsetAdjustment) + { + m_OffsetAdjustment = offsetAdjustment; + const size_t headerLen = getBasicHeaderSize(); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); -void DnsLayer::parseResources() -{ - size_t offsetInPacket = getBasicHeaderSize(); - IDnsResource* curResource = m_ResourceList; - - uint16_t numOfQuestions = be16toh(getDnsHeader()->numberOfQuestions); - uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers); - uint16_t numOfAuthority = be16toh(getDnsHeader()->numberOfAuthority); - uint16_t numOfAdditional = be16toh(getDnsHeader()->numberOfAdditional); + init(m_OffsetAdjustment, false); + } - uint32_t numOfOtherResources = numOfQuestions + numOfAnswers + numOfAuthority + numOfAdditional; + size_t DnsLayer::getBasicHeaderSize() + { + return sizeof(dnshdr) + m_OffsetAdjustment; + } - if (numOfOtherResources > 300) + dnshdr* DnsLayer::getDnsHeader() const { - PCPP_LOG_ERROR("DNS layer contains more than 300 resources, probably a bad packet. " - "Skipping parsing DNS resources"); - return; + uint8_t* ptr = m_Data + m_OffsetAdjustment; + return (dnshdr*)ptr; } - for (uint32_t i = 0; i < numOfOtherResources; i++) + bool DnsLayer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend, IDnsResource* resource) { - DnsResourceType resType; - if (numOfQuestions > 0) - { - resType = DnsQueryType; - numOfQuestions--; - } - else if (numOfAnswers > 0) - { - resType = DnsAnswerType; - numOfAnswers--; - } - else if (numOfAuthority > 0) - { - resType = DnsAuthorityType; - numOfAuthority--; - } - else - { - resType = DnsAdditionalType; - numOfAdditional--; - } + if (!Layer::extendLayer(offsetInLayer, numOfBytesToExtend)) + return false; - DnsResource* newResource = nullptr; - DnsQuery* newQuery = nullptr; - IDnsResource* newGenResource = nullptr; - if (resType == DnsQueryType) - { - newQuery = new DnsQuery(this, offsetInPacket); - newGenResource = newQuery; - offsetInPacket += newQuery->getSize(); - } - else + IDnsResource* curResource = resource->getNextResource(); + while (curResource != nullptr) { - newResource = new DnsResource(this, offsetInPacket, resType); - newGenResource = newResource; - offsetInPacket += newResource->getSize(); + curResource->m_OffsetInLayer += numOfBytesToExtend; + curResource = curResource->getNextResource(); } + return true; + } - if (offsetInPacket > m_DataLen) - { - //Parse packet failed, DNS resource is out of bounds. Probably a bad packet - delete newGenResource; - return; - } + bool DnsLayer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten, IDnsResource* resource) + { + if (!Layer::shortenLayer(offsetInLayer, numOfBytesToShorten)) + return false; - // this resource is the first resource - if (m_ResourceList == nullptr) + IDnsResource* curResource = resource->getNextResource(); + while (curResource != nullptr) { - m_ResourceList = newGenResource; - curResource = m_ResourceList; - } - else - { - curResource->setNexResource(newGenResource); + curResource->m_OffsetInLayer -= numOfBytesToShorten; curResource = curResource->getNextResource(); } - - if (resType == DnsQueryType && m_FirstQuery == nullptr) - m_FirstQuery = newQuery; - else if (resType == DnsAnswerType && m_FirstAnswer == nullptr) - m_FirstAnswer = newResource; - else if (resType == DnsAuthorityType && m_FirstAuthority == nullptr) - m_FirstAuthority = newResource; - else if (resType == DnsAdditionalType && m_FirstAdditional == nullptr) - m_FirstAdditional = newResource; + return true; } -} - -IDnsResource* DnsLayer::getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, bool exactMatch) const -{ - size_t index = 0; - while (index < resourceCount) + void DnsLayer::parseResources() { - if (startFrom == nullptr) - return nullptr; + size_t offsetInPacket = getBasicHeaderSize(); + IDnsResource* curResource = m_ResourceList; - std::string resourceName = startFrom->getName(); - if (exactMatch && resourceName == name) - return startFrom; - else if (!exactMatch && resourceName.find(name) != std::string::npos) - return startFrom; + uint16_t numOfQuestions = be16toh(getDnsHeader()->numberOfQuestions); + uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers); + uint16_t numOfAuthority = be16toh(getDnsHeader()->numberOfAuthority); + uint16_t numOfAdditional = be16toh(getDnsHeader()->numberOfAdditional); - startFrom = startFrom->getNextResource(); + uint32_t numOfOtherResources = numOfQuestions + numOfAnswers + numOfAuthority + numOfAdditional; - index++; - } + if (numOfOtherResources > 300) + { + PCPP_LOG_ERROR( + "DNS layer contains more than 300 resources, probably a bad packet. Skipping parsing DNS resources"); + return; + } - return nullptr; -} + for (uint32_t i = 0; i < numOfOtherResources; i++) + { + DnsResourceType resType; + if (numOfQuestions > 0) + { + resType = DnsQueryType; + numOfQuestions--; + } + else if (numOfAnswers > 0) + { + resType = DnsAnswerType; + numOfAnswers--; + } + else if (numOfAuthority > 0) + { + resType = DnsAuthorityType; + numOfAuthority--; + } + else + { + resType = DnsAdditionalType; + numOfAdditional--; + } + + DnsResource* newResource = nullptr; + DnsQuery* newQuery = nullptr; + IDnsResource* newGenResource = nullptr; + if (resType == DnsQueryType) + { + newQuery = new DnsQuery(this, offsetInPacket); + newGenResource = newQuery; + offsetInPacket += newQuery->getSize(); + } + else + { + newResource = new DnsResource(this, offsetInPacket, resType); + newGenResource = newResource; + offsetInPacket += newResource->getSize(); + } + + if (offsetInPacket > m_DataLen) + { + // Parse packet failed, DNS resource is out of bounds. Probably a bad packet + delete newGenResource; + return; + } + + // this resource is the first resource + if (m_ResourceList == nullptr) + { + m_ResourceList = newGenResource; + curResource = m_ResourceList; + } + else + { + curResource->setNexResource(newGenResource); + curResource = curResource->getNextResource(); + } + + if (resType == DnsQueryType && m_FirstQuery == nullptr) + m_FirstQuery = newQuery; + else if (resType == DnsAnswerType && m_FirstAnswer == nullptr) + m_FirstAnswer = newResource; + else if (resType == DnsAuthorityType && m_FirstAuthority == nullptr) + m_FirstAuthority = newResource; + else if (resType == DnsAdditionalType && m_FirstAdditional == nullptr) + m_FirstAdditional = newResource; + } + } -DnsQuery* DnsLayer::getQuery(const std::string& name, bool exactMatch) const -{ - uint16_t numOfQueries = be16toh(getDnsHeader()->numberOfQuestions); - IDnsResource* res = getResourceByName(m_FirstQuery, numOfQueries, name, exactMatch); - if (res != nullptr) - return dynamic_cast(res); - return nullptr; -} + IDnsResource* DnsLayer::getResourceByName(IDnsResource* startFrom, size_t resourceCount, const std::string& name, + bool exactMatch) const + { + size_t index = 0; + while (index < resourceCount) + { + if (startFrom == nullptr) + return nullptr; + std::string resourceName = startFrom->getName(); + if (exactMatch && resourceName == name) + return startFrom; + else if (!exactMatch && resourceName.find(name) != std::string::npos) + return startFrom; -DnsQuery* DnsLayer::getFirstQuery() const -{ - return m_FirstQuery; -} + startFrom = startFrom->getNextResource(); + index++; + } -DnsQuery* DnsLayer::getNextQuery(DnsQuery* query) const -{ - if (query == nullptr - || query->getNextResource() == nullptr - || query->getType() != DnsQueryType - || query->getNextResource()->getType() != DnsQueryType) return nullptr; + } - return (DnsQuery*)(query->getNextResource()); -} - -size_t DnsLayer::getQueryCount() const -{ - return be16toh(getDnsHeader()->numberOfQuestions); -} - -DnsResource* DnsLayer::getAnswer(const std::string& name, bool exactMatch) const -{ - uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers); - IDnsResource* res = getResourceByName(m_FirstAnswer, numOfAnswers, name, exactMatch); - if (res != nullptr) - return dynamic_cast(res); - return nullptr; -} - -DnsResource* DnsLayer::getFirstAnswer() const -{ - return m_FirstAnswer; -} - -DnsResource* DnsLayer::getNextAnswer(DnsResource* answer) const -{ - if (answer == nullptr - || answer->getNextResource() == nullptr - || answer->getType() != DnsAnswerType - || answer->getNextResource()->getType() != DnsAnswerType) + DnsQuery* DnsLayer::getQuery(const std::string& name, bool exactMatch) const + { + uint16_t numOfQueries = be16toh(getDnsHeader()->numberOfQuestions); + IDnsResource* res = getResourceByName(m_FirstQuery, numOfQueries, name, exactMatch); + if (res != nullptr) + return dynamic_cast(res); return nullptr; + } - return (DnsResource*)(answer->getNextResource()); -} - -size_t DnsLayer::getAnswerCount() const -{ - return be16toh(getDnsHeader()->numberOfAnswers); -} - -DnsResource* DnsLayer::getAuthority(const std::string& name, bool exactMatch) const -{ - uint16_t numOfAuthorities = be16toh(getDnsHeader()->numberOfAuthority); - IDnsResource* res = getResourceByName(m_FirstAuthority, numOfAuthorities, name, exactMatch); - if (res != nullptr) - return dynamic_cast(res); - return nullptr; -} - -DnsResource* DnsLayer::getFirstAuthority() const -{ - return m_FirstAuthority; -} - -DnsResource* DnsLayer::getNextAuthority(DnsResource* authority) const -{ - if (authority == nullptr - || authority->getNextResource() == nullptr - || authority->getType() != DnsAuthorityType - || authority->getNextResource()->getType() != DnsAuthorityType) - return nullptr; + DnsQuery* DnsLayer::getFirstQuery() const + { + return m_FirstQuery; + } - return (DnsResource*)(authority->getNextResource()); -} + DnsQuery* DnsLayer::getNextQuery(DnsQuery* query) const + { + if (query == nullptr || query->getNextResource() == nullptr || query->getType() != DnsQueryType || + query->getNextResource()->getType() != DnsQueryType) + return nullptr; -size_t DnsLayer::getAuthorityCount() const -{ - return be16toh(getDnsHeader()->numberOfAuthority); -} + return (DnsQuery*)(query->getNextResource()); + } -DnsResource* DnsLayer::getAdditionalRecord(const std::string& name, bool exactMatch) const -{ - uint16_t numOfAdditionalRecords = be16toh(getDnsHeader()->numberOfAdditional); - IDnsResource* res = getResourceByName(m_FirstAdditional, numOfAdditionalRecords, name, exactMatch); - if (res != nullptr) - return dynamic_cast(res); - return nullptr; -} - -DnsResource* DnsLayer::getFirstAdditionalRecord() const -{ - return m_FirstAdditional; -} + size_t DnsLayer::getQueryCount() const + { + return be16toh(getDnsHeader()->numberOfQuestions); + } -DnsResource* DnsLayer::getNextAdditionalRecord(DnsResource* additionalRecord) const -{ - if (additionalRecord == nullptr - || additionalRecord->getNextResource() == nullptr - || additionalRecord->getType() != DnsAdditionalType - || additionalRecord->getNextResource()->getType() != DnsAdditionalType) + DnsResource* DnsLayer::getAnswer(const std::string& name, bool exactMatch) const + { + uint16_t numOfAnswers = be16toh(getDnsHeader()->numberOfAnswers); + IDnsResource* res = getResourceByName(m_FirstAnswer, numOfAnswers, name, exactMatch); + if (res != nullptr) + return dynamic_cast(res); return nullptr; + } - return (DnsResource*)(additionalRecord->getNextResource()); -} - -size_t DnsLayer::getAdditionalRecordCount() const -{ - return be16toh(getDnsHeader()->numberOfAdditional); -} - -std::string DnsLayer::toString() const -{ - std::ostringstream tidAsString; - tidAsString << be16toh(getDnsHeader()->transactionID); - - std::ostringstream queryCount; - queryCount << getQueryCount(); - - std::ostringstream answerCount; - answerCount << getAnswerCount(); - - std::ostringstream authorityCount; - authorityCount << getAuthorityCount(); - - std::ostringstream additionalCount; - additionalCount << getAdditionalRecordCount(); - - if (getDnsHeader()->queryOrResponse == 1) + DnsResource* DnsLayer::getFirstAnswer() const { - return "DNS query response, ID: " + tidAsString.str() + ";" + - " queries: " + queryCount.str() + - ", answers: " + answerCount.str() + - ", authorities: " + authorityCount.str() + - ", additional record: " + additionalCount.str(); + return m_FirstAnswer; } - else if (getDnsHeader()->queryOrResponse == 0) - { - return "DNS query, ID: " + tidAsString.str() + ";" + - " queries: " + queryCount.str() + - ", answers: " + answerCount.str() + - ", authorities: " + authorityCount.str() + - ", additional record: " + additionalCount.str(); - } - else // not likely - a DNS with no answers and no queries + DnsResource* DnsLayer::getNextAnswer(DnsResource* answer) const { - return "DNS record without queries and answers, ID: " + tidAsString.str() + ";" + - " queries: " + queryCount.str() + - ", answers: " + answerCount.str() + - ", authorities: " + authorityCount.str() + - ", additional record: " + additionalCount.str(); + if (answer == nullptr || answer->getNextResource() == nullptr || answer->getType() != DnsAnswerType || + answer->getNextResource()->getType() != DnsAnswerType) + return nullptr; + + return (DnsResource*)(answer->getNextResource()); } -} -IDnsResource* DnsLayer::getFirstResource(DnsResourceType resType) const -{ - switch (resType) - { - case DnsQueryType: + size_t DnsLayer::getAnswerCount() const { - return m_FirstQuery; + return be16toh(getDnsHeader()->numberOfAnswers); } - case DnsAnswerType: + + DnsResource* DnsLayer::getAuthority(const std::string& name, bool exactMatch) const { - return m_FirstAnswer; + uint16_t numOfAuthorities = be16toh(getDnsHeader()->numberOfAuthority); + IDnsResource* res = getResourceByName(m_FirstAuthority, numOfAuthorities, name, exactMatch); + if (res != nullptr) + return dynamic_cast(res); + return nullptr; } - case DnsAuthorityType: + + DnsResource* DnsLayer::getFirstAuthority() const { return m_FirstAuthority; } - case DnsAdditionalType: + + DnsResource* DnsLayer::getNextAuthority(DnsResource* authority) const { - return m_FirstAdditional; - } - default: - return nullptr; + if (authority == nullptr || authority->getNextResource() == nullptr || + authority->getType() != DnsAuthorityType || authority->getNextResource()->getType() != DnsAuthorityType) + return nullptr; + + return (DnsResource*)(authority->getNextResource()); } -} -void DnsLayer::setFirstResource(DnsResourceType resType, IDnsResource* resource) -{ - switch (resType) - { - case DnsQueryType: + size_t DnsLayer::getAuthorityCount() const { - m_FirstQuery = dynamic_cast(resource); - break; + return be16toh(getDnsHeader()->numberOfAuthority); } - case DnsAnswerType: + + DnsResource* DnsLayer::getAdditionalRecord(const std::string& name, bool exactMatch) const { - m_FirstAnswer = dynamic_cast(resource); - break; + uint16_t numOfAdditionalRecords = be16toh(getDnsHeader()->numberOfAdditional); + IDnsResource* res = getResourceByName(m_FirstAdditional, numOfAdditionalRecords, name, exactMatch); + if (res != nullptr) + return dynamic_cast(res); + return nullptr; } - case DnsAuthorityType: + + DnsResource* DnsLayer::getFirstAdditionalRecord() const { - m_FirstAuthority = dynamic_cast(resource); - break; + return m_FirstAdditional; } - case DnsAdditionalType: + + DnsResource* DnsLayer::getNextAdditionalRecord(DnsResource* additionalRecord) const { - m_FirstAdditional = dynamic_cast(resource); - break; + if (additionalRecord == nullptr || additionalRecord->getNextResource() == nullptr || + additionalRecord->getType() != DnsAdditionalType || + additionalRecord->getNextResource()->getType() != DnsAdditionalType) + return nullptr; + + return (DnsResource*)(additionalRecord->getNextResource()); } - default: - return; + + size_t DnsLayer::getAdditionalRecordCount() const + { + return be16toh(getDnsHeader()->numberOfAdditional); } -} -DnsResource* DnsLayer::addResource(DnsResourceType resType, const std::string& name, DnsType dnsType, DnsClass dnsClass, - uint32_t ttl, IDnsResourceData* data) -{ - // create new query on temporary buffer - uint8_t newResourceRawData[4096]; - memset(newResourceRawData, 0, sizeof(newResourceRawData)); + std::string DnsLayer::toString() const + { + std::ostringstream tidAsString; + tidAsString << be16toh(getDnsHeader()->transactionID); - DnsResource* newResource = new DnsResource(newResourceRawData, resType); + std::ostringstream queryCount; + queryCount << getQueryCount(); - newResource->setDnsClass(dnsClass); + std::ostringstream answerCount; + answerCount << getAnswerCount(); - newResource->setDnsType(dnsType); + std::ostringstream authorityCount; + authorityCount << getAuthorityCount(); - // cannot return false since layer shouldn't be extended or shortened in this stage - newResource->setName(name); + std::ostringstream additionalCount; + additionalCount << getAdditionalRecordCount(); - newResource->setTTL(ttl); + if (getDnsHeader()->queryOrResponse == 1) + { + return "DNS query response, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() + + ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() + + ", additional record: " + additionalCount.str(); + } + else if (getDnsHeader()->queryOrResponse == 0) + { + return "DNS query, ID: " + tidAsString.str() + ";" + " queries: " + queryCount.str() + + ", answers: " + answerCount.str() + ", authorities: " + authorityCount.str() + + ", additional record: " + additionalCount.str(); + } + else // not likely - a DNS with no answers and no queries + { + return "DNS record without queries and answers, ID: " + tidAsString.str() + ";" + + " queries: " + queryCount.str() + ", answers: " + answerCount.str() + + ", authorities: " + authorityCount.str() + ", additional record: " + additionalCount.str(); + } + } - if (!newResource->setData(data)) + IDnsResource* DnsLayer::getFirstResource(DnsResourceType resType) const { - delete newResource; - PCPP_LOG_ERROR("Couldn't set new resource data"); - return nullptr; + switch (resType) + { + case DnsQueryType: + { + return m_FirstQuery; + } + case DnsAnswerType: + { + return m_FirstAnswer; + } + case DnsAuthorityType: + { + return m_FirstAuthority; + } + case DnsAdditionalType: + { + return m_FirstAdditional; + } + default: + return nullptr; + } } - size_t newResourceOffsetInLayer = getBasicHeaderSize(); - IDnsResource* curResource = m_ResourceList; - while (curResource != nullptr && curResource->getType() <= resType) + void DnsLayer::setFirstResource(DnsResourceType resType, IDnsResource* resource) { - newResourceOffsetInLayer += curResource->getSize(); - IDnsResource* nextResource = curResource->getNextResource(); - if (nextResource == nullptr || nextResource->getType() > resType) + switch (resType) + { + case DnsQueryType: + { + m_FirstQuery = dynamic_cast(resource); break; - curResource = nextResource; + } + case DnsAnswerType: + { + m_FirstAnswer = dynamic_cast(resource); + break; + } + case DnsAuthorityType: + { + m_FirstAuthority = dynamic_cast(resource); + break; + } + case DnsAdditionalType: + { + m_FirstAdditional = dynamic_cast(resource); + break; + } + default: + return; + } } - - // set next resource for new resource. This must happen here for extendLayer to succeed - if (curResource != nullptr) + DnsResource* DnsLayer::addResource(DnsResourceType resType, const std::string& name, DnsType dnsType, + DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data) { - if (curResource->getType() > newResource->getType()) - newResource->setNexResource(m_ResourceList); + // create new query on temporary buffer + uint8_t newResourceRawData[4096]; + memset(newResourceRawData, 0, sizeof(newResourceRawData)); + + DnsResource* newResource = new DnsResource(newResourceRawData, resType); + + newResource->setDnsClass(dnsClass); + + newResource->setDnsType(dnsType); + + // cannot return false since layer shouldn't be extended or shortened in this stage + newResource->setName(name); + + newResource->setTTL(ttl); + + if (!newResource->setData(data)) + { + delete newResource; + PCPP_LOG_ERROR("Couldn't set new resource data"); + return nullptr; + } + + size_t newResourceOffsetInLayer = getBasicHeaderSize(); + IDnsResource* curResource = m_ResourceList; + while (curResource != nullptr && curResource->getType() <= resType) + { + newResourceOffsetInLayer += curResource->getSize(); + IDnsResource* nextResource = curResource->getNextResource(); + if (nextResource == nullptr || nextResource->getType() > resType) + break; + curResource = nextResource; + } + + // set next resource for new resource. This must happen here for extendLayer to succeed + if (curResource != nullptr) + { + if (curResource->getType() > newResource->getType()) + newResource->setNexResource(m_ResourceList); + else + newResource->setNexResource(curResource->getNextResource()); + } else - newResource->setNexResource(curResource->getNextResource()); - } - else //curResource != NULL - newResource->setNexResource(m_ResourceList); + { + // curResource != NULL + newResource->setNexResource(m_ResourceList); + } - // extend layer to make room for the new resource - if (!extendLayer(newResourceOffsetInLayer, newResource->getSize(), newResource)) - { - PCPP_LOG_ERROR("Couldn't extend DNS layer, addResource failed"); - delete newResource; - return nullptr; - } + // extend layer to make room for the new resource + if (!extendLayer(newResourceOffsetInLayer, newResource->getSize(), newResource)) + { + PCPP_LOG_ERROR("Couldn't extend DNS layer, addResource failed"); + delete newResource; + return nullptr; + } - // connect the new resource to layer - newResource->setDnsLayer(this, newResourceOffsetInLayer); + // connect the new resource to layer + newResource->setDnsLayer(this, newResourceOffsetInLayer); - // connect the new resource to the layer's resource list - if (curResource != nullptr) - { - curResource->setNexResource(newResource); - // this means the new resource is the first of it's type - if (curResource->getType() < newResource->getType()) + // connect the new resource to the layer's resource list + if (curResource != nullptr) { - setFirstResource(resType, newResource); + curResource->setNexResource(newResource); + // this means the new resource is the first of it's type + if (curResource->getType() < newResource->getType()) + { + setFirstResource(resType, newResource); + } + // this means the new resource should be the first resource in the packet + else if (curResource->getType() > newResource->getType()) + { + m_ResourceList = newResource; + + setFirstResource(resType, newResource); + } } - // this means the new resource should be the first resource in the packet - else if (curResource->getType() > newResource->getType()) + else // curResource != NULL, meaning this is the first resource in layer { m_ResourceList = newResource; setFirstResource(resType, newResource); } - } - else // curResource != NULL, meaning this is the first resource in layer - { - m_ResourceList = newResource; - setFirstResource(resType, newResource); + return newResource; } - return newResource; -} + DnsQuery* DnsLayer::addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass) + { + // create new query on temporary buffer + uint8_t newQueryRawData[256]; + DnsQuery* newQuery = new DnsQuery(newQueryRawData); + newQuery->setDnsClass(dnsClass); + newQuery->setDnsType(dnsType); -DnsQuery* DnsLayer::addQuery(const std::string& name, DnsType dnsType, DnsClass dnsClass) -{ - // create new query on temporary buffer - uint8_t newQueryRawData[256]; - DnsQuery* newQuery = new DnsQuery(newQueryRawData); + // cannot return false since layer shouldn't be extended or shortened in this stage + newQuery->setName(name); - newQuery->setDnsClass(dnsClass); - newQuery->setDnsType(dnsType); + // find the offset in the layer to insert the new query + size_t newQueryOffsetInLayer = getBasicHeaderSize(); + DnsQuery* curQuery = getFirstQuery(); + while (curQuery != nullptr) + { + newQueryOffsetInLayer += curQuery->getSize(); + DnsQuery* nextQuery = getNextQuery(curQuery); + if (nextQuery == nullptr) + break; + curQuery = nextQuery; + } - // cannot return false since layer shouldn't be extended or shortened in this stage - newQuery->setName(name); + // set next resource for new query. This must happen here for extendLayer to succeed + if (curQuery != nullptr) + newQuery->setNexResource(curQuery->getNextResource()); + else + newQuery->setNexResource(m_ResourceList); + // extend layer to make room for the new query + if (!extendLayer(newQueryOffsetInLayer, newQuery->getSize(), newQuery)) + { + PCPP_LOG_ERROR("Couldn't extend DNS layer, addQuery failed"); + delete newQuery; + return nullptr; + } - // find the offset in the layer to insert the new query - size_t newQueryOffsetInLayer = getBasicHeaderSize(); - DnsQuery* curQuery = getFirstQuery(); - while (curQuery != nullptr) - { - newQueryOffsetInLayer += curQuery->getSize(); - DnsQuery* nextQuery = getNextQuery(curQuery); - if (nextQuery == nullptr) - break; - curQuery = nextQuery; + // connect the new query to layer + newQuery->setDnsLayer(this, newQueryOffsetInLayer); - } + // connect the new query to the layer's resource list + if (curQuery != nullptr) + curQuery->setNexResource(newQuery); + else // curQuery == NULL, meaning this is the first query + { + m_ResourceList = newQuery; + m_FirstQuery = newQuery; + } - // set next resource for new query. This must happen here for extendLayer to succeed - if (curQuery != nullptr) - newQuery->setNexResource(curQuery->getNextResource()); - else - newQuery->setNexResource(m_ResourceList); + // increase number of queries + getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() + 1); - // extend layer to make room for the new query - if (!extendLayer(newQueryOffsetInLayer, newQuery->getSize(), newQuery)) - { - PCPP_LOG_ERROR("Couldn't extend DNS layer, addQuery failed"); - delete newQuery; - return nullptr; + return newQuery; } - // connect the new query to layer - newQuery->setDnsLayer(this, newQueryOffsetInLayer); - - // connect the new query to the layer's resource list - if (curQuery != nullptr) - curQuery->setNexResource(newQuery); - else // curQuery == NULL, meaning this is the first query + DnsQuery* DnsLayer::addQuery(DnsQuery* const copyQuery) { - m_ResourceList = newQuery; - m_FirstQuery = newQuery; - } - - // increase number of queries - getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() + 1); - - return newQuery; -} - -DnsQuery* DnsLayer::addQuery(DnsQuery* const copyQuery) -{ - if (copyQuery == nullptr) - return nullptr; - - return addQuery(copyQuery->getName(), copyQuery->getDnsType(), copyQuery->getDnsClass()); -} + if (copyQuery == nullptr) + return nullptr; -bool DnsLayer::removeQuery(const std::string& queryNameToRemove, bool exactMatch) -{ - DnsQuery* queryToRemove = getQuery(queryNameToRemove, exactMatch); - if (queryToRemove == nullptr) - { - PCPP_LOG_DEBUG("Query not found"); - return false; + return addQuery(copyQuery->getName(), copyQuery->getDnsType(), copyQuery->getDnsClass()); } - return removeQuery(queryToRemove); -} - -bool DnsLayer::removeQuery(DnsQuery* queryToRemove) -{ - bool res = removeResource(queryToRemove); - if (res) + bool DnsLayer::removeQuery(const std::string& queryNameToRemove, bool exactMatch) { - // decrease number of query records - getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() - 1); - } + DnsQuery* queryToRemove = getQuery(queryNameToRemove, exactMatch); + if (queryToRemove == nullptr) + { + PCPP_LOG_DEBUG("Query not found"); + return false; + } - return res; -} + return removeQuery(queryToRemove); + } -DnsResource* DnsLayer::addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data) -{ - DnsResource* res = addResource(DnsAnswerType, name, dnsType, dnsClass, ttl, data); - if (res != nullptr) + bool DnsLayer::removeQuery(DnsQuery* queryToRemove) { - // increase number of answer records - getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() + 1); - } + bool res = removeResource(queryToRemove); + if (res) + { + // decrease number of query records + getDnsHeader()->numberOfQuestions = htobe16(getQueryCount() - 1); + } - return res; -} + return res; + } -DnsResource* DnsLayer::addAnswer(DnsResource* const copyAnswer) -{ - if (copyAnswer == nullptr) - return nullptr; + DnsResource* DnsLayer::addAnswer(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, + IDnsResourceData* data) + { + DnsResource* res = addResource(DnsAnswerType, name, dnsType, dnsClass, ttl, data); + if (res != nullptr) + { + // increase number of answer records + getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() + 1); + } - return addAnswer(copyAnswer->getName(), copyAnswer->getDnsType(), copyAnswer->getDnsClass(), copyAnswer->getTTL(), copyAnswer->getData().get()); -} + return res; + } -bool DnsLayer::removeAnswer(const std::string& answerNameToRemove, bool exactMatch) -{ - DnsResource* answerToRemove = getAnswer(answerNameToRemove, exactMatch); - if (answerToRemove == nullptr) + DnsResource* DnsLayer::addAnswer(DnsResource* const copyAnswer) { - PCPP_LOG_DEBUG("Answer record not found"); - return false; - } + if (copyAnswer == nullptr) + return nullptr; - return removeAnswer(answerToRemove); -} + return addAnswer(copyAnswer->getName(), copyAnswer->getDnsType(), copyAnswer->getDnsClass(), + copyAnswer->getTTL(), copyAnswer->getData().get()); + } -bool DnsLayer::removeAnswer(DnsResource* answerToRemove) -{ - bool res = removeResource(answerToRemove); - if (res) + bool DnsLayer::removeAnswer(const std::string& answerNameToRemove, bool exactMatch) { - // decrease number of answer records - getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() - 1); + DnsResource* answerToRemove = getAnswer(answerNameToRemove, exactMatch); + if (answerToRemove == nullptr) + { + PCPP_LOG_DEBUG("Answer record not found"); + return false; + } + + return removeAnswer(answerToRemove); } - return res; -} + bool DnsLayer::removeAnswer(DnsResource* answerToRemove) + { + bool res = removeResource(answerToRemove); + if (res) + { + // decrease number of answer records + getDnsHeader()->numberOfAnswers = htobe16(getAnswerCount() - 1); + } + return res; + } -DnsResource* DnsLayer::addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data) -{ - DnsResource* res = addResource(DnsAuthorityType, name, dnsType, dnsClass, ttl, data); - if (res != nullptr) + DnsResource* DnsLayer::addAuthority(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, + IDnsResourceData* data) { - // increase number of authority records - getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() + 1); - } + DnsResource* res = addResource(DnsAuthorityType, name, dnsType, dnsClass, ttl, data); + if (res != nullptr) + { + // increase number of authority records + getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() + 1); + } - return res; -} + return res; + } -DnsResource* DnsLayer::addAuthority(DnsResource* const copyAuthority) -{ - if (copyAuthority == nullptr) - return nullptr; + DnsResource* DnsLayer::addAuthority(DnsResource* const copyAuthority) + { + if (copyAuthority == nullptr) + return nullptr; - return addAuthority(copyAuthority->getName(), copyAuthority->getDnsType(), copyAuthority->getDnsClass(), copyAuthority->getTTL(), copyAuthority->getData().get()); -} + return addAuthority(copyAuthority->getName(), copyAuthority->getDnsType(), copyAuthority->getDnsClass(), + copyAuthority->getTTL(), copyAuthority->getData().get()); + } -bool DnsLayer::removeAuthority(const std::string& authorityNameToRemove, bool exactMatch) -{ - DnsResource* authorityToRemove = getAuthority(authorityNameToRemove, exactMatch); - if (authorityToRemove == nullptr) + bool DnsLayer::removeAuthority(const std::string& authorityNameToRemove, bool exactMatch) { - PCPP_LOG_DEBUG("Authority not found"); - return false; - } + DnsResource* authorityToRemove = getAuthority(authorityNameToRemove, exactMatch); + if (authorityToRemove == nullptr) + { + PCPP_LOG_DEBUG("Authority not found"); + return false; + } - return removeAuthority(authorityToRemove); -} + return removeAuthority(authorityToRemove); + } -bool DnsLayer::removeAuthority(DnsResource* authorityToRemove) -{ - bool res = removeResource(authorityToRemove); - if (res) + bool DnsLayer::removeAuthority(DnsResource* authorityToRemove) { - // decrease number of authority records - getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() - 1); + bool res = removeResource(authorityToRemove); + if (res) + { + // decrease number of authority records + getDnsHeader()->numberOfAuthority = htobe16(getAuthorityCount() - 1); + } + + return res; } - return res; -} + DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, + uint32_t ttl, IDnsResourceData* data) + { + DnsResource* res = addResource(DnsAdditionalType, name, dnsType, dnsClass, ttl, data); + if (res != nullptr) + { + // increase number of authority records + getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() + 1); + } + return res; + } -DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, DnsClass dnsClass, uint32_t ttl, IDnsResourceData* data) -{ - DnsResource* res = addResource(DnsAdditionalType, name, dnsType, dnsClass, ttl, data); - if (res != nullptr) + DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, + uint32_t customData2, IDnsResourceData* data) { - // increase number of authority records - getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() + 1); - } + DnsResource* res = addAdditionalRecord(name, dnsType, DNS_CLASS_ANY, customData2, data); + if (res != nullptr) + { + res->setCustomDnsClass(customData1); + } - return res; -} + return res; + } -DnsResource* DnsLayer::addAdditionalRecord(const std::string& name, DnsType dnsType, uint16_t customData1, uint32_t customData2, IDnsResourceData* data) -{ - DnsResource* res = addAdditionalRecord(name, dnsType, DNS_CLASS_ANY, customData2, data); - if (res != nullptr) + DnsResource* DnsLayer::addAdditionalRecord(DnsResource* const copyAdditionalRecord) { - res->setCustomDnsClass(customData1); - } + if (copyAdditionalRecord == nullptr) + return nullptr; - return res; -} + return addAdditionalRecord(copyAdditionalRecord->getName(), copyAdditionalRecord->getDnsType(), + copyAdditionalRecord->getCustomDnsClass(), copyAdditionalRecord->getTTL(), + copyAdditionalRecord->getData().get()); + } -DnsResource* DnsLayer::addAdditionalRecord(DnsResource* const copyAdditionalRecord) -{ - if (copyAdditionalRecord == nullptr) - return nullptr; + bool DnsLayer::removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch) + { + DnsResource* additionalRecordToRemove = getAdditionalRecord(additionalRecordNameToRemove, exactMatch); + if (additionalRecordToRemove == nullptr) + { + PCPP_LOG_DEBUG("Additional record not found"); + return false; + } - return addAdditionalRecord(copyAdditionalRecord->getName(), copyAdditionalRecord->getDnsType(), copyAdditionalRecord->getCustomDnsClass(), copyAdditionalRecord->getTTL(), copyAdditionalRecord->getData().get()); -} + return removeAdditionalRecord(additionalRecordToRemove); + } -bool DnsLayer::removeAdditionalRecord(const std::string& additionalRecordNameToRemove, bool exactMatch) -{ - DnsResource* additionalRecordToRemove = getAdditionalRecord(additionalRecordNameToRemove, exactMatch); - if (additionalRecordToRemove == nullptr) + bool DnsLayer::removeAdditionalRecord(DnsResource* additionalRecordToRemove) { - PCPP_LOG_DEBUG("Additional record not found"); - return false; - } + bool res = removeResource(additionalRecordToRemove); + if (res) + { + // decrease number of additional records + getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() - 1); + } - return removeAdditionalRecord(additionalRecordToRemove); -} + return res; + } -bool DnsLayer::removeAdditionalRecord(DnsResource* additionalRecordToRemove) -{ - bool res = removeResource(additionalRecordToRemove); - if (res) + bool DnsLayer::removeResource(IDnsResource* resourceToRemove) { - // decrease number of additional records - getDnsHeader()->numberOfAdditional = htobe16(getAdditionalRecordCount() - 1); - } + if (resourceToRemove == nullptr) + { + PCPP_LOG_DEBUG("resourceToRemove cannot be NULL"); + return false; + } - return res; -} + // find the resource preceding resourceToRemove + IDnsResource* prevResource = m_ResourceList; -bool DnsLayer::removeResource(IDnsResource* resourceToRemove) -{ - if (resourceToRemove == nullptr) - { - PCPP_LOG_DEBUG("resourceToRemove cannot be NULL"); - return false; - } + if (m_ResourceList != resourceToRemove) + { + while (prevResource != nullptr) + { + IDnsResource* temp = prevResource->getNextResource(); + if (temp == resourceToRemove) + break; + + prevResource = temp; + } + } - // find the resource preceding resourceToRemove - IDnsResource* prevResource = m_ResourceList; + if (prevResource == nullptr) + { + PCPP_LOG_DEBUG("Resource not found"); + return false; + } - if (m_ResourceList != resourceToRemove) - { - while (prevResource != nullptr) + // shorten the layer and fix offset in layer for all next DNS resources in the packet + if (!shortenLayer(resourceToRemove->m_OffsetInLayer, resourceToRemove->getSize(), resourceToRemove)) { - IDnsResource* temp = prevResource->getNextResource(); - if (temp == resourceToRemove) - break; + PCPP_LOG_ERROR("Couldn't shorten the DNS layer, resource cannot be removed"); + return false; + } - prevResource = temp; + // remove resourceToRemove from the resources linked list + if (m_ResourceList != resourceToRemove) + { + prevResource->setNexResource(resourceToRemove->getNextResource()); + } + else + { + m_ResourceList = resourceToRemove->getNextResource(); } - } - if (prevResource == nullptr) - { - PCPP_LOG_DEBUG("Resource not found"); - return false; - } + // check whether resourceToRemove was the first of its type + if (getFirstResource(resourceToRemove->getType()) == resourceToRemove) + { + IDnsResource* nextResource = resourceToRemove->getNextResource(); + if (nextResource != nullptr && nextResource->getType() == resourceToRemove->getType()) + setFirstResource(resourceToRemove->getType(), nextResource); + else + setFirstResource(resourceToRemove->getType(), nullptr); + } - // shorten the layer and fix offset in layer for all next DNS resources in the packet - if (!shortenLayer(resourceToRemove->m_OffsetInLayer, resourceToRemove->getSize(), resourceToRemove)) - { - PCPP_LOG_ERROR("Couldn't shorten the DNS layer, resource cannot be removed"); - return false; + // free resourceToRemove memory + delete resourceToRemove; + + return true; } - // remove resourceToRemove from the resources linked list - if (m_ResourceList != resourceToRemove) + // ~~~~~~~~~~~~~~~ + // DnsOverTcpLayer + // ~~~~~~~~~~~~~~~ + + uint16_t DnsOverTcpLayer::getTcpMessageLength() { - prevResource->setNexResource(resourceToRemove->getNextResource()); + return be16toh(*(uint16_t*)m_Data); } - else + + void DnsOverTcpLayer::setTcpMessageLength(uint16_t value) { - m_ResourceList = resourceToRemove->getNextResource(); + ((uint16_t*)m_Data)[0] = htobe16(value); } - // check whether resourceToRemove was the first of its type - if (getFirstResource(resourceToRemove->getType()) == resourceToRemove) + void DnsOverTcpLayer::computeCalculateFields() { - IDnsResource* nextResource = resourceToRemove->getNextResource(); - if (nextResource != nullptr && nextResource->getType() == resourceToRemove->getType()) - setFirstResource(resourceToRemove->getType(), nextResource); - else - setFirstResource(resourceToRemove->getType(), nullptr); + setTcpMessageLength(m_DataLen - sizeof(uint16_t)); } - // free resourceToRemove memory - delete resourceToRemove; - - return true; -} - - -// ~~~~~~~~~~~~~~~ -// DnsOverTcpLayer -// ~~~~~~~~~~~~~~~ - -uint16_t DnsOverTcpLayer::getTcpMessageLength() -{ - return be16toh(*(uint16_t*)m_Data); -} - -void DnsOverTcpLayer::setTcpMessageLength(uint16_t value) -{ - ((uint16_t*)m_Data)[0] = htobe16(value); -} - -void DnsOverTcpLayer::computeCalculateFields() -{ - setTcpMessageLength(m_DataLen - sizeof(uint16_t)); -} - -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/DnsResource.cpp b/Packet++/src/DnsResource.cpp index c1f97041a2..619a69b1e9 100644 --- a/Packet++/src/DnsResource.cpp +++ b/Packet++/src/DnsResource.cpp @@ -9,451 +9,450 @@ namespace pcpp { -IDnsResource::IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer) - : m_DnsLayer(dnsLayer), m_OffsetInLayer(offsetInLayer), m_NextResource(nullptr), m_ExternalRawData(nullptr) -{ - char decodedName[4096]; - m_NameLength = decodeName((const char*)getRawData(), decodedName); - if (m_NameLength > 0) - m_DecodedName = decodedName; -} - -IDnsResource::IDnsResource(uint8_t* emptyRawData) - : m_DnsLayer(nullptr), m_OffsetInLayer(0), m_NextResource(nullptr), m_DecodedName(""), m_NameLength(0), m_ExternalRawData(emptyRawData) -{ -} - -uint8_t* IDnsResource::getRawData() const -{ - if (m_DnsLayer == nullptr) - return m_ExternalRawData; - - return m_DnsLayer->m_Data + m_OffsetInLayer; -} - -static size_t cleanup(char* resultPtr, char* result, size_t encodedNameLength) -{ - // remove the last "." - if (resultPtr > result) + IDnsResource::IDnsResource(DnsLayer* dnsLayer, size_t offsetInLayer) + : m_DnsLayer(dnsLayer), m_OffsetInLayer(offsetInLayer), m_NextResource(nullptr), m_ExternalRawData(nullptr) { - result[resultPtr - result - 1] = 0; + char decodedName[4096]; + m_NameLength = decodeName((const char*)getRawData(), decodedName); + if (m_NameLength > 0) + m_DecodedName = decodedName; } - if (resultPtr - result < 256) + IDnsResource::IDnsResource(uint8_t* emptyRawData) + : m_DnsLayer(nullptr), m_OffsetInLayer(0), m_NextResource(nullptr), m_DecodedName(""), m_NameLength(0), + m_ExternalRawData(emptyRawData) + {} + + uint8_t* IDnsResource::getRawData() const { - // add the last '\0' to encodedNameLength - resultPtr[0] = 0; - encodedNameLength++; - } + if (m_DnsLayer == nullptr) + return m_ExternalRawData; - return encodedNameLength; -} + return m_DnsLayer->m_Data + m_OffsetInLayer; + } -size_t IDnsResource::decodeName(const char* encodedName, char* result, int iteration) -{ - size_t encodedNameLength = 0; - size_t decodedNameLength = 0; - char* resultPtr = result; - resultPtr[0] = 0; + static size_t cleanup(char* resultPtr, char* result, size_t encodedNameLength) + { + // remove the last "." + if (resultPtr > result) + { + result[resultPtr - result - 1] = 0; + } - size_t curOffsetInLayer = (uint8_t*)encodedName - m_DnsLayer->m_Data; - if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) - return encodedNameLength; + if (resultPtr - result < 256) + { + // add the last '\0' to encodedNameLength + resultPtr[0] = 0; + encodedNameLength++; + } - if (iteration > 20) - { return encodedNameLength; } - uint8_t wordLength = encodedName[0]; - - // A string to parse - while (wordLength != 0) + size_t IDnsResource::decodeName(const char* encodedName, char* result, int iteration) { - // A pointer to another place in the packet - if ((wordLength & 0xc0) == 0xc0) - { - if (curOffsetInLayer + 2 > m_DnsLayer->m_DataLen || encodedNameLength > 255) - return cleanup(resultPtr, result, encodedNameLength); + size_t encodedNameLength = 0; + size_t decodedNameLength = 0; + char* resultPtr = result; + resultPtr[0] = 0; - uint16_t offsetInLayer = (wordLength & 0x3f)*256 + (0xFF & encodedName[1]) + m_DnsLayer->m_OffsetAdjustment; - if (offsetInLayer < sizeof(dnshdr) || offsetInLayer >= m_DnsLayer->m_DataLen) - { - PCPP_LOG_ERROR("DNS parsing error: name pointer is illegal"); - return 0; - } + size_t curOffsetInLayer = (uint8_t*)encodedName - m_DnsLayer->m_Data; + if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) + return encodedNameLength; - char tempResult[4096]; - memset(tempResult, 0, sizeof(tempResult)); - int i = 0; - decodeName((const char*)(m_DnsLayer->m_Data + offsetInLayer), tempResult, iteration+1); - while (tempResult[i] != 0 && decodedNameLength < 255) - { - resultPtr[0] = tempResult[i++]; - resultPtr++; - decodedNameLength++; - } + if (iteration > 20) + { + return encodedNameLength; + } - resultPtr[0] = 0; + uint8_t wordLength = encodedName[0]; - // in this case the length of the pointer is: 1 byte for 0xc0 + 1 byte for the offset itself - return encodedNameLength + sizeof(uint16_t); - } - else + // A string to parse + while (wordLength != 0) { - // return if next word would be outside of the DNS layer or overflow the buffer behind resultPtr - if (curOffsetInLayer + wordLength + 1 > m_DnsLayer->m_DataLen || encodedNameLength + wordLength > 255) + // A pointer to another place in the packet + if ((wordLength & 0xc0) == 0xc0) { - // add the last '\0' to the decoded string - if (encodedNameLength == 256) + if (curOffsetInLayer + 2 > m_DnsLayer->m_DataLen || encodedNameLength > 255) + return cleanup(resultPtr, result, encodedNameLength); + + uint16_t offsetInLayer = + (wordLength & 0x3f) * 256 + (0xFF & encodedName[1]) + m_DnsLayer->m_OffsetAdjustment; + if (offsetInLayer < sizeof(dnshdr) || offsetInLayer >= m_DnsLayer->m_DataLen) { - resultPtr--; - // cppcheck-suppress unreadVariable - decodedNameLength--; + PCPP_LOG_ERROR("DNS parsing error: name pointer is illegal"); + return 0; } - else + + char tempResult[4096]; + memset(tempResult, 0, sizeof(tempResult)); + int i = 0; + decodeName((const char*)(m_DnsLayer->m_Data + offsetInLayer), tempResult, iteration + 1); + while (tempResult[i] != 0 && decodedNameLength < 255) { - encodedNameLength++; + resultPtr[0] = tempResult[i++]; + resultPtr++; + decodedNameLength++; } resultPtr[0] = 0; - return encodedNameLength; - } - - memcpy(resultPtr, encodedName+1, wordLength); - resultPtr += wordLength; - resultPtr[0] = '.'; - resultPtr++; - decodedNameLength += wordLength + 1; - encodedName += wordLength + 1; - encodedNameLength += wordLength + 1; - - curOffsetInLayer = (uint8_t*)encodedName - m_DnsLayer->m_Data; - if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) + // in this case the length of the pointer is: 1 byte for 0xc0 + 1 byte for the offset itself + return encodedNameLength + sizeof(uint16_t); + } + else { - // add the last '\0' to the decoded string - if (encodedNameLength == 256) + // return if next word would be outside of the DNS layer or overflow the buffer behind resultPtr + if (curOffsetInLayer + wordLength + 1 > m_DnsLayer->m_DataLen || encodedNameLength + wordLength > 255) { - // cppcheck-suppress unreadVariable - decodedNameLength--; - resultPtr--; + // add the last '\0' to the decoded string + if (encodedNameLength == 256) + { + resultPtr--; + // cppcheck-suppress unreadVariable + decodedNameLength--; + } + else + { + encodedNameLength++; + } + + resultPtr[0] = 0; + return encodedNameLength; } - else + + memcpy(resultPtr, encodedName + 1, wordLength); + resultPtr += wordLength; + resultPtr[0] = '.'; + resultPtr++; + decodedNameLength += wordLength + 1; + encodedName += wordLength + 1; + encodedNameLength += wordLength + 1; + + curOffsetInLayer = (uint8_t*)encodedName - m_DnsLayer->m_Data; + if (curOffsetInLayer + 1 > m_DnsLayer->m_DataLen) { - encodedNameLength++; + // add the last '\0' to the decoded string + if (encodedNameLength == 256) + { + // cppcheck-suppress unreadVariable + decodedNameLength--; + resultPtr--; + } + else + { + encodedNameLength++; + } + + resultPtr[0] = 0; + return encodedNameLength; } - resultPtr[0] = 0; - return encodedNameLength; + wordLength = encodedName[0]; } - - wordLength = encodedName[0]; } - } - - return cleanup(resultPtr, result, encodedNameLength); -} + return cleanup(resultPtr, result, encodedNameLength); + } -void IDnsResource::encodeName(const std::string& decodedName, char* result, size_t& resultLen) -{ - resultLen = 0; - std::stringstream strstream(decodedName); - std::string word; - while (getline(strstream, word, '.')) + void IDnsResource::encodeName(const std::string& decodedName, char* result, size_t& resultLen) { - // pointer to a different hostname in the packet - if (word[0] == '#') + resultLen = 0; + std::stringstream strstream(decodedName); + std::string word; + while (getline(strstream, word, '.')) { - // convert the number from string to int - std::stringstream stream(word.substr(1)); - int pointerInPacket = 0; - stream >> pointerInPacket; - - // verify it's indeed a number and that is in the range of [0-255] - if (stream.fail() || pointerInPacket < 0 || pointerInPacket > 0xff) + // pointer to a different hostname in the packet + if (word[0] == '#') { - PCPP_LOG_ERROR("Error encoding the string '" << decodedName << "'"); - return; + // convert the number from string to int + std::stringstream stream(word.substr(1)); + int pointerInPacket = 0; + stream >> pointerInPacket; + + // verify it's indeed a number and that is in the range of [0-255] + if (stream.fail() || pointerInPacket < 0 || pointerInPacket > 0xff) + { + PCPP_LOG_ERROR("Error encoding the string '" << decodedName << "'"); + return; + } + + // set the pointer to the encoded string result + result[0] = (uint8_t)0xc0; + result[1] = (uint8_t)pointerInPacket; + result += 2; + resultLen += 2; + return; // pointer always comes last } - // set the pointer to the encoded string result - result[0] = (uint8_t)0xc0; - result[1] = (uint8_t)pointerInPacket; - result += 2; - resultLen += 2; - return; // pointer always comes last + result[0] = word.length(); + result++; + memcpy(result, word.c_str(), word.length()); + result += word.length(); + resultLen += word.length() + 1; } - result[0] = word.length(); - result++; - memcpy(result, word.c_str(), word.length()); - result += word.length(); - resultLen += word.length() + 1; + result[0] = 0; + resultLen++; } - result[0] = 0; - resultLen++; -} - - -DnsType IDnsResource::getDnsType() const -{ - uint16_t dnsType = *(uint16_t*)(getRawData() + m_NameLength); - return (DnsType)be16toh(dnsType); -} + DnsType IDnsResource::getDnsType() const + { + uint16_t dnsType = *(uint16_t*)(getRawData() + m_NameLength); + return (DnsType)be16toh(dnsType); + } -void IDnsResource::setDnsType(DnsType newType) -{ - uint16_t newTypeAsInt = htobe16((uint16_t)newType); - memcpy(getRawData() + m_NameLength, &newTypeAsInt, sizeof(uint16_t)); -} + void IDnsResource::setDnsType(DnsType newType) + { + uint16_t newTypeAsInt = htobe16((uint16_t)newType); + memcpy(getRawData() + m_NameLength, &newTypeAsInt, sizeof(uint16_t)); + } -DnsClass IDnsResource::getDnsClass() const -{ - uint16_t dnsClass = *(uint16_t*)(getRawData() + m_NameLength + sizeof(uint16_t)); - return (DnsClass)be16toh(dnsClass); -} + DnsClass IDnsResource::getDnsClass() const + { + uint16_t dnsClass = *(uint16_t*)(getRawData() + m_NameLength + sizeof(uint16_t)); + return (DnsClass)be16toh(dnsClass); + } -void IDnsResource::setDnsClass(DnsClass newClass) -{ - uint16_t newClassAsInt = htobe16((uint16_t)newClass); - memcpy(getRawData() + m_NameLength + sizeof(uint16_t), &newClassAsInt, sizeof(uint16_t)); -} + void IDnsResource::setDnsClass(DnsClass newClass) + { + uint16_t newClassAsInt = htobe16((uint16_t)newClass); + memcpy(getRawData() + m_NameLength + sizeof(uint16_t), &newClassAsInt, sizeof(uint16_t)); + } -bool IDnsResource::setName(const std::string& newName) -{ - char encodedName[4096]; - size_t encodedNameLen = 0; - encodeName(newName, encodedName, encodedNameLen); - if (m_DnsLayer != nullptr) + bool IDnsResource::setName(const std::string& newName) { - if (encodedNameLen > m_NameLength) + char encodedName[4096]; + size_t encodedNameLen = 0; + encodeName(newName, encodedName, encodedNameLen); + if (m_DnsLayer != nullptr) { - if (!m_DnsLayer->extendLayer(m_OffsetInLayer, encodedNameLen-m_NameLength, this)) + if (encodedNameLen > m_NameLength) { - PCPP_LOG_ERROR("Couldn't set name for DNS query, unable to extend layer"); - return false; + if (!m_DnsLayer->extendLayer(m_OffsetInLayer, encodedNameLen - m_NameLength, this)) + { + PCPP_LOG_ERROR("Couldn't set name for DNS query, unable to extend layer"); + return false; + } } - } - else if (encodedNameLen < m_NameLength) - { - if (!m_DnsLayer->shortenLayer(m_OffsetInLayer, m_NameLength-encodedNameLen, this)) + else if (encodedNameLen < m_NameLength) { - PCPP_LOG_ERROR("Couldn't set name for DNS query, unable to shorten layer"); - return false; + if (!m_DnsLayer->shortenLayer(m_OffsetInLayer, m_NameLength - encodedNameLen, this)) + { + PCPP_LOG_ERROR("Couldn't set name for DNS query, unable to shorten layer"); + return false; + } } } - } - else - { - size_t size = getSize(); - char* tempData = new char[size]; - memcpy(tempData, m_ExternalRawData, size); - memcpy(m_ExternalRawData + encodedNameLen, tempData, size); - delete[] tempData; - } - - memcpy(getRawData(), encodedName, encodedNameLen); - m_NameLength = encodedNameLen; - m_DecodedName = newName; - - return true; -} - -void IDnsResource::setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer) -{ - memcpy(dnsLayer->m_Data + offsetInLayer, m_ExternalRawData, getSize()); - m_DnsLayer = dnsLayer; - m_OffsetInLayer = offsetInLayer; - m_ExternalRawData = nullptr; -} - -uint32_t DnsResource::getTTL() const -{ - uint32_t ttl = *(uint32_t*)(getRawData() + m_NameLength + 2*sizeof(uint16_t)); - return be32toh(ttl); -} - -void DnsResource::setTTL(uint32_t newTTL) -{ - newTTL = htobe32(newTTL); - memcpy(getRawData() + m_NameLength + 2*sizeof(uint16_t), &newTTL, sizeof(uint32_t)); -} - -size_t DnsResource::getDataLength() const -{ - - size_t sizeToRead = m_NameLength + 2*sizeof(uint16_t) + sizeof(uint32_t); - - // Heap buffer overflow may occur here, check boundary of m_DnsLayer->m_Data first - // Due to dataLength which is uint16_t, here m_DnsLayer->m_Data must have at least 2 bytes to read - if (m_DnsLayer && m_OffsetInLayer + sizeToRead >= m_DnsLayer->m_DataLen - 1) - { - return 0; - } - - uint16_t dataLength = *(uint16_t*)(getRawData() + sizeToRead); - return be16toh(dataLength); -} + else + { + size_t size = getSize(); + char* tempData = new char[size]; + memcpy(tempData, m_ExternalRawData, size); + memcpy(m_ExternalRawData + encodedNameLen, tempData, size); + delete[] tempData; + } -DnsResourceDataPtr DnsResource::getData() const -{ - uint8_t* resourceRawData = getRawData() + m_NameLength + 3*sizeof(uint16_t) + sizeof(uint32_t); - size_t dataLength = getDataLength(); + memcpy(getRawData(), encodedName, encodedNameLen); + m_NameLength = encodedNameLen; + m_DecodedName = newName; - switch (getDnsType()) - { - case DNS_TYPE_A: - { - return DnsResourceDataPtr(new IPv4DnsResourceData(resourceRawData, dataLength)); + return true; } - case DNS_TYPE_AAAA: + void IDnsResource::setDnsLayer(DnsLayer* dnsLayer, size_t offsetInLayer) { - return DnsResourceDataPtr(new IPv6DnsResourceData(resourceRawData, dataLength)); + memcpy(dnsLayer->m_Data + offsetInLayer, m_ExternalRawData, getSize()); + m_DnsLayer = dnsLayer; + m_OffsetInLayer = offsetInLayer; + m_ExternalRawData = nullptr; } - case DNS_TYPE_NS: - case DNS_TYPE_CNAME: - case DNS_TYPE_DNAM: - case DNS_TYPE_PTR: + uint32_t DnsResource::getTTL() const { - return DnsResourceDataPtr(new StringDnsResourceData(resourceRawData, dataLength, const_cast(static_cast(this)))); + uint32_t ttl = *(uint32_t*)(getRawData() + m_NameLength + 2 * sizeof(uint16_t)); + return be32toh(ttl); } - case DNS_TYPE_MX: + void DnsResource::setTTL(uint32_t newTTL) { - return DnsResourceDataPtr(new MxDnsResourceData(resourceRawData, dataLength, const_cast(static_cast(this)))); + newTTL = htobe32(newTTL); + memcpy(getRawData() + m_NameLength + 2 * sizeof(uint16_t), &newTTL, sizeof(uint32_t)); } - default: + size_t DnsResource::getDataLength() const { - return DnsResourceDataPtr(new GenericDnsResourceData(resourceRawData, dataLength)); - } - } -} - -size_t DnsResource::getDataOffset() const -{ - return (size_t)(m_OffsetInLayer + m_NameLength + 3*sizeof(uint16_t) + sizeof(uint32_t)); -} + size_t sizeToRead = m_NameLength + 2 * sizeof(uint16_t) + sizeof(uint32_t); -bool DnsResource::setData(IDnsResourceData* data) -{ - // convert data to byte array according to the DNS type - size_t dataLength = 0; - uint8_t dataAsByteArr[4096]; + // Heap buffer overflow may occur here, check boundary of m_DnsLayer->m_Data first + // Due to dataLength which is uint16_t, here m_DnsLayer->m_Data must have at least 2 bytes to read + if (m_DnsLayer && m_OffsetInLayer + sizeToRead >= m_DnsLayer->m_DataLen - 1) + { + return 0; + } - if (data == nullptr) - { - PCPP_LOG_ERROR("Given data is NULL"); - return false; + uint16_t dataLength = *(uint16_t*)(getRawData() + sizeToRead); + return be16toh(dataLength); } - switch (getDnsType()) - { - case DNS_TYPE_A: + DnsResourceDataPtr DnsResource::getData() const { - if (!data->isTypeOf()) + uint8_t* resourceRawData = getRawData() + m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t); + size_t dataLength = getDataLength(); + + switch (getDnsType()) { - PCPP_LOG_ERROR("DNS record is of type A but given data isn't of type IPv4DnsResourceData"); - return false; + case DNS_TYPE_A: + { + return DnsResourceDataPtr(new IPv4DnsResourceData(resourceRawData, dataLength)); } - break; - } - case DNS_TYPE_AAAA: - { - if (!data->isTypeOf()) + case DNS_TYPE_AAAA: { - PCPP_LOG_ERROR("DNS record is of type AAAA but given data isn't of type IPv6DnsResourceData"); - return false; + return DnsResourceDataPtr(new IPv6DnsResourceData(resourceRawData, dataLength)); } - break; - } - case DNS_TYPE_NS: - case DNS_TYPE_CNAME: - case DNS_TYPE_DNAM: - case DNS_TYPE_PTR: - { - if (!data->isTypeOf()) + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAM: + case DNS_TYPE_PTR: { - PCPP_LOG_ERROR("DNS record is of type NS, CNAME, DNAM or PTR but given data isn't of type StringDnsResourceData"); - return false; + return DnsResourceDataPtr(new StringDnsResourceData( + resourceRawData, dataLength, const_cast(static_cast(this)))); } - break; - } - case DNS_TYPE_MX: - { - if (!data->isTypeOf()) + case DNS_TYPE_MX: { - PCPP_LOG_ERROR("DNS record is of type MX but given data isn't of type MxDnsResourceData"); - return false; + return DnsResourceDataPtr(new MxDnsResourceData( + resourceRawData, dataLength, const_cast(static_cast(this)))); } - break; - } - default: - { - // do nothing + default: + { + return DnsResourceDataPtr(new GenericDnsResourceData(resourceRawData, dataLength)); + } + } } + size_t DnsResource::getDataOffset() const + { + return (size_t)(m_OffsetInLayer + m_NameLength + 3 * sizeof(uint16_t) + sizeof(uint32_t)); } - // convert the IDnsResourceData to byte array - if (!data->toByteArr(dataAsByteArr, dataLength, this)) + bool DnsResource::setData(IDnsResourceData* data) { - PCPP_LOG_ERROR("Cannot convert DNS resource data to byte array, data is probably invalid"); - return false; - } + // convert data to byte array according to the DNS type + size_t dataLength = 0; + uint8_t dataAsByteArr[4096]; - size_t dataLengthOffset = m_NameLength + (2*sizeof(uint16_t)) + sizeof(uint32_t); - size_t dataOffset = dataLengthOffset + sizeof(uint16_t); + if (data == nullptr) + { + PCPP_LOG_ERROR("Given data is NULL"); + return false; + } - if (m_DnsLayer != nullptr) - { - size_t curLength = getDataLength(); - if (dataLength > curLength) + switch (getDnsType()) + { + case DNS_TYPE_A: { - if (!m_DnsLayer->extendLayer(m_OffsetInLayer + dataOffset, dataLength-curLength, this)) + if (!data->isTypeOf()) { - PCPP_LOG_ERROR("Couldn't set data for DNS query, unable to extend layer"); + PCPP_LOG_ERROR("DNS record is of type A but given data isn't of type IPv4DnsResourceData"); return false; } + break; } - else if (dataLength < curLength) + + case DNS_TYPE_AAAA: { - if (!m_DnsLayer->shortenLayer(m_OffsetInLayer + dataOffset, curLength-dataLength, this)) + if (!data->isTypeOf()) { - PCPP_LOG_ERROR("Couldn't set data for DNS query, unable to shorten layer"); + PCPP_LOG_ERROR("DNS record is of type AAAA but given data isn't of type IPv6DnsResourceData"); return false; } + break; } - } - // write data to resource - memcpy(getRawData() + dataOffset, dataAsByteArr, dataLength); - //update data length in resource - dataLength = htobe16((uint16_t)dataLength); - memcpy(getRawData() + dataLengthOffset, &dataLength, sizeof(uint16_t)); + case DNS_TYPE_NS: + case DNS_TYPE_CNAME: + case DNS_TYPE_DNAM: + case DNS_TYPE_PTR: + { + if (!data->isTypeOf()) + { + PCPP_LOG_ERROR( + "DNS record is of type NS, CNAME, DNAM or PTR but given data isn't of type StringDnsResourceData"); + return false; + } + break; + } - return true; -} + case DNS_TYPE_MX: + { + if (!data->isTypeOf()) + { + PCPP_LOG_ERROR("DNS record is of type MX but given data isn't of type MxDnsResourceData"); + return false; + } + break; + } -uint16_t DnsResource::getCustomDnsClass() const -{ - uint16_t value = *(uint16_t*)(getRawData() + m_NameLength + sizeof(uint16_t)); - return be16toh(value); -} + default: + { + // do nothing + } + } -void DnsResource::setCustomDnsClass(uint16_t customValue) -{ - memcpy(getRawData() + m_NameLength + sizeof(uint16_t), &customValue, sizeof(uint16_t)); -} + // convert the IDnsResourceData to byte array + if (!data->toByteArr(dataAsByteArr, dataLength, this)) + { + PCPP_LOG_ERROR("Cannot convert DNS resource data to byte array, data is probably invalid"); + return false; + } + + size_t dataLengthOffset = m_NameLength + (2 * sizeof(uint16_t)) + sizeof(uint32_t); + size_t dataOffset = dataLengthOffset + sizeof(uint16_t); + + if (m_DnsLayer != nullptr) + { + size_t curLength = getDataLength(); + if (dataLength > curLength) + { + if (!m_DnsLayer->extendLayer(m_OffsetInLayer + dataOffset, dataLength - curLength, this)) + { + PCPP_LOG_ERROR("Couldn't set data for DNS query, unable to extend layer"); + return false; + } + } + else if (dataLength < curLength) + { + if (!m_DnsLayer->shortenLayer(m_OffsetInLayer + dataOffset, curLength - dataLength, this)) + { + PCPP_LOG_ERROR("Couldn't set data for DNS query, unable to shorten layer"); + return false; + } + } + } + + // write data to resource + memcpy(getRawData() + dataOffset, dataAsByteArr, dataLength); + // update data length in resource + dataLength = htobe16((uint16_t)dataLength); + memcpy(getRawData() + dataLengthOffset, &dataLength, sizeof(uint16_t)); + + return true; + } + + uint16_t DnsResource::getCustomDnsClass() const + { + uint16_t value = *(uint16_t*)(getRawData() + m_NameLength + sizeof(uint16_t)); + return be16toh(value); + } + + void DnsResource::setCustomDnsClass(uint16_t customValue) + { + memcpy(getRawData() + m_NameLength + sizeof(uint16_t), &customValue, sizeof(uint16_t)); + } -} +} // namespace pcpp diff --git a/Packet++/src/DnsResourceData.cpp b/Packet++/src/DnsResourceData.cpp index 26a0f79012..4de1e4e572 100644 --- a/Packet++/src/DnsResourceData.cpp +++ b/Packet++/src/DnsResourceData.cpp @@ -11,208 +11,208 @@ namespace pcpp { -size_t IDnsResourceData::decodeName(const char* encodedName, char* result, IDnsResource* dnsResource) const -{ - if (dnsResource == nullptr) + size_t IDnsResourceData::decodeName(const char* encodedName, char* result, IDnsResource* dnsResource) const { - PCPP_LOG_ERROR("Cannot decode name, DNS resource object is NULL"); - return 0; - } + if (dnsResource == nullptr) + { + PCPP_LOG_ERROR("Cannot decode name, DNS resource object is NULL"); + return 0; + } - return dnsResource->decodeName(encodedName, result); -} + return dnsResource->decodeName(encodedName, result); + } -void IDnsResourceData::encodeName(const std::string& decodedName, char* result, size_t& resultLen, IDnsResource* dnsResource) const -{ - if (dnsResource == nullptr) + void IDnsResourceData::encodeName(const std::string& decodedName, char* result, size_t& resultLen, + IDnsResource* dnsResource) const { - PCPP_LOG_ERROR("Cannot encode name, DNS resource object is NULL"); - return; - } + if (dnsResource == nullptr) + { + PCPP_LOG_ERROR("Cannot encode name, DNS resource object is NULL"); + return; + } - dnsResource->encodeName(decodedName, result, resultLen); -} + dnsResource->encodeName(decodedName, result, resultLen); + } + StringDnsResourceData::StringDnsResourceData(const uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource) + { + if (dataPtr && dataLen > 0) + { + char tempResult[4096]; + decodeName((const char*)dataPtr, tempResult, dnsResource); + m_Data = tempResult; + } + else + PCPP_LOG_ERROR("Cannot decode name, dataPtr is NULL or length is 0"); + } -StringDnsResourceData::StringDnsResourceData(const uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource) -{ - if (dataPtr && dataLen > 0) + bool StringDnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const { - char tempResult[4096]; - decodeName((const char*)dataPtr, tempResult, dnsResource); - m_Data = tempResult; + encodeName(m_Data, (char*)arr, arrLength, dnsResource); + return true; } - else - PCPP_LOG_ERROR("Cannot decode name, dataPtr is NULL or length is 0"); -} -bool StringDnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const -{ - encodeName(m_Data, (char*)arr, arrLength, dnsResource); - return true; -} + IPv4DnsResourceData::IPv4DnsResourceData(const uint8_t* dataPtr, size_t dataLen) + { + if (dataLen != 4) + { + PCPP_LOG_ERROR("DNS type is A but resource length is not 4 - malformed data"); + return; + } + + uint32_t addrAsInt = *(uint32_t*)dataPtr; + m_Data = IPv4Address(addrAsInt); + } -IPv4DnsResourceData::IPv4DnsResourceData(const uint8_t* dataPtr, size_t dataLen) -{ - if (dataLen != 4) + bool IPv4DnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource*) const { - PCPP_LOG_ERROR("DNS type is A but resource length is not 4 - malformed data"); - return; + arrLength = sizeof(uint32_t); + memcpy(arr, m_Data.toBytes(), sizeof(uint32_t)); + return true; } - uint32_t addrAsInt = *(uint32_t*)dataPtr; - m_Data = IPv4Address(addrAsInt); -} + IPv6DnsResourceData::IPv6DnsResourceData(const uint8_t* dataPtr, size_t dataLen) + { + if (dataLen != 16) + { + PCPP_LOG_ERROR("DNS type is AAAA but resource length is not 16 - malformed data"); + return; + } -bool IPv4DnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource*) const -{ - arrLength = sizeof(uint32_t); - memcpy(arr, m_Data.toBytes(), sizeof(uint32_t)); - return true; -} + m_Data = IPv6Address(dataPtr); + } -IPv6DnsResourceData::IPv6DnsResourceData(const uint8_t* dataPtr, size_t dataLen) -{ - if (dataLen != 16) + bool IPv6DnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource*) const { - PCPP_LOG_ERROR("DNS type is AAAA but resource length is not 16 - malformed data"); - return; + arrLength = 16; + m_Data.copyTo(arr); + return true; } - m_Data = IPv6Address(dataPtr); -} - -bool IPv6DnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource*) const -{ - arrLength = 16; - m_Data.copyTo(arr); - return true; -} + MxDnsResourceData::MxDnsResourceData(uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource) + { + if (dataPtr && dataLen > 0) + { + uint16_t preference = be16toh(*(uint16_t*)dataPtr); + char tempMX[4096]; + decodeName((const char*)(dataPtr + sizeof(preference)), tempMX, dnsResource); + m_Data.preference = preference; + m_Data.mailExchange = tempMX; + } + else + PCPP_LOG_ERROR("Cannot decode name, dataPtr is NULL or length is 0"); + } -MxDnsResourceData::MxDnsResourceData(uint8_t* dataPtr, size_t dataLen, IDnsResource* dnsResource) -{ - if (dataPtr && dataLen > 0) + MxDnsResourceData::MxDnsResourceData(const uint16_t& preference, const std::string& mailExchange) { - uint16_t preference = be16toh(*(uint16_t*)dataPtr); - char tempMX[4096]; - decodeName((const char*)(dataPtr + sizeof(preference)), tempMX, dnsResource); m_Data.preference = preference; - m_Data.mailExchange = tempMX; + m_Data.mailExchange = mailExchange; } - else - PCPP_LOG_ERROR("Cannot decode name, dataPtr is NULL or length is 0"); -} - -MxDnsResourceData::MxDnsResourceData(const uint16_t& preference, const std::string& mailExchange) -{ - m_Data.preference = preference; - m_Data.mailExchange = mailExchange; -} -bool MxDnsResourceData::operator==(const MxDnsResourceData& other) const -{ - return (m_Data.preference == other.m_Data.preference) && - (m_Data.mailExchange == other.m_Data.mailExchange); -} + bool MxDnsResourceData::operator==(const MxDnsResourceData& other) const + { + return (m_Data.preference == other.m_Data.preference) && (m_Data.mailExchange == other.m_Data.mailExchange); + } -void MxDnsResourceData::setMxData(uint16_t preference, std::string mailExchange) -{ - m_Data.preference = preference; - m_Data.mailExchange = std::move(mailExchange); -} + void MxDnsResourceData::setMxData(uint16_t preference, std::string mailExchange) + { + m_Data.preference = preference; + m_Data.mailExchange = std::move(mailExchange); + } -std::string MxDnsResourceData::toString() const -{ - std::stringstream result; - result << "pref: " << m_Data.preference << "; mx: " << m_Data.mailExchange; - return result.str(); -} + std::string MxDnsResourceData::toString() const + { + std::stringstream result; + result << "pref: " << m_Data.preference << "; mx: " << m_Data.mailExchange; + return result.str(); + } -bool MxDnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const -{ - uint16_t netOrderPreference = htobe16(m_Data.preference); - memcpy(arr, &netOrderPreference, sizeof(uint16_t)); - encodeName(m_Data.mailExchange, (char*)(arr + sizeof(uint16_t)), arrLength, dnsResource); - arrLength += sizeof(uint16_t); + bool MxDnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource* dnsResource) const + { + uint16_t netOrderPreference = htobe16(m_Data.preference); + memcpy(arr, &netOrderPreference, sizeof(uint16_t)); + encodeName(m_Data.mailExchange, (char*)(arr + sizeof(uint16_t)), arrLength, dnsResource); + arrLength += sizeof(uint16_t); - return true; -} + return true; + } -GenericDnsResourceData::GenericDnsResourceData(const uint8_t* dataPtr, size_t dataLen) -{ - m_Data = nullptr; - m_DataLen = 0; - if (dataLen > 0 && dataPtr != nullptr) + GenericDnsResourceData::GenericDnsResourceData(const uint8_t* dataPtr, size_t dataLen) { - m_DataLen = dataLen; - m_Data = new uint8_t[dataLen]; - memcpy(m_Data, dataPtr, dataLen); + m_Data = nullptr; + m_DataLen = 0; + if (dataLen > 0 && dataPtr != nullptr) + { + m_DataLen = dataLen; + m_Data = new uint8_t[dataLen]; + memcpy(m_Data, dataPtr, dataLen); + } } -} -GenericDnsResourceData::GenericDnsResourceData(const std::string& dataAsHexString) -{ - m_Data = nullptr; - uint8_t tempDataArr[2048]; - m_DataLen = hexStringToByteArray(dataAsHexString, tempDataArr, 2048); - if (m_DataLen != 0) + GenericDnsResourceData::GenericDnsResourceData(const std::string& dataAsHexString) { - m_Data = new uint8_t[m_DataLen]; - memcpy(m_Data, tempDataArr, m_DataLen); + m_Data = nullptr; + uint8_t tempDataArr[2048]; + m_DataLen = hexStringToByteArray(dataAsHexString, tempDataArr, 2048); + if (m_DataLen != 0) + { + m_Data = new uint8_t[m_DataLen]; + memcpy(m_Data, tempDataArr, m_DataLen); + } } -} - -GenericDnsResourceData::GenericDnsResourceData(const GenericDnsResourceData& other) : IDnsResourceData() -{ - m_DataLen = other.m_DataLen; - if (m_DataLen > 0 && other.m_Data != nullptr) + GenericDnsResourceData::GenericDnsResourceData(const GenericDnsResourceData& other) : IDnsResourceData() { - m_Data = new uint8_t[m_DataLen]; - memcpy(m_Data, other.m_Data, m_DataLen); - } -} + m_DataLen = other.m_DataLen; -GenericDnsResourceData& GenericDnsResourceData::operator=(const GenericDnsResourceData& other) -{ - if (m_Data != nullptr) - delete [] m_Data; + if (m_DataLen > 0 && other.m_Data != nullptr) + { + m_Data = new uint8_t[m_DataLen]; + memcpy(m_Data, other.m_Data, m_DataLen); + } + } - m_Data = nullptr; - m_DataLen = other.m_DataLen; - if (m_DataLen > 0 && other.m_Data != nullptr) + GenericDnsResourceData& GenericDnsResourceData::operator=(const GenericDnsResourceData& other) { - m_Data = new uint8_t[m_DataLen]; - memcpy(m_Data, other.m_Data, m_DataLen); + if (m_Data != nullptr) + delete[] m_Data; + + m_Data = nullptr; + m_DataLen = other.m_DataLen; + if (m_DataLen > 0 && other.m_Data != nullptr) + { + m_Data = new uint8_t[m_DataLen]; + memcpy(m_Data, other.m_Data, m_DataLen); + } + + return (*this); } - return (*this); -} - -bool GenericDnsResourceData::operator==(const GenericDnsResourceData& other) const -{ - if (m_DataLen != other.m_DataLen) - return false; - - return (memcmp(m_Data, other.m_Data, m_DataLen) == 0); -} + bool GenericDnsResourceData::operator==(const GenericDnsResourceData& other) const + { + if (m_DataLen != other.m_DataLen) + return false; -std::string GenericDnsResourceData::toString() const -{ - return byteArrayToHexString(m_Data, m_DataLen); -} + return (memcmp(m_Data, other.m_Data, m_DataLen) == 0); + } -bool GenericDnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource*) const -{ - if (m_DataLen == 0 || m_Data == nullptr) + std::string GenericDnsResourceData::toString() const { - PCPP_LOG_ERROR("Input data is null or illegal" << "|m_DataLen:" << m_DataLen); - return false; + return byteArrayToHexString(m_Data, m_DataLen); } - arrLength = m_DataLen; - memcpy(arr, m_Data, m_DataLen); - return true; -} + bool GenericDnsResourceData::toByteArr(uint8_t* arr, size_t& arrLength, IDnsResource*) const + { + if (m_DataLen == 0 || m_Data == nullptr) + { + PCPP_LOG_ERROR("Input data is null or illegal" + << "|m_DataLen:" << m_DataLen); + return false; + } + + arrLength = m_DataLen; + memcpy(arr, m_Data, m_DataLen); + return true; + } -} +} // namespace pcpp diff --git a/Packet++/src/EthDot3Layer.cpp b/Packet++/src/EthDot3Layer.cpp index 3f226cba09..dff65ac12a 100644 --- a/Packet++/src/EthDot3Layer.cpp +++ b/Packet++/src/EthDot3Layer.cpp @@ -6,57 +6,57 @@ namespace pcpp { -EthDot3Layer::EthDot3Layer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t length) : Layer() -{ - const size_t headerLen = sizeof(ether_dot3_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - - ether_dot3_header* ethHdr = (ether_dot3_header*)m_Data; - destMac.copyTo(ethHdr->dstMac); - sourceMac.copyTo(ethHdr->srcMac); - ethHdr->length = be16toh(length); - m_Protocol = Ethernet; -} - -void EthDot3Layer::parseNextLayer() -{ - if (m_DataLen <= sizeof(ether_dot3_header)) - return; + EthDot3Layer::EthDot3Layer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t length) : Layer() + { + const size_t headerLen = sizeof(ether_dot3_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + + ether_dot3_header* ethHdr = (ether_dot3_header*)m_Data; + destMac.copyTo(ethHdr->dstMac); + sourceMac.copyTo(ethHdr->srcMac); + ethHdr->length = be16toh(length); + m_Protocol = Ethernet; + } - uint8_t* payload = m_Data + sizeof(ether_dot3_header); - size_t payloadLen = m_DataLen - sizeof(ether_dot3_header); + void EthDot3Layer::parseNextLayer() + { + if (m_DataLen <= sizeof(ether_dot3_header)) + return; - if (LLCLayer::isDataValid(payload, payloadLen)) - m_NextLayer = new LLCLayer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); -} + uint8_t* payload = m_Data + sizeof(ether_dot3_header); + size_t payloadLen = m_DataLen - sizeof(ether_dot3_header); -std::string EthDot3Layer::toString() const -{ - return "IEEE 802.3 Ethernet, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); -} + if (LLCLayer::isDataValid(payload, payloadLen)) + m_NextLayer = new LLCLayer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } -bool EthDot3Layer::isDataValid(const uint8_t* data, size_t dataLen) -{ - if (dataLen >= sizeof(ether_dot3_header)) + std::string EthDot3Layer::toString() const { - /** - * LSAPs: ... Such a length must, when considered as an - * unsigned integer, be less than 0x5DC or it could be mistaken as - * an Ethertype... - * - * From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 - * More: IEEE Std 802.3 Clause 3.2.6 - */ - return be16toh(*(uint16_t*)(data + 12)) <= (uint16_t)0x05DC; + return "IEEE 802.3 Ethernet, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); } - else + + bool EthDot3Layer::isDataValid(const uint8_t* data, size_t dataLen) { - return false; + if (dataLen >= sizeof(ether_dot3_header)) + { + /** + * LSAPs: ... Such a length must, when considered as an + * unsigned integer, be less than 0x5DC or it could be mistaken as + * an Ethertype... + * + * From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 + * More: IEEE Std 802.3 Clause 3.2.6 + */ + return be16toh(*(uint16_t*)(data + 12)) <= (uint16_t)0x05DC; + } + else + { + return false; + } } -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/EthLayer.cpp b/Packet++/src/EthLayer.cpp index f0b60e3585..fe03e28ad0 100644 --- a/Packet++/src/EthLayer.cpp +++ b/Packet++/src/EthLayer.cpp @@ -15,120 +15,119 @@ namespace pcpp { + EthLayer::EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType) : Layer() + { + const size_t headerLen = sizeof(ether_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); -EthLayer::EthLayer(const MacAddress& sourceMac, const MacAddress& destMac, uint16_t etherType) : Layer() -{ - const size_t headerLen = sizeof(ether_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - - ether_header* ethHdr = (ether_header*)m_Data; - destMac.copyTo(ethHdr->dstMac); - sourceMac.copyTo(ethHdr->srcMac); - ethHdr->etherType = htobe16(etherType); - m_Protocol = Ethernet; -} + ether_header* ethHdr = (ether_header*)m_Data; + destMac.copyTo(ethHdr->dstMac); + sourceMac.copyTo(ethHdr->srcMac); + ethHdr->etherType = htobe16(etherType); + m_Protocol = Ethernet; + } -void EthLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(ether_header)) - return; + void EthLayer::parseNextLayer() + { + if (m_DataLen <= sizeof(ether_header)) + return; - ether_header* hdr = getEthHeader(); - uint8_t* payload = m_Data + sizeof(ether_header); - size_t payloadLen = m_DataLen - sizeof(ether_header); + ether_header* hdr = getEthHeader(); + uint8_t* payload = m_Data + sizeof(ether_header); + size_t payloadLen = m_DataLen - sizeof(ether_header); - switch (be16toh(hdr->etherType)) - { - case PCPP_ETHERTYPE_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_ARP: - m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_VLAN: - case PCPP_ETHERTYPE_IEEE_802_1AD: - m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_PPPOES: - m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_PPPOED: - m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_MPLS: - m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_WAKE_ON_LAN: - m_NextLayer = WakeOnLanLayer::isDataValid(payload, payloadLen) - ? static_cast(new WakeOnLanLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + switch (be16toh(hdr->etherType)) + { + case PCPP_ETHERTYPE_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_ARP: + m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_VLAN: + case PCPP_ETHERTYPE_IEEE_802_1AD: + m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_PPPOES: + m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_PPPOED: + m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_MPLS: + m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_WAKE_ON_LAN: + m_NextLayer = WakeOnLanLayer::isDataValid(payload, payloadLen) + ? static_cast(new WakeOnLanLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } } -} -void EthLayer::computeCalculateFields() -{ - if (m_NextLayer == nullptr) - return; - - switch (m_NextLayer->getProtocol()) + void EthLayer::computeCalculateFields() { - case IPv4: - getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); - break; - case IPv6: - getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); - break; - case ARP: - getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); - break; - case VLAN: - getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); - break; - default: - return; - } -} + if (m_NextLayer == nullptr) + return; -std::string EthLayer::toString() const -{ - return "Ethernet II Layer, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); -} + switch (m_NextLayer->getProtocol()) + { + case IPv4: + getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); + break; + case IPv6: + getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); + break; + case ARP: + getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); + break; + case VLAN: + getEthHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); + break; + default: + return; + } + } -bool EthLayer::isDataValid(const uint8_t* data, size_t dataLen) -{ - if (dataLen >= sizeof(ether_header)) + std::string EthLayer::toString() const { - /** - * Ethertypes: These are 16-bit identifiers appearing as the initial - * two octets after the MAC destination and source (or after a - * tag) which, when considered as an unsigned integer, are equal - * to or larger than 0x0600. - * - * From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 - * More: IEEE Std 802.3 Clause 3.2.6 - */ - return be16toh(*(uint16_t*)(data + 12)) >= (uint16_t)0x0600; + return "Ethernet II Layer, Src: " + getSourceMac().toString() + ", Dst: " + getDestMac().toString(); } - else + + bool EthLayer::isDataValid(const uint8_t* data, size_t dataLen) { - return false; + if (dataLen >= sizeof(ether_header)) + { + /** + * Ethertypes: These are 16-bit identifiers appearing as the initial + * two octets after the MAC destination and source (or after a + * tag) which, when considered as an unsigned integer, are equal + * to or larger than 0x0600. + * + * From: https://tools.ietf.org/html/rfc5342#section-2.3.2.1 + * More: IEEE Std 802.3 Clause 3.2.6 + */ + return be16toh(*(uint16_t*)(data + 12)) >= (uint16_t)0x0600; + } + else + { + return false; + } } -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/FtpLayer.cpp b/Packet++/src/FtpLayer.cpp index 01e9055889..f4e500e2ac 100644 --- a/Packet++/src/FtpLayer.cpp +++ b/Packet++/src/FtpLayer.cpp @@ -27,7 +27,7 @@ namespace pcpp return getCommandInternal(); } - bool FtpRequestLayer::setCommandOption(const std::string &value) + bool FtpRequestLayer::setCommandOption(const std::string& value) { return setCommandOptionInternal(value); } @@ -40,7 +40,7 @@ namespace pcpp std::string field = getCommandOptionInternal(); for (size_t idx = 0; idx < field.size(); ++idx) { - if (int(field.c_str()[idx]) < 127 && int(field.c_str()[idx]) > 31) // From SPACE to ~ + if (int(field.c_str()[idx]) < 127 && int(field.c_str()[idx]) > 31) // From SPACE to ~ ss << field.c_str()[idx]; } return ss.str(); @@ -95,8 +95,7 @@ namespace pcpp case FtpCommand::LANG: return "Language Negotiation"; case FtpCommand::LIST: - return "Returns information of a file or directory if specified, else information of the current working " - "directory is returned"; + return "Returns information of a file or directory if specified, else information of the current working directory is returned"; case FtpCommand::LPRT: return "Specifies a long address and port to which the server should connect"; case FtpCommand::LPSV: @@ -116,8 +115,7 @@ namespace pcpp case FtpCommand::MLSD: return "Lists the contents of a directory in a standardized machine-readable format"; case FtpCommand::MLST: - return "Provides data about exactly the object named on its command line in a standardized " - "machine-readable format"; + return "Provides data about exactly the object named on its command line in a standardized machine-readable format"; case FtpCommand::MODE: return "Sets the transfer mode (Stream, Block, or Compressed)"; case FtpCommand::NLST: @@ -155,15 +153,13 @@ namespace pcpp case FtpCommand::RNTO: return "Rename to"; case FtpCommand::SITE: - return "Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE " - "HELP output for complete list of supported commands"; + return "Sends site specific commands to remote server (like SITE IDLE 60 or SITE UMASK 002). Inspect SITE HELP output for complete list of supported commands"; case FtpCommand::SIZE: return "Return the size of a file"; case FtpCommand::SMNT: return "Mount file structure"; case FtpCommand::SPSV: - return "Use single port passive mode (only one TCP port number for both control connections and " - "passive-mode data connections)"; + return "Use single port passive mode (only one TCP port number for both control connections and passive-mode data connections)"; case FtpCommand::STAT: return "Returns information on the server status, including the status of the current connection"; case FtpCommand::STOR: @@ -207,7 +203,7 @@ namespace pcpp for (size_t idx = 0; idx < 4; ++idx) { char val = (uint64_t(code) >> (8 * idx)) & UINT8_MAX; - if (val) // Dont push if it is a null character + if (val) // Dont push if it is a null character { oss << val; } @@ -238,7 +234,7 @@ namespace pcpp return getCommandInternal(); } - bool FtpResponseLayer::setStatusOption(const std::string &value) + bool FtpResponseLayer::setStatusOption(const std::string& value) { return setCommandOptionInternal(value); } @@ -251,7 +247,7 @@ namespace pcpp std::string field = getCommandOptionInternal(); for (size_t idx = 0; idx < field.size(); ++idx) { - if (int(field.c_str()[idx]) < 127 && int(field.c_str()[idx]) > 31) // From SPACE to ~ + if (int(field.c_str()[idx]) < 127 && int(field.c_str()[idx]) > 31) // From SPACE to ~ ss << field.c_str()[idx]; } return ss.str(); @@ -390,4 +386,4 @@ namespace pcpp return "FTP Data"; } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/GreLayer.cpp b/Packet++/src/GreLayer.cpp index bae6aaefaa..da8b5d7170 100644 --- a/Packet++/src/GreLayer.cpp +++ b/Packet++/src/GreLayer.cpp @@ -20,599 +20,593 @@ namespace pcpp { -ProtocolType GreLayer::getGREVersion(uint8_t* greData, size_t greDataLen) -{ - if (greDataLen < sizeof(gre_basic_header)) - return UnknownProtocol; - - uint8_t version = *(greData+1); - version &= 0x07; - if (version == 0) - return GREv0; - else if (version == 1) - return GREv1; - else - return UnknownProtocol; -} - -uint8_t* GreLayer::getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const -{ - uint8_t* ptr = m_Data + sizeof(gre_basic_header); - - gre_basic_header* header = (gre_basic_header*)m_Data; + ProtocolType GreLayer::getGREVersion(uint8_t* greData, size_t greDataLen) + { + if (greDataLen < sizeof(gre_basic_header)) + return UnknownProtocol; + + uint8_t version = *(greData + 1); + version &= 0x07; + if (version == 0) + return GREv0; + else if (version == 1) + return GREv1; + else + return UnknownProtocol; + } - for (int curFieldAsInt = static_cast(GreChecksumOrRouting); curFieldAsInt < 4 /* this value is out of scope of GreField enum values */; ++curFieldAsInt) + uint8_t* GreLayer::getFieldValue(GreField field, bool returnOffsetEvenIfFieldMissing) const { - const GreField curField = static_cast(curFieldAsInt); - bool curFieldExists = false; + uint8_t* ptr = m_Data + sizeof(gre_basic_header); - uint8_t* origPtr = ptr; + gre_basic_header* header = (gre_basic_header*)m_Data; - switch (curField) + constexpr int numGreField = 4; + for (int curFieldAsInt = static_cast(GreChecksumOrRouting); curFieldAsInt < numGreField; ++curFieldAsInt) { - case GreChecksumOrRouting: - if (header->checksumBit == 1 || header->routingBit == 1) - { - curFieldExists = true; - ptr += sizeof(uint32_t); - } - break; - case GreKey: - if (header->keyBit == 1) + const GreField curField = static_cast(curFieldAsInt); + bool curFieldExists = false; + + uint8_t* origPtr = ptr; + + switch (curField) { - curFieldExists = true; - ptr += sizeof(uint32_t); + case GreChecksumOrRouting: + if (header->checksumBit == 1 || header->routingBit == 1) + { + curFieldExists = true; + ptr += sizeof(uint32_t); + } + break; + case GreKey: + if (header->keyBit == 1) + { + curFieldExists = true; + ptr += sizeof(uint32_t); + } + break; + case GreSeq: + if (header->sequenceNumBit == 1) + { + curFieldExists = true; + ptr += sizeof(uint32_t); + } + break; + case GreAck: + if (header->ackSequenceNumBit == 1) + { + curFieldExists = true; + ptr += sizeof(uint32_t); + } + break; + default: // shouldn't get there + return nullptr; } - break; - case GreSeq: - if (header->sequenceNumBit == 1) + + if (field == curField) { - curFieldExists = true; - ptr += sizeof(uint32_t); + if (curFieldExists || returnOffsetEvenIfFieldMissing) + return origPtr; + + return nullptr; } - break; - case GreAck: - if (header->ackSequenceNumBit == 1) + } // for + + return nullptr; + } + + void GreLayer::computeCalculateFieldsInner() + { + gre_basic_header* header = (gre_basic_header*)m_Data; + if (m_NextLayer != nullptr) + { + switch (m_NextLayer->getProtocol()) { - curFieldExists = true; - ptr += sizeof(uint32_t); + case IPv4: + header->protocol = htobe16(PCPP_ETHERTYPE_IP); + break; + case IPv6: + header->protocol = htobe16(PCPP_ETHERTYPE_IPV6); + break; + case VLAN: + header->protocol = htobe16(PCPP_ETHERTYPE_VLAN); + break; + case MPLS: + header->protocol = htobe16(PCPP_ETHERTYPE_MPLS); + break; + case PPP_PPTP: + header->protocol = htobe16(PCPP_ETHERTYPE_PPP); + break; + case Ethernet: + header->protocol = htobe16(PCPP_ETHERTYPE_ETHBRIDGE); + break; + default: + break; } - break; - default: // shouldn't get there - return nullptr; } + } + + bool GreLayer::getSequenceNumber(uint32_t& seqNumber) const + { + gre_basic_header* header = (gre_basic_header*)m_Data; + + if (header->sequenceNumBit == 0) + return false; + + uint32_t* val = (uint32_t*)getFieldValue(GreSeq, false); + if (val == nullptr) + return false; + + seqNumber = be32toh(*val); + return true; + } + + bool GreLayer::setSequenceNumber(uint32_t seqNumber) + { + gre_basic_header* header = (gre_basic_header*)m_Data; + + bool needToExtendLayer = false; + + if (header->sequenceNumBit == 0) + needToExtendLayer = true; - if (field == curField) + uint8_t* offsetPtr = getFieldValue(GreSeq, true); + + int offset = offsetPtr - m_Data; + if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) { - if (curFieldExists || returnOffsetEvenIfFieldMissing) - return origPtr; + header->sequenceNumBit = 0; + PCPP_LOG_ERROR("Couldn't extend layer to set sequence number"); + return false; + } + + header = (gre_basic_header*)m_Data; + header->sequenceNumBit = 1; + uint32_t* seqPtr = (uint32_t*)(m_Data + offset); + *seqPtr = htobe32(seqNumber); - return nullptr; + return true; + } + + bool GreLayer::unsetSequenceNumber() + { + gre_basic_header* header = (gre_basic_header*)m_Data; + + if (header->sequenceNumBit == 0) + { + PCPP_LOG_ERROR("Couldn't unset sequence number as it's already unset"); + return false; } - } // for - return nullptr; -} + uint8_t* offsetPtr = getFieldValue(GreSeq, true); -void GreLayer::computeCalculateFieldsInner() -{ - gre_basic_header* header = (gre_basic_header*)m_Data; - if (m_NextLayer != nullptr) + int offset = offsetPtr - m_Data; + if (!shortenLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Couldn't shorted layer to unset sequence number"); + return false; + } + + header = (gre_basic_header*)m_Data; + header->sequenceNumBit = 0; + return true; + } + + void GreLayer::parseNextLayer() { - switch (m_NextLayer->getProtocol()) + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + + gre_basic_header* header = (gre_basic_header*)m_Data; + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; + + switch (be16toh(header->protocol)) { - case IPv4: - header->protocol = htobe16(PCPP_ETHERTYPE_IP); + case PCPP_ETHERTYPE_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case IPv6: - header->protocol = htobe16(PCPP_ETHERTYPE_IPV6); + case PCPP_ETHERTYPE_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case VLAN: - header->protocol = htobe16(PCPP_ETHERTYPE_VLAN); + case PCPP_ETHERTYPE_VLAN: + m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); break; - case MPLS: - header->protocol = htobe16(PCPP_ETHERTYPE_MPLS); + case PCPP_ETHERTYPE_MPLS: + m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); break; - case PPP_PPTP: - header->protocol = htobe16(PCPP_ETHERTYPE_PPP); + case PCPP_ETHERTYPE_PPP: + m_NextLayer = new PPP_PPTPLayer(payload, payloadLen, this, m_Packet); break; - case Ethernet: - header->protocol = htobe16(PCPP_ETHERTYPE_ETHBRIDGE); + case PCPP_ETHERTYPE_ETHBRIDGE: + if (EthLayer::isDataValid(payload, payloadLen)) + { + m_NextLayer = new EthLayer(payload, payloadLen, this, m_Packet); + } + else if (EthDot3Layer::isDataValid(payload, payloadLen)) + { + m_NextLayer = new EthDot3Layer(payload, payloadLen, this, m_Packet); + } + else + { + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } break; default: - break; + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } } -} -bool GreLayer::getSequenceNumber(uint32_t& seqNumber) const -{ - gre_basic_header* header = (gre_basic_header*)m_Data; - - if (header->sequenceNumBit == 0) - return false; - - uint32_t* val = (uint32_t*)getFieldValue(GreSeq, false); - if (val == nullptr) - return false; - - seqNumber = be32toh(*val); - return true; -} + size_t GreLayer::getHeaderLen() const + { + size_t result = sizeof(gre_basic_header); -bool GreLayer::setSequenceNumber(uint32_t seqNumber) -{ - gre_basic_header* header = (gre_basic_header*)m_Data; + gre_basic_header* header = (gre_basic_header*)m_Data; - bool needToExtendLayer = false; + if (header->checksumBit == 1 || header->routingBit == 1) + result += 4; + if (header->keyBit == 1) + result += 4; + if (header->sequenceNumBit == 1) + result += 4; + if (header->ackSequenceNumBit == 1) + result += 4; - if (header->sequenceNumBit == 0) - needToExtendLayer = true; + return result; + } - uint8_t* offsetPtr = getFieldValue(GreSeq, true); + // ================ + // GREv0Layer class + // ================ - int offset = offsetPtr - m_Data; - if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) + GREv0Layer::GREv0Layer() { - header->sequenceNumBit = 0; - PCPP_LOG_ERROR("Couldn't extend layer to set sequence number"); - return false; + const size_t headerLen = sizeof(gre_basic_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + m_Protocol = GREv0; } - header = (gre_basic_header*)m_Data; - header->sequenceNumBit = 1; - uint32_t* seqPtr = (uint32_t*)(m_Data + offset); - *seqPtr = htobe32(seqNumber); - - return true; -} - -bool GreLayer::unsetSequenceNumber() -{ - gre_basic_header* header = (gre_basic_header*)m_Data; - - if (header->sequenceNumBit == 0) + bool GREv0Layer::getChecksum(uint16_t& checksum) { - PCPP_LOG_ERROR("Couldn't unset sequence number as it's already unset"); - return false; - } + if (getGreHeader()->checksumBit == 0) + return false; - uint8_t* offsetPtr = getFieldValue(GreSeq, true); + uint16_t* val = (uint16_t*)getFieldValue(GreChecksumOrRouting, false); + if (val == nullptr) + return false; - int offset = offsetPtr - m_Data; - if (!shortenLayer(offset, sizeof(uint32_t))) - { - PCPP_LOG_ERROR("Couldn't shorted layer to unset sequence number"); - return false; + checksum = be16toh(*val); + return true; } - header = (gre_basic_header*)m_Data; - header->sequenceNumBit = 0; - return true; -} + bool GREv0Layer::setChecksum(uint16_t checksum) + { + gre_basic_header* header = getGreHeader(); -void GreLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; + bool needToExtendLayer = false; - gre_basic_header* header = (gre_basic_header*)m_Data; - uint8_t* payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; + if (header->routingBit == 0 && header->checksumBit == 0) + needToExtendLayer = true; - switch (be16toh(header->protocol)) - { - case PCPP_ETHERTYPE_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_VLAN: - m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_MPLS: - m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_PPP: - m_NextLayer = new PPP_PPTPLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_ETHBRIDGE: - if (EthLayer::isDataValid(payload, payloadLen)) + uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true); + int offset = offsetPtr - m_Data; + // extend layer in 4 bytes to keep 4-byte alignment + if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) { - m_NextLayer = new EthLayer(payload, payloadLen, this, m_Packet); - } - else if (EthDot3Layer::isDataValid(payload, payloadLen)) - { - m_NextLayer = new EthDot3Layer(payload, payloadLen, this, m_Packet); - } - else - { - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + PCPP_LOG_ERROR("Couldn't extend layer to set checksum"); + return false; } - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - } -} - -size_t GreLayer::getHeaderLen() const -{ - size_t result = sizeof(gre_basic_header); - - gre_basic_header* header = (gre_basic_header*)m_Data; - - if (header->checksumBit == 1 || header->routingBit == 1 ) - result += 4; - if (header->keyBit == 1) - result += 4; - if (header->sequenceNumBit == 1) - result += 4; - if (header->ackSequenceNumBit == 1) - result += 4; - - return result; -} + uint16_t* checksumPtr = (uint16_t*)(m_Data + offset); + *checksumPtr = htobe16(checksum); + // if layer was extended in 4 bytes, make sure the offset field stays 0 + if (needToExtendLayer) + { + checksumPtr++; + *checksumPtr = 0; + } -// ================ -// GREv0Layer class -// ================ + header = getGreHeader(); + header->checksumBit = 1; + return true; + } -GREv0Layer::GREv0Layer() -{ - const size_t headerLen = sizeof(gre_basic_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = GREv0; -} - -bool GREv0Layer::getChecksum(uint16_t& checksum) -{ - if (getGreHeader()->checksumBit == 0) - return false; + bool GREv0Layer::unsetChecksum() + { + gre_basic_header* header = getGreHeader(); - uint16_t* val = (uint16_t*)getFieldValue(GreChecksumOrRouting, false); - if (val == nullptr) - return false; + if (header->checksumBit == 0) + { + PCPP_LOG_ERROR("Couldn't unset checksum as it's already unset"); + return false; + } - checksum = be16toh(*val); - return true; -} + // if both routing and checksum are unset we need to shorted the layer + bool needToShortenLayer = (header->routingBit == 0); -bool GREv0Layer::setChecksum(uint16_t checksum) -{ - gre_basic_header* header = getGreHeader(); + uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true); + int offset = offsetPtr - m_Data; + if (needToShortenLayer && !shortenLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Couldn't extend layer to unset checksum"); + return false; + } - bool needToExtendLayer = false; + if (!needToShortenLayer) // meaning routing bit is set - only zero the checksum field + { + uint16_t* checksumPtr = (uint16_t*)(m_Data + offset); + *checksumPtr = 0; + } - if (header->routingBit == 0 && header->checksumBit == 0) - needToExtendLayer = true; + header = getGreHeader(); + header->checksumBit = 0; - uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true); - int offset = offsetPtr - m_Data; - // extend layer in 4 bytes to keep 4-byte alignment - if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) - { - PCPP_LOG_ERROR("Couldn't extend layer to set checksum"); - return false; + return true; } - uint16_t* checksumPtr = (uint16_t*)(m_Data + offset); - *checksumPtr = htobe16(checksum); - - // if layer was extended in 4 bytes, make sure the offset field stays 0 - if (needToExtendLayer) + bool GREv0Layer::getOffset(uint16_t& offset) const { - checksumPtr++; - *checksumPtr = 0; - } + if (getGreHeader()->routingBit == 0) + return false; - header = getGreHeader(); - header->checksumBit = 1; + uint8_t* val = (uint8_t*)getFieldValue(GreChecksumOrRouting, false); + if (val == nullptr) + return false; - return true; -} - -bool GREv0Layer::unsetChecksum() -{ - gre_basic_header* header = getGreHeader(); + offset = be16toh(*(val + 2)); + return true; + } - if (header->checksumBit == 0) + bool GREv0Layer::getKey(uint32_t& key) const { - PCPP_LOG_ERROR("Couldn't unset checksum as it's already unset"); - return false; - } + if (getGreHeader()->keyBit == 0) + return false; - // if both routing and checksum are unset we need to shorted the layer - bool needToShortenLayer = (header->routingBit == 0); + uint32_t* val = (uint32_t*)getFieldValue(GreKey, false); + if (val == nullptr) + return false; - uint8_t* offsetPtr = getFieldValue(GreChecksumOrRouting, true); - int offset = offsetPtr - m_Data; - if (needToShortenLayer && !shortenLayer(offset, sizeof(uint32_t))) - { - PCPP_LOG_ERROR("Couldn't extend layer to unset checksum"); - return false; + key = be32toh(*val); + return true; } - if (!needToShortenLayer) // meaning routing bit is set - only zero the checksum field + bool GREv0Layer::setKey(uint32_t key) { - uint16_t* checksumPtr = (uint16_t*)(m_Data + offset); - *checksumPtr = 0; - } - - header = getGreHeader(); - header->checksumBit = 0; + gre_basic_header* header = getGreHeader(); - return true; -} + bool needToExtendLayer = false; -bool GREv0Layer::getOffset(uint16_t& offset) const -{ - if (getGreHeader()->routingBit == 0) - return false; + if (header->keyBit == 0) + needToExtendLayer = true; - uint8_t* val = (uint8_t*)getFieldValue(GreChecksumOrRouting, false); - if (val == nullptr) - return false; + uint8_t* offsetPtr = getFieldValue(GreKey, true); - offset = be16toh(*(val+2)); - return true; -} - -bool GREv0Layer::getKey(uint32_t& key) const -{ - if (getGreHeader()->keyBit == 0) - return false; + int offset = offsetPtr - m_Data; + if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) + { + header->keyBit = 0; + PCPP_LOG_ERROR("Couldn't extend layer to set key"); + return false; + } - uint32_t* val = (uint32_t*)getFieldValue(GreKey, false); - if (val == nullptr) - return false; + header = getGreHeader(); + header->keyBit = 1; + uint32_t* keyPtr = (uint32_t*)(m_Data + offset); + *keyPtr = htobe32(key); - key = be32toh(*val); - return true; -} + return true; + } -bool GREv0Layer::setKey(uint32_t key) -{ - gre_basic_header* header = getGreHeader(); + bool GREv0Layer::unsetKey() + { + gre_basic_header* header = getGreHeader(); - bool needToExtendLayer = false; + if (header->keyBit == 0) + { + PCPP_LOG_ERROR("Couldn't unset key as it's already unset"); + return false; + } - if (header->keyBit == 0) - needToExtendLayer = true; + uint8_t* offsetPtr = getFieldValue(GreKey, true); - uint8_t* offsetPtr = getFieldValue(GreKey, true); + int offset = offsetPtr - m_Data; + if (!shortenLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Couldn't shorted layer to unset key"); + return false; + } - int offset = offsetPtr - m_Data; - if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) - { + header = (gre_basic_header*)m_Data; header->keyBit = 0; - PCPP_LOG_ERROR("Couldn't extend layer to set key"); - return false; + return true; } - header = getGreHeader(); - header->keyBit = 1; - uint32_t* keyPtr = (uint32_t*)(m_Data + offset); - *keyPtr = htobe32(key); + void GREv0Layer::computeCalculateFields() + { + computeCalculateFieldsInner(); + + if (getGreHeader()->checksumBit == 0) + return; - return true; -} + // calculate checksum + setChecksum(0); -bool GREv0Layer::unsetKey() -{ - gre_basic_header* header = getGreHeader(); + ScalarBuffer buffer; + buffer.buffer = (uint16_t*)m_Data; + buffer.len = m_DataLen; + size_t checksum = computeChecksum(&buffer, 1); - if (header->keyBit == 0) - { - PCPP_LOG_ERROR("Couldn't unset key as it's already unset"); - return false; + setChecksum(checksum); } - uint8_t* offsetPtr = getFieldValue(GreKey, true); - - int offset = offsetPtr - m_Data; - if (!shortenLayer(offset, sizeof(uint32_t))) + std::string GREv0Layer::toString() const { - PCPP_LOG_ERROR("Couldn't shorted layer to unset key"); - return false; + return "GRE Layer, version 0"; } - header = (gre_basic_header*)m_Data; - header->keyBit = 0; - return true; -} - -void GREv0Layer::computeCalculateFields() -{ - computeCalculateFieldsInner(); + // ================ + // GREv1Layer class + // ================ - if (getGreHeader()->checksumBit == 0) - return; + GREv1Layer::GREv1Layer(uint16_t callID) + { + const size_t headerLen = sizeof(gre1_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + m_Protocol = GREv1; + + gre1_header* header = getGreHeader(); + header->keyBit = 1; + header->version = 1; + header->callID = htobe16(callID); + } - // calculate checksum - setChecksum(0); + bool GREv1Layer::getAcknowledgmentNum(uint32_t& ackNum) const + { + if (getGreHeader()->ackSequenceNumBit == 0) + return false; - ScalarBuffer buffer; - buffer.buffer = (uint16_t*)m_Data; - buffer.len = m_DataLen; - size_t checksum = computeChecksum(&buffer, 1); + uint32_t* val = (uint32_t*)getFieldValue(GreAck, false); + if (val == nullptr) + return false; - setChecksum(checksum); -} + ackNum = be32toh(*val); + return true; + } -std::string GREv0Layer::toString() const -{ - return "GRE Layer, version 0"; -} + bool GREv1Layer::setAcknowledgmentNum(uint32_t ackNum) + { + bool needToExtendLayer = false; + gre1_header* header = getGreHeader(); -// ================ -// GREv1Layer class -// ================ + if (header->ackSequenceNumBit == 0) + needToExtendLayer = true; -GREv1Layer::GREv1Layer(uint16_t callID) -{ - const size_t headerLen = sizeof(gre1_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = GREv1; - - gre1_header* header = getGreHeader(); - header->keyBit = 1; - header->version = 1; - header->callID = htobe16(callID); -} - -bool GREv1Layer::getAcknowledgmentNum(uint32_t& ackNum) const -{ - if (getGreHeader()->ackSequenceNumBit == 0) - return false; + uint8_t* offsetPtr = getFieldValue(GreAck, true); + int offset = offsetPtr - m_Data; + if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Couldn't extend layer to set ack number"); + return false; + } - uint32_t* val = (uint32_t*)getFieldValue(GreAck, false); - if (val == nullptr) - return false; + header = getGreHeader(); + header->ackSequenceNumBit = 1; + uint32_t* ackPtr = (uint32_t*)(m_Data + offset); + *ackPtr = htobe32(ackNum); + return true; + } - ackNum = be32toh(*val); - return true; -} + bool GREv1Layer::unsetAcknowledgmentNum() + { + gre1_header* header = getGreHeader(); -bool GREv1Layer::setAcknowledgmentNum(uint32_t ackNum) -{ - bool needToExtendLayer = false; + if (header->ackSequenceNumBit == 0) + { + PCPP_LOG_ERROR("Couldn't unset ack number as it's already unset"); + return false; + } - gre1_header* header = getGreHeader(); + uint8_t* offsetPtr = getFieldValue(GreAck, true); - if (header->ackSequenceNumBit == 0) - needToExtendLayer = true; + int offset = offsetPtr - m_Data; + if (!shortenLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Couldn't shorted layer to unset ack number"); + return false; + } - uint8_t* offsetPtr = getFieldValue(GreAck, true); - int offset = offsetPtr - m_Data; - if (needToExtendLayer && !extendLayer(offset, sizeof(uint32_t))) - { - PCPP_LOG_ERROR("Couldn't extend layer to set ack number"); - return false; + header = getGreHeader(); + header->ackSequenceNumBit = 0; + return true; } - header = getGreHeader(); - header->ackSequenceNumBit = 1; - uint32_t* ackPtr = (uint32_t*)(m_Data + offset); - *ackPtr = htobe32(ackNum); - return true; -} - -bool GREv1Layer::unsetAcknowledgmentNum() -{ - gre1_header* header = getGreHeader(); - - if (header->ackSequenceNumBit == 0) + void GREv1Layer::computeCalculateFields() { - PCPP_LOG_ERROR("Couldn't unset ack number as it's already unset"); - return false; - } + computeCalculateFieldsInner(); - uint8_t* offsetPtr = getFieldValue(GreAck, true); + getGreHeader()->payloadLength = htobe16(m_DataLen - getHeaderLen()); + } - int offset = offsetPtr - m_Data; - if (!shortenLayer(offset, sizeof(uint32_t))) + std::string GREv1Layer::toString() const { - PCPP_LOG_ERROR("Couldn't shorted layer to unset ack number"); - return false; + return "GRE Layer, version 1"; } - header = getGreHeader(); - header->ackSequenceNumBit = 0; - return true; -} - -void GREv1Layer::computeCalculateFields() -{ - computeCalculateFieldsInner(); - - getGreHeader()->payloadLength = htobe16(m_DataLen - getHeaderLen()); -} - -std::string GREv1Layer::toString() const -{ - return "GRE Layer, version 1"; -} + // =================== + // PPP_PPTPLayer class + // =================== - - -// =================== -// PPP_PPTPLayer class -// =================== - -PPP_PPTPLayer::PPP_PPTPLayer(uint8_t address, uint8_t control) -{ - const size_t headerLen = sizeof(ppp_pptp_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = PPP_PPTP; - - ppp_pptp_header* header = getPPP_PPTPHeader(); - header->address = address; - header->control = control; -} - - -void PPP_PPTPLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; - - uint8_t* payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; - - switch (be16toh(getPPP_PPTPHeader()->protocol)) + PPP_PPTPLayer::PPP_PPTPLayer(uint8_t address, uint8_t control) { - case PCPP_PPP_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_PPP_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; + const size_t headerLen = sizeof(ppp_pptp_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + m_Protocol = PPP_PPTP; + + ppp_pptp_header* header = getPPP_PPTPHeader(); + header->address = address; + header->control = control; } -} -void PPP_PPTPLayer::computeCalculateFields() -{ - ppp_pptp_header* header = getPPP_PPTPHeader(); - if (m_NextLayer != nullptr) + void PPP_PPTPLayer::parseNextLayer() { - switch (m_NextLayer->getProtocol()) + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; + + switch (be16toh(getPPP_PPTPHeader()->protocol)) { - case IPv4: - header->protocol = htobe16(PCPP_PPP_IP); + case PCPP_PPP_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case IPv6: - header->protocol = htobe16(PCPP_PPP_IPV6); + case PCPP_PPP_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; } } - else - header->protocol = 0; -} -} // namespace pcpp + void PPP_PPTPLayer::computeCalculateFields() + { + ppp_pptp_header* header = getPPP_PPTPHeader(); + if (m_NextLayer != nullptr) + { + switch (m_NextLayer->getProtocol()) + { + case IPv4: + header->protocol = htobe16(PCPP_PPP_IP); + break; + case IPv6: + header->protocol = htobe16(PCPP_PPP_IPV6); + break; + default: + break; + } + } + else + header->protocol = 0; + } + +} // namespace pcpp diff --git a/Packet++/src/GtpLayer.cpp b/Packet++/src/GtpLayer.cpp index 32c82471bf..3fb90e3571 100644 --- a/Packet++/src/GtpLayer.cpp +++ b/Packet++/src/GtpLayer.cpp @@ -14,669 +14,665 @@ namespace pcpp #define PCPP_GTP_V1_GPDU_MESSAGE_TYPE 0xff -/// ================== -/// GtpExtension class -/// ================== + /// ================== + /// GtpExtension class + /// ================== - -GtpV1Layer::GtpExtension::GtpExtension() -{ - m_Data = nullptr; - m_DataLen = 0; - m_ExtType = 0; -} - -GtpV1Layer::GtpExtension::GtpExtension(uint8_t* data, size_t dataLen, uint8_t type) -{ - m_Data = data; - m_DataLen = dataLen; - m_ExtType = type; -} - -GtpV1Layer::GtpExtension::GtpExtension(const GtpExtension& other) -{ - m_Data = other.m_Data; - m_DataLen = other.m_DataLen; - m_ExtType = other.m_ExtType; -} - -GtpV1Layer::GtpExtension& GtpV1Layer::GtpExtension::operator=(const GtpV1Layer::GtpExtension& other) -{ - m_Data = other.m_Data; - m_DataLen = other.m_DataLen; - m_ExtType = other.m_ExtType; - return *this; -} - -bool GtpV1Layer::GtpExtension::isNull() const -{ - return m_Data == nullptr; -} - -uint8_t GtpV1Layer::GtpExtension::getExtensionType() const -{ - return m_ExtType; -} - -size_t GtpV1Layer::GtpExtension::getTotalLength() const -{ - if (m_Data == nullptr) + GtpV1Layer::GtpExtension::GtpExtension() { - return 0; + m_Data = nullptr; + m_DataLen = 0; + m_ExtType = 0; } - size_t len = (size_t)(m_Data[0]*4); - if (len <= m_DataLen) + GtpV1Layer::GtpExtension::GtpExtension(uint8_t* data, size_t dataLen, uint8_t type) { - return len; + m_Data = data; + m_DataLen = dataLen; + m_ExtType = type; } - return m_DataLen; -} - -size_t GtpV1Layer::GtpExtension::getContentLength() const -{ - size_t res = getTotalLength(); - - if (res >= 2*sizeof(uint8_t)) + GtpV1Layer::GtpExtension::GtpExtension(const GtpExtension& other) { - return (size_t)(res - 2*sizeof(uint8_t)); + m_Data = other.m_Data; + m_DataLen = other.m_DataLen; + m_ExtType = other.m_ExtType; } - return 0; -} - -uint8_t* GtpV1Layer::GtpExtension::getContent() const -{ - if (m_Data == nullptr || getContentLength() == 0) + GtpV1Layer::GtpExtension& GtpV1Layer::GtpExtension::operator=(const GtpV1Layer::GtpExtension& other) { - return nullptr; + m_Data = other.m_Data; + m_DataLen = other.m_DataLen; + m_ExtType = other.m_ExtType; + return *this; } - return m_Data + sizeof(uint8_t); -} - -uint8_t GtpV1Layer::GtpExtension::getNextExtensionHeaderType() const -{ - if (m_Data == nullptr || getTotalLength() < 4) + bool GtpV1Layer::GtpExtension::isNull() const { - return 0; + return m_Data == nullptr; } - uint8_t res = *(uint8_t*)(m_Data + sizeof(uint8_t) + getContentLength()); - - return res; -} - -GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::getNextExtension() const -{ - size_t totalLength = getTotalLength(); - uint8_t nextExtType = getNextExtensionHeaderType(); - if (nextExtType > 0 && m_DataLen > totalLength + sizeof(uint8_t)) - { - return GtpV1Layer::GtpExtension(m_Data + totalLength, m_DataLen - totalLength, nextExtType); - } - else + uint8_t GtpV1Layer::GtpExtension::getExtensionType() const { - return GtpV1Layer::GtpExtension(); + return m_ExtType; } -} -void GtpV1Layer::GtpExtension::setNextHeaderType(uint8_t nextHeaderType) -{ - if (m_Data != nullptr && m_DataLen > 1) + size_t GtpV1Layer::GtpExtension::getTotalLength() const { - m_Data[getTotalLength() - 1] = nextHeaderType; - } -} + if (m_Data == nullptr) + { + return 0; + } -GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::createGtpExtension(uint8_t* data, size_t dataLen, uint8_t extType, uint16_t content) -{ - if (dataLen < 4*sizeof(uint8_t)) - { - return GtpExtension(); - } + size_t len = (size_t)(m_Data[0] * 4); + if (len <= m_DataLen) + { + return len; + } - data[0] = 1; - data[1] = (content >> 8); - data[2] = content & 0xff; - data[3] = 0; + return m_DataLen; + } - return GtpV1Layer::GtpExtension(data, dataLen, extType); -} + size_t GtpV1Layer::GtpExtension::getContentLength() const + { + size_t res = getTotalLength(); + if (res >= 2 * sizeof(uint8_t)) + { + return (size_t)(res - 2 * sizeof(uint8_t)); + } + return 0; + } + uint8_t* GtpV1Layer::GtpExtension::getContent() const + { + if (m_Data == nullptr || getContentLength() == 0) + { + return nullptr; + } -/// ================ -/// GtpV1Layer class -/// ================ + return m_Data + sizeof(uint8_t); + } + uint8_t GtpV1Layer::GtpExtension::getNextExtensionHeaderType() const + { + if (m_Data == nullptr || getTotalLength() < 4) + { + return 0; + } -GtpV1Layer::GtpV1Layer(GtpV1MessageType messageType, uint32_t teid) -{ - init(messageType, teid, false, 0, false, 0); -} + uint8_t res = *(uint8_t*)(m_Data + sizeof(uint8_t) + getContentLength()); -GtpV1Layer::GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum) -{ - init(messageType, teid, setSeqNum, seqNum, setNpduNum, npduNum); -} + return res; + } -void GtpV1Layer::init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, uint8_t npduNum) -{ - size_t dataLen = sizeof(gtpv1_header); - if (setSeqNum || setNpduNum) + GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::getNextExtension() const { - dataLen += sizeof(gtpv1_header_extra); + size_t totalLength = getTotalLength(); + uint8_t nextExtType = getNextExtensionHeaderType(); + if (nextExtType > 0 && m_DataLen > totalLength + sizeof(uint8_t)) + { + return GtpV1Layer::GtpExtension(m_Data + totalLength, m_DataLen - totalLength, nextExtType); + } + else + { + return GtpV1Layer::GtpExtension(); + } } - m_DataLen = dataLen; - m_Data = new uint8_t[dataLen]; - memset(m_Data, 0, dataLen); - m_Protocol = GTPv1; - - gtpv1_header* hdr = getHeader(); - hdr->version = 1; - hdr->protocolType = 1; - hdr->messageType = (uint8_t)messageType; - hdr->teid = htobe32(teid); - - if (setSeqNum || setNpduNum) + void GtpV1Layer::GtpExtension::setNextHeaderType(uint8_t nextHeaderType) { - hdr->messageLength = htobe16(sizeof(gtpv1_header_extra)); - gtpv1_header_extra* extraHdr = getHeaderExtra(); - if (setSeqNum) + if (m_Data != nullptr && m_DataLen > 1) { - hdr->sequenceNumberFlag = 1; - extraHdr->sequenceNumber = htobe16(seqNum); + m_Data[getTotalLength() - 1] = nextHeaderType; } + } - if (setNpduNum) + GtpV1Layer::GtpExtension GtpV1Layer::GtpExtension::createGtpExtension(uint8_t* data, size_t dataLen, + uint8_t extType, uint16_t content) + { + if (dataLen < 4 * sizeof(uint8_t)) { - hdr->npduNumberFlag = 1; - extraHdr->npduNumber = npduNum; + return GtpExtension(); } - } -} + data[0] = 1; + data[1] = (content >> 8); + data[2] = content & 0xff; + data[3] = 0; -bool GtpV1Layer::isGTPv1(const uint8_t* data, size_t dataSize) -{ - if(data != nullptr && dataSize >= sizeof(gtpv1_header) && (data[0] & 0xE0) == 0x20) - { - return true; + return GtpV1Layer::GtpExtension(data, dataLen, extType); } - return false; -} + /// ================ + /// GtpV1Layer class + /// ================ -GtpV1Layer::gtpv1_header_extra* GtpV1Layer::getHeaderExtra() const -{ - if (m_Data != nullptr && m_DataLen >= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra)) + GtpV1Layer::GtpV1Layer(GtpV1MessageType messageType, uint32_t teid) { - return (gtpv1_header_extra*)(m_Data + sizeof(gtpv1_header)); + init(messageType, teid, false, 0, false, 0); } - return nullptr; -} - -bool GtpV1Layer::getSequenceNumber(uint16_t& seqNumber) const -{ - gtpv1_header* header = getHeader(); - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (header != nullptr && headerExtra != nullptr && header->sequenceNumberFlag == 1) + GtpV1Layer::GtpV1Layer(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, + bool setNpduNum, uint8_t npduNum) { - seqNumber = be16toh(headerExtra->sequenceNumber); - return true; + init(messageType, teid, setSeqNum, seqNum, setNpduNum, npduNum); } - return false; -} + void GtpV1Layer::init(GtpV1MessageType messageType, uint32_t teid, bool setSeqNum, uint16_t seqNum, bool setNpduNum, + uint8_t npduNum) + { + size_t dataLen = sizeof(gtpv1_header); + if (setSeqNum || setNpduNum) + { + dataLen += sizeof(gtpv1_header_extra); + } -bool GtpV1Layer::setSequenceNumber(const uint16_t seqNumber) -{ - // get GTP header - gtpv1_header* header = getHeader(); - if (header == nullptr) + m_DataLen = dataLen; + m_Data = new uint8_t[dataLen]; + memset(m_Data, 0, dataLen); + m_Protocol = GTPv1; + + gtpv1_header* hdr = getHeader(); + hdr->version = 1; + hdr->protocolType = 1; + hdr->messageType = (uint8_t)messageType; + hdr->teid = htobe32(teid); + + if (setSeqNum || setNpduNum) + { + hdr->messageLength = htobe16(sizeof(gtpv1_header_extra)); + gtpv1_header_extra* extraHdr = getHeaderExtra(); + if (setSeqNum) + { + hdr->sequenceNumberFlag = 1; + extraHdr->sequenceNumber = htobe16(seqNum); + } + + if (setNpduNum) + { + hdr->npduNumberFlag = 1; + extraHdr->npduNumber = npduNum; + } + } + } + + bool GtpV1Layer::isGTPv1(const uint8_t* data, size_t dataSize) { - PCPP_LOG_ERROR("Set sequence failed: GTP header is NULL"); + if (data != nullptr && dataSize >= sizeof(gtpv1_header) && (data[0] & 0xE0) == 0x20) + { + return true; + } + return false; } - // if all flags are unset then create the GTP extra header - if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0) + GtpV1Layer::gtpv1_header_extra* GtpV1Layer::getHeaderExtra() const { - if (!extendLayer(sizeof(gtpv1_header), sizeof(gtpv1_header_extra))) + if (m_Data != nullptr && m_DataLen >= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra)) { - PCPP_LOG_ERROR("Set sequence failed: cannot extend layer"); - return false; + return (gtpv1_header_extra*)(m_Data + sizeof(gtpv1_header)); } - header = getHeader(); + + return nullptr; } - // get the extra header - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (headerExtra == nullptr) + bool GtpV1Layer::getSequenceNumber(uint16_t& seqNumber) const { - PCPP_LOG_ERROR("Set sequence failed: extra header is NULL"); + gtpv1_header* header = getHeader(); + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (header != nullptr && headerExtra != nullptr && header->sequenceNumberFlag == 1) + { + seqNumber = be16toh(headerExtra->sequenceNumber); + return true; + } + return false; } - // set seq number - header->sequenceNumberFlag = 1; - headerExtra->sequenceNumber = htobe16(seqNumber); + bool GtpV1Layer::setSequenceNumber(const uint16_t seqNumber) + { + // get GTP header + gtpv1_header* header = getHeader(); + if (header == nullptr) + { + PCPP_LOG_ERROR("Set sequence failed: GTP header is NULL"); + return false; + } + + // if all flags are unset then create the GTP extra header + if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0) + { + if (!extendLayer(sizeof(gtpv1_header), sizeof(gtpv1_header_extra))) + { + PCPP_LOG_ERROR("Set sequence failed: cannot extend layer"); + return false; + } + header = getHeader(); + } - // extend GTP length - header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(gtpv1_header_extra)); + // get the extra header + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (headerExtra == nullptr) + { + PCPP_LOG_ERROR("Set sequence failed: extra header is NULL"); + return false; + } - return true; -} + // set seq number + header->sequenceNumberFlag = 1; + headerExtra->sequenceNumber = htobe16(seqNumber); + + // extend GTP length + header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(gtpv1_header_extra)); -bool GtpV1Layer::getNpduNumber(uint8_t& npduNum) const -{ - gtpv1_header* header = getHeader(); - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (header != nullptr && headerExtra != nullptr && header->npduNumberFlag == 1) - { - npduNum = headerExtra->npduNumber; return true; } - return false; -} - -bool GtpV1Layer::setNpduNumber(const uint8_t npduNum) -{ - // get GTP header - gtpv1_header* header = getHeader(); - if (header == nullptr) + bool GtpV1Layer::getNpduNumber(uint8_t& npduNum) const { - PCPP_LOG_ERROR("Set N-PDU failed: GTP header is NULL"); + gtpv1_header* header = getHeader(); + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (header != nullptr && headerExtra != nullptr && header->npduNumberFlag == 1) + { + npduNum = headerExtra->npduNumber; + return true; + } + return false; } - // if all flags are unset then create the GTP extra header - if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0) + bool GtpV1Layer::setNpduNumber(const uint8_t npduNum) { - if (!extendLayer(sizeof(gtpv1_header), sizeof(gtpv1_header_extra))) + // get GTP header + gtpv1_header* header = getHeader(); + if (header == nullptr) { - PCPP_LOG_ERROR("Set N-PDU failed: cannot extend layer"); + PCPP_LOG_ERROR("Set N-PDU failed: GTP header is NULL"); return false; } - header = getHeader(); - } - // get the extra header - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (headerExtra == nullptr) - { - PCPP_LOG_ERROR("Set N-PDU failed: extra header is NULL"); - return false; - } + // if all flags are unset then create the GTP extra header + if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0) + { + if (!extendLayer(sizeof(gtpv1_header), sizeof(gtpv1_header_extra))) + { + PCPP_LOG_ERROR("Set N-PDU failed: cannot extend layer"); + return false; + } + header = getHeader(); + } - // set N-PDU value - header->npduNumberFlag = 1; - headerExtra->npduNumber = npduNum; + // get the extra header + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (headerExtra == nullptr) + { + PCPP_LOG_ERROR("Set N-PDU failed: extra header is NULL"); + return false; + } - // extend GTP length - header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(gtpv1_header_extra)); + // set N-PDU value + header->npduNumberFlag = 1; + headerExtra->npduNumber = npduNum; - return true; -} + // extend GTP length + header->messageLength = htobe16(be16toh(header->messageLength) + sizeof(gtpv1_header_extra)); -bool GtpV1Layer::getNextExtensionHeaderType(uint8_t& nextExtType) const -{ - gtpv1_header* header = getHeader(); - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (header != nullptr && headerExtra != nullptr && header->extensionHeaderFlag == 1) - { - nextExtType = headerExtra->nextExtensionHeader; return true; } - return false; -} - -GtpV1Layer::GtpExtension GtpV1Layer::getNextExtension() const -{ - uint8_t nextExtType = 0; - bool nextExtExists = getNextExtensionHeaderType(nextExtType); - if (!nextExtExists || nextExtType == 0 || m_DataLen <= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra)) + bool GtpV1Layer::getNextExtensionHeaderType(uint8_t& nextExtType) const { - return GtpV1Layer::GtpExtension(); - } + gtpv1_header* header = getHeader(); + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (header != nullptr && headerExtra != nullptr && header->extensionHeaderFlag == 1) + { + nextExtType = headerExtra->nextExtensionHeader; + return true; + } - return GtpV1Layer::GtpExtension(m_Data + sizeof(gtpv1_header) + sizeof(gtpv1_header_extra), m_DataLen - sizeof(gtpv1_header) - sizeof(gtpv1_header_extra), nextExtType); -} + return false; + } -GtpV1Layer::GtpExtension GtpV1Layer::addExtension(uint8_t extensionType, uint16_t extensionContent) -{ - // get GTP header - gtpv1_header* header = getHeader(); - if (header == nullptr) + GtpV1Layer::GtpExtension GtpV1Layer::getNextExtension() const { - PCPP_LOG_ERROR("Add extension failed: GTP header is NULL"); - return GtpExtension(); - } + uint8_t nextExtType = 0; + bool nextExtExists = getNextExtensionHeaderType(nextExtType); + if (!nextExtExists || nextExtType == 0 || m_DataLen <= sizeof(gtpv1_header) + sizeof(gtpv1_header_extra)) + { + return GtpV1Layer::GtpExtension(); + } - size_t offsetForNewExtension = sizeof(gtpv1_header); + return GtpV1Layer::GtpExtension(m_Data + sizeof(gtpv1_header) + sizeof(gtpv1_header_extra), + m_DataLen - sizeof(gtpv1_header) - sizeof(gtpv1_header_extra), nextExtType); + } - // if all flags are unset then create the GTP extra header - if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0) + GtpV1Layer::GtpExtension GtpV1Layer::addExtension(uint8_t extensionType, uint16_t extensionContent) { - if (!extendLayer(offsetForNewExtension, sizeof(gtpv1_header_extra))) + // get GTP header + gtpv1_header* header = getHeader(); + if (header == nullptr) { - PCPP_LOG_ERROR("Add extension failed: cannot extend layer"); + PCPP_LOG_ERROR("Add extension failed: GTP header is NULL"); return GtpExtension(); } - header = getHeader(); - } - // get the extra header - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (headerExtra == nullptr) - { - PCPP_LOG_ERROR("Add extension failed: extra header is NULL"); - return GtpExtension(); - } + size_t offsetForNewExtension = sizeof(gtpv1_header); - offsetForNewExtension += sizeof(gtpv1_header_extra); + // if all flags are unset then create the GTP extra header + if (header->npduNumberFlag == 0 && header->sequenceNumberFlag == 0 && header->extensionHeaderFlag == 0) + { + if (!extendLayer(offsetForNewExtension, sizeof(gtpv1_header_extra))) + { + PCPP_LOG_ERROR("Add extension failed: cannot extend layer"); + return GtpExtension(); + } + header = getHeader(); + } - // find the last GTP header extension - GtpV1Layer::GtpExtension lastExt = getNextExtension(); + // get the extra header + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (headerExtra == nullptr) + { + PCPP_LOG_ERROR("Add extension failed: extra header is NULL"); + return GtpExtension(); + } - // go over the GTP header extensions - while (!lastExt.getNextExtension().isNull()) - { - // add ext total length to offset - offsetForNewExtension += lastExt.getTotalLength(); - lastExt = lastExt.getNextExtension(); - } + offsetForNewExtension += sizeof(gtpv1_header_extra); - // lastExt != null means layer contains 1 or more extensions - if (!lastExt.isNull()) - { - // add ext total length to offset - offsetForNewExtension += lastExt.getTotalLength(); - } + // find the last GTP header extension + GtpV1Layer::GtpExtension lastExt = getNextExtension(); - // allocate extension space in layer (assuming extension length can only be 4 bytes) - if (!extendLayer(offsetForNewExtension, 4*sizeof(uint8_t))) - { - PCPP_LOG_ERROR("Add extension failed: cannot extend layer"); - return GtpExtension(); - } + // go over the GTP header extensions + while (!lastExt.getNextExtension().isNull()) + { + // add ext total length to offset + offsetForNewExtension += lastExt.getTotalLength(); + lastExt = lastExt.getNextExtension(); + } - // lastExt != null means layer contains 1 or more extensions - if (!lastExt.isNull()) - { - // set the next header type in the last extension - lastExt.setNextHeaderType(extensionType); - } - else - { - // mark extension flags in the layer - header->extensionHeaderFlag = 1; - headerExtra->nextExtensionHeader = extensionType; - } + // lastExt != null means layer contains 1 or more extensions + if (!lastExt.isNull()) + { + // add ext total length to offset + offsetForNewExtension += lastExt.getTotalLength(); + } - // create the extension data and return the extension object to the user - return GtpV1Layer::GtpExtension::createGtpExtension( - m_Data + offsetForNewExtension, - m_DataLen - offsetForNewExtension, - extensionType, - extensionContent); -} + // allocate extension space in layer (assuming extension length can only be 4 bytes) + if (!extendLayer(offsetForNewExtension, 4 * sizeof(uint8_t))) + { + PCPP_LOG_ERROR("Add extension failed: cannot extend layer"); + return GtpExtension(); + } -GtpV1MessageType GtpV1Layer::getMessageType() const -{ - gtpv1_header* header = getHeader(); + // lastExt != null means layer contains 1 or more extensions + if (!lastExt.isNull()) + { + // set the next header type in the last extension + lastExt.setNextHeaderType(extensionType); + } + else + { + // mark extension flags in the layer + header->extensionHeaderFlag = 1; + headerExtra->nextExtensionHeader = extensionType; + } - if (header == nullptr) - { - return GtpV1_MessageTypeUnknown; + // create the extension data and return the extension object to the user + return GtpV1Layer::GtpExtension::createGtpExtension( + m_Data + offsetForNewExtension, m_DataLen - offsetForNewExtension, extensionType, extensionContent); } - return (GtpV1MessageType)header->messageType; -} + GtpV1MessageType GtpV1Layer::getMessageType() const + { + gtpv1_header* header = getHeader(); -std::unordered_map createGtpV1MessageTypeToStringMap() -{ - std::unordered_map tempMap; - - tempMap[0] = "GTPv1 Message Type Unknown"; - tempMap[1] = "Echo Request"; - tempMap[2] = "Echo Response"; - tempMap[3] = "Version Not Supported"; - tempMap[4] = "Node Alive Request"; - tempMap[5] = "Node Alive Response"; - tempMap[6] = "Redirection Request"; - tempMap[7] = "Create PDP Context Request"; - tempMap[16] = "Create PDP Context Response"; - tempMap[17] = "Update PDP Context Request"; - tempMap[18] = "Update PDP Context Response"; - tempMap[19] = "Delete PDP Context Request"; - tempMap[20] = "Delete PDP Context Response"; - tempMap[22] = "Initiate PDP Context Activation Request"; - tempMap[23] = "Initiate PDP Context Activation Response"; - tempMap[26] = "Error Indication"; - tempMap[27] = "PDU Notification Request"; - tempMap[28] = "PDU Notification Response"; - tempMap[29] = "PDU Notification Reject Request"; - tempMap[30] = "PDU Notification Reject Response"; - tempMap[31] = "Supported Extensions Header Notification"; - tempMap[32] = "Send Routing for GPRS Request"; - tempMap[33] = "Send Routing for GPRS Response"; - tempMap[34] = "Failure Report Request"; - tempMap[35] = "Failure Report Response"; - tempMap[36] = "Note MS Present Request"; - tempMap[37] = "Note MS Present Response"; - tempMap[38] = "Identification Request"; - tempMap[39] = "Identification Response"; - tempMap[50] = "SGSN Context Request"; - tempMap[51] = "SGSN Context Response"; - tempMap[52] = "SGSN Context Acknowledge"; - tempMap[53] = "Forward Relocation Request"; - tempMap[54] = "Forward Relocation Response"; - tempMap[55] = "Forward Relocation Complete"; - tempMap[56] = "Relocation Cancel Request"; - tempMap[57] = "Relocation Cancel Response"; - tempMap[58] = "Forward SRNS Context"; - tempMap[59] = "Forward Relocation Complete Acknowledge"; - tempMap[60] = "Forward SRNS Context Acknowledge"; - tempMap[61] = "UE Registration Request"; - tempMap[62] = "UE Registration Response"; - tempMap[70] = "RAN Information Relay"; - tempMap[96] = "MBMS Notification Request"; - tempMap[97] = "MBMS Notification Response"; - tempMap[98] = "MBMS Notification Reject Request"; - tempMap[99] = "MBMS Notification Reject Response"; - tempMap[100] = "Create MBMS Notification Request"; - tempMap[101] = "Create MBMS Notification Response"; - tempMap[102] = "Update MBMS Notification Request"; - tempMap[103] = "Update MBMS Notification Response"; - tempMap[104] = "Delete MBMS Notification Request"; - tempMap[105] = "Delete MBMS Notification Response"; - tempMap[112] = "MBMS Registration Request"; - tempMap[113] = "MBMS Registration Response"; - tempMap[114] = "MBMS De-Registration Request"; - tempMap[115] = "MBMS De-Registration Response"; - tempMap[116] = "MBMS Session Start Request"; - tempMap[117] = "MBMS Session Start Response"; - tempMap[118] = "MBMS Session Stop Request"; - tempMap[119] = "MBMS Session Stop Response"; - tempMap[120] = "MBMS Session Update Request"; - tempMap[121] = "MBMS Session Update Response"; - tempMap[128] = "MS Info Change Request"; - tempMap[129] = "MS Info Change Response"; - tempMap[240] = "Data Record Transfer Request"; - tempMap[241] = "Data Record Transfer Response"; - tempMap[254] = "End Marker"; - tempMap[255] = "G-PDU"; - - return tempMap; -} - -const std::unordered_map GTPv1MsgTypeToStringMap = createGtpV1MessageTypeToStringMap(); - -std::string GtpV1Layer::getMessageTypeAsString() const -{ - gtpv1_header* header = getHeader(); + if (header == nullptr) + { + return GtpV1_MessageTypeUnknown; + } - if (header == nullptr) - { - return GTPv1MsgTypeToStringMap.find(0)->second; - } + return (GtpV1MessageType)header->messageType; + } + + std::unordered_map createGtpV1MessageTypeToStringMap() + { + std::unordered_map tempMap; + + tempMap[0] = "GTPv1 Message Type Unknown"; + tempMap[1] = "Echo Request"; + tempMap[2] = "Echo Response"; + tempMap[3] = "Version Not Supported"; + tempMap[4] = "Node Alive Request"; + tempMap[5] = "Node Alive Response"; + tempMap[6] = "Redirection Request"; + tempMap[7] = "Create PDP Context Request"; + tempMap[16] = "Create PDP Context Response"; + tempMap[17] = "Update PDP Context Request"; + tempMap[18] = "Update PDP Context Response"; + tempMap[19] = "Delete PDP Context Request"; + tempMap[20] = "Delete PDP Context Response"; + tempMap[22] = "Initiate PDP Context Activation Request"; + tempMap[23] = "Initiate PDP Context Activation Response"; + tempMap[26] = "Error Indication"; + tempMap[27] = "PDU Notification Request"; + tempMap[28] = "PDU Notification Response"; + tempMap[29] = "PDU Notification Reject Request"; + tempMap[30] = "PDU Notification Reject Response"; + tempMap[31] = "Supported Extensions Header Notification"; + tempMap[32] = "Send Routing for GPRS Request"; + tempMap[33] = "Send Routing for GPRS Response"; + tempMap[34] = "Failure Report Request"; + tempMap[35] = "Failure Report Response"; + tempMap[36] = "Note MS Present Request"; + tempMap[37] = "Note MS Present Response"; + tempMap[38] = "Identification Request"; + tempMap[39] = "Identification Response"; + tempMap[50] = "SGSN Context Request"; + tempMap[51] = "SGSN Context Response"; + tempMap[52] = "SGSN Context Acknowledge"; + tempMap[53] = "Forward Relocation Request"; + tempMap[54] = "Forward Relocation Response"; + tempMap[55] = "Forward Relocation Complete"; + tempMap[56] = "Relocation Cancel Request"; + tempMap[57] = "Relocation Cancel Response"; + tempMap[58] = "Forward SRNS Context"; + tempMap[59] = "Forward Relocation Complete Acknowledge"; + tempMap[60] = "Forward SRNS Context Acknowledge"; + tempMap[61] = "UE Registration Request"; + tempMap[62] = "UE Registration Response"; + tempMap[70] = "RAN Information Relay"; + tempMap[96] = "MBMS Notification Request"; + tempMap[97] = "MBMS Notification Response"; + tempMap[98] = "MBMS Notification Reject Request"; + tempMap[99] = "MBMS Notification Reject Response"; + tempMap[100] = "Create MBMS Notification Request"; + tempMap[101] = "Create MBMS Notification Response"; + tempMap[102] = "Update MBMS Notification Request"; + tempMap[103] = "Update MBMS Notification Response"; + tempMap[104] = "Delete MBMS Notification Request"; + tempMap[105] = "Delete MBMS Notification Response"; + tempMap[112] = "MBMS Registration Request"; + tempMap[113] = "MBMS Registration Response"; + tempMap[114] = "MBMS De-Registration Request"; + tempMap[115] = "MBMS De-Registration Response"; + tempMap[116] = "MBMS Session Start Request"; + tempMap[117] = "MBMS Session Start Response"; + tempMap[118] = "MBMS Session Stop Request"; + tempMap[119] = "MBMS Session Stop Response"; + tempMap[120] = "MBMS Session Update Request"; + tempMap[121] = "MBMS Session Update Response"; + tempMap[128] = "MS Info Change Request"; + tempMap[129] = "MS Info Change Response"; + tempMap[240] = "Data Record Transfer Request"; + tempMap[241] = "Data Record Transfer Response"; + tempMap[254] = "End Marker"; + tempMap[255] = "G-PDU"; + + return tempMap; + } + + const std::unordered_map GTPv1MsgTypeToStringMap = createGtpV1MessageTypeToStringMap(); + + std::string GtpV1Layer::getMessageTypeAsString() const + { + gtpv1_header* header = getHeader(); + + if (header == nullptr) + { + return GTPv1MsgTypeToStringMap.find(0)->second; + } - std::unordered_map::const_iterator iter = GTPv1MsgTypeToStringMap.find(header->messageType); - if (iter != GTPv1MsgTypeToStringMap.end()) - { - return iter->second; - } - else - { - return GTPv1MsgTypeToStringMap.find(0)->second; + std::unordered_map::const_iterator iter = + GTPv1MsgTypeToStringMap.find(header->messageType); + if (iter != GTPv1MsgTypeToStringMap.end()) + { + return iter->second; + } + else + { + return GTPv1MsgTypeToStringMap.find(0)->second; + } } -} -bool GtpV1Layer::isGTPUMessage() const -{ - gtpv1_header* header = getHeader(); - if (header == nullptr) + bool GtpV1Layer::isGTPUMessage() const { - return false; - } - - return header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE; -} + gtpv1_header* header = getHeader(); + if (header == nullptr) + { + return false; + } -bool GtpV1Layer::isGTPCMessage() const -{ - gtpv1_header* header = getHeader(); - if (header == nullptr) - { - return false; + return header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE; } - return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE; -} - - -void GtpV1Layer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (headerLen < sizeof(gtpv1_header)) + bool GtpV1Layer::isGTPCMessage() const { - // do nothing - return; - } + gtpv1_header* header = getHeader(); + if (header == nullptr) + { + return false; + } - gtpv1_header* header = getHeader(); - if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE) - { - // this is a GTP-C message, hence it is the last layer - return; + return header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE; } - if (m_DataLen <= headerLen) + void GtpV1Layer::parseNextLayer() { - // no data beyond headerLen, nothing to parse further - return; - } + size_t headerLen = getHeaderLen(); + if (headerLen < sizeof(gtpv1_header)) + { + // do nothing + return; + } - // GTP-U message, try to parse the next layer + gtpv1_header* header = getHeader(); + if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE) + { + // this is a GTP-C message, hence it is the last layer + return; + } - uint8_t* payload = (uint8_t*)(m_Data + headerLen); - size_t payloadLen = m_DataLen - headerLen; + if (m_DataLen <= headerLen) + { + // no data beyond headerLen, nothing to parse further + return; + } - uint8_t subProto = *payload; - if (subProto >= 0x45 && subProto <= 0x4e) - { - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - } - else if ((subProto & 0xf0) == 0x60) - { - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - } - else - { - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + // GTP-U message, try to parse the next layer + + uint8_t* payload = (uint8_t*)(m_Data + headerLen); + size_t payloadLen = m_DataLen - headerLen; + + uint8_t subProto = *payload; + if (subProto >= 0x45 && subProto <= 0x4e) + { + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + } + else if ((subProto & 0xf0) == 0x60) + { + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + } + else + { + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } } -} -size_t GtpV1Layer::getHeaderLen() const -{ - gtpv1_header* header = getHeader(); - if (header == nullptr) + size_t GtpV1Layer::getHeaderLen() const { - return 0; - } + gtpv1_header* header = getHeader(); + if (header == nullptr) + { + return 0; + } - size_t res = sizeof(gtpv1_header); + size_t res = sizeof(gtpv1_header); - if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE) - { - size_t msgLen = be16toh(header->messageLength); - res += (msgLen > m_DataLen - sizeof(gtpv1_header) ? m_DataLen - sizeof(gtpv1_header) : msgLen); - } - else - { - gtpv1_header_extra* headerExtra = getHeaderExtra(); - if (headerExtra != nullptr && (header->extensionHeaderFlag == 1 || header->sequenceNumberFlag == 1 || header->npduNumberFlag == 1)) + if (header->messageType != PCPP_GTP_V1_GPDU_MESSAGE_TYPE) + { + size_t msgLen = be16toh(header->messageLength); + res += (msgLen > m_DataLen - sizeof(gtpv1_header) ? m_DataLen - sizeof(gtpv1_header) : msgLen); + } + else { - res += sizeof(gtpv1_header_extra); - GtpExtension nextExt = getNextExtension(); - while (!nextExt.isNull()) + gtpv1_header_extra* headerExtra = getHeaderExtra(); + if (headerExtra != nullptr && + (header->extensionHeaderFlag == 1 || header->sequenceNumberFlag == 1 || header->npduNumberFlag == 1)) { - res += nextExt.getTotalLength(); - nextExt = nextExt.getNextExtension(); + res += sizeof(gtpv1_header_extra); + GtpExtension nextExt = getNextExtension(); + while (!nextExt.isNull()) + { + res += nextExt.getTotalLength(); + nextExt = nextExt.getNextExtension(); + } } } - } - return res; -} - -std::string GtpV1Layer::toString() const -{ - std::string res = "GTP v1 Layer"; + return res; + } - gtpv1_header* header = getHeader(); - if (header != nullptr) + std::string GtpV1Layer::toString() const { - std::stringstream teidStream; - teidStream << be32toh(header->teid); + std::string res = "GTP v1 Layer"; - std::string gtpu_gtpc; - if (header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE) - { - gtpu_gtpc = "GTP-U message"; - } - else + gtpv1_header* header = getHeader(); + if (header != nullptr) { - gtpu_gtpc = "GTP-C message: " + getMessageTypeAsString(); + std::stringstream teidStream; + teidStream << be32toh(header->teid); + + std::string gtpu_gtpc; + if (header->messageType == PCPP_GTP_V1_GPDU_MESSAGE_TYPE) + { + gtpu_gtpc = "GTP-U message"; + } + else + { + gtpu_gtpc = "GTP-C message: " + getMessageTypeAsString(); + } + + res += ", " + gtpu_gtpc + ", TEID: " + teidStream.str(); } - res += ", " + gtpu_gtpc + ", TEID: " + teidStream.str(); + return res; } - return res; -} - -void GtpV1Layer::computeCalculateFields() -{ - gtpv1_header* hdr = getHeader(); - if (hdr == nullptr) + void GtpV1Layer::computeCalculateFields() { - return; - } + gtpv1_header* hdr = getHeader(); + if (hdr == nullptr) + { + return; + } - hdr->messageLength = htobe16(m_DataLen - sizeof(gtpv1_header)); -} + hdr->messageLength = htobe16(m_DataLen - sizeof(gtpv1_header)); + } -} +} // namespace pcpp diff --git a/Packet++/src/HttpLayer.cpp b/Packet++/src/HttpLayer.cpp index b7fc02721a..c3949b9c3f 100644 --- a/Packet++/src/HttpLayer.cpp +++ b/Packet++/src/HttpLayer.cpp @@ -13,999 +13,980 @@ namespace pcpp { + // -------- Class HttpMessage ----------------- -// -------- Class HttpMessage ----------------- + HeaderField* HttpMessage::addField(const std::string& fieldName, const std::string& fieldValue) + { + if (getFieldByName(fieldName) != nullptr) + { + PCPP_LOG_ERROR("Field '" << fieldName << "' already exists!"); + return nullptr; + } + return TextBasedProtocolMessage::addField(fieldName, fieldValue); + } -HeaderField* HttpMessage::addField(const std::string& fieldName, const std::string& fieldValue) -{ - if (getFieldByName(fieldName) != nullptr) + HeaderField* HttpMessage::addField(const HeaderField& newField) { - PCPP_LOG_ERROR("Field '" << fieldName << "' already exists!"); - return nullptr; - } + if (getFieldByName(newField.getFieldName()) != nullptr) + { + PCPP_LOG_ERROR("Field '" << newField.getFieldName() << "' already exists!"); + return nullptr; + } - return TextBasedProtocolMessage::addField(fieldName, fieldValue); -} + return TextBasedProtocolMessage::addField(newField); + } -HeaderField* HttpMessage::addField(const HeaderField& newField) -{ - if (getFieldByName(newField.getFieldName()) != nullptr) + HeaderField* HttpMessage::insertField(HeaderField* prevField, const std::string& fieldName, + const std::string& fieldValue) { - PCPP_LOG_ERROR("Field '" << newField.getFieldName() << "' already exists!"); - return nullptr; - } + if (getFieldByName(fieldName) != nullptr) + { + PCPP_LOG_ERROR("Field '" << fieldName << "' already exists!"); + return nullptr; + } - return TextBasedProtocolMessage::addField(newField); -} + return TextBasedProtocolMessage::insertField(prevField, fieldName, fieldValue); + } -HeaderField* HttpMessage::insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue) -{ - if (getFieldByName(fieldName) != nullptr) + HeaderField* HttpMessage::insertField(HeaderField* prevField, const HeaderField& newField) { - PCPP_LOG_ERROR("Field '" << fieldName << "' already exists!"); - return nullptr; + if (getFieldByName(newField.getFieldName()) != nullptr) + { + PCPP_LOG_ERROR("Field '" << newField.getFieldName() << "' already exists!"); + return nullptr; + } + + return TextBasedProtocolMessage::insertField(prevField, newField); } - return TextBasedProtocolMessage::insertField(prevField, fieldName, fieldValue); -} + // -------- Class HttpRequestLayer ----------------- -HeaderField* HttpMessage::insertField(HeaderField* prevField, const HeaderField& newField) -{ - if (getFieldByName(newField.getFieldName()) != nullptr) + HttpRequestLayer::HttpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : HttpMessage(data, dataLen, prevLayer, packet) { - PCPP_LOG_ERROR("Field '" << newField.getFieldName() << "' already exists!"); - return nullptr; + m_Protocol = HTTPRequest; + m_FirstLine = new HttpRequestFirstLine(this); + m_FieldsOffset = m_FirstLine->getSize(); + parseFields(); } - return TextBasedProtocolMessage::insertField(prevField, newField); -} + HttpRequestLayer::HttpRequestLayer(HttpMethod method, const std::string& uri, HttpVersion version) + { + m_Protocol = HTTPRequest; + m_FirstLine = new HttpRequestFirstLine(this, method, version, uri); + m_FieldsOffset = m_FirstLine->getSize(); + } + HttpRequestLayer::HttpRequestLayer(const HttpRequestLayer& other) : HttpMessage(other) + { + m_FirstLine = new HttpRequestFirstLine(this); + } + HttpRequestLayer& HttpRequestLayer::operator=(const HttpRequestLayer& other) + { + HttpMessage::operator=(other); -// -------- Class HttpRequestLayer ----------------- + if (m_FirstLine != nullptr) + delete m_FirstLine; -HttpRequestLayer::HttpRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : HttpMessage(data, dataLen, prevLayer, packet) -{ - m_Protocol = HTTPRequest; - m_FirstLine = new HttpRequestFirstLine(this); - m_FieldsOffset = m_FirstLine->getSize(); - parseFields(); -} + m_FirstLine = new HttpRequestFirstLine(this); -HttpRequestLayer::HttpRequestLayer(HttpMethod method, const std::string& uri, HttpVersion version) -{ - m_Protocol = HTTPRequest; - m_FirstLine = new HttpRequestFirstLine(this, method, version, uri); - m_FieldsOffset = m_FirstLine->getSize(); -} + return *this; + } -HttpRequestLayer::HttpRequestLayer(const HttpRequestLayer& other) : HttpMessage(other) -{ - m_FirstLine = new HttpRequestFirstLine(this); -} + std::string HttpRequestLayer::getUrl() const + { + HeaderField* hostField = getFieldByName(PCPP_HTTP_HOST_FIELD); + if (hostField == nullptr) + return m_FirstLine->getUri(); -HttpRequestLayer& HttpRequestLayer::operator=(const HttpRequestLayer& other) -{ - HttpMessage::operator=(other); + return hostField->getFieldValue() + m_FirstLine->getUri(); + } - if (m_FirstLine != nullptr) + HttpRequestLayer::~HttpRequestLayer() + { delete m_FirstLine; + } - m_FirstLine = new HttpRequestFirstLine(this); - - return *this; -} - - -std::string HttpRequestLayer::getUrl() const -{ - HeaderField* hostField = getFieldByName(PCPP_HTTP_HOST_FIELD); - if (hostField == nullptr) - return m_FirstLine->getUri(); - - return hostField->getFieldValue() + m_FirstLine->getUri(); -} - -HttpRequestLayer::~HttpRequestLayer() -{ - delete m_FirstLine; -} - -std::string HttpRequestLayer::toString() const -{ - static const int maxLengthToPrint = 120; - std::string result = "HTTP request, "; - int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line - if (size <= 0) + std::string HttpRequestLayer::toString() const { - result += std::string("CORRUPT DATA"); + static const int maxLengthToPrint = 120; + std::string result = "HTTP request, "; + int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line + if (size <= 0) + { + result += std::string("CORRUPT DATA"); + return result; + } + if (size <= maxLengthToPrint) + { + char* firstLine = new char[size + 1]; + strncpy(firstLine, (char*)m_Data, size); + firstLine[size] = 0; + result += std::string(firstLine); + delete[] firstLine; + } + else + { + char firstLine[maxLengthToPrint + 1]; + strncpy(firstLine, (char*)m_Data, maxLengthToPrint - 3); + firstLine[maxLengthToPrint - 3] = '.'; + firstLine[maxLengthToPrint - 2] = '.'; + firstLine[maxLengthToPrint - 1] = '.'; + firstLine[maxLengthToPrint] = 0; + result += std::string(firstLine); + } + return result; } - if (size <= maxLengthToPrint) - { - char* firstLine = new char[size+1]; - strncpy(firstLine, (char*)m_Data, size); - firstLine[size] = 0; - result += std::string(firstLine); - delete[] firstLine; - } - else - { - char firstLine[maxLengthToPrint+1]; - strncpy(firstLine, (char*)m_Data, maxLengthToPrint-3); - firstLine[maxLengthToPrint-3] = '.'; - firstLine[maxLengthToPrint-2] = '.'; - firstLine[maxLengthToPrint-1] = '.'; - firstLine[maxLengthToPrint] = 0; - result += std::string(firstLine); - } - - return result; -} + // -------- Class HttpRequestFirstLine ----------------- + const std::string MethodEnumToString[9] = { "GET", "HEAD", "POST", "PUT", "DELETE", + "TRACE", "OPTIONS", "CONNECT", "PATCH" }; + const std::unordered_map HttpMethodStringToEnum{ + { "GET", HttpRequestLayer::HttpMethod::HttpGET }, + { "HEAD", HttpRequestLayer::HttpMethod::HttpHEAD }, + { "POST", HttpRequestLayer::HttpMethod::HttpPOST }, + { "PUT", HttpRequestLayer::HttpMethod::HttpPUT }, + { "DELETE", HttpRequestLayer::HttpMethod::HttpDELETE }, + { "TRACE", HttpRequestLayer::HttpMethod::HttpTRACE }, + { "OPTIONS", HttpRequestLayer::HttpMethod::HttpOPTIONS }, + { "CONNECT", HttpRequestLayer::HttpMethod::HttpCONNECT }, + { "PATCH", HttpRequestLayer::HttpMethod::HttpPATCH } + }; + const std::string VersionEnumToString[3] = { "0.9", "1.0", "1.1" }; + // clang-format off + const std::unordered_map HttpVersionStringToEnum{ + { "0.9", HttpVersion::ZeroDotNine }, + { "1.0", HttpVersion::OneDotZero }, + { "1.1", HttpVersion::OneDotOne } + }; + // clang-format on + HttpRequestFirstLine::HttpRequestFirstLine(HttpRequestLayer* httpRequest) : m_HttpRequest(httpRequest) + { + m_Method = parseMethod((char*)m_HttpRequest->m_Data, m_HttpRequest->getDataLen()); + if (m_Method == HttpRequestLayer::HttpMethodUnknown) + { + m_UriOffset = -1; + PCPP_LOG_DEBUG("Couldn't resolve HTTP request method"); + m_IsComplete = false; + m_Version = HttpVersionUnknown; + m_VersionOffset = -1; + m_FirstLineEndOffset = m_HttpRequest->getDataLen(); + return; + } + else + { + m_UriOffset = MethodEnumToString[m_Method].length() + 1; + } + parseVersion(); + if (m_VersionOffset < 0) + { + m_IsComplete = false; + m_FirstLineEndOffset = m_HttpRequest->getDataLen(); + return; + } -// -------- Class HttpRequestFirstLine ----------------- + char* endOfFirstLine; + if ((endOfFirstLine = (char*)memchr((char*)(m_HttpRequest->m_Data + m_VersionOffset), '\n', + m_HttpRequest->m_DataLen - (size_t)m_VersionOffset)) != nullptr) + { + m_FirstLineEndOffset = endOfFirstLine - (char*)m_HttpRequest->m_Data + 1; + m_IsComplete = true; + } + else + { + m_FirstLineEndOffset = m_HttpRequest->getDataLen(); + m_IsComplete = false; + } + if (Logger::getInstance().isDebugEnabled(PacketLogModuleHttpLayer)) + { + std::string method = + m_Method == HttpRequestLayer::HttpMethodUnknown ? "Unknown" : MethodEnumToString[m_Method]; + PCPP_LOG_DEBUG("Method='" << method << "'; " + << "HTTP version='" << VersionEnumToString[m_Version] << "'; " + << "URI='" << getUri() << "'"); + } + } -const std::string MethodEnumToString[9] = { - "GET", - "HEAD", - "POST", - "PUT", - "DELETE", - "TRACE", - "OPTIONS", - "CONNECT", - "PATCH" -}; + HttpRequestFirstLine::HttpRequestFirstLine(HttpRequestLayer* httpRequest, HttpRequestLayer::HttpMethod method, + HttpVersion version, const std::string& uri) + { + try // throw(HttpRequestFirstLineException) + { + if (method == HttpRequestLayer::HttpMethodUnknown) + { + m_Exception.setMessage("Method supplied was HttpMethodUnknown"); + throw m_Exception; + } -const std::unordered_map HttpMethodStringToEnum { - {"GET", HttpRequestLayer::HttpMethod::HttpGET }, - {"HEAD", HttpRequestLayer::HttpMethod::HttpHEAD }, - {"POST", HttpRequestLayer::HttpMethod::HttpPOST }, - {"PUT", HttpRequestLayer::HttpMethod::HttpPUT }, - {"DELETE", HttpRequestLayer::HttpMethod::HttpDELETE }, - {"TRACE", HttpRequestLayer::HttpMethod::HttpTRACE }, - {"OPTIONS", HttpRequestLayer::HttpMethod::HttpOPTIONS }, - {"CONNECT", HttpRequestLayer::HttpMethod::HttpCONNECT }, - {"PATCH", HttpRequestLayer::HttpMethod::HttpPATCH } -}; + if (version == HttpVersionUnknown) + { + m_Exception.setMessage("Version supplied was HttpVersionUnknown"); + throw m_Exception; + } -const std::string VersionEnumToString[3] = { - "0.9", - "1.0", - "1.1" -}; + m_HttpRequest = httpRequest; -const std::unordered_map HttpVersionStringToEnum { - { "0.9", HttpVersion::ZeroDotNine }, - { "1.0", HttpVersion::OneDotZero }, - { "1.1", HttpVersion::OneDotOne } -}; + m_Method = method; + m_Version = version; + std::string firstLine = + MethodEnumToString[m_Method] + " " + uri + " " + "HTTP/" + VersionEnumToString[m_Version] + "\r\n"; -HttpRequestFirstLine::HttpRequestFirstLine(HttpRequestLayer* httpRequest) : m_HttpRequest(httpRequest) -{ - m_Method = parseMethod((char*)m_HttpRequest->m_Data, m_HttpRequest->getDataLen()); - if (m_Method == HttpRequestLayer::HttpMethodUnknown) - { - m_UriOffset = -1; - PCPP_LOG_DEBUG("Couldn't resolve HTTP request method"); - m_IsComplete = false; - m_Version = HttpVersionUnknown; - m_VersionOffset = -1; - m_FirstLineEndOffset = m_HttpRequest->getDataLen(); - return; - } - else - m_UriOffset = MethodEnumToString[m_Method].length() + 1; + m_UriOffset = MethodEnumToString[m_Method].length() + 1; + m_FirstLineEndOffset = firstLine.length(); + m_VersionOffset = m_UriOffset + uri.length() + 6; - parseVersion(); - if(m_VersionOffset < 0) - { - m_IsComplete = false; - m_FirstLineEndOffset = m_HttpRequest->getDataLen(); - return; - } + m_HttpRequest->m_DataLen = firstLine.length(); + m_HttpRequest->m_Data = new uint8_t[m_HttpRequest->m_DataLen]; + memcpy(m_HttpRequest->m_Data, firstLine.c_str(), m_HttpRequest->m_DataLen); - char* endOfFirstLine; - if ((endOfFirstLine = (char*)memchr((char*)(m_HttpRequest->m_Data + m_VersionOffset), '\n', m_HttpRequest->m_DataLen-(size_t)m_VersionOffset)) != nullptr) - { - m_FirstLineEndOffset = endOfFirstLine - (char*)m_HttpRequest->m_Data + 1; - m_IsComplete = true; - } - else - { - m_FirstLineEndOffset = m_HttpRequest->getDataLen(); - m_IsComplete = false; - } - - if (Logger::getInstance().isDebugEnabled(PacketLogModuleHttpLayer)) - { - std::string method = m_Method == HttpRequestLayer::HttpMethodUnknown? "Unknown" : MethodEnumToString[m_Method]; - PCPP_LOG_DEBUG( - "Method='" << method << "'; " - << "HTTP version='" << VersionEnumToString[m_Version] << "'; " - << "URI='" << getUri() << "'"); + m_IsComplete = true; + } + catch (const HttpRequestFirstLineException&) + { + throw; + } + catch (...) + { + std::terminate(); + } } -} -HttpRequestFirstLine::HttpRequestFirstLine(HttpRequestLayer* httpRequest, HttpRequestLayer::HttpMethod method, HttpVersion version, const std::string &uri) -{ - try // throw(HttpRequestFirstLineException) + HttpRequestLayer::HttpMethod HttpRequestFirstLine::parseMethod(const char* data, size_t dataLen) { - if (method == HttpRequestLayer::HttpMethodUnknown) + if (!data || dataLen < 4) { - m_Exception.setMessage("Method supplied was HttpMethodUnknown"); - throw m_Exception; + return HttpRequestLayer::HttpMethodUnknown; } - if (version == HttpVersionUnknown) + size_t spaceIndex = 0; + while (spaceIndex < dataLen && data[spaceIndex] != ' ') { - m_Exception.setMessage("Version supplied was HttpVersionUnknown"); - throw m_Exception; + spaceIndex++; } - m_HttpRequest = httpRequest; + if (spaceIndex == 0 || spaceIndex == dataLen) + { + return HttpRequestLayer::HttpMethodUnknown; + } - m_Method = method; - m_Version = version; + auto methodAdEnum = HttpMethodStringToEnum.find(std::string(data, data + spaceIndex)); + if (methodAdEnum == HttpMethodStringToEnum.end()) + { + return HttpRequestLayer::HttpMethodUnknown; + } + return methodAdEnum->second; + } - std::string firstLine = MethodEnumToString[m_Method] + " " + uri + " " + "HTTP/" + VersionEnumToString[m_Version] + "\r\n"; + void HttpRequestFirstLine::parseVersion() + { + char* data = (char*)(m_HttpRequest->m_Data + m_UriOffset); + char* verPos = cross_platform_memmem(data, m_HttpRequest->getDataLen() - m_UriOffset, " HTTP/", 6); + if (verPos == nullptr) + { + m_Version = HttpVersionUnknown; + m_VersionOffset = -1; + return; + } - m_UriOffset = MethodEnumToString[m_Method].length() + 1; - m_FirstLineEndOffset = firstLine.length(); - m_VersionOffset = m_UriOffset + uri.length() + 6; + // verify packet doesn't end before the version, meaning still left place for " HTTP/x.y" (9 chars) + std::ptrdiff_t actualLen = verPos + 9 - (char*)m_HttpRequest->m_Data; + if (static_cast(actualLen) > m_HttpRequest->getDataLen()) + { + m_Version = HttpVersionUnknown; + m_VersionOffset = -1; + return; + } - m_HttpRequest->m_DataLen = firstLine.length(); - m_HttpRequest->m_Data = new uint8_t[m_HttpRequest->m_DataLen]; - memcpy(m_HttpRequest->m_Data, firstLine.c_str(), m_HttpRequest->m_DataLen); + // skip " HTTP/" (6 chars) + verPos += 6; + auto versionAsEnum = HttpVersionStringToEnum.find(std::string(verPos, verPos + 3)); + if (versionAsEnum == HttpVersionStringToEnum.end()) + { + m_Version = HttpVersionUnknown; + } + else + { + m_Version = versionAsEnum->second; + } - m_IsComplete = true; - } - catch(const HttpRequestFirstLineException&) - { - throw; - } - catch(...) - { - std::terminate(); + m_VersionOffset = verPos - (char*)m_HttpRequest->m_Data; } -} -HttpRequestLayer::HttpMethod HttpRequestFirstLine::parseMethod(const char* data, size_t dataLen) -{ - if (!data || dataLen < 4) + bool HttpRequestFirstLine::setMethod(HttpRequestLayer::HttpMethod newMethod) { - return HttpRequestLayer::HttpMethodUnknown; - } + if (newMethod == HttpRequestLayer::HttpMethodUnknown) + { + PCPP_LOG_ERROR("Requested method is HttpMethodUnknown"); + return false; + } - size_t spaceIndex = 0; - while (spaceIndex < dataLen && data[spaceIndex] != ' ' ) - { - spaceIndex++; - } + // extend or shorten layer + int lengthDifference = MethodEnumToString[newMethod].length() - MethodEnumToString[m_Method].length(); + if (lengthDifference > 0) + { + if (!m_HttpRequest->extendLayer(0, lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } + else if (lengthDifference < 0) + { + if (!m_HttpRequest->shortenLayer(0, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } - if (spaceIndex == 0 || spaceIndex == dataLen) - { - return HttpRequestLayer::HttpMethodUnknown; - } + if (lengthDifference != 0) + m_HttpRequest->shiftFieldsOffset(m_HttpRequest->getFirstField(), lengthDifference); - auto methodAdEnum = HttpMethodStringToEnum.find(std::string(data, data + spaceIndex)); - if (methodAdEnum == HttpMethodStringToEnum.end()) - { - return HttpRequestLayer::HttpMethodUnknown; - } - return methodAdEnum->second; -} + memcpy(m_HttpRequest->m_Data, MethodEnumToString[newMethod].c_str(), MethodEnumToString[newMethod].length()); -void HttpRequestFirstLine::parseVersion() -{ - char* data = (char*)(m_HttpRequest->m_Data + m_UriOffset); - char* verPos = cross_platform_memmem(data, m_HttpRequest->getDataLen() - m_UriOffset, " HTTP/", 6); - if (verPos == nullptr) - { - m_Version = HttpVersionUnknown; - m_VersionOffset = -1; - return; - } + m_Method = newMethod; + m_UriOffset += lengthDifference; + m_VersionOffset += lengthDifference; - // verify packet doesn't end before the version, meaning still left place for " HTTP/x.y" (9 chars) - std::ptrdiff_t actualLen = verPos + 9 - (char*)m_HttpRequest->m_Data; - if (static_cast(actualLen) > m_HttpRequest->getDataLen()) - { - m_Version = HttpVersionUnknown; - m_VersionOffset = -1; - return; + return true; } - //skip " HTTP/" (6 chars) - verPos += 6; - auto versionAsEnum = HttpVersionStringToEnum.find(std::string(verPos, verPos + 3)); - if (versionAsEnum == HttpVersionStringToEnum.end()) + std::string HttpRequestFirstLine::getUri() const { - m_Version = HttpVersionUnknown; - } - else - { - m_Version = versionAsEnum->second; - } + std::string result; + if (m_UriOffset != -1 && m_VersionOffset != -1) + result.assign((const char*)m_HttpRequest->m_Data + m_UriOffset, m_VersionOffset - 6 - m_UriOffset); - m_VersionOffset = verPos - (char*)m_HttpRequest->m_Data; -} + // else first line is illegal, return empty string -bool HttpRequestFirstLine::setMethod(HttpRequestLayer::HttpMethod newMethod) -{ - if (newMethod == HttpRequestLayer::HttpMethodUnknown) - { - PCPP_LOG_ERROR("Requested method is HttpMethodUnknown"); - return false; + return result; } - //extend or shorten layer - int lengthDifference = MethodEnumToString[newMethod].length() - MethodEnumToString[m_Method].length(); - if (lengthDifference > 0) + bool HttpRequestFirstLine::setUri(std::string newUri) { - if (!m_HttpRequest->extendLayer(0, lengthDifference)) + // make sure the new URI begins with "/" + if (newUri.compare(0, 1, "/") != 0) + newUri = "/" + newUri; + + // extend or shorten layer + std::string currentUri = getUri(); + int lengthDifference = newUri.length() - currentUri.length(); + if (lengthDifference > 0) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + if (!m_HttpRequest->extendLayer(m_UriOffset, lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } } - } - else if (lengthDifference < 0) - { - if (!m_HttpRequest->shortenLayer(0, 0-lengthDifference)) + else if (lengthDifference < 0) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; - + if (!m_HttpRequest->shortenLayer(m_UriOffset, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } } - } - - if (lengthDifference != 0) - m_HttpRequest->shiftFieldsOffset(m_HttpRequest->getFirstField(), lengthDifference); - - memcpy(m_HttpRequest->m_Data, MethodEnumToString[newMethod].c_str(), MethodEnumToString[newMethod].length()); - m_Method = newMethod; - m_UriOffset += lengthDifference; - m_VersionOffset += lengthDifference; - - return true; -} - -std::string HttpRequestFirstLine::getUri() const -{ - std::string result; - if (m_UriOffset != -1 && m_VersionOffset != -1) - result.assign((const char*)m_HttpRequest->m_Data + m_UriOffset, m_VersionOffset - 6 - m_UriOffset); - - //else first line is illegal, return empty string - - return result; -} + if (lengthDifference != 0) + m_HttpRequest->shiftFieldsOffset(m_HttpRequest->getFirstField(), lengthDifference); + + memcpy(m_HttpRequest->m_Data + m_UriOffset, newUri.c_str(), newUri.length()); + + m_VersionOffset += lengthDifference; + + return true; + } + + void HttpRequestFirstLine::setVersion(HttpVersion newVersion) + { + if (m_VersionOffset == -1) + return; + + if (newVersion == HttpVersionUnknown) + return; + + char* verPos = (char*)(m_HttpRequest->m_Data + m_VersionOffset); + memcpy(verPos, VersionEnumToString[newVersion].c_str(), 3); + + m_Version = newVersion; + } + + // -------- Class HttpResponseLayer ----------------- + + static const std::unordered_map intStatusCodeMap = { + { 100, HttpResponseStatusCode::Http100Continue }, + { 101, HttpResponseStatusCode::Http101SwitchingProtocols }, + { 102, HttpResponseStatusCode::Http102Processing }, + { 103, HttpResponseStatusCode::Http103EarlyHints }, + { 200, HttpResponseStatusCode::Http200OK }, + { 201, HttpResponseStatusCode::Http201Created }, + { 202, HttpResponseStatusCode::Http202Accepted }, + { 203, HttpResponseStatusCode::Http203NonAuthoritativeInformation }, + { 204, HttpResponseStatusCode::Http204NoContent }, + { 205, HttpResponseStatusCode::Http205ResetContent }, + { 206, HttpResponseStatusCode::Http206PartialContent }, + { 207, HttpResponseStatusCode::Http207MultiStatus }, + { 208, HttpResponseStatusCode::Http208AlreadyReported }, + { 226, HttpResponseStatusCode::Http226IMUsed }, + { 300, HttpResponseStatusCode::Http300MultipleChoices }, + { 301, HttpResponseStatusCode::Http301MovedPermanently }, + { 302, HttpResponseStatusCode::Http302 }, + { 303, HttpResponseStatusCode::Http303SeeOther }, + { 304, HttpResponseStatusCode::Http304NotModified }, + { 305, HttpResponseStatusCode::Http305UseProxy }, + { 306, HttpResponseStatusCode::Http306SwitchProxy }, + { 307, HttpResponseStatusCode::Http307TemporaryRedirect }, + { 308, HttpResponseStatusCode::Http308PermanentRedirect }, + { 400, HttpResponseStatusCode::Http400BadRequest }, + { 401, HttpResponseStatusCode::Http401Unauthorized }, + { 402, HttpResponseStatusCode::Http402PaymentRequired }, + { 403, HttpResponseStatusCode::Http403Forbidden }, + { 404, HttpResponseStatusCode::Http404NotFound }, + { 405, HttpResponseStatusCode::Http405MethodNotAllowed }, + { 406, HttpResponseStatusCode::Http406NotAcceptable }, + { 407, HttpResponseStatusCode::Http407ProxyAuthenticationRequired }, + { 408, HttpResponseStatusCode::Http408RequestTimeout }, + { 409, HttpResponseStatusCode::Http409Conflict }, + { 410, HttpResponseStatusCode::Http410Gone }, + { 411, HttpResponseStatusCode::Http411LengthRequired }, + { 412, HttpResponseStatusCode::Http412PreconditionFailed }, + { 413, HttpResponseStatusCode::Http413RequestEntityTooLarge }, + { 414, HttpResponseStatusCode::Http414RequestURITooLong }, + { 415, HttpResponseStatusCode::Http415UnsupportedMediaType }, + { 416, HttpResponseStatusCode::Http416RequestedRangeNotSatisfiable }, + { 417, HttpResponseStatusCode::Http417ExpectationFailed }, + { 418, HttpResponseStatusCode::Http418ImATeapot }, + { 419, HttpResponseStatusCode::Http419AuthenticationTimeout }, + { 420, HttpResponseStatusCode::Http420 }, + { 421, HttpResponseStatusCode::Http421MisdirectedRequest }, + { 422, HttpResponseStatusCode::Http422UnprocessableEntity }, + { 423, HttpResponseStatusCode::Http423Locked }, + { 424, HttpResponseStatusCode::Http424FailedDependency }, + { 425, HttpResponseStatusCode::Http425TooEarly }, + { 426, HttpResponseStatusCode::Http426UpgradeRequired }, + { 428, HttpResponseStatusCode::Http428PreconditionRequired }, + { 429, HttpResponseStatusCode::Http429TooManyRequests }, + { 431, HttpResponseStatusCode::Http431RequestHeaderFieldsTooLarge }, + { 440, HttpResponseStatusCode::Http440LoginTimeout }, + { 444, HttpResponseStatusCode::Http444NoResponse }, + { 449, HttpResponseStatusCode::Http449RetryWith }, + { 450, HttpResponseStatusCode::Http450BlockedByWindowsParentalControls }, + { 451, HttpResponseStatusCode::Http451 }, + { 494, HttpResponseStatusCode::Http494RequestHeaderTooLarge }, + { 495, HttpResponseStatusCode::Http495CertError }, + { 496, HttpResponseStatusCode::Http496NoCert }, + { 497, HttpResponseStatusCode::Http497HTTPtoHTTPS }, + { 498, HttpResponseStatusCode::Http498TokenExpiredInvalid }, + { 499, HttpResponseStatusCode::Http499 }, + { 500, HttpResponseStatusCode::Http500InternalServerError }, + { 501, HttpResponseStatusCode::Http501NotImplemented }, + { 502, HttpResponseStatusCode::Http502BadGateway }, + { 503, HttpResponseStatusCode::Http503ServiceUnavailable }, + { 504, HttpResponseStatusCode::Http504GatewayTimeout }, + { 505, HttpResponseStatusCode::Http505HTTPVersionNotSupported }, + { 506, HttpResponseStatusCode::Http506VariantAlsoNegotiates }, + { 507, HttpResponseStatusCode::Http507InsufficientStorage }, + { 508, HttpResponseStatusCode::Http508LoopDetected }, + { 509, HttpResponseStatusCode::Http509BandwidthLimitExceeded }, + { 510, HttpResponseStatusCode::Http510NotExtended }, + { 511, HttpResponseStatusCode::Http511NetworkAuthenticationRequired }, + { 520, HttpResponseStatusCode::Http520OriginError }, + { 521, HttpResponseStatusCode::Http521WebServerIsDown }, + { 522, HttpResponseStatusCode::Http522ConnectionTimedOut }, + { 523, HttpResponseStatusCode::Http523ProxyDeclinedRequest }, + { 524, HttpResponseStatusCode::Http524aTimeoutOccurred }, + { 598, HttpResponseStatusCode::Http598NetworkReadTimeoutError }, + { 599, HttpResponseStatusCode::Http599NetworkConnectTimeoutError }, + }; + + HttpResponseStatusCode::HttpResponseStatusCode(const int& statusCodeNumber, const std::string& statusMessage) + { + if (statusMessage != "") + { + m_CustomizedMessage = statusMessage; + } -bool HttpRequestFirstLine::setUri(std::string newUri) -{ - // make sure the new URI begins with "/" - if (newUri.compare(0, 1, "/") != 0) - newUri = "/" + newUri; + if (intStatusCodeMap.find(statusCodeNumber) != intStatusCodeMap.end()) + { + m_Value = intStatusCodeMap.at(statusCodeNumber); + return; + } - //extend or shorten layer - std::string currentUri = getUri(); - int lengthDifference = newUri.length() - currentUri.length(); - if (lengthDifference > 0) - { - if (!m_HttpRequest->extendLayer(m_UriOffset, lengthDifference)) + if (statusCodeNumber >= 100 && statusCodeNumber <= 199) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + m_Value = HttpResponseStatusCode::HttpStatus1xxCodeUnknown; } - } - else if (lengthDifference < 0) - { - if (!m_HttpRequest->shortenLayer(m_UriOffset, 0-lengthDifference)) + else if (statusCodeNumber >= 200 && statusCodeNumber <= 299) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + m_Value = HttpResponseStatusCode::HttpStatus2xxCodeUnknown; + } + else if (statusCodeNumber >= 300 && statusCodeNumber <= 399) + { + m_Value = HttpResponseStatusCode::HttpStatus3xxCodeUnknown; + } + else if (statusCodeNumber >= 400 && statusCodeNumber <= 499) + { + m_Value = HttpResponseStatusCode::HttpStatus4xxCodeUnknown; + } + else if (statusCodeNumber >= 500 && statusCodeNumber <= 599) + { + m_Value = HttpResponseStatusCode::HttpStatus5xxCodeUnknown; } } - if (lengthDifference != 0) - m_HttpRequest->shiftFieldsOffset(m_HttpRequest->getFirstField(), lengthDifference); - - memcpy(m_HttpRequest->m_Data + m_UriOffset, newUri.c_str(), newUri.length()); - - m_VersionOffset += lengthDifference; - - return true; -} - -void HttpRequestFirstLine::setVersion(HttpVersion newVersion) -{ - if (m_VersionOffset == -1) - return; - - if (newVersion == HttpVersionUnknown) - return; - - char* verPos = (char*)(m_HttpRequest->m_Data + m_VersionOffset); - memcpy(verPos, VersionEnumToString[newVersion].c_str(), 3); - - m_Version = newVersion; -} - - - - - - -// -------- Class HttpResponseLayer ----------------- - -static const std::unordered_map intStatusCodeMap = { - {100, HttpResponseStatusCode::Http100Continue}, - {101, HttpResponseStatusCode::Http101SwitchingProtocols}, - {102, HttpResponseStatusCode::Http102Processing}, - {103, HttpResponseStatusCode::Http103EarlyHints}, - {200, HttpResponseStatusCode::Http200OK}, - {201, HttpResponseStatusCode::Http201Created}, - {202, HttpResponseStatusCode::Http202Accepted}, - {203, HttpResponseStatusCode::Http203NonAuthoritativeInformation}, - {204, HttpResponseStatusCode::Http204NoContent}, - {205, HttpResponseStatusCode::Http205ResetContent}, - {206, HttpResponseStatusCode::Http206PartialContent}, - {207, HttpResponseStatusCode::Http207MultiStatus}, - {208, HttpResponseStatusCode::Http208AlreadyReported}, - {226, HttpResponseStatusCode::Http226IMUsed}, - {300, HttpResponseStatusCode::Http300MultipleChoices}, - {301, HttpResponseStatusCode::Http301MovedPermanently}, - {302, HttpResponseStatusCode::Http302}, - {303, HttpResponseStatusCode::Http303SeeOther}, - {304, HttpResponseStatusCode::Http304NotModified}, - {305, HttpResponseStatusCode::Http305UseProxy}, - {306, HttpResponseStatusCode::Http306SwitchProxy}, - {307, HttpResponseStatusCode::Http307TemporaryRedirect}, - {308, HttpResponseStatusCode::Http308PermanentRedirect}, - {400, HttpResponseStatusCode::Http400BadRequest}, - {401, HttpResponseStatusCode::Http401Unauthorized}, - {402, HttpResponseStatusCode::Http402PaymentRequired}, - {403, HttpResponseStatusCode::Http403Forbidden}, - {404, HttpResponseStatusCode::Http404NotFound}, - {405, HttpResponseStatusCode::Http405MethodNotAllowed}, - {406, HttpResponseStatusCode::Http406NotAcceptable}, - {407, HttpResponseStatusCode::Http407ProxyAuthenticationRequired}, - {408, HttpResponseStatusCode::Http408RequestTimeout}, - {409, HttpResponseStatusCode::Http409Conflict}, - {410, HttpResponseStatusCode::Http410Gone}, - {411, HttpResponseStatusCode::Http411LengthRequired}, - {412, HttpResponseStatusCode::Http412PreconditionFailed}, - {413, HttpResponseStatusCode::Http413RequestEntityTooLarge}, - {414, HttpResponseStatusCode::Http414RequestURITooLong}, - {415, HttpResponseStatusCode::Http415UnsupportedMediaType}, - {416, HttpResponseStatusCode::Http416RequestedRangeNotSatisfiable}, - {417, HttpResponseStatusCode::Http417ExpectationFailed}, - {418, HttpResponseStatusCode::Http418ImATeapot}, - {419, HttpResponseStatusCode::Http419AuthenticationTimeout}, - {420, HttpResponseStatusCode::Http420}, - {421, HttpResponseStatusCode::Http421MisdirectedRequest}, - {422, HttpResponseStatusCode::Http422UnprocessableEntity}, - {423, HttpResponseStatusCode::Http423Locked}, - {424, HttpResponseStatusCode::Http424FailedDependency}, - {425, HttpResponseStatusCode::Http425TooEarly}, - {426, HttpResponseStatusCode::Http426UpgradeRequired}, - {428, HttpResponseStatusCode::Http428PreconditionRequired}, - {429, HttpResponseStatusCode::Http429TooManyRequests}, - {431, HttpResponseStatusCode::Http431RequestHeaderFieldsTooLarge}, - {440, HttpResponseStatusCode::Http440LoginTimeout}, - {444, HttpResponseStatusCode::Http444NoResponse}, - {449, HttpResponseStatusCode::Http449RetryWith}, - {450, HttpResponseStatusCode::Http450BlockedByWindowsParentalControls}, - {451, HttpResponseStatusCode::Http451}, - {494, HttpResponseStatusCode::Http494RequestHeaderTooLarge}, - {495, HttpResponseStatusCode::Http495CertError}, - {496, HttpResponseStatusCode::Http496NoCert}, - {497, HttpResponseStatusCode::Http497HTTPtoHTTPS}, - {498, HttpResponseStatusCode::Http498TokenExpiredInvalid}, - {499, HttpResponseStatusCode::Http499}, - {500, HttpResponseStatusCode::Http500InternalServerError}, - {501, HttpResponseStatusCode::Http501NotImplemented}, - {502, HttpResponseStatusCode::Http502BadGateway}, - {503, HttpResponseStatusCode::Http503ServiceUnavailable}, - {504, HttpResponseStatusCode::Http504GatewayTimeout}, - {505, HttpResponseStatusCode::Http505HTTPVersionNotSupported}, - {506, HttpResponseStatusCode::Http506VariantAlsoNegotiates}, - {507, HttpResponseStatusCode::Http507InsufficientStorage}, - {508, HttpResponseStatusCode::Http508LoopDetected}, - {509, HttpResponseStatusCode::Http509BandwidthLimitExceeded}, - {510, HttpResponseStatusCode::Http510NotExtended}, - {511, HttpResponseStatusCode::Http511NetworkAuthenticationRequired}, - {520, HttpResponseStatusCode::Http520OriginError}, - {521, HttpResponseStatusCode::Http521WebServerIsDown}, - {522, HttpResponseStatusCode::Http522ConnectionTimedOut}, - {523, HttpResponseStatusCode::Http523ProxyDeclinedRequest}, - {524, HttpResponseStatusCode::Http524aTimeoutOccurred}, - {598, HttpResponseStatusCode::Http598NetworkReadTimeoutError}, - {599, HttpResponseStatusCode::Http599NetworkConnectTimeoutError}, -}; - -HttpResponseStatusCode::HttpResponseStatusCode(const int &statusCodeNumber, const std::string& statusMessage) -{ - if(statusMessage != "") + /** + * @struct HttpResponseStatusCodeHash + * @brief The helper structure for hash HttpResponseStatusCode while using std::unordered_map + */ + struct HttpResponseStatusCodeHash { - m_CustomizedMessage = statusMessage; + size_t operator()(const HttpResponseStatusCode& status) const + { + return static_cast(status); + } + }; + + static const std::unordered_map + statusCodeExplanationStringMap = { + { HttpResponseStatusCode::Http100Continue, "Continue" }, + { HttpResponseStatusCode::Http101SwitchingProtocols, "Switching Protocols" }, + { HttpResponseStatusCode::Http102Processing, "Processing" }, + { HttpResponseStatusCode::Http103EarlyHints, "Early Hints" }, + { HttpResponseStatusCode::Http200OK, "OK" }, + { HttpResponseStatusCode::Http201Created, "Created" }, + { HttpResponseStatusCode::Http202Accepted, "Accepted" }, + { HttpResponseStatusCode::Http203NonAuthoritativeInformation, "Non-Authoritative Information" }, + { HttpResponseStatusCode::Http204NoContent, "No Content" }, + { HttpResponseStatusCode::Http205ResetContent, "Reset Content" }, + { HttpResponseStatusCode::Http206PartialContent, "Partial Content" }, + { HttpResponseStatusCode::Http207MultiStatus, "Multi-Status" }, + { HttpResponseStatusCode::Http208AlreadyReported, "Already Reported" }, + { HttpResponseStatusCode::Http226IMUsed, "IM Used" }, + { HttpResponseStatusCode::Http300MultipleChoices, "Multiple Choices" }, + { HttpResponseStatusCode::Http301MovedPermanently, "Moved Permanently" }, + { HttpResponseStatusCode::Http302, "(various messages)" }, + { HttpResponseStatusCode::Http303SeeOther, "See Other" }, + { HttpResponseStatusCode::Http304NotModified, "Not Modified" }, + { HttpResponseStatusCode::Http305UseProxy, "Use Proxy" }, + { HttpResponseStatusCode::Http306SwitchProxy, "Switch Proxy" }, + { HttpResponseStatusCode::Http307TemporaryRedirect, "Temporary Redirect" }, + { HttpResponseStatusCode::Http308PermanentRedirect, "Permanent Redirect" }, + { HttpResponseStatusCode::Http400BadRequest, "Bad Request" }, + { HttpResponseStatusCode::Http401Unauthorized, "Unauthorized" }, + { HttpResponseStatusCode::Http402PaymentRequired, "Payment Required" }, + { HttpResponseStatusCode::Http403Forbidden, "Forbidden" }, + { HttpResponseStatusCode::Http404NotFound, "Not Found" }, + { HttpResponseStatusCode::Http405MethodNotAllowed, "Method Not Allowed" }, + { HttpResponseStatusCode::Http406NotAcceptable, "Not Acceptable" }, + { HttpResponseStatusCode::Http407ProxyAuthenticationRequired, "Proxy Authentication Required" }, + { HttpResponseStatusCode::Http408RequestTimeout, "Request Timeout" }, + { HttpResponseStatusCode::Http409Conflict, "Conflict" }, + { HttpResponseStatusCode::Http410Gone, "Gone" }, + { HttpResponseStatusCode::Http411LengthRequired, "Length Required" }, + { HttpResponseStatusCode::Http412PreconditionFailed, "Precondition Failed" }, + { HttpResponseStatusCode::Http413RequestEntityTooLarge, "Request Entity Too Large" }, + { HttpResponseStatusCode::Http414RequestURITooLong, "Request-URI Too Long" }, + { HttpResponseStatusCode::Http415UnsupportedMediaType, "Unsupported Media Type" }, + { HttpResponseStatusCode::Http416RequestedRangeNotSatisfiable, "Requested Range Not Satisfiable" }, + { HttpResponseStatusCode::Http417ExpectationFailed, "Expectation Failed" }, + { HttpResponseStatusCode::Http418ImATeapot, "I'm a teapot" }, + { HttpResponseStatusCode::Http419AuthenticationTimeout, "Authentication Timeout" }, + { HttpResponseStatusCode::Http420, "(various messages)" }, + { HttpResponseStatusCode::Http421MisdirectedRequest, "Misdirected Request" }, + { HttpResponseStatusCode::Http422UnprocessableEntity, "Unprocessable Entity" }, + { HttpResponseStatusCode::Http423Locked, "Locked" }, + { HttpResponseStatusCode::Http424FailedDependency, "Failed Dependency" }, + { HttpResponseStatusCode::Http425TooEarly, "Too Early" }, + { HttpResponseStatusCode::Http426UpgradeRequired, "Upgrade Required" }, + { HttpResponseStatusCode::Http428PreconditionRequired, "Precondition Required" }, + { HttpResponseStatusCode::Http429TooManyRequests, "Too Many Requests" }, + { HttpResponseStatusCode::Http431RequestHeaderFieldsTooLarge, "Request Header Fields Too Large" }, + { HttpResponseStatusCode::Http440LoginTimeout, "Login Timeout" }, + { HttpResponseStatusCode::Http444NoResponse, "No Response" }, + { HttpResponseStatusCode::Http449RetryWith, "Retry With" }, + { HttpResponseStatusCode::Http450BlockedByWindowsParentalControls, "Blocked by Windows Parental Controls" }, + { HttpResponseStatusCode::Http451, "(various messages)" }, + { HttpResponseStatusCode::Http494RequestHeaderTooLarge, "Request Header Too Large" }, + { HttpResponseStatusCode::Http495CertError, "Cert Error" }, + { HttpResponseStatusCode::Http496NoCert, "No Cert" }, + { HttpResponseStatusCode::Http497HTTPtoHTTPS, "HTTP to HTTPS" }, + { HttpResponseStatusCode::Http498TokenExpiredInvalid, "Token expired/invalid" }, + { HttpResponseStatusCode::Http499, "(various messages)" }, + { HttpResponseStatusCode::Http500InternalServerError, "Internal Server Error" }, + { HttpResponseStatusCode::Http501NotImplemented, "Not Implemented" }, + { HttpResponseStatusCode::Http502BadGateway, "Bad Gateway" }, + { HttpResponseStatusCode::Http503ServiceUnavailable, "Service Unavailable" }, + { HttpResponseStatusCode::Http504GatewayTimeout, "Gateway Timeout" }, + { HttpResponseStatusCode::Http505HTTPVersionNotSupported, "HTTP Version Not Supported" }, + { HttpResponseStatusCode::Http506VariantAlsoNegotiates, "Variant Also Negotiates" }, + { HttpResponseStatusCode::Http507InsufficientStorage, "Insufficient Storage" }, + { HttpResponseStatusCode::Http508LoopDetected, "Loop Detected" }, + { HttpResponseStatusCode::Http509BandwidthLimitExceeded, "Bandwidth Limit Exceeded" }, + { HttpResponseStatusCode::Http510NotExtended, "Not Extended" }, + { HttpResponseStatusCode::Http511NetworkAuthenticationRequired, "Network Authentication Required" }, + { HttpResponseStatusCode::Http520OriginError, "Origin Error" }, + { HttpResponseStatusCode::Http521WebServerIsDown, "Web server is down" }, + { HttpResponseStatusCode::Http522ConnectionTimedOut, "Connection timed out" }, + { HttpResponseStatusCode::Http523ProxyDeclinedRequest, "Proxy Declined Request" }, + { HttpResponseStatusCode::Http524aTimeoutOccurred, "A timeout occurred" }, + { HttpResponseStatusCode::Http598NetworkReadTimeoutError, "Network read timeout error" }, + { HttpResponseStatusCode::Http599NetworkConnectTimeoutError, "Network connect timeout error" }, + { HttpResponseStatusCode::HttpStatus1xxCodeUnknown, "1XX Status Code Unknown" }, + { HttpResponseStatusCode::HttpStatus2xxCodeUnknown, "2XX Status Code Unknown" }, + { HttpResponseStatusCode::HttpStatus3xxCodeUnknown, "3XX Status Code Unknown" }, + { HttpResponseStatusCode::HttpStatus4xxCodeUnknown, "4XX Status Code Unknown" }, + { HttpResponseStatusCode::HttpStatus5xxCodeUnknown, "5XX Status Code Unknown" }, + { HttpResponseStatusCode::HttpStatusCodeUnknown, "Status Code Unknown" }, + }; + + HttpResponseStatusCode::HttpResponseStatusCode(const Value& statusCode, const std::string& statusMessage) + : m_Value(statusCode) + { + if (statusMessage != "") + { + m_CustomizedMessage = statusMessage; + } } - if(intStatusCodeMap.find(statusCodeNumber) != intStatusCodeMap.end()) + std::string HttpResponseStatusCode::getMessage() const { - m_Value = intStatusCodeMap.at(statusCodeNumber); - return; + if (m_CustomizedMessage != "") + { + return m_CustomizedMessage; + } + return statusCodeExplanationStringMap.at(m_Value); } - if(statusCodeNumber >= 100 && statusCodeNumber <= 199) - { - m_Value = HttpResponseStatusCode::HttpStatus1xxCodeUnknown; - } - else if (statusCodeNumber >= 200 && statusCodeNumber <= 299) - { - m_Value = HttpResponseStatusCode::HttpStatus2xxCodeUnknown; - } - else if (statusCodeNumber >= 300 && statusCodeNumber <= 399) + HttpResponseLayer::HttpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : HttpMessage(data, dataLen, prevLayer, packet) { - m_Value = HttpResponseStatusCode::HttpStatus3xxCodeUnknown; + m_Protocol = HTTPResponse; + m_FirstLine = new HttpResponseFirstLine(this); + m_FieldsOffset = m_FirstLine->getSize(); + parseFields(); } - else if (statusCodeNumber >= 400 && statusCodeNumber <= 499) + + HttpResponseLayer::HttpResponseLayer(HttpVersion version, const HttpResponseStatusCode& statusCode, + const std::string& statusCodeString) { - m_Value = HttpResponseStatusCode::HttpStatus4xxCodeUnknown; + m_Protocol = HTTPResponse; + m_FirstLine = new HttpResponseFirstLine(this, version, HttpResponseStatusCode(statusCode, statusCodeString)); + m_FieldsOffset = m_FirstLine->getSize(); } - else if (statusCodeNumber >= 500 && statusCodeNumber <= 599) + + HttpResponseLayer::HttpResponseLayer(HttpVersion version, const HttpResponseStatusCode& statusCode) { - m_Value = HttpResponseStatusCode::HttpStatus5xxCodeUnknown; + m_Protocol = HTTPResponse; + m_FirstLine = new HttpResponseFirstLine(this, version, statusCode); + m_FieldsOffset = m_FirstLine->getSize(); } -} -/** - * @struct HttpResponseStatusCodeHash - * @brief The helper structure for hash HttpResponseStatusCode while using std::unordered_map - */ -struct HttpResponseStatusCodeHash -{ - size_t operator()(const HttpResponseStatusCode& status) const - { - return static_cast(status); - } -}; - -static const std::unordered_map statusCodeExplanationStringMap = { - {HttpResponseStatusCode::Http100Continue, "Continue"}, - {HttpResponseStatusCode::Http101SwitchingProtocols, "Switching Protocols"}, - {HttpResponseStatusCode::Http102Processing, "Processing"}, - {HttpResponseStatusCode::Http103EarlyHints, "Early Hints"}, - {HttpResponseStatusCode::Http200OK, "OK"}, - {HttpResponseStatusCode::Http201Created, "Created"}, - {HttpResponseStatusCode::Http202Accepted, "Accepted"}, - {HttpResponseStatusCode::Http203NonAuthoritativeInformation, "Non-Authoritative Information"}, - {HttpResponseStatusCode::Http204NoContent, "No Content"}, - {HttpResponseStatusCode::Http205ResetContent, "Reset Content"}, - {HttpResponseStatusCode::Http206PartialContent, "Partial Content"}, - {HttpResponseStatusCode::Http207MultiStatus, "Multi-Status"}, - {HttpResponseStatusCode::Http208AlreadyReported, "Already Reported"}, - {HttpResponseStatusCode::Http226IMUsed, "IM Used"}, - {HttpResponseStatusCode::Http300MultipleChoices, "Multiple Choices"}, - {HttpResponseStatusCode::Http301MovedPermanently, "Moved Permanently"}, - {HttpResponseStatusCode::Http302, "(various messages)"}, - {HttpResponseStatusCode::Http303SeeOther, "See Other"}, - {HttpResponseStatusCode::Http304NotModified, "Not Modified"}, - {HttpResponseStatusCode::Http305UseProxy, "Use Proxy"}, - {HttpResponseStatusCode::Http306SwitchProxy, "Switch Proxy"}, - {HttpResponseStatusCode::Http307TemporaryRedirect, "Temporary Redirect"}, - {HttpResponseStatusCode::Http308PermanentRedirect, "Permanent Redirect"}, - {HttpResponseStatusCode::Http400BadRequest, "Bad Request"}, - {HttpResponseStatusCode::Http401Unauthorized, "Unauthorized"}, - {HttpResponseStatusCode::Http402PaymentRequired, "Payment Required"}, - {HttpResponseStatusCode::Http403Forbidden, "Forbidden"}, - {HttpResponseStatusCode::Http404NotFound, "Not Found"}, - {HttpResponseStatusCode::Http405MethodNotAllowed, "Method Not Allowed"}, - {HttpResponseStatusCode::Http406NotAcceptable, "Not Acceptable"}, - {HttpResponseStatusCode::Http407ProxyAuthenticationRequired, "Proxy Authentication Required"}, - {HttpResponseStatusCode::Http408RequestTimeout, "Request Timeout"}, - {HttpResponseStatusCode::Http409Conflict, "Conflict"}, - {HttpResponseStatusCode::Http410Gone, "Gone"}, - {HttpResponseStatusCode::Http411LengthRequired, "Length Required"}, - {HttpResponseStatusCode::Http412PreconditionFailed, "Precondition Failed"}, - {HttpResponseStatusCode::Http413RequestEntityTooLarge, "Request Entity Too Large"}, - {HttpResponseStatusCode::Http414RequestURITooLong, "Request-URI Too Long"}, - {HttpResponseStatusCode::Http415UnsupportedMediaType, "Unsupported Media Type"}, - {HttpResponseStatusCode::Http416RequestedRangeNotSatisfiable, "Requested Range Not Satisfiable"}, - {HttpResponseStatusCode::Http417ExpectationFailed, "Expectation Failed"}, - {HttpResponseStatusCode::Http418ImATeapot, "I'm a teapot"}, - {HttpResponseStatusCode::Http419AuthenticationTimeout, "Authentication Timeout"}, - {HttpResponseStatusCode::Http420, "(various messages)"}, - {HttpResponseStatusCode::Http421MisdirectedRequest, "Misdirected Request"}, - {HttpResponseStatusCode::Http422UnprocessableEntity, "Unprocessable Entity"}, - {HttpResponseStatusCode::Http423Locked, "Locked"}, - {HttpResponseStatusCode::Http424FailedDependency, "Failed Dependency"}, - {HttpResponseStatusCode::Http425TooEarly, "Too Early"}, - {HttpResponseStatusCode::Http426UpgradeRequired, "Upgrade Required"}, - {HttpResponseStatusCode::Http428PreconditionRequired, "Precondition Required"}, - {HttpResponseStatusCode::Http429TooManyRequests, "Too Many Requests"}, - {HttpResponseStatusCode::Http431RequestHeaderFieldsTooLarge, "Request Header Fields Too Large"}, - {HttpResponseStatusCode::Http440LoginTimeout, "Login Timeout"}, - {HttpResponseStatusCode::Http444NoResponse, "No Response"}, - {HttpResponseStatusCode::Http449RetryWith, "Retry With"}, - {HttpResponseStatusCode::Http450BlockedByWindowsParentalControls, "Blocked by Windows Parental Controls"}, - {HttpResponseStatusCode::Http451, "(various messages)"}, - {HttpResponseStatusCode::Http494RequestHeaderTooLarge, "Request Header Too Large"}, - {HttpResponseStatusCode::Http495CertError, "Cert Error"}, - {HttpResponseStatusCode::Http496NoCert, "No Cert"}, - {HttpResponseStatusCode::Http497HTTPtoHTTPS, "HTTP to HTTPS"}, - {HttpResponseStatusCode::Http498TokenExpiredInvalid, "Token expired/invalid"}, - {HttpResponseStatusCode::Http499, "(various messages)"}, - {HttpResponseStatusCode::Http500InternalServerError, "Internal Server Error"}, - {HttpResponseStatusCode::Http501NotImplemented, "Not Implemented"}, - {HttpResponseStatusCode::Http502BadGateway, "Bad Gateway"}, - {HttpResponseStatusCode::Http503ServiceUnavailable, "Service Unavailable"}, - {HttpResponseStatusCode::Http504GatewayTimeout, "Gateway Timeout"}, - {HttpResponseStatusCode::Http505HTTPVersionNotSupported, "HTTP Version Not Supported"}, - {HttpResponseStatusCode::Http506VariantAlsoNegotiates, "Variant Also Negotiates"}, - {HttpResponseStatusCode::Http507InsufficientStorage, "Insufficient Storage"}, - {HttpResponseStatusCode::Http508LoopDetected, "Loop Detected"}, - {HttpResponseStatusCode::Http509BandwidthLimitExceeded, "Bandwidth Limit Exceeded"}, - {HttpResponseStatusCode::Http510NotExtended, "Not Extended"}, - {HttpResponseStatusCode::Http511NetworkAuthenticationRequired, "Network Authentication Required"}, - {HttpResponseStatusCode::Http520OriginError, "Origin Error"}, - {HttpResponseStatusCode::Http521WebServerIsDown, "Web server is down"}, - {HttpResponseStatusCode::Http522ConnectionTimedOut, "Connection timed out"}, - {HttpResponseStatusCode::Http523ProxyDeclinedRequest, "Proxy Declined Request"}, - {HttpResponseStatusCode::Http524aTimeoutOccurred, "A timeout occurred"}, - {HttpResponseStatusCode::Http598NetworkReadTimeoutError, "Network read timeout error"}, - {HttpResponseStatusCode::Http599NetworkConnectTimeoutError, "Network connect timeout error"}, - {HttpResponseStatusCode::HttpStatus1xxCodeUnknown, "1XX Status Code Unknown"}, - {HttpResponseStatusCode::HttpStatus2xxCodeUnknown, "2XX Status Code Unknown"}, - {HttpResponseStatusCode::HttpStatus3xxCodeUnknown, "3XX Status Code Unknown"}, - {HttpResponseStatusCode::HttpStatus4xxCodeUnknown, "4XX Status Code Unknown"}, - {HttpResponseStatusCode::HttpStatus5xxCodeUnknown, "5XX Status Code Unknown"}, - {HttpResponseStatusCode::HttpStatusCodeUnknown, "Status Code Unknown"}, -}; - -HttpResponseStatusCode::HttpResponseStatusCode(const Value& statusCode, const std::string& statusMessage) : m_Value(statusCode) -{ - if(statusMessage != "") + HttpResponseLayer::~HttpResponseLayer() { - m_CustomizedMessage = statusMessage; + delete m_FirstLine; } -} -std::string HttpResponseStatusCode::getMessage() const -{ - if(m_CustomizedMessage != "") + HttpResponseLayer::HttpResponseLayer(const HttpResponseLayer& other) : HttpMessage(other) { - return m_CustomizedMessage; + m_FirstLine = new HttpResponseFirstLine(this); } - return statusCodeExplanationStringMap.at(m_Value); -} - -HttpResponseLayer::HttpResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : HttpMessage(data, dataLen, prevLayer, packet) -{ - m_Protocol = HTTPResponse; - m_FirstLine = new HttpResponseFirstLine(this); - m_FieldsOffset = m_FirstLine->getSize(); - parseFields(); -} - -HttpResponseLayer::HttpResponseLayer(HttpVersion version, const HttpResponseStatusCode& statusCode, const std::string& statusCodeString) -{ - m_Protocol = HTTPResponse; - m_FirstLine = new HttpResponseFirstLine(this, version, HttpResponseStatusCode(statusCode, statusCodeString)); - m_FieldsOffset = m_FirstLine->getSize(); -} - -HttpResponseLayer::HttpResponseLayer(HttpVersion version, const HttpResponseStatusCode& statusCode) -{ - m_Protocol = HTTPResponse; - m_FirstLine = new HttpResponseFirstLine(this, version, statusCode); - m_FieldsOffset = m_FirstLine->getSize(); -} -HttpResponseLayer::~HttpResponseLayer() -{ - delete m_FirstLine; -} - - -HttpResponseLayer::HttpResponseLayer(const HttpResponseLayer& other) : HttpMessage(other) -{ - m_FirstLine = new HttpResponseFirstLine(this); -} - -HttpResponseLayer& HttpResponseLayer::operator=(const HttpResponseLayer& other) -{ - HttpMessage::operator=(other); - - if (m_FirstLine != nullptr) - delete m_FirstLine; - - m_FirstLine = new HttpResponseFirstLine(this); + HttpResponseLayer& HttpResponseLayer::operator=(const HttpResponseLayer& other) + { + HttpMessage::operator=(other); - return *this; -} + if (m_FirstLine != nullptr) + delete m_FirstLine; + m_FirstLine = new HttpResponseFirstLine(this); -HeaderField* HttpResponseLayer::setContentLength(int contentLength, const std::string &prevFieldName) -{ - std::ostringstream contentLengthAsString; - contentLengthAsString << contentLength; - std::string contentLengthFieldName(PCPP_HTTP_CONTENT_LENGTH_FIELD); - HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); - if (contentLengthField == nullptr) - { - HeaderField* prevField = getFieldByName(prevFieldName); - contentLengthField = insertField(prevField, PCPP_HTTP_CONTENT_LENGTH_FIELD, contentLengthAsString.str()); + return *this; } - else - contentLengthField->setFieldValue(contentLengthAsString.str()); - - return contentLengthField; -} -int HttpResponseLayer::getContentLength() const -{ - std::string contentLengthFieldName(PCPP_HTTP_CONTENT_LENGTH_FIELD); - std::transform(contentLengthFieldName.begin(), contentLengthFieldName.end(), contentLengthFieldName.begin(), ::tolower); - HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); - if (contentLengthField != nullptr) - return atoi(contentLengthField->getFieldValue().c_str()); - return 0; -} - -std::string HttpResponseLayer::toString() const -{ - static const int maxLengthToPrint = 120; - std::string result = "HTTP response, "; - int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line - if (size <= maxLengthToPrint) + HeaderField* HttpResponseLayer::setContentLength(int contentLength, const std::string& prevFieldName) { - char* firstLine = new char[size+1]; - strncpy(firstLine, (char*)m_Data, size); - firstLine[size] = 0; - result += std::string(firstLine); - delete[] firstLine; + std::ostringstream contentLengthAsString; + contentLengthAsString << contentLength; + std::string contentLengthFieldName(PCPP_HTTP_CONTENT_LENGTH_FIELD); + HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); + if (contentLengthField == nullptr) + { + HeaderField* prevField = getFieldByName(prevFieldName); + contentLengthField = insertField(prevField, PCPP_HTTP_CONTENT_LENGTH_FIELD, contentLengthAsString.str()); + } + else + contentLengthField->setFieldValue(contentLengthAsString.str()); + + return contentLengthField; } - else + + int HttpResponseLayer::getContentLength() const { - char firstLine[maxLengthToPrint+1]; - strncpy(firstLine, (char*)m_Data, maxLengthToPrint-3); - firstLine[maxLengthToPrint-3] = '.'; - firstLine[maxLengthToPrint-2] = '.'; - firstLine[maxLengthToPrint-1] = '.'; - firstLine[maxLengthToPrint] = 0; - result += std::string(firstLine); + std::string contentLengthFieldName(PCPP_HTTP_CONTENT_LENGTH_FIELD); + std::transform(contentLengthFieldName.begin(), contentLengthFieldName.end(), contentLengthFieldName.begin(), + ::tolower); + HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); + if (contentLengthField != nullptr) + return atoi(contentLengthField->getFieldValue().c_str()); + return 0; } - return result; -} - - -// -------- Class HttpResponseFirstLine ----------------- - - -int HttpResponseFirstLine::getStatusCodeAsInt() const -{ - return m_StatusCode.toInt(); -} - -std::string HttpResponseFirstLine::getStatusCodeString() const -{ - if (!m_StatusCode.isUnsupportedCode()) + std::string HttpResponseLayer::toString() const { - return m_StatusCode.getMessage(); - } + static const int maxLengthToPrint = 120; + std::string result = "HTTP response, "; + int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line + if (size <= maxLengthToPrint) + { + char* firstLine = new char[size + 1]; + strncpy(firstLine, (char*)m_Data, size); + firstLine[size] = 0; + result += std::string(firstLine); + delete[] firstLine; + } + else + { + char firstLine[maxLengthToPrint + 1]; + strncpy(firstLine, (char*)m_Data, maxLengthToPrint - 3); + firstLine[maxLengthToPrint - 3] = '.'; + firstLine[maxLengthToPrint - 2] = '.'; + firstLine[maxLengthToPrint - 1] = '.'; + firstLine[maxLengthToPrint] = 0; + result += std::string(firstLine); + } - //else first line is illegal, return empty string - return ""; -} + return result; + } -bool HttpResponseFirstLine::setStatusCode(const HttpResponseStatusCode& newStatusCode, const std::string& statusCodeString) -{ - return setStatusCode(HttpResponseStatusCode(newStatusCode, statusCodeString)); -} + // -------- Class HttpResponseFirstLine ----------------- -bool HttpResponseFirstLine::setStatusCode(const HttpResponseStatusCode& newStatusCode) -{ - if (newStatusCode.isUnsupportedCode()) + int HttpResponseFirstLine::getStatusCodeAsInt() const { - PCPP_LOG_ERROR("Requested status code is " << newStatusCode.toString() << ":" << statusCodeExplanationStringMap.at(newStatusCode)); - return false; + return m_StatusCode.toInt(); } - //extend or shorten layer - - size_t statusStringOffset = 13; - auto newStatusCodeMessage = newStatusCode.getMessage(); - - int lengthDifference = newStatusCodeMessage.length() - getStatusCodeString().length(); - if (lengthDifference > 0) + std::string HttpResponseFirstLine::getStatusCodeString() const { - if (!m_HttpResponse->extendLayer(statusStringOffset, lengthDifference)) + if (!m_StatusCode.isUnsupportedCode()) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + return m_StatusCode.getMessage(); } + + // else first line is illegal, return empty string + return ""; } - else if (lengthDifference < 0) + + bool HttpResponseFirstLine::setStatusCode(const HttpResponseStatusCode& newStatusCode, + const std::string& statusCodeString) { - if (!m_HttpResponse->shortenLayer(statusStringOffset, 0-lengthDifference)) + return setStatusCode(HttpResponseStatusCode(newStatusCode, statusCodeString)); + } + + bool HttpResponseFirstLine::setStatusCode(const HttpResponseStatusCode& newStatusCode) + { + if (newStatusCode.isUnsupportedCode()) { - PCPP_LOG_ERROR("Cannot change layer size"); + PCPP_LOG_ERROR("Requested status code is " << newStatusCode.toString() << ":" + << statusCodeExplanationStringMap.at(newStatusCode)); return false; - } - } - - if (lengthDifference != 0) - m_HttpResponse->shiftFieldsOffset(m_HttpResponse->getFirstField(), lengthDifference); - // copy status string - memcpy(m_HttpResponse->m_Data+statusStringOffset, newStatusCodeMessage.c_str(), newStatusCodeMessage.length()); + // extend or shorten layer - // change status code - memcpy(m_HttpResponse->m_Data+9, newStatusCode.toString().c_str(), 3); + size_t statusStringOffset = 13; + auto newStatusCodeMessage = newStatusCode.getMessage(); - m_StatusCode = newStatusCode; + int lengthDifference = newStatusCodeMessage.length() - getStatusCodeString().length(); + if (lengthDifference > 0) + { + if (!m_HttpResponse->extendLayer(statusStringOffset, lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } + else if (lengthDifference < 0) + { + if (!m_HttpResponse->shortenLayer(statusStringOffset, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } - m_FirstLineEndOffset += lengthDifference; + if (lengthDifference != 0) + m_HttpResponse->shiftFieldsOffset(m_HttpResponse->getFirstField(), lengthDifference); - return true; + // copy status string + memcpy(m_HttpResponse->m_Data + statusStringOffset, newStatusCodeMessage.c_str(), + newStatusCodeMessage.length()); -} + // change status code + memcpy(m_HttpResponse->m_Data + 9, newStatusCode.toString().c_str(), 3); -void HttpResponseFirstLine::setVersion(HttpVersion newVersion) -{ - if (newVersion == HttpVersionUnknown) - return; + m_StatusCode = newStatusCode; - char* verPos = (char*)(m_HttpResponse->m_Data + 5); - memcpy(verPos, VersionEnumToString[newVersion].c_str(), 3); + m_FirstLineEndOffset += lengthDifference; - m_Version = newVersion; -} + return true; + } -HttpResponseStatusCode HttpResponseFirstLine::parseStatusCode(const char* data, size_t dataLen) -{ - // minimum data should be 12B long: "HTTP/x.y XXX" - if (!data || dataLen < 12) + void HttpResponseFirstLine::setVersion(HttpVersion newVersion) { - return HttpResponseStatusCode::HttpStatusCodeUnknown; - } + if (newVersion == HttpVersionUnknown) + return; - const std::string codeString = std::string(data + 9, 3); + char* verPos = (char*)(m_HttpResponse->m_Data + 5); + memcpy(verPos, VersionEnumToString[newVersion].c_str(), 3); - if(codeString.empty() || (std::find_if(codeString.begin(), codeString.end(), [](unsigned char c){ return !std::isdigit(c); }) != codeString.end())) - { - return HttpResponseStatusCode::HttpStatusCodeUnknown; + m_Version = newVersion; } - constexpr size_t messageOffset = 13; // expect "HTTP/x.y XXX YYY", YYY starts from 13 - size_t offset = messageOffset; - bool isMessageFound = false; - while(offset < dataLen) + HttpResponseStatusCode HttpResponseFirstLine::parseStatusCode(const char* data, size_t dataLen) { - if(data[offset] == '\n') + // minimum data should be 12B long: "HTTP/x.y XXX" + if (!data || dataLen < 12) { - isMessageFound = true; - break; + return HttpResponseStatusCode::HttpStatusCodeUnknown; } - offset++; - } - if(!isMessageFound) - { - return HttpResponseStatusCode::HttpStatusCodeUnknown; - } + const std::string codeString = std::string(data + 9, 3); - std::string messageString(data + messageOffset, offset - messageOffset); - if(!messageString.empty() && messageString.back() == '\r') - { - messageString.pop_back(); - } - if(messageString.empty()) - { - return HttpResponseStatusCode::HttpStatusCodeUnknown; - } + if (codeString.empty() || (std::find_if(codeString.begin(), codeString.end(), + [](unsigned char c) { return !std::isdigit(c); }) != codeString.end())) + { + return HttpResponseStatusCode::HttpStatusCodeUnknown; + } - return HttpResponseStatusCode(std::stoi(codeString), messageString); -} + constexpr size_t messageOffset = 13; // expect "HTTP/x.y XXX YYY", YYY starts from 13 + size_t offset = messageOffset; + bool isMessageFound = false; + while (offset < dataLen) + { + if (data[offset] == '\n') + { + isMessageFound = true; + break; + } + offset++; + } -HttpResponseFirstLine::HttpResponseFirstLine(HttpResponseLayer* httpResponse) : m_HttpResponse(httpResponse) -{ - m_Version = parseVersion((char*)m_HttpResponse->m_Data, m_HttpResponse->getDataLen()); - if (m_Version == HttpVersionUnknown) - { - m_StatusCode = HttpResponseStatusCode::HttpStatusCodeUnknown; - } - else - { - m_StatusCode = parseStatusCode((char*)m_HttpResponse->m_Data, m_HttpResponse->getDataLen()); - } + if (!isMessageFound) + { + return HttpResponseStatusCode::HttpStatusCodeUnknown; + } + std::string messageString(data + messageOffset, offset - messageOffset); + if (!messageString.empty() && messageString.back() == '\r') + { + messageString.pop_back(); + } + if (messageString.empty()) + { + return HttpResponseStatusCode::HttpStatusCodeUnknown; + } - char* endOfFirstLine; - if ((endOfFirstLine = (char*)memchr((char*)(m_HttpResponse->m_Data), '\n', m_HttpResponse->m_DataLen)) != nullptr) - { - m_FirstLineEndOffset = endOfFirstLine - (char*)m_HttpResponse->m_Data + 1; - m_IsComplete = true; - } - else - { - m_FirstLineEndOffset = m_HttpResponse->getDataLen(); - m_IsComplete = false; + return HttpResponseStatusCode(std::stoi(codeString), messageString); } - if (Logger::getInstance().isDebugEnabled(PacketLogModuleHttpLayer)) + HttpResponseFirstLine::HttpResponseFirstLine(HttpResponseLayer* httpResponse) : m_HttpResponse(httpResponse) { - std::string version = (m_Version == HttpVersionUnknown ? "Unknown" : VersionEnumToString[m_Version]); - int statusCode = (m_StatusCode == HttpResponseStatusCode::HttpStatusCodeUnknown ? 0 : m_StatusCode.toInt()); - PCPP_LOG_DEBUG("Version='" << version << "'; Status code=" << statusCode << " '" << getStatusCodeString() << "'"); - } -} + m_Version = parseVersion((char*)m_HttpResponse->m_Data, m_HttpResponse->getDataLen()); + if (m_Version == HttpVersionUnknown) + { + m_StatusCode = HttpResponseStatusCode::HttpStatusCodeUnknown; + } + else + { + m_StatusCode = parseStatusCode((char*)m_HttpResponse->m_Data, m_HttpResponse->getDataLen()); + } + char* endOfFirstLine; + if ((endOfFirstLine = (char*)memchr((char*)(m_HttpResponse->m_Data), '\n', m_HttpResponse->m_DataLen)) != + nullptr) + { + m_FirstLineEndOffset = endOfFirstLine - (char*)m_HttpResponse->m_Data + 1; + m_IsComplete = true; + } + else + { + m_FirstLineEndOffset = m_HttpResponse->getDataLen(); + m_IsComplete = false; + } -HttpResponseFirstLine::HttpResponseFirstLine(HttpResponseLayer* httpResponse, HttpVersion version, const HttpResponseStatusCode& statusCode) -{ - if (statusCode.isUnsupportedCode()) - { - m_Exception.setMessage("Status code supplied was " + statusCodeExplanationStringMap.at(statusCode)); - throw m_Exception; + if (Logger::getInstance().isDebugEnabled(PacketLogModuleHttpLayer)) + { + std::string version = (m_Version == HttpVersionUnknown ? "Unknown" : VersionEnumToString[m_Version]); + int statusCode = (m_StatusCode == HttpResponseStatusCode::HttpStatusCodeUnknown ? 0 : m_StatusCode.toInt()); + PCPP_LOG_DEBUG("Version='" << version << "'; Status code=" << statusCode << " '" << getStatusCodeString() + << "'"); + } } - if (version == HttpVersionUnknown) + HttpResponseFirstLine::HttpResponseFirstLine(HttpResponseLayer* httpResponse, HttpVersion version, + const HttpResponseStatusCode& statusCode) { - m_Exception.setMessage("Version supplied was HttpVersionUnknown"); - throw m_Exception; - } + if (statusCode.isUnsupportedCode()) + { + m_Exception.setMessage("Status code supplied was " + statusCodeExplanationStringMap.at(statusCode)); + throw m_Exception; + } - m_HttpResponse = httpResponse; + if (version == HttpVersionUnknown) + { + m_Exception.setMessage("Version supplied was HttpVersionUnknown"); + throw m_Exception; + } - m_StatusCode = statusCode; - m_Version = version; + m_HttpResponse = httpResponse; - std::string firstLine = "HTTP/" + VersionEnumToString[m_Version] + " " + m_StatusCode.toString() + " " + m_StatusCode.getMessage() + "\r\n"; + m_StatusCode = statusCode; + m_Version = version; - m_FirstLineEndOffset = firstLine.length(); + std::string firstLine = "HTTP/" + VersionEnumToString[m_Version] + " " + m_StatusCode.toString() + " " + + m_StatusCode.getMessage() + "\r\n"; - m_HttpResponse->m_DataLen = firstLine.length(); - m_HttpResponse->m_Data = new uint8_t[m_HttpResponse->m_DataLen]; - memcpy(m_HttpResponse->m_Data, firstLine.c_str(), m_HttpResponse->m_DataLen); + m_FirstLineEndOffset = firstLine.length(); - m_IsComplete = true; -} + m_HttpResponse->m_DataLen = firstLine.length(); + m_HttpResponse->m_Data = new uint8_t[m_HttpResponse->m_DataLen]; + memcpy(m_HttpResponse->m_Data, firstLine.c_str(), m_HttpResponse->m_DataLen); -HttpVersion HttpResponseFirstLine::parseVersion(const char* data, size_t dataLen) -{ - if (!data || dataLen < 8) // "HTTP/x.y" - { - PCPP_LOG_DEBUG("HTTP response length < 8, cannot identify version"); - return HttpVersionUnknown; + m_IsComplete = true; } - if (data[0] != 'H' || data[1] != 'T' || data[2] != 'T' || data[3] != 'P' || data[4] != '/') + HttpVersion HttpResponseFirstLine::parseVersion(const char* data, size_t dataLen) { - PCPP_LOG_DEBUG("HTTP response does not begin with 'HTTP/'"); - return HttpVersionUnknown; - } + if (!data || dataLen < 8) // "HTTP/x.y" + { + PCPP_LOG_DEBUG("HTTP response length < 8, cannot identify version"); + return HttpVersionUnknown; + } - const char* verPos = data + 5; - auto versionAsEnum = HttpVersionStringToEnum.find(std::string(verPos, verPos + 3)); - if (versionAsEnum == HttpVersionStringToEnum.end()) - { - return HttpVersionUnknown; + if (data[0] != 'H' || data[1] != 'T' || data[2] != 'T' || data[3] != 'P' || data[4] != '/') + { + PCPP_LOG_DEBUG("HTTP response does not begin with 'HTTP/'"); + return HttpVersionUnknown; + } + + const char* verPos = data + 5; + auto versionAsEnum = HttpVersionStringToEnum.find(std::string(verPos, verPos + 3)); + if (versionAsEnum == HttpVersionStringToEnum.end()) + { + return HttpVersionUnknown; + } + return versionAsEnum->second; } - return versionAsEnum->second; -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/IPReassembly.cpp b/Packet++/src/IPReassembly.cpp index 95bbb48bab..470bdbf42b 100644 --- a/Packet++/src/IPReassembly.cpp +++ b/Packet++/src/IPReassembly.cpp @@ -11,651 +11,677 @@ namespace pcpp { -uint32_t IPReassemblyHashPacket(IPv4Layer* ipv4Layer) -{ - ScalarBuffer vec[3]; - - vec[0].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; - vec[0].len = 4; - vec[1].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst; - vec[1].len = 4; - vec[2].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipId; - vec[2].len = 2; - - return pcpp::fnvHash(vec, 3); -} - -uint32_t IPReassemblyHashBy3Tuple(const IPv4Address& ipSrc, const IPv4Address& ipDst, uint16_t ipID) -{ - ScalarBuffer vec[3]; - - uint16_t ipIdNetworkOrder = htobe16(ipID); - uint32_t ipSrcAsInt = ipSrc.toInt(); - uint32_t ipDstAsInt = ipDst.toInt(); - - - vec[0].buffer = (uint8_t*)&ipSrcAsInt; - vec[0].len = 4; - vec[1].buffer = (uint8_t*)&ipDstAsInt; - vec[1].len = 4; - vec[2].buffer = (uint8_t*)&ipIdNetworkOrder; - vec[2].len = 2; - - return pcpp::fnvHash(vec, 3); -} - -class IPFragmentWrapper -{ -public: - virtual bool isFragment() = 0; - virtual bool isFirstFragment() = 0; - virtual bool isLastFragment() = 0; - virtual uint16_t getFragmentOffset() = 0; - virtual uint32_t getFragmentId() = 0; - virtual uint32_t hashPacket() = 0; - virtual IPReassembly::PacketKey* createPacketKey() = 0; - - virtual uint8_t* getIPLayerPayload() = 0; - virtual size_t getIPLayerPayloadSize() = 0; - - virtual ~IPFragmentWrapper() { } - -protected: - - IPFragmentWrapper() {} -}; - -class IPv4FragmentWrapper : public IPFragmentWrapper -{ -public: - explicit IPv4FragmentWrapper(Packet* fragment) - { - m_IPLayer = fragment->isPacketOfType(IPv4) ? fragment->getLayerOfType() : nullptr; - } - - // implement abstract methods - - bool isFragment() override - { - return m_IPLayer->isFragment(); - } - - bool isFirstFragment() override + uint32_t IPReassemblyHashPacket(IPv4Layer* ipv4Layer) { - return m_IPLayer->isFirstFragment(); - } - - bool isLastFragment() override - { - return m_IPLayer->isLastFragment(); - } + ScalarBuffer vec[3]; - uint16_t getFragmentOffset() override - { - return m_IPLayer->getFragmentOffset(); - } + vec[0].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; + vec[0].len = 4; + vec[1].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst; + vec[1].len = 4; + vec[2].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipId; + vec[2].len = 2; - uint32_t getFragmentId() override - { - return (uint32_t)be16toh(m_IPLayer->getIPv4Header()->ipId); + return pcpp::fnvHash(vec, 3); } - uint32_t hashPacket() override + uint32_t IPReassemblyHashBy3Tuple(const IPv4Address& ipSrc, const IPv4Address& ipDst, uint16_t ipID) { ScalarBuffer vec[3]; - vec[0].buffer = (uint8_t*)&m_IPLayer->getIPv4Header()->ipSrc; + uint16_t ipIdNetworkOrder = htobe16(ipID); + uint32_t ipSrcAsInt = ipSrc.toInt(); + uint32_t ipDstAsInt = ipDst.toInt(); + + vec[0].buffer = (uint8_t*)&ipSrcAsInt; vec[0].len = 4; - vec[1].buffer = (uint8_t*)&m_IPLayer->getIPv4Header()->ipDst; + vec[1].buffer = (uint8_t*)&ipDstAsInt; vec[1].len = 4; - vec[2].buffer = (uint8_t*)&m_IPLayer->getIPv4Header()->ipId; + vec[2].buffer = (uint8_t*)&ipIdNetworkOrder; vec[2].len = 2; return pcpp::fnvHash(vec, 3); } - IPReassembly::PacketKey* createPacketKey() override - { - return new IPReassembly::IPv4PacketKey(be16toh(m_IPLayer->getIPv4Header()->ipId), m_IPLayer->getSrcIPv4Address(), m_IPLayer->getDstIPv4Address()); - } - - uint8_t* getIPLayerPayload() override + class IPFragmentWrapper { - return m_IPLayer->getLayerPayload(); - } + public: + virtual bool isFragment() = 0; + virtual bool isFirstFragment() = 0; + virtual bool isLastFragment() = 0; + virtual uint16_t getFragmentOffset() = 0; + virtual uint32_t getFragmentId() = 0; + virtual uint32_t hashPacket() = 0; + virtual IPReassembly::PacketKey* createPacketKey() = 0; - size_t getIPLayerPayloadSize() override - { - return m_IPLayer->getLayerPayloadSize(); - } + virtual uint8_t* getIPLayerPayload() = 0; + virtual size_t getIPLayerPayloadSize() = 0; -private: - IPv4Layer* m_IPLayer; + virtual ~IPFragmentWrapper() + {} -}; + protected: + IPFragmentWrapper() + {} + }; -class IPv6FragmentWrapper : public IPFragmentWrapper -{ -public: - explicit IPv6FragmentWrapper(Packet* fragment) + class IPv4FragmentWrapper : public IPFragmentWrapper { - m_IPLayer = fragment->isPacketOfType(IPv6) ? fragment->getLayerOfType() : nullptr; - if (m_IPLayer != nullptr) - m_FragHeader = m_IPLayer->getExtensionOfType(); - else - m_FragHeader = nullptr; - } - - // implement abstract methods + public: + explicit IPv4FragmentWrapper(Packet* fragment) + { + m_IPLayer = fragment->isPacketOfType(IPv4) ? fragment->getLayerOfType() : nullptr; + } - bool isFragment() override - { - return (m_FragHeader != nullptr); - } + // implement abstract methods - bool isFirstFragment() override - { - if (isFragment()) - return m_FragHeader->isFirstFragment(); + bool isFragment() override + { + return m_IPLayer->isFragment(); + } - return false; - } + bool isFirstFragment() override + { + return m_IPLayer->isFirstFragment(); + } - bool isLastFragment() override - { - if (isFragment()) - return m_FragHeader->isLastFragment(); + bool isLastFragment() override + { + return m_IPLayer->isLastFragment(); + } - return false; - } + uint16_t getFragmentOffset() override + { + return m_IPLayer->getFragmentOffset(); + } + uint32_t getFragmentId() override + { + return (uint32_t)be16toh(m_IPLayer->getIPv4Header()->ipId); + } - uint16_t getFragmentOffset() override - { - if (isFragment()) - return m_FragHeader->getFragmentOffset(); + uint32_t hashPacket() override + { + ScalarBuffer vec[3]; - return 0; - } + vec[0].buffer = (uint8_t*)&m_IPLayer->getIPv4Header()->ipSrc; + vec[0].len = 4; + vec[1].buffer = (uint8_t*)&m_IPLayer->getIPv4Header()->ipDst; + vec[1].len = 4; + vec[2].buffer = (uint8_t*)&m_IPLayer->getIPv4Header()->ipId; + vec[2].len = 2; - uint32_t getFragmentId() override - { - return be32toh(m_FragHeader->getFragHeader()->id); - } + return pcpp::fnvHash(vec, 3); + } - uint32_t hashPacket() override - { - if (m_FragHeader == nullptr) - return 0; + IPReassembly::PacketKey* createPacketKey() override + { + return new IPReassembly::IPv4PacketKey(be16toh(m_IPLayer->getIPv4Header()->ipId), + m_IPLayer->getSrcIPv4Address(), m_IPLayer->getDstIPv4Address()); + } - ScalarBuffer vec[3]; + uint8_t* getIPLayerPayload() override + { + return m_IPLayer->getLayerPayload(); + } - vec[0].buffer = m_IPLayer->getIPv6Header()->ipSrc; - vec[0].len = 16; - vec[1].buffer = m_IPLayer->getIPv6Header()->ipDst; - vec[1].len = 16; - vec[2].buffer = (uint8_t*)&m_FragHeader->getFragHeader()->id; - vec[2].len = 4; + size_t getIPLayerPayloadSize() override + { + return m_IPLayer->getLayerPayloadSize(); + } - return pcpp::fnvHash(vec, 3); - } + private: + IPv4Layer* m_IPLayer; + }; - IPReassembly::PacketKey* createPacketKey() override + class IPv6FragmentWrapper : public IPFragmentWrapper { - return new IPReassembly::IPv6PacketKey(be32toh(m_FragHeader->getFragHeader()->id), m_IPLayer->getSrcIPv6Address(), m_IPLayer->getDstIPv6Address()); - } + public: + explicit IPv6FragmentWrapper(Packet* fragment) + { + m_IPLayer = fragment->isPacketOfType(IPv6) ? fragment->getLayerOfType() : nullptr; + if (m_IPLayer != nullptr) + m_FragHeader = m_IPLayer->getExtensionOfType(); + else + m_FragHeader = nullptr; + } - uint8_t* getIPLayerPayload() override - { - return m_IPLayer->getLayerPayload(); - } + // implement abstract methods - size_t getIPLayerPayloadSize() override - { - return m_IPLayer->getLayerPayloadSize(); - } + bool isFragment() override + { + return (m_FragHeader != nullptr); + } -private: - IPv6Layer* m_IPLayer; - IPv6FragmentationHeader* m_FragHeader; + bool isFirstFragment() override + { + if (isFragment()) + return m_FragHeader->isFirstFragment(); -}; + return false; + } + bool isLastFragment() override + { + if (isFragment()) + return m_FragHeader->isLastFragment(); -uint32_t IPReassembly::IPv4PacketKey::getHashValue() const -{ - ScalarBuffer vec[3]; + return false; + } - uint16_t ipIdNetworkOrder = htobe16(m_IpID); - uint32_t ipSrcAsInt = m_SrcIP.toInt(); - uint32_t ipDstAsInt = m_DstIP.toInt(); + uint16_t getFragmentOffset() override + { + if (isFragment()) + return m_FragHeader->getFragmentOffset(); - vec[0].buffer = (uint8_t*)&ipSrcAsInt; - vec[0].len = 4; - vec[1].buffer = (uint8_t*)&ipDstAsInt; - vec[1].len = 4; - vec[2].buffer = (uint8_t*)&ipIdNetworkOrder; - vec[2].len = 2; + return 0; + } - return pcpp::fnvHash(vec, 3); -} + uint32_t getFragmentId() override + { + return be32toh(m_FragHeader->getFragHeader()->id); + } -uint32_t IPReassembly::IPv6PacketKey::getHashValue() const -{ - ScalarBuffer vec[3]; + uint32_t hashPacket() override + { + if (m_FragHeader == nullptr) + return 0; - uint32_t fragIdNetworkOrder = htobe32(m_FragmentID); - uint8_t ipSrcAsByteArr[16]; - uint8_t ipDstAsByteArr[16]; - m_SrcIP.copyTo(ipSrcAsByteArr); - m_DstIP.copyTo(ipDstAsByteArr); + ScalarBuffer vec[3]; - vec[0].buffer = ipSrcAsByteArr; - vec[0].len = 16; - vec[1].buffer = ipDstAsByteArr; - vec[1].len = 16; - vec[2].buffer = (uint8_t*)&fragIdNetworkOrder; - vec[2].len = 4; + vec[0].buffer = m_IPLayer->getIPv6Header()->ipSrc; + vec[0].len = 16; + vec[1].buffer = m_IPLayer->getIPv6Header()->ipDst; + vec[1].len = 16; + vec[2].buffer = (uint8_t*)&m_FragHeader->getFragHeader()->id; + vec[2].len = 4; - return pcpp::fnvHash(vec, 3); -} + return pcpp::fnvHash(vec, 3); + } + IPReassembly::PacketKey* createPacketKey() override + { + return new IPReassembly::IPv6PacketKey(be32toh(m_FragHeader->getFragHeader()->id), + m_IPLayer->getSrcIPv6Address(), m_IPLayer->getDstIPv6Address()); + } + uint8_t* getIPLayerPayload() override + { + return m_IPLayer->getLayerPayload(); + } -IPReassembly::~IPReassembly() -{ - // empty the map - go over all keys, delete all IPFragmentData objects and remove them from the map - while (!m_FragmentMap.empty()) - { - delete m_FragmentMap.begin()->second; - m_FragmentMap.erase(m_FragmentMap.begin()); - } -} + size_t getIPLayerPayloadSize() override + { + return m_IPLayer->getLayerPayloadSize(); + } -Packet* IPReassembly::processPacket(Packet* fragment, ReassemblyStatus& status, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) -{ - status = NON_IP_PACKET; + private: + IPv6Layer* m_IPLayer; + IPv6FragmentationHeader* m_FragHeader; + }; - // packet is not an IP packet - if (!fragment->isPacketOfType(IPv4) && !fragment->isPacketOfType(IPv6)) + uint32_t IPReassembly::IPv4PacketKey::getHashValue() const { - PCPP_LOG_DEBUG("Got a non-IP packet, returning packet to user"); - status = NON_IP_PACKET; - return fragment; - } + ScalarBuffer vec[3]; - // get IPv4 layer - //IPv4Layer* ipLayer = fragment->getLayerOfType(); + uint16_t ipIdNetworkOrder = htobe16(m_IpID); + uint32_t ipSrcAsInt = m_SrcIP.toInt(); + uint32_t ipDstAsInt = m_DstIP.toInt(); - // create fragment wrapper - IPv4FragmentWrapper ipv4Wrapper(fragment); - IPv6FragmentWrapper ipv6Wrapper(fragment); - IPFragmentWrapper* fragWrapper = nullptr; - if (fragment->isPacketOfType(IPv4)) - fragWrapper = &ipv4Wrapper; - else // fragment->isPacketOfType(IPv6) - fragWrapper = &ipv6Wrapper; + vec[0].buffer = (uint8_t*)&ipSrcAsInt; + vec[0].len = 4; + vec[1].buffer = (uint8_t*)&ipDstAsInt; + vec[1].len = 4; + vec[2].buffer = (uint8_t*)&ipIdNetworkOrder; + vec[2].len = 2; - // packet is not a fragment - if (!(fragWrapper->isFragment())) - { - PCPP_LOG_DEBUG("Got a non fragment packet with FragID=0x" << std::hex << fragWrapper->getFragmentId() << ", returning packet to user"); - status = NON_FRAGMENT; - return fragment; + return pcpp::fnvHash(vec, 3); } - // create a hash from source IP, destination IP and IP/fragment ID - uint32_t hash = fragWrapper->hashPacket(); - - IPFragmentData* fragData = nullptr; - - // check whether this packet already exists in the map - std::unordered_map::iterator iter = m_FragmentMap.find(hash); - - // this is the first fragment seen for this packet - if (iter == m_FragmentMap.end()) + uint32_t IPReassembly::IPv6PacketKey::getHashValue() const { - PCPP_LOG_DEBUG("Got new packet with FragID=0x" << std::hex << fragWrapper->getFragmentId() << ", allocating place in map"); + ScalarBuffer vec[3]; - // create the IPFragmentData object - fragData = new IPFragmentData(fragWrapper->createPacketKey(), fragWrapper->getFragmentId()); + uint32_t fragIdNetworkOrder = htobe32(m_FragmentID); + uint8_t ipSrcAsByteArr[16]; + uint8_t ipDstAsByteArr[16]; + m_SrcIP.copyTo(ipSrcAsByteArr); + m_DstIP.copyTo(ipDstAsByteArr); - // add the new fragment to the map - addNewFragment(hash, fragData); - } - else // packet was seen before - { - // get the IPFragmentData object - fragData = iter->second; + vec[0].buffer = ipSrcAsByteArr; + vec[0].len = 16; + vec[1].buffer = ipDstAsByteArr; + vec[1].len = 16; + vec[2].buffer = (uint8_t*)&fragIdNetworkOrder; + vec[2].len = 4; - // mark this packet as used - m_PacketLRU.put(hash, nullptr); + return pcpp::fnvHash(vec, 3); } - bool gotLastFragment = false; - - // if current fragment is the first fragment of this packet - if (fragWrapper->isFirstFragment()) + IPReassembly::~IPReassembly() { - if (fragData->data == nullptr) // first fragment + // empty the map - go over all keys, delete all IPFragmentData objects and remove them from the map + while (!m_FragmentMap.empty()) { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Got first fragment, allocating RawPacket"); - - // create the reassembled packet and copy the fragment data to it - - // copy only data from the beginning of the fragment to the end of IP layer payload. - // Don't copy data beyond it such as packet trailer - auto fragmentRawPacket = fragment->getRawPacket(); - auto rawDataLen = fragWrapper->getIPLayerPayload() - fragmentRawPacket ->getRawData() + fragWrapper->getIPLayerPayloadSize(); - auto rawData = new uint8_t[rawDataLen]; - memcpy(rawData, fragmentRawPacket->getRawData(), rawDataLen); - - fragData->data = new RawPacket(rawData, rawDataLen, fragmentRawPacket->getPacketTimeStamp(), true, fragmentRawPacket->getLinkLayerType()); - fragData->currentOffset = fragWrapper->getIPLayerPayloadSize(); - status = FIRST_FRAGMENT; - - // check if the next fragments already arrived out-of-order and waiting in the out-of-order list - gotLastFragment = matchOutOfOrderFragments(fragData); - } - else // duplicated first fragment - { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Got duplicated first fragment"); - status = FRAGMENT; - return nullptr; + delete m_FragmentMap.begin()->second; + m_FragmentMap.erase(m_FragmentMap.begin()); } } - else // not first fragment + Packet* IPReassembly::processPacket(Packet* fragment, ReassemblyStatus& status, ProtocolType parseUntil, + OsiModelLayer parseUntilLayer) { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Got fragment"); - - uint16_t fragOffset = fragWrapper->getFragmentOffset(); + status = NON_IP_PACKET; - // check if the current fragment offset matches the expected fragment offset - if (fragData->currentOffset == fragOffset) + // packet is not an IP packet + if (!fragment->isPacketOfType(IPv4) && !fragment->isPacketOfType(IPv6)) { - // malformed fragment which is not the first fragment but its offset is 0 - if (fragData->data == nullptr) - { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Fragment is malformed"); - status = MALFORMED_FRAGMENT; - return nullptr; - } - - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Found next matching fragment with offset " << fragOffset << ", adding fragment data to reassembled packet"); - - size_t payloadSize = fragWrapper->getIPLayerPayloadSize(); - // copy fragment data to reassembled packet - fragData->data->reallocateData(fragData->data->getRawDataLen() + payloadSize); - fragData->data->appendData(fragWrapper->getIPLayerPayload(), payloadSize); - - // update expected offset - fragData->currentOffset += payloadSize; - - // if this is the last fragment - mark it - if (fragWrapper->isLastFragment()) - gotLastFragment = true; - else - // if not the last fragment - check if the next fragments are waiting in the out-of-order list - gotLastFragment = matchOutOfOrderFragments(fragData); + PCPP_LOG_DEBUG("Got a non-IP packet, returning packet to user"); + status = NON_IP_PACKET; + return fragment; } - // if current fragment offset is larger than expected - this means this fragment is out-of-order - else if (fragOffset > fragData->currentOffset) - { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Got out-of-ordered fragment with offset " << fragOffset << " (expected: " << fragData->currentOffset << "). Adding it to out-of-order list"); - // create a new IPFragment and copy the fragment data and params to it - size_t payloadSize = fragWrapper->getIPLayerPayloadSize(); - IPFragment* newFrag = new IPFragment(); - newFrag->fragmentOffset = fragWrapper->getFragmentOffset(); - newFrag->fragmentData = new uint8_t[payloadSize]; - newFrag->fragmentDataLen = payloadSize; - memcpy(newFrag->fragmentData, fragWrapper->getIPLayerPayload(), newFrag->fragmentDataLen); - newFrag->lastFragment = fragWrapper->isLastFragment(); + // get IPv4 layer + // IPv4Layer* ipLayer = fragment->getLayerOfType(); - // store the IPFragment in the out-of-order fragment list - fragData->outOfOrderFragments.pushBack(newFrag); + // create fragment wrapper + IPv4FragmentWrapper ipv4Wrapper(fragment); + IPv6FragmentWrapper ipv6Wrapper(fragment); + IPFragmentWrapper* fragWrapper = nullptr; + if (fragment->isPacketOfType(IPv4)) + fragWrapper = &ipv4Wrapper; + else // fragment->isPacketOfType(IPv6) + fragWrapper = &ipv6Wrapper; - status = OUT_OF_ORDER_FRAGMENT; - return nullptr; - } - else + // packet is not a fragment + if (!(fragWrapper->isFragment())) { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Got a fragment with an offset that was already seen: " << fragOffset << " (current offset is: " << fragData->currentOffset << "), probably duplicated fragment"); + PCPP_LOG_DEBUG("Got a non fragment packet with FragID=0x" << std::hex << fragWrapper->getFragmentId() + << ", returning packet to user"); + status = NON_FRAGMENT; + return fragment; } - } + // create a hash from source IP, destination IP and IP/fragment ID + uint32_t hash = fragWrapper->hashPacket(); - // if seen the last fragment - if (gotLastFragment) - { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Reassembly process completed, allocating a packet and returning it"); - fragData->deleteData = false; + IPFragmentData* fragData = nullptr; + + // check whether this packet already exists in the map + std::unordered_map::iterator iter = m_FragmentMap.find(hash); - // fix IP length field - if (fragData->packetKey->getProtocolType() == IPv4) + // this is the first fragment seen for this packet + if (iter == m_FragmentMap.end()) { - Packet tempPacket(fragData->data, IPv4); - IPv4Layer* ipLayer = tempPacket.getLayerOfType(); - iphdr* iphdr = ipLayer->getIPv4Header(); - iphdr->totalLength = htobe16(fragData->currentOffset + ipLayer->getHeaderLen()); - iphdr->fragmentOffset = 0; + PCPP_LOG_DEBUG("Got new packet with FragID=0x" << std::hex << fragWrapper->getFragmentId() + << ", allocating place in map"); + + // create the IPFragmentData object + fragData = new IPFragmentData(fragWrapper->createPacketKey(), fragWrapper->getFragmentId()); + + // add the new fragment to the map + addNewFragment(hash, fragData); } - else + else // packet was seen before { - Packet tempPacket(fragData->data, IPv6); - IPv6Layer* ipLayer = tempPacket.getLayerOfType(); - tempPacket.getLayerOfType()->getIPv6Header()->payloadLength = fragData->currentOffset + ipLayer->getHeaderLen(); + // get the IPFragmentData object + fragData = iter->second; + + // mark this packet as used + m_PacketLRU.put(hash, nullptr); } - // create a new Packet object with the reassembled data as its RawPacket - Packet* reassembledPacket = new Packet(fragData->data, true, parseUntil, parseUntilLayer); + bool gotLastFragment = false; - if (fragData->packetKey->getProtocolType() == IPv4) - { - // re-calculate all IPv4 fields - reassembledPacket->getLayerOfType()->computeCalculateFields(); - } - else + // if current fragment is the first fragment of this packet + if (fragWrapper->isFirstFragment()) { - // remove fragment extension - IPv6Layer* ipLayer = reassembledPacket->getLayerOfType(); - ipLayer->removeAllExtensions(); + if (fragData->data == nullptr) // first fragment + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Got first fragment, allocating RawPacket"); - // re-calculate all IPv4 fields - ipLayer->computeCalculateFields(); - } + // create the reassembled packet and copy the fragment data to it - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Deleting fragment data from map"); + // copy only data from the beginning of the fragment to the end of IP layer payload. + // Don't copy data beyond it such as packet trailer + auto fragmentRawPacket = fragment->getRawPacket(); + auto rawDataLen = fragWrapper->getIPLayerPayload() - fragmentRawPacket->getRawData() + + fragWrapper->getIPLayerPayloadSize(); + auto rawData = new uint8_t[rawDataLen]; + memcpy(rawData, fragmentRawPacket->getRawData(), rawDataLen); - // delete the IPFragmentData object and remove it from the map - delete fragData; - m_FragmentMap.erase(iter); - m_PacketLRU.eraseElement(hash); - status = REASSEMBLED; - return reassembledPacket; - } + fragData->data = new RawPacket(rawData, rawDataLen, fragmentRawPacket->getPacketTimeStamp(), true, + fragmentRawPacket->getLinkLayerType()); + fragData->currentOffset = fragWrapper->getIPLayerPayloadSize(); + status = FIRST_FRAGMENT; + + // check if the next fragments already arrived out-of-order and waiting in the out-of-order list + gotLastFragment = matchOutOfOrderFragments(fragData); + } + else // duplicated first fragment + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Got duplicated first fragment"); + status = FRAGMENT; + return nullptr; + } + } - // if got to here it means this fragment is either the first fragment or a fragment in the middle. Set the appropriate status and return - if (status != FIRST_FRAGMENT) - status = FRAGMENT; + else // not first fragment + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() << "] Got fragment"); - return nullptr; -} + uint16_t fragOffset = fragWrapper->getFragmentOffset(); -Packet* IPReassembly::processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) -{ - Packet* parsedFragment = new Packet(fragment, false, parseUntil, parseUntilLayer); - Packet* result = processPacket(parsedFragment, status, parseUntil, parseUntilLayer); - if (result != parsedFragment) - delete parsedFragment; + // check if the current fragment offset matches the expected fragment offset + if (fragData->currentOffset == fragOffset) + { + // malformed fragment which is not the first fragment but its offset is 0 + if (fragData->data == nullptr) + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Fragment is malformed"); + status = MALFORMED_FRAGMENT; + return nullptr; + } - return result; -} + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Found next matching fragment with offset " << fragOffset + << ", adding fragment data to reassembled packet"); -Packet* IPReassembly::getCurrentPacket(const PacketKey& key) -{ - // create a hash out of the packet key - uint32_t hash = key.getHashValue(); + size_t payloadSize = fragWrapper->getIPLayerPayloadSize(); + // copy fragment data to reassembled packet + fragData->data->reallocateData(fragData->data->getRawDataLen() + payloadSize); + fragData->data->appendData(fragWrapper->getIPLayerPayload(), payloadSize); - // look for this hash value in the map - std::unordered_map::iterator iter = m_FragmentMap.find(hash); + // update expected offset + fragData->currentOffset += payloadSize; - // hash was found - if (iter != m_FragmentMap.end()) - { - IPFragmentData* fragData = iter->second; + // if this is the last fragment - mark it + if (fragWrapper->isLastFragment()) + gotLastFragment = true; + else + // if not the last fragment - check if the next fragments are waiting in the out-of-order list + gotLastFragment = matchOutOfOrderFragments(fragData); + } + // if current fragment offset is larger than expected - this means this fragment is out-of-order + else if (fragOffset > fragData->currentOffset) + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Got out-of-ordered fragment with offset " << fragOffset + << " (expected: " << fragData->currentOffset + << "). Adding it to out-of-order list"); + + // create a new IPFragment and copy the fragment data and params to it + size_t payloadSize = fragWrapper->getIPLayerPayloadSize(); + IPFragment* newFrag = new IPFragment(); + newFrag->fragmentOffset = fragWrapper->getFragmentOffset(); + newFrag->fragmentData = new uint8_t[payloadSize]; + newFrag->fragmentDataLen = payloadSize; + memcpy(newFrag->fragmentData, fragWrapper->getIPLayerPayload(), newFrag->fragmentDataLen); + newFrag->lastFragment = fragWrapper->isLastFragment(); + + // store the IPFragment in the out-of-order fragment list + fragData->outOfOrderFragments.pushBack(newFrag); + + status = OUT_OF_ORDER_FRAGMENT; + return nullptr; + } + else + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Got a fragment with an offset that was already seen: " << fragOffset + << " (current offset is: " << fragData->currentOffset + << "), probably duplicated fragment"); + } + } - // some data already exists - if (fragData != nullptr && fragData->data != nullptr) + // if seen the last fragment + if (gotLastFragment) { - // create a copy of the RawPacket object - RawPacket* partialRawPacket = new RawPacket(*(fragData->data)); + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Reassembly process completed, allocating a packet and returning it"); + fragData->deleteData = false; // fix IP length field if (fragData->packetKey->getProtocolType() == IPv4) { - Packet tempPacket(partialRawPacket, IPv4); + Packet tempPacket(fragData->data, IPv4); IPv4Layer* ipLayer = tempPacket.getLayerOfType(); - ipLayer->getIPv4Header()->totalLength = htobe16(fragData->currentOffset + ipLayer->getHeaderLen()); + iphdr* iphdr = ipLayer->getIPv4Header(); + iphdr->totalLength = htobe16(fragData->currentOffset + ipLayer->getHeaderLen()); + iphdr->fragmentOffset = 0; } else { - Packet tempPacket(partialRawPacket, IPv6); + Packet tempPacket(fragData->data, IPv6); IPv6Layer* ipLayer = tempPacket.getLayerOfType(); - tempPacket.getLayerOfType()->getIPv6Header()->payloadLength = fragData->currentOffset + + ipLayer->getHeaderLen(); + tempPacket.getLayerOfType()->getIPv6Header()->payloadLength = + fragData->currentOffset + ipLayer->getHeaderLen(); } - // create a packet object wrapping the RawPacket we've just created - Packet* partialDataPacket = new Packet(partialRawPacket, true); + // create a new Packet object with the reassembled data as its RawPacket + Packet* reassembledPacket = new Packet(fragData->data, true, parseUntil, parseUntilLayer); - // prepare the packet and return it - if (key.getProtocolType() == IPv4) + if (fragData->packetKey->getProtocolType() == IPv4) { - IPv4Layer* ipLayer = partialDataPacket->getLayerOfType(); - ipLayer->getIPv4Header()->fragmentOffset = 0; - ipLayer->computeCalculateFields(); + // re-calculate all IPv4 fields + reassembledPacket->getLayerOfType()->computeCalculateFields(); } - else // key.getProtocolType() == IPv6 + else { - IPv6Layer* ipLayer = partialDataPacket->getLayerOfType(); + // remove fragment extension + IPv6Layer* ipLayer = reassembledPacket->getLayerOfType(); ipLayer->removeAllExtensions(); + + // re-calculate all IPv4 fields ipLayer->computeCalculateFields(); } - return partialDataPacket; - } - } + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragWrapper->getFragmentId() + << "] Deleting fragment data from map"); - return nullptr; -} + // delete the IPFragmentData object and remove it from the map + delete fragData; + m_FragmentMap.erase(iter); + m_PacketLRU.eraseElement(hash); + status = REASSEMBLED; + return reassembledPacket; + } -void IPReassembly::removePacket(const PacketKey& key) -{ - // create a hash out of the packet key - uint32_t hash = key.getHashValue(); + // if got to here it means this fragment is either the first fragment or a fragment in the middle. Set the + // appropriate status and return + if (status != FIRST_FRAGMENT) + status = FRAGMENT; - // look for this hash value in the map - std::unordered_map::iterator iter = m_FragmentMap.find(hash); + return nullptr; + } - // hash was found - if (iter != m_FragmentMap.end()) + Packet* IPReassembly::processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil, + OsiModelLayer parseUntilLayer) { - // free all data saved in the map - delete iter->second; - m_FragmentMap.erase(iter); + Packet* parsedFragment = new Packet(fragment, false, parseUntil, parseUntilLayer); + Packet* result = processPacket(parsedFragment, status, parseUntil, parseUntilLayer); + if (result != parsedFragment) + delete parsedFragment; - // remove from LRU list - m_PacketLRU.eraseElement(hash); + return result; } -} -void IPReassembly::addNewFragment(uint32_t hash, IPFragmentData* fragData) -{ - // put the new frag in the LRU list - uint32_t packetRemoved; - - if (m_PacketLRU.put(hash, &packetRemoved) == 1) // this means LRU list was full and the least recently used item was removed + Packet* IPReassembly::getCurrentPacket(const PacketKey& key) { - // remove this item from the fragment map - std::unordered_map::iterator iter = m_FragmentMap.find(packetRemoved); - IPFragmentData* dataRemoved = iter->second; + // create a hash out of the packet key + uint32_t hash = key.getHashValue(); - PacketKey* key = nullptr; - if (m_OnFragmentsCleanCallback != nullptr) - key = dataRemoved->packetKey->clone(); + // look for this hash value in the map + std::unordered_map::iterator iter = m_FragmentMap.find(hash); + + // hash was found + if (iter != m_FragmentMap.end()) + { + IPFragmentData* fragData = iter->second; - PCPP_LOG_DEBUG("Reached maximum packet capacity, removing data for FragID=0x" << std::hex << dataRemoved->fragmentID); - delete dataRemoved; - m_FragmentMap.erase(iter); + // some data already exists + if (fragData != nullptr && fragData->data != nullptr) + { + // create a copy of the RawPacket object + RawPacket* partialRawPacket = new RawPacket(*(fragData->data)); - // fire callback if not null - if (m_OnFragmentsCleanCallback != nullptr) + // fix IP length field + if (fragData->packetKey->getProtocolType() == IPv4) + { + Packet tempPacket(partialRawPacket, IPv4); + IPv4Layer* ipLayer = tempPacket.getLayerOfType(); + ipLayer->getIPv4Header()->totalLength = htobe16(fragData->currentOffset + ipLayer->getHeaderLen()); + } + else + { + Packet tempPacket(partialRawPacket, IPv6); + IPv6Layer* ipLayer = tempPacket.getLayerOfType(); + tempPacket.getLayerOfType()->getIPv6Header()->payloadLength = + fragData->currentOffset + +ipLayer->getHeaderLen(); + } + + // create a packet object wrapping the RawPacket we've just created + Packet* partialDataPacket = new Packet(partialRawPacket, true); + + // prepare the packet and return it + if (key.getProtocolType() == IPv4) + { + IPv4Layer* ipLayer = partialDataPacket->getLayerOfType(); + ipLayer->getIPv4Header()->fragmentOffset = 0; + ipLayer->computeCalculateFields(); + } + else // key.getProtocolType() == IPv6 + { + IPv6Layer* ipLayer = partialDataPacket->getLayerOfType(); + ipLayer->removeAllExtensions(); + ipLayer->computeCalculateFields(); + } + + return partialDataPacket; + } + } + + return nullptr; + } + + void IPReassembly::removePacket(const PacketKey& key) + { + // create a hash out of the packet key + uint32_t hash = key.getHashValue(); + + // look for this hash value in the map + std::unordered_map::iterator iter = m_FragmentMap.find(hash); + + // hash was found + if (iter != m_FragmentMap.end()) { - m_OnFragmentsCleanCallback(key, m_CallbackUserCookie); - delete key; + // free all data saved in the map + delete iter->second; + m_FragmentMap.erase(iter); + + // remove from LRU list + m_PacketLRU.eraseElement(hash); } } - // add the new fragment to the map - std::pair pair(hash, fragData); - m_FragmentMap.insert(pair); -} + void IPReassembly::addNewFragment(uint32_t hash, IPFragmentData* fragData) + { + // put the new frag in the LRU list + uint32_t packetRemoved; -bool IPReassembly::matchOutOfOrderFragments(IPFragmentData* fragData) -{ - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID << "] Searching out-of-order fragment list for the next fragment"); + // this means LRU list was full and the least recently used item was removed + if (m_PacketLRU.put(hash, &packetRemoved) == 1) + { + // remove this item from the fragment map + std::unordered_map::iterator iter = m_FragmentMap.find(packetRemoved); + IPFragmentData* dataRemoved = iter->second; + + PacketKey* key = nullptr; + if (m_OnFragmentsCleanCallback != nullptr) + key = dataRemoved->packetKey->clone(); + + PCPP_LOG_DEBUG("Reached maximum packet capacity, removing data for FragID=0x" << std::hex + << dataRemoved->fragmentID); + delete dataRemoved; + m_FragmentMap.erase(iter); - // a flag indicating whether the last fragment of the packet was found - bool foundLastSegment = false; + // fire callback if not null + if (m_OnFragmentsCleanCallback != nullptr) + { + m_OnFragmentsCleanCallback(key, m_CallbackUserCookie); + delete key; + } + } + + // add the new fragment to the map + std::pair pair(hash, fragData); + m_FragmentMap.insert(pair); + } - // run until the last fragment was found or until we finished going over the out-of-order list and didn't find any matching fragment - while (!foundLastSegment) + bool IPReassembly::matchOutOfOrderFragments(IPFragmentData* fragData) { - bool foundOutOfOrderFrag = false; + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID + << "] Searching out-of-order fragment list for the next fragment"); - int index = 0; + // a flag indicating whether the last fragment of the packet was found + bool foundLastSegment = false; - // go over all fragment in the out-of-order list - while (index < (int)fragData->outOfOrderFragments.size()) + // run until the last fragment was found or until we finished going over the out-of-order list and didn't find + // any matching fragment + while (!foundLastSegment) { - // get the current fragment from the out-of-order list - IPFragment* frag = fragData->outOfOrderFragments.at(index); + bool foundOutOfOrderFrag = false; - // this fragment is exactly the one we're looking for - if (fragData->currentOffset == frag->fragmentOffset) + int index = 0; + + // go over all fragment in the out-of-order list + while (index < (int)fragData->outOfOrderFragments.size()) { - // add it to the reassembled packet - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID << "] Found the next matching fragment in out-of-order list with offset " << frag->fragmentOffset << ", adding its data to reassembled packet"); - fragData->data->reallocateData(fragData->data->getRawDataLen() + frag->fragmentDataLen); - fragData->data->appendData(frag->fragmentData, frag->fragmentDataLen); - fragData->currentOffset += frag->fragmentDataLen; - if (frag->lastFragment) // if this is the last fragment of the packet + // get the current fragment from the out-of-order list + IPFragment* frag = fragData->outOfOrderFragments.at(index); + + // this fragment is exactly the one we're looking for + if (fragData->currentOffset == frag->fragmentOffset) { - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID << "] Found last fragment inside out-of-order list"); - foundLastSegment = true; + // add it to the reassembled packet + PCPP_LOG_DEBUG("[FragID=0x" + << std::hex << fragData->fragmentID + << "] Found the next matching fragment in out-of-order list with offset " + << frag->fragmentOffset << ", adding its data to reassembled packet"); + fragData->data->reallocateData(fragData->data->getRawDataLen() + frag->fragmentDataLen); + fragData->data->appendData(frag->fragmentData, frag->fragmentDataLen); + fragData->currentOffset += frag->fragmentDataLen; + if (frag->lastFragment) // if this is the last fragment of the packet + { + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID + << "] Found last fragment inside out-of-order list"); + foundLastSegment = true; + } + + // remove this fragment from the out-of-order list + fragData->outOfOrderFragments.erase(fragData->outOfOrderFragments.begin() + index); + + // mark that we found at least one matching fragment in the out-of-order list + foundOutOfOrderFrag = true; } + else + index++; + } - // remove this fragment from the out-of-order list - fragData->outOfOrderFragments.erase(fragData->outOfOrderFragments.begin() + index); - - // mark that we found at least one matching fragment in the out-of-order list - foundOutOfOrderFrag = true; + // during the search we did on the out-of-order list we didn't find any matching fragment + if (!foundOutOfOrderFrag) + { + // break the loop - need to wait for the missing fragment in next incoming packets + PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID + << "] Didn't find the next fragment in out-of-order list"); + break; } - else - index++; } - // during the search we did on the out-of-order list we didn't find any matching fragment - if (!foundOutOfOrderFrag) - { - // break the loop - need to wait for the missing fragment in next incoming packets - PCPP_LOG_DEBUG("[FragID=0x" << std::hex << fragData->fragmentID << "] Didn't find the next fragment in out-of-order list"); - break; - } + return foundLastSegment; } - return foundLastSegment; -} - -} +} // namespace pcpp diff --git a/Packet++/src/IPSecLayer.cpp b/Packet++/src/IPSecLayer.cpp index 0ebee80198..445ddcb54c 100644 --- a/Packet++/src/IPSecLayer.cpp +++ b/Packet++/src/IPSecLayer.cpp @@ -13,119 +13,118 @@ namespace pcpp { -// --------------------------------- -// AuthenticationHeaderLayer methods -// --------------------------------- + // --------------------------------- + // AuthenticationHeaderLayer methods + // --------------------------------- -uint32_t AuthenticationHeaderLayer::getSPI() const -{ - return be32toh(getAHHeader()->spi); -} - -uint32_t AuthenticationHeaderLayer::getSequenceNumber() const -{ - return be32toh(getAHHeader()->sequenceNumber); -} - -size_t AuthenticationHeaderLayer::getICVLength() const -{ - // payloadLen = 3 (fixed ipsec_authentication_header size 32-bit words) + ICV - 2 - // ICV = (payloadLen + 2 - 3) in 32-bit words - return (getAHHeader()->payloadLen - 1)*4; -} + uint32_t AuthenticationHeaderLayer::getSPI() const + { + return be32toh(getAHHeader()->spi); + } -uint8_t* AuthenticationHeaderLayer::getICVBytes() const -{ - size_t icvLength = getICVLength(); - if (icvLength > 0) - return m_Data + sizeof(ipsec_authentication_header); - return nullptr; -} + uint32_t AuthenticationHeaderLayer::getSequenceNumber() const + { + return be32toh(getAHHeader()->sequenceNumber); + } -std::string AuthenticationHeaderLayer::getICVHexStream() const -{ - uint8_t* bytes = getICVBytes(); - if (bytes == nullptr) - return ""; + size_t AuthenticationHeaderLayer::getICVLength() const + { + // payloadLen = 3 (fixed ipsec_authentication_header size 32-bit words) + ICV - 2 + // ICV = (payloadLen + 2 - 3) in 32-bit words + return (getAHHeader()->payloadLen - 1) * 4; + } - return byteArrayToHexString(bytes, getICVLength()); -} + uint8_t* AuthenticationHeaderLayer::getICVBytes() const + { + size_t icvLength = getICVLength(); + if (icvLength > 0) + return m_Data + sizeof(ipsec_authentication_header); + return nullptr; + } -void AuthenticationHeaderLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; + std::string AuthenticationHeaderLayer::getICVHexStream() const + { + uint8_t* bytes = getICVBytes(); + if (bytes == nullptr) + return ""; - uint8_t* payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; + return byteArrayToHexString(bytes, getICVLength()); + } - switch (getAHHeader()->nextHeader) + void AuthenticationHeaderLayer::parseNextLayer() { - case PACKETPP_IPPROTO_UDP: - if (payloadLen >= sizeof(udphdr)) - m_NextLayer = new UdpLayer(payload, payloadLen, this, m_Packet); - break; - case PACKETPP_IPPROTO_TCP: - m_NextLayer = TcpLayer::isDataValid(payload, payloadLen) - ? static_cast(new TcpLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_IPIP: - { - uint8_t ipVersion = *payload >> 4; - if (ipVersion == 4 && IPv4Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new IPv4Layer(payload, payloadLen, this, m_Packet); - else if (ipVersion == 6 && IPv6Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new IPv6Layer(payload, payloadLen, this, m_Packet); - else + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; + + switch (getAHHeader()->nextHeader) + { + case PACKETPP_IPPROTO_UDP: + if (payloadLen >= sizeof(udphdr)) + m_NextLayer = new UdpLayer(payload, payloadLen, this, m_Packet); + break; + case PACKETPP_IPPROTO_TCP: + m_NextLayer = TcpLayer::isDataValid(payload, payloadLen) + ? static_cast(new TcpLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PACKETPP_IPPROTO_IPIP: + { + uint8_t ipVersion = *payload >> 4; + if (ipVersion == 4 && IPv4Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new IPv4Layer(payload, payloadLen, this, m_Packet); + else if (ipVersion == 6 && IPv6Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new IPv6Layer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + break; + } + case PACKETPP_IPPROTO_ESP: + m_NextLayer = ESPLayer::isDataValid(payload, payloadLen) + ? static_cast(new ESPLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + default: m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; - } - case PACKETPP_IPPROTO_ESP: - m_NextLayer = ESPLayer::isDataValid(payload, payloadLen) - ? static_cast(new ESPLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } } -} - -std::string AuthenticationHeaderLayer::toString() const -{ - return "Authentication Header Layer"; -} + std::string AuthenticationHeaderLayer::toString() const + { + return "Authentication Header Layer"; + } -// ---------------- -// ESPLayer methods -// ---------------- + // ---------------- + // ESPLayer methods + // ---------------- -uint32_t ESPLayer::getSPI() const -{ - return be32toh(getESPHeader()->spi); -} + uint32_t ESPLayer::getSPI() const + { + return be32toh(getESPHeader()->spi); + } -uint32_t ESPLayer::getSequenceNumber() const -{ - return be32toh(getESPHeader()->sequenceNumber); -} + uint32_t ESPLayer::getSequenceNumber() const + { + return be32toh(getESPHeader()->sequenceNumber); + } -void ESPLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; + void ESPLayer::parseNextLayer() + { + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; - m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); -} + m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + } -std::string ESPLayer::toString() const -{ - std::ostringstream stream; - stream << "ESP Layer, SPI: 0x" << std::hex << getSPI(); - return stream.str(); -} + std::string ESPLayer::toString() const + { + std::ostringstream stream; + stream << "ESP Layer, SPI: 0x" << std::hex << getSPI(); + return stream.str(); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/IPv4Layer.cpp b/Packet++/src/IPv4Layer.cpp index 777af11e96..7f09c5db5c 100644 --- a/Packet++/src/IPv4Layer.cpp +++ b/Packet++/src/IPv4Layer.cpp @@ -22,575 +22,582 @@ namespace pcpp #define IPV4OPT_DUMMY 0xff #define IPV4_MAX_OPT_SIZE 40 + /// ~~~~~~~~~~~~~~~~~ + /// IPv4OptionBuilder + /// ~~~~~~~~~~~~~~~~~ -/// ~~~~~~~~~~~~~~~~~ -/// IPv4OptionBuilder -/// ~~~~~~~~~~~~~~~~~ - -IPv4OptionBuilder::IPv4OptionBuilder(IPv4OptionTypes optionType, const std::vector& ipList) -{ - m_RecType = (uint8_t)optionType; - m_RecValueLen = ipList.size() * sizeof(uint32_t) + sizeof(uint8_t); - m_RecValue = new uint8_t[m_RecValueLen]; - - size_t curOffset = 0; - m_RecValue[curOffset++] = 0; // init pointer value - - bool firstZero = false; - for (const auto &ipAddr : ipList) + IPv4OptionBuilder::IPv4OptionBuilder(IPv4OptionTypes optionType, const std::vector& ipList) { - uint32_t ipAddrAsInt = ipAddr.toInt(); - - if (!firstZero) - m_RecValue[0] += (uint8_t)4; - - if (!firstZero && ipAddrAsInt == 0) - firstZero = true; + m_RecType = (uint8_t)optionType; + m_RecValueLen = ipList.size() * sizeof(uint32_t) + sizeof(uint8_t); + m_RecValue = new uint8_t[m_RecValueLen]; - memcpy(m_RecValue + curOffset, &ipAddrAsInt, sizeof(uint32_t)); - curOffset += sizeof(uint32_t); - } + size_t curOffset = 0; + m_RecValue[curOffset++] = 0; // init pointer value - m_BuilderParamsValid = true; -} + bool firstZero = false; + for (const auto& ipAddr : ipList) + { + uint32_t ipAddrAsInt = ipAddr.toInt(); -IPv4OptionBuilder::IPv4OptionBuilder(const IPv4TimestampOptionValue& timestampValue) -{ - m_RecType = (uint8_t)IPV4OPT_Timestamp; - m_RecValueLen = 0; - m_RecValue = nullptr; + if (!firstZero) + m_RecValue[0] += (uint8_t)4; - if (timestampValue.type == IPv4TimestampOptionValue::Unknown) - { - PCPP_LOG_ERROR("Cannot build timestamp option of type IPv4TimestampOptionValue::Unknown"); - m_BuilderParamsValid = false; - return; - } + if (!firstZero && ipAddrAsInt == 0) + firstZero = true; - if (timestampValue.type == IPv4TimestampOptionValue::TimestampsForPrespecifiedIPs) - { - PCPP_LOG_ERROR("Cannot build timestamp option of type IPv4TimestampOptionValue::TimestampsForPrespecifiedIPs - this type is not supported"); - m_BuilderParamsValid = false; - return; - } + memcpy(m_RecValue + curOffset, &ipAddrAsInt, sizeof(uint32_t)); + curOffset += sizeof(uint32_t); + } - if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP && timestampValue.timestamps.size() != timestampValue.ipAddresses.size()) - { - PCPP_LOG_ERROR("Cannot build timestamp option of type IPv4TimestampOptionValue::TimestampAndIP because number of timestamps and IP addresses is not equal"); - m_BuilderParamsValid = false; - return; + m_BuilderParamsValid = true; } - m_RecValueLen = timestampValue.timestamps.size() * sizeof(uint32_t) + 2 * sizeof(uint8_t); - - if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP) + IPv4OptionBuilder::IPv4OptionBuilder(const IPv4TimestampOptionValue& timestampValue) { - m_RecValueLen += timestampValue.timestamps.size() * sizeof(uint32_t); - } + m_RecType = (uint8_t)IPV4OPT_Timestamp; + m_RecValueLen = 0; + m_RecValue = nullptr; - m_RecValue = new uint8_t[m_RecValueLen]; + if (timestampValue.type == IPv4TimestampOptionValue::Unknown) + { + PCPP_LOG_ERROR("Cannot build timestamp option of type IPv4TimestampOptionValue::Unknown"); + m_BuilderParamsValid = false; + return; + } - size_t curOffset = 0; - m_RecValue[curOffset++] = 1; //pointer default value is 1 - means there are no empty timestamps - m_RecValue[curOffset++] = (uint8_t)timestampValue.type; // timestamp type + if (timestampValue.type == IPv4TimestampOptionValue::TimestampsForPrespecifiedIPs) + { + PCPP_LOG_ERROR( + "Cannot build timestamp option of type IPv4TimestampOptionValue::TimestampsForPrespecifiedIPs - this type is not supported"); + m_BuilderParamsValid = false; + return; + } - int firstZero = -1; - for (int i = 0; i < (int)timestampValue.timestamps.size(); i++) - { - uint32_t timestamp = htobe32(timestampValue.timestamps.at(i)); + if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP && + timestampValue.timestamps.size() != timestampValue.ipAddresses.size()) + { + PCPP_LOG_ERROR( + "Cannot build timestamp option of type IPv4TimestampOptionValue::TimestampAndIP because number of timestamps and IP addresses is not equal"); + m_BuilderParamsValid = false; + return; + } - // for pointer calculation - find the first timestamp equals to 0 - if (timestamp == 0 && firstZero == -1) - firstZero = i; + m_RecValueLen = timestampValue.timestamps.size() * sizeof(uint32_t) + 2 * sizeof(uint8_t); if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP) { - uint32_t ipAddrAsInt = timestampValue.ipAddresses.at(i).toInt(); - memcpy(m_RecValue + curOffset , &ipAddrAsInt, sizeof(uint32_t)); - curOffset += sizeof(uint32_t); + m_RecValueLen += timestampValue.timestamps.size() * sizeof(uint32_t); } - memcpy(m_RecValue + curOffset , ×tamp, sizeof(uint32_t)); - curOffset += sizeof(uint32_t); - } + m_RecValue = new uint8_t[m_RecValueLen]; - // calculate pointer field - if (firstZero > -1) - { - uint8_t pointerVal = (uint8_t)(4 * sizeof(uint8_t) + firstZero * sizeof(uint32_t) + 1); - if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP) - pointerVal += (uint8_t)(firstZero * sizeof(uint32_t)); + size_t curOffset = 0; + m_RecValue[curOffset++] = 1; // pointer default value is 1 - means there are no empty timestamps + m_RecValue[curOffset++] = (uint8_t)timestampValue.type; // timestamp type - m_RecValue[0] = pointerVal; - } + int firstZero = -1; + for (int i = 0; i < (int)timestampValue.timestamps.size(); i++) + { + uint32_t timestamp = htobe32(timestampValue.timestamps.at(i)); - m_BuilderParamsValid = true; -} + // for pointer calculation - find the first timestamp equals to 0 + if (timestamp == 0 && firstZero == -1) + firstZero = i; -IPv4Option IPv4OptionBuilder::build() const -{ - if (!m_BuilderParamsValid) - return IPv4Option(nullptr); + if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP) + { + uint32_t ipAddrAsInt = timestampValue.ipAddresses.at(i).toInt(); + memcpy(m_RecValue + curOffset, &ipAddrAsInt, sizeof(uint32_t)); + curOffset += sizeof(uint32_t); + } - size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); + memcpy(m_RecValue + curOffset, ×tamp, sizeof(uint32_t)); + curOffset += sizeof(uint32_t); + } - uint8_t recType = static_cast(m_RecType); - if ((recType == (uint8_t)IPV4OPT_NOP || recType == (uint8_t)IPV4OPT_EndOfOptionsList)) - { - if (m_RecValueLen != 0) + // calculate pointer field + if (firstZero > -1) { - PCPP_LOG_ERROR("Can't set IPv4 NOP option or IPv4 End-of-options option with size different than 0, tried to set size " << (int)m_RecValueLen); - return IPv4Option(nullptr); + uint8_t pointerVal = (uint8_t)(4 * sizeof(uint8_t) + firstZero * sizeof(uint32_t) + 1); + if (timestampValue.type == IPv4TimestampOptionValue::TimestampAndIP) + pointerVal += (uint8_t)(firstZero * sizeof(uint32_t)); + + m_RecValue[0] = pointerVal; } - optionSize = sizeof(uint8_t); + m_BuilderParamsValid = true; } - uint8_t* recordBuffer = new uint8_t[optionSize]; - memset(recordBuffer, 0, optionSize); - recordBuffer[0] = recType; - if (optionSize > 1) + IPv4Option IPv4OptionBuilder::build() const { - recordBuffer[1] = static_cast(optionSize); - if (optionSize > 2 && m_RecValue != nullptr) - memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); - } + if (!m_BuilderParamsValid) + return IPv4Option(nullptr); - return IPv4Option(recordBuffer); -} + size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); + uint8_t recType = static_cast(m_RecType); + if ((recType == (uint8_t)IPV4OPT_NOP || recType == (uint8_t)IPV4OPT_EndOfOptionsList)) + { + if (m_RecValueLen != 0) + { + PCPP_LOG_ERROR( + "Can't set IPv4 NOP option or IPv4 End-of-options option with size different than 0, tried to set size " + << (int)m_RecValueLen); + return IPv4Option(nullptr); + } + + optionSize = sizeof(uint8_t); + } -/// ~~~~~~~~~ -/// IPv4Layer -/// ~~~~~~~~~ + uint8_t* recordBuffer = new uint8_t[optionSize]; + memset(recordBuffer, 0, optionSize); + recordBuffer[0] = recType; + if (optionSize > 1) + { + recordBuffer[1] = static_cast(optionSize); + if (optionSize > 2 && m_RecValue != nullptr) + memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); + } + return IPv4Option(recordBuffer); + } -void IPv4Layer::initLayer() -{ - const size_t headerLen = sizeof(iphdr); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - m_Protocol = IPv4; - memset(m_Data, 0, headerLen); - iphdr* ipHdr = getIPv4Header(); - ipHdr->internetHeaderLength = (5 & 0xf); - m_NumOfTrailingBytes = 0; - m_TempHeaderExtension = 0; -} - -void IPv4Layer::initLayerInPacket(bool setTotalLenAsDataLen) -{ - m_Protocol = IPv4; - m_NumOfTrailingBytes = 0; - m_TempHeaderExtension = 0; - if (setTotalLenAsDataLen) + /// ~~~~~~~~~ + /// IPv4Layer + /// ~~~~~~~~~ + + void IPv4Layer::initLayer() { - size_t totalLen = be16toh(getIPv4Header()->totalLength); - // if totalLen == 0 this usually means TCP Segmentation Offload (TSO). In this case we should ignore the value of totalLen - // and look at the data captured on the wire - if ((totalLen < m_DataLen) && (totalLen !=0)) - m_DataLen = totalLen; + const size_t headerLen = sizeof(iphdr); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + m_Protocol = IPv4; + memset(m_Data, 0, headerLen); + iphdr* ipHdr = getIPv4Header(); + ipHdr->internetHeaderLength = (5 & 0xf); + m_NumOfTrailingBytes = 0; + m_TempHeaderExtension = 0; } -} -void IPv4Layer::copyLayerData(const IPv4Layer& other) -{ - m_OptionReader = other.m_OptionReader; - m_NumOfTrailingBytes = other.m_NumOfTrailingBytes; - m_TempHeaderExtension = other.m_TempHeaderExtension; -} + void IPv4Layer::initLayerInPacket(bool setTotalLenAsDataLen) + { + m_Protocol = IPv4; + m_NumOfTrailingBytes = 0; + m_TempHeaderExtension = 0; + if (setTotalLenAsDataLen) + { + size_t totalLen = be16toh(getIPv4Header()->totalLength); + // if totalLen == 0 this usually means TCP Segmentation Offload (TSO). In this case we should ignore the + // value of totalLen and look at the data captured on the wire + if ((totalLen < m_DataLen) && (totalLen != 0)) + m_DataLen = totalLen; + } + } -IPv4Layer::IPv4Layer() -{ - initLayer(); -} + void IPv4Layer::copyLayerData(const IPv4Layer& other) + { + m_OptionReader = other.m_OptionReader; + m_NumOfTrailingBytes = other.m_NumOfTrailingBytes; + m_TempHeaderExtension = other.m_TempHeaderExtension; + } -IPv4Layer::IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen) : Layer(data, dataLen, prevLayer, packet) -{ - initLayerInPacket(setTotalLenAsDataLen); -} + IPv4Layer::IPv4Layer() + { + initLayer(); + } -IPv4Layer::IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) -{ - initLayerInPacket(true); -} + IPv4Layer::IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet, bool setTotalLenAsDataLen) + : Layer(data, dataLen, prevLayer, packet) + { + initLayerInPacket(setTotalLenAsDataLen); + } -IPv4Layer::IPv4Layer(const IPv4Address& srcIP, const IPv4Address& dstIP) -{ - initLayer(); - iphdr* ipHdr = getIPv4Header(); - ipHdr->ipSrc = srcIP.toInt(); - ipHdr->ipDst = dstIP.toInt(); -} + IPv4Layer::IPv4Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + initLayerInPacket(true); + } -IPv4Layer::IPv4Layer(const IPv4Layer& other) : Layer(other) -{ - copyLayerData(other); -} + IPv4Layer::IPv4Layer(const IPv4Address& srcIP, const IPv4Address& dstIP) + { + initLayer(); + iphdr* ipHdr = getIPv4Header(); + ipHdr->ipSrc = srcIP.toInt(); + ipHdr->ipDst = dstIP.toInt(); + } -IPv4Layer& IPv4Layer::operator=(const IPv4Layer& other) -{ - Layer::operator=(other); + IPv4Layer::IPv4Layer(const IPv4Layer& other) : Layer(other) + { + copyLayerData(other); + } - copyLayerData(other); + IPv4Layer& IPv4Layer::operator=(const IPv4Layer& other) + { + Layer::operator=(other); - return *this; -} + copyLayerData(other); -void IPv4Layer::parseNextLayer() -{ - size_t hdrLen = getHeaderLen(); - if (m_DataLen <= hdrLen || hdrLen == 0) - return; + return *this; + } - iphdr* ipHdr = getIPv4Header(); + void IPv4Layer::parseNextLayer() + { + size_t hdrLen = getHeaderLen(); + if (m_DataLen <= hdrLen || hdrLen == 0) + return; - ProtocolType greVer = UnknownProtocol; - ProtocolType igmpVer = UnknownProtocol; - bool igmpQuery = false; + iphdr* ipHdr = getIPv4Header(); - uint8_t ipVersion = 0; + ProtocolType greVer = UnknownProtocol; + ProtocolType igmpVer = UnknownProtocol; + bool igmpQuery = false; - uint8_t* payload = m_Data + hdrLen; - size_t payloadLen = m_DataLen - hdrLen; + uint8_t ipVersion = 0; - // If it's a fragment don't parse upper layers, unless if it's the first fragment - // TODO: assuming first fragment contains at least L4 header, what if it's not true? - if (isFragment()) - { - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - return; - } + uint8_t* payload = m_Data + hdrLen; + size_t payloadLen = m_DataLen - hdrLen; - switch (ipHdr->protocol) - { - case PACKETPP_IPPROTO_UDP: - if (payloadLen >= sizeof(udphdr)) - m_NextLayer = new UdpLayer(payload, payloadLen, this, m_Packet); - break; - case PACKETPP_IPPROTO_TCP: - m_NextLayer = TcpLayer::isDataValid(payload, payloadLen) - ? static_cast(new TcpLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_ICMP: - m_NextLayer = IcmpLayer::isDataValid(payload, payloadLen) - ? static_cast(new IcmpLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_IPIP: - ipVersion = *payload >> 4; - if (ipVersion == 4 && IPv4Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new IPv4Layer(payload, payloadLen, this, m_Packet); - else if (ipVersion == 6 && IPv6Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new IPv6Layer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; - case PACKETPP_IPPROTO_GRE: - greVer = GreLayer::getGREVersion(payload, payloadLen); - if (greVer == GREv0 && GREv0Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new GREv0Layer(payload, payloadLen, this, m_Packet); - else if (greVer == GREv1 && GREv1Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new GREv1Layer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; - case PACKETPP_IPPROTO_IGMP: - igmpVer = IgmpLayer::getIGMPVerFromData( - payload, std::min(payloadLen, be16toh(getIPv4Header()->totalLength) - hdrLen), igmpQuery); - if (igmpVer == IGMPv1) - m_NextLayer = new IgmpV1Layer(payload, payloadLen, this, m_Packet); - else if (igmpVer == IGMPv2) - m_NextLayer = new IgmpV2Layer(payload, payloadLen, this, m_Packet); - else if (igmpVer == IGMPv3) + // If it's a fragment don't parse upper layers, unless if it's the first fragment + // TODO: assuming first fragment contains at least L4 header, what if it's not true? + if (isFragment()) { - if (igmpQuery) - m_NextLayer = new IgmpV3QueryLayer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new IgmpV3ReportLayer(payload, payloadLen, this, m_Packet); - } - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; - case PACKETPP_IPPROTO_AH: - m_NextLayer = AuthenticationHeaderLayer::isDataValid(payload, payloadLen) - ? static_cast(new AuthenticationHeaderLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_ESP: - m_NextLayer = ESPLayer::isDataValid(payload, payloadLen) - ? static_cast(new ESPLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_VRRP: - { - auto vrrpVer = VrrpLayer::getVersionFromData(payload, payloadLen); - if (vrrpVer == VRRPv2) - m_NextLayer = new VrrpV2Layer(payload, payloadLen, this, m_Packet); - else if (vrrpVer == VRRPv3) - m_NextLayer = new VrrpV3Layer(payload, payloadLen, this, m_Packet, IPAddress::IPv4AddressType); - else m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; - } - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - } -} - -void IPv4Layer::computeCalculateFields() -{ - iphdr* ipHdr = getIPv4Header(); - ipHdr->ipVersion = (4 & 0x0f); - ipHdr->totalLength = htobe16(m_DataLen); - ipHdr->headerChecksum = 0; + return; + } - if (m_NextLayer != nullptr) - { - switch (m_NextLayer->getProtocol()) + switch (ipHdr->protocol) { - case TCP: - ipHdr->protocol = PACKETPP_IPPROTO_TCP; + case PACKETPP_IPPROTO_UDP: + if (payloadLen >= sizeof(udphdr)) + m_NextLayer = new UdpLayer(payload, payloadLen, this, m_Packet); + break; + case PACKETPP_IPPROTO_TCP: + m_NextLayer = TcpLayer::isDataValid(payload, payloadLen) + ? static_cast(new TcpLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case UDP: - ipHdr->protocol = PACKETPP_IPPROTO_UDP; + case PACKETPP_IPPROTO_ICMP: + m_NextLayer = IcmpLayer::isDataValid(payload, payloadLen) + ? static_cast(new IcmpLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case ICMP: - ipHdr->protocol = PACKETPP_IPPROTO_ICMP; + case PACKETPP_IPPROTO_IPIP: + ipVersion = *payload >> 4; + if (ipVersion == 4 && IPv4Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new IPv4Layer(payload, payloadLen, this, m_Packet); + else if (ipVersion == 6 && IPv6Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new IPv6Layer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; - case GREv0: - case GREv1: - ipHdr->protocol = PACKETPP_IPPROTO_GRE; + case PACKETPP_IPPROTO_GRE: + greVer = GreLayer::getGREVersion(payload, payloadLen); + if (greVer == GREv0 && GREv0Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new GREv0Layer(payload, payloadLen, this, m_Packet); + else if (greVer == GREv1 && GREv1Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new GREv1Layer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; - case IGMPv1: - case IGMPv2: - case IGMPv3: - ipHdr->protocol = PACKETPP_IPPROTO_IGMP; + case PACKETPP_IPPROTO_IGMP: + igmpVer = IgmpLayer::getIGMPVerFromData( + payload, std::min(payloadLen, be16toh(getIPv4Header()->totalLength) - hdrLen), igmpQuery); + if (igmpVer == IGMPv1) + m_NextLayer = new IgmpV1Layer(payload, payloadLen, this, m_Packet); + else if (igmpVer == IGMPv2) + m_NextLayer = new IgmpV2Layer(payload, payloadLen, this, m_Packet); + else if (igmpVer == IGMPv3) + { + if (igmpQuery) + m_NextLayer = new IgmpV3QueryLayer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new IgmpV3ReportLayer(payload, payloadLen, this, m_Packet); + } + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; - case VRRPv2: - case VRRPv3: - ipHdr->protocol = PACKETPP_IPPROTO_VRRP; + case PACKETPP_IPPROTO_AH: + m_NextLayer = AuthenticationHeaderLayer::isDataValid(payload, payloadLen) + ? static_cast(new AuthenticationHeaderLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - default: + case PACKETPP_IPPROTO_ESP: + m_NextLayer = ESPLayer::isDataValid(payload, payloadLen) + ? static_cast(new ESPLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PACKETPP_IPPROTO_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PACKETPP_IPPROTO_VRRP: + { + auto vrrpVer = VrrpLayer::getVersionFromData(payload, payloadLen); + if (vrrpVer == VRRPv2) + m_NextLayer = new VrrpV2Layer(payload, payloadLen, this, m_Packet); + else if (vrrpVer == VRRPv3) + m_NextLayer = new VrrpV3Layer(payload, payloadLen, this, m_Packet, IPAddress::IPv4AddressType); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; } + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } } - ScalarBuffer scalar = { (uint16_t*)ipHdr, (size_t)(ipHdr->internetHeaderLength*4) } ; - ipHdr->headerChecksum = htobe16(computeChecksum(&scalar, 1)); -} - -bool IPv4Layer::isFragment() const -{ - return ((getFragmentFlags() & PCPP_IP_MORE_FRAGMENTS) != 0 || getFragmentOffset() != 0); -} - -bool IPv4Layer::isFirstFragment() const -{ - return isFragment() && (getFragmentOffset() == 0); -} + void IPv4Layer::computeCalculateFields() + { + iphdr* ipHdr = getIPv4Header(); + ipHdr->ipVersion = (4 & 0x0f); + ipHdr->totalLength = htobe16(m_DataLen); + ipHdr->headerChecksum = 0; -bool IPv4Layer::isLastFragment() const -{ - return isFragment() && ((getFragmentFlags() & PCPP_IP_MORE_FRAGMENTS) == 0); -} + if (m_NextLayer != nullptr) + { + switch (m_NextLayer->getProtocol()) + { + case TCP: + ipHdr->protocol = PACKETPP_IPPROTO_TCP; + break; + case UDP: + ipHdr->protocol = PACKETPP_IPPROTO_UDP; + break; + case ICMP: + ipHdr->protocol = PACKETPP_IPPROTO_ICMP; + break; + case GREv0: + case GREv1: + ipHdr->protocol = PACKETPP_IPPROTO_GRE; + break; + case IGMPv1: + case IGMPv2: + case IGMPv3: + ipHdr->protocol = PACKETPP_IPPROTO_IGMP; + break; + case VRRPv2: + case VRRPv3: + ipHdr->protocol = PACKETPP_IPPROTO_VRRP; + break; + default: + break; + } + } -uint8_t IPv4Layer::getFragmentFlags() const -{ - return getIPv4Header()->fragmentOffset & 0xE0; -} + ScalarBuffer scalar = { (uint16_t*)ipHdr, (size_t)(ipHdr->internetHeaderLength * 4) }; + ipHdr->headerChecksum = htobe16(computeChecksum(&scalar, 1)); + } -uint16_t IPv4Layer::getFragmentOffset() const -{ - return be16toh(getIPv4Header()->fragmentOffset & (uint16_t)0xFF1F) * 8; -} + bool IPv4Layer::isFragment() const + { + return ((getFragmentFlags() & PCPP_IP_MORE_FRAGMENTS) != 0 || getFragmentOffset() != 0); + } -std::string IPv4Layer::toString() const -{ - std::string fragment = ""; - if (isFragment()) + bool IPv4Layer::isFirstFragment() const { - if (isFirstFragment()) - fragment = "First fragment"; - else if (isLastFragment()) - fragment = "Last fragment"; - else - fragment = "Fragment"; + return isFragment() && (getFragmentOffset() == 0); + } - std::stringstream sstm; - sstm << fragment << " [offset= " << getFragmentOffset() << "], "; - fragment = sstm.str(); + bool IPv4Layer::isLastFragment() const + { + return isFragment() && ((getFragmentFlags() & PCPP_IP_MORE_FRAGMENTS) == 0); } - return "IPv4 Layer, " + fragment + "Src: " + getSrcIPv4Address().toString() + ", Dst: " + getDstIPv4Address().toString(); -} + uint8_t IPv4Layer::getFragmentFlags() const + { + return getIPv4Header()->fragmentOffset & 0xE0; + } -IPv4Option IPv4Layer::getOption(IPv4OptionTypes option) const -{ - return m_OptionReader.getTLVRecord((uint8_t)option, getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); -} + uint16_t IPv4Layer::getFragmentOffset() const + { + return be16toh(getIPv4Header()->fragmentOffset & (uint16_t)0xFF1F) * 8; + } -IPv4Option IPv4Layer::getFirstOption() const -{ - return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); -} + std::string IPv4Layer::toString() const + { + std::string fragment = ""; + if (isFragment()) + { + if (isFirstFragment()) + fragment = "First fragment"; + else if (isLastFragment()) + fragment = "Last fragment"; + else + fragment = "Fragment"; -IPv4Option IPv4Layer::getNextOption(IPv4Option& option) const -{ - return m_OptionReader.getNextTLVRecord(option, getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); -} + std::stringstream sstm; + sstm << fragment << " [offset= " << getFragmentOffset() << "], "; + fragment = sstm.str(); + } -size_t IPv4Layer::getOptionCount() const -{ - return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); -} + return "IPv4 Layer, " + fragment + "Src: " + getSrcIPv4Address().toString() + + ", Dst: " + getDstIPv4Address().toString(); + } -void IPv4Layer::adjustOptionsTrailer(size_t totalOptSize) -{ - size_t ipHdrSize = sizeof(iphdr); + IPv4Option IPv4Layer::getOption(IPv4OptionTypes option) const + { + return m_OptionReader.getTLVRecord((uint8_t)option, getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); + } - int newNumberOfTrailingBytes = 0; - while ((totalOptSize + newNumberOfTrailingBytes) % 4 != 0) - newNumberOfTrailingBytes++; + IPv4Option IPv4Layer::getFirstOption() const + { + return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); + } - if (newNumberOfTrailingBytes < m_NumOfTrailingBytes) - shortenLayer(ipHdrSize+totalOptSize, m_NumOfTrailingBytes - newNumberOfTrailingBytes); - else if (newNumberOfTrailingBytes > m_NumOfTrailingBytes) - extendLayer(ipHdrSize+totalOptSize, newNumberOfTrailingBytes - m_NumOfTrailingBytes); + IPv4Option IPv4Layer::getNextOption(IPv4Option& option) const + { + return m_OptionReader.getNextTLVRecord(option, getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); + } - m_NumOfTrailingBytes = newNumberOfTrailingBytes; + size_t IPv4Layer::getOptionCount() const + { + return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(iphdr)); + } - for (int i = 0; i < m_NumOfTrailingBytes; i++) - m_Data[ipHdrSize + totalOptSize + i] = IPV4OPT_DUMMY; + void IPv4Layer::adjustOptionsTrailer(size_t totalOptSize) + { + size_t ipHdrSize = sizeof(iphdr); - m_TempHeaderExtension = 0; - getIPv4Header()->internetHeaderLength = ((ipHdrSize + totalOptSize + m_NumOfTrailingBytes)/4 & 0x0f); -} + int newNumberOfTrailingBytes = 0; + while ((totalOptSize + newNumberOfTrailingBytes) % 4 != 0) + newNumberOfTrailingBytes++; -IPv4Option IPv4Layer::addOptionAt(const IPv4OptionBuilder& optionBuilder, int offset) -{ - IPv4Option newOption = optionBuilder.build(); - if (newOption.isNull()) - return newOption; + if (newNumberOfTrailingBytes < m_NumOfTrailingBytes) + shortenLayer(ipHdrSize + totalOptSize, m_NumOfTrailingBytes - newNumberOfTrailingBytes); + else if (newNumberOfTrailingBytes > m_NumOfTrailingBytes) + extendLayer(ipHdrSize + totalOptSize, newNumberOfTrailingBytes - m_NumOfTrailingBytes); - size_t sizeToExtend = newOption.getTotalSize(); + m_NumOfTrailingBytes = newNumberOfTrailingBytes; - size_t totalOptSize = getHeaderLen() - sizeof(iphdr) - m_NumOfTrailingBytes + sizeToExtend; + for (int i = 0; i < m_NumOfTrailingBytes; i++) + m_Data[ipHdrSize + totalOptSize + i] = IPV4OPT_DUMMY; - if (totalOptSize > IPV4_MAX_OPT_SIZE) - { - PCPP_LOG_ERROR("Cannot add option - adding this option will exceed IPv4 total option size which is " << IPV4_MAX_OPT_SIZE); - newOption.purgeRecordData(); - return IPv4Option(nullptr); + m_TempHeaderExtension = 0; + getIPv4Header()->internetHeaderLength = ((ipHdrSize + totalOptSize + m_NumOfTrailingBytes) / 4 & 0x0f); } - if (!extendLayer(offset, sizeToExtend)) + IPv4Option IPv4Layer::addOptionAt(const IPv4OptionBuilder& optionBuilder, int offset) { - PCPP_LOG_ERROR("Could not extend IPv4Layer in [" << sizeToExtend << "] bytes"); - newOption.purgeRecordData(); - return IPv4Option(nullptr); - } + IPv4Option newOption = optionBuilder.build(); + if (newOption.isNull()) + return newOption; - memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); + size_t sizeToExtend = newOption.getTotalSize(); - newOption.purgeRecordData(); + size_t totalOptSize = getHeaderLen() - sizeof(iphdr) - m_NumOfTrailingBytes + sizeToExtend; - // setting this m_TempHeaderExtension because adjustOptionsTrailer() may extend or shorten the layer and the extend or shorten methods need to know the accurate - // current size of the header. m_TempHeaderExtension will be added to the length extracted from getIPv4Header()->internetHeaderLength as the temp new size - m_TempHeaderExtension = sizeToExtend; - adjustOptionsTrailer(totalOptSize); - // the adjustOptionsTrailer() adds or removed the trailing bytes and sets getIPv4Header()->internetHeaderLength to the correct size, so the m_TempHeaderExtension - // isn't needed anymore - m_TempHeaderExtension = 0; + if (totalOptSize > IPV4_MAX_OPT_SIZE) + { + PCPP_LOG_ERROR("Cannot add option - adding this option will exceed IPv4 total option size which is " + << IPV4_MAX_OPT_SIZE); + newOption.purgeRecordData(); + return IPv4Option(nullptr); + } - m_OptionReader.changeTLVRecordCount(1); + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend IPv4Layer in [" << sizeToExtend << "] bytes"); + newOption.purgeRecordData(); + return IPv4Option(nullptr); + } - uint8_t* newOptPtr = m_Data + offset; + memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); - return IPv4Option(newOptPtr); -} + newOption.purgeRecordData(); -IPv4Option IPv4Layer::addOption(const IPv4OptionBuilder& optionBuilder) -{ - return addOptionAt(optionBuilder, getHeaderLen() - m_NumOfTrailingBytes); -} + // setting this m_TempHeaderExtension because adjustOptionsTrailer() may extend or shorten the layer and the + // extend or shorten methods need to know the accurate current size of the header. m_TempHeaderExtension will be + // added to the length extracted from getIPv4Header()->internetHeaderLength as the temp new size + m_TempHeaderExtension = sizeToExtend; + adjustOptionsTrailer(totalOptSize); + // the adjustOptionsTrailer() adds or removed the trailing bytes and sets getIPv4Header()->internetHeaderLength + // to the correct size, so the m_TempHeaderExtension isn't needed anymore + m_TempHeaderExtension = 0; -IPv4Option IPv4Layer::addOptionAfter(const IPv4OptionBuilder& optionBuilder, IPv4OptionTypes prevOptionType) -{ - int offset = 0; + m_OptionReader.changeTLVRecordCount(1); - IPv4Option prevOpt = getOption(prevOptionType); + uint8_t* newOptPtr = m_Data + offset; - if (prevOpt.isNull()) - { - offset = sizeof(iphdr); + return IPv4Option(newOptPtr); } - else + + IPv4Option IPv4Layer::addOption(const IPv4OptionBuilder& optionBuilder) { - offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + return addOptionAt(optionBuilder, getHeaderLen() - m_NumOfTrailingBytes); } - return addOptionAt(optionBuilder, offset); -} - -bool IPv4Layer::removeOption(IPv4OptionTypes option) -{ - IPv4Option opt = getOption(option); - if (opt.isNull()) + IPv4Option IPv4Layer::addOptionAfter(const IPv4OptionBuilder& optionBuilder, IPv4OptionTypes prevOptionType) { - return false; + int offset = 0; + + IPv4Option prevOpt = getOption(prevOptionType); + + if (prevOpt.isNull()) + { + offset = sizeof(iphdr); + } + else + { + offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + } + + return addOptionAt(optionBuilder, offset); } - // calculate total option size - IPv4Option curOpt = getFirstOption(); - size_t totalOptSize = 0; - while (!curOpt.isNull()) + bool IPv4Layer::removeOption(IPv4OptionTypes option) { - totalOptSize += curOpt.getTotalSize(); - curOpt = getNextOption(curOpt); - } - totalOptSize -= opt.getTotalSize(); + IPv4Option opt = getOption(option); + if (opt.isNull()) + { + return false; + } + // calculate total option size + IPv4Option curOpt = getFirstOption(); + size_t totalOptSize = 0; + while (!curOpt.isNull()) + { + totalOptSize += curOpt.getTotalSize(); + curOpt = getNextOption(curOpt); + } + totalOptSize -= opt.getTotalSize(); - int offset = opt.getRecordBasePtr() - m_Data; + int offset = opt.getRecordBasePtr() - m_Data; - size_t sizeToShorten = opt.getTotalSize(); - if (!shortenLayer(offset, sizeToShorten)) - { - PCPP_LOG_ERROR("Failed to remove IPv4 option: cannot shorten layer"); - return false; - } + size_t sizeToShorten = opt.getTotalSize(); + if (!shortenLayer(offset, sizeToShorten)) + { + PCPP_LOG_ERROR("Failed to remove IPv4 option: cannot shorten layer"); + return false; + } - // setting this m_TempHeaderExtension because adjustOptionsTrailer() may extend or shorten the layer and the extend or shorten methods need to know the accurate - // current size of the header. m_TempHeaderExtension will be added to the length extracted from getIPv4Header()->internetHeaderLength as the temp new size - m_TempHeaderExtension = 0 - sizeToShorten; - adjustOptionsTrailer(totalOptSize); - // the adjustOptionsTrailer() adds or removed the trailing bytes and sets getIPv4Header()->internetHeaderLength to the correct size, so the m_TempHeaderExtension - // isn't needed anymore - m_TempHeaderExtension = 0; + // setting this m_TempHeaderExtension because adjustOptionsTrailer() may extend or shorten the layer and the + // extend or shorten methods need to know the accurate current size of the header. m_TempHeaderExtension will be + // added to the length extracted from getIPv4Header()->internetHeaderLength as the temp new size + m_TempHeaderExtension = 0 - sizeToShorten; + adjustOptionsTrailer(totalOptSize); + // the adjustOptionsTrailer() adds or removed the trailing bytes and sets getIPv4Header()->internetHeaderLength + // to the correct size, so the m_TempHeaderExtension isn't needed anymore + m_TempHeaderExtension = 0; - m_OptionReader.changeTLVRecordCount(-1); + m_OptionReader.changeTLVRecordCount(-1); - return true; -} + return true; + } -bool IPv4Layer::removeAllOptions() -{ - int offset = sizeof(iphdr); + bool IPv4Layer::removeAllOptions() + { + int offset = sizeof(iphdr); - if (!shortenLayer(offset, getHeaderLen() - offset)) - return false; + if (!shortenLayer(offset, getHeaderLen() - offset)) + return false; - getIPv4Header()->internetHeaderLength = (5 & 0xf); - m_NumOfTrailingBytes = 0; - m_OptionReader.changeTLVRecordCount(0 - getOptionCount()); - return true; -} + getIPv4Header()->internetHeaderLength = (5 & 0xf); + m_NumOfTrailingBytes = 0; + m_OptionReader.changeTLVRecordCount(0 - getOptionCount()); + return true; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/IPv6Extensions.cpp b/Packet++/src/IPv6Extensions.cpp index 21274f854c..3a1bc08bb9 100644 --- a/Packet++/src/IPv6Extensions.cpp +++ b/Packet++/src/IPv6Extensions.cpp @@ -14,270 +14,277 @@ namespace pcpp { -// ============= -// IPv6Extension -// ============= + // ============= + // IPv6Extension + // ============= -IPv6Extension& IPv6Extension::operator=(const IPv6Extension& other) -{ - // notice this is not necessarily safe - it assumes the current extension has enough memory allocated to consume - // the other extension. That's why the assignment operator isn't public (it's currently used only inside IPv6Layer) - memcpy(getDataPtr(), other.getDataPtr(), other.getExtensionLen()); - m_NextHeader = nullptr; - m_ExtType = other.m_ExtType; - - return *this; -} - -uint8_t* IPv6Extension::getDataPtr() const -{ - if (m_DataContainer != nullptr) - return m_DataContainer->getDataPtr(m_Offset); - - return m_ShadowData; -} - -void IPv6Extension::initShadowPtr(size_t size) -{ - m_ShadowData = new uint8_t[size]; -} - -IPv6Extension::~IPv6Extension() -{ - if (m_ShadowData != nullptr) - delete [] m_ShadowData; -} - -// ======================= -// IPv6FragmentationHeader -// ======================= - -IPv6FragmentationHeader::IPv6FragmentationHeader(uint32_t fragId, uint16_t fragOffset, bool lastFragment) -{ - initShadowPtr(sizeof(ipv6_frag_header)); - m_ExtType = IPv6Fragmentation; - memset(getDataPtr(), 0, sizeof(ipv6_frag_header)); - - ipv6_frag_header* fragHdr = getFragHeader(); - fragHdr->nextHeader = 0; - fragHdr->headerLen = 0; - fragHdr->id = htobe32(fragId); + IPv6Extension& IPv6Extension::operator=(const IPv6Extension& other) + { + // notice this is not necessarily safe - it assumes the current extension has enough memory allocated to consume + // the other extension. That's why the assignment operator isn't public (it's currently used only inside + // IPv6Layer) + memcpy(getDataPtr(), other.getDataPtr(), other.getExtensionLen()); + m_NextHeader = nullptr; + m_ExtType = other.m_ExtType; + + return *this; + } - fragOffset /= 8; - fragOffset = htobe16(fragOffset << 3) & (uint16_t)0xf8ff; - if (!lastFragment) - fragOffset = fragOffset | 0x0100; + uint8_t* IPv6Extension::getDataPtr() const + { + if (m_DataContainer != nullptr) + return m_DataContainer->getDataPtr(m_Offset); - fragHdr->fragOffsetAndFlags = fragOffset; -} + return m_ShadowData; + } -bool IPv6FragmentationHeader::isFirstFragment() const -{ - return (getFragmentOffset() == 0); -} + void IPv6Extension::initShadowPtr(size_t size) + { + m_ShadowData = new uint8_t[size]; + } -bool IPv6FragmentationHeader::isLastFragment() const -{ - return (!isMoreFragments()); -} + IPv6Extension::~IPv6Extension() + { + if (m_ShadowData != nullptr) + delete[] m_ShadowData; + } -bool IPv6FragmentationHeader::isMoreFragments() const -{ - uint8_t isMoreFragsBit = (getFragHeader()->fragOffsetAndFlags & (uint16_t)0x0100) >> 8; - return (isMoreFragsBit == 1); -} + // ======================= + // IPv6FragmentationHeader + // ======================= -uint16_t IPv6FragmentationHeader::getFragmentOffset() const -{ - uint16_t fragOffset = (be16toh(getFragHeader()->fragOffsetAndFlags & (uint16_t)0xf8ff) >> 3) * 8; - return fragOffset; -} + IPv6FragmentationHeader::IPv6FragmentationHeader(uint32_t fragId, uint16_t fragOffset, bool lastFragment) + { + initShadowPtr(sizeof(ipv6_frag_header)); + m_ExtType = IPv6Fragmentation; + memset(getDataPtr(), 0, sizeof(ipv6_frag_header)); -// ==================== -// IPv6TLVOptionBuilder -// ==================== + ipv6_frag_header* fragHdr = getFragHeader(); + fragHdr->nextHeader = 0; + fragHdr->headerLen = 0; + fragHdr->id = htobe32(fragId); -IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::IPv6TLVOptionBuilder::build() const -{ - size_t optionTotalSize = sizeof(uint8_t); - uint8_t recType = static_cast(m_RecType); - if (recType != IPv6TLVOptionHeader::IPv6Option::Pad0OptionType) - optionTotalSize += sizeof(uint8_t) + m_RecValueLen; + fragOffset /= 8; + fragOffset = htobe16(fragOffset << 3) & (uint16_t)0xf8ff; + if (!lastFragment) + fragOffset = fragOffset | 0x0100; - uint8_t* recordBuffer = new uint8_t[optionTotalSize]; - memset(recordBuffer, 0, optionTotalSize); + fragHdr->fragOffsetAndFlags = fragOffset; + } - if (m_RecType != IPv6TLVOptionHeader::IPv6Option::Pad0OptionType) + bool IPv6FragmentationHeader::isFirstFragment() const { - recordBuffer[0] = recType; - recordBuffer[1] = static_cast(m_RecValueLen); - if (m_RecValueLen > 0) - memcpy(recordBuffer+2, m_RecValue, m_RecValueLen); + return (getFragmentOffset() == 0); } - return IPv6Option(recordBuffer); -} - -// =================== -// IPv6TLVOptionHeader -// =================== - -IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::getOption(uint8_t optionType) const -{ - return m_OptionReader.getTLVRecord(optionType, getDataPtr() + sizeof(ipv6_ext_base_header), getExtensionLen() - sizeof(ipv6_ext_base_header)); -} - -IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::getFirstOption() const -{ - return m_OptionReader.getFirstTLVRecord(getDataPtr() + sizeof(ipv6_ext_base_header), getExtensionLen() - sizeof(ipv6_ext_base_header)); -} - -IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::getNextOption(IPv6TLVOptionHeader::IPv6Option& option) const -{ - return m_OptionReader.getNextTLVRecord(option, getDataPtr() + sizeof(ipv6_ext_base_header), getExtensionLen() - sizeof(ipv6_ext_base_header)); -} + bool IPv6FragmentationHeader::isLastFragment() const + { + return (!isMoreFragments()); + } -size_t IPv6TLVOptionHeader::getOptionCount() const -{ - return m_OptionReader.getTLVRecordCount(getDataPtr() + sizeof(ipv6_ext_base_header), getExtensionLen() - sizeof(ipv6_ext_base_header)); -} + bool IPv6FragmentationHeader::isMoreFragments() const + { + uint8_t isMoreFragsBit = (getFragHeader()->fragOffsetAndFlags & (uint16_t)0x0100) >> 8; + return (isMoreFragsBit == 1); + } -IPv6TLVOptionHeader::IPv6TLVOptionHeader(const std::vector& options) -{ - m_ExtType = IPv6ExtensionUnknown; - m_OptionReader.changeTLVRecordCount(options.size()); + uint16_t IPv6FragmentationHeader::getFragmentOffset() const + { + uint16_t fragOffset = (be16toh(getFragHeader()->fragOffsetAndFlags & (uint16_t)0xf8ff) >> 3) * 8; + return fragOffset; + } - size_t totalSize = sizeof(uint16_t); // nextHeader + headerLen + // ==================== + // IPv6TLVOptionBuilder + // ==================== - for (const auto &iter : options) + IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::IPv6TLVOptionBuilder::build() const { - IPv6Option option = iter.build(); - totalSize += option.getTotalSize(); - option.purgeRecordData(); + size_t optionTotalSize = sizeof(uint8_t); + uint8_t recType = static_cast(m_RecType); + if (recType != IPv6TLVOptionHeader::IPv6Option::Pad0OptionType) + optionTotalSize += sizeof(uint8_t) + m_RecValueLen; + + uint8_t* recordBuffer = new uint8_t[optionTotalSize]; + memset(recordBuffer, 0, optionTotalSize); + + if (m_RecType != IPv6TLVOptionHeader::IPv6Option::Pad0OptionType) + { + recordBuffer[0] = recType; + recordBuffer[1] = static_cast(m_RecValueLen); + if (m_RecValueLen > 0) + memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); + } + + return IPv6Option(recordBuffer); } - while (totalSize % 8 != 0) - totalSize++; - - initShadowPtr(totalSize); - memset(getDataPtr(), 0, totalSize); + // =================== + // IPv6TLVOptionHeader + // =================== - getBaseHeader()->headerLen = ((totalSize / 8) - 1); + IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::getOption(uint8_t optionType) const + { + return m_OptionReader.getTLVRecord(optionType, getDataPtr() + sizeof(ipv6_ext_base_header), + getExtensionLen() - sizeof(ipv6_ext_base_header)); + } - size_t offset = sizeof(uint16_t); + IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::getFirstOption() const + { + return m_OptionReader.getFirstTLVRecord(getDataPtr() + sizeof(ipv6_ext_base_header), + getExtensionLen() - sizeof(ipv6_ext_base_header)); + } - for (const auto &iter : options) + IPv6TLVOptionHeader::IPv6Option IPv6TLVOptionHeader::getNextOption(IPv6TLVOptionHeader::IPv6Option& option) const { - IPv6Option option = iter.build(); - memcpy(getDataPtr() + offset, option.getRecordBasePtr(), option.getTotalSize()); - offset += option.getTotalSize(); - option.purgeRecordData(); + return m_OptionReader.getNextTLVRecord(option, getDataPtr() + sizeof(ipv6_ext_base_header), + getExtensionLen() - sizeof(ipv6_ext_base_header)); } -} -IPv6TLVOptionHeader::IPv6TLVOptionHeader(IDataContainer* dataContainer, size_t offset) : IPv6Extension(dataContainer, offset) -{ -} + size_t IPv6TLVOptionHeader::getOptionCount() const + { + return m_OptionReader.getTLVRecordCount(getDataPtr() + sizeof(ipv6_ext_base_header), + getExtensionLen() - sizeof(ipv6_ext_base_header)); + } -// ================= -// IPv6RoutingHeader -// ================= + IPv6TLVOptionHeader::IPv6TLVOptionHeader(const std::vector& options) + { + m_ExtType = IPv6ExtensionUnknown; + m_OptionReader.changeTLVRecordCount(options.size()); -IPv6RoutingHeader::IPv6RoutingHeader(uint8_t routingType, uint8_t segmentsLeft, const uint8_t* additionalRoutingData, size_t additionalRoutingDataLen) -{ - size_t totalSize = sizeof(ipv6_routing_header) + additionalRoutingDataLen; - while (totalSize % 8 != 0) - totalSize++; + size_t totalSize = sizeof(uint16_t); // nextHeader + headerLen - initShadowPtr(totalSize); - memset(getDataPtr(), 0, totalSize); + for (const auto& iter : options) + { + IPv6Option option = iter.build(); + totalSize += option.getTotalSize(); + option.purgeRecordData(); + } - m_ExtType = IPv6Routing; + while (totalSize % 8 != 0) + totalSize++; - ipv6_routing_header* routingHeader = getRoutingHeader(); - routingHeader->nextHeader = 0; - routingHeader->headerLen = ((totalSize / 8) - 1); - routingHeader->routingType = routingType; - routingHeader->segmentsLeft = segmentsLeft; + initShadowPtr(totalSize); + memset(getDataPtr(), 0, totalSize); - if (additionalRoutingDataLen > 0 && additionalRoutingData != nullptr) - { - uint8_t* additionalDataPtr = getDataPtr() + sizeof(ipv6_routing_header); - memcpy(additionalDataPtr, additionalRoutingData, additionalRoutingDataLen); - } -} + getBaseHeader()->headerLen = ((totalSize / 8) - 1); -uint8_t* IPv6RoutingHeader::getRoutingAdditionalData() const -{ - if (getExtensionLen() > sizeof(ipv6_routing_header)) - return getDataPtr() + sizeof(ipv6_routing_header); + size_t offset = sizeof(uint16_t); - return nullptr; -} + for (const auto& iter : options) + { + IPv6Option option = iter.build(); + memcpy(getDataPtr() + offset, option.getRecordBasePtr(), option.getTotalSize()); + offset += option.getTotalSize(); + option.purgeRecordData(); + } + } -size_t IPv6RoutingHeader::getRoutingAdditionalDataLength() const -{ - int result = getExtensionLen() - sizeof(ipv6_routing_header); - if (result < 0) - return (size_t)0; + IPv6TLVOptionHeader::IPv6TLVOptionHeader(IDataContainer* dataContainer, size_t offset) + : IPv6Extension(dataContainer, offset) + {} - return (size_t)result; -} + // ================= + // IPv6RoutingHeader + // ================= -IPv6Address IPv6RoutingHeader::getRoutingAdditionalDataAsIPv6Address(size_t offset) const -{ + IPv6RoutingHeader::IPv6RoutingHeader(uint8_t routingType, uint8_t segmentsLeft, + const uint8_t* additionalRoutingData, size_t additionalRoutingDataLen) + { + size_t totalSize = sizeof(ipv6_routing_header) + additionalRoutingDataLen; + while (totalSize % 8 != 0) + totalSize++; + + initShadowPtr(totalSize); + memset(getDataPtr(), 0, totalSize); + + m_ExtType = IPv6Routing; + + ipv6_routing_header* routingHeader = getRoutingHeader(); + routingHeader->nextHeader = 0; + routingHeader->headerLen = ((totalSize / 8) - 1); + routingHeader->routingType = routingType; + routingHeader->segmentsLeft = segmentsLeft; + + if (additionalRoutingDataLen > 0 && additionalRoutingData != nullptr) + { + uint8_t* additionalDataPtr = getDataPtr() + sizeof(ipv6_routing_header); + memcpy(additionalDataPtr, additionalRoutingData, additionalRoutingDataLen); + } + } - size_t routingAddDataLen = getRoutingAdditionalDataLength(); - if (routingAddDataLen - offset >= 16) - return IPv6Address(getRoutingAdditionalData() + offset); + uint8_t* IPv6RoutingHeader::getRoutingAdditionalData() const + { + if (getExtensionLen() > sizeof(ipv6_routing_header)) + return getDataPtr() + sizeof(ipv6_routing_header); - return IPv6Address(); -} + return nullptr; + } + size_t IPv6RoutingHeader::getRoutingAdditionalDataLength() const + { + int result = getExtensionLen() - sizeof(ipv6_routing_header); + if (result < 0) + return (size_t)0; -// ======================== -// IPv6AuthenticationHeader -// ======================== + return (size_t)result; + } -IPv6AuthenticationHeader::IPv6AuthenticationHeader(uint32_t securityParametersIndex, uint32_t sequenceNumber, const uint8_t* integrityCheckValue, size_t integrityCheckValueLen) -{ - size_t totalSize = sizeof(ipv6_authentication_header) + integrityCheckValueLen; - while (totalSize % 8 != 0) - totalSize++; + IPv6Address IPv6RoutingHeader::getRoutingAdditionalDataAsIPv6Address(size_t offset) const + { - initShadowPtr(totalSize); - memset(getDataPtr(), 0, totalSize); + size_t routingAddDataLen = getRoutingAdditionalDataLength(); + if (routingAddDataLen - offset >= 16) + return IPv6Address(getRoutingAdditionalData() + offset); - m_ExtType = IPv6AuthenticationHdr; + return IPv6Address(); + } - ipv6_authentication_header* authHeader = getAuthHeader(); - authHeader->nextHeader = 0; - authHeader->headerLen = ((totalSize / 4) - 2); - authHeader->securityParametersIndex = htobe32(securityParametersIndex); - authHeader->sequenceNumber = htobe32(sequenceNumber); + // ======================== + // IPv6AuthenticationHeader + // ======================== - if (integrityCheckValueLen > 0 && integrityCheckValue != nullptr) + IPv6AuthenticationHeader::IPv6AuthenticationHeader(uint32_t securityParametersIndex, uint32_t sequenceNumber, + const uint8_t* integrityCheckValue, + size_t integrityCheckValueLen) { - uint8_t* icvPtr = getDataPtr() + sizeof(ipv6_authentication_header); - memcpy(icvPtr, integrityCheckValue, integrityCheckValueLen); + size_t totalSize = sizeof(ipv6_authentication_header) + integrityCheckValueLen; + while (totalSize % 8 != 0) + totalSize++; + + initShadowPtr(totalSize); + memset(getDataPtr(), 0, totalSize); + + m_ExtType = IPv6AuthenticationHdr; + + ipv6_authentication_header* authHeader = getAuthHeader(); + authHeader->nextHeader = 0; + authHeader->headerLen = ((totalSize / 4) - 2); + authHeader->securityParametersIndex = htobe32(securityParametersIndex); + authHeader->sequenceNumber = htobe32(sequenceNumber); + + if (integrityCheckValueLen > 0 && integrityCheckValue != nullptr) + { + uint8_t* icvPtr = getDataPtr() + sizeof(ipv6_authentication_header); + memcpy(icvPtr, integrityCheckValue, integrityCheckValueLen); + } } -} -uint8_t* IPv6AuthenticationHeader::getIntegrityCheckValue() const -{ - if (getExtensionLen() > sizeof(ipv6_authentication_header)) - return getDataPtr() + sizeof(ipv6_authentication_header); + uint8_t* IPv6AuthenticationHeader::getIntegrityCheckValue() const + { + if (getExtensionLen() > sizeof(ipv6_authentication_header)) + return getDataPtr() + sizeof(ipv6_authentication_header); - return nullptr; -} + return nullptr; + } -size_t IPv6AuthenticationHeader::getIntegrityCheckValueLength() const -{ - int result = getExtensionLen() - sizeof(ipv6_authentication_header); - if (result < 0) - return (size_t)0; + size_t IPv6AuthenticationHeader::getIntegrityCheckValueLength() const + { + int result = getExtensionLen() - sizeof(ipv6_authentication_header); + if (result < 0) + return (size_t)0; - return (size_t)result; -} + return (size_t)result; + } -} +} // namespace pcpp diff --git a/Packet++/src/IPv6Layer.cpp b/Packet++/src/IPv6Layer.cpp index f6b5d78546..95e56879e3 100644 --- a/Packet++/src/IPv6Layer.cpp +++ b/Packet++/src/IPv6Layer.cpp @@ -16,351 +16,352 @@ namespace pcpp { -void IPv6Layer::initLayer() -{ - m_DataLen = sizeof(ip6_hdr); - m_Data = new uint8_t[m_DataLen]; - m_Protocol = IPv6; - m_FirstExtension = nullptr; - m_LastExtension = nullptr; - m_ExtensionsLen = 0; - memset(m_Data, 0, sizeof(ip6_hdr)); -} - -IPv6Layer::IPv6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) -{ - m_Protocol = IPv6; - m_FirstExtension = nullptr; - m_LastExtension = nullptr; - m_ExtensionsLen = 0; - - parseExtensions(); - - size_t totalLen = be16toh(getIPv6Header()->payloadLength) + getHeaderLen(); - if (totalLen < m_DataLen) - m_DataLen = totalLen; -} - -IPv6Layer::IPv6Layer() -{ - initLayer(); -} - -IPv6Layer::IPv6Layer(const IPv6Address& srcIP, const IPv6Address& dstIP) -{ - initLayer(); - ip6_hdr* ipHdr = getIPv6Header(); - srcIP.copyTo(ipHdr->ipSrc); - dstIP.copyTo(ipHdr->ipDst); -} - -IPv6Layer::IPv6Layer(const IPv6Layer& other) : Layer(other) -{ - m_FirstExtension = nullptr; - m_LastExtension = nullptr; - m_ExtensionsLen = 0; - parseExtensions(); -} - -IPv6Layer::~IPv6Layer() -{ - deleteExtensions(); -} - -IPv6Layer& IPv6Layer::operator=(const IPv6Layer& other) -{ - Layer::operator=(other); - - deleteExtensions(); - - parseExtensions(); - - return *this; -} - -void IPv6Layer::parseExtensions() -{ - uint8_t nextHdr = getIPv6Header()->nextHeader; - IPv6Extension* curExt = nullptr; - - size_t offset = sizeof(ip6_hdr); - - while (offset <= m_DataLen - 2*sizeof(uint8_t)) // 2*sizeof(uint8_t) is the min len for IPv6 extensions + void IPv6Layer::initLayer() { - IPv6Extension* newExt = nullptr; + m_DataLen = sizeof(ip6_hdr); + m_Data = new uint8_t[m_DataLen]; + m_Protocol = IPv6; + m_FirstExtension = nullptr; + m_LastExtension = nullptr; + m_ExtensionsLen = 0; + memset(m_Data, 0, sizeof(ip6_hdr)); + } - switch (nextHdr) - { - case PACKETPP_IPPROTO_FRAGMENT: - { - newExt = new IPv6FragmentationHeader(this, offset); - break; - } - case PACKETPP_IPPROTO_HOPOPTS: - { - newExt = new IPv6HopByHopHeader(this, offset); - break; - } - case PACKETPP_IPPROTO_DSTOPTS: - { - newExt = new IPv6DestinationHeader(this, offset); - break; - } - case PACKETPP_IPPROTO_ROUTING: - { - newExt = new IPv6RoutingHeader(this, offset); - break; - } - case PACKETPP_IPPROTO_AH: - { - newExt = new IPv6AuthenticationHeader(this, offset); - break; - } - default: - { - break; - } - } + IPv6Layer::IPv6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = IPv6; + m_FirstExtension = nullptr; + m_LastExtension = nullptr; + m_ExtensionsLen = 0; - if (newExt == nullptr) - break; + parseExtensions(); - if (m_FirstExtension == nullptr) - { - m_FirstExtension = newExt; - curExt = m_FirstExtension; - } - else - { - curExt->setNextHeader(newExt); - curExt = curExt->getNextHeader(); - } + size_t totalLen = be16toh(getIPv6Header()->payloadLength) + getHeaderLen(); + if (totalLen < m_DataLen) + m_DataLen = totalLen; + } - offset += newExt->getExtensionLen(); - nextHdr = newExt->getBaseHeader()->nextHeader; - m_ExtensionsLen += newExt->getExtensionLen(); + IPv6Layer::IPv6Layer() + { + initLayer(); } - m_LastExtension = curExt; -} + IPv6Layer::IPv6Layer(const IPv6Address& srcIP, const IPv6Address& dstIP) + { + initLayer(); + ip6_hdr* ipHdr = getIPv6Header(); + srcIP.copyTo(ipHdr->ipSrc); + dstIP.copyTo(ipHdr->ipDst); + } -void IPv6Layer::deleteExtensions() -{ - IPv6Extension* curExt = m_FirstExtension; - while (curExt != nullptr) + IPv6Layer::IPv6Layer(const IPv6Layer& other) : Layer(other) { - IPv6Extension* tmpExt = curExt->getNextHeader(); - delete curExt; - curExt = tmpExt; + m_FirstExtension = nullptr; + m_LastExtension = nullptr; + m_ExtensionsLen = 0; + parseExtensions(); } - m_FirstExtension = nullptr; - m_LastExtension = nullptr; - m_ExtensionsLen = 0; + IPv6Layer::~IPv6Layer() + { + deleteExtensions(); + } -} + IPv6Layer& IPv6Layer::operator=(const IPv6Layer& other) + { + Layer::operator=(other); -size_t IPv6Layer::getExtensionCount() const -{ - size_t extensionCount = 0; + deleteExtensions(); - IPv6Extension* curExt = m_FirstExtension; + parseExtensions(); - while (curExt != nullptr) - { - extensionCount++; - curExt = curExt->getNextHeader(); + return *this; } - return extensionCount; -} + void IPv6Layer::parseExtensions() + { + uint8_t nextHdr = getIPv6Header()->nextHeader; + IPv6Extension* curExt = nullptr; -void IPv6Layer::removeAllExtensions() -{ - if (m_LastExtension != nullptr) - getIPv6Header()->nextHeader = m_LastExtension->getBaseHeader()->nextHeader; + size_t offset = sizeof(ip6_hdr); - shortenLayer((int)sizeof(ip6_hdr), m_ExtensionsLen); + while (offset <= m_DataLen - 2 * sizeof(uint8_t)) // 2*sizeof(uint8_t) is the min len for IPv6 extensions + { + IPv6Extension* newExt = nullptr; - deleteExtensions(); -} + switch (nextHdr) + { + case PACKETPP_IPPROTO_FRAGMENT: + { + newExt = new IPv6FragmentationHeader(this, offset); + break; + } + case PACKETPP_IPPROTO_HOPOPTS: + { + newExt = new IPv6HopByHopHeader(this, offset); + break; + } + case PACKETPP_IPPROTO_DSTOPTS: + { + newExt = new IPv6DestinationHeader(this, offset); + break; + } + case PACKETPP_IPPROTO_ROUTING: + { + newExt = new IPv6RoutingHeader(this, offset); + break; + } + case PACKETPP_IPPROTO_AH: + { + newExt = new IPv6AuthenticationHeader(this, offset); + break; + } + default: + { + break; + } + } -bool IPv6Layer::isFragment() const -{ - return getExtensionOfType() != nullptr; -} + if (newExt == nullptr) + break; -void IPv6Layer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); + if (m_FirstExtension == nullptr) + { + m_FirstExtension = newExt; + curExt = m_FirstExtension; + } + else + { + curExt->setNextHeader(newExt); + curExt = curExt->getNextHeader(); + } - if (m_DataLen <= headerLen) - return; + offset += newExt->getExtensionLen(); + nextHdr = newExt->getBaseHeader()->nextHeader; + m_ExtensionsLen += newExt->getExtensionLen(); + } - uint8_t* payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; + m_LastExtension = curExt; + } - uint8_t nextHdr; - if (m_LastExtension != nullptr) + void IPv6Layer::deleteExtensions() { - if (m_LastExtension->getExtensionType() == IPv6Extension::IPv6Fragmentation) + IPv6Extension* curExt = m_FirstExtension; + while (curExt != nullptr) { - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - return; + IPv6Extension* tmpExt = curExt->getNextHeader(); + delete curExt; + curExt = tmpExt; } - nextHdr = m_LastExtension->getBaseHeader()->nextHeader; - } - else - { - nextHdr = getIPv6Header()->nextHeader; + m_FirstExtension = nullptr; + m_LastExtension = nullptr; + m_ExtensionsLen = 0; } - switch (nextHdr) + size_t IPv6Layer::getExtensionCount() const { - case PACKETPP_IPPROTO_UDP: - m_NextLayer = new UdpLayer(payload, payloadLen, this, m_Packet); - break; - case PACKETPP_IPPROTO_TCP: - m_NextLayer = TcpLayer::isDataValid(payload, payloadLen) - ? static_cast(new TcpLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_IPIP: - { - uint8_t ipVersion = *payload >> 4; - if (ipVersion == 4 && IPv4Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new IPv4Layer(payload, payloadLen, this, m_Packet); - else if (ipVersion == 6 && IPv6Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new IPv6Layer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; + size_t extensionCount = 0; + + IPv6Extension* curExt = m_FirstExtension; + + while (curExt != nullptr) + { + extensionCount++; + curExt = curExt->getNextHeader(); + } + + return extensionCount; } - case PACKETPP_IPPROTO_GRE: + + void IPv6Layer::removeAllExtensions() { - ProtocolType greVer = GreLayer::getGREVersion(payload, payloadLen); - if (greVer == GREv0 && GREv0Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new GREv0Layer(payload, payloadLen, this, m_Packet); - else if (greVer == GREv1 && GREv1Layer::isDataValid(payload, payloadLen)) - m_NextLayer = new GREv1Layer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; + if (m_LastExtension != nullptr) + getIPv6Header()->nextHeader = m_LastExtension->getBaseHeader()->nextHeader; + + shortenLayer((int)sizeof(ip6_hdr), m_ExtensionsLen); + + deleteExtensions(); } - case PACKETPP_IPPROTO_AH: - m_NextLayer = AuthenticationHeaderLayer::isDataValid(payload, payloadLen) - ? static_cast(new AuthenticationHeaderLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_ESP: - m_NextLayer = ESPLayer::isDataValid(payload, payloadLen) - ? static_cast(new ESPLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PACKETPP_IPPROTO_ICMPV6: + + bool IPv6Layer::isFragment() const { - m_NextLayer = IcmpV6Layer::parseIcmpV6Layer(payload, payloadLen, this, m_Packet); - break; + return getExtensionOfType() != nullptr; } - case PACKETPP_IPPROTO_VRRP: + + void IPv6Layer::parseNextLayer() { - auto vrrpVer = VrrpLayer::getVersionFromData(payload, payloadLen); - if (vrrpVer == VRRPv3) - m_NextLayer = new VrrpV3Layer(payload, payloadLen, this, m_Packet, IPAddress::IPv6AddressType); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; - } - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - return; - } -} + size_t headerLen = getHeaderLen(); -void IPv6Layer::computeCalculateFields() -{ - ip6_hdr* ipHdr = getIPv6Header(); - ipHdr->payloadLength = htobe16(m_DataLen - sizeof(ip6_hdr)); - ipHdr->ipVersion = (6 & 0x0f); + if (m_DataLen <= headerLen) + return; - if (m_NextLayer != nullptr) - { - uint8_t nextHeader = 0; - switch (m_NextLayer->getProtocol()) + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; + + uint8_t nextHdr; + if (m_LastExtension != nullptr) { - case TCP: - nextHeader = PACKETPP_IPPROTO_TCP; + if (m_LastExtension->getExtensionType() == IPv6Extension::IPv6Fragmentation) + { + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + return; + } + + nextHdr = m_LastExtension->getBaseHeader()->nextHeader; + } + else + { + nextHdr = getIPv6Header()->nextHeader; + } + + switch (nextHdr) + { + case PACKETPP_IPPROTO_UDP: + m_NextLayer = new UdpLayer(payload, payloadLen, this, m_Packet); break; - case UDP: - nextHeader = PACKETPP_IPPROTO_UDP; + case PACKETPP_IPPROTO_TCP: + m_NextLayer = TcpLayer::isDataValid(payload, payloadLen) + ? static_cast(new TcpLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case ICMP: - nextHeader = PACKETPP_IPPROTO_ICMP; + case PACKETPP_IPPROTO_IPIP: + { + uint8_t ipVersion = *payload >> 4; + if (ipVersion == 4 && IPv4Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new IPv4Layer(payload, payloadLen, this, m_Packet); + else if (ipVersion == 6 && IPv6Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new IPv6Layer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; - case ICMPv6: - nextHeader = PACKETPP_IPPROTO_ICMPV6; + } + case PACKETPP_IPPROTO_GRE: + { + ProtocolType greVer = GreLayer::getGREVersion(payload, payloadLen); + if (greVer == GREv0 && GREv0Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new GREv0Layer(payload, payloadLen, this, m_Packet); + else if (greVer == GREv1 && GREv1Layer::isDataValid(payload, payloadLen)) + m_NextLayer = new GREv1Layer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); break; - case GREv0: - case GREv1: - nextHeader = PACKETPP_IPPROTO_GRE; + } + case PACKETPP_IPPROTO_AH: + m_NextLayer = AuthenticationHeaderLayer::isDataValid(payload, payloadLen) + ? static_cast(new AuthenticationHeaderLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - case VRRPv3: - nextHeader = PACKETPP_IPPROTO_VRRP; + case PACKETPP_IPPROTO_ESP: + m_NextLayer = ESPLayer::isDataValid(payload, payloadLen) + ? static_cast(new ESPLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; - default: + case PACKETPP_IPPROTO_ICMPV6: + { + m_NextLayer = IcmpV6Layer::parseIcmpV6Layer(payload, payloadLen, this, m_Packet); break; } - - if (nextHeader != 0) + case PACKETPP_IPPROTO_VRRP: { - if (m_LastExtension != nullptr) - m_LastExtension->getBaseHeader()->nextHeader = nextHeader; + auto vrrpVer = VrrpLayer::getVersionFromData(payload, payloadLen); + if (vrrpVer == VRRPv3) + m_NextLayer = new VrrpV3Layer(payload, payloadLen, this, m_Packet, IPAddress::IPv6AddressType); else - ipHdr->nextHeader = nextHeader; + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + break; + } + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + return; } } -} -std::string IPv6Layer::toString() const -{ - std::string result = "IPv6 Layer, Src: " + getSrcIPv6Address().toString() + ", Dst: " + getDstIPv6Address().toString(); - if (m_ExtensionsLen > 0) + void IPv6Layer::computeCalculateFields() { - result += ", Options=["; - IPv6Extension* curExt = m_FirstExtension; - while (curExt != nullptr) + ip6_hdr* ipHdr = getIPv6Header(); + ipHdr->payloadLength = htobe16(m_DataLen - sizeof(ip6_hdr)); + ipHdr->ipVersion = (6 & 0x0f); + + if (m_NextLayer != nullptr) { - switch (curExt->getExtensionType()) + uint8_t nextHeader = 0; + switch (m_NextLayer->getProtocol()) { - case IPv6Extension::IPv6Fragmentation: - result += "Fragment,"; + case TCP: + nextHeader = PACKETPP_IPPROTO_TCP; + break; + case UDP: + nextHeader = PACKETPP_IPPROTO_UDP; break; - case IPv6Extension::IPv6HopByHop: - result += "Hop-By-Hop,"; + case ICMP: + nextHeader = PACKETPP_IPPROTO_ICMP; break; - case IPv6Extension::IPv6Destination: - result += "Destination,"; + case ICMPv6: + nextHeader = PACKETPP_IPPROTO_ICMPV6; break; - case IPv6Extension::IPv6Routing: - result += "Routing,"; + case GREv0: + case GREv1: + nextHeader = PACKETPP_IPPROTO_GRE; break; - case IPv6Extension::IPv6AuthenticationHdr: - result += "Authentication,"; + case VRRPv3: + nextHeader = PACKETPP_IPPROTO_VRRP; break; default: - result += "Unknown,"; break; } - curExt = curExt->getNextHeader(); + if (nextHeader != 0) + { + if (m_LastExtension != nullptr) + m_LastExtension->getBaseHeader()->nextHeader = nextHeader; + else + ipHdr->nextHeader = nextHeader; + } } - - // replace the last ',' - result[result.size() - 1] = ']'; } - return result; -} + std::string IPv6Layer::toString() const + { + std::string result = + "IPv6 Layer, Src: " + getSrcIPv6Address().toString() + ", Dst: " + getDstIPv6Address().toString(); + if (m_ExtensionsLen > 0) + { + result += ", Options=["; + IPv6Extension* curExt = m_FirstExtension; + while (curExt != nullptr) + { + switch (curExt->getExtensionType()) + { + case IPv6Extension::IPv6Fragmentation: + result += "Fragment,"; + break; + case IPv6Extension::IPv6HopByHop: + result += "Hop-By-Hop,"; + break; + case IPv6Extension::IPv6Destination: + result += "Destination,"; + break; + case IPv6Extension::IPv6Routing: + result += "Routing,"; + break; + case IPv6Extension::IPv6AuthenticationHdr: + result += "Authentication,"; + break; + default: + result += "Unknown,"; + break; + } + + curExt = curExt->getNextHeader(); + } + + // replace the last ',' + result[result.size() - 1] = ']'; + } + + return result; + } -}// namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/IcmpLayer.cpp b/Packet++/src/IcmpLayer.cpp index 564ad4bfd3..77370d112a 100644 --- a/Packet++/src/IcmpLayer.cpp +++ b/Packet++/src/IcmpLayer.cpp @@ -12,688 +12,702 @@ namespace pcpp { -icmp_router_address_structure* icmp_router_advertisement::getRouterAddress(int index) const -{ - if (index < 0 || index >= header->advertisementCount) - return nullptr; - - uint8_t* headerAsByteArr = (uint8_t*)header; - return (icmp_router_address_structure*)(headerAsByteArr + sizeof(icmp_router_advertisement_hdr) + index * sizeof(icmp_router_address_structure)); -} - -void icmp_router_address_structure::setRouterAddress(IPv4Address addr, uint32_t preference) -{ - routerAddress = addr.toInt(); - preferenceLevel = htobe32(preference); -} - -IcmpLayer::IcmpLayer() : Layer() -{ - m_DataLen = sizeof(icmphdr); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = ICMP; -} - -IcmpMessageType IcmpLayer::getMessageType() const -{ - uint8_t type = getIcmpHeader()->type; - if (type > 18) - return ICMP_UNSUPPORTED; - - return (IcmpMessageType)type; -} - -bool IcmpLayer::cleanIcmpLayer() -{ - // remove all layers after - - if (m_Packet != nullptr) + icmp_router_address_structure* icmp_router_advertisement::getRouterAddress(int index) const { - bool res = m_Packet->removeAllLayersAfter(this); - if (!res) - return false; - } + if (index < 0 || index >= header->advertisementCount) + return nullptr; - // shorten layer to size of icmphdr + uint8_t* headerAsByteArr = (uint8_t*)header; + return (icmp_router_address_structure*)(headerAsByteArr + sizeof(icmp_router_advertisement_hdr) + + index * sizeof(icmp_router_address_structure)); + } - size_t headerLen = this->getHeaderLen(); - if (headerLen > sizeof(icmphdr)) + void icmp_router_address_structure::setRouterAddress(IPv4Address addr, uint32_t preference) { - if (!this->shortenLayer(sizeof(icmphdr), headerLen - sizeof(icmphdr))) - return false; + routerAddress = addr.toInt(); + preferenceLevel = htobe32(preference); } - return true; -} - -bool IcmpLayer::setEchoData(IcmpMessageType echoType, uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen) -{ - if (!cleanIcmpLayer()) - return false; - - if (!this->extendLayer(m_DataLen, sizeof(icmp_echo_hdr) - sizeof(icmphdr) + dataLen)) - return false; - - getIcmpHeader()->type = (uint8_t)echoType; - - icmp_echo_request* header = nullptr; - if (echoType == ICMP_ECHO_REQUEST) - header = getEchoRequestData(); - else if (echoType == ICMP_ECHO_REPLY) - header = (icmp_echo_request*)getEchoReplyData(); - else - return false; - - header->header->code = 0; - header->header->checksum = 0; - header->header->id = htobe16(id); - header->header->sequence = htobe16(sequence); - header->header->timestamp = timestamp; - if (data != nullptr && dataLen > 0) - memcpy(header->data, data, dataLen); - - return true; -} - -bool IcmpLayer::setIpAndL4Layers(IPv4Layer* ipLayer, Layer* l4Layer) -{ - if (m_Packet == nullptr) + IcmpLayer::IcmpLayer() : Layer() { - PCPP_LOG_ERROR("Cannot set ICMP data that involves IP and L4 layers on a layer not attached to a packet. " - "Please add the ICMP layer to a packet and try again"); - return false; + m_DataLen = sizeof(icmphdr); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = ICMP; } - if (ipLayer != nullptr && !m_Packet->addLayer(ipLayer)) + IcmpMessageType IcmpLayer::getMessageType() const { - PCPP_LOG_ERROR("Couldn't add IP layer to ICMP packet"); - return false; + uint8_t type = getIcmpHeader()->type; + if (type > 18) + return ICMP_UNSUPPORTED; + + return (IcmpMessageType)type; } - if (l4Layer != nullptr && !m_Packet->addLayer(l4Layer)) + bool IcmpLayer::cleanIcmpLayer() { - PCPP_LOG_ERROR("Couldn't add L4 layer to ICMP packet"); - return false; - } + // remove all layers after - return true; -} + if (m_Packet != nullptr) + { + bool res = m_Packet->removeAllLayersAfter(this); + if (!res) + return false; + } -icmp_echo_request* IcmpLayer::getEchoRequestData() -{ - if (!isMessageOfType(ICMP_ECHO_REQUEST)) - return nullptr; + // shorten layer to size of icmphdr - m_EchoData.header = (icmp_echo_hdr*)m_Data; - m_EchoData.data = (uint8_t*)(m_Data + sizeof(icmp_echo_hdr)); - m_EchoData.dataLength = m_DataLen - sizeof(icmp_echo_hdr); + size_t headerLen = this->getHeaderLen(); + if (headerLen > sizeof(icmphdr)) + { + if (!this->shortenLayer(sizeof(icmphdr), headerLen - sizeof(icmphdr))) + return false; + } - return &m_EchoData; -} + return true; + } -icmp_echo_request* IcmpLayer::setEchoRequestData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen) -{ - if (setEchoData(ICMP_ECHO_REQUEST, id, sequence, timestamp, data, dataLen)) - return getEchoRequestData(); - else - return nullptr; -} + bool IcmpLayer::setEchoData(IcmpMessageType echoType, uint16_t id, uint16_t sequence, uint64_t timestamp, + const uint8_t* data, size_t dataLen) + { + if (!cleanIcmpLayer()) + return false; -icmp_echo_reply* IcmpLayer::getEchoReplyData() -{ - if (!isMessageOfType(ICMP_ECHO_REPLY)) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_echo_hdr) - sizeof(icmphdr) + dataLen)) + return false; - m_EchoData.header = (icmp_echo_hdr*)m_Data; - m_EchoData.data = (uint8_t*)(m_Data + sizeof(icmp_echo_hdr)); - m_EchoData.dataLength = m_DataLen - sizeof(icmp_echo_hdr); + getIcmpHeader()->type = (uint8_t)echoType; - return &m_EchoData; -} + icmp_echo_request* header = nullptr; + if (echoType == ICMP_ECHO_REQUEST) + header = getEchoRequestData(); + else if (echoType == ICMP_ECHO_REPLY) + header = (icmp_echo_request*)getEchoReplyData(); + else + return false; -icmp_echo_reply* IcmpLayer::setEchoReplyData(uint16_t id, uint16_t sequence, uint64_t timestamp, const uint8_t* data, size_t dataLen) -{ - if (setEchoData(ICMP_ECHO_REPLY, id, sequence, timestamp, data, dataLen)) - return getEchoReplyData(); - else - return nullptr; -} + header->header->code = 0; + header->header->checksum = 0; + header->header->id = htobe16(id); + header->header->sequence = htobe16(sequence); + header->header->timestamp = timestamp; + if (data != nullptr && dataLen > 0) + memcpy(header->data, data, dataLen); + return true; + } -icmp_timestamp_request* IcmpLayer::getTimestampRequestData() -{ - if (!isMessageOfType(ICMP_TIMESTAMP_REQUEST)) - return nullptr; + bool IcmpLayer::setIpAndL4Layers(IPv4Layer* ipLayer, Layer* l4Layer) + { + if (m_Packet == nullptr) + { + PCPP_LOG_ERROR("Cannot set ICMP data that involves IP and L4 layers on a layer not attached to a packet. " + "Please add the ICMP layer to a packet and try again"); + return false; + } - return (icmp_timestamp_request*)m_Data; -} + if (ipLayer != nullptr && !m_Packet->addLayer(ipLayer)) + { + PCPP_LOG_ERROR("Couldn't add IP layer to ICMP packet"); + return false; + } -icmp_timestamp_request* IcmpLayer::setTimestampRequestData(uint16_t id, uint16_t sequence, timeval originateTimestamp) -{ - if (!cleanIcmpLayer()) - return nullptr; + if (l4Layer != nullptr && !m_Packet->addLayer(l4Layer)) + { + PCPP_LOG_ERROR("Couldn't add L4 layer to ICMP packet"); + return false; + } - if (!this->extendLayer(m_DataLen, sizeof(icmp_timestamp_request) - sizeof(icmphdr))) - return nullptr; + return true; + } - getIcmpHeader()->type = (uint8_t)ICMP_TIMESTAMP_REQUEST; + icmp_echo_request* IcmpLayer::getEchoRequestData() + { + if (!isMessageOfType(ICMP_ECHO_REQUEST)) + return nullptr; - icmp_timestamp_request* header = getTimestampRequestData(); - header->code = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); - header->originateTimestamp = htobe32(originateTimestamp.tv_sec*1000 + originateTimestamp.tv_usec/1000); - header->receiveTimestamp = 0; - header->transmitTimestamp = 0; + m_EchoData.header = (icmp_echo_hdr*)m_Data; + m_EchoData.data = (uint8_t*)(m_Data + sizeof(icmp_echo_hdr)); + m_EchoData.dataLength = m_DataLen - sizeof(icmp_echo_hdr); - return header; -} + return &m_EchoData; + } -icmp_timestamp_reply* IcmpLayer::getTimestampReplyData() -{ - if (!isMessageOfType(ICMP_TIMESTAMP_REPLY)) - return nullptr; + icmp_echo_request* IcmpLayer::setEchoRequestData(uint16_t id, uint16_t sequence, uint64_t timestamp, + const uint8_t* data, size_t dataLen) + { + if (setEchoData(ICMP_ECHO_REQUEST, id, sequence, timestamp, data, dataLen)) + return getEchoRequestData(); + else + return nullptr; + } - return (icmp_timestamp_reply*)m_Data; -} + icmp_echo_reply* IcmpLayer::getEchoReplyData() + { + if (!isMessageOfType(ICMP_ECHO_REPLY)) + return nullptr; -icmp_timestamp_reply* IcmpLayer::setTimestampReplyData(uint16_t id, uint16_t sequence, - timeval originateTimestamp, timeval receiveTimestamp, timeval transmitTimestamp) -{ - if (!cleanIcmpLayer()) - return nullptr; + m_EchoData.header = (icmp_echo_hdr*)m_Data; + m_EchoData.data = (uint8_t*)(m_Data + sizeof(icmp_echo_hdr)); + m_EchoData.dataLength = m_DataLen - sizeof(icmp_echo_hdr); - if (!this->extendLayer(m_DataLen, sizeof(icmp_timestamp_reply) - sizeof(icmphdr))) - return nullptr; + return &m_EchoData; + } - getIcmpHeader()->type = (uint8_t)ICMP_TIMESTAMP_REPLY; + icmp_echo_reply* IcmpLayer::setEchoReplyData(uint16_t id, uint16_t sequence, uint64_t timestamp, + const uint8_t* data, size_t dataLen) + { + if (setEchoData(ICMP_ECHO_REPLY, id, sequence, timestamp, data, dataLen)) + return getEchoReplyData(); + else + return nullptr; + } - icmp_timestamp_reply* header = getTimestampReplyData(); - header->code = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); - header->originateTimestamp = htobe32(originateTimestamp.tv_sec*1000 + originateTimestamp.tv_usec/1000); - header->receiveTimestamp = htobe32(receiveTimestamp.tv_sec*1000 + receiveTimestamp.tv_usec/1000); - header->transmitTimestamp = htobe32(transmitTimestamp.tv_sec*1000 + transmitTimestamp.tv_usec/1000); + icmp_timestamp_request* IcmpLayer::getTimestampRequestData() + { + if (!isMessageOfType(ICMP_TIMESTAMP_REQUEST)) + return nullptr; - return header; -} + return (icmp_timestamp_request*)m_Data; + } -icmp_destination_unreachable* IcmpLayer::getDestUnreachableData() -{ - if (!isMessageOfType(ICMP_DEST_UNREACHABLE)) - return nullptr; + icmp_timestamp_request* IcmpLayer::setTimestampRequestData(uint16_t id, uint16_t sequence, + timeval originateTimestamp) + { + if (!cleanIcmpLayer()) + return nullptr; - return (icmp_destination_unreachable*)m_Data; -} + if (!this->extendLayer(m_DataLen, sizeof(icmp_timestamp_request) - sizeof(icmphdr))) + return nullptr; -icmp_destination_unreachable* IcmpLayer::setDestUnreachableData(IcmpDestUnreachableCodes code, uint16_t nextHopMTU, IPv4Layer* ipHeader, Layer* l4Header) -{ - if (!cleanIcmpLayer()) - return nullptr; + getIcmpHeader()->type = (uint8_t)ICMP_TIMESTAMP_REQUEST; - if (!this->extendLayer(m_DataLen, sizeof(icmp_destination_unreachable) - sizeof(icmphdr))) - return nullptr; + icmp_timestamp_request* header = getTimestampRequestData(); + header->code = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); + header->originateTimestamp = htobe32(originateTimestamp.tv_sec * 1000 + originateTimestamp.tv_usec / 1000); + header->receiveTimestamp = 0; + header->transmitTimestamp = 0; - getIcmpHeader()->type = (uint8_t)ICMP_DEST_UNREACHABLE; + return header; + } - icmp_destination_unreachable* header = getDestUnreachableData(); - header->code = code; - header->nextHopMTU = htobe16(nextHopMTU); - header->unused = 0; + icmp_timestamp_reply* IcmpLayer::getTimestampReplyData() + { + if (!isMessageOfType(ICMP_TIMESTAMP_REPLY)) + return nullptr; - if (!setIpAndL4Layers(ipHeader, l4Header)) - return nullptr; + return (icmp_timestamp_reply*)m_Data; + } - return header; -} + icmp_timestamp_reply* IcmpLayer::setTimestampReplyData(uint16_t id, uint16_t sequence, timeval originateTimestamp, + timeval receiveTimestamp, timeval transmitTimestamp) + { + if (!cleanIcmpLayer()) + return nullptr; -icmp_source_quench* IcmpLayer::getSourceQuenchdata() -{ - if (!isMessageOfType(ICMP_SOURCE_QUENCH)) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_timestamp_reply) - sizeof(icmphdr))) + return nullptr; - return (icmp_source_quench*)m_Data; + getIcmpHeader()->type = (uint8_t)ICMP_TIMESTAMP_REPLY; -} + icmp_timestamp_reply* header = getTimestampReplyData(); + header->code = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); + header->originateTimestamp = htobe32(originateTimestamp.tv_sec * 1000 + originateTimestamp.tv_usec / 1000); + header->receiveTimestamp = htobe32(receiveTimestamp.tv_sec * 1000 + receiveTimestamp.tv_usec / 1000); + header->transmitTimestamp = htobe32(transmitTimestamp.tv_sec * 1000 + transmitTimestamp.tv_usec / 1000); -icmp_source_quench* IcmpLayer::setSourceQuenchdata(IPv4Layer* ipHeader, Layer* l4Header) -{ - if (!cleanIcmpLayer()) - return nullptr; + return header; + } - if (!this->extendLayer(m_DataLen, sizeof(icmp_source_quench) - sizeof(icmphdr))) - return nullptr; + icmp_destination_unreachable* IcmpLayer::getDestUnreachableData() + { + if (!isMessageOfType(ICMP_DEST_UNREACHABLE)) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_SOURCE_QUENCH; + return (icmp_destination_unreachable*)m_Data; + } - icmp_source_quench* header = getSourceQuenchdata(); - header->unused = 0; + icmp_destination_unreachable* IcmpLayer::setDestUnreachableData(IcmpDestUnreachableCodes code, uint16_t nextHopMTU, + IPv4Layer* ipHeader, Layer* l4Header) + { + if (!cleanIcmpLayer()) + return nullptr; - if (!setIpAndL4Layers(ipHeader, l4Header)) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_destination_unreachable) - sizeof(icmphdr))) + return nullptr; - return header; -} + getIcmpHeader()->type = (uint8_t)ICMP_DEST_UNREACHABLE; -icmp_redirect* IcmpLayer::getRedirectData() -{ - if (!isMessageOfType(ICMP_REDIRECT)) - return nullptr; + icmp_destination_unreachable* header = getDestUnreachableData(); + header->code = code; + header->nextHopMTU = htobe16(nextHopMTU); + header->unused = 0; - return (icmp_redirect*)m_Data; -} + if (!setIpAndL4Layers(ipHeader, l4Header)) + return nullptr; -icmp_redirect* IcmpLayer::setRedirectData(uint8_t code, IPv4Address gatewayAddress, IPv4Layer* ipHeader, Layer* l4Header) -{ - if (code > 3) - { - PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP redirect data"); - return nullptr; + return header; } - if (!cleanIcmpLayer()) - return nullptr; - - if (!this->extendLayer(m_DataLen, sizeof(icmp_redirect) - sizeof(icmphdr))) - return nullptr; + icmp_source_quench* IcmpLayer::getSourceQuenchdata() + { + if (!isMessageOfType(ICMP_SOURCE_QUENCH)) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_REDIRECT; + return (icmp_source_quench*)m_Data; + } - icmp_redirect* header = getRedirectData(); - header->code = code; - header->gatewayAddress = gatewayAddress.toInt(); + icmp_source_quench* IcmpLayer::setSourceQuenchdata(IPv4Layer* ipHeader, Layer* l4Header) + { + if (!cleanIcmpLayer()) + return nullptr; - if (!setIpAndL4Layers(ipHeader, l4Header)) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_source_quench) - sizeof(icmphdr))) + return nullptr; - return header; -} + getIcmpHeader()->type = (uint8_t)ICMP_SOURCE_QUENCH; -icmp_router_advertisement* IcmpLayer::getRouterAdvertisementData() const -{ - if (!isMessageOfType(ICMP_ROUTER_ADV)) - return nullptr; + icmp_source_quench* header = getSourceQuenchdata(); + header->unused = 0; - m_RouterAdvData.header = (icmp_router_advertisement_hdr*)m_Data; + if (!setIpAndL4Layers(ipHeader, l4Header)) + return nullptr; - return &m_RouterAdvData; -} + return header; + } -icmp_router_advertisement* IcmpLayer::setRouterAdvertisementData(uint8_t code, uint16_t lifetimeInSeconds, const std::vector& routerAddresses) -{ - if (code != 0 && code != 16) + icmp_redirect* IcmpLayer::getRedirectData() { - PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP router advertisement data (only codes 0 and 16 are legal)"); - return nullptr; + if (!isMessageOfType(ICMP_REDIRECT)) + return nullptr; + + return (icmp_redirect*)m_Data; } - if (!cleanIcmpLayer()) - return nullptr; + icmp_redirect* IcmpLayer::setRedirectData(uint8_t code, IPv4Address gatewayAddress, IPv4Layer* ipHeader, + Layer* l4Header) + { + if (code > 3) + { + PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP redirect data"); + return nullptr; + } + + if (!cleanIcmpLayer()) + return nullptr; - if (!this->extendLayer(m_DataLen, sizeof(icmp_router_advertisement_hdr) + (routerAddresses.size()*sizeof(icmp_router_address_structure)) - sizeof(icmphdr))) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_redirect) - sizeof(icmphdr))) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_ROUTER_ADV; + getIcmpHeader()->type = (uint8_t)ICMP_REDIRECT; - icmp_router_advertisement* header = getRouterAdvertisementData(); - header->header->code = code; - header->header->lifetime = htobe16(lifetimeInSeconds); - header->header->advertisementCount = (uint8_t)routerAddresses.size(); - header->header->addressEntrySize = 2; + icmp_redirect* header = getRedirectData(); + header->code = code; + header->gatewayAddress = gatewayAddress.toInt(); - icmp_router_address_structure* curPos = (icmp_router_address_structure*)((uint8_t*)header->header + sizeof(icmp_router_advertisement_hdr)); - for (const auto &iter : routerAddresses) - { - curPos->routerAddress = iter.routerAddress; - curPos->preferenceLevel = iter.preferenceLevel; - curPos += 1; + if (!setIpAndL4Layers(ipHeader, l4Header)) + return nullptr; + + return header; } - return header; -} + icmp_router_advertisement* IcmpLayer::getRouterAdvertisementData() const + { + if (!isMessageOfType(ICMP_ROUTER_ADV)) + return nullptr; -icmp_router_solicitation* IcmpLayer::getRouterSolicitationData() -{ - if (!isMessageOfType(ICMP_ROUTER_SOL)) - return nullptr; + m_RouterAdvData.header = (icmp_router_advertisement_hdr*)m_Data; - return (icmp_router_solicitation*)m_Data; -} + return &m_RouterAdvData; + } -icmp_router_solicitation* IcmpLayer::setRouterSolicitationData() -{ - if (!cleanIcmpLayer()) - return nullptr; + icmp_router_advertisement* IcmpLayer::setRouterAdvertisementData( + uint8_t code, uint16_t lifetimeInSeconds, const std::vector& routerAddresses) + { + if (code != 0 && code != 16) + { + PCPP_LOG_ERROR("Unknown code " << (int)code + << " for ICMP router advertisement data (only codes 0 and 16 are legal)"); + return nullptr; + } + + if (!cleanIcmpLayer()) + return nullptr; + + if (!this->extendLayer(m_DataLen, sizeof(icmp_router_advertisement_hdr) + + (routerAddresses.size() * sizeof(icmp_router_address_structure)) - + sizeof(icmphdr))) + return nullptr; + + getIcmpHeader()->type = (uint8_t)ICMP_ROUTER_ADV; + + icmp_router_advertisement* header = getRouterAdvertisementData(); + header->header->code = code; + header->header->lifetime = htobe16(lifetimeInSeconds); + header->header->advertisementCount = (uint8_t)routerAddresses.size(); + header->header->addressEntrySize = 2; + + icmp_router_address_structure* curPos = + (icmp_router_address_structure*)((uint8_t*)header->header + sizeof(icmp_router_advertisement_hdr)); + for (const auto& iter : routerAddresses) + { + curPos->routerAddress = iter.routerAddress; + curPos->preferenceLevel = iter.preferenceLevel; + curPos += 1; + } + + return header; + } - getIcmpHeader()->type = (uint8_t)ICMP_ROUTER_SOL; + icmp_router_solicitation* IcmpLayer::getRouterSolicitationData() + { + if (!isMessageOfType(ICMP_ROUTER_SOL)) + return nullptr; - icmp_router_solicitation* header = getRouterSolicitationData(); - header->code = 0; + return (icmp_router_solicitation*)m_Data; + } - return header; -} + icmp_router_solicitation* IcmpLayer::setRouterSolicitationData() + { + if (!cleanIcmpLayer()) + return nullptr; -icmp_time_exceeded* IcmpLayer::getTimeExceededData() -{ - if (!isMessageOfType(ICMP_TIME_EXCEEDED)) - return nullptr; + getIcmpHeader()->type = (uint8_t)ICMP_ROUTER_SOL; - return (icmp_time_exceeded*)m_Data; -} + icmp_router_solicitation* header = getRouterSolicitationData(); + header->code = 0; -icmp_time_exceeded* IcmpLayer::setTimeExceededData(uint8_t code, IPv4Layer* ipHeader, Layer* l4Header) -{ - if (code > 1) - { - PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP time exceeded data"); - return nullptr; + return header; } - if (!cleanIcmpLayer()) - return nullptr; + icmp_time_exceeded* IcmpLayer::getTimeExceededData() + { + if (!isMessageOfType(ICMP_TIME_EXCEEDED)) + return nullptr; - if (!this->extendLayer(m_DataLen, sizeof(icmp_time_exceeded) - sizeof(icmphdr))) - return nullptr; + return (icmp_time_exceeded*)m_Data; + } - getIcmpHeader()->type = (uint8_t)ICMP_TIME_EXCEEDED; + icmp_time_exceeded* IcmpLayer::setTimeExceededData(uint8_t code, IPv4Layer* ipHeader, Layer* l4Header) + { + if (code > 1) + { + PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP time exceeded data"); + return nullptr; + } - icmp_time_exceeded* header = getTimeExceededData(); - header->code = code; - header->unused = 0; + if (!cleanIcmpLayer()) + return nullptr; - if (!setIpAndL4Layers(ipHeader, l4Header)) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_time_exceeded) - sizeof(icmphdr))) + return nullptr; - return header; -} + getIcmpHeader()->type = (uint8_t)ICMP_TIME_EXCEEDED; -icmp_param_problem* IcmpLayer::getParamProblemData() -{ - if (!isMessageOfType(ICMP_PARAM_PROBLEM)) - return nullptr; + icmp_time_exceeded* header = getTimeExceededData(); + header->code = code; + header->unused = 0; - return (icmp_param_problem*)m_Data; -} + if (!setIpAndL4Layers(ipHeader, l4Header)) + return nullptr; -icmp_param_problem* IcmpLayer::setParamProblemData(uint8_t code, uint8_t errorOctetPointer, IPv4Layer* ipHeader, Layer* l4Header) -{ - if (code > 2) - { - PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP parameter problem data"); - return nullptr; + return header; } - if (!cleanIcmpLayer()) - return nullptr; + icmp_param_problem* IcmpLayer::getParamProblemData() + { + if (!isMessageOfType(ICMP_PARAM_PROBLEM)) + return nullptr; - if (!this->extendLayer(m_DataLen, sizeof(icmp_param_problem) - sizeof(icmphdr))) - return nullptr; + return (icmp_param_problem*)m_Data; + } - getIcmpHeader()->type = (uint8_t)ICMP_PARAM_PROBLEM; + icmp_param_problem* IcmpLayer::setParamProblemData(uint8_t code, uint8_t errorOctetPointer, IPv4Layer* ipHeader, + Layer* l4Header) + { + if (code > 2) + { + PCPP_LOG_ERROR("Unknown code " << (int)code << " for ICMP parameter problem data"); + return nullptr; + } - icmp_param_problem* header = getParamProblemData(); - header->code = code; - header->unused1 = 0; - header->unused2 = 0; - header->pointer = errorOctetPointer; + if (!cleanIcmpLayer()) + return nullptr; - if (!setIpAndL4Layers(ipHeader, l4Header)) - return nullptr; + if (!this->extendLayer(m_DataLen, sizeof(icmp_param_problem) - sizeof(icmphdr))) + return nullptr; - return header; -} + getIcmpHeader()->type = (uint8_t)ICMP_PARAM_PROBLEM; -icmp_address_mask_request* IcmpLayer::getAddressMaskRequestData() -{ - if (!isMessageOfType(ICMP_ADDRESS_MASK_REQUEST)) - return nullptr; + icmp_param_problem* header = getParamProblemData(); + header->code = code; + header->unused1 = 0; + header->unused2 = 0; + header->pointer = errorOctetPointer; - return (icmp_address_mask_request*)m_Data; -} + if (!setIpAndL4Layers(ipHeader, l4Header)) + return nullptr; -icmp_address_mask_request* IcmpLayer::setAddressMaskRequestData(uint16_t id, uint16_t sequence, IPv4Address mask) -{ - if (!cleanIcmpLayer()) - return nullptr; + return header; + } - if (!this->extendLayer(m_DataLen, sizeof(icmp_address_mask_request) - sizeof(icmphdr))) - return nullptr; + icmp_address_mask_request* IcmpLayer::getAddressMaskRequestData() + { + if (!isMessageOfType(ICMP_ADDRESS_MASK_REQUEST)) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_ADDRESS_MASK_REQUEST; + return (icmp_address_mask_request*)m_Data; + } - icmp_address_mask_request* header = getAddressMaskRequestData(); - header->code = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); - header->addressMask = mask.toInt(); + icmp_address_mask_request* IcmpLayer::setAddressMaskRequestData(uint16_t id, uint16_t sequence, IPv4Address mask) + { + if (!cleanIcmpLayer()) + return nullptr; - return header; -} + if (!this->extendLayer(m_DataLen, sizeof(icmp_address_mask_request) - sizeof(icmphdr))) + return nullptr; -icmp_address_mask_reply* IcmpLayer::getAddressMaskReplyData() -{ - if (!isMessageOfType(ICMP_ADDRESS_MASK_REPLY)) - return nullptr; + getIcmpHeader()->type = (uint8_t)ICMP_ADDRESS_MASK_REQUEST; - return (icmp_address_mask_reply*)m_Data; -} + icmp_address_mask_request* header = getAddressMaskRequestData(); + header->code = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); + header->addressMask = mask.toInt(); -icmp_address_mask_reply* IcmpLayer::setAddressMaskReplyData(uint16_t id, uint16_t sequence, IPv4Address mask) -{ - if (!cleanIcmpLayer()) - return nullptr; + return header; + } - if (!this->extendLayer(m_DataLen, sizeof(icmp_address_mask_reply) - sizeof(icmphdr))) - return nullptr; + icmp_address_mask_reply* IcmpLayer::getAddressMaskReplyData() + { + if (!isMessageOfType(ICMP_ADDRESS_MASK_REPLY)) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_ADDRESS_MASK_REPLY; + return (icmp_address_mask_reply*)m_Data; + } - icmp_address_mask_reply* header = getAddressMaskReplyData(); - header->code = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); - header->addressMask = htobe32(mask.toInt()); + icmp_address_mask_reply* IcmpLayer::setAddressMaskReplyData(uint16_t id, uint16_t sequence, IPv4Address mask) + { + if (!cleanIcmpLayer()) + return nullptr; - return header; -} + if (!this->extendLayer(m_DataLen, sizeof(icmp_address_mask_reply) - sizeof(icmphdr))) + return nullptr; -icmp_info_request* IcmpLayer::getInfoRequestData() -{ - if (!isMessageOfType(ICMP_INFO_REQUEST)) - return nullptr; + getIcmpHeader()->type = (uint8_t)ICMP_ADDRESS_MASK_REPLY; - return (icmp_info_request*)m_Data; -} + icmp_address_mask_reply* header = getAddressMaskReplyData(); + header->code = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); + header->addressMask = htobe32(mask.toInt()); -icmp_info_request* IcmpLayer::setInfoRequestData(uint16_t id, uint16_t sequence) -{ - if (!cleanIcmpLayer()) - return nullptr; + return header; + } - if (!this->extendLayer(m_DataLen, sizeof(icmp_info_request) - sizeof(icmphdr))) - return nullptr; + icmp_info_request* IcmpLayer::getInfoRequestData() + { + if (!isMessageOfType(ICMP_INFO_REQUEST)) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_INFO_REQUEST; + return (icmp_info_request*)m_Data; + } - icmp_info_request* header = getInfoRequestData(); - header->code = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); + icmp_info_request* IcmpLayer::setInfoRequestData(uint16_t id, uint16_t sequence) + { + if (!cleanIcmpLayer()) + return nullptr; - return header; -} + if (!this->extendLayer(m_DataLen, sizeof(icmp_info_request) - sizeof(icmphdr))) + return nullptr; -icmp_info_reply* IcmpLayer::getInfoReplyData() -{ - if (!isMessageOfType(ICMP_INFO_REPLY)) - return nullptr; + getIcmpHeader()->type = (uint8_t)ICMP_INFO_REQUEST; - return (icmp_info_reply*)m_Data; -} + icmp_info_request* header = getInfoRequestData(); + header->code = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); -icmp_info_reply* IcmpLayer::setInfoReplyData(uint16_t id, uint16_t sequence) -{ - if (!cleanIcmpLayer()) - return nullptr; + return header; + } - if (!this->extendLayer(m_DataLen, sizeof(icmp_info_reply) - sizeof(icmphdr))) - return nullptr; + icmp_info_reply* IcmpLayer::getInfoReplyData() + { + if (!isMessageOfType(ICMP_INFO_REPLY)) + return nullptr; - getIcmpHeader()->type = (uint8_t)ICMP_INFO_REPLY; + return (icmp_info_reply*)m_Data; + } - icmp_info_reply* header = getInfoReplyData(); - header->code = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); + icmp_info_reply* IcmpLayer::setInfoReplyData(uint16_t id, uint16_t sequence) + { + if (!cleanIcmpLayer()) + return nullptr; - return header; -} + if (!this->extendLayer(m_DataLen, sizeof(icmp_info_reply) - sizeof(icmphdr))) + return nullptr; + getIcmpHeader()->type = (uint8_t)ICMP_INFO_REPLY; -void IcmpLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - - switch (getMessageType()) - { - case ICMP_DEST_UNREACHABLE: - case ICMP_SOURCE_QUENCH: - case ICMP_TIME_EXCEEDED: - case ICMP_REDIRECT: - case ICMP_PARAM_PROBLEM: - m_NextLayer = IPv4Layer::isDataValid(m_Data + headerLen, m_DataLen - headerLen) - ? static_cast(new IPv4Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet)) - : static_cast(new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet)); - return; - default: - if (m_DataLen > headerLen) - m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); - return; - } -} - -size_t IcmpLayer::getHeaderLen() const -{ - IcmpMessageType type = getMessageType(); - size_t routerAdvSize = 0; - switch (type) - { - case ICMP_ECHO_REQUEST: - case ICMP_ECHO_REPLY: - return m_DataLen; - case ICMP_TIMESTAMP_REQUEST: - case ICMP_TIMESTAMP_REPLY: - return sizeof(icmp_timestamp_request); - case ICMP_ROUTER_SOL: - case ICMP_INFO_REQUEST: - case ICMP_INFO_REPLY: - case ICMP_UNSUPPORTED: - return sizeof(icmphdr); - case ICMP_ADDRESS_MASK_REPLY: - case ICMP_ADDRESS_MASK_REQUEST: - return sizeof(icmp_address_mask_request); - case ICMP_DEST_UNREACHABLE: - return sizeof(icmp_destination_unreachable); - case ICMP_REDIRECT: - return sizeof(icmp_redirect); - case ICMP_TIME_EXCEEDED: - case ICMP_SOURCE_QUENCH: - return sizeof(icmp_time_exceeded); - case ICMP_PARAM_PROBLEM: - return sizeof(icmp_param_problem); - case ICMP_ROUTER_ADV: - routerAdvSize = sizeof(icmp_router_advertisement_hdr) + (getRouterAdvertisementData()->header->advertisementCount*sizeof(icmp_router_address_structure)); - if (routerAdvSize > m_DataLen) - return m_DataLen; - return routerAdvSize; - default: - return sizeof(icmphdr); + icmp_info_reply* header = getInfoReplyData(); + header->code = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); + + return header; } -} -void IcmpLayer::computeCalculateFields() -{ - // calculate checksum - getIcmpHeader()->checksum = 0; + void IcmpLayer::parseNextLayer() + { + size_t headerLen = getHeaderLen(); + + switch (getMessageType()) + { + case ICMP_DEST_UNREACHABLE: + case ICMP_SOURCE_QUENCH: + case ICMP_TIME_EXCEEDED: + case ICMP_REDIRECT: + case ICMP_PARAM_PROBLEM: + // clang-format off + m_NextLayer = IPv4Layer::isDataValid(m_Data + headerLen, m_DataLen - headerLen) + ? static_cast(new IPv4Layer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet)) + : static_cast(new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet)); + // clang-format on + return; + default: + if (m_DataLen > headerLen) + m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + return; + } + } - size_t icmpLen = 0; - Layer* curLayer = this; - while (curLayer != nullptr) + size_t IcmpLayer::getHeaderLen() const { - icmpLen += curLayer->getHeaderLen(); - curLayer = curLayer->getNextLayer(); + IcmpMessageType type = getMessageType(); + size_t routerAdvSize = 0; + switch (type) + { + case ICMP_ECHO_REQUEST: + case ICMP_ECHO_REPLY: + return m_DataLen; + case ICMP_TIMESTAMP_REQUEST: + case ICMP_TIMESTAMP_REPLY: + return sizeof(icmp_timestamp_request); + case ICMP_ROUTER_SOL: + case ICMP_INFO_REQUEST: + case ICMP_INFO_REPLY: + case ICMP_UNSUPPORTED: + return sizeof(icmphdr); + case ICMP_ADDRESS_MASK_REPLY: + case ICMP_ADDRESS_MASK_REQUEST: + return sizeof(icmp_address_mask_request); + case ICMP_DEST_UNREACHABLE: + return sizeof(icmp_destination_unreachable); + case ICMP_REDIRECT: + return sizeof(icmp_redirect); + case ICMP_TIME_EXCEEDED: + case ICMP_SOURCE_QUENCH: + return sizeof(icmp_time_exceeded); + case ICMP_PARAM_PROBLEM: + return sizeof(icmp_param_problem); + case ICMP_ROUTER_ADV: + // clang-format off + routerAdvSize = sizeof(icmp_router_advertisement_hdr) + (getRouterAdvertisementData()->header->advertisementCount * sizeof(icmp_router_address_structure)); + // clang-format on + if (routerAdvSize > m_DataLen) + return m_DataLen; + return routerAdvSize; + default: + return sizeof(icmphdr); + } } - ScalarBuffer buffer; - buffer.buffer = (uint16_t*)getIcmpHeader(); - buffer.len = icmpLen; - size_t checksum = computeChecksum(&buffer, 1); + void IcmpLayer::computeCalculateFields() + { + // calculate checksum + getIcmpHeader()->checksum = 0; + + size_t icmpLen = 0; + Layer* curLayer = this; + while (curLayer != nullptr) + { + icmpLen += curLayer->getHeaderLen(); + curLayer = curLayer->getNextLayer(); + } + + ScalarBuffer buffer; + buffer.buffer = (uint16_t*)getIcmpHeader(); + buffer.len = icmpLen; + size_t checksum = computeChecksum(&buffer, 1); + + getIcmpHeader()->checksum = htobe16(checksum); + } - getIcmpHeader()->checksum = htobe16(checksum); -} + std::string IcmpLayer::toString() const + { + std::string messageTypeAsString; + IcmpMessageType type = getMessageType(); + switch (type) + { + case ICMP_ECHO_REPLY: + messageTypeAsString = "Echo (ping) reply"; + break; + case ICMP_DEST_UNREACHABLE: + messageTypeAsString = "Destination unreachable"; + break; + case ICMP_SOURCE_QUENCH: + messageTypeAsString = "Source quench (flow control)"; + break; + case ICMP_REDIRECT: + messageTypeAsString = "Redirect"; + break; + case ICMP_ECHO_REQUEST: + messageTypeAsString = "Echo (ping) request"; + break; + case ICMP_ROUTER_ADV: + messageTypeAsString = "Router advertisement"; + break; + case ICMP_ROUTER_SOL: + messageTypeAsString = "Router solicitation"; + break; + case ICMP_TIME_EXCEEDED: + messageTypeAsString = "Time-to-live exceeded"; + break; + case ICMP_PARAM_PROBLEM: + messageTypeAsString = "Parameter problem: bad IP header"; + break; + case ICMP_TIMESTAMP_REQUEST: + messageTypeAsString = "Timestamp request"; + break; + case ICMP_TIMESTAMP_REPLY: + messageTypeAsString = "Timestamp reply"; + break; + case ICMP_INFO_REQUEST: + messageTypeAsString = "Information request"; + break; + case ICMP_INFO_REPLY: + messageTypeAsString = "Information reply"; + break; + case ICMP_ADDRESS_MASK_REQUEST: + messageTypeAsString = "Address mask request"; + break; + case ICMP_ADDRESS_MASK_REPLY: + messageTypeAsString = "Address mask reply"; + break; + default: + messageTypeAsString = "Unknown"; + break; + } + + std::ostringstream typeStream; + typeStream << (int)getIcmpHeader()->type; + + return "ICMP Layer, " + messageTypeAsString + " (type: " + typeStream.str() + ")"; + } -std::string IcmpLayer::toString() const -{ - std::string messageTypeAsString; - IcmpMessageType type = getMessageType(); - switch (type) - { - case ICMP_ECHO_REPLY: - messageTypeAsString = "Echo (ping) reply"; - break; - case ICMP_DEST_UNREACHABLE: - messageTypeAsString = "Destination unreachable"; - break; - case ICMP_SOURCE_QUENCH: - messageTypeAsString = "Source quench (flow control)"; - break; - case ICMP_REDIRECT: - messageTypeAsString = "Redirect"; - break; - case ICMP_ECHO_REQUEST: - messageTypeAsString = "Echo (ping) request"; - break; - case ICMP_ROUTER_ADV: - messageTypeAsString = "Router advertisement"; - break; - case ICMP_ROUTER_SOL: - messageTypeAsString = "Router solicitation"; - break; - case ICMP_TIME_EXCEEDED: - messageTypeAsString = "Time-to-live exceeded"; - break; - case ICMP_PARAM_PROBLEM: - messageTypeAsString = "Parameter problem: bad IP header"; - break; - case ICMP_TIMESTAMP_REQUEST: - messageTypeAsString = "Timestamp request"; - break; - case ICMP_TIMESTAMP_REPLY: - messageTypeAsString = "Timestamp reply"; - break; - case ICMP_INFO_REQUEST: - messageTypeAsString = "Information request"; - break; - case ICMP_INFO_REPLY: - messageTypeAsString = "Information reply"; - break; - case ICMP_ADDRESS_MASK_REQUEST: - messageTypeAsString = "Address mask request"; - break; - case ICMP_ADDRESS_MASK_REPLY: - messageTypeAsString = "Address mask reply"; - break; - default: - messageTypeAsString = "Unknown"; - break; - } - - std::ostringstream typeStream; - typeStream << (int)getIcmpHeader()->type; - - return "ICMP Layer, " + messageTypeAsString + " (type: " + typeStream.str() + ")"; -} - -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/IcmpV6Layer.cpp b/Packet++/src/IcmpV6Layer.cpp index 7fab0db9da..e118d1295f 100644 --- a/Packet++/src/IcmpV6Layer.cpp +++ b/Packet++/src/IcmpV6Layer.cpp @@ -15,155 +15,156 @@ namespace pcpp { -Layer* IcmpV6Layer::parseIcmpV6Layer(uint8_t *data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - if (dataLen < sizeof(icmpv6hdr)) - return new PayloadLayer(data, dataLen, prevLayer, packet); - - icmpv6hdr *hdr = (icmpv6hdr *)data; - ICMPv6MessageType messageType = static_cast(hdr->type); - - switch (messageType) + Layer* IcmpV6Layer::parseIcmpV6Layer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) { - case ICMPv6MessageType::ICMPv6_ECHO_REQUEST: - case ICMPv6MessageType::ICMPv6_ECHO_REPLY: - return new ICMPv6EchoLayer(data, dataLen, prevLayer, packet); - case ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION: - return new NDPNeighborSolicitationLayer(data, dataLen, prevLayer, packet); - case ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT: - return new NDPNeighborAdvertisementLayer(data, dataLen, prevLayer, packet); - case ICMPv6MessageType::ICMPv6_UNKNOWN_MESSAGE: - return new PayloadLayer(data, dataLen, prevLayer, packet); - default: - return new IcmpV6Layer(data, dataLen, prevLayer, packet); + if (dataLen < sizeof(icmpv6hdr)) + return new PayloadLayer(data, dataLen, prevLayer, packet); + + icmpv6hdr* hdr = (icmpv6hdr*)data; + ICMPv6MessageType messageType = static_cast(hdr->type); + + switch (messageType) + { + case ICMPv6MessageType::ICMPv6_ECHO_REQUEST: + case ICMPv6MessageType::ICMPv6_ECHO_REPLY: + return new ICMPv6EchoLayer(data, dataLen, prevLayer, packet); + case ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION: + return new NDPNeighborSolicitationLayer(data, dataLen, prevLayer, packet); + case ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT: + return new NDPNeighborAdvertisementLayer(data, dataLen, prevLayer, packet); + case ICMPv6MessageType::ICMPv6_UNKNOWN_MESSAGE: + return new PayloadLayer(data, dataLen, prevLayer, packet); + default: + return new IcmpV6Layer(data, dataLen, prevLayer, packet); + } } -} - -IcmpV6Layer::IcmpV6Layer(ICMPv6MessageType msgType, uint8_t code, const uint8_t *data, size_t dataLen) -{ - m_DataLen = sizeof(icmpv6hdr) + dataLen; - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = ICMPv6; - - icmpv6hdr *hdr = (icmpv6hdr *)m_Data; - hdr->type = static_cast(msgType); - hdr->code = code; - - if (data != nullptr && dataLen > 0) - memcpy(m_Data + sizeof(icmpv6hdr), data, dataLen); -} - -ICMPv6MessageType IcmpV6Layer::getMessageType() const -{ - return static_cast(getIcmpv6Header()->type); -} - -uint8_t IcmpV6Layer::getCode() const -{ - return getIcmpv6Header()->code; -} -uint16_t IcmpV6Layer::getChecksum() const -{ - return be16toh(getIcmpv6Header()->checksum); -} - -void IcmpV6Layer::computeCalculateFields() -{ - calculateChecksum(); -} - -void IcmpV6Layer::calculateChecksum() -{ - /* Pseudo header of 40 bytes which is composed as follows(in order): - - 16 bytes for the source address - - 16 bytes for the destination address - - 4 bytes big endian payload length(the same value as in the IPv6 header) - - 3 bytes zero + 1 byte nextheader( 58 decimal) big endian - */ - - getIcmpv6Header()->checksum = 0; - - if (m_PrevLayer != nullptr) + IcmpV6Layer::IcmpV6Layer(ICMPv6MessageType msgType, uint8_t code, const uint8_t* data, size_t dataLen) { - ScalarBuffer vec[2]; - - vec[0].buffer = (uint16_t *)m_Data; - vec[0].len = m_DataLen; + m_DataLen = sizeof(icmpv6hdr) + dataLen; + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = ICMPv6; - const unsigned int pseudoHeaderLen = 40; - const unsigned int bigEndianLen = htobe32(m_DataLen); - const unsigned int bigEndianNextHeader = htobe32(PACKETPP_IPPROTO_ICMPV6); + icmpv6hdr* hdr = (icmpv6hdr*)m_Data; + hdr->type = static_cast(msgType); + hdr->code = code; - uint16_t pseudoHeader[pseudoHeaderLen / 2]; - ((IPv6Layer *)m_PrevLayer)->getSrcIPv6Address().copyTo((uint8_t *)pseudoHeader); - ((IPv6Layer *)m_PrevLayer)->getDstIPv6Address().copyTo((uint8_t *)(pseudoHeader + 8)); - memcpy(&pseudoHeader[16], &bigEndianLen, sizeof(uint32_t)); - memcpy(&pseudoHeader[18], &bigEndianNextHeader, sizeof(uint32_t)); - vec[1].buffer = pseudoHeader; - vec[1].len = pseudoHeaderLen; + if (data != nullptr && dataLen > 0) + memcpy(m_Data + sizeof(icmpv6hdr), data, dataLen); + } - /* Calculate and write checksum */ - getIcmpv6Header()->checksum = htobe16(computeChecksum(vec, 2)); + ICMPv6MessageType IcmpV6Layer::getMessageType() const + { + return static_cast(getIcmpv6Header()->type); } -} -std::string IcmpV6Layer::toString() const -{ - std::ostringstream typeStream; - typeStream << (int)getMessageType(); - return "ICMPv6 Layer, Message type: " + typeStream.str(); -} + uint8_t IcmpV6Layer::getCode() const + { + return getIcmpv6Header()->code; + } -// -// ICMPv6EchoLayer -// + uint16_t IcmpV6Layer::getChecksum() const + { + return be16toh(getIcmpv6Header()->checksum); + } -ICMPv6EchoLayer::ICMPv6EchoLayer(ICMPv6EchoType echoType, uint16_t id, uint16_t sequence, const uint8_t *data, size_t dataLen) -{ - m_DataLen = sizeof(icmpv6_echo_hdr) + dataLen; - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = ICMPv6; + void IcmpV6Layer::computeCalculateFields() + { + calculateChecksum(); + } - icmpv6_echo_hdr *header = getEchoHeader(); + void IcmpV6Layer::calculateChecksum() + { + /* Pseudo header of 40 bytes which is composed as follows(in order): + - 16 bytes for the source address + - 16 bytes for the destination address + - 4 bytes big endian payload length(the same value as in the IPv6 header) + - 3 bytes zero + 1 byte nextheader( 58 decimal) big endian + */ + + getIcmpv6Header()->checksum = 0; + + if (m_PrevLayer != nullptr) + { + ScalarBuffer vec[2]; + + vec[0].buffer = (uint16_t*)m_Data; + vec[0].len = m_DataLen; + + const unsigned int pseudoHeaderLen = 40; + const unsigned int bigEndianLen = htobe32(m_DataLen); + const unsigned int bigEndianNextHeader = htobe32(PACKETPP_IPPROTO_ICMPV6); + + uint16_t pseudoHeader[pseudoHeaderLen / 2]; + ((IPv6Layer*)m_PrevLayer)->getSrcIPv6Address().copyTo((uint8_t*)pseudoHeader); + ((IPv6Layer*)m_PrevLayer)->getDstIPv6Address().copyTo((uint8_t*)(pseudoHeader + 8)); + memcpy(&pseudoHeader[16], &bigEndianLen, sizeof(uint32_t)); + memcpy(&pseudoHeader[18], &bigEndianNextHeader, sizeof(uint32_t)); + vec[1].buffer = pseudoHeader; + vec[1].len = pseudoHeaderLen; + + /* Calculate and write checksum */ + getIcmpv6Header()->checksum = htobe16(computeChecksum(vec, 2)); + } + } - switch (echoType) + std::string IcmpV6Layer::toString() const { - case REPLY: - header->type = static_cast(ICMPv6MessageType::ICMPv6_ECHO_REPLY); - break; - case REQUEST: - default: - header->type = static_cast(ICMPv6MessageType::ICMPv6_ECHO_REQUEST); - break; + std::ostringstream typeStream; + typeStream << (int)getMessageType(); + return "ICMPv6 Layer, Message type: " + typeStream.str(); } - header->code = 0; - header->checksum = 0; - header->id = htobe16(id); - header->sequence = htobe16(sequence); + // + // ICMPv6EchoLayer + // - if (data != nullptr && dataLen > 0) - memcpy(getEchoDataPtr(), data, dataLen); -} + ICMPv6EchoLayer::ICMPv6EchoLayer(ICMPv6EchoType echoType, uint16_t id, uint16_t sequence, const uint8_t* data, + size_t dataLen) + { + m_DataLen = sizeof(icmpv6_echo_hdr) + dataLen; + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = ICMPv6; + + icmpv6_echo_hdr* header = getEchoHeader(); + + switch (echoType) + { + case REPLY: + header->type = static_cast(ICMPv6MessageType::ICMPv6_ECHO_REPLY); + break; + case REQUEST: + default: + header->type = static_cast(ICMPv6MessageType::ICMPv6_ECHO_REQUEST); + break; + } + + header->code = 0; + header->checksum = 0; + header->id = htobe16(id); + header->sequence = htobe16(sequence); + + if (data != nullptr && dataLen > 0) + memcpy(getEchoDataPtr(), data, dataLen); + } -uint16_t ICMPv6EchoLayer::getIdentifier() const -{ - return be16toh(getEchoHeader()->id); -} + uint16_t ICMPv6EchoLayer::getIdentifier() const + { + return be16toh(getEchoHeader()->id); + } -uint16_t ICMPv6EchoLayer::getSequenceNr() const -{ - return be16toh(getEchoHeader()->sequence); -} + uint16_t ICMPv6EchoLayer::getSequenceNr() const + { + return be16toh(getEchoHeader()->sequence); + } -std::string ICMPv6EchoLayer::toString() const -{ - std::ostringstream typeStream; - typeStream << (int)getMessageType(); - return "ICMPv6 Layer, Echo Request/Reply Message (type: " + typeStream.str() + ")"; -} + std::string ICMPv6EchoLayer::toString() const + { + std::ostringstream typeStream; + typeStream << (int)getMessageType(); + return "ICMPv6 Layer, Echo Request/Reply Message (type: " + typeStream.str() + ")"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/IgmpLayer.cpp b/Packet++/src/IgmpLayer.cpp index c759765ecc..6f95416b5b 100644 --- a/Packet++/src/IgmpLayer.cpp +++ b/Packet++/src/IgmpLayer.cpp @@ -9,545 +9,529 @@ namespace pcpp { -/************* - * IgmpLayer - *************/ + /************* + * IgmpLayer + *************/ -IgmpLayer::IgmpLayer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime, ProtocolType igmpVer) -{ - m_DataLen = getHeaderSizeByVerAndType(igmpVer, type); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = igmpVer; + IgmpLayer::IgmpLayer(IgmpType type, const IPv4Address& groupAddr, uint8_t maxResponseTime, ProtocolType igmpVer) + { + m_DataLen = getHeaderSizeByVerAndType(igmpVer, type); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = igmpVer; - setType(type); - setGroupAddress(groupAddr); + setType(type); + setGroupAddress(groupAddr); - getIgmpHeader()->maxResponseTime = maxResponseTime; -} + getIgmpHeader()->maxResponseTime = maxResponseTime; + } -void IgmpLayer::setGroupAddress(const IPv4Address& groupAddr) -{ - igmp_header* hdr = getIgmpHeader(); - hdr->groupAddress = groupAddr.toInt(); -} + void IgmpLayer::setGroupAddress(const IPv4Address& groupAddr) + { + igmp_header* hdr = getIgmpHeader(); + hdr->groupAddress = groupAddr.toInt(); + } -IgmpType IgmpLayer::getType() const -{ - uint8_t type = getIgmpHeader()->type; - if (type < (uint8_t)IgmpType_MembershipQuery || - (type > (uint8_t)IgmpType_LeaveGroup && type < (uint8_t)IgmpType_MulticastTracerouteResponse) || - (type > (uint8_t)IgmpType_MulticastTraceroute && type < (uint8_t)IgmpType_MembershipReportV3) || - (type > (uint8_t)IgmpType_MembershipReportV3 && type < (uint8_t)IgmpType_MulticastRouterAdvertisement) || - type > IgmpType_MulticastRouterTermination) - return IgmpType_Unknown; - - return (IgmpType)type; -} - -void IgmpLayer::setType(IgmpType type) -{ - if (type == IgmpType_Unknown) - return; + IgmpType IgmpLayer::getType() const + { + uint8_t type = getIgmpHeader()->type; + if (type < (uint8_t)IgmpType_MembershipQuery || + (type > (uint8_t)IgmpType_LeaveGroup && type < (uint8_t)IgmpType_MulticastTracerouteResponse) || + (type > (uint8_t)IgmpType_MulticastTraceroute && type < (uint8_t)IgmpType_MembershipReportV3) || + (type > (uint8_t)IgmpType_MembershipReportV3 && type < (uint8_t)IgmpType_MulticastRouterAdvertisement) || + type > IgmpType_MulticastRouterTermination) + { + return IgmpType_Unknown; + } - igmp_header* hdr = getIgmpHeader(); - hdr->type = type; -} + return (IgmpType)type; + } -ProtocolType IgmpLayer::getIGMPVerFromData(uint8_t* data, size_t dataLen, bool& isQuery) -{ - isQuery = false; + void IgmpLayer::setType(IgmpType type) + { + if (type == IgmpType_Unknown) + return; - if (dataLen < 8 || data == nullptr) - return UnknownProtocol; + igmp_header* hdr = getIgmpHeader(); + hdr->type = type; + } - switch ((int)data[0]) + ProtocolType IgmpLayer::getIGMPVerFromData(uint8_t* data, size_t dataLen, bool& isQuery) { - case IgmpType_MembershipReportV2: - case IgmpType_LeaveGroup: - return IGMPv2; - case IgmpType_MembershipReportV1: - return IGMPv1; - case IgmpType_MembershipReportV3: - return IGMPv3; - case IgmpType_MembershipQuery: - { - isQuery = true; + isQuery = false; - if (dataLen >= sizeof(igmpv3_query_header)) - return IGMPv3; + if (dataLen < 8 || data == nullptr) + return UnknownProtocol; - if (data[1] == 0) - return IGMPv1; - else + switch ((int)data[0]) + { + case IgmpType_MembershipReportV2: + case IgmpType_LeaveGroup: return IGMPv2; - } - default: - return UnknownProtocol; - } -} + case IgmpType_MembershipReportV1: + return IGMPv1; + case IgmpType_MembershipReportV3: + return IGMPv3; + case IgmpType_MembershipQuery: + { + isQuery = true; -uint16_t IgmpLayer::calculateChecksum() -{ - ScalarBuffer buffer; - buffer.buffer = (uint16_t*)getIgmpHeader(); - buffer.len = getHeaderLen(); - return computeChecksum(&buffer, 1); -} + if (dataLen >= sizeof(igmpv3_query_header)) + return IGMPv3; -size_t IgmpLayer::getHeaderSizeByVerAndType(ProtocolType igmpVer, IgmpType igmpType) const -{ - if (igmpVer == IGMPv1 || igmpVer == IGMPv2) - return sizeof(igmp_header); + if (data[1] == 0) + return IGMPv1; + else + return IGMPv2; + } + default: + return UnknownProtocol; + } + } - if (igmpVer == IGMPv3) + uint16_t IgmpLayer::calculateChecksum() { - if (igmpType == IgmpType_MembershipQuery) - return sizeof(igmpv3_query_header); - else if (igmpType == IgmpType_MembershipReportV3) - return sizeof(igmpv3_report_header); + ScalarBuffer buffer; + buffer.buffer = (uint16_t*)getIgmpHeader(); + buffer.len = getHeaderLen(); + return computeChecksum(&buffer, 1); } - return 0; -} - -std::string IgmpLayer::toString() const -{ - std::string igmpVer = ""; - switch (getProtocol()) + size_t IgmpLayer::getHeaderSizeByVerAndType(ProtocolType igmpVer, IgmpType igmpType) const { - case IGMPv1: - igmpVer = "1"; - break; - case IGMPv2: - igmpVer = "2"; - break; - default: - igmpVer = "3"; - } + if (igmpVer == IGMPv1 || igmpVer == IGMPv2) + return sizeof(igmp_header); - std::string msgType; + if (igmpVer == IGMPv3) + { + if (igmpType == IgmpType_MembershipQuery) + return sizeof(igmpv3_query_header); + else if (igmpType == IgmpType_MembershipReportV3) + return sizeof(igmpv3_report_header); + } - switch (getType()) - { - case IgmpType_MembershipQuery: - msgType = "Membership Query"; - break; - case IgmpType_MembershipReportV1: - msgType = "Membership Report"; - break; - case IgmpType_DVMRP: - msgType = "DVMRP"; - break; - case IgmpType_P1Mv1: - msgType = "PIMv1"; - break; - case IgmpType_CiscoTrace: - msgType = "Cisco Trace"; - break; - case IgmpType_MembershipReportV2: - msgType = "Membership Report"; - break; - case IgmpType_LeaveGroup: - msgType = "Leave Group"; - break; - case IgmpType_MulticastTracerouteResponse: - msgType = "Multicast Traceroute Response"; - break; - case IgmpType_MulticastTraceroute: - msgType = "Multicast Traceroute"; - break; - case IgmpType_MembershipReportV3: - msgType = "Membership Report"; - break; - case IgmpType_MulticastRouterAdvertisement: - msgType = "Multicast Router Advertisement"; - break; - case IgmpType_MulticastRouterSolicitation: - msgType = "Multicast Router Solicitation"; - break; - case IgmpType_MulticastRouterTermination: - msgType = "Multicast Router Termination"; - break; - default: - msgType = "Unknown"; - break; + return 0; } - std::string result = "IGMPv" + igmpVer + " Layer, " + msgType + " message"; - return result; -} - + std::string IgmpLayer::toString() const + { + std::string igmpVer = ""; + switch (getProtocol()) + { + case IGMPv1: + igmpVer = "1"; + break; + case IGMPv2: + igmpVer = "2"; + break; + default: + igmpVer = "3"; + } + std::string msgType; + switch (getType()) + { + case IgmpType_MembershipQuery: + msgType = "Membership Query"; + break; + case IgmpType_MembershipReportV1: + msgType = "Membership Report"; + break; + case IgmpType_DVMRP: + msgType = "DVMRP"; + break; + case IgmpType_P1Mv1: + msgType = "PIMv1"; + break; + case IgmpType_CiscoTrace: + msgType = "Cisco Trace"; + break; + case IgmpType_MembershipReportV2: + msgType = "Membership Report"; + break; + case IgmpType_LeaveGroup: + msgType = "Leave Group"; + break; + case IgmpType_MulticastTracerouteResponse: + msgType = "Multicast Traceroute Response"; + break; + case IgmpType_MulticastTraceroute: + msgType = "Multicast Traceroute"; + break; + case IgmpType_MembershipReportV3: + msgType = "Membership Report"; + break; + case IgmpType_MulticastRouterAdvertisement: + msgType = "Multicast Router Advertisement"; + break; + case IgmpType_MulticastRouterSolicitation: + msgType = "Multicast Router Solicitation"; + break; + case IgmpType_MulticastRouterTermination: + msgType = "Multicast Router Termination"; + break; + default: + msgType = "Unknown"; + break; + } -/************* - * IgmpV1Layer - *************/ + std::string result = "IGMPv" + igmpVer + " Layer, " + msgType + " message"; + return result; + } + /************* + * IgmpV1Layer + *************/ -void IgmpV1Layer::computeCalculateFields() -{ - igmp_header* hdr = getIgmpHeader(); - hdr->checksum = 0; - hdr->checksum = htobe16(calculateChecksum()); - hdr->maxResponseTime = 0; -} + void IgmpV1Layer::computeCalculateFields() + { + igmp_header* hdr = getIgmpHeader(); + hdr->checksum = 0; + hdr->checksum = htobe16(calculateChecksum()); + hdr->maxResponseTime = 0; + } + /************* + * IgmpV2Layer + *************/ + void IgmpV2Layer::computeCalculateFields() + { + igmp_header* hdr = getIgmpHeader(); + hdr->checksum = 0; + hdr->checksum = htobe16(calculateChecksum()); + } + /****************** + * IgmpV3QueryLayer + ******************/ + IgmpV3QueryLayer::IgmpV3QueryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3) + {} -/************* - * IgmpV2Layer - *************/ + IgmpV3QueryLayer::IgmpV3QueryLayer(const IPv4Address& multicastAddr, uint8_t maxResponseTime, uint8_t s_qrv) + : IgmpLayer(IgmpType_MembershipQuery, multicastAddr, maxResponseTime, IGMPv3) + { + getIgmpV3QueryHeader()->s_qrv = s_qrv; + } + uint16_t IgmpV3QueryLayer::getSourceAddressCount() const + { + return be16toh(getIgmpV3QueryHeader()->numOfSources); + } -void IgmpV2Layer::computeCalculateFields() -{ - igmp_header* hdr = getIgmpHeader(); - hdr->checksum = 0; - hdr->checksum = htobe16(calculateChecksum()); -} + IPv4Address IgmpV3QueryLayer::getSourceAddressAtIndex(int index) const + { + uint16_t numOfSources = getSourceAddressCount(); + if (index < 0 || index >= numOfSources) + return IPv4Address(); + // verify numOfRecords is a reasonable number that points to data within the packet + int ptrOffset = index * sizeof(uint32_t) + sizeof(igmpv3_query_header); + if (ptrOffset + sizeof(uint32_t) > getDataLen()) + return IPv4Address(); + uint8_t* ptr = m_Data + ptrOffset; + return IPv4Address(*(uint32_t*)ptr); + } + size_t IgmpV3QueryLayer::getHeaderLen() const + { + uint16_t numOfSources = getSourceAddressCount(); + int headerLen = numOfSources * sizeof(uint32_t) + sizeof(igmpv3_query_header); -/****************** - * IgmpV3QueryLayer - ******************/ + // verify numOfRecords is a reasonable number that points to data within the packet + if ((size_t)headerLen > getDataLen()) + return getDataLen(); + return (size_t)headerLen; + } -IgmpV3QueryLayer::IgmpV3QueryLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : - IgmpLayer(data, dataLen, prevLayer, packet, IGMPv3) -{ -} + void IgmpV3QueryLayer::computeCalculateFields() + { + igmpv3_query_header* hdr = getIgmpV3QueryHeader(); + hdr->checksum = 0; + hdr->checksum = htobe16(calculateChecksum()); + } -IgmpV3QueryLayer::IgmpV3QueryLayer(const IPv4Address& multicastAddr, uint8_t maxResponseTime, uint8_t s_qrv) : - IgmpLayer(IgmpType_MembershipQuery, multicastAddr, maxResponseTime, IGMPv3) -{ - getIgmpV3QueryHeader()->s_qrv = s_qrv; -} + bool IgmpV3QueryLayer::addSourceAddress(const IPv4Address& addr) + { + return addSourceAddressAtIndex(addr, getSourceAddressCount()); + } -uint16_t IgmpV3QueryLayer::getSourceAddressCount() const -{ - return be16toh(getIgmpV3QueryHeader()->numOfSources); -} + bool IgmpV3QueryLayer::addSourceAddressAtIndex(const IPv4Address& addr, int index) + { + uint16_t sourceAddrCount = getSourceAddressCount(); -IPv4Address IgmpV3QueryLayer::getSourceAddressAtIndex(int index) const -{ - uint16_t numOfSources = getSourceAddressCount(); - if (index < 0 || index >= numOfSources) - return IPv4Address(); + if (index < 0 || index > (int)sourceAddrCount) + { + PCPP_LOG_ERROR("Cannot add source address at index " << index << ", index is out of bounds"); + return false; + } - // verify numOfRecords is a reasonable number that points to data within the packet - int ptrOffset = index * sizeof(uint32_t) + sizeof(igmpv3_query_header); - if (ptrOffset + sizeof(uint32_t) > getDataLen()) - return IPv4Address(); + size_t offset = sizeof(igmpv3_query_header) + index * sizeof(uint32_t); + if (offset > getHeaderLen()) + { + PCPP_LOG_ERROR("Cannot add source address at index " << index << ", index is out of packet bounds"); + return false; + } - uint8_t* ptr = m_Data + ptrOffset; - return IPv4Address(*(uint32_t*)ptr); -} + if (!extendLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Cannot add source address at index " << index << ", didn't manage to extend layer"); + return false; + } -size_t IgmpV3QueryLayer::getHeaderLen() const -{ - uint16_t numOfSources = getSourceAddressCount(); + memcpy(m_Data + offset, addr.toBytes(), sizeof(uint32_t)); - int headerLen = numOfSources * sizeof(uint32_t) + sizeof(igmpv3_query_header); + getIgmpV3QueryHeader()->numOfSources = htobe16(sourceAddrCount + 1); - // verify numOfRecords is a reasonable number that points to data within the packet - if ((size_t)headerLen > getDataLen()) - return getDataLen(); + return true; + } - return (size_t)headerLen; -} + bool IgmpV3QueryLayer::removeSourceAddressAtIndex(int index) + { + uint16_t sourceAddrCount = getSourceAddressCount(); -void IgmpV3QueryLayer::computeCalculateFields() -{ - igmpv3_query_header* hdr = getIgmpV3QueryHeader(); - hdr->checksum = 0; - hdr->checksum = htobe16(calculateChecksum()); -} + if (index < 0 || index > (int)sourceAddrCount - 1) + { + PCPP_LOG_ERROR("Cannot remove source address at index " << index << ", index is out of bounds"); + return false; + } -bool IgmpV3QueryLayer::addSourceAddress(const IPv4Address& addr) -{ - return addSourceAddressAtIndex(addr, getSourceAddressCount()); -} + size_t offset = sizeof(igmpv3_query_header) + index * sizeof(uint32_t); + if (offset >= getHeaderLen()) + { + PCPP_LOG_ERROR("Cannot remove source address at index " << index << ", index is out of packet bounds"); + return false; + } -bool IgmpV3QueryLayer::addSourceAddressAtIndex(const IPv4Address& addr, int index) -{ - uint16_t sourceAddrCount = getSourceAddressCount(); + if (!shortenLayer(offset, sizeof(uint32_t))) + { + PCPP_LOG_ERROR("Cannot remove source address at index " << index << ", didn't manage to shorten layer"); + return false; + } - if (index < 0 || index > (int)sourceAddrCount) - { - PCPP_LOG_ERROR("Cannot add source address at index " << index << ", index is out of bounds"); - return false; - } + getIgmpV3QueryHeader()->numOfSources = htobe16(sourceAddrCount - 1); - size_t offset = sizeof(igmpv3_query_header) + index * sizeof(uint32_t); - if (offset > getHeaderLen()) - { - PCPP_LOG_ERROR("Cannot add source address at index " << index << ", index is out of packet bounds"); - return false; + return true; } - if (!extendLayer(offset, sizeof(uint32_t))) + bool IgmpV3QueryLayer::removeAllSourceAddresses() { - PCPP_LOG_ERROR("Cannot add source address at index " << index << ", didn't manage to extend layer"); - return false; - } + size_t offset = sizeof(igmpv3_query_header); + size_t numOfBytesToShorted = getHeaderLen() - offset; - memcpy(m_Data + offset, addr.toBytes(), sizeof(uint32_t)); + if (!shortenLayer(offset, numOfBytesToShorted)) + { + PCPP_LOG_ERROR("Cannot remove all source addresses, didn't manage to shorten layer"); + return false; + } - getIgmpV3QueryHeader()->numOfSources = htobe16(sourceAddrCount+1); + getIgmpV3QueryHeader()->numOfSources = 0; - return true; -} + return true; + } -bool IgmpV3QueryLayer::removeSourceAddressAtIndex(int index) -{ - uint16_t sourceAddrCount = getSourceAddressCount(); + /******************* + * IgmpV3ReportLayer + *******************/ - if (index < 0 || index > (int)sourceAddrCount-1) + uint16_t IgmpV3ReportLayer::getGroupRecordCount() const { - PCPP_LOG_ERROR("Cannot remove source address at index " << index << ", index is out of bounds"); - return false; + return be16toh(getReportHeader()->numOfGroupRecords); } - size_t offset = sizeof(igmpv3_query_header) + index * sizeof(uint32_t); - if (offset >= getHeaderLen()) + igmpv3_group_record* IgmpV3ReportLayer::getFirstGroupRecord() const { - PCPP_LOG_ERROR("Cannot remove source address at index " << index << ", index is out of packet bounds"); - return false; + // check if there are group records at all + if (getHeaderLen() <= sizeof(igmpv3_report_header)) + return nullptr; + + uint8_t* curGroupPtr = m_Data + sizeof(igmpv3_report_header); + return (igmpv3_group_record*)curGroupPtr; } - if (!shortenLayer(offset, sizeof(uint32_t))) + igmpv3_group_record* IgmpV3ReportLayer::getNextGroupRecord(igmpv3_group_record* groupRecord) const { - PCPP_LOG_ERROR("Cannot remove source address at index " << index << ", didn't manage to shorten layer"); - return false; - } + if (groupRecord == nullptr) + return nullptr; - getIgmpV3QueryHeader()->numOfSources = htobe16(sourceAddrCount-1); + // prev group was the last group + if ((uint8_t*)groupRecord + groupRecord->getRecordLen() - m_Data >= (int)getHeaderLen()) + return nullptr; - return true; -} + igmpv3_group_record* nextGroup = (igmpv3_group_record*)((uint8_t*)groupRecord + groupRecord->getRecordLen()); -bool IgmpV3QueryLayer::removeAllSourceAddresses() -{ - size_t offset = sizeof(igmpv3_query_header); - size_t numOfBytesToShorted = getHeaderLen() - offset; + return nextGroup; + } - if (!shortenLayer(offset, numOfBytesToShorted)) + void IgmpV3ReportLayer::computeCalculateFields() { - PCPP_LOG_ERROR("Cannot remove all source addresses, didn't manage to shorten layer"); - return false; + igmpv3_report_header* hdr = getReportHeader(); + hdr->checksum = 0; + hdr->checksum = htobe16(calculateChecksum()); } - getIgmpV3QueryHeader()->numOfSources = 0; - - return true; -} - - - - - -/******************* - * IgmpV3ReportLayer - *******************/ - + igmpv3_group_record* IgmpV3ReportLayer::addGroupRecordAt(uint8_t recordType, const IPv4Address& multicastAddress, + const std::vector& sourceAddresses, + int offset) + { + if (offset > (int)getHeaderLen()) + { + PCPP_LOG_ERROR("Cannot add group record, offset is out of layer bounds"); + return nullptr; + } -uint16_t IgmpV3ReportLayer::getGroupRecordCount() const -{ - return be16toh(getReportHeader()->numOfGroupRecords); -} + size_t groupRecordSize = sizeof(igmpv3_group_record) + sizeof(uint32_t) * sourceAddresses.size(); -igmpv3_group_record* IgmpV3ReportLayer::getFirstGroupRecord() const -{ - // check if there are group records at all - if (getHeaderLen() <= sizeof(igmpv3_report_header)) - return nullptr; - - uint8_t* curGroupPtr = m_Data + sizeof(igmpv3_report_header); - return (igmpv3_group_record*)curGroupPtr; -} + if (!extendLayer(offset, groupRecordSize)) + { + PCPP_LOG_ERROR("Cannot add group record, cannot extend layer"); + return nullptr; + } -igmpv3_group_record* IgmpV3ReportLayer::getNextGroupRecord(igmpv3_group_record* groupRecord) const -{ - if (groupRecord == nullptr) - return nullptr; + uint8_t* groupRecordBuffer = new uint8_t[groupRecordSize]; + memset(groupRecordBuffer, 0, groupRecordSize); + igmpv3_group_record* newGroupRecord = (igmpv3_group_record*)groupRecordBuffer; + newGroupRecord->multicastAddress = multicastAddress.toInt(); + newGroupRecord->recordType = recordType; + newGroupRecord->auxDataLen = 0; + newGroupRecord->numOfSources = htobe16(sourceAddresses.size()); - // prev group was the last group - if ((uint8_t*)groupRecord + groupRecord->getRecordLen() - m_Data >= (int)getHeaderLen()) - return nullptr; + int srcAddrOffset = 0; + for (const auto& address : sourceAddresses) + { + memcpy(newGroupRecord->sourceAddresses + srcAddrOffset, address.toBytes(), sizeof(uint32_t)); + srcAddrOffset += sizeof(uint32_t); + } - igmpv3_group_record* nextGroup = (igmpv3_group_record*)((uint8_t*)groupRecord + groupRecord->getRecordLen()); + memcpy(m_Data + offset, groupRecordBuffer, groupRecordSize); - return nextGroup; -} + delete[] groupRecordBuffer; -void IgmpV3ReportLayer::computeCalculateFields() -{ - igmpv3_report_header* hdr = getReportHeader(); - hdr->checksum = 0; - hdr->checksum = htobe16(calculateChecksum()); -} + getReportHeader()->numOfGroupRecords = htobe16(getGroupRecordCount() + 1); -igmpv3_group_record* IgmpV3ReportLayer::addGroupRecordAt(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector& sourceAddresses, int offset) -{ - if (offset > (int)getHeaderLen()) - { - PCPP_LOG_ERROR("Cannot add group record, offset is out of layer bounds"); - return nullptr; + return (igmpv3_group_record*)(m_Data + offset); } - size_t groupRecordSize = sizeof(igmpv3_group_record) + sizeof(uint32_t)*sourceAddresses.size(); - - if (!extendLayer(offset, groupRecordSize)) + igmpv3_group_record* IgmpV3ReportLayer::addGroupRecord(uint8_t recordType, const IPv4Address& multicastAddress, + const std::vector& sourceAddresses) { - PCPP_LOG_ERROR("Cannot add group record, cannot extend layer"); - return nullptr; + return addGroupRecordAt(recordType, multicastAddress, sourceAddresses, (int)getHeaderLen()); } - uint8_t* groupRecordBuffer = new uint8_t[groupRecordSize]; - memset(groupRecordBuffer, 0, groupRecordSize); - igmpv3_group_record* newGroupRecord = (igmpv3_group_record*)groupRecordBuffer; - newGroupRecord->multicastAddress = multicastAddress.toInt(); - newGroupRecord->recordType = recordType; - newGroupRecord->auxDataLen = 0; - newGroupRecord->numOfSources = htobe16(sourceAddresses.size()); - - int srcAddrOffset = 0; - for (const auto &address : sourceAddresses) + igmpv3_group_record* IgmpV3ReportLayer::addGroupRecordAtIndex(uint8_t recordType, + const IPv4Address& multicastAddress, + const std::vector& sourceAddresses, + int index) { - memcpy(newGroupRecord->sourceAddresses + srcAddrOffset, address.toBytes(), sizeof(uint32_t)); - srcAddrOffset += sizeof(uint32_t); - } - - memcpy(m_Data + offset, groupRecordBuffer, groupRecordSize); - - delete[] groupRecordBuffer; - - getReportHeader()->numOfGroupRecords = htobe16(getGroupRecordCount() + 1); + int groupCnt = (int)getGroupRecordCount(); - return (igmpv3_group_record*)(m_Data + offset); -} - -igmpv3_group_record* IgmpV3ReportLayer::addGroupRecord(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector& sourceAddresses) -{ - return addGroupRecordAt(recordType, multicastAddress, sourceAddresses, (int)getHeaderLen()); -} - -igmpv3_group_record* IgmpV3ReportLayer::addGroupRecordAtIndex(uint8_t recordType, const IPv4Address& multicastAddress, const std::vector& sourceAddresses, int index) -{ - int groupCnt = (int)getGroupRecordCount(); - - if (index < 0 || index > groupCnt) - { - PCPP_LOG_ERROR("Cannot add group record, index " << index << " out of bounds"); - return nullptr; - } + if (index < 0 || index > groupCnt) + { + PCPP_LOG_ERROR("Cannot add group record, index " << index << " out of bounds"); + return nullptr; + } - size_t offset = sizeof(igmpv3_report_header); + size_t offset = sizeof(igmpv3_report_header); - igmpv3_group_record* curRecord = getFirstGroupRecord(); - for (int i = 0; i < index; i++) - { - if (curRecord == nullptr) + igmpv3_group_record* curRecord = getFirstGroupRecord(); + for (int i = 0; i < index; i++) { - PCPP_LOG_ERROR("Cannot add group record, cannot find group record at index " << i); - return nullptr; + if (curRecord == nullptr) + { + PCPP_LOG_ERROR("Cannot add group record, cannot find group record at index " << i); + return nullptr; + } + + offset += curRecord->getRecordLen(); + curRecord = getNextGroupRecord(curRecord); } - offset += curRecord->getRecordLen(); - curRecord = getNextGroupRecord(curRecord); + return addGroupRecordAt(recordType, multicastAddress, sourceAddresses, (int)offset); } - return addGroupRecordAt(recordType, multicastAddress, sourceAddresses, (int)offset); -} + bool IgmpV3ReportLayer::removeGroupRecordAtIndex(int index) + { + int groupCnt = (int)getGroupRecordCount(); -bool IgmpV3ReportLayer::removeGroupRecordAtIndex(int index) -{ - int groupCnt = (int)getGroupRecordCount(); + if (index < 0 || index >= groupCnt) + { + PCPP_LOG_ERROR("Cannot remove group record, index " << index << " is out of bounds"); + return false; + } - if (index < 0 || index >= groupCnt) - { - PCPP_LOG_ERROR("Cannot remove group record, index " << index << " is out of bounds"); - return false; - } + size_t offset = sizeof(igmpv3_report_header); - size_t offset = sizeof(igmpv3_report_header); + igmpv3_group_record* curRecord = getFirstGroupRecord(); + for (int i = 0; i < index; i++) + { + if (curRecord == nullptr) + { + PCPP_LOG_ERROR("Cannot remove group record at index " << index << ", cannot find group record at index " + << i); + return false; + } + + offset += curRecord->getRecordLen(); + curRecord = getNextGroupRecord(curRecord); + } - igmpv3_group_record* curRecord = getFirstGroupRecord(); - for (int i = 0; i < index; i++) - { - if (curRecord == nullptr) + if (!shortenLayer((int)offset, curRecord->getRecordLen())) { - PCPP_LOG_ERROR("Cannot remove group record at index " << index << ", cannot find group record at index " << i); + PCPP_LOG_ERROR("Cannot remove group record at index " << index << ", cannot shorted layer"); return false; } - offset += curRecord->getRecordLen(); - curRecord = getNextGroupRecord(curRecord); + getReportHeader()->numOfGroupRecords = htobe16(groupCnt - 1); + + return true; } - if (!shortenLayer((int)offset, curRecord->getRecordLen())) + bool IgmpV3ReportLayer::removeAllGroupRecords() { - PCPP_LOG_ERROR("Cannot remove group record at index " << index << ", cannot shorted layer"); - return false; - } + int offset = (int)sizeof(igmpv3_report_header); - getReportHeader()->numOfGroupRecords = htobe16(groupCnt-1); + if (!shortenLayer(offset, getHeaderLen() - offset)) + { + PCPP_LOG_ERROR("Cannot remove all group records, cannot shorted layer"); + return false; + } - return true; -} + getReportHeader()->numOfGroupRecords = 0; + return true; + } -bool IgmpV3ReportLayer::removeAllGroupRecords() -{ - int offset = (int)sizeof(igmpv3_report_header); + /********************* + * igmpv3_group_record + *********************/ - if (!shortenLayer(offset, getHeaderLen()-offset)) + uint16_t igmpv3_group_record::getSourceAddressCount() const { - PCPP_LOG_ERROR("Cannot remove all group records, cannot shorted layer"); - return false; + return be16toh(numOfSources); } - getReportHeader()->numOfGroupRecords = 0; - return true; -} - - - - - - -/********************* - * igmpv3_group_record - *********************/ - -uint16_t igmpv3_group_record::getSourceAddressCount() const -{ - return be16toh(numOfSources); -} - -IPv4Address igmpv3_group_record::getSourceAddressAtIndex(int index) const -{ - uint16_t numOfRecords = getSourceAddressCount(); - if (index < 0 || index >= numOfRecords) - return IPv4Address(); + IPv4Address igmpv3_group_record::getSourceAddressAtIndex(int index) const + { + uint16_t numOfRecords = getSourceAddressCount(); + if (index < 0 || index >= numOfRecords) + return IPv4Address(); - int offset = index * sizeof(uint32_t); - const uint8_t* ptr = sourceAddresses + offset; - return IPv4Address(*(uint32_t*)ptr); -} + int offset = index * sizeof(uint32_t); + const uint8_t* ptr = sourceAddresses + offset; + return IPv4Address(*(uint32_t*)ptr); + } -size_t igmpv3_group_record::getRecordLen() const -{ - uint16_t numOfRecords = getSourceAddressCount(); + size_t igmpv3_group_record::getRecordLen() const + { + uint16_t numOfRecords = getSourceAddressCount(); - int headerLen = numOfRecords * sizeof(uint32_t) + sizeof(igmpv3_group_record); - return (size_t)headerLen; -} + int headerLen = numOfRecords * sizeof(uint32_t) + sizeof(igmpv3_group_record); + return (size_t)headerLen; + } -} +} // namespace pcpp diff --git a/Packet++/src/LLCLayer.cpp b/Packet++/src/LLCLayer.cpp index a533466cae..f0a71c0703 100644 --- a/Packet++/src/LLCLayer.cpp +++ b/Packet++/src/LLCLayer.cpp @@ -8,48 +8,48 @@ namespace pcpp { -LLCLayer::LLCLayer(uint8_t dsap, uint8_t ssap, uint8_t control) -{ - m_DataLen = sizeof(llc_header); - m_Data = new uint8_t[sizeof(llc_header)]; - memset(m_Data, 0, sizeof(llc_header)); - - m_Protocol = LLC; - - // Set values - llc_header* header = getLlcHeader(); - header->dsap = dsap; - header->ssap = ssap; - header->control = control; -} + LLCLayer::LLCLayer(uint8_t dsap, uint8_t ssap, uint8_t control) + { + m_DataLen = sizeof(llc_header); + m_Data = new uint8_t[sizeof(llc_header)]; + memset(m_Data, 0, sizeof(llc_header)); -void LLCLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(llc_header)) - return; + m_Protocol = LLC; - llc_header *hdr = getLlcHeader(); - uint8_t *payload = m_Data + sizeof(llc_header); - size_t payloadLen = m_DataLen - sizeof(llc_header); + // Set values + llc_header* header = getLlcHeader(); + header->dsap = dsap; + header->ssap = ssap; + header->control = control; + } - if (hdr->dsap == 0x42 && hdr->ssap == 0x42 && StpLayer::isDataValid(payload, payloadLen)) + void LLCLayer::parseNextLayer() { - m_NextLayer = StpLayer::parseStpLayer(payload, payloadLen, this, m_Packet); - if (!m_NextLayer) - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - return; + if (m_DataLen <= sizeof(llc_header)) + return; + + llc_header* hdr = getLlcHeader(); + uint8_t* payload = m_Data + sizeof(llc_header); + size_t payloadLen = m_DataLen - sizeof(llc_header); + + if (hdr->dsap == 0x42 && hdr->ssap == 0x42 && StpLayer::isDataValid(payload, payloadLen)) + { + m_NextLayer = StpLayer::parseStpLayer(payload, payloadLen, this, m_Packet); + if (!m_NextLayer) + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + return; + } + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); -} -std::string LLCLayer::toString() const -{ - return "Logical Link Control"; -} + std::string LLCLayer::toString() const + { + return "Logical Link Control"; + } -bool LLCLayer::isDataValid(const uint8_t *data, size_t dataLen) -{ - return dataLen >= sizeof(llc_header) && !(data[0] == 0xFF && data[1] == 0xFF); -} + bool LLCLayer::isDataValid(const uint8_t* data, size_t dataLen) + { + return dataLen >= sizeof(llc_header) && !(data[0] == 0xFF && data[1] == 0xFF); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/Layer.cpp b/Packet++/src/Layer.cpp index c007b6ccda..5820b61daa 100644 --- a/Packet++/src/Layer.cpp +++ b/Packet++/src/Layer.cpp @@ -8,109 +8,110 @@ namespace pcpp { -Layer::~Layer() -{ - if (!isAllocatedToPacket()) - delete [] m_Data; -} - -Layer::Layer(const Layer& other) : m_Packet(nullptr), m_Protocol(other.m_Protocol), m_NextLayer(nullptr), m_PrevLayer(nullptr), m_IsAllocatedInPacket(false) -{ - m_DataLen = other.getHeaderLen(); - m_Data = new uint8_t[other.m_DataLen]; - memcpy(m_Data, other.m_Data, other.m_DataLen); -} - -Layer& Layer::operator=(const Layer& other) -{ - if (this == &other) - return *this; + Layer::~Layer() + { + if (!isAllocatedToPacket()) + delete[] m_Data; + } - if (m_Data != nullptr) - delete [] m_Data; + Layer::Layer(const Layer& other) + : m_Packet(nullptr), m_Protocol(other.m_Protocol), m_NextLayer(nullptr), m_PrevLayer(nullptr), + m_IsAllocatedInPacket(false) + { + m_DataLen = other.getHeaderLen(); + m_Data = new uint8_t[other.m_DataLen]; + memcpy(m_Data, other.m_Data, other.m_DataLen); + } - m_DataLen = other.getHeaderLen(); - m_Packet = nullptr; - m_Protocol = other.m_Protocol; - m_NextLayer = nullptr; - m_PrevLayer = nullptr; - m_Data = new uint8_t[other.m_DataLen]; - m_IsAllocatedInPacket = false; - memcpy(m_Data, other.m_Data, other.m_DataLen); + Layer& Layer::operator=(const Layer& other) + { + if (this == &other) + return *this; - return *this; -} + if (m_Data != nullptr) + delete[] m_Data; -bool Layer::isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const -{ - auto protocolToFamily = static_cast(m_Protocol); - return (m_Protocol != UnknownProtocol && - (protocolToFamily == (protocolTypeFamily & 0xff) || - protocolToFamily << 8 == (protocolTypeFamily & 0xff00) || - protocolToFamily << 16 == (protocolTypeFamily & 0xff0000) || - protocolToFamily << 24 == (protocolTypeFamily & 0xff000000))); -} + m_DataLen = other.getHeaderLen(); + m_Packet = nullptr; + m_Protocol = other.m_Protocol; + m_NextLayer = nullptr; + m_PrevLayer = nullptr; + m_Data = new uint8_t[other.m_DataLen]; + m_IsAllocatedInPacket = false; + memcpy(m_Data, other.m_Data, other.m_DataLen); + return *this; + } -void Layer::copyData(uint8_t* toArr) const -{ - memcpy(toArr, m_Data, m_DataLen); -} + bool Layer::isMemberOfProtocolFamily(ProtocolTypeFamily protocolTypeFamily) const + { + auto protocolToFamily = static_cast(m_Protocol); + return (m_Protocol != UnknownProtocol && (protocolToFamily == (protocolTypeFamily & 0xff) || + protocolToFamily << 8 == (protocolTypeFamily & 0xff00) || + protocolToFamily << 16 == (protocolTypeFamily & 0xff0000) || + protocolToFamily << 24 == (protocolTypeFamily & 0xff000000))); + } -bool Layer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend) -{ - if (m_Data == nullptr) + void Layer::copyData(uint8_t* toArr) const { - PCPP_LOG_ERROR("Layer's data is NULL"); - return false; + memcpy(toArr, m_Data, m_DataLen); } - if (m_Packet == nullptr) + bool Layer::extendLayer(int offsetInLayer, size_t numOfBytesToExtend) { - if ((size_t)offsetInLayer > m_DataLen) + if (m_Data == nullptr) { - PCPP_LOG_ERROR("Requested offset is larger than data length"); + PCPP_LOG_ERROR("Layer's data is NULL"); return false; } - uint8_t* newData = new uint8_t[m_DataLen + numOfBytesToExtend]; - memcpy(newData, m_Data, offsetInLayer); - memcpy(newData + offsetInLayer + numOfBytesToExtend, m_Data + offsetInLayer, m_DataLen - offsetInLayer); - delete [] m_Data; - m_Data = newData; - m_DataLen += numOfBytesToExtend; - return true; - } - - return m_Packet->extendLayer(this, offsetInLayer, numOfBytesToExtend); -} + if (m_Packet == nullptr) + { + if ((size_t)offsetInLayer > m_DataLen) + { + PCPP_LOG_ERROR("Requested offset is larger than data length"); + return false; + } + + uint8_t* newData = new uint8_t[m_DataLen + numOfBytesToExtend]; + memcpy(newData, m_Data, offsetInLayer); + memcpy(newData + offsetInLayer + numOfBytesToExtend, m_Data + offsetInLayer, m_DataLen - offsetInLayer); + delete[] m_Data; + m_Data = newData; + m_DataLen += numOfBytesToExtend; + return true; + } -bool Layer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten) -{ - if (m_Data == nullptr) - { - PCPP_LOG_ERROR("Layer's data is NULL"); - return false; + return m_Packet->extendLayer(this, offsetInLayer, numOfBytesToExtend); } - if (m_Packet == nullptr) + bool Layer::shortenLayer(int offsetInLayer, size_t numOfBytesToShorten) { - if ((size_t)offsetInLayer >= m_DataLen) + if (m_Data == nullptr) { - PCPP_LOG_ERROR("Requested offset is larger than data length"); + PCPP_LOG_ERROR("Layer's data is NULL"); return false; } - uint8_t* newData = new uint8_t[m_DataLen - numOfBytesToShorten]; - memcpy(newData, m_Data, offsetInLayer); - memcpy(newData + offsetInLayer, m_Data + offsetInLayer + numOfBytesToShorten, m_DataLen - offsetInLayer - numOfBytesToShorten); - delete [] m_Data; - m_Data = newData; - m_DataLen -= numOfBytesToShorten; - return true; - } + if (m_Packet == nullptr) + { + if ((size_t)offsetInLayer >= m_DataLen) + { + PCPP_LOG_ERROR("Requested offset is larger than data length"); + return false; + } + + uint8_t* newData = new uint8_t[m_DataLen - numOfBytesToShorten]; + memcpy(newData, m_Data, offsetInLayer); + memcpy(newData + offsetInLayer, m_Data + offsetInLayer + numOfBytesToShorten, + m_DataLen - offsetInLayer - numOfBytesToShorten); + delete[] m_Data; + m_Data = newData; + m_DataLen -= numOfBytesToShorten; + return true; + } - return m_Packet->shortenLayer(this, offsetInLayer, numOfBytesToShorten); -} + return m_Packet->shortenLayer(this, offsetInLayer, numOfBytesToShorten); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/LdapLayer.cpp b/Packet++/src/LdapLayer.cpp index fd2f9bd10d..470f2aeda3 100644 --- a/Packet++/src/LdapLayer.cpp +++ b/Packet++/src/LdapLayer.cpp @@ -2,56 +2,59 @@ #include "GeneralUtils.h" #include -namespace pcpp { +namespace pcpp +{ // region LdapOperationType + // clang-format off static const std::unordered_map> LdapOperationTypeToString{ - {LdapOperationType::BindRequest, "BindRequest"}, - {LdapOperationType::BindResponse, "BindResponse"}, - {LdapOperationType::UnbindRequest, "UnbindRequest"}, - {LdapOperationType::SearchRequest, "SearchRequest"}, - {LdapOperationType::SearchResultEntry, "SearchResultEntry"}, - {LdapOperationType::SearchResultDone, "SearchResultDone"}, - {LdapOperationType::ModifyRequest, "ModifyRequest"}, - {LdapOperationType::ModifyResponse, "ModifyResponse"}, - {LdapOperationType::AddRequest, "AddRequest"}, - {LdapOperationType::AddResponse, "AddResponse"}, - {LdapOperationType::DeleteRequest, "DeleteRequest"}, - {LdapOperationType::DeleteResponse, "DeleteResponse"}, - {LdapOperationType::ModifyDNRequest, "ModifyDNRequest"}, - {LdapOperationType::ModifyDNResponse, "ModifyDNResponse"}, - {LdapOperationType::CompareRequest, "CompareRequest"}, - {LdapOperationType::CompareResponse, "CompareResponse"}, - {LdapOperationType::AbandonRequest, "AbandonRequest"}, - {LdapOperationType::SearchResultReference, "SearchResultReference"}, - {LdapOperationType::ExtendedRequest, "ExtendedRequest"}, - {LdapOperationType::ExtendedResponse, "ExtendedResponse"}, - {LdapOperationType::IntermediateResponse, "IntermediateResponse"}, - {LdapOperationType::Unknown, "Unknown"} + { LdapOperationType::BindRequest, "BindRequest" }, + { LdapOperationType::BindResponse, "BindResponse" }, + { LdapOperationType::UnbindRequest, "UnbindRequest" }, + { LdapOperationType::SearchRequest, "SearchRequest" }, + { LdapOperationType::SearchResultEntry, "SearchResultEntry" }, + { LdapOperationType::SearchResultDone, "SearchResultDone" }, + { LdapOperationType::ModifyRequest, "ModifyRequest" }, + { LdapOperationType::ModifyResponse, "ModifyResponse" }, + { LdapOperationType::AddRequest, "AddRequest" }, + { LdapOperationType::AddResponse, "AddResponse" }, + { LdapOperationType::DeleteRequest, "DeleteRequest" }, + { LdapOperationType::DeleteResponse, "DeleteResponse" }, + { LdapOperationType::ModifyDNRequest, "ModifyDNRequest" }, + { LdapOperationType::ModifyDNResponse, "ModifyDNResponse" }, + { LdapOperationType::CompareRequest, "CompareRequest" }, + { LdapOperationType::CompareResponse, "CompareResponse" }, + { LdapOperationType::AbandonRequest, "AbandonRequest" }, + { LdapOperationType::SearchResultReference, "SearchResultReference" }, + { LdapOperationType::ExtendedRequest, "ExtendedRequest" }, + { LdapOperationType::ExtendedResponse, "ExtendedResponse" }, + { LdapOperationType::IntermediateResponse, "IntermediateResponse" }, + { LdapOperationType::Unknown, "Unknown" } }; + // clang-format on static const std::unordered_map UintToLdapOperationType{ - {static_cast(LdapOperationType::BindRequest), LdapOperationType::BindRequest}, - {static_cast(LdapOperationType::BindResponse), LdapOperationType::BindResponse}, - {static_cast(LdapOperationType::UnbindRequest), LdapOperationType::UnbindRequest}, - {static_cast(LdapOperationType::SearchRequest), LdapOperationType::SearchRequest}, - {static_cast(LdapOperationType::SearchResultEntry), LdapOperationType::SearchResultEntry}, - {static_cast(LdapOperationType::SearchResultDone), LdapOperationType::SearchResultDone}, - {static_cast(LdapOperationType::ModifyResponse), LdapOperationType::ModifyResponse}, - {static_cast(LdapOperationType::AddRequest), LdapOperationType::AddRequest}, - {static_cast(LdapOperationType::AddResponse), LdapOperationType::AddResponse}, - {static_cast(LdapOperationType::DeleteRequest), LdapOperationType::DeleteRequest}, - {static_cast(LdapOperationType::DeleteResponse), LdapOperationType::DeleteResponse}, - {static_cast(LdapOperationType::ModifyDNRequest), LdapOperationType::ModifyDNRequest}, - {static_cast(LdapOperationType::ModifyDNResponse), LdapOperationType::ModifyDNResponse}, - {static_cast(LdapOperationType::CompareRequest), LdapOperationType::CompareRequest}, - {static_cast(LdapOperationType::CompareResponse), LdapOperationType::CompareResponse}, - {static_cast(LdapOperationType::AbandonRequest), LdapOperationType::AbandonRequest}, - {static_cast(LdapOperationType::SearchResultReference), LdapOperationType::SearchResultReference}, - {static_cast(LdapOperationType::ExtendedRequest), LdapOperationType::ExtendedRequest}, - {static_cast(LdapOperationType::ExtendedResponse), LdapOperationType::ExtendedResponse}, - {static_cast(LdapOperationType::IntermediateResponse), LdapOperationType::IntermediateResponse} + { static_cast(LdapOperationType::BindRequest), LdapOperationType::BindRequest }, + { static_cast(LdapOperationType::BindResponse), LdapOperationType::BindResponse }, + { static_cast(LdapOperationType::UnbindRequest), LdapOperationType::UnbindRequest }, + { static_cast(LdapOperationType::SearchRequest), LdapOperationType::SearchRequest }, + { static_cast(LdapOperationType::SearchResultEntry), LdapOperationType::SearchResultEntry }, + { static_cast(LdapOperationType::SearchResultDone), LdapOperationType::SearchResultDone }, + { static_cast(LdapOperationType::ModifyResponse), LdapOperationType::ModifyResponse }, + { static_cast(LdapOperationType::AddRequest), LdapOperationType::AddRequest }, + { static_cast(LdapOperationType::AddResponse), LdapOperationType::AddResponse }, + { static_cast(LdapOperationType::DeleteRequest), LdapOperationType::DeleteRequest }, + { static_cast(LdapOperationType::DeleteResponse), LdapOperationType::DeleteResponse }, + { static_cast(LdapOperationType::ModifyDNRequest), LdapOperationType::ModifyDNRequest }, + { static_cast(LdapOperationType::ModifyDNResponse), LdapOperationType::ModifyDNResponse }, + { static_cast(LdapOperationType::CompareRequest), LdapOperationType::CompareRequest }, + { static_cast(LdapOperationType::CompareResponse), LdapOperationType::CompareResponse }, + { static_cast(LdapOperationType::AbandonRequest), LdapOperationType::AbandonRequest }, + { static_cast(LdapOperationType::SearchResultReference), LdapOperationType::SearchResultReference }, + { static_cast(LdapOperationType::ExtendedRequest), LdapOperationType::ExtendedRequest }, + { static_cast(LdapOperationType::ExtendedResponse), LdapOperationType::ExtendedResponse }, + { static_cast(LdapOperationType::IntermediateResponse), LdapOperationType::IntermediateResponse } }; std::string LdapOperationType::toString() const @@ -74,89 +77,93 @@ namespace pcpp { // region LdapResultCode + // clang-format off static const std::unordered_map> LdapResultCodeToString{ - {LdapResultCode::Success, "Success"}, - {LdapResultCode::OperationsError, "OperationsError"}, - {LdapResultCode::ProtocolError, "ProtocolError"}, - {LdapResultCode::TimeLimitExceeded, "TimeLimitExceeded"}, - {LdapResultCode::SizeLimitExceeded, "SizeLimitExceeded"}, - {LdapResultCode::CompareFalse, "CompareFalse"}, - {LdapResultCode::CompareTrue, "CompareTrue"}, - {LdapResultCode::AuthMethodNotSupported, "AuthMethodNotSupported"}, - {LdapResultCode::StrongerAuthRequired, "StrongerAuthRequired"}, - {LdapResultCode::Referral, "Referral"}, - {LdapResultCode::AdminLimitExceeded, "AdminLimitExceeded"}, - {LdapResultCode::UnavailableCriticalExtension, "UnavailableCriticalExtension"}, - {LdapResultCode::ConfidentialityRequired, "ConfidentialityRequired"}, - {LdapResultCode::SaslBindInProgress, "SaslBindInProgress"}, - {LdapResultCode::NoSuchAttribute, "NoSuchAttribute"}, - {LdapResultCode::UndefinedAttributeType, "UndefinedAttributeType"}, - {LdapResultCode::InappropriateMatching, "InappropriateMatching"}, - {LdapResultCode::ConstraintViolation, "ConstraintViolation"}, - {LdapResultCode::AttributeOrValueExists, "AttributeOrValueExists"}, - {LdapResultCode::InvalidAttributeSyntax, "InvalidAttributeSyntax"}, - {LdapResultCode::NoSuchObject, "NoSuchObject"}, - {LdapResultCode::AliasProblem, "AliasProblem"}, - {LdapResultCode::InvalidDNSyntax, "InvalidDNSyntax"}, - {LdapResultCode::AliasDereferencingProblem, "AliasDereferencingProblem"}, - {LdapResultCode::InappropriateAuthentication, "InappropriateAuthentication"}, - {LdapResultCode::InvalidCredentials, "InvalidCredentials"}, - {LdapResultCode::InsufficientAccessRights, "InsufficientAccessRights"}, - {LdapResultCode::Busy, "Busy"}, - {LdapResultCode::Unavailable, "Unavailable"}, - {LdapResultCode::UnwillingToPerform, "UnwillingToPerform"}, - {LdapResultCode::LoopDetect, "LoopDetect"}, - {LdapResultCode::NamingViolation, "NamingViolation"}, - {LdapResultCode::ObjectClassViolation, "ObjectClassViolation"}, - {LdapResultCode::NotAllowedOnNonLeaf, "NotAllowedOnNonLeaf"}, - {LdapResultCode::NotAllowedOnRDN, "NotAllowedOnRDN"}, - {LdapResultCode::EntryAlreadyExists, "EntryAlreadyExists"}, - {LdapResultCode::ObjectClassModsProhibited, "ObjectClassModsProhibited"}, - {LdapResultCode::AffectsMultipleDSAs, "AffectsMultipleDSAs"}, - {LdapResultCode::Other, "Other"} - }; - + { LdapResultCode::Success, "Success" }, + { LdapResultCode::OperationsError, "OperationsError" }, + { LdapResultCode::ProtocolError, "ProtocolError" }, + { LdapResultCode::TimeLimitExceeded, "TimeLimitExceeded" }, + { LdapResultCode::SizeLimitExceeded, "SizeLimitExceeded" }, + { LdapResultCode::CompareFalse, "CompareFalse" }, + { LdapResultCode::CompareTrue, "CompareTrue" }, + { LdapResultCode::AuthMethodNotSupported, "AuthMethodNotSupported" }, + { LdapResultCode::StrongerAuthRequired, "StrongerAuthRequired" }, + { LdapResultCode::Referral, "Referral" }, + { LdapResultCode::AdminLimitExceeded, "AdminLimitExceeded" }, + { LdapResultCode::UnavailableCriticalExtension, "UnavailableCriticalExtension" }, + { LdapResultCode::ConfidentialityRequired, "ConfidentialityRequired" }, + { LdapResultCode::SaslBindInProgress, "SaslBindInProgress" }, + { LdapResultCode::NoSuchAttribute, "NoSuchAttribute" }, + { LdapResultCode::UndefinedAttributeType, "UndefinedAttributeType" }, + { LdapResultCode::InappropriateMatching, "InappropriateMatching" }, + { LdapResultCode::ConstraintViolation, "ConstraintViolation" }, + { LdapResultCode::AttributeOrValueExists, "AttributeOrValueExists" }, + { LdapResultCode::InvalidAttributeSyntax, "InvalidAttributeSyntax" }, + { LdapResultCode::NoSuchObject, "NoSuchObject" }, + { LdapResultCode::AliasProblem, "AliasProblem" }, + { LdapResultCode::InvalidDNSyntax, "InvalidDNSyntax" }, + { LdapResultCode::AliasDereferencingProblem, "AliasDereferencingProblem" }, + { LdapResultCode::InappropriateAuthentication, "InappropriateAuthentication" }, + { LdapResultCode::InvalidCredentials, "InvalidCredentials" }, + { LdapResultCode::InsufficientAccessRights, "InsufficientAccessRights" }, + { LdapResultCode::Busy, "Busy" }, + { LdapResultCode::Unavailable, "Unavailable" }, + { LdapResultCode::UnwillingToPerform, "UnwillingToPerform" }, + { LdapResultCode::LoopDetect, "LoopDetect" }, + { LdapResultCode::NamingViolation, "NamingViolation" }, + { LdapResultCode::ObjectClassViolation, "ObjectClassViolation" }, + { LdapResultCode::NotAllowedOnNonLeaf, "NotAllowedOnNonLeaf" }, + { LdapResultCode::NotAllowedOnRDN, "NotAllowedOnRDN" }, + { LdapResultCode::EntryAlreadyExists, "EntryAlreadyExists" }, + { LdapResultCode::ObjectClassModsProhibited, "ObjectClassModsProhibited" }, + { LdapResultCode::AffectsMultipleDSAs, "AffectsMultipleDSAs" }, + { LdapResultCode::Other, "Other" } + }; + // clang-format on + + // clang-format off static const std::unordered_map UintToLdapResultCode{ - {static_cast(LdapResultCode::Success), LdapResultCode::Success}, - {static_cast(LdapResultCode::OperationsError), LdapResultCode::OperationsError}, - {static_cast(LdapResultCode::ProtocolError), LdapResultCode::ProtocolError}, - {static_cast(LdapResultCode::TimeLimitExceeded), LdapResultCode::TimeLimitExceeded}, - {static_cast(LdapResultCode::SizeLimitExceeded), LdapResultCode::SizeLimitExceeded}, - {static_cast(LdapResultCode::CompareFalse), LdapResultCode::CompareFalse}, - {static_cast(LdapResultCode::CompareTrue), LdapResultCode::CompareTrue}, - {static_cast(LdapResultCode::AuthMethodNotSupported), LdapResultCode::AuthMethodNotSupported}, - {static_cast(LdapResultCode::StrongerAuthRequired), LdapResultCode::StrongerAuthRequired}, - {static_cast(LdapResultCode::Referral), LdapResultCode::Referral}, - {static_cast(LdapResultCode::AdminLimitExceeded), LdapResultCode::AdminLimitExceeded}, - {static_cast(LdapResultCode::UnavailableCriticalExtension), LdapResultCode::UnavailableCriticalExtension}, - {static_cast(LdapResultCode::ConfidentialityRequired), LdapResultCode::ConfidentialityRequired}, - {static_cast(LdapResultCode::SaslBindInProgress), LdapResultCode::SaslBindInProgress}, - {static_cast(LdapResultCode::NoSuchAttribute), LdapResultCode::NoSuchAttribute}, - {static_cast(LdapResultCode::UndefinedAttributeType), LdapResultCode::UndefinedAttributeType}, - {static_cast(LdapResultCode::InappropriateMatching), LdapResultCode::InappropriateMatching}, - {static_cast(LdapResultCode::ConstraintViolation), LdapResultCode::ConstraintViolation}, - {static_cast(LdapResultCode::AttributeOrValueExists), LdapResultCode::AttributeOrValueExists}, - {static_cast(LdapResultCode::InvalidAttributeSyntax), LdapResultCode::InvalidAttributeSyntax}, - {static_cast(LdapResultCode::NoSuchObject), LdapResultCode::NoSuchObject}, - {static_cast(LdapResultCode::AliasProblem), LdapResultCode::AliasProblem}, - {static_cast(LdapResultCode::InvalidDNSyntax), LdapResultCode::InvalidDNSyntax}, - {static_cast(LdapResultCode::AliasDereferencingProblem), LdapResultCode::AliasDereferencingProblem}, - {static_cast(LdapResultCode::InappropriateAuthentication), LdapResultCode::InappropriateAuthentication}, - {static_cast(LdapResultCode::InvalidCredentials), LdapResultCode::InvalidCredentials}, - {static_cast(LdapResultCode::InsufficientAccessRights), LdapResultCode::InsufficientAccessRights}, - {static_cast(LdapResultCode::Busy), LdapResultCode::Busy}, - {static_cast(LdapResultCode::Unavailable), LdapResultCode::Unavailable}, - {static_cast(LdapResultCode::UnwillingToPerform), LdapResultCode::UnwillingToPerform}, - {static_cast(LdapResultCode::LoopDetect), LdapResultCode::LoopDetect}, - {static_cast(LdapResultCode::NamingViolation), LdapResultCode::NamingViolation}, - {static_cast(LdapResultCode::ObjectClassViolation), LdapResultCode::ObjectClassViolation}, - {static_cast(LdapResultCode::NotAllowedOnNonLeaf), LdapResultCode::NotAllowedOnNonLeaf}, - {static_cast(LdapResultCode::NotAllowedOnRDN), LdapResultCode::NotAllowedOnRDN}, - {static_cast(LdapResultCode::EntryAlreadyExists), LdapResultCode::EntryAlreadyExists}, - {static_cast(LdapResultCode::ObjectClassModsProhibited), LdapResultCode::ObjectClassModsProhibited}, - {static_cast(LdapResultCode::AffectsMultipleDSAs), LdapResultCode::AffectsMultipleDSAs}, - {static_cast(LdapResultCode::Other), LdapResultCode::Other} + { static_cast(LdapResultCode::Success), LdapResultCode::Success }, + { static_cast(LdapResultCode::OperationsError), LdapResultCode::OperationsError }, + { static_cast(LdapResultCode::ProtocolError), LdapResultCode::ProtocolError }, + { static_cast(LdapResultCode::TimeLimitExceeded), LdapResultCode::TimeLimitExceeded }, + { static_cast(LdapResultCode::SizeLimitExceeded), LdapResultCode::SizeLimitExceeded }, + { static_cast(LdapResultCode::CompareFalse), LdapResultCode::CompareFalse }, + { static_cast(LdapResultCode::CompareTrue), LdapResultCode::CompareTrue }, + { static_cast(LdapResultCode::AuthMethodNotSupported), LdapResultCode::AuthMethodNotSupported }, + { static_cast(LdapResultCode::StrongerAuthRequired), LdapResultCode::StrongerAuthRequired }, + { static_cast(LdapResultCode::Referral), LdapResultCode::Referral }, + { static_cast(LdapResultCode::AdminLimitExceeded), LdapResultCode::AdminLimitExceeded }, + { static_cast(LdapResultCode::UnavailableCriticalExtension), LdapResultCode::UnavailableCriticalExtension }, + { static_cast(LdapResultCode::ConfidentialityRequired), LdapResultCode::ConfidentialityRequired }, + { static_cast(LdapResultCode::SaslBindInProgress), LdapResultCode::SaslBindInProgress }, + { static_cast(LdapResultCode::NoSuchAttribute), LdapResultCode::NoSuchAttribute }, + { static_cast(LdapResultCode::UndefinedAttributeType), LdapResultCode::UndefinedAttributeType }, + { static_cast(LdapResultCode::InappropriateMatching), LdapResultCode::InappropriateMatching }, + { static_cast(LdapResultCode::ConstraintViolation), LdapResultCode::ConstraintViolation }, + { static_cast(LdapResultCode::AttributeOrValueExists), LdapResultCode::AttributeOrValueExists }, + { static_cast(LdapResultCode::InvalidAttributeSyntax), LdapResultCode::InvalidAttributeSyntax }, + { static_cast(LdapResultCode::NoSuchObject), LdapResultCode::NoSuchObject }, + { static_cast(LdapResultCode::AliasProblem), LdapResultCode::AliasProblem }, + { static_cast(LdapResultCode::InvalidDNSyntax), LdapResultCode::InvalidDNSyntax }, + { static_cast(LdapResultCode::AliasDereferencingProblem), LdapResultCode::AliasDereferencingProblem }, + { static_cast(LdapResultCode::InappropriateAuthentication), LdapResultCode::InappropriateAuthentication }, + { static_cast(LdapResultCode::InvalidCredentials), LdapResultCode::InvalidCredentials }, + { static_cast(LdapResultCode::InsufficientAccessRights), LdapResultCode::InsufficientAccessRights }, + { static_cast(LdapResultCode::Busy), LdapResultCode::Busy }, + { static_cast(LdapResultCode::Unavailable), LdapResultCode::Unavailable }, + { static_cast(LdapResultCode::UnwillingToPerform), LdapResultCode::UnwillingToPerform }, + { static_cast(LdapResultCode::LoopDetect), LdapResultCode::LoopDetect }, + { static_cast(LdapResultCode::NamingViolation), LdapResultCode::NamingViolation }, + { static_cast(LdapResultCode::ObjectClassViolation), LdapResultCode::ObjectClassViolation }, + { static_cast(LdapResultCode::NotAllowedOnNonLeaf), LdapResultCode::NotAllowedOnNonLeaf }, + { static_cast(LdapResultCode::NotAllowedOnRDN), LdapResultCode::NotAllowedOnRDN }, + { static_cast(LdapResultCode::EntryAlreadyExists), LdapResultCode::EntryAlreadyExists }, + { static_cast(LdapResultCode::ObjectClassModsProhibited), LdapResultCode::ObjectClassModsProhibited }, + { static_cast(LdapResultCode::AffectsMultipleDSAs), LdapResultCode::AffectsMultipleDSAs }, + { static_cast(LdapResultCode::Other), LdapResultCode::Other } }; + // clang-format on std::string LdapResultCode::toString() const { @@ -179,31 +186,36 @@ namespace pcpp { // region LdapLayer LdapLayer::LdapLayer(uint16_t messageId, LdapOperationType operationType, - const std::vector& messageRecords, const std::vector& controls) + const std::vector& messageRecords, const std::vector& controls) { init(messageId, operationType, messageRecords, controls); } - LdapLayer::LdapLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) + LdapLayer::LdapLayer(std::unique_ptr asn1Record, uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : Layer(data, dataLen, prevLayer, packet) { m_Protocol = LDAP; m_Asn1Record = std::move(asn1Record); } - void LdapLayer::init(uint16_t messageId, LdapOperationType operationType, const std::vector& messageRecords, const std::vector& controls) + void LdapLayer::init(uint16_t messageId, LdapOperationType operationType, + const std::vector& messageRecords, const std::vector& controls) { Asn1IntegerRecord messageIdRecord(messageId); std::unique_ptr messageRootRecord; if (!messageRecords.empty()) { - messageRootRecord = std::unique_ptr(new Asn1ConstructedRecord(Asn1TagClass::Application, operationType, messageRecords)); + messageRootRecord = std::unique_ptr( + new Asn1ConstructedRecord(Asn1TagClass::Application, operationType, messageRecords)); } else { - messageRootRecord = std::unique_ptr(new Asn1GenericRecord(Asn1TagClass::Application, false, operationType, "")); + messageRootRecord = + std::unique_ptr(new Asn1GenericRecord(Asn1TagClass::Application, false, operationType, "")); } - std::vector rootSubRecords = {&messageIdRecord, messageRootRecord.get()}; + std::vector rootSubRecords = { &messageIdRecord, messageRootRecord.get() }; std::unique_ptr controlsRecord; if (!controls.empty()) @@ -214,7 +226,7 @@ namespace pcpp { Asn1OctetStringRecord controlTypeRecord(control.controlType); if (control.controlValue.empty()) { - controlsSubRecords.pushBack(new Asn1SequenceRecord({&controlTypeRecord})); + controlsSubRecords.pushBack(new Asn1SequenceRecord({ &controlTypeRecord })); } else { @@ -222,10 +234,11 @@ namespace pcpp { std::unique_ptr controlValue(new uint8_t[controlValueSize]); controlValueSize = hexStringToByteArray(control.controlValue, controlValue.get(), controlValueSize); Asn1OctetStringRecord controlValueRecord(controlValue.get(), controlValueSize); - controlsSubRecords.pushBack(new Asn1SequenceRecord({&controlTypeRecord, &controlValueRecord})); + controlsSubRecords.pushBack(new Asn1SequenceRecord({ &controlTypeRecord, &controlValueRecord })); } } - controlsRecord = std::unique_ptr(new Asn1ConstructedRecord(Asn1TagClass::ContextSpecific, 0, controlsSubRecords)); + controlsRecord = std::unique_ptr( + new Asn1ConstructedRecord(Asn1TagClass::ContextSpecific, 0, controlsSubRecords)); rootSubRecords.push_back(controlsRecord.get()); } @@ -250,35 +263,36 @@ namespace pcpp { try { auto asn1Record = Asn1Record::decode(data, dataLen, true); - auto operationType = LdapOperationType::fromUintValue(asn1Record->castAs()->getSubRecords().at(operationTypeIndex)->getTagType()); + auto operationType = LdapOperationType::fromUintValue( + asn1Record->castAs()->getSubRecords().at(operationTypeIndex)->getTagType()); switch (operationType) { - case LdapOperationType::BindRequest: - return new LdapBindRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::BindResponse: - return new LdapBindResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::UnbindRequest: - return new LdapUnbindRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::SearchRequest: - return new LdapSearchRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::SearchResultEntry: - return new LdapSearchResultEntryLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::SearchResultDone: - return new LdapSearchResultDoneLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::ModifyResponse: - return new LdapModifyResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::AddResponse: - return new LdapAddResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::DeleteResponse: - return new LdapDeleteResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::ModifyDNResponse: - return new LdapModifyDNResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::CompareResponse: - return new LdapCompareResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); - case LdapOperationType::Unknown: - return nullptr; - default: - return new LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::BindRequest: + return new LdapBindRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::BindResponse: + return new LdapBindResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::UnbindRequest: + return new LdapUnbindRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::SearchRequest: + return new LdapSearchRequestLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::SearchResultEntry: + return new LdapSearchResultEntryLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::SearchResultDone: + return new LdapSearchResultDoneLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::ModifyResponse: + return new LdapModifyResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::AddResponse: + return new LdapAddResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::DeleteResponse: + return new LdapDeleteResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::ModifyDNResponse: + return new LdapModifyDNResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::CompareResponse: + return new LdapCompareResponseLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); + case LdapOperationType::Unknown: + return nullptr; + default: + return new LdapLayer(std::move(asn1Record), data, dataLen, prevLayer, packet); } } catch (...) @@ -314,11 +328,13 @@ namespace pcpp { for (auto controlRecord : controlsRecord->getSubRecords()) { auto controlSequence = controlRecord->castAs(); - auto controlType = controlSequence->getSubRecords().at(controlTypeIndex)->castAs()->getValue(); + auto controlType = + controlSequence->getSubRecords().at(controlTypeIndex)->castAs()->getValue(); std::string controlValue; if (controlSequence->getSubRecords().size() > controlValueIndex) { - controlValue = controlSequence->getSubRecords().at(controlValueIndex)->castAs()->getValue(); + controlValue = + controlSequence->getSubRecords().at(controlValueIndex)->castAs()->getValue(); } controls.push_back({ controlType, controlValue }); } @@ -347,21 +363,25 @@ namespace pcpp { // region LdapResponseLayer LdapResponseLayer::LdapResponseLayer(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, - const std::string& matchedDN, const std::string& diagnosticMessage, const std::vector& referral, - const std::vector& controls) + const std::string& matchedDN, const std::string& diagnosticMessage, + const std::vector& referral, + const std::vector& controls) { - LdapResponseLayer::init(messageId, operationType, resultCode, matchedDN, diagnosticMessage, referral, {}, controls); + LdapResponseLayer::init(messageId, operationType, resultCode, matchedDN, diagnosticMessage, referral, {}, + controls); } void LdapResponseLayer::init(uint16_t messageId, LdapOperationType operationType, LdapResultCode resultCode, - const std::string& matchedDN, const std::string& diagnosticMessage, const std::vector& referral, - const std::vector& additionalRecords, const std::vector& controls) + const std::string& matchedDN, const std::string& diagnosticMessage, + const std::vector& referral, + const std::vector& additionalRecords, + const std::vector& controls) { Asn1EnumeratedRecord resultCodeRecord(resultCode); Asn1OctetStringRecord matchedDNRecord(matchedDN); Asn1OctetStringRecord diagnosticMessageRecord(diagnosticMessage); - std::vector messageRecords = {&resultCodeRecord, &matchedDNRecord, &diagnosticMessageRecord}; + std::vector messageRecords = { &resultCodeRecord, &matchedDNRecord, &diagnosticMessageRecord }; std::unique_ptr referralRecord; if (!referral.empty()) @@ -371,8 +391,8 @@ namespace pcpp { { referralSubRecords.pushBack(new Asn1OctetStringRecord(uri)); } - referralRecord = std::unique_ptr(new Asn1ConstructedRecord( - Asn1TagClass::ContextSpecific, referralTagType, referralSubRecords)); + referralRecord = std::unique_ptr( + new Asn1ConstructedRecord(Asn1TagClass::ContextSpecific, referralTagType, referralSubRecords)); messageRecords.push_back(referralRecord.get()); } @@ -389,17 +409,29 @@ namespace pcpp { LdapResultCode LdapResponseLayer::getResultCode() const { - return LdapResultCode::fromUintValue(getLdapOperationAsn1Record()->getSubRecords().at(resultCodeIndex)->castAs()->getValue()); + return LdapResultCode::fromUintValue(getLdapOperationAsn1Record() + ->getSubRecords() + .at(resultCodeIndex) + ->castAs() + ->getValue()); } std::string LdapResponseLayer::getMatchedDN() const { - return getLdapOperationAsn1Record()->getSubRecords().at(matchedDNIndex)->castAs()->getValue(); + return getLdapOperationAsn1Record() + ->getSubRecords() + .at(matchedDNIndex) + ->castAs() + ->getValue(); } std::string LdapResponseLayer::getDiagnosticMessage() const { - return getLdapOperationAsn1Record()->getSubRecords().at(diagnotsticsMessageIndex)->castAs()->getValue(); + return getLdapOperationAsn1Record() + ->getSubRecords() + .at(diagnotsticsMessageIndex) + ->castAs() + ->getValue(); } std::vector LdapResponseLayer::getReferral() const @@ -411,7 +443,8 @@ namespace pcpp { } auto referralRecord = getLdapOperationAsn1Record()->getSubRecords().at(referralIndex); - if (referralRecord->getTagClass() != Asn1TagClass::ContextSpecific || referralRecord->getTagType() != referralTagType) + if (referralRecord->getTagClass() != Asn1TagClass::ContextSpecific || + referralRecord->getTagType() != referralTagType) { return result; } @@ -432,32 +465,34 @@ namespace pcpp { // region LdapBindRequestLayer - LdapBindRequestLayer::LdapBindRequestLayer( - uint16_t messageId, uint8_t version, const std::string& name, const std::string& simpleAuthentication, - const std::vector& controls) + LdapBindRequestLayer::LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, + const std::string& simpleAuthentication, + const std::vector& controls) { Asn1IntegerRecord versionRecord(version); Asn1OctetStringRecord nameRecord(name); - std::vector messageRecords = {&versionRecord, &nameRecord}; + std::vector messageRecords = { &versionRecord, &nameRecord }; std::unique_ptr simpleAuthenticationRecord; if (!simpleAuthentication.empty()) { auto data = reinterpret_cast(simpleAuthentication.data()); simpleAuthenticationRecord = std::unique_ptr( - new Asn1GenericRecord(Asn1TagClass::ContextSpecific, false, static_cast(LdapBindRequestLayer::AuthenticationType::Simple), data, simpleAuthentication.size())); + new Asn1GenericRecord(Asn1TagClass::ContextSpecific, false, + static_cast(LdapBindRequestLayer::AuthenticationType::Simple), data, + simpleAuthentication.size())); messageRecords.push_back(simpleAuthenticationRecord.get()); } LdapLayer::init(messageId, LdapOperationType::BindRequest, messageRecords, controls); } - LdapBindRequestLayer::LdapBindRequestLayer( - uint16_t messageId, uint8_t version, const std::string& name, const SaslAuthentication& saslAuthentication, - const std::vector& controls) + LdapBindRequestLayer::LdapBindRequestLayer(uint16_t messageId, uint8_t version, const std::string& name, + const SaslAuthentication& saslAuthentication, + const std::vector& controls) { Asn1IntegerRecord versionRecord(version); Asn1OctetStringRecord nameRecord(name); - std::vector messageRecords = {&versionRecord, &nameRecord}; + std::vector messageRecords = { &versionRecord, &nameRecord }; std::unique_ptr saslAuthenticationRecord; if (!saslAuthentication.mechanism.empty()) { @@ -465,12 +500,14 @@ namespace pcpp { saslAuthenticationRecords.pushBack(new Asn1OctetStringRecord(saslAuthentication.mechanism)); if (!saslAuthentication.credentials.empty()) { - auto credentialsRecord = new Asn1OctetStringRecord(saslAuthentication.credentials.data(), saslAuthentication.credentials.size()); + auto credentialsRecord = new Asn1OctetStringRecord(saslAuthentication.credentials.data(), + saslAuthentication.credentials.size()); saslAuthenticationRecords.pushBack(credentialsRecord); } - saslAuthenticationRecord = std::unique_ptr( - new Asn1ConstructedRecord(Asn1TagClass::ContextSpecific, static_cast(LdapBindRequestLayer::AuthenticationType::Sasl), saslAuthenticationRecords)); + saslAuthenticationRecord = std::unique_ptr(new Asn1ConstructedRecord( + Asn1TagClass::ContextSpecific, static_cast(LdapBindRequestLayer::AuthenticationType::Sasl), + saslAuthenticationRecords)); messageRecords.push_back(saslAuthenticationRecord.get()); } @@ -497,12 +534,12 @@ namespace pcpp { auto authType = getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->getTagType(); switch (authType) { - case 0: - return LdapBindRequestLayer::AuthenticationType::Simple; - case 3: - return LdapBindRequestLayer::AuthenticationType::Sasl; - default: - return LdapBindRequestLayer::AuthenticationType::NotApplicable; + case 0: + return LdapBindRequestLayer::AuthenticationType::Simple; + case 3: + return LdapBindRequestLayer::AuthenticationType::Sasl; + default: + return LdapBindRequestLayer::AuthenticationType::NotApplicable; } } @@ -513,8 +550,9 @@ namespace pcpp { throw std::invalid_argument("Authentication type is not simple"); } - auto authRecord = getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->castAs(); - return {reinterpret_cast(authRecord->getValue()), authRecord->getValueLength()}; + auto authRecord = + getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->castAs(); + return { reinterpret_cast(authRecord->getValue()), authRecord->getValueLength() }; } LdapBindRequestLayer::SaslAuthentication LdapBindRequestLayer::getSaslAuthentication() const @@ -524,7 +562,8 @@ namespace pcpp { throw std::invalid_argument("Authentication type is not sasl"); } - auto authRecord = getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->castAs(); + auto authRecord = + getLdapOperationAsn1Record()->getSubRecords().at(credentialIndex)->castAs(); std::string mechanism; std::vector credentials; if (authRecord->getSubRecords().size() > saslMechanismIndex) @@ -533,24 +572,25 @@ namespace pcpp { } if (authRecord->getSubRecords().size() > saslCredentialsIndex) { - auto credentialsAsString = authRecord->getSubRecords().at(saslCredentialsIndex)->castAs()->getValue(); + auto credentialsAsString = + authRecord->getSubRecords().at(saslCredentialsIndex)->castAs()->getValue(); credentials.resize(credentialsAsString.size() / 2); hexStringToByteArray(credentialsAsString, credentials.data(), credentials.size()); } - return {mechanism, credentials}; + return { mechanism, credentials }; } std::string LdapBindRequestLayer::getExtendedInfoString() const { switch (getAuthenticationType()) { - case AuthenticationType::Simple: - return "simple"; - case AuthenticationType::Sasl: - return "sasl"; - default: - return "Unknown"; + case AuthenticationType::Simple: + return "simple"; + case AuthenticationType::Sasl: + return "sasl"; + default: + return "Unknown"; } } @@ -559,27 +599,33 @@ namespace pcpp { // region LdapBindResponseLayer LdapBindResponseLayer::LdapBindResponseLayer(uint16_t messageId, LdapResultCode resultCode, - const std::string& matchedDN, const std::string& diagnosticMessage, - const std::vector& referral, const std::vector& serverSaslCredentials, - const std::vector& controls) + const std::string& matchedDN, const std::string& diagnosticMessage, + const std::vector& referral, + const std::vector& serverSaslCredentials, + const std::vector& controls) { std::vector additionalRecords; std::unique_ptr serverSaslCredentialsRecord; if (!serverSaslCredentials.empty()) { - serverSaslCredentialsRecord = std::unique_ptr(new Asn1GenericRecord(Asn1TagClass::ContextSpecific, false, serverSaslCredentialsTagType, serverSaslCredentials.data(), serverSaslCredentials.size())); + serverSaslCredentialsRecord = std::unique_ptr( + new Asn1GenericRecord(Asn1TagClass::ContextSpecific, false, serverSaslCredentialsTagType, + serverSaslCredentials.data(), serverSaslCredentials.size())); additionalRecords.push_back(serverSaslCredentialsRecord.get()); } - LdapResponseLayer::init(messageId, LdapOperationType::BindResponse, resultCode, matchedDN, diagnosticMessage, referral, additionalRecords, controls); + LdapResponseLayer::init(messageId, LdapOperationType::BindResponse, resultCode, matchedDN, diagnosticMessage, + referral, additionalRecords, controls); } std::vector LdapBindResponseLayer::getServerSaslCredentials() const { try { - auto serverSaslCredentialsRecord = getLdapOperationAsn1Record()->getSubRecords().back()->castAs(); - return {serverSaslCredentialsRecord->getValue(), serverSaslCredentialsRecord->getValue() + serverSaslCredentialsRecord->getValueLength()}; + auto serverSaslCredentialsRecord = + getLdapOperationAsn1Record()->getSubRecords().back()->castAs(); + return { serverSaslCredentialsRecord->getValue(), + serverSaslCredentialsRecord->getValue() + serverSaslCredentialsRecord->getValueLength() }; } catch (const std::exception&) { @@ -600,20 +646,24 @@ namespace pcpp { // region LdapSearchRequestLayer - const std::unordered_map> SearchRequestScopeToString { - {LdapSearchRequestLayer::SearchRequestScope::BaseObject, "BaseObject"}, - {LdapSearchRequestLayer::SearchRequestScope::SingleLevel, "SingleLevel"}, - {LdapSearchRequestLayer::SearchRequestScope::WholeSubtree, "WholeSubtree"}, - {LdapSearchRequestLayer::SearchRequestScope::Unknown, "Unknown"} - }; - - const std::unordered_map> DerefAliasesToString { - {LdapSearchRequestLayer::DerefAliases::NeverDerefAliases, "NeverDerefAliases"}, - {LdapSearchRequestLayer::DerefAliases::DerefInSearching, "DerefInSearching"}, - {LdapSearchRequestLayer::DerefAliases::DerefFindingBaseObj, "DerefFindingBaseObj"}, - {LdapSearchRequestLayer::DerefAliases::DerefAlways, "DerefAlways"}, - {LdapSearchRequestLayer::DerefAliases::Unknown, "Unknown"} - }; + const std::unordered_map> + SearchRequestScopeToString{ + { LdapSearchRequestLayer::SearchRequestScope::BaseObject, "BaseObject" }, + { LdapSearchRequestLayer::SearchRequestScope::SingleLevel, "SingleLevel" }, + { LdapSearchRequestLayer::SearchRequestScope::WholeSubtree, "WholeSubtree" }, + { LdapSearchRequestLayer::SearchRequestScope::Unknown, "Unknown" } + }; + + const std::unordered_map> + DerefAliasesToString{ + { LdapSearchRequestLayer::DerefAliases::NeverDerefAliases, "NeverDerefAliases" }, + { LdapSearchRequestLayer::DerefAliases::DerefInSearching, "DerefInSearching" }, + { LdapSearchRequestLayer::DerefAliases::DerefFindingBaseObj, "DerefFindingBaseObj" }, + { LdapSearchRequestLayer::DerefAliases::DerefAlways, "DerefAlways" }, + { LdapSearchRequestLayer::DerefAliases::Unknown, "Unknown" } + }; std::string LdapSearchRequestLayer::SearchRequestScope::toString() const { @@ -645,10 +695,11 @@ namespace pcpp { return LdapSearchRequestLayer::DerefAliases::Unknown; } - LdapSearchRequestLayer::LdapSearchRequestLayer( - uint16_t messageId, const std::string& baseObject, SearchRequestScope scope, DerefAliases derefAliases, - uint8_t sizeLimit, uint8_t timeLimit, bool typesOnly, Asn1Record* filterRecord, - const std::vector& attributes, const std::vector& controls) + LdapSearchRequestLayer::LdapSearchRequestLayer(uint16_t messageId, const std::string& baseObject, + SearchRequestScope scope, DerefAliases derefAliases, + uint8_t sizeLimit, uint8_t timeLimit, bool typesOnly, + Asn1Record* filterRecord, const std::vector& attributes, + const std::vector& controls) { Asn1OctetStringRecord baseObjectRecord(baseObject); Asn1EnumeratedRecord scopeRecord(scope); @@ -664,37 +715,55 @@ namespace pcpp { } Asn1SequenceRecord attributesRecord(attributeSubRecords); - LdapLayer::init(messageId, LdapOperationType::SearchRequest, {&baseObjectRecord, &scopeRecord, &derefAliasesRecord, &sizeLimitRecord, &timeLimitRecord, &typeOnlyRecord, filterRecord, &attributesRecord}, controls); + LdapLayer::init(messageId, LdapOperationType::SearchRequest, + { &baseObjectRecord, &scopeRecord, &derefAliasesRecord, &sizeLimitRecord, &timeLimitRecord, + &typeOnlyRecord, filterRecord, &attributesRecord }, + controls); } std::string LdapSearchRequestLayer::getBaseObject() const { - return getLdapOperationAsn1Record()->getSubRecords().at(baseObjectIndex)->castAs()->getValue(); + return getLdapOperationAsn1Record() + ->getSubRecords() + .at(baseObjectIndex) + ->castAs() + ->getValue(); } LdapSearchRequestLayer::SearchRequestScope LdapSearchRequestLayer::getScope() const { - return LdapSearchRequestLayer::SearchRequestScope::fromUintValue(getLdapOperationAsn1Record()->getSubRecords().at(scopeIndex)->castAs()->getValue()); + return LdapSearchRequestLayer::SearchRequestScope::fromUintValue( + getLdapOperationAsn1Record()->getSubRecords().at(scopeIndex)->castAs()->getValue()); } LdapSearchRequestLayer::DerefAliases LdapSearchRequestLayer::getDerefAlias() const { - return LdapSearchRequestLayer::DerefAliases::fromUintValue(getLdapOperationAsn1Record()->getSubRecords().at(derefAliasIndex)->castAs()->getValue()); + return LdapSearchRequestLayer::DerefAliases::fromUintValue(getLdapOperationAsn1Record() + ->getSubRecords() + .at(derefAliasIndex) + ->castAs() + ->getValue()); } uint8_t LdapSearchRequestLayer::getSizeLimit() const { - return static_cast(getLdapOperationAsn1Record()->getSubRecords().at(sizeLimitIndex)->castAs()->getValue()); + return static_cast( + getLdapOperationAsn1Record()->getSubRecords().at(sizeLimitIndex)->castAs()->getValue()); } uint8_t LdapSearchRequestLayer::getTimeLimit() const { - return static_cast(getLdapOperationAsn1Record()->getSubRecords().at(timeLimitIndex)->castAs()->getValue()); + return static_cast( + getLdapOperationAsn1Record()->getSubRecords().at(timeLimitIndex)->castAs()->getValue()); } bool LdapSearchRequestLayer::getTypesOnly() const { - return getLdapOperationAsn1Record()->getSubRecords().at(typesOnlyIndex)->castAs()->getValue(); + return getLdapOperationAsn1Record() + ->getSubRecords() + .at(typesOnlyIndex) + ->castAs() + ->getValue(); } Asn1Record* LdapSearchRequestLayer::getFilter() const @@ -710,7 +779,8 @@ namespace pcpp { return result; } - auto attributesRecord = getLdapOperationAsn1Record()->getSubRecords().at(attributesIndex)->castAs(); + auto attributesRecord = + getLdapOperationAsn1Record()->getSubRecords().at(attributesIndex)->castAs(); for (auto attribute : attributesRecord->getSubRecords()) { result.push_back(attribute->castAs()->getValue()); @@ -735,7 +805,8 @@ namespace pcpp { // region LdapSearchResultEntryLayer LdapSearchResultEntryLayer::LdapSearchResultEntryLayer(uint16_t messageId, const std::string& objectName, - const std::vector& attributes, const std::vector& controls) + const std::vector& attributes, + const std::vector& controls) { PointerVector attributesSubRecords; for (const auto& attribute : attributes) @@ -755,24 +826,31 @@ namespace pcpp { Asn1OctetStringRecord objectNameRecord(objectName); Asn1SequenceRecord attributesRecord(attributesSubRecords); - LdapLayer::init(messageId, LdapOperationType::SearchResultEntry, {&objectNameRecord, &attributesRecord}, controls); + LdapLayer::init(messageId, LdapOperationType::SearchResultEntry, { &objectNameRecord, &attributesRecord }, + controls); } std::string LdapSearchResultEntryLayer::getObjectName() const { - return getLdapOperationAsn1Record()->getSubRecords().at(objectNameIndex)->castAs()->getValue(); + return getLdapOperationAsn1Record() + ->getSubRecords() + .at(objectNameIndex) + ->castAs() + ->getValue(); } std::vector LdapSearchResultEntryLayer::getAttributes() const { std::vector result; - auto attributes = getLdapOperationAsn1Record()->getSubRecords().at(attributesIndex)->castAs(); + auto attributes = + getLdapOperationAsn1Record()->getSubRecords().at(attributesIndex)->castAs(); for (auto attributeRecord : attributes->getSubRecords()) { auto attrAsSequence = attributeRecord->castAs(); - auto type = attrAsSequence->getSubRecords().at(attributeTypeIndex)->castAs()->getValue(); + auto type = + attrAsSequence->getSubRecords().at(attributeTypeIndex)->castAs()->getValue(); std::vector values; auto valuesRecord = attrAsSequence->getSubRecords().at(attributeValueIndex)->castAs(); @@ -782,7 +860,7 @@ namespace pcpp { values.push_back(valueRecord->castAs()->getValue()); } - LdapAttribute ldapAttribute = {type, values}; + LdapAttribute ldapAttribute = { type, values }; result.push_back(ldapAttribute); } @@ -790,4 +868,4 @@ namespace pcpp { } // endregion -} +} // namespace pcpp diff --git a/Packet++/src/MplsLayer.cpp b/Packet++/src/MplsLayer.cpp index c497445c86..184222dc91 100644 --- a/Packet++/src/MplsLayer.cpp +++ b/Packet++/src/MplsLayer.cpp @@ -12,148 +12,150 @@ namespace pcpp { -MplsLayer::MplsLayer(uint32_t mplsLabel, uint8_t ttl, uint8_t experimentalUseValue, bool bottomOfStack) -{ - const size_t headerLen = sizeof(mpls_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = MPLS; - - setMplsLabel(mplsLabel); - setTTL(ttl); - setExperimentalUseValue(experimentalUseValue); - setBottomOfStack(bottomOfStack); -} - -bool MplsLayer::isBottomOfStack() const -{ - return (getMplsHeader()->misc & 0x01); -} + MplsLayer::MplsLayer(uint32_t mplsLabel, uint8_t ttl, uint8_t experimentalUseValue, bool bottomOfStack) + { + const size_t headerLen = sizeof(mpls_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + m_Protocol = MPLS; + + setMplsLabel(mplsLabel); + setTTL(ttl); + setExperimentalUseValue(experimentalUseValue); + setBottomOfStack(bottomOfStack); + } -void MplsLayer::setBottomOfStack(bool val) -{ - if (!val) - getMplsHeader()->misc &= 0xFE; - else - getMplsHeader()->misc |= 0x1; -} + bool MplsLayer::isBottomOfStack() const + { + return (getMplsHeader()->misc & 0x01); + } -uint8_t MplsLayer::getExperimentalUseValue() const -{ - return ((getMplsHeader()->misc & 0x0E) >> 1); -} + void MplsLayer::setBottomOfStack(bool val) + { + if (!val) + getMplsHeader()->misc &= 0xFE; + else + getMplsHeader()->misc |= 0x1; + } -bool MplsLayer::setExperimentalUseValue(uint8_t val) -{ - // exp value is only 3 bits - if (val > 7) + uint8_t MplsLayer::getExperimentalUseValue() const { - PCPP_LOG_ERROR("Set ExperimentalUse value got an illegal value: " << (int)val << ". Value must be lower than 8"); - return false; + return ((getMplsHeader()->misc & 0x0E) >> 1); } - mpls_header* hdr = getMplsHeader(); + bool MplsLayer::setExperimentalUseValue(uint8_t val) + { + // exp value is only 3 bits + if (val > 7) + { + PCPP_LOG_ERROR("Set ExperimentalUse value got an illegal value: " << (int)val + << ". Value must be lower than 8"); + return false; + } - // clear the 3 exp bits - hdr->misc &= 0xF1; + mpls_header* hdr = getMplsHeader(); - // move the 3 bits to their place - val = val << 1; + // clear the 3 exp bits + hdr->misc &= 0xF1; - hdr->misc |= val; + // move the 3 bits to their place + val = val << 1; - return true; -} + hdr->misc |= val; -uint32_t MplsLayer::getMplsLabel() const -{ - return (htobe16(getMplsHeader()->hiLabel) << 4) | ((getMplsHeader()->misc & 0xF0) >> 4); -} + return true; + } -bool MplsLayer::setMplsLabel(uint32_t label) -{ - if (label > 0xFFFFF) + uint32_t MplsLayer::getMplsLabel() const { - PCPP_LOG_ERROR("MPLS label mustn't exceed 20 bits which is the value 0xffff. Got a parameter with the value 0x" << std::hex << label); - return false; + return (htobe16(getMplsHeader()->hiLabel) << 4) | ((getMplsHeader()->misc & 0xF0) >> 4); } - mpls_header* hdr = getMplsHeader(); - - // clear the 4 label bits in misc field - hdr->misc &= 0x0F; - - // take the last nibble of the label value and move this nibble to its place in misc - uint8_t miscVal = (label & 0x0F) << 4; - - // update misc field - hdr->misc |= miscVal; + bool MplsLayer::setMplsLabel(uint32_t label) + { + if (label > 0xFFFFF) + { + PCPP_LOG_ERROR( + "MPLS label mustn't exceed 20 bits which is the value 0xffff. Got a parameter with the value 0x" + << std::hex << label); + return false; + } - // get rid of the nibble that went to misc - label = label >> 4; + mpls_header* hdr = getMplsHeader(); - // set the high 2 bytes of the label - hdr->hiLabel = (uint16_t)htobe16(label); + // clear the 4 label bits in misc field + hdr->misc &= 0x0F; - return true; -} + // take the last nibble of the label value and move this nibble to its place in misc + uint8_t miscVal = (label & 0x0F) << 4; + // update misc field + hdr->misc |= miscVal; -void MplsLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen < headerLen + 1) - return; + // get rid of the nibble that went to misc + label = label >> 4; - uint8_t* payload = m_Data + sizeof(mpls_header); - size_t payloadLen = m_DataLen - sizeof(mpls_header); + // set the high 2 bytes of the label + hdr->hiLabel = (uint16_t)htobe16(label); - if (!isBottomOfStack()) - { - m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); - return; + return true; } - uint8_t nextNibble = (*((uint8_t*)(m_Data + headerLen)) & 0xF0) >> 4; - switch (nextNibble) + void MplsLayer::parseNextLayer() { + size_t headerLen = getHeaderLen(); + if (m_DataLen < headerLen + 1) + return; + + uint8_t* payload = m_Data + sizeof(mpls_header); + size_t payloadLen = m_DataLen - sizeof(mpls_header); + + if (!isBottomOfStack()) + { + m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); + return; + } + + uint8_t nextNibble = (*((uint8_t*)(m_Data + headerLen)) & 0xF0) >> 4; + switch (nextNibble) + { case 4: m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; case 6: m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); break; default: m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } } -} -void MplsLayer::computeCalculateFields() -{ - Layer* nextLayer = getNextLayer(); - if (nextLayer != nullptr) + void MplsLayer::computeCalculateFields() { - setBottomOfStack((nextLayer->getProtocol() != MPLS)); + Layer* nextLayer = getNextLayer(); + if (nextLayer != nullptr) + { + setBottomOfStack((nextLayer->getProtocol() != MPLS)); + } } -} -std::string MplsLayer::toString() const -{ - std::ostringstream labelStream; - labelStream << getMplsLabel(); - std::ostringstream expStream; - expStream << (int)getExperimentalUseValue(); - std::ostringstream ttlStream; - ttlStream << (int)getTTL(); - std::string bottomOfStack = isBottomOfStack() ? "true" : "false"; - - return "MPLS Layer, Label: " + labelStream.str() + ", Exp: " + expStream.str() + ", TTL: " + ttlStream.str() + - ", Bottom of stack: " + bottomOfStack; -} - -} // namespace pcpp + std::string MplsLayer::toString() const + { + std::ostringstream labelStream; + labelStream << getMplsLabel(); + std::ostringstream expStream; + expStream << (int)getExperimentalUseValue(); + std::ostringstream ttlStream; + ttlStream << (int)getTTL(); + std::string bottomOfStack = isBottomOfStack() ? "true" : "false"; + + return "MPLS Layer, Label: " + labelStream.str() + ", Exp: " + expStream.str() + ", TTL: " + ttlStream.str() + + ", Bottom of stack: " + bottomOfStack; + } + +} // namespace pcpp diff --git a/Packet++/src/NdpLayer.cpp b/Packet++/src/NdpLayer.cpp index 29853f1e27..c0448938a5 100644 --- a/Packet++/src/NdpLayer.cpp +++ b/Packet++/src/NdpLayer.cpp @@ -6,214 +6,215 @@ namespace pcpp { -/* - * NdpOptionBuilder - */ + /* + * NdpOptionBuilder + */ -NdpOption NdpOptionBuilder::build() const -{ - size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); - size_t padding = (8 - (optionSize % 8)) % 8; // Padding bytes for a option with 8 byte boundary - size_t optionSizeWithPadding = optionSize + padding; - - uint8_t *recordBuffer = new uint8_t[optionSizeWithPadding]; - memset(recordBuffer, 0, optionSizeWithPadding); - recordBuffer[0] = static_cast(m_RecType); - recordBuffer[1] = static_cast(optionSizeWithPadding / 8); // length value is stored in units of 8 octets - memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); - - return NdpOption(recordBuffer); -} - -/* - * NDPLayerBase - */ - -size_t NDPLayerBase::getNdpOptionCount() const -{ - return m_OptionReader.getTLVRecordCount(getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); -} - -NdpOption NDPLayerBase::getFirstNdpOption() const -{ - return m_OptionReader.getFirstTLVRecord(getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); -} - -NdpOption NDPLayerBase::getNextNdpOption(NdpOption &option) const -{ - return m_OptionReader.getNextTLVRecord(option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); -} + NdpOption NdpOptionBuilder::build() const + { + size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); + size_t padding = (8 - (optionSize % 8)) % 8; // Padding bytes for a option with 8 byte boundary + size_t optionSizeWithPadding = optionSize + padding; + + uint8_t* recordBuffer = new uint8_t[optionSizeWithPadding]; + memset(recordBuffer, 0, optionSizeWithPadding); + recordBuffer[0] = static_cast(m_RecType); + // length value is stored in units of 8 octets + recordBuffer[1] = static_cast(optionSizeWithPadding / 8); + memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); + + return NdpOption(recordBuffer); + } -NdpOption NDPLayerBase::getNdpOption(NDPNeighborOptionTypes option) const -{ - return m_OptionReader.getTLVRecord((uint8_t)option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); -} + /* + * NDPLayerBase + */ -NdpOption NDPLayerBase::addNdpOption(const NdpOptionBuilder &optionBuilder) -{ - return addNdpOptionAt(optionBuilder, getHeaderLen()); -} + size_t NDPLayerBase::getNdpOptionCount() const + { + return m_OptionReader.getTLVRecordCount(getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); + } -NdpOption NDPLayerBase::addNdpOptionAt(const NdpOptionBuilder &optionBuilder, int offset) -{ - NdpOption newOption = optionBuilder.build(); + NdpOption NDPLayerBase::getFirstNdpOption() const + { + return m_OptionReader.getFirstTLVRecord(getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); + } - if (newOption.isNull()) + NdpOption NDPLayerBase::getNextNdpOption(NdpOption& option) const { - PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOption.getType()); - return newOption; + return m_OptionReader.getNextTLVRecord(option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); } - size_t sizeToExtend = newOption.getTotalSize(); + NdpOption NDPLayerBase::getNdpOption(NDPNeighborOptionTypes option) const + { + return m_OptionReader.getTLVRecord((uint8_t)option, getNdpOptionsBasePtr(), getHeaderLen() - getNdpHeaderLen()); + } - if (!extendLayer(offset, sizeToExtend)) + NdpOption NDPLayerBase::addNdpOption(const NdpOptionBuilder& optionBuilder) { - PCPP_LOG_ERROR("Could not extend NdpLayer in [" << sizeToExtend << "] bytes"); - newOption.purgeRecordData(); - return NdpOption(nullptr); + return addNdpOptionAt(optionBuilder, getHeaderLen()); } - memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); + NdpOption NDPLayerBase::addNdpOptionAt(const NdpOptionBuilder& optionBuilder, int offset) + { + NdpOption newOption = optionBuilder.build(); - newOption.purgeRecordData(); + if (newOption.isNull()) + { + PCPP_LOG_ERROR("Cannot build new option of type " << (int)newOption.getType()); + return newOption; + } - m_OptionReader.changeTLVRecordCount(1); + size_t sizeToExtend = newOption.getTotalSize(); - uint8_t *newOptPtr = m_Data + offset; + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend NdpLayer in [" << sizeToExtend << "] bytes"); + newOption.purgeRecordData(); + return NdpOption(nullptr); + } - return NdpOption(newOptPtr); -} + memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); -bool NDPLayerBase::removeAllNdpOptions() -{ - int offset = getNdpHeaderLen(); - if (!shortenLayer(offset, getHeaderLen() - offset)) - return false; + newOption.purgeRecordData(); - m_OptionReader.changeTLVRecordCount(0 - getNdpOptionCount()); - return true; -} + m_OptionReader.changeTLVRecordCount(1); -/* - * NDPNeighborSolicitationLayer - */ + uint8_t* newOptPtr = m_Data + offset; -NDPNeighborSolicitationLayer::NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address &targetIP) -{ - initLayer(code, targetIP); -} + return NdpOption(newOptPtr); + } -NDPNeighborSolicitationLayer::NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address &targetIP, - const MacAddress &srcMac) -{ - initLayer(code, targetIP); - this->addNdpOption( - pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER, srcMac.getRawData(), 6)); -} + bool NDPLayerBase::removeAllNdpOptions() + { + int offset = getNdpHeaderLen(); + if (!shortenLayer(offset, getHeaderLen() - offset)) + return false; -void NDPNeighborSolicitationLayer::initLayer(uint8_t code, const IPv6Address &targetIP) -{ - m_DataLen = sizeof(ndpneighborsolicitationhdr); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = ICMPv6; - - ndpneighborsolicitationhdr *pHdr = getNdpHeader(); - pHdr->type = static_cast(ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION); - pHdr->code = code; - memcpy(pHdr->targetIP, targetIP.toBytes(), 16); -} - -bool NDPNeighborSolicitationLayer::hasLinkLayerAddress() const -{ - NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); - return option.isNull() ? false : true; -} + m_OptionReader.changeTLVRecordCount(0 - getNdpOptionCount()); + return true; + } -MacAddress NDPNeighborSolicitationLayer::getLinkLayerAddress() const -{ - NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); + /* + * NDPNeighborSolicitationLayer + */ - if (option.isNull()) + NDPNeighborSolicitationLayer::NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address& targetIP) { - return MacAddress::Zero; + initLayer(code, targetIP); } - return MacAddress(option.getValue()); -} + NDPNeighborSolicitationLayer::NDPNeighborSolicitationLayer(uint8_t code, const IPv6Address& targetIP, + const MacAddress& srcMac) + { + initLayer(code, targetIP); + this->addNdpOption( + pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER, srcMac.getRawData(), 6)); + } -std::string NDPNeighborSolicitationLayer::toString() const -{ - std::ostringstream typeStream; - typeStream << "ICMPv6 Layer, Neighbor Solicitation Message, TargetIP: " + getTargetIP().toString(); - hasLinkLayerAddress() ? typeStream << ", SourceMAC: " + getLinkLayerAddress().toString() : typeStream << ", no Option"; + void NDPNeighborSolicitationLayer::initLayer(uint8_t code, const IPv6Address& targetIP) + { + m_DataLen = sizeof(ndpneighborsolicitationhdr); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = ICMPv6; + + ndpneighborsolicitationhdr* pHdr = getNdpHeader(); + pHdr->type = static_cast(ICMPv6MessageType::ICMPv6_NEIGHBOR_SOLICITATION); + pHdr->code = code; + memcpy(pHdr->targetIP, targetIP.toBytes(), 16); + } - return typeStream.str(); + bool NDPNeighborSolicitationLayer::hasLinkLayerAddress() const + { + NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); + return option.isNull() ? false : true; + } -} + MacAddress NDPNeighborSolicitationLayer::getLinkLayerAddress() const + { + NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_SOURCE_LINK_LAYER); -/* - * NDPNeighborAdvertisementLayer - */ + if (option.isNull()) + { + return MacAddress::Zero; + } -NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address &targetIP, - const MacAddress &targetMac, bool routerFlag, - bool unicastFlag, bool overrideFlag) -{ - initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); - this->addNdpOption( - pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER, targetMac.getRawData(), 6)); -} + return MacAddress(option.getValue()); + } -NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address &targetIP, bool routerFlag, - bool unicastFlag, bool overrideFlag) -{ - initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); -} + std::string NDPNeighborSolicitationLayer::toString() const + { + std::ostringstream typeStream; + typeStream << "ICMPv6 Layer, Neighbor Solicitation Message, TargetIP: " + getTargetIP().toString(); + hasLinkLayerAddress() ? typeStream << ", SourceMAC: " + getLinkLayerAddress().toString() + : typeStream << ", no Option"; -void NDPNeighborAdvertisementLayer::initLayer(uint8_t code, const IPv6Address &targetIP, bool routerFlag, - bool unicastFlag, bool overrideFlag) -{ - m_DataLen = sizeof(ndpneighboradvertisementhdr); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = ICMPv6; - - ndpneighboradvertisementhdr *pHdr = getNdpHeader(); - pHdr->type = static_cast(ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT); - pHdr->code = code; - pHdr->router = routerFlag; - pHdr->solicited = unicastFlag; - pHdr->override = overrideFlag; - - memcpy(pHdr->targetIP, targetIP.toBytes(), 16); -} - -bool NDPNeighborAdvertisementLayer::hasTargetMacInfo() const -{ - NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); - return option.isNull() ? false : true; -} + return typeStream.str(); + } -MacAddress NDPNeighborAdvertisementLayer::getTargetMac() const -{ - NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + /* + * NDPNeighborAdvertisementLayer + */ - if (option.isNull()) + NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, + const MacAddress& targetMac, bool routerFlag, + bool unicastFlag, bool overrideFlag) { - return MacAddress::Zero; + initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); + this->addNdpOption(pcpp::NdpOptionBuilder(pcpp::NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER, + targetMac.getRawData(), 6)); } - return MacAddress(option.getValue()); -} + NDPNeighborAdvertisementLayer::NDPNeighborAdvertisementLayer(uint8_t code, const IPv6Address& targetIP, + bool routerFlag, bool unicastFlag, bool overrideFlag) + { + initLayer(code, targetIP, routerFlag, unicastFlag, overrideFlag); + } -std::string NDPNeighborAdvertisementLayer::toString() const -{ - std::ostringstream typeStream; - typeStream << "ICMPv6 Layer, Neighbor Advertisement Message, TargetIP: " << getTargetIP().toString(); - hasTargetMacInfo() ? typeStream << ", TargetMAC: " + getTargetMac().toString() : typeStream << ", no Option"; + void NDPNeighborAdvertisementLayer::initLayer(uint8_t code, const IPv6Address& targetIP, bool routerFlag, + bool unicastFlag, bool overrideFlag) + { + m_DataLen = sizeof(ndpneighboradvertisementhdr); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = ICMPv6; + + ndpneighboradvertisementhdr* pHdr = getNdpHeader(); + pHdr->type = static_cast(ICMPv6MessageType::ICMPv6_NEIGHBOR_ADVERTISEMENT); + pHdr->code = code; + pHdr->router = routerFlag; + pHdr->solicited = unicastFlag; + pHdr->override = overrideFlag; + + memcpy(pHdr->targetIP, targetIP.toBytes(), 16); + } + + bool NDPNeighborAdvertisementLayer::hasTargetMacInfo() const + { + NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + return option.isNull() ? false : true; + } - return typeStream.str(); -} + MacAddress NDPNeighborAdvertisementLayer::getTargetMac() const + { + NdpOption option = this->getNdpOption(NDPNeighborOptionTypes::NDP_OPTION_TARGET_LINK_LAYER); + + if (option.isNull()) + { + return MacAddress::Zero; + } + + return MacAddress(option.getValue()); + } + + std::string NDPNeighborAdvertisementLayer::toString() const + { + std::ostringstream typeStream; + typeStream << "ICMPv6 Layer, Neighbor Advertisement Message, TargetIP: " << getTargetIP().toString(); + hasTargetMacInfo() ? typeStream << ", TargetMAC: " + getTargetMac().toString() : typeStream << ", no Option"; + + return typeStream.str(); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/NflogLayer.cpp b/Packet++/src/NflogLayer.cpp index c7a067bd86..305a56a3d1 100644 --- a/Packet++/src/NflogLayer.cpp +++ b/Packet++/src/NflogLayer.cpp @@ -9,102 +9,97 @@ #include - namespace pcpp { - /** IPv4 protocol */ - #define PCPP_WS_NFPROTO_IPV4 2 - /** IPv6 protocol */ - #define PCPP_WS_NFPROTO_IPV6 10 - - -uint8_t NflogLayer::getFamily() -{ - return getNflogHeader()->addressFamily; -} +/** IPv4 protocol */ +#define PCPP_WS_NFPROTO_IPV4 2 +/** IPv6 protocol */ +#define PCPP_WS_NFPROTO_IPV6 10 -uint8_t NflogLayer::getVersion() -{ - return getNflogHeader()->version; -} - -uint16_t NflogLayer::getResourceId() -{ - return be16toh(getNflogHeader()->resourceId); -} - -NflogTlv NflogLayer::getTlvByType(NflogTlvType type) const -{ - NflogTlv tlv = m_TlvReader.getTLVRecord( - static_cast (type), - getTlvsBasePtr(), - m_DataLen - sizeof(nflog_header)); - - return tlv; -} - -void NflogLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(nflog_header)) - return; - auto payloadInfo = getTlvByType(NflogTlvType::NFULA_PAYLOAD); - if (payloadInfo.isNull()) + uint8_t NflogLayer::getFamily() { - return; + return getNflogHeader()->addressFamily; } - uint8_t* payload = payloadInfo.getValue(); - size_t payloadLen = payloadInfo.getTotalSize() - sizeof(uint16_t) * 2; - - uint8_t family = getFamily(); + uint8_t NflogLayer::getVersion() + { + return getNflogHeader()->version; + } - switch (family) + uint16_t NflogLayer::getResourceId() { - case PCPP_WS_NFPROTO_IPV4: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_WS_NFPROTO_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + return be16toh(getNflogHeader()->resourceId); } -} + NflogTlv NflogLayer::getTlvByType(NflogTlvType type) const + { + const auto typeNum = static_cast(type); + NflogTlv tlv = m_TlvReader.getTLVRecord(typeNum, getTlvsBasePtr(), m_DataLen - sizeof(nflog_header)); -size_t NflogLayer::getHeaderLen() const -{ - size_t headerLen = sizeof(nflog_header); - NflogTlv currentTLV = m_TlvReader.getFirstTLVRecord( - getTlvsBasePtr(), - m_DataLen - sizeof(nflog_header)); + return tlv; + } - while (!currentTLV.isNull() && currentTLV.getType() != static_cast (NflogTlvType::NFULA_PAYLOAD)) + void NflogLayer::parseNextLayer() { - headerLen += currentTLV.getTotalSize(); - currentTLV = m_TlvReader.getNextTLVRecord(currentTLV, getTlvsBasePtr(), m_DataLen - sizeof(nflog_header)); + if (m_DataLen <= sizeof(nflog_header)) + { + return; + } + auto payloadInfo = getTlvByType(NflogTlvType::NFULA_PAYLOAD); + if (payloadInfo.isNull()) + { + return; + } + + uint8_t* payload = payloadInfo.getValue(); + size_t payloadLen = payloadInfo.getTotalSize() - sizeof(uint16_t) * 2; + + uint8_t family = getFamily(); + + switch (family) + { + case PCPP_WS_NFPROTO_IPV4: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_WS_NFPROTO_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } } - if (!currentTLV.isNull() && currentTLV.getType() == static_cast (NflogTlvType::NFULA_PAYLOAD)) + + size_t NflogLayer::getHeaderLen() const { - // for the length and type of the payload TLV - headerLen += 2 * sizeof (uint16_t); + size_t headerLen = sizeof(nflog_header); + NflogTlv currentTLV = m_TlvReader.getFirstTLVRecord(getTlvsBasePtr(), m_DataLen - sizeof(nflog_header)); + + while (!currentTLV.isNull() && currentTLV.getType() != static_cast(NflogTlvType::NFULA_PAYLOAD)) + { + headerLen += currentTLV.getTotalSize(); + currentTLV = m_TlvReader.getNextTLVRecord(currentTLV, getTlvsBasePtr(), m_DataLen - sizeof(nflog_header)); + } + if (!currentTLV.isNull() && currentTLV.getType() == static_cast(NflogTlvType::NFULA_PAYLOAD)) + { + // for the length and type of the payload TLV + headerLen += 2 * sizeof(uint16_t); + } + // nflog_header has not a form of TLV and contains 3 fields (family, resource_id, version) + return headerLen; } - // nflog_header has not a form of TLV and contains 3 fields (family, resource_id, version) - return headerLen; -} -std::string NflogLayer::toString() const -{ - return "Linux Netfilter NFLOG"; -} + std::string NflogLayer::toString() const + { + return "Linux Netfilter NFLOG"; + } -bool NflogLayer::isDataValid(const uint8_t* data, size_t dataLen) -{ - return data && dataLen >= sizeof(nflog_header); -} + bool NflogLayer::isDataValid(const uint8_t* data, size_t dataLen) + { + return data && dataLen >= sizeof(nflog_header); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/NtpLayer.cpp b/Packet++/src/NtpLayer.cpp index 6c135852e5..6fc1220ee7 100644 --- a/Packet++/src/NtpLayer.cpp +++ b/Packet++/src/NtpLayer.cpp @@ -17,609 +17,615 @@ namespace pcpp { - NtpLayer::NtpLayer() - { - m_DataLen = sizeof(ntp_header); - m_Data = new uint8_t[sizeof(ntp_header)]; - memset(m_Data, 0, sizeof(ntp_header)); - m_Protocol = NTP; - } - - NtpLayer::LeapIndicator NtpLayer::getLeapIndicator() const - { - if (getNtpHeader()->leapIndicator < 4) // Since leap indicator field is 2bit - return static_cast(getNtpHeader()->leapIndicator); - PCPP_LOG_ERROR("Unknown NTP Leap Indicator"); - return Unknown; - } - - void NtpLayer::setLeapIndicator(LeapIndicator val) - { - getNtpHeader()->leapIndicator = val; - } - - uint8_t NtpLayer::getVersion() const - { - return getNtpHeader()->version; - } - - void NtpLayer::setVersion(uint8_t val) - { - getNtpHeader()->version = val; - } - - NtpLayer::Mode NtpLayer::getMode() const - { - if (getNtpHeader()->mode < 8) // Since mode field 3bit - return static_cast(getNtpHeader()->mode); - PCPP_LOG_ERROR("Unknown NTP Mode"); - return Reserved; - } - - std::string NtpLayer::getModeString() const - { - switch (getMode()) - { - case Reserved: - return "Reserved"; - case SymActive: - return "Symmetrically Active"; - case SymPassive: - return "Symmetrically Passive"; - case Client: - return "Client"; - case Server: - return "Server"; - case Broadcast: - return "Broadcast"; - case Control: - return "Control"; - case PrivateUse: - return "Private Use"; - default: - PCPP_LOG_ERROR("Unknown NTP Mode"); - return std::string(); - } - } - - void NtpLayer::setMode(Mode val) - { - getNtpHeader()->mode = val; - } - - uint8_t NtpLayer::getStratum() const - { - return getNtpHeader()->stratum; - } - - void NtpLayer::setStratum(uint8_t val) - { - getNtpHeader()->stratum = val; - } - - int8_t NtpLayer::getPollInterval() const - { - return getNtpHeader()->pollInterval; - } - - void NtpLayer::setPollInterval(int8_t val) - { - getNtpHeader()->pollInterval = val; - } - - double NtpLayer::getPollIntervalInSecs() const - { - return pow(2, getPollInterval()); - } - - int8_t NtpLayer::getPrecision() const - { - return getNtpHeader()->precision; - } - - void NtpLayer::setPrecision(int8_t val) - { - getNtpHeader()->precision = val; - } - - double NtpLayer::getPrecisionInSecs() const - { - return pow(2, getPrecision()); - } - - uint32_t NtpLayer::getRootDelay() const - { - return getNtpHeader()->rootDelay; - } - - void NtpLayer::setRootDelay(uint32_t val) - { - getNtpHeader()->rootDelay = val; - } - - double NtpLayer::getRootDelayInSecs() const - { - return convertFromShortFormat(getRootDelay()); - } - - void NtpLayer::setRootDelayInSecs(double val) - { - getNtpHeader()->rootDelay = convertToShortFormat(val); - } - - uint32_t NtpLayer::getRootDispersion() const - { - return getNtpHeader()->rootDispersion; - } - - void NtpLayer::setRootDispersion(uint32_t val) - { - getNtpHeader()->rootDispersion = val; - } - - double NtpLayer::getRootDispersionInSecs() const - { - return convertFromShortFormat(getRootDispersion()); - } - - void NtpLayer::setRootDispersionInSecs(double val) - { - getNtpHeader()->rootDispersion = convertToShortFormat(val); - } - - uint32_t NtpLayer::getReferenceIdentifier() const - { - return getNtpHeader()->referenceIdentifier; - } - - void NtpLayer::setReferenceIdentifier(IPv4Address val) - { - getNtpHeader()->referenceIdentifier = val.toInt(); - } - - void NtpLayer::setReferenceIdentifier(ClockSource val) - { - getNtpHeader()->referenceIdentifier = static_cast(val); - } - - void NtpLayer::setReferenceIdentifier(KissODeath val) - { - getNtpHeader()->referenceIdentifier = static_cast(val); - } - - std::string NtpLayer::getReferenceIdentifierString() const - { - uint8_t stratum = getStratum(); - uint8_t version = getVersion(); - uint32_t refID = getReferenceIdentifier(); - - if (stratum == 0) - { - switch (version) - { - case 3: - { - switch (static_cast(refID)) - { - case ClockSource::DCN: - return "DCN routing protocol"; - case ClockSource::NIST: - return "NIST public modem"; - case ClockSource::TSP: - return "TSP time protocol"; - case ClockSource::DTS: - return "Digital Time Service"; - default: - return "Unknown"; - } - } - case 4: - { - switch (static_cast(refID)) - { - case KissODeath::ACST: - return "The association belongs to a anycast server"; - case KissODeath::AUTH: - return "Server authentication failed"; - case KissODeath::AUTO: - return "Autokey sequence failed"; - case KissODeath::BCST: - return "The association belongs to a broadcast server"; - case KissODeath::CRYP: - return "Cryptographic authentication or identification failed"; - case KissODeath::DENY: - return "Access denied by remote server"; - case KissODeath::DROP: - return "Lost peer in symmetric mode"; - case KissODeath::RSTR: - return "Access denied due to local policy"; - case KissODeath::INIT: - return "The association has not yet synchronized for the first time"; - case KissODeath::MCST: - return "The association belongs to a manycast server"; - case KissODeath::NKEY: - return "No key found. Either the key was never installed or is not trusted"; - case KissODeath::RATE: - return "Rate exceeded. The server has temporarily denied access because the client exceeded the rate " - "threshold"; - case KissODeath::RMOT: - return "Somebody is tinkering with the association from a remote host running ntpdc. Not to worry " - "unless some rascal has stolen your keys"; - case KissODeath::STEP: - return "A step change in system time has occurred, but the association has not yet resynchronized"; - default: - { - char arrBuff[5] = {static_cast((refID >> 24) & 0xFF), static_cast((refID >> 16) & 0xFF), - static_cast((refID >> 8) & 0xFF), static_cast((refID) & 0xFF), '\0'}; - return arrBuff; - } - } - } - } - } - else if (stratum == 1) - { - switch (version) - { - case 3: - { - switch (static_cast(refID)) - { - case ClockSource::ATOM: - return "Atomic clock"; - case ClockSource::VLF: - return "VLF radio"; - case ClockSource::LORC: - return "LORAN-C radionavigation"; - case ClockSource::GOES: - return "GOES UHF environment satellite"; - case ClockSource::GPS: - return "GPS UHF satellite positioning"; - default: - return "Unknown"; - } - } - case 4: - { - switch (static_cast(refID)) - { - case ClockSource::GOES: - return "Geosynchronous Orbit Environment Satellite"; - case ClockSource::GPS: - return "Global Position System"; - case ClockSource::GAL: - return "Galileo Positioning System"; - case ClockSource::PPS: - return "Generic pulse-per-second"; - case ClockSource::IRIG: - return "Inter-Range Instrumentation Group"; - case ClockSource::WWVB: - return "LF Radio WWVB Ft. Collins, CO 60 kHz"; - case ClockSource::DCF: - return "LF Radio DCF77 Mainflingen, DE 77.5 kHz"; - case ClockSource::HBG: - return "LF Radio HBG Prangins, HB 75 kHz"; - case ClockSource::MSF: - return "LF Radio MSF Anthorn, UK 60 kHz"; - case ClockSource::JJY: - return "LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz"; - case ClockSource::LORC: - return "MF Radio LORAN C station, 100 kHz"; - case ClockSource::TDF: - return "MF Radio Allouis, FR 162 kHz"; - case ClockSource::CHU: - return "HF Radio CHU Ottawa, Ontario"; - case ClockSource::WWV: - return "HF Radio WWV Ft. Collins, CO"; - case ClockSource::WWVH: - return "HF Radio WWVH Kauai, HI"; - case ClockSource::NIST: - return "NIST telephone modem"; - case ClockSource::ACTS: - return "NIST telephone modem"; - case ClockSource::USNO: - return "USNO telephone modem"; - case ClockSource::PTB: - return "European telephone modem"; - case ClockSource::MRS: - return "Multi Reference Sources"; - case ClockSource::XFAC: - return "Inter Face Association Changed"; - case ClockSource::STEP: - return "Step time change"; - case ClockSource::GOOG: - return "Google NTP servers"; - case ClockSource::DCFa: - return "Meinberg DCF77 with amplitude modulation"; - case ClockSource::DCFp: - return "Meinberg DCF77 with phase modulation)/pseudo random phase modulation"; - case ClockSource::GPSs: - return "Meinberg GPS (with shared memory access)"; - case ClockSource::GPSi: - return "Meinberg GPS (with interrupt based access)"; - case ClockSource::GLNs: - return "Meinberg GPS/GLONASS (with shared memory access)"; - case ClockSource::GLNi: - return "Meinberg GPS/GLONASS (with interrupt based access)"; - case ClockSource::LCL: - return "Meinberg Undisciplined local clock"; - case ClockSource::LOCL: - return "Meinberg Undisciplined local clock"; - default: - return "Unknown"; - } - } - } - } - else - { - // TODO: Support IPv6 cases for NTPv4, it equals to MD5 hash of first four octets of IPv6 address - - pcpp::IPv4Address addr(getReferenceIdentifier()); - return addr.toString(); - } - - PCPP_LOG_ERROR("Unknown Stratum type"); - return std::string(); - } - - uint64_t NtpLayer::getReferenceTimestamp() const - { - return getNtpHeader()->referenceTimestamp; - } - - void NtpLayer::setReferenceTimestamp(uint64_t val) - { - getNtpHeader()->referenceTimestamp = val; - } - - double NtpLayer::getReferenceTimestampInSecs() const - { - return convertFromTimestampFormat(getReferenceTimestamp()); - } - - void NtpLayer::setReferenceTimestampInSecs(double val) - { - getNtpHeader()->referenceTimestamp = convertToTimestampFormat(val); - } - - std::string NtpLayer::getReferenceTimestampAsString() - { - return convertToIsoFormat(getReferenceTimestamp()); - } - - uint64_t NtpLayer::getOriginTimestamp() const - { - return getNtpHeader()->originTimestamp; - } - - void NtpLayer::setOriginTimestamp(uint64_t val) - { - getNtpHeader()->originTimestamp = val; - } - - double NtpLayer::getOriginTimestampInSecs() const - { - return convertFromTimestampFormat(getOriginTimestamp()); - } - - void NtpLayer::setOriginTimestampInSecs(double val) - { - getNtpHeader()->originTimestamp = convertToTimestampFormat(val); - } - - std::string NtpLayer::getOriginTimestampAsString() - { - return convertToIsoFormat(getOriginTimestamp()); - } - - uint64_t NtpLayer::getReceiveTimestamp() const - { - return getNtpHeader()->receiveTimestamp; - } - - void NtpLayer::setReceiveTimestamp(uint64_t val) - { - getNtpHeader()->receiveTimestamp = val; - } - - double NtpLayer::getReceiveTimestampInSecs() const - { - return convertFromTimestampFormat(getReceiveTimestamp()); - } - - void NtpLayer::setReceiveTimestampInSecs(double val) - { - getNtpHeader()->receiveTimestamp = convertToTimestampFormat(val); - } - - std::string NtpLayer::getReceiveTimestampAsString() - { - return convertToIsoFormat(getReceiveTimestamp()); - } - - uint64_t NtpLayer::getTransmitTimestamp() const - { - return getNtpHeader()->transmitTimestamp; - } - - void NtpLayer::setTransmitTimestamp(uint64_t val) - { - getNtpHeader()->transmitTimestamp = val; - } - - double NtpLayer::getTransmitTimestampInSecs() const - { - return convertFromTimestampFormat(getTransmitTimestamp()); - } - - void NtpLayer::setTransmitTimestampInSecs(double val) - { - getNtpHeader()->transmitTimestamp = convertToTimestampFormat(val); - } - - std::string NtpLayer::getTransmitTimestampAsString() - { - return convertToIsoFormat(getTransmitTimestamp()); - } - - uint32_t NtpLayer::getKeyID() const - { - switch (getVersion()) - { - case 3: - { - if (m_DataLen < (sizeof(ntp_header) + sizeof(ntp_v3_auth))) - return 0; - - ntp_v3_auth *header = (ntp_v3_auth *)(m_Data + sizeof(ntp_header)); - return header->keyID; - } - case 4: - { - // TODO: Add support for extension fields - if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_md5))) - { - ntp_v4_auth_md5 *header = (ntp_v4_auth_md5 *)(m_Data + m_DataLen - sizeof(ntp_v4_auth_md5)); - return header->keyID; - } - if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_sha1))) - { - ntp_v4_auth_sha1 *header = (ntp_v4_auth_sha1 *)(m_Data + m_DataLen - sizeof(ntp_v4_auth_sha1)); - return header->keyID; - } - - PCPP_LOG_ERROR("NTP authentication parsing with extension fields are not supported"); - return 0; - } - default: - { - PCPP_LOG_ERROR("NTP version not supported"); - return 0; - } - } - } - - std::string NtpLayer::getDigest() const - { - switch (getVersion()) - { - case 3: - { - if (m_DataLen < (sizeof(ntp_header) + sizeof(ntp_v3_auth))) - return std::string(); - - ntp_v3_auth *header = (ntp_v3_auth *)(m_Data + sizeof(ntp_header)); - return byteArrayToHexString(header->dgst, 8); - } - case 4: - { - if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_md5))) - { - ntp_v4_auth_md5 *header = (ntp_v4_auth_md5 *)(m_Data + m_DataLen - sizeof(ntp_v4_auth_md5)); - return byteArrayToHexString(header->dgst, 16); - } - if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_sha1))) - { - ntp_v4_auth_sha1 *header = (ntp_v4_auth_sha1 *)(m_Data + m_DataLen - sizeof(ntp_v4_auth_sha1)); - return byteArrayToHexString(header->dgst, 20); - } - - PCPP_LOG_ERROR("NTP authentication parsing with extension fields are not supported"); - return std::string(); - } - default: - PCPP_LOG_ERROR("NTP version not supported"); - return std::string(); - } - } - - double NtpLayer::convertFromShortFormat(const uint32_t val) - { - double integerPart = netToHost16(val & 0xFFFF); - double fractionPart = netToHost16(((val & 0xFFFF0000) >> 16)) / NTP_FRIC; - - return integerPart + fractionPart; - } - - double NtpLayer::convertFromTimestampFormat(const uint64_t val) - { - double integerPart = netToHost32(val & 0xFFFFFFFF); - double fractionPart = netToHost32(((val & 0xFFFFFFFF00000000) >> 32)) / NTP_FRAC; - - // TODO: Return integer and fraction parts as struct to increase precision - // Offset change should be done here because of overflow - return integerPart + fractionPart - EPOCH_OFFSET; - } - - uint32_t NtpLayer::convertToShortFormat(const double val) - { - double integerPart; - double fractionPart = modf(val, &integerPart); - - // Cast values to 16bit - uint32_t integerPartInt = hostToNet16(integerPart); - uint32_t fractionPartInt = hostToNet16(fractionPart * NTP_FRIC); - - return integerPartInt | (fractionPartInt << 16); - } - - uint64_t NtpLayer::convertToTimestampFormat(const double val) - { - double integerPart; - double fractionPart = modf(val, &integerPart); - - // Cast values to 32bit - uint64_t integerPartInt = hostToNet32(integerPart + EPOCH_OFFSET); - uint64_t fractionPartInt = hostToNet32(fractionPart * NTP_FRAC); - - return integerPartInt | (fractionPartInt << 32); - } - - std::string NtpLayer::convertToIsoFormat(const double timestamp) - { - double integerPart; - double fractionPart = modf(timestamp, &integerPart); - - struct tm *timer; - time_t timeStruct = integerPart; + NtpLayer::NtpLayer() + { + m_DataLen = sizeof(ntp_header); + m_Data = new uint8_t[sizeof(ntp_header)]; + memset(m_Data, 0, sizeof(ntp_header)); + m_Protocol = NTP; + } + + NtpLayer::LeapIndicator NtpLayer::getLeapIndicator() const + { + if (getNtpHeader()->leapIndicator < 4) // Since leap indicator field is 2bit + return static_cast(getNtpHeader()->leapIndicator); + PCPP_LOG_ERROR("Unknown NTP Leap Indicator"); + return Unknown; + } + + void NtpLayer::setLeapIndicator(LeapIndicator val) + { + getNtpHeader()->leapIndicator = val; + } + + uint8_t NtpLayer::getVersion() const + { + return getNtpHeader()->version; + } + + void NtpLayer::setVersion(uint8_t val) + { + getNtpHeader()->version = val; + } + + NtpLayer::Mode NtpLayer::getMode() const + { + if (getNtpHeader()->mode < 8) // Since mode field 3bit + return static_cast(getNtpHeader()->mode); + PCPP_LOG_ERROR("Unknown NTP Mode"); + return Reserved; + } + + std::string NtpLayer::getModeString() const + { + switch (getMode()) + { + case Reserved: + return "Reserved"; + case SymActive: + return "Symmetrically Active"; + case SymPassive: + return "Symmetrically Passive"; + case Client: + return "Client"; + case Server: + return "Server"; + case Broadcast: + return "Broadcast"; + case Control: + return "Control"; + case PrivateUse: + return "Private Use"; + default: + PCPP_LOG_ERROR("Unknown NTP Mode"); + return std::string(); + } + } + + void NtpLayer::setMode(Mode val) + { + getNtpHeader()->mode = val; + } + + uint8_t NtpLayer::getStratum() const + { + return getNtpHeader()->stratum; + } + + void NtpLayer::setStratum(uint8_t val) + { + getNtpHeader()->stratum = val; + } + + int8_t NtpLayer::getPollInterval() const + { + return getNtpHeader()->pollInterval; + } + + void NtpLayer::setPollInterval(int8_t val) + { + getNtpHeader()->pollInterval = val; + } + + double NtpLayer::getPollIntervalInSecs() const + { + return pow(2, getPollInterval()); + } + + int8_t NtpLayer::getPrecision() const + { + return getNtpHeader()->precision; + } + + void NtpLayer::setPrecision(int8_t val) + { + getNtpHeader()->precision = val; + } + + double NtpLayer::getPrecisionInSecs() const + { + return pow(2, getPrecision()); + } + + uint32_t NtpLayer::getRootDelay() const + { + return getNtpHeader()->rootDelay; + } + + void NtpLayer::setRootDelay(uint32_t val) + { + getNtpHeader()->rootDelay = val; + } + + double NtpLayer::getRootDelayInSecs() const + { + return convertFromShortFormat(getRootDelay()); + } + + void NtpLayer::setRootDelayInSecs(double val) + { + getNtpHeader()->rootDelay = convertToShortFormat(val); + } + + uint32_t NtpLayer::getRootDispersion() const + { + return getNtpHeader()->rootDispersion; + } + + void NtpLayer::setRootDispersion(uint32_t val) + { + getNtpHeader()->rootDispersion = val; + } + + double NtpLayer::getRootDispersionInSecs() const + { + return convertFromShortFormat(getRootDispersion()); + } + + void NtpLayer::setRootDispersionInSecs(double val) + { + getNtpHeader()->rootDispersion = convertToShortFormat(val); + } + + uint32_t NtpLayer::getReferenceIdentifier() const + { + return getNtpHeader()->referenceIdentifier; + } + + void NtpLayer::setReferenceIdentifier(IPv4Address val) + { + getNtpHeader()->referenceIdentifier = val.toInt(); + } + + void NtpLayer::setReferenceIdentifier(ClockSource val) + { + getNtpHeader()->referenceIdentifier = static_cast(val); + } + + void NtpLayer::setReferenceIdentifier(KissODeath val) + { + getNtpHeader()->referenceIdentifier = static_cast(val); + } + + std::string NtpLayer::getReferenceIdentifierString() const + { + uint8_t stratum = getStratum(); + uint8_t version = getVersion(); + uint32_t refID = getReferenceIdentifier(); + + if (stratum == 0) + { + switch (version) + { + case 3: + { + switch (static_cast(refID)) + { + case ClockSource::DCN: + return "DCN routing protocol"; + case ClockSource::NIST: + return "NIST public modem"; + case ClockSource::TSP: + return "TSP time protocol"; + case ClockSource::DTS: + return "Digital Time Service"; + default: + return "Unknown"; + } + } + case 4: + { + switch (static_cast(refID)) + { + case KissODeath::ACST: + return "The association belongs to a anycast server"; + case KissODeath::AUTH: + return "Server authentication failed"; + case KissODeath::AUTO: + return "Autokey sequence failed"; + case KissODeath::BCST: + return "The association belongs to a broadcast server"; + case KissODeath::CRYP: + return "Cryptographic authentication or identification failed"; + case KissODeath::DENY: + return "Access denied by remote server"; + case KissODeath::DROP: + return "Lost peer in symmetric mode"; + case KissODeath::RSTR: + return "Access denied due to local policy"; + case KissODeath::INIT: + return "The association has not yet synchronized for the first time"; + case KissODeath::MCST: + return "The association belongs to a manycast server"; + case KissODeath::NKEY: + return "No key found. Either the key was never installed or is not trusted"; + case KissODeath::RATE: + return "Rate exceeded. The server has temporarily denied access because the client exceeded the rate " + "threshold"; + case KissODeath::RMOT: + return "Somebody is tinkering with the association from a remote host running ntpdc. Not to worry " + "unless some rascal has stolen your keys"; + case KissODeath::STEP: + return "A step change in system time has occurred, but the association has not yet resynchronized"; + default: + { + // clang-format off + char arrBuff[5] = { + static_cast((refID >> 24) & 0xFF), + static_cast((refID >> 16) & 0xFF), + static_cast((refID >> 8) & 0xFF), + static_cast((refID) & 0xFF), '\0' + }; + // clang-format on + return arrBuff; + } + } + } + } + } + else if (stratum == 1) + { + switch (version) + { + case 3: + { + switch (static_cast(refID)) + { + case ClockSource::ATOM: + return "Atomic clock"; + case ClockSource::VLF: + return "VLF radio"; + case ClockSource::LORC: + return "LORAN-C radionavigation"; + case ClockSource::GOES: + return "GOES UHF environment satellite"; + case ClockSource::GPS: + return "GPS UHF satellite positioning"; + default: + return "Unknown"; + } + } + case 4: + { + switch (static_cast(refID)) + { + case ClockSource::GOES: + return "Geosynchronous Orbit Environment Satellite"; + case ClockSource::GPS: + return "Global Position System"; + case ClockSource::GAL: + return "Galileo Positioning System"; + case ClockSource::PPS: + return "Generic pulse-per-second"; + case ClockSource::IRIG: + return "Inter-Range Instrumentation Group"; + case ClockSource::WWVB: + return "LF Radio WWVB Ft. Collins, CO 60 kHz"; + case ClockSource::DCF: + return "LF Radio DCF77 Mainflingen, DE 77.5 kHz"; + case ClockSource::HBG: + return "LF Radio HBG Prangins, HB 75 kHz"; + case ClockSource::MSF: + return "LF Radio MSF Anthorn, UK 60 kHz"; + case ClockSource::JJY: + return "LF Radio JJY Fukushima, JP 40 kHz, Saga, JP 60 kHz"; + case ClockSource::LORC: + return "MF Radio LORAN C station, 100 kHz"; + case ClockSource::TDF: + return "MF Radio Allouis, FR 162 kHz"; + case ClockSource::CHU: + return "HF Radio CHU Ottawa, Ontario"; + case ClockSource::WWV: + return "HF Radio WWV Ft. Collins, CO"; + case ClockSource::WWVH: + return "HF Radio WWVH Kauai, HI"; + case ClockSource::NIST: + return "NIST telephone modem"; + case ClockSource::ACTS: + return "NIST telephone modem"; + case ClockSource::USNO: + return "USNO telephone modem"; + case ClockSource::PTB: + return "European telephone modem"; + case ClockSource::MRS: + return "Multi Reference Sources"; + case ClockSource::XFAC: + return "Inter Face Association Changed"; + case ClockSource::STEP: + return "Step time change"; + case ClockSource::GOOG: + return "Google NTP servers"; + case ClockSource::DCFa: + return "Meinberg DCF77 with amplitude modulation"; + case ClockSource::DCFp: + return "Meinberg DCF77 with phase modulation)/pseudo random phase modulation"; + case ClockSource::GPSs: + return "Meinberg GPS (with shared memory access)"; + case ClockSource::GPSi: + return "Meinberg GPS (with interrupt based access)"; + case ClockSource::GLNs: + return "Meinberg GPS/GLONASS (with shared memory access)"; + case ClockSource::GLNi: + return "Meinberg GPS/GLONASS (with interrupt based access)"; + case ClockSource::LCL: + return "Meinberg Undisciplined local clock"; + case ClockSource::LOCL: + return "Meinberg Undisciplined local clock"; + default: + return "Unknown"; + } + } + } + } + else + { + // TODO: Support IPv6 cases for NTPv4, it equals to MD5 hash of first four octets of IPv6 address + + pcpp::IPv4Address addr(getReferenceIdentifier()); + return addr.toString(); + } + + PCPP_LOG_ERROR("Unknown Stratum type"); + return std::string(); + } + + uint64_t NtpLayer::getReferenceTimestamp() const + { + return getNtpHeader()->referenceTimestamp; + } + + void NtpLayer::setReferenceTimestamp(uint64_t val) + { + getNtpHeader()->referenceTimestamp = val; + } + + double NtpLayer::getReferenceTimestampInSecs() const + { + return convertFromTimestampFormat(getReferenceTimestamp()); + } + + void NtpLayer::setReferenceTimestampInSecs(double val) + { + getNtpHeader()->referenceTimestamp = convertToTimestampFormat(val); + } + + std::string NtpLayer::getReferenceTimestampAsString() + { + return convertToIsoFormat(getReferenceTimestamp()); + } + + uint64_t NtpLayer::getOriginTimestamp() const + { + return getNtpHeader()->originTimestamp; + } + + void NtpLayer::setOriginTimestamp(uint64_t val) + { + getNtpHeader()->originTimestamp = val; + } + + double NtpLayer::getOriginTimestampInSecs() const + { + return convertFromTimestampFormat(getOriginTimestamp()); + } + + void NtpLayer::setOriginTimestampInSecs(double val) + { + getNtpHeader()->originTimestamp = convertToTimestampFormat(val); + } + + std::string NtpLayer::getOriginTimestampAsString() + { + return convertToIsoFormat(getOriginTimestamp()); + } + + uint64_t NtpLayer::getReceiveTimestamp() const + { + return getNtpHeader()->receiveTimestamp; + } + + void NtpLayer::setReceiveTimestamp(uint64_t val) + { + getNtpHeader()->receiveTimestamp = val; + } + + double NtpLayer::getReceiveTimestampInSecs() const + { + return convertFromTimestampFormat(getReceiveTimestamp()); + } + + void NtpLayer::setReceiveTimestampInSecs(double val) + { + getNtpHeader()->receiveTimestamp = convertToTimestampFormat(val); + } + + std::string NtpLayer::getReceiveTimestampAsString() + { + return convertToIsoFormat(getReceiveTimestamp()); + } + + uint64_t NtpLayer::getTransmitTimestamp() const + { + return getNtpHeader()->transmitTimestamp; + } + + void NtpLayer::setTransmitTimestamp(uint64_t val) + { + getNtpHeader()->transmitTimestamp = val; + } + + double NtpLayer::getTransmitTimestampInSecs() const + { + return convertFromTimestampFormat(getTransmitTimestamp()); + } + + void NtpLayer::setTransmitTimestampInSecs(double val) + { + getNtpHeader()->transmitTimestamp = convertToTimestampFormat(val); + } + + std::string NtpLayer::getTransmitTimestampAsString() + { + return convertToIsoFormat(getTransmitTimestamp()); + } + + uint32_t NtpLayer::getKeyID() const + { + switch (getVersion()) + { + case 3: + { + if (m_DataLen < (sizeof(ntp_header) + sizeof(ntp_v3_auth))) + return 0; + + ntp_v3_auth* header = (ntp_v3_auth*)(m_Data + sizeof(ntp_header)); + return header->keyID; + } + case 4: + { + // TODO: Add support for extension fields + if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_md5))) + { + ntp_v4_auth_md5* header = (ntp_v4_auth_md5*)(m_Data + m_DataLen - sizeof(ntp_v4_auth_md5)); + return header->keyID; + } + if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_sha1))) + { + ntp_v4_auth_sha1* header = (ntp_v4_auth_sha1*)(m_Data + m_DataLen - sizeof(ntp_v4_auth_sha1)); + return header->keyID; + } + + PCPP_LOG_ERROR("NTP authentication parsing with extension fields are not supported"); + return 0; + } + default: + { + PCPP_LOG_ERROR("NTP version not supported"); + return 0; + } + } + } + + std::string NtpLayer::getDigest() const + { + switch (getVersion()) + { + case 3: + { + if (m_DataLen < (sizeof(ntp_header) + sizeof(ntp_v3_auth))) + return std::string(); + + ntp_v3_auth* header = (ntp_v3_auth*)(m_Data + sizeof(ntp_header)); + return byteArrayToHexString(header->dgst, 8); + } + case 4: + { + if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_md5))) + { + ntp_v4_auth_md5* header = (ntp_v4_auth_md5*)(m_Data + m_DataLen - sizeof(ntp_v4_auth_md5)); + return byteArrayToHexString(header->dgst, 16); + } + if (m_DataLen == (sizeof(ntp_header) + sizeof(ntp_v4_auth_sha1))) + { + ntp_v4_auth_sha1* header = (ntp_v4_auth_sha1*)(m_Data + m_DataLen - sizeof(ntp_v4_auth_sha1)); + return byteArrayToHexString(header->dgst, 20); + } + + PCPP_LOG_ERROR("NTP authentication parsing with extension fields are not supported"); + return std::string(); + } + default: + PCPP_LOG_ERROR("NTP version not supported"); + return std::string(); + } + } + + double NtpLayer::convertFromShortFormat(const uint32_t val) + { + double integerPart = netToHost16(val & 0xFFFF); + double fractionPart = netToHost16(((val & 0xFFFF0000) >> 16)) / NTP_FRIC; + + return integerPart + fractionPart; + } + + double NtpLayer::convertFromTimestampFormat(const uint64_t val) + { + double integerPart = netToHost32(val & 0xFFFFFFFF); + double fractionPart = netToHost32(((val & 0xFFFFFFFF00000000) >> 32)) / NTP_FRAC; + + // TODO: Return integer and fraction parts as struct to increase precision + // Offset change should be done here because of overflow + return integerPart + fractionPart - EPOCH_OFFSET; + } + + uint32_t NtpLayer::convertToShortFormat(const double val) + { + double integerPart; + double fractionPart = modf(val, &integerPart); + + // Cast values to 16bit + uint32_t integerPartInt = hostToNet16(integerPart); + uint32_t fractionPartInt = hostToNet16(fractionPart * NTP_FRIC); + + return integerPartInt | (fractionPartInt << 16); + } + + uint64_t NtpLayer::convertToTimestampFormat(const double val) + { + double integerPart; + double fractionPart = modf(val, &integerPart); + + // Cast values to 32bit + uint64_t integerPartInt = hostToNet32(integerPart + EPOCH_OFFSET); + uint64_t fractionPartInt = hostToNet32(fractionPart * NTP_FRAC); + + return integerPartInt | (fractionPartInt << 32); + } + + std::string NtpLayer::convertToIsoFormat(const double timestamp) + { + double integerPart; + double fractionPart = modf(timestamp, &integerPart); + + struct tm* timer; + time_t timeStruct = integerPart; #if defined(_WIN32) - if (timeStruct < 0) - timeStruct = 0; - timer = gmtime(&timeStruct); + if (timeStruct < 0) + timeStruct = 0; + timer = gmtime(&timeStruct); #else - struct tm timer_r; - timer = gmtime_r(&timeStruct, &timer_r); + struct tm timer_r; + timer = gmtime_r(&timeStruct, &timer_r); - if (timer != nullptr) - timer = &timer_r; + if (timer != nullptr) + timer = &timer_r; #endif - if (timer == nullptr) - { - PCPP_LOG_ERROR("Can't convert time"); - return std::string(); - } - char buffer[50], bufferFraction[15]; - strftime(buffer, sizeof(buffer) - sizeof(bufferFraction), "%Y-%m-%dT%H:%M:%S", timer); - - snprintf(bufferFraction, sizeof(bufferFraction), "%.04lfZ", fabs(fractionPart)); - strncat(buffer, &bufferFraction[1], sizeof(bufferFraction)); - - return std::string(buffer); - } - - std::string NtpLayer::convertToIsoFormat(const uint64_t timestampInNTPformat) - { - return convertToIsoFormat(convertFromTimestampFormat(timestampInNTPformat)); - } - - bool NtpLayer::isDataValid(const uint8_t *data, size_t dataSize) - { - return data && dataSize >= sizeof(ntp_header); - } - - std::string NtpLayer::toString() const - { - return std::string("NTP Layer v") + std::to_string(getVersion()) + ", Mode: " + getModeString(); - } -} + if (timer == nullptr) + { + PCPP_LOG_ERROR("Can't convert time"); + return std::string(); + } + char buffer[50], bufferFraction[15]; + strftime(buffer, sizeof(buffer) - sizeof(bufferFraction), "%Y-%m-%dT%H:%M:%S", timer); + + snprintf(bufferFraction, sizeof(bufferFraction), "%.04lfZ", fabs(fractionPart)); + strncat(buffer, &bufferFraction[1], sizeof(bufferFraction)); + + return std::string(buffer); + } + + std::string NtpLayer::convertToIsoFormat(const uint64_t timestampInNTPformat) + { + return convertToIsoFormat(convertFromTimestampFormat(timestampInNTPformat)); + } + + bool NtpLayer::isDataValid(const uint8_t* data, size_t dataSize) + { + return data && dataSize >= sizeof(ntp_header); + } + + std::string NtpLayer::toString() const + { + return std::string("NTP Layer v") + std::to_string(getVersion()) + ", Mode: " + getModeString(); + } +} // namespace pcpp diff --git a/Packet++/src/NullLoopbackLayer.cpp b/Packet++/src/NullLoopbackLayer.cpp index 5f6b95b3e5..7f67472cce 100644 --- a/Packet++/src/NullLoopbackLayer.cpp +++ b/Packet++/src/NullLoopbackLayer.cpp @@ -9,99 +9,97 @@ namespace pcpp { #define BSWAP16(x) (((x) >> 8) | ((x) << 8)) -#define BSWAP32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) \ - | (((x) & 0x0000FF00) << 8) | ((x) << 24)) +#define BSWAP32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24)) #define IEEE_802_3_MAX_LEN 0x5dc -NullLoopbackLayer::NullLoopbackLayer(uint32_t family) -{ - const size_t dataLen = sizeof(uint32_t); - m_DataLen = dataLen; - m_Data = new uint8_t[dataLen]; - memset(m_Data, 0, dataLen); - m_Protocol = NULL_LOOPBACK; + NullLoopbackLayer::NullLoopbackLayer(uint32_t family) + { + const size_t dataLen = sizeof(uint32_t); + m_DataLen = dataLen; + m_Data = new uint8_t[dataLen]; + memset(m_Data, 0, dataLen); + m_Protocol = NULL_LOOPBACK; - setFamily(family); -} + setFamily(family); + } -uint32_t NullLoopbackLayer::getFamily() const -{ - uint32_t family = *(uint32_t*)m_Data; - if ((family & 0xFFFF0000) != 0) + uint32_t NullLoopbackLayer::getFamily() const { - if ((family & 0xFF000000) == 0 && (family & 0x00FF0000) < 0x00060000) + uint32_t family = *(uint32_t*)m_Data; + if ((family & 0xFFFF0000) != 0) { - family >>= 16; + if ((family & 0xFF000000) == 0 && (family & 0x00FF0000) < 0x00060000) + { + family >>= 16; + } + else + { + family = BSWAP32(family); + } } - else + else if ((family & 0x000000FF) == 0 && (family & 0x0000FF00) < 0x00000600) { - family = BSWAP32(family); + family = BSWAP16(family & 0xFFFF); } + + return family; } - else if ((family & 0x000000FF) == 0 && (family & 0x0000FF00) < 0x00000600) + + void NullLoopbackLayer::setFamily(uint32_t family) { - family = BSWAP16(family & 0xFFFF); + *m_Data = family; } - return family; -} - -void NullLoopbackLayer::setFamily(uint32_t family) -{ - *m_Data = family; -} + void NullLoopbackLayer::parseNextLayer() + { + uint8_t* payload = m_Data + sizeof(uint32_t); + size_t payloadLen = m_DataLen - sizeof(uint32_t); -void NullLoopbackLayer::parseNextLayer() -{ - uint8_t* payload = m_Data + sizeof(uint32_t); - size_t payloadLen = m_DataLen - sizeof(uint32_t); + uint32_t family = getFamily(); + if (family > IEEE_802_3_MAX_LEN) + { + uint16_t ethType = (uint16_t)family; + switch (ethType) + { + case PCPP_ETHERTYPE_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + return; + case PCPP_ETHERTYPE_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + return; + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + return; + } + } - uint32_t family = getFamily(); - if (family > IEEE_802_3_MAX_LEN) - { - uint16_t ethType = (uint16_t)family; - switch (ethType) + switch (family) { - case PCPP_ETHERTYPE_IP: + case PCPP_BSD_AF_INET: m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - return; - case PCPP_ETHERTYPE_IPV6: + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_BSD_AF_INET6_BSD: + case PCPP_BSD_AF_INET6_FREEBSD: + case PCPP_BSD_AF_INET6_DARWIN: m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - return; + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; default: m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - return; } } - switch (family) + std::string NullLoopbackLayer::toString() const { - case PCPP_BSD_AF_INET: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_BSD_AF_INET6_BSD: - case PCPP_BSD_AF_INET6_FREEBSD: - case PCPP_BSD_AF_INET6_DARWIN: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + return "Null/Loopback"; } -} - - -std::string NullLoopbackLayer::toString() const -{ - return "Null/Loopback"; -} -} +} // namespace pcpp diff --git a/Packet++/src/PPPoELayer.cpp b/Packet++/src/PPPoELayer.cpp index b5a7b190f8..25b07f4033 100644 --- a/Packet++/src/PPPoELayer.cpp +++ b/Packet++/src/PPPoELayer.cpp @@ -12,426 +12,435 @@ namespace pcpp { -/// PPPoELayer -/// ~~~~~~~~~~ + /// PPPoELayer + /// ~~~~~~~~~~ -PPPoELayer::PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId, size_t additionalBytesToAllocate) -{ - const size_t dataLen = sizeof(pppoe_header) + additionalBytesToAllocate; - m_DataLen = dataLen; - m_Data = new uint8_t[dataLen]; - memset(m_Data, 0, dataLen); - - pppoe_header* pppoeHdr = getPPPoEHeader(); - pppoeHdr->version = (version & 0xf); - pppoeHdr->type = (type & 0x0f); - pppoeHdr->code = code; - pppoeHdr->sessionId = htobe16(sessionId); - pppoeHdr->payloadLength = 0; -} - -void PPPoELayer::computeCalculateFields() -{ - pppoe_header* pppoeHdr = (pppoe_header*)m_Data; - pppoeHdr->payloadLength = htobe16(m_DataLen - sizeof(pppoe_header)); -} - - - -/// PPPoESessionLayer -/// ~~~~~~~~~~~~~~~~~ - - -void PPPoESessionLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; - - uint8_t* payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; - - switch (getPPPNextProtocol()) + PPPoELayer::PPPoELayer(uint8_t version, uint8_t type, PPPoELayer::PPPoECode code, uint16_t sessionId, + size_t additionalBytesToAllocate) { - case PCPP_PPP_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_PPP_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - break; + const size_t dataLen = sizeof(pppoe_header) + additionalBytesToAllocate; + m_DataLen = dataLen; + m_Data = new uint8_t[dataLen]; + memset(m_Data, 0, dataLen); + + pppoe_header* pppoeHdr = getPPPoEHeader(); + pppoeHdr->version = (version & 0xf); + pppoeHdr->type = (type & 0x0f); + pppoeHdr->code = code; + pppoeHdr->sessionId = htobe16(sessionId); + pppoeHdr->payloadLength = 0; } -} - -uint16_t PPPoESessionLayer::getPPPNextProtocol() const -{ - if (m_DataLen < getHeaderLen()) + void PPPoELayer::computeCalculateFields() { - PCPP_LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header"); - return 0; + pppoe_header* pppoeHdr = (pppoe_header*)m_Data; + pppoeHdr->payloadLength = htobe16(m_DataLen - sizeof(pppoe_header)); } - uint16_t pppNextProto = *(uint16_t*)(m_Data + sizeof(pppoe_header)); - return be16toh(pppNextProto); -} + /// PPPoESessionLayer + /// ~~~~~~~~~~~~~~~~~ -void PPPoESessionLayer::setPPPNextProtocol(uint16_t nextProtocol) -{ - if (m_DataLen < getHeaderLen()) + void PPPoESessionLayer::parseNextLayer() { - PCPP_LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header"); - return; + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; + + switch (getPPPNextProtocol()) + { + case PCPP_PPP_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_PPP_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + break; + } } - uint16_t* pppProto = (uint16_t*)(m_Data + sizeof(pppoe_header)); - *pppProto = htobe16(nextProtocol); -} - -std::unordered_map createPPPNextProtoToStringMap() -{ - std::unordered_map tempMap; - tempMap[PCPP_PPP_PADDING] = "Padding Protocol"; - tempMap[PCPP_PPP_ROHC_SCID] = "ROHC small-CID"; - tempMap[PCPP_PPP_ROHC_LCID] = "ROHC large-CID"; - tempMap[PCPP_PPP_IP] = "Internet Protocol version 4"; - tempMap[PCPP_PPP_OSI] = "OSI Network Layer"; - tempMap[PCPP_PPP_XNSIDP] = "Xerox NS IDP"; - tempMap[PCPP_PPP_DEC4] = "DECnet Phase IV"; - tempMap[PCPP_PPP_AT] = "Appletalk"; - tempMap[PCPP_PPP_IPX] = "Novell IPX"; - tempMap[PCPP_PPP_VJC_COMP] = "Van Jacobson Compressed TCP/IP"; - tempMap[PCPP_PPP_VJC_UNCOMP] = "Van Jacobson Uncompressed TCP/IP"; - tempMap[PCPP_PPP_BCP] = "Bridging PDU"; - tempMap[PCPP_PPP_ST] = "Stream Protocol (ST-II)"; - tempMap[PCPP_PPP_VINES] = "Banyan Vines"; - tempMap[PCPP_PPP_AT_EDDP] = "AppleTalk EDDP"; - tempMap[PCPP_PPP_AT_SB] = "AppleTalk SmartBuffered"; - tempMap[PCPP_PPP_MP] = "Multi-Link"; - tempMap[PCPP_PPP_NB] = "NETBIOS Framing"; - tempMap[PCPP_PPP_CISCO] = "Cisco Systems"; - tempMap[PCPP_PPP_ASCOM] = "Ascom Timeplex"; - tempMap[PCPP_PPP_LBLB] = "Fujitsu Link Backup and Load Balancing (LBLB)"; - tempMap[PCPP_PPP_RL] = "DCA Remote Lan"; - tempMap[PCPP_PPP_SDTP] = "Serial Data Transport Protocol (PPP-SDTP)"; - tempMap[PCPP_PPP_LLC] = "SNA over 802.2"; - tempMap[PCPP_PPP_SNA] = "SNA"; - tempMap[PCPP_PPP_IPV6HC] = "IPv6 Header Compression "; - tempMap[PCPP_PPP_KNX] = "KNX Bridging Data"; - tempMap[PCPP_PPP_ENCRYPT] = "Encryption"; - tempMap[PCPP_PPP_ILE] = "Individual Link Encryption"; - tempMap[PCPP_PPP_IPV6] = "Internet Protocol version 6"; - tempMap[PCPP_PPP_MUX] = "PPP Muxing"; - tempMap[PCPP_PPP_VSNP] = "Vendor-Specific Network Protocol (VSNP)"; - tempMap[PCPP_PPP_TNP] = "TRILL Network Protocol (TNP)"; - tempMap[PCPP_PPP_RTP_FH] = "RTP IPHC Full Header"; - tempMap[PCPP_PPP_RTP_CTCP] = "RTP IPHC Compressed TCP"; - tempMap[PCPP_PPP_RTP_CNTCP] = "RTP IPHC Compressed Non TCP"; - tempMap[PCPP_PPP_RTP_CUDP8] = "RTP IPHC Compressed UDP 8"; - tempMap[PCPP_PPP_RTP_CRTP8] = "RTP IPHC Compressed RTP 8"; - tempMap[PCPP_PPP_STAMPEDE] = "Stampede Bridging"; - tempMap[PCPP_PPP_MPPLUS] = "MP+ Protocol"; - tempMap[PCPP_PPP_NTCITS_IPI] = "NTCITS IPI"; - tempMap[PCPP_PPP_ML_SLCOMP] = "Single link compression in multilink"; - tempMap[PCPP_PPP_COMP] = "Compressed datagram"; - tempMap[PCPP_PPP_STP_HELLO] = "802.1d Hello Packets"; - tempMap[PCPP_PPP_IBM_SR] = "IBM Source Routing BPDU"; - tempMap[PCPP_PPP_DEC_LB] = "DEC LANBridge100 Spanning Tree"; - tempMap[PCPP_PPP_CDP] = "Cisco Discovery Protocol"; - tempMap[PCPP_PPP_NETCS] = "Netcs Twin Routing"; - tempMap[PCPP_PPP_STP] = "STP - Scheduled Transfer Protocol"; - tempMap[PCPP_PPP_EDP] = "EDP - Extreme Discovery Protocol"; - tempMap[PCPP_PPP_OSCP] = "Optical Supervisory Channel Protocol (OSCP)"; - tempMap[PCPP_PPP_OSCP2] = "Optical Supervisory Channel Protocol (OSCP)"; - tempMap[PCPP_PPP_LUXCOM] = "Luxcom"; - tempMap[PCPP_PPP_SIGMA] = "Sigma Network Systems"; - tempMap[PCPP_PPP_ACSP] = "Apple Client Server Protocol"; - tempMap[PCPP_PPP_MPLS_UNI] = "MPLS Unicast"; - tempMap[PCPP_PPP_MPLS_MULTI] = "MPLS Multicast"; - tempMap[PCPP_PPP_P12844] = "IEEE p1284.4 standard - data packets"; - tempMap[PCPP_PPP_TETRA] = "ETSI TETRA Network Protocol Type 1"; - tempMap[PCPP_PPP_MFTP] = "Multichannel Flow Treatment Protocol"; - tempMap[PCPP_PPP_RTP_CTCPND] = "RTP IPHC Compressed TCP No Delta"; - tempMap[PCPP_PPP_RTP_CS] = "RTP IPHC Context State"; - tempMap[PCPP_PPP_RTP_CUDP16] = "RTP IPHC Compressed UDP 16"; - tempMap[PCPP_PPP_RTP_CRDP16] = "RTP IPHC Compressed RTP 16"; - tempMap[PCPP_PPP_CCCP] = "Cray Communications Control Protocol"; - tempMap[PCPP_PPP_CDPD_MNRP] = "CDPD Mobile Network Registration Protocol"; - tempMap[PCPP_PPP_EXPANDAP] = "Expand accelerator protocol"; - tempMap[PCPP_PPP_ODSICP] = "ODSICP NCP"; - tempMap[PCPP_PPP_DOCSIS] = "DOCSIS DLL"; - tempMap[PCPP_PPP_CETACEANNDP] = "Cetacean Network Detection Protocol"; - tempMap[PCPP_PPP_LZS] = "Stacker LZS"; - tempMap[PCPP_PPP_REFTEK] = "RefTek Protocol"; - tempMap[PCPP_PPP_FC] = "Fibre Channel"; - tempMap[PCPP_PPP_EMIT] = "EMIT Protocols"; - tempMap[PCPP_PPP_VSP] = "Vendor-Specific Protocol (VSP)"; - tempMap[PCPP_PPP_TLSP] = "TRILL Link State Protocol (TLSP)"; - tempMap[PCPP_PPP_IPCP] = "Internet Protocol Control Protocol"; - tempMap[PCPP_PPP_OSINLCP] = "OSI Network Layer Control Protocol"; - tempMap[PCPP_PPP_XNSIDPCP] = "Xerox NS IDP Control Protocol"; - tempMap[PCPP_PPP_DECNETCP] = "DECnet Phase IV Control Protocol"; - tempMap[PCPP_PPP_ATCP] = "AppleTalk Control Protocol"; - tempMap[PCPP_PPP_IPXCP] = "Novell IPX Control Protocol"; - tempMap[PCPP_PPP_BRIDGENCP] = "Bridging NCP"; - tempMap[PCPP_PPP_SPCP] = "Stream Protocol Control Protocol"; - tempMap[PCPP_PPP_BVCP] = "Banyan Vines Control Protocol"; - tempMap[PCPP_PPP_MLCP] = "Multi-Link Control Protocol"; - tempMap[PCPP_PPP_NBCP] = "NETBIOS Framing Control Protocol"; - tempMap[PCPP_PPP_CISCOCP] = "Cisco Systems Control Protocol"; - tempMap[PCPP_PPP_ASCOMCP] = "Ascom Timeplex"; - tempMap[PCPP_PPP_LBLBCP] = "Fujitsu LBLB Control Protocol"; - tempMap[PCPP_PPP_RLNCP] = "DCA Remote Lan Network Control Protocol (RLNCP)"; - tempMap[PCPP_PPP_SDCP] = "Serial Data Control Protocol (PPP-SDCP)"; - tempMap[PCPP_PPP_LLCCP] = "SNA over 802.2 Control Protocol"; - tempMap[PCPP_PPP_SNACP] = "SNA Control Protocol"; - tempMap[PCPP_PPP_IP6HCCP] = "IP6 Header Compression Control Protocol"; - tempMap[PCPP_PPP_KNXCP] = "KNX Bridging Control Protocol"; - tempMap[PCPP_PPP_ECP] = "Encryption Control Protocol"; - tempMap[PCPP_PPP_ILECP] = "Individual Link Encryption Control Protocol"; - tempMap[PCPP_PPP_IPV6CP] = "IPv6 Control Protocol"; - tempMap[PCPP_PPP_MUXCP] = "PPP Muxing Control Protocol"; - tempMap[PCPP_PPP_VSNCP] = "Vendor-Specific Network Control Protocol (VSNCP)"; - tempMap[PCPP_PPP_TNCP] = "TRILL Network Control Protocol"; - tempMap[PCPP_PPP_STAMPEDECP] = "Stampede Bridging Control Protocol"; - tempMap[PCPP_PPP_MPPCP] = "MP+ Control Protocol"; - tempMap[PCPP_PPP_IPICP] = "NTCITS IPI Control Protocol"; - tempMap[PCPP_PPP_SLCC] = "Single link compression in multilink control"; - tempMap[PCPP_PPP_CCP] = "Compression Control Protocol"; - tempMap[PCPP_PPP_CDPCP] = "Cisco Discovery Protocol Control Protocol"; - tempMap[PCPP_PPP_NETCSCP] = "Netcs Twin Routing"; - tempMap[PCPP_PPP_STPCP] = "STP - Control Protocol"; - tempMap[PCPP_PPP_EDPCP] = "EDPCP - Extreme Discovery Protocol Control Protocol"; - tempMap[PCPP_PPP_ACSPC] = "Apple Client Server Protocol Control"; - tempMap[PCPP_PPP_MPLSCP] = "MPLS Control Protocol"; - tempMap[PCPP_PPP_P12844CP] = "IEEE p1284.4 standard - Protocol Control"; - tempMap[PCPP_PPP_TETRACP] = "ETSI TETRA TNP1 Control Protocol"; - tempMap[PCPP_PPP_MFTPCP] = "Multichannel Flow Treatment Protocol"; - tempMap[PCPP_PPP_LCP] = "Link Control Protocol"; - tempMap[PCPP_PPP_PAP] = "Password Authentication Protocol"; - tempMap[PCPP_PPP_LQR] = "Link Quality Report"; - tempMap[PCPP_PPP_SPAP] = "Shiva Password Authentication Protocol"; - tempMap[PCPP_PPP_CBCP] = "Callback Control Protocol (CBCP)"; - tempMap[PCPP_PPP_BACP] = "BACP Bandwidth Allocation Control Protocol"; - tempMap[PCPP_PPP_BAP] = "BAP Bandwidth Allocation Protocol"; - tempMap[PCPP_PPP_VSAP] = "Vendor-Specific Authentication Protocol (VSAP)"; - tempMap[PCPP_PPP_CONTCP] = "Container Control Protocol"; - tempMap[PCPP_PPP_CHAP] = "Challenge Handshake Authentication Protocol"; - tempMap[PCPP_PPP_RSAAP] = "RSA Authentication Protocol"; - tempMap[PCPP_PPP_EAP] = "Extensible Authentication Protocol"; - tempMap[PCPP_PPP_SIEP] = "Mitsubishi Security Information Exchange Protocol (SIEP)"; - tempMap[PCPP_PPP_SBAP] = "Stampede Bridging Authorization Protocol"; - tempMap[PCPP_PPP_PRPAP] = "Proprietary Authentication Protocol"; - tempMap[PCPP_PPP_PRPAP2] = "Proprietary Authentication Protocol"; - tempMap[PCPP_PPP_PRPNIAP] = "Proprietary Node ID Authentication Protocol"; - return tempMap; -} - -const std::unordered_map PPPNextProtoToString = createPPPNextProtoToStringMap(); - -std::string PPPoESessionLayer::toString() const -{ - std::unordered_map::const_iterator iter = PPPNextProtoToString.find(getPPPNextProtocol()); - std::string nextProtocol; - if (iter != PPPNextProtoToString.end()) - nextProtocol = iter->second; - else + uint16_t PPPoESessionLayer::getPPPNextProtocol() const { - std::ostringstream stream; - stream << "Unknown (0x" << std::hex << getPPPNextProtocol() << ")"; - nextProtocol = stream.str(); + if (m_DataLen < getHeaderLen()) + { + PCPP_LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header"); + return 0; + } + + uint16_t pppNextProto = *(uint16_t*)(m_Data + sizeof(pppoe_header)); + return be16toh(pppNextProto); } - return "PPP-over-Ethernet Session (followed by '" + nextProtocol + "')"; -} - - + void PPPoESessionLayer::setPPPNextProtocol(uint16_t nextProtocol) + { + if (m_DataLen < getHeaderLen()) + { + PCPP_LOG_ERROR("ERROR: size of layer is smaller then PPPoE session header"); + return; + } + + uint16_t* pppProto = (uint16_t*)(m_Data + sizeof(pppoe_header)); + *pppProto = htobe16(nextProtocol); + } -/// PPPoEDiscoveryLayer -/// ~~~~~~~~~~~~~~~~~~~ + std::unordered_map createPPPNextProtoToStringMap() + { + std::unordered_map tempMap; + tempMap[PCPP_PPP_PADDING] = "Padding Protocol"; + tempMap[PCPP_PPP_ROHC_SCID] = "ROHC small-CID"; + tempMap[PCPP_PPP_ROHC_LCID] = "ROHC large-CID"; + tempMap[PCPP_PPP_IP] = "Internet Protocol version 4"; + tempMap[PCPP_PPP_OSI] = "OSI Network Layer"; + tempMap[PCPP_PPP_XNSIDP] = "Xerox NS IDP"; + tempMap[PCPP_PPP_DEC4] = "DECnet Phase IV"; + tempMap[PCPP_PPP_AT] = "Appletalk"; + tempMap[PCPP_PPP_IPX] = "Novell IPX"; + tempMap[PCPP_PPP_VJC_COMP] = "Van Jacobson Compressed TCP/IP"; + tempMap[PCPP_PPP_VJC_UNCOMP] = "Van Jacobson Uncompressed TCP/IP"; + tempMap[PCPP_PPP_BCP] = "Bridging PDU"; + tempMap[PCPP_PPP_ST] = "Stream Protocol (ST-II)"; + tempMap[PCPP_PPP_VINES] = "Banyan Vines"; + tempMap[PCPP_PPP_AT_EDDP] = "AppleTalk EDDP"; + tempMap[PCPP_PPP_AT_SB] = "AppleTalk SmartBuffered"; + tempMap[PCPP_PPP_MP] = "Multi-Link"; + tempMap[PCPP_PPP_NB] = "NETBIOS Framing"; + tempMap[PCPP_PPP_CISCO] = "Cisco Systems"; + tempMap[PCPP_PPP_ASCOM] = "Ascom Timeplex"; + tempMap[PCPP_PPP_LBLB] = "Fujitsu Link Backup and Load Balancing (LBLB)"; + tempMap[PCPP_PPP_RL] = "DCA Remote Lan"; + tempMap[PCPP_PPP_SDTP] = "Serial Data Transport Protocol (PPP-SDTP)"; + tempMap[PCPP_PPP_LLC] = "SNA over 802.2"; + tempMap[PCPP_PPP_SNA] = "SNA"; + tempMap[PCPP_PPP_IPV6HC] = "IPv6 Header Compression "; + tempMap[PCPP_PPP_KNX] = "KNX Bridging Data"; + tempMap[PCPP_PPP_ENCRYPT] = "Encryption"; + tempMap[PCPP_PPP_ILE] = "Individual Link Encryption"; + tempMap[PCPP_PPP_IPV6] = "Internet Protocol version 6"; + tempMap[PCPP_PPP_MUX] = "PPP Muxing"; + tempMap[PCPP_PPP_VSNP] = "Vendor-Specific Network Protocol (VSNP)"; + tempMap[PCPP_PPP_TNP] = "TRILL Network Protocol (TNP)"; + tempMap[PCPP_PPP_RTP_FH] = "RTP IPHC Full Header"; + tempMap[PCPP_PPP_RTP_CTCP] = "RTP IPHC Compressed TCP"; + tempMap[PCPP_PPP_RTP_CNTCP] = "RTP IPHC Compressed Non TCP"; + tempMap[PCPP_PPP_RTP_CUDP8] = "RTP IPHC Compressed UDP 8"; + tempMap[PCPP_PPP_RTP_CRTP8] = "RTP IPHC Compressed RTP 8"; + tempMap[PCPP_PPP_STAMPEDE] = "Stampede Bridging"; + tempMap[PCPP_PPP_MPPLUS] = "MP+ Protocol"; + tempMap[PCPP_PPP_NTCITS_IPI] = "NTCITS IPI"; + tempMap[PCPP_PPP_ML_SLCOMP] = "Single link compression in multilink"; + tempMap[PCPP_PPP_COMP] = "Compressed datagram"; + tempMap[PCPP_PPP_STP_HELLO] = "802.1d Hello Packets"; + tempMap[PCPP_PPP_IBM_SR] = "IBM Source Routing BPDU"; + tempMap[PCPP_PPP_DEC_LB] = "DEC LANBridge100 Spanning Tree"; + tempMap[PCPP_PPP_CDP] = "Cisco Discovery Protocol"; + tempMap[PCPP_PPP_NETCS] = "Netcs Twin Routing"; + tempMap[PCPP_PPP_STP] = "STP - Scheduled Transfer Protocol"; + tempMap[PCPP_PPP_EDP] = "EDP - Extreme Discovery Protocol"; + tempMap[PCPP_PPP_OSCP] = "Optical Supervisory Channel Protocol (OSCP)"; + tempMap[PCPP_PPP_OSCP2] = "Optical Supervisory Channel Protocol (OSCP)"; + tempMap[PCPP_PPP_LUXCOM] = "Luxcom"; + tempMap[PCPP_PPP_SIGMA] = "Sigma Network Systems"; + tempMap[PCPP_PPP_ACSP] = "Apple Client Server Protocol"; + tempMap[PCPP_PPP_MPLS_UNI] = "MPLS Unicast"; + tempMap[PCPP_PPP_MPLS_MULTI] = "MPLS Multicast"; + tempMap[PCPP_PPP_P12844] = "IEEE p1284.4 standard - data packets"; + tempMap[PCPP_PPP_TETRA] = "ETSI TETRA Network Protocol Type 1"; + tempMap[PCPP_PPP_MFTP] = "Multichannel Flow Treatment Protocol"; + tempMap[PCPP_PPP_RTP_CTCPND] = "RTP IPHC Compressed TCP No Delta"; + tempMap[PCPP_PPP_RTP_CS] = "RTP IPHC Context State"; + tempMap[PCPP_PPP_RTP_CUDP16] = "RTP IPHC Compressed UDP 16"; + tempMap[PCPP_PPP_RTP_CRDP16] = "RTP IPHC Compressed RTP 16"; + tempMap[PCPP_PPP_CCCP] = "Cray Communications Control Protocol"; + tempMap[PCPP_PPP_CDPD_MNRP] = "CDPD Mobile Network Registration Protocol"; + tempMap[PCPP_PPP_EXPANDAP] = "Expand accelerator protocol"; + tempMap[PCPP_PPP_ODSICP] = "ODSICP NCP"; + tempMap[PCPP_PPP_DOCSIS] = "DOCSIS DLL"; + tempMap[PCPP_PPP_CETACEANNDP] = "Cetacean Network Detection Protocol"; + tempMap[PCPP_PPP_LZS] = "Stacker LZS"; + tempMap[PCPP_PPP_REFTEK] = "RefTek Protocol"; + tempMap[PCPP_PPP_FC] = "Fibre Channel"; + tempMap[PCPP_PPP_EMIT] = "EMIT Protocols"; + tempMap[PCPP_PPP_VSP] = "Vendor-Specific Protocol (VSP)"; + tempMap[PCPP_PPP_TLSP] = "TRILL Link State Protocol (TLSP)"; + tempMap[PCPP_PPP_IPCP] = "Internet Protocol Control Protocol"; + tempMap[PCPP_PPP_OSINLCP] = "OSI Network Layer Control Protocol"; + tempMap[PCPP_PPP_XNSIDPCP] = "Xerox NS IDP Control Protocol"; + tempMap[PCPP_PPP_DECNETCP] = "DECnet Phase IV Control Protocol"; + tempMap[PCPP_PPP_ATCP] = "AppleTalk Control Protocol"; + tempMap[PCPP_PPP_IPXCP] = "Novell IPX Control Protocol"; + tempMap[PCPP_PPP_BRIDGENCP] = "Bridging NCP"; + tempMap[PCPP_PPP_SPCP] = "Stream Protocol Control Protocol"; + tempMap[PCPP_PPP_BVCP] = "Banyan Vines Control Protocol"; + tempMap[PCPP_PPP_MLCP] = "Multi-Link Control Protocol"; + tempMap[PCPP_PPP_NBCP] = "NETBIOS Framing Control Protocol"; + tempMap[PCPP_PPP_CISCOCP] = "Cisco Systems Control Protocol"; + tempMap[PCPP_PPP_ASCOMCP] = "Ascom Timeplex"; + tempMap[PCPP_PPP_LBLBCP] = "Fujitsu LBLB Control Protocol"; + tempMap[PCPP_PPP_RLNCP] = "DCA Remote Lan Network Control Protocol (RLNCP)"; + tempMap[PCPP_PPP_SDCP] = "Serial Data Control Protocol (PPP-SDCP)"; + tempMap[PCPP_PPP_LLCCP] = "SNA over 802.2 Control Protocol"; + tempMap[PCPP_PPP_SNACP] = "SNA Control Protocol"; + tempMap[PCPP_PPP_IP6HCCP] = "IP6 Header Compression Control Protocol"; + tempMap[PCPP_PPP_KNXCP] = "KNX Bridging Control Protocol"; + tempMap[PCPP_PPP_ECP] = "Encryption Control Protocol"; + tempMap[PCPP_PPP_ILECP] = "Individual Link Encryption Control Protocol"; + tempMap[PCPP_PPP_IPV6CP] = "IPv6 Control Protocol"; + tempMap[PCPP_PPP_MUXCP] = "PPP Muxing Control Protocol"; + tempMap[PCPP_PPP_VSNCP] = "Vendor-Specific Network Control Protocol (VSNCP)"; + tempMap[PCPP_PPP_TNCP] = "TRILL Network Control Protocol"; + tempMap[PCPP_PPP_STAMPEDECP] = "Stampede Bridging Control Protocol"; + tempMap[PCPP_PPP_MPPCP] = "MP+ Control Protocol"; + tempMap[PCPP_PPP_IPICP] = "NTCITS IPI Control Protocol"; + tempMap[PCPP_PPP_SLCC] = "Single link compression in multilink control"; + tempMap[PCPP_PPP_CCP] = "Compression Control Protocol"; + tempMap[PCPP_PPP_CDPCP] = "Cisco Discovery Protocol Control Protocol"; + tempMap[PCPP_PPP_NETCSCP] = "Netcs Twin Routing"; + tempMap[PCPP_PPP_STPCP] = "STP - Control Protocol"; + tempMap[PCPP_PPP_EDPCP] = "EDPCP - Extreme Discovery Protocol Control Protocol"; + tempMap[PCPP_PPP_ACSPC] = "Apple Client Server Protocol Control"; + tempMap[PCPP_PPP_MPLSCP] = "MPLS Control Protocol"; + tempMap[PCPP_PPP_P12844CP] = "IEEE p1284.4 standard - Protocol Control"; + tempMap[PCPP_PPP_TETRACP] = "ETSI TETRA TNP1 Control Protocol"; + tempMap[PCPP_PPP_MFTPCP] = "Multichannel Flow Treatment Protocol"; + tempMap[PCPP_PPP_LCP] = "Link Control Protocol"; + tempMap[PCPP_PPP_PAP] = "Password Authentication Protocol"; + tempMap[PCPP_PPP_LQR] = "Link Quality Report"; + tempMap[PCPP_PPP_SPAP] = "Shiva Password Authentication Protocol"; + tempMap[PCPP_PPP_CBCP] = "Callback Control Protocol (CBCP)"; + tempMap[PCPP_PPP_BACP] = "BACP Bandwidth Allocation Control Protocol"; + tempMap[PCPP_PPP_BAP] = "BAP Bandwidth Allocation Protocol"; + tempMap[PCPP_PPP_VSAP] = "Vendor-Specific Authentication Protocol (VSAP)"; + tempMap[PCPP_PPP_CONTCP] = "Container Control Protocol"; + tempMap[PCPP_PPP_CHAP] = "Challenge Handshake Authentication Protocol"; + tempMap[PCPP_PPP_RSAAP] = "RSA Authentication Protocol"; + tempMap[PCPP_PPP_EAP] = "Extensible Authentication Protocol"; + tempMap[PCPP_PPP_SIEP] = "Mitsubishi Security Information Exchange Protocol (SIEP)"; + tempMap[PCPP_PPP_SBAP] = "Stampede Bridging Authorization Protocol"; + tempMap[PCPP_PPP_PRPAP] = "Proprietary Authentication Protocol"; + tempMap[PCPP_PPP_PRPAP2] = "Proprietary Authentication Protocol"; + tempMap[PCPP_PPP_PRPNIAP] = "Proprietary Node ID Authentication Protocol"; + return tempMap; + } + const std::unordered_map PPPNextProtoToString = createPPPNextProtoToStringMap(); -PPPoEDiscoveryLayer::PPPoETagTypes PPPoEDiscoveryLayer::PPPoETag::getType() const -{ - if (m_Data == nullptr) - return PPPoEDiscoveryLayer::PPPoETagTypes::PPPOE_TAG_EOL; + std::string PPPoESessionLayer::toString() const + { + auto findResult = PPPNextProtoToString.find(getPPPNextProtocol()); + std::string nextProtocol; + if (findResult != PPPNextProtoToString.end()) + nextProtocol = findResult->second; + else + { + std::ostringstream stream; + stream << "Unknown (0x" << std::hex << getPPPNextProtocol() << ")"; + nextProtocol = stream.str(); + } + + return "PPP-over-Ethernet Session (followed by '" + nextProtocol + "')"; + } - return (PPPoEDiscoveryLayer::PPPoETagTypes)be16toh(m_Data->recordType); -} + /// PPPoEDiscoveryLayer + /// ~~~~~~~~~~~~~~~~~~~ -size_t PPPoEDiscoveryLayer::PPPoETag::getTotalSize() const -{ - if (m_Data == nullptr) - return 0; + PPPoEDiscoveryLayer::PPPoETagTypes PPPoEDiscoveryLayer::PPPoETag::getType() const + { + if (m_Data == nullptr) + return PPPoEDiscoveryLayer::PPPoETagTypes::PPPOE_TAG_EOL; - return 2*sizeof(uint16_t) + be16toh(m_Data->recordLen); -} + return (PPPoEDiscoveryLayer::PPPoETagTypes)be16toh(m_Data->recordType); + } -size_t PPPoEDiscoveryLayer::PPPoETag::getDataSize() const -{ - if (m_Data == nullptr) - return 0; + size_t PPPoEDiscoveryLayer::PPPoETag::getTotalSize() const + { + if (m_Data == nullptr) + return 0; - return be16toh(m_Data->recordLen); -} + return 2 * sizeof(uint16_t) + be16toh(m_Data->recordLen); + } -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::PPPoETagBuilder::build() const -{ - size_t tagSize = 2*sizeof(uint16_t) + m_RecValueLen; - uint8_t* recordBuffer = new uint8_t[tagSize]; - uint16_t tagTypeVal = htobe16(static_cast(m_RecType)); - uint16_t tagLength = htobe16(static_cast(m_RecValueLen)); - memcpy(recordBuffer, &tagTypeVal, sizeof(uint16_t)); - memcpy(recordBuffer + sizeof(uint16_t), &tagLength, sizeof(uint16_t)); - if (tagLength > 0 && m_RecValue != nullptr) - memcpy(recordBuffer + 2*sizeof(uint16_t), m_RecValue, m_RecValueLen); - - return PPPoEDiscoveryLayer::PPPoETag(recordBuffer); -} - -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) const -{ - return m_TagReader.getTLVRecord(static_cast(tagType), getTagBasePtr(), m_DataLen - sizeof(pppoe_header)); -} + size_t PPPoEDiscoveryLayer::PPPoETag::getDataSize() const + { + if (m_Data == nullptr) + return 0; -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getFirstTag() const -{ - return m_TagReader.getFirstTLVRecord(getTagBasePtr(), m_DataLen - sizeof(pppoe_header)); -} + return be16toh(m_Data->recordLen); + } -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getNextTag(const PPPoEDiscoveryLayer::PPPoETag& tag) const -{ - return m_TagReader.getNextTLVRecord(const_cast(tag), getTagBasePtr(), m_DataLen - sizeof(pppoe_header)); -} + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::PPPoETagBuilder::build() const + { + size_t tagSize = 2 * sizeof(uint16_t) + m_RecValueLen; + uint8_t* recordBuffer = new uint8_t[tagSize]; + uint16_t tagTypeVal = htobe16(static_cast(m_RecType)); + uint16_t tagLength = htobe16(static_cast(m_RecValueLen)); + memcpy(recordBuffer, &tagTypeVal, sizeof(uint16_t)); + memcpy(recordBuffer + sizeof(uint16_t), &tagLength, sizeof(uint16_t)); + if (tagLength > 0 && m_RecValue != nullptr) + memcpy(recordBuffer + 2 * sizeof(uint16_t), m_RecValue, m_RecValueLen); + + return PPPoEDiscoveryLayer::PPPoETag(recordBuffer); + } -int PPPoEDiscoveryLayer::getTagCount() const -{ - return m_TagReader.getTLVRecordCount(getTagBasePtr(), m_DataLen - sizeof(pppoe_header)); -} + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) const + { + return m_TagReader.getTLVRecord(static_cast(tagType), getTagBasePtr(), + m_DataLen - sizeof(pppoe_header)); + } -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTagAt(const PPPoETagBuilder& tagBuilder, int offset) -{ - PPPoETag newTag = tagBuilder.build(); - if (newTag.isNull()) + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getFirstTag() const { - PCPP_LOG_ERROR("Cannot build new tag of type " << (int)newTag.getType()); - return newTag; + return m_TagReader.getFirstTLVRecord(getTagBasePtr(), m_DataLen - sizeof(pppoe_header)); } - size_t sizeToExtend = newTag.getTotalSize(); + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::getNextTag(const PPPoEDiscoveryLayer::PPPoETag& tag) const + { + return m_TagReader.getNextTLVRecord(const_cast(tag), getTagBasePtr(), + m_DataLen - sizeof(pppoe_header)); + } - if (!extendLayer(offset, sizeToExtend)) + int PPPoEDiscoveryLayer::getTagCount() const { - PCPP_LOG_ERROR("Could not extend PPPoEDiscoveryLayer in [" << sizeToExtend << "] bytes"); - newTag.purgeRecordData(); - return PPPoETag(nullptr); + return m_TagReader.getTLVRecordCount(getTagBasePtr(), m_DataLen - sizeof(pppoe_header)); } - memcpy(m_Data + offset, newTag.getRecordBasePtr(), newTag.getTotalSize()); + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTagAt(const PPPoETagBuilder& tagBuilder, int offset) + { + PPPoETag newTag = tagBuilder.build(); + if (newTag.isNull()) + { + PCPP_LOG_ERROR("Cannot build new tag of type " << (int)newTag.getType()); + return newTag; + } - uint8_t* newTagPtr = m_Data + offset; + size_t sizeToExtend = newTag.getTotalSize(); - m_TagReader.changeTLVRecordCount(1); + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend PPPoEDiscoveryLayer in [" << sizeToExtend << "] bytes"); + newTag.purgeRecordData(); + return PPPoETag(nullptr); + } - newTag.purgeRecordData(); + memcpy(m_Data + offset, newTag.getRecordBasePtr(), newTag.getTotalSize()); - getPPPoEHeader()->payloadLength += htobe16(sizeToExtend); + uint8_t* newTagPtr = m_Data + offset; - return PPPoETag(newTagPtr); -} + m_TagReader.changeTLVRecordCount(1); -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTagAfter(const PPPoETagBuilder& tagBuilder, PPPoETagTypes prevTagType) -{ - int offset = 0; + newTag.purgeRecordData(); - PPPoETag prevTag = getTag(prevTagType); + getPPPoEHeader()->payloadLength += htobe16(sizeToExtend); - if (prevTag.isNull()) - { - offset = getHeaderLen(); - } - else - { - offset = prevTag.getRecordBasePtr() + prevTag.getTotalSize() - m_Data; + return PPPoETag(newTagPtr); } - return addTagAt(tagBuilder, offset); -} + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTagAfter(const PPPoETagBuilder& tagBuilder, + PPPoETagTypes prevTagType) + { + int offset = 0; -PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTag(const PPPoETagBuilder& tagBuilder) -{ - return addTagAt(tagBuilder, getHeaderLen()); -} + PPPoETag prevTag = getTag(prevTagType); -size_t PPPoEDiscoveryLayer::getHeaderLen() const -{ - size_t payloadLen = sizeof(pppoe_header) + be16toh(getPPPoEHeader()->payloadLength); - if (payloadLen > m_DataLen) - return m_DataLen; + if (prevTag.isNull()) + { + offset = getHeaderLen(); + } + else + { + offset = prevTag.getRecordBasePtr() + prevTag.getTotalSize() - m_Data; + } - return payloadLen; -} + return addTagAt(tagBuilder, offset); + } -bool PPPoEDiscoveryLayer::removeTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) -{ - PPPoEDiscoveryLayer::PPPoETag tagToRemove = getTag(tagType); - if (tagToRemove.isNull()) + PPPoEDiscoveryLayer::PPPoETag PPPoEDiscoveryLayer::addTag(const PPPoETagBuilder& tagBuilder) { - PCPP_LOG_ERROR("Couldn't find tag"); - return false; + return addTagAt(tagBuilder, getHeaderLen()); } - int offset = tagToRemove.getRecordBasePtr() - m_Data; + size_t PPPoEDiscoveryLayer::getHeaderLen() const + { + size_t payloadLen = sizeof(pppoe_header) + be16toh(getPPPoEHeader()->payloadLength); + if (payloadLen > m_DataLen) + return m_DataLen; - uint16_t tagTotalSize = tagToRemove.getTotalSize(); + return payloadLen; + } - if (!shortenLayer(offset, tagTotalSize)) + bool PPPoEDiscoveryLayer::removeTag(PPPoEDiscoveryLayer::PPPoETagTypes tagType) { - return false; - } + PPPoEDiscoveryLayer::PPPoETag tagToRemove = getTag(tagType); + if (tagToRemove.isNull()) + { + PCPP_LOG_ERROR("Couldn't find tag"); + return false; + } - m_TagReader.changeTLVRecordCount(-1); + int offset = tagToRemove.getRecordBasePtr() - m_Data; - getPPPoEHeader()->payloadLength -= htobe16(tagTotalSize); - return true; -} + uint16_t tagTotalSize = tagToRemove.getTotalSize(); -bool PPPoEDiscoveryLayer::removeAllTags() -{ - size_t tagCount = getTagCount(); - int offset = sizeof(pppoe_header); - if (!shortenLayer(offset, m_DataLen-offset)) + if (!shortenLayer(offset, tagTotalSize)) + { + return false; + } + + m_TagReader.changeTLVRecordCount(-1); + + getPPPoEHeader()->payloadLength -= htobe16(tagTotalSize); + return true; + } + + bool PPPoEDiscoveryLayer::removeAllTags() { - return false; + size_t tagCount = getTagCount(); + int offset = sizeof(pppoe_header); + if (!shortenLayer(offset, m_DataLen - offset)) + { + return false; + } + m_TagReader.changeTLVRecordCount(0 - tagCount); + getPPPoEHeader()->payloadLength = 0; + return true; } - m_TagReader.changeTLVRecordCount(0-tagCount); - getPPPoEHeader()->payloadLength = 0; - return true; -} -std::string PPPoEDiscoveryLayer::codeToString(PPPoECode code) const -{ - switch (code) + std::string PPPoEDiscoveryLayer::codeToString(PPPoECode code) const { - case PPPoELayer::PPPOE_CODE_SESSION:return std::string("PPPoE Session"); - case PPPoELayer::PPPOE_CODE_PADO: return std::string("PADO"); - case PPPoELayer::PPPOE_CODE_PADI: return std::string("PADI"); - case PPPoELayer::PPPOE_CODE_PADG: return std::string("PADG"); - case PPPoELayer::PPPOE_CODE_PADC: return std::string("PADC"); - case PPPoELayer::PPPOE_CODE_PADQ: return std::string("PADQ"); - case PPPoELayer::PPPOE_CODE_PADR: return std::string("PADR"); - case PPPoELayer::PPPOE_CODE_PADS: return std::string("PADS"); - case PPPoELayer::PPPOE_CODE_PADT: return std::string("PADT"); - case PPPoELayer::PPPOE_CODE_PADM: return std::string("PADM"); - case PPPoELayer::PPPOE_CODE_PADN: return std::string("PADN"); - default: return std::string("Unknown PPPoE code"); + switch (code) + { + case PPPoELayer::PPPOE_CODE_SESSION: + return std::string("PPPoE Session"); + case PPPoELayer::PPPOE_CODE_PADO: + return std::string("PADO"); + case PPPoELayer::PPPOE_CODE_PADI: + return std::string("PADI"); + case PPPoELayer::PPPOE_CODE_PADG: + return std::string("PADG"); + case PPPoELayer::PPPOE_CODE_PADC: + return std::string("PADC"); + case PPPoELayer::PPPOE_CODE_PADQ: + return std::string("PADQ"); + case PPPoELayer::PPPOE_CODE_PADR: + return std::string("PADR"); + case PPPoELayer::PPPOE_CODE_PADS: + return std::string("PADS"); + case PPPoELayer::PPPOE_CODE_PADT: + return std::string("PADT"); + case PPPoELayer::PPPOE_CODE_PADM: + return std::string("PADM"); + case PPPoELayer::PPPOE_CODE_PADN: + return std::string("PADN"); + default: + return std::string("Unknown PPPoE code"); + } } -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/Packet.cpp b/Packet++/src/Packet.cpp index cf6a9b03de..a5b28e1f31 100644 --- a/Packet++/src/Packet.cpp +++ b/Packet++/src/Packet.cpp @@ -18,512 +18,508 @@ #include #include #ifdef _MSC_VER -#include -#include "SystemUtils.h" +# include +# include "SystemUtils.h" #endif - namespace pcpp { -Packet::Packet(size_t maxPacketLen) : - m_RawPacket(nullptr), - m_FirstLayer(nullptr), - m_LastLayer(nullptr), - m_MaxPacketLen(maxPacketLen), - m_FreeRawPacket(true), - m_CanReallocateData(true) -{ - timeval time; - gettimeofday(&time, nullptr); - uint8_t* data = new uint8_t[maxPacketLen]; - memset(data, 0, maxPacketLen); - m_RawPacket = new RawPacket(data, 0, time, true, LINKTYPE_ETHERNET); -} - -Packet::Packet(uint8_t* buffer, size_t bufferSize) : - m_RawPacket(nullptr), - m_FirstLayer(nullptr), - m_LastLayer(nullptr), - m_MaxPacketLen(bufferSize), - m_FreeRawPacket(true), - m_CanReallocateData(false) -{ - timeval time; - gettimeofday(&time, nullptr); - memset(buffer, 0, bufferSize); - m_RawPacket = new RawPacket(buffer, 0, time, false, LINKTYPE_ETHERNET); -} - -void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, OsiModelLayer parseUntilLayer) -{ - destructPacketData(); - - m_FirstLayer = nullptr; - m_LastLayer = nullptr; - m_MaxPacketLen = rawPacket->getRawDataLen(); - m_FreeRawPacket = freeRawPacket; - m_RawPacket = rawPacket; - m_CanReallocateData = true; - if (m_RawPacket == nullptr) - return; - - LinkLayerType linkType = m_RawPacket->getLinkLayerType(); - - m_FirstLayer = createFirstLayer(linkType); - - m_LastLayer = m_FirstLayer; - Layer* curLayer = m_FirstLayer; - while (curLayer != nullptr && (parseUntil == UnknownProtocol || !curLayer->isMemberOfProtocolFamily(parseUntil)) && curLayer->getOsiModelLayer() <= parseUntilLayer) + Packet::Packet(size_t maxPacketLen) + : m_RawPacket(nullptr), m_FirstLayer(nullptr), m_LastLayer(nullptr), m_MaxPacketLen(maxPacketLen), + m_FreeRawPacket(true), m_CanReallocateData(true) { - curLayer->parseNextLayer(); - curLayer->m_IsAllocatedInPacket = true; - curLayer = curLayer->getNextLayer(); - if (curLayer != nullptr) - m_LastLayer = curLayer; + timeval time; + gettimeofday(&time, nullptr); + uint8_t* data = new uint8_t[maxPacketLen]; + memset(data, 0, maxPacketLen); + m_RawPacket = new RawPacket(data, 0, time, true, LINKTYPE_ETHERNET); } - if (curLayer != nullptr && curLayer->isMemberOfProtocolFamily(parseUntil)) + Packet::Packet(uint8_t* buffer, size_t bufferSize) + : m_RawPacket(nullptr), m_FirstLayer(nullptr), m_LastLayer(nullptr), m_MaxPacketLen(bufferSize), + m_FreeRawPacket(true), m_CanReallocateData(false) { - curLayer->m_IsAllocatedInPacket = true; + timeval time; + gettimeofday(&time, nullptr); + memset(buffer, 0, bufferSize); + m_RawPacket = new RawPacket(buffer, 0, time, false, LINKTYPE_ETHERNET); } - if (curLayer != nullptr && curLayer->getOsiModelLayer() > parseUntilLayer) + void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, + OsiModelLayer parseUntilLayer) { - m_LastLayer = curLayer->getPrevLayer(); - delete curLayer; - m_LastLayer->m_NextLayer = nullptr; - } + destructPacketData(); - if (m_LastLayer != nullptr && parseUntil == UnknownProtocol && parseUntilLayer == OsiModelLayerUnknown) - { - // find if there is data left in the raw packet that doesn't belong to any layer. In that case it's probably a packet trailer. - // create a PacketTrailerLayer layer and add it at the end of the packet - int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) - (m_LastLayer->getData() + m_LastLayer->getDataLen())); - if (trailerLen > 0) + m_FirstLayer = nullptr; + m_LastLayer = nullptr; + m_MaxPacketLen = rawPacket->getRawDataLen(); + m_FreeRawPacket = freeRawPacket; + m_RawPacket = rawPacket; + m_CanReallocateData = true; + if (m_RawPacket == nullptr) + return; + + LinkLayerType linkType = m_RawPacket->getLinkLayerType(); + + m_FirstLayer = createFirstLayer(linkType); + + m_LastLayer = m_FirstLayer; + Layer* curLayer = m_FirstLayer; + while (curLayer != nullptr && + (parseUntil == UnknownProtocol || !curLayer->isMemberOfProtocolFamily(parseUntil)) && + curLayer->getOsiModelLayer() <= parseUntilLayer) { - PacketTrailerLayer* trailerLayer = new PacketTrailerLayer( - (uint8_t*)(m_LastLayer->getData() + m_LastLayer->getDataLen()), - trailerLen, - m_LastLayer, - this); + curLayer->parseNextLayer(); + curLayer->m_IsAllocatedInPacket = true; + curLayer = curLayer->getNextLayer(); + if (curLayer != nullptr) + m_LastLayer = curLayer; + } - trailerLayer->m_IsAllocatedInPacket = true; - m_LastLayer->setNextLayer(trailerLayer); - m_LastLayer = trailerLayer; + if (curLayer != nullptr && curLayer->isMemberOfProtocolFamily(parseUntil)) + { + curLayer->m_IsAllocatedInPacket = true; } - } -} -Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) -{ - m_FreeRawPacket = false; - m_RawPacket = nullptr; - m_FirstLayer = nullptr; - setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer); -} + if (curLayer != nullptr && curLayer->getOsiModelLayer() > parseUntilLayer) + { + m_LastLayer = curLayer->getPrevLayer(); + delete curLayer; + m_LastLayer->m_NextLayer = nullptr; + } -Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil) -{ - m_FreeRawPacket = false; - m_RawPacket = nullptr; - m_FirstLayer = nullptr; - auto parseUntilFamily = static_cast(parseUntil); - setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); -} - -Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily) -{ - m_FreeRawPacket = false; - m_RawPacket = nullptr; - m_FirstLayer = nullptr; - setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); -} + if (m_LastLayer != nullptr && parseUntil == UnknownProtocol && parseUntilLayer == OsiModelLayerUnknown) + { + // find if there is data left in the raw packet that doesn't belong to any layer. In that case it's probably + // a packet trailer. create a PacketTrailerLayer layer and add it at the end of the packet + int trailerLen = (int)((m_RawPacket->getRawData() + m_RawPacket->getRawDataLen()) - + (m_LastLayer->getData() + m_LastLayer->getDataLen())); + if (trailerLen > 0) + { + PacketTrailerLayer* trailerLayer = new PacketTrailerLayer( + (uint8_t*)(m_LastLayer->getData() + m_LastLayer->getDataLen()), trailerLen, m_LastLayer, this); -Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer) -{ - m_FreeRawPacket = false; - m_RawPacket = nullptr; - m_FirstLayer = nullptr; - setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer); -} + trailerLayer->m_IsAllocatedInPacket = true; + m_LastLayer->setNextLayer(trailerLayer); + m_LastLayer = trailerLayer; + } + } + } -void Packet::destructPacketData() -{ - Layer* curLayer = m_FirstLayer; - while (curLayer != nullptr) + Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) { - Layer* nextLayer = curLayer->getNextLayer(); - if (curLayer->m_IsAllocatedInPacket) - delete curLayer; - curLayer = nextLayer; + m_FreeRawPacket = false; + m_RawPacket = nullptr; + m_FirstLayer = nullptr; + setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer); } - if (m_RawPacket != nullptr && m_FreeRawPacket) + Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil) { - delete m_RawPacket; + m_FreeRawPacket = false; + m_RawPacket = nullptr; + m_FirstLayer = nullptr; + auto parseUntilFamily = static_cast(parseUntil); + setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); } -} - -Packet& Packet::operator=(const Packet& other) -{ - destructPacketData(); - copyDataFrom(other); - - return *this; -} - -void Packet::copyDataFrom(const Packet& other) -{ - m_RawPacket = new RawPacket(*(other.m_RawPacket)); - m_FreeRawPacket = true; - m_MaxPacketLen = other.m_MaxPacketLen; - m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType()); - m_LastLayer = m_FirstLayer; - m_CanReallocateData = true; - Layer* curLayer = m_FirstLayer; - while (curLayer != nullptr) + Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily) { - curLayer->parseNextLayer(); - curLayer->m_IsAllocatedInPacket = true; - curLayer = curLayer->getNextLayer(); - if (curLayer != nullptr) - m_LastLayer = curLayer; + m_FreeRawPacket = false; + m_RawPacket = nullptr; + m_FirstLayer = nullptr; + setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); } -} -void Packet::reallocateRawData(size_t newSize) -{ - PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize); - - // allocate a new array with size newSize - m_MaxPacketLen = newSize; - - // set the new array to RawPacket - if (!m_RawPacket->reallocateData(m_MaxPacketLen)) + Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer) { - PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes"); - return; + m_FreeRawPacket = false; + m_RawPacket = nullptr; + m_FirstLayer = nullptr; + setRawPacket(rawPacket, false, UnknownProtocol, parseUntilLayer); } - // set all data pointers in layers to the new array address - const uint8_t* dataPtr = m_RawPacket->getRawData(); - - Layer* curLayer = m_FirstLayer; - while (curLayer != nullptr) + void Packet::destructPacketData() { - PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'"); - curLayer->m_Data = (uint8_t*)dataPtr; - dataPtr += curLayer->getHeaderLen(); - curLayer = curLayer->getNextLayer(); + Layer* curLayer = m_FirstLayer; + while (curLayer != nullptr) + { + Layer* nextLayer = curLayer->getNextLayer(); + if (curLayer->m_IsAllocatedInPacket) + delete curLayer; + curLayer = nextLayer; + } + + if (m_RawPacket != nullptr && m_FreeRawPacket) + { + delete m_RawPacket; + } } -} -bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket) -{ - if (newLayer == nullptr) + Packet& Packet::operator=(const Packet& other) { - PCPP_LOG_ERROR("Layer to add is NULL"); - return false; + destructPacketData(); + + copyDataFrom(other); + + return *this; } - if (newLayer->isAllocatedToPacket()) + void Packet::copyDataFrom(const Packet& other) { - PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet"); - return false; + m_RawPacket = new RawPacket(*(other.m_RawPacket)); + m_FreeRawPacket = true; + m_MaxPacketLen = other.m_MaxPacketLen; + m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType()); + m_LastLayer = m_FirstLayer; + m_CanReallocateData = true; + Layer* curLayer = m_FirstLayer; + while (curLayer != nullptr) + { + curLayer->parseNextLayer(); + curLayer->m_IsAllocatedInPacket = true; + curLayer = curLayer->getNextLayer(); + if (curLayer != nullptr) + m_LastLayer = curLayer; + } } - if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer) + void Packet::reallocateRawData(size_t newSize) { - PCPP_LOG_ERROR("Cannot insert layer after packet trailer"); - return false; + PCPP_LOG_DEBUG("Allocating packet to new size: " << newSize); + + // allocate a new array with size newSize + m_MaxPacketLen = newSize; + + // set the new array to RawPacket + if (!m_RawPacket->reallocateData(m_MaxPacketLen)) + { + PCPP_LOG_ERROR("Couldn't reallocate data of raw packet to " << m_MaxPacketLen << " bytes"); + return; + } + + // set all data pointers in layers to the new array address + const uint8_t* dataPtr = m_RawPacket->getRawData(); + + Layer* curLayer = m_FirstLayer; + while (curLayer != nullptr) + { + PCPP_LOG_DEBUG("Setting new data pointer to layer '" << typeid(curLayer).name() << "'"); + curLayer->m_Data = (uint8_t*)dataPtr; + dataPtr += curLayer->getHeaderLen(); + curLayer = curLayer->getNextLayer(); + } } - size_t newLayerHeaderLen = newLayer->getHeaderLen(); - if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen) + bool Packet::insertLayer(Layer* prevLayer, Layer* newLayer, bool ownInPacket) { - if (!m_CanReallocateData) + if (newLayer == nullptr) { - PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: " << m_MaxPacketLen << " bytes"); + PCPP_LOG_ERROR("Layer to add is NULL"); return false; } - // reallocate to maximum value of: twice the max size of the packet or max size + new required length - if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen*2) - reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen); - else - reallocateRawData(m_MaxPacketLen*2); - } - // insert layer data to raw packet - int indexToInsertData = 0; - if (prevLayer != nullptr) - indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData(); - m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen); + if (newLayer->isAllocatedToPacket()) + { + PCPP_LOG_ERROR("Layer is already allocated to another packet. Cannot use layer in more than one packet"); + return false; + } + + if (prevLayer != nullptr && prevLayer->getProtocol() == PacketTrailer) + { + PCPP_LOG_ERROR("Cannot insert layer after packet trailer"); + return false; + } - //delete previous layer data - delete[] newLayer->m_Data; + size_t newLayerHeaderLen = newLayer->getHeaderLen(); + if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen) + { + if (!m_CanReallocateData) + { + PCPP_LOG_ERROR("With the new layer the packet will exceed the size of the pre-allocated buffer: " + << m_MaxPacketLen << " bytes"); + return false; + } + // reallocate to maximum value of: twice the max size of the packet or max size + new required length + if (m_RawPacket->getRawDataLen() + newLayerHeaderLen > m_MaxPacketLen * 2) + reallocateRawData(m_RawPacket->getRawDataLen() + newLayerHeaderLen + m_MaxPacketLen); + else + reallocateRawData(m_MaxPacketLen * 2); + } - // add layer to layers linked list - if (prevLayer != nullptr) - { - newLayer->setNextLayer(prevLayer->getNextLayer()); - newLayer->setPrevLayer(prevLayer); - prevLayer->setNextLayer(newLayer); - } - else //prevLayer == NULL - { - newLayer->setNextLayer(m_FirstLayer); - if (m_FirstLayer != nullptr) - m_FirstLayer->setPrevLayer(newLayer); - m_FirstLayer = newLayer; - } + // insert layer data to raw packet + int indexToInsertData = 0; + if (prevLayer != nullptr) + indexToInsertData = prevLayer->m_Data + prevLayer->getHeaderLen() - m_RawPacket->getRawData(); + m_RawPacket->insertData(indexToInsertData, newLayer->m_Data, newLayerHeaderLen); - if (newLayer->getNextLayer() == nullptr) - m_LastLayer = newLayer; - else - newLayer->getNextLayer()->setPrevLayer(newLayer); + // delete previous layer data + delete[] newLayer->m_Data; - // assign layer with this packet only - newLayer->m_Packet = this; + // add layer to layers linked list + if (prevLayer != nullptr) + { + newLayer->setNextLayer(prevLayer->getNextLayer()); + newLayer->setPrevLayer(prevLayer); + prevLayer->setNextLayer(newLayer); + } + else // prevLayer == NULL + { + newLayer->setNextLayer(m_FirstLayer); + if (m_FirstLayer != nullptr) + m_FirstLayer->setPrevLayer(newLayer); + m_FirstLayer = newLayer; + } - // Set flag to indicate if new layer is allocated to packet. - if(ownInPacket) - newLayer->m_IsAllocatedInPacket = true; + if (newLayer->getNextLayer() == nullptr) + m_LastLayer = newLayer; + else + newLayer->getNextLayer()->setPrevLayer(newLayer); - // re-calculate all layers data ptr and data length + // assign layer with this packet only + newLayer->m_Packet = this; - // first, get ptr and data length of the raw packet - const uint8_t* dataPtr = m_RawPacket->getRawData(); - size_t dataLen = (size_t)m_RawPacket->getRawDataLen(); + // Set flag to indicate if new layer is allocated to packet. + if (ownInPacket) + newLayer->m_IsAllocatedInPacket = true; - // if a packet trailer exists, get its length - size_t packetTrailerLen = 0; - if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) - packetTrailerLen = m_LastLayer->getDataLen(); + // re-calculate all layers data ptr and data length - // go over all layers from the first layer to the last layer and set the data ptr and data length for each one - Layer* curLayer = m_FirstLayer; - while (curLayer != nullptr) - { - // set data ptr to layer - curLayer->m_Data = (uint8_t*)dataPtr; - - // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. - // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the whole data, including the - // packet trailer. If this layer is L3-7, exclude the packet trailer from its data length - if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) - curLayer->m_DataLen = dataLen; - else - curLayer->m_DataLen = dataLen - packetTrailerLen; + // first, get ptr and data length of the raw packet + const uint8_t* dataPtr = m_RawPacket->getRawData(); + size_t dataLen = (size_t)m_RawPacket->getRawDataLen(); - // advance data ptr and data length - dataPtr += curLayer->getHeaderLen(); - dataLen -= curLayer->getHeaderLen(); + // if a packet trailer exists, get its length + size_t packetTrailerLen = 0; + if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) + packetTrailerLen = m_LastLayer->getDataLen(); - // move to next layer - curLayer = curLayer->getNextLayer(); - } + // go over all layers from the first layer to the last layer and set the data ptr and data length for each one + Layer* curLayer = m_FirstLayer; + while (curLayer != nullptr) + { + // set data ptr to layer + curLayer->m_Data = (uint8_t*)dataPtr; + + // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. + // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the + // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data + // length + if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) + curLayer->m_DataLen = dataLen; + else + curLayer->m_DataLen = dataLen - packetTrailerLen; - return true; -} + // advance data ptr and data length + dataPtr += curLayer->getHeaderLen(); + dataLen -= curLayer->getHeaderLen(); -bool Packet::removeLayer(ProtocolType layerType, int index) -{ - Layer* layerToRemove = getLayerOfType(layerType, index); + // move to next layer + curLayer = curLayer->getNextLayer(); + } - if (layerToRemove != nullptr) - { - return removeLayer(layerToRemove, true); + return true; } - else - { - PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); - return false; - } -} -bool Packet::removeFirstLayer() -{ - Layer* firstLayer = getFirstLayer(); - if (firstLayer == nullptr) + bool Packet::removeLayer(ProtocolType layerType, int index) { - PCPP_LOG_ERROR("Packet has no layers"); - return false; - } + Layer* layerToRemove = getLayerOfType(layerType, index); - return removeLayer(firstLayer, true); -} + if (layerToRemove != nullptr) + { + return removeLayer(layerToRemove, true); + } + else + { + PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); + return false; + } + } -bool Packet::removeLastLayer() -{ - Layer* lastLayer = getLastLayer(); - if (lastLayer == nullptr) + bool Packet::removeFirstLayer() { - PCPP_LOG_ERROR("Packet has no layers"); - return false; - } + Layer* firstLayer = getFirstLayer(); + if (firstLayer == nullptr) + { + PCPP_LOG_ERROR("Packet has no layers"); + return false; + } - return removeLayer(lastLayer, true); -} + return removeLayer(firstLayer, true); + } -bool Packet::removeAllLayersAfter(Layer* layer) -{ - Layer* curLayer = layer->getNextLayer(); - while (curLayer != nullptr) + bool Packet::removeLastLayer() { - Layer* tempLayer = curLayer->getNextLayer(); - if (!removeLayer(curLayer, true)) + Layer* lastLayer = getLastLayer(); + if (lastLayer == nullptr) + { + PCPP_LOG_ERROR("Packet has no layers"); return false; - curLayer = tempLayer; + } + + return removeLayer(lastLayer, true); } - return true; -} + bool Packet::removeAllLayersAfter(Layer* layer) + { + Layer* curLayer = layer->getNextLayer(); + while (curLayer != nullptr) + { + Layer* tempLayer = curLayer->getNextLayer(); + if (!removeLayer(curLayer, true)) + return false; + curLayer = tempLayer; + } -Layer* Packet::detachLayer(ProtocolType layerType, int index) -{ - Layer* layerToDetach = getLayerOfType(layerType, index); + return true; + } - if (layerToDetach != nullptr) + Layer* Packet::detachLayer(ProtocolType layerType, int index) { - if (removeLayer(layerToDetach, false)) - return layerToDetach; + Layer* layerToDetach = getLayerOfType(layerType, index); + + if (layerToDetach != nullptr) + { + if (removeLayer(layerToDetach, false)) + return layerToDetach; + else + return nullptr; + } else + { + PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); return nullptr; + } } - else - { - PCPP_LOG_ERROR("Layer of the requested type was not found in packet"); - return nullptr; - } -} -bool Packet::removeLayer(Layer* layer, bool tryToDelete) -{ - if (layer == nullptr) + bool Packet::removeLayer(Layer* layer, bool tryToDelete) { - PCPP_LOG_ERROR("Layer is NULL"); - return false; - } + if (layer == nullptr) + { + PCPP_LOG_ERROR("Layer is NULL"); + return false; + } - // verify layer is allocated to a packet - if (!layer->isAllocatedToPacket()) - { - PCPP_LOG_ERROR("Layer isn't allocated to any packet"); - return false; - } + // verify layer is allocated to a packet + if (!layer->isAllocatedToPacket()) + { + PCPP_LOG_ERROR("Layer isn't allocated to any packet"); + return false; + } - // verify layer is allocated to *this* packet - Layer* curLayer = layer; - while (curLayer->m_PrevLayer != nullptr) - curLayer = curLayer->m_PrevLayer; - if (curLayer != m_FirstLayer) - { - PCPP_LOG_ERROR("Layer isn't allocated to this packet"); - return false; - } + // verify layer is allocated to *this* packet + Layer* curLayer = layer; + while (curLayer->m_PrevLayer != nullptr) + curLayer = curLayer->m_PrevLayer; + if (curLayer != m_FirstLayer) + { + PCPP_LOG_ERROR("Layer isn't allocated to this packet"); + return false; + } - // before removing the layer's data, copy it so it can be later assigned as the removed layer's data - size_t headerLen = layer->getHeaderLen(); - size_t layerOldDataSize = headerLen; - uint8_t* layerOldData = new uint8_t[layerOldDataSize]; - memcpy(layerOldData, layer->m_Data, layerOldDataSize); + // before removing the layer's data, copy it so it can be later assigned as the removed layer's data + size_t headerLen = layer->getHeaderLen(); + size_t layerOldDataSize = headerLen; + uint8_t* layerOldData = new uint8_t[layerOldDataSize]; + memcpy(layerOldData, layer->m_Data, layerOldDataSize); - // remove data from raw packet - size_t numOfBytesToRemove = headerLen; - int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData(); - if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove)) - { - PCPP_LOG_ERROR("Couldn't remove data from packet"); - delete [] layerOldData; - return false; - } + // remove data from raw packet + size_t numOfBytesToRemove = headerLen; + int indexOfDataToRemove = layer->m_Data - m_RawPacket->getRawData(); + if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToRemove)) + { + PCPP_LOG_ERROR("Couldn't remove data from packet"); + delete[] layerOldData; + return false; + } - // remove layer from layers linked list - if (layer->m_PrevLayer != nullptr) - layer->m_PrevLayer->setNextLayer(layer->m_NextLayer); - if (layer->m_NextLayer != nullptr) - layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer); + // remove layer from layers linked list + if (layer->m_PrevLayer != nullptr) + layer->m_PrevLayer->setNextLayer(layer->m_NextLayer); + if (layer->m_NextLayer != nullptr) + layer->m_NextLayer->setPrevLayer(layer->m_PrevLayer); - // take care of head and tail ptrs - if (m_FirstLayer == layer) - m_FirstLayer = layer->m_NextLayer; - if (m_LastLayer == layer) - m_LastLayer = layer->m_PrevLayer; - layer->setNextLayer(nullptr); - layer->setPrevLayer(nullptr); + // take care of head and tail ptrs + if (m_FirstLayer == layer) + m_FirstLayer = layer->m_NextLayer; + if (m_LastLayer == layer) + m_LastLayer = layer->m_PrevLayer; + layer->setNextLayer(nullptr); + layer->setPrevLayer(nullptr); - // get packet trailer len if exists - size_t packetTrailerLen = 0; - if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) - packetTrailerLen = m_LastLayer->getDataLen(); + // get packet trailer len if exists + size_t packetTrailerLen = 0; + if (m_LastLayer != nullptr && m_LastLayer->getProtocol() == PacketTrailer) + packetTrailerLen = m_LastLayer->getDataLen(); - // re-calculate all layers data ptr and data length + // re-calculate all layers data ptr and data length - // first, get ptr and data length of the raw packet - const uint8_t* dataPtr = m_RawPacket->getRawData(); - size_t dataLen = (size_t)m_RawPacket->getRawDataLen(); + // first, get ptr and data length of the raw packet + const uint8_t* dataPtr = m_RawPacket->getRawData(); + size_t dataLen = (size_t)m_RawPacket->getRawDataLen(); - curLayer = m_FirstLayer; + curLayer = m_FirstLayer; - // go over all layers from the first layer to the last layer and set the data ptr and data length for each one - while (curLayer != nullptr) - { - // set data ptr to layer - curLayer->m_Data = (uint8_t*)dataPtr; - - // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. - // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the whole data, including the - // packet trailer. If this layer is L3-7, exclude the packet trailer from its data length - if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) - curLayer->m_DataLen = dataLen; - else - curLayer->m_DataLen = dataLen - packetTrailerLen; + // go over all layers from the first layer to the last layer and set the data ptr and data length for each one + while (curLayer != nullptr) + { + // set data ptr to layer + curLayer->m_Data = (uint8_t*)dataPtr; + + // there is an assumption here that the packet trailer, if exists, corresponds to the L2 (data link) layers. + // so if there is a packet trailer and this layer is L2 (data link), set its data length to contain the + // whole data, including the packet trailer. If this layer is L3-7, exclude the packet trailer from its data + // length + if (curLayer->getOsiModelLayer() == OsiModelDataLinkLayer) + curLayer->m_DataLen = dataLen; + else + curLayer->m_DataLen = dataLen - packetTrailerLen; - // advance data ptr and data length - dataPtr += curLayer->getHeaderLen(); - dataLen -= curLayer->getHeaderLen(); + // advance data ptr and data length + dataPtr += curLayer->getHeaderLen(); + dataLen -= curLayer->getHeaderLen(); - // move to next layer - curLayer = curLayer->getNextLayer(); - } + // move to next layer + curLayer = curLayer->getNextLayer(); + } - // if layer was allocated by this packet and tryToDelete flag is set, delete it - if (tryToDelete && layer->m_IsAllocatedInPacket) - { - delete layer; - delete [] layerOldData; - } - // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can be reused - else - { - layer->m_Packet = nullptr; - layer->m_Data = layerOldData; - layer->m_DataLen = layerOldDataSize; - } + // if layer was allocated by this packet and tryToDelete flag is set, delete it + if (tryToDelete && layer->m_IsAllocatedInPacket) + { + delete layer; + delete[] layerOldData; + } + // if layer was not allocated by this packet or the tryToDelete is not set, detach it from the packet so it can + // be reused + else + { + layer->m_Packet = nullptr; + layer->m_Data = layerOldData; + layer->m_DataLen = layerOldDataSize; + } - return true; -} + return true; + } -Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const -{ - Layer* curLayer = getFirstLayer(); - int curIndex = 0; - while (curLayer != nullptr) + Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const { - if (curLayer->getProtocol() == layerType) + Layer* curLayer = getFirstLayer(); + int curIndex = 0; + while (curLayer != nullptr) { - if (curIndex < index) - curIndex++; - else - break; + if (curLayer->getProtocol() == layerType) + { + if (curIndex < index) + curIndex++; + else + break; + } + curLayer = curLayer->getNextLayer(); } - curLayer = curLayer->getNextLayer(); - } - return curLayer; -} + return curLayer; + } bool Packet::isPacketOfType(ProtocolType protocolType) const { @@ -555,277 +551,283 @@ Layer* Packet::getLayerOfType(ProtocolType layerType, int index) const return false; } -bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend) -{ - if (layer == nullptr) - { - PCPP_LOG_ERROR("Layer is NULL"); - return false; - } - - // verify layer is allocated to this packet - if (!(layer->m_Packet == this)) + bool Packet::extendLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToExtend) { - PCPP_LOG_ERROR("Layer isn't allocated to this packet"); - return false; - } + if (layer == nullptr) + { + PCPP_LOG_ERROR("Layer is NULL"); + return false; + } - if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen) - { - if (!m_CanReallocateData) + // verify layer is allocated to this packet + if (!(layer->m_Packet == this)) { - PCPP_LOG_ERROR("With the layer extended size the packet will exceed the size of the pre-allocated buffer: " << m_MaxPacketLen << " bytes"); + PCPP_LOG_ERROR("Layer isn't allocated to this packet"); return false; } - // reallocate to maximum value of: twice the max size of the packet or max size + new required length - if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen*2) - reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen); - else - reallocateRawData(m_MaxPacketLen*2); - } - // insert layer data to raw packet - int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); - // passing NULL to insertData will move the data by numOfBytesToExtend - // no new data has to be created for this insertion which saves at least little time - // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided above - // if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the packet size by numOfBytesToExtend - m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend); - - // re-calculate all layers data ptr and data length - const uint8_t* dataPtr = m_RawPacket->getRawData(); - - // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer - Layer* curLayer = m_FirstLayer; - bool passedExtendedLayer = false; - while (curLayer != nullptr) - { - // set the data ptr - curLayer->m_Data = (uint8_t*)dataPtr; + if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen) + { + if (!m_CanReallocateData) + { + PCPP_LOG_ERROR( + "With the layer extended size the packet will exceed the size of the pre-allocated buffer: " + << m_MaxPacketLen << " bytes"); + return false; + } + // reallocate to maximum value of: twice the max size of the packet or max size + new required length + if (m_RawPacket->getRawDataLen() + numOfBytesToExtend > m_MaxPacketLen * 2) + reallocateRawData(m_RawPacket->getRawDataLen() + numOfBytesToExtend + m_MaxPacketLen); + else + reallocateRawData(m_MaxPacketLen * 2); + } - // set a flag if arrived to the layer being extended - if (curLayer->getPrevLayer() == layer) - passedExtendedLayer = true; + // insert layer data to raw packet + int indexToInsertData = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); + // passing NULL to insertData will move the data by numOfBytesToExtend + // no new data has to be created for this insertion which saves at least little time + // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided + // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the + // packet size by numOfBytesToExtend + m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend); + + // re-calculate all layers data ptr and data length + const uint8_t* dataPtr = m_RawPacket->getRawData(); + + // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer + Layer* curLayer = m_FirstLayer; + bool passedExtendedLayer = false; + while (curLayer != nullptr) + { + // set the data ptr + curLayer->m_Data = (uint8_t*)dataPtr; - // change the data length only for layers who come before the extended layer. For layers who come after, data length isn't changed - if (!passedExtendedLayer) - curLayer->m_DataLen += numOfBytesToExtend; + // set a flag if arrived to the layer being extended + if (curLayer->getPrevLayer() == layer) + passedExtendedLayer = true; - // assuming header length of the layer that requested to be extended hasn't been enlarged yet - size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0); - dataPtr += headerLen; - curLayer = curLayer->getNextLayer(); - } + // change the data length only for layers who come before the extended layer. For layers who come after, + // data length isn't changed + if (!passedExtendedLayer) + curLayer->m_DataLen += numOfBytesToExtend; - return true; -} + // assuming header length of the layer that requested to be extended hasn't been enlarged yet + size_t headerLen = curLayer->getHeaderLen() + (curLayer == layer ? numOfBytesToExtend : 0); + dataPtr += headerLen; + curLayer = curLayer->getNextLayer(); + } -bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten) -{ - if (layer == nullptr) - { - PCPP_LOG_ERROR("Layer is NULL"); - return false; + return true; } - // verify layer is allocated to this packet - if (!(layer->m_Packet == this)) + bool Packet::shortenLayer(Layer* layer, int offsetInLayer, size_t numOfBytesToShorten) { - PCPP_LOG_ERROR("Layer isn't allocated to this packet"); - return false; - } + if (layer == nullptr) + { + PCPP_LOG_ERROR("Layer is NULL"); + return false; + } - // remove data from raw packet - int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); - if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten)) - { - PCPP_LOG_ERROR("Couldn't remove data from packet"); - return false; - } + // verify layer is allocated to this packet + if (!(layer->m_Packet == this)) + { + PCPP_LOG_ERROR("Layer isn't allocated to this packet"); + return false; + } - // re-calculate all layers data ptr and data length - const uint8_t* dataPtr = m_RawPacket->getRawData(); + // remove data from raw packet + int indexOfDataToRemove = layer->m_Data + offsetInLayer - m_RawPacket->getRawData(); + if (!m_RawPacket->removeData(indexOfDataToRemove, numOfBytesToShorten)) + { + PCPP_LOG_ERROR("Couldn't remove data from packet"); + return false; + } - // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer - Layer* curLayer = m_FirstLayer; - bool passedExtendedLayer = false; - while (curLayer != nullptr) - { - // set the data ptr - curLayer->m_Data = (uint8_t*)dataPtr; + // re-calculate all layers data ptr and data length + const uint8_t* dataPtr = m_RawPacket->getRawData(); - // set a flag if arrived to the layer being shortened - if (curLayer->getPrevLayer() == layer) - passedExtendedLayer = true; + // go over all layers from the first layer to the last layer and set the data ptr and data length for each layer + Layer* curLayer = m_FirstLayer; + bool passedExtendedLayer = false; + while (curLayer != nullptr) + { + // set the data ptr + curLayer->m_Data = (uint8_t*)dataPtr; - // change the data length only for layers who come before the shortened layer. For layers who come after, data length isn't changed - if (!passedExtendedLayer) - curLayer->m_DataLen -= numOfBytesToShorten; + // set a flag if arrived to the layer being shortened + if (curLayer->getPrevLayer() == layer) + passedExtendedLayer = true; - // assuming header length of the layer that requested to be extended hasn't been enlarged yet - size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0); - dataPtr += headerLen; - curLayer = curLayer->getNextLayer(); - } + // change the data length only for layers who come before the shortened layer. For layers who come after, + // data length isn't changed + if (!passedExtendedLayer) + curLayer->m_DataLen -= numOfBytesToShorten; - return true; -} + // assuming header length of the layer that requested to be extended hasn't been enlarged yet + size_t headerLen = curLayer->getHeaderLen() - (curLayer == layer ? numOfBytesToShorten : 0); + dataPtr += headerLen; + curLayer = curLayer->getNextLayer(); + } -void Packet::computeCalculateFields() -{ - // calculated fields should be calculated from top layer to bottom layer + return true; + } - Layer* curLayer = m_LastLayer; - while (curLayer != nullptr) + void Packet::computeCalculateFields() { - curLayer->computeCalculateFields(); - curLayer = curLayer->getPrevLayer(); + // calculated fields should be calculated from top layer to bottom layer + + Layer* curLayer = m_LastLayer; + while (curLayer != nullptr) + { + curLayer->computeCalculateFields(); + curLayer = curLayer->getPrevLayer(); + } } -} -std::string Packet::printPacketInfo(bool timeAsLocalTime) const -{ - std::ostringstream dataLenStream; - dataLenStream << m_RawPacket->getRawDataLen(); + std::string Packet::printPacketInfo(bool timeAsLocalTime) const + { + std::ostringstream dataLenStream; + dataLenStream << m_RawPacket->getRawDataLen(); - // convert raw packet timestamp to printable format - timespec timestamp = m_RawPacket->getPacketTimeStamp(); - time_t nowtime = timestamp.tv_sec; - struct tm *nowtm = nullptr; + // convert raw packet timestamp to printable format + timespec timestamp = m_RawPacket->getPacketTimeStamp(); + time_t nowtime = timestamp.tv_sec; + struct tm* nowtm = nullptr; #if __cplusplus > 199711L && !defined(_WIN32) - // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime, - // but they're defined only in newer compilers (>= C++0x). - // on Windows localtime and gmtime are already thread-safe so there is not need - // to use localtime_r and gmtime_r - struct tm nowtm_r; - if (timeAsLocalTime) - nowtm = localtime_r(&nowtime, &nowtm_r); - else - nowtm = gmtime_r(&nowtime, &nowtm_r); - - if (nowtm != nullptr) - nowtm = &nowtm_r; + // localtime_r and gmtime_r are thread-safe versions of localtime and gmtime, + // but they're defined only in newer compilers (>= C++0x). + // on Windows localtime and gmtime are already thread-safe so there is not need + // to use localtime_r and gmtime_r + struct tm nowtm_r; + if (timeAsLocalTime) + nowtm = localtime_r(&nowtime, &nowtm_r); + else + nowtm = gmtime_r(&nowtime, &nowtm_r); + + if (nowtm != nullptr) + nowtm = &nowtm_r; #else - // on Window compilers localtime and gmtime are already thread safe. - // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and gmtime - if (timeAsLocalTime) - nowtm = localtime(&nowtime); - else - nowtm = gmtime(&nowtime); + // on Window compilers localtime and gmtime are already thread safe. + // in old compilers (< C++0x) gmtime_r and localtime_r were not defined so we have to fall back to localtime and + // gmtime + if (timeAsLocalTime) + nowtm = localtime(&nowtime); + else + nowtm = gmtime(&nowtime); #endif - char buf[128]; - if (nowtm != nullptr) - { - char tmbuf[64]; - strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm); - snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec); - } - else - snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000"); + char buf[128]; + if (nowtm != nullptr) + { + char tmbuf[64]; + strftime(tmbuf, sizeof(tmbuf), "%Y-%m-%d %H:%M:%S", nowtm); + snprintf(buf, sizeof(buf), "%s.%09lu", tmbuf, (unsigned long)timestamp.tv_nsec); + } + else + snprintf(buf, sizeof(buf), "0000-00-00 00:00:00.000000000"); - return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf); -} + return "Packet length: " + dataLenStream.str() + " [Bytes], Arrival time: " + std::string(buf); + } -Layer* Packet::createFirstLayer(LinkLayerType linkType) -{ - size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen(); - if (rawDataLen == 0) - return nullptr; + Layer* Packet::createFirstLayer(LinkLayerType linkType) + { + size_t rawDataLen = (size_t)m_RawPacket->getRawDataLen(); + if (rawDataLen == 0) + return nullptr; - const uint8_t* rawData = m_RawPacket->getRawData(); + const uint8_t* rawData = m_RawPacket->getRawData(); - if (linkType == LINKTYPE_ETHERNET) - { - if (EthLayer::isDataValid(rawData, rawDataLen)) + if (linkType == LINKTYPE_ETHERNET) + { + if (EthLayer::isDataValid(rawData, rawDataLen)) + { + return new EthLayer((uint8_t*)rawData, rawDataLen, this); + } + else if (EthDot3Layer::isDataValid(rawData, rawDataLen)) + { + return new EthDot3Layer((uint8_t*)rawData, rawDataLen, this); + } + else + { + return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); + } + } + else if (linkType == LINKTYPE_LINUX_SLL) { - return new EthLayer((uint8_t*)rawData, rawDataLen, this); + return new SllLayer((uint8_t*)rawData, rawDataLen, this); } - else if (EthDot3Layer::isDataValid(rawData, rawDataLen)) + else if (linkType == LINKTYPE_LINUX_SLL2 && Sll2Layer::isDataValid(rawData, rawDataLen)) { - return new EthDot3Layer((uint8_t*)rawData, rawDataLen, this); + return new Sll2Layer((uint8_t*)rawData, rawDataLen, this); } - else + else if (linkType == LINKTYPE_NULL) { - return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); + if (rawDataLen >= sizeof(uint32_t)) + return new NullLoopbackLayer((uint8_t*)rawData, rawDataLen, this); + else // rawDataLen is too small fir Null/Loopback + return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); } - } - else if (linkType == LINKTYPE_LINUX_SLL) - { - return new SllLayer((uint8_t*)rawData, rawDataLen, this); - } - else if (linkType == LINKTYPE_LINUX_SLL2 && Sll2Layer::isDataValid(rawData, rawDataLen)) - { - return new Sll2Layer((uint8_t*)rawData, rawDataLen, this); - } - else if (linkType == LINKTYPE_NULL) - { - if (rawDataLen >= sizeof(uint32_t)) - return new NullLoopbackLayer((uint8_t*)rawData, rawDataLen, this); - else // rawDataLen is too small fir Null/Loopback - return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); - } - else if (linkType == LINKTYPE_RAW || linkType == LINKTYPE_DLT_RAW1 || linkType == LINKTYPE_DLT_RAW2) - { - uint8_t ipVer = rawData[0] & 0xf0; - if (ipVer == 0x40) + else if (linkType == LINKTYPE_RAW || linkType == LINKTYPE_DLT_RAW1 || linkType == LINKTYPE_DLT_RAW2) + { + uint8_t ipVer = rawData[0] & 0xf0; + if (ipVer == 0x40) + { + return IPv4Layer::isDataValid(rawData, rawDataLen) + ? static_cast(new IPv4Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) + : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); + } + else if (ipVer == 0x60) + { + return IPv6Layer::isDataValid(rawData, rawDataLen) + ? static_cast(new IPv6Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) + : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); + } + else + { + return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); + } + } + else if (linkType == LINKTYPE_IPV4) { return IPv4Layer::isDataValid(rawData, rawDataLen) - ? static_cast(new IPv4Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) - : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); + ? static_cast(new IPv4Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) + : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); } - else if (ipVer == 0x60) + else if (linkType == LINKTYPE_IPV6) { return IPv6Layer::isDataValid(rawData, rawDataLen) - ? static_cast(new IPv6Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) - : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); + ? static_cast(new IPv6Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) + : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); } - else + else if (linkType == LINKTYPE_NFLOG) { - return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); + return NflogLayer::isDataValid(rawData, rawDataLen) + ? static_cast(new NflogLayer((uint8_t*)rawData, rawDataLen, this)) + : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); } + + // unknown link type + return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); } - else if (linkType == LINKTYPE_IPV4) - { - return IPv4Layer::isDataValid(rawData, rawDataLen) - ? static_cast(new IPv4Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) - : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); - } - else if (linkType == LINKTYPE_IPV6) - { - return IPv6Layer::isDataValid(rawData, rawDataLen) - ? static_cast(new IPv6Layer((uint8_t*)rawData, rawDataLen, nullptr, this)) - : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); - } - else if (linkType == LINKTYPE_NFLOG) + + std::string Packet::toString(bool timeAsLocalTime) const { - return NflogLayer::isDataValid(rawData, rawDataLen) - ? static_cast(new NflogLayer((uint8_t*)rawData, rawDataLen, this)) - : static_cast(new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this)); + std::vector stringList; + toStringList(stringList, timeAsLocalTime); + return std::accumulate(stringList.begin(), stringList.end(), std::string(), + [](std::string a, const std::string& b) { return std::move(a) + b + '\n'; }); } - // unknown link type - return new PayloadLayer((uint8_t*)rawData, rawDataLen, nullptr, this); -} - -std::string Packet::toString(bool timeAsLocalTime) const -{ - std::vector stringList; - toStringList(stringList, timeAsLocalTime); - return std::accumulate(stringList.begin(), stringList.end(), std::string(), - [](std::string a, const std::string &b) { return std::move(a) + b + '\n'; }); -} - -void Packet::toStringList(std::vector& result, bool timeAsLocalTime) const -{ - result.clear(); - result.push_back(printPacketInfo(timeAsLocalTime)); - Layer* curLayer = m_FirstLayer; - while (curLayer != nullptr) + void Packet::toStringList(std::vector& result, bool timeAsLocalTime) const { - result.push_back(curLayer->toString()); - curLayer = curLayer->getNextLayer(); + result.clear(); + result.push_back(printPacketInfo(timeAsLocalTime)); + Layer* curLayer = m_FirstLayer; + while (curLayer != nullptr) + { + result.push_back(curLayer->toString()); + curLayer = curLayer->getNextLayer(); + } } -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/PacketTrailerLayer.cpp b/Packet++/src/PacketTrailerLayer.cpp index 60377ffb04..f05f381361 100644 --- a/Packet++/src/PacketTrailerLayer.cpp +++ b/Packet++/src/PacketTrailerLayer.cpp @@ -6,22 +6,22 @@ namespace pcpp { -std::string PacketTrailerLayer::getTrailerDataAsHexString() const -{ - return byteArrayToHexString(m_Data, m_DataLen, m_DataLen + 4); -} + std::string PacketTrailerLayer::getTrailerDataAsHexString() const + { + return byteArrayToHexString(m_Data, m_DataLen, m_DataLen + 4); + } -std::string PacketTrailerLayer::toString() const -{ - std::ostringstream dataLenStream; - dataLenStream << m_DataLen; + std::string PacketTrailerLayer::toString() const + { + std::ostringstream dataLenStream; + dataLenStream << m_DataLen; - std::string trailerStr = byteArrayToHexString(m_Data, m_DataLen, 15); + std::string trailerStr = byteArrayToHexString(m_Data, m_DataLen, 15); - if (m_DataLen > 15) - trailerStr += "..."; + if (m_DataLen > 15) + trailerStr += "..."; - return "Packet Trailer, Data: " + trailerStr + ", Length: " + dataLenStream.str() + " [Bytes]"; -} + return "Packet Trailer, Data: " + trailerStr + ", Length: " + dataLenStream.str() + " [Bytes]"; + } -} +} // namespace pcpp diff --git a/Packet++/src/PacketUtils.cpp b/Packet++/src/PacketUtils.cpp index c75d4b74d5..fda7a9bc40 100644 --- a/Packet++/src/PacketUtils.cpp +++ b/Packet++/src/PacketUtils.cpp @@ -9,239 +9,239 @@ namespace pcpp { -uint16_t computeChecksum(ScalarBuffer vec[], size_t vecSize) -{ - uint32_t sum = 0; - for (size_t i = 0; i vec[], size_t vecSize) { - uint32_t localSum = 0; - - // vec len is in bytes - for (size_t j = 0; j < vec[i].len / 2; j++) + uint32_t sum = 0; + for (size_t i = 0; i < vecSize; i++) { - PCPP_LOG_DEBUG("Value to add = 0x" << std::uppercase << std::hex << vec[i].buffer[j]); - localSum += vec[i].buffer[j]; - } - PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum); - - // check if there is one byte left - if (vec[i].len % 2) { - // access to the last byte using an uint8_t pointer - uint8_t *vecBytes = (uint8_t *)vec[i].buffer; - uint8_t lastByte = vecBytes[vec[i].len - 1]; - PCPP_LOG_DEBUG("1 byte left, adding value: 0x" << std::uppercase << std::hex << lastByte); - // We have read the latest byte manually but this byte should be properly interpreted - // as a 0xFF on LE and a 0xFF00 on BE to have a proper checksum computation - localSum += be16toh(lastByte << 8); + uint32_t localSum = 0; + + // vec len is in bytes + for (size_t j = 0; j < vec[i].len / 2; j++) + { + PCPP_LOG_DEBUG("Value to add = 0x" << std::uppercase << std::hex << vec[i].buffer[j]); + localSum += vec[i].buffer[j]; + } + PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum); + // check if there is one byte left + if (vec[i].len % 2) + { + // access to the last byte using an uint8_t pointer + uint8_t* vecBytes = (uint8_t*)vec[i].buffer; + uint8_t lastByte = vecBytes[vec[i].len - 1]; + PCPP_LOG_DEBUG("1 byte left, adding value: 0x" << std::uppercase << std::hex << lastByte); + // We have read the latest byte manually but this byte should be properly interpreted + // as a 0xFF on LE and a 0xFF00 on BE to have a proper checksum computation + localSum += be16toh(lastByte << 8); + + PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum); + } + + // carry count is added to the sum + while (localSum >> 16) + { + localSum = (localSum & 0xffff) + (localSum >> 16); + } PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum); + sum += localSum; } - // carry count is added to the sum - while (localSum>>16) + while (sum >> 16) { - localSum = (localSum & 0xffff) + (localSum >> 16); + sum = (sum & 0xffff) + (sum >> 16); } - PCPP_LOG_DEBUG("Local sum = " << localSum << ", 0x" << std::uppercase << std::hex << localSum); - sum += localSum; - } - - while (sum>>16) - { - sum = (sum & 0xffff) + (sum >> 16); - } - PCPP_LOG_DEBUG("Sum before invert = " << sum << ", 0x" << std::uppercase << std::hex << sum); + PCPP_LOG_DEBUG("Sum before invert = " << sum << ", 0x" << std::uppercase << std::hex << sum); - // To obtain the checksum we take the ones' complement of this result - uint16_t result = sum; - result = ~result; + // To obtain the checksum we take the ones' complement of this result + uint16_t result = sum; + result = ~result; - PCPP_LOG_DEBUG("Calculated checksum = " << sum << ", 0x" << std::uppercase << std::hex << result); + PCPP_LOG_DEBUG("Calculated checksum = " << sum << ", 0x" << std::uppercase << std::hex << result); - // We return the result in BigEndian byte order - return htobe16(result); -} - -uint16_t computePseudoHdrChecksum(uint8_t *dataPtr, size_t dataLen, IPAddress::AddressType ipAddrType, - uint8_t protocolType, IPAddress srcIPAddress, - IPAddress dstIPAddress) -{ - PCPP_LOG_DEBUG("Compute pseudo header checksum.\n DataLen = " << dataLen << "IPAddrType = " - << ipAddrType << "ProtocolType = " << protocolType << "SrcIP = " << srcIPAddress - << "DstIP = " << dstIPAddress); - - uint16_t checksumRes = 0; - ScalarBuffer vec[2]; - vec[0].buffer = (uint16_t *) dataPtr; - vec[0].len = dataLen; - - if (ipAddrType == IPAddress::IPv4AddressType) - { - uint32_t srcIP = srcIPAddress.getIPv4().toInt(); - uint32_t dstIP = dstIPAddress.getIPv4().toInt(); - uint16_t pseudoHeader[6]; - pseudoHeader[0] = srcIP >> 16; - pseudoHeader[1] = srcIP & 0xFFFF; - pseudoHeader[2] = dstIP >> 16; - pseudoHeader[3] = dstIP & 0xFFFF; - pseudoHeader[4] = 0xffff & htobe16(dataLen); - pseudoHeader[5] = htobe16(0x00ff & protocolType); - vec[1].buffer = pseudoHeader; - vec[1].len = 12; - checksumRes = computeChecksum(vec, 2); - } - else if (ipAddrType == IPAddress::IPv6AddressType) - { - uint16_t pseudoHeader[18]; - srcIPAddress.getIPv6().copyTo((uint8_t *) pseudoHeader); - dstIPAddress.getIPv6().copyTo((uint8_t *) (pseudoHeader + 8)); - pseudoHeader[16] = 0xffff & htobe16(dataLen); - pseudoHeader[17] = htobe16(0x00ff & protocolType); - vec[1].buffer = pseudoHeader; - vec[1].len = 36; - checksumRes = computeChecksum(vec, 2); - } - else - { - PCPP_LOG_ERROR("Compute pseudo header checksum failed, for unknown IPAddrType = " << ipAddrType); + // We return the result in BigEndian byte order + return htobe16(result); } - PCPP_LOG_DEBUG("Pseudo header checksum = 0xX" << std::uppercase << std::hex << checksumRes); - - return checksumRes; -} + uint16_t computePseudoHdrChecksum(uint8_t* dataPtr, size_t dataLen, IPAddress::AddressType ipAddrType, + uint8_t protocolType, IPAddress srcIPAddress, IPAddress dstIPAddress) + { + PCPP_LOG_DEBUG("Compute pseudo header checksum.\n DataLen = " << dataLen << "IPAddrType = " << ipAddrType + << "ProtocolType = " << protocolType << "SrcIP = " + << srcIPAddress << "DstIP = " << dstIPAddress); -static const uint32_t FNV_PRIME = 16777619u; -static const uint32_t OFFSET_BASIS = 2166136261u; + uint16_t checksumRes = 0; + ScalarBuffer vec[2]; + vec[0].buffer = (uint16_t*)dataPtr; + vec[0].len = dataLen; -uint32_t fnvHash(ScalarBuffer vec[], size_t vecSize) -{ - uint32_t hash = OFFSET_BASIS; - for (size_t i = 0; i < vecSize; ++i) - { - for (size_t j = 0; j < vec[i].len; ++j) + if (ipAddrType == IPAddress::IPv4AddressType) { - hash *= FNV_PRIME; - hash ^= vec[i].buffer[j]; + uint32_t srcIP = srcIPAddress.getIPv4().toInt(); + uint32_t dstIP = dstIPAddress.getIPv4().toInt(); + uint16_t pseudoHeader[6]; + pseudoHeader[0] = srcIP >> 16; + pseudoHeader[1] = srcIP & 0xFFFF; + pseudoHeader[2] = dstIP >> 16; + pseudoHeader[3] = dstIP & 0xFFFF; + pseudoHeader[4] = 0xffff & htobe16(dataLen); + pseudoHeader[5] = htobe16(0x00ff & protocolType); + vec[1].buffer = pseudoHeader; + vec[1].len = 12; + checksumRes = computeChecksum(vec, 2); + } + else if (ipAddrType == IPAddress::IPv6AddressType) + { + uint16_t pseudoHeader[18]; + srcIPAddress.getIPv6().copyTo((uint8_t*)pseudoHeader); + dstIPAddress.getIPv6().copyTo((uint8_t*)(pseudoHeader + 8)); + pseudoHeader[16] = 0xffff & htobe16(dataLen); + pseudoHeader[17] = htobe16(0x00ff & protocolType); + vec[1].buffer = pseudoHeader; + vec[1].len = 36; + checksumRes = computeChecksum(vec, 2); + } + else + { + PCPP_LOG_ERROR("Compute pseudo header checksum failed, for unknown IPAddrType = " << ipAddrType); } - } - return hash; -} - -uint32_t fnvHash(uint8_t* buffer, size_t bufSize) -{ - ScalarBuffer scalarBuf; - scalarBuf.buffer = buffer; - scalarBuf.len = bufSize; - return fnvHash(&scalarBuf, 1); -} - -uint32_t hash5Tuple(Packet* packet, bool const& directionUnique) -{ - if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6)) - return 0; - - if (packet->isPacketOfType(ICMP)) - return 0; - if (!(packet->isPacketOfType(TCP)) && (!packet->isPacketOfType(UDP))) - return 0; + PCPP_LOG_DEBUG("Pseudo header checksum = 0xX" << std::uppercase << std::hex << checksumRes); - ScalarBuffer vec[5]; + return checksumRes; + } - uint16_t portSrc = 0; - uint16_t portDst = 0; - int srcPosition = 0; + static const uint32_t FNV_PRIME = 16777619u; + static const uint32_t OFFSET_BASIS = 2166136261u; - TcpLayer* tcpLayer = packet->getLayerOfType(true); // lookup in reverse order - if (tcpLayer != nullptr) + uint32_t fnvHash(ScalarBuffer vec[], size_t vecSize) { - portSrc = tcpLayer->getTcpHeader()->portSrc; - portDst = tcpLayer->getTcpHeader()->portDst; + uint32_t hash = OFFSET_BASIS; + for (size_t i = 0; i < vecSize; ++i) + { + for (size_t j = 0; j < vec[i].len; ++j) + { + hash *= FNV_PRIME; + hash ^= vec[i].buffer[j]; + } + } + return hash; } - else + + uint32_t fnvHash(uint8_t* buffer, size_t bufSize) { - UdpLayer* udpLayer = packet->getLayerOfType(true); - portSrc = udpLayer->getUdpHeader()->portSrc; - portDst = udpLayer->getUdpHeader()->portDst; + ScalarBuffer scalarBuf; + scalarBuf.buffer = buffer; + scalarBuf.len = bufSize; + return fnvHash(&scalarBuf, 1); } - if( ! directionUnique) + uint32_t hash5Tuple(Packet* packet, bool const& directionUnique) { - if (portDst < portSrc) - srcPosition = 1; - } + if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6)) + return 0; - vec[0 + srcPosition].buffer = (uint8_t*)&portSrc; - vec[0 + srcPosition].len = 2; - vec[1 - srcPosition].buffer = (uint8_t*)&portDst; - vec[1 - srcPosition].len = 2; + if (packet->isPacketOfType(ICMP)) + return 0; + if (!(packet->isPacketOfType(TCP)) && (!packet->isPacketOfType(UDP))) + return 0; - IPv4Layer* ipv4Layer = packet->getLayerOfType(); - if (ipv4Layer != nullptr) - { - if (!directionUnique && portSrc == portDst && ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc) - srcPosition = 1; - - vec[2 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; - vec[2 + srcPosition].len = 4; - vec[3 - srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst; - vec[3 - srcPosition].len = 4; - vec[4].buffer = &(ipv4Layer->getIPv4Header()->protocol); - vec[4].len = 1; - } - else - { - IPv6Layer* ipv6Layer = packet->getLayerOfType(); - if (!directionUnique && portSrc == portDst && memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0) - srcPosition = 1; - - vec[2 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc; - vec[2 + srcPosition].len = 16; - vec[3 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst; - vec[3 - srcPosition].len = 16; - vec[4].buffer = &(ipv6Layer->getIPv6Header()->nextHeader); - vec[4].len = 1; - } + ScalarBuffer vec[5]; - return pcpp::fnvHash(vec, 5); -} + uint16_t portSrc = 0; + uint16_t portDst = 0; + int srcPosition = 0; + TcpLayer* tcpLayer = packet->getLayerOfType(true); // lookup in reverse order + if (tcpLayer != nullptr) + { + portSrc = tcpLayer->getTcpHeader()->portSrc; + portDst = tcpLayer->getTcpHeader()->portDst; + } + else + { + UdpLayer* udpLayer = packet->getLayerOfType(true); + portSrc = udpLayer->getUdpHeader()->portSrc; + portDst = udpLayer->getUdpHeader()->portDst; + } -uint32_t hash2Tuple(Packet* packet) -{ - if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6)) - return 0; + if (!directionUnique) + { + if (portDst < portSrc) + srcPosition = 1; + } - ScalarBuffer vec[2]; + vec[0 + srcPosition].buffer = (uint8_t*)&portSrc; + vec[0 + srcPosition].len = 2; + vec[1 - srcPosition].buffer = (uint8_t*)&portDst; + vec[1 - srcPosition].len = 2; - IPv4Layer* ipv4Layer = packet->getLayerOfType(); - if (ipv4Layer != nullptr) - { - int srcPosition = 0; - if (ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc) - srcPosition = 1; + IPv4Layer* ipv4Layer = packet->getLayerOfType(); + if (ipv4Layer != nullptr) + { + if (!directionUnique && portSrc == portDst && + ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc) + srcPosition = 1; + + vec[2 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; + vec[2 + srcPosition].len = 4; + vec[3 - srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst; + vec[3 - srcPosition].len = 4; + vec[4].buffer = &(ipv4Layer->getIPv4Header()->protocol); + vec[4].len = 1; + } + else + { + IPv6Layer* ipv6Layer = packet->getLayerOfType(); + if (!directionUnique && portSrc == portDst && + memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0) + srcPosition = 1; + + vec[2 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc; + vec[2 + srcPosition].len = 16; + vec[3 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst; + vec[3 - srcPosition].len = 16; + vec[4].buffer = &(ipv6Layer->getIPv6Header()->nextHeader); + vec[4].len = 1; + } - vec[0 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; - vec[0 + srcPosition].len = 4; - vec[1 - srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst; - vec[1 - srcPosition].len = 4; + return pcpp::fnvHash(vec, 5); } - else + + uint32_t hash2Tuple(Packet* packet) { - IPv6Layer* ipv6Layer = packet->getLayerOfType(); - int srcPosition = 0; - if (memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0) - srcPosition = 1; + if (!packet->isPacketOfType(IPv4) && !packet->isPacketOfType(IPv6)) + return 0; - vec[0 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc; - vec[0 + srcPosition].len = 16; - vec[1 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst; - vec[1 - srcPosition].len = 16; - } + ScalarBuffer vec[2]; - return pcpp::fnvHash(vec, 2); -} + IPv4Layer* ipv4Layer = packet->getLayerOfType(); + if (ipv4Layer != nullptr) + { + int srcPosition = 0; + if (ipv4Layer->getIPv4Header()->ipDst < ipv4Layer->getIPv4Header()->ipSrc) + srcPosition = 1; + + vec[0 + srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipSrc; + vec[0 + srcPosition].len = 4; + vec[1 - srcPosition].buffer = (uint8_t*)&ipv4Layer->getIPv4Header()->ipDst; + vec[1 - srcPosition].len = 4; + } + else + { + IPv6Layer* ipv6Layer = packet->getLayerOfType(); + int srcPosition = 0; + if (memcmp(ipv6Layer->getIPv6Header()->ipDst, ipv6Layer->getIPv6Header()->ipSrc, 16) < 0) + srcPosition = 1; + + vec[0 + srcPosition].buffer = ipv6Layer->getIPv6Header()->ipSrc; + vec[0 + srcPosition].len = 16; + vec[1 - srcPosition].buffer = ipv6Layer->getIPv6Header()->ipDst; + vec[1 - srcPosition].len = 16; + } + + return pcpp::fnvHash(vec, 2); + } } // namespace pcpp diff --git a/Packet++/src/PayloadLayer.cpp b/Packet++/src/PayloadLayer.cpp index 5e3f7f1e40..b85177ca85 100644 --- a/Packet++/src/PayloadLayer.cpp +++ b/Packet++/src/PayloadLayer.cpp @@ -8,51 +8,51 @@ namespace pcpp { -PayloadLayer::PayloadLayer(const uint8_t* data, size_t dataLen) : Layer() -{ - m_Data = new uint8_t[dataLen]; - memcpy(m_Data, data, dataLen); - m_DataLen = dataLen; - m_Protocol = GenericPayload; -} - -PayloadLayer::PayloadLayer(const std::string& payloadAsHexStream) -{ - m_DataLen = payloadAsHexStream.length() / 2; - m_Data = new uint8_t[m_DataLen]; - m_Protocol = GenericPayload; - if (hexStringToByteArray(payloadAsHexStream, m_Data, m_DataLen) == 0) + PayloadLayer::PayloadLayer(const uint8_t* data, size_t dataLen) : Layer() { - delete [] m_Data; - m_Data = nullptr; - m_DataLen = 0; + m_Data = new uint8_t[dataLen]; + memcpy(m_Data, data, dataLen); + m_DataLen = dataLen; + m_Protocol = GenericPayload; } -} -void PayloadLayer::setPayload(const uint8_t* newPayload, size_t newPayloadLength) -{ - if (newPayloadLength < m_DataLen) + PayloadLayer::PayloadLayer(const std::string& payloadAsHexStream) { - // shorten payload layer - shortenLayer(newPayloadLength, m_DataLen - newPayloadLength); + m_DataLen = payloadAsHexStream.length() / 2; + m_Data = new uint8_t[m_DataLen]; + m_Protocol = GenericPayload; + if (hexStringToByteArray(payloadAsHexStream, m_Data, m_DataLen) == 0) + { + delete[] m_Data; + m_Data = nullptr; + m_DataLen = 0; + } } - else if (newPayloadLength > m_DataLen) + + void PayloadLayer::setPayload(const uint8_t* newPayload, size_t newPayloadLength) { - // extend payload layer - extendLayer(m_DataLen, newPayloadLength - m_DataLen); + if (newPayloadLength < m_DataLen) + { + // shorten payload layer + shortenLayer(newPayloadLength, m_DataLen - newPayloadLength); + } + else if (newPayloadLength > m_DataLen) + { + // extend payload layer + extendLayer(m_DataLen, newPayloadLength - m_DataLen); + } + + // and copy data to layer + // this is also executed if the newPayloadLength == m_DataLen + memcpy(m_Data, newPayload, newPayloadLength); } - // and copy data to layer - // this is also executed if the newPayloadLength == m_DataLen - memcpy(m_Data, newPayload, newPayloadLength); -} - -std::string PayloadLayer::toString() const -{ - std::ostringstream dataLenStream; - dataLenStream << m_DataLen; + std::string PayloadLayer::toString() const + { + std::ostringstream dataLenStream; + dataLenStream << m_DataLen; - return "Payload Layer, Data length: " + dataLenStream.str() + " [Bytes]"; -} + return "Payload Layer, Data length: " + dataLenStream.str() + " [Bytes]"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/RadiusLayer.cpp b/Packet++/src/RadiusLayer.cpp index 4d4d58f77d..d5ad43ec36 100644 --- a/Packet++/src/RadiusLayer.cpp +++ b/Packet++/src/RadiusLayer.cpp @@ -10,249 +10,246 @@ namespace pcpp { -RadiusAttribute RadiusAttributeBuilder::build() const -{ - size_t recSize = m_RecValueLen+2; - uint8_t* recordBuffer = new uint8_t[recSize]; - memset(recordBuffer, 0, recSize); - recordBuffer[0] = static_cast(m_RecType); - recordBuffer[1] = static_cast(recSize); - if (m_RecValueLen > 0) - memcpy(recordBuffer+2, m_RecValue, m_RecValueLen); - - return RadiusAttribute(recordBuffer); -} - -RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize) -{ - m_DataLen = sizeof(radius_header); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = Radius; - - radius_header* hdr = getRadiusHeader(); - hdr->code = code; - hdr->id = id; - hdr->length = htobe16(sizeof(radius_header)); - if (authenticatorArrSize == 0 || authenticator == nullptr) - return; - if (authenticatorArrSize > 16) - authenticatorArrSize = 16; - memcpy(hdr->authenticator, authenticator, authenticatorArrSize); -} - -RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const std::string &authenticator) -{ - m_DataLen = sizeof(radius_header); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = Radius; - - radius_header* hdr = getRadiusHeader(); - hdr->code = code; - hdr->id = id; - hdr->length = htobe16(sizeof(radius_header)); - setAuthenticatorValue(authenticator); -} - -RadiusAttribute RadiusLayer::addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset) -{ - RadiusAttribute newAttr = attrBuilder.build(); - if (newAttr.isNull()) + RadiusAttribute RadiusAttributeBuilder::build() const { - PCPP_LOG_ERROR("Cannot build new attribute of type " << (int)newAttr.getType()); - return newAttr; + size_t recSize = m_RecValueLen + 2; + uint8_t* recordBuffer = new uint8_t[recSize]; + memset(recordBuffer, 0, recSize); + recordBuffer[0] = static_cast(m_RecType); + recordBuffer[1] = static_cast(recSize); + if (m_RecValueLen > 0) + memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); + + return RadiusAttribute(recordBuffer); } - size_t sizeToExtend = newAttr.getTotalSize(); - if (!extendLayer(offset, sizeToExtend)) + RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const uint8_t* authenticator, uint8_t authenticatorArrSize) { - PCPP_LOG_ERROR("Could not extend RadiusLayer in [" << newAttr.getTotalSize() << "] bytes"); - newAttr.purgeRecordData(); - return RadiusAttribute(nullptr); + m_DataLen = sizeof(radius_header); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = Radius; + + radius_header* hdr = getRadiusHeader(); + hdr->code = code; + hdr->id = id; + hdr->length = htobe16(sizeof(radius_header)); + if (authenticatorArrSize == 0 || authenticator == nullptr) + return; + if (authenticatorArrSize > 16) + authenticatorArrSize = 16; + memcpy(hdr->authenticator, authenticator, authenticatorArrSize); } - memcpy(m_Data + offset, newAttr.getRecordBasePtr(), newAttr.getTotalSize()); + RadiusLayer::RadiusLayer(uint8_t code, uint8_t id, const std::string& authenticator) + { + m_DataLen = sizeof(radius_header); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = Radius; + + radius_header* hdr = getRadiusHeader(); + hdr->code = code; + hdr->id = id; + hdr->length = htobe16(sizeof(radius_header)); + setAuthenticatorValue(authenticator); + } - uint8_t* newAttrPtr = m_Data + offset; + RadiusAttribute RadiusLayer::addAttrAt(const RadiusAttributeBuilder& attrBuilder, int offset) + { + RadiusAttribute newAttr = attrBuilder.build(); + if (newAttr.isNull()) + { + PCPP_LOG_ERROR("Cannot build new attribute of type " << (int)newAttr.getType()); + return newAttr; + } - m_AttributeReader.changeTLVRecordCount(1); + size_t sizeToExtend = newAttr.getTotalSize(); + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend RadiusLayer in [" << newAttr.getTotalSize() << "] bytes"); + newAttr.purgeRecordData(); + return RadiusAttribute(nullptr); + } - newAttr.purgeRecordData(); + memcpy(m_Data + offset, newAttr.getRecordBasePtr(), newAttr.getTotalSize()); - getRadiusHeader()->length = htobe16(m_DataLen); + uint8_t* newAttrPtr = m_Data + offset; - return RadiusAttribute(newAttrPtr); -} + m_AttributeReader.changeTLVRecordCount(1); -std::string RadiusLayer::getAuthenticatorValue() const -{ - return byteArrayToHexString(getRadiusHeader()->authenticator, 16); -} + newAttr.purgeRecordData(); -void RadiusLayer::setAuthenticatorValue(const std::string& authValue) -{ - hexStringToByteArray(authValue, getRadiusHeader()->authenticator, 16); -} + getRadiusHeader()->length = htobe16(m_DataLen); -std::string RadiusLayer::getRadiusMessageString(uint8_t radiusMessageCode) -{ - switch (radiusMessageCode) - { - case 1: - return "Access-Request"; - case 2: - return "Access-Accept"; - case 3: - return "Access-Reject"; - case 4: - return "Accounting-Request"; - case 5: - return "Accounting-Response"; - case 11: - return "Access-Challenge"; - case 12: - return "Status-Server"; - case 13: - return "Status-Client"; - case 40: - return "Disconnect-Request"; - case 41: - return "Disconnect-ACK"; - case 42: - return "Disconnect-NAK"; - case 43: - return "CoA-Request"; - case 44: - return "CoA-ACK"; - case 45: - return "CoA-NAK"; - case 255: - return "Reserved"; - default: - return "Unknown"; + return RadiusAttribute(newAttrPtr); } -} - -size_t RadiusLayer::getHeaderLen() const -{ - uint16_t len = be16toh(getRadiusHeader()->length); - if (len > m_DataLen) - return m_DataLen; - return len; -} - -void RadiusLayer::computeCalculateFields() -{ - getRadiusHeader()->length = htobe16(m_DataLen); -} - -std::string RadiusLayer::toString() const -{ - std::ostringstream str; - str << "RADIUS Layer, " << - RadiusLayer::getRadiusMessageString(getRadiusHeader()->code) << - "(" << - (int)getRadiusHeader()->code << - "), " - "Id=" << - (int)getRadiusHeader()->id << - ", " << - "Length=" << - be16toh(getRadiusHeader()->length); - - return str.str(); -} - -RadiusAttribute RadiusLayer::getFirstAttribute() const -{ - return m_AttributeReader.getFirstTLVRecord(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); -} + std::string RadiusLayer::getAuthenticatorValue() const + { + return byteArrayToHexString(getRadiusHeader()->authenticator, 16); + } -RadiusAttribute RadiusLayer::getNextAttribute(RadiusAttribute& attr) const -{ - return m_AttributeReader.getNextTLVRecord(attr, getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); -} + void RadiusLayer::setAuthenticatorValue(const std::string& authValue) + { + hexStringToByteArray(authValue, getRadiusHeader()->authenticator, 16); + } -RadiusAttribute RadiusLayer::getAttribute(uint8_t attributeType) const -{ - return m_AttributeReader.getTLVRecord(attributeType, getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); -} + std::string RadiusLayer::getRadiusMessageString(uint8_t radiusMessageCode) + { + switch (radiusMessageCode) + { + case 1: + return "Access-Request"; + case 2: + return "Access-Accept"; + case 3: + return "Access-Reject"; + case 4: + return "Accounting-Request"; + case 5: + return "Accounting-Response"; + case 11: + return "Access-Challenge"; + case 12: + return "Status-Server"; + case 13: + return "Status-Client"; + case 40: + return "Disconnect-Request"; + case 41: + return "Disconnect-ACK"; + case 42: + return "Disconnect-NAK"; + case 43: + return "CoA-Request"; + case 44: + return "CoA-ACK"; + case 45: + return "CoA-NAK"; + case 255: + return "Reserved"; + default: + return "Unknown"; + } + } -size_t RadiusLayer::getAttributeCount() const -{ - return m_AttributeReader.getTLVRecordCount(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); -} + size_t RadiusLayer::getHeaderLen() const + { + uint16_t len = be16toh(getRadiusHeader()->length); + if (len > m_DataLen) + return m_DataLen; -RadiusAttribute RadiusLayer::addAttribute(const RadiusAttributeBuilder& attrBuilder) -{ - int offset = getHeaderLen(); - return addAttrAt(attrBuilder, offset); -} + return len; + } -RadiusAttribute RadiusLayer::addAttributeAfter(const RadiusAttributeBuilder& attrBuilder, uint8_t prevAttrType) -{ - int offset = 0; + void RadiusLayer::computeCalculateFields() + { + getRadiusHeader()->length = htobe16(m_DataLen); + } - RadiusAttribute prevAttr = getAttribute(prevAttrType); + std::string RadiusLayer::toString() const + { + std::ostringstream str; + str << "RADIUS Layer, " << RadiusLayer::getRadiusMessageString(getRadiusHeader()->code) << "(" + << (int)getRadiusHeader()->code + << "), " + "Id=" + << (int)getRadiusHeader()->id << ", " + << "Length=" << be16toh(getRadiusHeader()->length); + + return str.str(); + } - if (prevAttr.isNull()) + RadiusAttribute RadiusLayer::getFirstAttribute() const { - offset = getHeaderLen(); + return m_AttributeReader.getFirstTLVRecord(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); } - else + + RadiusAttribute RadiusLayer::getNextAttribute(RadiusAttribute& attr) const { - offset = prevAttr.getRecordBasePtr() + prevAttr.getTotalSize() - m_Data; + return m_AttributeReader.getNextTLVRecord(attr, getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); } - return addAttrAt(attrBuilder, offset); -} + RadiusAttribute RadiusLayer::getAttribute(uint8_t attributeType) const + { + return m_AttributeReader.getTLVRecord(attributeType, getAttributesBasePtr(), + getHeaderLen() - sizeof(radius_header)); + } -bool RadiusLayer::removeAttribute(uint8_t attrType) -{ - RadiusAttribute attrToRemove = getAttribute(attrType); - if (attrToRemove.isNull()) + size_t RadiusLayer::getAttributeCount() const { - return false; + return m_AttributeReader.getTLVRecordCount(getAttributesBasePtr(), getHeaderLen() - sizeof(radius_header)); } - int offset = attrToRemove.getRecordBasePtr() - m_Data; + RadiusAttribute RadiusLayer::addAttribute(const RadiusAttributeBuilder& attrBuilder) + { + int offset = getHeaderLen(); + return addAttrAt(attrBuilder, offset); + } - if (!shortenLayer(offset, attrToRemove.getTotalSize())) + RadiusAttribute RadiusLayer::addAttributeAfter(const RadiusAttributeBuilder& attrBuilder, uint8_t prevAttrType) { - return false; + int offset = 0; + + RadiusAttribute prevAttr = getAttribute(prevAttrType); + + if (prevAttr.isNull()) + { + offset = getHeaderLen(); + } + else + { + offset = prevAttr.getRecordBasePtr() + prevAttr.getTotalSize() - m_Data; + } + + return addAttrAt(attrBuilder, offset); } - m_AttributeReader.changeTLVRecordCount(-1); - getRadiusHeader()->length = htobe16(m_DataLen); + bool RadiusLayer::removeAttribute(uint8_t attrType) + { + RadiusAttribute attrToRemove = getAttribute(attrType); + if (attrToRemove.isNull()) + { + return false; + } - return true; -} + int offset = attrToRemove.getRecordBasePtr() - m_Data; -bool RadiusLayer::removeAllAttributes() -{ - int offset = sizeof(radius_header); + if (!shortenLayer(offset, attrToRemove.getTotalSize())) + { + return false; + } - if (!shortenLayer(offset, getHeaderLen()-offset)) - return false; + m_AttributeReader.changeTLVRecordCount(-1); + getRadiusHeader()->length = htobe16(m_DataLen); + + return true; + } + + bool RadiusLayer::removeAllAttributes() + { + int offset = sizeof(radius_header); - m_AttributeReader.changeTLVRecordCount(0-getAttributeCount()); + if (!shortenLayer(offset, getHeaderLen() - offset)) + return false; - getRadiusHeader()->length = htobe16(m_DataLen); + m_AttributeReader.changeTLVRecordCount(0 - getAttributeCount()); - return true; -} + getRadiusHeader()->length = htobe16(m_DataLen); -bool RadiusLayer::isDataValid(const uint8_t* udpData, size_t udpDataLen) -{ - if(udpData != nullptr && udpDataLen >= sizeof(radius_header)) + return true; + } + + bool RadiusLayer::isDataValid(const uint8_t* udpData, size_t udpDataLen) { - const radius_header* radHdr = reinterpret_cast(udpData); - size_t radLen = be16toh(radHdr->length); - return radLen >= sizeof(radius_header) && radLen <= udpDataLen; + if (udpData != nullptr && udpDataLen >= sizeof(radius_header)) + { + const radius_header* radHdr = reinterpret_cast(udpData); + size_t radLen = be16toh(radHdr->length); + return radLen >= sizeof(radius_header) && radLen <= udpDataLen; + } + return false; } - return false; -} -} +} // namespace pcpp diff --git a/Packet++/src/RawPacket.cpp b/Packet++/src/RawPacket.cpp index 07dbbbe21c..4a42a3c7be 100644 --- a/Packet++/src/RawPacket.cpp +++ b/Packet++/src/RawPacket.cpp @@ -8,212 +8,221 @@ namespace pcpp { -void RawPacket::init(bool deleteRawDataAtDestructor) -{ - m_RawData = nullptr; - m_RawDataLen = 0; - m_FrameLength = 0; - m_DeleteRawDataAtDestructor = deleteRawDataAtDestructor; - m_RawPacketSet = false; - m_LinkLayerType = LINKTYPE_ETHERNET; -} - -RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) -{ - timespec nsec_time = {}; - TIMEVAL_TO_TIMESPEC(×tamp, &nsec_time); - init(deleteRawDataAtDestructor); - setRawData(pRawData, rawDataLen, nsec_time, layerType); -} - -RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) -{ - init(deleteRawDataAtDestructor); - setRawData(pRawData, rawDataLen, timestamp, layerType); -} - -RawPacket::RawPacket() -{ - init(); -} + void RawPacket::init(bool deleteRawDataAtDestructor) + { + m_RawData = nullptr; + m_RawDataLen = 0; + m_FrameLength = 0; + m_DeleteRawDataAtDestructor = deleteRawDataAtDestructor; + m_RawPacketSet = false; + m_LinkLayerType = LINKTYPE_ETHERNET; + } -RawPacket::~RawPacket() -{ - if (m_DeleteRawDataAtDestructor) + RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, + LinkLayerType layerType) { - delete[] m_RawData; + timespec nsec_time = {}; + TIMEVAL_TO_TIMESPEC(×tamp, &nsec_time); + init(deleteRawDataAtDestructor); + setRawData(pRawData, rawDataLen, nsec_time, layerType); } -} -RawPacket::RawPacket(const RawPacket& other) -{ - m_RawData = nullptr; - copyDataFrom(other, true); -} + RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, + LinkLayerType layerType) + { + init(deleteRawDataAtDestructor); + setRawData(pRawData, rawDataLen, timestamp, layerType); + } -RawPacket& RawPacket::operator=(const RawPacket& other) -{ - if (this != &other) + RawPacket::RawPacket() { - if (m_RawData != nullptr) - delete [] m_RawData; + init(); + } - m_RawPacketSet = false; + RawPacket::~RawPacket() + { + if (m_DeleteRawDataAtDestructor) + { + delete[] m_RawData; + } + } + RawPacket::RawPacket(const RawPacket& other) + { + m_RawData = nullptr; copyDataFrom(other, true); } - return *this; -} + RawPacket& RawPacket::operator=(const RawPacket& other) + { + if (this != &other) + { + if (m_RawData != nullptr) + delete[] m_RawData; + m_RawPacketSet = false; -void RawPacket::copyDataFrom(const RawPacket& other, bool allocateData) -{ - if (!other.m_RawPacketSet) - return; + copyDataFrom(other, true); + } - m_TimeStamp = other.m_TimeStamp; + return *this; + } - if (allocateData) + void RawPacket::copyDataFrom(const RawPacket& other, bool allocateData) { - m_DeleteRawDataAtDestructor = true; - m_RawData = new uint8_t[other.m_RawDataLen]; - m_RawDataLen = other.m_RawDataLen; + if (!other.m_RawPacketSet) + return; + + m_TimeStamp = other.m_TimeStamp; + + if (allocateData) + { + m_DeleteRawDataAtDestructor = true; + m_RawData = new uint8_t[other.m_RawDataLen]; + m_RawDataLen = other.m_RawDataLen; + } + + memcpy(m_RawData, other.m_RawData, other.m_RawDataLen); + m_LinkLayerType = other.m_LinkLayerType; + m_FrameLength = other.m_FrameLength; + m_RawPacketSet = true; } - memcpy(m_RawData, other.m_RawData, other.m_RawDataLen); - m_LinkLayerType = other.m_LinkLayerType; - m_FrameLength = other.m_FrameLength; - m_RawPacketSet = true; -} + bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType, + int frameLength) + { + timespec nsec_time; + TIMEVAL_TO_TIMESPEC(×tamp, &nsec_time); + return setRawData(pRawData, rawDataLen, nsec_time, layerType, frameLength); + } -bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType, int frameLength) -{ - timespec nsec_time; - TIMEVAL_TO_TIMESPEC(×tamp, &nsec_time); - return setRawData(pRawData, rawDataLen, nsec_time, layerType, frameLength); -} + bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType, + int frameLength) + { + if (frameLength == -1) + frameLength = rawDataLen; + m_FrameLength = frameLength; + if (m_RawData != nullptr && m_DeleteRawDataAtDestructor) + { + delete[] m_RawData; + } + + m_RawData = (uint8_t*)pRawData; + m_RawDataLen = rawDataLen; + m_TimeStamp = timestamp; + m_RawPacketSet = true; + m_LinkLayerType = layerType; + return true; + } -bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType, int frameLength) -{ - if(frameLength == -1) - frameLength = rawDataLen; - m_FrameLength = frameLength; - if (m_RawData != nullptr && m_DeleteRawDataAtDestructor) + bool RawPacket::initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, + LinkLayerType layerType) { - delete[] m_RawData; + init(false); + return setRawData(pRawData, rawDataLen, timestamp, layerType); } - m_RawData = (uint8_t*)pRawData; - m_RawDataLen = rawDataLen; - m_TimeStamp = timestamp; - m_RawPacketSet = true; - m_LinkLayerType = layerType; - return true; -} + void RawPacket::clear() + { + if (m_RawData != nullptr) + delete[] m_RawData; -bool RawPacket::initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType) -{ - init(false); - return setRawData(pRawData, rawDataLen, timestamp, layerType); -} + m_RawData = nullptr; + m_RawDataLen = 0; + m_FrameLength = 0; + m_RawPacketSet = false; + } -void RawPacket::clear() -{ - if (m_RawData != nullptr) - delete[] m_RawData; + void RawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) + { + memcpy((uint8_t*)m_RawData + m_RawDataLen, dataToAppend, dataToAppendLen); + m_RawDataLen += dataToAppendLen; + m_FrameLength = m_RawDataLen; + } - m_RawData = nullptr; - m_RawDataLen = 0; - m_FrameLength = 0; - m_RawPacketSet = false; -} + void RawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) + { + // memmove copies data as if there was an intermediate buffer in between - so it allows for copying processes on + // overlapping src/dest ptrs if insertData is called with atIndex == m_RawDataLen, then no data is being moved. + // The data of the raw packet is still extended by dataToInsertLen + memmove((uint8_t*)m_RawData + atIndex + dataToInsertLen, (uint8_t*)m_RawData + atIndex, m_RawDataLen - atIndex); + + if (dataToInsert != nullptr) + { + // insert data + memcpy((uint8_t*)m_RawData + atIndex, dataToInsert, dataToInsertLen); + } + + m_RawDataLen += dataToInsertLen; + m_FrameLength = m_RawDataLen; + } -void RawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) -{ - memcpy((uint8_t*)m_RawData + m_RawDataLen, dataToAppend, dataToAppendLen); - m_RawDataLen += dataToAppendLen; - m_FrameLength = m_RawDataLen; -} + bool RawPacket::reallocateData(size_t newBufferLength) + { + if ((int)newBufferLength == m_RawDataLen) + return true; -void RawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) -{ - // memmove copies data as if there was an intermediate buffer in between - so it allows for copying processes on overlapping src/dest ptrs - // if insertData is called with atIndex == m_RawDataLen, then no data is being moved. The data of the raw packet is still extended by dataToInsertLen - memmove((uint8_t*)m_RawData + atIndex + dataToInsertLen, (uint8_t*)m_RawData + atIndex, m_RawDataLen - atIndex); + if ((int)newBufferLength < m_RawDataLen) + { + PCPP_LOG_ERROR("Cannot reallocate raw packet to a smaller size. Current data length: " + << m_RawDataLen << "; requested length: " << newBufferLength); + return false; + } - if (dataToInsert != nullptr) - { - // insert data - memcpy((uint8_t*)m_RawData + atIndex, dataToInsert, dataToInsertLen); - } + uint8_t* newBuffer = new uint8_t[newBufferLength]; + memset(newBuffer, 0, newBufferLength); + memcpy(newBuffer, m_RawData, m_RawDataLen); + if (m_DeleteRawDataAtDestructor) + delete[] m_RawData; - m_RawDataLen += dataToInsertLen; - m_FrameLength = m_RawDataLen; -} + m_DeleteRawDataAtDestructor = true; + m_RawData = newBuffer; -bool RawPacket::reallocateData(size_t newBufferLength) -{ - if ((int)newBufferLength == m_RawDataLen) return true; + } - if ((int)newBufferLength < m_RawDataLen) + bool RawPacket::removeData(int atIndex, size_t numOfBytesToRemove) { - PCPP_LOG_ERROR("Cannot reallocate raw packet to a smaller size. Current data length: " << m_RawDataLen << "; requested length: " << newBufferLength); - return false; + if ((atIndex + (int)numOfBytesToRemove) > m_RawDataLen) + { + PCPP_LOG_ERROR("Remove section is out of raw packet bound"); + return false; + } + + // only move data if we are removing data somewhere in the layer, not at the end of the last layer + // this is so that resizing of the last layer can occur fast by just reducing the fictional length of the packet + // (m_RawDataLen) by the given amount + if ((atIndex + (int)numOfBytesToRemove) != m_RawDataLen) + // memmove copies data as if there was an intermediate buffer in between - so it allows for copying + // processes on overlapping src/dest ptrs + memmove((uint8_t*)m_RawData + atIndex, (uint8_t*)m_RawData + atIndex + numOfBytesToRemove, + m_RawDataLen - (atIndex + numOfBytesToRemove)); + + m_RawDataLen -= numOfBytesToRemove; + m_FrameLength = m_RawDataLen; + return true; } - uint8_t* newBuffer = new uint8_t[newBufferLength]; - memset(newBuffer, 0, newBufferLength); - memcpy(newBuffer, m_RawData, m_RawDataLen); - if (m_DeleteRawDataAtDestructor) - delete [] m_RawData; - - m_DeleteRawDataAtDestructor = true; - m_RawData = newBuffer; - - return true; -} - -bool RawPacket::removeData(int atIndex, size_t numOfBytesToRemove) -{ - if ((atIndex + (int)numOfBytesToRemove) > m_RawDataLen) + bool RawPacket::setPacketTimeStamp(timeval timestamp) { - PCPP_LOG_ERROR("Remove section is out of raw packet bound"); - return false; + timespec nsec_time; + TIMEVAL_TO_TIMESPEC(×tamp, &nsec_time); + return setPacketTimeStamp(nsec_time); } - // only move data if we are removing data somewhere in the layer, not at the end of the last layer - // this is so that resizing of the last layer can occur fast by just reducing the fictional length of the packet (m_RawDataLen) by the given amount - if((atIndex + (int)numOfBytesToRemove) != m_RawDataLen) - // memmove copies data as if there was an intermediate buffer in between - so it allows for copying processes on overlapping src/dest ptrs - memmove((uint8_t*)m_RawData + atIndex, (uint8_t*)m_RawData + atIndex + numOfBytesToRemove, m_RawDataLen - (atIndex + numOfBytesToRemove)); - - m_RawDataLen -= numOfBytesToRemove; - m_FrameLength = m_RawDataLen; - return true; -} - -bool RawPacket::setPacketTimeStamp(timeval timestamp) -{ - timespec nsec_time; - TIMEVAL_TO_TIMESPEC(×tamp, &nsec_time); - return setPacketTimeStamp(nsec_time); -} - -bool RawPacket::setPacketTimeStamp(timespec timestamp) -{ - m_TimeStamp = timestamp; - return true; -} - -bool RawPacket::isLinkTypeValid(int linkTypeValue) -{ - if ((linkTypeValue < 0 || linkTypeValue > 264) && linkTypeValue != 276) - return false; + bool RawPacket::setPacketTimeStamp(timespec timestamp) + { + m_TimeStamp = timestamp; + return true; + } - switch (static_cast(linkTypeValue)) + bool RawPacket::isLinkTypeValid(int linkTypeValue) { + if ((linkTypeValue < 0 || linkTypeValue > 264) && linkTypeValue != 276) + return false; + + switch (static_cast(linkTypeValue)) + { case LINKTYPE_ETHERNET: case LINKTYPE_LINUX_SLL: case LINKTYPE_RAW: @@ -308,7 +317,7 @@ bool RawPacket::isLinkTypeValid(int linkTypeValue) return true; default: return false; + } } -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/S7CommLayer.cpp b/Packet++/src/S7CommLayer.cpp index a61fa1aa28..40af5c0b29 100644 --- a/Packet++/src/S7CommLayer.cpp +++ b/Packet++/src/S7CommLayer.cpp @@ -11,7 +11,7 @@ namespace pcpp { S7CommLayer::S7CommLayer(uint8_t msgType, uint16_t pduRef, uint16_t paramLength, uint16_t dataLength, - uint8_t errorClass, uint8_t errorCode) + uint8_t errorClass, uint8_t errorCode) { size_t basicHeaderLen = msgType == 0x03 ? sizeof(s7comm_ack_data_hdr) : sizeof(s7commhdr); size_t headerLen = basicHeaderLen + paramLength + dataLength; @@ -21,7 +21,7 @@ namespace pcpp if (msgType == 0x03) { - auto *ack_d = (s7comm_ack_data_hdr *)m_Data; + auto* ack_d = (s7comm_ack_data_hdr*)m_Data; ack_d->protocolId = 0x32; ack_d->msgType = msgType; ack_d->reserved = 0x0000; @@ -33,7 +33,7 @@ namespace pcpp } else { - auto *s7commHdr = (s7commhdr *)m_Data; + auto* s7commHdr = (s7commhdr*)m_Data; s7commHdr->protocolId = 0x32; s7commHdr->msgType = msgType; s7commHdr->reserved = 0x0000; @@ -72,7 +72,7 @@ namespace pcpp return str.str(); } - bool S7CommLayer::isDataValid(const uint8_t *data, size_t dataSize) + bool S7CommLayer::isDataValid(const uint8_t* data, size_t dataSize) { if (!data || dataSize < sizeof(s7commhdr)) return false; @@ -80,33 +80,66 @@ namespace pcpp return data[0] == 0x32; } - uint8_t S7CommLayer::getProtocolId() const { return getS7commHeader()->protocolId; } + uint8_t S7CommLayer::getProtocolId() const + { + return getS7commHeader()->protocolId; + } - uint8_t S7CommLayer::getMsgType() const { return getS7commHeader()->msgType; } + uint8_t S7CommLayer::getMsgType() const + { + return getS7commHeader()->msgType; + } - uint16_t S7CommLayer::getParamLength() const { return be16toh(getS7commHeader()->paramLength); } + uint16_t S7CommLayer::getParamLength() const + { + return be16toh(getS7commHeader()->paramLength); + } - uint16_t S7CommLayer::getPduRef() const { return be16toh(getS7commHeader()->pduRef); } + uint16_t S7CommLayer::getPduRef() const + { + return be16toh(getS7commHeader()->pduRef); + } - uint16_t S7CommLayer::getDataLength() const { return be16toh(getS7commHeader()->dataLength); } + uint16_t S7CommLayer::getDataLength() const + { + return be16toh(getS7commHeader()->dataLength); + } - void S7CommLayer::setMsgType(uint8_t msgType) const { getS7commHeader()->msgType = msgType; } + void S7CommLayer::setMsgType(uint8_t msgType) const + { + getS7commHeader()->msgType = msgType; + } - uint8_t S7CommLayer::getErrorCode() const { return getS7commAckDataHeader()->errorCode; } + uint8_t S7CommLayer::getErrorCode() const + { + return getS7commAckDataHeader()->errorCode; + } - uint8_t S7CommLayer::getErrorClass() const { return getS7commAckDataHeader()->errorClass; } + uint8_t S7CommLayer::getErrorClass() const + { + return getS7commAckDataHeader()->errorClass; + } - void S7CommLayer::setPduRef(uint16_t pduRef) const { getS7commHeader()->pduRef = htobe16(pduRef); } + void S7CommLayer::setPduRef(uint16_t pduRef) const + { + getS7commHeader()->pduRef = htobe16(pduRef); + } - void S7CommLayer::setErrorCode(uint8_t errorCode) const { getS7commAckDataHeader()->errorCode = errorCode; } + void S7CommLayer::setErrorCode(uint8_t errorCode) const + { + getS7commAckDataHeader()->errorCode = errorCode; + } - void S7CommLayer::setErrorClass(uint8_t errorClass) const { getS7commAckDataHeader()->errorClass = errorClass; } + void S7CommLayer::setErrorClass(uint8_t errorClass) const + { + getS7commAckDataHeader()->errorClass = errorClass; + } - const S7CommParameter *S7CommLayer::getParameter() + const S7CommParameter* S7CommLayer::getParameter() { if (!m_Parameter) { - uint8_t *payload = m_Data + getS7commHeaderLength(); + uint8_t* payload = m_Data + getS7commHeaderLength(); m_Parameter = new S7CommParameter(payload, getParamLength()); } @@ -122,4 +155,4 @@ namespace pcpp return sizeof(s7commhdr); } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SSHLayer.cpp b/Packet++/src/SSHLayer.cpp index 5a862bde5b..2023bc11a5 100644 --- a/Packet++/src/SSHLayer.cpp +++ b/Packet++/src/SSHLayer.cpp @@ -11,252 +11,249 @@ namespace pcpp #define SSH_LAYER_BASE_STRING "SSH Layer" + // ---------------- + // SSHLayer methods + // ---------------- -// ---------------- -// SSHLayer methods -// ---------------- + SSHLayer* SSHLayer::createSSHMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + { + SSHIdentificationMessage* sshIdnetMsg = SSHIdentificationMessage::tryParse(data, dataLen, prevLayer, packet); + if (sshIdnetMsg != nullptr) + return sshIdnetMsg; -SSHLayer* SSHLayer::createSSHMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - SSHIdentificationMessage* sshIdnetMsg = SSHIdentificationMessage::tryParse(data, dataLen, prevLayer, packet); - if (sshIdnetMsg != nullptr) - return sshIdnetMsg; + SSHHandshakeMessage* sshHandshakeMessage = SSHHandshakeMessage::tryParse(data, dataLen, prevLayer, packet); + if (sshHandshakeMessage != nullptr) + return sshHandshakeMessage; - SSHHandshakeMessage* sshHandshakeMessage = SSHHandshakeMessage::tryParse(data, dataLen, prevLayer, packet); - if (sshHandshakeMessage != nullptr) - return sshHandshakeMessage; + return new SSHEncryptedMessage(data, dataLen, prevLayer, packet); + } - return new SSHEncryptedMessage(data, dataLen, prevLayer, packet); -} + void SSHLayer::parseNextLayer() + { + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + m_NextLayer = SSHLayer::createSSHMessage(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + } -void SSHLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; - m_NextLayer = SSHLayer::createSSHMessage(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); -} + // -------------------------------- + // SSHIdentificationMessage methods + // -------------------------------- + SSHIdentificationMessage* SSHIdentificationMessage::tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + { + // Payload must be at least as long as the string "SSH-" + if (dataLen < 5) + return nullptr; -// -------------------------------- -// SSHIdentificationMessage methods -// -------------------------------- + // Payload must begin with "SSH-" and end with "\n" + if (data[0] == 0x53 && data[1] == 0x53 && data[2] == 0x48 && data[3] == 0x2d && data[dataLen - 1] == 0x0a) + return new SSHIdentificationMessage(data, dataLen, prevLayer, packet); -SSHIdentificationMessage* SSHIdentificationMessage::tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - // Payload must be at least as long as the string "SSH-" - if (dataLen < 5) return nullptr; + } - // Payload must begin with "SSH-" and end with "\n" - if (data[0] == 0x53 && data[1] == 0x53 && data[2] == 0x48 && data[3] == 0x2d && data[dataLen - 1] == 0x0a) - return new SSHIdentificationMessage(data, dataLen, prevLayer, packet); - - return nullptr; -} - -std::string SSHIdentificationMessage::getIdentificationMessage() -{ - // check if message ends with "\r\n" or just with "\n" - size_t identMsgEOL = (m_Data[m_DataLen - 2] == 0x0d ? 2 : 1); - return std::string(reinterpret_cast(m_Data), m_DataLen - identMsgEOL); -} - -std::string SSHIdentificationMessage::toString() const -{ - return std::string(SSH_LAYER_BASE_STRING) + ", " + "Identification message"; -} - - -// --------------------------- -// SSHHandshakeMessage methods -// --------------------------- - -SSHHandshakeMessage::SSHHandshakeMessageType SSHHandshakeMessage::getMessageType() const -{ - uint8_t messageCode = getMsgBaseHeader()->messageCode; - if (messageCode == 20 || messageCode == 21 || (messageCode >= 30 && messageCode <= 34)) - return static_cast(messageCode); - return SSHHandshakeMessage::SSH_MSG_UNKNOWN; -} - -std::string SSHHandshakeMessage::getMessageTypeStr() const -{ - switch (getMessageType()) + std::string SSHIdentificationMessage::getIdentificationMessage() { - case SSHHandshakeMessage::SSH_MSG_KEX_INIT: - return "Key Exchange Init"; - case SSHHandshakeMessage::SSH_MSG_NEW_KEYS: - return "New Keys"; - case SSHHandshakeMessage::SSH_MSG_KEX_DH_INIT: - return "Diffie-Hellman Key Exchange Init"; - case SSHHandshakeMessage::SSH_MSG_KEX_DH_REPLY: - return "Diffie-Hellman Key Exchange Reply"; - case SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_INIT: - return "Diffie-Hellman Group Exchange Init"; - case SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_REPLY: - return "Diffie-Hellman Group Exchange Reply"; - case SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_REQUEST: - return "Diffie-Hellman Group Exchange Request"; - default: - return "Unknown"; - + // check if message ends with "\r\n" or just with "\n" + size_t identMsgEOL = (m_Data[m_DataLen - 2] == 0x0d ? 2 : 1); + return std::string(reinterpret_cast(m_Data), m_DataLen - identMsgEOL); } -} -uint8_t* SSHHandshakeMessage::getSSHHandshakeMessage() const -{ - return m_Data + sizeof(SSHHandshakeMessage::ssh_message_base); -} + std::string SSHIdentificationMessage::toString() const + { + return std::string(SSH_LAYER_BASE_STRING) + ", " + "Identification message"; + } -size_t SSHHandshakeMessage::getSSHHandshakeMessageLength() const -{ - uint32_t length = be32toh(getMsgBaseHeader()->packetLength); - return static_cast(length) - getMsgBaseHeader()->paddingLength - sizeof(uint8_t)*2; -} + // --------------------------- + // SSHHandshakeMessage methods + // --------------------------- -size_t SSHHandshakeMessage::getPaddingLength() const -{ - return getMsgBaseHeader()->paddingLength; -} + SSHHandshakeMessage::SSHHandshakeMessageType SSHHandshakeMessage::getMessageType() const + { + uint8_t messageCode = getMsgBaseHeader()->messageCode; + if (messageCode == 20 || messageCode == 21 || (messageCode >= 30 && messageCode <= 34)) + return static_cast(messageCode); + return SSHHandshakeMessage::SSH_MSG_UNKNOWN; + } -size_t SSHHandshakeMessage::getHeaderLen() const -{ - return (size_t)be32toh(getMsgBaseHeader()->packetLength) + sizeof(uint32_t); -} + std::string SSHHandshakeMessage::getMessageTypeStr() const + { + switch (getMessageType()) + { + case SSHHandshakeMessage::SSH_MSG_KEX_INIT: + return "Key Exchange Init"; + case SSHHandshakeMessage::SSH_MSG_NEW_KEYS: + return "New Keys"; + case SSHHandshakeMessage::SSH_MSG_KEX_DH_INIT: + return "Diffie-Hellman Key Exchange Init"; + case SSHHandshakeMessage::SSH_MSG_KEX_DH_REPLY: + return "Diffie-Hellman Key Exchange Reply"; + case SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_INIT: + return "Diffie-Hellman Group Exchange Init"; + case SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_REPLY: + return "Diffie-Hellman Group Exchange Reply"; + case SSHHandshakeMessage::SSH_MSG_KEX_DH_GEX_REQUEST: + return "Diffie-Hellman Group Exchange Request"; + default: + return "Unknown"; + } + } -std::string SSHHandshakeMessage::toString() const -{ - return std::string(SSH_LAYER_BASE_STRING) + ", " + "Handshake Message: " + getMessageTypeStr(); -} + uint8_t* SSHHandshakeMessage::getSSHHandshakeMessage() const + { + return m_Data + sizeof(SSHHandshakeMessage::ssh_message_base); + } -SSHHandshakeMessage* SSHHandshakeMessage::tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - if (dataLen < sizeof(SSHHandshakeMessage::ssh_message_base)) + size_t SSHHandshakeMessage::getSSHHandshakeMessageLength() const { - PCPP_LOG_DEBUG("Data length is smaller than the minimum size of an SSH handshake message. It's probably not an SSH handshake message"); - return nullptr; + uint32_t length = be32toh(getMsgBaseHeader()->packetLength); + return static_cast(length) - getMsgBaseHeader()->paddingLength - sizeof(uint8_t) * 2; } - SSHHandshakeMessage::ssh_message_base* msgBase = (SSHHandshakeMessage::ssh_message_base*)data; + size_t SSHHandshakeMessage::getPaddingLength() const + { + return getMsgBaseHeader()->paddingLength; + } - uint32_t msgLength = be32toh(msgBase->packetLength); - if (msgLength + sizeof(uint32_t) > dataLen) + size_t SSHHandshakeMessage::getHeaderLen() const { - PCPP_LOG_DEBUG("Message size is larger than layer size. It's probably not an SSH handshake message"); - return nullptr; + return (size_t)be32toh(getMsgBaseHeader()->packetLength) + sizeof(uint32_t); } - if (msgBase->paddingLength > msgLength) + std::string SSHHandshakeMessage::toString() const { - PCPP_LOG_DEBUG("Message padding is larger than message size. It's probably not an SSH handshake message"); - return nullptr; + return std::string(SSH_LAYER_BASE_STRING) + ", " + "Handshake Message: " + getMessageTypeStr(); } - if (msgBase->messageCode != 20 && - msgBase->messageCode != 21 && - (msgBase->messageCode < 30 || msgBase->messageCode > 49)) + SSHHandshakeMessage* SSHHandshakeMessage::tryParse(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + { + if (dataLen < sizeof(SSHHandshakeMessage::ssh_message_base)) { - PCPP_LOG_DEBUG("Unknown message type " << (int)msgBase->messageCode << ". It's probably not an SSH handshake message"); + PCPP_LOG_DEBUG( + "Data length is smaller than the minimum size of an SSH handshake message. It's probably not an SSH handshake message"); return nullptr; } - switch (msgBase->messageCode) - { - case SSHHandshakeMessage::SSH_MSG_KEX_INIT: - return new SSHKeyExchangeInitMessage(data, dataLen, prevLayer, packet); - default: - return new SSHHandshakeMessage(data, dataLen, prevLayer, packet); - } -} + SSHHandshakeMessage::ssh_message_base* msgBase = (SSHHandshakeMessage::ssh_message_base*)data; + uint32_t msgLength = be32toh(msgBase->packetLength); + if (msgLength + sizeof(uint32_t) > dataLen) + { + PCPP_LOG_DEBUG("Message size is larger than layer size. It's probably not an SSH handshake message"); + return nullptr; + } -// --------------------------------- -// SSHKeyExchangeInitMessage methods -// --------------------------------- + if (msgBase->paddingLength > msgLength) + { + PCPP_LOG_DEBUG("Message padding is larger than message size. It's probably not an SSH handshake message"); + return nullptr; + } -SSHKeyExchangeInitMessage::SSHKeyExchangeInitMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SSHHandshakeMessage(data, dataLen, prevLayer, packet), m_OffsetsInitialized(false) -{ - memset(m_FieldOffsets, 0, 11*sizeof(size_t)); -} + if (msgBase->messageCode != 20 && msgBase->messageCode != 21 && + (msgBase->messageCode < 30 || msgBase->messageCode > 49)) + { + PCPP_LOG_DEBUG("Unknown message type " << (int)msgBase->messageCode + << ". It's probably not an SSH handshake message"); + return nullptr; + } -void SSHKeyExchangeInitMessage::parseMessageAndInitOffsets() -{ - m_OffsetsInitialized = true; - if (m_DataLen <= sizeof(ssh_message_base) + 16) - return; + switch (msgBase->messageCode) + { + case SSHHandshakeMessage::SSH_MSG_KEX_INIT: + return new SSHKeyExchangeInitMessage(data, dataLen, prevLayer, packet); + default: + return new SSHHandshakeMessage(data, dataLen, prevLayer, packet); + } + } - size_t offset = sizeof(ssh_message_base) + 16; - for (int i = 0; i < 10; i++) + // --------------------------------- + // SSHKeyExchangeInitMessage methods + // --------------------------------- + + SSHKeyExchangeInitMessage::SSHKeyExchangeInitMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, + Packet* packet) + : SSHHandshakeMessage(data, dataLen, prevLayer, packet), m_OffsetsInitialized(false) { - if (offset + sizeof(uint32_t) >= m_DataLen) - return; + memset(m_FieldOffsets, 0, 11 * sizeof(size_t)); + } - size_t fieldLength = static_cast(be32toh(*(uint32_t*)(m_Data + offset))); - if (offset + sizeof(uint32_t) + fieldLength > m_DataLen) + void SSHKeyExchangeInitMessage::parseMessageAndInitOffsets() + { + m_OffsetsInitialized = true; + if (m_DataLen <= sizeof(ssh_message_base) + 16) return; - PCPP_LOG_DEBUG("Field offset [" << i << "] = " << offset << ", length = " << fieldLength); - m_FieldOffsets[i] = offset; - offset += sizeof(uint32_t) + fieldLength; - } + size_t offset = sizeof(ssh_message_base) + 16; + for (int i = 0; i < 10; i++) + { + if (offset + sizeof(uint32_t) >= m_DataLen) + return; - if (offset >= m_DataLen) - return; + size_t fieldLength = static_cast(be32toh(*(uint32_t*)(m_Data + offset))); + if (offset + sizeof(uint32_t) + fieldLength > m_DataLen) + return; - m_FieldOffsets[10] = offset; + PCPP_LOG_DEBUG("Field offset [" << i << "] = " << offset << ", length = " << fieldLength); + m_FieldOffsets[i] = offset; + offset += sizeof(uint32_t) + fieldLength; + } -} + if (offset >= m_DataLen) + return; -std::string SSHKeyExchangeInitMessage::getFieldValue(int fieldOffsetIndex) -{ - if (!m_OffsetsInitialized) - parseMessageAndInitOffsets(); + m_FieldOffsets[10] = offset; + } - if (m_FieldOffsets[fieldOffsetIndex] == 0) - return ""; + std::string SSHKeyExchangeInitMessage::getFieldValue(int fieldOffsetIndex) + { + if (!m_OffsetsInitialized) + parseMessageAndInitOffsets(); - size_t fieldOffset = m_FieldOffsets[fieldOffsetIndex]; - uint32_t fieldLength = be32toh(*(uint32_t*)(m_Data + fieldOffset)); - return std::string(reinterpret_cast(m_Data + fieldOffset + sizeof(uint32_t)), (size_t)fieldLength); -} + if (m_FieldOffsets[fieldOffsetIndex] == 0) + return ""; -uint8_t* SSHKeyExchangeInitMessage::getCookie() -{ - if (m_DataLen < sizeof(ssh_message_base) + 16) - return nullptr; + size_t fieldOffset = m_FieldOffsets[fieldOffsetIndex]; + uint32_t fieldLength = be32toh(*(uint32_t*)(m_Data + fieldOffset)); + return std::string(reinterpret_cast(m_Data + fieldOffset + sizeof(uint32_t)), (size_t)fieldLength); + } - return m_Data + sizeof(ssh_message_base); -} + uint8_t* SSHKeyExchangeInitMessage::getCookie() + { + if (m_DataLen < sizeof(ssh_message_base) + 16) + return nullptr; -std::string SSHKeyExchangeInitMessage::getCookieAsHexStream() -{ - uint8_t* cookie = getCookie(); - if (cookie == nullptr) - return ""; + return m_Data + sizeof(ssh_message_base); + } - return byteArrayToHexString(cookie, 16); -} + std::string SSHKeyExchangeInitMessage::getCookieAsHexStream() + { + uint8_t* cookie = getCookie(); + if (cookie == nullptr) + return ""; -bool SSHKeyExchangeInitMessage::isFirstKexPacketFollows() -{ - if (!m_OffsetsInitialized) - parseMessageAndInitOffsets(); + return byteArrayToHexString(cookie, 16); + } - if (m_FieldOffsets[10] == 0) - return false; + bool SSHKeyExchangeInitMessage::isFirstKexPacketFollows() + { + if (!m_OffsetsInitialized) + parseMessageAndInitOffsets(); - return m_Data[m_FieldOffsets[10]] != 0; -} + if (m_FieldOffsets[10] == 0) + return false; + return m_Data[m_FieldOffsets[10]] != 0; + } -// --------------------------- -// SSHEncryptedMessage methods -// --------------------------- + // --------------------------- + // SSHEncryptedMessage methods + // --------------------------- -std::string SSHEncryptedMessage::toString() const -{ - return std::string(SSH_LAYER_BASE_STRING) + ", " + "Encrypted Message"; -} + std::string SSHEncryptedMessage::toString() const + { + return std::string(SSH_LAYER_BASE_STRING) + ", " + "Encrypted Message"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SSLCommon.cpp b/Packet++/src/SSLCommon.cpp index 08070c1f0d..31207d8866 100644 --- a/Packet++/src/SSLCommon.cpp +++ b/Packet++/src/SSLCommon.cpp @@ -5,88 +5,87 @@ namespace pcpp { -// ------------------------- -// SSLVersion methods -// ------------------------- + // ------------------------- + // SSLVersion methods + // ------------------------- -SSLVersion::SSLVersionEnum SSLVersion::asEnum(bool countTlsDraftsAs1_3) -{ - if (m_SSLVersionValue >= 0x0300 && m_SSLVersionValue <= 0x0304) - return static_cast(m_SSLVersionValue); - - if ((m_SSLVersionValue >= 0x7f0e && m_SSLVersionValue <= 0x7f1c) || m_SSLVersionValue == 0xfb17 || m_SSLVersionValue == 0xfb1a) + SSLVersion::SSLVersionEnum SSLVersion::asEnum(bool countTlsDraftsAs1_3) { - if (countTlsDraftsAs1_3) - return SSLVersion::TLS1_3; - else + if (m_SSLVersionValue >= 0x0300 && m_SSLVersionValue <= 0x0304) return static_cast(m_SSLVersionValue); - } - - if (m_SSLVersionValue == 0x200) - return SSLVersion::SSL2; - return SSLVersion::Unknown; -} + if ((m_SSLVersionValue >= 0x7f0e && m_SSLVersionValue <= 0x7f1c) || m_SSLVersionValue == 0xfb17 || + m_SSLVersionValue == 0xfb1a) + { + if (countTlsDraftsAs1_3) + return SSLVersion::TLS1_3; + else + return static_cast(m_SSLVersionValue); + } + if (m_SSLVersionValue == 0x200) + return SSLVersion::SSL2; -std::string SSLVersion::toString(bool countTlsDraftsAs1_3) -{ - SSLVersionEnum enumValue = asEnum(countTlsDraftsAs1_3); + return SSLVersion::Unknown; + } - switch (enumValue) + std::string SSLVersion::toString(bool countTlsDraftsAs1_3) { - case SSLVersion::TLS1_3: - return "TLS 1.3"; - case SSLVersion::TLS1_2: - return "TLS 1.2"; - case SSLVersion::TLS1_1: - return "TLS 1.1"; - case SSLVersion::TLS1_0: - return "TLS 1.0"; - case SSLVersion::SSL3: - return "SSL 3.0"; - case SSLVersion::TLS1_3_D28: - return "TLS 1.3 (draft 28)"; - case SSLVersion::TLS1_3_D27: - return "TLS 1.3 (draft 27)"; - case SSLVersion::TLS1_3_D26: - return "TLS 1.3 (draft 26)"; - case SSLVersion::TLS1_3_D25: - return "TLS 1.3 (draft 25)"; - case SSLVersion::TLS1_3_D24: - return "TLS 1.3 (draft 24)"; - case SSLVersion::TLS1_3_D23: - return "TLS 1.3 (draft 23)"; - case SSLVersion::TLS1_3_D22: - return "TLS 1.3 (draft 22)"; - case SSLVersion::TLS1_3_D21: - return "TLS 1.3 (draft 21)"; - case SSLVersion::TLS1_3_D20: - return "TLS 1.3 (draft 20)"; - case SSLVersion::TLS1_3_D19: - return "TLS 1.3 (draft 19)"; - case SSLVersion::TLS1_3_D18: - return "TLS 1.3 (draft 18)"; - case SSLVersion::TLS1_3_D17: - return "TLS 1.3 (draft 17)"; - case SSLVersion::TLS1_3_D16: - return "TLS 1.3 (draft 16)"; - case SSLVersion::TLS1_3_D15: - return "TLS 1.3 (draft 15)"; - case SSLVersion::TLS1_3_D14: - return "TLS 1.3 (draft 14)"; - case SSLVersion::TLS1_3_FBD23: - return "TLS 1.3 (Facebook draft 23)"; - case SSLVersion::TLS1_3_FBD26: - return "TLS 1.3 (Facebook draft 26)"; - case SSLVersion::Unknown: - return "Unknown"; - case SSLVersion::SSL2: - return "SSL 2.0"; - default: - return "Unknown"; - } -} + SSLVersionEnum enumValue = asEnum(countTlsDraftsAs1_3); + switch (enumValue) + { + case SSLVersion::TLS1_3: + return "TLS 1.3"; + case SSLVersion::TLS1_2: + return "TLS 1.2"; + case SSLVersion::TLS1_1: + return "TLS 1.1"; + case SSLVersion::TLS1_0: + return "TLS 1.0"; + case SSLVersion::SSL3: + return "SSL 3.0"; + case SSLVersion::TLS1_3_D28: + return "TLS 1.3 (draft 28)"; + case SSLVersion::TLS1_3_D27: + return "TLS 1.3 (draft 27)"; + case SSLVersion::TLS1_3_D26: + return "TLS 1.3 (draft 26)"; + case SSLVersion::TLS1_3_D25: + return "TLS 1.3 (draft 25)"; + case SSLVersion::TLS1_3_D24: + return "TLS 1.3 (draft 24)"; + case SSLVersion::TLS1_3_D23: + return "TLS 1.3 (draft 23)"; + case SSLVersion::TLS1_3_D22: + return "TLS 1.3 (draft 22)"; + case SSLVersion::TLS1_3_D21: + return "TLS 1.3 (draft 21)"; + case SSLVersion::TLS1_3_D20: + return "TLS 1.3 (draft 20)"; + case SSLVersion::TLS1_3_D19: + return "TLS 1.3 (draft 19)"; + case SSLVersion::TLS1_3_D18: + return "TLS 1.3 (draft 18)"; + case SSLVersion::TLS1_3_D17: + return "TLS 1.3 (draft 17)"; + case SSLVersion::TLS1_3_D16: + return "TLS 1.3 (draft 16)"; + case SSLVersion::TLS1_3_D15: + return "TLS 1.3 (draft 15)"; + case SSLVersion::TLS1_3_D14: + return "TLS 1.3 (draft 14)"; + case SSLVersion::TLS1_3_FBD23: + return "TLS 1.3 (Facebook draft 23)"; + case SSLVersion::TLS1_3_FBD26: + return "TLS 1.3 (Facebook draft 26)"; + case SSLVersion::Unknown: + return "Unknown"; + case SSLVersion::SSL2: + return "SSL 2.0"; + default: + return "Unknown"; + } + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SSLHandshake.cpp b/Packet++/src/SSLHandshake.cpp index 6da7cc21ab..18baa236db 100644 --- a/Packet++/src/SSLHandshake.cpp +++ b/Packet++/src/SSLHandshake.cpp @@ -10,2139 +10,2131 @@ #include "Logger.h" #include "SSLHandshake.h" - namespace pcpp { -// -------------- -// SSLCipherSuite -// -------------- - -static const SSLCipherSuite Cipher1 = SSLCipherSuite(0x0000, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_NULL, SSL_HASH_NULL, "TLS_NULL_WITH_NULL_NULL"); -static const SSLCipherSuite Cipher2 = SSLCipherSuite(0x0001, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_MD5, "TLS_RSA_WITH_NULL_MD5"); -static const SSLCipherSuite Cipher3 = SSLCipherSuite(0x0002, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_RSA_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher4 = SSLCipherSuite(0x0003, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC4_40, SSL_HASH_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"); -static const SSLCipherSuite Cipher5 = SSLCipherSuite(0x0004, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_MD5, "TLS_RSA_WITH_RC4_128_MD5"); -static const SSLCipherSuite Cipher6 = SSLCipherSuite(0x0005, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_RSA_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher7 = SSLCipherSuite(0x0006, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC2_CBC_40, SSL_HASH_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"); -static const SSLCipherSuite Cipher8 = SSLCipherSuite(0x0007, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_IDEA_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"); -static const SSLCipherSuite Cipher9 = SSLCipherSuite(0x0008, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"); -static const SSLCipherSuite Cipher10 = SSLCipherSuite(0x0009, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher11 = SSLCipherSuite(0x000A, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher12 = SSLCipherSuite(0x000B, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"); -static const SSLCipherSuite Cipher13 = SSLCipherSuite(0x000C, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher14 = SSLCipherSuite(0x000D, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher15 = SSLCipherSuite(0x000E, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"); -static const SSLCipherSuite Cipher16 = SSLCipherSuite(0x000F, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher17 = SSLCipherSuite(0x0010, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher18 = SSLCipherSuite(0x0011, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"); -static const SSLCipherSuite Cipher19 = SSLCipherSuite(0x0012, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher20 = SSLCipherSuite(0x0013, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher21 = SSLCipherSuite(0x0014, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"); -static const SSLCipherSuite Cipher22 = SSLCipherSuite(0x0015, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher23 = SSLCipherSuite(0x0016, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher24 = SSLCipherSuite(0x0017, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_RC4_40, SSL_HASH_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"); -static const SSLCipherSuite Cipher25 = SSLCipherSuite(0x0018, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_RC4_128, SSL_HASH_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"); -static const SSLCipherSuite Cipher26 = SSLCipherSuite(0x0019, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"); -static const SSLCipherSuite Cipher27 = SSLCipherSuite(0x001A, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher28 = SSLCipherSuite(0x001B, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher29 = SSLCipherSuite(0x001E, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_KRB5_WITH_DES_CBC_SHA"); -static const SSLCipherSuite Cipher30 = SSLCipherSuite(0x001F, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher31 = SSLCipherSuite(0x0020, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_KRB5_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher32 = SSLCipherSuite(0x0021, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_IDEA_CBC, SSL_HASH_SHA, "TLS_KRB5_WITH_IDEA_CBC_SHA"); -static const SSLCipherSuite Cipher33 = SSLCipherSuite(0x0022, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC, SSL_HASH_MD5, "TLS_KRB5_WITH_DES_CBC_MD5"); -static const SSLCipherSuite Cipher34 = SSLCipherSuite(0x0023, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_3DES_EDE_CBC, SSL_HASH_MD5, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"); -static const SSLCipherSuite Cipher35 = SSLCipherSuite(0x0024, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_128, SSL_HASH_MD5, "TLS_KRB5_WITH_RC4_128_MD5"); -static const SSLCipherSuite Cipher36 = SSLCipherSuite(0x0025, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_IDEA_CBC, SSL_HASH_MD5, "TLS_KRB5_WITH_IDEA_CBC_MD5"); -static const SSLCipherSuite Cipher37 = SSLCipherSuite(0x0026, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC_40, SSL_HASH_SHA, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"); -static const SSLCipherSuite Cipher38 = SSLCipherSuite(0x0027, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC2_CBC_40, SSL_HASH_SHA, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"); -static const SSLCipherSuite Cipher39 = SSLCipherSuite(0x0028, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_40, SSL_HASH_SHA, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"); -static const SSLCipherSuite Cipher40 = SSLCipherSuite(0x0029, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC_40, SSL_HASH_MD5, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"); -static const SSLCipherSuite Cipher41 = SSLCipherSuite(0x002A, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC2_CBC_40, SSL_HASH_MD5, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"); -static const SSLCipherSuite Cipher42 = SSLCipherSuite(0x002B, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_40, SSL_HASH_MD5, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"); -static const SSLCipherSuite Cipher43 = SSLCipherSuite(0x002C, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_PSK_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher44 = SSLCipherSuite(0x002D, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher45 = SSLCipherSuite(0x002E, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher46 = SSLCipherSuite(0x002F, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher47 = SSLCipherSuite(0x0030, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher48 = SSLCipherSuite(0x0031, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher49 = SSLCipherSuite(0x0032, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher50 = SSLCipherSuite(0x0033, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher51 = SSLCipherSuite(0x0034, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher52 = SSLCipherSuite(0x0035, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher53 = SSLCipherSuite(0x0036, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher54 = SSLCipherSuite(0x0037, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher55 = SSLCipherSuite(0x0038, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher56 = SSLCipherSuite(0x0039, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher57 = SSLCipherSuite(0x003A, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher58 = SSLCipherSuite(0x003B, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_RSA_WITH_NULL_SHA256"); -static const SSLCipherSuite Cipher59 = SSLCipherSuite(0x003C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher60 = SSLCipherSuite(0x003D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"); -static const SSLCipherSuite Cipher61 = SSLCipherSuite(0x003E, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher62 = SSLCipherSuite(0x003F, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher63 = SSLCipherSuite(0x0040, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher64 = SSLCipherSuite(0x0041, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"); -static const SSLCipherSuite Cipher65 = SSLCipherSuite(0x0042, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"); -static const SSLCipherSuite Cipher66 = SSLCipherSuite(0x0043, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"); -static const SSLCipherSuite Cipher67 = SSLCipherSuite(0x0044, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"); -static const SSLCipherSuite Cipher68 = SSLCipherSuite(0x0045, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"); -static const SSLCipherSuite Cipher69 = SSLCipherSuite(0x0046, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"); -static const SSLCipherSuite Cipher70 = SSLCipherSuite(0x0067, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher71 = SSLCipherSuite(0x0068, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"); -static const SSLCipherSuite Cipher72 = SSLCipherSuite(0x0069, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"); -static const SSLCipherSuite Cipher73 = SSLCipherSuite(0x006A, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"); -static const SSLCipherSuite Cipher74 = SSLCipherSuite(0x006B, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"); -static const SSLCipherSuite Cipher75 = SSLCipherSuite(0x006C, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher76 = SSLCipherSuite(0x006D, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"); -static const SSLCipherSuite Cipher77 = SSLCipherSuite(0x0084, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"); -static const SSLCipherSuite Cipher78 = SSLCipherSuite(0x0085, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"); -static const SSLCipherSuite Cipher79 = SSLCipherSuite(0x0086, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"); -static const SSLCipherSuite Cipher80 = SSLCipherSuite(0x0087, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"); -static const SSLCipherSuite Cipher81 = SSLCipherSuite(0x0088, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"); -static const SSLCipherSuite Cipher82 = SSLCipherSuite(0x0089, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"); -static const SSLCipherSuite Cipher83 = SSLCipherSuite(0x008A, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_PSK_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher84 = SSLCipherSuite(0x008B, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher85 = SSLCipherSuite(0x008C, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_PSK_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher86 = SSLCipherSuite(0x008D, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_PSK_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher87 = SSLCipherSuite(0x008E, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher88 = SSLCipherSuite(0x008F, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher89 = SSLCipherSuite(0x0090, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher90 = SSLCipherSuite(0x0091, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher91 = SSLCipherSuite(0x0092, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher92 = SSLCipherSuite(0x0093, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher93 = SSLCipherSuite(0x0094, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher94 = SSLCipherSuite(0x0095, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher95 = SSLCipherSuite(0x0096, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_SEED_CBC_SHA"); -static const SSLCipherSuite Cipher96 = SSLCipherSuite(0x0097, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_SEED_CBC_SHA"); -static const SSLCipherSuite Cipher97 = SSLCipherSuite(0x0098, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_SEED_CBC_SHA"); -static const SSLCipherSuite Cipher98 = SSLCipherSuite(0x0099, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"); -static const SSLCipherSuite Cipher99 = SSLCipherSuite(0x009A, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"); -static const SSLCipherSuite Cipher100 = SSLCipherSuite(0x009B, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_SEED_CBC_SHA"); -static const SSLCipherSuite Cipher101 = SSLCipherSuite(0x009C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher102 = SSLCipherSuite(0x009D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_RSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher103 = SSLCipherSuite(0x009E, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher104 = SSLCipherSuite(0x009F, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher105 = SSLCipherSuite(0x00A0, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher106 = SSLCipherSuite(0x00A1, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher107 = SSLCipherSuite(0x00A2, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher108 = SSLCipherSuite(0x00A3, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher109 = SSLCipherSuite(0x00A4, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher110 = SSLCipherSuite(0x00A5, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher111 = SSLCipherSuite(0x00A6, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher112 = SSLCipherSuite(0x00A7, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher113 = SSLCipherSuite(0x00A8, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_PSK_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher114 = SSLCipherSuite(0x00A9, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_PSK_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher115 = SSLCipherSuite(0x00AA, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher116 = SSLCipherSuite(0x00AB, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher117 = SSLCipherSuite(0x00AC, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher118 = SSLCipherSuite(0x00AD, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher119 = SSLCipherSuite(0x00AE, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_PSK_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher120 = SSLCipherSuite(0x00AF, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_PSK_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher121 = SSLCipherSuite(0x00B0, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_PSK_WITH_NULL_SHA256"); -static const SSLCipherSuite Cipher122 = SSLCipherSuite(0x00B1, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_PSK_WITH_NULL_SHA384"); -static const SSLCipherSuite Cipher123 = SSLCipherSuite(0x00B2, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher124 = SSLCipherSuite(0x00B3, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher125 = SSLCipherSuite(0x00B4, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_NULL_SHA256"); -static const SSLCipherSuite Cipher126 = SSLCipherSuite(0x00B5, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_NULL_SHA384"); -static const SSLCipherSuite Cipher127 = SSLCipherSuite(0x00B6, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher128 = SSLCipherSuite(0x00B7, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher129 = SSLCipherSuite(0x00B8, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_NULL_SHA256"); -static const SSLCipherSuite Cipher130 = SSLCipherSuite(0x00B9, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_NULL_SHA384"); -static const SSLCipherSuite Cipher131 = SSLCipherSuite(0x00BA, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher132 = SSLCipherSuite(0x00BB, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher133 = SSLCipherSuite(0x00BC, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher134 = SSLCipherSuite(0x00BD, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher135 = SSLCipherSuite(0x00BE, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher136 = SSLCipherSuite(0x00BF, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher137 = SSLCipherSuite(0x00C0, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"); -static const SSLCipherSuite Cipher138 = SSLCipherSuite(0x00C1, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"); -static const SSLCipherSuite Cipher139 = SSLCipherSuite(0x00C2, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"); -static const SSLCipherSuite Cipher140 = SSLCipherSuite(0x00C3, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"); -static const SSLCipherSuite Cipher141 = SSLCipherSuite(0x00C4, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"); -static const SSLCipherSuite Cipher142 = SSLCipherSuite(0x00C5, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"); -static const SSLCipherSuite Cipher143 = SSLCipherSuite(0xC001, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher144 = SSLCipherSuite(0xC002, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher145 = SSLCipherSuite(0xC003, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher146 = SSLCipherSuite(0xC004, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher147 = SSLCipherSuite(0xC005, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher148 = SSLCipherSuite(0xC006, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher149 = SSLCipherSuite(0xC007, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher150 = SSLCipherSuite(0xC008, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher151 = SSLCipherSuite(0xC009, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher152 = SSLCipherSuite(0xC00A, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher153 = SSLCipherSuite(0xC00B, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher154 = SSLCipherSuite(0xC00C, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher155 = SSLCipherSuite(0xC00D, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher156 = SSLCipherSuite(0xC00E, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher157 = SSLCipherSuite(0xC00F, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher158 = SSLCipherSuite(0xC010, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher159 = SSLCipherSuite(0xC011, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher160 = SSLCipherSuite(0xC012, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher161 = SSLCipherSuite(0xC013, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher162 = SSLCipherSuite(0xC014, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher163 = SSLCipherSuite(0xC015, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher164 = SSLCipherSuite(0xC016, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher165 = SSLCipherSuite(0xC017, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher166 = SSLCipherSuite(0xC018, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher167 = SSLCipherSuite(0xC019, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher168 = SSLCipherSuite(0xC01A, SSL_KEYX_SRP, SSL_AUTH_SHA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher169 = SSLCipherSuite(0xC01B, SSL_KEYX_SRP, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher170 = SSLCipherSuite(0xC01C, SSL_KEYX_SRP, SSL_AUTH_DSS, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher171 = SSLCipherSuite(0xC01D, SSL_KEYX_SRP, SSL_AUTH_SHA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher172 = SSLCipherSuite(0xC01E, SSL_KEYX_SRP, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher173 = SSLCipherSuite(0xC01F, SSL_KEYX_SRP, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher174 = SSLCipherSuite(0xC020, SSL_KEYX_SRP, SSL_AUTH_SHA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher175 = SSLCipherSuite(0xC021, SSL_KEYX_SRP, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher176 = SSLCipherSuite(0xC022, SSL_KEYX_SRP, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher177 = SSLCipherSuite(0xC023, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher178 = SSLCipherSuite(0xC024, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher179 = SSLCipherSuite(0xC025, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher180 = SSLCipherSuite(0xC026, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher181 = SSLCipherSuite(0xC027, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher182 = SSLCipherSuite(0xC028, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher183 = SSLCipherSuite(0xC029, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher184 = SSLCipherSuite(0xC02A, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher185 = SSLCipherSuite(0xC02B, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher186 = SSLCipherSuite(0xC02C, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher187 = SSLCipherSuite(0xC02D, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher188 = SSLCipherSuite(0xC02E, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher189 = SSLCipherSuite(0xC02F, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher190 = SSLCipherSuite(0xC030, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher191 = SSLCipherSuite(0xC031, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher192 = SSLCipherSuite(0xC032, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher193 = SSLCipherSuite(0xC033, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_RC4_128_SHA"); -static const SSLCipherSuite Cipher194 = SSLCipherSuite(0xC034, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"); -static const SSLCipherSuite Cipher195 = SSLCipherSuite(0xC035, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"); -static const SSLCipherSuite Cipher196 = SSLCipherSuite(0xC036, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"); -static const SSLCipherSuite Cipher197 = SSLCipherSuite(0xC037, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"); -static const SSLCipherSuite Cipher198 = SSLCipherSuite(0xC038, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"); -static const SSLCipherSuite Cipher199 = SSLCipherSuite(0xC039, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_NULL_SHA"); -static const SSLCipherSuite Cipher200 = SSLCipherSuite(0xC03A, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_NULL_SHA256"); -static const SSLCipherSuite Cipher201 = SSLCipherSuite(0xC03B, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_NULL_SHA384"); -static const SSLCipherSuite Cipher202 = SSLCipherSuite(0xC03C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher203 = SSLCipherSuite(0xC03D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_RSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher204 = SSLCipherSuite(0xC03E, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher205 = SSLCipherSuite(0xC03F, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher206 = SSLCipherSuite(0xC040, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher207 = SSLCipherSuite(0xC041, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher208 = SSLCipherSuite(0xC042, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher209 = SSLCipherSuite(0xC043, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher210 = SSLCipherSuite(0xC044, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher211 = SSLCipherSuite(0xC045, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher212 = SSLCipherSuite(0xC046, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher213 = SSLCipherSuite(0xC047, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher214 = SSLCipherSuite(0xC048, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher215 = SSLCipherSuite(0xC049, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher216 = SSLCipherSuite(0xC04A, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher217 = SSLCipherSuite(0xC04B, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher218 = SSLCipherSuite(0xC04C, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher219 = SSLCipherSuite(0xC04D, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher220 = SSLCipherSuite(0xC04E, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher221 = SSLCipherSuite(0xC04F, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher222 = SSLCipherSuite(0xC050, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher223 = SSLCipherSuite(0xC051, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher224 = SSLCipherSuite(0xC052, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher225 = SSLCipherSuite(0xC053, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher226 = SSLCipherSuite(0xC054, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher227 = SSLCipherSuite(0xC055, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher228 = SSLCipherSuite(0xC056, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher229 = SSLCipherSuite(0xC057, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher230 = SSLCipherSuite(0xC058, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher231 = SSLCipherSuite(0xC059, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher232 = SSLCipherSuite(0xC05A, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher233 = SSLCipherSuite(0xC05B, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher234 = SSLCipherSuite(0xC05C, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher235 = SSLCipherSuite(0xC05D, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher236 = SSLCipherSuite(0xC05E, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher237 = SSLCipherSuite(0xC05F, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher238 = SSLCipherSuite(0xC060, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher239 = SSLCipherSuite(0xC061, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher240 = SSLCipherSuite(0xC062, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher241 = SSLCipherSuite(0xC063, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher242 = SSLCipherSuite(0xC064, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_PSK_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher243 = SSLCipherSuite(0xC065, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_PSK_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher244 = SSLCipherSuite(0xC066, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher245 = SSLCipherSuite(0xC067, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher246 = SSLCipherSuite(0xC068, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher247 = SSLCipherSuite(0xC069, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher248 = SSLCipherSuite(0xC06A, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_PSK_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher249 = SSLCipherSuite(0xC06B, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_PSK_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher250 = SSLCipherSuite(0xC06C, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher251 = SSLCipherSuite(0xC06D, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher252 = SSLCipherSuite(0xC06E, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher253 = SSLCipherSuite(0xC06F, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher254 = SSLCipherSuite(0xC070, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher255 = SSLCipherSuite(0xC071, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher256 = SSLCipherSuite(0xC072, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher257 = SSLCipherSuite(0xC073, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher258 = SSLCipherSuite(0xC074, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher259 = SSLCipherSuite(0xC075, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher260 = SSLCipherSuite(0xC076, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher261 = SSLCipherSuite(0xC077, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher262 = SSLCipherSuite(0xC078, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher263 = SSLCipherSuite(0xC079, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher264 = SSLCipherSuite(0xC07A, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher265 = SSLCipherSuite(0xC07B, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher266 = SSLCipherSuite(0xC07C, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher267 = SSLCipherSuite(0xC07D, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher268 = SSLCipherSuite(0xC07E, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher269 = SSLCipherSuite(0xC07F, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher270 = SSLCipherSuite(0xC080, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher271 = SSLCipherSuite(0xC081, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher272 = SSLCipherSuite(0xC082, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher273 = SSLCipherSuite(0xC083, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher274 = SSLCipherSuite(0xC084, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher275 = SSLCipherSuite(0xC085, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher276 = SSLCipherSuite(0xC086, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher277 = SSLCipherSuite(0xC087, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher278 = SSLCipherSuite(0xC088, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher279 = SSLCipherSuite(0xC089, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher280 = SSLCipherSuite(0xC08A, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher281 = SSLCipherSuite(0xC08B, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher282 = SSLCipherSuite(0xC08C, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher283 = SSLCipherSuite(0xC08D, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher284 = SSLCipherSuite(0xC08E, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher285 = SSLCipherSuite(0xC08F, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher286 = SSLCipherSuite(0xC090, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher287 = SSLCipherSuite(0xC091, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher288 = SSLCipherSuite(0xC092, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"); -static const SSLCipherSuite Cipher289 = SSLCipherSuite(0xC093, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"); -static const SSLCipherSuite Cipher290 = SSLCipherSuite(0xC094, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher291 = SSLCipherSuite(0xC095, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher292 = SSLCipherSuite(0xC096, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher293 = SSLCipherSuite(0xC097, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher294 = SSLCipherSuite(0xC098, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher295 = SSLCipherSuite(0xC099, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher296 = SSLCipherSuite(0xC09A, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"); -static const SSLCipherSuite Cipher297 = SSLCipherSuite(0xC09B, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"); -static const SSLCipherSuite Cipher298 = SSLCipherSuite(0xC09C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_RSA_WITH_AES_128_CCM"); -static const SSLCipherSuite Cipher299 = SSLCipherSuite(0xC09D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_RSA_WITH_AES_256_CCM"); -static const SSLCipherSuite Cipher300 = SSLCipherSuite(0xC09E, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_DHE_RSA_WITH_AES_128_CCM"); -static const SSLCipherSuite Cipher301 = SSLCipherSuite(0xC09F, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_DHE_RSA_WITH_AES_256_CCM"); -static const SSLCipherSuite Cipher302 = SSLCipherSuite(0xC0A0, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_RSA_WITH_AES_128_CCM_8"); -static const SSLCipherSuite Cipher303 = SSLCipherSuite(0xC0A1, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_RSA_WITH_AES_256_CCM_8"); -static const SSLCipherSuite Cipher304 = SSLCipherSuite(0xC0A2, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_DHE_RSA_WITH_AES_128_CCM_8"); -static const SSLCipherSuite Cipher305 = SSLCipherSuite(0xC0A3, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_DHE_RSA_WITH_AES_256_CCM_8"); -static const SSLCipherSuite Cipher306 = SSLCipherSuite(0xC0A4, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_PSK_WITH_AES_128_CCM"); -static const SSLCipherSuite Cipher307 = SSLCipherSuite(0xC0A5, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_PSK_WITH_AES_256_CCM"); -static const SSLCipherSuite Cipher308 = SSLCipherSuite(0xC0A6, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_DHE_PSK_WITH_AES_128_CCM"); -static const SSLCipherSuite Cipher309 = SSLCipherSuite(0xC0A7, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_DHE_PSK_WITH_AES_256_CCM"); -static const SSLCipherSuite Cipher310 = SSLCipherSuite(0xC0A8, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_PSK_WITH_AES_128_CCM_8"); -static const SSLCipherSuite Cipher311 = SSLCipherSuite(0xC0A9, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_PSK_WITH_AES_256_CCM_8"); -static const SSLCipherSuite Cipher312 = SSLCipherSuite(0xC0AA, SSL_KEYX_PSK, SSL_AUTH_DHE, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_PSK_DHE_WITH_AES_128_CCM_8"); -static const SSLCipherSuite Cipher313 = SSLCipherSuite(0xC0AB, SSL_KEYX_PSK, SSL_AUTH_DHE, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_PSK_DHE_WITH_AES_256_CCM_8"); -static const SSLCipherSuite Cipher314 = SSLCipherSuite(0xC0AC, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"); -static const SSLCipherSuite Cipher315 = SSLCipherSuite(0xC0AD, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"); -static const SSLCipherSuite Cipher316 = SSLCipherSuite(0xC0AE, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"); -static const SSLCipherSuite Cipher317 = SSLCipherSuite(0xC0AF, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"); -static const SSLCipherSuite Cipher318 = SSLCipherSuite(0xCCA8, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher319 = SSLCipherSuite(0xCCA9, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher320 = SSLCipherSuite(0xCCAA, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher321 = SSLCipherSuite(0xCCAB, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher322 = SSLCipherSuite(0xCCAC, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher323 = SSLCipherSuite(0xCCAD, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher324 = SSLCipherSuite(0xCCAE, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher325 = SSLCipherSuite(0x1301, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_AES_128_GCM_SHA256"); -static const SSLCipherSuite Cipher326 = SSLCipherSuite(0x1302, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_AES_256_GCM_SHA384"); -static const SSLCipherSuite Cipher327 = SSLCipherSuite(0x1303, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_CHACHA20_POLY1305_SHA256"); -static const SSLCipherSuite Cipher328 = SSLCipherSuite(0x1304, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_128_CCM, SSL_HASH_SHA256, "TLS_AES_128_CCM_SHA256"); -static const SSLCipherSuite Cipher329 = SSLCipherSuite(0x1305, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_128_CCM_8, SSL_HASH_SHA256, "TLS_AES_128_CCM_8_SHA256"); - - -static std::unordered_map createCipherSuiteIdToObjectMap() -{ - std::unordered_map result; - - result[0x0000] = (SSLCipherSuite*)&Cipher1; - result[0x0001] = (SSLCipherSuite*)&Cipher2; - result[0x0002] = (SSLCipherSuite*)&Cipher3; - result[0x0003] = (SSLCipherSuite*)&Cipher4; - result[0x0004] = (SSLCipherSuite*)&Cipher5; - result[0x0005] = (SSLCipherSuite*)&Cipher6; - result[0x0006] = (SSLCipherSuite*)&Cipher7; - result[0x0007] = (SSLCipherSuite*)&Cipher8; - result[0x0008] = (SSLCipherSuite*)&Cipher9; - result[0x0009] = (SSLCipherSuite*)&Cipher10; - result[0x000A] = (SSLCipherSuite*)&Cipher11; - result[0x000B] = (SSLCipherSuite*)&Cipher12; - result[0x000C] = (SSLCipherSuite*)&Cipher13; - result[0x000D] = (SSLCipherSuite*)&Cipher14; - result[0x000E] = (SSLCipherSuite*)&Cipher15; - result[0x000F] = (SSLCipherSuite*)&Cipher16; - result[0x0010] = (SSLCipherSuite*)&Cipher17; - result[0x0011] = (SSLCipherSuite*)&Cipher18; - result[0x0012] = (SSLCipherSuite*)&Cipher19; - result[0x0013] = (SSLCipherSuite*)&Cipher20; - result[0x0014] = (SSLCipherSuite*)&Cipher21; - result[0x0015] = (SSLCipherSuite*)&Cipher22; - result[0x0016] = (SSLCipherSuite*)&Cipher23; - result[0x0017] = (SSLCipherSuite*)&Cipher24; - result[0x0018] = (SSLCipherSuite*)&Cipher25; - result[0x0019] = (SSLCipherSuite*)&Cipher26; - result[0x001A] = (SSLCipherSuite*)&Cipher27; - result[0x001B] = (SSLCipherSuite*)&Cipher28; - result[0x001E] = (SSLCipherSuite*)&Cipher29; - result[0x001F] = (SSLCipherSuite*)&Cipher30; - result[0x0020] = (SSLCipherSuite*)&Cipher31; - result[0x0021] = (SSLCipherSuite*)&Cipher32; - result[0x0022] = (SSLCipherSuite*)&Cipher33; - result[0x0023] = (SSLCipherSuite*)&Cipher34; - result[0x0024] = (SSLCipherSuite*)&Cipher35; - result[0x0025] = (SSLCipherSuite*)&Cipher36; - result[0x0026] = (SSLCipherSuite*)&Cipher37; - result[0x0027] = (SSLCipherSuite*)&Cipher38; - result[0x0028] = (SSLCipherSuite*)&Cipher39; - result[0x0029] = (SSLCipherSuite*)&Cipher40; - result[0x002A] = (SSLCipherSuite*)&Cipher41; - result[0x002B] = (SSLCipherSuite*)&Cipher42; - result[0x002C] = (SSLCipherSuite*)&Cipher43; - result[0x002D] = (SSLCipherSuite*)&Cipher44; - result[0x002E] = (SSLCipherSuite*)&Cipher45; - result[0x002F] = (SSLCipherSuite*)&Cipher46; - result[0x0030] = (SSLCipherSuite*)&Cipher47; - result[0x0031] = (SSLCipherSuite*)&Cipher48; - result[0x0032] = (SSLCipherSuite*)&Cipher49; - result[0x0033] = (SSLCipherSuite*)&Cipher50; - result[0x0034] = (SSLCipherSuite*)&Cipher51; - result[0x0035] = (SSLCipherSuite*)&Cipher52; - result[0x0036] = (SSLCipherSuite*)&Cipher53; - result[0x0037] = (SSLCipherSuite*)&Cipher54; - result[0x0038] = (SSLCipherSuite*)&Cipher55; - result[0x0039] = (SSLCipherSuite*)&Cipher56; - result[0x003A] = (SSLCipherSuite*)&Cipher57; - result[0x003B] = (SSLCipherSuite*)&Cipher58; - result[0x003C] = (SSLCipherSuite*)&Cipher59; - result[0x003D] = (SSLCipherSuite*)&Cipher60; - result[0x003E] = (SSLCipherSuite*)&Cipher61; - result[0x003F] = (SSLCipherSuite*)&Cipher62; - result[0x0040] = (SSLCipherSuite*)&Cipher63; - result[0x0041] = (SSLCipherSuite*)&Cipher64; - result[0x0042] = (SSLCipherSuite*)&Cipher65; - result[0x0043] = (SSLCipherSuite*)&Cipher66; - result[0x0044] = (SSLCipherSuite*)&Cipher67; - result[0x0045] = (SSLCipherSuite*)&Cipher68; - result[0x0046] = (SSLCipherSuite*)&Cipher69; - result[0x0067] = (SSLCipherSuite*)&Cipher70; - result[0x0068] = (SSLCipherSuite*)&Cipher71; - result[0x0069] = (SSLCipherSuite*)&Cipher72; - result[0x006A] = (SSLCipherSuite*)&Cipher73; - result[0x006B] = (SSLCipherSuite*)&Cipher74; - result[0x006C] = (SSLCipherSuite*)&Cipher75; - result[0x006D] = (SSLCipherSuite*)&Cipher76; - result[0x0084] = (SSLCipherSuite*)&Cipher77; - result[0x0085] = (SSLCipherSuite*)&Cipher78; - result[0x0086] = (SSLCipherSuite*)&Cipher79; - result[0x0087] = (SSLCipherSuite*)&Cipher80; - result[0x0088] = (SSLCipherSuite*)&Cipher81; - result[0x0089] = (SSLCipherSuite*)&Cipher82; - result[0x008A] = (SSLCipherSuite*)&Cipher83; - result[0x008B] = (SSLCipherSuite*)&Cipher84; - result[0x008C] = (SSLCipherSuite*)&Cipher85; - result[0x008D] = (SSLCipherSuite*)&Cipher86; - result[0x008E] = (SSLCipherSuite*)&Cipher87; - result[0x008F] = (SSLCipherSuite*)&Cipher88; - result[0x0090] = (SSLCipherSuite*)&Cipher89; - result[0x0091] = (SSLCipherSuite*)&Cipher90; - result[0x0092] = (SSLCipherSuite*)&Cipher91; - result[0x0093] = (SSLCipherSuite*)&Cipher92; - result[0x0094] = (SSLCipherSuite*)&Cipher93; - result[0x0095] = (SSLCipherSuite*)&Cipher94; - result[0x0096] = (SSLCipherSuite*)&Cipher95; - result[0x0097] = (SSLCipherSuite*)&Cipher96; - result[0x0098] = (SSLCipherSuite*)&Cipher97; - result[0x0099] = (SSLCipherSuite*)&Cipher98; - result[0x009A] = (SSLCipherSuite*)&Cipher99; - result[0x009B] = (SSLCipherSuite*)&Cipher100; - result[0x009C] = (SSLCipherSuite*)&Cipher101; - result[0x009D] = (SSLCipherSuite*)&Cipher102; - result[0x009E] = (SSLCipherSuite*)&Cipher103; - result[0x009F] = (SSLCipherSuite*)&Cipher104; - result[0x00A0] = (SSLCipherSuite*)&Cipher105; - result[0x00A1] = (SSLCipherSuite*)&Cipher106; - result[0x00A2] = (SSLCipherSuite*)&Cipher107; - result[0x00A3] = (SSLCipherSuite*)&Cipher108; - result[0x00A4] = (SSLCipherSuite*)&Cipher109; - result[0x00A5] = (SSLCipherSuite*)&Cipher110; - result[0x00A6] = (SSLCipherSuite*)&Cipher111; - result[0x00A7] = (SSLCipherSuite*)&Cipher112; - result[0x00A8] = (SSLCipherSuite*)&Cipher113; - result[0x00A9] = (SSLCipherSuite*)&Cipher114; - result[0x00AA] = (SSLCipherSuite*)&Cipher115; - result[0x00AB] = (SSLCipherSuite*)&Cipher116; - result[0x00AC] = (SSLCipherSuite*)&Cipher117; - result[0x00AD] = (SSLCipherSuite*)&Cipher118; - result[0x00AE] = (SSLCipherSuite*)&Cipher119; - result[0x00AF] = (SSLCipherSuite*)&Cipher120; - result[0x00B0] = (SSLCipherSuite*)&Cipher121; - result[0x00B1] = (SSLCipherSuite*)&Cipher122; - result[0x00B2] = (SSLCipherSuite*)&Cipher123; - result[0x00B3] = (SSLCipherSuite*)&Cipher124; - result[0x00B4] = (SSLCipherSuite*)&Cipher125; - result[0x00B5] = (SSLCipherSuite*)&Cipher126; - result[0x00B6] = (SSLCipherSuite*)&Cipher127; - result[0x00B7] = (SSLCipherSuite*)&Cipher128; - result[0x00B8] = (SSLCipherSuite*)&Cipher129; - result[0x00B9] = (SSLCipherSuite*)&Cipher130; - result[0x00BA] = (SSLCipherSuite*)&Cipher131; - result[0x00BB] = (SSLCipherSuite*)&Cipher132; - result[0x00BC] = (SSLCipherSuite*)&Cipher133; - result[0x00BD] = (SSLCipherSuite*)&Cipher134; - result[0x00BE] = (SSLCipherSuite*)&Cipher135; - result[0x00BF] = (SSLCipherSuite*)&Cipher136; - result[0x00C0] = (SSLCipherSuite*)&Cipher137; - result[0x00C1] = (SSLCipherSuite*)&Cipher138; - result[0x00C2] = (SSLCipherSuite*)&Cipher139; - result[0x00C3] = (SSLCipherSuite*)&Cipher140; - result[0x00C4] = (SSLCipherSuite*)&Cipher141; - result[0x00C5] = (SSLCipherSuite*)&Cipher142; - result[0xC001] = (SSLCipherSuite*)&Cipher143; - result[0xC002] = (SSLCipherSuite*)&Cipher144; - result[0xC003] = (SSLCipherSuite*)&Cipher145; - result[0xC004] = (SSLCipherSuite*)&Cipher146; - result[0xC005] = (SSLCipherSuite*)&Cipher147; - result[0xC006] = (SSLCipherSuite*)&Cipher148; - result[0xC007] = (SSLCipherSuite*)&Cipher149; - result[0xC008] = (SSLCipherSuite*)&Cipher150; - result[0xC009] = (SSLCipherSuite*)&Cipher151; - result[0xC00A] = (SSLCipherSuite*)&Cipher152; - result[0xC00B] = (SSLCipherSuite*)&Cipher153; - result[0xC00C] = (SSLCipherSuite*)&Cipher154; - result[0xC00D] = (SSLCipherSuite*)&Cipher155; - result[0xC00E] = (SSLCipherSuite*)&Cipher156; - result[0xC00F] = (SSLCipherSuite*)&Cipher157; - result[0xC010] = (SSLCipherSuite*)&Cipher158; - result[0xC011] = (SSLCipherSuite*)&Cipher159; - result[0xC012] = (SSLCipherSuite*)&Cipher160; - result[0xC013] = (SSLCipherSuite*)&Cipher161; - result[0xC014] = (SSLCipherSuite*)&Cipher162; - result[0xC015] = (SSLCipherSuite*)&Cipher163; - result[0xC016] = (SSLCipherSuite*)&Cipher164; - result[0xC017] = (SSLCipherSuite*)&Cipher165; - result[0xC018] = (SSLCipherSuite*)&Cipher166; - result[0xC019] = (SSLCipherSuite*)&Cipher167; - result[0xC01A] = (SSLCipherSuite*)&Cipher168; - result[0xC01B] = (SSLCipherSuite*)&Cipher169; - result[0xC01C] = (SSLCipherSuite*)&Cipher170; - result[0xC01D] = (SSLCipherSuite*)&Cipher171; - result[0xC01E] = (SSLCipherSuite*)&Cipher172; - result[0xC01F] = (SSLCipherSuite*)&Cipher173; - result[0xC020] = (SSLCipherSuite*)&Cipher174; - result[0xC021] = (SSLCipherSuite*)&Cipher175; - result[0xC022] = (SSLCipherSuite*)&Cipher176; - result[0xC023] = (SSLCipherSuite*)&Cipher177; - result[0xC024] = (SSLCipherSuite*)&Cipher178; - result[0xC025] = (SSLCipherSuite*)&Cipher179; - result[0xC026] = (SSLCipherSuite*)&Cipher180; - result[0xC027] = (SSLCipherSuite*)&Cipher181; - result[0xC028] = (SSLCipherSuite*)&Cipher182; - result[0xC029] = (SSLCipherSuite*)&Cipher183; - result[0xC02A] = (SSLCipherSuite*)&Cipher184; - result[0xC02B] = (SSLCipherSuite*)&Cipher185; - result[0xC02C] = (SSLCipherSuite*)&Cipher186; - result[0xC02D] = (SSLCipherSuite*)&Cipher187; - result[0xC02E] = (SSLCipherSuite*)&Cipher188; - result[0xC02F] = (SSLCipherSuite*)&Cipher189; - result[0xC030] = (SSLCipherSuite*)&Cipher190; - result[0xC031] = (SSLCipherSuite*)&Cipher191; - result[0xC032] = (SSLCipherSuite*)&Cipher192; - result[0xC033] = (SSLCipherSuite*)&Cipher193; - result[0xC034] = (SSLCipherSuite*)&Cipher194; - result[0xC035] = (SSLCipherSuite*)&Cipher195; - result[0xC036] = (SSLCipherSuite*)&Cipher196; - result[0xC037] = (SSLCipherSuite*)&Cipher197; - result[0xC038] = (SSLCipherSuite*)&Cipher198; - result[0xC039] = (SSLCipherSuite*)&Cipher199; - result[0xC03A] = (SSLCipherSuite*)&Cipher200; - result[0xC03B] = (SSLCipherSuite*)&Cipher201; - result[0xC03C] = (SSLCipherSuite*)&Cipher202; - result[0xC03D] = (SSLCipherSuite*)&Cipher203; - result[0xC03E] = (SSLCipherSuite*)&Cipher204; - result[0xC03F] = (SSLCipherSuite*)&Cipher205; - result[0xC040] = (SSLCipherSuite*)&Cipher206; - result[0xC041] = (SSLCipherSuite*)&Cipher207; - result[0xC042] = (SSLCipherSuite*)&Cipher208; - result[0xC043] = (SSLCipherSuite*)&Cipher209; - result[0xC044] = (SSLCipherSuite*)&Cipher210; - result[0xC045] = (SSLCipherSuite*)&Cipher211; - result[0xC046] = (SSLCipherSuite*)&Cipher212; - result[0xC047] = (SSLCipherSuite*)&Cipher213; - result[0xC048] = (SSLCipherSuite*)&Cipher214; - result[0xC049] = (SSLCipherSuite*)&Cipher215; - result[0xC04A] = (SSLCipherSuite*)&Cipher216; - result[0xC04B] = (SSLCipherSuite*)&Cipher217; - result[0xC04C] = (SSLCipherSuite*)&Cipher218; - result[0xC04D] = (SSLCipherSuite*)&Cipher219; - result[0xC04E] = (SSLCipherSuite*)&Cipher220; - result[0xC04F] = (SSLCipherSuite*)&Cipher221; - result[0xC050] = (SSLCipherSuite*)&Cipher222; - result[0xC051] = (SSLCipherSuite*)&Cipher223; - result[0xC052] = (SSLCipherSuite*)&Cipher224; - result[0xC053] = (SSLCipherSuite*)&Cipher225; - result[0xC054] = (SSLCipherSuite*)&Cipher226; - result[0xC055] = (SSLCipherSuite*)&Cipher227; - result[0xC056] = (SSLCipherSuite*)&Cipher228; - result[0xC057] = (SSLCipherSuite*)&Cipher229; - result[0xC058] = (SSLCipherSuite*)&Cipher230; - result[0xC059] = (SSLCipherSuite*)&Cipher231; - result[0xC05A] = (SSLCipherSuite*)&Cipher232; - result[0xC05B] = (SSLCipherSuite*)&Cipher233; - result[0xC05C] = (SSLCipherSuite*)&Cipher234; - result[0xC05D] = (SSLCipherSuite*)&Cipher235; - result[0xC05E] = (SSLCipherSuite*)&Cipher236; - result[0xC05F] = (SSLCipherSuite*)&Cipher237; - result[0xC060] = (SSLCipherSuite*)&Cipher238; - result[0xC061] = (SSLCipherSuite*)&Cipher239; - result[0xC062] = (SSLCipherSuite*)&Cipher240; - result[0xC063] = (SSLCipherSuite*)&Cipher241; - result[0xC064] = (SSLCipherSuite*)&Cipher242; - result[0xC065] = (SSLCipherSuite*)&Cipher243; - result[0xC066] = (SSLCipherSuite*)&Cipher244; - result[0xC067] = (SSLCipherSuite*)&Cipher245; - result[0xC068] = (SSLCipherSuite*)&Cipher246; - result[0xC069] = (SSLCipherSuite*)&Cipher247; - result[0xC06A] = (SSLCipherSuite*)&Cipher248; - result[0xC06B] = (SSLCipherSuite*)&Cipher249; - result[0xC06C] = (SSLCipherSuite*)&Cipher250; - result[0xC06D] = (SSLCipherSuite*)&Cipher251; - result[0xC06E] = (SSLCipherSuite*)&Cipher252; - result[0xC06F] = (SSLCipherSuite*)&Cipher253; - result[0xC070] = (SSLCipherSuite*)&Cipher254; - result[0xC071] = (SSLCipherSuite*)&Cipher255; - result[0xC072] = (SSLCipherSuite*)&Cipher256; - result[0xC073] = (SSLCipherSuite*)&Cipher257; - result[0xC074] = (SSLCipherSuite*)&Cipher258; - result[0xC075] = (SSLCipherSuite*)&Cipher259; - result[0xC076] = (SSLCipherSuite*)&Cipher260; - result[0xC077] = (SSLCipherSuite*)&Cipher261; - result[0xC078] = (SSLCipherSuite*)&Cipher262; - result[0xC079] = (SSLCipherSuite*)&Cipher263; - result[0xC07A] = (SSLCipherSuite*)&Cipher264; - result[0xC07B] = (SSLCipherSuite*)&Cipher265; - result[0xC07C] = (SSLCipherSuite*)&Cipher266; - result[0xC07D] = (SSLCipherSuite*)&Cipher267; - result[0xC07E] = (SSLCipherSuite*)&Cipher268; - result[0xC07F] = (SSLCipherSuite*)&Cipher269; - result[0xC080] = (SSLCipherSuite*)&Cipher270; - result[0xC081] = (SSLCipherSuite*)&Cipher271; - result[0xC082] = (SSLCipherSuite*)&Cipher272; - result[0xC083] = (SSLCipherSuite*)&Cipher273; - result[0xC084] = (SSLCipherSuite*)&Cipher274; - result[0xC085] = (SSLCipherSuite*)&Cipher275; - result[0xC086] = (SSLCipherSuite*)&Cipher276; - result[0xC087] = (SSLCipherSuite*)&Cipher277; - result[0xC088] = (SSLCipherSuite*)&Cipher278; - result[0xC089] = (SSLCipherSuite*)&Cipher279; - result[0xC08A] = (SSLCipherSuite*)&Cipher280; - result[0xC08B] = (SSLCipherSuite*)&Cipher281; - result[0xC08C] = (SSLCipherSuite*)&Cipher282; - result[0xC08D] = (SSLCipherSuite*)&Cipher283; - result[0xC08E] = (SSLCipherSuite*)&Cipher284; - result[0xC08F] = (SSLCipherSuite*)&Cipher285; - result[0xC090] = (SSLCipherSuite*)&Cipher286; - result[0xC091] = (SSLCipherSuite*)&Cipher287; - result[0xC092] = (SSLCipherSuite*)&Cipher288; - result[0xC093] = (SSLCipherSuite*)&Cipher289; - result[0xC094] = (SSLCipherSuite*)&Cipher290; - result[0xC095] = (SSLCipherSuite*)&Cipher291; - result[0xC096] = (SSLCipherSuite*)&Cipher292; - result[0xC097] = (SSLCipherSuite*)&Cipher293; - result[0xC098] = (SSLCipherSuite*)&Cipher294; - result[0xC099] = (SSLCipherSuite*)&Cipher295; - result[0xC09A] = (SSLCipherSuite*)&Cipher296; - result[0xC09B] = (SSLCipherSuite*)&Cipher297; - result[0xC09C] = (SSLCipherSuite*)&Cipher298; - result[0xC09D] = (SSLCipherSuite*)&Cipher299; - result[0xC09E] = (SSLCipherSuite*)&Cipher300; - result[0xC09F] = (SSLCipherSuite*)&Cipher301; - result[0xC0A0] = (SSLCipherSuite*)&Cipher302; - result[0xC0A1] = (SSLCipherSuite*)&Cipher303; - result[0xC0A2] = (SSLCipherSuite*)&Cipher304; - result[0xC0A3] = (SSLCipherSuite*)&Cipher305; - result[0xC0A4] = (SSLCipherSuite*)&Cipher306; - result[0xC0A5] = (SSLCipherSuite*)&Cipher307; - result[0xC0A6] = (SSLCipherSuite*)&Cipher308; - result[0xC0A7] = (SSLCipherSuite*)&Cipher309; - result[0xC0A8] = (SSLCipherSuite*)&Cipher310; - result[0xC0A9] = (SSLCipherSuite*)&Cipher311; - result[0xC0AA] = (SSLCipherSuite*)&Cipher312; - result[0xC0AB] = (SSLCipherSuite*)&Cipher313; - result[0xC0AC] = (SSLCipherSuite*)&Cipher314; - result[0xC0AD] = (SSLCipherSuite*)&Cipher315; - result[0xC0AE] = (SSLCipherSuite*)&Cipher316; - result[0xC0AF] = (SSLCipherSuite*)&Cipher317; - result[0xCCA8] = (SSLCipherSuite*)&Cipher318; - result[0xCCA9] = (SSLCipherSuite*)&Cipher319; - result[0xCCAA] = (SSLCipherSuite*)&Cipher320; - result[0xCCAB] = (SSLCipherSuite*)&Cipher321; - result[0xCCAC] = (SSLCipherSuite*)&Cipher322; - result[0xCCAD] = (SSLCipherSuite*)&Cipher323; - result[0xCCAE] = (SSLCipherSuite*)&Cipher324; - result[0x1301] = (SSLCipherSuite*)&Cipher325; - result[0x1302] = (SSLCipherSuite*)&Cipher326; - result[0x1303] = (SSLCipherSuite*)&Cipher327; - result[0x1304] = (SSLCipherSuite*)&Cipher328; - result[0x1305] = (SSLCipherSuite*)&Cipher329; - return result; -} - -#define A 54059 /* a prime */ -#define B 76963 /* another prime */ -#define C 86969 /* yet another prime */ -#define FIRST_HASH 37 /* also prime */ -static uint32_t hashString(std::string str) -{ - unsigned h = FIRST_HASH; - for(std::string::size_type i = 0; i < str.size(); ++i) + // -------------- + // SSLCipherSuite + // -------------- + + // clang-format off + static const SSLCipherSuite Cipher1 = SSLCipherSuite(0x0000, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_NULL, SSL_HASH_NULL, "TLS_NULL_WITH_NULL_NULL"); + static const SSLCipherSuite Cipher2 = SSLCipherSuite(0x0001, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_MD5, "TLS_RSA_WITH_NULL_MD5"); + static const SSLCipherSuite Cipher3 = SSLCipherSuite(0x0002, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_RSA_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher4 = SSLCipherSuite(0x0003, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC4_40, SSL_HASH_MD5, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"); + static const SSLCipherSuite Cipher5 = SSLCipherSuite(0x0004, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_MD5, "TLS_RSA_WITH_RC4_128_MD5"); + static const SSLCipherSuite Cipher6 = SSLCipherSuite(0x0005, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_RSA_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher7 = SSLCipherSuite(0x0006, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_RC2_CBC_40, SSL_HASH_MD5, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"); + static const SSLCipherSuite Cipher8 = SSLCipherSuite(0x0007, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_IDEA_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_IDEA_CBC_SHA"); + static const SSLCipherSuite Cipher9 = SSLCipherSuite(0x0008, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"); + static const SSLCipherSuite Cipher10 = SSLCipherSuite(0x0009, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher11 = SSLCipherSuite(0x000A, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher12 = SSLCipherSuite(0x000B, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"); + static const SSLCipherSuite Cipher13 = SSLCipherSuite(0x000C, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher14 = SSLCipherSuite(0x000D, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher15 = SSLCipherSuite(0x000E, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"); + static const SSLCipherSuite Cipher16 = SSLCipherSuite(0x000F, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher17 = SSLCipherSuite(0x0010, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher18 = SSLCipherSuite(0x0011, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"); + static const SSLCipherSuite Cipher19 = SSLCipherSuite(0x0012, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher20 = SSLCipherSuite(0x0013, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher21 = SSLCipherSuite(0x0014, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"); + static const SSLCipherSuite Cipher22 = SSLCipherSuite(0x0015, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher23 = SSLCipherSuite(0x0016, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher24 = SSLCipherSuite(0x0017, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_RC4_40, SSL_HASH_MD5, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"); + static const SSLCipherSuite Cipher25 = SSLCipherSuite(0x0018, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_RC4_128, SSL_HASH_MD5, "TLS_DH_anon_WITH_RC4_128_MD5"); + static const SSLCipherSuite Cipher26 = SSLCipherSuite(0x0019, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_DES40_CBC, SSL_HASH_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"); + static const SSLCipherSuite Cipher27 = SSLCipherSuite(0x001A, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher28 = SSLCipherSuite(0x001B, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher29 = SSLCipherSuite(0x001E, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC, SSL_HASH_SHA, "TLS_KRB5_WITH_DES_CBC_SHA"); + static const SSLCipherSuite Cipher30 = SSLCipherSuite(0x001F, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher31 = SSLCipherSuite(0x0020, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_KRB5_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher32 = SSLCipherSuite(0x0021, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_IDEA_CBC, SSL_HASH_SHA, "TLS_KRB5_WITH_IDEA_CBC_SHA"); + static const SSLCipherSuite Cipher33 = SSLCipherSuite(0x0022, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC, SSL_HASH_MD5, "TLS_KRB5_WITH_DES_CBC_MD5"); + static const SSLCipherSuite Cipher34 = SSLCipherSuite(0x0023, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_3DES_EDE_CBC, SSL_HASH_MD5, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"); + static const SSLCipherSuite Cipher35 = SSLCipherSuite(0x0024, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_128, SSL_HASH_MD5, "TLS_KRB5_WITH_RC4_128_MD5"); + static const SSLCipherSuite Cipher36 = SSLCipherSuite(0x0025, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_IDEA_CBC, SSL_HASH_MD5, "TLS_KRB5_WITH_IDEA_CBC_MD5"); + static const SSLCipherSuite Cipher37 = SSLCipherSuite(0x0026, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC_40, SSL_HASH_SHA, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"); + static const SSLCipherSuite Cipher38 = SSLCipherSuite(0x0027, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC2_CBC_40, SSL_HASH_SHA, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"); + static const SSLCipherSuite Cipher39 = SSLCipherSuite(0x0028, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_40, SSL_HASH_SHA, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"); + static const SSLCipherSuite Cipher40 = SSLCipherSuite(0x0029, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_DES_CBC_40, SSL_HASH_MD5, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"); + static const SSLCipherSuite Cipher41 = SSLCipherSuite(0x002A, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC2_CBC_40, SSL_HASH_MD5, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"); + static const SSLCipherSuite Cipher42 = SSLCipherSuite(0x002B, SSL_KEYX_KRB5, SSL_AUTH_KRB5, SSL_SYM_RC4_40, SSL_HASH_MD5, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"); + static const SSLCipherSuite Cipher43 = SSLCipherSuite(0x002C, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_PSK_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher44 = SSLCipherSuite(0x002D, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher45 = SSLCipherSuite(0x002E, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher46 = SSLCipherSuite(0x002F, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher47 = SSLCipherSuite(0x0030, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher48 = SSLCipherSuite(0x0031, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher49 = SSLCipherSuite(0x0032, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher50 = SSLCipherSuite(0x0033, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher51 = SSLCipherSuite(0x0034, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher52 = SSLCipherSuite(0x0035, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher53 = SSLCipherSuite(0x0036, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher54 = SSLCipherSuite(0x0037, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher55 = SSLCipherSuite(0x0038, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher56 = SSLCipherSuite(0x0039, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher57 = SSLCipherSuite(0x003A, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher58 = SSLCipherSuite(0x003B, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_RSA_WITH_NULL_SHA256"); + static const SSLCipherSuite Cipher59 = SSLCipherSuite(0x003C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher60 = SSLCipherSuite(0x003D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"); + static const SSLCipherSuite Cipher61 = SSLCipherSuite(0x003E, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher62 = SSLCipherSuite(0x003F, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher63 = SSLCipherSuite(0x0040, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher64 = SSLCipherSuite(0x0041, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"); + static const SSLCipherSuite Cipher65 = SSLCipherSuite(0x0042, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"); + static const SSLCipherSuite Cipher66 = SSLCipherSuite(0x0043, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"); + static const SSLCipherSuite Cipher67 = SSLCipherSuite(0x0044, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"); + static const SSLCipherSuite Cipher68 = SSLCipherSuite(0x0045, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"); + static const SSLCipherSuite Cipher69 = SSLCipherSuite(0x0046, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"); + static const SSLCipherSuite Cipher70 = SSLCipherSuite(0x0067, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher71 = SSLCipherSuite(0x0068, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"); + static const SSLCipherSuite Cipher72 = SSLCipherSuite(0x0069, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"); + static const SSLCipherSuite Cipher73 = SSLCipherSuite(0x006A, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"); + static const SSLCipherSuite Cipher74 = SSLCipherSuite(0x006B, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"); + static const SSLCipherSuite Cipher75 = SSLCipherSuite(0x006C, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher76 = SSLCipherSuite(0x006D, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_256_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"); + static const SSLCipherSuite Cipher77 = SSLCipherSuite(0x0084, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"); + static const SSLCipherSuite Cipher78 = SSLCipherSuite(0x0085, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"); + static const SSLCipherSuite Cipher79 = SSLCipherSuite(0x0086, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"); + static const SSLCipherSuite Cipher80 = SSLCipherSuite(0x0087, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"); + static const SSLCipherSuite Cipher81 = SSLCipherSuite(0x0088, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"); + static const SSLCipherSuite Cipher82 = SSLCipherSuite(0x0089, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"); + static const SSLCipherSuite Cipher83 = SSLCipherSuite(0x008A, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_PSK_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher84 = SSLCipherSuite(0x008B, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher85 = SSLCipherSuite(0x008C, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_PSK_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher86 = SSLCipherSuite(0x008D, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_PSK_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher87 = SSLCipherSuite(0x008E, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher88 = SSLCipherSuite(0x008F, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher89 = SSLCipherSuite(0x0090, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher90 = SSLCipherSuite(0x0091, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher91 = SSLCipherSuite(0x0092, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher92 = SSLCipherSuite(0x0093, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher93 = SSLCipherSuite(0x0094, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher94 = SSLCipherSuite(0x0095, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher95 = SSLCipherSuite(0x0096, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_RSA_WITH_SEED_CBC_SHA"); + static const SSLCipherSuite Cipher96 = SSLCipherSuite(0x0097, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DH_DSS_WITH_SEED_CBC_SHA"); + static const SSLCipherSuite Cipher97 = SSLCipherSuite(0x0098, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DH_RSA_WITH_SEED_CBC_SHA"); + static const SSLCipherSuite Cipher98 = SSLCipherSuite(0x0099, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"); + static const SSLCipherSuite Cipher99 = SSLCipherSuite(0x009A, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"); + static const SSLCipherSuite Cipher100 = SSLCipherSuite(0x009B, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_SEED_CBC, SSL_HASH_SHA, "TLS_DH_anon_WITH_SEED_CBC_SHA"); + static const SSLCipherSuite Cipher101 = SSLCipherSuite(0x009C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher102 = SSLCipherSuite(0x009D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_RSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher103 = SSLCipherSuite(0x009E, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher104 = SSLCipherSuite(0x009F, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher105 = SSLCipherSuite(0x00A0, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher106 = SSLCipherSuite(0x00A1, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher107 = SSLCipherSuite(0x00A2, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher108 = SSLCipherSuite(0x00A3, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher109 = SSLCipherSuite(0x00A4, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher110 = SSLCipherSuite(0x00A5, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher111 = SSLCipherSuite(0x00A6, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher112 = SSLCipherSuite(0x00A7, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher113 = SSLCipherSuite(0x00A8, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_PSK_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher114 = SSLCipherSuite(0x00A9, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_PSK_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher115 = SSLCipherSuite(0x00AA, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher116 = SSLCipherSuite(0x00AB, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher117 = SSLCipherSuite(0x00AC, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher118 = SSLCipherSuite(0x00AD, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher119 = SSLCipherSuite(0x00AE, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_PSK_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher120 = SSLCipherSuite(0x00AF, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_PSK_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher121 = SSLCipherSuite(0x00B0, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_PSK_WITH_NULL_SHA256"); + static const SSLCipherSuite Cipher122 = SSLCipherSuite(0x00B1, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_PSK_WITH_NULL_SHA384"); + static const SSLCipherSuite Cipher123 = SSLCipherSuite(0x00B2, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher124 = SSLCipherSuite(0x00B3, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher125 = SSLCipherSuite(0x00B4, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_NULL_SHA256"); + static const SSLCipherSuite Cipher126 = SSLCipherSuite(0x00B5, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_NULL_SHA384"); + static const SSLCipherSuite Cipher127 = SSLCipherSuite(0x00B6, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher128 = SSLCipherSuite(0x00B7, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher129 = SSLCipherSuite(0x00B8, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_NULL_SHA256"); + static const SSLCipherSuite Cipher130 = SSLCipherSuite(0x00B9, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_NULL_SHA384"); + static const SSLCipherSuite Cipher131 = SSLCipherSuite(0x00BA, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher132 = SSLCipherSuite(0x00BB, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher133 = SSLCipherSuite(0x00BC, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher134 = SSLCipherSuite(0x00BD, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher135 = SSLCipherSuite(0x00BE, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher136 = SSLCipherSuite(0x00BF, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher137 = SSLCipherSuite(0x00C0, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"); + static const SSLCipherSuite Cipher138 = SSLCipherSuite(0x00C1, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"); + static const SSLCipherSuite Cipher139 = SSLCipherSuite(0x00C2, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"); + static const SSLCipherSuite Cipher140 = SSLCipherSuite(0x00C3, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"); + static const SSLCipherSuite Cipher141 = SSLCipherSuite(0x00C4, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"); + static const SSLCipherSuite Cipher142 = SSLCipherSuite(0x00C5, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"); + static const SSLCipherSuite Cipher143 = SSLCipherSuite(0xC001, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher144 = SSLCipherSuite(0xC002, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher145 = SSLCipherSuite(0xC003, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher146 = SSLCipherSuite(0xC004, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher147 = SSLCipherSuite(0xC005, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher148 = SSLCipherSuite(0xC006, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher149 = SSLCipherSuite(0xC007, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher150 = SSLCipherSuite(0xC008, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher151 = SSLCipherSuite(0xC009, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher152 = SSLCipherSuite(0xC00A, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher153 = SSLCipherSuite(0xC00B, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher154 = SSLCipherSuite(0xC00C, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher155 = SSLCipherSuite(0xC00D, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher156 = SSLCipherSuite(0xC00E, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher157 = SSLCipherSuite(0xC00F, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher158 = SSLCipherSuite(0xC010, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher159 = SSLCipherSuite(0xC011, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher160 = SSLCipherSuite(0xC012, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher161 = SSLCipherSuite(0xC013, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher162 = SSLCipherSuite(0xC014, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher163 = SSLCipherSuite(0xC015, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher164 = SSLCipherSuite(0xC016, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher165 = SSLCipherSuite(0xC017, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher166 = SSLCipherSuite(0xC018, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher167 = SSLCipherSuite(0xC019, SSL_KEYX_ECDH, SSL_AUTH_anon, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher168 = SSLCipherSuite(0xC01A, SSL_KEYX_SRP, SSL_AUTH_SHA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher169 = SSLCipherSuite(0xC01B, SSL_KEYX_SRP, SSL_AUTH_RSA, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher170 = SSLCipherSuite(0xC01C, SSL_KEYX_SRP, SSL_AUTH_DSS, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher171 = SSLCipherSuite(0xC01D, SSL_KEYX_SRP, SSL_AUTH_SHA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher172 = SSLCipherSuite(0xC01E, SSL_KEYX_SRP, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher173 = SSLCipherSuite(0xC01F, SSL_KEYX_SRP, SSL_AUTH_DSS, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher174 = SSLCipherSuite(0xC020, SSL_KEYX_SRP, SSL_AUTH_SHA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher175 = SSLCipherSuite(0xC021, SSL_KEYX_SRP, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher176 = SSLCipherSuite(0xC022, SSL_KEYX_SRP, SSL_AUTH_DSS, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher177 = SSLCipherSuite(0xC023, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher178 = SSLCipherSuite(0xC024, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher179 = SSLCipherSuite(0xC025, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher180 = SSLCipherSuite(0xC026, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher181 = SSLCipherSuite(0xC027, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher182 = SSLCipherSuite(0xC028, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher183 = SSLCipherSuite(0xC029, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher184 = SSLCipherSuite(0xC02A, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher185 = SSLCipherSuite(0xC02B, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher186 = SSLCipherSuite(0xC02C, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher187 = SSLCipherSuite(0xC02D, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher188 = SSLCipherSuite(0xC02E, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher189 = SSLCipherSuite(0xC02F, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher190 = SSLCipherSuite(0xC030, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher191 = SSLCipherSuite(0xC031, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher192 = SSLCipherSuite(0xC032, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher193 = SSLCipherSuite(0xC033, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_RC4_128, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_RC4_128_SHA"); + static const SSLCipherSuite Cipher194 = SSLCipherSuite(0xC034, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_3DES_EDE_CBC, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"); + static const SSLCipherSuite Cipher195 = SSLCipherSuite(0xC035, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"); + static const SSLCipherSuite Cipher196 = SSLCipherSuite(0xC036, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"); + static const SSLCipherSuite Cipher197 = SSLCipherSuite(0xC037, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"); + static const SSLCipherSuite Cipher198 = SSLCipherSuite(0xC038, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_AES_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"); + static const SSLCipherSuite Cipher199 = SSLCipherSuite(0xC039, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA, "TLS_ECDHE_PSK_WITH_NULL_SHA"); + static const SSLCipherSuite Cipher200 = SSLCipherSuite(0xC03A, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_NULL_SHA256"); + static const SSLCipherSuite Cipher201 = SSLCipherSuite(0xC03B, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_NULL, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_NULL_SHA384"); + static const SSLCipherSuite Cipher202 = SSLCipherSuite(0xC03C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher203 = SSLCipherSuite(0xC03D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_RSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher204 = SSLCipherSuite(0xC03E, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher205 = SSLCipherSuite(0xC03F, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher206 = SSLCipherSuite(0xC040, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher207 = SSLCipherSuite(0xC041, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher208 = SSLCipherSuite(0xC042, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher209 = SSLCipherSuite(0xC043, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher210 = SSLCipherSuite(0xC044, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher211 = SSLCipherSuite(0xC045, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher212 = SSLCipherSuite(0xC046, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher213 = SSLCipherSuite(0xC047, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher214 = SSLCipherSuite(0xC048, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher215 = SSLCipherSuite(0xC049, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher216 = SSLCipherSuite(0xC04A, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher217 = SSLCipherSuite(0xC04B, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher218 = SSLCipherSuite(0xC04C, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher219 = SSLCipherSuite(0xC04D, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher220 = SSLCipherSuite(0xC04E, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher221 = SSLCipherSuite(0xC04F, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher222 = SSLCipherSuite(0xC050, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher223 = SSLCipherSuite(0xC051, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher224 = SSLCipherSuite(0xC052, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher225 = SSLCipherSuite(0xC053, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher226 = SSLCipherSuite(0xC054, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher227 = SSLCipherSuite(0xC055, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher228 = SSLCipherSuite(0xC056, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher229 = SSLCipherSuite(0xC057, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher230 = SSLCipherSuite(0xC058, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher231 = SSLCipherSuite(0xC059, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher232 = SSLCipherSuite(0xC05A, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher233 = SSLCipherSuite(0xC05B, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher234 = SSLCipherSuite(0xC05C, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher235 = SSLCipherSuite(0xC05D, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher236 = SSLCipherSuite(0xC05E, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher237 = SSLCipherSuite(0xC05F, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher238 = SSLCipherSuite(0xC060, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher239 = SSLCipherSuite(0xC061, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher240 = SSLCipherSuite(0xC062, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher241 = SSLCipherSuite(0xC063, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher242 = SSLCipherSuite(0xC064, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_PSK_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher243 = SSLCipherSuite(0xC065, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_PSK_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher244 = SSLCipherSuite(0xC066, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher245 = SSLCipherSuite(0xC067, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher246 = SSLCipherSuite(0xC068, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher247 = SSLCipherSuite(0xC069, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher248 = SSLCipherSuite(0xC06A, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_PSK_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher249 = SSLCipherSuite(0xC06B, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_PSK_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher250 = SSLCipherSuite(0xC06C, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher251 = SSLCipherSuite(0xC06D, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher252 = SSLCipherSuite(0xC06E, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher253 = SSLCipherSuite(0xC06F, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_ARIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher254 = SSLCipherSuite(0xC070, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_ARIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher255 = SSLCipherSuite(0xC071, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_ARIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher256 = SSLCipherSuite(0xC072, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher257 = SSLCipherSuite(0xC073, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher258 = SSLCipherSuite(0xC074, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher259 = SSLCipherSuite(0xC075, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher260 = SSLCipherSuite(0xC076, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher261 = SSLCipherSuite(0xC077, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher262 = SSLCipherSuite(0xC078, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher263 = SSLCipherSuite(0xC079, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher264 = SSLCipherSuite(0xC07A, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher265 = SSLCipherSuite(0xC07B, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher266 = SSLCipherSuite(0xC07C, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher267 = SSLCipherSuite(0xC07D, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher268 = SSLCipherSuite(0xC07E, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher269 = SSLCipherSuite(0xC07F, SSL_KEYX_DH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher270 = SSLCipherSuite(0xC080, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher271 = SSLCipherSuite(0xC081, SSL_KEYX_DHE, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher272 = SSLCipherSuite(0xC082, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher273 = SSLCipherSuite(0xC083, SSL_KEYX_DH, SSL_AUTH_DSS, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher274 = SSLCipherSuite(0xC084, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher275 = SSLCipherSuite(0xC085, SSL_KEYX_DH, SSL_AUTH_anon, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher276 = SSLCipherSuite(0xC086, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher277 = SSLCipherSuite(0xC087, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher278 = SSLCipherSuite(0xC088, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher279 = SSLCipherSuite(0xC089, SSL_KEYX_ECDH, SSL_AUTH_ECDSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher280 = SSLCipherSuite(0xC08A, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher281 = SSLCipherSuite(0xC08B, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher282 = SSLCipherSuite(0xC08C, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher283 = SSLCipherSuite(0xC08D, SSL_KEYX_ECDH, SSL_AUTH_RSA, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher284 = SSLCipherSuite(0xC08E, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher285 = SSLCipherSuite(0xC08F, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher286 = SSLCipherSuite(0xC090, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher287 = SSLCipherSuite(0xC091, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher288 = SSLCipherSuite(0xC092, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_GCM, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"); + static const SSLCipherSuite Cipher289 = SSLCipherSuite(0xC093, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_GCM, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"); + static const SSLCipherSuite Cipher290 = SSLCipherSuite(0xC094, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher291 = SSLCipherSuite(0xC095, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher292 = SSLCipherSuite(0xC096, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher293 = SSLCipherSuite(0xC097, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher294 = SSLCipherSuite(0xC098, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher295 = SSLCipherSuite(0xC099, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher296 = SSLCipherSuite(0xC09A, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_128_CBC, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"); + static const SSLCipherSuite Cipher297 = SSLCipherSuite(0xC09B, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_CAMELLIA_256_CBC, SSL_HASH_SHA384, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"); + static const SSLCipherSuite Cipher298 = SSLCipherSuite(0xC09C, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_RSA_WITH_AES_128_CCM"); + static const SSLCipherSuite Cipher299 = SSLCipherSuite(0xC09D, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_RSA_WITH_AES_256_CCM"); + static const SSLCipherSuite Cipher300 = SSLCipherSuite(0xC09E, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_DHE_RSA_WITH_AES_128_CCM"); + static const SSLCipherSuite Cipher301 = SSLCipherSuite(0xC09F, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_DHE_RSA_WITH_AES_256_CCM"); + static const SSLCipherSuite Cipher302 = SSLCipherSuite(0xC0A0, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_RSA_WITH_AES_128_CCM_8"); + static const SSLCipherSuite Cipher303 = SSLCipherSuite(0xC0A1, SSL_KEYX_RSA, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_RSA_WITH_AES_256_CCM_8"); + static const SSLCipherSuite Cipher304 = SSLCipherSuite(0xC0A2, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_DHE_RSA_WITH_AES_128_CCM_8"); + static const SSLCipherSuite Cipher305 = SSLCipherSuite(0xC0A3, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_DHE_RSA_WITH_AES_256_CCM_8"); + static const SSLCipherSuite Cipher306 = SSLCipherSuite(0xC0A4, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_PSK_WITH_AES_128_CCM"); + static const SSLCipherSuite Cipher307 = SSLCipherSuite(0xC0A5, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_PSK_WITH_AES_256_CCM"); + static const SSLCipherSuite Cipher308 = SSLCipherSuite(0xC0A6, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_DHE_PSK_WITH_AES_128_CCM"); + static const SSLCipherSuite Cipher309 = SSLCipherSuite(0xC0A7, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_DHE_PSK_WITH_AES_256_CCM"); + static const SSLCipherSuite Cipher310 = SSLCipherSuite(0xC0A8, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_PSK_WITH_AES_128_CCM_8"); + static const SSLCipherSuite Cipher311 = SSLCipherSuite(0xC0A9, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_PSK_WITH_AES_256_CCM_8"); + static const SSLCipherSuite Cipher312 = SSLCipherSuite(0xC0AA, SSL_KEYX_PSK, SSL_AUTH_DHE, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_PSK_DHE_WITH_AES_128_CCM_8"); + static const SSLCipherSuite Cipher313 = SSLCipherSuite(0xC0AB, SSL_KEYX_PSK, SSL_AUTH_DHE, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_PSK_DHE_WITH_AES_256_CCM_8"); + static const SSLCipherSuite Cipher314 = SSLCipherSuite(0xC0AC, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128, SSL_HASH_CCM, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"); + static const SSLCipherSuite Cipher315 = SSLCipherSuite(0xC0AD, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256, SSL_HASH_CCM, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"); + static const SSLCipherSuite Cipher316 = SSLCipherSuite(0xC0AE, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_128, SSL_HASH_CCM_8, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"); + static const SSLCipherSuite Cipher317 = SSLCipherSuite(0xC0AF, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_AES_256, SSL_HASH_CCM_8, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"); + static const SSLCipherSuite Cipher318 = SSLCipherSuite(0xCCA8, SSL_KEYX_ECDHE, SSL_AUTH_RSA, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher319 = SSLCipherSuite(0xCCA9, SSL_KEYX_ECDHE, SSL_AUTH_ECDSA, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher320 = SSLCipherSuite(0xCCAA, SSL_KEYX_DHE, SSL_AUTH_RSA, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher321 = SSLCipherSuite(0xCCAB, SSL_KEYX_PSK, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher322 = SSLCipherSuite(0xCCAC, SSL_KEYX_ECDHE, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher323 = SSLCipherSuite(0xCCAD, SSL_KEYX_DHE, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher324 = SSLCipherSuite(0xCCAE, SSL_KEYX_RSA, SSL_AUTH_PSK, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher325 = SSLCipherSuite(0x1301, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_128_GCM, SSL_HASH_SHA256, "TLS_AES_128_GCM_SHA256"); + static const SSLCipherSuite Cipher326 = SSLCipherSuite(0x1302, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_256_GCM, SSL_HASH_SHA384, "TLS_AES_256_GCM_SHA384"); + static const SSLCipherSuite Cipher327 = SSLCipherSuite(0x1303, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_CHACHA20_POLY1305, SSL_HASH_SHA256, "TLS_CHACHA20_POLY1305_SHA256"); + static const SSLCipherSuite Cipher328 = SSLCipherSuite(0x1304, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_128_CCM, SSL_HASH_SHA256, "TLS_AES_128_CCM_SHA256"); + static const SSLCipherSuite Cipher329 = SSLCipherSuite(0x1305, SSL_KEYX_NULL, SSL_AUTH_NULL, SSL_SYM_AES_128_CCM_8, SSL_HASH_SHA256, "TLS_AES_128_CCM_8_SHA256"); + // clang-format on + + static std::unordered_map createCipherSuiteIdToObjectMap() { - h = (h * A) ^ (str[i] * B); + std::unordered_map result; + + result[0x0000] = (SSLCipherSuite*)&Cipher1; + result[0x0001] = (SSLCipherSuite*)&Cipher2; + result[0x0002] = (SSLCipherSuite*)&Cipher3; + result[0x0003] = (SSLCipherSuite*)&Cipher4; + result[0x0004] = (SSLCipherSuite*)&Cipher5; + result[0x0005] = (SSLCipherSuite*)&Cipher6; + result[0x0006] = (SSLCipherSuite*)&Cipher7; + result[0x0007] = (SSLCipherSuite*)&Cipher8; + result[0x0008] = (SSLCipherSuite*)&Cipher9; + result[0x0009] = (SSLCipherSuite*)&Cipher10; + result[0x000A] = (SSLCipherSuite*)&Cipher11; + result[0x000B] = (SSLCipherSuite*)&Cipher12; + result[0x000C] = (SSLCipherSuite*)&Cipher13; + result[0x000D] = (SSLCipherSuite*)&Cipher14; + result[0x000E] = (SSLCipherSuite*)&Cipher15; + result[0x000F] = (SSLCipherSuite*)&Cipher16; + result[0x0010] = (SSLCipherSuite*)&Cipher17; + result[0x0011] = (SSLCipherSuite*)&Cipher18; + result[0x0012] = (SSLCipherSuite*)&Cipher19; + result[0x0013] = (SSLCipherSuite*)&Cipher20; + result[0x0014] = (SSLCipherSuite*)&Cipher21; + result[0x0015] = (SSLCipherSuite*)&Cipher22; + result[0x0016] = (SSLCipherSuite*)&Cipher23; + result[0x0017] = (SSLCipherSuite*)&Cipher24; + result[0x0018] = (SSLCipherSuite*)&Cipher25; + result[0x0019] = (SSLCipherSuite*)&Cipher26; + result[0x001A] = (SSLCipherSuite*)&Cipher27; + result[0x001B] = (SSLCipherSuite*)&Cipher28; + result[0x001E] = (SSLCipherSuite*)&Cipher29; + result[0x001F] = (SSLCipherSuite*)&Cipher30; + result[0x0020] = (SSLCipherSuite*)&Cipher31; + result[0x0021] = (SSLCipherSuite*)&Cipher32; + result[0x0022] = (SSLCipherSuite*)&Cipher33; + result[0x0023] = (SSLCipherSuite*)&Cipher34; + result[0x0024] = (SSLCipherSuite*)&Cipher35; + result[0x0025] = (SSLCipherSuite*)&Cipher36; + result[0x0026] = (SSLCipherSuite*)&Cipher37; + result[0x0027] = (SSLCipherSuite*)&Cipher38; + result[0x0028] = (SSLCipherSuite*)&Cipher39; + result[0x0029] = (SSLCipherSuite*)&Cipher40; + result[0x002A] = (SSLCipherSuite*)&Cipher41; + result[0x002B] = (SSLCipherSuite*)&Cipher42; + result[0x002C] = (SSLCipherSuite*)&Cipher43; + result[0x002D] = (SSLCipherSuite*)&Cipher44; + result[0x002E] = (SSLCipherSuite*)&Cipher45; + result[0x002F] = (SSLCipherSuite*)&Cipher46; + result[0x0030] = (SSLCipherSuite*)&Cipher47; + result[0x0031] = (SSLCipherSuite*)&Cipher48; + result[0x0032] = (SSLCipherSuite*)&Cipher49; + result[0x0033] = (SSLCipherSuite*)&Cipher50; + result[0x0034] = (SSLCipherSuite*)&Cipher51; + result[0x0035] = (SSLCipherSuite*)&Cipher52; + result[0x0036] = (SSLCipherSuite*)&Cipher53; + result[0x0037] = (SSLCipherSuite*)&Cipher54; + result[0x0038] = (SSLCipherSuite*)&Cipher55; + result[0x0039] = (SSLCipherSuite*)&Cipher56; + result[0x003A] = (SSLCipherSuite*)&Cipher57; + result[0x003B] = (SSLCipherSuite*)&Cipher58; + result[0x003C] = (SSLCipherSuite*)&Cipher59; + result[0x003D] = (SSLCipherSuite*)&Cipher60; + result[0x003E] = (SSLCipherSuite*)&Cipher61; + result[0x003F] = (SSLCipherSuite*)&Cipher62; + result[0x0040] = (SSLCipherSuite*)&Cipher63; + result[0x0041] = (SSLCipherSuite*)&Cipher64; + result[0x0042] = (SSLCipherSuite*)&Cipher65; + result[0x0043] = (SSLCipherSuite*)&Cipher66; + result[0x0044] = (SSLCipherSuite*)&Cipher67; + result[0x0045] = (SSLCipherSuite*)&Cipher68; + result[0x0046] = (SSLCipherSuite*)&Cipher69; + result[0x0067] = (SSLCipherSuite*)&Cipher70; + result[0x0068] = (SSLCipherSuite*)&Cipher71; + result[0x0069] = (SSLCipherSuite*)&Cipher72; + result[0x006A] = (SSLCipherSuite*)&Cipher73; + result[0x006B] = (SSLCipherSuite*)&Cipher74; + result[0x006C] = (SSLCipherSuite*)&Cipher75; + result[0x006D] = (SSLCipherSuite*)&Cipher76; + result[0x0084] = (SSLCipherSuite*)&Cipher77; + result[0x0085] = (SSLCipherSuite*)&Cipher78; + result[0x0086] = (SSLCipherSuite*)&Cipher79; + result[0x0087] = (SSLCipherSuite*)&Cipher80; + result[0x0088] = (SSLCipherSuite*)&Cipher81; + result[0x0089] = (SSLCipherSuite*)&Cipher82; + result[0x008A] = (SSLCipherSuite*)&Cipher83; + result[0x008B] = (SSLCipherSuite*)&Cipher84; + result[0x008C] = (SSLCipherSuite*)&Cipher85; + result[0x008D] = (SSLCipherSuite*)&Cipher86; + result[0x008E] = (SSLCipherSuite*)&Cipher87; + result[0x008F] = (SSLCipherSuite*)&Cipher88; + result[0x0090] = (SSLCipherSuite*)&Cipher89; + result[0x0091] = (SSLCipherSuite*)&Cipher90; + result[0x0092] = (SSLCipherSuite*)&Cipher91; + result[0x0093] = (SSLCipherSuite*)&Cipher92; + result[0x0094] = (SSLCipherSuite*)&Cipher93; + result[0x0095] = (SSLCipherSuite*)&Cipher94; + result[0x0096] = (SSLCipherSuite*)&Cipher95; + result[0x0097] = (SSLCipherSuite*)&Cipher96; + result[0x0098] = (SSLCipherSuite*)&Cipher97; + result[0x0099] = (SSLCipherSuite*)&Cipher98; + result[0x009A] = (SSLCipherSuite*)&Cipher99; + result[0x009B] = (SSLCipherSuite*)&Cipher100; + result[0x009C] = (SSLCipherSuite*)&Cipher101; + result[0x009D] = (SSLCipherSuite*)&Cipher102; + result[0x009E] = (SSLCipherSuite*)&Cipher103; + result[0x009F] = (SSLCipherSuite*)&Cipher104; + result[0x00A0] = (SSLCipherSuite*)&Cipher105; + result[0x00A1] = (SSLCipherSuite*)&Cipher106; + result[0x00A2] = (SSLCipherSuite*)&Cipher107; + result[0x00A3] = (SSLCipherSuite*)&Cipher108; + result[0x00A4] = (SSLCipherSuite*)&Cipher109; + result[0x00A5] = (SSLCipherSuite*)&Cipher110; + result[0x00A6] = (SSLCipherSuite*)&Cipher111; + result[0x00A7] = (SSLCipherSuite*)&Cipher112; + result[0x00A8] = (SSLCipherSuite*)&Cipher113; + result[0x00A9] = (SSLCipherSuite*)&Cipher114; + result[0x00AA] = (SSLCipherSuite*)&Cipher115; + result[0x00AB] = (SSLCipherSuite*)&Cipher116; + result[0x00AC] = (SSLCipherSuite*)&Cipher117; + result[0x00AD] = (SSLCipherSuite*)&Cipher118; + result[0x00AE] = (SSLCipherSuite*)&Cipher119; + result[0x00AF] = (SSLCipherSuite*)&Cipher120; + result[0x00B0] = (SSLCipherSuite*)&Cipher121; + result[0x00B1] = (SSLCipherSuite*)&Cipher122; + result[0x00B2] = (SSLCipherSuite*)&Cipher123; + result[0x00B3] = (SSLCipherSuite*)&Cipher124; + result[0x00B4] = (SSLCipherSuite*)&Cipher125; + result[0x00B5] = (SSLCipherSuite*)&Cipher126; + result[0x00B6] = (SSLCipherSuite*)&Cipher127; + result[0x00B7] = (SSLCipherSuite*)&Cipher128; + result[0x00B8] = (SSLCipherSuite*)&Cipher129; + result[0x00B9] = (SSLCipherSuite*)&Cipher130; + result[0x00BA] = (SSLCipherSuite*)&Cipher131; + result[0x00BB] = (SSLCipherSuite*)&Cipher132; + result[0x00BC] = (SSLCipherSuite*)&Cipher133; + result[0x00BD] = (SSLCipherSuite*)&Cipher134; + result[0x00BE] = (SSLCipherSuite*)&Cipher135; + result[0x00BF] = (SSLCipherSuite*)&Cipher136; + result[0x00C0] = (SSLCipherSuite*)&Cipher137; + result[0x00C1] = (SSLCipherSuite*)&Cipher138; + result[0x00C2] = (SSLCipherSuite*)&Cipher139; + result[0x00C3] = (SSLCipherSuite*)&Cipher140; + result[0x00C4] = (SSLCipherSuite*)&Cipher141; + result[0x00C5] = (SSLCipherSuite*)&Cipher142; + result[0xC001] = (SSLCipherSuite*)&Cipher143; + result[0xC002] = (SSLCipherSuite*)&Cipher144; + result[0xC003] = (SSLCipherSuite*)&Cipher145; + result[0xC004] = (SSLCipherSuite*)&Cipher146; + result[0xC005] = (SSLCipherSuite*)&Cipher147; + result[0xC006] = (SSLCipherSuite*)&Cipher148; + result[0xC007] = (SSLCipherSuite*)&Cipher149; + result[0xC008] = (SSLCipherSuite*)&Cipher150; + result[0xC009] = (SSLCipherSuite*)&Cipher151; + result[0xC00A] = (SSLCipherSuite*)&Cipher152; + result[0xC00B] = (SSLCipherSuite*)&Cipher153; + result[0xC00C] = (SSLCipherSuite*)&Cipher154; + result[0xC00D] = (SSLCipherSuite*)&Cipher155; + result[0xC00E] = (SSLCipherSuite*)&Cipher156; + result[0xC00F] = (SSLCipherSuite*)&Cipher157; + result[0xC010] = (SSLCipherSuite*)&Cipher158; + result[0xC011] = (SSLCipherSuite*)&Cipher159; + result[0xC012] = (SSLCipherSuite*)&Cipher160; + result[0xC013] = (SSLCipherSuite*)&Cipher161; + result[0xC014] = (SSLCipherSuite*)&Cipher162; + result[0xC015] = (SSLCipherSuite*)&Cipher163; + result[0xC016] = (SSLCipherSuite*)&Cipher164; + result[0xC017] = (SSLCipherSuite*)&Cipher165; + result[0xC018] = (SSLCipherSuite*)&Cipher166; + result[0xC019] = (SSLCipherSuite*)&Cipher167; + result[0xC01A] = (SSLCipherSuite*)&Cipher168; + result[0xC01B] = (SSLCipherSuite*)&Cipher169; + result[0xC01C] = (SSLCipherSuite*)&Cipher170; + result[0xC01D] = (SSLCipherSuite*)&Cipher171; + result[0xC01E] = (SSLCipherSuite*)&Cipher172; + result[0xC01F] = (SSLCipherSuite*)&Cipher173; + result[0xC020] = (SSLCipherSuite*)&Cipher174; + result[0xC021] = (SSLCipherSuite*)&Cipher175; + result[0xC022] = (SSLCipherSuite*)&Cipher176; + result[0xC023] = (SSLCipherSuite*)&Cipher177; + result[0xC024] = (SSLCipherSuite*)&Cipher178; + result[0xC025] = (SSLCipherSuite*)&Cipher179; + result[0xC026] = (SSLCipherSuite*)&Cipher180; + result[0xC027] = (SSLCipherSuite*)&Cipher181; + result[0xC028] = (SSLCipherSuite*)&Cipher182; + result[0xC029] = (SSLCipherSuite*)&Cipher183; + result[0xC02A] = (SSLCipherSuite*)&Cipher184; + result[0xC02B] = (SSLCipherSuite*)&Cipher185; + result[0xC02C] = (SSLCipherSuite*)&Cipher186; + result[0xC02D] = (SSLCipherSuite*)&Cipher187; + result[0xC02E] = (SSLCipherSuite*)&Cipher188; + result[0xC02F] = (SSLCipherSuite*)&Cipher189; + result[0xC030] = (SSLCipherSuite*)&Cipher190; + result[0xC031] = (SSLCipherSuite*)&Cipher191; + result[0xC032] = (SSLCipherSuite*)&Cipher192; + result[0xC033] = (SSLCipherSuite*)&Cipher193; + result[0xC034] = (SSLCipherSuite*)&Cipher194; + result[0xC035] = (SSLCipherSuite*)&Cipher195; + result[0xC036] = (SSLCipherSuite*)&Cipher196; + result[0xC037] = (SSLCipherSuite*)&Cipher197; + result[0xC038] = (SSLCipherSuite*)&Cipher198; + result[0xC039] = (SSLCipherSuite*)&Cipher199; + result[0xC03A] = (SSLCipherSuite*)&Cipher200; + result[0xC03B] = (SSLCipherSuite*)&Cipher201; + result[0xC03C] = (SSLCipherSuite*)&Cipher202; + result[0xC03D] = (SSLCipherSuite*)&Cipher203; + result[0xC03E] = (SSLCipherSuite*)&Cipher204; + result[0xC03F] = (SSLCipherSuite*)&Cipher205; + result[0xC040] = (SSLCipherSuite*)&Cipher206; + result[0xC041] = (SSLCipherSuite*)&Cipher207; + result[0xC042] = (SSLCipherSuite*)&Cipher208; + result[0xC043] = (SSLCipherSuite*)&Cipher209; + result[0xC044] = (SSLCipherSuite*)&Cipher210; + result[0xC045] = (SSLCipherSuite*)&Cipher211; + result[0xC046] = (SSLCipherSuite*)&Cipher212; + result[0xC047] = (SSLCipherSuite*)&Cipher213; + result[0xC048] = (SSLCipherSuite*)&Cipher214; + result[0xC049] = (SSLCipherSuite*)&Cipher215; + result[0xC04A] = (SSLCipherSuite*)&Cipher216; + result[0xC04B] = (SSLCipherSuite*)&Cipher217; + result[0xC04C] = (SSLCipherSuite*)&Cipher218; + result[0xC04D] = (SSLCipherSuite*)&Cipher219; + result[0xC04E] = (SSLCipherSuite*)&Cipher220; + result[0xC04F] = (SSLCipherSuite*)&Cipher221; + result[0xC050] = (SSLCipherSuite*)&Cipher222; + result[0xC051] = (SSLCipherSuite*)&Cipher223; + result[0xC052] = (SSLCipherSuite*)&Cipher224; + result[0xC053] = (SSLCipherSuite*)&Cipher225; + result[0xC054] = (SSLCipherSuite*)&Cipher226; + result[0xC055] = (SSLCipherSuite*)&Cipher227; + result[0xC056] = (SSLCipherSuite*)&Cipher228; + result[0xC057] = (SSLCipherSuite*)&Cipher229; + result[0xC058] = (SSLCipherSuite*)&Cipher230; + result[0xC059] = (SSLCipherSuite*)&Cipher231; + result[0xC05A] = (SSLCipherSuite*)&Cipher232; + result[0xC05B] = (SSLCipherSuite*)&Cipher233; + result[0xC05C] = (SSLCipherSuite*)&Cipher234; + result[0xC05D] = (SSLCipherSuite*)&Cipher235; + result[0xC05E] = (SSLCipherSuite*)&Cipher236; + result[0xC05F] = (SSLCipherSuite*)&Cipher237; + result[0xC060] = (SSLCipherSuite*)&Cipher238; + result[0xC061] = (SSLCipherSuite*)&Cipher239; + result[0xC062] = (SSLCipherSuite*)&Cipher240; + result[0xC063] = (SSLCipherSuite*)&Cipher241; + result[0xC064] = (SSLCipherSuite*)&Cipher242; + result[0xC065] = (SSLCipherSuite*)&Cipher243; + result[0xC066] = (SSLCipherSuite*)&Cipher244; + result[0xC067] = (SSLCipherSuite*)&Cipher245; + result[0xC068] = (SSLCipherSuite*)&Cipher246; + result[0xC069] = (SSLCipherSuite*)&Cipher247; + result[0xC06A] = (SSLCipherSuite*)&Cipher248; + result[0xC06B] = (SSLCipherSuite*)&Cipher249; + result[0xC06C] = (SSLCipherSuite*)&Cipher250; + result[0xC06D] = (SSLCipherSuite*)&Cipher251; + result[0xC06E] = (SSLCipherSuite*)&Cipher252; + result[0xC06F] = (SSLCipherSuite*)&Cipher253; + result[0xC070] = (SSLCipherSuite*)&Cipher254; + result[0xC071] = (SSLCipherSuite*)&Cipher255; + result[0xC072] = (SSLCipherSuite*)&Cipher256; + result[0xC073] = (SSLCipherSuite*)&Cipher257; + result[0xC074] = (SSLCipherSuite*)&Cipher258; + result[0xC075] = (SSLCipherSuite*)&Cipher259; + result[0xC076] = (SSLCipherSuite*)&Cipher260; + result[0xC077] = (SSLCipherSuite*)&Cipher261; + result[0xC078] = (SSLCipherSuite*)&Cipher262; + result[0xC079] = (SSLCipherSuite*)&Cipher263; + result[0xC07A] = (SSLCipherSuite*)&Cipher264; + result[0xC07B] = (SSLCipherSuite*)&Cipher265; + result[0xC07C] = (SSLCipherSuite*)&Cipher266; + result[0xC07D] = (SSLCipherSuite*)&Cipher267; + result[0xC07E] = (SSLCipherSuite*)&Cipher268; + result[0xC07F] = (SSLCipherSuite*)&Cipher269; + result[0xC080] = (SSLCipherSuite*)&Cipher270; + result[0xC081] = (SSLCipherSuite*)&Cipher271; + result[0xC082] = (SSLCipherSuite*)&Cipher272; + result[0xC083] = (SSLCipherSuite*)&Cipher273; + result[0xC084] = (SSLCipherSuite*)&Cipher274; + result[0xC085] = (SSLCipherSuite*)&Cipher275; + result[0xC086] = (SSLCipherSuite*)&Cipher276; + result[0xC087] = (SSLCipherSuite*)&Cipher277; + result[0xC088] = (SSLCipherSuite*)&Cipher278; + result[0xC089] = (SSLCipherSuite*)&Cipher279; + result[0xC08A] = (SSLCipherSuite*)&Cipher280; + result[0xC08B] = (SSLCipherSuite*)&Cipher281; + result[0xC08C] = (SSLCipherSuite*)&Cipher282; + result[0xC08D] = (SSLCipherSuite*)&Cipher283; + result[0xC08E] = (SSLCipherSuite*)&Cipher284; + result[0xC08F] = (SSLCipherSuite*)&Cipher285; + result[0xC090] = (SSLCipherSuite*)&Cipher286; + result[0xC091] = (SSLCipherSuite*)&Cipher287; + result[0xC092] = (SSLCipherSuite*)&Cipher288; + result[0xC093] = (SSLCipherSuite*)&Cipher289; + result[0xC094] = (SSLCipherSuite*)&Cipher290; + result[0xC095] = (SSLCipherSuite*)&Cipher291; + result[0xC096] = (SSLCipherSuite*)&Cipher292; + result[0xC097] = (SSLCipherSuite*)&Cipher293; + result[0xC098] = (SSLCipherSuite*)&Cipher294; + result[0xC099] = (SSLCipherSuite*)&Cipher295; + result[0xC09A] = (SSLCipherSuite*)&Cipher296; + result[0xC09B] = (SSLCipherSuite*)&Cipher297; + result[0xC09C] = (SSLCipherSuite*)&Cipher298; + result[0xC09D] = (SSLCipherSuite*)&Cipher299; + result[0xC09E] = (SSLCipherSuite*)&Cipher300; + result[0xC09F] = (SSLCipherSuite*)&Cipher301; + result[0xC0A0] = (SSLCipherSuite*)&Cipher302; + result[0xC0A1] = (SSLCipherSuite*)&Cipher303; + result[0xC0A2] = (SSLCipherSuite*)&Cipher304; + result[0xC0A3] = (SSLCipherSuite*)&Cipher305; + result[0xC0A4] = (SSLCipherSuite*)&Cipher306; + result[0xC0A5] = (SSLCipherSuite*)&Cipher307; + result[0xC0A6] = (SSLCipherSuite*)&Cipher308; + result[0xC0A7] = (SSLCipherSuite*)&Cipher309; + result[0xC0A8] = (SSLCipherSuite*)&Cipher310; + result[0xC0A9] = (SSLCipherSuite*)&Cipher311; + result[0xC0AA] = (SSLCipherSuite*)&Cipher312; + result[0xC0AB] = (SSLCipherSuite*)&Cipher313; + result[0xC0AC] = (SSLCipherSuite*)&Cipher314; + result[0xC0AD] = (SSLCipherSuite*)&Cipher315; + result[0xC0AE] = (SSLCipherSuite*)&Cipher316; + result[0xC0AF] = (SSLCipherSuite*)&Cipher317; + result[0xCCA8] = (SSLCipherSuite*)&Cipher318; + result[0xCCA9] = (SSLCipherSuite*)&Cipher319; + result[0xCCAA] = (SSLCipherSuite*)&Cipher320; + result[0xCCAB] = (SSLCipherSuite*)&Cipher321; + result[0xCCAC] = (SSLCipherSuite*)&Cipher322; + result[0xCCAD] = (SSLCipherSuite*)&Cipher323; + result[0xCCAE] = (SSLCipherSuite*)&Cipher324; + result[0x1301] = (SSLCipherSuite*)&Cipher325; + result[0x1302] = (SSLCipherSuite*)&Cipher326; + result[0x1303] = (SSLCipherSuite*)&Cipher327; + result[0x1304] = (SSLCipherSuite*)&Cipher328; + result[0x1305] = (SSLCipherSuite*)&Cipher329; + return result; } - return h; -} - -static std::unordered_map createCipherSuiteStringToObjectMap() -{ - std::unordered_map result; - - result[0x9F180F43] = (SSLCipherSuite*)&Cipher1; - result[0x97D9341F] = (SSLCipherSuite*)&Cipher2; - result[0x288FABA1] = (SSLCipherSuite*)&Cipher3; - result[0x9179C5BD] = (SSLCipherSuite*)&Cipher4; - result[0x68DF0C8F] = (SSLCipherSuite*)&Cipher5; - result[0x5FB32DF1] = (SSLCipherSuite*)&Cipher6; - result[0x2A1FC0FC] = (SSLCipherSuite*)&Cipher7; - result[0x5BF6459E] = (SSLCipherSuite*)&Cipher8; - result[0x60D692F4] = (SSLCipherSuite*)&Cipher9; - result[0x26A21427] = (SSLCipherSuite*)&Cipher10; - result[0xD3558C6D] = (SSLCipherSuite*)&Cipher11; - result[0xAE2673E9] = (SSLCipherSuite*)&Cipher12; - result[0xC63B19B0] = (SSLCipherSuite*)&Cipher13; - result[0xFE49B3BC] = (SSLCipherSuite*)&Cipher14; - result[0x625A86D5] = (SSLCipherSuite*)&Cipher15; - result[0x60FF1BD4] = (SSLCipherSuite*)&Cipher16; - result[0xE101D5C8] = (SSLCipherSuite*)&Cipher17; - result[0x422859E8] = (SSLCipherSuite*)&Cipher18; - result[0x88ABC503] = (SSLCipherSuite*)&Cipher19; - result[0x44284B1] = (SSLCipherSuite*)&Cipher20; - result[0xFD71B064] = (SSLCipherSuite*)&Cipher21; - result[0x76F35237] = (SSLCipherSuite*)&Cipher22; - result[0x7D93159D] = (SSLCipherSuite*)&Cipher23; - result[0x6E9D1AE2] = (SSLCipherSuite*)&Cipher24; - result[0xFA0974E4] = (SSLCipherSuite*)&Cipher25; - result[0xEC27ACB1] = (SSLCipherSuite*)&Cipher26; - result[0x6859C7A8] = (SSLCipherSuite*)&Cipher27; - result[0x55FD3D14] = (SSLCipherSuite*)&Cipher28; - result[0xA7650023] = (SSLCipherSuite*)&Cipher29; - result[0xDC042011] = (SSLCipherSuite*)&Cipher30; - result[0x94BFBF4D] = (SSLCipherSuite*)&Cipher31; - result[0x2FE24162] = (SSLCipherSuite*)&Cipher32; - result[0xC449D595] = (SSLCipherSuite*)&Cipher33; - result[0xE11292AF] = (SSLCipherSuite*)&Cipher34; - result[0x47D0643] = (SSLCipherSuite*)&Cipher35; - result[0xC9ABBA3C] = (SSLCipherSuite*)&Cipher36; - result[0x9F323A5F] = (SSLCipherSuite*)&Cipher37; - result[0xFBF78046] = (SSLCipherSuite*)&Cipher38; - result[0x859BD79F] = (SSLCipherSuite*)&Cipher39; - result[0xF9FBBB39] = (SSLCipherSuite*)&Cipher40; - result[0x63587748] = (SSLCipherSuite*)&Cipher41; - result[0xF84CAE79] = (SSLCipherSuite*)&Cipher42; - result[0xCA39F6F1] = (SSLCipherSuite*)&Cipher43; - result[0xDC4D17C1] = (SSLCipherSuite*)&Cipher44; - result[0x955FBE28] = (SSLCipherSuite*)&Cipher45; - result[0x73ED7B86] = (SSLCipherSuite*)&Cipher46; - result[0x14A51855] = (SSLCipherSuite*)&Cipher47; - result[0x2CE54061] = (SSLCipherSuite*)&Cipher48; - result[0x3360789A] = (SSLCipherSuite*)&Cipher49; - result[0xDFEF59B6] = (SSLCipherSuite*)&Cipher50; - result[0xE819855D] = (SSLCipherSuite*)&Cipher51; - result[0x24CC3946] = (SSLCipherSuite*)&Cipher52; - result[0x1CACB5FD] = (SSLCipherSuite*)&Cipher53; - result[0x40193001] = (SSLCipherSuite*)&Cipher54; - result[0xA3846DA2] = (SSLCipherSuite*)&Cipher55; - result[0x8F3B7CF6] = (SSLCipherSuite*)&Cipher56; - result[0xC7B09945] = (SSLCipherSuite*)&Cipher57; - result[0xD8172F82] = (SSLCipherSuite*)&Cipher58; - result[0xB6748503] = (SSLCipherSuite*)&Cipher59; - result[0xDB105043] = (SSLCipherSuite*)&Cipher60; - result[0x21E8AC2E] = (SSLCipherSuite*)&Cipher61; - result[0x55096FC2] = (SSLCipherSuite*)&Cipher62; - result[0x38F955AF] = (SSLCipherSuite*)&Cipher63; - result[0xBA8C1D77] = (SSLCipherSuite*)&Cipher64; - result[0x91128102] = (SSLCipherSuite*)&Cipher65; - result[0xA7ED740E] = (SSLCipherSuite*)&Cipher66; - result[0x75C4908B] = (SSLCipherSuite*)&Cipher67; - result[0xBC6C5E87] = (SSLCipherSuite*)&Cipher68; - result[0xA0499A2A] = (SSLCipherSuite*)&Cipher69; - result[0x4F0FFC13] = (SSLCipherSuite*)&Cipher70; - result[0xCCEE9996] = (SSLCipherSuite*)&Cipher71; - result[0x8570DA22] = (SSLCipherSuite*)&Cipher72; - result[0x75D4FD57] = (SSLCipherSuite*)&Cipher73; - result[0x602E04D3] = (SSLCipherSuite*)&Cipher74; - result[0x5EDC9C36] = (SSLCipherSuite*)&Cipher75; - result[0xE66C167E] = (SSLCipherSuite*)&Cipher76; - result[0x909F6D7B] = (SSLCipherSuite*)&Cipher77; - result[0x3C35B1AA] = (SSLCipherSuite*)&Cipher78; - result[0x6D4D1A2E] = (SSLCipherSuite*)&Cipher79; - result[0xBF788317] = (SSLCipherSuite*)&Cipher80; - result[0x5329738B] = (SSLCipherSuite*)&Cipher81; - result[0x7D11AB2] = (SSLCipherSuite*)&Cipher82; - result[0x461ACA21] = (SSLCipherSuite*)&Cipher83; - result[0x15404ADD] = (SSLCipherSuite*)&Cipher84; - result[0x3806AF6] = (SSLCipherSuite*)&Cipher85; - result[0xB2D80EB6] = (SSLCipherSuite*)&Cipher86; - result[0xE54425D1] = (SSLCipherSuite*)&Cipher87; - result[0x476457CD] = (SSLCipherSuite*)&Cipher88; - result[0x1D55E526] = (SSLCipherSuite*)&Cipher89; - result[0x953C69E6] = (SSLCipherSuite*)&Cipher90; - result[0x6ADE7E16] = (SSLCipherSuite*)&Cipher91; - result[0xE8C7BBE8] = (SSLCipherSuite*)&Cipher92; - result[0x623DC741] = (SSLCipherSuite*)&Cipher93; - result[0xF403E1] = (SSLCipherSuite*)&Cipher94; - result[0x90D8CADC] = (SSLCipherSuite*)&Cipher95; - result[0xC30D1199] = (SSLCipherSuite*)&Cipher96; - result[0x9CFB1B5D] = (SSLCipherSuite*)&Cipher97; - result[0x2D3B99E8] = (SSLCipherSuite*)&Cipher98; - result[0x4A9E8B0C] = (SSLCipherSuite*)&Cipher99; - result[0x16BD2351] = (SSLCipherSuite*)&Cipher100; - result[0x586BC20E] = (SSLCipherSuite*)&Cipher101; - result[0x996B90AA] = (SSLCipherSuite*)&Cipher102; - result[0x2F3871FE] = (SSLCipherSuite*)&Cipher103; - result[0xF2DD519A] = (SSLCipherSuite*)&Cipher104; - result[0x52615F23] = (SSLCipherSuite*)&Cipher105; - result[0xDEE51337] = (SSLCipherSuite*)&Cipher106; - result[0xB30890E2] = (SSLCipherSuite*)&Cipher107; - result[0x40F3FF3E] = (SSLCipherSuite*)&Cipher108; - result[0xE306EE17] = (SSLCipherSuite*)&Cipher109; - result[0x870C6FCB] = (SSLCipherSuite*)&Cipher110; - result[0xEB12CAEF] = (SSLCipherSuite*)&Cipher111; - result[0x68795983] = (SSLCipherSuite*)&Cipher112; - result[0x606BA9BE] = (SSLCipherSuite*)&Cipher113; - result[0x2C33475A] = (SSLCipherSuite*)&Cipher114; - result[0x640CAAEE] = (SSLCipherSuite*)&Cipher115; - result[0x6603488A] = (SSLCipherSuite*)&Cipher116; - result[0x8BA58643] = (SSLCipherSuite*)&Cipher117; - result[0x16059E57] = (SSLCipherSuite*)&Cipher118; - result[0x1B0606D3] = (SSLCipherSuite*)&Cipher119; - result[0x1CF76007] = (SSLCipherSuite*)&Cipher120; - result[0x618CE8F2] = (SSLCipherSuite*)&Cipher121; - result[0xE264D3B6] = (SSLCipherSuite*)&Cipher122; - result[0xB4C5AE63] = (SSLCipherSuite*)&Cipher123; - result[0x95DF4757] = (SSLCipherSuite*)&Cipher124; - result[0x1D1CF062] = (SSLCipherSuite*)&Cipher125; - result[0xE7AA2826] = (SSLCipherSuite*)&Cipher126; - result[0x38D94EE2] = (SSLCipherSuite*)&Cipher127; - result[0x889BA306] = (SSLCipherSuite*)&Cipher128; - result[0x5B816E75] = (SSLCipherSuite*)&Cipher129; - result[0x6F18C4DD] = (SSLCipherSuite*)&Cipher130; - result[0x2E1C05E0] = (SSLCipherSuite*)&Cipher131; - result[0x5592CFF7] = (SSLCipherSuite*)&Cipher132; - result[0x8221D38B] = (SSLCipherSuite*)&Cipher133; - result[0x9538105C] = (SSLCipherSuite*)&Cipher134; - result[0xF1100DD0] = (SSLCipherSuite*)&Cipher135; - result[0xF492EF1F] = (SSLCipherSuite*)&Cipher136; - result[0x226BD52C] = (SSLCipherSuite*)&Cipher137; - result[0xBBACE99F] = (SSLCipherSuite*)&Cipher138; - result[0xB3D4B66B] = (SSLCipherSuite*)&Cipher139; - result[0x8C619440] = (SSLCipherSuite*)&Cipher140; - result[0xE60B95C] = (SSLCipherSuite*)&Cipher141; - result[0x24F48D07] = (SSLCipherSuite*)&Cipher142; - result[0x15C7AF26] = (SSLCipherSuite*)&Cipher143; - result[0xCBA219CC] = (SSLCipherSuite*)&Cipher144; - result[0x9BD946BE] = (SSLCipherSuite*)&Cipher145; - result[0x7CCA46FF] = (SSLCipherSuite*)&Cipher146; - result[0x9FB51FA3] = (SSLCipherSuite*)&Cipher147; - result[0xC82A275B] = (SSLCipherSuite*)&Cipher148; - result[0x4472A583] = (SSLCipherSuite*)&Cipher149; - result[0xDBA3A5CF] = (SSLCipherSuite*)&Cipher150; - result[0x86338128] = (SSLCipherSuite*)&Cipher151; - result[0x8CCE91E4] = (SSLCipherSuite*)&Cipher152; - result[0xA81C6CA0] = (SSLCipherSuite*)&Cipher153; - result[0x6D80815E] = (SSLCipherSuite*)&Cipher154; - result[0xA383DEB0] = (SSLCipherSuite*)&Cipher155; - result[0x52073879] = (SSLCipherSuite*)&Cipher156; - result[0x5BA0B279] = (SSLCipherSuite*)&Cipher157; - result[0xD787CCC9] = (SSLCipherSuite*)&Cipher158; - result[0x9C86C6A9] = (SSLCipherSuite*)&Cipher159; - result[0xDAE424E5] = (SSLCipherSuite*)&Cipher160; - result[0x72C15ECE] = (SSLCipherSuite*)&Cipher161; - result[0xF0E8FB6E] = (SSLCipherSuite*)&Cipher162; - result[0xA2005D44] = (SSLCipherSuite*)&Cipher163; - result[0x77F79962] = (SSLCipherSuite*)&Cipher164; - result[0x25C8184C] = (SSLCipherSuite*)&Cipher165; - result[0x2070F8A5] = (SSLCipherSuite*)&Cipher166; - result[0x4189ED8D] = (SSLCipherSuite*)&Cipher167; - result[0x94C21B1] = (SSLCipherSuite*)&Cipher168; - result[0x1B0CB25C] = (SSLCipherSuite*)&Cipher169; - result[0xF18127A0] = (SSLCipherSuite*)&Cipher170; - result[0xC7FCA79A] = (SSLCipherSuite*)&Cipher171; - result[0xC1DEE135] = (SSLCipherSuite*)&Cipher172; - result[0xDA7143E9] = (SSLCipherSuite*)&Cipher173; - result[0xE82B6A2] = (SSLCipherSuite*)&Cipher174; - result[0x438EC1DD] = (SSLCipherSuite*)&Cipher175; - result[0x6BE32FA9] = (SSLCipherSuite*)&Cipher176; - result[0x18A5C375] = (SSLCipherSuite*)&Cipher177; - result[0x24136C59] = (SSLCipherSuite*)&Cipher178; - result[0x88529408] = (SSLCipherSuite*)&Cipher179; - result[0xADAB33FC] = (SSLCipherSuite*)&Cipher180; - result[0x79407DCB] = (SSLCipherSuite*)&Cipher181; - result[0x64970FFF] = (SSLCipherSuite*)&Cipher182; - result[0x8260DC9A] = (SSLCipherSuite*)&Cipher183; - result[0x4B74FFFE] = (SSLCipherSuite*)&Cipher184; - result[0x350DD5C8] = (SSLCipherSuite*)&Cipher185; - result[0x53E057C] = (SSLCipherSuite*)&Cipher186; - result[0x266020E1] = (SSLCipherSuite*)&Cipher187; - result[0xE6DB4B9D] = (SSLCipherSuite*)&Cipher188; - result[0x5A992E6] = (SSLCipherSuite*)&Cipher189; - result[0x1B33C882] = (SSLCipherSuite*)&Cipher190; - result[0x33579D2B] = (SSLCipherSuite*)&Cipher191; - result[0x1BD7F7FF] = (SSLCipherSuite*)&Cipher192; - result[0x39C59ED9] = (SSLCipherSuite*)&Cipher193; - result[0x4F19FB95] = (SSLCipherSuite*)&Cipher194; - result[0x8F4737BE] = (SSLCipherSuite*)&Cipher195; - result[0x2567AA9E] = (SSLCipherSuite*)&Cipher196; - result[0xEEF843DB] = (SSLCipherSuite*)&Cipher197; - result[0x978C4E4F] = (SSLCipherSuite*)&Cipher198; - result[0x2F8D17D9] = (SSLCipherSuite*)&Cipher199; - result[0x7F80393A] = (SSLCipherSuite*)&Cipher200; - result[0xDCA5AE1E] = (SSLCipherSuite*)&Cipher201; - result[0x74AA95D7] = (SSLCipherSuite*)&Cipher202; - result[0xB93174BB] = (SSLCipherSuite*)&Cipher203; - result[0x46E274FC] = (SSLCipherSuite*)&Cipher204; - result[0x9DC85330] = (SSLCipherSuite*)&Cipher205; - result[0x972847B8] = (SSLCipherSuite*)&Cipher206; - result[0xFCF61DAC] = (SSLCipherSuite*)&Cipher207; - result[0x73C0029B] = (SSLCipherSuite*)&Cipher208; - result[0xDA41D70F] = (SSLCipherSuite*)&Cipher209; - result[0x12CBC4E7] = (SSLCipherSuite*)&Cipher210; - result[0x8B2D5ACB] = (SSLCipherSuite*)&Cipher211; - result[0x28C0C084] = (SSLCipherSuite*)&Cipher212; - result[0x1602C1F8] = (SSLCipherSuite*)&Cipher213; - result[0xF5FB9ED] = (SSLCipherSuite*)&Cipher214; - result[0xE8E30E91] = (SSLCipherSuite*)&Cipher215; - result[0x70BA7792] = (SSLCipherSuite*)&Cipher216; - result[0x94C38076] = (SSLCipherSuite*)&Cipher217; - result[0xE5B3483F] = (SSLCipherSuite*)&Cipher218; - result[0x892DEBE3] = (SSLCipherSuite*)&Cipher219; - result[0x65609E50] = (SSLCipherSuite*)&Cipher220; - result[0xAB4F3F04] = (SSLCipherSuite*)&Cipher221; - result[0x8BFC76DA] = (SSLCipherSuite*)&Cipher222; - result[0xD4BDCD6] = (SSLCipherSuite*)&Cipher223; - result[0xCAB8F54A] = (SSLCipherSuite*)&Cipher224; - result[0xA10DCFC6] = (SSLCipherSuite*)&Cipher225; - result[0xD6B71B71] = (SSLCipherSuite*)&Cipher226; - result[0x6D775A2D] = (SSLCipherSuite*)&Cipher227; - result[0x7997AD16] = (SSLCipherSuite*)&Cipher228; - result[0x5338C632] = (SSLCipherSuite*)&Cipher229; - result[0x45F0598D] = (SSLCipherSuite*)&Cipher230; - result[0x2D8B6A99] = (SSLCipherSuite*)&Cipher231; - result[0xE14DC125] = (SSLCipherSuite*)&Cipher232; - result[0x1538351] = (SSLCipherSuite*)&Cipher233; - result[0x1A8CE530] = (SSLCipherSuite*)&Cipher234; - result[0xB01E69C4] = (SSLCipherSuite*)&Cipher235; - result[0xCCBF70D3] = (SSLCipherSuite*)&Cipher236; - result[0xEF664FE7] = (SSLCipherSuite*)&Cipher237; - result[0xF6ED4F52] = (SSLCipherSuite*)&Cipher238; - result[0x7D6522E] = (SSLCipherSuite*)&Cipher239; - result[0xBDB5C9B9] = (SSLCipherSuite*)&Cipher240; - result[0xD98D5C95] = (SSLCipherSuite*)&Cipher241; - result[0x92B92727] = (SSLCipherSuite*)&Cipher242; - result[0xB4FE570B] = (SSLCipherSuite*)&Cipher243; - result[0x8DCF7F77] = (SSLCipherSuite*)&Cipher244; - result[0x8208545B] = (SSLCipherSuite*)&Cipher245; - result[0x39A13298] = (SSLCipherSuite*)&Cipher246; - result[0xECB7070C] = (SSLCipherSuite*)&Cipher247; - result[0xAFA95F8A] = (SSLCipherSuite*)&Cipher248; - result[0x3D80E106] = (SSLCipherSuite*)&Cipher249; - result[0x83AF9B7A] = (SSLCipherSuite*)&Cipher250; - result[0x1FAAC2F6] = (SSLCipherSuite*)&Cipher251; - result[0x2AF11F51] = (SSLCipherSuite*)&Cipher252; - result[0xEDFD300D] = (SSLCipherSuite*)&Cipher253; - result[0x91AA268F] = (SSLCipherSuite*)&Cipher254; - result[0x9DF0E933] = (SSLCipherSuite*)&Cipher255; - result[0xF3951A6A] = (SSLCipherSuite*)&Cipher256; - result[0xE4FF8DCE] = (SSLCipherSuite*)&Cipher257; - result[0xBE4DFC61] = (SSLCipherSuite*)&Cipher258; - result[0xBB2CF025] = (SSLCipherSuite*)&Cipher259; - result[0x354D38A8] = (SSLCipherSuite*)&Cipher260; - result[0xE2444B9C] = (SSLCipherSuite*)&Cipher261; - result[0xF8298D43] = (SSLCipherSuite*)&Cipher262; - result[0x3EC413B7] = (SSLCipherSuite*)&Cipher263; - result[0xE0C75BE9] = (SSLCipherSuite*)&Cipher264; - result[0x7191BE45] = (SSLCipherSuite*)&Cipher265; - result[0xDDE7C439] = (SSLCipherSuite*)&Cipher266; - result[0xBE715415] = (SSLCipherSuite*)&Cipher267; - result[0x6CF8F9A6] = (SSLCipherSuite*)&Cipher268; - result[0x36D61242] = (SSLCipherSuite*)&Cipher269; - result[0xFA9BA9ED] = (SSLCipherSuite*)&Cipher270; - result[0x4588B179] = (SSLCipherSuite*)&Cipher271; - result[0xB3C246FA] = (SSLCipherSuite*)&Cipher272; - result[0x750EEB76] = (SSLCipherSuite*)&Cipher273; - result[0xC50ACCB2] = (SSLCipherSuite*)&Cipher274; - result[0x9555CD0E] = (SSLCipherSuite*)&Cipher275; - result[0xF25A659B] = (SSLCipherSuite*)&Cipher276; - result[0x1670E72F] = (SSLCipherSuite*)&Cipher277; - result[0xDB0DD6BC] = (SSLCipherSuite*)&Cipher278; - result[0x19CACD70] = (SSLCipherSuite*)&Cipher279; - result[0xC54D5481] = (SSLCipherSuite*)&Cipher280; - result[0x7BCCA2BD] = (SSLCipherSuite*)&Cipher281; - result[0xA851374E] = (SSLCipherSuite*)&Cipher282; - result[0xE887BEA] = (SSLCipherSuite*)&Cipher283; - result[0xDECAA7F9] = (SSLCipherSuite*)&Cipher284; - result[0x29DA73D5] = (SSLCipherSuite*)&Cipher285; - result[0xAC69ECC9] = (SSLCipherSuite*)&Cipher286; - result[0x6AE55625] = (SSLCipherSuite*)&Cipher287; - result[0x2BB24546] = (SSLCipherSuite*)&Cipher288; - result[0x7AB5F262] = (SSLCipherSuite*)&Cipher289; - result[0x3DB83990] = (SSLCipherSuite*)&Cipher290; - result[0xC852A244] = (SSLCipherSuite*)&Cipher291; - result[0xA3C952C0] = (SSLCipherSuite*)&Cipher292; - result[0xAF630C34] = (SSLCipherSuite*)&Cipher293; - result[0xD4EE22B] = (SSLCipherSuite*)&Cipher294; - result[0x83F4C5DF] = (SSLCipherSuite*)&Cipher295; - result[0xCCF6F918] = (SSLCipherSuite*)&Cipher296; - result[0x955C9E8C] = (SSLCipherSuite*)&Cipher297; - result[0xF3559154] = (SSLCipherSuite*)&Cipher298; - result[0xE0991C14] = (SSLCipherSuite*)&Cipher299; - result[0x7F6BF424] = (SSLCipherSuite*)&Cipher300; - result[0x4A129264] = (SSLCipherSuite*)&Cipher301; - result[0xB25E29E3] = (SSLCipherSuite*)&Cipher302; - result[0xA6E15A23] = (SSLCipherSuite*)&Cipher303; - result[0x637C5C53] = (SSLCipherSuite*)&Cipher304; - result[0x22794513] = (SSLCipherSuite*)&Cipher305; - result[0x4CE30464] = (SSLCipherSuite*)&Cipher306; - result[0xFDFE3B24] = (SSLCipherSuite*)&Cipher307; - result[0xDC8A2074] = (SSLCipherSuite*)&Cipher308; - result[0xFD448934] = (SSLCipherSuite*)&Cipher309; - result[0xF4FC2B13] = (SSLCipherSuite*)&Cipher310; - result[0xB10ECD53] = (SSLCipherSuite*)&Cipher311; - result[0xF44F4BC7] = (SSLCipherSuite*)&Cipher312; - result[0x49AF0BF] = (SSLCipherSuite*)&Cipher313; - result[0xDFAF479A] = (SSLCipherSuite*)&Cipher314; - result[0x82BF78CE] = (SSLCipherSuite*)&Cipher315; - result[0x46CD83C9] = (SSLCipherSuite*)&Cipher316; - result[0x8F7D7465] = (SSLCipherSuite*)&Cipher317; - result[0xBD9CDFE5] = (SSLCipherSuite*)&Cipher318; - result[0x92942203] = (SSLCipherSuite*)&Cipher319; - result[0x783C98AD] = (SSLCipherSuite*)&Cipher320; - result[0x92213B6D] = (SSLCipherSuite*)&Cipher321; - result[0xCFCB1A55] = (SSLCipherSuite*)&Cipher322; - result[0x54C2D55D] = (SSLCipherSuite*)&Cipher323; - result[0xDCD6F114] = (SSLCipherSuite*)&Cipher324; - result[0x6AD23C40] = (SSLCipherSuite*)&Cipher325; - result[0x5F5239D4] = (SSLCipherSuite*)&Cipher326; - result[0xAB27704B] = (SSLCipherSuite*)&Cipher327; - result[0xA3178D0C] = (SSLCipherSuite*)&Cipher328; - result[0x5DAAA195] = (SSLCipherSuite*)&Cipher329; - - return result; -} - -std::set createGreaseSet() -{ - uint16_t greaseExtensions[] = {0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a, 0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa}; - return std::set(greaseExtensions, greaseExtensions + 16); -} - -static const std::unordered_map CipherSuiteIdToObjectMap = createCipherSuiteIdToObjectMap(); - -static const std::unordered_map CipherSuiteStringToObjectMap = createCipherSuiteStringToObjectMap(); - -static const std::set GreaseSet = createGreaseSet(); - -SSLCipherSuite* SSLCipherSuite::getCipherSuiteByID(uint16_t id) -{ - std::unordered_map::const_iterator pos = CipherSuiteIdToObjectMap.find(id); - if (pos == CipherSuiteIdToObjectMap.end()) - return nullptr; - else - return pos->second; -} - -SSLCipherSuite* SSLCipherSuite::getCipherSuiteByName(std::string name) -{ - uint32_t nameHash = hashString(std::move(name)); - std::unordered_map::const_iterator pos = CipherSuiteStringToObjectMap.find(nameHash); - if (pos == CipherSuiteStringToObjectMap.end()) - return nullptr; - else - return pos->second; -} -// -------------------- -// SSLExtension methods -// -------------------- +#define A 54059 /* a prime */ +#define B 76963 /* another prime */ +#define C 86969 /* yet another prime */ +#define FIRST_HASH 37 /* also prime */ -SSLExtension::SSLExtension(uint8_t* data) -{ - m_RawData = data; -} + static uint32_t hashString(std::string str) + { + unsigned h = FIRST_HASH; + for (std::string::size_type i = 0; i < str.size(); ++i) + { + h = (h * A) ^ (str[i] * B); + } + return h; + } -SSLExtensionType SSLExtension::getType() const -{ - uint16_t typeAsInt = getTypeAsInt(); - if (typeAsInt <= 24 || typeAsInt == 35 || typeAsInt == 65281) - return (SSLExtensionType)typeAsInt; + static std::unordered_map createCipherSuiteStringToObjectMap() + { + std::unordered_map result; + + result[0x9F180F43] = (SSLCipherSuite*)&Cipher1; + result[0x97D9341F] = (SSLCipherSuite*)&Cipher2; + result[0x288FABA1] = (SSLCipherSuite*)&Cipher3; + result[0x9179C5BD] = (SSLCipherSuite*)&Cipher4; + result[0x68DF0C8F] = (SSLCipherSuite*)&Cipher5; + result[0x5FB32DF1] = (SSLCipherSuite*)&Cipher6; + result[0x2A1FC0FC] = (SSLCipherSuite*)&Cipher7; + result[0x5BF6459E] = (SSLCipherSuite*)&Cipher8; + result[0x60D692F4] = (SSLCipherSuite*)&Cipher9; + result[0x26A21427] = (SSLCipherSuite*)&Cipher10; + result[0xD3558C6D] = (SSLCipherSuite*)&Cipher11; + result[0xAE2673E9] = (SSLCipherSuite*)&Cipher12; + result[0xC63B19B0] = (SSLCipherSuite*)&Cipher13; + result[0xFE49B3BC] = (SSLCipherSuite*)&Cipher14; + result[0x625A86D5] = (SSLCipherSuite*)&Cipher15; + result[0x60FF1BD4] = (SSLCipherSuite*)&Cipher16; + result[0xE101D5C8] = (SSLCipherSuite*)&Cipher17; + result[0x422859E8] = (SSLCipherSuite*)&Cipher18; + result[0x88ABC503] = (SSLCipherSuite*)&Cipher19; + result[0x44284B1] = (SSLCipherSuite*)&Cipher20; + result[0xFD71B064] = (SSLCipherSuite*)&Cipher21; + result[0x76F35237] = (SSLCipherSuite*)&Cipher22; + result[0x7D93159D] = (SSLCipherSuite*)&Cipher23; + result[0x6E9D1AE2] = (SSLCipherSuite*)&Cipher24; + result[0xFA0974E4] = (SSLCipherSuite*)&Cipher25; + result[0xEC27ACB1] = (SSLCipherSuite*)&Cipher26; + result[0x6859C7A8] = (SSLCipherSuite*)&Cipher27; + result[0x55FD3D14] = (SSLCipherSuite*)&Cipher28; + result[0xA7650023] = (SSLCipherSuite*)&Cipher29; + result[0xDC042011] = (SSLCipherSuite*)&Cipher30; + result[0x94BFBF4D] = (SSLCipherSuite*)&Cipher31; + result[0x2FE24162] = (SSLCipherSuite*)&Cipher32; + result[0xC449D595] = (SSLCipherSuite*)&Cipher33; + result[0xE11292AF] = (SSLCipherSuite*)&Cipher34; + result[0x47D0643] = (SSLCipherSuite*)&Cipher35; + result[0xC9ABBA3C] = (SSLCipherSuite*)&Cipher36; + result[0x9F323A5F] = (SSLCipherSuite*)&Cipher37; + result[0xFBF78046] = (SSLCipherSuite*)&Cipher38; + result[0x859BD79F] = (SSLCipherSuite*)&Cipher39; + result[0xF9FBBB39] = (SSLCipherSuite*)&Cipher40; + result[0x63587748] = (SSLCipherSuite*)&Cipher41; + result[0xF84CAE79] = (SSLCipherSuite*)&Cipher42; + result[0xCA39F6F1] = (SSLCipherSuite*)&Cipher43; + result[0xDC4D17C1] = (SSLCipherSuite*)&Cipher44; + result[0x955FBE28] = (SSLCipherSuite*)&Cipher45; + result[0x73ED7B86] = (SSLCipherSuite*)&Cipher46; + result[0x14A51855] = (SSLCipherSuite*)&Cipher47; + result[0x2CE54061] = (SSLCipherSuite*)&Cipher48; + result[0x3360789A] = (SSLCipherSuite*)&Cipher49; + result[0xDFEF59B6] = (SSLCipherSuite*)&Cipher50; + result[0xE819855D] = (SSLCipherSuite*)&Cipher51; + result[0x24CC3946] = (SSLCipherSuite*)&Cipher52; + result[0x1CACB5FD] = (SSLCipherSuite*)&Cipher53; + result[0x40193001] = (SSLCipherSuite*)&Cipher54; + result[0xA3846DA2] = (SSLCipherSuite*)&Cipher55; + result[0x8F3B7CF6] = (SSLCipherSuite*)&Cipher56; + result[0xC7B09945] = (SSLCipherSuite*)&Cipher57; + result[0xD8172F82] = (SSLCipherSuite*)&Cipher58; + result[0xB6748503] = (SSLCipherSuite*)&Cipher59; + result[0xDB105043] = (SSLCipherSuite*)&Cipher60; + result[0x21E8AC2E] = (SSLCipherSuite*)&Cipher61; + result[0x55096FC2] = (SSLCipherSuite*)&Cipher62; + result[0x38F955AF] = (SSLCipherSuite*)&Cipher63; + result[0xBA8C1D77] = (SSLCipherSuite*)&Cipher64; + result[0x91128102] = (SSLCipherSuite*)&Cipher65; + result[0xA7ED740E] = (SSLCipherSuite*)&Cipher66; + result[0x75C4908B] = (SSLCipherSuite*)&Cipher67; + result[0xBC6C5E87] = (SSLCipherSuite*)&Cipher68; + result[0xA0499A2A] = (SSLCipherSuite*)&Cipher69; + result[0x4F0FFC13] = (SSLCipherSuite*)&Cipher70; + result[0xCCEE9996] = (SSLCipherSuite*)&Cipher71; + result[0x8570DA22] = (SSLCipherSuite*)&Cipher72; + result[0x75D4FD57] = (SSLCipherSuite*)&Cipher73; + result[0x602E04D3] = (SSLCipherSuite*)&Cipher74; + result[0x5EDC9C36] = (SSLCipherSuite*)&Cipher75; + result[0xE66C167E] = (SSLCipherSuite*)&Cipher76; + result[0x909F6D7B] = (SSLCipherSuite*)&Cipher77; + result[0x3C35B1AA] = (SSLCipherSuite*)&Cipher78; + result[0x6D4D1A2E] = (SSLCipherSuite*)&Cipher79; + result[0xBF788317] = (SSLCipherSuite*)&Cipher80; + result[0x5329738B] = (SSLCipherSuite*)&Cipher81; + result[0x7D11AB2] = (SSLCipherSuite*)&Cipher82; + result[0x461ACA21] = (SSLCipherSuite*)&Cipher83; + result[0x15404ADD] = (SSLCipherSuite*)&Cipher84; + result[0x3806AF6] = (SSLCipherSuite*)&Cipher85; + result[0xB2D80EB6] = (SSLCipherSuite*)&Cipher86; + result[0xE54425D1] = (SSLCipherSuite*)&Cipher87; + result[0x476457CD] = (SSLCipherSuite*)&Cipher88; + result[0x1D55E526] = (SSLCipherSuite*)&Cipher89; + result[0x953C69E6] = (SSLCipherSuite*)&Cipher90; + result[0x6ADE7E16] = (SSLCipherSuite*)&Cipher91; + result[0xE8C7BBE8] = (SSLCipherSuite*)&Cipher92; + result[0x623DC741] = (SSLCipherSuite*)&Cipher93; + result[0xF403E1] = (SSLCipherSuite*)&Cipher94; + result[0x90D8CADC] = (SSLCipherSuite*)&Cipher95; + result[0xC30D1199] = (SSLCipherSuite*)&Cipher96; + result[0x9CFB1B5D] = (SSLCipherSuite*)&Cipher97; + result[0x2D3B99E8] = (SSLCipherSuite*)&Cipher98; + result[0x4A9E8B0C] = (SSLCipherSuite*)&Cipher99; + result[0x16BD2351] = (SSLCipherSuite*)&Cipher100; + result[0x586BC20E] = (SSLCipherSuite*)&Cipher101; + result[0x996B90AA] = (SSLCipherSuite*)&Cipher102; + result[0x2F3871FE] = (SSLCipherSuite*)&Cipher103; + result[0xF2DD519A] = (SSLCipherSuite*)&Cipher104; + result[0x52615F23] = (SSLCipherSuite*)&Cipher105; + result[0xDEE51337] = (SSLCipherSuite*)&Cipher106; + result[0xB30890E2] = (SSLCipherSuite*)&Cipher107; + result[0x40F3FF3E] = (SSLCipherSuite*)&Cipher108; + result[0xE306EE17] = (SSLCipherSuite*)&Cipher109; + result[0x870C6FCB] = (SSLCipherSuite*)&Cipher110; + result[0xEB12CAEF] = (SSLCipherSuite*)&Cipher111; + result[0x68795983] = (SSLCipherSuite*)&Cipher112; + result[0x606BA9BE] = (SSLCipherSuite*)&Cipher113; + result[0x2C33475A] = (SSLCipherSuite*)&Cipher114; + result[0x640CAAEE] = (SSLCipherSuite*)&Cipher115; + result[0x6603488A] = (SSLCipherSuite*)&Cipher116; + result[0x8BA58643] = (SSLCipherSuite*)&Cipher117; + result[0x16059E57] = (SSLCipherSuite*)&Cipher118; + result[0x1B0606D3] = (SSLCipherSuite*)&Cipher119; + result[0x1CF76007] = (SSLCipherSuite*)&Cipher120; + result[0x618CE8F2] = (SSLCipherSuite*)&Cipher121; + result[0xE264D3B6] = (SSLCipherSuite*)&Cipher122; + result[0xB4C5AE63] = (SSLCipherSuite*)&Cipher123; + result[0x95DF4757] = (SSLCipherSuite*)&Cipher124; + result[0x1D1CF062] = (SSLCipherSuite*)&Cipher125; + result[0xE7AA2826] = (SSLCipherSuite*)&Cipher126; + result[0x38D94EE2] = (SSLCipherSuite*)&Cipher127; + result[0x889BA306] = (SSLCipherSuite*)&Cipher128; + result[0x5B816E75] = (SSLCipherSuite*)&Cipher129; + result[0x6F18C4DD] = (SSLCipherSuite*)&Cipher130; + result[0x2E1C05E0] = (SSLCipherSuite*)&Cipher131; + result[0x5592CFF7] = (SSLCipherSuite*)&Cipher132; + result[0x8221D38B] = (SSLCipherSuite*)&Cipher133; + result[0x9538105C] = (SSLCipherSuite*)&Cipher134; + result[0xF1100DD0] = (SSLCipherSuite*)&Cipher135; + result[0xF492EF1F] = (SSLCipherSuite*)&Cipher136; + result[0x226BD52C] = (SSLCipherSuite*)&Cipher137; + result[0xBBACE99F] = (SSLCipherSuite*)&Cipher138; + result[0xB3D4B66B] = (SSLCipherSuite*)&Cipher139; + result[0x8C619440] = (SSLCipherSuite*)&Cipher140; + result[0xE60B95C] = (SSLCipherSuite*)&Cipher141; + result[0x24F48D07] = (SSLCipherSuite*)&Cipher142; + result[0x15C7AF26] = (SSLCipherSuite*)&Cipher143; + result[0xCBA219CC] = (SSLCipherSuite*)&Cipher144; + result[0x9BD946BE] = (SSLCipherSuite*)&Cipher145; + result[0x7CCA46FF] = (SSLCipherSuite*)&Cipher146; + result[0x9FB51FA3] = (SSLCipherSuite*)&Cipher147; + result[0xC82A275B] = (SSLCipherSuite*)&Cipher148; + result[0x4472A583] = (SSLCipherSuite*)&Cipher149; + result[0xDBA3A5CF] = (SSLCipherSuite*)&Cipher150; + result[0x86338128] = (SSLCipherSuite*)&Cipher151; + result[0x8CCE91E4] = (SSLCipherSuite*)&Cipher152; + result[0xA81C6CA0] = (SSLCipherSuite*)&Cipher153; + result[0x6D80815E] = (SSLCipherSuite*)&Cipher154; + result[0xA383DEB0] = (SSLCipherSuite*)&Cipher155; + result[0x52073879] = (SSLCipherSuite*)&Cipher156; + result[0x5BA0B279] = (SSLCipherSuite*)&Cipher157; + result[0xD787CCC9] = (SSLCipherSuite*)&Cipher158; + result[0x9C86C6A9] = (SSLCipherSuite*)&Cipher159; + result[0xDAE424E5] = (SSLCipherSuite*)&Cipher160; + result[0x72C15ECE] = (SSLCipherSuite*)&Cipher161; + result[0xF0E8FB6E] = (SSLCipherSuite*)&Cipher162; + result[0xA2005D44] = (SSLCipherSuite*)&Cipher163; + result[0x77F79962] = (SSLCipherSuite*)&Cipher164; + result[0x25C8184C] = (SSLCipherSuite*)&Cipher165; + result[0x2070F8A5] = (SSLCipherSuite*)&Cipher166; + result[0x4189ED8D] = (SSLCipherSuite*)&Cipher167; + result[0x94C21B1] = (SSLCipherSuite*)&Cipher168; + result[0x1B0CB25C] = (SSLCipherSuite*)&Cipher169; + result[0xF18127A0] = (SSLCipherSuite*)&Cipher170; + result[0xC7FCA79A] = (SSLCipherSuite*)&Cipher171; + result[0xC1DEE135] = (SSLCipherSuite*)&Cipher172; + result[0xDA7143E9] = (SSLCipherSuite*)&Cipher173; + result[0xE82B6A2] = (SSLCipherSuite*)&Cipher174; + result[0x438EC1DD] = (SSLCipherSuite*)&Cipher175; + result[0x6BE32FA9] = (SSLCipherSuite*)&Cipher176; + result[0x18A5C375] = (SSLCipherSuite*)&Cipher177; + result[0x24136C59] = (SSLCipherSuite*)&Cipher178; + result[0x88529408] = (SSLCipherSuite*)&Cipher179; + result[0xADAB33FC] = (SSLCipherSuite*)&Cipher180; + result[0x79407DCB] = (SSLCipherSuite*)&Cipher181; + result[0x64970FFF] = (SSLCipherSuite*)&Cipher182; + result[0x8260DC9A] = (SSLCipherSuite*)&Cipher183; + result[0x4B74FFFE] = (SSLCipherSuite*)&Cipher184; + result[0x350DD5C8] = (SSLCipherSuite*)&Cipher185; + result[0x53E057C] = (SSLCipherSuite*)&Cipher186; + result[0x266020E1] = (SSLCipherSuite*)&Cipher187; + result[0xE6DB4B9D] = (SSLCipherSuite*)&Cipher188; + result[0x5A992E6] = (SSLCipherSuite*)&Cipher189; + result[0x1B33C882] = (SSLCipherSuite*)&Cipher190; + result[0x33579D2B] = (SSLCipherSuite*)&Cipher191; + result[0x1BD7F7FF] = (SSLCipherSuite*)&Cipher192; + result[0x39C59ED9] = (SSLCipherSuite*)&Cipher193; + result[0x4F19FB95] = (SSLCipherSuite*)&Cipher194; + result[0x8F4737BE] = (SSLCipherSuite*)&Cipher195; + result[0x2567AA9E] = (SSLCipherSuite*)&Cipher196; + result[0xEEF843DB] = (SSLCipherSuite*)&Cipher197; + result[0x978C4E4F] = (SSLCipherSuite*)&Cipher198; + result[0x2F8D17D9] = (SSLCipherSuite*)&Cipher199; + result[0x7F80393A] = (SSLCipherSuite*)&Cipher200; + result[0xDCA5AE1E] = (SSLCipherSuite*)&Cipher201; + result[0x74AA95D7] = (SSLCipherSuite*)&Cipher202; + result[0xB93174BB] = (SSLCipherSuite*)&Cipher203; + result[0x46E274FC] = (SSLCipherSuite*)&Cipher204; + result[0x9DC85330] = (SSLCipherSuite*)&Cipher205; + result[0x972847B8] = (SSLCipherSuite*)&Cipher206; + result[0xFCF61DAC] = (SSLCipherSuite*)&Cipher207; + result[0x73C0029B] = (SSLCipherSuite*)&Cipher208; + result[0xDA41D70F] = (SSLCipherSuite*)&Cipher209; + result[0x12CBC4E7] = (SSLCipherSuite*)&Cipher210; + result[0x8B2D5ACB] = (SSLCipherSuite*)&Cipher211; + result[0x28C0C084] = (SSLCipherSuite*)&Cipher212; + result[0x1602C1F8] = (SSLCipherSuite*)&Cipher213; + result[0xF5FB9ED] = (SSLCipherSuite*)&Cipher214; + result[0xE8E30E91] = (SSLCipherSuite*)&Cipher215; + result[0x70BA7792] = (SSLCipherSuite*)&Cipher216; + result[0x94C38076] = (SSLCipherSuite*)&Cipher217; + result[0xE5B3483F] = (SSLCipherSuite*)&Cipher218; + result[0x892DEBE3] = (SSLCipherSuite*)&Cipher219; + result[0x65609E50] = (SSLCipherSuite*)&Cipher220; + result[0xAB4F3F04] = (SSLCipherSuite*)&Cipher221; + result[0x8BFC76DA] = (SSLCipherSuite*)&Cipher222; + result[0xD4BDCD6] = (SSLCipherSuite*)&Cipher223; + result[0xCAB8F54A] = (SSLCipherSuite*)&Cipher224; + result[0xA10DCFC6] = (SSLCipherSuite*)&Cipher225; + result[0xD6B71B71] = (SSLCipherSuite*)&Cipher226; + result[0x6D775A2D] = (SSLCipherSuite*)&Cipher227; + result[0x7997AD16] = (SSLCipherSuite*)&Cipher228; + result[0x5338C632] = (SSLCipherSuite*)&Cipher229; + result[0x45F0598D] = (SSLCipherSuite*)&Cipher230; + result[0x2D8B6A99] = (SSLCipherSuite*)&Cipher231; + result[0xE14DC125] = (SSLCipherSuite*)&Cipher232; + result[0x1538351] = (SSLCipherSuite*)&Cipher233; + result[0x1A8CE530] = (SSLCipherSuite*)&Cipher234; + result[0xB01E69C4] = (SSLCipherSuite*)&Cipher235; + result[0xCCBF70D3] = (SSLCipherSuite*)&Cipher236; + result[0xEF664FE7] = (SSLCipherSuite*)&Cipher237; + result[0xF6ED4F52] = (SSLCipherSuite*)&Cipher238; + result[0x7D6522E] = (SSLCipherSuite*)&Cipher239; + result[0xBDB5C9B9] = (SSLCipherSuite*)&Cipher240; + result[0xD98D5C95] = (SSLCipherSuite*)&Cipher241; + result[0x92B92727] = (SSLCipherSuite*)&Cipher242; + result[0xB4FE570B] = (SSLCipherSuite*)&Cipher243; + result[0x8DCF7F77] = (SSLCipherSuite*)&Cipher244; + result[0x8208545B] = (SSLCipherSuite*)&Cipher245; + result[0x39A13298] = (SSLCipherSuite*)&Cipher246; + result[0xECB7070C] = (SSLCipherSuite*)&Cipher247; + result[0xAFA95F8A] = (SSLCipherSuite*)&Cipher248; + result[0x3D80E106] = (SSLCipherSuite*)&Cipher249; + result[0x83AF9B7A] = (SSLCipherSuite*)&Cipher250; + result[0x1FAAC2F6] = (SSLCipherSuite*)&Cipher251; + result[0x2AF11F51] = (SSLCipherSuite*)&Cipher252; + result[0xEDFD300D] = (SSLCipherSuite*)&Cipher253; + result[0x91AA268F] = (SSLCipherSuite*)&Cipher254; + result[0x9DF0E933] = (SSLCipherSuite*)&Cipher255; + result[0xF3951A6A] = (SSLCipherSuite*)&Cipher256; + result[0xE4FF8DCE] = (SSLCipherSuite*)&Cipher257; + result[0xBE4DFC61] = (SSLCipherSuite*)&Cipher258; + result[0xBB2CF025] = (SSLCipherSuite*)&Cipher259; + result[0x354D38A8] = (SSLCipherSuite*)&Cipher260; + result[0xE2444B9C] = (SSLCipherSuite*)&Cipher261; + result[0xF8298D43] = (SSLCipherSuite*)&Cipher262; + result[0x3EC413B7] = (SSLCipherSuite*)&Cipher263; + result[0xE0C75BE9] = (SSLCipherSuite*)&Cipher264; + result[0x7191BE45] = (SSLCipherSuite*)&Cipher265; + result[0xDDE7C439] = (SSLCipherSuite*)&Cipher266; + result[0xBE715415] = (SSLCipherSuite*)&Cipher267; + result[0x6CF8F9A6] = (SSLCipherSuite*)&Cipher268; + result[0x36D61242] = (SSLCipherSuite*)&Cipher269; + result[0xFA9BA9ED] = (SSLCipherSuite*)&Cipher270; + result[0x4588B179] = (SSLCipherSuite*)&Cipher271; + result[0xB3C246FA] = (SSLCipherSuite*)&Cipher272; + result[0x750EEB76] = (SSLCipherSuite*)&Cipher273; + result[0xC50ACCB2] = (SSLCipherSuite*)&Cipher274; + result[0x9555CD0E] = (SSLCipherSuite*)&Cipher275; + result[0xF25A659B] = (SSLCipherSuite*)&Cipher276; + result[0x1670E72F] = (SSLCipherSuite*)&Cipher277; + result[0xDB0DD6BC] = (SSLCipherSuite*)&Cipher278; + result[0x19CACD70] = (SSLCipherSuite*)&Cipher279; + result[0xC54D5481] = (SSLCipherSuite*)&Cipher280; + result[0x7BCCA2BD] = (SSLCipherSuite*)&Cipher281; + result[0xA851374E] = (SSLCipherSuite*)&Cipher282; + result[0xE887BEA] = (SSLCipherSuite*)&Cipher283; + result[0xDECAA7F9] = (SSLCipherSuite*)&Cipher284; + result[0x29DA73D5] = (SSLCipherSuite*)&Cipher285; + result[0xAC69ECC9] = (SSLCipherSuite*)&Cipher286; + result[0x6AE55625] = (SSLCipherSuite*)&Cipher287; + result[0x2BB24546] = (SSLCipherSuite*)&Cipher288; + result[0x7AB5F262] = (SSLCipherSuite*)&Cipher289; + result[0x3DB83990] = (SSLCipherSuite*)&Cipher290; + result[0xC852A244] = (SSLCipherSuite*)&Cipher291; + result[0xA3C952C0] = (SSLCipherSuite*)&Cipher292; + result[0xAF630C34] = (SSLCipherSuite*)&Cipher293; + result[0xD4EE22B] = (SSLCipherSuite*)&Cipher294; + result[0x83F4C5DF] = (SSLCipherSuite*)&Cipher295; + result[0xCCF6F918] = (SSLCipherSuite*)&Cipher296; + result[0x955C9E8C] = (SSLCipherSuite*)&Cipher297; + result[0xF3559154] = (SSLCipherSuite*)&Cipher298; + result[0xE0991C14] = (SSLCipherSuite*)&Cipher299; + result[0x7F6BF424] = (SSLCipherSuite*)&Cipher300; + result[0x4A129264] = (SSLCipherSuite*)&Cipher301; + result[0xB25E29E3] = (SSLCipherSuite*)&Cipher302; + result[0xA6E15A23] = (SSLCipherSuite*)&Cipher303; + result[0x637C5C53] = (SSLCipherSuite*)&Cipher304; + result[0x22794513] = (SSLCipherSuite*)&Cipher305; + result[0x4CE30464] = (SSLCipherSuite*)&Cipher306; + result[0xFDFE3B24] = (SSLCipherSuite*)&Cipher307; + result[0xDC8A2074] = (SSLCipherSuite*)&Cipher308; + result[0xFD448934] = (SSLCipherSuite*)&Cipher309; + result[0xF4FC2B13] = (SSLCipherSuite*)&Cipher310; + result[0xB10ECD53] = (SSLCipherSuite*)&Cipher311; + result[0xF44F4BC7] = (SSLCipherSuite*)&Cipher312; + result[0x49AF0BF] = (SSLCipherSuite*)&Cipher313; + result[0xDFAF479A] = (SSLCipherSuite*)&Cipher314; + result[0x82BF78CE] = (SSLCipherSuite*)&Cipher315; + result[0x46CD83C9] = (SSLCipherSuite*)&Cipher316; + result[0x8F7D7465] = (SSLCipherSuite*)&Cipher317; + result[0xBD9CDFE5] = (SSLCipherSuite*)&Cipher318; + result[0x92942203] = (SSLCipherSuite*)&Cipher319; + result[0x783C98AD] = (SSLCipherSuite*)&Cipher320; + result[0x92213B6D] = (SSLCipherSuite*)&Cipher321; + result[0xCFCB1A55] = (SSLCipherSuite*)&Cipher322; + result[0x54C2D55D] = (SSLCipherSuite*)&Cipher323; + result[0xDCD6F114] = (SSLCipherSuite*)&Cipher324; + result[0x6AD23C40] = (SSLCipherSuite*)&Cipher325; + result[0x5F5239D4] = (SSLCipherSuite*)&Cipher326; + result[0xAB27704B] = (SSLCipherSuite*)&Cipher327; + result[0xA3178D0C] = (SSLCipherSuite*)&Cipher328; + result[0x5DAAA195] = (SSLCipherSuite*)&Cipher329; + + return result; + } - return SSL_EXT_Unknown; -} + std::set createGreaseSet() + { + uint16_t greaseExtensions[] = { 0x0a0a, 0x1a1a, 0x2a2a, 0x3a3a, 0x4a4a, 0x5a5a, 0x6a6a, 0x7a7a, + 0x8a8a, 0x9a9a, 0xaaaa, 0xbaba, 0xcaca, 0xdada, 0xeaea, 0xfafa }; + return std::set(greaseExtensions, greaseExtensions + 16); + } -uint16_t SSLExtension::getTypeAsInt() const -{ - return be16toh(getExtensionStruct()->extensionType); -} + static const std::unordered_map CipherSuiteIdToObjectMap = + createCipherSuiteIdToObjectMap(); -uint16_t SSLExtension::getLength() const -{ - return be16toh(getExtensionStruct()->extensionDataLength); -} + static const std::unordered_map CipherSuiteStringToObjectMap = + createCipherSuiteStringToObjectMap(); -uint16_t SSLExtension::getTotalLength() const -{ - return getLength() + 2*sizeof(uint16_t); -} + static const std::set GreaseSet = createGreaseSet(); -uint8_t* SSLExtension::getData() const -{ - if (getLength() > 0) + SSLCipherSuite* SSLCipherSuite::getCipherSuiteByID(uint16_t id) { - return getExtensionStruct()->extensionData; + std::unordered_map::const_iterator pos = CipherSuiteIdToObjectMap.find(id); + if (pos == CipherSuiteIdToObjectMap.end()) + return nullptr; + else + return pos->second; } - return nullptr; -} - - -// ---------------------------------------- -// SSLServerNameIndicationExtension methods -// ---------------------------------------- - -std::string SSLServerNameIndicationExtension::getHostName() const -{ - auto *extensionDataPtr = getData(); - if (extensionDataPtr == nullptr) + SSLCipherSuite* SSLCipherSuite::getCipherSuiteByName(std::string name) { - return ""; + uint32_t nameHash = hashString(std::move(name)); + std::unordered_map::const_iterator pos = CipherSuiteStringToObjectMap.find(nameHash); + if (pos == CipherSuiteStringToObjectMap.end()) + return nullptr; + else + return pos->second; } - uint8_t *hostNameLengthPos = extensionDataPtr + sizeof(uint16_t) + sizeof(uint8_t); - uint16_t hostNameLength = be16toh(*(uint16_t*)hostNameLengthPos); + // -------------------- + // SSLExtension methods + // -------------------- - char* hostNameAsCharArr = new char[hostNameLength+1]; - memset(hostNameAsCharArr, 0, hostNameLength+1); - memcpy(hostNameAsCharArr, hostNameLengthPos + sizeof(uint16_t), hostNameLength); + SSLExtension::SSLExtension(uint8_t* data) + { + m_RawData = data; + } - std::string res = std::string(hostNameAsCharArr); - delete[] hostNameAsCharArr; - return res; -} + SSLExtensionType SSLExtension::getType() const + { + uint16_t typeAsInt = getTypeAsInt(); + if (typeAsInt <= 24 || typeAsInt == 35 || typeAsInt == 65281) + return (SSLExtensionType)typeAsInt; + return SSL_EXT_Unknown; + } -// ------------------------------------- -// SSLSupportedVersionsExtension methods -// ------------------------------------- + uint16_t SSLExtension::getTypeAsInt() const + { + return be16toh(getExtensionStruct()->extensionType); + } -std::vector SSLSupportedVersionsExtension::getSupportedVersions() const -{ - std::vector result; - uint16_t extensionLength = getLength(); - if (extensionLength == 2) // server hello message + uint16_t SSLExtension::getLength() const { - result.push_back(SSLVersion(be16toh(*(uint16_t*)getData()))); + return be16toh(getExtensionStruct()->extensionDataLength); } - else // client-hello message + + uint16_t SSLExtension::getTotalLength() const { - uint8_t listLength = *getData(); - if (listLength != static_cast(extensionLength - 1) || listLength % 2 != 0) - return result; // bad extension data + return getLength() + 2 * sizeof(uint16_t); + } - uint8_t* dataPtr = getData() + sizeof(uint8_t); - for (int i = 0; i < listLength / 2; i++) + uint8_t* SSLExtension::getData() const + { + if (getLength() > 0) { - result.push_back(SSLVersion(be16toh(*(uint16_t*)dataPtr))); - dataPtr += sizeof(uint16_t); + return getExtensionStruct()->extensionData; } + + return nullptr; } - return result; -} + // ---------------------------------------- + // SSLServerNameIndicationExtension methods + // ---------------------------------------- + std::string SSLServerNameIndicationExtension::getHostName() const + { + auto* extensionDataPtr = getData(); + if (extensionDataPtr == nullptr) + { + return ""; + } -// ----------------------------------- -// TLSSupportedGroupsExtension methods -// ----------------------------------- + uint8_t* hostNameLengthPos = extensionDataPtr + sizeof(uint16_t) + sizeof(uint8_t); + uint16_t hostNameLength = be16toh(*(uint16_t*)hostNameLengthPos); -std::vector TLSSupportedGroupsExtension::getSupportedGroups() const -{ - std::vector result; + char* hostNameAsCharArr = new char[hostNameLength + 1]; + memset(hostNameAsCharArr, 0, hostNameLength + 1); + memcpy(hostNameAsCharArr, hostNameLengthPos + sizeof(uint16_t), hostNameLength); - uint16_t extensionLength = getLength(); - if (extensionLength < sizeof(uint16_t)) - return result; //bad extension data + std::string res = std::string(hostNameAsCharArr); + delete[] hostNameAsCharArr; + return res; + } - uint16_t listLength = be16toh(*(uint16_t*)getData()); - if (listLength != (extensionLength - sizeof(uint16_t)) || listLength % 2 != 0) - return result; // bad extension data + // ------------------------------------- + // SSLSupportedVersionsExtension methods + // ------------------------------------- - uint8_t* dataPtr = getData() + sizeof(uint16_t); - for (int i = 0; i < listLength / 2; i++) + std::vector SSLSupportedVersionsExtension::getSupportedVersions() const { - result.push_back(be16toh(*(uint16_t*)dataPtr)); - dataPtr += sizeof(uint16_t); + std::vector result; + uint16_t extensionLength = getLength(); + if (extensionLength == 2) // server hello message + { + result.push_back(SSLVersion(be16toh(*(uint16_t*)getData()))); + } + else // client-hello message + { + uint8_t listLength = *getData(); + if (listLength != static_cast(extensionLength - 1) || listLength % 2 != 0) + return result; // bad extension data + + uint8_t* dataPtr = getData() + sizeof(uint8_t); + for (int i = 0; i < listLength / 2; i++) + { + result.push_back(SSLVersion(be16toh(*(uint16_t*)dataPtr))); + dataPtr += sizeof(uint16_t); + } + } + + return result; } - return result; -} + // ----------------------------------- + // TLSSupportedGroupsExtension methods + // ----------------------------------- + std::vector TLSSupportedGroupsExtension::getSupportedGroups() const + { + std::vector result; -// --------------------------------- -// TLSECPointFormatExtension methods -// --------------------------------- + uint16_t extensionLength = getLength(); + if (extensionLength < sizeof(uint16_t)) + return result; // bad extension data -std::vector TLSECPointFormatExtension::getECPointFormatList() const -{ - std::vector result; + uint16_t listLength = be16toh(*(uint16_t*)getData()); + if (listLength != (extensionLength - sizeof(uint16_t)) || listLength % 2 != 0) + return result; // bad extension data - uint16_t extensionLength = getLength(); - uint8_t listLength = *getData(); - if (listLength != static_cast(extensionLength - 1)) - return result; // bad extension data + uint8_t* dataPtr = getData() + sizeof(uint16_t); + for (int i = 0; i < listLength / 2; i++) + { + result.push_back(be16toh(*(uint16_t*)dataPtr)); + dataPtr += sizeof(uint16_t); + } - uint8_t* dataPtr = getData() + sizeof(uint8_t); - for (int i = 0; i < listLength; i++) - { - result.push_back(*dataPtr); - dataPtr += sizeof(uint8_t); + return result; } - return result; -} - + // --------------------------------- + // TLSECPointFormatExtension methods + // --------------------------------- -// --------------------------- -// SSLHandshakeMessage methods -// --------------------------- - -SSLHandshakeMessage::SSLHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) -{ - m_Data = data; - m_DataLen = dataLen; - m_Container = container; -} - -SSLHandshakeMessage* SSLHandshakeMessage::createHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) -{ - if (dataLen < sizeof(ssl_tls_handshake_layer)) - return nullptr; + std::vector TLSECPointFormatExtension::getECPointFormatList() const + { + std::vector result; - ssl_tls_handshake_layer* hsMsgHeader = (ssl_tls_handshake_layer*)data; - - if (dataLen >= 16 && (be64toh(*(uint64_t*)data) <= 0xFFFFFF || hsMsgHeader->length1 >= 1)) - // possibly Encrypted Handshake Message - // used heuristic: - // - handshake layer of more than 16 byte - // - first 5 bytes of the handshake message are zeroes - // - or wrong message length is over 64K - // - or message type makes so sense (handled through the switch statement) - return new SSLUnknownMessage(data, dataLen, container); - - switch (hsMsgHeader->handshakeType) - { - case SSL_CLIENT_HELLO: - return new SSLClientHelloMessage(data, dataLen, container); - case SSL_SERVER_HELLO: - return new SSLServerHelloMessage(data, dataLen, container); - case SSL_HELLO_REQUEST: - return new SSLHelloRequestMessage(data, dataLen, container); - case SSL_CERTIFICATE: - return new SSLCertificateMessage(data, dataLen, container); - case SSL_SERVER_KEY_EXCHANGE: - return new SSLServerKeyExchangeMessage(data, dataLen, container); - case SSL_CERTIFICATE_REQUEST: - return new SSLCertificateRequestMessage(data, dataLen, container); - case SSL_CERTIFICATE_VERIFY: - return new SSLCertificateVerifyMessage(data, dataLen, container); - case SSL_CLIENT_KEY_EXCHANGE: - return new SSLClientKeyExchangeMessage(data, dataLen, container); - case SSL_FINISHED: - return new SSLFinishedMessage(data, dataLen, container); - case SSL_SERVER_DONE: - return new SSLServerHelloDoneMessage(data, dataLen, container); - case SSL_NEW_SESSION_TICKET: - return new SSLNewSessionTicketMessage(data, dataLen, container); - default: - return new SSLUnknownMessage(data, dataLen, container); - } -} - -SSLHandshakeType SSLHandshakeMessage::getHandshakeType() const -{ - ssl_tls_handshake_layer* handshakeLayer = (ssl_tls_handshake_layer*)m_Data; - return (SSLHandshakeType)handshakeLayer->handshakeType; -} + uint16_t extensionLength = getLength(); + uint8_t listLength = *getData(); + if (listLength != static_cast(extensionLength - 1)) + return result; // bad extension data -size_t SSLHandshakeMessage::getMessageLength() const -{ - ssl_tls_handshake_layer* handshakeLayer = (ssl_tls_handshake_layer*)m_Data; - //TODO: add handshakeLayer->length1 to the calculation - size_t len = sizeof(ssl_tls_handshake_layer) + be16toh(handshakeLayer->length2); - if (len > m_DataLen) - return m_DataLen; + uint8_t* dataPtr = getData() + sizeof(uint8_t); + for (int i = 0; i < listLength; i++) + { + result.push_back(*dataPtr); + dataPtr += sizeof(uint8_t); + } - return len; -} + return result; + } -bool SSLHandshakeMessage::isMessageComplete() const -{ - if (m_DataLen < sizeof(ssl_tls_handshake_layer)) - return false; + // --------------------------- + // SSLHandshakeMessage methods + // --------------------------- - ssl_tls_handshake_layer* handshakeLayer = (ssl_tls_handshake_layer*)m_Data; - size_t len = sizeof(ssl_tls_handshake_layer) + be16toh(handshakeLayer->length2); - return len <= m_DataLen; -} + SSLHandshakeMessage::SSLHandshakeMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + { + m_Data = data; + m_DataLen = dataLen; + m_Container = container; + } + SSLHandshakeMessage* SSLHandshakeMessage::createHandshakeMessage(uint8_t* data, size_t dataLen, + SSLHandshakeLayer* container) + { + if (dataLen < sizeof(ssl_tls_handshake_layer)) + return nullptr; -// ----------------------------- -// SSLClientHelloMessage methods -// ----------------------------- + ssl_tls_handshake_layer* hsMsgHeader = (ssl_tls_handshake_layer*)data; -SSLClientHelloMessage::SSLClientHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) - : SSLHandshakeMessage(data, dataLen, container) -{ - size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t) + sizeof(uint16_t)*getCipherSuiteCount() + 2*sizeof(uint8_t); - if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) - return; - - uint8_t* extensionLengthPos = m_Data + extensionLengthOffset; - uint16_t extensionLength = getExtensionsLength(); - uint8_t* extensionPos = extensionLengthPos + sizeof(uint16_t); - uint8_t* curPos = extensionPos; - size_t messageLen = getMessageLength(); - size_t minSSLExtensionLen = 2*sizeof(uint16_t); - while ((curPos - extensionPos) < (int)extensionLength - && (curPos - m_Data) < (int)messageLen - && (int)messageLen - (curPos - m_Data) >= (int)minSSLExtensionLen) - { - SSLExtension* newExt = nullptr; - uint16_t sslExtType = be16toh(*(uint16_t*)curPos); - switch (sslExtType) + if (dataLen >= 16 && (be64toh(*(uint64_t*)data) <= 0xFFFFFF || hsMsgHeader->length1 >= 1)) { - case SSL_EXT_SERVER_NAME: - newExt = new SSLServerNameIndicationExtension(curPos); - break; - case SSL_EXT_SUPPORTED_VERSIONS: - newExt = new SSLSupportedVersionsExtension(curPos); - break; - case SSL_EXT_SUPPORTED_GROUPS: - newExt = new TLSSupportedGroupsExtension(curPos); - break; - case SSL_EXT_EC_POINT_FORMATS: - newExt = new TLSECPointFormatExtension(curPos); - break; - default: - newExt = new SSLExtension(curPos); + // possibly Encrypted Handshake Message + // used heuristic: + // - handshake layer of more than 16 byte + // - first 5 bytes of the handshake message are zeroes + // - or wrong message length is over 64K + // - or message type makes so sense (handled through the switch statement) + return new SSLUnknownMessage(data, dataLen, container); } - // Total length can be zero only if getLength() == 0xfffc which is way too large - // and means that this extension (and packet) are malformed - if (newExt->getTotalLength() == 0) + switch (hsMsgHeader->handshakeType) { - delete newExt; - break; + case SSL_CLIENT_HELLO: + return new SSLClientHelloMessage(data, dataLen, container); + case SSL_SERVER_HELLO: + return new SSLServerHelloMessage(data, dataLen, container); + case SSL_HELLO_REQUEST: + return new SSLHelloRequestMessage(data, dataLen, container); + case SSL_CERTIFICATE: + return new SSLCertificateMessage(data, dataLen, container); + case SSL_SERVER_KEY_EXCHANGE: + return new SSLServerKeyExchangeMessage(data, dataLen, container); + case SSL_CERTIFICATE_REQUEST: + return new SSLCertificateRequestMessage(data, dataLen, container); + case SSL_CERTIFICATE_VERIFY: + return new SSLCertificateVerifyMessage(data, dataLen, container); + case SSL_CLIENT_KEY_EXCHANGE: + return new SSLClientKeyExchangeMessage(data, dataLen, container); + case SSL_FINISHED: + return new SSLFinishedMessage(data, dataLen, container); + case SSL_SERVER_DONE: + return new SSLServerHelloDoneMessage(data, dataLen, container); + case SSL_NEW_SESSION_TICKET: + return new SSLNewSessionTicketMessage(data, dataLen, container); + default: + return new SSLUnknownMessage(data, dataLen, container); } - - - m_ExtensionList.pushBack(newExt); - curPos += newExt->getTotalLength(); } -} - -SSLVersion SSLClientHelloMessage::getHandshakeVersion() const -{ - uint16_t handshakeVersion = be16toh(getClientHelloHeader()->handshakeVersion); - return SSLVersion(handshakeVersion); -} - -uint8_t SSLClientHelloMessage::getSessionIDLength() const -{ - if (m_DataLen <= sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t)) - return 0; - - uint8_t val = *(m_Data + sizeof(ssl_tls_client_server_hello)); - if ((size_t)val > m_DataLen - sizeof(ssl_tls_client_server_hello) - 1) - return (uint8_t)(m_DataLen - sizeof(ssl_tls_client_server_hello) - 1); - - return val; -} - -uint8_t* SSLClientHelloMessage::getSessionID() const -{ - if (getSessionIDLength() > 0) - return (m_Data + sizeof(ssl_tls_client_server_hello) + 1); - else - return nullptr; -} - -int SSLClientHelloMessage::getCipherSuiteCount() const -{ - size_t cipherSuiteOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength(); - if (cipherSuiteOffset + sizeof(uint16_t) > m_DataLen) - return 0; - - uint16_t cipherSuiteLen = *(uint16_t*)(m_Data + cipherSuiteOffset); - return be16toh(cipherSuiteLen) / 2; -} - -SSLCipherSuite* SSLClientHelloMessage::getCipherSuite(int index) const -{ - bool isValid; - uint16_t id = getCipherSuiteID(index, isValid); - return (isValid ? SSLCipherSuite::getCipherSuiteByID(id) : nullptr); -} -uint16_t SSLClientHelloMessage::getCipherSuiteID(int index, bool& isValid) const -{ - if (index < 0 || index >= getCipherSuiteCount()) + SSLHandshakeType SSLHandshakeMessage::getHandshakeType() const { - isValid = false; - return 0; + ssl_tls_handshake_layer* handshakeLayer = (ssl_tls_handshake_layer*)m_Data; + return (SSLHandshakeType)handshakeLayer->handshakeType; } - size_t cipherSuiteStartOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t); - if (cipherSuiteStartOffset + sizeof(uint16_t) * (index + 1) > m_DataLen) + size_t SSLHandshakeMessage::getMessageLength() const { - isValid = false; - return 0; - } - - isValid = true; - uint16_t* cipherSuiteStartPos = (uint16_t*)(m_Data + cipherSuiteStartOffset); - return be16toh(*(cipherSuiteStartPos+index)); -} + ssl_tls_handshake_layer* handshakeLayer = (ssl_tls_handshake_layer*)m_Data; + // TODO: add handshakeLayer->length1 to the calculation + size_t len = sizeof(ssl_tls_handshake_layer) + be16toh(handshakeLayer->length2); + if (len > m_DataLen) + return m_DataLen; -uint8_t SSLClientHelloMessage::getCompressionMethodsValue() const -{ - size_t offset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t) + sizeof(uint16_t)*getCipherSuiteCount() + sizeof(uint8_t); - if (offset + sizeof(uint8_t) > m_DataLen) - return 0xff; - - uint8_t* pos = m_Data + offset; - return *pos; -} + return len; + } -int SSLClientHelloMessage::getExtensionCount() const -{ - return m_ExtensionList.size(); -} + bool SSLHandshakeMessage::isMessageComplete() const + { + if (m_DataLen < sizeof(ssl_tls_handshake_layer)) + return false; -uint16_t SSLClientHelloMessage::getExtensionsLength() const -{ - size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t) + sizeof(uint16_t)*getCipherSuiteCount() + 2*sizeof(uint8_t); - if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) - return 0; + ssl_tls_handshake_layer* handshakeLayer = (ssl_tls_handshake_layer*)m_Data; + size_t len = sizeof(ssl_tls_handshake_layer) + be16toh(handshakeLayer->length2); + return len <= m_DataLen; + } - uint8_t* extensionLengthPos = m_Data + extensionLengthOffset; - return be16toh(*(uint16_t*)extensionLengthPos); -} + // ----------------------------- + // SSLClientHelloMessage methods + // ----------------------------- -SSLExtension* SSLClientHelloMessage::getExtension(int index) const -{ - return const_cast(m_ExtensionList.at(index)); -} - -SSLExtension* SSLClientHelloMessage::getExtensionOfType(uint16_t type) const -{ - size_t vecSize = m_ExtensionList.size(); - for (size_t i = 0; i < vecSize; i++) + SSLClientHelloMessage::SSLClientHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) { - SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); - if (curElem->getTypeAsInt() == type) - return curElem; + size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + + sizeof(uint16_t) + sizeof(uint16_t) * getCipherSuiteCount() + + 2 * sizeof(uint8_t); + if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) + return; + + uint8_t* extensionLengthPos = m_Data + extensionLengthOffset; + uint16_t extensionLength = getExtensionsLength(); + uint8_t* extensionPos = extensionLengthPos + sizeof(uint16_t); + uint8_t* curPos = extensionPos; + size_t messageLen = getMessageLength(); + size_t minSSLExtensionLen = 2 * sizeof(uint16_t); + while ((curPos - extensionPos) < (int)extensionLength && (curPos - m_Data) < (int)messageLen && + (int)messageLen - (curPos - m_Data) >= (int)minSSLExtensionLen) + { + SSLExtension* newExt = nullptr; + uint16_t sslExtType = be16toh(*(uint16_t*)curPos); + switch (sslExtType) + { + case SSL_EXT_SERVER_NAME: + newExt = new SSLServerNameIndicationExtension(curPos); + break; + case SSL_EXT_SUPPORTED_VERSIONS: + newExt = new SSLSupportedVersionsExtension(curPos); + break; + case SSL_EXT_SUPPORTED_GROUPS: + newExt = new TLSSupportedGroupsExtension(curPos); + break; + case SSL_EXT_EC_POINT_FORMATS: + newExt = new TLSECPointFormatExtension(curPos); + break; + default: + newExt = new SSLExtension(curPos); + } + + // Total length can be zero only if getLength() == 0xfffc which is way too large + // and means that this extension (and packet) are malformed + if (newExt->getTotalLength() == 0) + { + delete newExt; + break; + } + + m_ExtensionList.pushBack(newExt); + curPos += newExt->getTotalLength(); + } } - return nullptr; -} - -SSLExtension* SSLClientHelloMessage::getExtensionOfType(SSLExtensionType type) const -{ - size_t vecSize = m_ExtensionList.size(); - for (size_t i = 0; i < vecSize; i++) + SSLVersion SSLClientHelloMessage::getHandshakeVersion() const { - SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); - if (curElem->getType() == type) - return curElem; + uint16_t handshakeVersion = be16toh(getClientHelloHeader()->handshakeVersion); + return SSLVersion(handshakeVersion); } - return nullptr; -} + uint8_t SSLClientHelloMessage::getSessionIDLength() const + { + if (m_DataLen <= sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t)) + return 0; -SSLClientHelloMessage::ClientHelloTLSFingerprint SSLClientHelloMessage::generateTLSFingerprint() const -{ - SSLClientHelloMessage::ClientHelloTLSFingerprint result; + uint8_t val = *(m_Data + sizeof(ssl_tls_client_server_hello)); + if ((size_t)val > m_DataLen - sizeof(ssl_tls_client_server_hello) - 1) + return (uint8_t)(m_DataLen - sizeof(ssl_tls_client_server_hello) - 1); - // extract version - result.tlsVersion = getHandshakeVersion().asUInt(); + return val; + } - // extract cipher suites - int cipherSuiteCount = getCipherSuiteCount(); - for (int i = 0; i < cipherSuiteCount; i++) + uint8_t* SSLClientHelloMessage::getSessionID() const { - bool isValid = false; - uint16_t cipherSuiteID = getCipherSuiteID(i, isValid); - if (isValid && GreaseSet.find(cipherSuiteID) == GreaseSet.end()) - result.cipherSuites.push_back(cipherSuiteID); + if (getSessionIDLength() > 0) + return (m_Data + sizeof(ssl_tls_client_server_hello) + 1); + else + return nullptr; } - // extract extensions - int extensionCount = getExtensionCount(); - for (int i = 0; i < extensionCount; i++) + int SSLClientHelloMessage::getCipherSuiteCount() const { - uint16_t extensionType = getExtension(i)->getTypeAsInt(); - if (GreaseSet.find(extensionType) != GreaseSet.end()) - continue; + size_t cipherSuiteOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength(); + if (cipherSuiteOffset + sizeof(uint16_t) > m_DataLen) + return 0; - result.extensions.push_back(extensionType); + uint16_t cipherSuiteLen = *(uint16_t*)(m_Data + cipherSuiteOffset); + return be16toh(cipherSuiteLen) / 2; } - // extract supported groups - TLSSupportedGroupsExtension* supportedGroupsExt = getExtensionOfType(); - if (supportedGroupsExt != nullptr) + SSLCipherSuite* SSLClientHelloMessage::getCipherSuite(int index) const { - std::vector supportedGroups = supportedGroupsExt->getSupportedGroups(); - for (const auto &iter : supportedGroups) - if (GreaseSet.find(iter) == GreaseSet.end()) - result.supportedGroups.push_back(iter); + bool isValid; + uint16_t id = getCipherSuiteID(index, isValid); + return (isValid ? SSLCipherSuite::getCipherSuiteByID(id) : nullptr); } - // extract EC point formats - TLSECPointFormatExtension* ecPointFormatExt = getExtensionOfType(); - if (ecPointFormatExt != nullptr) + uint16_t SSLClientHelloMessage::getCipherSuiteID(int index, bool& isValid) const { - result.ecPointFormats = ecPointFormatExt->getECPointFormatList(); - } - - return result; -} + if (index < 0 || index >= getCipherSuiteCount()) + { + isValid = false; + return 0; + } -std::string SSLClientHelloMessage::toString() const -{ - return "Client Hello message"; -} + size_t cipherSuiteStartOffset = + sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t); + if (cipherSuiteStartOffset + sizeof(uint16_t) * (index + 1) > m_DataLen) + { + isValid = false; + return 0; + } + isValid = true; + uint16_t* cipherSuiteStartPos = (uint16_t*)(m_Data + cipherSuiteStartOffset); + return be16toh(*(cipherSuiteStartPos + index)); + } -// ------------------------------------------------ -// SSLClientHelloMessage::ClientHelloTLSFingerprint -// ------------------------------------------------ + uint8_t SSLClientHelloMessage::getCompressionMethodsValue() const + { + size_t offset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + + sizeof(uint16_t) + sizeof(uint16_t) * getCipherSuiteCount() + sizeof(uint8_t); + if (offset + sizeof(uint8_t) > m_DataLen) + return 0xff; -std::string SSLClientHelloMessage::ClientHelloTLSFingerprint::toString() -{ - std::stringstream tlsFingerprint; + uint8_t* pos = m_Data + offset; + return *pos; + } - // add version - tlsFingerprint << tlsVersion << ","; + int SSLClientHelloMessage::getExtensionCount() const + { + return m_ExtensionList.size(); + } - // add cipher suites - bool firstCipher = true; - for (const auto &iter : cipherSuites) + uint16_t SSLClientHelloMessage::getExtensionsLength() const { - tlsFingerprint << (firstCipher ? "" : "-") << iter; - firstCipher = false; + size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + + sizeof(uint16_t) + sizeof(uint16_t) * getCipherSuiteCount() + + 2 * sizeof(uint8_t); + if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) + return 0; + + uint8_t* extensionLengthPos = m_Data + extensionLengthOffset; + return be16toh(*(uint16_t*)extensionLengthPos); } - tlsFingerprint << ","; - // add extensions - bool firstExtension = true; - for (const auto &iter : extensions) + SSLExtension* SSLClientHelloMessage::getExtension(int index) const { - tlsFingerprint << (firstExtension ? "" : "-") << iter; - firstExtension = false; + return const_cast(m_ExtensionList.at(index)); } - tlsFingerprint << ","; - // add supported groups - bool firstGroup = true; - for (const auto &iter : supportedGroups) + SSLExtension* SSLClientHelloMessage::getExtensionOfType(uint16_t type) const { - tlsFingerprint << (firstGroup ? "" : "-") << iter; - firstGroup = false; + size_t vecSize = m_ExtensionList.size(); + for (size_t i = 0; i < vecSize; i++) + { + SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); + if (curElem->getTypeAsInt() == type) + return curElem; + } + + return nullptr; } - tlsFingerprint << ","; - // add EC point formats - bool firstPointFormat = true; - for (auto iter : ecPointFormats) + SSLExtension* SSLClientHelloMessage::getExtensionOfType(SSLExtensionType type) const { - tlsFingerprint << (firstPointFormat ? "" : "-") << (int)iter; - firstPointFormat = false; + size_t vecSize = m_ExtensionList.size(); + for (size_t i = 0; i < vecSize; i++) + { + SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); + if (curElem->getType() == type) + return curElem; + } + + return nullptr; } - return tlsFingerprint.str(); -} + SSLClientHelloMessage::ClientHelloTLSFingerprint SSLClientHelloMessage::generateTLSFingerprint() const + { + SSLClientHelloMessage::ClientHelloTLSFingerprint result; -std::string SSLClientHelloMessage::ClientHelloTLSFingerprint::toMD5() -{ - return toStringAndMD5().second; -} + // extract version + result.tlsVersion = getHandshakeVersion().asUInt(); -std::pair SSLClientHelloMessage::ClientHelloTLSFingerprint::toStringAndMD5() -{ - std::string str = toString(); - MD5 md5; - return std::pair(str, md5(str)); -} + // extract cipher suites + int cipherSuiteCount = getCipherSuiteCount(); + for (int i = 0; i < cipherSuiteCount; i++) + { + bool isValid = false; + uint16_t cipherSuiteID = getCipherSuiteID(i, isValid); + if (isValid && GreaseSet.find(cipherSuiteID) == GreaseSet.end()) + result.cipherSuites.push_back(cipherSuiteID); + } + // extract extensions + int extensionCount = getExtensionCount(); + for (int i = 0; i < extensionCount; i++) + { + uint16_t extensionType = getExtension(i)->getTypeAsInt(); + if (GreaseSet.find(extensionType) != GreaseSet.end()) + continue; -// ----------------------------- -// SSLServerHelloMessage methods -// ----------------------------- + result.extensions.push_back(extensionType); + } -SSLServerHelloMessage::SSLServerHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) - : SSLHandshakeMessage(data, dataLen, container) -{ - size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t) + sizeof(uint8_t); - if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) - return; - - uint8_t* extensionLengthPos = m_Data + extensionLengthOffset; - uint16_t extensionLength = getExtensionsLength(); - uint8_t* extensionPos = extensionLengthPos + sizeof(uint16_t); - uint8_t* curPos = extensionPos; - size_t messageLen = getMessageLength(); - size_t minSSLExtensionLen = 2*sizeof(uint16_t); - while ((curPos - extensionPos) < (int)extensionLength - && (curPos - m_Data) < (int)messageLen - && (int)messageLen - (curPos - m_Data) >= (int)minSSLExtensionLen) - { - SSLExtension* newExt = nullptr; - uint16_t sslExtType = be16toh(*(uint16_t*)curPos); - switch (sslExtType) + // extract supported groups + TLSSupportedGroupsExtension* supportedGroupsExt = getExtensionOfType(); + if (supportedGroupsExt != nullptr) { - case SSL_EXT_SERVER_NAME: - newExt = new SSLServerNameIndicationExtension(curPos); - break; - case SSL_EXT_SUPPORTED_VERSIONS: - newExt = new SSLSupportedVersionsExtension(curPos); - break; - case SSL_EXT_SUPPORTED_GROUPS: - newExt = new TLSSupportedGroupsExtension(curPos); - break; - case SSL_EXT_EC_POINT_FORMATS: - newExt = new TLSECPointFormatExtension(curPos); - break; - default: - newExt = new SSLExtension(curPos); + std::vector supportedGroups = supportedGroupsExt->getSupportedGroups(); + for (const auto& iter : supportedGroups) + if (GreaseSet.find(iter) == GreaseSet.end()) + result.supportedGroups.push_back(iter); } - if (newExt->getTotalLength() == 0) + // extract EC point formats + TLSECPointFormatExtension* ecPointFormatExt = getExtensionOfType(); + if (ecPointFormatExt != nullptr) { - delete newExt; - break; + result.ecPointFormats = ecPointFormatExt->getECPointFormatList(); } - m_ExtensionList.pushBack(newExt); - curPos += newExt->getTotalLength(); + return result; } -} -SSLVersion SSLServerHelloMessage::getHandshakeVersion() const -{ - SSLSupportedVersionsExtension* supportedVersionsExt = getExtensionOfType(); - if (supportedVersionsExt != nullptr) + std::string SSLClientHelloMessage::toString() const { - std::vector supportedVersions = supportedVersionsExt->getSupportedVersions(); - if (supportedVersions.size() == 1) - return supportedVersions[0]; + return "Client Hello message"; } - uint16_t handshakeVersion = be16toh(getServerHelloHeader()->handshakeVersion); - return SSLVersion(handshakeVersion); + // ------------------------------------------------ + // SSLClientHelloMessage::ClientHelloTLSFingerprint + // ------------------------------------------------ -} -uint8_t SSLServerHelloMessage::getSessionIDLength() const -{ - if (m_DataLen <= sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t)) - return 0; + std::string SSLClientHelloMessage::ClientHelloTLSFingerprint::toString() + { + std::stringstream tlsFingerprint; - uint8_t val = *(m_Data + sizeof(ssl_tls_client_server_hello)); - if ((size_t)val > m_DataLen - sizeof(ssl_tls_client_server_hello) - 1) - return (uint8_t)(m_DataLen - sizeof(ssl_tls_client_server_hello) - 1); + // add version + tlsFingerprint << tlsVersion << ","; - return val; -} + // add cipher suites + bool firstCipher = true; + for (const auto& iter : cipherSuites) + { + tlsFingerprint << (firstCipher ? "" : "-") << iter; + firstCipher = false; + } + tlsFingerprint << ","; -uint8_t* SSLServerHelloMessage::getSessionID() const -{ - if (getSessionIDLength() > 0) - return (m_Data + sizeof(ssl_tls_client_server_hello) + 1); - else - return nullptr; -} + // add extensions + bool firstExtension = true; + for (const auto& iter : extensions) + { + tlsFingerprint << (firstExtension ? "" : "-") << iter; + firstExtension = false; + } + tlsFingerprint << ","; -SSLCipherSuite* SSLServerHelloMessage::getCipherSuite() const -{ - bool isValid; - uint16_t id = getCipherSuiteID(isValid); - return (isValid ? SSLCipherSuite::getCipherSuiteByID(id) : nullptr); -} + // add supported groups + bool firstGroup = true; + for (const auto& iter : supportedGroups) + { + tlsFingerprint << (firstGroup ? "" : "-") << iter; + firstGroup = false; + } + tlsFingerprint << ","; -uint16_t SSLServerHelloMessage::getCipherSuiteID(bool& isValid) const -{ - size_t cipherSuiteStartOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength(); - if (cipherSuiteStartOffset + sizeof(uint16_t) > m_DataLen) + // add EC point formats + bool firstPointFormat = true; + for (auto iter : ecPointFormats) + { + tlsFingerprint << (firstPointFormat ? "" : "-") << (int)iter; + firstPointFormat = false; + } + + return tlsFingerprint.str(); + } + + std::string SSLClientHelloMessage::ClientHelloTLSFingerprint::toMD5() { - isValid = false; - return 0; + return toStringAndMD5().second; } - isValid = true; - uint16_t* cipherSuiteStartPos = (uint16_t*)(m_Data + cipherSuiteStartOffset); - return be16toh(*(cipherSuiteStartPos)); -} + std::pair SSLClientHelloMessage::ClientHelloTLSFingerprint::toStringAndMD5() + { + std::string str = toString(); + MD5 md5; + return std::pair(str, md5(str)); + } -uint8_t SSLServerHelloMessage::getCompressionMethodsValue() const -{ - size_t offset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t); - if (offset + sizeof(uint8_t) > m_DataLen) - return 0xff; + // ----------------------------- + // SSLServerHelloMessage methods + // ----------------------------- - uint8_t* pos = m_Data + offset; - return *pos; -} + SSLServerHelloMessage::SSLServerHelloMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + { + size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + + sizeof(uint16_t) + sizeof(uint8_t); + if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) + return; + + uint8_t* extensionLengthPos = m_Data + extensionLengthOffset; + uint16_t extensionLength = getExtensionsLength(); + uint8_t* extensionPos = extensionLengthPos + sizeof(uint16_t); + uint8_t* curPos = extensionPos; + size_t messageLen = getMessageLength(); + size_t minSSLExtensionLen = 2 * sizeof(uint16_t); + while ((curPos - extensionPos) < (int)extensionLength && (curPos - m_Data) < (int)messageLen && + (int)messageLen - (curPos - m_Data) >= (int)minSSLExtensionLen) + { + SSLExtension* newExt = nullptr; + uint16_t sslExtType = be16toh(*(uint16_t*)curPos); + switch (sslExtType) + { + case SSL_EXT_SERVER_NAME: + newExt = new SSLServerNameIndicationExtension(curPos); + break; + case SSL_EXT_SUPPORTED_VERSIONS: + newExt = new SSLSupportedVersionsExtension(curPos); + break; + case SSL_EXT_SUPPORTED_GROUPS: + newExt = new TLSSupportedGroupsExtension(curPos); + break; + case SSL_EXT_EC_POINT_FORMATS: + newExt = new TLSECPointFormatExtension(curPos); + break; + default: + newExt = new SSLExtension(curPos); + } + + if (newExt->getTotalLength() == 0) + { + delete newExt; + break; + } + + m_ExtensionList.pushBack(newExt); + curPos += newExt->getTotalLength(); + } + } -int SSLServerHelloMessage::getExtensionCount() const -{ - return m_ExtensionList.size(); -} + SSLVersion SSLServerHelloMessage::getHandshakeVersion() const + { + SSLSupportedVersionsExtension* supportedVersionsExt = getExtensionOfType(); + if (supportedVersionsExt != nullptr) + { + std::vector supportedVersions = supportedVersionsExt->getSupportedVersions(); + if (supportedVersions.size() == 1) + return supportedVersions[0]; + } -uint16_t SSLServerHelloMessage::getExtensionsLength() const -{ - size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t) + sizeof(uint8_t); - if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) - return 0; + uint16_t handshakeVersion = be16toh(getServerHelloHeader()->handshakeVersion); + return SSLVersion(handshakeVersion); + } + uint8_t SSLServerHelloMessage::getSessionIDLength() const + { + if (m_DataLen <= sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t)) + return 0; - uint16_t* extensionLengthPos = (uint16_t*)(m_Data + extensionLengthOffset); - return be16toh(*extensionLengthPos); -} + uint8_t val = *(m_Data + sizeof(ssl_tls_client_server_hello)); + if ((size_t)val > m_DataLen - sizeof(ssl_tls_client_server_hello) - 1) + return (uint8_t)(m_DataLen - sizeof(ssl_tls_client_server_hello) - 1); -SSLExtension* SSLServerHelloMessage::getExtension(int index) const -{ - if (index < 0 || index >= (int)m_ExtensionList.size()) - return nullptr; - - return const_cast(m_ExtensionList.at(index)); -} + return val; + } -SSLExtension* SSLServerHelloMessage::getExtensionOfType(uint16_t type) const -{ - size_t vecSize = m_ExtensionList.size(); - for (size_t i = 0; i < vecSize; i++) + uint8_t* SSLServerHelloMessage::getSessionID() const { - SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); - if (curElem->getType() == type) - return curElem; + if (getSessionIDLength() > 0) + return (m_Data + sizeof(ssl_tls_client_server_hello) + 1); + else + return nullptr; } - return nullptr; -} - -SSLExtension* SSLServerHelloMessage::getExtensionOfType(SSLExtensionType type) const -{ - size_t vecSize = m_ExtensionList.size(); - for (size_t i = 0; i < vecSize; i++) + SSLCipherSuite* SSLServerHelloMessage::getCipherSuite() const { - SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); - if (curElem->getType() == type) - return curElem; + bool isValid; + uint16_t id = getCipherSuiteID(isValid); + return (isValid ? SSLCipherSuite::getCipherSuiteByID(id) : nullptr); } - return nullptr; -} + uint16_t SSLServerHelloMessage::getCipherSuiteID(bool& isValid) const + { + size_t cipherSuiteStartOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength(); + if (cipherSuiteStartOffset + sizeof(uint16_t) > m_DataLen) + { + isValid = false; + return 0; + } -SSLServerHelloMessage::ServerHelloTLSFingerprint SSLServerHelloMessage::generateTLSFingerprint() const -{ - SSLServerHelloMessage::ServerHelloTLSFingerprint result; + isValid = true; + uint16_t* cipherSuiteStartPos = (uint16_t*)(m_Data + cipherSuiteStartOffset); + return be16toh(*(cipherSuiteStartPos)); + } - // extract version - result.tlsVersion = getHandshakeVersion().asUInt(); + uint8_t SSLServerHelloMessage::getCompressionMethodsValue() const + { + size_t offset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + sizeof(uint16_t); + if (offset + sizeof(uint8_t) > m_DataLen) + return 0xff; - // extract cipher suite - bool isValid; - uint16_t cipherSuite = getCipherSuiteID(isValid); - result.cipherSuite = (isValid ? cipherSuite : 0); + uint8_t* pos = m_Data + offset; + return *pos; + } - // extract extensions - int extensionCount = getExtensionCount(); - for (int i = 0; i < extensionCount; i++) + int SSLServerHelloMessage::getExtensionCount() const { - uint16_t extensionType = getExtension(i)->getTypeAsInt(); - result.extensions.push_back(extensionType); + return m_ExtensionList.size(); } - return result; -} + uint16_t SSLServerHelloMessage::getExtensionsLength() const + { + size_t extensionLengthOffset = sizeof(ssl_tls_client_server_hello) + sizeof(uint8_t) + getSessionIDLength() + + sizeof(uint16_t) + sizeof(uint8_t); + if (extensionLengthOffset + sizeof(uint16_t) > m_DataLen) + return 0; -std::string SSLServerHelloMessage::toString() const -{ - return "Server Hello message"; -} + uint16_t* extensionLengthPos = (uint16_t*)(m_Data + extensionLengthOffset); + return be16toh(*extensionLengthPos); + } + SSLExtension* SSLServerHelloMessage::getExtension(int index) const + { + if (index < 0 || index >= (int)m_ExtensionList.size()) + return nullptr; -// ------------------------------------------------ -// SSLServerHelloMessage::ServerHelloTLSFingerprint -// ------------------------------------------------ + return const_cast(m_ExtensionList.at(index)); + } -std::string SSLServerHelloMessage::ServerHelloTLSFingerprint::toString() -{ - std::stringstream tlsFingerprint; + SSLExtension* SSLServerHelloMessage::getExtensionOfType(uint16_t type) const + { + size_t vecSize = m_ExtensionList.size(); + for (size_t i = 0; i < vecSize; i++) + { + SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); + if (curElem->getType() == type) + return curElem; + } - // add version and cipher suite - tlsFingerprint << tlsVersion << "," << cipherSuite << ","; + return nullptr; + } - // add extensions - bool firstExtension = true; - for (const auto &iter : extensions) + SSLExtension* SSLServerHelloMessage::getExtensionOfType(SSLExtensionType type) const { - tlsFingerprint << (firstExtension ? "" : "-") << iter; - firstExtension = false; - } + size_t vecSize = m_ExtensionList.size(); + for (size_t i = 0; i < vecSize; i++) + { + SSLExtension* curElem = const_cast(m_ExtensionList.at(i)); + if (curElem->getType() == type) + return curElem; + } - return tlsFingerprint.str(); -} + return nullptr; + } -std::string SSLServerHelloMessage::ServerHelloTLSFingerprint::toMD5() -{ - return toStringAndMD5().second; -} + SSLServerHelloMessage::ServerHelloTLSFingerprint SSLServerHelloMessage::generateTLSFingerprint() const + { + SSLServerHelloMessage::ServerHelloTLSFingerprint result; -std::pair SSLServerHelloMessage::ServerHelloTLSFingerprint::toStringAndMD5() -{ - std::string str = toString(); - MD5 md5; - return std::pair(str, md5(str)); -} + // extract version + result.tlsVersion = getHandshakeVersion().asUInt(); + // extract cipher suite + bool isValid; + uint16_t cipherSuite = getCipherSuiteID(isValid); + result.cipherSuite = (isValid ? cipherSuite : 0); -// ----------------------------- -// SSLCertificateMessage methods -// ----------------------------- + // extract extensions + int extensionCount = getExtensionCount(); + for (int i = 0; i < extensionCount; i++) + { + uint16_t extensionType = getExtension(i)->getTypeAsInt(); + result.extensions.push_back(extensionType); + } -SSLCertificateMessage::SSLCertificateMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) - : SSLHandshakeMessage(data, dataLen, container) -{ - if (dataLen < sizeof(ssl_tls_handshake_layer) + - sizeof(uint8_t)*3) // certificates length (3B) - return; + return result; + } - size_t messageLen = getMessageLength(); - // read certificates length - // TODO: certificates length is 3B. Currently assuming the MSB is 0 and reading only 2 LSBs - uint8_t* curPos = data + sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t); - uint16_t certificatesLength = be16toh(*(uint16_t*)(curPos)); - if (certificatesLength == 0) - return; + std::string SSLServerHelloMessage::toString() const + { + return "Server Hello message"; + } - // advance to position of first certificate - curPos += sizeof(uint16_t); + // ------------------------------------------------ + // SSLServerHelloMessage::ServerHelloTLSFingerprint + // ------------------------------------------------ - while (true) + std::string SSLServerHelloMessage::ServerHelloTLSFingerprint::toString() { - // try to read certificate length (3B) - // TODO: certificate length is 3B. Currently assuming the MSB is 0 and reading only 2 LSBs - if (curPos + 3*sizeof(uint8_t) - data > (int)messageLen) - break; - - // read certificate length - curPos += sizeof(uint8_t); - uint16_t certificateLength = be16toh(*(uint16_t*)(curPos)); + std::stringstream tlsFingerprint; - // advance to start position of certificate - curPos += sizeof(uint16_t); + // add version and cipher suite + tlsFingerprint << tlsVersion << "," << cipherSuite << ","; - // if packet doesn't contain the full certificate, read only what you got from current position till the - // end of the packet - bool certificateFull = true; - if (curPos - data + certificateLength > (int)messageLen) + // add extensions + bool firstExtension = true; + for (const auto& iter : extensions) { - certificateLength = messageLen - (curPos - data); - certificateFull = false; + tlsFingerprint << (firstExtension ? "" : "-") << iter; + firstExtension = false; } - PCPP_LOG_DEBUG("Parsing certificate: pos=" << (int)(curPos-data) << "; len=" << certificateLength); - SSLx509Certificate* newCert = new SSLx509Certificate(curPos, certificateLength, certificateFull); - m_CertificateList.pushBack(newCert); - - curPos += certificateLength; + return tlsFingerprint.str(); } -} - -std::string SSLCertificateMessage::toString() const -{ - return "Certificate message"; -} - -int SSLCertificateMessage::getNumOfCertificates() const -{ - return m_CertificateList.size(); -} -SSLx509Certificate* SSLCertificateMessage::getCertificate(int index) const -{ - if (index < 0 || index > (int)m_CertificateList.size()) + std::string SSLServerHelloMessage::ServerHelloTLSFingerprint::toMD5() { - PCPP_LOG_DEBUG("certificate index out of range: asked for index " << index << ", total size is " << m_CertificateList.size()); - return nullptr; + return toStringAndMD5().second; } - return const_cast(m_CertificateList.at(index)); -} - + std::pair SSLServerHelloMessage::ServerHelloTLSFingerprint::toStringAndMD5() + { + std::string str = toString(); + MD5 md5; + return std::pair(str, md5(str)); + } + // ----------------------------- + // SSLCertificateMessage methods + // ----------------------------- -// ------------------------------ -// SSLHelloRequestMessage methods -// ------------------------------ + SSLCertificateMessage::SSLCertificateMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) + { + if (dataLen < sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t) * 3) // certificates length (3B) + return; + + size_t messageLen = getMessageLength(); + // read certificates length + // TODO: certificates length is 3B. Currently assuming the MSB is 0 and reading only 2 LSBs + uint8_t* curPos = data + sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t); + uint16_t certificatesLength = be16toh(*(uint16_t*)(curPos)); + if (certificatesLength == 0) + return; + + // advance to position of first certificate + curPos += sizeof(uint16_t); -std::string SSLHelloRequestMessage::toString() const -{ - return "Hello Request message"; -} + while (true) + { + // try to read certificate length (3B) + // TODO: certificate length is 3B. Currently assuming the MSB is 0 and reading only 2 LSBs + if (curPos + 3 * sizeof(uint8_t) - data > (int)messageLen) + break; + + // read certificate length + curPos += sizeof(uint8_t); + uint16_t certificateLength = be16toh(*(uint16_t*)(curPos)); + + // advance to start position of certificate + curPos += sizeof(uint16_t); + + // if packet doesn't contain the full certificate, read only what you got from current position till the + // end of the packet + bool certificateFull = true; + if (curPos - data + certificateLength > (int)messageLen) + { + certificateLength = messageLen - (curPos - data); + certificateFull = false; + } + + PCPP_LOG_DEBUG("Parsing certificate: pos=" << (int)(curPos - data) << "; len=" << certificateLength); + SSLx509Certificate* newCert = new SSLx509Certificate(curPos, certificateLength, certificateFull); + m_CertificateList.pushBack(newCert); + + curPos += certificateLength; + } + } + std::string SSLCertificateMessage::toString() const + { + return "Certificate message"; + } -// --------------------------------- -// SSLServerHelloDoneMessage methods -// --------------------------------- + int SSLCertificateMessage::getNumOfCertificates() const + { + return m_CertificateList.size(); + } -std::string SSLServerHelloDoneMessage::toString() const -{ - return "Server Hello Done message"; -} + SSLx509Certificate* SSLCertificateMessage::getCertificate(int index) const + { + if (index < 0 || index > (int)m_CertificateList.size()) + { + PCPP_LOG_DEBUG("certificate index out of range: asked for index " << index << ", total size is " + << m_CertificateList.size()); + return nullptr; + } -// ----------------------------------- -// SSLServerKeyExchangeMessage methods -// ----------------------------------- + return const_cast(m_CertificateList.at(index)); + } -uint8_t* SSLServerKeyExchangeMessage::getServerKeyExchangeParams() const -{ - if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) - return (m_Data + sizeof(ssl_tls_handshake_layer)); + // ------------------------------ + // SSLHelloRequestMessage methods + // ------------------------------ - return nullptr; -} + std::string SSLHelloRequestMessage::toString() const + { + return "Hello Request message"; + } -size_t SSLServerKeyExchangeMessage::getServerKeyExchangeParamsLength() const -{ - size_t msgLength = getMessageLength(); - if (msgLength <= sizeof(ssl_tls_handshake_layer)) - return 0; + // --------------------------------- + // SSLServerHelloDoneMessage methods + // --------------------------------- - return msgLength - sizeof(ssl_tls_handshake_layer); -} + std::string SSLServerHelloDoneMessage::toString() const + { + return "Server Hello Done message"; + } -std::string SSLServerKeyExchangeMessage::toString() const -{ - return "Server Key Exchange message"; -} + // ----------------------------------- + // SSLServerKeyExchangeMessage methods + // ----------------------------------- -// ----------------------------------- -// SSLClientKeyExchangeMessage methods -// ----------------------------------- + uint8_t* SSLServerKeyExchangeMessage::getServerKeyExchangeParams() const + { + if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) + return (m_Data + sizeof(ssl_tls_handshake_layer)); -uint8_t* SSLClientKeyExchangeMessage::getClientKeyExchangeParams() const -{ - if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) - return (m_Data + sizeof(ssl_tls_handshake_layer)); + return nullptr; + } - return nullptr; -} + size_t SSLServerKeyExchangeMessage::getServerKeyExchangeParamsLength() const + { + size_t msgLength = getMessageLength(); + if (msgLength <= sizeof(ssl_tls_handshake_layer)) + return 0; -size_t SSLClientKeyExchangeMessage::getClientKeyExchangeParamsLength() const -{ - size_t msgLength = getMessageLength(); - if (msgLength <= sizeof(ssl_tls_handshake_layer)) - return 0; + return msgLength - sizeof(ssl_tls_handshake_layer); + } - return msgLength - sizeof(ssl_tls_handshake_layer); -} + std::string SSLServerKeyExchangeMessage::toString() const + { + return "Server Key Exchange message"; + } -std::string SSLClientKeyExchangeMessage::toString() const -{ - return "Client Key Exchange message"; -} + // ----------------------------------- + // SSLClientKeyExchangeMessage methods + // ----------------------------------- + uint8_t* SSLClientKeyExchangeMessage::getClientKeyExchangeParams() const + { + if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) + return (m_Data + sizeof(ssl_tls_handshake_layer)); -// ------------------------------------ -// SSLCertificateRequestMessage methods -// ------------------------------------ + return nullptr; + } -SSLCertificateRequestMessage::SSLCertificateRequestMessage(uint8_t* data, size_t dataLen, SSLHandshakeLayer* container) - : SSLHandshakeMessage(data, dataLen, container) -{ - size_t minMessageSize = sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t); // certificate types count (1B) - if (dataLen < minMessageSize) - return; + size_t SSLClientKeyExchangeMessage::getClientKeyExchangeParamsLength() const + { + size_t msgLength = getMessageLength(); + if (msgLength <= sizeof(ssl_tls_handshake_layer)) + return 0; - size_t messageLen = getMessageLength(); - if (messageLen < minMessageSize) - return; + return msgLength - sizeof(ssl_tls_handshake_layer); + } - uint8_t certificateTypesCount = *(uint8_t*)(data + sizeof(ssl_tls_handshake_layer)); + std::string SSLClientKeyExchangeMessage::toString() const + { + return "Client Key Exchange message"; + } - if (certificateTypesCount > messageLen - minMessageSize) - certificateTypesCount = messageLen - minMessageSize; + // ------------------------------------ + // SSLCertificateRequestMessage methods + // ------------------------------------ - uint8_t* pos = data + sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t); - for (uint8_t i = 0; i < certificateTypesCount; i++) + SSLCertificateRequestMessage::SSLCertificateRequestMessage(uint8_t* data, size_t dataLen, + SSLHandshakeLayer* container) + : SSLHandshakeMessage(data, dataLen, container) { - uint8_t certType = *(uint8_t*)(pos + i); - if (certType == 0 || - (certType > 6 && certType < 20) || - (certType > 20 && certType < 64) || - certType > 64) - m_ClientCertificateTypes.push_back(SSL_CCT_UNKNOWN); - else - m_ClientCertificateTypes.push_back(static_cast(certType)); - } -} + size_t minMessageSize = sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t); // certificate types count (1B) + if (dataLen < minMessageSize) + return; -std::vector& SSLCertificateRequestMessage::getCertificateTypes() -{ - return m_ClientCertificateTypes; -} + size_t messageLen = getMessageLength(); + if (messageLen < minMessageSize) + return; -uint8_t* SSLCertificateRequestMessage::getCertificateAuthorityData() const -{ - size_t messageLen = getMessageLength(); - size_t offset = sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t) + m_ClientCertificateTypes.size() + sizeof(uint16_t); - if (offset >= messageLen) - return nullptr; + uint8_t certificateTypesCount = *(uint8_t*)(data + sizeof(ssl_tls_handshake_layer)); - return m_Data + offset; -} + if (certificateTypesCount > messageLen - minMessageSize) + certificateTypesCount = messageLen - minMessageSize; -size_t SSLCertificateRequestMessage::getCertificateAuthorityLength() const -{ - size_t messageLen = getMessageLength(); - size_t offset = sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t) + m_ClientCertificateTypes.size(); - if (offset + sizeof(uint16_t) >= messageLen) - return 0; + uint8_t* pos = data + sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t); + for (uint8_t i = 0; i < certificateTypesCount; i++) + { + uint8_t certType = *(uint8_t*)(pos + i); + if (certType == 0 || (certType > 6 && certType < 20) || (certType > 20 && certType < 64) || certType > 64) + m_ClientCertificateTypes.push_back(SSL_CCT_UNKNOWN); + else + m_ClientCertificateTypes.push_back(static_cast(certType)); + } + } - uint16_t certAuthLen = be16toh(*(uint16_t*)(m_Data + offset)); + std::vector& SSLCertificateRequestMessage::getCertificateTypes() + { + return m_ClientCertificateTypes; + } - offset += sizeof(uint16_t); + uint8_t* SSLCertificateRequestMessage::getCertificateAuthorityData() const + { + size_t messageLen = getMessageLength(); + size_t offset = + sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t) + m_ClientCertificateTypes.size() + sizeof(uint16_t); + if (offset >= messageLen) + return nullptr; - if (messageLen - offset < certAuthLen) - return messageLen - offset; + return m_Data + offset; + } - return certAuthLen; -} + size_t SSLCertificateRequestMessage::getCertificateAuthorityLength() const + { + size_t messageLen = getMessageLength(); + size_t offset = sizeof(ssl_tls_handshake_layer) + sizeof(uint8_t) + m_ClientCertificateTypes.size(); + if (offset + sizeof(uint16_t) >= messageLen) + return 0; -std::string SSLCertificateRequestMessage::toString() const -{ - return "Certificate Request message"; -} + uint16_t certAuthLen = be16toh(*(uint16_t*)(m_Data + offset)); + offset += sizeof(uint16_t); -// ----------------------------------- -// SSLCertificateVerifyMessage methods -// ----------------------------------- + if (messageLen - offset < certAuthLen) + return messageLen - offset; -uint8_t* SSLCertificateVerifyMessage::getSignedHash() const -{ - if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) - return (m_Data + sizeof(ssl_tls_handshake_layer)); + return certAuthLen; + } - return nullptr; -} + std::string SSLCertificateRequestMessage::toString() const + { + return "Certificate Request message"; + } -size_t SSLCertificateVerifyMessage::getSignedHashLength() const -{ - size_t msgLength = getMessageLength(); - if (msgLength <= sizeof(ssl_tls_handshake_layer)) - return 0; + // ----------------------------------- + // SSLCertificateVerifyMessage methods + // ----------------------------------- - return msgLength - sizeof(ssl_tls_handshake_layer); -} + uint8_t* SSLCertificateVerifyMessage::getSignedHash() const + { + if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) + return (m_Data + sizeof(ssl_tls_handshake_layer)); -std::string SSLCertificateVerifyMessage::toString() const -{ - return "Certificate Verify message"; -} + return nullptr; + } -// -------------------------- -// SSLFinishedMessage methods -// -------------------------- + size_t SSLCertificateVerifyMessage::getSignedHashLength() const + { + size_t msgLength = getMessageLength(); + if (msgLength <= sizeof(ssl_tls_handshake_layer)) + return 0; -uint8_t* SSLFinishedMessage::getSignedHash() const -{ - if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) - return (m_Data + sizeof(ssl_tls_handshake_layer)); + return msgLength - sizeof(ssl_tls_handshake_layer); + } - return nullptr; -} + std::string SSLCertificateVerifyMessage::toString() const + { + return "Certificate Verify message"; + } -size_t SSLFinishedMessage::getSignedHashLength() const -{ - size_t msgLength = getMessageLength(); - if (msgLength <= sizeof(ssl_tls_handshake_layer)) - return 0; + // -------------------------- + // SSLFinishedMessage methods + // -------------------------- - return msgLength - sizeof(ssl_tls_handshake_layer); -} + uint8_t* SSLFinishedMessage::getSignedHash() const + { + if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) + return (m_Data + sizeof(ssl_tls_handshake_layer)); -std::string SSLFinishedMessage::toString() const -{ - return "Finished message"; -} + return nullptr; + } + size_t SSLFinishedMessage::getSignedHashLength() const + { + size_t msgLength = getMessageLength(); + if (msgLength <= sizeof(ssl_tls_handshake_layer)) + return 0; -// ---------------------------------- -// SSLNewSessionTicketMessage methods -// ---------------------------------- + return msgLength - sizeof(ssl_tls_handshake_layer); + } -uint8_t* SSLNewSessionTicketMessage::getSessionTicketData() const -{ - if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) - return (m_Data + sizeof(ssl_tls_handshake_layer)); + std::string SSLFinishedMessage::toString() const + { + return "Finished message"; + } - return nullptr; -} + // ---------------------------------- + // SSLNewSessionTicketMessage methods + // ---------------------------------- -size_t SSLNewSessionTicketMessage::getSessionTicketDataLength() const -{ - size_t msgLength = getMessageLength(); - if (msgLength <= sizeof(ssl_tls_handshake_layer)) - return 0; + uint8_t* SSLNewSessionTicketMessage::getSessionTicketData() const + { + if (getMessageLength() > sizeof(ssl_tls_handshake_layer)) + return (m_Data + sizeof(ssl_tls_handshake_layer)); - return msgLength - sizeof(ssl_tls_handshake_layer); -} + return nullptr; + } -std::string SSLNewSessionTicketMessage::toString() const -{ - return "New Session Ticket message"; -} + size_t SSLNewSessionTicketMessage::getSessionTicketDataLength() const + { + size_t msgLength = getMessageLength(); + if (msgLength <= sizeof(ssl_tls_handshake_layer)) + return 0; + return msgLength - sizeof(ssl_tls_handshake_layer); + } -// ------------------------- -// SSLUnknownMessage methods -// ------------------------- + std::string SSLNewSessionTicketMessage::toString() const + { + return "New Session Ticket message"; + } -SSLHandshakeType SSLUnknownMessage::getHandshakeType() const -{ - // if message type is unknown, it may be some encrypted message so message type isn't necessarily written - // in clear in the first byte. So always return SSL_HANDSHAKE_UNKNOWN - return SSL_HANDSHAKE_UNKNOWN; -} + // ------------------------- + // SSLUnknownMessage methods + // ------------------------- -size_t SSLUnknownMessage::getMessageLength() const -{ - // if message type is unknown, it may be some encrypted message so message length isn't necessarily written - // in clear. So in this case assume message is in length of all remaining data - return m_DataLen; -} + SSLHandshakeType SSLUnknownMessage::getHandshakeType() const + { + // if message type is unknown, it may be some encrypted message so message type isn't necessarily written + // in clear in the first byte. So always return SSL_HANDSHAKE_UNKNOWN + return SSL_HANDSHAKE_UNKNOWN; + } + size_t SSLUnknownMessage::getMessageLength() const + { + // if message type is unknown, it may be some encrypted message so message length isn't necessarily written + // in clear. So in this case assume message is in length of all remaining data + return m_DataLen; + } -std::string SSLUnknownMessage::toString() const -{ - return "Unknown message"; -} + std::string SSLUnknownMessage::toString() const + { + return "Unknown message"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SSLLayer.cpp b/Packet++/src/SSLLayer.cpp index 422d0938e2..3025bdd582 100644 --- a/Packet++/src/SSLLayer.cpp +++ b/Packet++/src/SSLLayer.cpp @@ -5,49 +5,46 @@ #include "EndianPortable.h" #include - namespace pcpp { -// ---------------- -// SSLLayer methods -// ---------------- + // ---------------- + // SSLLayer methods + // ---------------- -bool SSLLayer::IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, bool ignorePorts) -{ - // check the port map first - if (!ignorePorts && !isSSLPort(srcPort) && !isSSLPort(dstPort)) - return false; + bool SSLLayer::IsSSLMessage(uint16_t srcPort, uint16_t dstPort, uint8_t* data, size_t dataLen, bool ignorePorts) + { + // check the port map first + if (!ignorePorts && !isSSLPort(srcPort) && !isSSLPort(dstPort)) + return false; - if (dataLen < sizeof(ssl_tls_record_layer)) - return false; + if (dataLen < sizeof(ssl_tls_record_layer)) + return false; - ssl_tls_record_layer* recordLayer = (ssl_tls_record_layer*)data; + ssl_tls_record_layer* recordLayer = (ssl_tls_record_layer*)data; - // there is no SSL message with length 0 - if (recordLayer->length == 0) - return false; + // there is no SSL message with length 0 + if (recordLayer->length == 0) + return false; - if (recordLayer->recordType < 20 || recordLayer->recordType > 23) - return false; + if (recordLayer->recordType < 20 || recordLayer->recordType > 23) + return false; - SSLVersion::SSLVersionEnum recordVersion = SSLVersion(be16toh(recordLayer->recordVersion)).asEnum(true); + SSLVersion::SSLVersionEnum recordVersion = SSLVersion(be16toh(recordLayer->recordVersion)).asEnum(true); - if (recordVersion == SSLVersion::TLS1_3 || - recordVersion == SSLVersion::TLS1_2 || - recordVersion == SSLVersion::TLS1_1 || - recordVersion == SSLVersion::TLS1_0 || - recordVersion == SSLVersion::SSL3) - return true; - else - return false; -} + if (recordVersion == SSLVersion::TLS1_3 || recordVersion == SSLVersion::TLS1_2 || + recordVersion == SSLVersion::TLS1_1 || recordVersion == SSLVersion::TLS1_0 || + recordVersion == SSLVersion::SSL3) + return true; + else + return false; + } -SSLLayer* SSLLayer::createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - ssl_tls_record_layer* recordLayer = (ssl_tls_record_layer*)data; - switch (recordLayer->recordType) + SSLLayer* SSLLayer::createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) { + ssl_tls_record_layer* recordLayer = (ssl_tls_record_layer*)data; + switch (recordLayer->recordType) + { case SSL_HANDSHAKE: { return new SSLHandshakeLayer(data, dataLen, prevLayer, packet); @@ -70,189 +67,188 @@ SSLLayer* SSLLayer::createSSLMessage(uint8_t* data, size_t dataLen, Layer* prevL default: return nullptr; + } } -} -SSLVersion SSLLayer::getRecordVersion() const -{ - uint16_t recordVersion = be16toh(getRecordLayer()->recordVersion); - return SSLVersion(recordVersion); -} - -SSLRecordType SSLLayer::getRecordType() const -{ - return (SSLRecordType)(getRecordLayer()->recordType); -} + SSLVersion SSLLayer::getRecordVersion() const + { + uint16_t recordVersion = be16toh(getRecordLayer()->recordVersion); + return SSLVersion(recordVersion); + } -size_t SSLLayer::getHeaderLen() const -{ - size_t len = sizeof(ssl_tls_record_layer) + be16toh(getRecordLayer()->length); - if (len > m_DataLen) - return m_DataLen; - return len; -} + SSLRecordType SSLLayer::getRecordType() const + { + return (SSLRecordType)(getRecordLayer()->recordType); + } -void SSLLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; + size_t SSLLayer::getHeaderLen() const + { + size_t len = sizeof(ssl_tls_record_layer) + be16toh(getRecordLayer()->length); + if (len > m_DataLen) + return m_DataLen; + return len; + } - if (SSLLayer::IsSSLMessage(0, 0, m_Data + headerLen, m_DataLen - headerLen, true)) - m_NextLayer = SSLLayer::createSSLMessage(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); -} + void SSLLayer::parseNextLayer() + { + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + if (SSLLayer::IsSSLMessage(0, 0, m_Data + headerLen, m_DataLen - headerLen, true)) + m_NextLayer = SSLLayer::createSSLMessage(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + } -// ------------------------- -// SSLHandshakeLayer methods -// ------------------------- + // ------------------------- + // SSLHandshakeLayer methods + // ------------------------- -std::string SSLHandshakeLayer::toString() const -{ - std::stringstream result; - result << getRecordVersion().toString(true) << " Layer, Handshake:"; - for(size_t i = 0; i < m_MessageList.size(); i++) + std::string SSLHandshakeLayer::toString() const { - if (i == 0) - result << " " << m_MessageList.at(i)->toString(); - else - result << ", " << m_MessageList.at(i)->toString(); + std::stringstream result; + result << getRecordVersion().toString(true) << " Layer, Handshake:"; + for (size_t i = 0; i < m_MessageList.size(); i++) + { + if (i == 0) + result << " " << m_MessageList.at(i)->toString(); + else + result << ", " << m_MessageList.at(i)->toString(); + } + return result.str(); } - return result.str(); -} - -SSLHandshakeLayer::SSLHandshakeLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) - : SSLLayer(data, dataLen, prevLayer, packet) -{ - uint8_t* curPos = m_Data + sizeof(ssl_tls_record_layer); - size_t recordDataLen = be16toh(getRecordLayer()->length); - if (recordDataLen > m_DataLen - sizeof(ssl_tls_record_layer)) - recordDataLen = m_DataLen - sizeof(ssl_tls_record_layer); - size_t curPosIndex = 0; - while (true) + SSLHandshakeLayer::SSLHandshakeLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SSLLayer(data, dataLen, prevLayer, packet) { - SSLHandshakeMessage* message = SSLHandshakeMessage::createHandshakeMessage(curPos, recordDataLen-curPosIndex, this); - if (message == nullptr) - break; + uint8_t* curPos = m_Data + sizeof(ssl_tls_record_layer); + size_t recordDataLen = be16toh(getRecordLayer()->length); + if (recordDataLen > m_DataLen - sizeof(ssl_tls_record_layer)) + recordDataLen = m_DataLen - sizeof(ssl_tls_record_layer); - m_MessageList.pushBack(message); - curPos += message->getMessageLength(); - curPosIndex += message->getMessageLength(); + size_t curPosIndex = 0; + while (true) + { + SSLHandshakeMessage* message = + SSLHandshakeMessage::createHandshakeMessage(curPos, recordDataLen - curPosIndex, this); + if (message == nullptr) + break; + + m_MessageList.pushBack(message); + curPos += message->getMessageLength(); + curPosIndex += message->getMessageLength(); + } } -} -SSLHandshakeMessage* SSLHandshakeLayer::getHandshakeMessageAt(int index) const -{ - if (index < 0 || index >= (int)(m_MessageList.size())) - return nullptr; + SSLHandshakeMessage* SSLHandshakeLayer::getHandshakeMessageAt(int index) const + { + if (index < 0 || index >= (int)(m_MessageList.size())) + return nullptr; - return const_cast(m_MessageList.at(index)); -} + return const_cast(m_MessageList.at(index)); + } + // -------------------------------- + // SSLChangeCipherSpecLayer methods + // -------------------------------- -// -------------------------------- -// SSLChangeCipherSpecLayer methods -// -------------------------------- + std::string SSLChangeCipherSpecLayer::toString() const + { + std::stringstream result; + result << getRecordVersion().toString(true) << " Layer, Change Cipher Spec"; + return result.str(); + } -std::string SSLChangeCipherSpecLayer::toString() const -{ - std::stringstream result; - result << getRecordVersion().toString(true) << " Layer, Change Cipher Spec"; - return result.str(); -} + // --------------------- + // SSLAlertLayer methods + // --------------------- -// --------------------- -// SSLAlertLayer methods -// --------------------- + SSLAlertLevel SSLAlertLayer::getAlertLevel() const + { + uint8_t* pos = m_Data + sizeof(ssl_tls_record_layer); + uint8_t alertLevel = *pos; + if (alertLevel == SSL_ALERT_LEVEL_WARNING || alertLevel == SSL_ALERT_LEVEL_FATAL) + return (SSLAlertLevel)alertLevel; + else + return SSL_ALERT_LEVEL_ENCRYPTED; + } -SSLAlertLevel SSLAlertLayer::getAlertLevel() const -{ - uint8_t* pos = m_Data + sizeof(ssl_tls_record_layer); - uint8_t alertLevel = *pos; - if (alertLevel == SSL_ALERT_LEVEL_WARNING || alertLevel == SSL_ALERT_LEVEL_FATAL) - return (SSLAlertLevel)alertLevel; - else - return SSL_ALERT_LEVEL_ENCRYPTED; -} - -SSLAlertDescription SSLAlertLayer::getAlertDescription() -{ - if (getAlertLevel() == SSL_ALERT_LEVEL_ENCRYPTED) - return SSL_ALERT_ENCRYPTED; + SSLAlertDescription SSLAlertLayer::getAlertDescription() + { + if (getAlertLevel() == SSL_ALERT_LEVEL_ENCRYPTED) + return SSL_ALERT_ENCRYPTED; - uint8_t* pos = m_Data + sizeof(ssl_tls_record_layer) + sizeof(uint8_t); - uint8_t alertDesc = *pos; + uint8_t* pos = m_Data + sizeof(ssl_tls_record_layer) + sizeof(uint8_t); + uint8_t alertDesc = *pos; - switch (alertDesc) + switch (alertDesc) + { + case SSL_ALERT_CLOSE_NOTIFY: + case SSL_ALERT_UNEXPECTED_MESSAGE: + case SSL_ALERT_BAD_RECORD_MAC: + case SSL_ALERT_DECRYPTION_FAILED: + case SSL_ALERT_RECORD_OVERFLOW: + case SSL_ALERT_DECOMPRESSION_FAILURE: + case SSL_ALERT_HANDSHAKE_FAILURE: + case SSL_ALERT_NO_CERTIFICATE: + case SSL_ALERT_BAD_CERTIFICATE: + case SSL_ALERT_UNSUPPORTED_CERTIFICATE: + case SSL_ALERT_CERTIFICATE_REVOKED: + case SSL_ALERT_CERTIFICATE_EXPIRED: + case SSL_ALERT_CERTIFICATE_UNKNOWN: + case SSL_ALERT_ILLEGAL_PARAMETER: + case SSL_ALERT_UNKNOWN_CA: + case SSL_ALERT_ACCESS_DENIED: + case SSL_ALERT_DECODE_ERROR: + case SSL_ALERT_DECRYPT_ERROR: + case SSL_ALERT_EXPORT_RESTRICTION: + case SSL_ALERT_PROTOCOL_VERSION: + case SSL_ALERT_INSUFFICIENT_SECURITY: + case SSL_ALERT_INTERNAL_ERROR: + case SSL_ALERT_USER_CANCELLED: + case SSL_ALERT_NO_RENEGOTIATION: + return (SSLAlertDescription)alertDesc; + break; + default: + return SSL_ALERT_ENCRYPTED; + } + } + + std::string SSLAlertLayer::toString() const { - case SSL_ALERT_CLOSE_NOTIFY: - case SSL_ALERT_UNEXPECTED_MESSAGE: - case SSL_ALERT_BAD_RECORD_MAC: - case SSL_ALERT_DECRYPTION_FAILED: - case SSL_ALERT_RECORD_OVERFLOW: - case SSL_ALERT_DECOMPRESSION_FAILURE: - case SSL_ALERT_HANDSHAKE_FAILURE: - case SSL_ALERT_NO_CERTIFICATE: - case SSL_ALERT_BAD_CERTIFICATE: - case SSL_ALERT_UNSUPPORTED_CERTIFICATE: - case SSL_ALERT_CERTIFICATE_REVOKED: - case SSL_ALERT_CERTIFICATE_EXPIRED: - case SSL_ALERT_CERTIFICATE_UNKNOWN: - case SSL_ALERT_ILLEGAL_PARAMETER: - case SSL_ALERT_UNKNOWN_CA: - case SSL_ALERT_ACCESS_DENIED: - case SSL_ALERT_DECODE_ERROR: - case SSL_ALERT_DECRYPT_ERROR: - case SSL_ALERT_EXPORT_RESTRICTION: - case SSL_ALERT_PROTOCOL_VERSION: - case SSL_ALERT_INSUFFICIENT_SECURITY: - case SSL_ALERT_INTERNAL_ERROR: - case SSL_ALERT_USER_CANCELLED: - case SSL_ALERT_NO_RENEGOTIATION: - return (SSLAlertDescription)alertDesc; - break; - default: - return SSL_ALERT_ENCRYPTED; + std::stringstream result; + result << getRecordVersion().toString(true) << " Layer, "; + if (getAlertLevel() == SSL_ALERT_LEVEL_ENCRYPTED) + result << "Encrypted Alert"; + else + // TODO: add alert level and description here + result << "Alert"; + return result.str(); } -} -std::string SSLAlertLayer::toString() const -{ - std::stringstream result; - result << getRecordVersion().toString(true) << " Layer, "; - if (getAlertLevel() == SSL_ALERT_LEVEL_ENCRYPTED) - result << "Encrypted Alert"; - else - //TODO: add alert level and description here - result << "Alert"; - return result.str(); -} - -// ------------------------------- -// SSLApplicationDataLayer methods -// ------------------------------- - -uint8_t* SSLApplicationDataLayer::getEncryptedData() const -{ - if (getHeaderLen() <= sizeof(ssl_tls_record_layer)) - return nullptr; + // ------------------------------- + // SSLApplicationDataLayer methods + // ------------------------------- - return m_Data + sizeof(ssl_tls_record_layer); -} + uint8_t* SSLApplicationDataLayer::getEncryptedData() const + { + if (getHeaderLen() <= sizeof(ssl_tls_record_layer)) + return nullptr; -size_t SSLApplicationDataLayer::getEncryptedDataLen() const -{ - int result = (int)getHeaderLen() - (int)sizeof(ssl_tls_record_layer); - if (result < 0) - return 0; + return m_Data + sizeof(ssl_tls_record_layer); + } - return (size_t)result; -} + size_t SSLApplicationDataLayer::getEncryptedDataLen() const + { + int result = (int)getHeaderLen() - (int)sizeof(ssl_tls_record_layer); + if (result < 0) + return 0; -std::string SSLApplicationDataLayer::toString() const -{ - return getRecordVersion().toString(true) + " Layer, Application Data"; -} + return (size_t)result; + } + + std::string SSLApplicationDataLayer::toString() const + { + return getRecordVersion().toString(true) + " Layer, Application Data"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SdpLayer.cpp b/Packet++/src/SdpLayer.cpp index 97ac0273d6..240fd75e73 100644 --- a/Packet++/src/SdpLayer.cpp +++ b/Packet++/src/SdpLayer.cpp @@ -1,6 +1,5 @@ #define LOG_MODULE PacketLogModuleSdpLayer - #include "SdpLayer.h" #include "Logger.h" #include @@ -10,134 +9,136 @@ namespace pcpp { -std::vector splitByWhiteSpaces(const std::string& str) -{ - std::string buf; - std::stringstream stream(str); - std::vector result; - while (stream >> buf) - result.push_back(buf); - - return result; -} - - -SdpLayer::SdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) -{ - m_Protocol = SDP; - m_FieldsOffset = 0; - parseFields(); -} - -SdpLayer::SdpLayer() -{ - m_Protocol = SDP; - m_FieldsOffset = 0; -} - -SdpLayer::SdpLayer(const std::string& username, long sessionID, long sessionVersion, IPv4Address ipAddress, const std::string& sessionName, long startTime, long stopTime) -{ - m_Protocol = SDP; - m_FieldsOffset = 0; - - // must initialize m_Data otherwise addField() will fail while trying to extend the layer - // initializing in length of 1 but keeping m_DataLen with value of 0. - // when extending the field m_Data is purged so there isn't a memory leak here - m_Data = new uint8_t[1]; - m_DataLen = 0; - - addField(PCPP_SDP_PROTOCOL_VERSION_FIELD, "0"); - - std::stringstream sessionIDStream; - sessionIDStream << sessionID; - std::stringstream sessionVersionStream; - sessionVersionStream << sessionVersion; - std::string networkInfo = "IN IP4 " + ipAddress.toString(); - std::string originatorFieldValue = username + " " + sessionIDStream.str() + " " + sessionVersionStream.str() + " " + networkInfo; - addField(PCPP_SDP_ORIGINATOR_FIELD, originatorFieldValue); - - addField(PCPP_SDP_SESSION_NAME_FIELD, sessionName); - - addField(PCPP_SDP_CONNECTION_INFO_FIELD, networkInfo); - - std::stringstream startTimeStream; - startTimeStream << startTime; - std::stringstream stopTimeStream; - stopTimeStream << stopTime; - addField(PCPP_SDP_TIME_FIELD, startTimeStream.str() + " " + stopTimeStream.str()); -} - -std::string SdpLayer::toString() const -{ - return "SDP Layer"; -} - -IPv4Address SdpLayer::getOwnerIPv4Address() const -{ - HeaderField* originator = getFieldByName(PCPP_SDP_ORIGINATOR_FIELD); - if (originator == nullptr) - return IPv4Address::Zero; + std::vector splitByWhiteSpaces(const std::string& str) + { + std::string buf; + std::stringstream stream(str); + std::vector result; + while (stream >> buf) + result.push_back(buf); - std::vector tokens = splitByWhiteSpaces(originator->getFieldValue()); - if (tokens.size() < 6) - return IPv4Address::Zero; + return result; + } - if (tokens[3] != "IN" || tokens[4] != "IP4") - return IPv4Address::Zero; + SdpLayer::SdpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : TextBasedProtocolMessage(data, dataLen, prevLayer, packet) + { + m_Protocol = SDP; + m_FieldsOffset = 0; + parseFields(); + } - try + SdpLayer::SdpLayer() { - return IPv4Address(tokens[5]); + m_Protocol = SDP; + m_FieldsOffset = 0; } - catch (const std::exception&) + + SdpLayer::SdpLayer(const std::string& username, long sessionID, long sessionVersion, IPv4Address ipAddress, + const std::string& sessionName, long startTime, long stopTime) { - return IPv4Address::Zero; + m_Protocol = SDP; + m_FieldsOffset = 0; + + // must initialize m_Data otherwise addField() will fail while trying to extend the layer + // initializing in length of 1 but keeping m_DataLen with value of 0. + // when extending the field m_Data is purged so there isn't a memory leak here + m_Data = new uint8_t[1]; + m_DataLen = 0; + + addField(PCPP_SDP_PROTOCOL_VERSION_FIELD, "0"); + + std::stringstream sessionIDStream; + sessionIDStream << sessionID; + std::stringstream sessionVersionStream; + sessionVersionStream << sessionVersion; + std::string networkInfo = "IN IP4 " + ipAddress.toString(); + std::string originatorFieldValue = + username + " " + sessionIDStream.str() + " " + sessionVersionStream.str() + " " + networkInfo; + addField(PCPP_SDP_ORIGINATOR_FIELD, originatorFieldValue); + + addField(PCPP_SDP_SESSION_NAME_FIELD, sessionName); + + addField(PCPP_SDP_CONNECTION_INFO_FIELD, networkInfo); + + std::stringstream startTimeStream; + startTimeStream << startTime; + std::stringstream stopTimeStream; + stopTimeStream << stopTime; + addField(PCPP_SDP_TIME_FIELD, startTimeStream.str() + " " + stopTimeStream.str()); } -} -uint16_t SdpLayer::getMediaPort(const std::string& mediaType) const -{ - int mediaFieldIndex = 0; - HeaderField* mediaDesc = getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldIndex); + std::string SdpLayer::toString() const + { + return "SDP Layer"; + } - while (mediaDesc != nullptr) + IPv4Address SdpLayer::getOwnerIPv4Address() const { - std::vector tokens = splitByWhiteSpaces(mediaDesc->getFieldValue()); + HeaderField* originator = getFieldByName(PCPP_SDP_ORIGINATOR_FIELD); + if (originator == nullptr) + return IPv4Address::Zero; + + std::vector tokens = splitByWhiteSpaces(originator->getFieldValue()); + if (tokens.size() < 6) + return IPv4Address::Zero; - if (tokens.size() >= 2 && tokens[0] == mediaType) - return atoi(tokens[1].c_str()); + if (tokens[3] != "IN" || tokens[4] != "IP4") + return IPv4Address::Zero; - mediaFieldIndex++; - mediaDesc = getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldIndex); + try + { + return IPv4Address(tokens[5]); + } + catch (const std::exception&) + { + return IPv4Address::Zero; + } } - return 0; -} + uint16_t SdpLayer::getMediaPort(const std::string& mediaType) const + { + int mediaFieldIndex = 0; + HeaderField* mediaDesc = getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldIndex); -bool SdpLayer::addMediaDescription(const std::string& mediaType, uint16_t mediaPort, const std::string& mediaProtocol, const std::string& mediaFormat, const std::vector &mediaAttributes) -{ - std::stringstream portStream; - portStream << mediaPort; + while (mediaDesc != nullptr) + { + std::vector tokens = splitByWhiteSpaces(mediaDesc->getFieldValue()); - std::string mediaFieldValue = mediaType + " " + portStream.str() + " " + mediaProtocol + " " + mediaFormat; - if (addField(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldValue) == nullptr) - { - PCPP_LOG_ERROR("Failed to add media description field"); - return false; - } + if (tokens.size() >= 2 && tokens[0] == mediaType) + return atoi(tokens[1].c_str()); + mediaFieldIndex++; + mediaDesc = getFieldByName(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldIndex); + } + + return 0; + } - for (const auto &iter : mediaAttributes) + bool SdpLayer::addMediaDescription(const std::string& mediaType, uint16_t mediaPort, + const std::string& mediaProtocol, const std::string& mediaFormat, + const std::vector& mediaAttributes) { - if (addField(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, iter) == nullptr) + std::stringstream portStream; + portStream << mediaPort; + + std::string mediaFieldValue = mediaType + " " + portStream.str() + " " + mediaProtocol + " " + mediaFormat; + if (addField(PCPP_SDP_MEDIA_NAME_FIELD, mediaFieldValue) == nullptr) { - PCPP_LOG_ERROR("Failed to add media attribute '" << iter << "'"); + PCPP_LOG_ERROR("Failed to add media description field"); return false; } - } - return true; -} + for (const auto& iter : mediaAttributes) + { + if (addField(PCPP_SDP_MEDIA_ATTRIBUTE_FIELD, iter) == nullptr) + { + PCPP_LOG_ERROR("Failed to add media attribute '" << iter << "'"); + return false; + } + } + return true; + } -} +} // namespace pcpp diff --git a/Packet++/src/SingleCommandTextProtocol.cpp b/Packet++/src/SingleCommandTextProtocol.cpp index 75ee9089c9..7d6ee5c7d0 100644 --- a/Packet++/src/SingleCommandTextProtocol.cpp +++ b/Packet++/src/SingleCommandTextProtocol.cpp @@ -7,8 +7,8 @@ #define ASCII_HYPHEN 0x2d #define ASCII_SPACE 0x20 -#define MAX_COMMAND_LENGTH 9 // From SMTP command "STARTTLS" + 1 byte hyphen or space -#define MIN_PACKET_LENGTH 2 // CRLF +#define MAX_COMMAND_LENGTH 9 // From SMTP command "STARTTLS" + 1 byte hyphen or space +#define MIN_PACKET_LENGTH 2 // CRLF namespace pcpp { @@ -25,7 +25,7 @@ namespace pcpp // the first MAX_CONTENT_LENGTH bytes, search the both of hyphen and space to take // correct command delimiter - std::string field(reinterpret_cast(m_Data), maxLen); + std::string field(reinterpret_cast(m_Data), maxLen); size_t posHyphen = field.find_first_of(ASCII_HYPHEN); size_t posSpace = field.find_first_of(ASCII_SPACE); @@ -52,14 +52,14 @@ namespace pcpp memset(&m_Data[getArgumentFieldOffset()], ASCII_SPACE, 1); } - bool SingleCommandTextProtocol::hyphenRequired(const std::string &value) + bool SingleCommandTextProtocol::hyphenRequired(const std::string& value) { size_t firstPos = value.find("\r\n"); size_t lastPos = value.rfind("\r\n"); return (firstPos != std::string::npos) && (lastPos != std::string::npos) && (firstPos != lastPos); } - SingleCommandTextProtocol::SingleCommandTextProtocol(const std::string &command, const std::string &option) + SingleCommandTextProtocol::SingleCommandTextProtocol(const std::string& command, const std::string& option) { m_Data = new uint8_t[MIN_PACKET_LENGTH]; m_DataLen = MIN_PACKET_LENGTH; @@ -126,8 +126,8 @@ namespace pcpp // If there is no option remove trailing newline characters if (offset == (m_DataLen - 1) && offset > 1) - return std::string((char *)m_Data, offset - 1); - return std::string((char *)m_Data, offset); + return std::string((char*)m_Data, offset - 1); + return std::string((char*)m_Data, offset); } std::string SingleCommandTextProtocol::getCommandOptionInternal() const @@ -139,14 +139,14 @@ namespace pcpp int addition = offset ? 1 : 0; if (offset != (m_DataLen - 1)) { - auto option = std::string((char *)&m_Data[offset + addition], m_DataLen - (offset + 2 + addition)); + auto option = std::string((char*)&m_Data[offset + addition], m_DataLen - (offset + 2 + addition)); // Remove XXX- and XXX since they are delimiters of the protocol where XXX is the usually status code // Check RFC821 (SMTP) Section 3.3 and RFC959 (FTP) Section 4.2 auto code = getCommandInternal(); - auto vDelim = std::vector {code + " ", code + "-"}; + auto vDelim = std::vector{ code + " ", code + "-" }; - for (const auto &delim : vDelim) + for (const auto& delim : vDelim) { size_t pos = 0; while ((pos = option.find(delim, pos)) != std::string::npos) @@ -159,15 +159,18 @@ namespace pcpp return ""; } - bool SingleCommandTextProtocol::isMultiLine() const { return m_Data[getArgumentFieldOffset()] == ASCII_HYPHEN; } + bool SingleCommandTextProtocol::isMultiLine() const + { + return m_Data[getArgumentFieldOffset()] == ASCII_HYPHEN; + } - bool SingleCommandTextProtocol::isDataValid(const uint8_t *data, size_t dataSize) + bool SingleCommandTextProtocol::isDataValid(const uint8_t* data, size_t dataSize) { if (data == nullptr || dataSize < MIN_PACKET_LENGTH) return false; - std::string payload = std::string((char *)data, dataSize); + std::string payload = std::string((char*)data, dataSize); return payload.rfind("\r\n") == dataSize - 2; } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SipLayer.cpp b/Packet++/src/SipLayer.cpp index daa5e8cde3..d560323975 100644 --- a/Packet++/src/SipLayer.cpp +++ b/Packet++/src/SipLayer.cpp @@ -15,963 +15,852 @@ namespace pcpp { -const std::string SipMethodEnumToString[14] = { - "INVITE", - "ACK", - "BYE", - "CANCEL", - "REGISTER", - "PRACK", - "OPTIONS", - "SUBSCRIBE", - "NOTIFY", - "PUBLISH", - "INFO", - "REFER", - "MESSAGE", - "UPDATE" -}; - -const std::unordered_map SipMethodStringToEnum { - {"INVITE", SipRequestLayer::SipMethod::SipINVITE }, - {"ACK", SipRequestLayer::SipMethod::SipACK }, - {"BYE", SipRequestLayer::SipMethod::SipBYE }, - {"CANCEL", SipRequestLayer::SipMethod::SipCANCEL }, - {"REGISTER", SipRequestLayer::SipMethod::SipREGISTER }, - {"PRACK", SipRequestLayer::SipMethod::SipPRACK }, - {"OPTIONS", SipRequestLayer::SipMethod::SipOPTIONS }, - {"SUBSCRIBE", SipRequestLayer::SipMethod::SipSUBSCRIBE }, - {"NOTIFY", SipRequestLayer::SipMethod::SipNOTIFY }, - {"PUBLISH", SipRequestLayer::SipMethod::SipPUBLISH }, - {"INFO", SipRequestLayer::SipMethod::SipINFO }, - {"REFER", SipRequestLayer::SipMethod::SipREFER }, - {"MESSAGE", SipRequestLayer::SipMethod::SipMESSAGE }, - {"UPDATE", SipRequestLayer::SipMethod::SipUPDATE }, -}; - - - - -// -------- Class SipLayer ----------------- - -int SipLayer::getContentLength() const -{ - std::string contentLengthFieldName(PCPP_SIP_CONTENT_LENGTH_FIELD); - std::transform(contentLengthFieldName.begin(), contentLengthFieldName.end(), contentLengthFieldName.begin(), ::tolower); - HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); - if (contentLengthField != nullptr) - return atoi(contentLengthField->getFieldValue().c_str()); - return 0; -} - -HeaderField* SipLayer::setContentLength(int contentLength, const std::string &prevFieldName) -{ - std::ostringstream contentLengthAsString; - contentLengthAsString << contentLength; - std::string contentLengthFieldName(PCPP_SIP_CONTENT_LENGTH_FIELD); - HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); - if (contentLengthField == nullptr) - { - HeaderField* prevField = getFieldByName(prevFieldName); - contentLengthField = insertField(prevField, PCPP_SIP_CONTENT_LENGTH_FIELD, contentLengthAsString.str()); + const std::string SipMethodEnumToString[14] = { "INVITE", "ACK", "BYE", "CANCEL", "REGISTER", + "PRACK", "OPTIONS", "SUBSCRIBE", "NOTIFY", "PUBLISH", + "INFO", "REFER", "MESSAGE", "UPDATE" }; + + const std::unordered_map SipMethodStringToEnum{ + { "INVITE", SipRequestLayer::SipMethod::SipINVITE }, + { "ACK", SipRequestLayer::SipMethod::SipACK }, + { "BYE", SipRequestLayer::SipMethod::SipBYE }, + { "CANCEL", SipRequestLayer::SipMethod::SipCANCEL }, + { "REGISTER", SipRequestLayer::SipMethod::SipREGISTER }, + { "PRACK", SipRequestLayer::SipMethod::SipPRACK }, + { "OPTIONS", SipRequestLayer::SipMethod::SipOPTIONS }, + { "SUBSCRIBE", SipRequestLayer::SipMethod::SipSUBSCRIBE }, + { "NOTIFY", SipRequestLayer::SipMethod::SipNOTIFY }, + { "PUBLISH", SipRequestLayer::SipMethod::SipPUBLISH }, + { "INFO", SipRequestLayer::SipMethod::SipINFO }, + { "REFER", SipRequestLayer::SipMethod::SipREFER }, + { "MESSAGE", SipRequestLayer::SipMethod::SipMESSAGE }, + { "UPDATE", SipRequestLayer::SipMethod::SipUPDATE }, + }; + + // -------- Class SipLayer ----------------- + + int SipLayer::getContentLength() const + { + std::string contentLengthFieldName(PCPP_SIP_CONTENT_LENGTH_FIELD); + std::transform(contentLengthFieldName.begin(), contentLengthFieldName.end(), contentLengthFieldName.begin(), + ::tolower); + HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); + if (contentLengthField != nullptr) + return atoi(contentLengthField->getFieldValue().c_str()); + return 0; + } + + HeaderField* SipLayer::setContentLength(int contentLength, const std::string& prevFieldName) + { + std::ostringstream contentLengthAsString; + contentLengthAsString << contentLength; + std::string contentLengthFieldName(PCPP_SIP_CONTENT_LENGTH_FIELD); + HeaderField* contentLengthField = getFieldByName(contentLengthFieldName); + if (contentLengthField == nullptr) + { + HeaderField* prevField = getFieldByName(prevFieldName); + contentLengthField = insertField(prevField, PCPP_SIP_CONTENT_LENGTH_FIELD, contentLengthAsString.str()); + } + else + contentLengthField->setFieldValue(contentLengthAsString.str()); + + return contentLengthField; } - else - contentLengthField->setFieldValue(contentLengthAsString.str()); - return contentLengthField; -} + void SipLayer::parseNextLayer() + { + if (getLayerPayloadSize() == 0) + return; -void SipLayer::parseNextLayer() -{ - if (getLayerPayloadSize() == 0) - return; + size_t headerLen = getHeaderLen(); + std::string contentType; + if (getContentLength() > 0) + { + HeaderField* contentTypeField = getFieldByName(PCPP_SIP_CONTENT_TYPE_FIELD); + if (contentTypeField != nullptr) + contentType = contentTypeField->getFieldValue(); + } - size_t headerLen = getHeaderLen(); - std::string contentType; - if (getContentLength() > 0) - { - HeaderField *contentTypeField = getFieldByName(PCPP_SIP_CONTENT_TYPE_FIELD); - if (contentTypeField != nullptr) - contentType = contentTypeField->getFieldValue(); + if (contentType.find("application/sdp") != std::string::npos) + { + m_NextLayer = new SdpLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + } + else + { + m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + } } - if (contentType.find("application/sdp") != std::string::npos) - { - m_NextLayer = new SdpLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); - } - else + void SipLayer::computeCalculateFields() { - m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + HeaderField* contentLengthField = getFieldByName(PCPP_SIP_CONTENT_LENGTH_FIELD); + if (contentLengthField == nullptr) + return; + + size_t headerLen = getHeaderLen(); + if (m_DataLen > headerLen) + { + int currentContentLength = getContentLength(); + if (currentContentLength != (int)(m_DataLen - headerLen)) + setContentLength(m_DataLen - headerLen); + } } -} -void SipLayer::computeCalculateFields() -{ - HeaderField* contentLengthField = getFieldByName(PCPP_SIP_CONTENT_LENGTH_FIELD); - if (contentLengthField == nullptr) - return; + // -------- Class SipRequestFirstLine ----------------- - size_t headerLen = getHeaderLen(); - if (m_DataLen > headerLen) + SipRequestFirstLine::SipRequestFirstLine(SipRequestLayer* sipRequest) : m_SipRequest(sipRequest) { - int currentContentLength = getContentLength(); - if (currentContentLength != (int)(m_DataLen - headerLen)) - setContentLength(m_DataLen - headerLen); - } -} + m_Method = parseMethod((char*)m_SipRequest->m_Data, m_SipRequest->getDataLen()); + if (m_Method == SipRequestLayer::SipMethodUnknown) + { + m_UriOffset = -1; + PCPP_LOG_DEBUG("Couldn't resolve SIP request method"); + } + else + m_UriOffset = SipMethodEnumToString[m_Method].length() + 1; + parseVersion(); + char* endOfFirstLine; + if ((endOfFirstLine = (char*)memchr((char*)(m_SipRequest->m_Data + m_VersionOffset), '\n', + m_SipRequest->m_DataLen - (size_t)m_VersionOffset)) != nullptr) + { + m_FirstLineEndOffset = endOfFirstLine - (char*)m_SipRequest->m_Data + 1; + m_IsComplete = true; + } + else + { + m_FirstLineEndOffset = m_SipRequest->getDataLen(); + m_IsComplete = false; + } + if (Logger::getInstance().isDebugEnabled(PacketLogModuleSipLayer)) + { + std::string method = + (m_Method == SipRequestLayer::SipMethodUnknown ? "Unknown" : SipMethodEnumToString[m_Method]); + PCPP_LOG_DEBUG("Method='" << method << "'; SIP version='" << m_Version << "'; URI='" << getUri() << "'"); + } + } + SipRequestFirstLine::SipRequestFirstLine(SipRequestLayer* sipRequest, SipRequestLayer::SipMethod method, + const std::string& version, const std::string& uri) + try // throw(SipRequestFirstLineException) + { + if (method == SipRequestLayer::SipMethodUnknown) + { + m_Exception.setMessage("Method supplied was SipMethodUnknown"); + throw m_Exception; + } + if (version == "") + { + m_Exception.setMessage("Version supplied was empty string"); + throw m_Exception; + } + m_SipRequest = sipRequest; + m_Method = method; + m_Version = version; -// -------- Class SipRequestFirstLine ----------------- + std::string firstLine = SipMethodEnumToString[m_Method] + " " + uri + " " + version + "\r\n"; -SipRequestFirstLine::SipRequestFirstLine(SipRequestLayer* sipRequest) : m_SipRequest(sipRequest) -{ - m_Method = parseMethod((char*)m_SipRequest->m_Data, m_SipRequest->getDataLen()); - if (m_Method == SipRequestLayer::SipMethodUnknown) - { - m_UriOffset = -1; - PCPP_LOG_DEBUG("Couldn't resolve SIP request method"); - } - else m_UriOffset = SipMethodEnumToString[m_Method].length() + 1; + m_FirstLineEndOffset = firstLine.length(); + m_VersionOffset = m_UriOffset + uri.length() + 6; - parseVersion(); + m_SipRequest->m_DataLen = firstLine.length(); + m_SipRequest->m_Data = new uint8_t[m_SipRequest->m_DataLen]; + memcpy(m_SipRequest->m_Data, firstLine.c_str(), m_SipRequest->m_DataLen); - char* endOfFirstLine; - if ((endOfFirstLine = (char *)memchr((char*)(m_SipRequest->m_Data + m_VersionOffset), '\n', m_SipRequest->m_DataLen-(size_t)m_VersionOffset)) != nullptr) - { - m_FirstLineEndOffset = endOfFirstLine - (char*)m_SipRequest->m_Data + 1; m_IsComplete = true; } - else + catch (const SipRequestFirstLineException&) { - m_FirstLineEndOffset = m_SipRequest->getDataLen(); - m_IsComplete = false; + throw; } - - if (Logger::getInstance().isDebugEnabled(PacketLogModuleSipLayer)) - { - std::string method = (m_Method == SipRequestLayer::SipMethodUnknown? "Unknown" : SipMethodEnumToString[m_Method]); - PCPP_LOG_DEBUG("Method='" << method << "'; SIP version='" << m_Version << "'; URI='" << getUri() << "'"); - } -} - -SipRequestFirstLine::SipRequestFirstLine(SipRequestLayer* sipRequest, SipRequestLayer::SipMethod method, const std::string& version, const std::string& uri) -try // throw(SipRequestFirstLineException) -{ - if (method == SipRequestLayer::SipMethodUnknown) + catch (...) { - m_Exception.setMessage("Method supplied was SipMethodUnknown"); - throw m_Exception; + std::terminate(); } - if (version == "") + SipRequestLayer::SipMethod SipRequestFirstLine::parseMethod(const char* data, size_t dataLen) { - m_Exception.setMessage("Version supplied was empty string"); - throw m_Exception; - } - - m_SipRequest = sipRequest; - - m_Method = method; - m_Version = version; - - std::string firstLine = SipMethodEnumToString[m_Method] + " " + uri + " " + version + "\r\n"; - - m_UriOffset = SipMethodEnumToString[m_Method].length() + 1; - m_FirstLineEndOffset = firstLine.length(); - m_VersionOffset = m_UriOffset + uri.length() + 6; - - m_SipRequest->m_DataLen = firstLine.length(); - m_SipRequest->m_Data = new uint8_t[m_SipRequest->m_DataLen]; - memcpy(m_SipRequest->m_Data, firstLine.c_str(), m_SipRequest->m_DataLen); - - m_IsComplete = true; -} -catch(const SipRequestFirstLineException&) -{ - throw; -} -catch(...) -{ - std::terminate(); -} - -SipRequestLayer::SipMethod SipRequestFirstLine::parseMethod(const char* data, size_t dataLen) -{ - if (!data || dataLen < 4) - { - return SipRequestLayer::SipMethodUnknown; - } - - size_t spaceIndex = 0; - while (spaceIndex < dataLen && data[spaceIndex] != ' ' ) - { - spaceIndex++; - } + if (!data || dataLen < 4) + { + return SipRequestLayer::SipMethodUnknown; + } - if (spaceIndex == 0 || spaceIndex == dataLen) - { - return SipRequestLayer::SipMethodUnknown; - } + size_t spaceIndex = 0; + while (spaceIndex < dataLen && data[spaceIndex] != ' ') + { + spaceIndex++; + } - auto methodAdEnum = SipMethodStringToEnum.find(std::string(data, data + spaceIndex)); - if (methodAdEnum == SipMethodStringToEnum.end()) - { - return SipRequestLayer::SipMethodUnknown; - } - return methodAdEnum->second; -} + if (spaceIndex == 0 || spaceIndex == dataLen) + { + return SipRequestLayer::SipMethodUnknown; + } -void SipRequestFirstLine::parseVersion() -{ - if (m_SipRequest->getDataLen() < static_cast(m_UriOffset)) - { - m_Version = ""; - m_VersionOffset = -1; - return; + auto methodAdEnum = SipMethodStringToEnum.find(std::string(data, data + spaceIndex)); + if (methodAdEnum == SipMethodStringToEnum.end()) + { + return SipRequestLayer::SipMethodUnknown; + } + return methodAdEnum->second; } - char* data = (char*)(m_SipRequest->m_Data + m_UriOffset); - char* verPos = (char*)cross_platform_memmem(data, m_SipRequest->getDataLen() - m_UriOffset, " SIP/", 5); - if (verPos == nullptr) + void SipRequestFirstLine::parseVersion() { - m_Version = ""; - m_VersionOffset = -1; - return; - } + if (m_SipRequest->getDataLen() < static_cast(m_UriOffset)) + { + m_Version = ""; + m_VersionOffset = -1; + return; + } - // verify packet doesn't end before the version, meaning still left place for " SIP/x.y" (7 chars) - if ((uint16_t)(verPos + 7 - (char*)m_SipRequest->m_Data) > m_SipRequest->getDataLen()) - { - m_Version = ""; - m_VersionOffset = -1; - return; - } + char* data = (char*)(m_SipRequest->m_Data + m_UriOffset); + char* verPos = (char*)cross_platform_memmem(data, m_SipRequest->getDataLen() - m_UriOffset, " SIP/", 5); + if (verPos == nullptr) + { + m_Version = ""; + m_VersionOffset = -1; + return; + } - //skip the space char - verPos++; + // verify packet doesn't end before the version, meaning still left place for " SIP/x.y" (7 chars) + if ((uint16_t)(verPos + 7 - (char*)m_SipRequest->m_Data) > m_SipRequest->getDataLen()) + { + m_Version = ""; + m_VersionOffset = -1; + return; + } - int endOfVerPos = 0; - while (((verPos + endOfVerPos) < (char *) (m_SipRequest->m_Data + m_SipRequest->m_DataLen)) && ((verPos+endOfVerPos)[0] != '\r') && ((verPos+endOfVerPos)[0] != '\n')) - endOfVerPos++; + // skip the space char + verPos++; - m_Version = std::string(verPos, endOfVerPos); + int endOfVerPos = 0; + while (((verPos + endOfVerPos) < (char*)(m_SipRequest->m_Data + m_SipRequest->m_DataLen)) && + ((verPos + endOfVerPos)[0] != '\r') && ((verPos + endOfVerPos)[0] != '\n')) + endOfVerPos++; - m_VersionOffset = verPos - (char*)m_SipRequest->m_Data; -} + m_Version = std::string(verPos, endOfVerPos); -bool SipRequestFirstLine::setMethod(SipRequestLayer::SipMethod newMethod) -{ - if (newMethod == SipRequestLayer::SipMethodUnknown) - { - PCPP_LOG_ERROR("Requested method is SipMethodUnknown"); - return false; + m_VersionOffset = verPos - (char*)m_SipRequest->m_Data; } - //extend or shorten layer - int lengthDifference = SipMethodEnumToString[newMethod].length() - SipMethodEnumToString[m_Method].length(); - if (lengthDifference > 0) + bool SipRequestFirstLine::setMethod(SipRequestLayer::SipMethod newMethod) { - if (!m_SipRequest->extendLayer(0, lengthDifference)) + if (newMethod == SipRequestLayer::SipMethodUnknown) { - PCPP_LOG_ERROR("Cannot change layer size"); + PCPP_LOG_ERROR("Requested method is SipMethodUnknown"); return false; } - } - else if (lengthDifference < 0) - { - if (!m_SipRequest->shortenLayer(0, 0-lengthDifference)) - { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + // extend or shorten layer + int lengthDifference = SipMethodEnumToString[newMethod].length() - SipMethodEnumToString[m_Method].length(); + if (lengthDifference > 0) + { + if (!m_SipRequest->extendLayer(0, lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } + else if (lengthDifference < 0) + { + if (!m_SipRequest->shortenLayer(0, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } } - } - - if (lengthDifference != 0) - { - m_SipRequest->shiftFieldsOffset(m_SipRequest->getFirstField(), lengthDifference); - m_SipRequest->m_FieldsOffset += lengthDifference; - } - memcpy(m_SipRequest->m_Data, SipMethodEnumToString[newMethod].c_str(), SipMethodEnumToString[newMethod].length()); + if (lengthDifference != 0) + { + m_SipRequest->shiftFieldsOffset(m_SipRequest->getFirstField(), lengthDifference); + m_SipRequest->m_FieldsOffset += lengthDifference; + } - m_UriOffset += lengthDifference; - m_VersionOffset += lengthDifference; - m_FirstLineEndOffset += lengthDifference; + memcpy(m_SipRequest->m_Data, SipMethodEnumToString[newMethod].c_str(), + SipMethodEnumToString[newMethod].length()); - m_Method = newMethod; + m_UriOffset += lengthDifference; + m_VersionOffset += lengthDifference; + m_FirstLineEndOffset += lengthDifference; - return true; -} + m_Method = newMethod; -std::string SipRequestFirstLine::getUri() const -{ - std::string result; - if (m_UriOffset != -1 && m_VersionOffset != -1) - result.assign((char*)(m_SipRequest->m_Data + m_UriOffset), m_VersionOffset-1-m_UriOffset); + return true; + } - //else first line is illegal, return empty string + std::string SipRequestFirstLine::getUri() const + { + std::string result; + if (m_UriOffset != -1 && m_VersionOffset != -1) + result.assign((char*)(m_SipRequest->m_Data + m_UriOffset), m_VersionOffset - 1 - m_UriOffset); - return result; -} + // else first line is illegal, return empty string -bool SipRequestFirstLine::setUri(const std::string& newUri) -{ - if (newUri == "") - { - PCPP_LOG_ERROR("URI cannot be empty"); - return false; + return result; } - //extend or shorten layer - std::string currentUri = getUri(); - int lengthDifference = newUri.length() - currentUri.length(); - if (lengthDifference > 0) + bool SipRequestFirstLine::setUri(const std::string& newUri) { - if (!m_SipRequest->extendLayer(m_UriOffset, lengthDifference)) + if (newUri == "") { - PCPP_LOG_ERROR("Cannot change layer size"); + PCPP_LOG_ERROR("URI cannot be empty"); return false; } - } - else if (lengthDifference < 0) - { - if (!m_SipRequest->shortenLayer(m_UriOffset, 0-lengthDifference)) + + // extend or shorten layer + std::string currentUri = getUri(); + int lengthDifference = newUri.length() - currentUri.length(); + if (lengthDifference > 0) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + if (!m_SipRequest->extendLayer(m_UriOffset, lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } + else if (lengthDifference < 0) + { + if (!m_SipRequest->shortenLayer(m_UriOffset, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } } - } - - if (lengthDifference != 0) - { - m_SipRequest->shiftFieldsOffset(m_SipRequest->getFirstField(), lengthDifference); - m_SipRequest->m_FieldsOffset += lengthDifference; - } - - memcpy(m_SipRequest->m_Data + m_UriOffset, newUri.c_str(), newUri.length()); - - m_VersionOffset += lengthDifference; - m_FirstLineEndOffset += lengthDifference; - - return true; -} - - - - - -// -------- Class SipRequestLayer ----------------- - -SipRequestLayer::SipRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SipLayer(data, dataLen, prevLayer, packet) -{ - m_Protocol = SIPRequest; - m_FirstLine = new SipRequestFirstLine(this); - m_FieldsOffset = m_FirstLine->getSize(); - parseFields(); -} - -SipRequestLayer::SipRequestLayer(SipMethod method, const std::string& requestUri, const std::string& version) -{ - m_Protocol = SIPRequest; - m_FirstLine = new SipRequestFirstLine(this, method, std::move(version), std::move(requestUri)); - m_FieldsOffset = m_FirstLine->getSize(); -} -SipRequestLayer::SipRequestLayer(const SipRequestLayer& other) : SipLayer(other) -{ - m_FirstLine = new SipRequestFirstLine(this); -} + if (lengthDifference != 0) + { + m_SipRequest->shiftFieldsOffset(m_SipRequest->getFirstField(), lengthDifference); + m_SipRequest->m_FieldsOffset += lengthDifference; + } -SipRequestLayer& SipRequestLayer::operator=(const SipRequestLayer& other) -{ - SipLayer::operator=(other); + memcpy(m_SipRequest->m_Data + m_UriOffset, newUri.c_str(), newUri.length()); - if (m_FirstLine != nullptr) - delete m_FirstLine; + m_VersionOffset += lengthDifference; + m_FirstLineEndOffset += lengthDifference; - m_FirstLine = new SipRequestFirstLine(this); + return true; + } - return *this; -} + // -------- Class SipRequestLayer ----------------- -SipRequestLayer::~SipRequestLayer() -{ - delete m_FirstLine; -} + SipRequestLayer::SipRequestLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SipLayer(data, dataLen, prevLayer, packet) + { + m_Protocol = SIPRequest; + m_FirstLine = new SipRequestFirstLine(this); + m_FieldsOffset = m_FirstLine->getSize(); + parseFields(); + } -std::string SipRequestLayer::toString() const -{ - static const int maxLengthToPrint = 120; - std::string result = "SIP request, "; - int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line - if (size <= 0) + SipRequestLayer::SipRequestLayer(SipMethod method, const std::string& requestUri, const std::string& version) { - result += std::string("CORRUPT DATA"); - return result; + m_Protocol = SIPRequest; + m_FirstLine = new SipRequestFirstLine(this, method, std::move(version), std::move(requestUri)); + m_FieldsOffset = m_FirstLine->getSize(); } - if (size <= maxLengthToPrint) - { - char* firstLine = new char[size+1]; - strncpy(firstLine, (char*)m_Data, size); - firstLine[size] = 0; - result += std::string(firstLine); - delete[] firstLine; - } - else - { - char firstLine[maxLengthToPrint+1]; - strncpy(firstLine, (char*)m_Data, maxLengthToPrint-3); - firstLine[maxLengthToPrint-3] = '.'; - firstLine[maxLengthToPrint-2] = '.'; - firstLine[maxLengthToPrint-1] = '.'; - firstLine[maxLengthToPrint] = 0; - result += std::string(firstLine); - } - - return result; -} - - - - - - -// -------- Class SipResponseLayer ----------------- - - - -const std::string StatusCodeEnumToString[77] = { - "Trying", - "Ringing", - "Call is Being Forwarded", - "Queued", - "Session in Progress", - "Early Dialog Terminated", - "OK", - "Accepted", - "No Notification", - "Multiple Choices", - "Moved Permanently", - "Moved Temporarily", - "Use Proxy", - "Alternative Service", - "Bad Request", - "Unauthorized", - "Payment Required", - "Forbidden", - "Not Found", - "Method Not Allowed", - "Not Acceptable", - "Proxy Authentication Required", - "Request Timeout", - "Conflict", - "Gone", - "Length Required", - "Conditional Request Failed", - "Request Entity Too Large", - "Request-URI Too Long", - "Unsupported Media Type", - "Unsupported URI Scheme", - "Unknown Resource-Priority", - "Bad Extension", - "Extension Required", - "Session Interval Too Small", - "Interval Too Brief", - "Bad Location Information", - "Bad Alert Message", - "Use Identity Header", - "Provide Referrer Identity", - "Flow Failed", - "Anonymity Disallowed", - "Bad Identity-Info", - "Unsupported Certificate", - "Invalid Identity Header", - "First Hop Lacks Outbound Support", - "Max-Breadth Exceeded", - "Bad Info Package", - "Consent Needed", - "Temporarily Unavailable", - "Call_Transaction Does Not Exist", - "Loop Detected", - "Too Many Hops", - "Address Incomplete", - "Ambiguous", - "Busy Here", - "Request Terminated", - "Not Acceptable Here", - "Bad Event", - "Request Pending", - "Undecipherable", - "Security Agreement Required", - "Server Internal Error", - "Not Implemented", - "Bad Gateway", - "Service Unavailable", - "Server Timeout", - "Version Not Supported", - "Message Too Large", - "Push Notification Service Not Supported", - "Precondition Failure", - "Busy Everywhere", - "Decline", - "Does Not Exist Anywhere", - "Not Acceptable", - "Unwanted", - "Rejected" -}; - - -const int StatusCodeEnumToInt[77] = { - 100, - 180, - 181, - 182, - 183, - 199, - 200, - 202, - 204, - 300, - 301, - 302, - 305, - 380, - 400, - 401, - 402, - 403, - 404, - 405, - 406, - 407, - 408, - 409, - 410, - 411, - 412, - 413, - 414, - 415, - 416, - 417, - 420, - 421, - 422, - 425, - 423, - 424, - 428, - 429, - 430, - 433, - 436, - 437, - 438, - 439, - 440, - 469, - 470, - 480, - 481, - 482, - 483, - 484, - 485, - 486, - 487, - 488, - 489, - 491, - 493, - 494, - 500, - 501, - 502, - 503, - 504, - 505, - 513, - 555, - 580, - 600, - 603, - 604, - 606, - 607, - 608 -}; - - -const std::unordered_map StatusCodeStringToEnumMap { - {"100", SipResponseLayer::SipResponseStatusCode::Sip100Trying }, - {"180", SipResponseLayer::SipResponseStatusCode::Sip180Ringing }, - {"181", SipResponseLayer::SipResponseStatusCode::Sip181CallisBeingForwarded }, - {"182", SipResponseLayer::SipResponseStatusCode::Sip182Queued }, - {"183", SipResponseLayer::SipResponseStatusCode::Sip183SessioninProgress }, - {"199", SipResponseLayer::SipResponseStatusCode::Sip199EarlyDialogTerminated }, - {"200", SipResponseLayer::SipResponseStatusCode::Sip200OK }, - {"202", SipResponseLayer::SipResponseStatusCode::Sip202Accepted }, - {"204", SipResponseLayer::SipResponseStatusCode::Sip204NoNotification }, - {"300", SipResponseLayer::SipResponseStatusCode::Sip300MultipleChoices }, - {"301", SipResponseLayer::SipResponseStatusCode::Sip301MovedPermanently }, - {"302", SipResponseLayer::SipResponseStatusCode::Sip302MovedTemporarily }, - {"305", SipResponseLayer::SipResponseStatusCode::Sip305UseProxy }, - {"380", SipResponseLayer::SipResponseStatusCode::Sip380AlternativeService }, - {"400", SipResponseLayer::SipResponseStatusCode::Sip400BadRequest }, - {"401", SipResponseLayer::SipResponseStatusCode::Sip401Unauthorized }, - {"402", SipResponseLayer::SipResponseStatusCode::Sip402PaymentRequired }, - {"403", SipResponseLayer::SipResponseStatusCode::Sip403Forbidden }, - {"404", SipResponseLayer::SipResponseStatusCode::Sip404NotFound }, - {"405", SipResponseLayer::SipResponseStatusCode::Sip405MethodNotAllowed }, - {"406", SipResponseLayer::SipResponseStatusCode::Sip406NotAcceptable }, - {"407", SipResponseLayer::SipResponseStatusCode::Sip407ProxyAuthenticationRequired }, - {"408", SipResponseLayer::SipResponseStatusCode::Sip408RequestTimeout }, - {"409", SipResponseLayer::SipResponseStatusCode::Sip409Conflict }, - {"410", SipResponseLayer::SipResponseStatusCode::Sip410Gone }, - {"411", SipResponseLayer::SipResponseStatusCode::Sip411LengthRequired }, - {"412", SipResponseLayer::SipResponseStatusCode::Sip412ConditionalRequestFailed }, - {"413", SipResponseLayer::SipResponseStatusCode::Sip413RequestEntityTooLarge }, - {"414", SipResponseLayer::SipResponseStatusCode::Sip414RequestURITooLong }, - {"415", SipResponseLayer::SipResponseStatusCode::Sip415UnsupportedMediaType }, - {"416", SipResponseLayer::SipResponseStatusCode::Sip416UnsupportedURIScheme }, - {"417", SipResponseLayer::SipResponseStatusCode::Sip417UnknownResourcePriority }, - {"420", SipResponseLayer::SipResponseStatusCode::Sip420BadExtension }, - {"421", SipResponseLayer::SipResponseStatusCode::Sip421ExtensionRequired }, - {"422", SipResponseLayer::SipResponseStatusCode::Sip422SessionIntervalTooSmall }, - {"423", SipResponseLayer::SipResponseStatusCode::Sip423IntervalTooBrief }, - {"424", SipResponseLayer::SipResponseStatusCode::Sip424BadLocationInformation }, - {"425", SipResponseLayer::SipResponseStatusCode::Sip425BadAlertMessage }, - {"428", SipResponseLayer::SipResponseStatusCode::Sip428UseIdentityHeader }, - {"429", SipResponseLayer::SipResponseStatusCode::Sip429ProvideReferrerIdentity }, - {"430", SipResponseLayer::SipResponseStatusCode::Sip430FlowFailed }, - {"433", SipResponseLayer::SipResponseStatusCode::Sip433AnonymityDisallowed }, - {"436", SipResponseLayer::SipResponseStatusCode::Sip436BadIdentityInfo }, - {"437", SipResponseLayer::SipResponseStatusCode::Sip437UnsupportedCertificate }, - {"438", SipResponseLayer::SipResponseStatusCode::Sip438InvalidIdentityHeader }, - {"439", SipResponseLayer::SipResponseStatusCode::Sip439FirstHopLacksOutboundSupport }, - {"440", SipResponseLayer::SipResponseStatusCode::Sip440MaxBreadthExceeded }, - {"469", SipResponseLayer::SipResponseStatusCode::Sip469BadInfoPackage }, - {"470", SipResponseLayer::SipResponseStatusCode::Sip470ConsentNeeded }, - {"480", SipResponseLayer::SipResponseStatusCode::Sip480TemporarilyUnavailable }, - {"481", SipResponseLayer::SipResponseStatusCode::Sip481Call_TransactionDoesNotExist }, - {"482", SipResponseLayer::SipResponseStatusCode::Sip482LoopDetected }, - {"483", SipResponseLayer::SipResponseStatusCode::Sip483TooManyHops }, - {"484", SipResponseLayer::SipResponseStatusCode::Sip484AddressIncomplete }, - {"485", SipResponseLayer::SipResponseStatusCode::Sip485Ambiguous }, - {"486", SipResponseLayer::SipResponseStatusCode::Sip486BusyHere }, - {"487", SipResponseLayer::SipResponseStatusCode::Sip487RequestTerminated }, - {"488", SipResponseLayer::SipResponseStatusCode::Sip488NotAcceptableHere }, - {"489", SipResponseLayer::SipResponseStatusCode::Sip489BadEvent }, - {"491", SipResponseLayer::SipResponseStatusCode::Sip491RequestPending }, - {"493", SipResponseLayer::SipResponseStatusCode::Sip493Undecipherable }, - {"494", SipResponseLayer::SipResponseStatusCode::Sip494SecurityAgreementRequired }, - {"500", SipResponseLayer::SipResponseStatusCode::Sip500ServerInternalError }, - {"501", SipResponseLayer::SipResponseStatusCode::Sip501NotImplemented }, - {"502", SipResponseLayer::SipResponseStatusCode::Sip502BadGateway }, - {"503", SipResponseLayer::SipResponseStatusCode::Sip503ServiceUnavailable }, - {"504", SipResponseLayer::SipResponseStatusCode::Sip504ServerTimeout }, - {"505", SipResponseLayer::SipResponseStatusCode::Sip505VersionNotSupported }, - {"513", SipResponseLayer::SipResponseStatusCode::Sip513MessageTooLarge }, - {"555", SipResponseLayer::SipResponseStatusCode::Sip555PushNotificationServiceNotSupported }, - {"580", SipResponseLayer::SipResponseStatusCode::Sip580PreconditionFailure }, - {"600", SipResponseLayer::SipResponseStatusCode::Sip600BusyEverywhere }, - {"603", SipResponseLayer::SipResponseStatusCode::Sip603Decline }, - {"604", SipResponseLayer::SipResponseStatusCode::Sip604DoesNotExistAnywhere }, - {"606", SipResponseLayer::SipResponseStatusCode::Sip606NotAcceptable }, - {"607", SipResponseLayer::SipResponseStatusCode::Sip607Unwanted }, - {"608", SipResponseLayer::SipResponseStatusCode::Sip608Rejected }, -}; - - - -SipResponseLayer::SipResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : SipLayer(data, dataLen, prevLayer, packet) -{ - m_Protocol = SIPResponse; - m_FirstLine = new SipResponseFirstLine(this); - m_FieldsOffset = m_FirstLine->getSize(); - parseFields(); -} -SipResponseLayer::SipResponseLayer(SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString, const std::string& sipVersion) -{ - m_Protocol = SIPResponse; - m_FirstLine = new SipResponseFirstLine(this, std::move(sipVersion), statusCode, std::move(statusCodeString)); - m_FieldsOffset = m_FirstLine->getSize(); -} + SipRequestLayer::SipRequestLayer(const SipRequestLayer& other) : SipLayer(other) + { + m_FirstLine = new SipRequestFirstLine(this); + } -SipResponseLayer::~SipResponseLayer() -{ - delete m_FirstLine; -} + SipRequestLayer& SipRequestLayer::operator=(const SipRequestLayer& other) + { + SipLayer::operator=(other); + if (m_FirstLine != nullptr) + delete m_FirstLine; -SipResponseLayer::SipResponseLayer(const SipResponseLayer& other) : SipLayer(other) -{ - m_FirstLine = new SipResponseFirstLine(this); -} + m_FirstLine = new SipRequestFirstLine(this); -SipResponseLayer& SipResponseLayer::operator=(const SipResponseLayer& other) -{ - SipLayer::operator=(other); + return *this; + } - if (m_FirstLine != nullptr) + SipRequestLayer::~SipRequestLayer() + { delete m_FirstLine; + } - m_FirstLine = new SipResponseFirstLine(this); - - return *this; -} - -std::string SipResponseLayer::toString() const -{ - static const int maxLengthToPrint = 120; - std::string result = "SIP response, "; - int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line - if (size <= 0) + std::string SipRequestLayer::toString() const { - result += std::string("CORRUPT DATA"); + static const int maxLengthToPrint = 120; + std::string result = "SIP request, "; + int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line + if (size <= 0) + { + result += std::string("CORRUPT DATA"); + return result; + } + if (size <= maxLengthToPrint) + { + char* firstLine = new char[size + 1]; + strncpy(firstLine, (char*)m_Data, size); + firstLine[size] = 0; + result += std::string(firstLine); + delete[] firstLine; + } + else + { + char firstLine[maxLengthToPrint + 1]; + strncpy(firstLine, (char*)m_Data, maxLengthToPrint - 3); + firstLine[maxLengthToPrint - 3] = '.'; + firstLine[maxLengthToPrint - 2] = '.'; + firstLine[maxLengthToPrint - 1] = '.'; + firstLine[maxLengthToPrint] = 0; + result += std::string(firstLine); + } + return result; } - if (size <= maxLengthToPrint) + + // -------- Class SipResponseLayer ----------------- + + const std::string StatusCodeEnumToString[77] = { "Trying", + "Ringing", + "Call is Being Forwarded", + "Queued", + "Session in Progress", + "Early Dialog Terminated", + "OK", + "Accepted", + "No Notification", + "Multiple Choices", + "Moved Permanently", + "Moved Temporarily", + "Use Proxy", + "Alternative Service", + "Bad Request", + "Unauthorized", + "Payment Required", + "Forbidden", + "Not Found", + "Method Not Allowed", + "Not Acceptable", + "Proxy Authentication Required", + "Request Timeout", + "Conflict", + "Gone", + "Length Required", + "Conditional Request Failed", + "Request Entity Too Large", + "Request-URI Too Long", + "Unsupported Media Type", + "Unsupported URI Scheme", + "Unknown Resource-Priority", + "Bad Extension", + "Extension Required", + "Session Interval Too Small", + "Interval Too Brief", + "Bad Location Information", + "Bad Alert Message", + "Use Identity Header", + "Provide Referrer Identity", + "Flow Failed", + "Anonymity Disallowed", + "Bad Identity-Info", + "Unsupported Certificate", + "Invalid Identity Header", + "First Hop Lacks Outbound Support", + "Max-Breadth Exceeded", + "Bad Info Package", + "Consent Needed", + "Temporarily Unavailable", + "Call_Transaction Does Not Exist", + "Loop Detected", + "Too Many Hops", + "Address Incomplete", + "Ambiguous", + "Busy Here", + "Request Terminated", + "Not Acceptable Here", + "Bad Event", + "Request Pending", + "Undecipherable", + "Security Agreement Required", + "Server Internal Error", + "Not Implemented", + "Bad Gateway", + "Service Unavailable", + "Server Timeout", + "Version Not Supported", + "Message Too Large", + "Push Notification Service Not Supported", + "Precondition Failure", + "Busy Everywhere", + "Decline", + "Does Not Exist Anywhere", + "Not Acceptable", + "Unwanted", + "Rejected" }; + + const int StatusCodeEnumToInt[77] = { 100, 180, 181, 182, 183, 199, 200, 202, 204, 300, 301, 302, 305, + 380, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 416, 417, 420, 421, 422, 425, 423, 424, 428, + 429, 430, 433, 436, 437, 438, 439, 440, 469, 470, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 491, 493, 494, 500, 501, 502, + 503, 504, 505, 513, 555, 580, 600, 603, 604, 606, 607, 608 }; + + const std::unordered_map StatusCodeStringToEnumMap{ + { "100", SipResponseLayer::SipResponseStatusCode::Sip100Trying }, + { "180", SipResponseLayer::SipResponseStatusCode::Sip180Ringing }, + { "181", SipResponseLayer::SipResponseStatusCode::Sip181CallisBeingForwarded }, + { "182", SipResponseLayer::SipResponseStatusCode::Sip182Queued }, + { "183", SipResponseLayer::SipResponseStatusCode::Sip183SessioninProgress }, + { "199", SipResponseLayer::SipResponseStatusCode::Sip199EarlyDialogTerminated }, + { "200", SipResponseLayer::SipResponseStatusCode::Sip200OK }, + { "202", SipResponseLayer::SipResponseStatusCode::Sip202Accepted }, + { "204", SipResponseLayer::SipResponseStatusCode::Sip204NoNotification }, + { "300", SipResponseLayer::SipResponseStatusCode::Sip300MultipleChoices }, + { "301", SipResponseLayer::SipResponseStatusCode::Sip301MovedPermanently }, + { "302", SipResponseLayer::SipResponseStatusCode::Sip302MovedTemporarily }, + { "305", SipResponseLayer::SipResponseStatusCode::Sip305UseProxy }, + { "380", SipResponseLayer::SipResponseStatusCode::Sip380AlternativeService }, + { "400", SipResponseLayer::SipResponseStatusCode::Sip400BadRequest }, + { "401", SipResponseLayer::SipResponseStatusCode::Sip401Unauthorized }, + { "402", SipResponseLayer::SipResponseStatusCode::Sip402PaymentRequired }, + { "403", SipResponseLayer::SipResponseStatusCode::Sip403Forbidden }, + { "404", SipResponseLayer::SipResponseStatusCode::Sip404NotFound }, + { "405", SipResponseLayer::SipResponseStatusCode::Sip405MethodNotAllowed }, + { "406", SipResponseLayer::SipResponseStatusCode::Sip406NotAcceptable }, + { "407", SipResponseLayer::SipResponseStatusCode::Sip407ProxyAuthenticationRequired }, + { "408", SipResponseLayer::SipResponseStatusCode::Sip408RequestTimeout }, + { "409", SipResponseLayer::SipResponseStatusCode::Sip409Conflict }, + { "410", SipResponseLayer::SipResponseStatusCode::Sip410Gone }, + { "411", SipResponseLayer::SipResponseStatusCode::Sip411LengthRequired }, + { "412", SipResponseLayer::SipResponseStatusCode::Sip412ConditionalRequestFailed }, + { "413", SipResponseLayer::SipResponseStatusCode::Sip413RequestEntityTooLarge }, + { "414", SipResponseLayer::SipResponseStatusCode::Sip414RequestURITooLong }, + { "415", SipResponseLayer::SipResponseStatusCode::Sip415UnsupportedMediaType }, + { "416", SipResponseLayer::SipResponseStatusCode::Sip416UnsupportedURIScheme }, + { "417", SipResponseLayer::SipResponseStatusCode::Sip417UnknownResourcePriority }, + { "420", SipResponseLayer::SipResponseStatusCode::Sip420BadExtension }, + { "421", SipResponseLayer::SipResponseStatusCode::Sip421ExtensionRequired }, + { "422", SipResponseLayer::SipResponseStatusCode::Sip422SessionIntervalTooSmall }, + { "423", SipResponseLayer::SipResponseStatusCode::Sip423IntervalTooBrief }, + { "424", SipResponseLayer::SipResponseStatusCode::Sip424BadLocationInformation }, + { "425", SipResponseLayer::SipResponseStatusCode::Sip425BadAlertMessage }, + { "428", SipResponseLayer::SipResponseStatusCode::Sip428UseIdentityHeader }, + { "429", SipResponseLayer::SipResponseStatusCode::Sip429ProvideReferrerIdentity }, + { "430", SipResponseLayer::SipResponseStatusCode::Sip430FlowFailed }, + { "433", SipResponseLayer::SipResponseStatusCode::Sip433AnonymityDisallowed }, + { "436", SipResponseLayer::SipResponseStatusCode::Sip436BadIdentityInfo }, + { "437", SipResponseLayer::SipResponseStatusCode::Sip437UnsupportedCertificate }, + { "438", SipResponseLayer::SipResponseStatusCode::Sip438InvalidIdentityHeader }, + { "439", SipResponseLayer::SipResponseStatusCode::Sip439FirstHopLacksOutboundSupport }, + { "440", SipResponseLayer::SipResponseStatusCode::Sip440MaxBreadthExceeded }, + { "469", SipResponseLayer::SipResponseStatusCode::Sip469BadInfoPackage }, + { "470", SipResponseLayer::SipResponseStatusCode::Sip470ConsentNeeded }, + { "480", SipResponseLayer::SipResponseStatusCode::Sip480TemporarilyUnavailable }, + { "481", SipResponseLayer::SipResponseStatusCode::Sip481Call_TransactionDoesNotExist }, + { "482", SipResponseLayer::SipResponseStatusCode::Sip482LoopDetected }, + { "483", SipResponseLayer::SipResponseStatusCode::Sip483TooManyHops }, + { "484", SipResponseLayer::SipResponseStatusCode::Sip484AddressIncomplete }, + { "485", SipResponseLayer::SipResponseStatusCode::Sip485Ambiguous }, + { "486", SipResponseLayer::SipResponseStatusCode::Sip486BusyHere }, + { "487", SipResponseLayer::SipResponseStatusCode::Sip487RequestTerminated }, + { "488", SipResponseLayer::SipResponseStatusCode::Sip488NotAcceptableHere }, + { "489", SipResponseLayer::SipResponseStatusCode::Sip489BadEvent }, + { "491", SipResponseLayer::SipResponseStatusCode::Sip491RequestPending }, + { "493", SipResponseLayer::SipResponseStatusCode::Sip493Undecipherable }, + { "494", SipResponseLayer::SipResponseStatusCode::Sip494SecurityAgreementRequired }, + { "500", SipResponseLayer::SipResponseStatusCode::Sip500ServerInternalError }, + { "501", SipResponseLayer::SipResponseStatusCode::Sip501NotImplemented }, + { "502", SipResponseLayer::SipResponseStatusCode::Sip502BadGateway }, + { "503", SipResponseLayer::SipResponseStatusCode::Sip503ServiceUnavailable }, + { "504", SipResponseLayer::SipResponseStatusCode::Sip504ServerTimeout }, + { "505", SipResponseLayer::SipResponseStatusCode::Sip505VersionNotSupported }, + { "513", SipResponseLayer::SipResponseStatusCode::Sip513MessageTooLarge }, + { "555", SipResponseLayer::SipResponseStatusCode::Sip555PushNotificationServiceNotSupported }, + { "580", SipResponseLayer::SipResponseStatusCode::Sip580PreconditionFailure }, + { "600", SipResponseLayer::SipResponseStatusCode::Sip600BusyEverywhere }, + { "603", SipResponseLayer::SipResponseStatusCode::Sip603Decline }, + { "604", SipResponseLayer::SipResponseStatusCode::Sip604DoesNotExistAnywhere }, + { "606", SipResponseLayer::SipResponseStatusCode::Sip606NotAcceptable }, + { "607", SipResponseLayer::SipResponseStatusCode::Sip607Unwanted }, + { "608", SipResponseLayer::SipResponseStatusCode::Sip608Rejected }, + }; + + SipResponseLayer::SipResponseLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SipLayer(data, dataLen, prevLayer, packet) + { + m_Protocol = SIPResponse; + m_FirstLine = new SipResponseFirstLine(this); + m_FieldsOffset = m_FirstLine->getSize(); + parseFields(); + } + + SipResponseLayer::SipResponseLayer(SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString, + const std::string& sipVersion) + { + m_Protocol = SIPResponse; + m_FirstLine = new SipResponseFirstLine(this, std::move(sipVersion), statusCode, std::move(statusCodeString)); + m_FieldsOffset = m_FirstLine->getSize(); + } + + SipResponseLayer::~SipResponseLayer() { - char* firstLine = new char[size+1]; - strncpy(firstLine, (char*)m_Data, size); - firstLine[size] = 0; - result += std::string(firstLine); - delete[] firstLine; + delete m_FirstLine; } - else + + SipResponseLayer::SipResponseLayer(const SipResponseLayer& other) : SipLayer(other) { - char firstLine[maxLengthToPrint+1]; - strncpy(firstLine, (char*)m_Data, maxLengthToPrint-3); - firstLine[maxLengthToPrint-3] = '.'; - firstLine[maxLengthToPrint-2] = '.'; - firstLine[maxLengthToPrint-1] = '.'; - firstLine[maxLengthToPrint] = 0; - result += std::string(firstLine); + m_FirstLine = new SipResponseFirstLine(this); } - return result; -} - - - - - - + SipResponseLayer& SipResponseLayer::operator=(const SipResponseLayer& other) + { + SipLayer::operator=(other); + if (m_FirstLine != nullptr) + delete m_FirstLine; -// -------- Class SipResponseFirstLine ----------------- + m_FirstLine = new SipResponseFirstLine(this); -int SipResponseFirstLine::getStatusCodeAsInt() const -{ - return StatusCodeEnumToInt[m_StatusCode]; -} + return *this; + } -std::string SipResponseFirstLine::getStatusCodeString() const -{ - std::string result; - const int statusStringOffset = 12; - if (m_StatusCode != SipResponseLayer::SipStatusCodeUnknown) + std::string SipResponseLayer::toString() const { - int statusStringEndOffset = m_FirstLineEndOffset - 2; - if ((*(m_SipResponse->m_Data + statusStringEndOffset)) != '\r') - statusStringEndOffset++; - result.assign((char*)(m_SipResponse->m_Data + statusStringOffset), statusStringEndOffset-statusStringOffset); - } + static const int maxLengthToPrint = 120; + std::string result = "SIP response, "; + int size = m_FirstLine->getSize() - 2; // the -2 is to remove \r\n at the end of the first line + if (size <= 0) + { + result += std::string("CORRUPT DATA"); + return result; + } + if (size <= maxLengthToPrint) + { + char* firstLine = new char[size + 1]; + strncpy(firstLine, (char*)m_Data, size); + firstLine[size] = 0; + result += std::string(firstLine); + delete[] firstLine; + } + else + { + char firstLine[maxLengthToPrint + 1]; + strncpy(firstLine, (char*)m_Data, maxLengthToPrint - 3); + firstLine[maxLengthToPrint - 3] = '.'; + firstLine[maxLengthToPrint - 2] = '.'; + firstLine[maxLengthToPrint - 1] = '.'; + firstLine[maxLengthToPrint] = 0; + result += std::string(firstLine); + } - //else first line is illegal, return empty string + return result; + } - return result; -} + // -------- Class SipResponseFirstLine ----------------- -bool SipResponseFirstLine::setStatusCode(SipResponseLayer::SipResponseStatusCode newStatusCode, std::string statusCodeString) -{ - if (newStatusCode == SipResponseLayer::SipStatusCodeUnknown) + int SipResponseFirstLine::getStatusCodeAsInt() const { - PCPP_LOG_ERROR("Requested status code is SipStatusCodeUnknown"); - return false; + return StatusCodeEnumToInt[m_StatusCode]; } - //extend or shorten layer - - size_t statusStringOffset = 12; - if (statusCodeString == "") - statusCodeString = StatusCodeEnumToString[newStatusCode]; - int lengthDifference = statusCodeString.length() - getStatusCodeString().length(); - - if (lengthDifference > 0) + std::string SipResponseFirstLine::getStatusCodeString() const { - if (!m_SipResponse->extendLayer(statusStringOffset, lengthDifference)) + std::string result; + const int statusStringOffset = 12; + if (m_StatusCode != SipResponseLayer::SipStatusCodeUnknown) { - PCPP_LOG_ERROR("Cannot change layer size"); - return false; + int statusStringEndOffset = m_FirstLineEndOffset - 2; + if ((*(m_SipResponse->m_Data + statusStringEndOffset)) != '\r') + statusStringEndOffset++; + result.assign((char*)(m_SipResponse->m_Data + statusStringOffset), + statusStringEndOffset - statusStringOffset); } + + // else first line is illegal, return empty string + + return result; } - else if (lengthDifference < 0) + + bool SipResponseFirstLine::setStatusCode(SipResponseLayer::SipResponseStatusCode newStatusCode, + std::string statusCodeString) { - if (!m_SipResponse->shortenLayer(statusStringOffset, 0-lengthDifference)) + if (newStatusCode == SipResponseLayer::SipStatusCodeUnknown) { - PCPP_LOG_ERROR("Cannot change layer size"); + PCPP_LOG_ERROR("Requested status code is SipStatusCodeUnknown"); return false; - } - } - if (lengthDifference != 0) - { - m_SipResponse->shiftFieldsOffset(m_SipResponse->getFirstField(), lengthDifference); - m_SipResponse->m_FieldsOffset += lengthDifference; - } + // extend or shorten layer - // copy status string - memcpy(m_SipResponse->m_Data+statusStringOffset, statusCodeString.c_str(), statusCodeString.length()); + size_t statusStringOffset = 12; + if (statusCodeString == "") + statusCodeString = StatusCodeEnumToString[newStatusCode]; + int lengthDifference = statusCodeString.length() - getStatusCodeString().length(); - // change status code - std::ostringstream statusCodeAsString; - statusCodeAsString << StatusCodeEnumToInt[newStatusCode]; - memcpy(m_SipResponse->m_Data+8, statusCodeAsString.str().c_str(), 3); + if (lengthDifference > 0) + { + if (!m_SipResponse->extendLayer(statusStringOffset, lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } + else if (lengthDifference < 0) + { + if (!m_SipResponse->shortenLayer(statusStringOffset, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Cannot change layer size"); + return false; + } + } - m_StatusCode = newStatusCode; - m_FirstLineEndOffset += lengthDifference; + if (lengthDifference != 0) + { + m_SipResponse->shiftFieldsOffset(m_SipResponse->getFirstField(), lengthDifference); + m_SipResponse->m_FieldsOffset += lengthDifference; + } - return true; + // copy status string + memcpy(m_SipResponse->m_Data + statusStringOffset, statusCodeString.c_str(), statusCodeString.length()); -} + // change status code + std::ostringstream statusCodeAsString; + statusCodeAsString << StatusCodeEnumToInt[newStatusCode]; + memcpy(m_SipResponse->m_Data + 8, statusCodeAsString.str().c_str(), 3); -void SipResponseFirstLine::setVersion(const std::string& newVersion) -{ - if (newVersion == "") - return; + m_StatusCode = newStatusCode; + m_FirstLineEndOffset += lengthDifference; - if (newVersion.length() != m_Version.length()) - { - PCPP_LOG_ERROR("Expected version length is " << m_Version.length() << " characters in the format of SIP/x.y"); - return; + return true; } - char* verPos = (char*)m_SipResponse->m_Data; - memcpy(verPos, newVersion.c_str(), newVersion.length()); - m_Version = newVersion; -} - -SipResponseLayer::SipResponseStatusCode SipResponseFirstLine::parseStatusCode(const char* data, size_t dataLen) -{ - // minimum data should be 12B long: "SIP/x.y XXX " - if (!data || dataLen < 12) + void SipResponseFirstLine::setVersion(const std::string& newVersion) { - return SipResponseLayer::SipStatusCodeUnknown; - } + if (newVersion == "") + return; - const char* statusCodeData = data + 8; - if (statusCodeData[3] != ' ') - { - return SipResponseLayer::SipStatusCodeUnknown; - } + if (newVersion.length() != m_Version.length()) + { + PCPP_LOG_ERROR("Expected version length is " << m_Version.length() + << " characters in the format of SIP/x.y"); + return; + } - auto codeAsEnum = StatusCodeStringToEnumMap.find(std::string(statusCodeData, 3)); - if (codeAsEnum == StatusCodeStringToEnumMap.end()) - { - return SipResponseLayer::SipStatusCodeUnknown; + char* verPos = (char*)m_SipResponse->m_Data; + memcpy(verPos, newVersion.c_str(), newVersion.length()); + m_Version = newVersion; } - return codeAsEnum->second; -} -SipResponseFirstLine::SipResponseFirstLine(SipResponseLayer* sipResponse) : m_SipResponse(sipResponse) -{ - m_Version = parseVersion((char*)m_SipResponse->m_Data, m_SipResponse->getDataLen()); - if (m_Version == "") - { - m_StatusCode = SipResponseLayer::SipStatusCodeUnknown; - } - else + SipResponseLayer::SipResponseStatusCode SipResponseFirstLine::parseStatusCode(const char* data, size_t dataLen) { - m_StatusCode = parseStatusCode((char*)m_SipResponse->m_Data, m_SipResponse->getDataLen()); - } + // minimum data should be 12B long: "SIP/x.y XXX " + if (!data || dataLen < 12) + { + return SipResponseLayer::SipStatusCodeUnknown; + } + const char* statusCodeData = data + 8; + if (statusCodeData[3] != ' ') + { + return SipResponseLayer::SipStatusCodeUnknown; + } - char* endOfFirstLine; - if ((endOfFirstLine = (char *)memchr((char*)(m_SipResponse->m_Data), '\n', m_SipResponse->m_DataLen)) != nullptr) - { - m_FirstLineEndOffset = endOfFirstLine - (char*)m_SipResponse->m_Data + 1; - m_IsComplete = true; - } - else - { - m_FirstLineEndOffset = m_SipResponse->getDataLen(); - m_IsComplete = false; + auto codeAsEnum = StatusCodeStringToEnumMap.find(std::string(statusCodeData, 3)); + if (codeAsEnum == StatusCodeStringToEnumMap.end()) + { + return SipResponseLayer::SipStatusCodeUnknown; + } + return codeAsEnum->second; } - if (Logger::getInstance().isDebugEnabled(PacketLogModuleSipLayer)) + SipResponseFirstLine::SipResponseFirstLine(SipResponseLayer* sipResponse) : m_SipResponse(sipResponse) { - int statusCode = (m_StatusCode == SipResponseLayer::SipStatusCodeUnknown ? 0 : StatusCodeEnumToInt[m_StatusCode]); - PCPP_LOG_DEBUG("Version='" << m_Version << "'; Status code=" << statusCode << " '" << getStatusCodeString() << "'"); - } -} + m_Version = parseVersion((char*)m_SipResponse->m_Data, m_SipResponse->getDataLen()); + if (m_Version == "") + { + m_StatusCode = SipResponseLayer::SipStatusCodeUnknown; + } + else + { + m_StatusCode = parseStatusCode((char*)m_SipResponse->m_Data, m_SipResponse->getDataLen()); + } + char* endOfFirstLine; + if ((endOfFirstLine = (char*)memchr((char*)(m_SipResponse->m_Data), '\n', m_SipResponse->m_DataLen)) != nullptr) + { + m_FirstLineEndOffset = endOfFirstLine - (char*)m_SipResponse->m_Data + 1; + m_IsComplete = true; + } + else + { + m_FirstLineEndOffset = m_SipResponse->getDataLen(); + m_IsComplete = false; + } -SipResponseFirstLine::SipResponseFirstLine(SipResponseLayer* sipResponse, const std::string& version, SipResponseLayer::SipResponseStatusCode statusCode, std::string statusCodeString) -{ - if (statusCode == SipResponseLayer::SipStatusCodeUnknown) - { - m_Exception.setMessage("Status code supplied was SipStatusCodeUnknown"); - throw m_Exception; + if (Logger::getInstance().isDebugEnabled(PacketLogModuleSipLayer)) + { + int statusCode = + (m_StatusCode == SipResponseLayer::SipStatusCodeUnknown ? 0 : StatusCodeEnumToInt[m_StatusCode]); + PCPP_LOG_DEBUG("Version='" << m_Version << "'; Status code=" << statusCode << " '" << getStatusCodeString() + << "'"); + } } - if (version == "") + SipResponseFirstLine::SipResponseFirstLine(SipResponseLayer* sipResponse, const std::string& version, + SipResponseLayer::SipResponseStatusCode statusCode, + std::string statusCodeString) { - m_Exception.setMessage("Version supplied was unknown"); - throw m_Exception; - } + if (statusCode == SipResponseLayer::SipStatusCodeUnknown) + { + m_Exception.setMessage("Status code supplied was SipStatusCodeUnknown"); + throw m_Exception; + } - m_SipResponse = sipResponse; + if (version == "") + { + m_Exception.setMessage("Version supplied was unknown"); + throw m_Exception; + } - m_StatusCode = statusCode; - m_Version = version; + m_SipResponse = sipResponse; - std::ostringstream statusCodeAsString; - statusCodeAsString << StatusCodeEnumToInt[m_StatusCode]; - if (statusCodeString == "") - statusCodeString = StatusCodeEnumToString[m_StatusCode]; - std::string firstLine = m_Version + " " + statusCodeAsString.str() + " " + statusCodeString + "\r\n"; + m_StatusCode = statusCode; + m_Version = version; - m_FirstLineEndOffset = firstLine.length(); + std::ostringstream statusCodeAsString; + statusCodeAsString << StatusCodeEnumToInt[m_StatusCode]; + if (statusCodeString == "") + statusCodeString = StatusCodeEnumToString[m_StatusCode]; + std::string firstLine = m_Version + " " + statusCodeAsString.str() + " " + statusCodeString + "\r\n"; - m_SipResponse->m_DataLen = firstLine.length(); - m_SipResponse->m_Data = new uint8_t[m_SipResponse->m_DataLen]; - memcpy(m_SipResponse->m_Data, firstLine.c_str(), m_SipResponse->m_DataLen); + m_FirstLineEndOffset = firstLine.length(); - m_IsComplete = true; -} + m_SipResponse->m_DataLen = firstLine.length(); + m_SipResponse->m_Data = new uint8_t[m_SipResponse->m_DataLen]; + memcpy(m_SipResponse->m_Data, firstLine.c_str(), m_SipResponse->m_DataLen); -std::string SipResponseFirstLine::parseVersion(const char* data, size_t dataLen) -{ - if (!data || dataLen < 8) // "SIP/x.y " - { - PCPP_LOG_DEBUG("SIP response length < 8, cannot identify version"); - return ""; + m_IsComplete = true; } - if (data[0] != 'S' || data[1] != 'I' || data[2] != 'P' || data[3] != '/') + std::string SipResponseFirstLine::parseVersion(const char* data, size_t dataLen) { - PCPP_LOG_DEBUG("SIP response does not begin with 'SIP/'"); - return ""; - } + if (!data || dataLen < 8) // "SIP/x.y " + { + PCPP_LOG_DEBUG("SIP response length < 8, cannot identify version"); + return ""; + } - char* nextSpace = (char*)memchr(data, ' ', dataLen); - if (nextSpace == nullptr) - return ""; + if (data[0] != 'S' || data[1] != 'I' || data[2] != 'P' || data[3] != '/') + { + PCPP_LOG_DEBUG("SIP response does not begin with 'SIP/'"); + return ""; + } - return std::string(data, nextSpace - data); -} + char* nextSpace = (char*)memchr(data, ' ', dataLen); + if (nextSpace == nullptr) + return ""; + return std::string(data, nextSpace - data); + } -} +} // namespace pcpp diff --git a/Packet++/src/Sll2Layer.cpp b/Packet++/src/Sll2Layer.cpp index 81df2bec56..99638b46bb 100644 --- a/Packet++/src/Sll2Layer.cpp +++ b/Packet++/src/Sll2Layer.cpp @@ -14,102 +14,103 @@ namespace pcpp { -Sll2Layer::Sll2Layer(uint32_t interfaceIndex, uint16_t ARPHRDType, uint8_t packetType) -{ - const size_t headerLen = sizeof(sll2_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - setPacketType(packetType); - setArphrdType(ARPHRDType); - setInterfaceIndex(interfaceIndex); - m_Protocol = SLL2; -} - -bool Sll2Layer::setLinkLayerAddr(const uint8_t* addr, size_t addrLength) -{ - if (addr == nullptr || addrLength == 0 || addrLength > 8) + Sll2Layer::Sll2Layer(uint32_t interfaceIndex, uint16_t ARPHRDType, uint8_t packetType) { - PCPP_LOG_ERROR("Address length is out of bounds, it must be between 1 and 8"); - return false; + const size_t headerLen = sizeof(sll2_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + setPacketType(packetType); + setArphrdType(ARPHRDType); + setInterfaceIndex(interfaceIndex); + m_Protocol = SLL2; } - getSll2Header()->link_layer_addr_len = addrLength; - memcpy(getSll2Header()->link_layer_addr, addr, addrLength); - return true; -} + bool Sll2Layer::setLinkLayerAddr(const uint8_t* addr, size_t addrLength) + { + if (addr == nullptr || addrLength == 0 || addrLength > 8) + { + PCPP_LOG_ERROR("Address length is out of bounds, it must be between 1 and 8"); + return false; + } + + getSll2Header()->link_layer_addr_len = addrLength; + memcpy(getSll2Header()->link_layer_addr, addr, addrLength); + return true; + } -MacAddress Sll2Layer::getLinkLayerAsMacAddress() { - const uint8_t* data = getLinkLayerAddr(); - uint8_t dataLen = getLinkLayerAddrLen(); - if (data == nullptr || dataLen == 0 || dataLen > 8) { - return MacAddress::Zero; + MacAddress Sll2Layer::getLinkLayerAsMacAddress() + { + const uint8_t* data = getLinkLayerAddr(); + uint8_t dataLen = getLinkLayerAddrLen(); + if (data == nullptr || dataLen == 0 || dataLen > 8) + { + return MacAddress::Zero; + } + return MacAddress(data); } - return MacAddress(data); -} -bool Sll2Layer::setMacAddressAsLinkLayer(const MacAddress& macAddr) -{ - uint8_t macAddrAsArr[6]; - macAddr.copyTo(macAddrAsArr); - return setLinkLayerAddr(macAddrAsArr, 6); -} + bool Sll2Layer::setMacAddressAsLinkLayer(const MacAddress& macAddr) + { + uint8_t macAddrAsArr[6]; + macAddr.copyTo(macAddrAsArr); + return setLinkLayerAddr(macAddrAsArr, 6); + } -void Sll2Layer::parseNextLayer() -{ - if (m_DataLen <= sizeof(sll2_header)) - return; - - uint8_t* payload = m_Data + sizeof(sll2_header); - size_t payloadLen = m_DataLen - sizeof(sll2_header); - - sll2_header* hdr = getSll2Header(); - switch (be16toh(hdr->protocol_type)) - { - case PCPP_ETHERTYPE_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_ARP: - m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_VLAN: - case PCPP_ETHERTYPE_IEEE_802_1AD: - m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_PPPOES: - m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_PPPOED: - m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_MPLS: - m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); - } - -} - -void Sll2Layer::computeCalculateFields() -{ - if (m_NextLayer == nullptr) - return; + void Sll2Layer::parseNextLayer() + { + if (m_DataLen <= sizeof(sll2_header)) + return; - sll2_header* hdr = getSll2Header(); - switch (m_NextLayer->getProtocol()) + uint8_t* payload = m_Data + sizeof(sll2_header); + size_t payloadLen = m_DataLen - sizeof(sll2_header); + + sll2_header* hdr = getSll2Header(); + switch (be16toh(hdr->protocol_type)) + { + case PCPP_ETHERTYPE_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_ARP: + m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_VLAN: + case PCPP_ETHERTYPE_IEEE_802_1AD: + m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_PPPOES: + m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_PPPOED: + m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_MPLS: + m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); + break; + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } + } + + void Sll2Layer::computeCalculateFields() { + if (m_NextLayer == nullptr) + return; + + sll2_header* hdr = getSll2Header(); + switch (m_NextLayer->getProtocol()) + { case IPv4: hdr->protocol_type = htobe16(PCPP_ETHERTYPE_IP); break; @@ -124,67 +125,67 @@ void Sll2Layer::computeCalculateFields() break; default: return; + } } -} -bool Sll2Layer::isDataValid(const uint8_t* data, size_t dataLen) -{ - return data && dataLen >= sizeof(sll2_header); -} + bool Sll2Layer::isDataValid(const uint8_t* data, size_t dataLen) + { + return data && dataLen >= sizeof(sll2_header); + } -std::string Sll2Layer::toString() const -{ - return "Linux cooked header v2"; -} + std::string Sll2Layer::toString() const + { + return "Linux cooked header v2"; + } -uint16_t Sll2Layer::getProtocolType() const -{ - return be16toh(getSll2Header()->protocol_type); -} + uint16_t Sll2Layer::getProtocolType() const + { + return be16toh(getSll2Header()->protocol_type); + } -void Sll2Layer::setProtocolType(uint16_t protocolType) -{ - getSll2Header()->protocol_type = htobe16(protocolType); -} + void Sll2Layer::setProtocolType(uint16_t protocolType) + { + getSll2Header()->protocol_type = htobe16(protocolType); + } -uint32_t Sll2Layer::getInterfaceIndex() const -{ - return be32toh(getSll2Header()->interface_index); -} + uint32_t Sll2Layer::getInterfaceIndex() const + { + return be32toh(getSll2Header()->interface_index); + } -void Sll2Layer::setInterfaceIndex(uint32_t interfaceIndex) -{ - getSll2Header()->interface_index = htobe32(interfaceIndex); -} + void Sll2Layer::setInterfaceIndex(uint32_t interfaceIndex) + { + getSll2Header()->interface_index = htobe32(interfaceIndex); + } -uint16_t Sll2Layer::getArphrdType() const -{ - return be16toh(getSll2Header()->ARPHRD_type); -} + uint16_t Sll2Layer::getArphrdType() const + { + return be16toh(getSll2Header()->ARPHRD_type); + } -void Sll2Layer::setArphrdType(uint16_t arphrdType) -{ - getSll2Header()->ARPHRD_type = htobe16(arphrdType); -} + void Sll2Layer::setArphrdType(uint16_t arphrdType) + { + getSll2Header()->ARPHRD_type = htobe16(arphrdType); + } -uint8_t Sll2Layer::getPacketType() const -{ - return getSll2Header()->packet_type; -} + uint8_t Sll2Layer::getPacketType() const + { + return getSll2Header()->packet_type; + } -void Sll2Layer::setPacketType(uint8_t packetType) -{ - getSll2Header()->packet_type = packetType; -} + void Sll2Layer::setPacketType(uint8_t packetType) + { + getSll2Header()->packet_type = packetType; + } -uint8_t Sll2Layer::getLinkLayerAddrLen() const -{ - return getSll2Header()->link_layer_addr_len; -} + uint8_t Sll2Layer::getLinkLayerAddrLen() const + { + return getSll2Header()->link_layer_addr_len; + } -const uint8_t *Sll2Layer::getLinkLayerAddr() const -{ - return getSll2Header()->link_layer_addr; -} + const uint8_t* Sll2Layer::getLinkLayerAddr() const + { + return getSll2Header()->link_layer_addr; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SllLayer.cpp b/Packet++/src/SllLayer.cpp index 27497b48f5..405990cc99 100644 --- a/Packet++/src/SllLayer.cpp +++ b/Packet++/src/SllLayer.cpp @@ -15,95 +15,94 @@ namespace pcpp { -SllLayer::SllLayer(uint16_t packetType, uint16_t ARPHRDType) -{ - const size_t headerLen = sizeof(sll_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - sll_header* sllHdr = (sll_header*)m_Data; - sllHdr->packet_type = htobe16(packetType); - sllHdr->ARPHRD_type = htobe16(ARPHRDType); - m_Protocol = SLL; -} - -bool SllLayer::setLinkLayerAddr(uint8_t* addr, size_t addrLength) -{ - if (addr == nullptr || addrLength == 0 || addrLength > 8) + SllLayer::SllLayer(uint16_t packetType, uint16_t ARPHRDType) { - PCPP_LOG_ERROR("Address length is out of bounds, it must be between 1 and 8"); - return false; + const size_t headerLen = sizeof(sll_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + sll_header* sllHdr = (sll_header*)m_Data; + sllHdr->packet_type = htobe16(packetType); + sllHdr->ARPHRD_type = htobe16(ARPHRDType); + m_Protocol = SLL; } - sll_header* sllHdr = getSllHeader(); - memcpy(sllHdr->link_layer_addr, addr, addrLength); - sllHdr->link_layer_addr_len = htobe16(addrLength); - - return true; -} - -bool SllLayer::setMacAddressAsLinkLayer(MacAddress const& macAddr) -{ - uint8_t macAddrAsArr[6]; - macAddr.copyTo(macAddrAsArr); - return setLinkLayerAddr(macAddrAsArr, 6); -} + bool SllLayer::setLinkLayerAddr(uint8_t* addr, size_t addrLength) + { + if (addr == nullptr || addrLength == 0 || addrLength > 8) + { + PCPP_LOG_ERROR("Address length is out of bounds, it must be between 1 and 8"); + return false; + } -void SllLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(sll_header)) - return; + sll_header* sllHdr = getSllHeader(); + memcpy(sllHdr->link_layer_addr, addr, addrLength); + sllHdr->link_layer_addr_len = htobe16(addrLength); - uint8_t* payload = m_Data + sizeof(sll_header); - size_t payloadLen = m_DataLen - sizeof(sll_header); + return true; + } - sll_header* hdr = getSllHeader(); - switch (be16toh(hdr->protocol_type)) + bool SllLayer::setMacAddressAsLinkLayer(MacAddress const& macAddr) { - case PCPP_ETHERTYPE_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_ARP: - m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_VLAN: - case PCPP_ETHERTYPE_IEEE_802_1AD: - m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_PPPOES: - m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_PPPOED: - m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_MPLS: - m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); - break; - default: - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + uint8_t macAddrAsArr[6]; + macAddr.copyTo(macAddrAsArr); + return setLinkLayerAddr(macAddrAsArr, 6); } -} + void SllLayer::parseNextLayer() + { + if (m_DataLen <= sizeof(sll_header)) + return; -void SllLayer::computeCalculateFields() -{ - if (m_NextLayer == nullptr) - return; + uint8_t* payload = m_Data + sizeof(sll_header); + size_t payloadLen = m_DataLen - sizeof(sll_header); - sll_header* hdr = getSllHeader(); - switch (m_NextLayer->getProtocol()) + sll_header* hdr = getSllHeader(); + switch (be16toh(hdr->protocol_type)) + { + case PCPP_ETHERTYPE_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_ARP: + m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_VLAN: + case PCPP_ETHERTYPE_IEEE_802_1AD: + m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_PPPOES: + m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_PPPOED: + m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_MPLS: + m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); + break; + default: + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } + } + + void SllLayer::computeCalculateFields() { + if (m_NextLayer == nullptr) + return; + + sll_header* hdr = getSllHeader(); + switch (m_NextLayer->getProtocol()) + { case IPv4: hdr->protocol_type = htobe16(PCPP_ETHERTYPE_IP); break; @@ -118,12 +117,12 @@ void SllLayer::computeCalculateFields() break; default: return; + } } -} -std::string SllLayer::toString() const -{ - return "Linux cooked header"; -} + std::string SllLayer::toString() const + { + return "Linux cooked header"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SmtpLayer.cpp b/Packet++/src/SmtpLayer.cpp index 214c0db759..dc633c9a2f 100644 --- a/Packet++/src/SmtpLayer.cpp +++ b/Packet++/src/SmtpLayer.cpp @@ -7,7 +7,10 @@ namespace pcpp { // ----------------- Class SmtpRequestLayer ----------------- - bool SmtpRequestLayer::setCommand(SmtpCommand code) { return setCommandInternal(getCommandAsString(code)); } + bool SmtpRequestLayer::setCommand(SmtpCommand code) + { + return setCommandInternal(getCommandAsString(code)); + } SmtpRequestLayer::SmtpCommand SmtpRequestLayer::getCommand() const { @@ -20,9 +23,15 @@ namespace pcpp return static_cast(val); } - std::string SmtpRequestLayer::getCommandString() const { return getCommandInternal(); } + std::string SmtpRequestLayer::getCommandString() const + { + return getCommandInternal(); + } - bool SmtpRequestLayer::setCommandOption(const std::string &value) { return setCommandOptionInternal(value); } + bool SmtpRequestLayer::setCommandOption(const std::string& value) + { + return setCommandOptionInternal(value); + } std::string SmtpRequestLayer::getCommandOption(bool removeEscapeCharacters) const { @@ -107,7 +116,7 @@ namespace pcpp for (size_t idx = 0; idx < 8; ++idx) { char val = (uint64_t(code) >> (8 * idx)) & UINT8_MAX; - if (val) // Dont push if it is a null character + if (val) // Dont push if it is a null character { oss << val; } @@ -133,9 +142,15 @@ namespace pcpp return static_cast(atoi(getCommandInternal().c_str())); } - std::string SmtpResponseLayer::getStatusCodeString() const { return getCommandInternal(); } + std::string SmtpResponseLayer::getStatusCodeString() const + { + return getCommandInternal(); + } - bool SmtpResponseLayer::setStatusOption(const std::string &value) { return setCommandOptionInternal(value); } + bool SmtpResponseLayer::setStatusOption(const std::string& value) + { + return setCommandOptionInternal(value); + } std::string SmtpResponseLayer::getStatusOption(bool removeEscapeCharacters) const { @@ -239,4 +254,4 @@ namespace pcpp return "SMTP response layer, status code: " + getStatusCodeAsString(getStatusCode()); } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/SomeIpLayer.cpp b/Packet++/src/SomeIpLayer.cpp index f97c006a44..9c351d0675 100644 --- a/Packet++/src/SomeIpLayer.cpp +++ b/Packet++/src/SomeIpLayer.cpp @@ -12,355 +12,348 @@ namespace pcpp { -// SomeIpLayer + // SomeIpLayer -void splitUint32Id(uint32_t uint32Id, uint16_t &uint16IdUpper, uint16_t &uint16IdLower) -{ - uint16IdLower = (uint32Id & 0x0000ffff); - uint16IdUpper = (uint32Id & 0xffff0000) >> 16; -} - -std::unordered_set SomeIpLayer::m_SomeIpPorts{}; - -SomeIpLayer::SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, - uint8_t interfaceVersion, MsgType type, uint8_t returnCode, const uint8_t *const data, - size_t dataLen) -{ - const size_t headerLen = sizeof(someiphdr); - m_DataLen = headerLen + dataLen; - m_Data = new uint8_t[m_DataLen]; - m_Protocol = SomeIP; - memset(m_Data, 0, headerLen); - memcpy(m_Data + headerLen, data, dataLen); - - setServiceID(serviceID); - setMethodID(methodID); - setPayloadLength((uint32_t)dataLen); - setClientID(clientID); - setSessionID(sessionID); - setProtocolVersion(0x01); - setInterfaceVersion(interfaceVersion); - setMessageType(type); - setReturnCode(returnCode); -} - -Layer* SomeIpLayer::parseSomeIpLayer(uint8_t *data, size_t dataLen, Layer* prevLayer, Packet* packet) -{ - /* Ideas taken from wireshark some ip dissector */ - const size_t headerLen = sizeof(someiphdr); - if (dataLen < headerLen) - return new PayloadLayer(data, dataLen, prevLayer, packet); - - uint32_t lengthBE = 0; - memcpy(&lengthBE, data + sizeof(uint32_t), sizeof(uint32_t)); // length field in SOME/IP header - uint32_t length = be32toh(lengthBE); - if ((length < 8) || (length > dataLen - 8)) - return new PayloadLayer(data, dataLen, prevLayer, packet); - - if (data[12] != SOMEIP_PROTOCOL_VERSION) - return new PayloadLayer(data, dataLen, prevLayer, packet); + void splitUint32Id(uint32_t uint32Id, uint16_t& uint16IdUpper, uint16_t& uint16IdLower) + { + uint16IdLower = (uint32Id & 0x0000ffff); + uint16IdUpper = (uint32Id & 0xffff0000) >> 16; + } - someiphdr *hdr = (someiphdr *)data; + std::unordered_set SomeIpLayer::m_SomeIpPorts{}; - switch (static_cast(hdr->msgType & ~(uint8_t)MsgType::TP_REQUEST)) + SomeIpLayer::SomeIpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, const uint8_t* const data, + size_t dataLen) { - case MsgType::REQUEST: - case MsgType::REQUEST_ACK: - case MsgType::REQUEST_NO_RETURN: - case MsgType::REQUEST_NO_RETURN_ACK: - case MsgType::NOTIFICATION: - case MsgType::NOTIFICATION_ACK: - case MsgType::RESPONSE: - case MsgType::RESPONSE_ACK: - case MsgType::ERRORS: - case MsgType::ERROR_ACK: - break; - default: - return new PayloadLayer(data, dataLen, prevLayer, packet); + const size_t headerLen = sizeof(someiphdr); + m_DataLen = headerLen + dataLen; + m_Data = new uint8_t[m_DataLen]; + m_Protocol = SomeIP; + memset(m_Data, 0, headerLen); + memcpy(m_Data + headerLen, data, dataLen); + + setServiceID(serviceID); + setMethodID(methodID); + setPayloadLength((uint32_t)dataLen); + setClientID(clientID); + setSessionID(sessionID); + setProtocolVersion(0x01); + setInterfaceVersion(interfaceVersion); + setMessageType(type); + setReturnCode(returnCode); } - if (be16toh(hdr->serviceID) == 0xFFFF && be16toh(hdr->methodID) == 0x8100 && SomeIpSdLayer::isDataValid(data, dataLen)) + Layer* SomeIpLayer::parseSomeIpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) { - return new SomeIpSdLayer(data, dataLen, prevLayer, packet); + /* Ideas taken from wireshark some ip dissector */ + const size_t headerLen = sizeof(someiphdr); + if (dataLen < headerLen) + return new PayloadLayer(data, dataLen, prevLayer, packet); + + uint32_t lengthBE = 0; + memcpy(&lengthBE, data + sizeof(uint32_t), sizeof(uint32_t)); // length field in SOME/IP header + uint32_t length = be32toh(lengthBE); + if ((length < 8) || (length > dataLen - 8)) + return new PayloadLayer(data, dataLen, prevLayer, packet); + + if (data[12] != SOMEIP_PROTOCOL_VERSION) + return new PayloadLayer(data, dataLen, prevLayer, packet); + + someiphdr* hdr = (someiphdr*)data; + + switch (static_cast(hdr->msgType & ~(uint8_t)MsgType::TP_REQUEST)) + { + case MsgType::REQUEST: + case MsgType::REQUEST_ACK: + case MsgType::REQUEST_NO_RETURN: + case MsgType::REQUEST_NO_RETURN_ACK: + case MsgType::NOTIFICATION: + case MsgType::NOTIFICATION_ACK: + case MsgType::RESPONSE: + case MsgType::RESPONSE_ACK: + case MsgType::ERRORS: + case MsgType::ERROR_ACK: + break; + default: + return new PayloadLayer(data, dataLen, prevLayer, packet); + } + + if (be16toh(hdr->serviceID) == 0xFFFF && be16toh(hdr->methodID) == 0x8100 && + SomeIpSdLayer::isDataValid(data, dataLen)) + { + return new SomeIpSdLayer(data, dataLen, prevLayer, packet); + } + else if ((hdr->msgType & (uint8_t)SomeIpLayer::MsgType::TP_REQUEST) != 0) + { + return new SomeIpTpLayer(data, dataLen, prevLayer, packet); + } + else + { + return new SomeIpLayer(data, dataLen, prevLayer, packet); + } } - else if ((hdr->msgType & (uint8_t)SomeIpLayer::MsgType::TP_REQUEST) != 0) + + bool SomeIpLayer::isSomeIpPort(uint16_t port) { - return new SomeIpTpLayer(data, dataLen, prevLayer, packet); + return SomeIpSdLayer::isSomeIpSdPort(port) || + std::any_of(m_SomeIpPorts.begin(), m_SomeIpPorts.end(), + [&](const uint16_t& someIpPort) { return someIpPort == port; }); } - else + + void SomeIpLayer::addSomeIpPort(uint16_t port) { - return new SomeIpLayer(data, dataLen, prevLayer, packet); + m_SomeIpPorts.insert(port); } -} - -bool SomeIpLayer::isSomeIpPort(uint16_t port) -{ - return SomeIpSdLayer::isSomeIpSdPort(port) || - std::any_of(m_SomeIpPorts.begin(), m_SomeIpPorts.end(), - [&](const uint16_t &someIpPort) { return someIpPort == port; }); -} - -void SomeIpLayer::addSomeIpPort(uint16_t port) -{ - m_SomeIpPorts.insert(port); -} -void SomeIpLayer::removeSomeIpPort(uint16_t port) -{ - m_SomeIpPorts.erase(port); -} - -void SomeIpLayer::removeAllSomeIpPorts() -{ - m_SomeIpPorts.clear(); -} - -uint32_t SomeIpLayer::getMessageID() const -{ - someiphdr *hdr = getSomeIpHeader(); + void SomeIpLayer::removeSomeIpPort(uint16_t port) + { + m_SomeIpPorts.erase(port); + } - return ((uint32_t)be16toh(hdr->serviceID) << 16) + be16toh(hdr->methodID); -} + void SomeIpLayer::removeAllSomeIpPorts() + { + m_SomeIpPorts.clear(); + } -void SomeIpLayer::setMessageID(uint32_t messageID) -{ - uint16_t methodID; - uint16_t serviceID; + uint32_t SomeIpLayer::getMessageID() const + { + someiphdr* hdr = getSomeIpHeader(); - splitUint32Id(messageID, serviceID, methodID); + return ((uint32_t)be16toh(hdr->serviceID) << 16) + be16toh(hdr->methodID); + } - someiphdr *hdr = getSomeIpHeader(); - hdr->serviceID = htobe16(serviceID); - hdr->methodID = htobe16(methodID); -} + void SomeIpLayer::setMessageID(uint32_t messageID) + { + uint16_t methodID; + uint16_t serviceID; -uint16_t SomeIpLayer::getServiceID() const -{ - return be16toh(getSomeIpHeader()->serviceID); -} + splitUint32Id(messageID, serviceID, methodID); -void SomeIpLayer::setServiceID(uint16_t serviceID) -{ - getSomeIpHeader()->serviceID = htobe16(serviceID); -} + someiphdr* hdr = getSomeIpHeader(); + hdr->serviceID = htobe16(serviceID); + hdr->methodID = htobe16(methodID); + } -uint16_t SomeIpLayer::getMethodID() const -{ - return be16toh(getSomeIpHeader()->methodID); -} + uint16_t SomeIpLayer::getServiceID() const + { + return be16toh(getSomeIpHeader()->serviceID); + } -void SomeIpLayer::setMethodID(uint16_t methodID) -{ - getSomeIpHeader()->methodID = htobe16(methodID); -} + void SomeIpLayer::setServiceID(uint16_t serviceID) + { + getSomeIpHeader()->serviceID = htobe16(serviceID); + } -uint32_t SomeIpLayer::getLengthField() const -{ - return be32toh(getSomeIpHeader()->length); -} + uint16_t SomeIpLayer::getMethodID() const + { + return be16toh(getSomeIpHeader()->methodID); + } -uint32_t SomeIpLayer::getRequestID() const -{ - someiphdr *hdr = getSomeIpHeader(); + void SomeIpLayer::setMethodID(uint16_t methodID) + { + getSomeIpHeader()->methodID = htobe16(methodID); + } - return ((uint32_t)be16toh(hdr->clientID) << 16) + be16toh(hdr->sessionID); -} + uint32_t SomeIpLayer::getLengthField() const + { + return be32toh(getSomeIpHeader()->length); + } -void SomeIpLayer::setRequestID(uint32_t requestID) -{ - uint16_t clientID; - uint16_t sessionID; + uint32_t SomeIpLayer::getRequestID() const + { + someiphdr* hdr = getSomeIpHeader(); - splitUint32Id(requestID, clientID, sessionID); + return ((uint32_t)be16toh(hdr->clientID) << 16) + be16toh(hdr->sessionID); + } - someiphdr *hdr = getSomeIpHeader(); - hdr->clientID = htobe16(clientID); - hdr->sessionID = htobe16(sessionID); -} + void SomeIpLayer::setRequestID(uint32_t requestID) + { + uint16_t clientID; + uint16_t sessionID; -uint16_t SomeIpLayer::getClientID() const -{ - return be16toh(getSomeIpHeader()->clientID); -} + splitUint32Id(requestID, clientID, sessionID); -void SomeIpLayer::setClientID(uint16_t clientID) -{ - getSomeIpHeader()->clientID = htobe16(clientID); -} + someiphdr* hdr = getSomeIpHeader(); + hdr->clientID = htobe16(clientID); + hdr->sessionID = htobe16(sessionID); + } -uint16_t SomeIpLayer::getSessionID() const -{ - return be16toh(getSomeIpHeader()->sessionID); -} + uint16_t SomeIpLayer::getClientID() const + { + return be16toh(getSomeIpHeader()->clientID); + } -void SomeIpLayer::setSessionID(uint16_t sessionID) -{ - getSomeIpHeader()->sessionID = htobe16(sessionID); -} + void SomeIpLayer::setClientID(uint16_t clientID) + { + getSomeIpHeader()->clientID = htobe16(clientID); + } -uint8_t SomeIpLayer::getProtocolVersion() const -{ - return getSomeIpHeader()->protocolVersion; -} + uint16_t SomeIpLayer::getSessionID() const + { + return be16toh(getSomeIpHeader()->sessionID); + } -void SomeIpLayer::setProtocolVersion(uint8_t version) -{ - getSomeIpHeader()->protocolVersion = version; -} + void SomeIpLayer::setSessionID(uint16_t sessionID) + { + getSomeIpHeader()->sessionID = htobe16(sessionID); + } -uint8_t SomeIpLayer::getInterfaceVersion() const -{ - return getSomeIpHeader()->interfaceVersion; -} + uint8_t SomeIpLayer::getProtocolVersion() const + { + return getSomeIpHeader()->protocolVersion; + } -void SomeIpLayer::setInterfaceVersion(uint8_t version) -{ - getSomeIpHeader()->interfaceVersion = version; -} + void SomeIpLayer::setProtocolVersion(uint8_t version) + { + getSomeIpHeader()->protocolVersion = version; + } -SomeIpLayer::MsgType SomeIpLayer::getMessageType() const -{ - return static_cast(getSomeIpHeader()->msgType); -} + uint8_t SomeIpLayer::getInterfaceVersion() const + { + return getSomeIpHeader()->interfaceVersion; + } -uint8_t SomeIpLayer::getMessageTypeAsInt() const -{ - return getSomeIpHeader()->msgType; -} + void SomeIpLayer::setInterfaceVersion(uint8_t version) + { + getSomeIpHeader()->interfaceVersion = version; + } -void SomeIpLayer::setMessageType(MsgType type) -{ - setMessageType(static_cast(type)); -} + SomeIpLayer::MsgType SomeIpLayer::getMessageType() const + { + return static_cast(getSomeIpHeader()->msgType); + } -void SomeIpLayer::setMessageType(uint8_t type) -{ - getSomeIpHeader()->msgType = type; -} + uint8_t SomeIpLayer::getMessageTypeAsInt() const + { + return getSomeIpHeader()->msgType; + } -uint8_t SomeIpLayer::getReturnCode() const -{ - return getSomeIpHeader()->returnCode; -} + void SomeIpLayer::setMessageType(MsgType type) + { + setMessageType(static_cast(type)); + } -void SomeIpLayer::setReturnCode(uint8_t returnCode) -{ - getSomeIpHeader()->returnCode = returnCode; -} + void SomeIpLayer::setMessageType(uint8_t type) + { + getSomeIpHeader()->msgType = type; + } -void SomeIpLayer::setPayloadLength(uint32_t payloadLength) -{ - someiphdr *hdr = getSomeIpHeader(); - hdr->length = htobe32(sizeof(someiphdr) - sizeof(hdr->serviceID) - sizeof(hdr->methodID) - sizeof(hdr->length) + - payloadLength); -} + uint8_t SomeIpLayer::getReturnCode() const + { + return getSomeIpHeader()->returnCode; + } -void SomeIpLayer::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; + void SomeIpLayer::setReturnCode(uint8_t returnCode) + { + getSomeIpHeader()->returnCode = returnCode; + } - uint8_t *payload = m_Data + headerLen; - size_t payloadLen = m_DataLen - headerLen; + void SomeIpLayer::setPayloadLength(uint32_t payloadLength) + { + someiphdr* hdr = getSomeIpHeader(); + hdr->length = htobe32(sizeof(someiphdr) - sizeof(hdr->serviceID) - sizeof(hdr->methodID) - sizeof(hdr->length) + + payloadLength); + } - m_NextLayer = parseSomeIpLayer(payload, payloadLen, this, m_Packet); -} + void SomeIpLayer::parseNextLayer() + { + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; -std::string SomeIpLayer::toString() const -{ - std::stringstream dataStream; + uint8_t* payload = m_Data + headerLen; + size_t payloadLen = m_DataLen - headerLen; - dataStream << "SOME/IP Layer" - << std::hex - << ", Service ID: 0x" << getServiceID() - << ", Method ID: 0x" << getMethodID() - << std::dec - << ", Length: " << getLengthField(); + m_NextLayer = parseSomeIpLayer(payload, payloadLen, this, m_Packet); + } - return dataStream.str(); -} + std::string SomeIpLayer::toString() const + { + std::stringstream dataStream; -// SomeIpTpLayer + dataStream << "SOME/IP Layer" << std::hex << ", Service ID: 0x" << getServiceID() << ", Method ID: 0x" + << getMethodID() << std::dec << ", Length: " << getLengthField(); -SomeIpTpLayer::SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, - uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, - bool moreSegmentsFlag, const uint8_t *const data, size_t dataLen) -{ - const size_t headerLen = sizeof(someiptphdr); - - m_DataLen = headerLen + dataLen; - m_Data = new uint8_t[m_DataLen]; - m_Protocol = SomeIP; - memset(m_Data, 0, headerLen); - memcpy(m_Data + headerLen, data, dataLen); - - setServiceID(serviceID); - setMethodID(methodID); - setPayloadLength((uint32_t)(dataLen + sizeof(uint32_t))); - setClientID(clientID); - setSessionID(sessionID); - setProtocolVersion(0x01); - setInterfaceVersion(interfaceVersion); - setMessageType(setTpFlag((uint8_t)type)); - setReturnCode(returnCode); - setOffset(offset); - setMoreSegmentsFlag(moreSegmentsFlag); -} - -uint32_t SomeIpTpLayer::getOffset() const -{ - return (be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_OFFSET_MASK) >> 4; -} + return dataStream.str(); + } -void SomeIpTpLayer::setOffset(uint32_t offset) -{ - uint32_t val = (offset << 4) | (be32toh(getSomeIpTpHeader()->offsetAndFlag) & ~SOMEIP_TP_OFFSET_MASK); - getSomeIpTpHeader()->offsetAndFlag = htobe32(val); -} + // SomeIpTpLayer -bool SomeIpTpLayer::getMoreSegmentsFlag() const -{ - return be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_MORE_FLAG_MASK; -} + SomeIpTpLayer::SomeIpTpLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint32_t offset, + bool moreSegmentsFlag, const uint8_t* const data, size_t dataLen) + { + const size_t headerLen = sizeof(someiptphdr); + + m_DataLen = headerLen + dataLen; + m_Data = new uint8_t[m_DataLen]; + m_Protocol = SomeIP; + memset(m_Data, 0, headerLen); + memcpy(m_Data + headerLen, data, dataLen); + + setServiceID(serviceID); + setMethodID(methodID); + setPayloadLength((uint32_t)(dataLen + sizeof(uint32_t))); + setClientID(clientID); + setSessionID(sessionID); + setProtocolVersion(0x01); + setInterfaceVersion(interfaceVersion); + setMessageType(setTpFlag((uint8_t)type)); + setReturnCode(returnCode); + setOffset(offset); + setMoreSegmentsFlag(moreSegmentsFlag); + } -void SomeIpTpLayer::setMoreSegmentsFlag(bool flag) -{ - uint32_t val = be32toh(getSomeIpTpHeader()->offsetAndFlag); + uint32_t SomeIpTpLayer::getOffset() const + { + return (be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_OFFSET_MASK) >> 4; + } - if (flag) + void SomeIpTpLayer::setOffset(uint32_t offset) { - val = val | SOMEIP_TP_MORE_FLAG_MASK; + uint32_t val = (offset << 4) | (be32toh(getSomeIpTpHeader()->offsetAndFlag) & ~SOMEIP_TP_OFFSET_MASK); + getSomeIpTpHeader()->offsetAndFlag = htobe32(val); } - else + + bool SomeIpTpLayer::getMoreSegmentsFlag() const { - val = val & ~SOMEIP_TP_MORE_FLAG_MASK; + return be32toh(getSomeIpTpHeader()->offsetAndFlag) & SOMEIP_TP_MORE_FLAG_MASK; } - getSomeIpTpHeader()->offsetAndFlag = htobe32(val); -} + void SomeIpTpLayer::setMoreSegmentsFlag(bool flag) + { + uint32_t val = be32toh(getSomeIpTpHeader()->offsetAndFlag); + + if (flag) + { + val = val | SOMEIP_TP_MORE_FLAG_MASK; + } + else + { + val = val & ~SOMEIP_TP_MORE_FLAG_MASK; + } + + getSomeIpTpHeader()->offsetAndFlag = htobe32(val); + } -void SomeIpTpLayer::computeCalculateFields() -{ - setMessageType(setTpFlag(getMessageTypeAsInt())); -} + void SomeIpTpLayer::computeCalculateFields() + { + setMessageType(setTpFlag(getMessageTypeAsInt())); + } -std::string SomeIpTpLayer::toString() const -{ - std::stringstream dataStream; + std::string SomeIpTpLayer::toString() const + { + std::stringstream dataStream; - dataStream << "SOME/IP-TP Layer" - << std::hex - << ", Service ID: 0x" << getServiceID() - << ", Method ID: 0x" << getMethodID() - << std::dec - << ", Length: " << getLengthField(); + dataStream << "SOME/IP-TP Layer" << std::hex << ", Service ID: 0x" << getServiceID() << ", Method ID: 0x" + << getMethodID() << std::dec << ", Length: " << getLengthField(); - return dataStream.str(); -} + return dataStream.str(); + } -uint8_t SomeIpTpLayer::setTpFlag(uint8_t messageType) -{ - return messageType | (uint8_t)SomeIpLayer::MsgType::TP_REQUEST; -} -} // namespace pcpp + uint8_t SomeIpTpLayer::setTpFlag(uint8_t messageType) + { + return messageType | (uint8_t)SomeIpLayer::MsgType::TP_REQUEST; + } +} // namespace pcpp diff --git a/Packet++/src/SomeIpSdLayer.cpp b/Packet++/src/SomeIpSdLayer.cpp index 89a20d92b1..2538959944 100644 --- a/Packet++/src/SomeIpSdLayer.cpp +++ b/Packet++/src/SomeIpSdLayer.cpp @@ -10,561 +10,519 @@ namespace pcpp { -/* - * SomeIpSdOption - */ -SomeIpSdOption::~SomeIpSdOption() -{ - if (m_ShadowData != nullptr) - delete[] m_ShadowData; -} - -SomeIpSdOption::OptionType SomeIpSdOption::getType() const { - return static_cast(getSomeIpSdOptionHeader()->type); -} + /* + * SomeIpSdOption + */ + SomeIpSdOption::~SomeIpSdOption() + { + if (m_ShadowData != nullptr) + delete[] m_ShadowData; + } -uint8_t* SomeIpSdOption::getDataPtr() const -{ - if (m_DataContainer != nullptr) - return m_DataContainer->getDataPtr(m_Offset); + SomeIpSdOption::OptionType SomeIpSdOption::getType() const + { + return static_cast(getSomeIpSdOptionHeader()->type); + } - return m_ShadowData; -} + uint8_t* SomeIpSdOption::getDataPtr() const + { + if (m_DataContainer != nullptr) + return m_DataContainer->getDataPtr(m_Offset); -SomeIpSdOption::someipsdhdroptionsbase *SomeIpSdOption::getSomeIpSdOptionHeader() const -{ - return (someipsdhdroptionsbase *)getDataPtr(); -} + return m_ShadowData; + } -void SomeIpSdOption::initStdFields(OptionType type) -{ - someipsdhdroptionsbase *optionHdr = getSomeIpSdOptionHeader(); - - optionHdr->type = static_cast(type); - /* Length field is excluding length field itself and uint8_t type field */ - optionHdr->length = htobe16((uint16_t)(m_DataLen - sizeof(optionHdr->length) - sizeof(optionHdr->type))); -} - -/* - * SomeIpSdIPv4Option - */ -SomeIpSdIPv4Option::SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port, - SomeIpSdProtocolType l4Protocol) -{ - m_DataLen = sizeof(someipsdhdroptionsipv4); - m_ShadowData = new uint8_t[m_DataLen]; - memset(m_ShadowData, 0, m_DataLen); - - switch(type) - { - case IPv4OptionType::IPv4Endpoint: - initStdFields(OptionType::IPv4Endpoint); - break; - case IPv4OptionType::IPv4Multicast: - initStdFields(OptionType::IPv4Multicast); - break; - case IPv4OptionType::IPv4SdEndpoint: - initStdFields(OptionType::IPv4SdEndpoint); - break; - } - - someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); - hdr->ipv4Address = ipAddress.toInt(); - hdr->portNumber = htobe16(port); - hdr->l4Protocol = l4Protocol; -} - -SomeIpSdIPv4Option::SomeIpSdIPv4Option(const IDataContainer *dataContainer, size_t offset) - : SomeIpSdOption(dataContainer, offset) -{ - m_DataLen = sizeof(someipsdhdroptionsipv4); -} + SomeIpSdOption::someipsdhdroptionsbase* SomeIpSdOption::getSomeIpSdOptionHeader() const + { + return (someipsdhdroptionsbase*)getDataPtr(); + } -IPv4Address SomeIpSdIPv4Option::getIpAddress() const -{ - someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); - IPv4Address ipAddr(hdr->ipv4Address); + void SomeIpSdOption::initStdFields(OptionType type) + { + someipsdhdroptionsbase* optionHdr = getSomeIpSdOptionHeader(); - return ipAddr; -} + optionHdr->type = static_cast(type); + /* Length field is excluding length field itself and uint8_t type field */ + optionHdr->length = htobe16((uint16_t)(m_DataLen - sizeof(optionHdr->length) - sizeof(optionHdr->type))); + } -uint16_t SomeIpSdIPv4Option::getPort() const -{ - someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); - return be16toh(hdr->portNumber); -} + /* + * SomeIpSdIPv4Option + */ + SomeIpSdIPv4Option::SomeIpSdIPv4Option(IPv4OptionType type, IPv4Address ipAddress, uint16_t port, + SomeIpSdProtocolType l4Protocol) + { + m_DataLen = sizeof(someipsdhdroptionsipv4); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); -SomeIpSdProtocolType SomeIpSdIPv4Option::getProtocol() const -{ - someipsdhdroptionsipv4 *hdr = (someipsdhdroptionsipv4 *)getDataPtr(); - return hdr->l4Protocol; -} - -/* - * SomeIpSdIPv6Option - */ -SomeIpSdIPv6Option::SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port, - SomeIpSdProtocolType l4Protocol) -{ - m_DataLen = sizeof(someipsdhdroptionsipv6); - m_ShadowData = new uint8_t[m_DataLen]; - memset(m_ShadowData, 0, m_DataLen); - - switch(type) - { - case IPv6OptionType::IPv6Endpoint: - initStdFields(OptionType::IPv6Endpoint); - break; - case IPv6OptionType::IPv6Multicast: - initStdFields(OptionType::IPv6Multicast); - break; - case IPv6OptionType::IPv6SdEndpoint: - initStdFields(OptionType::IPv6SdEndpoint); - break; - } - - someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); - std::memcpy(hdr->ipv6Address, ipAddress.toBytes(), 16); - hdr->portNumber = htobe16(port); - hdr->l4Protocol = l4Protocol; -} - -SomeIpSdIPv6Option::SomeIpSdIPv6Option(const IDataContainer *dataContainer, size_t offset) - : SomeIpSdOption(dataContainer, offset) -{ - m_DataLen = sizeof(someipsdhdroptionsipv6); -} + switch (type) + { + case IPv4OptionType::IPv4Endpoint: + initStdFields(OptionType::IPv4Endpoint); + break; + case IPv4OptionType::IPv4Multicast: + initStdFields(OptionType::IPv4Multicast); + break; + case IPv4OptionType::IPv4SdEndpoint: + initStdFields(OptionType::IPv4SdEndpoint); + break; + } -IPv6Address SomeIpSdIPv6Option::getIpAddress() const -{ - someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); - IPv6Address ipAddr(hdr->ipv6Address); + someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr(); + hdr->ipv4Address = ipAddress.toInt(); + hdr->portNumber = htobe16(port); + hdr->l4Protocol = l4Protocol; + } - return ipAddr; -} + SomeIpSdIPv4Option::SomeIpSdIPv4Option(const IDataContainer* dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) + { + m_DataLen = sizeof(someipsdhdroptionsipv4); + } -uint16_t SomeIpSdIPv6Option::getPort() const -{ - someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); - return be16toh(hdr->portNumber); -} + IPv4Address SomeIpSdIPv4Option::getIpAddress() const + { + someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr(); + IPv4Address ipAddr(hdr->ipv4Address); -SomeIpSdProtocolType SomeIpSdIPv6Option::getProtocol() const -{ - someipsdhdroptionsipv6 *hdr = (someipsdhdroptionsipv6 *)getDataPtr(); - return hdr->l4Protocol; -} - -/* - * SomeIpSdConfigurationOption - */ -SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const std::string &configurationString) -{ - m_DataLen = configurationString.length() + sizeof(someipsdhdroptionsbase); - m_ShadowData = new uint8_t[m_DataLen]; - memset(m_ShadowData, 0, m_DataLen); + return ipAddr; + } - initStdFields(OptionType::ConfigurationString); - std::memcpy(getDataPtr() + sizeof(someipsdhdroptionsbase), configurationString.c_str(), - configurationString.length()); -} + uint16_t SomeIpSdIPv4Option::getPort() const + { + someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr(); + return be16toh(hdr->portNumber); + } -SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const IDataContainer *dataContainer, size_t offset) - : SomeIpSdOption(dataContainer, offset) -{ - m_DataLen = sizeof(someipsdhdroptionsbase) - 1 + be16toh(getSomeIpSdOptionHeader()->length); -} + SomeIpSdProtocolType SomeIpSdIPv4Option::getProtocol() const + { + someipsdhdroptionsipv4* hdr = (someipsdhdroptionsipv4*)getDataPtr(); + return hdr->l4Protocol; + } -std::string SomeIpSdConfigurationOption::getConfigurationString() const -{ - return std::string((char *)getDataPtr() + sizeof(someipsdhdroptionsbase), - be16toh(getSomeIpSdOptionHeader()->length) - 1); -} - -/* - * SomeIpSdLoadBalancingOption - */ -SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight) -{ - m_DataLen = sizeof(someipsdhdroptionsload); - m_ShadowData = new uint8_t[m_DataLen]; - memset(m_ShadowData, 0, m_DataLen); + /* + * SomeIpSdIPv6Option + */ + SomeIpSdIPv6Option::SomeIpSdIPv6Option(IPv6OptionType type, IPv6Address ipAddress, uint16_t port, + SomeIpSdProtocolType l4Protocol) + { + m_DataLen = sizeof(someipsdhdroptionsipv6); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); - initStdFields(OptionType::LoadBalancing); + switch (type) + { + case IPv6OptionType::IPv6Endpoint: + initStdFields(OptionType::IPv6Endpoint); + break; + case IPv6OptionType::IPv6Multicast: + initStdFields(OptionType::IPv6Multicast); + break; + case IPv6OptionType::IPv6SdEndpoint: + initStdFields(OptionType::IPv6SdEndpoint); + break; + } - someipsdhdroptionsload *hdr = (someipsdhdroptionsload *)getDataPtr(); - hdr->priority = htobe16(priority); - hdr->weight = htobe16(weight); -} + someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr(); + std::memcpy(hdr->ipv6Address, ipAddress.toBytes(), 16); + hdr->portNumber = htobe16(port); + hdr->l4Protocol = l4Protocol; + } -SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(const IDataContainer *dataContainer, size_t offset) - : SomeIpSdOption(dataContainer, offset) -{ - m_DataLen = sizeof(someipsdhdroptionsload); -} + SomeIpSdIPv6Option::SomeIpSdIPv6Option(const IDataContainer* dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) + { + m_DataLen = sizeof(someipsdhdroptionsipv6); + } -uint16_t SomeIpSdLoadBalancingOption::getPriority() const -{ - someipsdhdroptionsload *hdr = (someipsdhdroptionsload *)getDataPtr(); - return be16toh(hdr->priority); -} + IPv6Address SomeIpSdIPv6Option::getIpAddress() const + { + someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr(); + IPv6Address ipAddr(hdr->ipv6Address); -uint16_t SomeIpSdLoadBalancingOption::getWeight() const -{ - someipsdhdroptionsload *hdr = (someipsdhdroptionsload *)getDataPtr(); - return be16toh(hdr->weight); -} + return ipAddr; + } -/* - * SomeIpSdEntry - */ + uint16_t SomeIpSdIPv6Option::getPort() const + { + someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr(); + return be16toh(hdr->portNumber); + } -SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, - uint32_t TTL, uint32_t minorVersion) -{ - initStdFields(type, serviceID, instanceID, majorVersion, TTL); - setMinorVersion(minorVersion); -} + SomeIpSdProtocolType SomeIpSdIPv6Option::getProtocol() const + { + someipsdhdroptionsipv6* hdr = (someipsdhdroptionsipv6*)getDataPtr(); + return hdr->l4Protocol; + } -SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, - uint32_t TTL, uint8_t counter, uint16_t eventGroupID) -{ - initStdFields(type, serviceID, instanceID, majorVersion, TTL); - setCounter(counter); - setEventgroupId(eventGroupID); -} + /* + * SomeIpSdConfigurationOption + */ + SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const std::string& configurationString) + { + m_DataLen = configurationString.length() + sizeof(someipsdhdroptionsbase); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); -SomeIpSdEntry::SomeIpSdEntry(const SomeIpSdLayer *pSomeIpSdLayer, size_t offset) - : m_Layer(pSomeIpSdLayer), m_Offset(offset), m_ShadowData(nullptr) -{ - EntryType entryType; + initStdFields(OptionType::ConfigurationString); + std::memcpy(getDataPtr() + sizeof(someipsdhdroptionsbase), configurationString.c_str(), + configurationString.length()); + } - someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); - TypeInternal internalType = static_cast(hdr->type); - auto ttl = getTtl(); + SomeIpSdConfigurationOption::SomeIpSdConfigurationOption(const IDataContainer* dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) + { + m_DataLen = sizeof(someipsdhdroptionsbase) - 1 + be16toh(getSomeIpSdOptionHeader()->length); + } - switch(internalType) + std::string SomeIpSdConfigurationOption::getConfigurationString() const { - case SomeIpSdEntry::TypeInternal::FindService_Internal: - entryType = SomeIpSdEntry::EntryType::FindService; - break; - case SomeIpSdEntry::TypeInternal::OfferService_Internal: - if (ttl == 0) - { - entryType = EntryType::StopOfferService; - } - else - { - entryType = EntryType::OfferService; - } - break; - case SomeIpSdEntry::TypeInternal::SubscribeEventgroup_Internal: - if (ttl == 0) - { - entryType = EntryType::StopSubscribeEventgroup; - } - else - { - entryType = EntryType::SubscribeEventgroup; - } - break; - case SomeIpSdEntry::TypeInternal::SubscribeEventgroupAck_Internal: - if (ttl == 0) - { - entryType = EntryType::SubscribeEventgroupNack; - } - else - { - entryType = EntryType::SubscribeEventgroupAck; - } - break; - default: - entryType = EntryType::UnknownEntryType; - break; + return std::string((char*)getDataPtr() + sizeof(someipsdhdroptionsbase), + be16toh(getSomeIpSdOptionHeader()->length) - 1); } - m_EntryType = entryType; -} + /* + * SomeIpSdLoadBalancingOption + */ + SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(uint16_t priority, uint16_t weight) + { + m_DataLen = sizeof(someipsdhdroptionsload); + m_ShadowData = new uint8_t[m_DataLen]; + memset(m_ShadowData, 0, m_DataLen); -SomeIpSdEntry::~SomeIpSdEntry() -{ - if (m_ShadowData != nullptr) - delete[] m_ShadowData; -} + initStdFields(OptionType::LoadBalancing); -uint8_t *SomeIpSdEntry::getDataPtr() const -{ - if (m_Layer != nullptr) - return m_Layer->getDataPtr(m_Offset); + someipsdhdroptionsload* hdr = (someipsdhdroptionsload*)getDataPtr(); + hdr->priority = htobe16(priority); + hdr->weight = htobe16(weight); + } - return m_ShadowData; -} + SomeIpSdLoadBalancingOption::SomeIpSdLoadBalancingOption(const IDataContainer* dataContainer, size_t offset) + : SomeIpSdOption(dataContainer, offset) + { + m_DataLen = sizeof(someipsdhdroptionsload); + } -SomeIpSdEntry::someipsdhdrentry *SomeIpSdEntry::getSomeIpSdEntryHeader() const -{ - return (someipsdhdrentry *)getDataPtr(); -} + uint16_t SomeIpSdLoadBalancingOption::getPriority() const + { + someipsdhdroptionsload* hdr = (someipsdhdroptionsload*)getDataPtr(); + return be16toh(hdr->priority); + } -uint32_t SomeIpSdEntry::getNumOptions() const -{ - auto *hdr = getSomeIpSdEntryHeader(); - return hdr->nrOpt1 + hdr->nrOpt2; -} + uint16_t SomeIpSdLoadBalancingOption::getWeight() const + { + someipsdhdroptionsload* hdr = (someipsdhdroptionsload*)getDataPtr(); + return be16toh(hdr->weight); + } -uint16_t SomeIpSdEntry::getServiceId() const -{ - return be16toh(getSomeIpSdEntryHeader()->serviceID); -} + /* + * SomeIpSdEntry + */ -void SomeIpSdEntry::setServiceId(uint16_t serviceId) -{ - getSomeIpSdEntryHeader()->serviceID = htobe16(serviceId); -} + SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, + uint32_t TTL, uint32_t minorVersion) + { + initStdFields(type, serviceID, instanceID, majorVersion, TTL); + setMinorVersion(minorVersion); + } -uint16_t SomeIpSdEntry::getInstanceId() const -{ - return be16toh(getSomeIpSdEntryHeader()->instanceID); -} + SomeIpSdEntry::SomeIpSdEntry(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, + uint32_t TTL, uint8_t counter, uint16_t eventGroupID) + { + initStdFields(type, serviceID, instanceID, majorVersion, TTL); + setCounter(counter); + setEventgroupId(eventGroupID); + } -void SomeIpSdEntry::setInstanceId(uint16_t instanceId) -{ - getSomeIpSdEntryHeader()->instanceID = htobe16(instanceId); -} + SomeIpSdEntry::SomeIpSdEntry(const SomeIpSdLayer* pSomeIpSdLayer, size_t offset) + : m_Layer(pSomeIpSdLayer), m_Offset(offset), m_ShadowData(nullptr) + { + EntryType entryType; -uint8_t SomeIpSdEntry::getMajorVersion() const -{ - return (be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL) >> 24; -} + someipsdhdrentry* hdr = getSomeIpSdEntryHeader(); + TypeInternal internalType = static_cast(hdr->type); + auto ttl = getTtl(); -void SomeIpSdEntry::setMajorVersion(uint8_t majorVersion) -{ - someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); - uint32_t val = (majorVersion << 24) | (be32toh(hdr->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL); - hdr->majorVersion_ttl = htobe32(val); -} + switch (internalType) + { + case SomeIpSdEntry::TypeInternal::FindService_Internal: + entryType = SomeIpSdEntry::EntryType::FindService; + break; + case SomeIpSdEntry::TypeInternal::OfferService_Internal: + if (ttl == 0) + { + entryType = EntryType::StopOfferService; + } + else + { + entryType = EntryType::OfferService; + } + break; + case SomeIpSdEntry::TypeInternal::SubscribeEventgroup_Internal: + if (ttl == 0) + { + entryType = EntryType::StopSubscribeEventgroup; + } + else + { + entryType = EntryType::SubscribeEventgroup; + } + break; + case SomeIpSdEntry::TypeInternal::SubscribeEventgroupAck_Internal: + if (ttl == 0) + { + entryType = EntryType::SubscribeEventgroupNack; + } + else + { + entryType = EntryType::SubscribeEventgroupAck; + } + break; + default: + entryType = EntryType::UnknownEntryType; + break; + } -uint32_t SomeIpSdEntry::getTtl() const -{ - return be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL; -} + m_EntryType = entryType; + } -void SomeIpSdEntry::setTtl(uint32_t ttl) -{ - someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); - uint32_t val = (ttl & SOMEIPSD_HDR_ENTRY_MASK_TTL) | (be32toh(hdr->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL); - hdr->majorVersion_ttl = htobe32(val); -} + SomeIpSdEntry::~SomeIpSdEntry() + { + if (m_ShadowData != nullptr) + delete[] m_ShadowData; + } -uint32_t SomeIpSdEntry::getMinorVersion() const -{ - return be32toh(getSomeIpSdEntryHeader()->data); -} + uint8_t* SomeIpSdEntry::getDataPtr() const + { + if (m_Layer != nullptr) + return m_Layer->getDataPtr(m_Offset); -void SomeIpSdEntry::setMinorVersion(uint32_t minorVersion) -{ - getSomeIpSdEntryHeader()->data = htobe32(minorVersion); -} + return m_ShadowData; + } -uint8_t SomeIpSdEntry::getCounter() const -{ - return (uint8_t)((be32toh(getSomeIpSdEntryHeader()->data) >> 16) & 0x0F); -} + SomeIpSdEntry::someipsdhdrentry* SomeIpSdEntry::getSomeIpSdEntryHeader() const + { + return (someipsdhdrentry*)getDataPtr(); + } -void SomeIpSdEntry::setCounter(uint8_t counter) -{ - someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); - hdr->data = htobe32((be32toh(hdr->data) & 0xFFF0FFFF) | ((counter & 0x0F) << 16)); -} + uint32_t SomeIpSdEntry::getNumOptions() const + { + auto* hdr = getSomeIpSdEntryHeader(); + return hdr->nrOpt1 + hdr->nrOpt2; + } -uint16_t SomeIpSdEntry::getEventgroupId() const -{ - return (uint16_t)(be32toh(getSomeIpSdEntryHeader()->data) & 0x0000FFFF); -} + uint16_t SomeIpSdEntry::getServiceId() const + { + return be16toh(getSomeIpSdEntryHeader()->serviceID); + } -void SomeIpSdEntry::setEventgroupId(uint16_t eventgroupID) -{ - someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); - hdr->data = htobe32((be32toh(hdr->data) & 0xFFFF0000) | eventgroupID); -} + void SomeIpSdEntry::setServiceId(uint16_t serviceId) + { + getSomeIpSdEntryHeader()->serviceID = htobe16(serviceId); + } -void SomeIpSdEntry::initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, - uint32_t TTL) -{ - m_EntryType = type; - m_Layer = nullptr; - m_Offset = 0; + uint16_t SomeIpSdEntry::getInstanceId() const + { + return be16toh(getSomeIpSdEntryHeader()->instanceID); + } - size_t dataLen = sizeof(someipsdhdrentry); - m_ShadowData = new uint8_t[dataLen]; - memset(m_ShadowData, 0, dataLen); + void SomeIpSdEntry::setInstanceId(uint16_t instanceId) + { + getSomeIpSdEntryHeader()->instanceID = htobe16(instanceId); + } - someipsdhdrentry *hdr = getSomeIpSdEntryHeader(); - setServiceId(serviceID); - setInstanceId(instanceID); - setMajorVersion(majorVersion); - setTtl(TTL); + uint8_t SomeIpSdEntry::getMajorVersion() const + { + return (be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL) >> 24; + } - switch (type) + void SomeIpSdEntry::setMajorVersion(uint8_t majorVersion) { - case EntryType::FindService: + someipsdhdrentry* hdr = getSomeIpSdEntryHeader(); + uint32_t val = (majorVersion << 24) | (be32toh(hdr->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL); + hdr->majorVersion_ttl = htobe32(val); + } + + uint32_t SomeIpSdEntry::getTtl() const { - hdr->type = static_cast(TypeInternal::FindService_Internal); - break; + return be32toh(getSomeIpSdEntryHeader()->majorVersion_ttl) & SOMEIPSD_HDR_ENTRY_MASK_TTL; } - case EntryType::OfferService: - case EntryType::StopOfferService: + + void SomeIpSdEntry::setTtl(uint32_t ttl) { - hdr->type = static_cast(TypeInternal::OfferService_Internal); - break; + someipsdhdrentry* hdr = getSomeIpSdEntryHeader(); + uint32_t val = + (ttl & SOMEIPSD_HDR_ENTRY_MASK_TTL) | (be32toh(hdr->majorVersion_ttl) & ~SOMEIPSD_HDR_ENTRY_MASK_TTL); + hdr->majorVersion_ttl = htobe32(val); } - case EntryType::SubscribeEventgroup: - case EntryType::StopSubscribeEventgroup: + + uint32_t SomeIpSdEntry::getMinorVersion() const { - hdr->type = static_cast(TypeInternal::SubscribeEventgroup_Internal); - break; + return be32toh(getSomeIpSdEntryHeader()->data); } - case EntryType::SubscribeEventgroupAck: - case EntryType::SubscribeEventgroupNack: + + void SomeIpSdEntry::setMinorVersion(uint32_t minorVersion) { - hdr->type = static_cast(TypeInternal::SubscribeEventgroupAck_Internal); - break; + getSomeIpSdEntryHeader()->data = htobe32(minorVersion); } - default: - break; + + uint8_t SomeIpSdEntry::getCounter() const + { + return (uint8_t)((be32toh(getSomeIpSdEntryHeader()->data) >> 16) & 0x0F); } -} -/* - * SomeIpSdLayer - */ -SomeIpSdLayer::SomeIpSdLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) - : SomeIpLayer(data, dataLen, prevLayer, packet) -{ - countOptions(m_NumOptions, data); -} + void SomeIpSdEntry::setCounter(uint8_t counter) + { + someipsdhdrentry* hdr = getSomeIpSdEntryHeader(); + hdr->data = htobe32((be32toh(hdr->data) & 0xFFF0FFFF) | ((counter & 0x0F) << 16)); + } -SomeIpSdLayer::SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, - uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags) -{ - m_Protocol = SomeIP; - m_DataLen = sizeof(someipsdhdr) + 2 * sizeof(uint32_t); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - - m_NumOptions = 0; - - setServiceID(serviceID); - setMethodID(methodID); - setPayloadLength(sizeof(uint32_t) * 3); // Flags+Reserved, Length Entries, Length Options - setClientID(clientID); - setSessionID(sessionID); - setProtocolVersion(0x01); - setInterfaceVersion(interfaceVersion); - setMessageType(type); - setReturnCode(returnCode); - setFlags(flags); -} - -uint8_t SomeIpSdLayer::getFlags() const -{ - someipsdhdr *hdr = (someipsdhdr *)m_Data; - return hdr->flags; -} + uint16_t SomeIpSdEntry::getEventgroupId() const + { + return (uint16_t)(be32toh(getSomeIpSdEntryHeader()->data) & 0x0000FFFF); + } -void SomeIpSdLayer::setFlags(uint8_t flags) -{ - someipsdhdr *hdr = (someipsdhdr *)m_Data; - hdr->flags = flags; -} + void SomeIpSdEntry::setEventgroupId(uint16_t eventgroupID) + { + someipsdhdrentry* hdr = getSomeIpSdEntryHeader(); + hdr->data = htobe32((be32toh(hdr->data) & 0xFFFF0000) | eventgroupID); + } -uint32_t SomeIpSdLayer::getNumEntries() const -{ - return (uint32_t)(getLenEntries() / sizeof(SomeIpSdEntry::someipsdhdrentry)); -} + void SomeIpSdEntry::initStdFields(EntryType type, uint16_t serviceID, uint16_t instanceID, uint8_t majorVersion, + uint32_t TTL) + { + m_EntryType = type; + m_Layer = nullptr; + m_Offset = 0; -uint32_t SomeIpSdLayer::getNumOptions() const -{ - return m_NumOptions; -} + size_t dataLen = sizeof(someipsdhdrentry); + m_ShadowData = new uint8_t[dataLen]; + memset(m_ShadowData, 0, dataLen); -const SomeIpSdLayer::EntriesVec SomeIpSdLayer::getEntries() const -{ - size_t remainingLen = getLenEntries(); - size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t); + someipsdhdrentry* hdr = getSomeIpSdEntryHeader(); + setServiceId(serviceID); + setInstanceId(instanceID); + setMajorVersion(majorVersion); + setTtl(TTL); - EntriesVec vecEntries; - EntryPtr entry; + switch (type) + { + case EntryType::FindService: + { + hdr->type = static_cast(TypeInternal::FindService_Internal); + break; + } + case EntryType::OfferService: + case EntryType::StopOfferService: + { + hdr->type = static_cast(TypeInternal::OfferService_Internal); + break; + } + case EntryType::SubscribeEventgroup: + case EntryType::StopSubscribeEventgroup: + { + hdr->type = static_cast(TypeInternal::SubscribeEventgroup_Internal); + break; + } + case EntryType::SubscribeEventgroupAck: + case EntryType::SubscribeEventgroupNack: + { + hdr->type = static_cast(TypeInternal::SubscribeEventgroupAck_Internal); + break; + } + default: + break; + } + } - while (remainingLen > 0) + /* + * SomeIpSdLayer + */ + SomeIpSdLayer::SomeIpSdLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : SomeIpLayer(data, dataLen, prevLayer, packet) { - entry = new SomeIpSdEntry(this, offset); - - size_t entryLen = entry->getLength(); - remainingLen -= entryLen; - offset += entryLen; - - vecEntries.push_back(entry); + countOptions(m_NumOptions, data); } - return vecEntries; -}; - -const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptions() const -{ - OptionsVec vecOptions; - OptionPtr option; - - size_t remainingLen = getLenOptions(); - size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + SomeIpSdLayer::SomeIpSdLayer(uint16_t serviceID, uint16_t methodID, uint16_t clientID, uint16_t sessionID, + uint8_t interfaceVersion, MsgType type, uint8_t returnCode, uint8_t flags) + { + m_Protocol = SomeIP; + m_DataLen = sizeof(someipsdhdr) + 2 * sizeof(uint32_t); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + + m_NumOptions = 0; + + setServiceID(serviceID); + setMethodID(methodID); + setPayloadLength(sizeof(uint32_t) * 3); // Flags+Reserved, Length Entries, Length Options + setClientID(clientID); + setSessionID(sessionID); + setProtocolVersion(0x01); + setInterfaceVersion(interfaceVersion); + setMessageType(type); + setReturnCode(returnCode); + setFlags(flags); + } - while (remainingLen > 0) + uint8_t SomeIpSdLayer::getFlags() const { - SomeIpSdOption::someipsdhdroptionsbase *hdr = (SomeIpSdOption::someipsdhdroptionsbase *)(m_Data + offset); - SomeIpSdOption::OptionType optionType = static_cast(hdr->type); + someipsdhdr* hdr = (someipsdhdr*)m_Data; + return hdr->flags; + } - option = parseOption(optionType, offset); + void SomeIpSdLayer::setFlags(uint8_t flags) + { + someipsdhdr* hdr = (someipsdhdr*)m_Data; + hdr->flags = flags; + } - if (option != nullptr) - { - vecOptions.push_back(std::move(option)); - } + uint32_t SomeIpSdLayer::getNumEntries() const + { + return (uint32_t)(getLenEntries() / sizeof(SomeIpSdEntry::someipsdhdrentry)); + } - size_t optionLen = be16toh(hdr->length) + 3; - remainingLen -= optionLen; - offset += optionLen; + uint32_t SomeIpSdLayer::getNumOptions() const + { + return m_NumOptions; } - return vecOptions; -} + const SomeIpSdLayer::EntriesVec SomeIpSdLayer::getEntries() const + { + size_t remainingLen = getLenEntries(); + size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t); -const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t index) const -{ - OptionsVec vecOptions; - OptionPtr option; + EntriesVec vecEntries; + EntryPtr entry; - if (index >= getNumEntries()) - return vecOptions; + while (remainingLen > 0) + { + entry = new SomeIpSdEntry(this, offset); - size_t remainingLen = getLenOptions(); - size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + size_t entryLen = entry->getLength(); + remainingLen -= entryLen; + offset += entryLen; - size_t offsetToEntry = sizeof(someipsdhdr) + sizeof(uint32_t) + index * sizeof(SomeIpSdEntry::someipsdhdrentry); - SomeIpSdEntry::someipsdhdrentry *hdrEntry = (SomeIpSdEntry::someipsdhdrentry *)(m_Data + offsetToEntry); - uint8_t startIdxRun1 = hdrEntry->indexFirstOption; - uint8_t lenRun1 = hdrEntry->nrOpt1; - uint8_t startIdxRun2 = hdrEntry->indexSecondOption; - uint8_t lenRun2 = hdrEntry->nrOpt2; + vecEntries.push_back(entry); + } - int idx = 0; + return vecEntries; + }; - while (remainingLen > 0) + const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptions() const { - SomeIpSdOption::someipsdhdroptionsbase *hdrOption = (SomeIpSdOption::someipsdhdroptionsbase *)(m_Data + offset); + OptionsVec vecOptions; + OptionPtr option; + + size_t remainingLen = getLenOptions(); + size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); - if (((idx >= startIdxRun1) && (idx < (startIdxRun1 + lenRun1))) || - ((idx >= startIdxRun2) && (idx < (startIdxRun2 + lenRun2)))) + while (remainingLen > 0) { - SomeIpSdOption::OptionType optionType = static_cast(hdrOption->type); + SomeIpSdOption::someipsdhdroptionsbase* hdr = (SomeIpSdOption::someipsdhdroptionsbase*)(m_Data + offset); + SomeIpSdOption::OptionType optionType = static_cast(hdr->type); option = parseOption(optionType, offset); @@ -572,250 +530,297 @@ const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t inde { vecOptions.push_back(std::move(option)); } + + size_t optionLen = be16toh(hdr->length) + 3; + remainingLen -= optionLen; + offset += optionLen; } - size_t optionLen = be16toh(hdrOption->length) + 3; - remainingLen -= optionLen; - offset += optionLen; - ++idx; + return vecOptions; } - return vecOptions; -} - -bool SomeIpSdLayer::addOptionTo(uint32_t indexEntry, const SomeIpSdOption &option) -{ - if (indexEntry >= getNumEntries()) + const SomeIpSdLayer::OptionsVec SomeIpSdLayer::getOptionsFromEntry(uint32_t index) const { - return false; - } + OptionsVec vecOptions; + OptionPtr option; - uint32_t indexOption = findOption(option); - bool success = addOptionIndex(indexEntry, indexOption); + if (index >= getNumEntries()) + return vecOptions; - if (!success) - { - return false; - } + size_t remainingLen = getLenOptions(); + size_t offset = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); - if (indexOption == m_NumOptions) - { - addOption(option); - } + size_t offsetToEntry = sizeof(someipsdhdr) + sizeof(uint32_t) + index * sizeof(SomeIpSdEntry::someipsdhdrentry); + SomeIpSdEntry::someipsdhdrentry* hdrEntry = (SomeIpSdEntry::someipsdhdrentry*)(m_Data + offsetToEntry); + uint8_t startIdxRun1 = hdrEntry->indexFirstOption; + uint8_t lenRun1 = hdrEntry->nrOpt1; + uint8_t startIdxRun2 = hdrEntry->indexSecondOption; + uint8_t lenRun2 = hdrEntry->nrOpt2; - return true; -} + int idx = 0; -std::string SomeIpSdLayer::toString() const -{ - std::stringstream dataStream; + while (remainingLen > 0) + { + SomeIpSdOption::someipsdhdroptionsbase* hdrOption = + (SomeIpSdOption::someipsdhdroptionsbase*)(m_Data + offset); - dataStream << "SOME/IP-SD Layer, " << getNumEntries() << " entries, " << getNumOptions() << " options"; + if (((idx >= startIdxRun1) && (idx < (startIdxRun1 + lenRun1))) || + ((idx >= startIdxRun2) && (idx < (startIdxRun2 + lenRun2)))) + { + SomeIpSdOption::OptionType optionType = static_cast(hdrOption->type); - return dataStream.str(); -} + option = parseOption(optionType, offset); -uint32_t SomeIpSdLayer::addEntry(const SomeIpSdEntry &entry) -{ - size_t lenEntries = getLenEntries(); - int offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + lenEntries; + if (option != nullptr) + { + vecOptions.push_back(std::move(option)); + } + } + + size_t optionLen = be16toh(hdrOption->length) + 3; + remainingLen -= optionLen; + offset += optionLen; + ++idx; + } - extendLayer(offsetToAddAt, entry.getLength()); + return vecOptions; + } - setLenEntries(lenEntries + entry.getLength()); + bool SomeIpSdLayer::addOptionTo(uint32_t indexEntry, const SomeIpSdOption& option) + { + if (indexEntry >= getNumEntries()) + { + return false; + } - memcpy(m_Data + offsetToAddAt, entry.getDataPtr(), entry.getLength()); + uint32_t indexOption = findOption(option); + bool success = addOptionIndex(indexEntry, indexOption); - auto hdr = getSomeIpHeader(); - hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)entry.getLength()); + if (!success) + { + return false; + } - return getNumEntries() - 1; -} + if (indexOption == m_NumOptions) + { + addOption(option); + } -bool SomeIpSdLayer::isDataValid(const uint8_t* data, size_t dataLen) -{ - uint32_t count; - if (!data || - dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) || - dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) || - dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) + getLenOptions(data) || - !countOptions(count, data)) - { - return false; + return true; } - return true; -} + std::string SomeIpSdLayer::toString() const + { + std::stringstream dataStream; + + dataStream << "SOME/IP-SD Layer, " << getNumEntries() << " entries, " << getNumOptions() << " options"; -bool SomeIpSdLayer::countOptions(uint32_t& count, const uint8_t* data) -{ - size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t); - size_t lenOptions = getLenOptions(data); - uint32_t len = 0; + return dataStream.str(); + } - count = 0; - while (len < lenOptions) + uint32_t SomeIpSdLayer::addEntry(const SomeIpSdEntry& entry) { - if (len + sizeof(uint16_t) + 3 * sizeof(uint8_t) > lenOptions) - return false; + size_t lenEntries = getLenEntries(); + int offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + lenEntries; + + extendLayer(offsetToAddAt, entry.getLength()); + + setLenEntries(lenEntries + entry.getLength()); + + memcpy(m_Data + offsetToAddAt, entry.getDataPtr(), entry.getLength()); - uint32_t lenOption = be16toh(*((uint16_t *)(data + offsetOption + len))) + 3 * sizeof(uint8_t); - len += lenOption; - if (len > lenOptions) // the last one must be equal to lenOptions + auto hdr = getSomeIpHeader(); + hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)entry.getLength()); + + return getNumEntries() - 1; + } + + bool SomeIpSdLayer::isDataValid(const uint8_t* data, size_t dataLen) + { + uint32_t count; + if (!data || dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) || + dataLen < sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) || + dataLen < + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t) + getLenOptions(data) || + !countOptions(count, data)) + { return false; + } - ++(count); + return true; } - return true; -} -uint32_t SomeIpSdLayer::findOption(const SomeIpSdOption &option) -{ - size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); + bool SomeIpSdLayer::countOptions(uint32_t& count, const uint8_t* data) + { + size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data) + sizeof(uint32_t); + size_t lenOptions = getLenOptions(data); + uint32_t len = 0; + + count = 0; + while (len < lenOptions) + { + if (len + sizeof(uint16_t) + 3 * sizeof(uint8_t) > lenOptions) + return false; + + uint32_t lenOption = be16toh(*((uint16_t*)(data + offsetOption + len))) + 3 * sizeof(uint8_t); + len += lenOption; + if (len > lenOptions) // the last one must be equal to lenOptions + return false; + + ++(count); + } + return true; + } - uint32_t i = 0; - while (i < m_NumOptions) + uint32_t SomeIpSdLayer::findOption(const SomeIpSdOption& option) { - uint32_t lenOption = be16toh(*((uint16_t *)(m_Data + offsetOption))) + 3 * sizeof(uint8_t); + size_t offsetOption = sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries() + sizeof(uint32_t); - if (option.getLength() == lenOption) + uint32_t i = 0; + while (i < m_NumOptions) { - if (memcmp(m_Data + offsetOption, option.getDataPtr(), option.getLength()) == 0) + uint32_t lenOption = be16toh(*((uint16_t*)(m_Data + offsetOption))) + 3 * sizeof(uint8_t); + + if (option.getLength() == lenOption) { - return i; + if (memcmp(m_Data + offsetOption, option.getDataPtr(), option.getLength()) == 0) + { + return i; + } } + + offsetOption += lenOption; + ++i; } + return i; + } + + void SomeIpSdLayer::addOption(const SomeIpSdOption& option) + { + int offsetToAddAt = (int)getHeaderLen(); + + extendLayer(offsetToAddAt, option.getLength()); + memcpy(m_Data + offsetToAddAt, option.getDataPtr(), option.getLength()); + + setLenOptions(uint32_t(getLenOptions() + option.getLength())); + + auto hdr = getSomeIpHeader(); + hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)option.getLength()); - offsetOption += lenOption; - ++i; + ++m_NumOptions; } - return i; -} -void SomeIpSdLayer::addOption(const SomeIpSdOption &option) -{ - int offsetToAddAt = (int)getHeaderLen(); + bool SomeIpSdLayer::addOptionIndex(uint32_t indexEntry, uint32_t indexOffset) + { + /* + The SOME/IP-SD protocol supports two option runs. Runs meaning that two different starting indices with + differing length can be provided. Of course, this only works if the indices in both runs are consecutive. - extendLayer(offsetToAddAt, option.getLength()); - memcpy(m_Data + offsetToAddAt, option.getDataPtr(), option.getLength()); + So, indices like this would work: + 1 2 3 ; 7 8 - setLenOptions(uint32_t(getLenOptions() + option.getLength())); + What wouldn't work is this: + 1 2 3 ; 7 9 + 1 3 ; 7 8 + */ - auto hdr = getSomeIpHeader(); - hdr->length = htobe32(be32toh(hdr->length) + (uint32_t)option.getLength()); + const size_t someipsdhdrentrySize = sizeof(SomeIpSdEntry::someipsdhdrentry); + size_t offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + indexEntry * someipsdhdrentrySize; + auto hdrEntry = (SomeIpSdEntry::someipsdhdrentry*)(m_Data + offsetToAddAt); - ++m_NumOptions; -} + uint8_t indexFirstOption = hdrEntry->indexFirstOption; + uint8_t lenFirstOption = hdrEntry->nrOpt1; -bool SomeIpSdLayer::addOptionIndex(uint32_t indexEntry, uint32_t indexOffset) -{ - /* The SOME/IP-SD protocol supports two option runs. Runs meaning that two different starting indices with differing - length can be provided. Of course, this only works if the indices in both runs are consecutive. + if (lenFirstOption == 0) + { + hdrEntry->indexFirstOption = indexOffset; + ++hdrEntry->nrOpt1; + return true; + } - So, indices like this would work: - 1 2 3 ; 7 8 + if (static_cast(indexFirstOption + lenFirstOption + 1) == indexOffset) + { + ++hdrEntry->nrOpt1; + return true; + } - What wouldn't work is this: - 1 2 3 ; 7 9 - 1 3 ; 7 8 - */ + uint8_t indexSecondOption = hdrEntry->indexSecondOption; + uint8_t lenSecondOption = hdrEntry->nrOpt2; - size_t offsetToAddAt = sizeof(someipsdhdr) + sizeof(uint32_t) + indexEntry*sizeof(SomeIpSdEntry::someipsdhdrentry); - auto hdrEntry = (SomeIpSdEntry::someipsdhdrentry *)(m_Data + offsetToAddAt); + if (lenSecondOption == 0) + { + hdrEntry->indexFirstOption = indexOffset; + ++hdrEntry->nrOpt1; + return true; + } - uint8_t indexFirstOption = hdrEntry->indexFirstOption; - uint8_t lenFirstOption = hdrEntry->nrOpt1; + if (static_cast(indexSecondOption + lenSecondOption + 1) == indexOffset) + { + ++hdrEntry->nrOpt2; + return true; + } - if (lenFirstOption == 0) - { - hdrEntry->indexFirstOption = indexOffset; - ++hdrEntry->nrOpt1; - return true; + return false; } - if (static_cast(indexFirstOption + lenFirstOption + 1) == indexOffset) + SomeIpSdLayer::OptionPtr SomeIpSdLayer::parseOption(SomeIpSdOption::OptionType type, size_t offset) const { - ++hdrEntry->nrOpt1; - return true; + switch (type) + { + case SomeIpSdOption::OptionType::IPv4Endpoint: + case SomeIpSdOption::OptionType::IPv4Multicast: + case SomeIpSdOption::OptionType::IPv4SdEndpoint: + { + return new SomeIpSdIPv4Option(this, offset); + } + case SomeIpSdOption::OptionType::IPv6Endpoint: + case SomeIpSdOption::OptionType::IPv6Multicast: + case SomeIpSdOption::OptionType::IPv6SdEndpoint: + { + return new SomeIpSdIPv6Option(this, offset); + } + case SomeIpSdOption::OptionType::ConfigurationString: + { + return new SomeIpSdConfigurationOption(this, offset); + } + case SomeIpSdOption::OptionType::LoadBalancing: + { + return new SomeIpSdLoadBalancingOption(this, offset); + } + default: + break; + } + return nullptr; } - uint8_t indexSecondOption = hdrEntry->indexSecondOption; - uint8_t lenSecondOption = hdrEntry->nrOpt2; - - if (lenSecondOption == 0) + size_t SomeIpSdLayer::getLenEntries() const { - hdrEntry->indexFirstOption = indexOffset; - ++hdrEntry->nrOpt1; - return true; + return getLenEntries(m_Data); } - if (static_cast(indexSecondOption + lenSecondOption + 1) == indexOffset) + size_t SomeIpSdLayer::getLenEntries(const uint8_t* data) { - ++hdrEntry->nrOpt2; - return true; + return be32toh(*((uint32_t*)(data + sizeof(someipsdhdr)))); } - return false; -} - -SomeIpSdLayer::OptionPtr SomeIpSdLayer::parseOption(SomeIpSdOption::OptionType type, size_t offset) const -{ - switch (type) - { - case SomeIpSdOption::OptionType::IPv4Endpoint: - case SomeIpSdOption::OptionType::IPv4Multicast: - case SomeIpSdOption::OptionType::IPv4SdEndpoint: + size_t SomeIpSdLayer::getLenOptions() const { - return new SomeIpSdIPv4Option(this, offset); + return getLenOptions(m_Data); } - case SomeIpSdOption::OptionType::IPv6Endpoint: - case SomeIpSdOption::OptionType::IPv6Multicast: - case SomeIpSdOption::OptionType::IPv6SdEndpoint: + + size_t SomeIpSdLayer::getLenOptions(const uint8_t* data) { - return new SomeIpSdIPv6Option(this, offset); + return be32toh(*((uint32_t*)(data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data)))); } - case SomeIpSdOption::OptionType::ConfigurationString: + + void SomeIpSdLayer::setLenEntries(uint32_t length) { - return new SomeIpSdConfigurationOption(this, offset); + *((uint32_t*)(m_Data + sizeof(someipsdhdr))) = htobe32(length); } - case SomeIpSdOption::OptionType::LoadBalancing: + + void SomeIpSdLayer::setLenOptions(uint32_t length) { - return new SomeIpSdLoadBalancingOption(this, offset); - } - default: - break; + *((uint32_t*)(m_Data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries())) = htobe32(length); } - return nullptr; -} - -size_t SomeIpSdLayer::getLenEntries() const -{ - return getLenEntries(m_Data); -} - -size_t SomeIpSdLayer::getLenEntries(const uint8_t* data) -{ - return be32toh(*((uint32_t *)(data + sizeof(someipsdhdr)))); -} - -size_t SomeIpSdLayer::getLenOptions() const -{ - return getLenOptions(m_Data); -} - -size_t SomeIpSdLayer::getLenOptions(const uint8_t* data) -{ - return be32toh(*((uint32_t *)(data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries(data)))); -} - -void SomeIpSdLayer::setLenEntries(uint32_t length) -{ - *((uint32_t *)(m_Data + sizeof(someipsdhdr))) = htobe32(length); -} - -void SomeIpSdLayer::setLenOptions(uint32_t length) -{ - *((uint32_t *)(m_Data + sizeof(someipsdhdr) + sizeof(uint32_t) + getLenEntries())) = htobe32(length); -} -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/StpLayer.cpp b/Packet++/src/StpLayer.cpp index a433a1e400..147395018d 100644 --- a/Packet++/src/StpLayer.cpp +++ b/Packet++/src/StpLayer.cpp @@ -8,266 +8,341 @@ namespace pcpp { -// ---------------------- Class STPLayer ---------------------- -MacAddress StpLayer::StpMulticastDstMAC("01:80:C2:00:00:00"); -MacAddress StpLayer::StpUplinkFastMulticastDstMAC("01:00:0C:CD:CD:CD"); + // ---------------------- Class STPLayer ---------------------- + MacAddress StpLayer::StpMulticastDstMAC("01:80:C2:00:00:00"); + MacAddress StpLayer::StpUplinkFastMulticastDstMAC("01:00:0C:CD:CD:CD"); -MacAddress StpLayer::IDtoMacAddress(uint64_t id) -{ - return MacAddress((id >> 40) & 0xFF, (id >> 32) & 0xFF, (id >> 24) & 0xFF, (id >> 16) & 0xFF, (id >> 8) & 0xFF, - id & 0xFF); -} + MacAddress StpLayer::IDtoMacAddress(uint64_t id) + { + return MacAddress((id >> 40) & 0xFF, (id >> 32) & 0xFF, (id >> 24) & 0xFF, (id >> 16) & 0xFF, (id >> 8) & 0xFF, + id & 0xFF); + } -uint64_t StpLayer::macAddressToID(const pcpp::MacAddress &addr) -{ - uint8_t value[6]; - addr.copyTo(value); - return ((uint64_t(value[0]) << 40) | (uint64_t(value[1]) << 32) | (uint64_t(value[2]) << 24) | - (uint64_t(value[3]) << 16) | (uint64_t(value[4]) << 8) | (uint64_t(value[5]))); -} + uint64_t StpLayer::macAddressToID(const pcpp::MacAddress& addr) + { + uint8_t value[6]; + addr.copyTo(value); + return ((uint64_t(value[0]) << 40) | (uint64_t(value[1]) << 32) | (uint64_t(value[2]) << 24) | + (uint64_t(value[3]) << 16) | (uint64_t(value[4]) << 8) | (uint64_t(value[5]))); + } -bool StpLayer::isDataValid(const uint8_t *data, size_t dataLen) { return data && dataLen; } + bool StpLayer::isDataValid(const uint8_t* data, size_t dataLen) + { + return data && dataLen; + } -StpLayer *StpLayer::parseStpLayer(uint8_t *data, size_t dataLen, Layer *prevLayer, Packet *packet) -{ - if (dataLen >= sizeof(stp_tcn_bpdu)) + StpLayer* StpLayer::parseStpLayer(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) { - stp_tcn_bpdu *ptr = (stp_tcn_bpdu *)data; - switch (ptr->type) + if (dataLen >= sizeof(stp_tcn_bpdu)) { - case 0x00: - return StpConfigurationBPDULayer::isDataValid(data, dataLen) - ? new StpConfigurationBPDULayer(data, dataLen, prevLayer, packet) - : nullptr; - case 0x02: - if (ptr->version == 0x2) - return RapidStpLayer::isDataValid(data, dataLen) - ? new RapidStpLayer(data, dataLen, prevLayer, packet) - : nullptr; - if (ptr->version == 0x3) - return MultipleStpLayer::isDataValid(data, dataLen) - ? new MultipleStpLayer(data, dataLen, prevLayer, packet) - : nullptr; - PCPP_LOG_DEBUG("Unknown Spanning Tree Version"); - return nullptr; - case 0x80: - return StpTopologyChangeBPDULayer::isDataValid(data, dataLen) - ? new StpTopologyChangeBPDULayer(data, dataLen, prevLayer, packet) - : nullptr; - // TODO: Per VLAN Spanning Tree+ (PVST+) - // TODO: Rapid Per VLAN Spanning Tree+ (RPVST+) - // TODO: Cisco Uplink Fast - default: - PCPP_LOG_DEBUG("Unknown Spanning Tree Protocol type"); - return nullptr; + stp_tcn_bpdu* ptr = (stp_tcn_bpdu*)data; + switch (ptr->type) + { + case 0x00: + return StpConfigurationBPDULayer::isDataValid(data, dataLen) + ? new StpConfigurationBPDULayer(data, dataLen, prevLayer, packet) + : nullptr; + case 0x02: + if (ptr->version == 0x2) + return RapidStpLayer::isDataValid(data, dataLen) + ? new RapidStpLayer(data, dataLen, prevLayer, packet) + : nullptr; + if (ptr->version == 0x3) + return MultipleStpLayer::isDataValid(data, dataLen) + ? new MultipleStpLayer(data, dataLen, prevLayer, packet) + : nullptr; + PCPP_LOG_DEBUG("Unknown Spanning Tree Version"); + return nullptr; + case 0x80: + return StpTopologyChangeBPDULayer::isDataValid(data, dataLen) + ? new StpTopologyChangeBPDULayer(data, dataLen, prevLayer, packet) + : nullptr; + // TODO: Per VLAN Spanning Tree+ (PVST+) + // TODO: Rapid Per VLAN Spanning Tree+ (RPVST+) + // TODO: Cisco Uplink Fast + default: + PCPP_LOG_DEBUG("Unknown Spanning Tree Protocol type"); + return nullptr; + } } - } - PCPP_LOG_DEBUG("Data length is less than any STP header"); - return nullptr; -} + PCPP_LOG_DEBUG("Data length is less than any STP header"); + return nullptr; + } -// ---------------------- Class StpTopologyChangeBPDULayer ---------------------- -StpTopologyChangeBPDULayer::StpTopologyChangeBPDULayer() : StpLayer(sizeof(stp_tcn_bpdu)) -{ - // Set initial values for TCN - setProtoId(0x0); - setVersion(0x0); - setType(0x80); -} + // ---------------------- Class StpTopologyChangeBPDULayer ---------------------- + StpTopologyChangeBPDULayer::StpTopologyChangeBPDULayer() : StpLayer(sizeof(stp_tcn_bpdu)) + { + // Set initial values for TCN + setProtoId(0x0); + setVersion(0x0); + setType(0x80); + } -void StpTopologyChangeBPDULayer::parseNextLayer() -{ - if (m_DataLen > sizeof(stp_tcn_bpdu)) - m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_tcn_bpdu), this, m_Packet); -} + void StpTopologyChangeBPDULayer::parseNextLayer() + { + if (m_DataLen > sizeof(stp_tcn_bpdu)) + m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_tcn_bpdu), this, m_Packet); + } -// ---------------------- Class StpConfigurationBPDULayer ---------------------- -StpConfigurationBPDULayer::StpConfigurationBPDULayer() : StpTopologyChangeBPDULayer(sizeof(stp_conf_bpdu)) -{ - // Set initial value for configuration BPDU - setProtoId(0x0); - setVersion(0x0); - setType(0x0); -} + // ---------------------- Class StpConfigurationBPDULayer ---------------------- + StpConfigurationBPDULayer::StpConfigurationBPDULayer() : StpTopologyChangeBPDULayer(sizeof(stp_conf_bpdu)) + { + // Set initial value for configuration BPDU + setProtoId(0x0); + setVersion(0x0); + setType(0x0); + } -uint64_t StpConfigurationBPDULayer::getRootId() const { return be64toh(getStpConfHeader()->rootId); } + uint64_t StpConfigurationBPDULayer::getRootId() const + { + return be64toh(getStpConfHeader()->rootId); + } -void StpConfigurationBPDULayer::setRootId(uint64_t value) { getStpConfHeader()->rootId = htobe64(value); } + void StpConfigurationBPDULayer::setRootId(uint64_t value) + { + getStpConfHeader()->rootId = htobe64(value); + } -uint16_t StpConfigurationBPDULayer::getRootPriority() const { return be16toh(getStpConfHeader()->rootId) & 0xf000; } + uint16_t StpConfigurationBPDULayer::getRootPriority() const + { + return be16toh(getStpConfHeader()->rootId) & 0xf000; + } -void StpConfigurationBPDULayer::setRootPriority(uint16_t value) -{ - getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0xf000)) | htobe16(value & 0xf000); -} + void StpConfigurationBPDULayer::setRootPriority(uint16_t value) + { + getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0xf000)) | htobe16(value & 0xf000); + } -uint16_t StpConfigurationBPDULayer::getRootSystemIDExtension() const -{ - return be16toh(getStpConfHeader()->rootId) & 0x0fff; -} + uint16_t StpConfigurationBPDULayer::getRootSystemIDExtension() const + { + return be16toh(getStpConfHeader()->rootId) & 0x0fff; + } -void StpConfigurationBPDULayer::setRootSystemIDExtension(uint16_t value) -{ - getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); -} + void StpConfigurationBPDULayer::setRootSystemIDExtension(uint16_t value) + { + getStpConfHeader()->rootId = (getStpConfHeader()->rootId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); + } -void StpConfigurationBPDULayer::setRootSystemID(const pcpp::MacAddress &value) -{ - setRootId((getRootId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); -}; + void StpConfigurationBPDULayer::setRootSystemID(const pcpp::MacAddress& value) + { + setRootId((getRootId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); + }; -uint32_t StpConfigurationBPDULayer::getPathCost() const { return be32toh(getStpConfHeader()->pathCost); } + uint32_t StpConfigurationBPDULayer::getPathCost() const + { + return be32toh(getStpConfHeader()->pathCost); + } -void StpConfigurationBPDULayer::setPathCost(uint32_t value) { getStpConfHeader()->pathCost = htobe32(value); } + void StpConfigurationBPDULayer::setPathCost(uint32_t value) + { + getStpConfHeader()->pathCost = htobe32(value); + } -uint64_t StpConfigurationBPDULayer::getBridgeId() const { return be64toh(getStpConfHeader()->bridgeId); } + uint64_t StpConfigurationBPDULayer::getBridgeId() const + { + return be64toh(getStpConfHeader()->bridgeId); + } -void StpConfigurationBPDULayer::setBridgeId(uint64_t value) { getStpConfHeader()->bridgeId = htobe64(value); } + void StpConfigurationBPDULayer::setBridgeId(uint64_t value) + { + getStpConfHeader()->bridgeId = htobe64(value); + } -uint16_t StpConfigurationBPDULayer::getBridgePriority() const -{ - return be16toh(getStpConfHeader()->bridgeId) & 0xf000; -} + uint16_t StpConfigurationBPDULayer::getBridgePriority() const + { + return be16toh(getStpConfHeader()->bridgeId) & 0xf000; + } -void StpConfigurationBPDULayer::setBridgePriority(uint16_t value) -{ - getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000); -} + void StpConfigurationBPDULayer::setBridgePriority(uint16_t value) + { + getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000); + } -uint16_t StpConfigurationBPDULayer::getBridgeSystemIDExtension() const -{ - return be16toh(getStpConfHeader()->bridgeId) & 0x0fff; -} + uint16_t StpConfigurationBPDULayer::getBridgeSystemIDExtension() const + { + return be16toh(getStpConfHeader()->bridgeId) & 0x0fff; + } -void StpConfigurationBPDULayer::setBridgeSystemIDExtension(uint16_t value) -{ - getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); -} + void StpConfigurationBPDULayer::setBridgeSystemIDExtension(uint16_t value) + { + getStpConfHeader()->bridgeId = (getStpConfHeader()->bridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); + } -void StpConfigurationBPDULayer::setBridgeSystemID(const pcpp::MacAddress &value) -{ - setBridgeId((getBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); -} + void StpConfigurationBPDULayer::setBridgeSystemID(const pcpp::MacAddress& value) + { + setBridgeId((getBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); + } -uint16_t StpConfigurationBPDULayer::getPortId() const { return be16toh(getStpConfHeader()->portId); } + uint16_t StpConfigurationBPDULayer::getPortId() const + { + return be16toh(getStpConfHeader()->portId); + } -void StpConfigurationBPDULayer::setPortId(uint16_t value) { getStpConfHeader()->portId = htobe16(value); } + void StpConfigurationBPDULayer::setPortId(uint16_t value) + { + getStpConfHeader()->portId = htobe16(value); + } -double StpConfigurationBPDULayer::getMessageAge() const { return getStpConfHeader()->msgAge; } + double StpConfigurationBPDULayer::getMessageAge() const + { + return getStpConfHeader()->msgAge; + } -void StpConfigurationBPDULayer::setMessageAge(double value) { getStpConfHeader()->msgAge = value; } + void StpConfigurationBPDULayer::setMessageAge(double value) + { + getStpConfHeader()->msgAge = value; + } -double StpConfigurationBPDULayer::getMaximumAge() const { return getStpConfHeader()->maxAge; } + double StpConfigurationBPDULayer::getMaximumAge() const + { + return getStpConfHeader()->maxAge; + } -void StpConfigurationBPDULayer::setMaximumAge(double value) { getStpConfHeader()->maxAge = value; } + void StpConfigurationBPDULayer::setMaximumAge(double value) + { + getStpConfHeader()->maxAge = value; + } -double StpConfigurationBPDULayer::getTransmissionInterval() const { return getStpConfHeader()->helloTime; } + double StpConfigurationBPDULayer::getTransmissionInterval() const + { + return getStpConfHeader()->helloTime; + } -void StpConfigurationBPDULayer::setTransmissionInterval(double value) { getStpConfHeader()->helloTime = value; } + void StpConfigurationBPDULayer::setTransmissionInterval(double value) + { + getStpConfHeader()->helloTime = value; + } -double StpConfigurationBPDULayer::getForwardDelay() const { return getStpConfHeader()->forwardDelay; } + double StpConfigurationBPDULayer::getForwardDelay() const + { + return getStpConfHeader()->forwardDelay; + } -void StpConfigurationBPDULayer::setForwardDelay(double value) { getStpConfHeader()->forwardDelay = value; } + void StpConfigurationBPDULayer::setForwardDelay(double value) + { + getStpConfHeader()->forwardDelay = value; + } -void StpConfigurationBPDULayer::parseNextLayer() -{ - if (m_DataLen > sizeof(stp_conf_bpdu)) - m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_conf_bpdu), this, m_Packet); -} + void StpConfigurationBPDULayer::parseNextLayer() + { + if (m_DataLen > sizeof(stp_conf_bpdu)) + m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(stp_conf_bpdu), this, m_Packet); + } -// ---------------------- Class RapidStpLayer ---------------------- -RapidStpLayer::RapidStpLayer() : StpConfigurationBPDULayer(sizeof(rstp_conf_bpdu)) -{ - // Set initial value for Rapid STP - setProtoId(0x0); - setVersion(0x2); - setType(0x2); -} + // ---------------------- Class RapidStpLayer ---------------------- + RapidStpLayer::RapidStpLayer() : StpConfigurationBPDULayer(sizeof(rstp_conf_bpdu)) + { + // Set initial value for Rapid STP + setProtoId(0x0); + setVersion(0x2); + setType(0x2); + } -void RapidStpLayer::parseNextLayer() -{ - if (m_DataLen > sizeof(rstp_conf_bpdu)) - m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(rstp_conf_bpdu), this, m_Packet); -} + void RapidStpLayer::parseNextLayer() + { + if (m_DataLen > sizeof(rstp_conf_bpdu)) + m_NextLayer = new PayloadLayer(m_Data, m_DataLen - sizeof(rstp_conf_bpdu), this, m_Packet); + } -// ---------------------- Class MultipleStpLayer ---------------------- -MultipleStpLayer::MultipleStpLayer() : RapidStpLayer(sizeof(mstp_conf_bpdu)) -{ - // Set initial value for Multiple STP - setProtoId(0x0); - setVersion(0x3); - setType(0x2); -} + // ---------------------- Class MultipleStpLayer ---------------------- + MultipleStpLayer::MultipleStpLayer() : RapidStpLayer(sizeof(mstp_conf_bpdu)) + { + // Set initial value for Multiple STP + setProtoId(0x0); + setVersion(0x3); + setType(0x2); + } -uint16_t MultipleStpLayer::getVersion3Len() const { return be16toh(getMstpHeader()->version3Len); } + uint16_t MultipleStpLayer::getVersion3Len() const + { + return be16toh(getMstpHeader()->version3Len); + } -void MultipleStpLayer::setVersion3Len(uint16_t value) { getMstpHeader()->version3Len = htobe16(value); } + void MultipleStpLayer::setVersion3Len(uint16_t value) + { + getMstpHeader()->version3Len = htobe16(value); + } -uint32_t MultipleStpLayer::getCISTIrpc() const { return be32toh(getMstpHeader()->irpc); } + uint32_t MultipleStpLayer::getCISTIrpc() const + { + return be32toh(getMstpHeader()->irpc); + } -void MultipleStpLayer::setCISTIrpc(uint32_t value) { getMstpHeader()->irpc = htobe32(value); } + void MultipleStpLayer::setCISTIrpc(uint32_t value) + { + getMstpHeader()->irpc = htobe32(value); + } -uint64_t MultipleStpLayer::getCISTBridgeId() const { return be64toh(getMstpHeader()->cistBridgeId); } + uint64_t MultipleStpLayer::getCISTBridgeId() const + { + return be64toh(getMstpHeader()->cistBridgeId); + } -void MultipleStpLayer::setCISTBridgeId(uint64_t value) { getMstpHeader()->cistBridgeId = htobe64(value); } + void MultipleStpLayer::setCISTBridgeId(uint64_t value) + { + getMstpHeader()->cistBridgeId = htobe64(value); + } -uint16_t MultipleStpLayer::getCISTBridgePriority() const { return be16toh(getMstpHeader()->cistBridgeId) & 0xf000; } + uint16_t MultipleStpLayer::getCISTBridgePriority() const + { + return be16toh(getMstpHeader()->cistBridgeId) & 0xf000; + } -void MultipleStpLayer::setCISTBridgePriority(uint16_t value) -{ - getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000); -} + void MultipleStpLayer::setCISTBridgePriority(uint16_t value) + { + getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0xf000)) | htobe16(value & 0xf000); + } -uint16_t MultipleStpLayer::getCISTBridgeSystemIDExtension() const -{ - return be16toh(getMstpHeader()->cistBridgeId) & 0x0fff; -} + uint16_t MultipleStpLayer::getCISTBridgeSystemIDExtension() const + { + return be16toh(getMstpHeader()->cistBridgeId) & 0x0fff; + } -void MultipleStpLayer::setCISTBridgeSystemIDExtension(uint16_t value) -{ - getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); -} + void MultipleStpLayer::setCISTBridgeSystemIDExtension(uint16_t value) + { + getMstpHeader()->cistBridgeId = (getMstpHeader()->cistBridgeId & ~htobe16(0x0fff)) | htobe16(value & 0x0fff); + } -void MultipleStpLayer::setCISTBridgeSystemID(const pcpp::MacAddress &value) -{ - setCISTBridgeId((getCISTBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); -} + void MultipleStpLayer::setCISTBridgeSystemID(const pcpp::MacAddress& value) + { + setCISTBridgeId((getCISTBridgeId() & (uint64_t(0xffff) << 48)) | macAddressToID(value)); + } -std::string MultipleStpLayer::getMstConfigurationName() const -{ - std::string str = std::string((char *)(getMstpHeader()->mstConfigName), 32); - str.erase(std::find(str.begin(), str.end(), '\0'), str.end()); - return str; -} + std::string MultipleStpLayer::getMstConfigurationName() const + { + std::string str = std::string((char*)(getMstpHeader()->mstConfigName), 32); + str.erase(std::find(str.begin(), str.end(), '\0'), str.end()); + return str; + } -uint16_t MultipleStpLayer::getMstConfigRevision() const -{ - return be16toh(getMstpHeader()->mstConfigRevision); -} + uint16_t MultipleStpLayer::getMstConfigRevision() const + { + return be16toh(getMstpHeader()->mstConfigRevision); + } -void MultipleStpLayer::setMstConfigRevision(uint16_t value) -{ - getMstpHeader()->mstConfigRevision = htobe16(value); -} + void MultipleStpLayer::setMstConfigRevision(uint16_t value) + { + getMstpHeader()->mstConfigRevision = htobe16(value); + } -void MultipleStpLayer::setMstConfigDigest(const uint8_t *value, uint8_t len) -{ - memset(getMstpHeader()->mstConfigDigest, 0, 16); - memcpy(getMstpHeader()->mstConfigDigest, value, std::min(len, 16)); -} + void MultipleStpLayer::setMstConfigDigest(const uint8_t* value, uint8_t len) + { + memset(getMstpHeader()->mstConfigDigest, 0, 16); + memcpy(getMstpHeader()->mstConfigDigest, value, std::min(len, 16)); + } -void MultipleStpLayer::setMstConfigurationName(const std::string &value) -{ - memset(getMstpHeader()->mstConfigName, 0, 32); - memcpy(getMstpHeader()->mstConfigName, value.c_str(), std::min(value.size(), 32)); -} + void MultipleStpLayer::setMstConfigurationName(const std::string& value) + { + memset(getMstpHeader()->mstConfigName, 0, 32); + memcpy(getMstpHeader()->mstConfigName, value.c_str(), std::min(value.size(), 32)); + } -msti_conf_msg *MultipleStpLayer::getMstiConfMessages() const -{ - if (getNumberOfMSTIConfMessages()) - return (msti_conf_msg *)(m_Data + sizeof(mstp_conf_bpdu)); - return nullptr; -} + msti_conf_msg* MultipleStpLayer::getMstiConfMessages() const + { + if (getNumberOfMSTIConfMessages()) + return (msti_conf_msg*)(m_Data + sizeof(mstp_conf_bpdu)); + return nullptr; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/TLVData.cpp b/Packet++/src/TLVData.cpp index 161fe723cb..7fc571635d 100644 --- a/Packet++/src/TLVData.cpp +++ b/Packet++/src/TLVData.cpp @@ -5,109 +5,108 @@ namespace pcpp { -TLVRecordBuilder::TLVRecordBuilder() -{ - m_RecType = 0; - m_RecValueLen = 0; - m_RecValue = nullptr; -} - -TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, const uint8_t* recValue, uint8_t recValueLen) -{ - init(recType, recValue, recValueLen); -} - -TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, uint8_t recValue) -{ - init(recType, &recValue, sizeof(uint8_t)); -} - -TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, uint16_t recValue) -{ - recValue = htobe16(recValue); - init(recType, (uint8_t*)&recValue, sizeof(uint16_t)); -} - -TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, uint32_t recValue) -{ - recValue = htobe32(recValue); - init(recType, (uint8_t*)&recValue, sizeof(uint32_t)); -} + TLVRecordBuilder::TLVRecordBuilder() + { + m_RecType = 0; + m_RecValueLen = 0; + m_RecValue = nullptr; + } -TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, const IPv4Address& recValue) -{ - uint32_t recIntValue = recValue.toInt(); - init(recType, (uint8_t*)&recIntValue, sizeof(uint32_t)); -} + TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, const uint8_t* recValue, uint8_t recValueLen) + { + init(recType, recValue, recValueLen); + } -TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, const std::string& recValue, bool valueIsHexString) -{ - m_RecType = 0; - m_RecValueLen = 0; - m_RecValue = nullptr; + TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, uint8_t recValue) + { + init(recType, &recValue, sizeof(uint8_t)); + } - if (valueIsHexString) + TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, uint16_t recValue) { - uint8_t recValueByteArr[512]; - size_t byteArraySize = hexStringToByteArray(recValue, recValueByteArr, 512); - if (byteArraySize > 0) - { - init(recType, recValueByteArr, byteArraySize); - } + recValue = htobe16(recValue); + init(recType, (uint8_t*)&recValue, sizeof(uint16_t)); } - else + + TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, uint32_t recValue) { - uint8_t* recValueByteArr = (uint8_t*)recValue.c_str(); - init(recType, recValueByteArr, recValue.length()); + recValue = htobe32(recValue); + init(recType, (uint8_t*)&recValue, sizeof(uint32_t)); } -} -void TLVRecordBuilder::copyData(const TLVRecordBuilder& other) -{ - m_RecType = other.m_RecType; - m_RecValueLen = other.m_RecValueLen; - m_RecValue = nullptr; - if (other.m_RecValue != nullptr) + TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, const IPv4Address& recValue) { - m_RecValue = new uint8_t[m_RecValueLen]; - memcpy(m_RecValue, other.m_RecValue, m_RecValueLen); + uint32_t recIntValue = recValue.toInt(); + init(recType, (uint8_t*)&recIntValue, sizeof(uint32_t)); } -} -TLVRecordBuilder::TLVRecordBuilder(const TLVRecordBuilder& other) -{ - copyData(other); -} + TLVRecordBuilder::TLVRecordBuilder(uint32_t recType, const std::string& recValue, bool valueIsHexString) + { + m_RecType = 0; + m_RecValueLen = 0; + m_RecValue = nullptr; -TLVRecordBuilder& TLVRecordBuilder::operator=(const TLVRecordBuilder& other) -{ - if (m_RecValue != nullptr) + if (valueIsHexString) + { + uint8_t recValueByteArr[512]; + size_t byteArraySize = hexStringToByteArray(recValue, recValueByteArr, 512); + if (byteArraySize > 0) + { + init(recType, recValueByteArr, byteArraySize); + } + } + else + { + uint8_t* recValueByteArr = (uint8_t*)recValue.c_str(); + init(recType, recValueByteArr, recValue.length()); + } + } + + void TLVRecordBuilder::copyData(const TLVRecordBuilder& other) { - delete [] m_RecValue; + m_RecType = other.m_RecType; + m_RecValueLen = other.m_RecValueLen; m_RecValue = nullptr; + if (other.m_RecValue != nullptr) + { + m_RecValue = new uint8_t[m_RecValueLen]; + memcpy(m_RecValue, other.m_RecValue, m_RecValueLen); + } } - copyData(other); + TLVRecordBuilder::TLVRecordBuilder(const TLVRecordBuilder& other) + { + copyData(other); + } - return *this; -} + TLVRecordBuilder& TLVRecordBuilder::operator=(const TLVRecordBuilder& other) + { + if (m_RecValue != nullptr) + { + delete[] m_RecValue; + m_RecValue = nullptr; + } -TLVRecordBuilder::~TLVRecordBuilder() -{ - if (m_RecValue != nullptr) delete [] m_RecValue; -} + copyData(other); -void TLVRecordBuilder::init(uint32_t recType, const uint8_t* recValue, size_t recValueLen) -{ - m_RecType = recType; - m_RecValueLen = recValueLen; - m_RecValue = new uint8_t[recValueLen]; - if (recValue != nullptr) - memcpy(m_RecValue, recValue, recValueLen); - else - memset(m_RecValue, 0, recValueLen); -} + return *this; + } + TLVRecordBuilder::~TLVRecordBuilder() + { + if (m_RecValue != nullptr) + delete[] m_RecValue; + } + void TLVRecordBuilder::init(uint32_t recType, const uint8_t* recValue, size_t recValueLen) + { + m_RecType = recType; + m_RecValueLen = recValueLen; + m_RecValue = new uint8_t[recValueLen]; + if (recValue != nullptr) + memcpy(m_RecValue, recValue, recValueLen); + else + memset(m_RecValue, 0, recValueLen); + } -} +} // namespace pcpp diff --git a/Packet++/src/TcpLayer.cpp b/Packet++/src/TcpLayer.cpp index e992cf213a..8731c25fc2 100644 --- a/Packet++/src/TcpLayer.cpp +++ b/Packet++/src/TcpLayer.cpp @@ -28,497 +28,507 @@ namespace pcpp #define TCPOPT_DUMMY 0xff -/// ~~~~~~~~~~~~~~~~ -/// TcpOptionBuilder -/// ~~~~~~~~~~~~~~~~ + /// ~~~~~~~~~~~~~~~~ + /// TcpOptionBuilder + /// ~~~~~~~~~~~~~~~~ -TcpOptionBuilder::TcpOptionBuilder(NopEolOptionTypes optionType) -{ - switch (optionType) - { - case EOL: - init(static_cast(PCPP_TCPOPT_EOL), nullptr, 0); - break; - case NOP: - default: - init(static_cast(PCPP_TCPOPT_NOP), nullptr, 0); - break; - } -} - -TcpOptionBuilder::TcpOptionBuilder(const NopEolOptionEnumType optionType) -{ - switch (optionType) + TcpOptionBuilder::TcpOptionBuilder(NopEolOptionTypes optionType) { - case NopEolOptionEnumType::Eol: - init(static_cast(TcpOptionEnumType::Eol), nullptr, 0); - break; - case NopEolOptionEnumType::Nop: - default: - init(static_cast(TcpOptionEnumType::Nop), nullptr, 0); - break; + switch (optionType) + { + case EOL: + init(static_cast(PCPP_TCPOPT_EOL), nullptr, 0); + break; + case NOP: + default: + init(static_cast(PCPP_TCPOPT_NOP), nullptr, 0); + break; + } } -} -TcpOption TcpOptionBuilder::build() const -{ - uint8_t recType = static_cast(m_RecType); - size_t optionSize = m_RecValueLen + 2*sizeof(uint8_t); - - if (recType == static_cast(TcpOptionEnumType::Eol) || recType == static_cast(TcpOptionEnumType::Nop)) + TcpOptionBuilder::TcpOptionBuilder(const NopEolOptionEnumType optionType) { - if (m_RecValueLen != 0) + switch (optionType) { - PCPP_LOG_ERROR("TCP NOP and TCP EOL options are 1-byte long and don't have option value. Tried to set option value of size " << m_RecValueLen); - return TcpOption(nullptr); + case NopEolOptionEnumType::Eol: + init(static_cast(TcpOptionEnumType::Eol), nullptr, 0); + break; + case NopEolOptionEnumType::Nop: + default: + init(static_cast(TcpOptionEnumType::Nop), nullptr, 0); + break; } - - optionSize = 1; } - uint8_t* recordBuffer = new uint8_t[optionSize]; - memset(recordBuffer, 0, optionSize); - recordBuffer[0] = recType; - if (optionSize > 1) + TcpOption TcpOptionBuilder::build() const { - recordBuffer[1] = static_cast(optionSize); - if (optionSize > 2 && m_RecValue != nullptr) - memcpy(recordBuffer+2, m_RecValue, m_RecValueLen); - } - - return TcpOption(recordBuffer); -} - - - -/// ~~~~~~~~ -/// TcpLayer -/// ~~~~~~~~ - -uint16_t TcpLayer::getSrcPort() const -{ - return be16toh(getTcpHeader()->portSrc); -} - -uint16_t TcpLayer::getDstPort() const -{ - return be16toh(getTcpHeader()->portDst); -} + uint8_t recType = static_cast(m_RecType); + size_t optionSize = m_RecValueLen + 2 * sizeof(uint8_t); -TcpOption TcpLayer::getTcpOption(const TcpOptionEnumType option) const -{ - return m_OptionReader.getTLVRecord(static_cast(option), getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); -} + if (recType == static_cast(TcpOptionEnumType::Eol) || + recType == static_cast(TcpOptionEnumType::Nop)) + { + if (m_RecValueLen != 0) + { + PCPP_LOG_ERROR( + "TCP NOP and TCP EOL options are 1-byte long and don't have option value. Tried to set option value of size " + << m_RecValueLen); + return TcpOption(nullptr); + } + + optionSize = 1; + } -TcpOption TcpLayer::getFirstTcpOption() const -{ - return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); -} + uint8_t* recordBuffer = new uint8_t[optionSize]; + memset(recordBuffer, 0, optionSize); + recordBuffer[0] = recType; + if (optionSize > 1) + { + recordBuffer[1] = static_cast(optionSize); + if (optionSize > 2 && m_RecValue != nullptr) + memcpy(recordBuffer + 2, m_RecValue, m_RecValueLen); + } -TcpOption TcpLayer::getNextTcpOption(TcpOption& tcpOption) const -{ - TcpOption nextOpt = m_OptionReader.getNextTLVRecord(tcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); - if (nextOpt.isNotNull() && nextOpt.getType() == TCPOPT_DUMMY) - return TcpOption(nullptr); + return TcpOption(recordBuffer); + } - return nextOpt; -} + /// ~~~~~~~~ + /// TcpLayer + /// ~~~~~~~~ -size_t TcpLayer::getTcpOptionCount() const -{ - return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); -} + uint16_t TcpLayer::getSrcPort() const + { + return be16toh(getTcpHeader()->portSrc); + } -TcpOption TcpLayer::addTcpOption(const TcpOptionBuilder& optionBuilder) -{ - return addTcpOptionAt(optionBuilder, getHeaderLen()-m_NumOfTrailingBytes); -} + uint16_t TcpLayer::getDstPort() const + { + return be16toh(getTcpHeader()->portDst); + } -TcpOption TcpLayer::insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, const TcpOptionEnumType prevOptionType) -{ - int offset = 0; + TcpOption TcpLayer::getTcpOption(const TcpOptionEnumType option) const + { + return m_OptionReader.getTLVRecord(static_cast(option), getOptionsBasePtr(), + getHeaderLen() - sizeof(tcphdr)); + } - if (prevOptionType == TcpOptionEnumType::Unknown) + TcpOption TcpLayer::getFirstTcpOption() const { - offset = sizeof(tcphdr); + return m_OptionReader.getFirstTLVRecord(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); } - else + + TcpOption TcpLayer::getNextTcpOption(TcpOption& tcpOption) const { - const TcpOption prevOpt = getTcpOption(prevOptionType); - if (prevOpt.isNull()) - { - PCPP_LOG_ERROR("Previous option of type " << static_cast(prevOptionType) << " not found, cannot add a new TCP option"); + TcpOption nextOpt = + m_OptionReader.getNextTLVRecord(tcpOption, getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); + if (nextOpt.isNotNull() && nextOpt.getType() == TCPOPT_DUMMY) return TcpOption(nullptr); - } - offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + return nextOpt; } - return addTcpOptionAt(optionBuilder, offset); -} - -bool TcpLayer::removeTcpOption(const TcpOptionEnumType optionType) -{ - const TcpOption opt = getTcpOption(optionType); - if (opt.isNull()) + size_t TcpLayer::getTcpOptionCount() const { - return false; + return m_OptionReader.getTLVRecordCount(getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); } - // calculate total TCP option size - TcpOption curOpt = getFirstTcpOption(); - size_t totalOptSize = 0; - while (!curOpt.isNull()) + TcpOption TcpLayer::addTcpOption(const TcpOptionBuilder& optionBuilder) { - totalOptSize += curOpt.getTotalSize(); - curOpt = getNextTcpOption(curOpt); + return addTcpOptionAt(optionBuilder, getHeaderLen() - m_NumOfTrailingBytes); } - totalOptSize -= opt.getTotalSize(); + TcpOption TcpLayer::insertTcpOptionAfter(const TcpOptionBuilder& optionBuilder, + const TcpOptionEnumType prevOptionType) + { + int offset = 0; - int offset = opt.getRecordBasePtr() - m_Data; + if (prevOptionType == TcpOptionEnumType::Unknown) + { + offset = sizeof(tcphdr); + } + else + { + const TcpOption prevOpt = getTcpOption(prevOptionType); + if (prevOpt.isNull()) + { + PCPP_LOG_ERROR("Previous option of type " << static_cast(prevOptionType) + << " not found, cannot add a new TCP option"); + return TcpOption(nullptr); + } + + offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + } - if (!shortenLayer(offset, opt.getTotalSize())) - { - return false; + return addTcpOptionAt(optionBuilder, offset); } - adjustTcpOptionTrailer(totalOptSize); + bool TcpLayer::removeTcpOption(const TcpOptionEnumType optionType) + { + const TcpOption opt = getTcpOption(optionType); + if (opt.isNull()) + { + return false; + } - m_OptionReader.changeTLVRecordCount(-1); + // calculate total TCP option size + TcpOption curOpt = getFirstTcpOption(); + size_t totalOptSize = 0; + while (!curOpt.isNull()) + { + totalOptSize += curOpt.getTotalSize(); + curOpt = getNextTcpOption(curOpt); + } + totalOptSize -= opt.getTotalSize(); - return true; -} + int offset = opt.getRecordBasePtr() - m_Data; -bool TcpLayer::removeAllTcpOptions() -{ - const int offset = sizeof(tcphdr); + if (!shortenLayer(offset, opt.getTotalSize())) + { + return false; + } - if (!shortenLayer(offset, getHeaderLen()-offset)) - return false; + adjustTcpOptionTrailer(totalOptSize); - getTcpHeader()->dataOffset = sizeof(tcphdr)/4; - m_NumOfTrailingBytes = 0; - m_OptionReader.changeTLVRecordCount(0-getTcpOptionCount()); - return true; -} + m_OptionReader.changeTLVRecordCount(-1); -TcpOption TcpLayer::addTcpOptionAt(const TcpOptionBuilder& optionBuilder, const int offset) -{ - TcpOption newOption = optionBuilder.build(); - if (newOption.isNull()) - return newOption; - - // calculate total TCP option size - TcpOption curOpt = getFirstTcpOption(); - size_t totalOptSize = 0; - while (!curOpt.isNull()) - { - totalOptSize += curOpt.getTotalSize(); - curOpt = getNextTcpOption(curOpt); + return true; } - totalOptSize += newOption.getTotalSize(); - - size_t sizeToExtend = newOption.getTotalSize(); - if (!extendLayer(offset, sizeToExtend)) + bool TcpLayer::removeAllTcpOptions() { - PCPP_LOG_ERROR("Could not extend TcpLayer in [" << sizeToExtend << "] bytes"); - newOption.purgeRecordData(); - return TcpOption(nullptr); - } + const int offset = sizeof(tcphdr); - memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); + if (!shortenLayer(offset, getHeaderLen() - offset)) + return false; - newOption.purgeRecordData(); - - adjustTcpOptionTrailer(totalOptSize); + getTcpHeader()->dataOffset = sizeof(tcphdr) / 4; + m_NumOfTrailingBytes = 0; + m_OptionReader.changeTLVRecordCount(0 - getTcpOptionCount()); + return true; + } - m_OptionReader.changeTLVRecordCount(1); + TcpOption TcpLayer::addTcpOptionAt(const TcpOptionBuilder& optionBuilder, const int offset) + { + TcpOption newOption = optionBuilder.build(); + if (newOption.isNull()) + return newOption; + + // calculate total TCP option size + TcpOption curOpt = getFirstTcpOption(); + size_t totalOptSize = 0; + while (!curOpt.isNull()) + { + totalOptSize += curOpt.getTotalSize(); + curOpt = getNextTcpOption(curOpt); + } + totalOptSize += newOption.getTotalSize(); - uint8_t* newOptPtr = m_Data + offset; + size_t sizeToExtend = newOption.getTotalSize(); - return TcpOption(newOptPtr); -} + if (!extendLayer(offset, sizeToExtend)) + { + PCPP_LOG_ERROR("Could not extend TcpLayer in [" << sizeToExtend << "] bytes"); + newOption.purgeRecordData(); + return TcpOption(nullptr); + } -void TcpLayer::adjustTcpOptionTrailer(const size_t totalOptSize) -{ - int newNumberOfTrailingBytes = 0; - while ((totalOptSize + newNumberOfTrailingBytes) % 4 != 0) - newNumberOfTrailingBytes++; + memcpy(m_Data + offset, newOption.getRecordBasePtr(), newOption.getTotalSize()); - if (newNumberOfTrailingBytes < m_NumOfTrailingBytes) - shortenLayer(sizeof(tcphdr)+totalOptSize, m_NumOfTrailingBytes - newNumberOfTrailingBytes - 1); - else if (newNumberOfTrailingBytes > m_NumOfTrailingBytes) - extendLayer(sizeof(tcphdr)+totalOptSize, newNumberOfTrailingBytes - m_NumOfTrailingBytes); + newOption.purgeRecordData(); - m_NumOfTrailingBytes = newNumberOfTrailingBytes; + adjustTcpOptionTrailer(totalOptSize); - for (int i = 0; i < m_NumOfTrailingBytes; i++) - m_Data[sizeof(tcphdr) + totalOptSize + i] = TCPOPT_DUMMY; + m_OptionReader.changeTLVRecordCount(1); - getTcpHeader()->dataOffset = (sizeof(tcphdr) + totalOptSize + m_NumOfTrailingBytes)/4; -} + uint8_t* newOptPtr = m_Data + offset; -uint16_t TcpLayer::calculateChecksum(const bool writeResultToPacket) -{ - tcphdr* tcpHdr = getTcpHeader(); - uint16_t checksumRes = 0; - const uint16_t currChecksumValue = tcpHdr->headerChecksum; + return TcpOption(newOptPtr); + } - if (m_PrevLayer != nullptr) + void TcpLayer::adjustTcpOptionTrailer(const size_t totalOptSize) { - tcpHdr->headerChecksum = 0; - PCPP_LOG_DEBUG("TCP data len = " << m_DataLen); - - if (m_PrevLayer->getProtocol() == IPv4) - { - const IPv4Address srcIP = static_cast(m_PrevLayer)->getSrcIPv4Address(); - const IPv4Address dstIP = static_cast(m_PrevLayer)->getDstIPv4Address(); + int newNumberOfTrailingBytes = 0; + while ((totalOptSize + newNumberOfTrailingBytes) % 4 != 0) + newNumberOfTrailingBytes++; - checksumRes = pcpp::computePseudoHdrChecksum(reinterpret_cast(tcpHdr), getDataLen(), - IPAddress::IPv4AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP); + if (newNumberOfTrailingBytes < m_NumOfTrailingBytes) + shortenLayer(sizeof(tcphdr) + totalOptSize, m_NumOfTrailingBytes - newNumberOfTrailingBytes - 1); + else if (newNumberOfTrailingBytes > m_NumOfTrailingBytes) + extendLayer(sizeof(tcphdr) + totalOptSize, newNumberOfTrailingBytes - m_NumOfTrailingBytes); - PCPP_LOG_DEBUG("calculated IPv4 TCP checksum = 0x" << std::uppercase << std::hex << checksumRes); - } - else if (m_PrevLayer->getProtocol() == IPv6) - { - const IPv6Address srcIP = static_cast(m_PrevLayer)->getSrcIPv6Address(); - const IPv6Address dstIP = static_cast(m_PrevLayer)->getDstIPv6Address(); + m_NumOfTrailingBytes = newNumberOfTrailingBytes; - checksumRes = computePseudoHdrChecksum(reinterpret_cast(tcpHdr), getDataLen(), - IPAddress::IPv6AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP); + for (int i = 0; i < m_NumOfTrailingBytes; i++) + m_Data[sizeof(tcphdr) + totalOptSize + i] = TCPOPT_DUMMY; - PCPP_LOG_DEBUG("calculated IPv6 TCP checksum = 0xX" << std::uppercase << std::hex << checksumRes); - } + getTcpHeader()->dataOffset = (sizeof(tcphdr) + totalOptSize + m_NumOfTrailingBytes) / 4; } - if(writeResultToPacket) - tcpHdr->headerChecksum = htobe16(checksumRes); - else - tcpHdr->headerChecksum = currChecksumValue; - - return checksumRes; -} - -void TcpLayer::initLayer() -{ - m_DataLen = sizeof(tcphdr); - m_Data = new uint8_t[m_DataLen]; - memset(m_Data, 0, m_DataLen); - m_Protocol = TCP; - m_NumOfTrailingBytes = 0; - getTcpHeader()->dataOffset = sizeof(tcphdr)/4; -} - -TcpLayer::TcpLayer(uint8_t* data, const size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet) -{ - m_Protocol = TCP; - m_NumOfTrailingBytes = 0; -} - -TcpLayer::TcpLayer() -{ - initLayer(); -} + uint16_t TcpLayer::calculateChecksum(const bool writeResultToPacket) + { + tcphdr* tcpHdr = getTcpHeader(); + uint16_t checksumRes = 0; + const uint16_t currChecksumValue = tcpHdr->headerChecksum; -TcpLayer::TcpLayer(const uint16_t portSrc, const uint16_t portDst) -{ - initLayer(); - getTcpHeader()->portDst = htobe16(portDst); - getTcpHeader()->portSrc = htobe16(portSrc); -} + if (m_PrevLayer != nullptr) + { + tcpHdr->headerChecksum = 0; + PCPP_LOG_DEBUG("TCP data len = " << m_DataLen); + + if (m_PrevLayer->getProtocol() == IPv4) + { + const IPv4Address srcIP = static_cast(m_PrevLayer)->getSrcIPv4Address(); + const IPv4Address dstIP = static_cast(m_PrevLayer)->getDstIPv4Address(); + + checksumRes = + pcpp::computePseudoHdrChecksum(reinterpret_cast(tcpHdr), getDataLen(), + IPAddress::IPv4AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP); + + PCPP_LOG_DEBUG("calculated IPv4 TCP checksum = 0x" << std::uppercase << std::hex << checksumRes); + } + else if (m_PrevLayer->getProtocol() == IPv6) + { + const IPv6Address srcIP = static_cast(m_PrevLayer)->getSrcIPv6Address(); + const IPv6Address dstIP = static_cast(m_PrevLayer)->getDstIPv6Address(); + + checksumRes = computePseudoHdrChecksum(reinterpret_cast(tcpHdr), getDataLen(), + IPAddress::IPv6AddressType, PACKETPP_IPPROTO_TCP, srcIP, dstIP); + + PCPP_LOG_DEBUG("calculated IPv6 TCP checksum = 0xX" << std::uppercase << std::hex << checksumRes); + } + } -void TcpLayer::copyLayerData(const TcpLayer& other) -{ - m_OptionReader = other.m_OptionReader; - m_NumOfTrailingBytes = other.m_NumOfTrailingBytes; -} + if (writeResultToPacket) + tcpHdr->headerChecksum = htobe16(checksumRes); + else + tcpHdr->headerChecksum = currChecksumValue; -TcpLayer::TcpLayer(const TcpLayer& other) : Layer(other) -{ - copyLayerData(other); -} + return checksumRes; + } -TcpLayer& TcpLayer::operator=(const TcpLayer& other) -{ - Layer::operator=(other); + void TcpLayer::initLayer() + { + m_DataLen = sizeof(tcphdr); + m_Data = new uint8_t[m_DataLen]; + memset(m_Data, 0, m_DataLen); + m_Protocol = TCP; + m_NumOfTrailingBytes = 0; + getTcpHeader()->dataOffset = sizeof(tcphdr) / 4; + } - copyLayerData(other); + TcpLayer::TcpLayer(uint8_t* data, const size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet) + { + m_Protocol = TCP; + m_NumOfTrailingBytes = 0; + } - return *this; -} + TcpLayer::TcpLayer() + { + initLayer(); + } -void TcpLayer::parseNextLayer() -{ - const size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; - - uint8_t* payload = m_Data + headerLen; - const size_t payloadLen = m_DataLen - headerLen; - const uint16_t portDst = getDstPort(); - const uint16_t portSrc = getSrcPort(); - const char* payloadChar = reinterpret_cast(payload); - - if (HttpMessage::isHttpPort(portDst) && - HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) - m_NextLayer = new HttpRequestLayer(payload, payloadLen, this, m_Packet); - else if (HttpMessage::isHttpPort(portSrc) && - HttpResponseFirstLine::parseVersion(payloadChar, payloadLen) != HttpVersion::HttpVersionUnknown && - !HttpResponseFirstLine::parseStatusCode(payloadChar, payloadLen).isUnsupportedCode()) - m_NextLayer = new HttpResponseLayer(payload, payloadLen, this, m_Packet); - else if (SSLLayer::IsSSLMessage(portSrc, portDst, payload, payloadLen)) - m_NextLayer = SSLLayer::createSSLMessage(payload, payloadLen, this, m_Packet); - else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) + TcpLayer::TcpLayer(const uint16_t portSrc, const uint16_t portDst) { - if (SipRequestFirstLine::parseMethod(payloadChar, payloadLen) != SipRequestLayer::SipMethodUnknown) - m_NextLayer = new SipRequestLayer(payload, payloadLen, this, m_Packet); - else if (SipResponseFirstLine::parseStatusCode(payloadChar, payloadLen) != SipResponseLayer::SipStatusCodeUnknown) - m_NextLayer = new SipResponseLayer(payload, payloadLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + initLayer(); + getTcpHeader()->portDst = htobe16(portDst); + getTcpHeader()->portSrc = htobe16(portSrc); } - else if (BgpLayer::isBgpPort(portSrc, portDst)) + + void TcpLayer::copyLayerData(const TcpLayer& other) { - m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, m_Packet); - if (!m_NextLayer) - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + m_OptionReader = other.m_OptionReader; + m_NumOfTrailingBytes = other.m_NumOfTrailingBytes; } - else if (SSHLayer::isSSHPort(portSrc, portDst)) - m_NextLayer = SSHLayer::createSSHMessage(payload, payloadLen, this, m_Packet); - else if (DnsLayer::isDataValid(payload, payloadLen, true) && (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) - m_NextLayer = new DnsOverTcpLayer(payload, payloadLen, this, m_Packet); - else if (TelnetLayer::isDataValid(payload, payloadLen) && (TelnetLayer::isTelnetPort(portDst) || TelnetLayer::isTelnetPort(portSrc))) - m_NextLayer = new TelnetLayer(payload, payloadLen, this, m_Packet); - else if (FtpLayer::isFtpPort(portSrc) && FtpLayer::isDataValid(payload, payloadLen)) - m_NextLayer = new FtpResponseLayer(payload, payloadLen, this, m_Packet); - else if (FtpLayer::isFtpPort(portDst) && FtpLayer::isDataValid(payload, payloadLen)) - m_NextLayer = new FtpRequestLayer(payload, payloadLen, this, m_Packet); - else if (FtpLayer::isFtpDataPort(portSrc) || FtpLayer::isFtpDataPort(portDst)) - m_NextLayer = new FtpDataLayer(payload, payloadLen, this, m_Packet); - else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) - m_NextLayer = SomeIpLayer::parseSomeIpLayer(payload, payloadLen, this, m_Packet); - else if (TpktLayer::isDataValid(payload, payloadLen) && TpktLayer::isTpktPort(portSrc, portDst)) - m_NextLayer = new TpktLayer(payload, payloadLen, this, m_Packet); - else if (SmtpLayer::isSmtpPort(portSrc) && SmtpLayer::isDataValid(payload, payloadLen)) - m_NextLayer = new SmtpResponseLayer(payload, payloadLen, this, m_Packet); - else if (SmtpLayer::isSmtpPort(portDst) && SmtpLayer::isDataValid(payload, payloadLen)) - m_NextLayer = new SmtpRequestLayer(payload, payloadLen, this, m_Packet); - else if (LdapLayer::isLdapPort(portDst) || LdapLayer::isLdapPort(portSrc)) + + TcpLayer::TcpLayer(const TcpLayer& other) : Layer(other) { - m_NextLayer = LdapLayer::parseLdapMessage(payload, payloadLen, this, m_Packet); - if (!m_NextLayer) - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + copyLayerData(other); } - else - m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); -} -void TcpLayer::computeCalculateFields() -{ - tcphdr* tcpHdr = getTcpHeader(); + TcpLayer& TcpLayer::operator=(const TcpLayer& other) + { + Layer::operator=(other); - tcpHdr->dataOffset = getHeaderLen() >> 2; - calculateChecksum(true); -} + copyLayerData(other); -std::string TcpLayer::toString() const -{ - const tcphdr* hdr = getTcpHeader(); - std::string result = "TCP Layer, "; - if (hdr->synFlag) - { - if (hdr->ackFlag) - result += "[SYN, ACK], "; - else - result += "[SYN], "; + return *this; } - else if (hdr->finFlag) + + void TcpLayer::parseNextLayer() { - if (hdr->ackFlag) - result += "[FIN, ACK], "; + const size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + + uint8_t* payload = m_Data + headerLen; + const size_t payloadLen = m_DataLen - headerLen; + const uint16_t portDst = getDstPort(); + const uint16_t portSrc = getSrcPort(); + const char* payloadChar = reinterpret_cast(payload); + + if (HttpMessage::isHttpPort(portDst) && + HttpRequestFirstLine::parseMethod(payloadChar, payloadLen) != HttpRequestLayer::HttpMethodUnknown) + m_NextLayer = new HttpRequestLayer(payload, payloadLen, this, m_Packet); + else if (HttpMessage::isHttpPort(portSrc) && + HttpResponseFirstLine::parseVersion(payloadChar, payloadLen) != HttpVersion::HttpVersionUnknown && + !HttpResponseFirstLine::parseStatusCode(payloadChar, payloadLen).isUnsupportedCode()) + m_NextLayer = new HttpResponseLayer(payload, payloadLen, this, m_Packet); + else if (SSLLayer::IsSSLMessage(portSrc, portDst, payload, payloadLen)) + m_NextLayer = SSLLayer::createSSLMessage(payload, payloadLen, this, m_Packet); + else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) + { + if (SipRequestFirstLine::parseMethod(payloadChar, payloadLen) != SipRequestLayer::SipMethodUnknown) + m_NextLayer = new SipRequestLayer(payload, payloadLen, this, m_Packet); + else if (SipResponseFirstLine::parseStatusCode(payloadChar, payloadLen) != + SipResponseLayer::SipStatusCodeUnknown) + m_NextLayer = new SipResponseLayer(payload, payloadLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } + else if (BgpLayer::isBgpPort(portSrc, portDst)) + { + m_NextLayer = BgpLayer::parseBgpLayer(payload, payloadLen, this, m_Packet); + if (!m_NextLayer) + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } + else if (SSHLayer::isSSHPort(portSrc, portDst)) + m_NextLayer = SSHLayer::createSSHMessage(payload, payloadLen, this, m_Packet); + else if (DnsLayer::isDataValid(payload, payloadLen, true) && + (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) + m_NextLayer = new DnsOverTcpLayer(payload, payloadLen, this, m_Packet); + else if (TelnetLayer::isDataValid(payload, payloadLen) && + (TelnetLayer::isTelnetPort(portDst) || TelnetLayer::isTelnetPort(portSrc))) + m_NextLayer = new TelnetLayer(payload, payloadLen, this, m_Packet); + else if (FtpLayer::isFtpPort(portSrc) && FtpLayer::isDataValid(payload, payloadLen)) + m_NextLayer = new FtpResponseLayer(payload, payloadLen, this, m_Packet); + else if (FtpLayer::isFtpPort(portDst) && FtpLayer::isDataValid(payload, payloadLen)) + m_NextLayer = new FtpRequestLayer(payload, payloadLen, this, m_Packet); + else if (FtpLayer::isFtpDataPort(portSrc) || FtpLayer::isFtpDataPort(portDst)) + m_NextLayer = new FtpDataLayer(payload, payloadLen, this, m_Packet); + else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) + m_NextLayer = SomeIpLayer::parseSomeIpLayer(payload, payloadLen, this, m_Packet); + else if (TpktLayer::isDataValid(payload, payloadLen) && TpktLayer::isTpktPort(portSrc, portDst)) + m_NextLayer = new TpktLayer(payload, payloadLen, this, m_Packet); + else if (SmtpLayer::isSmtpPort(portSrc) && SmtpLayer::isDataValid(payload, payloadLen)) + m_NextLayer = new SmtpResponseLayer(payload, payloadLen, this, m_Packet); + else if (SmtpLayer::isSmtpPort(portDst) && SmtpLayer::isDataValid(payload, payloadLen)) + m_NextLayer = new SmtpRequestLayer(payload, payloadLen, this, m_Packet); + else if (LdapLayer::isLdapPort(portDst) || LdapLayer::isLdapPort(portSrc)) + { + m_NextLayer = LdapLayer::parseLdapMessage(payload, payloadLen, this, m_Packet); + if (!m_NextLayer) + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); + } else - result += "[FIN], "; + m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } - else if (hdr->ackFlag) - result += "[ACK], "; - std::ostringstream srcPortStream; - srcPortStream << getSrcPort(); - std::ostringstream dstPortStream; - dstPortStream << getDstPort(); - result += "Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); + void TcpLayer::computeCalculateFields() + { + tcphdr* tcpHdr = getTcpHeader(); - return result; -} + tcpHdr->dataOffset = getHeaderLen() >> 2; + calculateChecksum(true); + } -/// ~~~~~~~~ -/// TcpLayer Deprecated Code -/// ~~~~~~~~ + std::string TcpLayer::toString() const + { + const tcphdr* hdr = getTcpHeader(); + std::string result = "TCP Layer, "; + if (hdr->synFlag) + { + if (hdr->ackFlag) + result += "[SYN, ACK], "; + else + result += "[SYN], "; + } + else if (hdr->finFlag) + { + if (hdr->ackFlag) + result += "[FIN, ACK], "; + else + result += "[FIN], "; + } + else if (hdr->ackFlag) + result += "[ACK], "; -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED -TcpOption TcpLayer::addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType) -{ - int offset = 0; + std::ostringstream srcPortStream; + srcPortStream << getSrcPort(); + std::ostringstream dstPortStream; + dstPortStream << getDstPort(); + result += "Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); - if (prevOptionType == TcpOptionType::TCPOPT_Unknown) - { - offset = sizeof(tcphdr); + return result; } - else + + /// ~~~~~~~~ + /// TcpLayer Deprecated Code + /// ~~~~~~~~ + + DISABLE_WARNING_PUSH + DISABLE_WARNING_DEPRECATED + TcpOption TcpLayer::addTcpOptionAfter(const TcpOptionBuilder& optionBuilder, TcpOptionType prevOptionType) { - TcpOption prevOpt = getTcpOption(prevOptionType); - if (prevOpt.isNull()) + int offset = 0; + + if (prevOptionType == TcpOptionType::TCPOPT_Unknown) { - PCPP_LOG_ERROR("Previous option of type " << static_cast(prevOptionType) << " not found, cannot add a new TCP option"); - return TcpOption(nullptr); + offset = sizeof(tcphdr); + } + else + { + TcpOption prevOpt = getTcpOption(prevOptionType); + if (prevOpt.isNull()) + { + PCPP_LOG_ERROR("Previous option of type " << static_cast(prevOptionType) + << " not found, cannot add a new TCP option"); + return TcpOption(nullptr); + } + + offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; } - offset = prevOpt.getRecordBasePtr() + prevOpt.getTotalSize() - m_Data; + return addTcpOptionAt(optionBuilder, offset); } - return addTcpOptionAt(optionBuilder, offset); -} - -TcpOption TcpLayer::getTcpOption(TcpOptionType option) const -{ - return m_OptionReader.getTLVRecord(static_cast(option), getOptionsBasePtr(), getHeaderLen() - sizeof(tcphdr)); -} - -bool TcpLayer::removeTcpOption(TcpOptionType optionType) -{ - TcpOption opt = getTcpOption(optionType); - if (opt.isNull()) + TcpOption TcpLayer::getTcpOption(TcpOptionType option) const { - return false; + return m_OptionReader.getTLVRecord(static_cast(option), getOptionsBasePtr(), + getHeaderLen() - sizeof(tcphdr)); } - // calculate total TCP option size - TcpOption curOpt = getFirstTcpOption(); - size_t totalOptSize = 0; - while (!curOpt.isNull()) + bool TcpLayer::removeTcpOption(TcpOptionType optionType) { - totalOptSize += curOpt.getTotalSize(); - curOpt = getNextTcpOption(curOpt); - } - totalOptSize -= opt.getTotalSize(); + TcpOption opt = getTcpOption(optionType); + if (opt.isNull()) + { + return false; + } + // calculate total TCP option size + TcpOption curOpt = getFirstTcpOption(); + size_t totalOptSize = 0; + while (!curOpt.isNull()) + { + totalOptSize += curOpt.getTotalSize(); + curOpt = getNextTcpOption(curOpt); + } + totalOptSize -= opt.getTotalSize(); - int offset = opt.getRecordBasePtr() - m_Data; + int offset = opt.getRecordBasePtr() - m_Data; - if (!shortenLayer(offset, opt.getTotalSize())) - { - return false; - } + if (!shortenLayer(offset, opt.getTotalSize())) + { + return false; + } - adjustTcpOptionTrailer(totalOptSize); + adjustTcpOptionTrailer(totalOptSize); - m_OptionReader.changeTLVRecordCount(-1); + m_OptionReader.changeTLVRecordCount(-1); - return true; -} -DISABLE_WARNING_POP + return true; + } + DISABLE_WARNING_POP -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/TcpReassembly.cpp b/Packet++/src/TcpReassembly.cpp index 3a696abf43..17e04ddb4f 100644 --- a/Packet++/src/TcpReassembly.cpp +++ b/Packet++/src/TcpReassembly.cpp @@ -10,686 +10,706 @@ #include "EndianPortable.h" #include "TimespecTimeval.h" #ifdef _MSC_VER -#include +# include #endif #define PURGE_FREQ_SECS 1 -#define SEQ_LT(a,b) ((int32_t)((a)-(b)) < 0) -#define SEQ_LEQ(a,b) ((int32_t)((a)-(b)) <= 0) -#define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0) -#define SEQ_GEQ(a,b) ((int32_t)((a)-(b)) >= 0) +#define SEQ_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define SEQ_LEQ(a, b) ((int32_t)((a) - (b)) <= 0) +#define SEQ_GT(a, b) ((int32_t)((a) - (b)) > 0) +#define SEQ_GEQ(a, b) ((int32_t)((a) - (b)) >= 0) namespace pcpp { -static timeval timespecToTimeval(const timespec& in) -{ - timeval out; - TIMESPEC_TO_TIMEVAL(&out, &in); - return out; -} - - -TcpReassembly::TcpReassembly(OnTcpMessageReady onMessageReadyCallback, void* userCookie, OnTcpConnectionStart onConnectionStartCallback, OnTcpConnectionEnd onConnectionEndCallback, const TcpReassemblyConfiguration &config) -{ - m_OnMessageReadyCallback = onMessageReadyCallback; - m_UserCookie = userCookie; - m_OnConnStart = onConnectionStartCallback; - m_OnConnEnd = onConnectionEndCallback; - m_ClosedConnectionDelay = (config.closedConnectionDelay > 0) ? config.closedConnectionDelay : 5; - m_RemoveConnInfo = config.removeConnInfo; - m_MaxNumToClean = (config.removeConnInfo == true && config.maxNumToClean == 0) ? 30 : config.maxNumToClean; - m_MaxOutOfOrderFragments = config.maxOutOfOrderFragments; - m_PurgeTimepoint = time(nullptr) + PURGE_FREQ_SECS; - m_EnableBaseBufferClearCondition = config.enableBaseBufferClearCondition; -} - - -TcpReassembly::ReassemblyStatus TcpReassembly::reassemblePacket(Packet& tcpData) -{ - // automatic cleanup - if (m_RemoveConnInfo == true) - { - if (time(nullptr) >= m_PurgeTimepoint) - { - purgeClosedConnections(); - m_PurgeTimepoint = time(nullptr) + PURGE_FREQ_SECS; - } - } - - - // calculate packet's source and dest IP address - IPAddress srcIP, dstIP; - - if (tcpData.isPacketOfType(IP)) + static timeval timespecToTimeval(const timespec& in) { - const IPLayer* ipLayer = tcpData.getLayerOfType(); - srcIP = ipLayer->getSrcIPAddress(); - dstIP = ipLayer->getDstIPAddress(); + timeval out; + TIMESPEC_TO_TIMEVAL(&out, &in); + return out; } - else - return NonIpPacket; - // Ignore non-TCP packets - TcpLayer* tcpLayer = tcpData.getLayerOfType(true); // lookup in reverse order - if (tcpLayer == nullptr) + TcpReassembly::TcpReassembly(OnTcpMessageReady onMessageReadyCallback, void* userCookie, + OnTcpConnectionStart onConnectionStartCallback, + OnTcpConnectionEnd onConnectionEndCallback, const TcpReassemblyConfiguration& config) { - return NonTcpPacket; + m_OnMessageReadyCallback = onMessageReadyCallback; + m_UserCookie = userCookie; + m_OnConnStart = onConnectionStartCallback; + m_OnConnEnd = onConnectionEndCallback; + m_ClosedConnectionDelay = (config.closedConnectionDelay > 0) ? config.closedConnectionDelay : 5; + m_RemoveConnInfo = config.removeConnInfo; + m_MaxNumToClean = (config.removeConnInfo == true && config.maxNumToClean == 0) ? 30 : config.maxNumToClean; + m_MaxOutOfOrderFragments = config.maxOutOfOrderFragments; + m_PurgeTimepoint = time(nullptr) + PURGE_FREQ_SECS; + m_EnableBaseBufferClearCondition = config.enableBaseBufferClearCondition; } - // Ignore the packet if it's an ICMP packet that has a TCP layer - // Several ICMP messages (like "destination unreachable") have TCP data as part of the ICMP message. - // This is not real TCP data and packet can be ignored - if (tcpData.isPacketOfType(ICMP)) + TcpReassembly::ReassemblyStatus TcpReassembly::reassemblePacket(Packet& tcpData) { - PCPP_LOG_DEBUG("Packet is of type ICMP so TCP data is probably part of the ICMP message. Ignoring this packet"); - return NonTcpPacket; - } - - ReassemblyStatus status = TcpMessageHandled; + // automatic cleanup + if (m_RemoveConnInfo == true) + { + if (time(nullptr) >= m_PurgeTimepoint) + { + purgeClosedConnections(); + m_PurgeTimepoint = time(nullptr) + PURGE_FREQ_SECS; + } + } - // set the TCP payload size - size_t tcpPayloadSize = tcpLayer->getLayerPayloadSize(); + // calculate packet's source and dest IP address + IPAddress srcIP, dstIP; - // calculate if this packet has FIN or RST flags - bool isFin = (tcpLayer->getTcpHeader()->finFlag == 1); - bool isRst = (tcpLayer->getTcpHeader()->rstFlag == 1); - bool isFinOrRst = isFin || isRst; + if (tcpData.isPacketOfType(IP)) + { + const IPLayer* ipLayer = tcpData.getLayerOfType(); + srcIP = ipLayer->getSrcIPAddress(); + dstIP = ipLayer->getDstIPAddress(); + } + else + return NonIpPacket; - // ignore ACK packets or TCP packets with no payload (except for SYN, FIN or RST packets which we'll later need) - if (tcpPayloadSize == 0 && tcpLayer->getTcpHeader()->synFlag == 0 && !isFinOrRst) - { - return Ignore_PacketWithNoData; - } + // Ignore non-TCP packets + TcpLayer* tcpLayer = tcpData.getLayerOfType(true); // lookup in reverse order + if (tcpLayer == nullptr) + { + return NonTcpPacket; + } - TcpReassemblyData* tcpReassemblyData = nullptr; + // Ignore the packet if it's an ICMP packet that has a TCP layer + // Several ICMP messages (like "destination unreachable") have TCP data as part of the ICMP message. + // This is not real TCP data and packet can be ignored + if (tcpData.isPacketOfType(ICMP)) + { + PCPP_LOG_DEBUG( + "Packet is of type ICMP so TCP data is probably part of the ICMP message. Ignoring this packet"); + return NonTcpPacket; + } - // calculate flow key for this packet - uint32_t flowKey = hash5Tuple(&tcpData); + ReassemblyStatus status = TcpMessageHandled; - // time stamp for this packet - timeval currTime = timespecToTimeval(tcpData.getRawPacket()->getPacketTimeStamp()); + // set the TCP payload size + size_t tcpPayloadSize = tcpLayer->getLayerPayloadSize(); - // find the connection in the connection map - ConnectionList::iterator iter = m_ConnectionList.find(flowKey); + // calculate if this packet has FIN or RST flags + bool isFin = (tcpLayer->getTcpHeader()->finFlag == 1); + bool isRst = (tcpLayer->getTcpHeader()->rstFlag == 1); + bool isFinOrRst = isFin || isRst; - if (iter == m_ConnectionList.end()) - { - // if it's a packet of a new connection, create a TcpReassemblyData object and add it to the active connection list - std::pair pair = m_ConnectionList.insert(std::make_pair(flowKey, TcpReassemblyData())); - tcpReassemblyData = &pair.first->second; - tcpReassemblyData->connData.srcIP = srcIP; - tcpReassemblyData->connData.dstIP = dstIP; - tcpReassemblyData->connData.srcPort = tcpLayer->getSrcPort(); - tcpReassemblyData->connData.dstPort = tcpLayer->getDstPort(); - tcpReassemblyData->connData.flowKey = flowKey; - tcpReassemblyData->connData.setStartTime(currTime); - - m_ConnectionInfo[flowKey] = tcpReassemblyData->connData; - - // fire connection start callback - if (m_OnConnStart != nullptr) - m_OnConnStart(tcpReassemblyData->connData, m_UserCookie); - } - else // connection already exists - { - // if this packet belongs to a connection that was already closed (for example: data packet that comes after FIN), ignore it. - if (iter->second.closed) + // ignore ACK packets or TCP packets with no payload (except for SYN, FIN or RST packets which we'll later need) + if (tcpPayloadSize == 0 && tcpLayer->getTcpHeader()->synFlag == 0 && !isFinOrRst) { - PCPP_LOG_DEBUG("Ignoring packet of already closed flow [0x" << std::hex << flowKey << "]"); - return Ignore_PacketOfClosedFlow; + return Ignore_PacketWithNoData; } - tcpReassemblyData = &iter->second; + TcpReassemblyData* tcpReassemblyData = nullptr; - if (currTime.tv_sec > tcpReassemblyData->connData.endTime.tv_sec) + // calculate flow key for this packet + uint32_t flowKey = hash5Tuple(&tcpData); + + // time stamp for this packet + timeval currTime = timespecToTimeval(tcpData.getRawPacket()->getPacketTimeStamp()); + + // find the connection in the connection map + ConnectionList::iterator iter = m_ConnectionList.find(flowKey); + + if (iter == m_ConnectionList.end()) { - tcpReassemblyData->connData.setEndTime(currTime); - m_ConnectionInfo[flowKey].setEndTime(currTime); + // if it's a packet of a new connection, create a TcpReassemblyData object and add it to the active + // connection list + std::pair pair = + m_ConnectionList.insert(std::make_pair(flowKey, TcpReassemblyData())); + tcpReassemblyData = &pair.first->second; + tcpReassemblyData->connData.srcIP = srcIP; + tcpReassemblyData->connData.dstIP = dstIP; + tcpReassemblyData->connData.srcPort = tcpLayer->getSrcPort(); + tcpReassemblyData->connData.dstPort = tcpLayer->getDstPort(); + tcpReassemblyData->connData.flowKey = flowKey; + tcpReassemblyData->connData.setStartTime(currTime); + + m_ConnectionInfo[flowKey] = tcpReassemblyData->connData; + + // fire connection start callback + if (m_OnConnStart != nullptr) + m_OnConnStart(tcpReassemblyData->connData, m_UserCookie); } - else if (currTime.tv_sec == tcpReassemblyData->connData.endTime.tv_sec) + else // connection already exists { - if (currTime.tv_usec > tcpReassemblyData->connData.endTime.tv_usec) + // if this packet belongs to a connection that was already closed (for example: data packet that comes after + // FIN), ignore it. + if (iter->second.closed) + { + PCPP_LOG_DEBUG("Ignoring packet of already closed flow [0x" << std::hex << flowKey << "]"); + return Ignore_PacketOfClosedFlow; + } + + tcpReassemblyData = &iter->second; + + if (currTime.tv_sec > tcpReassemblyData->connData.endTime.tv_sec) { tcpReassemblyData->connData.setEndTime(currTime); m_ConnectionInfo[flowKey].setEndTime(currTime); } + else if (currTime.tv_sec == tcpReassemblyData->connData.endTime.tv_sec) + { + if (currTime.tv_usec > tcpReassemblyData->connData.endTime.tv_usec) + { + tcpReassemblyData->connData.setEndTime(currTime); + m_ConnectionInfo[flowKey].setEndTime(currTime); + } + } } - } - timeval timestampOfTheReceivedPacket = currTime; - int8_t sideIndex = -1; - bool first = false; + timeval timestampOfTheReceivedPacket = currTime; + int8_t sideIndex = -1; + bool first = false; - // calculate packet's source port - uint16_t srcPort = tcpLayer->getTcpHeader()->portSrc; + // calculate packet's source port + uint16_t srcPort = tcpLayer->getTcpHeader()->portSrc; - // if this is a new connection and it's the first packet we see on that connection - if (tcpReassemblyData->numOfSides == 0) - { - PCPP_LOG_DEBUG("Setting side for new connection"); - - // open the first side of the connection, side index is 0 - sideIndex = 0; - tcpReassemblyData->twoSides[sideIndex].srcIP = srcIP; - tcpReassemblyData->twoSides[sideIndex].srcPort = srcPort; - tcpReassemblyData->numOfSides++; - first = true; - } - // if there is already one side in this connection (which will be at side index 0) - else if (tcpReassemblyData->numOfSides == 1) - { - // check if packet belongs to that side - if (tcpReassemblyData->twoSides[0].srcPort == srcPort && tcpReassemblyData->twoSides[0].srcIP == srcIP) + // if this is a new connection and it's the first packet we see on that connection + if (tcpReassemblyData->numOfSides == 0) { + PCPP_LOG_DEBUG("Setting side for new connection"); + + // open the first side of the connection, side index is 0 sideIndex = 0; - } - else - { - // this means packet belong to the second side which doesn't yet exist. Open a second side with side index 1 - PCPP_LOG_DEBUG("Setting second side of a connection"); - sideIndex = 1; tcpReassemblyData->twoSides[sideIndex].srcIP = srcIP; tcpReassemblyData->twoSides[sideIndex].srcPort = srcPort; tcpReassemblyData->numOfSides++; first = true; } - } - // if there are already 2 sides open for this connection - else if (tcpReassemblyData->numOfSides == 2) - { - // check if packet matches side 0 - if (tcpReassemblyData->twoSides[0].srcPort == srcPort && tcpReassemblyData->twoSides[0].srcIP == srcIP) + // if there is already one side in this connection (which will be at side index 0) + else if (tcpReassemblyData->numOfSides == 1) { - sideIndex = 0; + // check if packet belongs to that side + if (tcpReassemblyData->twoSides[0].srcPort == srcPort && tcpReassemblyData->twoSides[0].srcIP == srcIP) + { + sideIndex = 0; + } + else + { + // this means packet belong to the second side which doesn't yet exist. Open a second side with side + // index 1 + PCPP_LOG_DEBUG("Setting second side of a connection"); + sideIndex = 1; + tcpReassemblyData->twoSides[sideIndex].srcIP = srcIP; + tcpReassemblyData->twoSides[sideIndex].srcPort = srcPort; + tcpReassemblyData->numOfSides++; + first = true; + } } - // check if packet matches side 1 - else if (tcpReassemblyData->twoSides[1].srcPort == srcPort && tcpReassemblyData->twoSides[1].srcIP == srcIP) + // if there are already 2 sides open for this connection + else if (tcpReassemblyData->numOfSides == 2) { - sideIndex = 1; + // check if packet matches side 0 + if (tcpReassemblyData->twoSides[0].srcPort == srcPort && tcpReassemblyData->twoSides[0].srcIP == srcIP) + { + sideIndex = 0; + } + // check if packet matches side 1 + else if (tcpReassemblyData->twoSides[1].srcPort == srcPort && tcpReassemblyData->twoSides[1].srcIP == srcIP) + { + sideIndex = 1; + } + // packet doesn't match either side. This case doesn't make sense but it's handled anyway. Packet will be + // ignored + else + { + PCPP_LOG_ERROR("Error occurred - packet doesn't match either side of the connection!!"); + return Error_PacketDoesNotMatchFlow; + } } - // packet doesn't match either side. This case doesn't make sense but it's handled anyway. Packet will be ignored + // there are more than 2 side - this case doesn't make sense and shouldn't happen, but handled anyway. Packet + // will be ignored else { - PCPP_LOG_ERROR("Error occurred - packet doesn't match either side of the connection!!"); + PCPP_LOG_ERROR("Error occurred - connection has more than 2 sides!!"); return Error_PacketDoesNotMatchFlow; } - } - // there are more than 2 side - this case doesn't make sense and shouldn't happen, but handled anyway. Packet will be ignored - else - { - PCPP_LOG_ERROR("Error occurred - connection has more than 2 sides!!"); - return Error_PacketDoesNotMatchFlow; - } - // if this side already got FIN or RST packet before, ignore this packet as this side is considered closed - if (tcpReassemblyData->twoSides[sideIndex].gotFinOrRst) - { - PCPP_LOG_DEBUG("Got a packet after FIN or RST were already seen on this side (" << static_cast(sideIndex) << "). Ignoring this packet"); - return Ignore_PacketOfClosedFlow; - } - - // handle FIN/RST packets that don't contain additional TCP data - if (isFinOrRst && tcpPayloadSize == 0) - { - PCPP_LOG_DEBUG("Got FIN or RST packet without data on side " << sideIndex); - - handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); - return FIN_RSTWithNoData; - } - - // check if this packet contains data from a different side than the side seen before. - // If this is the case then treat the out-of-order packet list as missing data and send them to the user (callback) together with an indication that some data was missing. - // Why? because a new packet from the other side means the previous message was probably already received and a new message is starting. - // In this case out-of-order packets are probably actually missing data - // For example: let's assume these are HTTP messages. If we're seeing the first packet of a response this means the server has already received the full request and is now starting - // to send the response. So if we still have out-of-order packets from the request it probably means that some packets were lost during the capture. So we don't expect the client to - // continue sending packets of the previous request, so we'll treat the out-of-order packets as missing data - // - // I'm aware that there are edge cases where the situation I described above is not true, but at some point we must clean the out-of-order packet list to avoid memory leak. - // I decided to do what Wireshark does and clean this list when starting to see a message from the other side - - // Since there are instances where this buffer clear condition can lead to declaration of excessive missing packets. Hence user should have a config file parameter - // to disable this and purely rely on max buffer size condition. As none of them are perfect solutions this will give user a little more control over it. - - if (m_EnableBaseBufferClearCondition && !first && tcpPayloadSize > 0 && tcpReassemblyData->prevSide != -1 && tcpReassemblyData->prevSide != sideIndex && - tcpReassemblyData->twoSides[tcpReassemblyData->prevSide].tcpFragmentList.size() > 0) - { - PCPP_LOG_DEBUG("Seeing a first data packet from a different side. Previous side was " << static_cast(tcpReassemblyData->prevSide) << ", current side is " << static_cast(sideIndex)); - checkOutOfOrderFragments(tcpReassemblyData, tcpReassemblyData->prevSide, true); - } - tcpReassemblyData->prevSide = sideIndex; - - // extract sequence value from packet - uint32_t sequence = be32toh(tcpLayer->getTcpHeader()->sequenceNumber); - - // if it's the first packet we see on this side of the connection - if (first) - { - PCPP_LOG_DEBUG("First data from this side of the connection"); - - // set initial sequence - tcpReassemblyData->twoSides[sideIndex].sequence = sequence + tcpPayloadSize; - if (tcpLayer->getTcpHeader()->synFlag != 0) - tcpReassemblyData->twoSides[sideIndex].sequence++; - - // send data to the callback - if (tcpPayloadSize != 0 && m_OnMessageReadyCallback != nullptr) + // if this side already got FIN or RST packet before, ignore this packet as this side is considered closed + if (tcpReassemblyData->twoSides[sideIndex].gotFinOrRst) { - TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, 0, tcpReassemblyData->connData, timestampOfTheReceivedPacket); - m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + PCPP_LOG_DEBUG("Got a packet after FIN or RST were already seen on this side (" + << static_cast(sideIndex) << "). Ignoring this packet"); + return Ignore_PacketOfClosedFlow; } - status = TcpMessageHandled; - // handle case where this packet is FIN or RST (although it's unlikely) - if (isFinOrRst) - handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + // handle FIN/RST packets that don't contain additional TCP data + if (isFinOrRst && tcpPayloadSize == 0) + { + PCPP_LOG_DEBUG("Got FIN or RST packet without data on side " << sideIndex); - // return - nothing else to do here - return status; - } + handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + return FIN_RSTWithNoData; + } - // if packet sequence is smaller than expected - this means that part or all of the TCP data is being re-transmitted - if (SEQ_LT(sequence, tcpReassemblyData->twoSides[sideIndex].sequence)) - { - PCPP_LOG_DEBUG("Found new data with the sequence lower than expected"); + // check if this packet contains data from a different side than the side seen before. + // If this is the case then treat the out-of-order packet list as missing data and send them to the user + // (callback) together with an indication that some data was missing. Why? because a new packet from the other + // side means the previous message was probably already received and a new message is starting. In this case + // out-of-order packets are probably actually missing data For example: let's assume these are HTTP messages. If + // we're seeing the first packet of a response this means the server has already received the full request and + // is now starting to send the response. So if we still have out-of-order packets from the request it probably + // means that some packets were lost during the capture. So we don't expect the client to continue sending + // packets of the previous request, so we'll treat the out-of-order packets as missing data + // + // I'm aware that there are edge cases where the situation I described above is not true, but at some point we + // must clean the out-of-order packet list to avoid memory leak. I decided to do what Wireshark does and clean + // this list when starting to see a message from the other side + + // Since there are instances where this buffer clear condition can lead to declaration of excessive missing + // packets. Hence user should have a config file parameter to disable this and purely rely on max buffer size + // condition. As none of them are perfect solutions this will give user a little more control over it. + + if (m_EnableBaseBufferClearCondition && !first && tcpPayloadSize > 0 && tcpReassemblyData->prevSide != -1 && + tcpReassemblyData->prevSide != sideIndex && + tcpReassemblyData->twoSides[tcpReassemblyData->prevSide].tcpFragmentList.size() > 0) + { + PCPP_LOG_DEBUG("Seeing a first data packet from a different side. Previous side was " + << static_cast(tcpReassemblyData->prevSide) << ", current side is " + << static_cast(sideIndex)); + checkOutOfOrderFragments(tcpReassemblyData, tcpReassemblyData->prevSide, true); + } + tcpReassemblyData->prevSide = sideIndex; - // calculate the sequence after this packet to see if this TCP payload contains also new data - uint32_t newSequence = sequence + tcpPayloadSize; + // extract sequence value from packet + uint32_t sequence = be32toh(tcpLayer->getTcpHeader()->sequenceNumber); - // this means that some of payload is new - if (SEQ_GT(newSequence, tcpReassemblyData->twoSides[sideIndex].sequence)) + // if it's the first packet we see on this side of the connection + if (first) { - // calculate the size of the new data - uint32_t newLength = tcpReassemblyData->twoSides[sideIndex].sequence - sequence; + PCPP_LOG_DEBUG("First data from this side of the connection"); - PCPP_LOG_DEBUG("Although sequence is lower than expected payload is long enough to contain new data. Calling the callback with the new data"); + // set initial sequence + tcpReassemblyData->twoSides[sideIndex].sequence = sequence + tcpPayloadSize; + if (tcpLayer->getTcpHeader()->synFlag != 0) + tcpReassemblyData->twoSides[sideIndex].sequence++; - // update the sequence for this side to include the new data that was seen - tcpReassemblyData->twoSides[sideIndex].sequence += tcpPayloadSize - newLength; - - // send only the new data to the callback - if (m_OnMessageReadyCallback != nullptr) + // send data to the callback + if (tcpPayloadSize != 0 && m_OnMessageReadyCallback != nullptr) { - TcpStreamData streamData(tcpLayer->getLayerPayload() + newLength, tcpPayloadSize - newLength, 0, tcpReassemblyData->connData, timestampOfTheReceivedPacket); + TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, 0, tcpReassemblyData->connData, + timestampOfTheReceivedPacket); m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); } status = TcpMessageHandled; - } - else - { - status = Ignore_Retransimission; - } - // handle case where this packet is FIN or RST - if (isFinOrRst) - handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + // handle case where this packet is FIN or RST (although it's unlikely) + if (isFinOrRst) + handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); - // return - nothing else to do here - return status; - } + // return - nothing else to do here + return status; + } - // if packet sequence is exactly as expected - this is the "good" case and the most common one - else if (sequence == tcpReassemblyData->twoSides[sideIndex].sequence) - { - // if TCP data size is 0 - nothing to do - if (tcpPayloadSize == 0) + // if packet sequence is smaller than expected - this means that part or all of the TCP data is being + // re-transmitted + if (SEQ_LT(sequence, tcpReassemblyData->twoSides[sideIndex].sequence)) { - PCPP_LOG_DEBUG("Payload length is 0, doing nothing"); + PCPP_LOG_DEBUG("Found new data with the sequence lower than expected"); - // handle case where this packet is FIN or RST - if (isFinOrRst) + // calculate the sequence after this packet to see if this TCP payload contains also new data + uint32_t newSequence = sequence + tcpPayloadSize; + + // this means that some of payload is new + if (SEQ_GT(newSequence, tcpReassemblyData->twoSides[sideIndex].sequence)) { - handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); - status = FIN_RSTWithNoData; + // calculate the size of the new data + uint32_t newLength = tcpReassemblyData->twoSides[sideIndex].sequence - sequence; + + PCPP_LOG_DEBUG( + "Although sequence is lower than expected payload is long enough to contain new data. Calling the callback with the new data"); + + // update the sequence for this side to include the new data that was seen + tcpReassemblyData->twoSides[sideIndex].sequence += tcpPayloadSize - newLength; + + // send only the new data to the callback + if (m_OnMessageReadyCallback != nullptr) + { + TcpStreamData streamData(tcpLayer->getLayerPayload() + newLength, tcpPayloadSize - newLength, 0, + tcpReassemblyData->connData, timestampOfTheReceivedPacket); + m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + } + status = TcpMessageHandled; } else { - status = Ignore_PacketWithNoData; + status = Ignore_Retransimission; } + // handle case where this packet is FIN or RST + if (isFinOrRst) + handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + + // return - nothing else to do here return status; } - PCPP_LOG_DEBUG("Found new data with expected sequence. Calling the callback"); + // if packet sequence is exactly as expected - this is the "good" case and the most common one + else if (sequence == tcpReassemblyData->twoSides[sideIndex].sequence) + { + // if TCP data size is 0 - nothing to do + if (tcpPayloadSize == 0) + { + PCPP_LOG_DEBUG("Payload length is 0, doing nothing"); - // update the sequence for this side to include TCP data from this packet - tcpReassemblyData->twoSides[sideIndex].sequence += tcpPayloadSize; + // handle case where this packet is FIN or RST + if (isFinOrRst) + { + handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + status = FIN_RSTWithNoData; + } + else + { + status = Ignore_PacketWithNoData; + } - // if this is a SYN packet - add +1 to the sequence - if (tcpLayer->getTcpHeader()->synFlag != 0) - tcpReassemblyData->twoSides[sideIndex].sequence++; + return status; + } - // send the data to the callback - if (m_OnMessageReadyCallback != nullptr) - { - TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, 0, tcpReassemblyData->connData,timestampOfTheReceivedPacket); - m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); - } - status = TcpMessageHandled; + PCPP_LOG_DEBUG("Found new data with expected sequence. Calling the callback"); - // now that we've seen new data, go over the list of out-of-order packets and see if one or more of them fits now - checkOutOfOrderFragments(tcpReassemblyData, sideIndex, false); + // update the sequence for this side to include TCP data from this packet + tcpReassemblyData->twoSides[sideIndex].sequence += tcpPayloadSize; - // handle case where this packet is FIN or RST - if (isFinOrRst) - handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + // if this is a SYN packet - add +1 to the sequence + if (tcpLayer->getTcpHeader()->synFlag != 0) + tcpReassemblyData->twoSides[sideIndex].sequence++; - // return - nothing else to do here - return status; - } + // send the data to the callback + if (m_OnMessageReadyCallback != nullptr) + { + TcpStreamData streamData(tcpLayer->getLayerPayload(), tcpPayloadSize, 0, tcpReassemblyData->connData, + timestampOfTheReceivedPacket); + m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + } + status = TcpMessageHandled; - // this case means sequence size of the packet is higher than expected which means the packet is out-of-order or some packets were lost (missing data). - // we don't know which of the 2 cases it is at this point so we just add this data to the out-of-order packet list - else - { - // if TCP data size is 0 - nothing to do - if (tcpPayloadSize == 0) - { - PCPP_LOG_DEBUG("Payload length is 0, doing nothing"); + // now that we've seen new data, go over the list of out-of-order packets and see if one or more of them + // fits now + checkOutOfOrderFragments(tcpReassemblyData, sideIndex, false); // handle case where this packet is FIN or RST if (isFinOrRst) - { handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); - status = FIN_RSTWithNoData; - } - else - { - status = Ignore_PacketWithNoData; - } + // return - nothing else to do here return status; } - // create a new TcpFragment, copy the TCP data to it and add this packet to the the out-of-order packet list - TcpFragment* newTcpFrag = new TcpFragment(); - newTcpFrag->data = new uint8_t[tcpPayloadSize]; - newTcpFrag->dataLength = tcpPayloadSize; - newTcpFrag->sequence = sequence; - newTcpFrag->timestamp = timestampOfTheReceivedPacket; - memcpy(newTcpFrag->data, tcpLayer->getLayerPayload(), tcpPayloadSize); - tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.pushBack(newTcpFrag); - - PCPP_LOG_DEBUG("Found out-of-order packet and added a new TCP fragment with size " << tcpPayloadSize << " to the out-of-order list of side " << static_cast(sideIndex)); - status = OutOfOrderTcpMessageBuffered; - - // check if we've stored too many out-of-order fragments; if so, consider missing packets lost and - // continue processing until the number of stored fragments is lower than the acceptable limit again - if (m_MaxOutOfOrderFragments > 0 && tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.size() > m_MaxOutOfOrderFragments) - { - checkOutOfOrderFragments(tcpReassemblyData, sideIndex, false); - } - - // handle case where this packet is FIN or RST - if (isFinOrRst) + // this case means sequence size of the packet is higher than expected which means the packet is out-of-order or + // some packets were lost (missing data). we don't know which of the 2 cases it is at this point so we just add + // this data to the out-of-order packet list + else { - handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); - } - - return status; - } -} + // if TCP data size is 0 - nothing to do + if (tcpPayloadSize == 0) + { + PCPP_LOG_DEBUG("Payload length is 0, doing nothing"); -TcpReassembly::ReassemblyStatus TcpReassembly::reassemblePacket(RawPacket* tcpRawData) -{ - Packet parsedPacket(tcpRawData, false); - return reassemblePacket(parsedPacket); -} + // handle case where this packet is FIN or RST + if (isFinOrRst) + { + handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + status = FIN_RSTWithNoData; + } + else + { + status = Ignore_PacketWithNoData; + } -static std::string prepareMissingDataMessage(uint32_t missingDataLen) -{ - std::stringstream missingDataTextStream; - missingDataTextStream << '[' << missingDataLen << " bytes missing]"; - return missingDataTextStream.str(); -} + return status; + } -void TcpReassembly::handleFinOrRst(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, uint32_t flowKey, bool isRst) -{ - // if this side already saw a FIN or RST packet, do nothing and return - if (tcpReassemblyData->twoSides[sideIndex].gotFinOrRst) - return; + // create a new TcpFragment, copy the TCP data to it and add this packet to the the out-of-order packet list + TcpFragment* newTcpFrag = new TcpFragment(); + newTcpFrag->data = new uint8_t[tcpPayloadSize]; + newTcpFrag->dataLength = tcpPayloadSize; + newTcpFrag->sequence = sequence; + newTcpFrag->timestamp = timestampOfTheReceivedPacket; + memcpy(newTcpFrag->data, tcpLayer->getLayerPayload(), tcpPayloadSize); + tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.pushBack(newTcpFrag); + + PCPP_LOG_DEBUG("Found out-of-order packet and added a new TCP fragment with size " + << tcpPayloadSize << " to the out-of-order list of side " << static_cast(sideIndex)); + status = OutOfOrderTcpMessageBuffered; + + // check if we've stored too many out-of-order fragments; if so, consider missing packets lost and + // continue processing until the number of stored fragments is lower than the acceptable limit again + if (m_MaxOutOfOrderFragments > 0 && + tcpReassemblyData->twoSides[sideIndex].tcpFragmentList.size() > m_MaxOutOfOrderFragments) + { + checkOutOfOrderFragments(tcpReassemblyData, sideIndex, false); + } - PCPP_LOG_DEBUG("Handling FIN or RST packet on side " << static_cast(sideIndex)); + // handle case where this packet is FIN or RST + if (isFinOrRst) + { + handleFinOrRst(tcpReassemblyData, sideIndex, flowKey, isRst); + } - // set FIN/RST flag for this side - tcpReassemblyData->twoSides[sideIndex].gotFinOrRst = true; + return status; + } + } - // check if the other side also sees FIN or RST packet. If so - just close the flow. Otherwise - clear the out-of-order packets for this side - int otherSideIndex = 1 - sideIndex; - if (tcpReassemblyData->twoSides[otherSideIndex].gotFinOrRst) + TcpReassembly::ReassemblyStatus TcpReassembly::reassemblePacket(RawPacket* tcpRawData) { - closeConnectionInternal(flowKey, TcpReassembly::TcpReassemblyConnectionClosedByFIN_RST); - return; + Packet parsedPacket(tcpRawData, false); + return reassemblePacket(parsedPacket); } - else - checkOutOfOrderFragments(tcpReassemblyData, sideIndex, true); - // and if it's a rst, close the flow unilaterally - if(isRst) - closeConnectionInternal(flowKey, TcpReassembly::TcpReassemblyConnectionClosedByFIN_RST); -} - -void TcpReassembly::checkOutOfOrderFragments(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, bool cleanWholeFragList) -{ - if (m_ProcessingOutOfOrder) + static std::string prepareMissingDataMessage(uint32_t missingDataLen) { - return; + std::stringstream missingDataTextStream; + missingDataTextStream << '[' << missingDataLen << " bytes missing]"; + return missingDataTextStream.str(); } - OutOfOrderProcessingGuard guard(m_ProcessingOutOfOrder); + void TcpReassembly::handleFinOrRst(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, uint32_t flowKey, + bool isRst) + { + // if this side already saw a FIN or RST packet, do nothing and return + if (tcpReassemblyData->twoSides[sideIndex].gotFinOrRst) + return; + + PCPP_LOG_DEBUG("Handling FIN or RST packet on side " << static_cast(sideIndex)); - bool foundSomething = false; + // set FIN/RST flag for this side + tcpReassemblyData->twoSides[sideIndex].gotFinOrRst = true; - auto& curSideData = tcpReassemblyData->twoSides[sideIndex]; + // check if the other side also sees FIN or RST packet. If so - just close the flow. Otherwise - clear the + // out-of-order packets for this side + int otherSideIndex = 1 - sideIndex; + if (tcpReassemblyData->twoSides[otherSideIndex].gotFinOrRst) + { + closeConnectionInternal(flowKey, TcpReassembly::TcpReassemblyConnectionClosedByFIN_RST); + return; + } + else + checkOutOfOrderFragments(tcpReassemblyData, sideIndex, true); - do + // and if it's a rst, close the flow unilaterally + if (isRst) + closeConnectionInternal(flowKey, TcpReassembly::TcpReassemblyConnectionClosedByFIN_RST); + } + + void TcpReassembly::checkOutOfOrderFragments(TcpReassemblyData* tcpReassemblyData, int8_t sideIndex, + bool cleanWholeFragList) { - PCPP_LOG_DEBUG("Starting first iteration of checkOutOfOrderFragments - looking for fragments that match the current sequence or have smaller sequence"); + if (m_ProcessingOutOfOrder) + { + return; + } + + OutOfOrderProcessingGuard guard(m_ProcessingOutOfOrder); - foundSomething = false; + bool foundSomething = false; + + auto& curSideData = tcpReassemblyData->twoSides[sideIndex]; do { - auto tcpFragIter = curSideData.tcpFragmentList.begin(); + PCPP_LOG_DEBUG( + "Starting first iteration of checkOutOfOrderFragments - looking for fragments that match the current sequence or have smaller sequence"); + foundSomething = false; - // first fragment list iteration - go over the whole fragment list and see if can find fragments that match the current sequence - // or have smaller sequence but have big enough payload to get new data - while (tcpFragIter != curSideData.tcpFragmentList.end()) + do { - // if fragment sequence matches the current sequence - if ((*tcpFragIter)->sequence == curSideData.sequence) + auto tcpFragIter = curSideData.tcpFragmentList.begin(); + foundSomething = false; + + // first fragment list iteration - go over the whole fragment list and see if can find fragments that + // match the current sequence or have smaller sequence but have big enough payload to get new data + while (tcpFragIter != curSideData.tcpFragmentList.end()) { - // pop the fragment from fragment list - auto curTcpFrag = curSideData.tcpFragmentList.getAndDetach(tcpFragIter); - // update sequence - curSideData.sequence += curTcpFrag->dataLength; - if (curTcpFrag->data != nullptr) + // if fragment sequence matches the current sequence + if ((*tcpFragIter)->sequence == curSideData.sequence) { - PCPP_LOG_DEBUG("Found an out-of-order packet matching to the current sequence with size " << curTcpFrag->dataLength << " on side " << static_cast(sideIndex) << ". Pulling it out of the list and sending the data to the callback"); - - // send new data to callback - - if (m_OnMessageReadyCallback != nullptr) + // pop the fragment from fragment list + auto curTcpFrag = curSideData.tcpFragmentList.getAndDetach(tcpFragIter); + // update sequence + curSideData.sequence += curTcpFrag->dataLength; + if (curTcpFrag->data != nullptr) { - TcpStreamData streamData(curTcpFrag->data, curTcpFrag->dataLength, 0, tcpReassemblyData->connData, curTcpFrag->timestamp); - m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + PCPP_LOG_DEBUG("Found an out-of-order packet matching to the current sequence with size " + << curTcpFrag->dataLength << " on side " << static_cast(sideIndex) + << ". Pulling it out of the list and sending the data to the callback"); + + // send new data to callback + + if (m_OnMessageReadyCallback != nullptr) + { + TcpStreamData streamData(curTcpFrag->data, curTcpFrag->dataLength, 0, + tcpReassemblyData->connData, curTcpFrag->timestamp); + m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + } } - } - - foundSomething = true; - continue; - } + foundSomething = true; - // if fragment sequence has lower sequence than the current sequence - if (SEQ_LT((*tcpFragIter)->sequence, curSideData.sequence)) - { - // pop the fragment from fragment list - auto curTcpFrag = curSideData.tcpFragmentList.getAndDetach(tcpFragIter); - // check if it still has new data - uint32_t newSequence = curTcpFrag->sequence + curTcpFrag->dataLength; + continue; + } - // it has new data - if (SEQ_GT(newSequence, curSideData.sequence)) + // if fragment sequence has lower sequence than the current sequence + if (SEQ_LT((*tcpFragIter)->sequence, curSideData.sequence)) { - // calculate the delta new data size - uint32_t newLength = curSideData.sequence - curTcpFrag->sequence; + // pop the fragment from fragment list + auto curTcpFrag = curSideData.tcpFragmentList.getAndDetach(tcpFragIter); + // check if it still has new data + uint32_t newSequence = curTcpFrag->sequence + curTcpFrag->dataLength; - PCPP_LOG_DEBUG("Found a fragment in the out-of-order list which its sequence is lower than expected but its payload is long enough to contain new data. " - "Calling the callback with the new data. Fragment size is " << curTcpFrag->dataLength << " on side " << static_cast(sideIndex) << ", new data size is " << static_cast(curTcpFrag->dataLength - newLength)); - - // update current sequence with the delta new data size - curSideData.sequence += curTcpFrag->dataLength - newLength; - - // send only the new data to the callback - if (m_OnMessageReadyCallback != nullptr) + // it has new data + if (SEQ_GT(newSequence, curSideData.sequence)) + { + // calculate the delta new data size + uint32_t newLength = curSideData.sequence - curTcpFrag->sequence; + + PCPP_LOG_DEBUG( + "Found a fragment in the out-of-order list which its sequence is lower than expected but its payload is long enough to contain new data. " + "Calling the callback with the new data. Fragment size is " + << curTcpFrag->dataLength << " on side " << static_cast(sideIndex) + << ", new data size is " << static_cast(curTcpFrag->dataLength - newLength)); + + // update current sequence with the delta new data size + curSideData.sequence += curTcpFrag->dataLength - newLength; + + // send only the new data to the callback + if (m_OnMessageReadyCallback != nullptr) + { + TcpStreamData streamData(curTcpFrag->data + newLength, + curTcpFrag->dataLength - newLength, 0, + tcpReassemblyData->connData, curTcpFrag->timestamp); + m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + } + + foundSomething = true; + } + else { - TcpStreamData streamData(curTcpFrag->data + newLength, curTcpFrag->dataLength - newLength, 0, tcpReassemblyData->connData, curTcpFrag->timestamp); - m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + PCPP_LOG_DEBUG( + "Found a fragment in the out-of-order list which doesn't contain any new data, ignoring it. Fragment size is " + << curTcpFrag->dataLength << " on side " << static_cast(sideIndex)); } - foundSomething = true; - } - else - { - PCPP_LOG_DEBUG("Found a fragment in the out-of-order list which doesn't contain any new data, ignoring it. Fragment size is " << curTcpFrag->dataLength << " on side " << static_cast(sideIndex)); + continue; } - continue; + // if got to here it means the fragment has higher sequence than current sequence, increment it and + // continue + tcpFragIter++; } - //if got to here it means the fragment has higher sequence than current sequence, increment it and continue - tcpFragIter++; - } - - // if managed to find new segment, do the search all over again - } while (foundSomething); - + // if managed to find new segment, do the search all over again + } while (foundSomething); - // if got here it means we're left only with fragments that have higher sequence than current sequence. This means out-of-order packets or - // missing data. If we don't want to clear the frag list yet and the number of out of order fragments isn't above the configured limit, - // assume it's out-of-order and return - if (!cleanWholeFragList && (m_MaxOutOfOrderFragments == 0 || curSideData.tcpFragmentList.size() <= m_MaxOutOfOrderFragments)) - { - return; - } + // if got here it means we're left only with fragments that have higher sequence than current sequence. This + // means out-of-order packets or missing data. If we don't want to clear the frag list yet and the number of + // out of order fragments isn't above the configured limit, assume it's out-of-order and return + if (!cleanWholeFragList && + (m_MaxOutOfOrderFragments == 0 || curSideData.tcpFragmentList.size() <= m_MaxOutOfOrderFragments)) + { + return; + } - PCPP_LOG_DEBUG("Starting second iteration of checkOutOfOrderFragments - handle missing data"); + PCPP_LOG_DEBUG("Starting second iteration of checkOutOfOrderFragments - handle missing data"); - // second fragment list iteration - now we're left only with fragments that have higher sequence than current sequence. This means missing data. - // Search for the fragment with the closest sequence to the current one + // second fragment list iteration - now we're left only with fragments that have higher sequence than + // current sequence. This means missing data. Search for the fragment with the closest sequence to the + // current one - uint32_t closestSequence = 0xffffffff; - bool closestSequenceDefined = false; - auto closestSequenceFragIt = curSideData.tcpFragmentList.end(); + uint32_t closestSequence = 0xffffffff; + bool closestSequenceDefined = false; + auto closestSequenceFragIt = curSideData.tcpFragmentList.end(); - for (auto tcpFragIter = curSideData.tcpFragmentList.begin(); tcpFragIter != curSideData.tcpFragmentList.end(); tcpFragIter++) - { - // check if its sequence is closer than current closest sequence - if (!closestSequenceDefined || SEQ_LT((*tcpFragIter)->sequence, closestSequence)) + for (auto tcpFragIter = curSideData.tcpFragmentList.begin(); + tcpFragIter != curSideData.tcpFragmentList.end(); tcpFragIter++) { - closestSequence = (*tcpFragIter)->sequence; - closestSequenceFragIt = tcpFragIter; - closestSequenceDefined = true; + // check if its sequence is closer than current closest sequence + if (!closestSequenceDefined || SEQ_LT((*tcpFragIter)->sequence, closestSequence)) + { + closestSequence = (*tcpFragIter)->sequence; + closestSequenceFragIt = tcpFragIter; + closestSequenceDefined = true; + } } - } - // this means fragment list is not empty at this stage - if (closestSequenceFragIt != curSideData.tcpFragmentList.end()) - { - // get the fragment with the closest sequence - auto curTcpFrag = curSideData.tcpFragmentList.getAndDetach(closestSequenceFragIt); + // this means fragment list is not empty at this stage + if (closestSequenceFragIt != curSideData.tcpFragmentList.end()) + { + // get the fragment with the closest sequence + auto curTcpFrag = curSideData.tcpFragmentList.getAndDetach(closestSequenceFragIt); - // calculate number of missing bytes - uint32_t missingDataLen = curTcpFrag->sequence - curSideData.sequence; + // calculate number of missing bytes + uint32_t missingDataLen = curTcpFrag->sequence - curSideData.sequence; - // update sequence - curSideData.sequence = curTcpFrag->sequence + curTcpFrag->dataLength; - if (curTcpFrag->data != nullptr) - { - // send new data to callback - if (m_OnMessageReadyCallback != nullptr) + // update sequence + curSideData.sequence = curTcpFrag->sequence + curTcpFrag->dataLength; + if (curTcpFrag->data != nullptr) { - // prepare missing data text - std::string missingDataTextStr = prepareMissingDataMessage(missingDataLen); - - // add missing data text to the data that will be sent to the callback. This means that the data will look something like: - // "[xx bytes missing]" - std::vector dataWithMissingDataText; - dataWithMissingDataText.reserve(missingDataTextStr.length() + curTcpFrag->dataLength); - dataWithMissingDataText.insert(dataWithMissingDataText.end(), missingDataTextStr.begin(), missingDataTextStr.end()); - dataWithMissingDataText.insert(dataWithMissingDataText.end(), curTcpFrag->data, curTcpFrag->data + curTcpFrag->dataLength); - - //TcpStreamData streamData(curTcpFrag->data, curTcpFrag->dataLength, tcpReassemblyData->connData); - TcpStreamData streamData(&dataWithMissingDataText[0], dataWithMissingDataText.size(), missingDataLen, tcpReassemblyData->connData, curTcpFrag->timestamp); - m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); - - PCPP_LOG_DEBUG("Found missing data on side " << static_cast(sideIndex) << ": " << missingDataLen << " byte are missing. Sending the closest fragment which is in size " << curTcpFrag->dataLength << " + missing text message which size is " << missingDataTextStr.length()); + // send new data to callback + if (m_OnMessageReadyCallback != nullptr) + { + // prepare missing data text + std::string missingDataTextStr = prepareMissingDataMessage(missingDataLen); + + // add missing data text to the data that will be sent to the callback. This means that the data + // will look something like: + // "[xx bytes missing]" + std::vector dataWithMissingDataText; + dataWithMissingDataText.reserve(missingDataTextStr.length() + curTcpFrag->dataLength); + dataWithMissingDataText.insert(dataWithMissingDataText.end(), missingDataTextStr.begin(), + missingDataTextStr.end()); + dataWithMissingDataText.insert(dataWithMissingDataText.end(), curTcpFrag->data, + curTcpFrag->data + curTcpFrag->dataLength); + + // TcpStreamData streamData(curTcpFrag->data, curTcpFrag->dataLength, + // tcpReassemblyData->connData); + TcpStreamData streamData(&dataWithMissingDataText[0], dataWithMissingDataText.size(), + missingDataLen, tcpReassemblyData->connData, curTcpFrag->timestamp); + m_OnMessageReadyCallback(sideIndex, streamData, m_UserCookie); + + PCPP_LOG_DEBUG("Found missing data on side " + << static_cast(sideIndex) << ": " << missingDataLen + << " byte are missing. Sending the closest fragment which is in size " + << curTcpFrag->dataLength << " + missing text message which size is " + << missingDataTextStr.length()); + } } - } - PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments again from the start"); + PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments again from the start"); - // call the method again from the start to do the whole search again (both iterations). - // the stop condition is when the list is empty (so closestSequenceFragIndex == -1) - foundSomething = true; - } - - } while (foundSomething); -} + // call the method again from the start to do the whole search again (both iterations). + // the stop condition is when the list is empty (so closestSequenceFragIndex == -1) + foundSomething = true; + } -void TcpReassembly::closeConnection(uint32_t flowKey) -{ - closeConnectionInternal(flowKey, TcpReassembly::TcpReassemblyConnectionClosedManually); -} + } while (foundSomething); + } -void TcpReassembly::closeConnectionInternal(uint32_t flowKey, ConnectionEndReason reason) -{ - ConnectionList::iterator iter = m_ConnectionList.find(flowKey); - if (iter == m_ConnectionList.end()) + void TcpReassembly::closeConnection(uint32_t flowKey) { - PCPP_LOG_ERROR("Cannot close flow with key 0x" << std::uppercase << std::hex << flowKey << ": cannot find flow"); - return; + closeConnectionInternal(flowKey, TcpReassembly::TcpReassemblyConnectionClosedManually); } - TcpReassemblyData& tcpReassemblyData = iter->second; - - if (tcpReassemblyData.closed) // the connection is already closed - return; - - PCPP_LOG_DEBUG("Closing connection with flow key 0x" << std::hex << flowKey); - - PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments on side 0"); - checkOutOfOrderFragments(&tcpReassemblyData, 0, true); - - PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments on side 1"); - checkOutOfOrderFragments(&tcpReassemblyData, 1, true); - - if (m_OnConnEnd != nullptr) - m_OnConnEnd(tcpReassemblyData.connData, reason, m_UserCookie); - - tcpReassemblyData.closed = true; // mark the connection as closed - insertIntoCleanupList(flowKey); - - PCPP_LOG_DEBUG("Connection with flow key 0x" << std::hex << flowKey << " is closed"); -} - -void TcpReassembly::closeAllConnections() -{ - PCPP_LOG_DEBUG("Closing all flows"); - - ConnectionList::iterator iter = m_ConnectionList.begin(), iterEnd = m_ConnectionList.end(); - for (; iter != iterEnd; ++iter) + void TcpReassembly::closeConnectionInternal(uint32_t flowKey, ConnectionEndReason reason) { + ConnectionList::iterator iter = m_ConnectionList.find(flowKey); + if (iter == m_ConnectionList.end()) + { + PCPP_LOG_ERROR("Cannot close flow with key 0x" << std::uppercase << std::hex << flowKey + << ": cannot find flow"); + return; + } + TcpReassemblyData& tcpReassemblyData = iter->second; - if (tcpReassemblyData.closed) // the connection is already closed, skip it - continue; + if (tcpReassemblyData.closed) // the connection is already closed + return; - uint32_t flowKey = tcpReassemblyData.connData.flowKey; PCPP_LOG_DEBUG("Closing connection with flow key 0x" << std::hex << flowKey); PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments on side 0"); @@ -699,63 +719,95 @@ void TcpReassembly::closeAllConnections() checkOutOfOrderFragments(&tcpReassemblyData, 1, true); if (m_OnConnEnd != nullptr) - m_OnConnEnd(tcpReassemblyData.connData, TcpReassemblyConnectionClosedManually, m_UserCookie); + m_OnConnEnd(tcpReassemblyData.connData, reason, m_UserCookie); - tcpReassemblyData.closed = true; // mark the connection as closed + tcpReassemblyData.closed = true; // mark the connection as closed insertIntoCleanupList(flowKey); PCPP_LOG_DEBUG("Connection with flow key 0x" << std::hex << flowKey << " is closed"); } -} -int TcpReassembly::isConnectionOpen(const ConnectionData& connection) const -{ - ConnectionList::const_iterator iter = m_ConnectionList.find(connection.flowKey); - if (iter != m_ConnectionList.end()) - return iter->second.closed == false; + void TcpReassembly::closeAllConnections() + { + PCPP_LOG_DEBUG("Closing all flows"); - return -1; -} + ConnectionList::iterator iter = m_ConnectionList.begin(), iterEnd = m_ConnectionList.end(); + for (; iter != iterEnd; ++iter) + { + TcpReassemblyData& tcpReassemblyData = iter->second; -void TcpReassembly::insertIntoCleanupList(uint32_t flowKey) -{ - // m_CleanupList is a map with key of type time_t (expiration time). The mapped type is a list that stores the flow keys to be cleared in certain point of time. - // m_CleanupList.insert inserts an empty list if the container does not already contain an element with an equivalent key, - // otherwise this method returns an iterator to the element that prevents insertion. - std::pair pair = m_CleanupList.insert(std::make_pair(time(nullptr) + m_ClosedConnectionDelay, CleanupList::mapped_type())); + if (tcpReassemblyData.closed) // the connection is already closed, skip it + continue; - // getting the reference to list - CleanupList::mapped_type& keysList = pair.first->second; - keysList.push_front(flowKey); -} + uint32_t flowKey = tcpReassemblyData.connData.flowKey; + PCPP_LOG_DEBUG("Closing connection with flow key 0x" << std::hex << flowKey); -uint32_t TcpReassembly::purgeClosedConnections(uint32_t maxNumToClean) -{ - uint32_t count = 0; + PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments on side 0"); + checkOutOfOrderFragments(&tcpReassemblyData, 0, true); + + PCPP_LOG_DEBUG("Calling checkOutOfOrderFragments on side 1"); + checkOutOfOrderFragments(&tcpReassemblyData, 1, true); + + if (m_OnConnEnd != nullptr) + m_OnConnEnd(tcpReassemblyData.connData, TcpReassemblyConnectionClosedManually, m_UserCookie); + + tcpReassemblyData.closed = true; // mark the connection as closed + insertIntoCleanupList(flowKey); - if (maxNumToClean == 0) - maxNumToClean = m_MaxNumToClean; + PCPP_LOG_DEBUG("Connection with flow key 0x" << std::hex << flowKey << " is closed"); + } + } + + int TcpReassembly::isConnectionOpen(const ConnectionData& connection) const + { + ConnectionList::const_iterator iter = m_ConnectionList.find(connection.flowKey); + if (iter != m_ConnectionList.end()) + return iter->second.closed == false; + + return -1; + } + + void TcpReassembly::insertIntoCleanupList(uint32_t flowKey) + { + // m_CleanupList is a map with key of type time_t (expiration time). The mapped type is a list that stores the + // flow keys to be cleared in certain point of time. m_CleanupList.insert inserts an empty list if the container + // does not already contain an element with an equivalent key, otherwise this method returns an iterator to the + // element that prevents insertion. + std::pair pair = + m_CleanupList.insert(std::make_pair(time(nullptr) + m_ClosedConnectionDelay, CleanupList::mapped_type())); + + // getting the reference to list + CleanupList::mapped_type& keysList = pair.first->second; + keysList.push_front(flowKey); + } - CleanupList::iterator iterTime = m_CleanupList.begin(), iterTimeEnd = m_CleanupList.upper_bound(time(nullptr)); - while (iterTime != iterTimeEnd && count < maxNumToClean) + uint32_t TcpReassembly::purgeClosedConnections(uint32_t maxNumToClean) { - CleanupList::mapped_type& keysList = iterTime->second; + uint32_t count = 0; - for (; !keysList.empty() && count < maxNumToClean; ++count) + if (maxNumToClean == 0) + maxNumToClean = m_MaxNumToClean; + + CleanupList::iterator iterTime = m_CleanupList.begin(), iterTimeEnd = m_CleanupList.upper_bound(time(nullptr)); + while (iterTime != iterTimeEnd && count < maxNumToClean) { - CleanupList::mapped_type::const_reference key = keysList.front(); - m_ConnectionInfo.erase(key); - m_ConnectionList.erase(key); - keysList.pop_front(); + CleanupList::mapped_type& keysList = iterTime->second; + + for (; !keysList.empty() && count < maxNumToClean; ++count) + { + CleanupList::mapped_type::const_reference key = keysList.front(); + m_ConnectionInfo.erase(key); + m_ConnectionList.erase(key); + keysList.pop_front(); + } + + if (keysList.empty()) + m_CleanupList.erase(iterTime++); + else + ++iterTime; } - if (keysList.empty()) - m_CleanupList.erase(iterTime++); - else - ++iterTime; + return count; } - return count; -} - -} +} // namespace pcpp diff --git a/Packet++/src/TelnetLayer.cpp b/Packet++/src/TelnetLayer.cpp index f1fe581786..e59c1345f9 100644 --- a/Packet++/src/TelnetLayer.cpp +++ b/Packet++/src/TelnetLayer.cpp @@ -11,469 +11,473 @@ namespace pcpp { -bool TelnetLayer::isDataField(uint8_t *pos) const -{ - // "FF FF" means data - return pos[0] != static_cast(TelnetCommand::InterpretAsCommand) || pos[1] == static_cast(TelnetCommand::InterpretAsCommand); -} - -bool TelnetLayer::isCommandField(uint8_t *pos) const -{ - return !isDataField(pos); -} - -size_t TelnetLayer::distanceToNextIAC(uint8_t *startPos, size_t maxLength) -{ - uint8_t *pos = nullptr; - size_t addition = 0; - size_t currentOffset = 0; - do + bool TelnetLayer::isDataField(uint8_t* pos) const { - // If it is second turn position should be adjusted to after second FF - if (addition) - addition += 2; - - pos = (uint8_t *)memchr(startPos + currentOffset + 1, static_cast(TelnetCommand::InterpretAsCommand), maxLength - currentOffset); - if (pos) - addition += pos - (startPos + currentOffset); - else - addition += maxLength - currentOffset; - currentOffset = currentOffset + addition; - // "FF FF" means data continue - } while (pos && ((pos + 1) < (startPos + maxLength)) && (pos[1] == static_cast(TelnetCommand::InterpretAsCommand)) && (currentOffset < maxLength)); - - return addition; -} + // "FF FF" means data + return pos[0] != static_cast(TelnetCommand::InterpretAsCommand) || + pos[1] == static_cast(TelnetCommand::InterpretAsCommand); + } -size_t TelnetLayer::getFieldLen(uint8_t *startPos, size_t maxLength) -{ - // Check first byte is IAC - if (startPos && (startPos[0] == static_cast(TelnetCommand::InterpretAsCommand)) && (maxLength >= 2)) + bool TelnetLayer::isCommandField(uint8_t* pos) const { - // If subnegotiation parse until next IAC - if (startPos[1] == static_cast(TelnetCommand::Subnegotiation)) - return distanceToNextIAC(startPos, maxLength); - // Only WILL, WONT, DO, DONT have option. Ref http://pcmicro.com/netfoss/telnet.html - else if (startPos[1] >= static_cast(TelnetCommand::WillPerform) && startPos[1] <= static_cast(TelnetCommand::DontPerform)) - return 3; - return 2; + return !isDataField(pos); } - return distanceToNextIAC(startPos, maxLength); -} -uint8_t *TelnetLayer::getNextDataField(uint8_t *pos, size_t len) -{ - size_t offset = 0; - while (offset < len) + size_t TelnetLayer::distanceToNextIAC(uint8_t* startPos, size_t maxLength) { - // Move to next field - size_t length = getFieldLen(pos, len - offset); - pos += length; - offset += length; - - if (isDataField(pos)) - return pos; + uint8_t* pos = nullptr; + size_t addition = 0; + size_t currentOffset = 0; + do + { + // If it is second turn position should be adjusted to after second FF + if (addition) + addition += 2; + + pos = (uint8_t*)memchr(startPos + currentOffset + 1, static_cast(TelnetCommand::InterpretAsCommand), + maxLength - currentOffset); + if (pos) + addition += pos - (startPos + currentOffset); + else + addition += maxLength - currentOffset; + currentOffset = currentOffset + addition; + // "FF FF" means data continue + } while (pos && ((pos + 1) < (startPos + maxLength)) && + (pos[1] == static_cast(TelnetCommand::InterpretAsCommand)) && (currentOffset < maxLength)); + + return addition; } - return nullptr; -} + size_t TelnetLayer::getFieldLen(uint8_t* startPos, size_t maxLength) + { + // Check first byte is IAC + if (startPos && (startPos[0] == static_cast(TelnetCommand::InterpretAsCommand)) && (maxLength >= 2)) + { + // If subnegotiation parse until next IAC + if (startPos[1] == static_cast(TelnetCommand::Subnegotiation)) + return distanceToNextIAC(startPos, maxLength); + // Only WILL, WONT, DO, DONT have option. Ref http://pcmicro.com/netfoss/telnet.html + else if (startPos[1] >= static_cast(TelnetCommand::WillPerform) && + startPos[1] <= static_cast(TelnetCommand::DontPerform)) + return 3; + return 2; + } + return distanceToNextIAC(startPos, maxLength); + } -uint8_t *TelnetLayer::getNextCommandField(uint8_t *pos, size_t len) -{ - size_t offset = 0; - while (offset < len) + uint8_t* TelnetLayer::getNextDataField(uint8_t* pos, size_t len) { - // Move to next field - size_t length = getFieldLen(pos, len - offset); - pos += length; - offset += length; + size_t offset = 0; + while (offset < len) + { + // Move to next field + size_t length = getFieldLen(pos, len - offset); + pos += length; + offset += length; + + if (isDataField(pos)) + return pos; + } - if (isCommandField(pos)) - return pos; + return nullptr; } - return nullptr; -} + uint8_t* TelnetLayer::getNextCommandField(uint8_t* pos, size_t len) + { + size_t offset = 0; + while (offset < len) + { + // Move to next field + size_t length = getFieldLen(pos, len - offset); + pos += length; + offset += length; -int16_t TelnetLayer::getSubCommand(uint8_t *pos, size_t len) -{ - if (len < 3 || pos[1] < static_cast(TelnetCommand::Subnegotiation)) - return static_cast(TelnetOption::TelnetOptionNoOption); - return pos[2]; -} + if (isCommandField(pos)) + return pos; + } -uint8_t *TelnetLayer::getCommandData(uint8_t *pos, size_t &len) -{ - if (pos[1] == static_cast(TelnetCommand::Subnegotiation) && len > 3) - { - len -= 3; - return &pos[3]; + return nullptr; } - len = 0; - return nullptr; -} - -std::string TelnetLayer::getDataAsString(bool removeEscapeCharacters) -{ - uint8_t *dataPos = nullptr; - if (isDataField(m_Data)) - dataPos = m_Data; - else - dataPos = getNextDataField(m_Data, m_DataLen); - if (!dataPos) + int16_t TelnetLayer::getSubCommand(uint8_t* pos, size_t len) { - PCPP_LOG_DEBUG("Packet does not have a data field"); - return std::string(); + if (len < 3 || pos[1] < static_cast(TelnetCommand::Subnegotiation)) + return static_cast(TelnetOption::TelnetOptionNoOption); + return pos[2]; } - // Convert to string - if (removeEscapeCharacters) + uint8_t* TelnetLayer::getCommandData(uint8_t* pos, size_t& len) { - std::stringstream ss; - for (size_t idx = 0; idx < m_DataLen - (dataPos - m_Data) + 1; ++idx) + if (pos[1] == static_cast(TelnetCommand::Subnegotiation) && len > 3) { - if (int(dataPos[idx]) < 127 && int(dataPos[idx]) > 31) // From SPACE to ~ - ss << dataPos[idx]; + len -= 3; + return &pos[3]; } - return ss.str(); + len = 0; + return nullptr; } - return std::string((char *)m_Data, m_DataLen); -} - -size_t TelnetLayer::getTotalNumberOfCommands() -{ - size_t ctr = 0; - if (isCommandField(m_Data)) - ++ctr; - uint8_t *pos = m_Data; - while (pos != nullptr) + std::string TelnetLayer::getDataAsString(bool removeEscapeCharacters) { - size_t offset = pos - m_Data; - pos = getNextCommandField(pos, m_DataLen - offset); - if (pos) - ++ctr; + uint8_t* dataPos = nullptr; + if (isDataField(m_Data)) + dataPos = m_Data; + else + dataPos = getNextDataField(m_Data, m_DataLen); + + if (!dataPos) + { + PCPP_LOG_DEBUG("Packet does not have a data field"); + return std::string(); + } + + // Convert to string + if (removeEscapeCharacters) + { + std::stringstream ss; + for (size_t idx = 0; idx < m_DataLen - (dataPos - m_Data) + 1; ++idx) + { + if (int(dataPos[idx]) < 127 && int(dataPos[idx]) > 31) // From SPACE to ~ + ss << dataPos[idx]; + } + return ss.str(); + } + return std::string((char*)m_Data, m_DataLen); } - return ctr; -} + size_t TelnetLayer::getTotalNumberOfCommands() + { + size_t ctr = 0; + if (isCommandField(m_Data)) + ++ctr; -size_t TelnetLayer::getNumberOfCommands(TelnetCommand command) -{ - if (static_cast(command) < 0) - return 0; + uint8_t* pos = m_Data; + while (pos != nullptr) + { + size_t offset = pos - m_Data; + pos = getNextCommandField(pos, m_DataLen - offset); + if (pos) + ++ctr; + } - size_t ctr = 0; - if (isCommandField(m_Data) && m_Data[1] == static_cast(command)) - ++ctr; + return ctr; + } - uint8_t *pos = m_Data; - while (pos != nullptr) + size_t TelnetLayer::getNumberOfCommands(TelnetCommand command) { - size_t offset = pos - m_Data; - pos = getNextCommandField(pos, m_DataLen - offset); - if (pos && pos[1] == static_cast(command)) + if (static_cast(command) < 0) + return 0; + + size_t ctr = 0; + if (isCommandField(m_Data) && m_Data[1] == static_cast(command)) ++ctr; - } - return ctr; -} + uint8_t* pos = m_Data; + while (pos != nullptr) + { + size_t offset = pos - m_Data; + pos = getNextCommandField(pos, m_DataLen - offset); + if (pos && pos[1] == static_cast(command)) + ++ctr; + } + + return ctr; + } -TelnetLayer::TelnetCommand TelnetLayer::getFirstCommand() -{ - // If starts with command - if (isCommandField(m_Data)) - return static_cast(m_Data[1]); - - // Check is there any command - uint8_t *pos = getNextCommandField(m_Data, m_DataLen); - if (pos) - return static_cast(pos[1]); - return TelnetCommand::TelnetCommandEndOfPacket; -} - -TelnetLayer::TelnetCommand TelnetLayer::getNextCommand() -{ - if (lastPositionOffset == SIZE_MAX) + TelnetLayer::TelnetCommand TelnetLayer::getFirstCommand() { - lastPositionOffset = 0; + // If starts with command if (isCommandField(m_Data)) - return static_cast(m_Data[1]); + return static_cast(m_Data[1]); + + // Check is there any command + uint8_t* pos = getNextCommandField(m_Data, m_DataLen); + if (pos) + return static_cast(pos[1]); + return TelnetCommand::TelnetCommandEndOfPacket; } - uint8_t *pos = getNextCommandField(&m_Data[lastPositionOffset], m_DataLen - lastPositionOffset); - if (pos) + TelnetLayer::TelnetCommand TelnetLayer::getNextCommand() { - lastPositionOffset = pos - m_Data; - return static_cast(pos[1]); - } - lastPositionOffset = SIZE_MAX; - return TelnetCommand::TelnetCommandEndOfPacket; -} + if (lastPositionOffset == SIZE_MAX) + { + lastPositionOffset = 0; + if (isCommandField(m_Data)) + return static_cast(m_Data[1]); + } -TelnetLayer::TelnetOption TelnetLayer::getOption() -{ - if (lastPositionOffset < m_DataLen) - return static_cast(getSubCommand( - &m_Data[lastPositionOffset], getFieldLen(&m_Data[lastPositionOffset], m_DataLen - lastPositionOffset))); - return TelnetOption::TelnetOptionNoOption; -} + uint8_t* pos = getNextCommandField(&m_Data[lastPositionOffset], m_DataLen - lastPositionOffset); + if (pos) + { + lastPositionOffset = pos - m_Data; + return static_cast(pos[1]); + } + lastPositionOffset = SIZE_MAX; + return TelnetCommand::TelnetCommandEndOfPacket; + } -TelnetLayer::TelnetOption TelnetLayer::getOption(TelnetCommand command) -{ - // Check input - if (static_cast(command) < 0) + TelnetLayer::TelnetOption TelnetLayer::getOption() { - PCPP_LOG_ERROR("Command type can't be negative"); + if (lastPositionOffset < m_DataLen) + return static_cast(getSubCommand( + &m_Data[lastPositionOffset], getFieldLen(&m_Data[lastPositionOffset], m_DataLen - lastPositionOffset))); return TelnetOption::TelnetOptionNoOption; } - if (isCommandField(m_Data) && m_Data[1] == static_cast(command)) - return static_cast(getSubCommand(m_Data, getFieldLen(m_Data, m_DataLen))); - - uint8_t *pos = m_Data; - while (pos != nullptr) + TelnetLayer::TelnetOption TelnetLayer::getOption(TelnetCommand command) { - size_t offset = pos - m_Data; - pos = getNextCommandField(pos, m_DataLen - offset); - - if (pos && pos[1] == static_cast(command)) - return static_cast(getSubCommand(pos, getFieldLen(pos, m_DataLen - offset))); - } + // Check input + if (static_cast(command) < 0) + { + PCPP_LOG_ERROR("Command type can't be negative"); + return TelnetOption::TelnetOptionNoOption; + } - PCPP_LOG_DEBUG("Can't find requested command"); - return TelnetOption::TelnetOptionNoOption; -} + if (isCommandField(m_Data) && m_Data[1] == static_cast(command)) + return static_cast(getSubCommand(m_Data, getFieldLen(m_Data, m_DataLen))); -uint8_t *TelnetLayer::getOptionData(size_t &length) -{ - if (lastPositionOffset < m_DataLen) - { - size_t lenBuffer = getFieldLen(&m_Data[lastPositionOffset], m_DataLen - lastPositionOffset); - uint8_t *posBuffer = getCommandData(&m_Data[lastPositionOffset], lenBuffer); + uint8_t* pos = m_Data; + while (pos != nullptr) + { + size_t offset = pos - m_Data; + pos = getNextCommandField(pos, m_DataLen - offset); - length = lenBuffer; - return posBuffer; - } - return nullptr; -} + if (pos && pos[1] == static_cast(command)) + return static_cast(getSubCommand(pos, getFieldLen(pos, m_DataLen - offset))); + } -uint8_t *TelnetLayer::getOptionData(TelnetCommand command, size_t &length) -{ - // Check input - if (static_cast(command) < 0) - { - PCPP_LOG_ERROR("Command type can't be negative"); - length = 0; - return nullptr; + PCPP_LOG_DEBUG("Can't find requested command"); + return TelnetOption::TelnetOptionNoOption; } - if (isCommandField(m_Data) && m_Data[1] == static_cast(command)) + uint8_t* TelnetLayer::getOptionData(size_t& length) { - size_t lenBuffer = getFieldLen(m_Data, m_DataLen); - uint8_t *posBuffer = getCommandData(m_Data, lenBuffer); + if (lastPositionOffset < m_DataLen) + { + size_t lenBuffer = getFieldLen(&m_Data[lastPositionOffset], m_DataLen - lastPositionOffset); + uint8_t* posBuffer = getCommandData(&m_Data[lastPositionOffset], lenBuffer); - length = lenBuffer; - return posBuffer; + length = lenBuffer; + return posBuffer; + } + return nullptr; } - uint8_t *pos = m_Data; - while (pos != nullptr) + uint8_t* TelnetLayer::getOptionData(TelnetCommand command, size_t& length) { - size_t offset = pos - m_Data; - pos = getNextCommandField(pos, m_DataLen - offset); + // Check input + if (static_cast(command) < 0) + { + PCPP_LOG_ERROR("Command type can't be negative"); + length = 0; + return nullptr; + } - if (pos && pos[1] == static_cast(command)) + if (isCommandField(m_Data) && m_Data[1] == static_cast(command)) { size_t lenBuffer = getFieldLen(m_Data, m_DataLen); - uint8_t *posBuffer = getCommandData(m_Data, lenBuffer); + uint8_t* posBuffer = getCommandData(m_Data, lenBuffer); length = lenBuffer; return posBuffer; } - } - PCPP_LOG_DEBUG("Can't find requested command"); - length = 0; - return nullptr; -} + uint8_t* pos = m_Data; + while (pos != nullptr) + { + size_t offset = pos - m_Data; + pos = getNextCommandField(pos, m_DataLen - offset); -std::string TelnetLayer::getTelnetCommandAsString(TelnetCommand val) -{ - switch (val) + if (pos && pos[1] == static_cast(command)) + { + size_t lenBuffer = getFieldLen(m_Data, m_DataLen); + uint8_t* posBuffer = getCommandData(m_Data, lenBuffer); + + length = lenBuffer; + return posBuffer; + } + } + + PCPP_LOG_DEBUG("Can't find requested command"); + length = 0; + return nullptr; + } + + std::string TelnetLayer::getTelnetCommandAsString(TelnetCommand val) { - case TelnetCommand::TelnetCommandEndOfPacket: - return "Reached end of packet while parsing"; - case TelnetCommand::EndOfFile: - return "End of File"; - case TelnetCommand::Suspend: - return "Suspend current process"; - case TelnetCommand::Abort: - return "Abort Process"; - case TelnetCommand::EndOfRecordCommand: - return "End of Record"; - case TelnetCommand::SubnegotiationEnd: - return "Subnegotiation End"; - case TelnetCommand::NoOperation: - return "No Operation"; - case TelnetCommand::DataMark: - return "Data Mark"; - case TelnetCommand::Break: - return "Break"; - case TelnetCommand::InterruptProcess: - return "Interrupt Process"; - case TelnetCommand::AbortOutput: - return "Abort Output"; - case TelnetCommand::AreYouThere: - return "Are You There"; - case TelnetCommand::EraseCharacter: - return "Erase Character"; - case TelnetCommand::EraseLine: - return "Erase Line"; - case TelnetCommand::GoAhead: - return "Go Ahead"; - case TelnetCommand::Subnegotiation: - return "Subnegotiation"; - case TelnetCommand::WillPerform: - return "Will Perform"; - case TelnetCommand::WontPerform: - return "Wont Perform"; - case TelnetCommand::DoPerform: - return "Do Perform"; - case TelnetCommand::DontPerform: - return "Dont Perform"; - case TelnetCommand::InterpretAsCommand: - return "Interpret As Command"; - default: - return "Unknown Command"; + switch (val) + { + case TelnetCommand::TelnetCommandEndOfPacket: + return "Reached end of packet while parsing"; + case TelnetCommand::EndOfFile: + return "End of File"; + case TelnetCommand::Suspend: + return "Suspend current process"; + case TelnetCommand::Abort: + return "Abort Process"; + case TelnetCommand::EndOfRecordCommand: + return "End of Record"; + case TelnetCommand::SubnegotiationEnd: + return "Subnegotiation End"; + case TelnetCommand::NoOperation: + return "No Operation"; + case TelnetCommand::DataMark: + return "Data Mark"; + case TelnetCommand::Break: + return "Break"; + case TelnetCommand::InterruptProcess: + return "Interrupt Process"; + case TelnetCommand::AbortOutput: + return "Abort Output"; + case TelnetCommand::AreYouThere: + return "Are You There"; + case TelnetCommand::EraseCharacter: + return "Erase Character"; + case TelnetCommand::EraseLine: + return "Erase Line"; + case TelnetCommand::GoAhead: + return "Go Ahead"; + case TelnetCommand::Subnegotiation: + return "Subnegotiation"; + case TelnetCommand::WillPerform: + return "Will Perform"; + case TelnetCommand::WontPerform: + return "Wont Perform"; + case TelnetCommand::DoPerform: + return "Do Perform"; + case TelnetCommand::DontPerform: + return "Dont Perform"; + case TelnetCommand::InterpretAsCommand: + return "Interpret As Command"; + default: + return "Unknown Command"; + } } -} -std::string TelnetLayer::getTelnetOptionAsString(TelnetOption val) -{ - switch (val) + std::string TelnetLayer::getTelnetOptionAsString(TelnetOption val) { - case TelnetOption::TelnetOptionNoOption: - return "No option for this command"; - case TelnetOption::TransmitBinary: - return "Binary Transmission"; - case TelnetOption::Echo: - return "Echo"; - case TelnetOption::Reconnection: - return "Reconnection"; - case TelnetOption::SuppressGoAhead: - return "Suppress Go Ahead"; - case TelnetOption::ApproxMsgSizeNegotiation: - return "Negotiate approximate message size"; - case TelnetOption::Status: - return "Status"; - case TelnetOption::TimingMark: - return "Timing Mark"; - case TelnetOption::RemoteControlledTransAndEcho: - return "Remote Controlled Transmission and Echo"; - case TelnetOption::OutputLineWidth: - return "Output Line Width"; - case TelnetOption::OutputPageSize: - return "Output Page Size"; - case TelnetOption::OutputCarriageReturnDisposition: - return "Negotiate About Output Carriage-Return Disposition"; - case TelnetOption::OutputHorizontalTabStops: - return "Negotiate About Output Horizontal Tabstops"; - case TelnetOption::OutputHorizontalTabDisposition: - return "Negotiate About Output Horizontal Tab Disposition"; - case TelnetOption::OutputFormfeedDisposition: - return "Negotiate About Output Formfeed Disposition"; - case TelnetOption::OutputVerticalTabStops: - return "Negotiate About Vertical Tabstops"; - case TelnetOption::OutputVerticalTabDisposition: - return "Negotiate About Output Vertcial Tab Disposition"; - case TelnetOption::OutputLinefeedDisposition: - return "Negotiate About Output Linefeed Disposition"; - case TelnetOption::ExtendedASCII: - return "Extended ASCII"; - case TelnetOption::Logout: - return "Logout"; - case TelnetOption::ByteMacro: - return "Byte Macro"; - case TelnetOption::DataEntryTerminal: - return "Data Entry Terminal"; - case TelnetOption::SUPDUP: - return "SUPDUP"; - case TelnetOption::SUPDUPOutput: - return "SUPDUP Output"; - case TelnetOption::SendLocation: - return "Send Location"; - case TelnetOption::TerminalType: - return "Terminal Type"; - case TelnetOption::EndOfRecordOption: - return "End Of Record"; - case TelnetOption::TACACSUserIdentification: - return "TACACS User Identification"; - case TelnetOption::OutputMarking: - return "Output Marking"; - case TelnetOption::TerminalLocationNumber: - return "Terminal Location Number"; - case TelnetOption::Telnet3270Regime: - return "Telnet 3270 Regime"; - case TelnetOption::X3Pad: - return "X3 Pad"; - case TelnetOption::NegotiateAboutWindowSize: - return "Negotiate About Window Size"; - case TelnetOption::TerminalSpeed: - return "Terminal Speed"; - case TelnetOption::RemoteFlowControl: - return "Remote Flow Control"; - case TelnetOption::Linemode: - return "Line mode"; - case TelnetOption::XDisplayLocation: - return "X Display Location"; - case TelnetOption::EnvironmentOption: - return "Environment Option"; - case TelnetOption::AuthenticationOption: - return "Authentication Option"; - case TelnetOption::EncryptionOption: - return "Encryption Option"; - case TelnetOption::NewEnvironmentOption: - return "New Environment Option"; - case TelnetOption::TN3270E: - return "TN3270E"; - case TelnetOption::XAuth: - return "X Server Authentication"; - case TelnetOption::Charset: - return "Charset"; - case TelnetOption::TelnetRemoteSerialPort: - return "Telnet Remote Serial Port"; - case TelnetOption::ComPortControlOption: - return "Com Port Control Option"; - case TelnetOption::TelnetSuppressLocalEcho: - return "Telnet Suppress Local Echo"; - case TelnetOption::TelnetStartTLS: - return "Telnet Start TLS"; - case TelnetOption::Kermit: - return "Kermit"; - case TelnetOption::SendURL: - return "Send URL"; - case TelnetOption::ForwardX: - return "Forward X Server"; - case TelnetOption::TelOptPragmaLogon: - return "Telnet Option Pragma Logon"; - case TelnetOption::TelOptSSPILogon: - return "Telnet Option SSPI Logon"; - case TelnetOption::TelOptPragmaHeartbeat: - return "Telnet Option Pragma Heartbeat"; - case TelnetOption::ExtendedOptions: - return "Extended option list"; - default: - return "Unknown Option"; + switch (val) + { + case TelnetOption::TelnetOptionNoOption: + return "No option for this command"; + case TelnetOption::TransmitBinary: + return "Binary Transmission"; + case TelnetOption::Echo: + return "Echo"; + case TelnetOption::Reconnection: + return "Reconnection"; + case TelnetOption::SuppressGoAhead: + return "Suppress Go Ahead"; + case TelnetOption::ApproxMsgSizeNegotiation: + return "Negotiate approximate message size"; + case TelnetOption::Status: + return "Status"; + case TelnetOption::TimingMark: + return "Timing Mark"; + case TelnetOption::RemoteControlledTransAndEcho: + return "Remote Controlled Transmission and Echo"; + case TelnetOption::OutputLineWidth: + return "Output Line Width"; + case TelnetOption::OutputPageSize: + return "Output Page Size"; + case TelnetOption::OutputCarriageReturnDisposition: + return "Negotiate About Output Carriage-Return Disposition"; + case TelnetOption::OutputHorizontalTabStops: + return "Negotiate About Output Horizontal Tabstops"; + case TelnetOption::OutputHorizontalTabDisposition: + return "Negotiate About Output Horizontal Tab Disposition"; + case TelnetOption::OutputFormfeedDisposition: + return "Negotiate About Output Formfeed Disposition"; + case TelnetOption::OutputVerticalTabStops: + return "Negotiate About Vertical Tabstops"; + case TelnetOption::OutputVerticalTabDisposition: + return "Negotiate About Output Vertcial Tab Disposition"; + case TelnetOption::OutputLinefeedDisposition: + return "Negotiate About Output Linefeed Disposition"; + case TelnetOption::ExtendedASCII: + return "Extended ASCII"; + case TelnetOption::Logout: + return "Logout"; + case TelnetOption::ByteMacro: + return "Byte Macro"; + case TelnetOption::DataEntryTerminal: + return "Data Entry Terminal"; + case TelnetOption::SUPDUP: + return "SUPDUP"; + case TelnetOption::SUPDUPOutput: + return "SUPDUP Output"; + case TelnetOption::SendLocation: + return "Send Location"; + case TelnetOption::TerminalType: + return "Terminal Type"; + case TelnetOption::EndOfRecordOption: + return "End Of Record"; + case TelnetOption::TACACSUserIdentification: + return "TACACS User Identification"; + case TelnetOption::OutputMarking: + return "Output Marking"; + case TelnetOption::TerminalLocationNumber: + return "Terminal Location Number"; + case TelnetOption::Telnet3270Regime: + return "Telnet 3270 Regime"; + case TelnetOption::X3Pad: + return "X3 Pad"; + case TelnetOption::NegotiateAboutWindowSize: + return "Negotiate About Window Size"; + case TelnetOption::TerminalSpeed: + return "Terminal Speed"; + case TelnetOption::RemoteFlowControl: + return "Remote Flow Control"; + case TelnetOption::Linemode: + return "Line mode"; + case TelnetOption::XDisplayLocation: + return "X Display Location"; + case TelnetOption::EnvironmentOption: + return "Environment Option"; + case TelnetOption::AuthenticationOption: + return "Authentication Option"; + case TelnetOption::EncryptionOption: + return "Encryption Option"; + case TelnetOption::NewEnvironmentOption: + return "New Environment Option"; + case TelnetOption::TN3270E: + return "TN3270E"; + case TelnetOption::XAuth: + return "X Server Authentication"; + case TelnetOption::Charset: + return "Charset"; + case TelnetOption::TelnetRemoteSerialPort: + return "Telnet Remote Serial Port"; + case TelnetOption::ComPortControlOption: + return "Com Port Control Option"; + case TelnetOption::TelnetSuppressLocalEcho: + return "Telnet Suppress Local Echo"; + case TelnetOption::TelnetStartTLS: + return "Telnet Start TLS"; + case TelnetOption::Kermit: + return "Kermit"; + case TelnetOption::SendURL: + return "Send URL"; + case TelnetOption::ForwardX: + return "Forward X Server"; + case TelnetOption::TelOptPragmaLogon: + return "Telnet Option Pragma Logon"; + case TelnetOption::TelOptSSPILogon: + return "Telnet Option SSPI Logon"; + case TelnetOption::TelOptPragmaHeartbeat: + return "Telnet Option Pragma Heartbeat"; + case TelnetOption::ExtendedOptions: + return "Extended option list"; + default: + return "Unknown Option"; + } } -} -std::string TelnetLayer::toString() const -{ - if (isDataField(m_Data)) - return "Telnet Data"; - return "Telnet Control"; -} + std::string TelnetLayer::toString() const + { + if (isDataField(m_Data)) + return "Telnet Data"; + return "Telnet Control"; + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/TextBasedProtocol.cpp b/Packet++/src/TextBasedProtocol.cpp index 9b50723803..7f0f2af246 100644 --- a/Packet++/src/TextBasedProtocol.cpp +++ b/Packet++/src/TextBasedProtocol.cpp @@ -9,685 +9,699 @@ namespace pcpp { -// this implementation of strnlen is required since mingw doesn't have strnlen -size_t tbp_my_own_strnlen(const char* s, size_t maxlen) -{ - if (s == nullptr || maxlen == 0) - return 0; - - size_t i = 0; - for(; (i < maxlen) && s[i]; ++i); - return i; -} - - -// -------- Class TextBasedProtocolMessage ----------------- + // this implementation of strnlen is required since mingw doesn't have strnlen + size_t tbp_my_own_strnlen(const char* s, size_t maxlen) + { + if (s == nullptr || maxlen == 0) + return 0; + size_t i = 0; + for (; (i < maxlen) && s[i]; ++i) + ; + return i; + } -TextBasedProtocolMessage::TextBasedProtocolMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet), - m_FieldList(nullptr), m_LastField(nullptr), m_FieldsOffset(0) {} + // -------- Class TextBasedProtocolMessage ----------------- -TextBasedProtocolMessage::TextBasedProtocolMessage(const TextBasedProtocolMessage& other) : Layer(other) -{ - copyDataFrom(other); -} + TextBasedProtocolMessage::TextBasedProtocolMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) + : Layer(data, dataLen, prevLayer, packet), m_FieldList(nullptr), m_LastField(nullptr), m_FieldsOffset(0) + {} -TextBasedProtocolMessage& TextBasedProtocolMessage::operator=(const TextBasedProtocolMessage& other) -{ - Layer::operator=(other); - HeaderField* curField = m_FieldList; - while (curField != nullptr) + TextBasedProtocolMessage::TextBasedProtocolMessage(const TextBasedProtocolMessage& other) : Layer(other) { - HeaderField* temp = curField; - curField = curField->getNextField(); - delete temp; + copyDataFrom(other); } - copyDataFrom(other); - - return *this; -} - -void TextBasedProtocolMessage::copyDataFrom(const TextBasedProtocolMessage& other) -{ - // copy field list - if (other.m_FieldList != nullptr) + TextBasedProtocolMessage& TextBasedProtocolMessage::operator=(const TextBasedProtocolMessage& other) { - m_FieldList = new HeaderField(*(other.m_FieldList)); + Layer::operator=(other); HeaderField* curField = m_FieldList; - curField->attachToTextBasedProtocolMessage(this, other.m_FieldList->m_NameOffsetInMessage); - HeaderField* curOtherField = other.m_FieldList; - while (curOtherField->getNextField() != nullptr) + while (curField != nullptr) { - HeaderField* newField = new HeaderField(*(curOtherField->getNextField())); - newField->attachToTextBasedProtocolMessage(this, curOtherField->getNextField()->m_NameOffsetInMessage); - curField->setNextField(newField); + HeaderField* temp = curField; curField = curField->getNextField(); - curOtherField = curOtherField->getNextField(); + delete temp; } - m_LastField = curField; - } - else - { - m_FieldList = nullptr; - m_LastField = nullptr; - } - - m_FieldsOffset = other.m_FieldsOffset; + copyDataFrom(other); - // copy map - for(HeaderField* field = m_FieldList; field != nullptr; field = field->getNextField()) - { - m_FieldNameToFieldMap.insert(std::pair(field->getFieldName(), field)); + return *this; } -} - -void TextBasedProtocolMessage::parseFields() -{ - char nameValueSeparator = getHeaderFieldNameValueSeparator(); - bool spacesAllowedBetweenNameAndValue = spacesAllowedBetweenHeaderFieldNameAndValue(); - - HeaderField* firstField = new HeaderField(this, m_FieldsOffset, nameValueSeparator, spacesAllowedBetweenNameAndValue); - PCPP_LOG_DEBUG("Added new field: name='" << firstField->getFieldName() << "'; offset in packet=" << firstField->m_NameOffsetInMessage << "; length=" << firstField->getFieldSize()); - PCPP_LOG_DEBUG(" Field value = " << firstField->getFieldValue()); - - if (m_FieldList == nullptr) - m_FieldList = firstField; - else - m_FieldList->setNextField(firstField); - - std::string fieldName = firstField->getFieldName(); - std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); - m_FieldNameToFieldMap.insert(std::pair(fieldName, firstField)); - - // Last field will be empty and contain just "\n" or "\r\n". This field will mark the end of the header - HeaderField* curField = m_FieldList; - int curOffset = m_FieldsOffset; - // last field can be one of: - // a.) \r\n\r\n or \n\n marking the end of the header - // b.) the end of the packet - while (!curField->isEndOfHeader() && curOffset + curField->getFieldSize() < m_DataLen) - { - curOffset += curField->getFieldSize(); - HeaderField* newField = new HeaderField(this, curOffset, nameValueSeparator, spacesAllowedBetweenNameAndValue); - if(newField->getFieldSize() > 0) + void TextBasedProtocolMessage::copyDataFrom(const TextBasedProtocolMessage& other) + { + // copy field list + if (other.m_FieldList != nullptr) { - PCPP_LOG_DEBUG("Added new field: name='" << newField->getFieldName() << "'; offset in packet=" << newField->m_NameOffsetInMessage << "; length=" << newField->getFieldSize()); - PCPP_LOG_DEBUG(" Field value = " << newField->getFieldValue()); - curField->setNextField(newField); - curField = newField; - fieldName = newField->getFieldName(); - std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); - m_FieldNameToFieldMap.insert(std::pair(fieldName, newField)); + m_FieldList = new HeaderField(*(other.m_FieldList)); + HeaderField* curField = m_FieldList; + curField->attachToTextBasedProtocolMessage(this, other.m_FieldList->m_NameOffsetInMessage); + HeaderField* curOtherField = other.m_FieldList; + while (curOtherField->getNextField() != nullptr) + { + HeaderField* newField = new HeaderField(*(curOtherField->getNextField())); + newField->attachToTextBasedProtocolMessage(this, curOtherField->getNextField()->m_NameOffsetInMessage); + curField->setNextField(newField); + curField = curField->getNextField(); + curOtherField = curOtherField->getNextField(); + } + + m_LastField = curField; } else { - delete newField; - break; + m_FieldList = nullptr; + m_LastField = nullptr; } - } - - m_LastField = curField; -} + m_FieldsOffset = other.m_FieldsOffset; -TextBasedProtocolMessage::~TextBasedProtocolMessage() -{ - while (m_FieldList != nullptr) - { - HeaderField* temp = m_FieldList; - m_FieldList = m_FieldList->getNextField(); - delete temp; + // copy map + for (HeaderField* field = m_FieldList; field != nullptr; field = field->getNextField()) + { + m_FieldNameToFieldMap.insert(std::pair(field->getFieldName(), field)); + } } -} + void TextBasedProtocolMessage::parseFields() + { + char nameValueSeparator = getHeaderFieldNameValueSeparator(); + bool spacesAllowedBetweenNameAndValue = spacesAllowedBetweenHeaderFieldNameAndValue(); -HeaderField* TextBasedProtocolMessage::addField(const std::string& fieldName, const std::string& fieldValue) -{ - HeaderField newField(fieldName, fieldValue, getHeaderFieldNameValueSeparator(), spacesAllowedBetweenHeaderFieldNameAndValue()); - return addField(newField); -} + HeaderField* firstField = + new HeaderField(this, m_FieldsOffset, nameValueSeparator, spacesAllowedBetweenNameAndValue); + PCPP_LOG_DEBUG("Added new field: name='" << firstField->getFieldName() + << "'; offset in packet=" << firstField->m_NameOffsetInMessage + << "; length=" << firstField->getFieldSize()); + PCPP_LOG_DEBUG(" Field value = " << firstField->getFieldValue()); -HeaderField* TextBasedProtocolMessage::addField(const HeaderField& newField) -{ - return insertField(m_LastField, newField); -} + if (m_FieldList == nullptr) + m_FieldList = firstField; + else + m_FieldList->setNextField(firstField); -HeaderField* TextBasedProtocolMessage::addEndOfHeader() -{ - HeaderField endOfHeaderField(PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER, "", '\0', false); - return insertField(m_LastField, endOfHeaderField); -} + std::string fieldName = firstField->getFieldName(); + std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); + m_FieldNameToFieldMap.insert(std::pair(fieldName, firstField)); + // Last field will be empty and contain just "\n" or "\r\n". This field will mark the end of the header + HeaderField* curField = m_FieldList; + int curOffset = m_FieldsOffset; + // last field can be one of: + // a.) \r\n\r\n or \n\n marking the end of the header + // b.) the end of the packet + while (!curField->isEndOfHeader() && curOffset + curField->getFieldSize() < m_DataLen) + { + curOffset += curField->getFieldSize(); + HeaderField* newField = + new HeaderField(this, curOffset, nameValueSeparator, spacesAllowedBetweenNameAndValue); + if (newField->getFieldSize() > 0) + { + PCPP_LOG_DEBUG("Added new field: name='" << newField->getFieldName() + << "'; offset in packet=" << newField->m_NameOffsetInMessage + << "; length=" << newField->getFieldSize()); + PCPP_LOG_DEBUG(" Field value = " << newField->getFieldValue()); + curField->setNextField(newField); + curField = newField; + fieldName = newField->getFieldName(); + std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); + m_FieldNameToFieldMap.insert(std::pair(fieldName, newField)); + } + else + { + delete newField; + break; + } + } -HeaderField* TextBasedProtocolMessage::insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue) -{ - HeaderField newField(fieldName, fieldValue, getHeaderFieldNameValueSeparator(), spacesAllowedBetweenHeaderFieldNameAndValue()); - return insertField(prevField, newField); -} + m_LastField = curField; + } -HeaderField* TextBasedProtocolMessage::insertField(std::string prevFieldName, const std::string& fieldName, const std::string& fieldValue) -{ - if (prevFieldName == "") + TextBasedProtocolMessage::~TextBasedProtocolMessage() { - return insertField(nullptr, fieldName, fieldValue); + while (m_FieldList != nullptr) + { + HeaderField* temp = m_FieldList; + m_FieldList = m_FieldList->getNextField(); + delete temp; + } } - else - { - HeaderField* prevField = getFieldByName(prevFieldName); - if (prevField == nullptr) - return nullptr; - return insertField(prevField, fieldName, fieldValue); + HeaderField* TextBasedProtocolMessage::addField(const std::string& fieldName, const std::string& fieldValue) + { + HeaderField newField(fieldName, fieldValue, getHeaderFieldNameValueSeparator(), + spacesAllowedBetweenHeaderFieldNameAndValue()); + return addField(newField); } -} - -HeaderField* TextBasedProtocolMessage::insertField(HeaderField* prevField, const HeaderField& newField) -{ - if (newField.m_TextBasedProtocolMessage != nullptr) + HeaderField* TextBasedProtocolMessage::addField(const HeaderField& newField) { - PCPP_LOG_ERROR("This field is already associated with another message"); - return nullptr; + return insertField(m_LastField, newField); } - if (prevField != nullptr && prevField->getFieldName() == PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) + HeaderField* TextBasedProtocolMessage::addEndOfHeader() { - PCPP_LOG_ERROR("Cannot add a field after end of header"); - return nullptr; + HeaderField endOfHeaderField(PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER, "", '\0', false); + return insertField(m_LastField, endOfHeaderField); } - HeaderField* newFieldToAdd = new HeaderField(newField); - - int newFieldOffset = m_FieldsOffset; - if (prevField != nullptr) - newFieldOffset = prevField->m_NameOffsetInMessage + prevField->getFieldSize(); - - // extend layer to make room for the new field. Field will be added just before the last field - if (!extendLayer(newFieldOffset, newFieldToAdd->getFieldSize())) + HeaderField* TextBasedProtocolMessage::insertField(HeaderField* prevField, const std::string& fieldName, + const std::string& fieldValue) { - PCPP_LOG_ERROR("Cannot extend layer to insert the header"); - delete newFieldToAdd; - return nullptr; + HeaderField newField(fieldName, fieldValue, getHeaderFieldNameValueSeparator(), + spacesAllowedBetweenHeaderFieldNameAndValue()); + return insertField(prevField, newField); } - HeaderField* curField = m_FieldList; - if (prevField != nullptr) - curField = prevField->getNextField(); + HeaderField* TextBasedProtocolMessage::insertField(std::string prevFieldName, const std::string& fieldName, + const std::string& fieldValue) + { + if (prevFieldName == "") + { + return insertField(nullptr, fieldName, fieldValue); + } + else + { + HeaderField* prevField = getFieldByName(prevFieldName); + if (prevField == nullptr) + return nullptr; - // go over all fields after prevField and update their offsets - shiftFieldsOffset(curField, newFieldToAdd->getFieldSize()); + return insertField(prevField, fieldName, fieldValue); + } + } - // copy new field data to message - memcpy(m_Data + newFieldOffset, newFieldToAdd->m_NewFieldData, newFieldToAdd->getFieldSize()); + HeaderField* TextBasedProtocolMessage::insertField(HeaderField* prevField, const HeaderField& newField) + { + if (newField.m_TextBasedProtocolMessage != nullptr) + { + PCPP_LOG_ERROR("This field is already associated with another message"); + return nullptr; + } - // attach new field to message - newFieldToAdd->attachToTextBasedProtocolMessage(this, newFieldOffset); + if (prevField != nullptr && prevField->getFieldName() == PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) + { + PCPP_LOG_ERROR("Cannot add a field after end of header"); + return nullptr; + } - // insert field into fields link list - if (prevField == nullptr) - { - newFieldToAdd->setNextField(m_FieldList); - m_FieldList = newFieldToAdd; - } - else - { - newFieldToAdd->setNextField(prevField->getNextField()); - prevField->setNextField(newFieldToAdd); - } + HeaderField* newFieldToAdd = new HeaderField(newField); - // if newField is the last field, update m_LastField - if (newFieldToAdd->getNextField() == nullptr) - m_LastField = newFieldToAdd; + int newFieldOffset = m_FieldsOffset; + if (prevField != nullptr) + newFieldOffset = prevField->m_NameOffsetInMessage + prevField->getFieldSize(); - // insert the new field into name to field map - std::string fieldName = newFieldToAdd->getFieldName(); - std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); - m_FieldNameToFieldMap.insert(std::pair(fieldName, newFieldToAdd)); + // extend layer to make room for the new field. Field will be added just before the last field + if (!extendLayer(newFieldOffset, newFieldToAdd->getFieldSize())) + { + PCPP_LOG_ERROR("Cannot extend layer to insert the header"); + delete newFieldToAdd; + return nullptr; + } - return newFieldToAdd; -} + HeaderField* curField = m_FieldList; + if (prevField != nullptr) + curField = prevField->getNextField(); -bool TextBasedProtocolMessage::removeField(std::string fieldName, int index) -{ - std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); + // go over all fields after prevField and update their offsets + shiftFieldsOffset(curField, newFieldToAdd->getFieldSize()); - HeaderField* fieldToRemove = nullptr; + // copy new field data to message + memcpy(m_Data + newFieldOffset, newFieldToAdd->m_NewFieldData, newFieldToAdd->getFieldSize()); - std::pair ::iterator, std::multimap::iterator> range; - range = m_FieldNameToFieldMap.equal_range(fieldName); - int i = 0; - for (std::multimap::iterator iter = range.first; iter != range.second; ++iter) - { - if (i == index) + // attach new field to message + newFieldToAdd->attachToTextBasedProtocolMessage(this, newFieldOffset); + + // insert field into fields link list + if (prevField == nullptr) { - fieldToRemove = iter->second; - break; + newFieldToAdd->setNextField(m_FieldList); + m_FieldList = newFieldToAdd; + } + else + { + newFieldToAdd->setNextField(prevField->getNextField()); + prevField->setNextField(newFieldToAdd); } - i++; - } - - if (fieldToRemove != nullptr) - return removeField(fieldToRemove); - else - { - PCPP_LOG_ERROR("Cannot find field '" << fieldName << "'"); - return false; - } -} + // if newField is the last field, update m_LastField + if (newFieldToAdd->getNextField() == nullptr) + m_LastField = newFieldToAdd; -bool TextBasedProtocolMessage::removeField(HeaderField* fieldToRemove) -{ - if (fieldToRemove == nullptr) - return true; + // insert the new field into name to field map + std::string fieldName = newFieldToAdd->getFieldName(); + std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); + m_FieldNameToFieldMap.insert(std::pair(fieldName, newFieldToAdd)); - if (fieldToRemove->m_TextBasedProtocolMessage != this) - { - PCPP_LOG_ERROR("Field isn't associated with this message"); - return false; + return newFieldToAdd; } - std::string fieldName = fieldToRemove->getFieldName(); - - // shorten layer and delete this field - if (!shortenLayer(fieldToRemove->m_NameOffsetInMessage, fieldToRemove->getFieldSize())) + bool TextBasedProtocolMessage::removeField(std::string fieldName, int index) { - PCPP_LOG_ERROR("Cannot shorten layer"); - return false; - } + std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); - // update offsets of all fields after this field - HeaderField* curField = fieldToRemove->getNextField(); - shiftFieldsOffset(curField, 0-fieldToRemove->getFieldSize()); -// while (curField != NULL) -// { -// curField->m_NameOffsetInMessage -= fieldToRemove->getFieldSize(); -// if (curField->m_ValueOffsetInMessage != -1) -// curField->m_ValueOffsetInMessage -= fieldToRemove->getFieldSize(); -// -// curField = curField->getNextField(); -// } + HeaderField* fieldToRemove = nullptr; - // update fields link list - if (fieldToRemove == m_FieldList) - m_FieldList = m_FieldList->getNextField(); - else - { - curField = m_FieldList; - while (curField->getNextField() != fieldToRemove) - curField = curField->getNextField(); + auto range = m_FieldNameToFieldMap.equal_range(fieldName); + int i = 0; + for (std::multimap::iterator iter = range.first; iter != range.second; ++iter) + { + if (i == index) + { + fieldToRemove = iter->second; + break; + } - curField->setNextField(fieldToRemove->getNextField()); - } + i++; + } - // re-calculate m_LastField if needed - if (fieldToRemove == m_LastField) - { - if (m_FieldList == nullptr) - m_LastField = nullptr; + if (fieldToRemove != nullptr) + return removeField(fieldToRemove); else { - curField = m_FieldList; - while (curField->getNextField() != nullptr) - curField = curField->getNextField(); - m_LastField = curField; + PCPP_LOG_ERROR("Cannot find field '" << fieldName << "'"); + return false; } } - // remove the hash entry for this field - std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); - std::pair ::iterator, std::multimap::iterator> range; - range = m_FieldNameToFieldMap.equal_range(fieldName); - for (std::multimap::iterator iter = range.first; iter != range.second; ++iter) + bool TextBasedProtocolMessage::removeField(HeaderField* fieldToRemove) { - if (iter->second == fieldToRemove) + if (fieldToRemove == nullptr) + return true; + + if (fieldToRemove->m_TextBasedProtocolMessage != this) { - m_FieldNameToFieldMap.erase(iter); - break; + PCPP_LOG_ERROR("Field isn't associated with this message"); + return false; } - } - // finally - delete this field - delete fieldToRemove; + std::string fieldName = fieldToRemove->getFieldName(); - return true; -} + // shorten layer and delete this field + if (!shortenLayer(fieldToRemove->m_NameOffsetInMessage, fieldToRemove->getFieldSize())) + { + PCPP_LOG_ERROR("Cannot shorten layer"); + return false; + } -bool TextBasedProtocolMessage::isHeaderComplete() const -{ - if (m_LastField == nullptr) - return false; + // update offsets of all fields after this field + HeaderField* curField = fieldToRemove->getNextField(); + shiftFieldsOffset(curField, 0 - fieldToRemove->getFieldSize()); + // while (curField != NULL) + // { + // curField->m_NameOffsetInMessage -= fieldToRemove->getFieldSize(); + // if (curField->m_ValueOffsetInMessage != -1) + // curField->m_ValueOffsetInMessage -= fieldToRemove->getFieldSize(); + // + // curField = curField->getNextField(); + // } + + // update fields link list + if (fieldToRemove == m_FieldList) + m_FieldList = m_FieldList->getNextField(); + else + { + curField = m_FieldList; + while (curField->getNextField() != fieldToRemove) + curField = curField->getNextField(); - return (m_LastField->getFieldName() == PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER); -} + curField->setNextField(fieldToRemove->getNextField()); + } -void TextBasedProtocolMessage::shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift) -{ - while (fromField != nullptr) - { - fromField->m_NameOffsetInMessage += numOfBytesToShift; - if (fromField->m_ValueOffsetInMessage != -1) - fromField->m_ValueOffsetInMessage += numOfBytesToShift; - fromField = fromField->getNextField(); - } -} + // re-calculate m_LastField if needed + if (fieldToRemove == m_LastField) + { + if (m_FieldList == nullptr) + m_LastField = nullptr; + else + { + curField = m_FieldList; + while (curField->getNextField() != nullptr) + curField = curField->getNextField(); + m_LastField = curField; + } + } -HeaderField* TextBasedProtocolMessage::getFieldByName(std::string fieldName, int index) const -{ - std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); + // remove the hash entry for this field + std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); + auto range = m_FieldNameToFieldMap.equal_range(fieldName); + for (std::multimap::iterator iter = range.first; iter != range.second; ++iter) + { + if (iter->second == fieldToRemove) + { + m_FieldNameToFieldMap.erase(iter); + break; + } + } - std::pair ::const_iterator, std::multimap::const_iterator> range; - range = m_FieldNameToFieldMap.equal_range(fieldName); - int i = 0; - for (std::multimap::const_iterator iter = range.first; iter != range.second; ++iter) - { - if (i == index) - return iter->second; + // finally - delete this field + delete fieldToRemove; - i++; + return true; } - return nullptr; -} + bool TextBasedProtocolMessage::isHeaderComplete() const + { + if (m_LastField == nullptr) + return false; -int TextBasedProtocolMessage::getFieldCount() const -{ - int result = 0; + return (m_LastField->getFieldName() == PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER); + } - HeaderField* curField = getFirstField(); - while (curField != nullptr) + void TextBasedProtocolMessage::shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift) { - if (!curField->isEndOfHeader()) - result++; - curField = curField->getNextField(); + while (fromField != nullptr) + { + fromField->m_NameOffsetInMessage += numOfBytesToShift; + if (fromField->m_ValueOffsetInMessage != -1) + fromField->m_ValueOffsetInMessage += numOfBytesToShift; + fromField = fromField->getNextField(); + } } - return result; -} + HeaderField* TextBasedProtocolMessage::getFieldByName(std::string fieldName, int index) const + { + std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); -void TextBasedProtocolMessage::parseNextLayer() -{ - size_t headerLen = getHeaderLen(); - if (m_DataLen <= headerLen) - return; + auto range = m_FieldNameToFieldMap.equal_range(fieldName); + int i = 0; + for (std::multimap::const_iterator iter = range.first; iter != range.second; ++iter) + { + if (i == index) + return iter->second; - m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); -} + i++; + } -size_t TextBasedProtocolMessage::getHeaderLen() const -{ - return m_LastField->m_NameOffsetInMessage + m_LastField->m_FieldSize; -} + return nullptr; + } -void TextBasedProtocolMessage::computeCalculateFields() -{ - //nothing to do for now -} + int TextBasedProtocolMessage::getFieldCount() const + { + int result = 0; + HeaderField* curField = getFirstField(); + while (curField != nullptr) + { + if (!curField->isEndOfHeader()) + result++; + curField = curField->getNextField(); + } + + return result; + } + + void TextBasedProtocolMessage::parseNextLayer() + { + size_t headerLen = getHeaderLen(); + if (m_DataLen <= headerLen) + return; + m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); + } + size_t TextBasedProtocolMessage::getHeaderLen() const + { + return m_LastField->m_NameOffsetInMessage + m_LastField->m_FieldSize; + } + void TextBasedProtocolMessage::computeCalculateFields() + { + // nothing to do for now + } -// -------- Class HeaderField ----------------- + // -------- Class HeaderField ----------------- + HeaderField::HeaderField(TextBasedProtocolMessage* TextBasedProtocolMessage, int offsetInMessage, + char nameValueSeparator, bool spacesAllowedBetweenNameAndValue) + : m_NewFieldData(nullptr), m_TextBasedProtocolMessage(TextBasedProtocolMessage), + m_NameOffsetInMessage(offsetInMessage), m_NextField(nullptr), m_NameValueSeparator(nameValueSeparator), + m_SpacesAllowedBetweenNameAndValue(spacesAllowedBetweenNameAndValue) + { + char* fieldData = (char*)(m_TextBasedProtocolMessage->m_Data + m_NameOffsetInMessage); + char* fieldEndPtr = + (char*)memchr(fieldData, '\n', m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); + if (fieldEndPtr == nullptr) + m_FieldSize = + tbp_my_own_strnlen(fieldData, m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); + else + m_FieldSize = fieldEndPtr - fieldData + 1; -HeaderField::HeaderField(TextBasedProtocolMessage* TextBasedProtocolMessage, int offsetInMessage, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue) : - m_NewFieldData(nullptr), m_TextBasedProtocolMessage(TextBasedProtocolMessage), m_NameOffsetInMessage(offsetInMessage), m_NextField(nullptr), - m_NameValueSeparator(nameValueSeparator), m_SpacesAllowedBetweenNameAndValue(spacesAllowedBetweenNameAndValue) -{ - char* fieldData = (char*)(m_TextBasedProtocolMessage->m_Data + m_NameOffsetInMessage); - char* fieldEndPtr = (char*)memchr(fieldData, '\n', m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); - if (fieldEndPtr == nullptr) - m_FieldSize = tbp_my_own_strnlen(fieldData, m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); - else - m_FieldSize = fieldEndPtr - fieldData + 1; - - if (m_FieldSize == 0 || (*fieldData) == '\r' || (*fieldData) == '\n') - { - m_FieldNameSize = -1; - m_ValueOffsetInMessage = -1; - m_FieldValueSize = -1; - m_FieldNameSize = -1; - m_IsEndOfHeaderField = true; - return; - } - else - m_IsEndOfHeaderField = false; - - char* fieldValuePtr = (char*)memchr(fieldData, nameValueSeparator, m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); - // could not find the position of the separator, meaning field value position is unknown - if (fieldValuePtr == nullptr || (fieldEndPtr != nullptr && fieldValuePtr >= fieldEndPtr)) - { - m_ValueOffsetInMessage = -1; - m_FieldValueSize = -1; - m_FieldNameSize = m_FieldSize; - } - else - { - m_FieldNameSize = fieldValuePtr - fieldData; - // Header field looks like this: [separator] - // So fieldValuePtr give us the position of the separator. Value offset is the first non-space byte forward - fieldValuePtr++; - - // reached the end of the packet and value start offset wasn't found - if ((size_t)(fieldValuePtr - (char*)(m_TextBasedProtocolMessage->m_Data)) >= m_TextBasedProtocolMessage->getDataLen()) + if (m_FieldSize == 0 || (*fieldData) == '\r' || (*fieldData) == '\n') { + m_FieldNameSize = -1; m_ValueOffsetInMessage = -1; m_FieldValueSize = -1; + m_FieldNameSize = -1; + m_IsEndOfHeaderField = true; return; } + else + m_IsEndOfHeaderField = false; - if (spacesAllowedBetweenNameAndValue) - { - // advance fieldValuePtr 1 byte forward while didn't get to end of packet and fieldValuePtr points to a space char - while ((size_t)(fieldValuePtr - (char*)m_TextBasedProtocolMessage->m_Data) < m_TextBasedProtocolMessage->getDataLen() && (*fieldValuePtr) == ' ') - { - fieldValuePtr++; - } - } - - // reached the end of the packet and value start offset wasn't found - if ((size_t)(fieldValuePtr - (char*)(m_TextBasedProtocolMessage->m_Data)) >= m_TextBasedProtocolMessage->getDataLen()) + char* fieldValuePtr = (char*)memchr(fieldData, nameValueSeparator, + m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); + // could not find the position of the separator, meaning field value position is unknown + if (fieldValuePtr == nullptr || (fieldEndPtr != nullptr && fieldValuePtr >= fieldEndPtr)) { m_ValueOffsetInMessage = -1; m_FieldValueSize = -1; + m_FieldNameSize = m_FieldSize; } else { - m_ValueOffsetInMessage = fieldValuePtr - (char*)m_TextBasedProtocolMessage->m_Data; - // couldn't find the end of the field, so assuming the field value length is from m_ValueOffsetInMessage until the end of the packet - if (fieldEndPtr == nullptr) - m_FieldValueSize = (char*)(m_TextBasedProtocolMessage->m_Data + m_TextBasedProtocolMessage->getDataLen()) - fieldValuePtr; + m_FieldNameSize = fieldValuePtr - fieldData; + // Header field looks like this: [separator] + // So fieldValuePtr give us the position of the separator. Value offset is the first non-space byte forward + fieldValuePtr++; + + // reached the end of the packet and value start offset wasn't found + if ((size_t)(fieldValuePtr - (char*)(m_TextBasedProtocolMessage->m_Data)) >= + m_TextBasedProtocolMessage->getDataLen()) + { + m_ValueOffsetInMessage = -1; + m_FieldValueSize = -1; + return; + } + + if (spacesAllowedBetweenNameAndValue) + { + // advance fieldValuePtr 1 byte forward while didn't get to end of packet and fieldValuePtr points to a + // space char + while ((size_t)(fieldValuePtr - (char*)m_TextBasedProtocolMessage->m_Data) < + m_TextBasedProtocolMessage->getDataLen() && + (*fieldValuePtr) == ' ') + { + fieldValuePtr++; + } + } + + // reached the end of the packet and value start offset wasn't found + if ((size_t)(fieldValuePtr - (char*)(m_TextBasedProtocolMessage->m_Data)) >= + m_TextBasedProtocolMessage->getDataLen()) + { + m_ValueOffsetInMessage = -1; + m_FieldValueSize = -1; + } else { - m_FieldValueSize = fieldEndPtr - fieldValuePtr; - // if field ends with \r\n, decrease the value length by 1 - if ((*(--fieldEndPtr)) == '\r') - m_FieldValueSize--; + m_ValueOffsetInMessage = fieldValuePtr - (char*)m_TextBasedProtocolMessage->m_Data; + // couldn't find the end of the field, so assuming the field value length is from m_ValueOffsetInMessage + // until the end of the packet + if (fieldEndPtr == nullptr) + { + // clang-format off + m_FieldValueSize = (char*)(m_TextBasedProtocolMessage->m_Data + m_TextBasedProtocolMessage->getDataLen()) - fieldValuePtr; + // clang-format on + } + else + { + m_FieldValueSize = fieldEndPtr - fieldValuePtr; + // if field ends with \r\n, decrease the value length by 1 + if ((*(--fieldEndPtr)) == '\r') + m_FieldValueSize--; + } } } } -} -HeaderField::HeaderField(const std::string& name, const std::string& value, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue) -{ - m_NameValueSeparator = nameValueSeparator; - m_SpacesAllowedBetweenNameAndValue = spacesAllowedBetweenNameAndValue; - initNewField(std::move(name), std::move(value)); -} + HeaderField::HeaderField(const std::string& name, const std::string& value, char nameValueSeparator, + bool spacesAllowedBetweenNameAndValue) + { + m_NameValueSeparator = nameValueSeparator; + m_SpacesAllowedBetweenNameAndValue = spacesAllowedBetweenNameAndValue; + initNewField(std::move(name), std::move(value)); + } -void HeaderField::initNewField(const std::string& name, const std::string& value) -{ - m_TextBasedProtocolMessage = nullptr; - m_NameOffsetInMessage = 0; - m_NextField = nullptr; - - // first building the name-value separator - std::string nameValueSeparation(1, m_NameValueSeparator); - if (m_SpacesAllowedBetweenNameAndValue) - nameValueSeparation += " "; - - // Field size is: name_length + separator_len + value_length + '\r\n' - if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) - m_FieldSize = name.length() + nameValueSeparation.length() + value.length() + 2; - else - // Field is \r\n (2B) - m_FieldSize = 2; - - m_NewFieldData = new uint8_t[m_FieldSize]; - std::string fieldData; - - if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) - fieldData = name + nameValueSeparation + value + "\r\n"; - else - fieldData = "\r\n"; - - // copy field data to m_NewFieldData - memcpy(m_NewFieldData, fieldData.c_str(), m_FieldSize); - - // calculate value offset - if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) - m_ValueOffsetInMessage = name.length() + nameValueSeparation.length(); - else - m_ValueOffsetInMessage = 0; - m_FieldNameSize = name.length(); - m_FieldValueSize = value.length(); - - if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) - m_IsEndOfHeaderField = false; - else - m_IsEndOfHeaderField = true; -} - -HeaderField::~HeaderField() -{ - if (m_NewFieldData != nullptr) - delete [] m_NewFieldData; -} + void HeaderField::initNewField(const std::string& name, const std::string& value) + { + m_TextBasedProtocolMessage = nullptr; + m_NameOffsetInMessage = 0; + m_NextField = nullptr; + + // first building the name-value separator + std::string nameValueSeparation(1, m_NameValueSeparator); + if (m_SpacesAllowedBetweenNameAndValue) + nameValueSeparation += " "; + + // Field size is: name_length + separator_len + value_length + '\r\n' + if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) + m_FieldSize = name.length() + nameValueSeparation.length() + value.length() + 2; + else + // Field is \r\n (2B) + m_FieldSize = 2; -HeaderField::HeaderField(const HeaderField& other) : m_NameValueSeparator('\0'), m_SpacesAllowedBetweenNameAndValue(false) -{ - m_NameValueSeparator = other.m_NameValueSeparator; - m_SpacesAllowedBetweenNameAndValue = other.m_SpacesAllowedBetweenNameAndValue; - initNewField(other.getFieldName(), other.getFieldValue()); -} + m_NewFieldData = new uint8_t[m_FieldSize]; + std::string fieldData; -HeaderField& HeaderField::operator=(const HeaderField& other) -{ - m_NameValueSeparator = other.m_NameValueSeparator; - m_SpacesAllowedBetweenNameAndValue = other.m_SpacesAllowedBetweenNameAndValue; - if (m_NewFieldData != nullptr) - delete [] m_NewFieldData; - initNewField(other.getFieldName(), other.getFieldValue()); + if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) + fieldData = name + nameValueSeparation + value + "\r\n"; + else + fieldData = "\r\n"; - return (*this); -} + // copy field data to m_NewFieldData + memcpy(m_NewFieldData, fieldData.c_str(), m_FieldSize); -char* HeaderField::getData() const -{ - if (m_TextBasedProtocolMessage == nullptr) - return (char*)m_NewFieldData; - else - return (char*)(m_TextBasedProtocolMessage->m_Data); -} + // calculate value offset + if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) + m_ValueOffsetInMessage = name.length() + nameValueSeparation.length(); + else + m_ValueOffsetInMessage = 0; + m_FieldNameSize = name.length(); + m_FieldValueSize = value.length(); -void HeaderField::setNextField(HeaderField* nextField) -{ - m_NextField = nextField; -} + if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) + m_IsEndOfHeaderField = false; + else + m_IsEndOfHeaderField = true; + } -HeaderField* HeaderField::getNextField() const -{ - return m_NextField; -} + HeaderField::~HeaderField() + { + if (m_NewFieldData != nullptr) + delete[] m_NewFieldData; + } -std::string HeaderField::getFieldName() const -{ - std::string result; + HeaderField::HeaderField(const HeaderField& other) + : m_NameValueSeparator('\0'), m_SpacesAllowedBetweenNameAndValue(false) + { + m_NameValueSeparator = other.m_NameValueSeparator; + m_SpacesAllowedBetweenNameAndValue = other.m_SpacesAllowedBetweenNameAndValue; + initNewField(other.getFieldName(), other.getFieldValue()); + } - if (m_FieldNameSize != (size_t)-1) - result.assign((const char*)(((HeaderField*)this)->getData() + m_NameOffsetInMessage), m_FieldNameSize); + HeaderField& HeaderField::operator=(const HeaderField& other) + { + m_NameValueSeparator = other.m_NameValueSeparator; + m_SpacesAllowedBetweenNameAndValue = other.m_SpacesAllowedBetweenNameAndValue; + if (m_NewFieldData != nullptr) + delete[] m_NewFieldData; + initNewField(other.getFieldName(), other.getFieldValue()); - return result; -} + return (*this); + } -std::string HeaderField::getFieldValue() const -{ - std::string result; - if (m_ValueOffsetInMessage != -1) - result.assign((const char*)(((HeaderField*)this)->getData() + m_ValueOffsetInMessage), m_FieldValueSize); - return result; -} + char* HeaderField::getData() const + { + if (m_TextBasedProtocolMessage == nullptr) + return (char*)m_NewFieldData; + else + return (char*)(m_TextBasedProtocolMessage->m_Data); + } -bool HeaderField::setFieldValue(const std::string& newValue) -{ - // Field isn't linked with any message yet - if (m_TextBasedProtocolMessage == nullptr) + void HeaderField::setNextField(HeaderField* nextField) { - std::string name = getFieldName(); - delete [] m_NewFieldData; - initNewField(name, newValue); - return true; + m_NextField = nextField; } - std::string curValue = getFieldValue(); - int lengthDifference = newValue.length() - curValue.length(); - // new value is longer than current value - if (lengthDifference > 0) + HeaderField* HeaderField::getNextField() const { - if (!m_TextBasedProtocolMessage->extendLayer(m_ValueOffsetInMessage, lengthDifference)) - { - PCPP_LOG_ERROR("Could not extend layer"); - return false; - } + return m_NextField; } - // new value is shorter than current value - else if (lengthDifference < 0) + + std::string HeaderField::getFieldName() const + { + std::string result; + + if (m_FieldNameSize != (size_t)-1) + result.assign((const char*)(((HeaderField*)this)->getData() + m_NameOffsetInMessage), m_FieldNameSize); + + return result; + } + + std::string HeaderField::getFieldValue() const + { + std::string result; + if (m_ValueOffsetInMessage != -1) + result.assign((const char*)(((HeaderField*)this)->getData() + m_ValueOffsetInMessage), m_FieldValueSize); + return result; + } + + bool HeaderField::setFieldValue(const std::string& newValue) { - if (!m_TextBasedProtocolMessage->shortenLayer(m_ValueOffsetInMessage, 0 - lengthDifference)) + // Field isn't linked with any message yet + if (m_TextBasedProtocolMessage == nullptr) { - PCPP_LOG_ERROR("Could not shorten layer"); - return false; + std::string name = getFieldName(); + delete[] m_NewFieldData; + initNewField(name, newValue); + return true; } - } - if (lengthDifference != 0) - m_TextBasedProtocolMessage->shiftFieldsOffset(getNextField(), lengthDifference); + std::string curValue = getFieldValue(); + int lengthDifference = newValue.length() - curValue.length(); + // new value is longer than current value + if (lengthDifference > 0) + { + if (!m_TextBasedProtocolMessage->extendLayer(m_ValueOffsetInMessage, lengthDifference)) + { + PCPP_LOG_ERROR("Could not extend layer"); + return false; + } + } + // new value is shorter than current value + else if (lengthDifference < 0) + { + if (!m_TextBasedProtocolMessage->shortenLayer(m_ValueOffsetInMessage, 0 - lengthDifference)) + { + PCPP_LOG_ERROR("Could not shorten layer"); + return false; + } + } - // update sizes - m_FieldValueSize += lengthDifference; - m_FieldSize += lengthDifference; + if (lengthDifference != 0) + m_TextBasedProtocolMessage->shiftFieldsOffset(getNextField(), lengthDifference); - // write new value to field data - memcpy(getData() + m_ValueOffsetInMessage, newValue.c_str(), newValue.length()); + // update sizes + m_FieldValueSize += lengthDifference; + m_FieldSize += lengthDifference; - return true; -} + // write new value to field data + memcpy(getData() + m_ValueOffsetInMessage, newValue.c_str(), newValue.length()); -void HeaderField::attachToTextBasedProtocolMessage(TextBasedProtocolMessage* message, int fieldOffsetInMessage) -{ - if (m_TextBasedProtocolMessage != nullptr && m_TextBasedProtocolMessage != message) - { - PCPP_LOG_ERROR("Header field already associated with another message"); - return; + return true; } - if (m_NewFieldData == nullptr) + void HeaderField::attachToTextBasedProtocolMessage(TextBasedProtocolMessage* message, int fieldOffsetInMessage) { - PCPP_LOG_ERROR("Header field doesn't have new field data"); - return; - } + if (m_TextBasedProtocolMessage != nullptr && m_TextBasedProtocolMessage != message) + { + PCPP_LOG_ERROR("Header field already associated with another message"); + return; + } - delete [] m_NewFieldData; - m_NewFieldData = nullptr; - m_TextBasedProtocolMessage = message; + if (m_NewFieldData == nullptr) + { + PCPP_LOG_ERROR("Header field doesn't have new field data"); + return; + } + + delete[] m_NewFieldData; + m_NewFieldData = nullptr; + m_TextBasedProtocolMessage = message; - int valueAndNameDifference = m_ValueOffsetInMessage - m_NameOffsetInMessage; - m_NameOffsetInMessage = fieldOffsetInMessage; - m_ValueOffsetInMessage = m_NameOffsetInMessage + valueAndNameDifference; -} + int valueAndNameDifference = m_ValueOffsetInMessage - m_NameOffsetInMessage; + m_NameOffsetInMessage = fieldOffsetInMessage; + m_ValueOffsetInMessage = m_NameOffsetInMessage + valueAndNameDifference; + } -} +} // namespace pcpp diff --git a/Packet++/src/TpktLayer.cpp b/Packet++/src/TpktLayer.cpp index 038791d18d..941402c20d 100644 --- a/Packet++/src/TpktLayer.cpp +++ b/Packet++/src/TpktLayer.cpp @@ -14,22 +14,37 @@ namespace pcpp m_DataLen = sizeof(tpkthdr); m_Data = new uint8_t[m_DataLen]; memset(m_Data, 0, m_DataLen); - tpkthdr *tpktHdr = getTpktHeader(); + tpkthdr* tpktHdr = getTpktHeader(); tpktHdr->version = version; tpktHdr->reserved = 0; tpktHdr->length = htobe16(length); m_Protocol = TPKT; } - uint8_t TpktLayer::getReserved() const { return getTpktHeader()->reserved; } + uint8_t TpktLayer::getReserved() const + { + return getTpktHeader()->reserved; + } - uint8_t TpktLayer::getVersion() const { return getTpktHeader()->version; } + uint8_t TpktLayer::getVersion() const + { + return getTpktHeader()->version; + } - uint16_t TpktLayer::getLength() const { return htobe16(getTpktHeader()->length); } + uint16_t TpktLayer::getLength() const + { + return htobe16(getTpktHeader()->length); + } - void TpktLayer::setLength(uint16_t length) const { getTpktHeader()->length = htobe16(length); } + void TpktLayer::setLength(uint16_t length) const + { + getTpktHeader()->length = htobe16(length); + } - void TpktLayer::setVersion(uint8_t version) const { getTpktHeader()->version = version; } + void TpktLayer::setVersion(uint8_t version) const + { + getTpktHeader()->version = version; + } std::string TpktLayer::toString() const { @@ -47,13 +62,15 @@ namespace pcpp if (m_DataLen <= headerLen) return; - uint8_t *payload = m_Data + headerLen; + uint8_t* payload = m_Data + headerLen; size_t payloadLen = m_DataLen - headerLen; - if (CotpLayer::isDataValid(payload, payloadLen)) { + if (CotpLayer::isDataValid(payload, payloadLen)) + { m_NextLayer = new CotpLayer(payload, payloadLen, this, m_Packet); - } else + } + else m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet); } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/UdpLayer.cpp b/Packet++/src/UdpLayer.cpp index cc92e420ba..bac4bcb8c6 100644 --- a/Packet++/src/UdpLayer.cpp +++ b/Packet++/src/UdpLayer.cpp @@ -23,130 +23,136 @@ namespace pcpp { -UdpLayer::UdpLayer(uint16_t portSrc, uint16_t portDst) -{ - const size_t headerLen = sizeof(udphdr); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - udphdr* udpHdr = (udphdr*)m_Data; - udpHdr->portDst = htobe16(portDst); - udpHdr->portSrc = htobe16(portSrc); - m_Protocol = UDP; -} - -uint16_t UdpLayer::getSrcPort() const -{ - return be16toh(getUdpHeader()->portSrc); -} + UdpLayer::UdpLayer(uint16_t portSrc, uint16_t portDst) + { + const size_t headerLen = sizeof(udphdr); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + udphdr* udpHdr = (udphdr*)m_Data; + udpHdr->portDst = htobe16(portDst); + udpHdr->portSrc = htobe16(portSrc); + m_Protocol = UDP; + } -uint16_t UdpLayer::getDstPort() const -{ - return be16toh(getUdpHeader()->portDst); -} + uint16_t UdpLayer::getSrcPort() const + { + return be16toh(getUdpHeader()->portSrc); + } -uint16_t UdpLayer::calculateChecksum(bool writeResultToPacket) -{ - udphdr* udpHdr = (udphdr*)m_Data; - uint16_t checksumRes = 0; - uint16_t currChecksumValue = udpHdr->headerChecksum; + uint16_t UdpLayer::getDstPort() const + { + return be16toh(getUdpHeader()->portDst); + } - if (m_PrevLayer != nullptr) - { - udpHdr->headerChecksum = 0; - PCPP_LOG_DEBUG("UDP data len = " << m_DataLen); + uint16_t UdpLayer::calculateChecksum(bool writeResultToPacket) + { + udphdr* udpHdr = (udphdr*)m_Data; + uint16_t checksumRes = 0; + uint16_t currChecksumValue = udpHdr->headerChecksum; - if (m_PrevLayer->getProtocol() == IPv4) + if (m_PrevLayer != nullptr) { - IPv4Address srcIP = ((IPv4Layer*)m_PrevLayer)->getSrcIPv4Address(); - IPv4Address dstIP = ((IPv4Layer*)m_PrevLayer)->getDstIPv4Address(); + udpHdr->headerChecksum = 0; + PCPP_LOG_DEBUG("UDP data len = " << m_DataLen); - checksumRes = pcpp::computePseudoHdrChecksum((uint8_t *) udpHdr, getDataLen(), IPAddress::IPv4AddressType, - PACKETPP_IPPROTO_UDP, srcIP, dstIP); + if (m_PrevLayer->getProtocol() == IPv4) + { + IPv4Address srcIP = ((IPv4Layer*)m_PrevLayer)->getSrcIPv4Address(); + IPv4Address dstIP = ((IPv4Layer*)m_PrevLayer)->getDstIPv4Address(); - PCPP_LOG_DEBUG("calculated IPv4 UDP checksum = 0x" << std::uppercase << std::hex << checksumRes); - } - else if (m_PrevLayer->getProtocol() == IPv6) - { - IPv6Address srcIP = ((IPv6Layer*)m_PrevLayer)->getSrcIPv6Address(); - IPv6Address dstIP = ((IPv6Layer*)m_PrevLayer)->getDstIPv6Address(); + checksumRes = pcpp::computePseudoHdrChecksum((uint8_t*)udpHdr, getDataLen(), IPAddress::IPv4AddressType, + PACKETPP_IPPROTO_UDP, srcIP, dstIP); + + PCPP_LOG_DEBUG("calculated IPv4 UDP checksum = 0x" << std::uppercase << std::hex << checksumRes); + } + else if (m_PrevLayer->getProtocol() == IPv6) + { + IPv6Address srcIP = ((IPv6Layer*)m_PrevLayer)->getSrcIPv6Address(); + IPv6Address dstIP = ((IPv6Layer*)m_PrevLayer)->getDstIPv6Address(); - checksumRes = computePseudoHdrChecksum((uint8_t *) udpHdr, getDataLen(), IPAddress::IPv6AddressType, - PACKETPP_IPPROTO_UDP, srcIP, dstIP); + checksumRes = computePseudoHdrChecksum((uint8_t*)udpHdr, getDataLen(), IPAddress::IPv6AddressType, + PACKETPP_IPPROTO_UDP, srcIP, dstIP); - PCPP_LOG_DEBUG("calculated IPv6 UDP checksum = 0xX" << std::uppercase << std::hex << checksumRes); + PCPP_LOG_DEBUG("calculated IPv6 UDP checksum = 0xX" << std::uppercase << std::hex << checksumRes); + } } - } - if (checksumRes == 0) - checksumRes = 0xffff; + if (checksumRes == 0) + checksumRes = 0xffff; - if(writeResultToPacket) - udpHdr->headerChecksum = htobe16(checksumRes); - else - udpHdr->headerChecksum = currChecksumValue; + if (writeResultToPacket) + udpHdr->headerChecksum = htobe16(checksumRes); + else + udpHdr->headerChecksum = currChecksumValue; - return checksumRes; -} + return checksumRes; + } -void UdpLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(udphdr)) - return; - - uint16_t portDst = getDstPort(); - uint16_t portSrc = getSrcPort(); - - uint8_t* udpData = m_Data + sizeof(udphdr); - size_t udpDataLen = m_DataLen - sizeof(udphdr); - - if ((portSrc == 68 && portDst == 67) || (portSrc == 67 && portDst == 68) || (portSrc == 67 && portDst == 67)) - m_NextLayer = new DhcpLayer(udpData, udpDataLen, this, m_Packet); - else if (VxlanLayer::isVxlanPort(portDst)) - m_NextLayer = new VxlanLayer(udpData, udpDataLen, this, m_Packet); - else if (DnsLayer::isDataValid(udpData, udpDataLen) && (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) - m_NextLayer = new DnsLayer(udpData, udpDataLen, this, m_Packet); - else if(SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) + void UdpLayer::parseNextLayer() { - if (SipRequestFirstLine::parseMethod((char*)udpData, udpDataLen) != SipRequestLayer::SipMethodUnknown) - m_NextLayer = new SipRequestLayer(udpData, udpDataLen, this, m_Packet); - else if (SipResponseFirstLine::parseStatusCode((char*)udpData, udpDataLen) != SipResponseLayer::SipStatusCodeUnknown - && SipResponseFirstLine::parseVersion((char*)udpData, udpDataLen) != "") - m_NextLayer = new SipResponseLayer(udpData, udpDataLen, this, m_Packet); + if (m_DataLen <= sizeof(udphdr)) + return; + + uint16_t portDst = getDstPort(); + uint16_t portSrc = getSrcPort(); + + uint8_t* udpData = m_Data + sizeof(udphdr); + size_t udpDataLen = m_DataLen - sizeof(udphdr); + + if ((portSrc == 68 && portDst == 67) || (portSrc == 67 && portDst == 68) || (portSrc == 67 && portDst == 67)) + m_NextLayer = new DhcpLayer(udpData, udpDataLen, this, m_Packet); + else if (VxlanLayer::isVxlanPort(portDst)) + m_NextLayer = new VxlanLayer(udpData, udpDataLen, this, m_Packet); + else if (DnsLayer::isDataValid(udpData, udpDataLen) && + (DnsLayer::isDnsPort(portDst) || DnsLayer::isDnsPort(portSrc))) + m_NextLayer = new DnsLayer(udpData, udpDataLen, this, m_Packet); + else if (SipLayer::isSipPort(portDst) || SipLayer::isSipPort(portSrc)) + { + if (SipRequestFirstLine::parseMethod((char*)udpData, udpDataLen) != SipRequestLayer::SipMethodUnknown) + m_NextLayer = new SipRequestLayer(udpData, udpDataLen, this, m_Packet); + else if (SipResponseFirstLine::parseStatusCode((char*)udpData, udpDataLen) != + SipResponseLayer::SipStatusCodeUnknown && + SipResponseFirstLine::parseVersion((char*)udpData, udpDataLen) != "") + m_NextLayer = new SipResponseLayer(udpData, udpDataLen, this, m_Packet); + else + m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, m_Packet); + } + else if ((RadiusLayer::isRadiusPort(portDst) || RadiusLayer::isRadiusPort(portSrc)) && + RadiusLayer::isDataValid(udpData, udpDataLen)) + m_NextLayer = new RadiusLayer(udpData, udpDataLen, this, m_Packet); + else if ((GtpV1Layer::isGTPv1Port(portDst) || GtpV1Layer::isGTPv1Port(portSrc)) && + GtpV1Layer::isGTPv1(udpData, udpDataLen)) + m_NextLayer = new GtpV1Layer(udpData, udpDataLen, this, m_Packet); + else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && + (DhcpV6Layer::isDataValid(udpData, udpDataLen))) + m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); + else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && + NtpLayer::isDataValid(udpData, udpDataLen)) + m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); + else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) + m_NextLayer = SomeIpLayer::parseSomeIpLayer(udpData, udpDataLen, this, m_Packet); + else if ((WakeOnLanLayer::isWakeOnLanPort(portDst) && WakeOnLanLayer::isDataValid(udpData, udpDataLen))) + m_NextLayer = new WakeOnLanLayer(udpData, udpDataLen, this, m_Packet); else m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, m_Packet); } - else if ((RadiusLayer::isRadiusPort(portDst) || RadiusLayer::isRadiusPort(portSrc)) && RadiusLayer::isDataValid(udpData, udpDataLen)) - m_NextLayer = new RadiusLayer(udpData, udpDataLen, this, m_Packet); - else if ((GtpV1Layer::isGTPv1Port(portDst) || GtpV1Layer::isGTPv1Port(portSrc)) && GtpV1Layer::isGTPv1(udpData, udpDataLen)) - m_NextLayer = new GtpV1Layer(udpData, udpDataLen, this, m_Packet); - else if ((DhcpV6Layer::isDhcpV6Port(portSrc) || DhcpV6Layer::isDhcpV6Port(portDst)) && (DhcpV6Layer::isDataValid(udpData, udpDataLen))) - m_NextLayer = new DhcpV6Layer(udpData, udpDataLen, this, m_Packet); - else if ((NtpLayer::isNTPPort(portSrc) || NtpLayer::isNTPPort(portDst)) && NtpLayer::isDataValid(udpData, udpDataLen)) - m_NextLayer = new NtpLayer(udpData, udpDataLen, this, m_Packet); - else if (SomeIpLayer::isSomeIpPort(portSrc) || SomeIpLayer::isSomeIpPort(portDst)) - m_NextLayer = SomeIpLayer::parseSomeIpLayer(udpData, udpDataLen, this, m_Packet); - else if ((WakeOnLanLayer::isWakeOnLanPort(portDst) && WakeOnLanLayer::isDataValid(udpData, udpDataLen))) - m_NextLayer = new WakeOnLanLayer(udpData, udpDataLen, this, m_Packet); - else - m_NextLayer = new PayloadLayer(udpData, udpDataLen, this, m_Packet); -} - -void UdpLayer::computeCalculateFields() -{ - udphdr* udpHdr = (udphdr*)m_Data; - udpHdr->length = htobe16(m_DataLen); - calculateChecksum(true); -} -std::string UdpLayer::toString() const -{ - std::ostringstream srcPortStream; - srcPortStream << getSrcPort(); - std::ostringstream dstPortStream; - dstPortStream << getDstPort(); + void UdpLayer::computeCalculateFields() + { + udphdr* udpHdr = (udphdr*)m_Data; + udpHdr->length = htobe16(m_DataLen); + calculateChecksum(true); + } - return "UDP Layer, Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); -} + std::string UdpLayer::toString() const + { + std::ostringstream srcPortStream; + srcPortStream << getSrcPort(); + std::ostringstream dstPortStream; + dstPortStream << getDstPort(); + + return "UDP Layer, Src port: " + srcPortStream.str() + ", Dst port: " + dstPortStream.str(); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/VlanLayer.cpp b/Packet++/src/VlanLayer.cpp index 0556e5fc89..fe72a1263e 100644 --- a/Packet++/src/VlanLayer.cpp +++ b/Packet++/src/VlanLayer.cpp @@ -15,133 +15,134 @@ namespace pcpp { -VlanLayer::VlanLayer(const uint16_t vlanID, bool cfi, uint8_t priority, uint16_t etherType) -{ - const size_t headerLen = sizeof(vlan_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = VLAN; - - vlan_header* vlanHeader = getVlanHeader(); - setVlanID(vlanID); - setCFI(cfi); - setPriority(priority); - vlanHeader->etherType = htobe16(etherType); -} - -uint16_t VlanLayer::getVlanID() const -{ - return be16toh(getVlanHeader()->vlan) & 0xFFF; -} - -uint8_t VlanLayer::getCFI() const -{ - return ((be16toh(getVlanHeader()->vlan) >> 12) & 1); -} - -uint8_t VlanLayer::getPriority() const -{ - return (be16toh(getVlanHeader()->vlan) >> 13) & 7; -} - -void VlanLayer::setVlanID(uint16_t id) -{ - getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~0xFFF)) | (id & 0xFFF)); -} + VlanLayer::VlanLayer(const uint16_t vlanID, bool cfi, uint8_t priority, uint16_t etherType) + { + const size_t headerLen = sizeof(vlan_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + m_Protocol = VLAN; + + vlan_header* vlanHeader = getVlanHeader(); + setVlanID(vlanID); + setCFI(cfi); + setPriority(priority); + vlanHeader->etherType = htobe16(etherType); + } -void VlanLayer::setCFI(bool cfi) -{ - getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~(1 << 12))) | ((cfi & 1) << 12)); -} + uint16_t VlanLayer::getVlanID() const + { + return be16toh(getVlanHeader()->vlan) & 0xFFF; + } -void VlanLayer::setPriority(uint8_t priority) -{ - getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~(7 << 13))) | ((priority & 7) << 13)); -} + uint8_t VlanLayer::getCFI() const + { + return ((be16toh(getVlanHeader()->vlan) >> 12) & 1); + } -void VlanLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(vlan_header)) - return; + uint8_t VlanLayer::getPriority() const + { + return (be16toh(getVlanHeader()->vlan) >> 13) & 7; + } - uint8_t* payload = m_Data + sizeof(vlan_header); - size_t payloadLen = m_DataLen - sizeof(vlan_header); + void VlanLayer::setVlanID(uint16_t id) + { + getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~0xFFF)) | (id & 0xFFF)); + } - vlan_header* hdr = getVlanHeader(); - switch (be16toh(hdr->etherType)) + void VlanLayer::setCFI(bool cfi) { - case PCPP_ETHERTYPE_IP: - m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_IPV6: - m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) - ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_ARP: - m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_VLAN: - case PCPP_ETHERTYPE_IEEE_802_1AD: - m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); - break; - case PCPP_ETHERTYPE_PPPOES: - m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_PPPOED: - m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) - ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); - break; - case PCPP_ETHERTYPE_MPLS: - m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); - break; - default: - m_NextLayer = (be16toh(hdr->etherType) < 1500 && LLCLayer::isDataValid(payload, payloadLen)) - ? static_cast(new LLCLayer(payload, payloadLen, this, m_Packet)) - : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~(1 << 12))) | ((cfi & 1) << 12)); } -} -void VlanLayer::computeCalculateFields() -{ - if (m_NextLayer == nullptr) - return; + void VlanLayer::setPriority(uint8_t priority) + { + getVlanHeader()->vlan = htobe16((be16toh(getVlanHeader()->vlan) & (~(7 << 13))) | ((priority & 7) << 13)); + } - switch (m_NextLayer->getProtocol()) + void VlanLayer::parseNextLayer() { - case IPv4: - getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); - break; - case IPv6: - getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); - break; - case ARP: - getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); - break; - case VLAN: - getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); - break; - default: - return; + if (m_DataLen <= sizeof(vlan_header)) + return; + + uint8_t* payload = m_Data + sizeof(vlan_header); + size_t payloadLen = m_DataLen - sizeof(vlan_header); + + vlan_header* hdr = getVlanHeader(); + switch (be16toh(hdr->etherType)) + { + case PCPP_ETHERTYPE_IP: + m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv4Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_IPV6: + m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen) + ? static_cast(new IPv6Layer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_ARP: + m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_VLAN: + case PCPP_ETHERTYPE_IEEE_802_1AD: + m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet); + break; + case PCPP_ETHERTYPE_PPPOES: + m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoESessionLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_PPPOED: + m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen) + ? static_cast(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + break; + case PCPP_ETHERTYPE_MPLS: + m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet); + break; + default: + m_NextLayer = (be16toh(hdr->etherType) < 1500 && LLCLayer::isDataValid(payload, payloadLen)) + ? static_cast(new LLCLayer(payload, payloadLen, this, m_Packet)) + : static_cast(new PayloadLayer(payload, payloadLen, this, m_Packet)); + } } -} -std::string VlanLayer::toString() const -{ - std::ostringstream cfiStream; - cfiStream << (int)getCFI(); - std::ostringstream priStream; - priStream << (int)getPriority(); - std::ostringstream idStream; - idStream << getVlanID(); + void VlanLayer::computeCalculateFields() + { + if (m_NextLayer == nullptr) + return; + + switch (m_NextLayer->getProtocol()) + { + case IPv4: + getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_IP); + break; + case IPv6: + getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_IPV6); + break; + case ARP: + getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_ARP); + break; + case VLAN: + getVlanHeader()->etherType = htobe16(PCPP_ETHERTYPE_VLAN); + break; + default: + return; + } + } - return "VLAN Layer, Priority: " + priStream.str() + ", Vlan ID: " + idStream.str() + ", CFI: " + cfiStream.str(); -} + std::string VlanLayer::toString() const + { + std::ostringstream cfiStream; + cfiStream << (int)getCFI(); + std::ostringstream priStream; + priStream << (int)getPriority(); + std::ostringstream idStream; + idStream << getVlanID(); + + return "VLAN Layer, Priority: " + priStream.str() + ", Vlan ID: " + idStream.str() + + ", CFI: " + cfiStream.str(); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Packet++/src/VrrpLayer.cpp b/Packet++/src/VrrpLayer.cpp old mode 100755 new mode 100644 index ab0ac44b9e..ac3791ee2a --- a/Packet++/src/VrrpLayer.cpp +++ b/Packet++/src/VrrpLayer.cpp @@ -8,17 +8,18 @@ #include "PayloadLayer.h" #include "VrrpLayer.h" -namespace pcpp { +namespace pcpp +{ -#define VRRP_PRIO_STOP 0 /* priority to stop */ -#define VRRP_PRIO_DEF 100 /* default priority */ -#define VRRP_PRIO_OWNER 255 /* priority of the ip owner */ +#define VRRP_PRIO_STOP 0 /* priority to stop */ +#define VRRP_PRIO_DEF 100 /* default priority */ +#define VRRP_PRIO_OWNER 255 /* priority of the ip owner */ #define VRRP_PACKET_FIX_LEN 8 #define VRRP_PACKET_MAX_IP_ADDRESS_NUM 255 -#define VRRP_V2_VERSION 2 -#define VRRP_V3_VERSION 3 +#define VRRP_V2_VERSION 2 +#define VRRP_V3_VERSION 3 /************* * VrrpLayer @@ -45,23 +46,23 @@ namespace pcpp { setPriority(priority); } - ProtocolType VrrpLayer::getVersionFromData(uint8_t *data, size_t dataLen) + ProtocolType VrrpLayer::getVersionFromData(uint8_t* data, size_t dataLen) { if (!data || dataLen <= VRRP_PACKET_FIX_LEN) { return UnknownProtocol; } - auto *vrrpPacketCommon = (vrrp_header *) data; + auto* vrrpPacketCommon = (vrrp_header*)data; uint8_t version = vrrpPacketCommon->version; switch (version) { - case VRRP_V2_VERSION: - return VRRPv2; - case VRRP_V3_VERSION: - return VRRPv3; - default: - return UnknownProtocol; + case VRRP_V2_VERSION: + return VRRPv2; + case VRRP_V3_VERSION: + return VRRPv3; + default: + return UnknownProtocol; } } @@ -96,23 +97,25 @@ namespace pcpp { { switch (getVrrpHeader()->priority) { - case VRRP_PRIO_DEF: - return VrrpLayer::VrrpPriority::Default; + case VRRP_PRIO_DEF: + return VrrpLayer::VrrpPriority::Default; - case VRRP_PRIO_STOP: - return VrrpLayer::VrrpPriority::Stop; + case VRRP_PRIO_STOP: + return VrrpLayer::VrrpPriority::Stop; - case VRRP_PRIO_OWNER: - return VrrpLayer::VrrpPriority::Owner; + case VRRP_PRIO_OWNER: + return VrrpLayer::VrrpPriority::Owner; - default: - return VrrpLayer::VrrpPriority::Other; + default: + return VrrpLayer::VrrpPriority::Other; } } std::string VrrpLayer::toString() const { - return "VRRP v" + std::to_string(getVersion()) + " Layer, virtual router ID: " + std::to_string(getVirtualRouterID()) + ", IP address count: " + std::to_string(getIPAddressesCount()); + return "VRRP v" + std::to_string(getVersion()) + + " Layer, virtual router ID: " + std::to_string(getVirtualRouterID()) + + ", IP address count: " + std::to_string(getIPAddressesCount()); } uint8_t VrrpLayer::getVersion() const @@ -192,7 +195,7 @@ namespace pcpp { return (m_Data + VRRP_PACKET_FIX_LEN); } - uint8_t *VrrpLayer::getNextIPAddressPtr(uint8_t* ipAddressPtr) const + uint8_t* VrrpLayer::getNextIPAddressPtr(uint8_t* ipAddressPtr) const { if (ipAddressPtr == nullptr) { @@ -202,7 +205,7 @@ namespace pcpp { size_t ipAddressLen = getIPAddressLen(); // prev virtual IP address was the last virtual IP address - if (ipAddressPtr + ipAddressLen - m_Data >= (int) getHeaderLen()) + if (ipAddressPtr + ipAddressLen - m_Data >= (int)getHeaderLen()) { return nullptr; } @@ -210,15 +213,15 @@ namespace pcpp { return (ipAddressPtr + ipAddressLen); } - bool VrrpLayer::addIPAddressesAt(const std::vector &ipAddresses, int offset) + bool VrrpLayer::addIPAddressesAt(const std::vector& ipAddresses, int offset) { - if (offset > (int) getHeaderLen()) + if (offset > (int)getHeaderLen()) { PCPP_LOG_ERROR("Cannot add virtual IP address offset(" << offset << ") is out of layer bounds"); return false; } - for (auto ipAddress: ipAddresses) + for (auto ipAddress : ipAddresses) { if (!isIPAddressValid(ipAddress)) { @@ -247,8 +250,8 @@ namespace pcpp { } size_t ipAddrOffset = 0; - uint8_t *newIpAddresses = getData() + offset; - for (auto ipAddress: ipAddresses) + uint8_t* newIpAddresses = getData() + offset; + for (auto ipAddress : ipAddresses) { copyIPAddressToData(newIpAddresses + ipAddrOffset, ipAddress); ipAddrOffset += ipAddrLen; @@ -259,22 +262,22 @@ namespace pcpp { return true; } - bool VrrpLayer::addIPAddresses(const std::vector &ipAddresses) + bool VrrpLayer::addIPAddresses(const std::vector& ipAddresses) { - return addIPAddressesAt(ipAddresses, (int) getHeaderLen()); + return addIPAddressesAt(ipAddresses, (int)getHeaderLen()); } - bool VrrpLayer::addIPAddress(const IPAddress &ipAddress) + bool VrrpLayer::addIPAddress(const IPAddress& ipAddress) { std::vector ipAddresses; ipAddresses.push_back(ipAddress); - return addIPAddressesAt(ipAddresses, (int) getHeaderLen()); + return addIPAddressesAt(ipAddresses, (int)getHeaderLen()); } bool VrrpLayer::removeIPAddressAtIndex(int index) { - int ipAddressCount = (int) getIPAddressesCount(); + int ipAddressCount = (int)getIPAddressesCount(); if (index < 0 || index >= ipAddressCount) { @@ -291,7 +294,7 @@ namespace pcpp { if (curIpAddressPtr == nullptr) { PCPP_LOG_ERROR("Cannot remove virtual IP address at index " - << index << ", cannot find virtual IP address at index " << i); + << index << ", cannot find virtual IP address at index " << i); return false; } @@ -299,7 +302,7 @@ namespace pcpp { curIpAddressPtr = getNextIPAddressPtr(curIpAddressPtr); } - if (!shortenLayer((int) offset, ipAddressLen)) + if (!shortenLayer((int)offset, ipAddressLen)) { PCPP_LOG_ERROR("Cannot remove virtual IP address at index " << index << ", cannot shorted layer"); return false; @@ -330,7 +333,7 @@ namespace pcpp { return true; } - void VrrpLayer::copyIPAddressToData(uint8_t *data, const IPAddress &ipAddress) const + void VrrpLayer::copyIPAddressToData(uint8_t* data, const IPAddress& ipAddress) const { size_t ipAddressLen = getIPAddressLen(); @@ -344,17 +347,17 @@ namespace pcpp { } } - IPAddress VrrpLayer::getIPAddressFromData(uint8_t *data) const + IPAddress VrrpLayer::getIPAddressFromData(uint8_t* data) const { if (getAddressType() == IPAddress::IPv4AddressType) { - return IPv4Address(*((uint32_t *) data)); + return IPv4Address(*((uint32_t*)data)); } return IPv6Address(data); } - bool VrrpLayer::isIPAddressValid(IPAddress &ipAddress) const + bool VrrpLayer::isIPAddressValid(IPAddress& ipAddress) const { if (ipAddress.isIPv6() && (getProtocol() != VRRPv3)) { @@ -384,7 +387,8 @@ namespace pcpp { * Vrrpv2Layer *************/ - VrrpV2Layer::VrrpV2Layer(uint8_t virtualRouterId, uint8_t priority, uint8_t advInt, uint8_t authType) : VrrpLayer(VRRPv2, virtualRouterId, priority) + VrrpV2Layer::VrrpV2Layer(uint8_t virtualRouterId, uint8_t priority, uint8_t advInt, uint8_t authType) + : VrrpLayer(VRRPv2, virtualRouterId, priority) { setAdvInt(advInt); setAuthType(authType); @@ -404,26 +408,26 @@ namespace pcpp { uint8_t VrrpV2Layer::getAdvInt() const { uint16_t authAdvInt = getVrrpHeader()->authTypeAdvInt; - auto authAdvIntPtr = (vrrpv2_auth_adv *) (&authAdvInt); + auto authAdvIntPtr = (vrrpv2_auth_adv*)(&authAdvInt); return authAdvIntPtr->advInt; } void VrrpV2Layer::setAdvInt(uint8_t advInt) { - auto authAdvIntPtr = (vrrpv2_auth_adv *)&getVrrpHeader()->authTypeAdvInt; + auto authAdvIntPtr = (vrrpv2_auth_adv*)&getVrrpHeader()->authTypeAdvInt; authAdvIntPtr->advInt = advInt; } uint8_t VrrpV2Layer::getAuthType() const { uint16_t authAdvInt = getVrrpHeader()->authTypeAdvInt; - auto *authAdvIntPtr = (vrrpv2_auth_adv *) (&authAdvInt); + auto* authAdvIntPtr = (vrrpv2_auth_adv*)(&authAdvInt); return authAdvIntPtr->authType; } void VrrpV2Layer::setAuthType(uint8_t authType) { - auto authAdvIntPtr = (vrrpv2_auth_adv *)&getVrrpHeader()->authTypeAdvInt; + auto authAdvIntPtr = (vrrpv2_auth_adv*)&getVrrpHeader()->authTypeAdvInt; authAdvIntPtr->authType = authType; } @@ -436,7 +440,7 @@ namespace pcpp { auto vrrpHeader = getVrrpHeader(); ScalarBuffer buffer = {}; - buffer.buffer = (uint16_t *) vrrpHeader; + buffer.buffer = (uint16_t*)vrrpHeader; buffer.len = getHeaderLen(); uint16_t currChecksumValue = vrrpHeader->checksum; @@ -451,8 +455,9 @@ namespace pcpp { * Vrrpv3Layer *************/ - VrrpV3Layer::VrrpV3Layer(IPAddress::AddressType addressType, uint8_t virtualRouterId, uint8_t priority, uint16_t maxAdvInt) : VrrpLayer( - VRRPv3, virtualRouterId, priority) + VrrpV3Layer::VrrpV3Layer(IPAddress::AddressType addressType, uint8_t virtualRouterId, uint8_t priority, + uint16_t maxAdvInt) + : VrrpLayer(VRRPv3, virtualRouterId, priority) { setAddressType(addressType); setMaxAdvInt(maxAdvInt); @@ -461,7 +466,7 @@ namespace pcpp { uint16_t VrrpV3Layer::getMaxAdvInt() const { uint16_t authAdvInt = getVrrpHeader()->authTypeAdvInt; - auto rsvdAdv = (vrrpv3_rsvd_adv *) (&authAdvInt); + auto rsvdAdv = (vrrpv3_rsvd_adv*)(&authAdvInt); return be16toh(rsvdAdv->maxAdvInt); } @@ -471,16 +476,17 @@ namespace pcpp { { throw std::invalid_argument("maxAdvInt must not exceed 12 bits length"); } - auto rsvdAdv = (vrrpv3_rsvd_adv *)&getVrrpHeader()->authTypeAdvInt; + auto rsvdAdv = (vrrpv3_rsvd_adv*)&getVrrpHeader()->authTypeAdvInt; rsvdAdv->maxAdvInt = htobe16(maxAdvInt); } uint16_t VrrpV3Layer::calculateChecksum() const { - auto *ipLayer = m_Packet->getLayerOfType(); + 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; } @@ -493,17 +499,17 @@ namespace pcpp { uint16_t checksum; if (getAddressType() == IPAddress::IPv4AddressType) { - checksum = computePseudoHdrChecksum((uint8_t *) vrrpHeader, getDataLen(), IPAddress::IPv4AddressType, - PACKETPP_IPPROTO_VRRP, srcIPAddr, dstIPAddr); + checksum = computePseudoHdrChecksum((uint8_t*)vrrpHeader, getDataLen(), IPAddress::IPv4AddressType, + PACKETPP_IPPROTO_VRRP, srcIPAddr, dstIPAddr); } else { - checksum = computePseudoHdrChecksum((uint8_t *) vrrpHeader, getDataLen(), IPAddress::IPv6AddressType, - PACKETPP_IPPROTO_VRRP, srcIPAddr, dstIPAddr); + checksum = computePseudoHdrChecksum((uint8_t*)vrrpHeader, getDataLen(), IPAddress::IPv6AddressType, + PACKETPP_IPPROTO_VRRP, srcIPAddr, dstIPAddr); } vrrpHeader->checksum = currChecksumValue; return checksum; } -} +} // namespace pcpp diff --git a/Packet++/src/VxlanLayer.cpp b/Packet++/src/VxlanLayer.cpp index b0c89537e7..1ec5c806eb 100644 --- a/Packet++/src/VxlanLayer.cpp +++ b/Packet++/src/VxlanLayer.cpp @@ -6,53 +6,54 @@ namespace pcpp { -VxlanLayer::VxlanLayer(uint32_t vni, uint16_t groupPolicyID, bool setGbpFlag, bool setPolicyAppliedFlag, bool setDontLearnFlag) -{ - const size_t headerLen = sizeof(vxlan_header); - m_DataLen = headerLen; - m_Data = new uint8_t[headerLen]; - memset(m_Data, 0, headerLen); - m_Protocol = VXLAN; - - if (vni != 0) - setVNI(vni); - - vxlan_header* vxlanHeader = getVxlanHeader(); - - if (groupPolicyID != 0) - vxlanHeader->groupPolicyID = htobe16(groupPolicyID); - - vxlanHeader->vniPresentFlag = 1; - - if (setGbpFlag) - vxlanHeader->gbpFlag = 1; - if (setPolicyAppliedFlag) - vxlanHeader->policyAppliedFlag = 1; - if (setDontLearnFlag) - vxlanHeader->dontLearnFlag = 1; -} - -uint32_t VxlanLayer::getVNI() const -{ - return (be32toh(getVxlanHeader()->vni) >> 8); -} - -void VxlanLayer::setVNI(uint32_t vni) -{ - getVxlanHeader()->vni = htobe32(vni << 8); -} - -std::string VxlanLayer::toString() const -{ - return "VXLAN Layer"; -} - -void VxlanLayer::parseNextLayer() -{ - if (m_DataLen <= sizeof(vxlan_header)) - return; - - m_NextLayer = new EthLayer(m_Data + sizeof(vxlan_header), m_DataLen - sizeof(vxlan_header), this, m_Packet); -} - -} + VxlanLayer::VxlanLayer(uint32_t vni, uint16_t groupPolicyID, bool setGbpFlag, bool setPolicyAppliedFlag, + bool setDontLearnFlag) + { + const size_t headerLen = sizeof(vxlan_header); + m_DataLen = headerLen; + m_Data = new uint8_t[headerLen]; + memset(m_Data, 0, headerLen); + m_Protocol = VXLAN; + + if (vni != 0) + setVNI(vni); + + vxlan_header* vxlanHeader = getVxlanHeader(); + + if (groupPolicyID != 0) + vxlanHeader->groupPolicyID = htobe16(groupPolicyID); + + vxlanHeader->vniPresentFlag = 1; + + if (setGbpFlag) + vxlanHeader->gbpFlag = 1; + if (setPolicyAppliedFlag) + vxlanHeader->policyAppliedFlag = 1; + if (setDontLearnFlag) + vxlanHeader->dontLearnFlag = 1; + } + + uint32_t VxlanLayer::getVNI() const + { + return (be32toh(getVxlanHeader()->vni) >> 8); + } + + void VxlanLayer::setVNI(uint32_t vni) + { + getVxlanHeader()->vni = htobe32(vni << 8); + } + + std::string VxlanLayer::toString() const + { + return "VXLAN Layer"; + } + + void VxlanLayer::parseNextLayer() + { + if (m_DataLen <= sizeof(vxlan_header)) + return; + + m_NextLayer = new EthLayer(m_Data + sizeof(vxlan_header), m_DataLen - sizeof(vxlan_header), this, m_Packet); + } + +} // namespace pcpp diff --git a/Packet++/src/WakeOnLanLayer.cpp b/Packet++/src/WakeOnLanLayer.cpp index c5c6996551..1175375d5a 100644 --- a/Packet++/src/WakeOnLanLayer.cpp +++ b/Packet++/src/WakeOnLanLayer.cpp @@ -4,133 +4,132 @@ #include "GeneralUtils.h" #include "Logger.h" - namespace pcpp { -void WakeOnLanLayer::init(uint16_t len) -{ - m_Data = new uint8_t[len]; - m_DataLen = len; - m_Protocol = WakeOnLan; + void WakeOnLanLayer::init(uint16_t len) + { + m_Data = new uint8_t[len]; + m_DataLen = len; + m_Protocol = WakeOnLan; - memset(getWakeOnLanHeader()->sync, 0xFF, 6); -} + memset(getWakeOnLanHeader()->sync, 0xFF, 6); + } -WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress &targetAddr) -{ - init(sizeof(wol_header)); - setTargetAddr(targetAddr); -} + WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress& targetAddr) + { + init(sizeof(wol_header)); + setTargetAddr(targetAddr); + } -WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress &targetAddr, uint8_t *password, uint8_t len) -{ - init(sizeof(wol_header) + len); - setTargetAddr(targetAddr); - setPassword(password, len); -} + WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress& targetAddr, uint8_t* password, uint8_t len) + { + init(sizeof(wol_header) + len); + setTargetAddr(targetAddr); + setPassword(password, len); + } -WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress &targetAddr, const pcpp::MacAddress &password) -{ - init(sizeof(wol_header) + 6); - setTargetAddr(targetAddr); - setPassword(password); -} + WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress& targetAddr, const pcpp::MacAddress& password) + { + init(sizeof(wol_header) + 6); + setTargetAddr(targetAddr); + setPassword(password); + } -WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress &targetAddr, const IPv4Address &password) -{ - init(sizeof(wol_header) + 4); - setTargetAddr(targetAddr); - setPassword(password); -} + WakeOnLanLayer::WakeOnLanLayer(const pcpp::MacAddress& targetAddr, const IPv4Address& password) + { + init(sizeof(wol_header) + 4); + setTargetAddr(targetAddr); + setPassword(password); + } -pcpp::MacAddress WakeOnLanLayer::getTargetAddr() const -{ - return pcpp::MacAddress(getWakeOnLanHeader()->addrBody); -} + pcpp::MacAddress WakeOnLanLayer::getTargetAddr() const + { + return pcpp::MacAddress(getWakeOnLanHeader()->addrBody); + } -void WakeOnLanLayer::setTargetAddr(const pcpp::MacAddress &targetAddr) -{ - for (size_t idx = 0; idx < 16; ++idx) - memcpy(&(getWakeOnLanHeader()->addrBody[idx * 6]), targetAddr.getRawData(), 6); -} + void WakeOnLanLayer::setTargetAddr(const pcpp::MacAddress& targetAddr) + { + for (size_t idx = 0; idx < 16; ++idx) + memcpy(&(getWakeOnLanHeader()->addrBody[idx * 6]), targetAddr.getRawData(), 6); + } -std::string WakeOnLanLayer::getPassword() const -{ - size_t passSize = m_DataLen - sizeof(wol_header); - switch (passSize) + std::string WakeOnLanLayer::getPassword() const { - case 0: - return std::string(); - case 4: - return IPv4Address(&m_Data[sizeof(wol_header)]).toString(); - case 6: - return MacAddress(&m_Data[sizeof(wol_header)]).toString(); - default: - return byteArrayToHexString(&m_Data[sizeof(wol_header)], passSize); + size_t passSize = m_DataLen - sizeof(wol_header); + switch (passSize) + { + case 0: + return std::string(); + case 4: + return IPv4Address(&m_Data[sizeof(wol_header)]).toString(); + case 6: + return MacAddress(&m_Data[sizeof(wol_header)]).toString(); + default: + return byteArrayToHexString(&m_Data[sizeof(wol_header)], passSize); + } } -} -bool WakeOnLanLayer::setPassword(const uint8_t *password, uint8_t len) -{ - if (len) + bool WakeOnLanLayer::setPassword(const uint8_t* password, uint8_t len) { - if (m_DataLen > sizeof(wol_header) + len) + if (len) { - if (!shortenLayer(sizeof(wol_header), m_DataLen - (sizeof(wol_header) + len))) + if (m_DataLen > sizeof(wol_header) + len) { - PCPP_LOG_ERROR("Can't shorten Wake on LAN layer"); - return false; + if (!shortenLayer(sizeof(wol_header), m_DataLen - (sizeof(wol_header) + len))) + { + PCPP_LOG_ERROR("Can't shorten Wake on LAN layer"); + return false; + } } - } - else if (m_DataLen < sizeof(wol_header) + len) - { - if (!extendLayer(m_DataLen, (sizeof(wol_header) + len) - m_DataLen)) + else if (m_DataLen < sizeof(wol_header) + len) { - PCPP_LOG_ERROR("Can't extend Wake on LAN layer"); - return false; + if (!extendLayer(m_DataLen, (sizeof(wol_header) + len) - m_DataLen)) + { + PCPP_LOG_ERROR("Can't extend Wake on LAN layer"); + return false; + } } + memcpy(&m_Data[sizeof(wol_header)], password, len); } - memcpy(&m_Data[sizeof(wol_header)], password, len); - } - return true; -} + return true; + } -bool WakeOnLanLayer::setPassword(const std::string &password) -{ - return setPassword(reinterpret_cast(password.c_str()), password.size()); -} + bool WakeOnLanLayer::setPassword(const std::string& password) + { + return setPassword(reinterpret_cast(password.c_str()), password.size()); + } -bool WakeOnLanLayer::setPassword(const MacAddress &addr) -{ - return setPassword(addr.getRawData(), 6); -} + bool WakeOnLanLayer::setPassword(const MacAddress& addr) + { + return setPassword(addr.getRawData(), 6); + } -bool WakeOnLanLayer::setPassword(const IPv4Address &addr) -{ - return setPassword(addr.toBytes(), 4); -} + bool WakeOnLanLayer::setPassword(const IPv4Address& addr) + { + return setPassword(addr.toBytes(), 4); + } -bool WakeOnLanLayer::isDataValid(const uint8_t *data, size_t dataSize) -{ - if (data && dataSize >= sizeof(wol_header)) + bool WakeOnLanLayer::isDataValid(const uint8_t* data, size_t dataSize) { - // It should repeat same MAC address at the payload 16 times - pcpp::MacAddress bufAddr(&data[6]); - for (size_t idx = 1; idx < 16; ++idx) + if (data && dataSize >= sizeof(wol_header)) { - if (bufAddr != pcpp::MacAddress(&data[6 + idx * 6])) - return false; + // It should repeat same MAC address at the payload 16 times + pcpp::MacAddress bufAddr(&data[6]); + for (size_t idx = 1; idx < 16; ++idx) + { + if (bufAddr != pcpp::MacAddress(&data[6 + idx * 6])) + return false; + } + return true; } - return true; + return false; } - return false; -} -std::string WakeOnLanLayer::toString() const -{ - return "Wake On LAN Layer, target address: " + getTargetAddr().toString(); -} + std::string WakeOnLanLayer::toString() const + { + return "Wake On LAN Layer, target address: " + getTargetAddr().toString(); + } -} // namespace pcpp +} // namespace pcpp From 0a843116d6f679f6dcc9f9c3c002ca94b32c227f Mon Sep 17 00:00:00 2001 From: "Liu, An-Chi" Date: Thu, 8 Aug 2024 15:25:28 +0900 Subject: [PATCH 28/35] support RawSocketDevice with timeout in millisecond precision. (#1529) * support RawSocketDevice with timeout in millisecond precision. * support RawSocketDevice with timeout in millisecond precision * use steady_clock --- Pcap++/header/RawSocketDevice.h | 10 ++++++---- Pcap++/src/RawSocketDevice.cpp | 31 +++++++++++++++++++------------ 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Pcap++/header/RawSocketDevice.h b/Pcap++/header/RawSocketDevice.h index ceb863d91c..d0aba6ba09 100644 --- a/Pcap++/header/RawSocketDevice.h +++ b/Pcap++/header/RawSocketDevice.h @@ -86,7 +86,8 @@ namespace pcpp * @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 + * 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 @@ -94,18 +95,19 @@ namespace pcpp * - 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, int timeout = -1); + 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 + * @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, int timeout, int& failedRecv); + 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. diff --git a/Pcap++/src/RawSocketDevice.cpp b/Pcap++/src/RawSocketDevice.cpp index 4b68849d37..c4651439af 100644 --- a/Pcap++/src/RawSocketDevice.cpp +++ b/Pcap++/src/RawSocketDevice.cpp @@ -1,5 +1,6 @@ #include "RawSocketDevice.h" #include "EndianPortable.h" +#include #ifdef __linux__ #include #include @@ -95,7 +96,7 @@ RawSocketDevice::~RawSocketDevice() close(); } -RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawPacket, bool blocking, int timeout) +RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawPacket, bool blocking, double timeout) { #if defined(_WIN32) @@ -116,7 +117,7 @@ RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawP u_long blockingMode = (blocking? 0 : 1); ioctlsocket(fd, FIONBIO, &blockingMode); - DWORD timeoutVal = timeout * 1000; + DWORD timeoutVal = timeout * 1000; // convert to milliseconds setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal)); //recvfrom(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0, (struct sockaddr*)&sockAddr,(socklen_t*)&sockAddrLen); @@ -179,8 +180,8 @@ RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawP // set timeout on socket struct timeval timeoutVal; - timeoutVal.tv_sec = timeout; - timeoutVal.tv_usec = 0; + timeoutVal.tv_sec = static_cast(timeout); + timeoutVal.tv_usec = static_cast((timeout - timeoutVal.tv_sec) * 1000000); setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal)); int bufferLen = recv(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0); @@ -216,7 +217,7 @@ RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawP #endif } -int RawSocketDevice::receivePackets(RawPacketVector& packetVec, int timeout, int& failedRecv) +int RawSocketDevice::receivePackets(RawPacketVector& packetVec, double timeout, int& failedRecv) { if (!isOpened()) { @@ -224,18 +225,26 @@ int RawSocketDevice::receivePackets(RawPacketVector& packetVec, int timeout, int return 0; } - long curSec, curNsec; - clockGetTime(curSec, curNsec); + int64_t timeoutMilli = timeout * 1000; int packetCount = 0; failedRecv = 0; - long timeoutSec = curSec + timeout; + auto start = std::chrono::steady_clock::now(); - while (curSec < timeoutSec) + while (true) { + auto now = std::chrono::steady_clock::now(); + auto elapsedMilli = std::chrono::duration_cast(now - start).count(); + double elapsedSec = static_cast(elapsedMilli) / 1000; + + if (elapsedMilli >= timeoutMilli) + { + break; + } + RawPacket* rawPacket = new RawPacket(); - if (receivePacket(*rawPacket, true, timeoutSec-curSec) == RecvSuccess) + if (receivePacket(*rawPacket, true, elapsedSec) == RecvSuccess) { packetVec.pushBack(rawPacket); packetCount++; @@ -245,8 +254,6 @@ int RawSocketDevice::receivePackets(RawPacketVector& packetVec, int timeout, int failedRecv++; delete rawPacket; } - - clockGetTime(curSec, curNsec); } return packetCount; From 39913f1ed80d8f13c2a4f88c2c1c64ab467de3dc Mon Sep 17 00:00:00 2001 From: Serdar Sanli Date: Mon, 12 Aug 2024 03:11:15 +0100 Subject: [PATCH 29/35] Fix precision issue on pcapng reader (#1514) --- .../LightPcapNg/include/light_pcapng_ext.h | 2 +- .../LightPcapNg/src/light_pcapng_ext.c | 29 ++++++++++--------- Tests/Pcap++Test/Common/PcapFileNamesDef.h | 1 + Tests/Pcap++Test/TestDefinition.h | 1 + Tests/Pcap++Test/Tests/FileTests.cpp | 21 ++++++++++++++ Tests/Pcap++Test/main.cpp | 1 + 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/3rdParty/LightPcapNg/LightPcapNg/include/light_pcapng_ext.h b/3rdParty/LightPcapNg/LightPcapNg/include/light_pcapng_ext.h index 6d8b2b1fa6..624d937411 100644 --- a/3rdParty/LightPcapNg/LightPcapNg/include/light_pcapng_ext.h +++ b/3rdParty/LightPcapNg/LightPcapNg/include/light_pcapng_ext.h @@ -71,7 +71,7 @@ typedef struct _light_pcapng_file_info { size_t user_app_desc_size; size_t interface_block_count; uint16_t link_types[MAX_SUPPORTED_INTERFACE_BLOCKS]; - double timestamp_resolution[MAX_SUPPORTED_INTERFACE_BLOCKS]; + uint64_t timestamp_ticks_per_second[MAX_SUPPORTED_INTERFACE_BLOCKS]; // PCPP patch } light_pcapng_file_info; diff --git a/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c b/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c index add45a468f..c7d6df30c3 100644 --- a/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c +++ b/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c @@ -123,24 +123,25 @@ static light_pcapng_file_info *__create_file_info(light_pcapng pcapng_head) return file_info; } -static double __power_of(int x, int y) +// PCPP patch +static uint64_t int_pow(uint64_t x, uint8_t y) { int i; - double res = 1; - - if (y < 0) - return 1 / __power_of(x, -y); + uint64_t res = 1; for (i = 0; i < y; i++) res *= x; return res; } +// PCPP patch end +// PCPP patch static void __append_interface_block_to_file_info(const light_pcapng interface_block, light_pcapng_file_info* info) { struct _light_interface_description_block* interface_desc_block; light_option ts_resolution_option = NULL; + uint32_t ticks_per_sec; if (info->interface_block_count >= MAX_SUPPORTED_INTERFACE_BLOCKS) return; @@ -150,19 +151,21 @@ static void __append_interface_block_to_file_info(const light_pcapng interface_b ts_resolution_option = light_get_option(interface_block, LIGHT_OPTION_IF_TSRESOL); if (ts_resolution_option == NULL) { - info->timestamp_resolution[info->interface_block_count] = __power_of(10,-6); + ticks_per_sec = int_pow(10, 6); } else { uint8_t* raw_ts_data = (uint8_t*)light_get_option_data(ts_resolution_option); if (*raw_ts_data < 128) - info->timestamp_resolution[info->interface_block_count] = __power_of(10, (-1)*(*raw_ts_data)); + ticks_per_sec = int_pow(10, (*raw_ts_data)); else - info->timestamp_resolution[info->interface_block_count] = __power_of(2, (-1)*((*raw_ts_data)-128)); + ticks_per_sec = int_pow(2, ((*raw_ts_data)-128)); } + info->timestamp_ticks_per_second[info->interface_block_count] = ticks_per_sec; info->link_types[info->interface_block_count++] = interface_desc_block->link_type; } +// PCPP patch end static light_boolean __is_open_for_write(const struct _light_pcapng_t* pcapng) { @@ -418,15 +421,13 @@ int light_get_next_packet(light_pcapng_t *pcapng, light_packet_header *packet_he uint64_t timestamp = epb->timestamp_high; timestamp = timestamp << 32; timestamp += epb->timestamp_low; - double timestamp_res = pcapng->file_info->timestamp_resolution[epb->interface_id]; - uint64_t packet_secs = timestamp * timestamp_res; + uint64_t ticks_per_sec = pcapng->file_info->timestamp_ticks_per_second[epb->interface_id]; + uint64_t packet_secs = timestamp / ticks_per_sec; + uint64_t ticks = timestamp % ticks_per_sec; if (packet_secs <= MAXIMUM_PACKET_SECONDS_VALUE) { packet_header->timestamp.tv_sec = packet_secs; - packet_header->timestamp.tv_nsec = - (timestamp - (packet_secs / timestamp_res)) // number of time units less than seconds - * timestamp_res // shift . to the left to get 0.{previous_number} - * 1000000000; // get the nanoseconds + packet_header->timestamp.tv_nsec = (1000000000ul * ticks) / ticks_per_sec; } else { diff --git a/Tests/Pcap++Test/Common/PcapFileNamesDef.h b/Tests/Pcap++Test/Common/PcapFileNamesDef.h index 8dfd584c73..d39c35c38d 100644 --- a/Tests/Pcap++Test/Common/PcapFileNamesDef.h +++ b/Tests/Pcap++Test/Common/PcapFileNamesDef.h @@ -31,3 +31,4 @@ #define SLL2_PCAP_WRITE_PATH "PcapExamples/sll2_copy.pcap" #define EXAMPLE_PCAP_MICRO_PATH "PcapExamples/microsecs.pcap" #define EXAMPLE_PCAP_NANO_PATH "PcapExamples/nanosecs.pcap" +#define EXAMPLE_PCAPNG_NANO_PATH "PcapExamples/nanosecs.pcapng" diff --git a/Tests/Pcap++Test/TestDefinition.h b/Tests/Pcap++Test/TestDefinition.h index 29dbb1298f..2ed9ac12b5 100644 --- a/Tests/Pcap++Test/TestDefinition.h +++ b/Tests/Pcap++Test/TestDefinition.h @@ -29,6 +29,7 @@ PTF_TEST_CASE(TestPcapNgFileTooManyInterfaces); PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv6); PTF_TEST_CASE(TestPcapFileReadLinkTypeIPv4); PTF_TEST_CASE(TestSolarisSnoopFileRead); +PTF_TEST_CASE(TestPcapNgFilePrecision); // Implemented in LiveDeviceTests.cpp PTF_TEST_CASE(TestPcapLiveDeviceList); diff --git a/Tests/Pcap++Test/Tests/FileTests.cpp b/Tests/Pcap++Test/Tests/FileTests.cpp index 9403b73b1b..cf715e1f7c 100644 --- a/Tests/Pcap++Test/Tests/FileTests.cpp +++ b/Tests/Pcap++Test/Tests/FileTests.cpp @@ -180,6 +180,27 @@ PTF_TEST_CASE(TestPcapFilePrecision) readerDevMicro.close(); } // TestPcapFilePrecision +PTF_TEST_CASE(TestPcapNgFilePrecision) +{ + std::array testPayload = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + pcpp::RawPacket rawPacketNano(testPayload.data(), testPayload.size(), timespec({ 1722196160, 123456789 }), + false); // 1722196160.123456789 + + pcpp::PcapNgFileWriterDevice writerDev(EXAMPLE_PCAPNG_NANO_PATH); + PTF_ASSERT_TRUE(writerDev.open()); + PTF_ASSERT_TRUE(writerDev.writePacket(rawPacketNano)); + writerDev.close(); + + pcpp::PcapNgFileReaderDevice readerDev(EXAMPLE_PCAPNG_NANO_PATH); + PTF_ASSERT_TRUE(readerDev.open()); + pcpp::RawPacket readPacket; + PTF_ASSERT_TRUE(readerDev.getNextPacket(readPacket)); + PTF_ASSERT_EQUAL(readPacket.getPacketTimeStamp().tv_sec, 1722196160); + PTF_ASSERT_EQUAL(readPacket.getPacketTimeStamp().tv_nsec, 123456789); + readerDev.close(); +} // TestPcapNgFilePrecision + PTF_TEST_CASE(TestPcapSllFileReadWrite) { pcpp::PcapFileReaderDevice readerDev(SLL_PCAP_PATH); diff --git a/Tests/Pcap++Test/main.cpp b/Tests/Pcap++Test/main.cpp index ec159a31e2..3e6479110f 100644 --- a/Tests/Pcap++Test/main.cpp +++ b/Tests/Pcap++Test/main.cpp @@ -223,6 +223,7 @@ int main(int argc, char* argv[]) PTF_RUN_TEST(TestPcapNgFileReadWrite, "no_network;pcap;pcapng"); PTF_RUN_TEST(TestPcapNgFileReadWriteAdv, "no_network;pcap;pcapng"); PTF_RUN_TEST(TestPcapNgFileTooManyInterfaces, "no_network;pcap;pcapng"); + PTF_RUN_TEST(TestPcapNgFilePrecision, "no_network;pcapng"); PTF_RUN_TEST(TestPcapFileReadLinkTypeIPv6, "no_network;pcap"); PTF_RUN_TEST(TestPcapFileReadLinkTypeIPv4, "no_network;pcap"); PTF_RUN_TEST(TestSolarisSnoopFileRead, "no_network;pcap;snoop"); From 650e6da6b7f86bd7704bf4f3eb163160c19f33df Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Mon, 12 Aug 2024 06:02:26 +0300 Subject: [PATCH 30/35] Broke up PcapLiveDeviceList initialization into steps. (#1515) * Broke up PcapLiveDeviceList initialization into steps. * Fixed fetchDnsServers returns. * Lint --- Pcap++/header/PcapLiveDeviceList.h | 6 +-- Pcap++/src/PcapLiveDeviceList.cpp | 60 +++++++++++++++++------------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/Pcap++/header/PcapLiveDeviceList.h b/Pcap++/header/PcapLiveDeviceList.h index 7a93fe9d74..6fc976889a 100644 --- a/Pcap++/header/PcapLiveDeviceList.h +++ b/Pcap++/header/PcapLiveDeviceList.h @@ -33,11 +33,9 @@ namespace pcpp // private c'tor PcapLiveDeviceList(); - void init(); + static std::vector> fetchAllLocalDevices(); + static std::vector fetchDnsServers(); - void setDnsServers(); - - void updateLiveDeviceListView() const; public: PcapLiveDeviceList(const PcapLiveDeviceList&) = delete; PcapLiveDeviceList(PcapLiveDeviceList&&) noexcept = delete; diff --git a/Pcap++/src/PcapLiveDeviceList.cpp b/Pcap++/src/PcapLiveDeviceList.cpp index 5d0650d731..8763d536a1 100644 --- a/Pcap++/src/PcapLiveDeviceList.cpp +++ b/Pcap++/src/PcapLiveDeviceList.cpp @@ -26,14 +26,25 @@ namespace pcpp { + namespace + { + void syncPointerVectors(std::vector> const& mainVector, std::vector& viewVector) + { + viewVector.resize(mainVector.size()); + // Full update of all elements of the view vector to synchronize them with the main vector. + std::transform(mainVector.begin(), mainVector.end(), viewVector.begin(), + [](const std::unique_ptr& ptr) { return ptr.get(); }); + } + } -PcapLiveDeviceList::PcapLiveDeviceList() +PcapLiveDeviceList::PcapLiveDeviceList() : m_LiveDeviceList(fetchAllLocalDevices()), m_DnsServers(fetchDnsServers()) { - init(); + syncPointerVectors(m_LiveDeviceList, m_LiveDeviceListView); } -void PcapLiveDeviceList::init() +std::vector> PcapLiveDeviceList::fetchAllLocalDevices() { + std::vector> deviceList; std::unique_ptr interfaceList; try { @@ -54,19 +65,14 @@ void PcapLiveDeviceList::init() #else //__linux__, __APPLE__, __FreeBSD__ auto dev = std::unique_ptr(new PcapLiveDevice(currInterface, true, true, true)); #endif - m_LiveDeviceList.push_back(std::move(dev)); + deviceList.push_back(std::move(dev)); } - - m_LiveDeviceListView.resize(m_LiveDeviceList.size()); - // Full update of all elements of the view vector to synchronize them with the main vector. - std::transform(m_LiveDeviceList.begin(), m_LiveDeviceList.end(), m_LiveDeviceListView.begin(), - [](const std::unique_ptr& ptr) { return ptr.get(); }); - - setDnsServers(); + return deviceList; } -void PcapLiveDeviceList::setDnsServers() +std::vector PcapLiveDeviceList::fetchDnsServers() { + std::vector dnsServers; #if defined(_WIN32) FIXED_INFO* fixedInfo; ULONG ulOutBufLen; @@ -96,7 +102,7 @@ void PcapLiveDeviceList::setDnsServers() int dnsServerCounter = 0; try { - m_DnsServers.push_back(IPv4Address(fixedInfo->DnsServerList.IpAddress.String)); + dnsServers.push_back(IPv4Address(fixedInfo->DnsServerList.IpAddress.String)); PCPP_LOG_DEBUG("Default DNS server IP #" << dnsServerCounter++ << ": " << fixedInfo->DnsServerList.IpAddress.String); } catch(const std::exception&) @@ -109,7 +115,7 @@ void PcapLiveDeviceList::setDnsServers() { try { - m_DnsServers.push_back(IPv4Address(pIPAddr->IpAddress.String)); + dnsServers.push_back(IPv4Address(pIPAddr->IpAddress.String)); PCPP_LOG_DEBUG("Default DNS server IP #" << dnsServerCounter++ << ": " << pIPAddr->IpAddress.String); } catch(const std::exception&) @@ -126,7 +132,7 @@ void PcapLiveDeviceList::setDnsServers() if (nmcliExists != "") { PCPP_LOG_DEBUG("Error retrieving DNS server list: nmcli doesn't exist"); - return; + return {}; } // check nmcli major version (0 or 1) @@ -145,7 +151,7 @@ void PcapLiveDeviceList::setDnsServers() if (dnsServersInfo == "") { PCPP_LOG_DEBUG("Error retrieving DNS server list: call to nmcli gave no output"); - return; + return {}; } std::istringstream stream(dnsServersInfo); @@ -169,9 +175,9 @@ void PcapLiveDeviceList::setDnsServers() continue; } - if (std::find(m_DnsServers.begin(), m_DnsServers.end(), dnsIPAddr) == m_DnsServers.end()) + if (std::find(dnsServers.begin(), dnsServers.end(), dnsIPAddr) == dnsServers.end()) { - m_DnsServers.push_back(dnsIPAddr); + dnsServers.push_back(dnsIPAddr); PCPP_LOG_DEBUG("Default DNS server IP #" << i++ << ": " << dnsIPAddr); } } @@ -181,7 +187,7 @@ void PcapLiveDeviceList::setDnsServers() if (dynRef == nullptr) { PCPP_LOG_DEBUG("Couldn't set DNS server list: failed to retrieve SCDynamicStore"); - return; + return {}; } CFDictionaryRef dnsDict = (CFDictionaryRef)SCDynamicStoreCopyValue(dynRef,CFSTR("State:/Network/Global/DNS")); @@ -190,7 +196,7 @@ void PcapLiveDeviceList::setDnsServers() { PCPP_LOG_DEBUG("Couldn't set DNS server list: failed to get DNS dictionary"); CFRelease(dynRef); - return; + return {}; } CFArrayRef serverAddresses = (CFArrayRef)CFDictionaryGetValue(dnsDict, CFSTR("ServerAddresses")); @@ -200,7 +206,7 @@ void PcapLiveDeviceList::setDnsServers() PCPP_LOG_DEBUG("Couldn't set DNS server list: server addresses array is null"); CFRelease(dynRef); CFRelease(dnsDict); - return; + return {}; } CFIndex count = CFArrayGetCount(serverAddresses); @@ -216,7 +222,7 @@ void PcapLiveDeviceList::setDnsServers() CFStringGetCString(serverAddress, serverAddressCString, 20, kCFStringEncodingUTF8); try { - m_DnsServers.push_back(IPv4Address(serverAddressCString)); + dnsServers.push_back(IPv4Address(serverAddressCString)); PCPP_LOG_DEBUG("Default DNS server IP #" << (int)(i+1) << ": " << serverAddressCString); } catch(const std::exception& e) @@ -243,7 +249,7 @@ void PcapLiveDeviceList::setDnsServers() try { - m_DnsServers.push_back(IPv4Address(internal::in_addr2int(*inaddr))); + dnsServers.push_back(IPv4Address(internal::in_addr2int(*inaddr))); } catch(const std::exception& e) { @@ -252,6 +258,7 @@ void PcapLiveDeviceList::setDnsServers() } #endif + return dnsServers; } PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPAddress& ipAddr) const @@ -386,10 +393,11 @@ PcapLiveDeviceList* PcapLiveDeviceList::clone() void PcapLiveDeviceList::reset() { m_LiveDeviceListView.clear(); - m_LiveDeviceList.clear(); - m_DnsServers.clear(); - init(); + m_LiveDeviceList = fetchAllLocalDevices(); + m_DnsServers = fetchDnsServers(); + + syncPointerVectors(m_LiveDeviceList, m_LiveDeviceListView); } } // namespace pcpp From 83446075c03554434178c85a25e10720043942a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20=C3=87etin?= <64282645+egecetin@users.noreply.github.com> Date: Mon, 12 Aug 2024 07:39:18 +0300 Subject: [PATCH 31/35] Fix codecov reports (#1524) * Fix codecov reports * remove all gcno files to prevent caching * remove after restore * dir fixed? * maybe after configure * ccache configuration to fix * try to exclude gcda gcno * Bump action version * remove unneccesary flag --------- Co-authored-by: Liu, An-Chi --- .github/workflows/build_and_test.yml | 59 +++++++++++++++------------- codecov.yml | 6 +++ 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 1c501e9697..1a08fc9bce 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -95,7 +95,10 @@ jobs: id: ccache-restore uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: - path: ${{ env.CCACHE_DIR }} + path: | + ${{ env.CCACHE_DIR }} + !*.gcda + !*.gcno key: ${{ matrix.image }}-ccache-${{ github.run_id }} restore-keys: | ${{ matrix.image }}-ccache @@ -133,20 +136,20 @@ jobs: - name: Test Tutorials run: cd build_examples/tutorials_bin && ./Tutorial-HelloWorld - # - name: Create Cobertura Report - # run: | - # ${{ matrix.python }} -m pip install gcovr - # gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml - - # - name: Upload Coverage Results - # uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 - # with: - # files: ./coverage.xml - # flags: ${{ matrix.image }},unittest - # fail_ci_if_error: false - # verbose: true - # env: - # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Create Cobertura Report + run: | + ${{ matrix.python }} -m pip install gcovr + gcovr -v -r . ${{ matrix.additional-gcov-flags }} $GCOVR_FLAGS -o coverage.xml + + - name: Upload Coverage Results + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + with: + files: ./coverage.xml + flags: ${{ matrix.image }},unittest + fail_ci_if_error: false + verbose: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Save Ccache uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 @@ -378,16 +381,16 @@ jobs: python3 -m pip install gcovr gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - # - name: Upload Coverage Results - # uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 - # if: ${{ matrix.host-arch == matrix.arch }} - # with: - # files: ./coverage.xml - # flags: ${{ matrix.os-version }},unittest - # fail_ci_if_error: false - # verbose: true - # env: - # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: Upload Coverage Results + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + if: ${{ matrix.host-arch == matrix.arch }} + with: + files: ./coverage.xml + flags: ${{ matrix.os-version }},unittest + fail_ci_if_error: false + verbose: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Save Ccache uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 @@ -468,7 +471,7 @@ jobs: run: gcovr -v -g -k -r . $env:GCOVR_FLAGS.split() -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: ${{ matrix.sys }},unittest @@ -559,7 +562,7 @@ jobs: python -m pytest --root-path=../../Dist/examples_bin - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./Tests/Pcap++Test/Pcap++Coverage.xml,./Tests/Packet++Test/Packet++Coverage.xml flags: ${{ matrix.os }},unittest,${{ matrix.pcap_lib }} @@ -718,7 +721,7 @@ jobs: gcovr -v -r . $GCOVR_FLAGS -o coverage.xml - name: Upload Coverage Results - uses: codecov/codecov-action@ab904c41d6ece82784817410c45d8b8c02684457 # v3.1.6 + uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 with: files: ./coverage.xml flags: xdp,unittest diff --git a/codecov.yml b/codecov.yml index 5b852de37f..846afb7749 100644 --- a/codecov.yml +++ b/codecov.yml @@ -8,3 +8,9 @@ coverage: codecov: notify: after_n_builds: 16 + wait_for_ci: yes + +ignore: + - "3rdParty/*" + - "Tests/*" + - "Examples/*" From 0122abaa54212dd8a63633a86eab016b38ad261a Mon Sep 17 00:00:00 2001 From: seladb Date: Tue, 13 Aug 2024 23:06:10 -0700 Subject: [PATCH 32/35] Fix LightPcapNg timestamp calculation (#1535) * Support `ticks_per_sec` being zero * One more fix --- 3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c b/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c index c7d6df30c3..a773812763 100644 --- a/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c +++ b/3rdParty/LightPcapNg/LightPcapNg/src/light_pcapng_ext.c @@ -422,10 +422,10 @@ int light_get_next_packet(light_pcapng_t *pcapng, light_packet_header *packet_he timestamp = timestamp << 32; timestamp += epb->timestamp_low; uint64_t ticks_per_sec = pcapng->file_info->timestamp_ticks_per_second[epb->interface_id]; - uint64_t packet_secs = timestamp / ticks_per_sec; - uint64_t ticks = timestamp % ticks_per_sec; - if (packet_secs <= MAXIMUM_PACKET_SECONDS_VALUE) + uint64_t packet_secs = (ticks_per_sec != 0 ? timestamp / ticks_per_sec : 0); + if (packet_secs <= MAXIMUM_PACKET_SECONDS_VALUE && packet_secs != 0) { + uint64_t ticks = timestamp % ticks_per_sec; packet_header->timestamp.tv_sec = packet_secs; packet_header->timestamp.tv_nsec = (1000000000ul * ticks) / ticks_per_sec; } From 0cc772e3d9acaa8d179a86caa2ec8c464810e4fb Mon Sep 17 00:00:00 2001 From: Zhengfei He <157287166+zhengfeihe@users.noreply.github.com> Date: Wed, 14 Aug 2024 15:11:38 +0900 Subject: [PATCH 33/35] Replace netifaces by scapy (#1489) --- ci/run_tests/requirements.txt | 2 +- ci/run_tests/run_tests.py | 5 +++-- ci/run_tests/run_tests_windows.py | 25 ++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ci/run_tests/requirements.txt b/ci/run_tests/requirements.txt index b00a84e7ca..81360b1777 100644 --- a/ci/run_tests/requirements.txt +++ b/ci/run_tests/requirements.txt @@ -1 +1 @@ -netifaces==0.11.0 +scapy==2.5.0 diff --git a/ci/run_tests/run_tests.py b/ci/run_tests/run_tests.py index 43a938e8e0..efb2797675 100644 --- a/ci/run_tests/run_tests.py +++ b/ci/run_tests/run_tests.py @@ -1,7 +1,7 @@ import os import subprocess import argparse -import netifaces as ni +from scapy.all import get_if_addr PCAP_FILE_PATH = os.path.join("Tests", "Pcap++Test", "PcapExamples", "example.pcap") @@ -32,7 +32,8 @@ def main(): ) args = parser.parse_args() - ip_address = ni.ifaddresses(args.interface)[ni.AF_INET][0]["addr"] + ip_address = get_if_addr(args.interface) + print("IP address is: %s" % ip_address) try: diff --git a/ci/run_tests/run_tests_windows.py b/ci/run_tests/run_tests_windows.py index bba46d8ba3..e12d609b29 100644 --- a/ci/run_tests/run_tests_windows.py +++ b/ci/run_tests/run_tests_windows.py @@ -1,7 +1,8 @@ import os import argparse import subprocess -import netifaces as ni +import scapy.arch.windows +from ipaddress import IPv4Address TCPREPLAY_PATH = "tcpreplay-4.4.1-win" PCAP_FILE_PATH = os.path.abspath( @@ -9,6 +10,24 @@ ) +def validate_ipv4_address(address): + try: + IPv4Address(address) + return True + except ValueError: + return False + + +def get_ip_by_guid(guid): + interfaces = scapy.arch.windows.get_windows_if_list() + for iface in interfaces: + ips = iface.get("ips", []) + # Find the first valid IPv4 address inside iface["ips"]. If no address is found, return None + return next(filter(validate_ipv4_address, ips), None) + # Return None if no matching interface is found + return None + + def find_interface(): completed_process = subprocess.run( ["tcpreplay.exe", "--listnics"], @@ -26,8 +45,8 @@ def find_interface(): if len(columns) > 1 and columns[1].startswith("\\Device\\NPF_"): interface = columns[1] try: - ni_interface = interface.lstrip("\\Device\\NPF_") - ip_address = ni.ifaddresses(ni_interface)[ni.AF_INET][0]["addr"] + nic_guid = interface.lstrip("\\Device\\NPF_") + ip_address = get_ip_by_guid(nic_guid) if ip_address.startswith("169.254"): continue completed_process = subprocess.run( From 6627ab7c2cd891089bd7603791f019aa75d6aaa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ege=20=C3=87etin?= <64282645+egecetin@users.noreply.github.com> Date: Wed, 14 Aug 2024 10:38:23 +0300 Subject: [PATCH 34/35] Fix unknown read in TelnetLayer (#1534) * Fix unknown read in TelnetLayer * need at least 2 bytes for command * fix formatting --------- Co-authored-by: Liu, An-Chi --- Packet++/src/TelnetLayer.cpp | 3 ++- ...testcase-minimized-FuzzTarget-4981601846820864 | Bin 0 -> 211 bytes 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Tests/Fuzzers/RegressionTests/regression_samples/clusterfuzz-testcase-minimized-FuzzTarget-4981601846820864 diff --git a/Packet++/src/TelnetLayer.cpp b/Packet++/src/TelnetLayer.cpp index e59c1345f9..b8ee8cbbd4 100644 --- a/Packet++/src/TelnetLayer.cpp +++ b/Packet++/src/TelnetLayer.cpp @@ -92,7 +92,8 @@ namespace pcpp pos += length; offset += length; - if (isCommandField(pos)) + if ((static_cast(pos - m_Data) <= (m_DataLen - 2)) && + isCommandField(pos)) // Need at least 2 bytes for command return pos; } diff --git a/Tests/Fuzzers/RegressionTests/regression_samples/clusterfuzz-testcase-minimized-FuzzTarget-4981601846820864 b/Tests/Fuzzers/RegressionTests/regression_samples/clusterfuzz-testcase-minimized-FuzzTarget-4981601846820864 new file mode 100644 index 0000000000000000000000000000000000000000..7ee74fb4fb53a3e4f6a7f1e0af426b40713b9288 GIT binary patch literal 211 zcmca|c+)~A1{MYdAoveNK&-&S0ObCMfYl5jj)H=#0>gX-1t6OZst72?AP$lNf&U=A eC;*+0A_?Ju?ZOZTSqpInObSy3CIh2URR91*;5w!N literal 0 HcmV?d00001 From b27e84f9041411ccfd8e4cdb6b813ffc50ccc9f1 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Wed, 14 Aug 2024 11:54:01 +0300 Subject: [PATCH 35/35] Clang-format for Pcap++ (#1516) * Formatted Pcap++ headers. - Includes manual review. * Format *.cpp files. * Updated pre-commit. * Fix doxygen error. * Fixed indents. * Documentation fixes. - Align spaces to bullet points - Break up long lines. - Typo fixes. - Removed IPv6 support todo, as it is already completed. - Updated IPFilter documentation to include IPv6 support. * Align more spaces to bullet points. * Formatted RawSocketDevice.h * Fix pre-commit line limit fail. * Replaced
tags with line break in documentation. * Moved comments above lines for nicer formatting. * Formatting fixes. * Cleaned up
tags. * Fixed uneven quotation marks. * Lint --------- Co-authored-by: Liu, An-Chi --- .pre-commit-config.yaml | 2 +- Pcap++/header/Device.h | 38 +- Pcap++/header/DeviceUtils.h | 4 +- Pcap++/header/DpdkDevice.h | 698 +++--- Pcap++/header/DpdkDeviceList.h | 148 +- Pcap++/header/KniDevice.h | 195 +- Pcap++/header/KniDeviceList.h | 12 +- Pcap++/header/LinuxNicInformationSocket.h | 3 +- Pcap++/header/MBufRawPacket.h | 148 +- Pcap++/header/NetworkUtils.h | 78 +- Pcap++/header/PcapDevice.h | 43 +- Pcap++/header/PcapFileDevice.h | 363 ++-- Pcap++/header/PcapFilter.h | 555 +++-- Pcap++/header/PcapLiveDevice.h | 433 ++-- Pcap++/header/PcapLiveDeviceList.h | 30 +- Pcap++/header/PcapRemoteDevice.h | 119 +- Pcap++/header/PcapRemoteDeviceList.h | 129 +- Pcap++/header/PcapUtils.h | 4 +- Pcap++/header/PfRingDevice.h | 100 +- Pcap++/header/PfRingDeviceList.h | 25 +- Pcap++/header/RawSocketDevice.h | 119 +- Pcap++/header/WinPcapLiveDevice.h | 53 +- Pcap++/header/XdpDevice.h | 76 +- Pcap++/src/DeviceUtils.cpp | 4 +- Pcap++/src/DpdkDevice.cpp | 2341 +++++++++++---------- Pcap++/src/DpdkDeviceList.cpp | 672 +++--- Pcap++/src/KniDevice.cpp | 1545 +++++++------- Pcap++/src/KniDeviceList.cpp | 238 +-- Pcap++/src/LinuxNicInformationSocket.cpp | 110 +- Pcap++/src/MBufRawPacket.cpp | 481 ++--- Pcap++/src/NetworkUtils.cpp | 646 +++--- Pcap++/src/PcapDevice.cpp | 99 +- Pcap++/src/PcapFileDevice.cpp | 1522 +++++++------- Pcap++/src/PcapFilter.cpp | 578 ++--- Pcap++/src/PcapLiveDevice.cpp | 1888 +++++++++-------- Pcap++/src/PcapLiveDeviceList.cpp | 584 ++--- Pcap++/src/PcapRemoteDevice.cpp | 211 +- Pcap++/src/PcapRemoteDeviceList.cpp | 324 +-- Pcap++/src/PcapUtils.cpp | 14 +- Pcap++/src/PfRingDevice.cpp | 1340 ++++++------ Pcap++/src/PfRingDeviceList.cpp | 149 +- Pcap++/src/RawSocketDevice.cpp | 793 +++---- Pcap++/src/WinPcapLiveDevice.cpp | 197 +- Pcap++/src/XdpDevice.cpp | 917 ++++---- 44 files changed, 9358 insertions(+), 8670 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a2d6e22a2b..d25b97d4c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: clang-format args: ["--style=file"] # Use the .clang-format file for configuration - files: ^(Common\+\+|Tests|Examples|Packet\+\+)/.*\.(cpp|h)$ + files: ^(Common\+\+|Packet\+\+|Pcap\+\+|Tests|Examples)/.*\.(cpp|h)$ - id: cppcheck args: ["--std=c++11", "--language=c++", "--suppressions-list=cppcheckSuppressions.txt", "--inline-suppr", "--force"] - repo: https://github.com/codespell-project/codespell diff --git a/Pcap++/header/Device.h b/Pcap++/header/Device.h index eafd1ceea6..d8ba547076 100644 --- a/Pcap++/header/Device.h +++ b/Pcap++/header/Device.h @@ -7,9 +7,9 @@ #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 */ @@ -26,11 +26,12 @@ namespace pcpp bool m_DeviceOpened; // c'tor should not be public - IDevice() : m_DeviceOpened(false) {} + IDevice() : m_DeviceOpened(false) + {} public: - - virtual ~IDevice() {} + virtual ~IDevice() + {} /** * Open the device @@ -46,10 +47,12 @@ namespace pcpp /** * @return True if the file is opened, false otherwise */ - inline bool isOpened() { return m_DeviceOpened; } + inline bool isOpened() + { + return m_DeviceOpened; + } }; - /** * @class IFilterableDevice * An abstract interface representing all devices that have BPF (Berkeley Packet Filter) filtering capabilities, @@ -59,16 +62,17 @@ namespace pcpp class IFilterableDevice { protected: - // c'tor should not be public - IFilterableDevice() {} + IFilterableDevice() + {} public: - - virtual ~IFilterableDevice() {} + virtual ~IFilterableDevice() + {} /** - * Set a filter for the device. When implemented by the device, only packets that match the filter will be received + * 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 */ @@ -80,8 +84,10 @@ namespace pcpp } /** - * 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) + * 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; @@ -92,4 +98,4 @@ namespace pcpp */ virtual bool clearFilter() = 0; }; -} +} // namespace pcpp diff --git a/Pcap++/header/DeviceUtils.h b/Pcap++/header/DeviceUtils.h index 7a33e2e277..b453eb3d97 100644 --- a/Pcap++/header/DeviceUtils.h +++ b/Pcap++/header/DeviceUtils.h @@ -18,7 +18,7 @@ namespace pcpp * @throws std::runtime_error The system encountered an error fetching the devices. */ std::unique_ptr getAllLocalPcapDevices(); - } + } // namespace internal /// @endcond -} +} // namespace pcpp diff --git a/Pcap++/header/DpdkDevice.h b/Pcap++/header/DpdkDevice.h index 069bcc6df4..9d101d64ce 100644 --- a/Pcap++/header/DpdkDevice.h +++ b/Pcap++/header/DpdkDevice.h @@ -12,45 +12,48 @@ /** * @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
- *
+ * 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 + * - 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 + * - 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 + * - On application startup call DpdkDeviceList#initDpdk() static method to initialize DPDK infrastructure and + * DpdkDevice instances * - Open the relevant DpdkDevice(s) * - Send & receive packets... */ @@ -61,9 +64,9 @@ 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 { @@ -75,13 +78,15 @@ namespace pcpp 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 */ 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 */ PMD_E1000EM, @@ -126,51 +131,56 @@ namespace pcpp * @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 + * @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); + 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.
+ * 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 + * __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 + * - 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()
+ * __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
+ * __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 + * - 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: + public: /** * An enum describing all RSS (Receive Side Scaling) hash functions supported in DPDK. Notice not all * PMDs support all types of hash functions @@ -178,83 +188,86 @@ namespace pcpp enum DpdkRssHashFunction { /** No RSS */ - RSS_NONE = 0, + RSS_NONE = 0, /** IPv4 based flow */ - RSS_IPV4 = 0x1, + RSS_IPV4 = 0x1, /** Fragmented IPv4 based flow */ - RSS_FRAG_IPV4 = 0x2, + RSS_FRAG_IPV4 = 0x2, /** Non-fragmented IPv4 + TCP flow */ - RSS_NONFRAG_IPV4_TCP = 0x4, + RSS_NONFRAG_IPV4_TCP = 0x4, /** Non-fragmented IPv4 + UDP flow */ - RSS_NONFRAG_IPV4_UDP = 0x8, + RSS_NONFRAG_IPV4_UDP = 0x8, /** Non-fragmented IPv4 + SCTP flow */ - RSS_NONFRAG_IPV4_SCTP = 0x10, + RSS_NONFRAG_IPV4_SCTP = 0x10, /** Non-fragmented IPv4 + non TCP/UDP/SCTP flow */ - RSS_NONFRAG_IPV4_OTHER = 0x20, + RSS_NONFRAG_IPV4_OTHER = 0x20, /** IPv6 based flow */ - RSS_IPV6 = 0x40, + RSS_IPV6 = 0x40, /** Fragmented IPv6 based flow */ - RSS_FRAG_IPV6 = 0x80, + RSS_FRAG_IPV6 = 0x80, /** Non-fragmented IPv6 + TCP flow */ - RSS_NONFRAG_IPV6_TCP = 0x100, + RSS_NONFRAG_IPV6_TCP = 0x100, /** Non-fragmented IPv6 + UDP flow */ - RSS_NONFRAG_IPV6_UDP = 0x200, + RSS_NONFRAG_IPV6_UDP = 0x200, /** Non-fragmented IPv6 + SCTP flow */ - RSS_NONFRAG_IPV6_SCTP = 0x400, + RSS_NONFRAG_IPV6_SCTP = 0x400, /** Non-fragmented IPv6 + non TCP/UDP/SCTP flow */ - RSS_NONFRAG_IPV6_OTHER = 0x800, + RSS_NONFRAG_IPV6_OTHER = 0x800, /** L2 payload based flow */ - RSS_L2_PAYLOAD = 0x1000, + RSS_L2_PAYLOAD = 0x1000, /** IPv6 Ex based flow */ - RSS_IPV6_EX = 0x2000, + RSS_IPV6_EX = 0x2000, /** IPv6 + TCP Ex based flow */ - RSS_IPV6_TCP_EX = 0x4000, + RSS_IPV6_TCP_EX = 0x4000, /** IPv6 + UDP Ex based flow */ - RSS_IPV6_UDP_EX = 0x8000, + RSS_IPV6_UDP_EX = 0x8000, /** Consider device port number as a flow differentiator */ - RSS_PORT = 0x10000, + RSS_PORT = 0x10000, /** VXLAN protocol based flow */ - RSS_VXLAN = 0x20000, + RSS_VXLAN = 0x20000, /** GENEVE protocol based flow */ - RSS_GENEVE = 0x40000, + RSS_GENEVE = 0x40000, /** NVGRE protocol based flow */ - RSS_NVGRE = 0x80000, + RSS_NVGRE = 0x80000, /** All RSS functions supported by the device */ - RSS_ALL_SUPPORTED = -1, + RSS_ALL_SUPPORTED = -1, /** A default set of RSS functions supported by the device */ - RSS_DEFAULT = PCPP_RSS_HASH_MAGIC_NUMBER + 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 + * 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 NULL 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 NULL value causes a default random hash key to be used by the device + * driver */ uint8_t* rssKey; @@ -265,32 +278,34 @@ namespace pcpp 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 + * @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, - uint64_t rssHashFunction = RSS_DEFAULT, - uint8_t* rssKey = DpdkDevice::m_RSSKey, - uint8_t rssKeyLength = 40) + uint16_t transmitDescriptorsNumber = 512, + uint16_t flushTxBufferTimeout = 100, + uint64_t rssHashFunction = RSS_DEFAULT, + uint8_t* rssKey = DpdkDevice::m_RSSKey, uint8_t rssKeyLength = 40) { this->receiveDescriptorsNumber = receiveDescriptorsNumber; this->transmitDescriptorsNumber = transmitDescriptorsNumber; @@ -358,7 +373,8 @@ namespace pcpp RxTxStats aggregatedRxStats; /** 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 */ uint64_t rxErroneousPackets; @@ -371,48 +387,71 @@ namespace pcpp /** * @return The device ID (DPDK port ID) */ - int getDeviceId() const { return m_Id; } + int getDeviceId() const + { + return m_Id; + } /** * @return The device name which is in the format of 'DPDK_[PORT-ID]' */ - std::string getDeviceName() const { return m_DeviceName; } + std::string getDeviceName() const + { + return m_DeviceName; + } /** * @return The MAC address of the device (DPDK port) */ - MacAddress getMacAddress() const { return m_MacAddress; } + 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; } + 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; } + DpdkPMDType getPMDType() const + { + return m_PMDType; + } /** * @return The PCI address of the device */ - std::string getPciAddress() const { return m_PciAddress; } + std::string getPciAddress() const + { + return m_PciAddress; + } /** * @return The device's maximum transmission unit (MTU) in bytes */ - uint16_t getMtu() const { return m_DeviceMtu; } + 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 + * @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; @@ -430,185 +469,219 @@ namespace pcpp /** * @return The number of RX queues currently opened for this device (as configured in openMultiQueues() ) */ - uint16_t getNumOfOpenedRxQueues() const { return m_NumOfRxQueuesOpened; } + uint16_t getNumOfOpenedRxQueues() const + { + return m_NumOfRxQueuesOpened; + } /** * @return The number of TX queues currently opened for this device (as configured in openMultiQueues() ) */ - uint16_t getNumOfOpenedTxQueues() const { return m_NumOfTxQueuesOpened; } + uint16_t getNumOfOpenedTxQueues() const + { + return m_NumOfTxQueuesOpened; + } /** * @return The total number of RX queues available on this device */ - uint16_t getTotalNumOfRxQueues() const { return m_TotalAvailableRxQueues; } + uint16_t getTotalNumOfRxQueues() const + { + return m_TotalAvailableRxQueues; + } /** * @return The total number of TX queues available on this device */ - uint16_t getTotalNumOfTxQueues() const { return m_TotalAvailableTxQueues; } - + 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 + * @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 + * 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 + * @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] 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 + * @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 + * - 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 + * @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); + 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 - *

+ * - 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 + * @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 + * - 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 + * @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 - *

+ * - 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 + * @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 + * 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 + * @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 + * 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 + * @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); @@ -627,54 +700,65 @@ namespace pcpp 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 - */ - 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 + * 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 */ 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 + * 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 + * @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); + 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(); @@ -700,15 +784,15 @@ namespace pcpp 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 + * 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 + * 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 */ @@ -723,14 +807,15 @@ namespace pcpp /** * 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 + * @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; @@ -746,15 +831,19 @@ namespace pcpp */ std::vector rssHashFunctionMaskToString(uint64_t rssHFMask) const; - //overridden methods + // 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 + * 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); }; + bool open() override + { + return openMultiQueues(1, 1); + }; /** * Close the DpdkDevice. When device is closed it's not possible work with it @@ -762,15 +851,19 @@ namespace pcpp void close() override; private: - struct DpdkCoreConfiguration { int RxQueueId; bool IsCoreInUse; - void clear() { RxQueueId = -1; IsCoreInUse = false; } + void clear() + { + RxQueueId = -1; + IsCoreInUse = false; + } - DpdkCoreConfiguration() : RxQueueId(-1), IsCoreInUse(false) {} + DpdkCoreConfiguration() : RxQueueId(-1), IsCoreInUse(false) + {} }; DpdkDevice(int port, uint32_t mBufPoolSize, uint16_t mMbufDataSize); @@ -789,7 +882,8 @@ namespace pcpp void setDeviceInfo(); typedef rte_mbuf* (*PacketIterator)(void* packetStorage, int index); - uint16_t sendPacketsInner(uint16_t txQueueId, void* packetStorage, PacketIterator iter, int arrLength, bool useTxBuffer); + uint16_t sendPacketsInner(uint16_t txQueueId, void* packetStorage, PacketIterator iter, int arrLength, + bool useTxBuffer); uint64_t convertRssHfToDpdkRssHf(uint64_t rssHF) const; uint64_t convertDpdkRssHfToRssHf(uint64_t dpdkRssHF) const; @@ -821,12 +915,12 @@ namespace pcpp bool m_WasOpened; - // RSS key used by the NIC for load balancing the packets between cores + // RSS key used by the NIC for load balancing the packets between cores static uint8_t m_RSSKey[40]; mutable DpdkDeviceStats m_PrevStats; }; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/DpdkDeviceList.h b/Pcap++/header/DpdkDeviceList.h index e1336e982d..dad1be868c 100644 --- a/Pcap++/header/DpdkDeviceList.h +++ b/Pcap++/header/DpdkDeviceList.h @@ -13,21 +13,22 @@ */ /** -* \namespace pcpp -* \brief The main namespace for the PcapPlusPlus lib -*/ + * \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. + * 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 { @@ -35,24 +36,26 @@ namespace pcpp /** * A virtual d'tor. Can be overridden by child class if needed */ - virtual ~DpdkWorkerThread() {} + virtual ~DpdkWorkerThread() + {} /** - * An abstract method that must be implemented by child class. It's the indication for the worker to start running + * 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) + * 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; @@ -62,16 +65,17 @@ namespace pcpp /** * @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 + * 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; + private: bool m_IsInitialized; static bool m_IsDpdkInitialized; @@ -83,18 +87,22 @@ namespace pcpp DpdkDeviceList(); - bool isInitialized() const { return (m_IsInitialized && m_IsDpdkInitialized); } + bool isInitialized() const + { + return (m_IsInitialized && m_IsDpdkInitialized); + } bool initDpdkDevices(uint32_t mBufPoolSizePerDevice, uint16_t mMbufDataSize); static bool verifyHugePagesAndDpdkDriver(); static int dpdkWorkerThreadStart(void* ptr); - public: + 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 + * 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() @@ -107,31 +115,38 @@ namespace pcpp } /** - * 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) + * 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] 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 + * @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); + 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 @@ -150,7 +165,10 @@ namespace pcpp /** * @return A vector of all DpdkDevice instances */ - const std::vector& getDpdkDeviceList() const { return m_DpdkDeviceList; } + const std::vector& getDpdkDeviceList() const + { + return m_DpdkDeviceList; + } /** * @return DPDK master core which is the core that initializes the application @@ -164,8 +182,8 @@ namespace pcpp 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; @@ -177,32 +195,34 @@ namespace pcpp 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(); }; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/KniDevice.h b/Pcap++/header/KniDevice.h index 57d8640edd..3e0e32ac67 100644 --- a/Pcap++/header/KniDevice.h +++ b/Pcap++/header/KniDevice.h @@ -72,7 +72,8 @@ * suitable access rights (must have CAP_NET_ADMIN). * * Useful links: - * - KNI interface concept DPDK documentation + * - KNI interface concept DPDK + * documentation * - KNI PMD * - KNI DPDK sample application * - KNI DPDK test plan @@ -92,7 +93,8 @@ namespace pcpp /** * Defines the signature callback used by capturing API on KNI device */ - typedef bool (*OnKniPacketArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, KniDevice* device, void* userCookie); + typedef bool (*OnKniPacketArriveCallback)(MBufRawPacket* packets, uint32_t numOfPackets, KniDevice* device, + void* userCookie); /** * @class KniDevice @@ -123,6 +125,7 @@ namespace pcpp { friend class KniDeviceList; friend class MBufRawPacket; + public: /** * Various link related constants for KNI device @@ -235,8 +238,7 @@ namespace pcpp * Must be less than or equal to IFNAMSIZ (16 chars including \0 on most systems) */ std::string name; - union - { + union { KniIoctlCallbacks* callbacks; KniOldIoctlCallbacks* oldCallbacks; }; @@ -284,15 +286,24 @@ namespace pcpp /** * Indicates whether the KNI device was initialized successfully */ - inline bool isInitialized() const { return !(m_Device == NULL || m_MBufMempool == NULL); } + inline bool isInitialized() const + { + return !(m_Device == NULL || m_MBufMempool == NULL); + } /** * Obtains name of KNI device in form of C++ string */ - inline std::string getName() const { return std::string(m_DeviceInfo.name); } + inline std::string getName() const + { + return std::string(m_DeviceInfo.name); + } /** * Obtains port ID of KNI device */ - inline uint16_t getPort() const { return m_DeviceInfo.portId; } + 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). @@ -404,7 +415,8 @@ namespace pcpp * - 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 + * @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(); @@ -414,7 +426,8 @@ namespace pcpp * 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. + * 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 @@ -436,29 +449,34 @@ namespace pcpp /** * @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 + * @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 + * 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 + * @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] 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 + * @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); @@ -467,13 +485,13 @@ namespace pcpp /** * @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 + * - 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 @@ -482,14 +500,14 @@ namespace pcpp /** * @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 - *

+ * - 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 @@ -498,10 +516,10 @@ namespace pcpp /** * @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 + * - 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 */ @@ -509,14 +527,14 @@ namespace pcpp /** * @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 - *

+ * - 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 */ @@ -524,28 +542,33 @@ namespace pcpp /** * @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 + * 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 + * 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 + * @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 + * 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); @@ -557,12 +580,14 @@ namespace pcpp * 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. + * 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 + * @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 @@ -573,25 +598,26 @@ namespace pcpp * @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); + * 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. */ @@ -635,7 +661,10 @@ namespace pcpp KniThread* thread; static void runCapture(void* devicePointer, std::atomic& stopThread); - inline bool isRunning() const { return thread != NULL; } + inline bool isRunning() const + { + return thread != NULL; + } void cleanup(); } m_Capturing; struct KniRequests @@ -649,6 +678,6 @@ namespace pcpp } m_Requests; }; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/KniDeviceList.h b/Pcap++/header/KniDeviceList.h index 41a1a3273d..82d802a10f 100644 --- a/Pcap++/header/KniDeviceList.h +++ b/Pcap++/header/KniDeviceList.h @@ -37,6 +37,7 @@ namespace pcpp * @param[in] kniDevice KNI device to be destroyed explicitly */ void destroyDevice(KniDevice* kniDevice); + public: /** * Callback related constants for KNI device @@ -55,7 +56,8 @@ namespace pcpp { /** 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 */ CALLBACK_MAC, @@ -75,7 +77,10 @@ namespace pcpp /** * @return true if KNI module was initialized successfully false otherwise */ - inline bool isInitialized() { return m_Initialized; } + inline bool isInitialized() + { + return m_Initialized; + } /* Device manipulation */ @@ -119,11 +124,12 @@ namespace pcpp * @param[in] cbType One of KniCallbackType enum values */ static bool isCallbackSupported(const KniCallbackType cbType); + private: std::vector m_Devices; bool m_Initialized; int m_KniUniqueId; }; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/LinuxNicInformationSocket.h b/Pcap++/header/LinuxNicInformationSocket.h index c88a37a146..2eb2b0dc47 100644 --- a/Pcap++/header/LinuxNicInformationSocket.h +++ b/Pcap++/header/LinuxNicInformationSocket.h @@ -62,6 +62,7 @@ namespace pcpp * 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 */ LinuxNicInformationSocket(const LinuxNicInformationSocket&); @@ -69,4 +70,4 @@ namespace pcpp LinuxNicInformationSocket operator=(const LinuxNicInformationSocket&); LinuxSocket m_Socket; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/MBufRawPacket.h b/Pcap++/header/MBufRawPacket.h index 699d33f8b6..90e79736b4 100644 --- a/Pcap++/header/MBufRawPacket.h +++ b/Pcap++/header/MBufRawPacket.h @@ -10,9 +10,9 @@ 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 { @@ -21,27 +21,29 @@ namespace pcpp class KniDevice; #endif - #define MBUFRAWPACKET_OBJECT_TYPE 1 +#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) + * 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 + * - 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 { @@ -59,24 +61,29 @@ namespace pcpp void setMBuf(struct rte_mbuf* mBuf, timespec timestamp); bool init(struct rte_mempool* mempool); bool initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool); - public: + 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(NULL), m_Mempool(NULL), m_MbufDataSize(0), m_FreeMbuf(true) { m_DeleteRawDataAtDestructor = false; } + MBufRawPacket() : RawPacket(), m_MBuf(NULL), m_Mempool(NULL), 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 + * 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); @@ -87,8 +94,8 @@ namespace pcpp * 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 + * @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); @@ -99,8 +106,8 @@ namespace pcpp * 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 + * @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 @@ -113,8 +120,8 @@ namespace pcpp * 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 + * @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); @@ -127,8 +134,8 @@ namespace pcpp * 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 + * @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 @@ -136,38 +143,48 @@ namespace pcpp /** * @return A pointer to the DPDK mbuf stored in this object */ - inline rte_mbuf* getMBuf() { return m_MBuf; } + inline rte_mbuf* getMBuf() + { + return m_MBuf; + } // overridden methods /** * @return MBufRawPacket object type */ - inline uint8_t getObjectType() const override { 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) + * 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); /** * 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 NULL), this method will call the init() 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 NULL), 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 + * @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); + bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); /** * Clears the object and frees the mbuf @@ -175,17 +192,19 @@ namespace pcpp 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 NULL) or mbuf append failed an error is printed to log + * 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 NULL) 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 NULL) or mbuf append failed an error is printed to log + * 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 NULL) 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 @@ -193,29 +212,34 @@ namespace pcpp 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 + * 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 NULL), 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 + * @return True if all bytes were removed successfully, or false if MBufRawPacket is not initialize (mbuf is + * NULL), 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 + * 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. + * 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; } + inline void setFreeMbuf(bool val = true) + { + m_FreeMbuf = val; + } }; /** @@ -224,6 +248,6 @@ namespace pcpp */ typedef PointerVector MBufRawPacketVector; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/NetworkUtils.h b/Pcap++/header/NetworkUtils.h index 441532d5bf..7df6b397a3 100644 --- a/Pcap++/header/NetworkUtils.h +++ b/Pcap++/header/NetworkUtils.h @@ -4,25 +4,24 @@ #include "IpAddress.h" #include "PcapLiveDevice.h" - /// @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 + * 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 @@ -39,49 +38,56 @@ namespace pcpp 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 + * 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[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 + * @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; - + 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. + * 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] 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) + * @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; + 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() + {} }; -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/PcapDevice.h b/Pcap++/header/PcapDevice.h index 2e055c4857..b8b50b6ca5 100644 --- a/Pcap++/header/PcapDevice.h +++ b/Pcap++/header/PcapDevice.h @@ -10,18 +10,18 @@ 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 + // Forward Declaration - required for IPcapDevice::matchPacketWithFilter class GeneralFilter; /** * @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 + * 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 { @@ -29,10 +29,12 @@ namespace pcpp pcap_t* m_PcapDescriptor; // c'tor should not be public - IPcapDevice() : IDevice() { m_PcapDescriptor = NULL; } + IPcapDevice() : IDevice() + { + m_PcapDescriptor = NULL; + } public: - /** * @struct PcapStats * A container for pcap device statistics @@ -47,7 +49,6 @@ namespace pcpp uint64_t packetsDropByInterface; }; - virtual ~IPcapDevice(); /** @@ -64,24 +65,24 @@ namespace pcpp 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) + * 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); @@ -93,4 +94,4 @@ namespace pcpp bool clearFilter(); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index 81da66054f..8006943745 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -11,9 +11,9 @@ 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 { /** @@ -44,13 +44,12 @@ namespace pcpp virtual ~IFileDevice(); public: - /** - * @return The name of the file - */ + * @return The name of the file + */ std::string getFileName() const; - //override methods + // override methods /** * Close the file @@ -58,7 +57,6 @@ namespace pcpp 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 @@ -70,22 +68,22 @@ namespace pcpp 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() + * 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() {} + virtual ~IFileReaderDevice() + {} /** - * @return The file size in bytes - */ + * @return The file size in bytes + */ uint64_t getFileSize() const; virtual bool getNextPacket(RawPacket& rawPacket) = 0; @@ -93,25 +91,26 @@ namespace pcpp /** * 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) + * @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 + * 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 + * 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 { @@ -125,27 +124,38 @@ namespace pcpp 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() + * 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) {} + PcapFileReaderDevice(const std::string& fileName) + : IFileReaderDevice(fileName), m_Precision(FileTimestampPrecision::Unknown), + m_PcapLinkLayerType(LINKTYPE_ETHERNET) + {} /** * A destructor for this class */ - virtual ~PcapFileReaderDevice() {} + virtual ~PcapFileReaderDevice() + {} /** - * @return The link layer type of this file - */ - LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; } + * @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. - */ - FileTimestampPrecision getTimestampPrecision() const { return m_Precision; } + * @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 @@ -153,25 +163,26 @@ namespace pcpp */ static bool isNanoSecondPrecisionSupported(); - //overridden methods + // 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 + * @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) + * @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 + * 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; @@ -179,33 +190,36 @@ namespace pcpp /** * @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 + * 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) +#pragma pack(1) /* * File format header. */ - typedef struct { - uint64_t identification_pattern; - uint32_t version_number; - uint32_t datalink_type; + typedef struct + { + uint64_t identification_pattern; + uint32_t version_number; + uint32_t datalink_type; } snoop_file_header_t; /* * 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 */ + 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 */ } snoop_packet_header_t; - #pragma pack() +#pragma pack() LinkLayerType m_PcapLinkLayerType; std::ifstream m_snoopFile; @@ -216,11 +230,13 @@ namespace pcpp 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() + * 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) {} + SnoopFileReaderDevice(const std::string& fileName) + : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET) + {} /** * A destructor for this class @@ -228,30 +244,33 @@ namespace pcpp virtual ~SnoopFileReaderDevice(); /** - * @return The link layer type of this file - */ - LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; } - + * @return The link layer type of this file + */ + LinkLayerType getLinkLayerType() const + { + return m_PcapLinkLayerType; + } - //overridden methods + // 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 + * @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) + * @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 + * 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; @@ -262,10 +281,10 @@ namespace pcpp 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 + * 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 { @@ -279,8 +298,8 @@ namespace pcpp 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() + * 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); @@ -288,64 +307,68 @@ namespace pcpp /** * A destructor for this class */ - virtual ~PcapNgFileReaderDevice() { close(); } + 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 + * 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 + * 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 + * 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 + * 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 + * 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 + * @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 + // 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 + * @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) + * @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(); @@ -357,7 +380,8 @@ namespace pcpp /** * 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) + * @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); @@ -368,7 +392,6 @@ namespace pcpp void close(); }; - /** * @class IFileWriterDevice * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer devices @@ -382,11 +405,11 @@ namespace pcpp IFileWriterDevice(const std::string& fileName); public: - /** * A destructor for this class */ - virtual ~IFileWriterDevice() {} + virtual ~IFileWriterDevice() + {} virtual bool writePacket(RawPacket const& packet) = 0; @@ -396,7 +419,6 @@ 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 @@ -420,22 +442,27 @@ namespace pcpp 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() + * 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 + * @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); + PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET, + bool nanosecondsPrecision = false); /** * A destructor for this class */ - ~PcapFileWriterDevice() {} + ~PcapFileWriterDevice() + {} /** - * 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 + * 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 @@ -444,18 +471,22 @@ namespace pcpp 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 + * 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 + * @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. */ - FileTimestampPrecision getTimestampPrecision() const { return m_Precision; } + FileTimestampPrecision getTimestampPrecision() const + { + return m_Precision; + } /** * A static method that checks if nano-second precision is supported in the current platform and environment @@ -463,13 +494,13 @@ namespace pcpp */ static bool isNanoSecondPrecisionSupported(); - //override methods + // 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) + * @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; @@ -478,10 +509,10 @@ namespace pcpp * 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 + * @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; @@ -502,13 +533,12 @@ namespace pcpp 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 + * 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 { @@ -522,71 +552,80 @@ 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() + * 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 + * @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 */ - virtual ~PcapNgFileWriterDevice() { close(); } + 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) - */ - 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 + * 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) + * @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 + // 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 + * 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) + * @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 + * 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 + * @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) + * @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(); @@ -595,9 +634,9 @@ namespace pcpp * 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 + * @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); @@ -619,11 +658,11 @@ namespace pcpp /** * 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) + * @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); - }; -}// namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/PcapFilter.h b/Pcap++/header/PcapFilter.h index c632ae68c2..9e72ed8b7b 100644 --- a/Pcap++/header/PcapFilter.h +++ b/Pcap++/header/PcapFilter.h @@ -8,32 +8,36 @@ #include "ArpLayer.h" #include "RawPacket.h" -//Forward Declaration - used in GeneralFilter +// 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 - * h olds IPFilter and PortFilter inside it + * 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 + * \brief The main namespace for the PcapPlusPlus lib + */ namespace pcpp { - //Forward Declaration - used in GeneralFilter + // Forward Declaration - used in GeneralFilter class RawPacket; /** @@ -49,7 +53,6 @@ namespace pcpp SRC_OR_DST } Direction; - /** * Supported operators enum */ @@ -79,7 +82,7 @@ namespace pcpp { void operator()(bpf_program* ptr) const; }; - } + } // namespace internal /** * @class BpfFilterWrapper @@ -95,7 +98,6 @@ namespace pcpp void freeProgram(); public: - /** * A c'tor for this class */ @@ -115,8 +117,8 @@ namespace pcpp 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. + * 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 @@ -144,12 +146,14 @@ namespace pcpp * @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); + 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.
+ * 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 @@ -160,28 +164,31 @@ namespace pcpp 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 + * @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() {} + GeneralFilter() + {} /** * Virtual destructor, frees the bpf program */ - virtual ~GeneralFilter() {} + virtual ~GeneralFilter() + {} }; /** * @class BPFStringFilter - * This class can be loaded with a BPF filter string and then can be used to verify the string is valid.
+ * 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 { @@ -189,82 +196,106 @@ namespace pcpp const std::string m_FilterStr; public: - explicit BPFStringFilter(const std::string& filterStr) : m_FilterStr(filterStr) {} + explicit BPFStringFilter(const std::string& filterStr) : m_FilterStr(filterStr) + {} - virtual ~BPFStringFilter() {} + 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 + * @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
+ * 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: Direction m_Dir; + protected: void parseDirection(std::string& directionAsString); - Direction getDir() const { return m_Dir; } - explicit IFilterWithDirection(Direction dir) { m_Dir = dir; } + Direction getDir() const + { + return m_Dir; + } + explicit IFilterWithDirection(Direction dir) + { + m_Dir = dir; + } + public: /** * Set the direction for the filter (source or destination) * @param[in] dir The direction */ - void setDirection(Direction dir) { m_Dir = dir; } + 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
+ * 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: FilterOperator m_Operator; + protected: std::string parseOperator(); - FilterOperator getOperator() const { return m_Operator; } - explicit IFilterWithOperator(FilterOperator op) { m_Operator = op; } + FilterOperator getOperator() const + { + return m_Operator; + } + explicit IFilterWithOperator(FilterOperator op) + { + m_Operator = op; + } + public: /** * Set the operator for the filter * @param[in] op The operator to set */ - void setOperator(FilterOperator op) { m_Operator = op; } + void setOperator(FilterOperator op) + { + m_Operator = op; + } }; - - /** * @class IPFilter - * A class for representing IPv4 address filter, equivalent to "net src x.x.x.x" or "net dst x.x.x.x"
+ * 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 - * @todo Add IPv6 filtering support */ class IPFilter : public IFilterWithDirection { private: IPAddress m_Address; IPNetwork m_Network; + public: /** * The basic constructor that creates the filter from an IP address string and direction (source or destination) @@ -272,25 +303,33 @@ namespace pcpp * @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) {} + 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) */ - IPFilter(const IPAddress& ipAddress, Direction dir) : IFilterWithDirection(dir), m_Address(ipAddress), m_Network(ipAddress) {} + 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". + * 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.. + * @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) {} + 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: @@ -299,21 +338,28 @@ namespace pcpp * 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::). + * @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) {} + 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". + * 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. + * @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) {} + 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 @@ -322,17 +368,23 @@ namespace pcpp * 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. + * @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) {} + 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] 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) {} + IPFilter(const IPNetwork& network, Direction dir) + : IFilterWithDirection(dir), m_Address(network.getNetworkPrefix()), m_Network(network) + {} void parseToString(std::string& result) override; @@ -351,7 +403,10 @@ namespace pcpp * @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)); } + void setAddr(const std::string& ipAddress) + { + this->setAddr(IPAddress(ipAddress)); + } /** * Set the IP address @@ -374,51 +429,67 @@ namespace pcpp /** * Set the subnet mask - * @param[in] netmask The mask to use. The mask should match the IP versrion and be in a valid format. + * @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. + * 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); } + void setMask(const std::string& netmask) + { + m_Network = IPNetwork(m_Address, netmask); + } /** * Clears the subnet mask. */ - void clearMask() { this->clearLen(); } + 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. + * 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); } + void setLen(const int len) + { + m_Network = IPNetwork(m_Address, len); + } /** * Clears the subnet mask length. */ - void clearLen() { m_Network = IPNetwork(m_Address); } + 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"
+ * 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.) */ - IPv4IDFilter(uint16_t ipID, FilterOperator op) : IFilterWithOperator(op), m_IpID(ipID) {} + IPv4IDFilter(uint16_t ipID, FilterOperator op) : IFilterWithOperator(op), m_IpID(ipID) + {} void parseToString(std::string& result) override; @@ -426,28 +497,33 @@ namespace pcpp * Set the IP ID to filter * @param[in] ipID The IP ID to filter */ - void setIpID(uint16_t ipID) { m_IpID = ipID; } + 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"
+ * 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.) */ - IPv4TotalLengthFilter(uint16_t totalLength, FilterOperator op) : IFilterWithOperator(op), m_TotalLength(totalLength) {} + IPv4TotalLengthFilter(uint16_t totalLength, FilterOperator op) + : IFilterWithOperator(op), m_TotalLength(totalLength) + {} void parseToString(std::string& result) override; @@ -455,14 +531,16 @@ namespace pcpp * Set the total length value * @param[in] totalLength The total length value to filter */ - void setTotalLength(uint16_t totalLength) { m_TotalLength = totalLength; } + 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"
+ * 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 @@ -470,6 +548,7 @@ namespace pcpp private: std::string m_Port; void portToString(uint16_t portAsInt); + public: /** * A constructor that gets the port and the direction and creates the filter @@ -484,15 +563,18 @@ namespace pcpp * Set the port * @param[in] port The port to create the filter with */ - void setPort(uint16_t port) { portToString(port); } + 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
+ * 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 @@ -500,6 +582,7 @@ namespace pcpp private: uint16_t m_FromPort; uint16_t m_ToPort; + public: /** * A constructor that gets the port range the the direction and creates the filter with them @@ -507,7 +590,9 @@ namespace pcpp * @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) {} + PortRangeFilter(uint16_t fromPort, uint16_t toPort, Direction dir) + : IFilterWithDirection(dir), m_FromPort(fromPort), m_ToPort(toPort) + {} void parseToString(std::string& result) override; @@ -515,33 +600,41 @@ namespace pcpp * 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; } + 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 */ - void setToPort(uint16_t toPort) { m_ToPort = toPort; } + 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"
+ * 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) */ - MacAddressFilter(MacAddress address, Direction dir) : IFilterWithDirection(dir), m_MacAddress(address) {} + MacAddressFilter(MacAddress address, Direction dir) : IFilterWithDirection(dir), m_MacAddress(address) + {} void parseToString(std::string& result) override; @@ -549,27 +642,31 @@ namespace pcpp * Set the MAC address * @param[in] address The MAC address to use for filtering */ - void setMacAddress(MacAddress address) { m_MacAddress = address; } + 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.
+ * 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 */ - explicit EtherTypeFilter(uint16_t etherType) : m_EtherType(etherType) {} + explicit EtherTypeFilter(uint16_t etherType) : m_EtherType(etherType) + {} void parseToString(std::string& result) override; @@ -577,20 +674,24 @@ namespace pcpp * Set the EtherType value * @param[in] etherType The EtherType value to create the filter with */ - void setEtherType(uint16_t etherType) { m_EtherType = etherType; } + 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.
+ * 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. @@ -607,7 +708,10 @@ namespace pcpp * Add filter to the composite filter * @param[in] filter The filter to add */ - void addFilter(GeneralFilter* filter) { m_FilterList.push_back(filter); } + void addFilter(GeneralFilter* filter) + { + m_FilterList.push_back(filter); + } /** * Removes the first matching filter from the composite filter @@ -624,7 +728,10 @@ namespace pcpp /** * Remove all filters from the composite filter. */ - void clearAllFilters() { m_FilterList.clear(); } + void clearAllFilters() + { + m_FilterList.clear(); + } }; /** @@ -640,23 +747,30 @@ namespace pcpp namespace internal { - /* Could potentially be moved into CompositeLogicFilter as a private member function, with if constexpr when C++17 is the minimum supported standard.*/ + /* 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() { return " and "; }; - template <> constexpr const char *getCompositeLogicOpDelimiter() { return " or "; }; - } + template constexpr const char* getCompositeLogicOpDelimiter() = delete; + template <> constexpr const char* getCompositeLogicOpDelimiter() + { + return " and "; + }; + template <> constexpr const char* getCompositeLogicOpDelimiter() + { + return " or "; + }; + } // namespace internal /** * @class CompositeLogicFilter - * A class for connecting several filters into one filter with logical operation between them.
+ * 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 + template class CompositeLogicFilter : public CompositeFilter { public: using CompositeFilter::CompositeFilter; @@ -680,34 +794,45 @@ 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 + * _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 + * _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
+ * 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 */ - explicit NotFilter(GeneralFilter* filterToInverse) { m_FilterToInverse = filterToInverse; } + explicit NotFilter(GeneralFilter* filterToInverse) + { + m_FilterToInverse = filterToInverse; + } void parseToString(std::string& result) override; @@ -715,16 +840,19 @@ namespace pcpp * 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; } + 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: + * 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), + * 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 @@ -733,56 +861,67 @@ namespace pcpp { 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 + * @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) {} + 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 + * @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) {} + 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 + * @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; } + 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 + * @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; } + 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
+ * 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 */ - explicit ArpFilter(ArpOpcode opCode) : m_OpCode(opCode) {} + explicit ArpFilter(ArpOpcode opCode) : m_OpCode(opCode) + {} void parseToString(std::string& result) override; @@ -790,27 +929,31 @@ namespace pcpp * Set the ARP opcode * @param[in] opCode The ARP opcode: ::ARP_REQUEST or ::ARP_REPLY */ - void setOpCode(ArpOpcode opCode) { m_OpCode = opCode; } + 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
+ * 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 */ - explicit VlanFilter(uint16_t vlanId) : m_VlanID(vlanId) {} + explicit VlanFilter(uint16_t vlanId) : m_VlanID(vlanId) + {} void parseToString(std::string& result) override; @@ -818,14 +961,16 @@ namespace pcpp * 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; } + 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
+ * 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 @@ -851,8 +996,8 @@ namespace pcpp }; /** - * 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 { @@ -861,49 +1006,60 @@ namespace pcpp /** Match packets that contain at least one of the flags defined in the filter */ MatchOneAtLeast }; + private: uint8_t m_TcpFlagsBitMask; 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 + * 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) {} + 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] 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; m_MatchOption = matchOption; } + void setTcpFlagsBitMask(uint8_t tcpFlagBitMask, MatchOptions matchOption) + { + m_TcpFlagsBitMask = tcpFlagBitMask; + m_MatchOption = matchOption; + } void parseToString(std::string& result) override; }; - - /** * @class TcpWindowSizeFilter - * A class for filtering TCP packets that matches TCP window-size criteria
+ * 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" + * 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) {} + TcpWindowSizeFilter(uint16_t windowSize, FilterOperator op) : IFilterWithOperator(op), m_WindowSize(windowSize) + {} void parseToString(std::string& result) override; @@ -911,28 +1067,32 @@ namespace pcpp * 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; } + void setWindowSize(uint16_t windowSize) + { + m_WindowSize = windowSize; + } }; - - /** * @class UdpLengthFilter - * A class for filtering UDP packets that matches UDP length criteria
+ * 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" + * 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) {} + UdpLengthFilter(uint16_t length, FilterOperator op) : IFilterWithOperator(op), m_Length(length) + {} void parseToString(std::string& result) override; @@ -940,7 +1100,10 @@ namespace pcpp * Set length value * @param[in] length The length value that will be used in the filter */ - void setLength(uint16_t length) { m_Length = length; } + void setLength(uint16_t length) + { + m_Length = length; + } }; -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/PcapLiveDevice.h b/Pcap++/header/PcapLiveDevice.h index 868af6a3a7..afa0fc1cf3 100644 --- a/Pcap++/header/PcapLiveDevice.h +++ b/Pcap++/header/PcapLiveDevice.h @@ -19,9 +19,9 @@ 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 { @@ -44,9 +44,9 @@ namespace pcpp */ using OnPacketArrivesStopBlocking = std::function; - /** - * A callback that is called periodically for stats collection if user asked to start packet capturing with periodic stats collection + * 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 */ @@ -58,26 +58,30 @@ namespace pcpp /** * @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 + * 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; + protected: // This is a second descriptor for the same device. It is needed because of a bug // that occurs in libpcap on Linux (on Windows using WinPcap/Npcap it works well): @@ -113,9 +117,10 @@ namespace pcpp bool m_UsePoll; // c'tor is not public, there should be only one for every interface (created by PcapLiveDeviceList) - PcapLiveDevice(pcap_if_t* pInterface, bool calculateMTU, bool calculateMacAddress, bool calculateDefaultGateway); + PcapLiveDevice(pcap_if_t* pInterface, bool calculateMTU, bool calculateMacAddress, + bool calculateDefaultGateway); // copy c'tor is not public - PcapLiveDevice( const PcapLiveDevice& other ); + PcapLiveDevice(const PcapLiveDevice& other); PcapLiveDevice& operator=(const PcapLiveDevice& other); void setDeviceMtu(); @@ -129,8 +134,8 @@ namespace pcpp static void onPacketArrives(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet); static void onPacketArrivesNoCallback(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet); static void onPacketArrivesBlockingMode(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet); - public: + public: /** * The type of the live device */ @@ -144,7 +149,6 @@ namespace pcpp RemoteDevice }; - /** * Device capturing mode */ @@ -156,9 +160,9 @@ namespace pcpp Promiscuous = 1 }; - /** - * Set direction for capturing packets (you can read more here: ) + * Set direction for capturing packets (you can read more here: + * ) */ enum PcapDirection { @@ -170,11 +174,10 @@ namespace pcpp 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 + * 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 { @@ -190,58 +193,57 @@ namespace pcpp /** * 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 + * 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: * . - */ + */ 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] 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] 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) + * @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) { this->mode = mode; this->packetBufferTimeoutMs = packetBufferTimeoutMs; @@ -253,7 +255,6 @@ namespace pcpp } }; - /** * A destructor for this class */ @@ -262,39 +263,65 @@ namespace pcpp /** * @return The type of the device (libPcap, WinPcap/Npcap or a remote device) */ - virtual LiveDeviceType getDeviceType() const { return LibPcapDevice; } + virtual LiveDeviceType getDeviceType() const + { + return LibPcapDevice; + } /** * @return The name of the device (e.g eth0), taken from pcap_if_t->name */ - std::string getName() const { return m_Name; } + std::string getName() const + { + return m_Name; + } /** - * @return A human-readable description of the device, taken from pcap_if_t->description. May be NULL in some interfaces + * @return A human-readable description of the device, taken from pcap_if_t->description. May be NULL in some + * interfaces */ - std::string getDesc() const { return m_Description; } + std::string getDesc() const + { + return m_Description; + } /** * @return True if this interface is a loopback interface, false otherwise */ - bool getLoopback() const { return m_IsLoopback; } + bool getLoopback() const + { + return m_IsLoopback; + } /** * @return The device's maximum transmission unit (MTU) in bytes */ - virtual uint32_t getMtu() const { return m_DeviceMtu; } + virtual uint32_t getMtu() const + { + return m_DeviceMtu; + } /** * @return The device's link layer type */ - virtual LinkLayerType getLinkType() const { return m_LinkType; } + virtual LinkLayerType getLinkType() const + { + return m_LinkType; + } /** * @return A vector containing all addresses defined for this interface, each in pcap_addr_t struct - * @deprecated This method is deprecated and will be removed in future versions. Please use getIPAddresses() instead. + * @deprecated This method is deprecated and will be removed in future versions. Please use getIPAddresses() + * instead. */ + // clang-format off + // Breaking the macro into multiple lines causes doxygen to cause a fit. PCPP_DEPRECATED("This method is deprecated and will be removed in future versions. Please use getIPAddresses() instead.") - const std::vector& getAddresses() const { return m_Addresses; } + // clang-format on + const std::vector& getAddresses() const + { + return m_Addresses; + } /** * @return A vector containing all IP addresses defined for this interface. @@ -304,42 +331,51 @@ namespace pcpp /** * @return The MAC address for this interface */ - virtual MacAddress getMacAddress() const { return m_MacAddress; } + 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. + * 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 + * @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 @@ -348,56 +384,64 @@ namespace pcpp 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. + * 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] 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 + * @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); + 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. + * 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 + * @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); + 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 + * 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 @@ -406,31 +450,35 @@ namespace pcpp 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. - */ - 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) + * 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) */ void stopCapture(); @@ -449,11 +497,13 @@ namespace pcpp /** * 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): + * @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 @@ -463,14 +513,16 @@ namespace pcpp /** * 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. + * 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): + * @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 @@ -482,24 +534,31 @@ namespace pcpp * 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): + * @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); + 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): + * @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 @@ -509,11 +568,12 @@ namespace pcpp /** * 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] 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. + * @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 @@ -524,11 +584,12 @@ namespace pcpp /** * 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] 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. + * @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 @@ -539,10 +600,11 @@ namespace pcpp /** * 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. + * @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 @@ -551,21 +613,22 @@ namespace pcpp */ 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 + * 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() */ @@ -587,4 +650,4 @@ namespace pcpp virtual PcapLiveDevice* cloneInternal(pcap_if_t& devInterface) const; }; -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/PcapLiveDeviceList.h b/Pcap++/header/PcapLiveDeviceList.h index 6fc976889a..8776590cc9 100644 --- a/Pcap++/header/PcapLiveDeviceList.h +++ b/Pcap++/header/PcapLiveDeviceList.h @@ -5,21 +5,21 @@ #include #include - /// @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 + * 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 { @@ -55,7 +55,10 @@ namespace pcpp /** * @return A vector containing pointers to all live devices currently installed on the machine */ - const std::vector& getPcapLiveDevicesList() const { return m_LiveDeviceListView; }; + 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 @@ -100,10 +103,13 @@ namespace pcpp 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; } + const std::vector& getDnsServers() const + { + return m_DnsServers; + } /** * Copies the current live device list @@ -117,4 +123,4 @@ namespace pcpp void reset(); }; -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/header/PcapRemoteDevice.h b/Pcap++/header/PcapRemoteDevice.h index 3ea51e130a..a28cffd4bb 100644 --- a/Pcap++/header/PcapRemoteDevice.h +++ b/Pcap++/header/PcapRemoteDevice.h @@ -2,27 +2,26 @@ #if defined(_WIN32) -#include -#include -#include "PcapLiveDevice.h" - +# include +# include +# include "PcapLiveDevice.h" /// @file 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 + * 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 { @@ -32,13 +31,18 @@ namespace pcpp * @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; } + 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 */ - PcapRemoteAuthentication(const PcapRemoteAuthentication& other) : userName(other.userName), password(other.password) {} + PcapRemoteAuthentication(const PcapRemoteAuthentication& other) + : userName(other.userName), password(other.password) + {} /** * The username for authentication @@ -51,9 +55,9 @@ namespace pcpp 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 + * 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; @@ -61,35 +65,41 @@ namespace pcpp /** * @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 + * 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; + private: IPAddress m_RemoteMachineIpAddress; uint16_t m_RemoteMachinePort; std::shared_ptr m_RemoteAuthentication; - // c'tor is private, as only PcapRemoteDeviceList should create instances of it, and it'll create only one for every remote interface - PcapRemoteDevice(pcap_if_t* iface, std::shared_ptr remoteAuthentication, const IPAddress& remoteMachineIP, uint16_t remoteMachinePort); + // c'tor is private, as only PcapRemoteDeviceList should create instances of it, and it'll create only one for + // every remote interface + PcapRemoteDevice(pcap_if_t* iface, std::shared_ptr remoteAuthentication, + const IPAddress& remoteMachineIP, uint16_t remoteMachinePort); - static void* remoteDeviceCaptureThreadMain(void *ptr); + static void* remoteDeviceCaptureThreadMain(void* ptr); - //overridden methods + // overridden methods ThreadStart getCaptureThreadStart(); public: @@ -98,22 +108,34 @@ namespace pcpp PcapRemoteDevice& operator=(const PcapRemoteDevice&) = delete; PcapRemoteDevice& operator=(PcapRemoteDevice&&) noexcept = delete; - ~PcapRemoteDevice() override {} + ~PcapRemoteDevice() override + {} /** - * @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; } + 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; } + uint16_t getRemoteMachinePort() const + { + return m_RemoteMachinePort; + } /** * @return The type of the device (libPcap, WinPcap/Npcap or a remote device) */ - LiveDeviceType getDeviceType() const override { return RemoteDevice; } + LiveDeviceType getDeviceType() const override + { + return RemoteDevice; + } /** * MTU isn't supported for remote devices @@ -128,19 +150,20 @@ namespace pcpp 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; }; -} // namespace pcpp +} // namespace pcpp -#endif // _WIN32 +#endif // _WIN32 diff --git a/Pcap++/header/PcapRemoteDeviceList.h b/Pcap++/header/PcapRemoteDeviceList.h index 3b00bd2738..d11ea5e2d9 100644 --- a/Pcap++/header/PcapRemoteDeviceList.h +++ b/Pcap++/header/PcapRemoteDeviceList.h @@ -2,29 +2,31 @@ #if defined(_WIN32) -#include -#include "IpAddress.h" -#include "PcapRemoteDevice.h" -#include "DeprecationUtils.h" +# include +# include "IpAddress.h" +# include "PcapRemoteDevice.h" +# include "DeprecationUtils.h" /// @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 + * 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 { @@ -58,18 +60,23 @@ 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 + * 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 NULL if (an appropriate error will be printed to log in each case): + * @return A pointer to the newly created PcapRemoteDeviceList, or NULL if (an appropriate error will be printed + * to log in each case): * - IP address provided is NULL 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. + * - 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); @@ -85,29 +92,34 @@ namespace pcpp * @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): + * @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 + * 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 + * 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 - * @return A pointer to the newly created PcapRemoteDeviceList, or NULL if (an appropriate error will be printed to log in each case): + * @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 NULL if (an appropriate error will be printed + * to log in each case): * - IP address provided is NULL 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. + * - 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); + static PcapRemoteDeviceList* getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, + PcapRemoteAuthentication* remoteAuth); /** * A static method for creating a PcapRemoteDeviceList instance for a specific remote machine. @@ -122,23 +134,31 @@ namespace pcpp * @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): + * @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 + * devices on the remote machine */ - static std::unique_ptr createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication const* remoteAuth); + static std::unique_ptr createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, + PcapRemoteAuthentication const* remoteAuth); /** * @return The IP address of the remote machine */ - IPAddress getRemoteMachineIpAddress() const { return m_RemoteMachineIpAddress; } + 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; } + uint16_t getRemoteMachinePort() const + { + return m_RemoteMachinePort; + } /** * Search a PcapRemoteDevice in the list by its IPv4 address @@ -171,25 +191,36 @@ namespace pcpp /** * @return An iterator object pointing to the first PcapRemoteDevice in list */ - RemoteDeviceListIterator begin() { return m_RemoteDeviceList.begin(); } + RemoteDeviceListIterator begin() + { + return m_RemoteDeviceList.begin(); + } /** * @return A const iterator object pointing to the first PcapRemoteDevice in list */ - ConstRemoteDeviceListIterator begin() const { return m_RemoteDeviceList.begin(); } + ConstRemoteDeviceListIterator begin() const + { + return m_RemoteDeviceList.begin(); + } /** * @return An iterator object pointing to the last PcapRemoteDevice in list */ - RemoteDeviceListIterator end() { return m_RemoteDeviceList.end(); } + RemoteDeviceListIterator end() + { + return m_RemoteDeviceList.end(); + } /** * @return A const iterator object pointing to the last PcapRemoteDevice in list */ - ConstRemoteDeviceListIterator end() const { return m_RemoteDeviceList.end(); } - + ConstRemoteDeviceListIterator end() const + { + return m_RemoteDeviceList.end(); + } }; -} // namespace pcpp +} // namespace pcpp -#endif // _WIN32 +#endif // _WIN32 diff --git a/Pcap++/header/PcapUtils.h b/Pcap++/header/PcapUtils.h index d9f76033fe..5942ad2c5d 100644 --- a/Pcap++/header/PcapUtils.h +++ b/Pcap++/header/PcapUtils.h @@ -29,7 +29,7 @@ namespace pcpp { void operator()(pcap_if_t* ptr) const; }; - } + } // namespace internal /// @endcond -} +} // namespace pcpp diff --git a/Pcap++/header/PfRingDevice.h b/Pcap++/header/PfRingDevice.h index 78940d2dc4..304f40c3c8 100644 --- a/Pcap++/header/PfRingDevice.h +++ b/Pcap++/header/PfRingDevice.h @@ -16,16 +16,16 @@ 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 { class PfRingDevice; - typedef void (*OnPfRingPacketsArriveCallback)(RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, PfRingDevice* device, void* userCookie); - + typedef void (*OnPfRingPacketsArriveCallback)(RawPacket* packets, uint32_t numOfPackets, uint8_t threadId, + PfRingDevice* device, void* userCookie); /** * @class PfRingDevice @@ -34,8 +34,8 @@ namespace pcpp class PfRingDevice : public IDevice, public IFilterableDevice { friend class PfRingDeviceList; - private: + private: struct CoreConfiguration { std::thread RxThread; @@ -68,7 +68,11 @@ namespace pcpp int openSingleRxChannel(const char* deviceName, pfring** ring); - bool getIsHwClockEnable() { setPfRingDeviceAttributes(); return m_HwClockEnabled; } + bool getIsHwClockEnable() + { + setPfRingDeviceAttributes(); + return m_HwClockEnabled; + } bool setPfRingDeviceClock(pfring* ring); void clearCoreConfiguration(); @@ -77,8 +81,8 @@ namespace pcpp void setPfRingDeviceAttributes(); bool sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues); - public: + public: /** * An enum representing the type of packet distribution between different RX channels */ @@ -115,59 +119,79 @@ namespace pcpp * Get the MAC address of the current device * @return The MAC address of the current device */ - MacAddress getMacAddress() { setPfRingDeviceAttributes(); return m_MacAddress; } + MacAddress getMacAddress() + { + setPfRingDeviceAttributes(); + return m_MacAddress; + } /** * Get PF_RING interface index of the current device * @return PF_RING interface index of the current device */ - int getInterfaceIndex() { setPfRingDeviceAttributes(); return m_InterfaceIndex; } + int getInterfaceIndex() + { + setPfRingDeviceAttributes(); + return m_InterfaceIndex; + } /** * Get MTU of the current device * @return Upon success return the device MTU, 0 otherwise */ - int getMtu() { setPfRingDeviceAttributes(); return m_DeviceMTU; } + 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 */ - bool isHwClockEnabledForDevice() { setPfRingDeviceAttributes(); return m_HwClockEnabled; } + bool isHwClockEnabledForDevice() + { + setPfRingDeviceAttributes(); + return m_HwClockEnabled; + } /** * Gets the interface name (e.g eth0, eth1, etc.) * @return The interface name */ - std::string getDeviceName() const { return m_DeviceName; } - + 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 + * @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 + * 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] 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); + bool startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, + CoreMask coreMask); /** * 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 @@ -178,9 +202,9 @@ namespace pcpp 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) + * 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 @@ -190,10 +214,10 @@ namespace pcpp /** * 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" + * 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 @@ -207,7 +231,10 @@ namespace pcpp * opened for each RX queue * @return Number of opened RX channels */ - uint8_t getNumOfOpenedRxChannels() const { return m_NumOfOpenedRxChannels; } + uint8_t getNumOfOpenedRxChannels() const + { + return m_NumOfOpenedRxChannels; + } /** * Gets the total number of RX channels (RX queues) this interface has @@ -224,20 +251,23 @@ namespace pcpp /** * 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 + * @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 + * @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; @@ -314,10 +344,8 @@ namespace pcpp */ 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 @@ -345,6 +373,6 @@ namespace pcpp bool clearFilter(); }; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/PfRingDeviceList.h b/Pcap++/header/PfRingDeviceList.h index d800862c21..e0011cf897 100644 --- a/Pcap++/header/PfRingDeviceList.h +++ b/Pcap++/header/PfRingDeviceList.h @@ -8,16 +8,16 @@ /// @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 + * 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 { @@ -27,6 +27,7 @@ namespace pcpp std::string m_PfRingVersion; PfRingDeviceList(); + public: PfRingDeviceList(const PfRingDeviceList&) = delete; PfRingDeviceList(PfRingDeviceList&&) noexcept = delete; @@ -47,22 +48,28 @@ namespace pcpp * 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; } + 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 */ - PfRingDevice* getPfRingDeviceByName(const std::string &devName) const; + PfRingDevice* getPfRingDeviceByName(const std::string& devName) const; /** * Get installed PF_RING version * @return A string representing PF_RING version */ - std::string getPfRingVersion() const { return m_PfRingVersion; } + std::string getPfRingVersion() const + { + return m_PfRingVersion; + } }; -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/header/RawSocketDevice.h b/Pcap++/header/RawSocketDevice.h index d0aba6ba09..254af4e186 100644 --- a/Pcap++/header/RawSocketDevice.h +++ b/Pcap++/header/RawSocketDevice.h @@ -6,40 +6,40 @@ #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 + * 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. + * 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 */ @@ -49,18 +49,19 @@ namespace pcpp RecvSuccess = 0, /** 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 */ 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); @@ -71,39 +72,39 @@ namespace pcpp /** * 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 + * - 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. + * 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. + * @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 + * - 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 + * 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[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 */ @@ -115,16 +116,16 @@ namespace pcpp * 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 + * @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 + * 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 @@ -145,7 +146,6 @@ namespace pcpp void close() override; private: - enum SocketFamily { Ethernet = 0, @@ -158,6 +158,5 @@ namespace pcpp IPAddress m_InterfaceIP; RecvPacketResult getError(int& errorCode) const; - }; -} +} // namespace pcpp diff --git a/Pcap++/header/WinPcapLiveDevice.h b/Pcap++/header/WinPcapLiveDevice.h index 153f80d3d2..9cc5a501a3 100644 --- a/Pcap++/header/WinPcapLiveDevice.h +++ b/Pcap++/header/WinPcapLiveDevice.h @@ -4,62 +4,77 @@ /// @file -#include "PcapLiveDevice.h" +# 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 + * 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; + protected: int m_MinAmountOfDataToCopyFromKernelToApplication; // c'tor is not public, there should be only one for every interface (created by PcapLiveDeviceList) WinPcapLiveDevice(pcap_if_t* iface, bool calculateMTU, bool calculateMacAddress, bool calculateDefaultGateway); // copy c'tor is not public - WinPcapLiveDevice( const WinPcapLiveDevice& other ); + WinPcapLiveDevice(const WinPcapLiveDevice& other); WinPcapLiveDevice& operator=(const WinPcapLiveDevice& other); public: - virtual LiveDeviceType getDeviceType() const { return WinPcapDevice; } + virtual LiveDeviceType getDeviceType() const + { + return WinPcapDevice; + } - bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie); - bool startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie); - bool startCapture(RawPacketVector& capturedPacketsVector) { return PcapLiveDevice::startCapture(capturedPacketsVector); } + bool startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, + int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, + void* onStatsUpdateUserCookie); + bool startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, + void* onStatsUpdateUserCookie); + bool startCapture(RawPacketVector& capturedPacketsVector) + { + return PcapLiveDevice::startCapture(capturedPacketsVector); + } 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 + * 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; } + int getMinAmountOfDataToCopyFromKernelToApplication() const + { + return m_MinAmountOfDataToCopyFromKernelToApplication; + } protected: WinPcapLiveDevice* cloneInternal(pcap_if_t& devInterface) const override; }; -} // namespace pcpp +} // namespace pcpp -#endif // _WIN32 +#endif // _WIN32 diff --git a/Pcap++/header/XdpDevice.h b/Pcap++/header/XdpDevice.h index cf1a0bb9c0..7e573e2304 100644 --- a/Pcap++/header/XdpDevice.h +++ b/Pcap++/header/XdpDevice.h @@ -7,8 +7,8 @@ #include /** -* \namespace pcpp -* \brief The main namespace for the PcapPlusPlus lib + * \namespace pcpp + * \brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { @@ -17,13 +17,12 @@ namespace pcpp * 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. + * 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 @@ -46,7 +45,8 @@ namespace pcpp */ 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 */ DriverMode = 2, @@ -105,19 +105,17 @@ namespace pcpp * @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] 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 + * @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, - uint16_t rxTxBatchSize = 0) + 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, + uint16_t rxTxBatchSize = 0) { this->attachMode = attachMode; this->umemNumFrames = umemNumFrames; @@ -229,8 +227,8 @@ namespace pcpp * @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. + * @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); @@ -251,7 +249,8 @@ namespace pcpp * @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); + bool sendPackets(const RawPacketVector& packets, bool waitForTxCompletion = false, + int waitForTxCompletionTimeoutMS = 5000); /** * Send an array of packets. @@ -265,12 +264,16 @@ namespace pcpp * @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); + 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 */ - XdpDeviceConfiguration* getConfig() const { return m_Config; } + XdpDeviceConfiguration* getConfig() const + { + return m_Config; + } /** * @return Current device statistics @@ -281,12 +284,19 @@ namespace pcpp class XdpUmem { public: - explicit XdpUmem(uint16_t numFrames, uint16_t frameSize, uint32_t fillRingSize, uint32_t completionRingSize); + explicit XdpUmem(uint16_t numFrames, uint16_t frameSize, uint32_t fillRingSize, + uint32_t completionRingSize); virtual ~XdpUmem(); - inline uint16_t getFrameSize() const { return m_FrameSize; } - inline uint16_t getFrameCount() const { return m_FrameCount; } + inline uint16_t getFrameSize() const + { + return m_FrameSize; + } + inline uint16_t getFrameCount() const + { + return m_FrameCount; + } std::pair> allocateFrames(uint32_t count); @@ -296,9 +306,15 @@ namespace pcpp void setData(uint64_t addr, const uint8_t* data, size_t dataLen); - inline size_t getFreeFrameCount() { return m_FreeFrames.size(); } + inline size_t getFreeFrameCount() + { + return m_FreeFrames.size(); + } - inline void* getInfo() { return m_UmemInfo; } + inline void* getInfo() + { + return m_UmemInfo; + } private: void* m_UmemInfo; @@ -321,12 +337,14 @@ namespace pcpp std::string m_InterfaceName; XdpDeviceConfiguration* m_Config; bool m_ReceivingPackets; - XdpUmem* m_Umem; + XdpUmem* m_Umem; void* m_SocketInfo; XdpDeviceStats m_Stats; XdpPrevDeviceStats m_PrevStats; - bool sendPackets(const std::function& getPacketAt, const std::function& getPacketCount, bool waitForTxCompletion = false, int waitForTxCompletionTimeoutMS = 5000); + bool sendPackets(const std::function& getPacketAt, + const std::function& getPacketCount, bool waitForTxCompletion = false, + int waitForTxCompletionTimeoutMS = 5000); bool populateFillRing(uint32_t count, uint32_t rxId = 0); bool populateFillRing(const std::vector& addresses, uint32_t rxId); uint32_t checkCompletionRing(); @@ -335,4 +353,4 @@ namespace pcpp bool initConfig(); bool getSocketStats(); }; -} +} // namespace pcpp diff --git a/Pcap++/src/DeviceUtils.cpp b/Pcap++/src/DeviceUtils.cpp index 785c726b47..25bb5e5f20 100644 --- a/Pcap++/src/DeviceUtils.cpp +++ b/Pcap++/src/DeviceUtils.cpp @@ -23,5 +23,5 @@ namespace pcpp // Assigns the raw pointer to the smart pointer with specialized deleter. return std::unique_ptr(interfaceListRaw); } - } -} + } // namespace internal +} // namespace pcpp diff --git a/Pcap++/src/DpdkDevice.cpp b/Pcap++/src/DpdkDevice.cpp index 27e6bec5a7..7f0bfc185e 100644 --- a/Pcap++/src/DpdkDevice.cpp +++ b/Pcap++/src/DpdkDevice.cpp @@ -2,1514 +2,1543 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModuleDpdkDevice - -#define __STDC_LIMIT_MACROS -#define __STDC_FORMAT_MACROS - -#include "DpdkDevice.h" -#include "DpdkDeviceList.h" -#include "Logger.h" -#include "rte_version.h" -#if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) -#include "rte_bus_pci.h" -#endif -#include "rte_pci.h" -#include "rte_config.h" -#include "rte_ethdev.h" -#include "rte_errno.h" -#include "rte_malloc.h" -#include "rte_cycles.h" -#include -#include -#include - -#define MAX_BURST_SIZE 64 - -#define MEMPOOL_CACHE_SIZE 256 - -#if (RTE_VER_YEAR < 21) || (RTE_VER_YEAR == 21 && RTE_VER_MONTH < 11) -#define GET_MASTER_CORE rte_get_master_lcore -#else -#define GET_MASTER_CORE rte_get_main_lcore -#endif +# define LOG_MODULE PcapLogModuleDpdkDevice + +# define __STDC_LIMIT_MACROS +# define __STDC_FORMAT_MACROS + +# include "DpdkDevice.h" +# include "DpdkDeviceList.h" +# include "Logger.h" +# include "rte_version.h" +# if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) +# include "rte_bus_pci.h" +# endif +# include "rte_pci.h" +# include "rte_config.h" +# include "rte_ethdev.h" +# include "rte_errno.h" +# include "rte_malloc.h" +# include "rte_cycles.h" +# include +# include +# include + +# define MAX_BURST_SIZE 64 + +# define MEMPOOL_CACHE_SIZE 256 + +# if (RTE_VER_YEAR < 21) || (RTE_VER_YEAR == 21 && RTE_VER_MONTH < 11) +# define GET_MASTER_CORE rte_get_master_lcore +# else +# define GET_MASTER_CORE rte_get_main_lcore +# endif namespace pcpp { -/** - * ================ - * Class DpdkDevice - * ================ - */ - -#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 */ -#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 -#define DPDK_CONFIG_MQ_NO_RSS ETH_MQ_RX_NONE -#else -#define DPDK_CONFIG_ETH_LINK_FULL_DUPLEX RTE_ETH_LINK_FULL_DUPLEX -#define DPDK_CONFIG_MQ_RSS RTE_ETH_MQ_RX_RSS -#define DPDK_CONFIG_MQ_NO_RSS RTE_ETH_MQ_RX_NONE -#endif - -#if (RTE_VER_YEAR < 22) || (RTE_VER_YEAR == 22 && RTE_VER_MONTH < 11) -#define DPDK_CONFIG_ETH_RSS_IPV4 ETH_RSS_IPV4 -#define DPDK_CONFIG_ETH_RSS_FRAG_IPV4 ETH_RSS_FRAG_IPV4 -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP ETH_RSS_NONFRAG_IPV4_TCP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP ETH_RSS_NONFRAG_IPV4_UDP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP ETH_RSS_NONFRAG_IPV4_SCTP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER ETH_RSS_NONFRAG_IPV4_OTHER -#define DPDK_CONFIG_ETH_RSS_IPV6 ETH_RSS_IPV6 -#define DPDK_CONFIG_ETH_RSS_FRAG_IPV6 ETH_RSS_FRAG_IPV6 -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP ETH_RSS_NONFRAG_IPV6_TCP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP ETH_RSS_NONFRAG_IPV6_UDP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP ETH_RSS_NONFRAG_IPV6_SCTP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER ETH_RSS_NONFRAG_IPV6_OTHER -#define DPDK_CONFIG_ETH_RSS_L2_PAYLOAD ETH_RSS_L2_PAYLOAD -#define DPDK_CONFIG_ETH_RSS_IPV6_EX ETH_RSS_IPV6_EX -#define DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX ETH_RSS_IPV6_TCP_EX -#define DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX ETH_RSS_IPV6_UDP_EX -#define DPDK_CONFIG_ETH_RSS_PORT ETH_RSS_PORT -#define DPDK_CONFIG_ETH_RSS_VXLAN ETH_RSS_VXLAN -#define DPDK_CONFIG_ETH_RSS_GENEVE ETH_RSS_GENEVE -#define DPDK_CONFIG_ETH_RSS_NVGRE ETH_RSS_NVGRE -#else -#define DPDK_CONFIG_ETH_RSS_IPV4 RTE_ETH_RSS_IPV4 -#define DPDK_CONFIG_ETH_RSS_FRAG_IPV4 RTE_ETH_RSS_FRAG_IPV4 -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP RTE_ETH_RSS_NONFRAG_IPV4_TCP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP RTE_ETH_RSS_NONFRAG_IPV4_UDP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP RTE_ETH_RSS_NONFRAG_IPV4_SCTP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER RTE_ETH_RSS_NONFRAG_IPV4_OTHER -#define DPDK_CONFIG_ETH_RSS_IPV6 RTE_ETH_RSS_IPV6 -#define DPDK_CONFIG_ETH_RSS_FRAG_IPV6 RTE_ETH_RSS_FRAG_IPV6 -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP RTE_ETH_RSS_NONFRAG_IPV6_TCP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP RTE_ETH_RSS_NONFRAG_IPV6_UDP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP RTE_ETH_RSS_NONFRAG_IPV6_SCTP -#define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER RTE_ETH_RSS_NONFRAG_IPV6_OTHER -#define DPDK_CONFIG_ETH_RSS_L2_PAYLOAD RTE_ETH_RSS_L2_PAYLOAD -#define DPDK_CONFIG_ETH_RSS_IPV6_EX RTE_ETH_RSS_IPV6_EX -#define DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX RTE_ETH_RSS_IPV6_TCP_EX -#define DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX RTE_ETH_RSS_IPV6_UDP_EX -#define DPDK_CONFIG_ETH_RSS_PORT RTE_ETH_RSS_PORT -#define DPDK_CONFIG_ETH_RSS_VXLAN RTE_ETH_RSS_VXLAN -#define DPDK_CONFIG_ETH_RSS_GENEVE RTE_ETH_RSS_GENEVE -#define DPDK_CONFIG_ETH_RSS_NVGRE RTE_ETH_RSS_NVGRE -#endif - - -//RSS random key: -uint8_t DpdkDevice::m_RSSKey[40] = { - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + /** + * ================ + * Class DpdkDevice + * ================ + */ + +# 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 */ +# 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 +# define DPDK_CONFIG_MQ_NO_RSS ETH_MQ_RX_NONE +# else +# define DPDK_CONFIG_ETH_LINK_FULL_DUPLEX RTE_ETH_LINK_FULL_DUPLEX +# define DPDK_CONFIG_MQ_RSS RTE_ETH_MQ_RX_RSS +# define DPDK_CONFIG_MQ_NO_RSS RTE_ETH_MQ_RX_NONE +# endif + +# if (RTE_VER_YEAR < 22) || (RTE_VER_YEAR == 22 && RTE_VER_MONTH < 11) +# define DPDK_CONFIG_ETH_RSS_IPV4 ETH_RSS_IPV4 +# define DPDK_CONFIG_ETH_RSS_FRAG_IPV4 ETH_RSS_FRAG_IPV4 +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP ETH_RSS_NONFRAG_IPV4_TCP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP ETH_RSS_NONFRAG_IPV4_UDP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP ETH_RSS_NONFRAG_IPV4_SCTP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER ETH_RSS_NONFRAG_IPV4_OTHER +# define DPDK_CONFIG_ETH_RSS_IPV6 ETH_RSS_IPV6 +# define DPDK_CONFIG_ETH_RSS_FRAG_IPV6 ETH_RSS_FRAG_IPV6 +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP ETH_RSS_NONFRAG_IPV6_TCP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP ETH_RSS_NONFRAG_IPV6_UDP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP ETH_RSS_NONFRAG_IPV6_SCTP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER ETH_RSS_NONFRAG_IPV6_OTHER +# define DPDK_CONFIG_ETH_RSS_L2_PAYLOAD ETH_RSS_L2_PAYLOAD +# define DPDK_CONFIG_ETH_RSS_IPV6_EX ETH_RSS_IPV6_EX +# define DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX ETH_RSS_IPV6_TCP_EX +# define DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX ETH_RSS_IPV6_UDP_EX +# define DPDK_CONFIG_ETH_RSS_PORT ETH_RSS_PORT +# define DPDK_CONFIG_ETH_RSS_VXLAN ETH_RSS_VXLAN +# define DPDK_CONFIG_ETH_RSS_GENEVE ETH_RSS_GENEVE +# define DPDK_CONFIG_ETH_RSS_NVGRE ETH_RSS_NVGRE +# else +# define DPDK_CONFIG_ETH_RSS_IPV4 RTE_ETH_RSS_IPV4 +# define DPDK_CONFIG_ETH_RSS_FRAG_IPV4 RTE_ETH_RSS_FRAG_IPV4 +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP RTE_ETH_RSS_NONFRAG_IPV4_TCP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP RTE_ETH_RSS_NONFRAG_IPV4_UDP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP RTE_ETH_RSS_NONFRAG_IPV4_SCTP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER RTE_ETH_RSS_NONFRAG_IPV4_OTHER +# define DPDK_CONFIG_ETH_RSS_IPV6 RTE_ETH_RSS_IPV6 +# define DPDK_CONFIG_ETH_RSS_FRAG_IPV6 RTE_ETH_RSS_FRAG_IPV6 +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP RTE_ETH_RSS_NONFRAG_IPV6_TCP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP RTE_ETH_RSS_NONFRAG_IPV6_UDP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP RTE_ETH_RSS_NONFRAG_IPV6_SCTP +# define DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER RTE_ETH_RSS_NONFRAG_IPV6_OTHER +# define DPDK_CONFIG_ETH_RSS_L2_PAYLOAD RTE_ETH_RSS_L2_PAYLOAD +# define DPDK_CONFIG_ETH_RSS_IPV6_EX RTE_ETH_RSS_IPV6_EX +# define DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX RTE_ETH_RSS_IPV6_TCP_EX +# define DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX RTE_ETH_RSS_IPV6_UDP_EX +# define DPDK_CONFIG_ETH_RSS_PORT RTE_ETH_RSS_PORT +# define DPDK_CONFIG_ETH_RSS_VXLAN RTE_ETH_RSS_VXLAN +# define DPDK_CONFIG_ETH_RSS_GENEVE RTE_ETH_RSS_GENEVE +# define DPDK_CONFIG_ETH_RSS_NVGRE RTE_ETH_RSS_NVGRE +# endif + + // RSS random key: + uint8_t DpdkDevice::m_RSSKey[40] = { + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, + 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, }; -DpdkDevice::DpdkDevice(int port, uint32_t mBufPoolSize, uint16_t mBufDataSize) - : m_Id(port), m_MacAddress(MacAddress::Zero), m_MBufDataSize(mBufDataSize < 1 ? RTE_MBUF_DEFAULT_BUF_SIZE : mBufDataSize) -{ - std::ostringstream deviceNameStream; - deviceNameStream << "DPDK_" << m_Id; - m_DeviceName = deviceNameStream.str(); - m_DeviceSocketId = rte_eth_dev_socket_id(m_Id); - -#if (RTE_VER_YEAR > 19) || (RTE_VER_YEAR == 19 && RTE_VER_MONTH >= 8) - struct rte_ether_addr etherAddr; -#else - struct ether_addr etherAddr; -#endif - rte_eth_macaddr_get((uint8_t) m_Id, ðerAddr); - m_MacAddress = MacAddress(etherAddr.addr_bytes[0], etherAddr.addr_bytes[1], - etherAddr.addr_bytes[2], etherAddr.addr_bytes[3], - etherAddr.addr_bytes[4], etherAddr.addr_bytes[5]); - - rte_eth_dev_get_mtu((uint8_t) m_Id, &m_DeviceMtu); - - char mBufMemPoolName[32]; - sprintf(mBufMemPoolName, "MBufMemPool%d", m_Id); - if (!initMemPool(m_MBufMempool, mBufMemPoolName, mBufPoolSize)) - { - PCPP_LOG_ERROR("Could not initialize mBuf mempool. Device not initialized"); - return; - } - - m_NumOfRxQueuesOpened = 0; - m_NumOfTxQueuesOpened = 0; - - setDeviceInfo(); - - memset(&m_PrevStats, 0 ,sizeof(m_PrevStats)); + DpdkDevice::DpdkDevice(int port, uint32_t mBufPoolSize, uint16_t mBufDataSize) + : m_Id(port), m_MacAddress(MacAddress::Zero), + m_MBufDataSize(mBufDataSize < 1 ? RTE_MBUF_DEFAULT_BUF_SIZE : mBufDataSize) + { + std::ostringstream deviceNameStream; + deviceNameStream << "DPDK_" << m_Id; + m_DeviceName = deviceNameStream.str(); + m_DeviceSocketId = rte_eth_dev_socket_id(m_Id); + +# if (RTE_VER_YEAR > 19) || (RTE_VER_YEAR == 19 && RTE_VER_MONTH >= 8) + struct rte_ether_addr etherAddr; +# else + struct ether_addr etherAddr; +# endif + rte_eth_macaddr_get((uint8_t)m_Id, ðerAddr); + m_MacAddress = MacAddress(etherAddr.addr_bytes[0], etherAddr.addr_bytes[1], etherAddr.addr_bytes[2], + etherAddr.addr_bytes[3], etherAddr.addr_bytes[4], etherAddr.addr_bytes[5]); + + rte_eth_dev_get_mtu((uint8_t)m_Id, &m_DeviceMtu); + + char mBufMemPoolName[32]; + sprintf(mBufMemPoolName, "MBufMemPool%d", m_Id); + if (!initMemPool(m_MBufMempool, mBufMemPoolName, mBufPoolSize)) + { + PCPP_LOG_ERROR("Could not initialize mBuf mempool. Device not initialized"); + return; + } - m_TxBuffers = NULL; - m_TxBufferLastDrainTsc = NULL; + m_NumOfRxQueuesOpened = 0; + m_NumOfTxQueuesOpened = 0; - m_DeviceOpened = false; - m_WasOpened = false; - m_StopThread = true; -} + setDeviceInfo(); -DpdkDevice::~DpdkDevice() -{ - if (m_TxBuffers != NULL) - delete [] m_TxBuffers; + memset(&m_PrevStats, 0, sizeof(m_PrevStats)); - if (m_TxBufferLastDrainTsc != NULL) - delete [] m_TxBufferLastDrainTsc; -} - -uint32_t DpdkDevice::getCurrentCoreId() const -{ - return rte_lcore_id(); -} + m_TxBuffers = NULL; + m_TxBufferLastDrainTsc = NULL; -bool DpdkDevice::setMtu(uint16_t newMtu) -{ - int res = rte_eth_dev_set_mtu(m_Id, newMtu); - if (res != 0) - { - PCPP_LOG_ERROR("Couldn't set device MTU. DPDK error: " << res); - return false; + m_DeviceOpened = false; + m_WasOpened = false; + m_StopThread = true; } - PCPP_LOG_DEBUG("Managed to set MTU from " << m_DeviceMtu << " to " << newMtu); - m_DeviceMtu = newMtu; - return true; -} - -bool DpdkDevice::openMultiQueues(uint16_t numOfRxQueuesToOpen, uint16_t numOfTxQueuesToOpen, const DpdkDeviceConfiguration& config) -{ - if (m_DeviceOpened) + DpdkDevice::~DpdkDevice() { - PCPP_LOG_ERROR("Device already opened"); - return false; - } + if (m_TxBuffers != NULL) + delete[] m_TxBuffers; - // There is a VMXNET3 limitation that when opening a device with a certain number of RX+TX queues - // it's impossible to close it and open it again with a larger number of RX+TX queues. So for this - // PMD I made a patch to open the device in the first time with maximum RX & TX queue, close it - // immediately and open it again with number of queues the user wanted to - if (!m_WasOpened && m_PMDType == PMD_VMXNET3) - { - m_WasOpened = true; - openMultiQueues(getTotalNumOfRxQueues(), getTotalNumOfTxQueues(), config); - close(); + if (m_TxBufferLastDrainTsc != NULL) + delete[] m_TxBufferLastDrainTsc; } - m_Config = config; - - if (!configurePort(numOfRxQueuesToOpen, numOfTxQueuesToOpen)) + uint32_t DpdkDevice::getCurrentCoreId() const { - m_DeviceOpened = false; - return false; + return rte_lcore_id(); } - clearCoreConfiguration(); - - if (!initQueues(numOfRxQueuesToOpen, numOfTxQueuesToOpen)) - return false; - - if (!startDevice()) + bool DpdkDevice::setMtu(uint16_t newMtu) { - PCPP_LOG_ERROR("failed to start device " << m_Id); - m_DeviceOpened = false; - return false; - } - - m_NumOfRxQueuesOpened = numOfRxQueuesToOpen; - m_NumOfTxQueuesOpened = numOfTxQueuesToOpen; - - rte_eth_stats_reset(m_Id); - - m_DeviceOpened = true; - return m_DeviceOpened; -} - + int res = rte_eth_dev_set_mtu(m_Id, newMtu); + if (res != 0) + { + PCPP_LOG_ERROR("Couldn't set device MTU. DPDK error: " << res); + return false; + } -void DpdkDevice::close() -{ - if (!m_DeviceOpened) - { - PCPP_LOG_DEBUG("Trying to close device [" << m_DeviceName << "] but device is already closed"); - return; - } - stopCapture(); - clearCoreConfiguration(); - m_NumOfRxQueuesOpened = 0; - m_NumOfTxQueuesOpened = 0; - rte_eth_dev_stop(m_Id); - PCPP_LOG_DEBUG("Called rte_eth_dev_stop for device [" << m_DeviceName << "]"); - - if (m_TxBuffers != NULL) - { - delete [] m_TxBuffers; - m_TxBuffers = NULL; + PCPP_LOG_DEBUG("Managed to set MTU from " << m_DeviceMtu << " to " << newMtu); + m_DeviceMtu = newMtu; + return true; } - if (m_TxBufferLastDrainTsc != NULL) + bool DpdkDevice::openMultiQueues(uint16_t numOfRxQueuesToOpen, uint16_t numOfTxQueuesToOpen, + const DpdkDeviceConfiguration& config) { - delete [] m_TxBufferLastDrainTsc; - m_TxBufferLastDrainTsc = NULL; - } - - m_DeviceOpened = false; -} - + if (m_DeviceOpened) + { + PCPP_LOG_ERROR("Device already opened"); + return false; + } -bool DpdkDevice::configurePort(uint8_t numOfRxQueues, uint8_t numOfTxQueues) -{ - if (numOfRxQueues > getTotalNumOfRxQueues()) - { - PCPP_LOG_ERROR("Could not open more than " << getTotalNumOfRxQueues() << " RX queues"); - return false; - } + // There is a VMXNET3 limitation that when opening a device with a certain number of RX+TX queues + // it's impossible to close it and open it again with a larger number of RX+TX queues. So for this + // PMD I made a patch to open the device in the first time with maximum RX & TX queue, close it + // immediately and open it again with number of queues the user wanted to + if (!m_WasOpened && m_PMDType == PMD_VMXNET3) + { + m_WasOpened = true; + openMultiQueues(getTotalNumOfRxQueues(), getTotalNumOfTxQueues(), config); + close(); + } - if (numOfTxQueues > getTotalNumOfTxQueues()) - { - PCPP_LOG_ERROR("Could not open more than " << getTotalNumOfTxQueues() << " TX queues"); - return false; - } + m_Config = config; - // if PMD doesn't support RSS, set RSS HF to 0 - if (getSupportedRssHashFunctions() == 0 && getConfiguredRssHashFunction() != 0) - { - PCPP_LOG_DEBUG("PMD '" << m_PMDName << "' doesn't support RSS, setting RSS hash functions to 0"); - m_Config.rssHashFunction = RSS_NONE; - } + if (!configurePort(numOfRxQueuesToOpen, numOfTxQueuesToOpen)) + { + m_DeviceOpened = false; + return false; + } - if (!isDeviceSupportRssHashFunction(getConfiguredRssHashFunction())) - { - PCPP_LOG_ERROR("PMD '" << m_PMDName << "' doesn't support the request RSS hash functions 0x" << std::hex << getConfiguredRssHashFunction()); - return false; - } + clearCoreConfiguration(); - // verify num of RX queues is nonzero - if (numOfRxQueues == 0) - { - PCPP_LOG_ERROR("Num of RX queues must be nonzero."); - return false; - } + if (!initQueues(numOfRxQueuesToOpen, numOfTxQueuesToOpen)) + return false; - // verify num of RX queues is power of 2 for virtual devices - if (isVirtual()) - { - bool isRxQueuePowerOfTwo = !(numOfRxQueues & (numOfRxQueues - 1)); - if (!isRxQueuePowerOfTwo) + if (!startDevice()) { - PCPP_LOG_ERROR("Num of RX queues must be power of 2 when device is virtual (because of DPDK limitation). Attempted to open device with " << numOfRxQueues << " RX queues"); + PCPP_LOG_ERROR("failed to start device " << m_Id); + m_DeviceOpened = false; return false; } - } - struct rte_eth_conf portConf; - memset(&portConf,0,sizeof(rte_eth_conf)); -#if (RTE_VER_YEAR < 22) || (RTE_VER_YEAR == 22 && RTE_VER_MONTH < 11) - portConf.rxmode.split_hdr_size = DPDK_CONFIG_SPLIT_HEADER_SIZE; -#endif -#if (RTE_VER_YEAR < 18) || (RTE_VER_YEAR == 18 && RTE_VER_MONTH < 8) - portConf.rxmode.header_split = DPDK_CONFIG_HEADER_SPLIT; - portConf.rxmode.hw_ip_checksum = DPDK_CONFIG_HW_IP_CHECKSUM; - portConf.rxmode.hw_vlan_filter = DPDK_CONFIG_HW_VLAN_FILTER; - portConf.rxmode.jumbo_frame = DPDK_CONFIG_JUMBO_FRAME; - portConf.rxmode.hw_strip_crc = DPDK_CONFIG_HW_STRIP_CRC; -#endif - // Enable RSS only if hardware supports it and the user wants to use it - if (m_Config.rssHashFunction == RSS_NONE) - { - portConf.rxmode.mq_mode = DPDK_CONFIG_MQ_NO_RSS; - } - else - { - portConf.rxmode.mq_mode = DPDK_CONFIG_MQ_RSS; - } + m_NumOfRxQueuesOpened = numOfRxQueuesToOpen; + m_NumOfTxQueuesOpened = numOfTxQueuesToOpen; - portConf.rx_adv_conf.rss_conf.rss_key = m_Config.rssKey; - portConf.rx_adv_conf.rss_conf.rss_key_len = m_Config.rssKeyLength; - portConf.rx_adv_conf.rss_conf.rss_hf = convertRssHfToDpdkRssHf(getConfiguredRssHashFunction()); + rte_eth_stats_reset(m_Id); - int res = rte_eth_dev_configure((uint8_t) m_Id, numOfRxQueues, numOfTxQueues, &portConf); - if (res < 0) - { - PCPP_LOG_ERROR("Failed to configure device [" << m_DeviceName << "]. error is: '" << rte_strerror(res) << "' [Error code: " << res << "]"); - return false; + m_DeviceOpened = true; + return m_DeviceOpened; } - PCPP_LOG_DEBUG("Successfully called rte_eth_dev_configure for device [" << m_DeviceName << "] with " << numOfRxQueues << " RX queues and " << numOfTxQueues << " TX queues"); + void DpdkDevice::close() + { + if (!m_DeviceOpened) + { + PCPP_LOG_DEBUG("Trying to close device [" << m_DeviceName << "] but device is already closed"); + return; + } + stopCapture(); + clearCoreConfiguration(); + m_NumOfRxQueuesOpened = 0; + m_NumOfTxQueuesOpened = 0; + rte_eth_dev_stop(m_Id); + PCPP_LOG_DEBUG("Called rte_eth_dev_stop for device [" << m_DeviceName << "]"); - return true; -} + if (m_TxBuffers != NULL) + { + delete[] m_TxBuffers; + m_TxBuffers = NULL; + } -bool DpdkDevice::initQueues(uint8_t numOfRxQueuesToInit, uint8_t numOfTxQueuesToInit) -{ - rte_eth_dev_info devInfo; - rte_eth_dev_info_get(m_Id, &devInfo); - if (numOfRxQueuesToInit > devInfo.max_rx_queues) - { - PCPP_LOG_ERROR("Num of RX queues requested for open [" << numOfRxQueuesToInit << "] is larger than RX queues available in NIC [" << devInfo.max_rx_queues << "]"); - return false; - } + if (m_TxBufferLastDrainTsc != NULL) + { + delete[] m_TxBufferLastDrainTsc; + m_TxBufferLastDrainTsc = NULL; + } - if (numOfTxQueuesToInit > devInfo.max_tx_queues) - { - PCPP_LOG_ERROR("Num of TX queues requested for open [" << numOfTxQueuesToInit << "] is larger than TX queues available in NIC [" << devInfo.max_tx_queues << "]"); - return false; + m_DeviceOpened = false; } - for (uint8_t i = 0; i < numOfRxQueuesToInit; i++) + bool DpdkDevice::configurePort(uint8_t numOfRxQueues, uint8_t numOfTxQueues) { - int ret = rte_eth_rx_queue_setup((uint8_t) m_Id, i, - m_Config.receiveDescriptorsNumber, m_DeviceSocketId, - NULL, m_MBufMempool); + if (numOfRxQueues > getTotalNumOfRxQueues()) + { + PCPP_LOG_ERROR("Could not open more than " << getTotalNumOfRxQueues() << " RX queues"); + return false; + } - if (ret < 0) + if (numOfTxQueues > getTotalNumOfTxQueues()) { - PCPP_LOG_ERROR("Failed to init RX queue for device [" << m_DeviceName << "]. Error was: '" << rte_strerror(ret) << "' [Error code: " << ret << "]"); + PCPP_LOG_ERROR("Could not open more than " << getTotalNumOfTxQueues() << " TX queues"); return false; } - } - PCPP_LOG_DEBUG("Successfully initialized " << numOfRxQueuesToInit << " RX queues for device [" << m_DeviceName << "]"); + // if PMD doesn't support RSS, set RSS HF to 0 + if (getSupportedRssHashFunctions() == 0 && getConfiguredRssHashFunction() != 0) + { + PCPP_LOG_DEBUG("PMD '" << m_PMDName << "' doesn't support RSS, setting RSS hash functions to 0"); + m_Config.rssHashFunction = RSS_NONE; + } - for (uint8_t i = 0; i < numOfTxQueuesToInit; i++) - { - int ret = rte_eth_tx_queue_setup((uint8_t) m_Id, i, - m_Config.transmitDescriptorsNumber, - m_DeviceSocketId, NULL); - if (ret < 0) + if (!isDeviceSupportRssHashFunction(getConfiguredRssHashFunction())) { - PCPP_LOG_ERROR("Failed to init TX queue #" << i << " for port " << m_Id << ". Error was: '" << rte_strerror(ret) << "' [Error code: " << ret << "]"); + PCPP_LOG_ERROR("PMD '" << m_PMDName << "' doesn't support the request RSS hash functions 0x" << std::hex + << getConfiguredRssHashFunction()); return false; } - } - if (m_TxBuffers != NULL) - delete [] m_TxBuffers; + // verify num of RX queues is nonzero + if (numOfRxQueues == 0) + { + PCPP_LOG_ERROR("Num of RX queues must be nonzero."); + return false; + } - if (m_TxBufferLastDrainTsc != NULL) - delete [] m_TxBufferLastDrainTsc; + // verify num of RX queues is power of 2 for virtual devices + if (isVirtual()) + { + bool isRxQueuePowerOfTwo = !(numOfRxQueues & (numOfRxQueues - 1)); + if (!isRxQueuePowerOfTwo) + { + PCPP_LOG_ERROR( + "Num of RX queues must be power of 2 when device is virtual (because of DPDK limitation). Attempted to open device with " + << numOfRxQueues << " RX queues"); + return false; + } + } - m_TxBuffers = new rte_eth_dev_tx_buffer*[numOfTxQueuesToInit]; - m_TxBufferLastDrainTsc = new uint64_t[numOfTxQueuesToInit]; - memset(m_TxBufferLastDrainTsc, 0, sizeof(uint64_t)*numOfTxQueuesToInit); + struct rte_eth_conf portConf; + memset(&portConf, 0, sizeof(rte_eth_conf)); +# if (RTE_VER_YEAR < 22) || (RTE_VER_YEAR == 22 && RTE_VER_MONTH < 11) + portConf.rxmode.split_hdr_size = DPDK_CONFIG_SPLIT_HEADER_SIZE; +# endif +# if (RTE_VER_YEAR < 18) || (RTE_VER_YEAR == 18 && RTE_VER_MONTH < 8) + portConf.rxmode.header_split = DPDK_CONFIG_HEADER_SPLIT; + portConf.rxmode.hw_ip_checksum = DPDK_CONFIG_HW_IP_CHECKSUM; + portConf.rxmode.hw_vlan_filter = DPDK_CONFIG_HW_VLAN_FILTER; + portConf.rxmode.jumbo_frame = DPDK_CONFIG_JUMBO_FRAME; + portConf.rxmode.hw_strip_crc = DPDK_CONFIG_HW_STRIP_CRC; +# endif + // Enable RSS only if hardware supports it and the user wants to use it + if (m_Config.rssHashFunction == RSS_NONE) + { + portConf.rxmode.mq_mode = DPDK_CONFIG_MQ_NO_RSS; + } + else + { + portConf.rxmode.mq_mode = DPDK_CONFIG_MQ_RSS; + } - for (uint8_t i = 0; i < numOfTxQueuesToInit; i++) - { - m_TxBuffers[i] = (rte_eth_dev_tx_buffer*)rte_zmalloc_socket("tx_buffer", RTE_ETH_TX_BUFFER_SIZE(MAX_BURST_SIZE), 0, m_DeviceSocketId); + portConf.rx_adv_conf.rss_conf.rss_key = m_Config.rssKey; + portConf.rx_adv_conf.rss_conf.rss_key_len = m_Config.rssKeyLength; + portConf.rx_adv_conf.rss_conf.rss_hf = convertRssHfToDpdkRssHf(getConfiguredRssHashFunction()); - if (m_TxBuffers[i] == NULL) + int res = rte_eth_dev_configure((uint8_t)m_Id, numOfRxQueues, numOfTxQueues, &portConf); + if (res < 0) { - PCPP_LOG_ERROR("Failed to allocate TX buffer for port " << m_Id << " TX queue " << (int)i); + PCPP_LOG_ERROR("Failed to configure device [" << m_DeviceName << "]. error is: '" << rte_strerror(res) + << "' [Error code: " << res << "]"); return false; } - int res = rte_eth_tx_buffer_init(m_TxBuffers[i], MAX_BURST_SIZE); + PCPP_LOG_DEBUG("Successfully called rte_eth_dev_configure for device [" + << m_DeviceName << "] with " << numOfRxQueues << " RX queues and " << numOfTxQueues + << " TX queues"); - if (res != 0) + return true; + } + + bool DpdkDevice::initQueues(uint8_t numOfRxQueuesToInit, uint8_t numOfTxQueuesToInit) + { + rte_eth_dev_info devInfo; + rte_eth_dev_info_get(m_Id, &devInfo); + if (numOfRxQueuesToInit > devInfo.max_rx_queues) { - PCPP_LOG_ERROR("Failed to init TX buffer for port " << m_Id << " TX queue " << (int)i); + PCPP_LOG_ERROR("Num of RX queues requested for open [" << numOfRxQueuesToInit + << "] is larger than RX queues available in NIC [" + << devInfo.max_rx_queues << "]"); return false; } - } - m_TxBufferDrainTsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * m_Config.flushTxBufferTimeout; + if (numOfTxQueuesToInit > devInfo.max_tx_queues) + { + PCPP_LOG_ERROR("Num of TX queues requested for open [" << numOfTxQueuesToInit + << "] is larger than TX queues available in NIC [" + << devInfo.max_tx_queues << "]"); + return false; + } - memset(m_TxBufferLastDrainTsc, 0, sizeof(uint64_t)*numOfTxQueuesToInit); + for (uint8_t i = 0; i < numOfRxQueuesToInit; i++) + { + int ret = rte_eth_rx_queue_setup((uint8_t)m_Id, i, m_Config.receiveDescriptorsNumber, m_DeviceSocketId, + NULL, m_MBufMempool); - PCPP_LOG_DEBUG("Successfully initialized " << numOfTxQueuesToInit << " TX queues for device [" << m_DeviceName << "]"); + if (ret < 0) + { + PCPP_LOG_ERROR("Failed to init RX queue for device [" << m_DeviceName << "]. Error was: '" + << rte_strerror(ret) << "' [Error code: " << ret + << "]"); + return false; + } + } - return true; -} + PCPP_LOG_DEBUG("Successfully initialized " << numOfRxQueuesToInit << " RX queues for device [" << m_DeviceName + << "]"); + for (uint8_t i = 0; i < numOfTxQueuesToInit; i++) + { + int ret = + rte_eth_tx_queue_setup((uint8_t)m_Id, i, m_Config.transmitDescriptorsNumber, m_DeviceSocketId, NULL); + if (ret < 0) + { + PCPP_LOG_ERROR("Failed to init TX queue #" << i << " for port " << m_Id << ". Error was: '" + << rte_strerror(ret) << "' [Error code: " << ret << "]"); + return false; + } + } -bool DpdkDevice::initMemPool(struct rte_mempool*& memPool, const char* mempoolName, uint32_t mBufPoolSize) -{ - bool ret = false; + if (m_TxBuffers != NULL) + delete[] m_TxBuffers; - // create mbuf pool - memPool = rte_pktmbuf_pool_create(mempoolName, mBufPoolSize, MEMPOOL_CACHE_SIZE, 0, m_MBufDataSize, m_DeviceSocketId); - if (memPool == NULL) - { - PCPP_LOG_ERROR("Failed to create packets memory pool for port " << m_Id << ", pool name: " << mempoolName << ". Error was: '" << rte_strerror(rte_errno) << "' [Error code: " << rte_errno << "]"); - } - else - { - PCPP_LOG_DEBUG("Successfully initialized packets pool of size [" << mBufPoolSize << "] for device [" << m_DeviceName << "]"); - ret = true; - } - return ret; -} + if (m_TxBufferLastDrainTsc != NULL) + delete[] m_TxBufferLastDrainTsc; -bool DpdkDevice::startDevice() -{ - int ret = rte_eth_dev_start((uint8_t) m_Id); - if (ret < 0) - { - PCPP_LOG_ERROR("Failed to start device " << m_Id << ". Error is " << ret); - return false; - } + m_TxBuffers = new rte_eth_dev_tx_buffer*[numOfTxQueuesToInit]; + m_TxBufferLastDrainTsc = new uint64_t[numOfTxQueuesToInit]; + memset(m_TxBufferLastDrainTsc, 0, sizeof(uint64_t) * numOfTxQueuesToInit); - LinkStatus status; - getLinkStatus(status); - if (Logger::getInstance().isDebugEnabled(PcapLogModuleDpdkDevice)) - { - std::string linkStatus = (status.linkUp ? "up" : "down"); - std::string linkDuplex = (status.linkDuplex == LinkStatus::FULL_DUPLEX ? "full-duplex" : "half-duplex"); - PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] : Link " << linkStatus << "; Speed: " << status.linkSpeedMbps << " Mbps; " << linkDuplex); - } + for (uint8_t i = 0; i < numOfTxQueuesToInit; i++) + { + m_TxBuffers[i] = (rte_eth_dev_tx_buffer*)rte_zmalloc_socket( + "tx_buffer", RTE_ETH_TX_BUFFER_SIZE(MAX_BURST_SIZE), 0, m_DeviceSocketId); - rte_eth_promiscuous_enable((uint8_t) m_Id); - PCPP_LOG_DEBUG("Started device [" << m_DeviceName << "]"); + if (m_TxBuffers[i] == NULL) + { + PCPP_LOG_ERROR("Failed to allocate TX buffer for port " << m_Id << " TX queue " << (int)i); + return false; + } - return true; -} + int res = rte_eth_tx_buffer_init(m_TxBuffers[i], MAX_BURST_SIZE); + if (res != 0) + { + PCPP_LOG_ERROR("Failed to init TX buffer for port " << m_Id << " TX queue " << (int)i); + return false; + } + } -void DpdkDevice::clearCoreConfiguration() -{ - for (int i = 0; i < MAX_NUM_OF_CORES; i++) - { - m_CoreConfiguration[i].IsCoreInUse = false; - } -} + m_TxBufferDrainTsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * m_Config.flushTxBufferTimeout; -int DpdkDevice::getCoresInUseCount() const -{ - int res = 0; - for (int i = 0; i < MAX_NUM_OF_CORES; i++) - if (m_CoreConfiguration[i].IsCoreInUse) - res++; + memset(m_TxBufferLastDrainTsc, 0, sizeof(uint64_t) * numOfTxQueuesToInit); - return res; -} + PCPP_LOG_DEBUG("Successfully initialized " << numOfTxQueuesToInit << " TX queues for device [" << m_DeviceName + << "]"); -void DpdkDevice::setDeviceInfo() -{ - rte_eth_dev_info portInfo; - rte_eth_dev_info_get(m_Id, &portInfo); - m_PMDName = std::string(portInfo.driver_name); - - if (m_PMDName == "eth_bond") - m_PMDType = PMD_BOND; - else if (m_PMDName == "rte_em_pmd") - m_PMDType = PMD_E1000EM; - else if (m_PMDName == "rte_igb_pmd") - m_PMDType = PMD_IGB; - else if (m_PMDName == "rte_igbvf_pmd") - m_PMDType = PMD_IGBVF; - else if (m_PMDName == "rte_enic_pmd") - m_PMDType = PMD_ENIC; - else if (m_PMDName == "rte_pmd_fm10k") - m_PMDType = PMD_FM10K; - else if (m_PMDName == "rte_i40e_pmd" || m_PMDName == "net_i40e") - m_PMDType = PMD_I40E; - else if (m_PMDName == "rte_i40evf_pmd") - m_PMDType = PMD_I40EVF; - else if (m_PMDName == "rte_ixgbe_pmd") - m_PMDType = PMD_IXGBE; - else if (m_PMDName == "rte_ixgbevf_pmd") - m_PMDType = PMD_IXGBEVF; - else if (m_PMDName == "librte_pmd_mlx4") - m_PMDType = PMD_MLX4; - else if (m_PMDName == "eth_null") - m_PMDType = PMD_NULL; - else if (m_PMDName == "eth_pcap") - m_PMDType = PMD_PCAP; - else if (m_PMDName == "eth_ring") - m_PMDType = PMD_RING; - else if (m_PMDName == "rte_virtio_pmd") - m_PMDType = PMD_VIRTIO; - else if (m_PMDName == "rte_vmxnet3_pmd") - m_PMDType = PMD_VMXNET3; - else if (m_PMDName == "eth_xenvirt") - m_PMDType = PMD_XENVIRT; - else - m_PMDType = PMD_UNKNOWN; - -#if (RTE_VER_YEAR < 18) || (RTE_VER_YEAR == 18 && RTE_VER_MONTH < 5) // before 18.05 - char pciName[30]; - #if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) // 17.11 - 18.02 - rte_pci_device_name(&(portInfo.pci_dev->addr), pciName, 30); - #else // 16.11 - 17.11 - rte_eal_pci_device_name(&(portInfo.pci_dev->addr), pciName, 30); - #endif - m_PciAddress = std::string(pciName); -#elif (RTE_VER_YEAR < 22) || (RTE_VER_YEAR == 22 && RTE_VER_MONTH < 11) // before 22.11 - m_PciAddress = std::string(portInfo.device->name); -#else // 22.11 forward - m_PciAddress = std::string(rte_dev_name(portInfo.device)); -#endif - - PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] has " << portInfo.max_rx_queues << " RX queues"); - PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] has " << portInfo.max_tx_queues << " TX queues"); - - m_TotalAvailableRxQueues = portInfo.max_rx_queues; - m_TotalAvailableTxQueues = portInfo.max_tx_queues; -} - - -bool DpdkDevice::isVirtual() const -{ - switch (m_PMDType) - { - case PMD_IGBVF: - case PMD_I40EVF: - case PMD_IXGBEVF: - case PMD_PCAP: - case PMD_RING: - case PMD_VIRTIO: - case PMD_VMXNET3: - case PMD_XENVIRT: return true; - default: - return false; } -} - -void DpdkDevice::getLinkStatus(LinkStatus& linkStatus) const -{ - struct rte_eth_link link; - rte_eth_link_get((uint8_t) m_Id, &link); - linkStatus.linkUp = link.link_status; - linkStatus.linkSpeedMbps = (unsigned) link.link_speed; - linkStatus.linkDuplex = (link.link_duplex == DPDK_CONFIG_ETH_LINK_FULL_DUPLEX) ? LinkStatus::FULL_DUPLEX : LinkStatus::HALF_DUPLEX; -} + bool DpdkDevice::initMemPool(struct rte_mempool*& memPool, const char* mempoolName, uint32_t mBufPoolSize) + { + bool ret = false; + // create mbuf pool + memPool = + rte_pktmbuf_pool_create(mempoolName, mBufPoolSize, MEMPOOL_CACHE_SIZE, 0, m_MBufDataSize, m_DeviceSocketId); + if (memPool == NULL) + { + PCPP_LOG_ERROR("Failed to create packets memory pool for port " + << m_Id << ", pool name: " << mempoolName << ". Error was: '" << rte_strerror(rte_errno) + << "' [Error code: " << rte_errno << "]"); + } + else + { + PCPP_LOG_DEBUG("Successfully initialized packets pool of size [" << mBufPoolSize << "] for device [" + << m_DeviceName << "]"); + ret = true; + } + return ret; + } -bool DpdkDevice::initCoreConfigurationByCoreMask(CoreMask coreMask) -{ - int i = 0; - int numOfCores = getNumOfCores(); - clearCoreConfiguration(); - while ((coreMask != 0) && (i < numOfCores)) + bool DpdkDevice::startDevice() { - if (coreMask & 1) + int ret = rte_eth_dev_start((uint8_t)m_Id); + if (ret < 0) { - if (i == DpdkDeviceList::getInstance().getDpdkMasterCore().Id) - { - PCPP_LOG_ERROR("Core " << i << " is the master core, you can't use it for capturing threads"); - clearCoreConfiguration(); - return false; - } + PCPP_LOG_ERROR("Failed to start device " << m_Id << ". Error is " << ret); + return false; + } - if (!rte_lcore_is_enabled(i)) - { - PCPP_LOG_ERROR("Trying to use core #" << i << " which isn't initialized by DPDK"); - clearCoreConfiguration(); - return false; - } - m_CoreConfiguration[i].IsCoreInUse = true; + LinkStatus status; + getLinkStatus(status); + if (Logger::getInstance().isDebugEnabled(PcapLogModuleDpdkDevice)) + { + std::string linkStatus = (status.linkUp ? "up" : "down"); + std::string linkDuplex = (status.linkDuplex == LinkStatus::FULL_DUPLEX ? "full-duplex" : "half-duplex"); + PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] : Link " << linkStatus + << "; Speed: " << status.linkSpeedMbps << " Mbps; " << linkDuplex); } - coreMask = coreMask >> 1; - i++; + rte_eth_promiscuous_enable((uint8_t)m_Id); + PCPP_LOG_DEBUG("Started device [" << m_DeviceName << "]"); + + return true; } - if (coreMask != 0) // this mean coreMask contains a core that doesn't exist + void DpdkDevice::clearCoreConfiguration() { - PCPP_LOG_ERROR("Trying to use a core [" << i << "] that doesn't exist while machine has " << numOfCores << " cores"); - clearCoreConfiguration(); - return false; + for (int i = 0; i < MAX_NUM_OF_CORES; i++) + { + m_CoreConfiguration[i].IsCoreInUse = false; + } } - return true; -} + int DpdkDevice::getCoresInUseCount() const + { + int res = 0; + for (int i = 0; i < MAX_NUM_OF_CORES; i++) + if (m_CoreConfiguration[i].IsCoreInUse) + res++; + + return res; + } + + void DpdkDevice::setDeviceInfo() + { + rte_eth_dev_info portInfo; + rte_eth_dev_info_get(m_Id, &portInfo); + m_PMDName = std::string(portInfo.driver_name); + + if (m_PMDName == "eth_bond") + m_PMDType = PMD_BOND; + else if (m_PMDName == "rte_em_pmd") + m_PMDType = PMD_E1000EM; + else if (m_PMDName == "rte_igb_pmd") + m_PMDType = PMD_IGB; + else if (m_PMDName == "rte_igbvf_pmd") + m_PMDType = PMD_IGBVF; + else if (m_PMDName == "rte_enic_pmd") + m_PMDType = PMD_ENIC; + else if (m_PMDName == "rte_pmd_fm10k") + m_PMDType = PMD_FM10K; + else if (m_PMDName == "rte_i40e_pmd" || m_PMDName == "net_i40e") + m_PMDType = PMD_I40E; + else if (m_PMDName == "rte_i40evf_pmd") + m_PMDType = PMD_I40EVF; + else if (m_PMDName == "rte_ixgbe_pmd") + m_PMDType = PMD_IXGBE; + else if (m_PMDName == "rte_ixgbevf_pmd") + m_PMDType = PMD_IXGBEVF; + else if (m_PMDName == "librte_pmd_mlx4") + m_PMDType = PMD_MLX4; + else if (m_PMDName == "eth_null") + m_PMDType = PMD_NULL; + else if (m_PMDName == "eth_pcap") + m_PMDType = PMD_PCAP; + else if (m_PMDName == "eth_ring") + m_PMDType = PMD_RING; + else if (m_PMDName == "rte_virtio_pmd") + m_PMDType = PMD_VIRTIO; + else if (m_PMDName == "rte_vmxnet3_pmd") + m_PMDType = PMD_VMXNET3; + else if (m_PMDName == "eth_xenvirt") + m_PMDType = PMD_XENVIRT; + else + m_PMDType = PMD_UNKNOWN; +# if (RTE_VER_YEAR < 18) || (RTE_VER_YEAR == 18 && RTE_VER_MONTH < 5) // before 18.05 + char pciName[30]; +# if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) // 17.11 - 18.02 + rte_pci_device_name(&(portInfo.pci_dev->addr), pciName, 30); +# else // 16.11 - 17.11 + rte_eal_pci_device_name(&(portInfo.pci_dev->addr), pciName, 30); +# endif + m_PciAddress = std::string(pciName); +# elif (RTE_VER_YEAR < 22) || (RTE_VER_YEAR == 22 && RTE_VER_MONTH < 11) // before 22.11 + m_PciAddress = std::string(portInfo.device->name); +# else // 22.11 forward + m_PciAddress = std::string(rte_dev_name(portInfo.device)); +# endif -bool DpdkDevice::startCaptureSingleThread(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie) -{ - if (!m_StopThread) - { - PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time"); - return false; + PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] has " << portInfo.max_rx_queues << " RX queues"); + PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] has " << portInfo.max_tx_queues << " TX queues"); + + m_TotalAvailableRxQueues = portInfo.max_rx_queues; + m_TotalAvailableTxQueues = portInfo.max_tx_queues; } - if (m_NumOfRxQueuesOpened != 1) + bool DpdkDevice::isVirtual() const { - PCPP_LOG_ERROR("Cannot start capturing on a single thread when more than 1 RX queue is opened"); - return false; + switch (m_PMDType) + { + case PMD_IGBVF: + case PMD_I40EVF: + case PMD_IXGBEVF: + case PMD_PCAP: + case PMD_RING: + case PMD_VIRTIO: + case PMD_VMXNET3: + case PMD_XENVIRT: + return true; + default: + return false; + } } - PCPP_LOG_DEBUG("Trying to start capturing on a single thread for device [" << m_DeviceName << "]"); - - clearCoreConfiguration(); - - m_OnPacketsArriveCallback = onPacketsArrive; - m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; - - m_StopThread = false; + void DpdkDevice::getLinkStatus(LinkStatus& linkStatus) const + { + struct rte_eth_link link; + rte_eth_link_get((uint8_t)m_Id, &link); + linkStatus.linkUp = link.link_status; + linkStatus.linkSpeedMbps = (unsigned)link.link_speed; + linkStatus.linkDuplex = + (link.link_duplex == DPDK_CONFIG_ETH_LINK_FULL_DUPLEX) ? LinkStatus::FULL_DUPLEX : LinkStatus::HALF_DUPLEX; + } - for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + bool DpdkDevice::initCoreConfigurationByCoreMask(CoreMask coreMask) { - if (coreId == (int)GET_MASTER_CORE() || !rte_lcore_is_enabled(coreId)) - continue; + int i = 0; + int numOfCores = getNumOfCores(); + clearCoreConfiguration(); + while ((coreMask != 0) && (i < numOfCores)) + { + if (coreMask & 1) + { + if (i == DpdkDeviceList::getInstance().getDpdkMasterCore().Id) + { + PCPP_LOG_ERROR("Core " << i << " is the master core, you can't use it for capturing threads"); + clearCoreConfiguration(); + return false; + } - m_CoreConfiguration[coreId].IsCoreInUse = true; - m_CoreConfiguration[coreId].RxQueueId = 0; + if (!rte_lcore_is_enabled(i)) + { + PCPP_LOG_ERROR("Trying to use core #" << i << " which isn't initialized by DPDK"); + clearCoreConfiguration(); + return false; + } + m_CoreConfiguration[i].IsCoreInUse = true; + } + + coreMask = coreMask >> 1; + i++; + } - PCPP_LOG_DEBUG("Trying to start capturing on core " << coreId); - int err = rte_eal_remote_launch(dpdkCaptureThreadMain, (void*)this, coreId); - if (err != 0) + if (coreMask != 0) // this mean coreMask contains a core that doesn't exist { - PCPP_LOG_ERROR("Cannot create capture thread for device '" << m_DeviceName << "'"); - m_CoreConfiguration[coreId].IsCoreInUse = false; + PCPP_LOG_ERROR("Trying to use a core [" << i << "] that doesn't exist while machine has " << numOfCores + << " cores"); + clearCoreConfiguration(); return false; } - PCPP_LOG_DEBUG("Capturing started for device [" << m_DeviceName << "]"); return true; } - PCPP_LOG_ERROR("Could not find initialized core so capturing thread cannot be initialized"); - return false; -} - -bool DpdkDevice::startCaptureMultiThreads(OnDpdkPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask) -{ - if (!m_DeviceOpened) + bool DpdkDevice::startCaptureSingleThread(OnDpdkPacketsArriveCallback onPacketsArrive, + void* onPacketsArriveUserCookie) { - PCPP_LOG_ERROR("Device not opened"); - return false; - } + if (!m_StopThread) + { + PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time"); + return false; + } - if (!initCoreConfigurationByCoreMask(coreMask)) - return false; + if (m_NumOfRxQueuesOpened != 1) + { + PCPP_LOG_ERROR("Cannot start capturing on a single thread when more than 1 RX queue is opened"); + return false; + } + + PCPP_LOG_DEBUG("Trying to start capturing on a single thread for device [" << m_DeviceName << "]"); - if (m_NumOfRxQueuesOpened != getCoresInUseCount()) - { - PCPP_LOG_ERROR("Cannot use a different number of queues and cores. Opened " << m_NumOfRxQueuesOpened << " queues but set " << getCoresInUseCount() << " cores in core mask"); clearCoreConfiguration(); + + m_OnPacketsArriveCallback = onPacketsArrive; + m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; + + m_StopThread = false; + + for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + { + if (coreId == (int)GET_MASTER_CORE() || !rte_lcore_is_enabled(coreId)) + continue; + + m_CoreConfiguration[coreId].IsCoreInUse = true; + m_CoreConfiguration[coreId].RxQueueId = 0; + + PCPP_LOG_DEBUG("Trying to start capturing on core " << coreId); + int err = rte_eal_remote_launch(dpdkCaptureThreadMain, (void*)this, coreId); + if (err != 0) + { + PCPP_LOG_ERROR("Cannot create capture thread for device '" << m_DeviceName << "'"); + m_CoreConfiguration[coreId].IsCoreInUse = false; + return false; + } + + PCPP_LOG_DEBUG("Capturing started for device [" << m_DeviceName << "]"); + return true; + } + + PCPP_LOG_ERROR("Could not find initialized core so capturing thread cannot be initialized"); return false; } - m_StopThread = false; - int rxQueue = 0; - for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + bool DpdkDevice::startCaptureMultiThreads(OnDpdkPacketsArriveCallback onPacketsArrive, + void* onPacketsArriveUserCookie, CoreMask coreMask) { - if (!m_CoreConfiguration[coreId].IsCoreInUse) - continue; - - // create a new thread - m_CoreConfiguration[coreId].RxQueueId = rxQueue++; - int err = rte_eal_remote_launch(dpdkCaptureThreadMain, (void*)this, coreId); - if (err != 0) + if (!m_DeviceOpened) { - PCPP_LOG_ERROR("Cannot create capture thread #" << coreId << " for device '" << m_DeviceName << "': [" << strerror(err) << "]"); - m_CoreConfiguration[coreId].clear(); + PCPP_LOG_ERROR("Device not opened"); return false; } - } - m_OnPacketsArriveCallback = onPacketsArrive; - m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; + if (!initCoreConfigurationByCoreMask(coreMask)) + return false; - return true; -} + if (m_NumOfRxQueuesOpened != getCoresInUseCount()) + { + PCPP_LOG_ERROR("Cannot use a different number of queues and cores. Opened " + << m_NumOfRxQueuesOpened << " queues but set " << getCoresInUseCount() + << " cores in core mask"); + clearCoreConfiguration(); + return false; + } -void DpdkDevice::stopCapture() -{ - PCPP_LOG_DEBUG("Trying to stop capturing on device [" << m_DeviceName << "]"); - m_StopThread = true; - for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) - { - if (!m_CoreConfiguration[coreId].IsCoreInUse) - continue; - rte_eal_wait_lcore(coreId); - PCPP_LOG_DEBUG("Thread on core [" << coreId << "] stopped"); - } + m_StopThread = false; + int rxQueue = 0; + for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + { + if (!m_CoreConfiguration[coreId].IsCoreInUse) + continue; - PCPP_LOG_DEBUG("All capturing threads stopped"); -} + // create a new thread + m_CoreConfiguration[coreId].RxQueueId = rxQueue++; + int err = rte_eal_remote_launch(dpdkCaptureThreadMain, (void*)this, coreId); + if (err != 0) + { + PCPP_LOG_ERROR("Cannot create capture thread #" << coreId << " for device '" << m_DeviceName << "': [" + << strerror(err) << "]"); + m_CoreConfiguration[coreId].clear(); + return false; + } + } -int DpdkDevice::dpdkCaptureThreadMain(void *ptr) -{ - DpdkDevice* pThis = (DpdkDevice*)ptr; - struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; + m_OnPacketsArriveCallback = onPacketsArrive; + m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; - if (pThis == NULL) - { - PCPP_LOG_ERROR("Failed to retrieve DPDK device in capture thread main loop"); - return 1; + return true; } - uint32_t coreId = pThis->getCurrentCoreId(); - PCPP_LOG_DEBUG("Starting capture thread " << coreId); + void DpdkDevice::stopCapture() + { + PCPP_LOG_DEBUG("Trying to stop capturing on device [" << m_DeviceName << "]"); + m_StopThread = true; + for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + { + if (!m_CoreConfiguration[coreId].IsCoreInUse) + continue; + rte_eal_wait_lcore(coreId); + PCPP_LOG_DEBUG("Thread on core [" << coreId << "] stopped"); + } - int queueId = pThis->m_CoreConfiguration[coreId].RxQueueId; + PCPP_LOG_DEBUG("All capturing threads stopped"); + } - while (likely(!pThis->m_StopThread)) + int DpdkDevice::dpdkCaptureThreadMain(void* ptr) { - uint32_t numOfPktsReceived = rte_eth_rx_burst(pThis->m_Id, queueId, mBufArray, MAX_BURST_SIZE); + DpdkDevice* pThis = (DpdkDevice*)ptr; + struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; - if (unlikely(numOfPktsReceived == 0)) - continue; + if (pThis == NULL) + { + PCPP_LOG_ERROR("Failed to retrieve DPDK device in capture thread main loop"); + return 1; + } - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + uint32_t coreId = pThis->getCurrentCoreId(); + PCPP_LOG_DEBUG("Starting capture thread " << coreId); - if (likely(pThis->m_OnPacketsArriveCallback != NULL)) + int queueId = pThis->m_CoreConfiguration[coreId].RxQueueId; + + while (likely(!pThis->m_StopThread)) { - MBufRawPacket rawPackets[MAX_BURST_SIZE]; - for (uint32_t index = 0; index < numOfPktsReceived; ++index) + uint32_t numOfPktsReceived = rte_eth_rx_burst(pThis->m_Id, queueId, mBufArray, MAX_BURST_SIZE); + + if (unlikely(numOfPktsReceived == 0)) + continue; + + timespec time; + clock_gettime(CLOCK_REALTIME, &time); + + if (likely(pThis->m_OnPacketsArriveCallback != NULL)) { - rawPackets[index].setMBuf(mBufArray[index], time); - } + MBufRawPacket rawPackets[MAX_BURST_SIZE]; + for (uint32_t index = 0; index < numOfPktsReceived; ++index) + { + rawPackets[index].setMBuf(mBufArray[index], time); + } - pThis->m_OnPacketsArriveCallback(rawPackets, numOfPktsReceived, coreId, pThis, pThis->m_OnPacketsArriveUserCookie); + pThis->m_OnPacketsArriveCallback(rawPackets, numOfPktsReceived, coreId, pThis, + pThis->m_OnPacketsArriveUserCookie); + } } - } - PCPP_LOG_DEBUG("Exiting capture thread " << coreId); + PCPP_LOG_DEBUG("Exiting capture thread " << coreId); - return 0; -} + return 0; + } -#define nanosec_gap(begin, end) ((end.tv_sec - begin.tv_sec) * 1000000000.0 + (end.tv_nsec - begin.tv_nsec)) +# define nanosec_gap(begin, end) ((end.tv_sec - begin.tv_sec) * 1000000000.0 + (end.tv_nsec - begin.tv_nsec)) -void DpdkDevice::getStatistics(DpdkDeviceStats& stats) const -{ - timespec timestamp; - clock_gettime(CLOCK_MONOTONIC, ×tamp); - struct rte_eth_stats rteStats; - rte_eth_stats_get(m_Id, &rteStats); - - double secsElapsed = (double)nanosec_gap(m_PrevStats.timestamp, timestamp) / 1000000000.0; - - stats.devId = m_Id; - stats.timestamp = timestamp; - stats.rxErroneousPackets = rteStats.ierrors; - stats.rxMbufAlocFailed = rteStats.rx_nombuf; - stats.rxPacketsDroppedByHW = rteStats.imissed; - stats.aggregatedRxStats.packets = rteStats.ipackets; - stats.aggregatedRxStats.bytes = rteStats.ibytes; - stats.aggregatedRxStats.packetsPerSec = (stats.aggregatedRxStats.packets - m_PrevStats.aggregatedRxStats.packets) / secsElapsed; - stats.aggregatedRxStats.bytesPerSec = (stats.aggregatedRxStats.bytes - m_PrevStats.aggregatedRxStats.bytes) / secsElapsed; - stats.aggregatedTxStats.packets = rteStats.opackets; - stats.aggregatedTxStats.bytes = rteStats.obytes; - stats.aggregatedTxStats.packetsPerSec = (stats.aggregatedTxStats.packets - m_PrevStats.aggregatedTxStats.packets) / secsElapsed; - stats.aggregatedTxStats.bytesPerSec = (stats.aggregatedTxStats.bytes - m_PrevStats.aggregatedTxStats.bytes) / secsElapsed; - - int numRxQs = std::min(DPDK_MAX_RX_QUEUES, RTE_ETHDEV_QUEUE_STAT_CNTRS); - int numTxQs = std::min(DPDK_MAX_TX_QUEUES, RTE_ETHDEV_QUEUE_STAT_CNTRS); - - for (int i = 0; i < numRxQs; i++) + void DpdkDevice::getStatistics(DpdkDeviceStats& stats) const { - stats.rxStats[i].packets = rteStats.q_ipackets[i]; - stats.rxStats[i].bytes = rteStats.q_ibytes[i]; - stats.rxStats[i].packetsPerSec = (stats.rxStats[i].packets - m_PrevStats.rxStats[i].packets) / secsElapsed; - stats.rxStats[i].bytesPerSec = (stats.rxStats[i].bytes - m_PrevStats.rxStats[i].bytes) / secsElapsed; - } + timespec timestamp; + clock_gettime(CLOCK_MONOTONIC, ×tamp); + struct rte_eth_stats rteStats; + rte_eth_stats_get(m_Id, &rteStats); - for (int i = 0; i < numTxQs; i++) - { - stats.txStats[i].packets = rteStats.q_opackets[i]; - stats.txStats[i].bytes = rteStats.q_obytes[i]; - stats.txStats[i].packetsPerSec = (stats.txStats[i].packets - m_PrevStats.txStats[i].packets) / secsElapsed; - stats.txStats[i].bytesPerSec = (stats.txStats[i].bytes - m_PrevStats.txStats[i].bytes) / secsElapsed; - } + double secsElapsed = (double)nanosec_gap(m_PrevStats.timestamp, timestamp) / 1000000000.0; - //m_PrevStats = stats; - memcpy(&m_PrevStats, &stats, sizeof(m_PrevStats)); -} + stats.devId = m_Id; + stats.timestamp = timestamp; + stats.rxErroneousPackets = rteStats.ierrors; + stats.rxMbufAlocFailed = rteStats.rx_nombuf; + stats.rxPacketsDroppedByHW = rteStats.imissed; + stats.aggregatedRxStats.packets = rteStats.ipackets; + stats.aggregatedRxStats.bytes = rteStats.ibytes; + stats.aggregatedRxStats.packetsPerSec = + (stats.aggregatedRxStats.packets - m_PrevStats.aggregatedRxStats.packets) / secsElapsed; + stats.aggregatedRxStats.bytesPerSec = + (stats.aggregatedRxStats.bytes - m_PrevStats.aggregatedRxStats.bytes) / secsElapsed; + stats.aggregatedTxStats.packets = rteStats.opackets; + stats.aggregatedTxStats.bytes = rteStats.obytes; + stats.aggregatedTxStats.packetsPerSec = + (stats.aggregatedTxStats.packets - m_PrevStats.aggregatedTxStats.packets) / secsElapsed; + stats.aggregatedTxStats.bytesPerSec = + (stats.aggregatedTxStats.bytes - m_PrevStats.aggregatedTxStats.bytes) / secsElapsed; -void DpdkDevice::clearStatistics() -{ - rte_eth_stats_reset(m_Id); - memset(&m_PrevStats, 0 ,sizeof(m_PrevStats)); -} + int numRxQs = std::min(DPDK_MAX_RX_QUEUES, RTE_ETHDEV_QUEUE_STAT_CNTRS); + int numTxQs = std::min(DPDK_MAX_TX_QUEUES, RTE_ETHDEV_QUEUE_STAT_CNTRS); + for (int i = 0; i < numRxQs; i++) + { + stats.rxStats[i].packets = rteStats.q_ipackets[i]; + stats.rxStats[i].bytes = rteStats.q_ibytes[i]; + stats.rxStats[i].packetsPerSec = (stats.rxStats[i].packets - m_PrevStats.rxStats[i].packets) / secsElapsed; + stats.rxStats[i].bytesPerSec = (stats.rxStats[i].bytes - m_PrevStats.rxStats[i].bytes) / secsElapsed; + } -bool DpdkDevice::setFilter(GeneralFilter& filter) -{ - //TODO: I think DPDK supports filters - PCPP_LOG_ERROR("Filters aren't supported in DPDK device"); - return false; -} + for (int i = 0; i < numTxQs; i++) + { + stats.txStats[i].packets = rteStats.q_opackets[i]; + stats.txStats[i].bytes = rteStats.q_obytes[i]; + stats.txStats[i].packetsPerSec = (stats.txStats[i].packets - m_PrevStats.txStats[i].packets) / secsElapsed; + stats.txStats[i].bytesPerSec = (stats.txStats[i].bytes - m_PrevStats.txStats[i].bytes) / secsElapsed; + } -bool DpdkDevice::setFilter(std::string filterAsString) -{ - //TODO: I think DPDK supports filters - PCPP_LOG_ERROR("Filters aren't supported in DPDK device"); - return false; -} + // m_PrevStats = stats; + memcpy(&m_PrevStats, &stats, sizeof(m_PrevStats)); + } -uint16_t DpdkDevice::receivePackets(MBufRawPacketVector& rawPacketsArr, uint16_t rxQueueId) const -{ - if (!m_DeviceOpened) + void DpdkDevice::clearStatistics() { - PCPP_LOG_ERROR("Device not opened"); - return 0; + rte_eth_stats_reset(m_Id); + memset(&m_PrevStats, 0, sizeof(m_PrevStats)); } - if (!m_StopThread) + bool DpdkDevice::setFilter(GeneralFilter& filter) { - PCPP_LOG_ERROR("DpdkDevice capture mode is currently running. Cannot receive packets in parallel"); - return 0; + // TODO: I think DPDK supports filters + PCPP_LOG_ERROR("Filters aren't supported in DPDK device"); + return false; } - if (rxQueueId >= m_TotalAvailableRxQueues) + bool DpdkDevice::setFilter(std::string filterAsString) { - PCPP_LOG_ERROR("RX queue ID #" << rxQueueId << " not available for this device"); - return 0; + // TODO: I think DPDK supports filters + PCPP_LOG_ERROR("Filters aren't supported in DPDK device"); + return false; } - struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; - uint32_t numOfPktsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, MAX_BURST_SIZE); + uint16_t DpdkDevice::receivePackets(MBufRawPacketVector& rawPacketsArr, uint16_t rxQueueId) const + { + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device not opened"); + return 0; + } - //the following line trashes the log with many messages. Uncomment only if necessary - //PCPP_LOG_DEBUG("Captured %d packets", numOfPktsReceived); + if (!m_StopThread) + { + PCPP_LOG_ERROR("DpdkDevice capture mode is currently running. Cannot receive packets in parallel"); + return 0; + } - if (unlikely(!numOfPktsReceived)) - { - return 0; - } + if (rxQueueId >= m_TotalAvailableRxQueues) + { + PCPP_LOG_ERROR("RX queue ID #" << rxQueueId << " not available for this device"); + return 0; + } - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; + uint32_t numOfPktsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, MAX_BURST_SIZE); - for (uint32_t index = 0; index < numOfPktsReceived; ++index) - { - struct rte_mbuf* mBuf = mBufArray[index]; - MBufRawPacket* newRawPacket = new MBufRawPacket(); - newRawPacket->setMBuf(mBuf, time); - rawPacketsArr.pushBack(newRawPacket); - } + // the following line trashes the log with many messages. Uncomment only if necessary + // PCPP_LOG_DEBUG("Captured %d packets", numOfPktsReceived); - return numOfPktsReceived; -} + if (unlikely(!numOfPktsReceived)) + { + return 0; + } -uint16_t DpdkDevice::receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength, uint16_t rxQueueId) const -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("Device not opened"); - return 0; - } + timespec time; + clock_gettime(CLOCK_REALTIME, &time); - if (unlikely(!m_StopThread)) - { - PCPP_LOG_ERROR("DpdkDevice capture mode is currently running. Cannot receive packets in parallel"); - return 0; - } + for (uint32_t index = 0; index < numOfPktsReceived; ++index) + { + struct rte_mbuf* mBuf = mBufArray[index]; + MBufRawPacket* newRawPacket = new MBufRawPacket(); + newRawPacket->setMBuf(mBuf, time); + rawPacketsArr.pushBack(newRawPacket); + } - if (unlikely(rxQueueId >= m_TotalAvailableRxQueues)) - { - PCPP_LOG_ERROR("RX queue ID #" << rxQueueId << " not available for this device"); - return 0; + return numOfPktsReceived; } - if (unlikely(rawPacketsArr == NULL)) + uint16_t DpdkDevice::receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength, + uint16_t rxQueueId) const { - PCPP_LOG_ERROR("Provided address of array to store packets is NULL"); - return 0; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("Device not opened"); + return 0; + } - struct rte_mbuf* mBufArray[rawPacketArrLength]; - uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, rawPacketArrLength); + if (unlikely(!m_StopThread)) + { + PCPP_LOG_ERROR("DpdkDevice capture mode is currently running. Cannot receive packets in parallel"); + return 0; + } - if (unlikely(!packetsReceived)) - { - return 0; - } + if (unlikely(rxQueueId >= m_TotalAvailableRxQueues)) + { + PCPP_LOG_ERROR("RX queue ID #" << rxQueueId << " not available for this device"); + return 0; + } - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + if (unlikely(rawPacketsArr == NULL)) + { + PCPP_LOG_ERROR("Provided address of array to store packets is NULL"); + return 0; + } - for (size_t index = 0; index < packetsReceived; ++index) - { - struct rte_mbuf* mBuf = mBufArray[index]; - if (rawPacketsArr[index] == NULL) - rawPacketsArr[index] = new MBufRawPacket(); + struct rte_mbuf* mBufArray[rawPacketArrLength]; + uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, rawPacketArrLength); - rawPacketsArr[index]->setMBuf(mBuf, time); - } + if (unlikely(!packetsReceived)) + { + return 0; + } - return packetsReceived; -} + timespec time; + clock_gettime(CLOCK_REALTIME, &time); -uint16_t DpdkDevice::receivePackets(Packet** packetsArr, uint16_t packetsArrLength, uint16_t rxQueueId) const -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("Device not opened"); - return 0; - } + for (size_t index = 0; index < packetsReceived; ++index) + { + struct rte_mbuf* mBuf = mBufArray[index]; + if (rawPacketsArr[index] == NULL) + rawPacketsArr[index] = new MBufRawPacket(); - if (unlikely(!m_StopThread)) - { - PCPP_LOG_ERROR("DpdkDevice capture mode is currently running. Cannot receive packets in parallel"); - return 0; - } + rawPacketsArr[index]->setMBuf(mBuf, time); + } - if (unlikely(rxQueueId >= m_TotalAvailableRxQueues)) - { - PCPP_LOG_ERROR("RX queue ID #" << rxQueueId << " not available for this device"); - return 0; + return packetsReceived; } - struct rte_mbuf* mBufArray[packetsArrLength]; - uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, packetsArrLength); - - if (unlikely(!packetsReceived)) + uint16_t DpdkDevice::receivePackets(Packet** packetsArr, uint16_t packetsArrLength, uint16_t rxQueueId) const { - return 0; - } - - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("Device not opened"); + return 0; + } - for (size_t index = 0; index < packetsReceived; ++index) - { - struct rte_mbuf* mBuf = mBufArray[index]; - MBufRawPacket* newRawPacket = new MBufRawPacket(); - newRawPacket->setMBuf(mBuf, time); - if (packetsArr[index] == NULL) - packetsArr[index] = new Packet(); + if (unlikely(!m_StopThread)) + { + PCPP_LOG_ERROR("DpdkDevice capture mode is currently running. Cannot receive packets in parallel"); + return 0; + } - packetsArr[index]->setRawPacket(newRawPacket, true); - } + if (unlikely(rxQueueId >= m_TotalAvailableRxQueues)) + { + PCPP_LOG_ERROR("RX queue ID #" << rxQueueId << " not available for this device"); + return 0; + } - return packetsReceived; -} + struct rte_mbuf* mBufArray[packetsArrLength]; + uint16_t packetsReceived = rte_eth_rx_burst(m_Id, rxQueueId, mBufArray, packetsArrLength); -uint16_t DpdkDevice::flushTxBuffer(bool flushOnlyIfTimeoutExpired, uint16_t txQueueId) -{ - bool flush = true; + if (unlikely(!packetsReceived)) + { + return 0; + } - if (flushOnlyIfTimeoutExpired) - { - uint64_t curTsc = rte_rdtsc(); + timespec time; + clock_gettime(CLOCK_REALTIME, &time); - if (curTsc - m_TxBufferLastDrainTsc[txQueueId] > m_TxBufferDrainTsc) - m_TxBufferLastDrainTsc[txQueueId] = curTsc; - else - flush = false; - } + for (size_t index = 0; index < packetsReceived; ++index) + { + struct rte_mbuf* mBuf = mBufArray[index]; + MBufRawPacket* newRawPacket = new MBufRawPacket(); + newRawPacket->setMBuf(mBuf, time); + if (packetsArr[index] == NULL) + packetsArr[index] = new Packet(); - if (flush) - return rte_eth_tx_buffer_flush(m_Id, txQueueId, m_TxBuffers[txQueueId]); + packetsArr[index]->setRawPacket(newRawPacket, true); + } - return 0; -} + return packetsReceived; + } -static rte_mbuf* getNextPacketFromMBufRawPacketArray(void* packetStorage, int index) -{ - MBufRawPacket** packetsArr = (MBufRawPacket**)packetStorage; - return packetsArr[index]->getMBuf(); -} + uint16_t DpdkDevice::flushTxBuffer(bool flushOnlyIfTimeoutExpired, uint16_t txQueueId) + { + bool flush = true; -static rte_mbuf* getNextPacketFromMBufArray(void* packetStorage, int index) -{ - rte_mbuf** mbufArr = (rte_mbuf**)packetStorage; - return mbufArr[index]; -} + if (flushOnlyIfTimeoutExpired) + { + uint64_t curTsc = rte_rdtsc(); -static rte_mbuf* getNextPacketFromMBufRawPacketVec(void* packetStorage, int index) -{ - MBufRawPacketVector* packetVec = (MBufRawPacketVector*)packetStorage; - return packetVec->at(index)->getMBuf(); -} + if (curTsc - m_TxBufferLastDrainTsc[txQueueId] > m_TxBufferDrainTsc) + m_TxBufferLastDrainTsc[txQueueId] = curTsc; + else + flush = false; + } -static rte_mbuf* getNextPacketFromMBufRawPacket(void* packetStorage, int index) -{ - MBufRawPacket* mbufRawPacket = (MBufRawPacket*)packetStorage; - return mbufRawPacket->getMBuf(); -} + if (flush) + return rte_eth_tx_buffer_flush(m_Id, txQueueId, m_TxBuffers[txQueueId]); -uint16_t DpdkDevice::sendPacketsInner(uint16_t txQueueId, void* packetStorage, PacketIterator iter, int arrLength, bool useTxBuffer) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("Device '" << m_DeviceName << "' not opened!"); return 0; } - if (unlikely(txQueueId >= m_NumOfTxQueuesOpened)) + static rte_mbuf* getNextPacketFromMBufRawPacketArray(void* packetStorage, int index) { - PCPP_LOG_ERROR("TX queue " << txQueueId << " isn't opened in device"); - return 0; + MBufRawPacket** packetsArr = (MBufRawPacket**)packetStorage; + return packetsArr[index]->getMBuf(); } - rte_mbuf* mBufArr[MAX_BURST_SIZE]; + static rte_mbuf* getNextPacketFromMBufArray(void* packetStorage, int index) + { + rte_mbuf** mbufArr = (rte_mbuf**)packetStorage; + return mbufArr[index]; + } - int packetIndex = 0; - int mBufArrIndex = 0; - uint16_t packetsSent = 0; - int lastSleep = 0; + static rte_mbuf* getNextPacketFromMBufRawPacketVec(void* packetStorage, int index) + { + MBufRawPacketVector* packetVec = (MBufRawPacketVector*)packetStorage; + return packetVec->at(index)->getMBuf(); + } - #define PACKET_TRANSMISSION_THRESHOLD 0.8 - int packetTxThreshold = m_Config.transmitDescriptorsNumber*PACKET_TRANSMISSION_THRESHOLD; + static rte_mbuf* getNextPacketFromMBufRawPacket(void* packetStorage, int index) + { + MBufRawPacket* mbufRawPacket = (MBufRawPacket*)packetStorage; + return mbufRawPacket->getMBuf(); + } - while (packetIndex < arrLength) + uint16_t DpdkDevice::sendPacketsInner(uint16_t txQueueId, void* packetStorage, PacketIterator iter, int arrLength, + bool useTxBuffer) { - rte_mbuf* mBuf = iter(packetStorage, packetIndex); + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("Device '" << m_DeviceName << "' not opened!"); + return 0; + } - if (useTxBuffer) + if (unlikely(txQueueId >= m_NumOfTxQueuesOpened)) { - packetsSent += rte_eth_tx_buffer(m_Id, txQueueId, m_TxBuffers[txQueueId], mBuf); + PCPP_LOG_ERROR("TX queue " << txQueueId << " isn't opened in device"); + return 0; } - else + + rte_mbuf* mBufArr[MAX_BURST_SIZE]; + + int packetIndex = 0; + int mBufArrIndex = 0; + uint16_t packetsSent = 0; + int lastSleep = 0; + +# define PACKET_TRANSMISSION_THRESHOLD 0.8 + int packetTxThreshold = m_Config.transmitDescriptorsNumber * PACKET_TRANSMISSION_THRESHOLD; + + while (packetIndex < arrLength) { - mBufArr[mBufArrIndex++] = mBuf; + rte_mbuf* mBuf = iter(packetStorage, packetIndex); - if (unlikely(mBufArrIndex == MAX_BURST_SIZE)) + if (useTxBuffer) + { + packetsSent += rte_eth_tx_buffer(m_Id, txQueueId, m_TxBuffers[txQueueId], mBuf); + } + else { - packetsSent += rte_eth_tx_burst(m_Id, txQueueId, mBufArr, MAX_BURST_SIZE); - mBufArrIndex = 0; + mBufArr[mBufArrIndex++] = mBuf; - if (unlikely((packetsSent - lastSleep) >= packetTxThreshold)) + if (unlikely(mBufArrIndex == MAX_BURST_SIZE)) { - PCPP_LOG_DEBUG("Since NIC couldn't send all packet in this iteration, waiting for 0.2 second for H/W descriptors to get free"); - usleep(200000); - lastSleep = packetsSent; + packetsSent += rte_eth_tx_burst(m_Id, txQueueId, mBufArr, MAX_BURST_SIZE); + mBufArrIndex = 0; + + if (unlikely((packetsSent - lastSleep) >= packetTxThreshold)) + { + PCPP_LOG_DEBUG( + "Since NIC couldn't send all packet in this iteration, waiting for 0.2 second for H/W descriptors to get free"); + usleep(200000); + lastSleep = packetsSent; + } } } + + packetIndex++; } - packetIndex++; - } + if (useTxBuffer) + { + packetsSent += flushTxBuffer(true, txQueueId); + } + else if (mBufArrIndex > 0) + { + packetsSent += rte_eth_tx_burst(m_Id, txQueueId, mBufArr, mBufArrIndex); + } - if (useTxBuffer) - { - packetsSent += flushTxBuffer(true, txQueueId); + return packetsSent; } - else if (mBufArrIndex > 0) + + uint16_t DpdkDevice::sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength, uint16_t txQueueId, + bool useTxBuffer) { - packetsSent += rte_eth_tx_burst(m_Id, txQueueId, mBufArr, mBufArrIndex); - } + uint16_t packetsSent = sendPacketsInner(txQueueId, (void*)rawPacketsArr, getNextPacketFromMBufRawPacketArray, + arrLength, useTxBuffer); - return packetsSent; -} + bool needToFreeMbuf = false; + int applyForMBufs = arrLength; + if (unlikely(!useTxBuffer && (packetsSent != arrLength))) + { + applyForMBufs = packetsSent; + } -uint16_t DpdkDevice::sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength, uint16_t txQueueId, bool useTxBuffer) -{ - uint16_t packetsSent = sendPacketsInner(txQueueId, (void*)rawPacketsArr, getNextPacketFromMBufRawPacketArray, arrLength, useTxBuffer); + for (int index = 0; index < applyForMBufs; index++) + rawPacketsArr[index]->setFreeMbuf(needToFreeMbuf); - bool needToFreeMbuf = false; - int applyForMBufs = arrLength; + for (int index = applyForMBufs; index < arrLength; index++) + rawPacketsArr[index]->setFreeMbuf(!needToFreeMbuf); - if (unlikely(!useTxBuffer && (packetsSent != arrLength))) - { - applyForMBufs = packetsSent; + return packetsSent; } - for (int index = 0; index < applyForMBufs; index++) - rawPacketsArr[index]->setFreeMbuf(needToFreeMbuf); - - for (int index = applyForMBufs; index < arrLength; index++) - rawPacketsArr[index]->setFreeMbuf(!needToFreeMbuf); - - return packetsSent; -} - -uint16_t DpdkDevice::sendPackets(Packet** packetsArr, uint16_t arrLength, uint16_t txQueueId, bool useTxBuffer) -{ - rte_mbuf* mBufArr[arrLength]; - MBufRawPacketVector mBufVec; - MBufRawPacket* mBufRawPacketArr[arrLength]; - - for (size_t i = 0; i < arrLength; i++) + uint16_t DpdkDevice::sendPackets(Packet** packetsArr, uint16_t arrLength, uint16_t txQueueId, bool useTxBuffer) { - MBufRawPacket* rawPacket = NULL; - uint8_t rawPacketType = packetsArr[i]->getRawPacketReadOnly()->getObjectType(); - if (rawPacketType != MBUFRAWPACKET_OBJECT_TYPE) + rte_mbuf* mBufArr[arrLength]; + MBufRawPacketVector mBufVec; + MBufRawPacket* mBufRawPacketArr[arrLength]; + + for (size_t i = 0; i < arrLength; i++) { - rawPacket = new MBufRawPacket(); - if (unlikely(!rawPacket->initFromRawPacket(packetsArr[i]->getRawPacketReadOnly(), this))) + MBufRawPacket* rawPacket = NULL; + uint8_t rawPacketType = packetsArr[i]->getRawPacketReadOnly()->getObjectType(); + if (rawPacketType != MBUFRAWPACKET_OBJECT_TYPE) + { + rawPacket = new MBufRawPacket(); + if (unlikely(!rawPacket->initFromRawPacket(packetsArr[i]->getRawPacketReadOnly(), this))) + { + delete rawPacket; + return 0; + } + + mBufVec.pushBack(rawPacket); + } + else { - delete rawPacket; - return 0; + rawPacket = (MBufRawPacket*)packetsArr[i]->getRawPacketReadOnly(); } - mBufVec.pushBack(rawPacket); + mBufArr[i] = rawPacket->getMBuf(); + mBufRawPacketArr[i] = rawPacket; } - else - { - rawPacket = (MBufRawPacket*)packetsArr[i]->getRawPacketReadOnly(); - } - - mBufArr[i] = rawPacket->getMBuf(); - mBufRawPacketArr[i] = rawPacket; - } - - uint16_t packetsSent = sendPacketsInner(txQueueId, (void*)mBufArr, getNextPacketFromMBufArray, arrLength, useTxBuffer); - bool needToFreeMbuf = (!useTxBuffer && (packetsSent != arrLength)); - for (int index = 0; index < arrLength; index++) - mBufRawPacketArr[index]->setFreeMbuf(needToFreeMbuf); + uint16_t packetsSent = + sendPacketsInner(txQueueId, (void*)mBufArr, getNextPacketFromMBufArray, arrLength, useTxBuffer); - return packetsSent; -} + bool needToFreeMbuf = (!useTxBuffer && (packetsSent != arrLength)); + for (int index = 0; index < arrLength; index++) + mBufRawPacketArr[index]->setFreeMbuf(needToFreeMbuf); -uint16_t DpdkDevice::sendPackets(RawPacketVector& rawPacketsVec, uint16_t txQueueId, bool useTxBuffer) -{ - size_t vecSize = rawPacketsVec.size(); - rte_mbuf* mBufArr[vecSize]; - MBufRawPacket* mBufRawPacketArr[vecSize]; - MBufRawPacketVector mBufVec; - int mBufIndex = 0; + return packetsSent; + } - for (RawPacketVector::ConstVectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); iter++) + uint16_t DpdkDevice::sendPackets(RawPacketVector& rawPacketsVec, uint16_t txQueueId, bool useTxBuffer) { - MBufRawPacket* rawPacket = NULL; - uint8_t rawPacketType = (*iter)->getObjectType(); - if (rawPacketType != MBUFRAWPACKET_OBJECT_TYPE) + size_t vecSize = rawPacketsVec.size(); + rte_mbuf* mBufArr[vecSize]; + MBufRawPacket* mBufRawPacketArr[vecSize]; + MBufRawPacketVector mBufVec; + int mBufIndex = 0; + + for (RawPacketVector::ConstVectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); iter++) { - rawPacket = new MBufRawPacket(); - if (unlikely(!rawPacket->initFromRawPacket(*iter, this))) + MBufRawPacket* rawPacket = NULL; + uint8_t rawPacketType = (*iter)->getObjectType(); + if (rawPacketType != MBUFRAWPACKET_OBJECT_TYPE) + { + rawPacket = new MBufRawPacket(); + if (unlikely(!rawPacket->initFromRawPacket(*iter, this))) + { + delete rawPacket; + return 0; + } + + mBufVec.pushBack(rawPacket); + } + else { - delete rawPacket; - return 0; + rawPacket = (MBufRawPacket*)(*iter); } - mBufVec.pushBack(rawPacket); - } - else - { - rawPacket = (MBufRawPacket*)(*iter); + mBufRawPacketArr[mBufIndex] = rawPacket; + mBufArr[mBufIndex++] = rawPacket->getMBuf(); } - mBufRawPacketArr[mBufIndex] = rawPacket; - mBufArr[mBufIndex++] = rawPacket->getMBuf(); + uint16_t packetsSent = + sendPacketsInner(txQueueId, (void*)mBufArr, getNextPacketFromMBufArray, vecSize, useTxBuffer); + + bool needToFreeMbuf = (!useTxBuffer && (packetsSent != vecSize)); + for (size_t index = 0; index < rawPacketsVec.size(); index++) + mBufRawPacketArr[index]->setFreeMbuf(needToFreeMbuf); + + return packetsSent; } - uint16_t packetsSent = sendPacketsInner(txQueueId, (void*)mBufArr, getNextPacketFromMBufArray, vecSize, useTxBuffer); + uint16_t DpdkDevice::sendPackets(MBufRawPacketVector& rawPacketsVec, uint16_t txQueueId, bool useTxBuffer) + { + size_t vecSize = rawPacketsVec.size(); + uint16_t packetsSent = sendPacketsInner(txQueueId, (void*)(&rawPacketsVec), getNextPacketFromMBufRawPacketVec, + vecSize, useTxBuffer); + + bool needToFreeMbuf = (!useTxBuffer && (packetsSent != vecSize)); - bool needToFreeMbuf = (!useTxBuffer && (packetsSent != vecSize)); - for (size_t index = 0; index < rawPacketsVec.size(); index++) - mBufRawPacketArr[index]->setFreeMbuf(needToFreeMbuf); + for (size_t index = 0; index < vecSize; index++) + rawPacketsVec.at(index)->setFreeMbuf(needToFreeMbuf); - return packetsSent; -} + return packetsSent; + } -uint16_t DpdkDevice::sendPackets(MBufRawPacketVector& rawPacketsVec, uint16_t txQueueId, bool useTxBuffer) -{ - size_t vecSize = rawPacketsVec.size(); - uint16_t packetsSent = sendPacketsInner(txQueueId, (void*)(&rawPacketsVec), getNextPacketFromMBufRawPacketVec, vecSize, useTxBuffer); + bool DpdkDevice::sendPacket(RawPacket& rawPacket, uint16_t txQueueId, bool useTxBuffer) + { + uint8_t rawPacketType = rawPacket.getObjectType(); + if (rawPacketType == MBUFRAWPACKET_OBJECT_TYPE) + { + bool packetSent = (sendPacketsInner(txQueueId, (MBufRawPacket*)&rawPacket, getNextPacketFromMBufRawPacket, + 1, useTxBuffer) == 1); + bool needToFreeMbuf = (!useTxBuffer && !packetSent); + ((MBufRawPacket*)&rawPacket)->setFreeMbuf(needToFreeMbuf); + return packetSent; + } - bool needToFreeMbuf = (!useTxBuffer && (packetsSent != vecSize)); + MBufRawPacket mbufRawPacket; + if (unlikely(!mbufRawPacket.initFromRawPacket(&rawPacket, this))) + return false; - for (size_t index = 0; index < vecSize; index++) - rawPacketsVec.at(index)->setFreeMbuf(needToFreeMbuf); + bool packetSent = + (sendPacketsInner(txQueueId, &mbufRawPacket, getNextPacketFromMBufRawPacket, 1, useTxBuffer) == 1); + bool needToFreeMbuf = (!useTxBuffer && !packetSent); + mbufRawPacket.setFreeMbuf(needToFreeMbuf); - return packetsSent; -} + return packetSent; + } -bool DpdkDevice::sendPacket(RawPacket& rawPacket, uint16_t txQueueId, bool useTxBuffer) -{ - uint8_t rawPacketType = rawPacket.getObjectType(); - if (rawPacketType == MBUFRAWPACKET_OBJECT_TYPE) + bool DpdkDevice::sendPacket(MBufRawPacket& rawPacket, uint16_t txQueueId, bool useTxBuffer) { - bool packetSent = (sendPacketsInner(txQueueId, (MBufRawPacket*)&rawPacket, getNextPacketFromMBufRawPacket, 1, useTxBuffer) == 1); + bool packetSent = + (sendPacketsInner(txQueueId, &rawPacket, getNextPacketFromMBufRawPacket, 1, useTxBuffer) == 1); bool needToFreeMbuf = (!useTxBuffer && !packetSent); - ((MBufRawPacket*)&rawPacket)->setFreeMbuf(needToFreeMbuf); + rawPacket.setFreeMbuf(needToFreeMbuf); return packetSent; } - MBufRawPacket mbufRawPacket; - if (unlikely(!mbufRawPacket.initFromRawPacket(&rawPacket, this))) - return false; - - bool packetSent = (sendPacketsInner(txQueueId, &mbufRawPacket, getNextPacketFromMBufRawPacket, 1, useTxBuffer) == 1); - bool needToFreeMbuf = (!useTxBuffer && !packetSent); - mbufRawPacket.setFreeMbuf(needToFreeMbuf); - - return packetSent; -} - -bool DpdkDevice::sendPacket(MBufRawPacket& rawPacket, uint16_t txQueueId, bool useTxBuffer) -{ - bool packetSent = (sendPacketsInner(txQueueId, &rawPacket, getNextPacketFromMBufRawPacket, 1, useTxBuffer) == 1); - bool needToFreeMbuf = (!useTxBuffer && !packetSent); - rawPacket.setFreeMbuf(needToFreeMbuf); - return packetSent; -} - -bool DpdkDevice::sendPacket(Packet& packet, uint16_t txQueueId, bool useTxBuffer) -{ - return sendPacket(*(packet.getRawPacket()), txQueueId); -} - -int DpdkDevice::getAmountOfFreeMbufs() const -{ - return (int)rte_mempool_avail_count(m_MBufMempool); -} + bool DpdkDevice::sendPacket(Packet& packet, uint16_t txQueueId, bool useTxBuffer) + { + return sendPacket(*(packet.getRawPacket()), txQueueId); + } -int DpdkDevice::getAmountOfMbufsInUse() const -{ - return (int)rte_mempool_in_use_count(m_MBufMempool); -} + int DpdkDevice::getAmountOfFreeMbufs() const + { + return (int)rte_mempool_avail_count(m_MBufMempool); + } -uint64_t DpdkDevice::convertRssHfToDpdkRssHf(uint64_t rssHF) const -{ - if (rssHF == (uint64_t)-1) + int DpdkDevice::getAmountOfMbufsInUse() const { - rte_eth_dev_info devInfo; - rte_eth_dev_info_get(m_Id, &devInfo); - return devInfo.flow_type_rss_offloads; + return (int)rte_mempool_in_use_count(m_MBufMempool); } - uint64_t dpdkRssHF = 0; + uint64_t DpdkDevice::convertRssHfToDpdkRssHf(uint64_t rssHF) const + { + if (rssHF == (uint64_t)-1) + { + rte_eth_dev_info devInfo; + rte_eth_dev_info_get(m_Id, &devInfo); + return devInfo.flow_type_rss_offloads; + } - if ((rssHF & RSS_IPV4) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV4; + uint64_t dpdkRssHF = 0; - if ((rssHF & RSS_FRAG_IPV4) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_FRAG_IPV4; + if ((rssHF & RSS_IPV4) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV4; - if ((rssHF & RSS_NONFRAG_IPV4_TCP) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP; + if ((rssHF & RSS_FRAG_IPV4) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_FRAG_IPV4; - if ((rssHF & RSS_NONFRAG_IPV4_UDP) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP; + if ((rssHF & RSS_NONFRAG_IPV4_TCP) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP; - if ((rssHF & RSS_NONFRAG_IPV4_SCTP) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP; + if ((rssHF & RSS_NONFRAG_IPV4_UDP) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP; - if ((rssHF & RSS_NONFRAG_IPV4_OTHER) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER; + if ((rssHF & RSS_NONFRAG_IPV4_SCTP) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP; - if ((rssHF & RSS_IPV6) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6; + if ((rssHF & RSS_NONFRAG_IPV4_OTHER) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER; - if ((rssHF & RSS_FRAG_IPV6) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_FRAG_IPV6; + if ((rssHF & RSS_IPV6) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6; - if ((rssHF & RSS_NONFRAG_IPV6_TCP) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP; + if ((rssHF & RSS_FRAG_IPV6) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_FRAG_IPV6; - if ((rssHF & RSS_NONFRAG_IPV6_UDP) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP; + if ((rssHF & RSS_NONFRAG_IPV6_TCP) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP; - if ((rssHF & RSS_NONFRAG_IPV6_SCTP) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP; + if ((rssHF & RSS_NONFRAG_IPV6_UDP) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP; - if ((rssHF & RSS_NONFRAG_IPV6_OTHER) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER; + if ((rssHF & RSS_NONFRAG_IPV6_SCTP) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP; - if ((rssHF & RSS_L2_PAYLOAD) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_L2_PAYLOAD; + if ((rssHF & RSS_NONFRAG_IPV6_OTHER) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER; - if ((rssHF & RSS_IPV6_EX) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6_EX; + if ((rssHF & RSS_L2_PAYLOAD) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_L2_PAYLOAD; - if ((rssHF & RSS_IPV6_TCP_EX) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX; + if ((rssHF & RSS_IPV6_EX) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6_EX; - if ((rssHF & RSS_IPV6_UDP_EX) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX; + if ((rssHF & RSS_IPV6_TCP_EX) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX; - if ((rssHF & RSS_PORT) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_PORT; + if ((rssHF & RSS_IPV6_UDP_EX) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX; - if ((rssHF & RSS_VXLAN) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_VXLAN; + if ((rssHF & RSS_PORT) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_PORT; - if ((rssHF & RSS_GENEVE) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_GENEVE; + if ((rssHF & RSS_VXLAN) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_VXLAN; - if ((rssHF & RSS_NVGRE) != 0) - dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NVGRE; + if ((rssHF & RSS_GENEVE) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_GENEVE; - return dpdkRssHF; -} + if ((rssHF & RSS_NVGRE) != 0) + dpdkRssHF |= DPDK_CONFIG_ETH_RSS_NVGRE; -uint64_t DpdkDevice::convertDpdkRssHfToRssHf(uint64_t dpdkRssHF) const -{ - uint64_t rssHF = 0; + return dpdkRssHF; + } - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV4) != 0) - rssHF |= RSS_IPV4; + uint64_t DpdkDevice::convertDpdkRssHfToRssHf(uint64_t dpdkRssHF) const + { + uint64_t rssHF = 0; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_FRAG_IPV4) != 0) - rssHF |= RSS_FRAG_IPV4; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV4) != 0) + rssHF |= RSS_IPV4; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP) != 0) - rssHF |= RSS_NONFRAG_IPV4_TCP; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_FRAG_IPV4) != 0) + rssHF |= RSS_FRAG_IPV4; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP) != 0) - rssHF |= RSS_NONFRAG_IPV4_UDP; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_TCP) != 0) + rssHF |= RSS_NONFRAG_IPV4_TCP; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP) != 0) - rssHF |= RSS_NONFRAG_IPV4_SCTP; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_UDP) != 0) + rssHF |= RSS_NONFRAG_IPV4_UDP; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER) != 0) - rssHF |= RSS_NONFRAG_IPV4_OTHER; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_SCTP) != 0) + rssHF |= RSS_NONFRAG_IPV4_SCTP; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6) != 0) - rssHF |= RSS_IPV6; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV4_OTHER) != 0) + rssHF |= RSS_NONFRAG_IPV4_OTHER; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_FRAG_IPV6) != 0) - rssHF |= RSS_FRAG_IPV6; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6) != 0) + rssHF |= RSS_IPV6; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP) != 0) - rssHF |= RSS_NONFRAG_IPV6_TCP; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_FRAG_IPV6) != 0) + rssHF |= RSS_FRAG_IPV6; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP) != 0) - rssHF |= RSS_NONFRAG_IPV6_UDP; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_TCP) != 0) + rssHF |= RSS_NONFRAG_IPV6_TCP; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP) != 0) - rssHF |= RSS_NONFRAG_IPV6_SCTP; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_UDP) != 0) + rssHF |= RSS_NONFRAG_IPV6_UDP; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER) != 0) - rssHF |= RSS_NONFRAG_IPV6_OTHER; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_SCTP) != 0) + rssHF |= RSS_NONFRAG_IPV6_SCTP; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_L2_PAYLOAD) != 0) - rssHF |= RSS_L2_PAYLOAD; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NONFRAG_IPV6_OTHER) != 0) + rssHF |= RSS_NONFRAG_IPV6_OTHER; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6_EX) != 0) - rssHF |= RSS_IPV6_EX; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_L2_PAYLOAD) != 0) + rssHF |= RSS_L2_PAYLOAD; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX) != 0) - rssHF |= RSS_IPV6_TCP_EX; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6_EX) != 0) + rssHF |= RSS_IPV6_EX; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX) != 0) - rssHF |= RSS_IPV6_UDP_EX; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6_TCP_EX) != 0) + rssHF |= RSS_IPV6_TCP_EX; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_PORT) != 0) - rssHF |= RSS_PORT; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_IPV6_UDP_EX) != 0) + rssHF |= RSS_IPV6_UDP_EX; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_VXLAN) != 0) - rssHF |= RSS_VXLAN; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_PORT) != 0) + rssHF |= RSS_PORT; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_GENEVE) != 0) - rssHF |= RSS_GENEVE; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_VXLAN) != 0) + rssHF |= RSS_VXLAN; - if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NVGRE) != 0) - rssHF |= RSS_NVGRE; + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_GENEVE) != 0) + rssHF |= RSS_GENEVE; - return rssHF; -} + if ((dpdkRssHF & DPDK_CONFIG_ETH_RSS_NVGRE) != 0) + rssHF |= RSS_NVGRE; -bool DpdkDevice::isDeviceSupportRssHashFunction(DpdkRssHashFunction rssHF) const -{ - return isDeviceSupportRssHashFunction((uint64_t)rssHF); -} + return rssHF; + } -bool DpdkDevice::isDeviceSupportRssHashFunction(uint64_t rssHFMask) const -{ - uint64_t dpdkRssHF = convertRssHfToDpdkRssHf(rssHFMask); + bool DpdkDevice::isDeviceSupportRssHashFunction(DpdkRssHashFunction rssHF) const + { + return isDeviceSupportRssHashFunction((uint64_t)rssHF); + } - rte_eth_dev_info devInfo; - rte_eth_dev_info_get(m_Id, &devInfo); + bool DpdkDevice::isDeviceSupportRssHashFunction(uint64_t rssHFMask) const + { + uint64_t dpdkRssHF = convertRssHfToDpdkRssHf(rssHFMask); - return ((devInfo.flow_type_rss_offloads & dpdkRssHF) == dpdkRssHF); -} + rte_eth_dev_info devInfo; + rte_eth_dev_info_get(m_Id, &devInfo); -uint64_t DpdkDevice::getSupportedRssHashFunctions() const -{ - rte_eth_dev_info devInfo; - rte_eth_dev_info_get(m_Id, &devInfo); + return ((devInfo.flow_type_rss_offloads & dpdkRssHF) == dpdkRssHF); + } - return convertDpdkRssHfToRssHf(devInfo.flow_type_rss_offloads); -} + uint64_t DpdkDevice::getSupportedRssHashFunctions() const + { + rte_eth_dev_info devInfo; + rte_eth_dev_info_get(m_Id, &devInfo); -uint64_t DpdkDevice::getConfiguredRssHashFunction() const -{ - if (m_Config.rssHashFunction == static_cast(RSS_DEFAULT)) + return convertDpdkRssHfToRssHf(devInfo.flow_type_rss_offloads); + } + + uint64_t DpdkDevice::getConfiguredRssHashFunction() const { - if (m_PMDType == PMD_I40E || m_PMDType == PMD_I40EVF) + if (m_Config.rssHashFunction == static_cast(RSS_DEFAULT)) { - return RSS_NONFRAG_IPV4_TCP | RSS_NONFRAG_IPV4_UDP | RSS_NONFRAG_IPV4_OTHER | RSS_FRAG_IPV4 | RSS_NONFRAG_IPV6_TCP | RSS_NONFRAG_IPV6_UDP | RSS_NONFRAG_IPV6_OTHER | RSS_FRAG_IPV6; + if (m_PMDType == PMD_I40E || m_PMDType == PMD_I40EVF) + { + return RSS_NONFRAG_IPV4_TCP | RSS_NONFRAG_IPV4_UDP | RSS_NONFRAG_IPV4_OTHER | RSS_FRAG_IPV4 | + RSS_NONFRAG_IPV6_TCP | RSS_NONFRAG_IPV6_UDP | RSS_NONFRAG_IPV6_OTHER | RSS_FRAG_IPV6; + } + else + { + return RSS_IPV4 | RSS_IPV6; + } } - else + + if (m_Config.rssHashFunction == static_cast(RSS_ALL_SUPPORTED)) { - return RSS_IPV4 | RSS_IPV6; + return getSupportedRssHashFunctions(); } + return m_Config.rssHashFunction; } - if (m_Config.rssHashFunction == static_cast(RSS_ALL_SUPPORTED)) - { - return getSupportedRssHashFunctions(); - } - - return m_Config.rssHashFunction; -} - -std::vector DpdkDevice::rssHashFunctionMaskToString(uint64_t rssHFMask) const -{ - std::vector result = std::vector(); - - if (rssHFMask == RSS_NONE) + std::vector DpdkDevice::rssHashFunctionMaskToString(uint64_t rssHFMask) const { - result.push_back("RSS_NONE"); - return result; - } + std::vector result = std::vector(); - if ((rssHFMask & RSS_IPV4) != 0) - result.push_back("RSS_IPV4"); + if (rssHFMask == RSS_NONE) + { + result.push_back("RSS_NONE"); + return result; + } - if ((rssHFMask & RSS_FRAG_IPV4) != 0) - result.push_back("RSS_FRAG_IPV4"); + if ((rssHFMask & RSS_IPV4) != 0) + result.push_back("RSS_IPV4"); - if ((rssHFMask & RSS_NONFRAG_IPV4_TCP) != 0) - result.push_back("RSS_NONFRAG_IPV4_TCP"); + if ((rssHFMask & RSS_FRAG_IPV4) != 0) + result.push_back("RSS_FRAG_IPV4"); - if ((rssHFMask & RSS_NONFRAG_IPV4_UDP) != 0) - result.push_back("RSS_NONFRAG_IPV4_UDP"); + if ((rssHFMask & RSS_NONFRAG_IPV4_TCP) != 0) + result.push_back("RSS_NONFRAG_IPV4_TCP"); - if ((rssHFMask & RSS_NONFRAG_IPV4_SCTP) != 0) - result.push_back("RSS_NONFRAG_IPV4_SCTP"); + if ((rssHFMask & RSS_NONFRAG_IPV4_UDP) != 0) + result.push_back("RSS_NONFRAG_IPV4_UDP"); - if ((rssHFMask & RSS_NONFRAG_IPV4_OTHER) != 0) - result.push_back("RSS_NONFRAG_IPV4_OTHER"); + if ((rssHFMask & RSS_NONFRAG_IPV4_SCTP) != 0) + result.push_back("RSS_NONFRAG_IPV4_SCTP"); - if ((rssHFMask & RSS_IPV6) != 0) - result.push_back("RSS_IPV6"); + if ((rssHFMask & RSS_NONFRAG_IPV4_OTHER) != 0) + result.push_back("RSS_NONFRAG_IPV4_OTHER"); - if ((rssHFMask & RSS_FRAG_IPV6) != 0) - result.push_back("RSS_FRAG_IPV6"); + if ((rssHFMask & RSS_IPV6) != 0) + result.push_back("RSS_IPV6"); - if ((rssHFMask & RSS_NONFRAG_IPV6_TCP) != 0) - result.push_back("RSS_NONFRAG_IPV6_TCP"); + if ((rssHFMask & RSS_FRAG_IPV6) != 0) + result.push_back("RSS_FRAG_IPV6"); - if ((rssHFMask & RSS_NONFRAG_IPV6_UDP) != 0) - result.push_back("RSS_NONFRAG_IPV6_UDP"); + if ((rssHFMask & RSS_NONFRAG_IPV6_TCP) != 0) + result.push_back("RSS_NONFRAG_IPV6_TCP"); - if ((rssHFMask & RSS_NONFRAG_IPV6_SCTP) != 0) - result.push_back("RSS_NONFRAG_IPV6_SCTP"); + if ((rssHFMask & RSS_NONFRAG_IPV6_UDP) != 0) + result.push_back("RSS_NONFRAG_IPV6_UDP"); - if ((rssHFMask & RSS_NONFRAG_IPV6_OTHER) != 0) - result.push_back("RSS_NONFRAG_IPV6_OTHER"); + if ((rssHFMask & RSS_NONFRAG_IPV6_SCTP) != 0) + result.push_back("RSS_NONFRAG_IPV6_SCTP"); - if ((rssHFMask & RSS_L2_PAYLOAD) != 0) - result.push_back("RSS_L2_PAYLOAD"); + if ((rssHFMask & RSS_NONFRAG_IPV6_OTHER) != 0) + result.push_back("RSS_NONFRAG_IPV6_OTHER"); - if ((rssHFMask & RSS_IPV6_EX) != 0) - result.push_back("RSS_IPV6_EX"); + if ((rssHFMask & RSS_L2_PAYLOAD) != 0) + result.push_back("RSS_L2_PAYLOAD"); - if ((rssHFMask & RSS_IPV6_TCP_EX) != 0) - result.push_back("RSS_IPV6_TCP_EX"); + if ((rssHFMask & RSS_IPV6_EX) != 0) + result.push_back("RSS_IPV6_EX"); - if ((rssHFMask & RSS_IPV6_UDP_EX) != 0) - result.push_back("RSS_IPV6_UDP_EX"); + if ((rssHFMask & RSS_IPV6_TCP_EX) != 0) + result.push_back("RSS_IPV6_TCP_EX"); - if ((rssHFMask & RSS_PORT) != 0) - result.push_back("RSS_PORT"); + if ((rssHFMask & RSS_IPV6_UDP_EX) != 0) + result.push_back("RSS_IPV6_UDP_EX"); - if ((rssHFMask & RSS_VXLAN) != 0) - result.push_back("RSS_VXLAN"); + if ((rssHFMask & RSS_PORT) != 0) + result.push_back("RSS_PORT"); - if ((rssHFMask & RSS_GENEVE) != 0) - result.push_back("RSS_GENEVE"); + if ((rssHFMask & RSS_VXLAN) != 0) + result.push_back("RSS_VXLAN"); - if ((rssHFMask & RSS_NVGRE) != 0) - result.push_back("RSS_NVGRE"); + if ((rssHFMask & RSS_GENEVE) != 0) + result.push_back("RSS_GENEVE"); - return result; -} + if ((rssHFMask & RSS_NVGRE) != 0) + result.push_back("RSS_NVGRE"); + return result; + } -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/DpdkDeviceList.cpp b/Pcap++/src/DpdkDeviceList.cpp index f2b139129b..1c94dd7f2c 100644 --- a/Pcap++/src/DpdkDeviceList.cpp +++ b/Pcap++/src/DpdkDeviceList.cpp @@ -2,432 +2,440 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModuleDpdkDevice - -#define __STDC_LIMIT_MACROS -#define __STDC_FORMAT_MACROS - -#include "DpdkDeviceList.h" -#include "Logger.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#if (RTE_VER_YEAR < 21) || (RTE_VER_YEAR == 21 && RTE_VER_MONTH < 11) -#define GET_MASTER_CORE rte_get_master_lcore -#define MASTER_LCORE "--master-lcore" -#else -#define GET_MASTER_CORE rte_get_main_lcore -#define MASTER_LCORE "--main-lcore" -#endif +# define LOG_MODULE PcapLogModuleDpdkDevice + +# define __STDC_LIMIT_MACROS +# define __STDC_FORMAT_MACROS + +# include "DpdkDeviceList.h" +# include "Logger.h" + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# include +# include +# include +# include +# include + +# if (RTE_VER_YEAR < 21) || (RTE_VER_YEAR == 21 && RTE_VER_MONTH < 11) +# define GET_MASTER_CORE rte_get_master_lcore +# define MASTER_LCORE "--master-lcore" +# else +# define GET_MASTER_CORE rte_get_main_lcore +# define MASTER_LCORE "--main-lcore" +# endif namespace pcpp { -bool DpdkDeviceList::m_IsDpdkInitialized = false; -CoreMask DpdkDeviceList::m_CoreMask = 0; -uint32_t DpdkDeviceList::m_MBufPoolSizePerDevice = 0; -uint16_t DpdkDeviceList::m_MBufDataSize = 0; + bool DpdkDeviceList::m_IsDpdkInitialized = false; + CoreMask DpdkDeviceList::m_CoreMask = 0; + uint32_t DpdkDeviceList::m_MBufPoolSizePerDevice = 0; + uint16_t DpdkDeviceList::m_MBufDataSize = 0; -DpdkDeviceList::DpdkDeviceList() -{ - m_IsInitialized = false; -} - -DpdkDeviceList::~DpdkDeviceList() -{ - for (auto dev : m_DpdkDeviceList) + DpdkDeviceList::DpdkDeviceList() { - delete dev; + m_IsInitialized = false; } - m_DpdkDeviceList.clear(); -} - -bool DpdkDeviceList::initDpdk(CoreMask coreMask, uint32_t mBufPoolSizePerDevice, uint16_t mBufDataSize, uint8_t masterCore, uint32_t initDpdkArgc, char **initDpdkArgv, const std::string& appName, bool verifyHugePagesAndDriver) -{ - char **initDpdkArgvBuffer; - - if (m_IsDpdkInitialized) + DpdkDeviceList::~DpdkDeviceList() { - if (coreMask == m_CoreMask) - return true; - else + for (auto dev : m_DpdkDeviceList) { - PCPP_LOG_ERROR("Trying to re-initialize DPDK with a different core mask"); - return false; + delete dev; } - } - if (verifyHugePagesAndDriver && !verifyHugePagesAndDpdkDriver()) - { - return false; + m_DpdkDeviceList.clear(); } - // verify mBufPoolSizePerDevice is power of 2 minus 1 - bool isPoolSizePowerOfTwoMinusOne = !(mBufPoolSizePerDevice == 0) && !((mBufPoolSizePerDevice+1) & (mBufPoolSizePerDevice)); - if (!isPoolSizePowerOfTwoMinusOne) + bool DpdkDeviceList::initDpdk(CoreMask coreMask, uint32_t mBufPoolSizePerDevice, uint16_t mBufDataSize, + uint8_t masterCore, uint32_t initDpdkArgc, char** initDpdkArgv, + const std::string& appName, bool verifyHugePagesAndDriver) { - PCPP_LOG_ERROR("mBuf pool size must be a power of two minus one: n = (2^q - 1). It's currently: " << mBufPoolSizePerDevice); - return false; - } + char** initDpdkArgvBuffer; + if (m_IsDpdkInitialized) + { + if (coreMask == m_CoreMask) + return true; + else + { + PCPP_LOG_ERROR("Trying to re-initialize DPDK with a different core mask"); + return false; + } + } - std::stringstream dpdkParamsStream; - dpdkParamsStream << appName << " "; - dpdkParamsStream << "-n "; - dpdkParamsStream << "2 "; - dpdkParamsStream << "-c "; - dpdkParamsStream << "0x" << std::hex << std::setw(2) << std::setfill('0') << coreMask << " "; - dpdkParamsStream << MASTER_LCORE << " "; - dpdkParamsStream << (int)masterCore << " "; + if (verifyHugePagesAndDriver && !verifyHugePagesAndDpdkDriver()) + { + return false; + } - uint32_t i = 0; - while (i < initDpdkArgc && initDpdkArgv[i] != NULL) - { - dpdkParamsStream << initDpdkArgv[i] << " "; - i++; - } + // verify mBufPoolSizePerDevice is power of 2 minus 1 + bool isPoolSizePowerOfTwoMinusOne = + !(mBufPoolSizePerDevice == 0) && !((mBufPoolSizePerDevice + 1) & (mBufPoolSizePerDevice)); + if (!isPoolSizePowerOfTwoMinusOne) + { + PCPP_LOG_ERROR("mBuf pool size must be a power of two minus one: n = (2^q - 1). It's currently: " + << mBufPoolSizePerDevice); + return false; + } - // Should be equal to the number of static params - initDpdkArgc += 7; - std::string dpdkParamsArray[initDpdkArgc]; - initDpdkArgvBuffer = new char*[initDpdkArgc]; - i = 0; - while (dpdkParamsStream.good() && i < initDpdkArgc) - { - dpdkParamsStream >> dpdkParamsArray[i]; - initDpdkArgvBuffer[i] = new char[dpdkParamsArray[i].length() + 1]; - strcpy(initDpdkArgvBuffer[i], dpdkParamsArray[i].c_str()); - i++; - } + std::stringstream dpdkParamsStream; + dpdkParamsStream << appName << " "; + dpdkParamsStream << "-n "; + dpdkParamsStream << "2 "; + dpdkParamsStream << "-c "; + dpdkParamsStream << "0x" << std::hex << std::setw(2) << std::setfill('0') << coreMask << " "; + dpdkParamsStream << MASTER_LCORE << " "; + dpdkParamsStream << (int)masterCore << " "; + + uint32_t i = 0; + while (i < initDpdkArgc && initDpdkArgv[i] != NULL) + { + dpdkParamsStream << initDpdkArgv[i] << " "; + i++; + } - char* lastParam = initDpdkArgvBuffer[i-1]; + // Should be equal to the number of static params + initDpdkArgc += 7; + std::string dpdkParamsArray[initDpdkArgc]; + initDpdkArgvBuffer = new char*[initDpdkArgc]; + i = 0; + while (dpdkParamsStream.good() && i < initDpdkArgc) + { + dpdkParamsStream >> dpdkParamsArray[i]; + initDpdkArgvBuffer[i] = new char[dpdkParamsArray[i].length() + 1]; + strcpy(initDpdkArgvBuffer[i], dpdkParamsArray[i].c_str()); + i++; + } - for (i = 0; i < initDpdkArgc; i++) - { - PCPP_LOG_DEBUG("DPDK initialization params: " << initDpdkArgvBuffer[i]); - } + char* lastParam = initDpdkArgvBuffer[i - 1]; - optind = 1; - // init the EAL - int ret = rte_eal_init(initDpdkArgc, (char**)initDpdkArgvBuffer); - if (ret < 0) - { - PCPP_LOG_ERROR("failed to init the DPDK EAL"); - return false; - } + for (i = 0; i < initDpdkArgc; i++) + { + PCPP_LOG_DEBUG("DPDK initialization params: " << initDpdkArgvBuffer[i]); + } - for (i = 0; i < initDpdkArgc-1; i++) - { - delete [] initDpdkArgvBuffer[i]; - } - delete [] lastParam; + optind = 1; + // init the EAL + int ret = rte_eal_init(initDpdkArgc, (char**)initDpdkArgvBuffer); + if (ret < 0) + { + PCPP_LOG_ERROR("failed to init the DPDK EAL"); + return false; + } - delete [] initDpdkArgvBuffer; + for (i = 0; i < initDpdkArgc - 1; i++) + { + delete[] initDpdkArgvBuffer[i]; + } + delete[] lastParam; - m_CoreMask = coreMask; - m_IsDpdkInitialized = true; + delete[] initDpdkArgvBuffer; - m_MBufPoolSizePerDevice = mBufPoolSizePerDevice; - m_MBufDataSize = mBufDataSize; - DpdkDeviceList::getInstance().setDpdkLogLevel(Logger::Info); - return DpdkDeviceList::getInstance().initDpdkDevices(m_MBufPoolSizePerDevice, m_MBufDataSize); -} + m_CoreMask = coreMask; + m_IsDpdkInitialized = true; -bool DpdkDeviceList::initDpdkDevices(uint32_t mBufPoolSizePerDevice, uint16_t mBufDataSize) -{ - if (!m_IsDpdkInitialized) - { - PCPP_LOG_ERROR("DPDK is not initialized!! Please call DpdkDeviceList::initDpdk(coreMask, mBufPoolSizePerDevice) before start using DPDK devices"); - return false; + m_MBufPoolSizePerDevice = mBufPoolSizePerDevice; + m_MBufDataSize = mBufDataSize; + DpdkDeviceList::getInstance().setDpdkLogLevel(Logger::Info); + return DpdkDeviceList::getInstance().initDpdkDevices(m_MBufPoolSizePerDevice, m_MBufDataSize); } - if (m_IsInitialized) - return true; + bool DpdkDeviceList::initDpdkDevices(uint32_t mBufPoolSizePerDevice, uint16_t mBufDataSize) + { + if (!m_IsDpdkInitialized) + { + PCPP_LOG_ERROR( + "DPDK is not initialized!! Please call DpdkDeviceList::initDpdk(coreMask, mBufPoolSizePerDevice) before start using DPDK devices"); + return false; + } -#if (RTE_VER_YEAR < 18) || (RTE_VER_YEAR == 18 && RTE_VER_MONTH < 5) - int numOfPorts = (int)rte_eth_dev_count(); -#else - int numOfPorts = (int)rte_eth_dev_count_avail(); -#endif + if (m_IsInitialized) + return true; - if (numOfPorts <= 0) - { - PCPP_LOG_ERROR("Zero DPDK ports are initialized. Something went wrong while initializing DPDK"); - return false; - } +# if (RTE_VER_YEAR < 18) || (RTE_VER_YEAR == 18 && RTE_VER_MONTH < 5) + int numOfPorts = (int)rte_eth_dev_count(); +# else + int numOfPorts = (int)rte_eth_dev_count_avail(); +# endif - PCPP_LOG_DEBUG("Found " << numOfPorts << " DPDK ports. Constructing DpdkDevice for each one"); + if (numOfPorts <= 0) + { + PCPP_LOG_ERROR("Zero DPDK ports are initialized. Something went wrong while initializing DPDK"); + return false; + } - // Initialize a DpdkDevice per port - for (int i = 0; i < numOfPorts; i++) - { - DpdkDevice* newDevice = new DpdkDevice(i, mBufPoolSizePerDevice, mBufDataSize); - PCPP_LOG_DEBUG("DpdkDevice #" << i << ": Name='" << newDevice->getDeviceName() << "', PCI-slot='" << newDevice->getPciAddress() << "', PMD='" << newDevice->getPMDName() << "', MAC Addr='" << newDevice->getMacAddress() << "'"); - m_DpdkDeviceList.push_back(newDevice); - } + PCPP_LOG_DEBUG("Found " << numOfPorts << " DPDK ports. Constructing DpdkDevice for each one"); - m_IsInitialized = true; - return true; -} + // Initialize a DpdkDevice per port + for (int i = 0; i < numOfPorts; i++) + { + DpdkDevice* newDevice = new DpdkDevice(i, mBufPoolSizePerDevice, mBufDataSize); + PCPP_LOG_DEBUG("DpdkDevice #" << i << ": Name='" << newDevice->getDeviceName() << "', PCI-slot='" + << newDevice->getPciAddress() << "', PMD='" << newDevice->getPMDName() + << "', MAC Addr='" << newDevice->getMacAddress() << "'"); + m_DpdkDeviceList.push_back(newDevice); + } -DpdkDevice* DpdkDeviceList::getDeviceByPort(int portId) const -{ - if (!isInitialized()) - { - PCPP_LOG_ERROR("DpdkDeviceList not initialized"); - return NULL; + m_IsInitialized = true; + return true; } - if ((uint32_t)portId >= m_DpdkDeviceList.size()) + DpdkDevice* DpdkDeviceList::getDeviceByPort(int portId) const { - return NULL; - } + if (!isInitialized()) + { + PCPP_LOG_ERROR("DpdkDeviceList not initialized"); + return NULL; + } - return m_DpdkDeviceList.at(portId); -} + if ((uint32_t)portId >= m_DpdkDeviceList.size()) + { + return NULL; + } -DpdkDevice* DpdkDeviceList::getDeviceByPciAddress(const std::string& pciAddr) const -{ - if (!isInitialized()) - { - PCPP_LOG_ERROR("DpdkDeviceList not initialized"); - return NULL; + return m_DpdkDeviceList.at(portId); } - auto devIter = std::find_if(m_DpdkDeviceList.begin(), m_DpdkDeviceList.end(), - [&pciAddr](const DpdkDevice *dev) { return dev->getPciAddress() == pciAddr; }); - - if (devIter == m_DpdkDeviceList.end()) + DpdkDevice* DpdkDeviceList::getDeviceByPciAddress(const std::string& pciAddr) const { - PCPP_LOG_DEBUG("Found no DPDK devices with PCI address '" << pciAddr << "'"); - return nullptr; - } - - return *devIter; -} - -bool DpdkDeviceList::verifyHugePagesAndDpdkDriver() -{ - std::string execResult = executeShellCommand("cat /proc/meminfo | grep -s HugePages_Total | awk '{print $2}'"); - // trim '\n' at the end - execResult.erase(std::remove(execResult.begin(), execResult.end(), '\n'), execResult.end()); + if (!isInitialized()) + { + PCPP_LOG_ERROR("DpdkDeviceList not initialized"); + return NULL; + } - // convert the result to long - char* endPtr; - long totalHugePages = strtol(execResult.c_str(), &endPtr, 10); + auto devIter = std::find_if(m_DpdkDeviceList.begin(), m_DpdkDeviceList.end(), + [&pciAddr](const DpdkDevice* dev) { return dev->getPciAddress() == pciAddr; }); - PCPP_LOG_DEBUG("Total number of huge-pages is " << totalHugePages); + if (devIter == m_DpdkDeviceList.end()) + { + PCPP_LOG_DEBUG("Found no DPDK devices with PCI address '" << pciAddr << "'"); + return nullptr; + } - if (totalHugePages <= 0) - { - PCPP_LOG_ERROR("Huge pages aren't set, DPDK cannot be initialized. Please run /setup_dpdk.sh"); - return false; + return *devIter; } - execResult = executeShellCommand("lsmod | grep -s igb_uio"); - if (execResult == "") + bool DpdkDeviceList::verifyHugePagesAndDpdkDriver() { - try + std::string execResult = executeShellCommand("cat /proc/meminfo | grep -s HugePages_Total | awk '{print $2}'"); + // trim '\n' at the end + execResult.erase(std::remove(execResult.begin(), execResult.end(), '\n'), execResult.end()); + + // convert the result to long + char* endPtr; + long totalHugePages = strtol(execResult.c_str(), &endPtr, 10); + + PCPP_LOG_DEBUG("Total number of huge-pages is " << totalHugePages); + + if (totalHugePages <= 0) { - execResult = executeShellCommand("modinfo -d uio_pci_generic"); - PCPP_LOG_DEBUG("uio_pci_generic module is loaded"); + PCPP_LOG_ERROR( + "Huge pages aren't set, DPDK cannot be initialized. Please run /setup_dpdk.sh"); + return false; } - catch (const std::runtime_error&) + + execResult = executeShellCommand("lsmod | grep -s igb_uio"); + if (execResult == "") { try { - execResult = executeShellCommand("modinfo -d vfio-pci"); - PCPP_LOG_DEBUG("vfio-pci module is loaded"); + execResult = executeShellCommand("modinfo -d uio_pci_generic"); + PCPP_LOG_DEBUG("uio_pci_generic module is loaded"); } catch (const std::runtime_error&) { - PCPP_LOG_ERROR("None of igb_uio, uio_pci_generic, vfio-pci kernel modules are loaded so DPDK cannot be " - "initialized. Please run /setup_dpdk.sh"); - return false; + try + { + execResult = executeShellCommand("modinfo -d vfio-pci"); + PCPP_LOG_DEBUG("vfio-pci module is loaded"); + } + catch (const std::runtime_error&) + { + PCPP_LOG_ERROR( + "None of igb_uio, uio_pci_generic, vfio-pci kernel modules are loaded so DPDK cannot be " + "initialized. Please run /setup_dpdk.sh"); + return false; + } } } - } - else - PCPP_LOG_DEBUG("igb_uio driver is loaded"); - - return true; -} - -SystemCore DpdkDeviceList::getDpdkMasterCore() const -{ - return SystemCores::IdToSystemCore[GET_MASTER_CORE()]; -} - -void DpdkDeviceList::setDpdkLogLevel(Logger::LogLevel logLevel) -{ -#if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) - if (logLevel == Logger::Info) - rte_log_set_global_level(RTE_LOG_NOTICE); - else // logLevel == Logger::Debug - rte_log_set_global_level(RTE_LOG_DEBUG); -#else - if (logLevel == Logger::Info) - rte_set_log_level(RTE_LOG_NOTICE); - else // logLevel == Logger::Debug - rte_set_log_level(RTE_LOG_DEBUG); -#endif -} - -Logger::LogLevel DpdkDeviceList::getDpdkLogLevel() const -{ -#if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) - if (rte_log_get_global_level() <= RTE_LOG_NOTICE) -#else - if (rte_get_log_level() <= RTE_LOG_NOTICE) -#endif - return Logger::Info; - else - return Logger::Debug; -} - -bool DpdkDeviceList::writeDpdkLogToFile(FILE* logFile) -{ - return (rte_openlog_stream(logFile) == 0); -} + else + PCPP_LOG_DEBUG("igb_uio driver is loaded"); -int DpdkDeviceList::dpdkWorkerThreadStart(void *ptr) -{ - DpdkWorkerThread* workerThread = (DpdkWorkerThread*)ptr; - workerThread->run(rte_lcore_id()); - return 0; -} + return true; + } -bool DpdkDeviceList::startDpdkWorkerThreads(CoreMask coreMask, std::vector& workerThreadsVec) -{ - if (!isInitialized()) + SystemCore DpdkDeviceList::getDpdkMasterCore() const { - PCPP_LOG_ERROR("DpdkDeviceList not initialized"); - return false; + return SystemCores::IdToSystemCore[GET_MASTER_CORE()]; } - CoreMask tempCoreMask = coreMask; - size_t numOfCoresInMask = 0; - int coreNum = 0; - while (tempCoreMask > 0) + void DpdkDeviceList::setDpdkLogLevel(Logger::LogLevel logLevel) { - if (tempCoreMask & 1) - { - if (!rte_lcore_is_enabled(coreNum)) - { - PCPP_LOG_ERROR("Trying to use core #" << coreNum << " which isn't initialized by DPDK"); - return false; - } - - numOfCoresInMask++; - } - tempCoreMask = tempCoreMask >> 1; - coreNum++; +# if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) + if (logLevel == Logger::Info) + rte_log_set_global_level(RTE_LOG_NOTICE); + else // logLevel == Logger::Debug + rte_log_set_global_level(RTE_LOG_DEBUG); +# else + if (logLevel == Logger::Info) + rte_set_log_level(RTE_LOG_NOTICE); + else // logLevel == Logger::Debug + rte_set_log_level(RTE_LOG_DEBUG); +# endif } - if (numOfCoresInMask == 0) + Logger::LogLevel DpdkDeviceList::getDpdkLogLevel() const { - PCPP_LOG_ERROR("Number of cores in mask is 0"); - return false; +# if (RTE_VER_YEAR > 17) || (RTE_VER_YEAR == 17 && RTE_VER_MONTH >= 11) + if (rte_log_get_global_level() <= RTE_LOG_NOTICE) +# else + if (rte_get_log_level() <= RTE_LOG_NOTICE) +# endif + return Logger::Info; + else + return Logger::Debug; } - if (numOfCoresInMask != workerThreadsVec.size()) + bool DpdkDeviceList::writeDpdkLogToFile(FILE* logFile) { - PCPP_LOG_ERROR("Number of cores in core mask different from workerThreadsVec size"); - return false; + return (rte_openlog_stream(logFile) == 0); } - if (coreMask & getDpdkMasterCore().Mask) + int DpdkDeviceList::dpdkWorkerThreadStart(void* ptr) { - PCPP_LOG_ERROR("Cannot run worker thread on DPDK master core"); - return false; + DpdkWorkerThread* workerThread = (DpdkWorkerThread*)ptr; + workerThread->run(rte_lcore_id()); + return 0; } - m_WorkerThreads.clear(); - uint32_t index = 0; - auto iter = workerThreadsVec.begin(); - while (iter != workerThreadsVec.end()) + bool DpdkDeviceList::startDpdkWorkerThreads(CoreMask coreMask, std::vector& workerThreadsVec) { - SystemCore core = SystemCores::IdToSystemCore[index]; - if (!(coreMask & core.Mask)) + if (!isInitialized()) { - index++; - continue; + PCPP_LOG_ERROR("DpdkDeviceList not initialized"); + return false; } - int err = rte_eal_remote_launch(dpdkWorkerThreadStart, *iter, core.Id); - if (err != 0) + CoreMask tempCoreMask = coreMask; + size_t numOfCoresInMask = 0; + int coreNum = 0; + while (tempCoreMask > 0) { - for (const auto &thread : workerThreadsVec) + if (tempCoreMask & 1) { - thread->stop(); - rte_eal_wait_lcore(thread->getCoreId()); - PCPP_LOG_DEBUG("Thread on core [" << thread->getCoreId() << "] stopped"); + if (!rte_lcore_is_enabled(coreNum)) + { + PCPP_LOG_ERROR("Trying to use core #" << coreNum << " which isn't initialized by DPDK"); + return false; + } + + numOfCoresInMask++; } - PCPP_LOG_ERROR("Cannot create worker thread #" << core.Id << ". Error was: [" << strerror(err) << "]"); + tempCoreMask = tempCoreMask >> 1; + coreNum++; + } + + if (numOfCoresInMask == 0) + { + PCPP_LOG_ERROR("Number of cores in mask is 0"); return false; } - m_WorkerThreads.push_back(*iter); - ++index; - ++iter; - } + if (numOfCoresInMask != workerThreadsVec.size()) + { + PCPP_LOG_ERROR("Number of cores in core mask different from workerThreadsVec size"); + return false; + } - return true; -} + if (coreMask & getDpdkMasterCore().Mask) + { + PCPP_LOG_ERROR("Cannot run worker thread on DPDK master core"); + return false; + } -void DpdkDeviceList::stopDpdkWorkerThreads() -{ - if (m_WorkerThreads.empty()) - { - PCPP_LOG_ERROR("No worker threads were set"); - return; + m_WorkerThreads.clear(); + uint32_t index = 0; + auto iter = workerThreadsVec.begin(); + while (iter != workerThreadsVec.end()) + { + SystemCore core = SystemCores::IdToSystemCore[index]; + if (!(coreMask & core.Mask)) + { + index++; + continue; + } + + int err = rte_eal_remote_launch(dpdkWorkerThreadStart, *iter, core.Id); + if (err != 0) + { + for (const auto& thread : workerThreadsVec) + { + thread->stop(); + rte_eal_wait_lcore(thread->getCoreId()); + PCPP_LOG_DEBUG("Thread on core [" << thread->getCoreId() << "] stopped"); + } + PCPP_LOG_ERROR("Cannot create worker thread #" << core.Id << ". Error was: [" << strerror(err) << "]"); + return false; + } + m_WorkerThreads.push_back(*iter); + + ++index; + ++iter; + } + + return true; } - for (const auto &thread : m_WorkerThreads) + void DpdkDeviceList::stopDpdkWorkerThreads() { - thread->stop(); - rte_eal_wait_lcore(thread->getCoreId()); - PCPP_LOG_DEBUG("Thread on core [" << thread->getCoreId() << "] stopped"); - } + if (m_WorkerThreads.empty()) + { + PCPP_LOG_ERROR("No worker threads were set"); + return; + } - m_WorkerThreads.clear(); - std::vector(m_WorkerThreads).swap(m_WorkerThreads); + for (const auto& thread : m_WorkerThreads) + { + thread->stop(); + rte_eal_wait_lcore(thread->getCoreId()); + PCPP_LOG_DEBUG("Thread on core [" << thread->getCoreId() << "] stopped"); + } - PCPP_LOG_DEBUG("All worker threads stopped"); -} + m_WorkerThreads.clear(); + std::vector(m_WorkerThreads).swap(m_WorkerThreads); + + PCPP_LOG_DEBUG("All worker threads stopped"); + } -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/KniDevice.cpp b/Pcap++/src/KniDevice.cpp index 8dd37d47d7..40f38fa58d 100644 --- a/Pcap++/src/KniDevice.cpp +++ b/Pcap++/src/KniDevice.cpp @@ -2,987 +2,964 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModuleKniDevice - -#include "KniDevice.h" -#include "Logger.h" -#include "SystemUtils.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifndef KNI_MEMPOOL_NAME_PREFIX -# define KNI_MEMPOOL_NAME_PREFIX "kniMempool" -#endif -#ifndef MEMPOOL_CACHE_SIZE -# define MEMPOOL_CACHE_SIZE 256 -#endif -#ifndef MAX_BURST_SIZE -# define MAX_BURST_SIZE 64 -#endif - -#define CPP_VLA(TYPE, SIZE) (TYPE*)__builtin_alloca(sizeof(TYPE) * SIZE) +# define LOG_MODULE PcapLogModuleKniDevice + +# include "KniDevice.h" +# include "Logger.h" +# include "SystemUtils.h" + +# include +# include +# include +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include + +# include +# include +# include +# include + +# ifndef KNI_MEMPOOL_NAME_PREFIX +# define KNI_MEMPOOL_NAME_PREFIX "kniMempool" +# endif +# ifndef MEMPOOL_CACHE_SIZE +# define MEMPOOL_CACHE_SIZE 256 +# endif +# ifndef MAX_BURST_SIZE +# define MAX_BURST_SIZE 64 +# endif + +# define CPP_VLA(TYPE, SIZE) (TYPE*)__builtin_alloca(sizeof(TYPE) * SIZE) namespace pcpp { -/** - * ========================== - * Class KniDevice::KniThread - * ========================== - */ + /** + * ========================== + * Class KniDevice::KniThread + * ========================== + */ -struct KniDevice::KniThread -{ - enum KniThreadCleanupState + struct KniDevice::KniThread { - JOINABLE, - DETACHED, - INVALID + enum KniThreadCleanupState + { + JOINABLE, + DETACHED, + INVALID + }; + typedef void (*threadMain)(void*, std::atomic&); + KniThread(KniThreadCleanupState s, threadMain tm, void* data); + ~KniThread(); + + void cancel(); + + std::thread m_Descriptor; + KniThreadCleanupState m_CleanupState; + std::atomic m_StopThread; }; - typedef void(*threadMain)(void*, std::atomic& ); - KniThread(KniThreadCleanupState s, threadMain tm, void* data); - ~KniThread(); - - void cancel(); - std::thread m_Descriptor; - KniThreadCleanupState m_CleanupState; - std::atomic m_StopThread; -}; + KniDevice::KniThread::KniThread(KniThreadCleanupState s, threadMain tm, void* data) : m_CleanupState(s) + { + m_StopThread = false; + m_Descriptor = std::thread(tm, data, std::ref(m_StopThread)); -KniDevice::KniThread::KniThread(KniThreadCleanupState s, threadMain tm, void* data) : - m_CleanupState(s) -{ - m_StopThread = false; - m_Descriptor = std::thread(tm, data, std::ref(m_StopThread)); + if (m_CleanupState == DETACHED) + { + m_Descriptor.detach(); + } + } - if (m_CleanupState == DETACHED) + KniDevice::KniThread::~KniThread() { - m_Descriptor.detach(); + if (m_CleanupState == JOINABLE) + { + m_Descriptor.join(); + } } -} -KniDevice::KniThread::~KniThread() -{ - if (m_CleanupState == JOINABLE) + void KniDevice::KniThread::cancel() { - m_Descriptor.join(); + m_StopThread = true; } -} -void KniDevice::KniThread::cancel() -{ - m_StopThread = true; -} + /** + * =============== + * Class KniDevice + * =============== + */ + namespace + { -/** - * =============== - * Class KniDevice - * =============== - */ + inline bool destroyKniDevice(struct rte_kni* kni, const char* deviceName) + { + if (rte_kni_release(kni) < 0) + { + PCPP_LOG_ERROR("Failed to destroy DPDK KNI device " << deviceName); + return true; + } + return false; + } -namespace -{ + inline KniDevice::KniLinkState setKniDeviceLinkState(struct rte_kni* kni, const char* deviceName, + KniDevice::KniLinkState state = KniDevice::LINK_UP) + { + KniDevice::KniLinkState oldState = KniDevice::LINK_NOT_SUPPORTED; + if (kni == NULL || !(state == KniDevice::LINK_UP || state == KniDevice::LINK_DOWN)) + { + return oldState = KniDevice::LINK_ERROR; + } +# if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) + oldState = (KniDevice::KniLinkState)rte_kni_update_link(kni, state); + if (oldState == KniDevice::LINK_ERROR) + { //? NOTE(echo-Mike): Not LOG_ERROR because will generate a lot of junk messages on some DPDK versions + PCPP_LOG_DEBUG("DPDK KNI Failed to update links state for device '" << deviceName << "'"); + } +# else + // To avoid compiler warnings + (void)kni; + (void)deviceName; +# endif + return oldState; + } -inline bool destroyKniDevice(struct rte_kni* kni, const char* deviceName) -{ - if (rte_kni_release(kni) < 0) + inline struct rte_mempool* createMempool(size_t mempoolSize, int unique, const char* deviceName) + { + struct rte_mempool* result = NULL; + char mempoolName[64]; + snprintf(mempoolName, sizeof(mempoolName), KNI_MEMPOOL_NAME_PREFIX "%d", unique); + result = rte_pktmbuf_pool_create(mempoolName, mempoolSize, MEMPOOL_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, + rte_socket_id()); + if (result == NULL) + { + PCPP_LOG_ERROR("Failed to create packets memory pool for KNI device '" + << deviceName << "', pool name: " << mempoolName); + } + else + { + PCPP_LOG_DEBUG("Successfully initialized packets pool of size [" << mempoolSize << "] for KNI device [" + << deviceName << "]"); + } + return result; + } + + } // namespace + + KniDevice::KniDevice(const KniDeviceConfiguration& conf, size_t mempoolSize, int unique) + : m_Device(NULL), m_MBufMempool(NULL) { - PCPP_LOG_ERROR("Failed to destroy DPDK KNI device " << deviceName); - return true; - } - return false; -} + struct rte_kni_ops kniOps; + struct rte_kni_conf kniConf; + if (!m_DeviceInfo.init(conf)) + return; + m_Requests.thread = NULL; + std::memset(&m_Capturing, 0, sizeof(m_Capturing)); + std::memset(&m_Requests, 0, sizeof(m_Requests)); -inline KniDevice::KniLinkState setKniDeviceLinkState( - struct rte_kni* kni, - const char* deviceName, - KniDevice::KniLinkState state = KniDevice::LINK_UP -) -{ - KniDevice::KniLinkState oldState = KniDevice::LINK_NOT_SUPPORTED; - if (kni == NULL || !(state == KniDevice::LINK_UP || state == KniDevice::LINK_DOWN)) - { - return oldState = KniDevice::LINK_ERROR; - } - #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) - oldState = (KniDevice::KniLinkState)rte_kni_update_link(kni, state); - if (oldState == KniDevice::LINK_ERROR) - { //? NOTE(echo-Mike): Not LOG_ERROR because will generate a lot of junk messages on some DPDK versions - PCPP_LOG_DEBUG("DPDK KNI Failed to update links state for device '" << deviceName << "'"); - } - #else - // To avoid compiler warnings - (void) kni; - (void) deviceName; - #endif - return oldState; -} - -inline struct rte_mempool* createMempool(size_t mempoolSize, int unique, const char* deviceName) -{ - struct rte_mempool* result = NULL; - char mempoolName[64]; - snprintf(mempoolName, sizeof(mempoolName), - KNI_MEMPOOL_NAME_PREFIX "%d", - unique - ); - result = rte_pktmbuf_pool_create( - mempoolName, - mempoolSize, - MEMPOOL_CACHE_SIZE, - 0, - RTE_MBUF_DEFAULT_BUF_SIZE, - rte_socket_id() - ); - if (result == NULL) - { - PCPP_LOG_ERROR("Failed to create packets memory pool for KNI device '" << deviceName << "', pool name: " << mempoolName); - } - else - { - PCPP_LOG_DEBUG("Successfully initialized packets pool of size [" << mempoolSize << "] for KNI device [" << deviceName << "]"); - } - return result; -} - -} // namespace - -KniDevice::KniDevice(const KniDeviceConfiguration& conf, size_t mempoolSize, int unique) : - m_Device(NULL), m_MBufMempool(NULL) -{ - struct rte_kni_ops kniOps; - struct rte_kni_conf kniConf; - if (!m_DeviceInfo.init(conf)) - return; - m_Requests.thread = NULL; - std::memset(&m_Capturing, 0, sizeof(m_Capturing)); - std::memset(&m_Requests, 0, sizeof(m_Requests)); - - if ((m_MBufMempool = createMempool(mempoolSize, unique, conf.name.c_str())) == NULL) - return; - - std::memset(&kniOps, 0, sizeof(kniOps)); - std::memset(&kniConf, 0, sizeof(kniConf)); - snprintf(kniConf.name, RTE_KNI_NAMESIZE, "%s", conf.name.c_str()); - kniConf.core_id = conf.kthreadCoreId; - kniConf.mbuf_size = RTE_MBUF_DEFAULT_BUF_SIZE; - kniConf.force_bind = conf.bindKthread ? 1 : 0; - #if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) + if ((m_MBufMempool = createMempool(mempoolSize, unique, conf.name.c_str())) == NULL) + return; + + std::memset(&kniOps, 0, sizeof(kniOps)); + std::memset(&kniConf, 0, sizeof(kniConf)); + snprintf(kniConf.name, RTE_KNI_NAMESIZE, "%s", conf.name.c_str()); + kniConf.core_id = conf.kthreadCoreId; + kniConf.mbuf_size = RTE_MBUF_DEFAULT_BUF_SIZE; + kniConf.force_bind = conf.bindKthread ? 1 : 0; +# if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) if (conf.mac != MacAddress::Zero) conf.mac.copyTo((uint8_t*)kniConf.mac_addr); kniConf.mtu = conf.mtu; - #endif +# endif - kniOps.port_id = conf.portId; - #if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 0) + kniOps.port_id = conf.portId; +# if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 0) if (conf.callbacks != NULL) { kniOps.change_mtu = conf.callbacks->change_mtu; kniOps.config_network_if = conf.callbacks->config_network_if; - #if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) +# if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) kniOps.config_mac_address = conf.callbacks->config_mac_address; kniOps.config_promiscusity = conf.callbacks->config_promiscusity; - #endif +# endif } - #else +# else if (conf.oldCallbacks != NULL) { kniOps.change_mtu = conf.oldCallbacks->change_mtu; kniOps.config_network_if = conf.oldCallbacks->config_network_if; } - #endif +# endif - m_Device = rte_kni_alloc(m_MBufMempool, &kniConf, &kniOps); - if (m_Device == NULL) - { - PCPP_LOG_ERROR("DPDK have failed to create KNI device " << conf.name); + m_Device = rte_kni_alloc(m_MBufMempool, &kniConf, &kniOps); + if (m_Device == NULL) + { + PCPP_LOG_ERROR("DPDK have failed to create KNI device " << conf.name); + } } -} -KniDevice::~KniDevice() -{ - m_Requests.cleanup(); - m_Capturing.cleanup(); - if (m_Device != NULL) + KniDevice::~KniDevice() { - setKniDeviceLinkState(m_Device, m_DeviceInfo.name.c_str(), KniDevice::LINK_DOWN); - destroyKniDevice(m_Device, m_DeviceInfo.name.c_str()); + m_Requests.cleanup(); + m_Capturing.cleanup(); + if (m_Device != NULL) + { + setKniDeviceLinkState(m_Device, m_DeviceInfo.name.c_str(), KniDevice::LINK_DOWN); + destroyKniDevice(m_Device, m_DeviceInfo.name.c_str()); + } + if (m_MBufMempool != NULL) + rte_mempool_free(m_MBufMempool); } - if (m_MBufMempool != NULL) - rte_mempool_free(m_MBufMempool); -} -bool KniDevice::KniDeviceInfo::init(const KniDeviceConfiguration& conf) -{ - link = KniDevice::LINK_NOT_SUPPORTED; - promisc = KniDevice::PROMISC_DISABLE; - portId = conf.portId; - mtu = conf.mtu; - if (conf.name.empty()) - { - PCPP_LOG_ERROR( - "Failed to create KNI device. " - "Empty name provided" - ); - return false; - } - if (conf.name.size() >= IFNAMSIZ) + bool KniDevice::KniDeviceInfo::init(const KniDeviceConfiguration& conf) { - PCPP_LOG_ERROR( - "Failed to create KNI device. " - "Provided name has length more than possible to handle <" << IFNAMSIZ-1 << ">" - ); - return false; + link = KniDevice::LINK_NOT_SUPPORTED; + promisc = KniDevice::PROMISC_DISABLE; + portId = conf.portId; + mtu = conf.mtu; + if (conf.name.empty()) + { + PCPP_LOG_ERROR("Failed to create KNI device. " + "Empty name provided"); + return false; + } + if (conf.name.size() >= IFNAMSIZ) + { + PCPP_LOG_ERROR("Failed to create KNI device. " + "Provided name has length more than possible to handle <" + << IFNAMSIZ - 1 << ">"); + return false; + } + name = conf.name; + mac = conf.mac; + return true; } - name = conf.name; - mac = conf.mac; - return true; -} -KniDevice::KniLinkState KniDevice::getLinkState(KniInfoState state) -{ - if (state == KniDevice::INFO_CACHED) - return m_DeviceInfo.link; - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) + KniDevice::KniLinkState KniDevice::getLinkState(KniInfoState state) { - PCPP_LOG_ERROR("DPDK KNI failed to obtain interface link state from Linux"); - PCPP_LOG_DEBUG("Last known link state for device '" << m_DeviceInfo.name << "' is returned"); - return m_DeviceInfo.link; + if (state == KniDevice::INFO_CACHED) + return m_DeviceInfo.link; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to obtain interface link state from Linux"); + PCPP_LOG_DEBUG("Last known link state for device '" << m_DeviceInfo.name << "' is returned"); + return m_DeviceInfo.link; + } + return m_DeviceInfo.link = KniLinkState(req.ifr_flags & IFF_UP); } - return m_DeviceInfo.link = KniLinkState(req.ifr_flags & IFF_UP); -} -MacAddress KniDevice::getMacAddress(KniInfoState state) -{ - if (state == KniDevice::INFO_CACHED) - return m_DeviceInfo.mac; - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - req.ifr_hwaddr.sa_family = ARPHRD_ETHER; - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFHWADDR, &req)) + MacAddress KniDevice::getMacAddress(KniInfoState state) { - PCPP_LOG_ERROR("DPDK KNI failed to obtain MAC address from Linux"); - PCPP_LOG_DEBUG("Last known MAC address for device '" << m_DeviceInfo.name << "' is returned"); - return m_DeviceInfo.mac; + if (state == KniDevice::INFO_CACHED) + return m_DeviceInfo.mac; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + req.ifr_hwaddr.sa_family = ARPHRD_ETHER; + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFHWADDR, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to obtain MAC address from Linux"); + PCPP_LOG_DEBUG("Last known MAC address for device '" << m_DeviceInfo.name << "' is returned"); + return m_DeviceInfo.mac; + } + return m_DeviceInfo.mac = MacAddress((uint8_t*)req.ifr_hwaddr.sa_data); } - return m_DeviceInfo.mac = MacAddress((uint8_t*)req.ifr_hwaddr.sa_data); -} -uint16_t KniDevice::getMtu(KniInfoState state) -{ - if (state == KniDevice::INFO_CACHED) - return m_DeviceInfo.mtu; - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFMTU, &req)) + uint16_t KniDevice::getMtu(KniInfoState state) { - PCPP_LOG_ERROR("DPDK KNI failed to obtain interface MTU from Linux"); - PCPP_LOG_DEBUG("Last known MTU for device '" << m_DeviceInfo.name << "' is returned"); - return m_DeviceInfo.mtu; + if (state == KniDevice::INFO_CACHED) + return m_DeviceInfo.mtu; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFMTU, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to obtain interface MTU from Linux"); + PCPP_LOG_DEBUG("Last known MTU for device '" << m_DeviceInfo.name << "' is returned"); + return m_DeviceInfo.mtu; + } + return m_DeviceInfo.mtu = req.ifr_mtu; } - return m_DeviceInfo.mtu = req.ifr_mtu; -} -KniDevice::KniPromiscuousMode KniDevice::getPromiscuous(KniInfoState state) -{ - if (state == KniDevice::INFO_CACHED) - return m_DeviceInfo.promisc; - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) + KniDevice::KniPromiscuousMode KniDevice::getPromiscuous(KniInfoState state) { - PCPP_LOG_ERROR("DPDK KNI failed to obtain interface Promiscuous mode from Linux"); - PCPP_LOG_DEBUG("Last known Promiscuous mode for device '" << m_DeviceInfo.name << "' is returned"); - return m_DeviceInfo.promisc; + if (state == KniDevice::INFO_CACHED) + return m_DeviceInfo.promisc; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to obtain interface Promiscuous mode from Linux"); + PCPP_LOG_DEBUG("Last known Promiscuous mode for device '" << m_DeviceInfo.name << "' is returned"); + return m_DeviceInfo.promisc; + } + return m_DeviceInfo.promisc = + (req.ifr_flags & IFF_PROMISC) ? KniDevice::PROMISC_ENABLE : KniDevice::PROMISC_DISABLE; } - return m_DeviceInfo.promisc = (req.ifr_flags & IFF_PROMISC) ? KniDevice::PROMISC_ENABLE : KniDevice::PROMISC_DISABLE; -} -bool KniDevice::setLinkState(KniLinkState state) -{ - if (!(state == KniDevice::LINK_DOWN || state == KniDevice::LINK_UP)) - return false; - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) - { - PCPP_LOG_ERROR("DPDK KNI failed to obtain interface flags from Linux"); - return false; - } - if ((state == KniDevice::LINK_DOWN && req.ifr_flags & IFF_UP) || - (state == KniDevice::LINK_UP && !(req.ifr_flags & IFF_UP))) + bool KniDevice::setLinkState(KniLinkState state) { - req.ifr_flags ^= IFF_UP; - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFFLAGS, &req)) + if (!(state == KniDevice::LINK_DOWN || state == KniDevice::LINK_UP)) + return false; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) { - PCPP_LOG_ERROR("DPDK KNI failed to set '" << m_DeviceInfo.name << "' link mode"); + PCPP_LOG_ERROR("DPDK KNI failed to obtain interface flags from Linux"); return false; } + if ((state == KniDevice::LINK_DOWN && req.ifr_flags & IFF_UP) || + (state == KniDevice::LINK_UP && !(req.ifr_flags & IFF_UP))) + { + req.ifr_flags ^= IFF_UP; + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFFLAGS, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to set '" << m_DeviceInfo.name << "' link mode"); + return false; + } + } + m_DeviceInfo.link = state; + return true; } - m_DeviceInfo.link = state; - return true; -} -bool KniDevice::setMacAddress(const MacAddress& mac) -{ - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - req.ifr_hwaddr.sa_family = ARPHRD_ETHER; - mac.copyTo((uint8_t*)req.ifr_hwaddr.sa_data); - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFHWADDR, &req)) + bool KniDevice::setMacAddress(const MacAddress& mac) { - PCPP_LOG_ERROR("DPDK KNI failed to set MAC address"); - return false; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + req.ifr_hwaddr.sa_family = ARPHRD_ETHER; + mac.copyTo((uint8_t*)req.ifr_hwaddr.sa_data); + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFHWADDR, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to set MAC address"); + return false; + } + m_DeviceInfo.mac = mac; + return true; } - m_DeviceInfo.mac = mac; - return true; -} -bool KniDevice::setMtu(uint16_t mtu) -{ - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - req.ifr_mtu = mtu; - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFMTU, &req)) + bool KniDevice::setMtu(uint16_t mtu) { - PCPP_LOG_ERROR("DPDK KNI failed to set interface MTU"); - return false; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + req.ifr_mtu = mtu; + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFMTU, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to set interface MTU"); + return false; + } + m_DeviceInfo.mtu = mtu; + return true; } - m_DeviceInfo.mtu = mtu; - return true; -} -bool KniDevice::setPromiscuous(KniPromiscuousMode mode) -{ - if (!(mode == KniDevice::PROMISC_DISABLE || mode == KniDevice::PROMISC_ENABLE)) - return false; - struct ifreq req; - std::memset(&req, 0, sizeof(req)); - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) + bool KniDevice::setPromiscuous(KniPromiscuousMode mode) { - PCPP_LOG_ERROR("DPDK KNI failed to obtain interface flags from Linux"); - return false; - } - if ((mode == KniDevice::PROMISC_DISABLE && req.ifr_flags & IFF_PROMISC) || - (mode == KniDevice::PROMISC_ENABLE && !(req.ifr_flags & IFF_PROMISC))) - { - req.ifr_flags ^= IFF_PROMISC; - if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFFLAGS, &req)) + if (!(mode == KniDevice::PROMISC_DISABLE || mode == KniDevice::PROMISC_ENABLE)) + return false; + struct ifreq req; + std::memset(&req, 0, sizeof(req)); + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCGIFFLAGS, &req)) { - PCPP_LOG_ERROR("DPDK KNI failed to set '" << m_DeviceInfo.name << "' link mode"); + PCPP_LOG_ERROR("DPDK KNI failed to obtain interface flags from Linux"); return false; } + if ((mode == KniDevice::PROMISC_DISABLE && req.ifr_flags & IFF_PROMISC) || + (mode == KniDevice::PROMISC_ENABLE && !(req.ifr_flags & IFF_PROMISC))) + { + req.ifr_flags ^= IFF_PROMISC; + if (!m_DeviceInfo.soc.makeRequest(m_DeviceInfo.name.c_str(), SIOCSIFFLAGS, &req)) + { + PCPP_LOG_ERROR("DPDK KNI failed to set '" << m_DeviceInfo.name << "' link mode"); + return false; + } + } + m_DeviceInfo.promisc = mode; + return true; } - m_DeviceInfo.promisc = mode; - return true; -} - -KniDevice::KniLinkState KniDevice::updateLinkState(KniLinkState state) -{ - KniLinkState oldState = setKniDeviceLinkState(m_Device, m_DeviceInfo.name.c_str(), state); - if (oldState != KniDevice::LINK_NOT_SUPPORTED && oldState != KniDevice::LINK_ERROR) - m_DeviceInfo.link = state; - return oldState; -} -bool KniDevice::handleRequests() -{ - return rte_kni_handle_request(m_Device) == 0; -} - -void KniDevice::KniRequests::cleanup() -{ - if (thread) - thread->cancel(); - delete thread; - thread = NULL; - sleepS = sleepNs = 0; -} - -void KniDevice::KniRequests::runRequests(void* devicePointer, std::atomic& stopThread) -{ - KniDevice* device = (KniDevice*)devicePointer; - struct timespec sleepTime; - sleepTime.tv_sec = device->m_Requests.sleepS; - sleepTime.tv_nsec = device->m_Requests.sleepNs; - struct rte_kni* kni_dev = device->m_Device; - for(;;) + KniDevice::KniLinkState KniDevice::updateLinkState(KniLinkState state) { - nanosleep(&sleepTime, NULL); - rte_kni_handle_request(kni_dev); - if (stopThread) - { - return; - } + KniLinkState oldState = setKniDeviceLinkState(m_Device, m_DeviceInfo.name.c_str(), state); + if (oldState != KniDevice::LINK_NOT_SUPPORTED && oldState != KniDevice::LINK_ERROR) + m_DeviceInfo.link = state; + return oldState; } -} -bool KniDevice::startRequestHandlerThread(long sleepSeconds, long sleepNanoSeconds) -{ - if (m_Requests.thread != NULL) + bool KniDevice::handleRequests() { - PCPP_LOG_ERROR("KNI request thread is already started for device '" << m_DeviceInfo.name << "'"); - return false; + return rte_kni_handle_request(m_Device) == 0; } - m_Requests.sleepS = sleepSeconds; - m_Requests.sleepNs = sleepNanoSeconds; - m_Requests.thread = new KniThread(KniThread::DETACHED, KniRequests::runRequests, (void*)this); - if (m_Requests.thread->m_CleanupState == KniThread::INVALID) + + void KniDevice::KniRequests::cleanup() { - m_Requests.cleanup(); - return false; + if (thread) + thread->cancel(); + delete thread; + thread = NULL; + sleepS = sleepNs = 0; } - return true; -} -void KniDevice::stopRequestHandlerThread() -{ - if (m_Requests.thread == NULL) + void KniDevice::KniRequests::runRequests(void* devicePointer, std::atomic& stopThread) { - PCPP_LOG_DEBUG("Attempt to stop not running KNI request thread for device '" << m_DeviceInfo.name << "'"); - return; + KniDevice* device = (KniDevice*)devicePointer; + struct timespec sleepTime; + sleepTime.tv_sec = device->m_Requests.sleepS; + sleepTime.tv_nsec = device->m_Requests.sleepNs; + struct rte_kni* kni_dev = device->m_Device; + for (;;) + { + nanosleep(&sleepTime, NULL); + rte_kni_handle_request(kni_dev); + if (stopThread) + { + return; + } + } } - m_Requests.cleanup(); -} -uint16_t KniDevice::receivePackets(MBufRawPacketVector& rawPacketsArr) -{ - if (unlikely(!m_DeviceOpened)) + bool KniDevice::startRequestHandlerThread(long sleepSeconds, long sleepNanoSeconds) { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; + if (m_Requests.thread != NULL) + { + PCPP_LOG_ERROR("KNI request thread is already started for device '" << m_DeviceInfo.name << "'"); + return false; + } + m_Requests.sleepS = sleepSeconds; + m_Requests.sleepNs = sleepNanoSeconds; + m_Requests.thread = new KniThread(KniThread::DETACHED, KniRequests::runRequests, (void*)this); + if (m_Requests.thread->m_CleanupState == KniThread::INVALID) + { + m_Requests.cleanup(); + return false; + } + return true; } - if (unlikely(m_Capturing.isRunning())) + + void KniDevice::stopRequestHandlerThread() { - PCPP_LOG_ERROR( - "KNI device '" << m_DeviceInfo.name << "' capture mode is currently running. " - "Cannot receive packets in parallel" - ); - return 0; + if (m_Requests.thread == NULL) + { + PCPP_LOG_DEBUG("Attempt to stop not running KNI request thread for device '" << m_DeviceInfo.name << "'"); + return; + } + m_Requests.cleanup(); } - struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; - uint32_t numOfPktsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); + uint16_t KniDevice::receivePackets(MBufRawPacketVector& rawPacketsArr) + { + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } + if (unlikely(m_Capturing.isRunning())) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name + << "' capture mode is currently running. " + "Cannot receive packets in parallel"); + return 0; + } - //the following line trashes the log with many messages. Uncomment only if necessary - //PCPP_LOG_DEBUG("KNI Captured %d packets", numOfPktsReceived); + struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; + uint32_t numOfPktsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); - if (unlikely(!numOfPktsReceived)) - { - return 0; - } + // the following line trashes the log with many messages. Uncomment only if necessary + // PCPP_LOG_DEBUG("KNI Captured %d packets", numOfPktsReceived); - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + if (unlikely(!numOfPktsReceived)) + { + return 0; + } - for (uint32_t index = 0; index < numOfPktsReceived; ++index) - { - struct rte_mbuf* mBuf = mBufArray[index]; - MBufRawPacket* newRawPacket = new MBufRawPacket(); - newRawPacket->setMBuf(mBuf, time); - rawPacketsArr.pushBack(newRawPacket); - } + timespec time; + clock_gettime(CLOCK_REALTIME, &time); - return numOfPktsReceived; -} + for (uint32_t index = 0; index < numOfPktsReceived; ++index) + { + struct rte_mbuf* mBuf = mBufArray[index]; + MBufRawPacket* newRawPacket = new MBufRawPacket(); + newRawPacket->setMBuf(mBuf, time); + rawPacketsArr.pushBack(newRawPacket); + } -uint16_t KniDevice::receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; - } - if (unlikely(m_Capturing.isRunning())) - { - PCPP_LOG_ERROR( - "KNI device '" << m_DeviceInfo.name << "' capture mode is currently running. " - "Cannot receive packets in parallel" - ); - return 0; + return numOfPktsReceived; } - if (unlikely(rawPacketsArr == NULL)) - { - PCPP_LOG_ERROR("KNI Provided address of array to store packets is NULL"); - return 0; - } - - struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, rawPacketArrLength); - uint16_t packetsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); - if (unlikely(!packetsReceived)) + uint16_t KniDevice::receivePackets(MBufRawPacket** rawPacketsArr, uint16_t rawPacketArrLength) { - return 0; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } + if (unlikely(m_Capturing.isRunning())) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name + << "' capture mode is currently running. " + "Cannot receive packets in parallel"); + return 0; + } + if (unlikely(rawPacketsArr == NULL)) + { + PCPP_LOG_ERROR("KNI Provided address of array to store packets is NULL"); + return 0; + } - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, rawPacketArrLength); + uint16_t packetsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); - for (size_t index = 0; index < packetsReceived; ++index) - { - struct rte_mbuf* mBuf = mBufArray[index]; - if (rawPacketsArr[index] == NULL) - rawPacketsArr[index] = new MBufRawPacket(); + if (unlikely(!packetsReceived)) + { + return 0; + } - rawPacketsArr[index]->setMBuf(mBuf, time); - } + timespec time; + clock_gettime(CLOCK_REALTIME, &time); - return packetsReceived; -} + for (size_t index = 0; index < packetsReceived; ++index) + { + struct rte_mbuf* mBuf = mBufArray[index]; + if (rawPacketsArr[index] == NULL) + rawPacketsArr[index] = new MBufRawPacket(); -uint16_t KniDevice::receivePackets(Packet** packetsArr, uint16_t packetsArrLength) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; + rawPacketsArr[index]->setMBuf(mBuf, time); + } + + return packetsReceived; } - if (unlikely(m_Capturing.isRunning())) + + uint16_t KniDevice::receivePackets(Packet** packetsArr, uint16_t packetsArrLength) { - PCPP_LOG_ERROR( - "KNI device '" << m_DeviceInfo.name << "' capture mode is currently running. " - "Cannot receive packets in parallel" - ); - return 0; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } + if (unlikely(m_Capturing.isRunning())) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name + << "' capture mode is currently running. " + "Cannot receive packets in parallel"); + return 0; + } + struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, packetsArrLength); + uint16_t packetsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); - struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, packetsArrLength); - uint16_t packetsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); + if (unlikely(!packetsReceived)) + { + return 0; + } - if (unlikely(!packetsReceived)) - { - return 0; - } + timespec time; + clock_gettime(CLOCK_REALTIME, &time); - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + for (size_t index = 0; index < packetsReceived; ++index) + { + struct rte_mbuf* mBuf = mBufArray[index]; + MBufRawPacket* newRawPacket = new MBufRawPacket(); + newRawPacket->setMBuf(mBuf, time); + if (packetsArr[index] == NULL) + packetsArr[index] = new Packet(); - for (size_t index = 0; index < packetsReceived; ++index) - { - struct rte_mbuf* mBuf = mBufArray[index]; - MBufRawPacket* newRawPacket = new MBufRawPacket(); - newRawPacket->setMBuf(mBuf, time); - if (packetsArr[index] == NULL) - packetsArr[index] = new Packet(); + packetsArr[index]->setRawPacket(newRawPacket, true); + } - packetsArr[index]->setRawPacket(newRawPacket, true); + return packetsReceived; } - return packetsReceived; -} - -uint16_t KniDevice::sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength) -{ - if (unlikely(!m_DeviceOpened)) + uint16_t KniDevice::sendPackets(MBufRawPacket** rawPacketsArr, uint16_t arrLength) { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } - struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); - for (uint16_t i = 0; i < arrLength; ++i) - { - mBufArray[i] = rawPacketsArr[i]->getMBuf(); - } + struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); + for (uint16_t i = 0; i < arrLength; ++i) + { + mBufArray[i] = rawPacketsArr[i]->getMBuf(); + } - uint16_t packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); - for (uint16_t i = 0; i < arrLength; ++i) - { - rawPacketsArr[i]->setFreeMbuf(i >= packetsSent); - } + uint16_t packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); + for (uint16_t i = 0; i < arrLength; ++i) + { + rawPacketsArr[i]->setFreeMbuf(i >= packetsSent); + } - return packetsSent; -} + return packetsSent; + } -uint16_t KniDevice::sendPackets(Packet** packetsArr, uint16_t arrLength) -{ - if (unlikely(!m_DeviceOpened)) + uint16_t KniDevice::sendPackets(Packet** packetsArr, uint16_t arrLength) { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } - struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); - MBufRawPacket** mBufRawPacketArr = CPP_VLA(MBufRawPacket*, arrLength); - MBufRawPacket** allocated = CPP_VLA(MBufRawPacket*, arrLength); - uint16_t allocated_count = 0, packetsSent = 0; - MBufRawPacket* rawPacket; - RawPacket* raw_pkt; + struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); + MBufRawPacket** mBufRawPacketArr = CPP_VLA(MBufRawPacket*, arrLength); + MBufRawPacket** allocated = CPP_VLA(MBufRawPacket*, arrLength); + uint16_t allocated_count = 0, packetsSent = 0; + MBufRawPacket* rawPacket; + RawPacket* raw_pkt; - for (uint16_t i = 0; i < arrLength; ++i) - { - raw_pkt = packetsArr[i]->getRawPacketReadOnly(); - uint8_t raw_type = raw_pkt->getObjectType(); - if (raw_type != MBUFRAWPACKET_OBJECT_TYPE) + for (uint16_t i = 0; i < arrLength; ++i) { - MBufRawPacket* pkt = new MBufRawPacket(); - if (unlikely(!pkt->initFromRawPacket(raw_pkt, this))) + raw_pkt = packetsArr[i]->getRawPacketReadOnly(); + uint8_t raw_type = raw_pkt->getObjectType(); + if (raw_type != MBUFRAWPACKET_OBJECT_TYPE) { - delete pkt; - goto error_out; + MBufRawPacket* pkt = new MBufRawPacket(); + if (unlikely(!pkt->initFromRawPacket(raw_pkt, this))) + { + delete pkt; + goto error_out; + } + rawPacket = allocated[allocated_count++] = pkt; } - rawPacket = allocated[allocated_count++] = pkt; + else + { + rawPacket = (MBufRawPacket*)raw_pkt; + } + mBufRawPacketArr[i] = rawPacket; + mBufArray[i] = rawPacket->getMBuf(); } - else + + packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); + for (uint16_t i = 0; i < arrLength; ++i) { - rawPacket = (MBufRawPacket*)raw_pkt; + mBufRawPacketArr[i]->setFreeMbuf(i >= packetsSent); } - mBufRawPacketArr[i] = rawPacket; - mBufArray[i] = rawPacket->getMBuf(); + + error_out: + for (uint16_t i = 0; i < allocated_count; ++i) + delete allocated[i]; + return packetsSent; } - packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); - for (uint16_t i = 0; i < arrLength; ++i) + uint16_t KniDevice::sendPackets(MBufRawPacketVector& rawPacketsVec) { - mBufRawPacketArr[i]->setFreeMbuf(i >= packetsSent); - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } -error_out: - for (uint16_t i = 0; i < allocated_count; ++i) - delete allocated[i]; - return packetsSent; -} + size_t arrLength = rawPacketsVec.size(); + struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); + uint16_t pos = 0; + for (MBufRawPacketVector::VectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); ++iter) + { + mBufArray[pos] = (*iter)->getMBuf(); + ++pos; + } -uint16_t KniDevice::sendPackets(MBufRawPacketVector& rawPacketsVec) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; - } + uint16_t packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); + pos = 0; + for (MBufRawPacketVector::VectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); ++iter) + { + (*iter)->setFreeMbuf(pos >= packetsSent); + ++pos; + } - size_t arrLength = rawPacketsVec.size(); - struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); - uint16_t pos = 0; - for (MBufRawPacketVector::VectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); ++iter) - { - mBufArray[pos] = (*iter)->getMBuf(); - ++pos; + return packetsSent; } - uint16_t packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); - pos = 0; - for (MBufRawPacketVector::VectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); ++iter) + uint16_t KniDevice::sendPackets(RawPacketVector& rawPacketsVec) { - (*iter)->setFreeMbuf(pos >= packetsSent); - ++pos; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } - return packetsSent; -} + size_t arrLength = rawPacketsVec.size(); + struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); + MBufRawPacket** mBufRawPacketArr = CPP_VLA(MBufRawPacket*, arrLength); + MBufRawPacket** allocated = CPP_VLA(MBufRawPacket*, arrLength); + uint16_t allocatedCount = 0, packetsSent = 0, pos = 0; + MBufRawPacket* rawPacket; -uint16_t KniDevice::sendPackets(RawPacketVector& rawPacketsVec) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; - } + for (RawPacketVector::VectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); ++iter) + { + uint8_t raw_type = (*iter)->getObjectType(); + if (raw_type != MBUFRAWPACKET_OBJECT_TYPE) + { + MBufRawPacket* pkt = new MBufRawPacket(); + if (unlikely(!pkt->initFromRawPacket(*iter, this))) + { + delete pkt; + goto error_out; + } + rawPacket = allocated[allocatedCount++] = pkt; + } + else + { + rawPacket = (MBufRawPacket*)(*iter); + } + mBufRawPacketArr[pos] = rawPacket; + mBufArray[pos] = rawPacket->getMBuf(); + ++pos; + } - size_t arrLength = rawPacketsVec.size(); - struct rte_mbuf** mBufArray = CPP_VLA(struct rte_mbuf*, arrLength); - MBufRawPacket** mBufRawPacketArr = CPP_VLA(MBufRawPacket*, arrLength); - MBufRawPacket** allocated = CPP_VLA(MBufRawPacket*, arrLength); - uint16_t allocatedCount = 0, packetsSent = 0, pos = 0; - MBufRawPacket* rawPacket; + packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); + for (uint16_t i = 0; i < arrLength; ++i) + { + mBufRawPacketArr[i]->setFreeMbuf(i >= packetsSent); + } + + error_out: + for (uint16_t i = 0; i < allocatedCount; ++i) + delete allocated[i]; + return packetsSent; + } - for (RawPacketVector::VectorIterator iter = rawPacketsVec.begin(); iter != rawPacketsVec.end(); ++iter) + bool KniDevice::sendPacket(RawPacket& rawPacket) { - uint8_t raw_type = (*iter)->getObjectType(); - if (raw_type != MBUFRAWPACKET_OBJECT_TYPE) + if (unlikely(!m_DeviceOpened)) { - MBufRawPacket* pkt = new MBufRawPacket(); - if (unlikely(!pkt->initFromRawPacket(*iter, this))) + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; + } + + struct rte_mbuf* mbuf; + MBufRawPacket* mbufRawPacket = NULL; + bool sent = false; + bool wasAllocated = false; + + if (rawPacket.getObjectType() != MBUFRAWPACKET_OBJECT_TYPE) + { + mbufRawPacket = new MBufRawPacket(); + if (unlikely(!mbufRawPacket->initFromRawPacket(&rawPacket, this))) { - delete pkt; - goto error_out; + delete mbufRawPacket; + return sent; } - rawPacket = allocated[allocatedCount++] = pkt; + mbuf = mbufRawPacket->getMBuf(); + wasAllocated = true; } else { - rawPacket = (MBufRawPacket*)(*iter); + mbufRawPacket = (MBufRawPacket*)(&rawPacket); + mbuf = mbufRawPacket->getMBuf(); } - mBufRawPacketArr[pos] = rawPacket; - mBufArray[pos] = rawPacket->getMBuf(); - ++pos; - } - - packetsSent = rte_kni_tx_burst(m_Device, mBufArray, arrLength); - for (uint16_t i = 0; i < arrLength; ++i) - { - mBufRawPacketArr[i]->setFreeMbuf(i >= packetsSent); - } -error_out: - for (uint16_t i = 0; i < allocatedCount; ++i) - delete allocated[i]; - return packetsSent; -} + sent = rte_kni_tx_burst(m_Device, &mbuf, 1); + mbufRawPacket->setFreeMbuf(!sent); + if (wasAllocated) + delete mbufRawPacket; -bool KniDevice::sendPacket(RawPacket& rawPacket) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; + return sent; } - struct rte_mbuf* mbuf; - MBufRawPacket* mbufRawPacket = NULL; - bool sent = false; - bool wasAllocated = false; - - if (rawPacket.getObjectType() != MBUFRAWPACKET_OBJECT_TYPE) + bool KniDevice::sendPacket(MBufRawPacket& rawPacket) { - mbufRawPacket = new MBufRawPacket(); - if (unlikely(!mbufRawPacket->initFromRawPacket(&rawPacket, this))) + if (unlikely(!m_DeviceOpened)) { - delete mbufRawPacket; - return sent; + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); + return 0; } - mbuf = mbufRawPacket->getMBuf(); - wasAllocated = true; - } - else - { - mbufRawPacket = (MBufRawPacket*)(&rawPacket); - mbuf = mbufRawPacket->getMBuf(); - } - sent = rte_kni_tx_burst(m_Device, &mbuf, 1); - mbufRawPacket->setFreeMbuf(!sent); - if (wasAllocated) - delete mbufRawPacket; + struct rte_mbuf* mbuf = rawPacket.getMBuf(); + bool sent = false; - return sent; -} + sent = rte_kni_tx_burst(m_Device, &mbuf, 1); + rawPacket.setFreeMbuf(!sent); -bool KniDevice::sendPacket(MBufRawPacket& rawPacket) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened"); - return 0; + return sent; } - struct rte_mbuf* mbuf = rawPacket.getMBuf(); - bool sent = false; + bool KniDevice::sendPacket(Packet& packet) + { + return sendPacket(*packet.getRawPacket()); + } - sent = rte_kni_tx_burst(m_Device, &mbuf, 1); - rawPacket.setFreeMbuf(!sent); + void KniDevice::KniCapturing::runCapture(void* devicePointer, std::atomic& stopThread) + { + KniDevice* device = (KniDevice*)devicePointer; + OnKniPacketArriveCallback callback = device->m_Capturing.callback; + void* userCookie = device->m_Capturing.userCookie; + struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; + struct rte_kni* kni = device->m_Device; - return sent; -} + PCPP_LOG_DEBUG("Starting KNI capture thread for device '" << device->m_DeviceInfo.name << "'"); -bool KniDevice::sendPacket(Packet& packet) -{ - return sendPacket(*packet.getRawPacket()); -} + for (;;) + { + uint32_t numOfPktsReceived = rte_kni_rx_burst(kni, mBufArray, MAX_BURST_SIZE); + if (unlikely(numOfPktsReceived == 0)) + { + if (stopThread) + { + return; + } + continue; + } -void KniDevice::KniCapturing::runCapture(void* devicePointer, std::atomic& stopThread) -{ - KniDevice* device = (KniDevice*)devicePointer; - OnKniPacketArriveCallback callback = device->m_Capturing.callback; - void* userCookie = device->m_Capturing.userCookie; - struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; - struct rte_kni* kni = device->m_Device; + timespec time; + clock_gettime(CLOCK_REALTIME, &time); - PCPP_LOG_DEBUG("Starting KNI capture thread for device '" << device->m_DeviceInfo.name << "'"); + if (likely(callback != NULL)) + { + MBufRawPacket rawPackets[MAX_BURST_SIZE]; + for (uint32_t index = 0; index < numOfPktsReceived; ++index) + { + rawPackets[index].setMBuf(mBufArray[index], time); + } - for(;;) - { - uint32_t numOfPktsReceived = rte_kni_rx_burst(kni, mBufArray, MAX_BURST_SIZE); - if (unlikely(numOfPktsReceived == 0)) - { + if (!callback(rawPackets, numOfPktsReceived, device, userCookie)) + break; + } if (stopThread) { return; } - continue; } + } - timespec time; - clock_gettime(CLOCK_REALTIME, &time); + void KniDevice::KniCapturing::cleanup() + { + if (thread) + thread->cancel(); + delete thread; + thread = NULL; + callback = NULL; + userCookie = NULL; + } - if (likely(callback != NULL)) + bool KniDevice::startCapture(OnKniPacketArriveCallback onPacketArrives, void* onPacketArrivesUserCookie) + { + if (unlikely(!m_DeviceOpened)) { - MBufRawPacket rawPackets[MAX_BURST_SIZE]; - for (uint32_t index = 0; index < numOfPktsReceived; ++index) - { - rawPackets[index].setMBuf(mBufArray[index], time); - } - - if (!callback(rawPackets, numOfPktsReceived, device, userCookie)) - break; + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened. Can't start capture"); + return false; } - if (stopThread) + if (unlikely(m_Capturing.thread != NULL)) { - return; + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is already capturing"); + return false; } - } -} -void KniDevice::KniCapturing::cleanup() -{ - if (thread) - thread->cancel(); - delete thread; - thread = NULL; - callback = NULL; - userCookie = NULL; -} - -bool KniDevice::startCapture( - OnKniPacketArriveCallback onPacketArrives, - void* onPacketArrivesUserCookie -) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened. Can't start capture"); - return false; - } - if (unlikely(m_Capturing.thread != NULL)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is already capturing"); - return false; - } + m_Capturing.callback = onPacketArrives; + m_Capturing.userCookie = onPacketArrivesUserCookie; - m_Capturing.callback = onPacketArrives; - m_Capturing.userCookie = onPacketArrivesUserCookie; + m_Capturing.thread = new KniThread(KniThread::JOINABLE, KniCapturing::runCapture, (void*)this); + if (m_Capturing.thread->m_CleanupState == KniThread::INVALID) + { + PCPP_LOG_DEBUG("KNI failed to start capturing thread on device '" << m_DeviceInfo.name << "'"); + delete m_Capturing.thread; + return false; + } - m_Capturing.thread = new KniThread(KniThread::JOINABLE, KniCapturing::runCapture, (void*)this); - if (m_Capturing.thread->m_CleanupState == KniThread::INVALID) - { - PCPP_LOG_DEBUG("KNI failed to start capturing thread on device '" << m_DeviceInfo.name << "'"); - delete m_Capturing.thread; - return false; + return true; } - return true; -} - -void KniDevice::stopCapture() -{ - if (m_Capturing.thread == NULL) + void KniDevice::stopCapture() { - PCPP_LOG_DEBUG("Attempt to stop not running KNI capturing thread for device '" << m_DeviceInfo.name << "'"); - return; + if (m_Capturing.thread == NULL) + { + PCPP_LOG_DEBUG("Attempt to stop not running KNI capturing thread for device '" << m_DeviceInfo.name << "'"); + return; + } + m_Capturing.cleanup(); } - m_Capturing.cleanup(); -} -int KniDevice::startCaptureBlockingMode( - OnKniPacketArriveCallback onPacketArrives, - void* onPacketArrivesUserCookie, - int timeout -) -{ - if (unlikely(!m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened. Can't start capture"); - return 0; - } - if (unlikely(m_Capturing.thread != NULL)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is already capturing"); - return 0; - } - m_Capturing.callback = onPacketArrives; - m_Capturing.userCookie = onPacketArrivesUserCookie; - if (unlikely(m_Capturing.callback == NULL)) + int KniDevice::startCaptureBlockingMode(OnKniPacketArriveCallback onPacketArrives, void* onPacketArrivesUserCookie, + int timeout) { - PCPP_LOG_ERROR("Attempt to start KNI device '" << m_DeviceInfo.name << "' capturing in blocking mode without callback"); - return 0; - } + if (unlikely(!m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is not opened. Can't start capture"); + return 0; + } + if (unlikely(m_Capturing.thread != NULL)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is already capturing"); + return 0; + } + m_Capturing.callback = onPacketArrives; + m_Capturing.userCookie = onPacketArrivesUserCookie; + if (unlikely(m_Capturing.callback == NULL)) + { + PCPP_LOG_ERROR("Attempt to start KNI device '" << m_DeviceInfo.name + << "' capturing in blocking mode without callback"); + return 0; + } - struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; + struct rte_mbuf* mBufArray[MAX_BURST_SIZE]; - if (timeout <= 0) - { - for(;;) + if (timeout <= 0) { - uint32_t numOfPktsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); - if (likely(numOfPktsReceived != 0)) + for (;;) { - MBufRawPacket rawPackets[MAX_BURST_SIZE]; - timespec time; - clock_gettime(CLOCK_REALTIME, &time); - - for (uint32_t index = 0; index < numOfPktsReceived; ++index) + uint32_t numOfPktsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); + if (likely(numOfPktsReceived != 0)) { - rawPackets[index].setMBuf(mBufArray[index], time); - } + MBufRawPacket rawPackets[MAX_BURST_SIZE]; + timespec time; + clock_gettime(CLOCK_REALTIME, &time); + + for (uint32_t index = 0; index < numOfPktsReceived; ++index) + { + rawPackets[index].setMBuf(mBufArray[index], time); + } - if (!m_Capturing.callback(rawPackets, numOfPktsReceived, this, m_Capturing.userCookie)) - return 1; + if (!m_Capturing.callback(rawPackets, numOfPktsReceived, this, m_Capturing.userCookie)) + return 1; + } } } - } - else - { - long startTimeSec = 0, startTimeNSec = 0; - long curTimeSec = 0, curTimeNSec = 0; - clockGetTime(startTimeSec, startTimeNSec); - - while(curTimeSec <= (startTimeSec + timeout)) + else { - clockGetTime(curTimeSec, curTimeNSec); - uint32_t numOfPktsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); - if (likely(numOfPktsReceived != 0)) - { - MBufRawPacket rawPackets[MAX_BURST_SIZE]; - timespec time; - time.tv_sec = curTimeSec; - time.tv_nsec = curTimeNSec; + long startTimeSec = 0, startTimeNSec = 0; + long curTimeSec = 0, curTimeNSec = 0; + clockGetTime(startTimeSec, startTimeNSec); - for (uint32_t index = 0; index < numOfPktsReceived; ++index) + while (curTimeSec <= (startTimeSec + timeout)) + { + clockGetTime(curTimeSec, curTimeNSec); + uint32_t numOfPktsReceived = rte_kni_rx_burst(m_Device, mBufArray, MAX_BURST_SIZE); + if (likely(numOfPktsReceived != 0)) { - rawPackets[index].setMBuf(mBufArray[index], time); + MBufRawPacket rawPackets[MAX_BURST_SIZE]; + timespec time; + time.tv_sec = curTimeSec; + time.tv_nsec = curTimeNSec; + + for (uint32_t index = 0; index < numOfPktsReceived; ++index) + { + rawPackets[index].setMBuf(mBufArray[index], time); + } + + if (!m_Capturing.callback(rawPackets, numOfPktsReceived, this, m_Capturing.userCookie)) + return 1; } - - if (!m_Capturing.callback(rawPackets, numOfPktsReceived, this, m_Capturing.userCookie)) - return 1; } } + return -1; } - return -1; -} -bool KniDevice::open() -{ - if (unlikely(m_DeviceOpened)) - { - PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is already opened"); - return false; - } - (void) updateLinkState(LINK_UP); - switch (m_DeviceInfo.link) + bool KniDevice::open() { + if (unlikely(m_DeviceOpened)) + { + PCPP_LOG_ERROR("KNI device '" << m_DeviceInfo.name << "' is already opened"); + return false; + } + (void)updateLinkState(LINK_UP); + switch (m_DeviceInfo.link) + { case LINK_ERROR: return m_DeviceOpened = false; case LINK_NOT_SUPPORTED: @@ -991,20 +968,20 @@ bool KniDevice::open() /* fall through */ case LINK_UP: return m_DeviceOpened = true; + } + return false; } - return false; -} -void KniDevice::close() -{ - if (m_Capturing.thread != NULL) + void KniDevice::close() { - m_Capturing.cleanup(); + if (m_Capturing.thread != NULL) + { + m_Capturing.cleanup(); + } + updateLinkState(LINK_DOWN); + m_DeviceOpened = false; } - updateLinkState(LINK_DOWN); - m_DeviceOpened = false; -} -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/KniDeviceList.cpp b/Pcap++/src/KniDeviceList.cpp index 546cb3a607..75f7d26c50 100644 --- a/Pcap++/src/KniDeviceList.cpp +++ b/Pcap++/src/KniDeviceList.cpp @@ -2,170 +2,158 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModuleKniDevice +# define LOG_MODULE PcapLogModuleKniDevice -#include -#include +# include +# include -#include "KniDeviceList.h" -#include "Logger.h" -#include "SystemUtils.h" +# include "KniDeviceList.h" +# include "Logger.h" +# include "SystemUtils.h" -#include -#include +# include +# include -#ifndef MAX_KNI_DEVICES +# ifndef MAX_KNI_DEVICES // This value have no meaning in current DPDK implementation (ver >= 18.11) // In older versions have literal meaning -# define MAX_KNI_DEVICES 4 -#endif +# define MAX_KNI_DEVICES 4 +# endif namespace pcpp { -/** - * =================== - * Class KniDeviceList - * =================== - */ + /** + * =================== + * Class KniDeviceList + * =================== + */ -static inline bool checkKniDriver() -{ - std::string execResult = executeShellCommand("lsmod | grep -s rte_kni"); - if (execResult == "") + static inline bool checkKniDriver() { - PCPP_LOG_ERROR("rte_kni driver isn't loaded, DPDK KNI module cannot be initialized"); - return false; + std::string execResult = executeShellCommand("lsmod | grep -s rte_kni"); + if (execResult == "") + { + PCPP_LOG_ERROR("rte_kni driver isn't loaded, DPDK KNI module cannot be initialized"); + return false; + } + PCPP_LOG_DEBUG("rte_kni driver is loaded"); + return true; } - PCPP_LOG_DEBUG("rte_kni driver is loaded"); - return true; -} -KniDeviceList::KniDeviceList() : - m_Devices(), - m_Initialized(true), m_KniUniqueId(0) -{ - m_Devices.reserve(MAX_KNI_DEVICES); - if (!checkKniDriver()) + KniDeviceList::KniDeviceList() : m_Devices(), m_Initialized(true), m_KniUniqueId(0) { - m_Initialized = false; - return; - } - if (!DpdkDeviceList::getInstance().isInitialized()) - { - m_Initialized = false; - return; - } - #if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) + m_Devices.reserve(MAX_KNI_DEVICES); + if (!checkKniDriver()) + { + m_Initialized = false; + return; + } + if (!DpdkDeviceList::getInstance().isInitialized()) + { + m_Initialized = false; + return; + } +# if RTE_VERSION >= RTE_VERSION_NUM(18, 11, 0, 0) if (rte_kni_init(MAX_KNI_DEVICES) < 0) { PCPP_LOG_ERROR("Failed to initialize DPDK KNI module"); m_Initialized = false; } - #else +# else rte_kni_init(MAX_KNI_DEVICES); - #endif -} +# endif + } -KniDeviceList::~KniDeviceList() -{ - for (size_t i = 0; i < m_Devices.size(); ++i) - delete m_Devices[i]; - rte_kni_close(); -} + KniDeviceList::~KniDeviceList() + { + for (size_t i = 0; i < m_Devices.size(); ++i) + delete m_Devices[i]; + rte_kni_close(); + } -KniDeviceList& KniDeviceList::getInstance() -{ - static KniDeviceList g_KniDeviceList; - return g_KniDeviceList; -} - -KniDevice* KniDeviceList::createDevice( - const KniDevice::KniDeviceConfiguration& config, - const size_t mempoolSize -) -{ - if (!isInitialized()) - return NULL; - KniDevice* kniDevice = getDeviceByName(std::string(config.name)); - if (kniDevice != NULL) + KniDeviceList& KniDeviceList::getInstance() { - PCPP_LOG_ERROR("Attempt to create DPDK KNI device with same name: '" << config.name << "'"); - PCPP_LOG_DEBUG("Use KniDeviceList::getDeviceByName or KniDeviceList::getDeviceByPort."); - return NULL; + static KniDeviceList g_KniDeviceList; + return g_KniDeviceList; } - if (config.portId != UINT16_MAX) + + KniDevice* KniDeviceList::createDevice(const KniDevice::KniDeviceConfiguration& config, const size_t mempoolSize) { - kniDevice = getDeviceByPort(config.portId); + if (!isInitialized()) + return NULL; + KniDevice* kniDevice = getDeviceByName(std::string(config.name)); if (kniDevice != NULL) { - PCPP_LOG_ERROR("Attempt to create DPDK KNI device with same port ID: " << config.portId); + PCPP_LOG_ERROR("Attempt to create DPDK KNI device with same name: '" << config.name << "'"); PCPP_LOG_DEBUG("Use KniDeviceList::getDeviceByName or KniDeviceList::getDeviceByPort."); return NULL; } + if (config.portId != UINT16_MAX) + { + kniDevice = getDeviceByPort(config.portId); + if (kniDevice != NULL) + { + PCPP_LOG_ERROR("Attempt to create DPDK KNI device with same port ID: " << config.portId); + PCPP_LOG_DEBUG("Use KniDeviceList::getDeviceByName or KniDeviceList::getDeviceByPort."); + return NULL; + } + } + kniDevice = new KniDevice(config, mempoolSize, m_KniUniqueId++); + m_Devices.push_back(kniDevice); + return kniDevice; } - kniDevice = new KniDevice(config, mempoolSize, m_KniUniqueId++); - m_Devices.push_back(kniDevice); - return kniDevice; -} -void KniDeviceList::destroyDevice(KniDevice* kniDevice) -{ - m_Devices.erase( - std::remove( - m_Devices.begin(), - m_Devices.end(), - kniDevice - ), - m_Devices.end() - ); - delete kniDevice; -} - -KniDevice* KniDeviceList::getDeviceByPort(const uint16_t portId) -{ - //? Linear search here is optimal for low count of devices. - //? We assume that no one will create large count of devices or will rapidly search them. - //? Same for function - KniDevice* kniDevice = NULL; - if (!isInitialized()) - return kniDevice; - for (size_t i = 0; i < m_Devices.size(); ++i) + void KniDeviceList::destroyDevice(KniDevice* kniDevice) { - kniDevice = m_Devices[i]; - if (kniDevice && kniDevice->m_DeviceInfo.portId == portId) + m_Devices.erase(std::remove(m_Devices.begin(), m_Devices.end(), kniDevice), m_Devices.end()); + delete kniDevice; + } + + KniDevice* KniDeviceList::getDeviceByPort(const uint16_t portId) + { + //? Linear search here is optimal for low count of devices. + //? We assume that no one will create large count of devices or will rapidly search them. + //? Same for function + KniDevice* kniDevice = NULL; + if (!isInitialized()) return kniDevice; + for (size_t i = 0; i < m_Devices.size(); ++i) + { + kniDevice = m_Devices[i]; + if (kniDevice && kniDevice->m_DeviceInfo.portId == portId) + return kniDevice; + } + return kniDevice = NULL; } - return kniDevice = NULL; -} -KniDevice* KniDeviceList::getDeviceByName(const std::string& name) -{ - KniDevice* kniDevice = NULL; - if (!isInitialized()) - return kniDevice; - for (size_t i = 0; i < m_Devices.size(); ++i) + KniDevice* KniDeviceList::getDeviceByName(const std::string& name) { - kniDevice = m_Devices[i]; - if (kniDevice && kniDevice->m_DeviceInfo.name == name) + KniDevice* kniDevice = NULL; + if (!isInitialized()) return kniDevice; + for (size_t i = 0; i < m_Devices.size(); ++i) + { + kniDevice = m_Devices[i]; + if (kniDevice && kniDevice->m_DeviceInfo.name == name) + return kniDevice; + } + return kniDevice = NULL; } - return kniDevice = NULL; -} -KniDeviceList::KniCallbackVersion KniDeviceList::callbackVersion() -{ - #if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 0) + KniDeviceList::KniCallbackVersion KniDeviceList::callbackVersion() + { +# if RTE_VERSION >= RTE_VERSION_NUM(17, 11, 0, 0) return KniDeviceList::CALLBACKS_NEW; - #else +# else return KniDeviceList::CALLBACKS_OLD; - #endif -} +# endif + } -bool KniDeviceList::isCallbackSupported(const KniCallbackType cbType) -{ - switch (cbType) + bool KniDeviceList::isCallbackSupported(const KniCallbackType cbType) { + switch (cbType) + { case KniDeviceList::CALLBACK_MTU: /* fall through */ case KniDeviceList::CALLBACK_LINK: @@ -173,15 +161,15 @@ bool KniDeviceList::isCallbackSupported(const KniCallbackType cbType) case KniDeviceList::CALLBACK_MAC: /* fall through */ case KniDeviceList::CALLBACK_PROMISC: - #if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) +# if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0) return true; - #else +# else return false; - #endif +# endif + } + return false; } - return false; -} -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/LinuxNicInformationSocket.cpp b/Pcap++/src/LinuxNicInformationSocket.cpp index e49387f8b6..a70db5e341 100644 --- a/Pcap++/src/LinuxNicInformationSocket.cpp +++ b/Pcap++/src/LinuxNicInformationSocket.cpp @@ -1,84 +1,74 @@ #ifdef __linux__ -#define LOG_MODULE UndefinedLogModule +# define LOG_MODULE UndefinedLogModule -#include "Logger.h" -#include "LinuxNicInformationSocket.h" +# include "Logger.h" +# include "LinuxNicInformationSocket.h" -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include -#include -#include -#include +# include +# include +# include -#define INVALID_SOCKET_VALUE (-1) +# define INVALID_SOCKET_VALUE (-1) namespace pcpp { -static inline LinuxNicInformationSocket::LinuxSocket -openLinuxNicInformationSocket() -{ - LinuxNicInformationSocket::LinuxSocket soc = socket(AF_INET, SOCK_DGRAM, 0); - if (soc < 0) + static inline LinuxNicInformationSocket::LinuxSocket openLinuxNicInformationSocket() { - const char* error = std::strerror(errno); - PCPP_LOG_DEBUG("Can't open Linux information socket. Errno string: "<< error); - return soc = INVALID_SOCKET_VALUE; + LinuxNicInformationSocket::LinuxSocket soc = socket(AF_INET, SOCK_DGRAM, 0); + if (soc < 0) + { + const char* error = std::strerror(errno); + PCPP_LOG_DEBUG("Can't open Linux information socket. Errno string: " << error); + return soc = INVALID_SOCKET_VALUE; + } + return soc; } - return soc; -} -LinuxNicInformationSocket::LinuxNicInformationSocket() : - m_Socket(openLinuxNicInformationSocket()) -{} + LinuxNicInformationSocket::LinuxNicInformationSocket() : m_Socket(openLinuxNicInformationSocket()) + {} -LinuxNicInformationSocket::~LinuxNicInformationSocket() -{ - if (m_Socket == INVALID_SOCKET_VALUE) + LinuxNicInformationSocket::~LinuxNicInformationSocket() { - PCPP_LOG_DEBUG("Closing not opened Linux NIC information socket"); - } - else - { - close(m_Socket); + if (m_Socket == INVALID_SOCKET_VALUE) + { + PCPP_LOG_DEBUG("Closing not opened Linux NIC information socket"); + } + else + { + close(m_Socket); + } } -} -bool LinuxNicInformationSocket::makeRequest( - const char* nicName, - const IoctlType ioctlType, - ifreq* request -) -{ - if (m_Socket == INVALID_SOCKET_VALUE) + bool LinuxNicInformationSocket::makeRequest(const char* nicName, const IoctlType ioctlType, ifreq* request) { - m_Socket = openLinuxNicInformationSocket(); if (m_Socket == INVALID_SOCKET_VALUE) { - PCPP_LOG_ERROR( - "Request to Linux NIC incformation socket failed. " - "Can't open socket" - ); + m_Socket = openLinuxNicInformationSocket(); + if (m_Socket == INVALID_SOCKET_VALUE) + { + PCPP_LOG_ERROR("Request to Linux NIC incformation socket failed. " + "Can't open socket"); + return false; + } + } + snprintf(request->ifr_name, IFNAMSIZ, "%s", nicName); + if (ioctl(m_Socket, ioctlType, request)) + { + const char* error = std::strerror(errno); + PCPP_LOG_ERROR("Request to Linux NIC incformation socket failed. " + "ioctl(2) failed with error string: " + << error); return false; } + return true; } - snprintf(request->ifr_name, IFNAMSIZ, "%s", nicName); - if (ioctl(m_Socket, ioctlType, request)) - { - const char* error = std::strerror(errno); - PCPP_LOG_ERROR( - "Request to Linux NIC incformation socket failed. " - "ioctl(2) failed with error string: " - << error - ); - return false; - } - return true; -} -} // namespace pcpp +} // namespace pcpp #endif /* __linux__ */ diff --git a/Pcap++/src/MBufRawPacket.cpp b/Pcap++/src/MBufRawPacket.cpp index 05ef54e8fd..3a5d8d8cdf 100644 --- a/Pcap++/src/MBufRawPacket.cpp +++ b/Pcap++/src/MBufRawPacket.cpp @@ -2,338 +2,343 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModuleMBufRawPacket +# define LOG_MODULE PcapLogModuleMBufRawPacket -#define __STDC_LIMIT_MACROS -#define __STDC_FORMAT_MACROS +# define __STDC_LIMIT_MACROS +# define __STDC_FORMAT_MACROS -#include "rte_mbuf.h" -#include "rte_mempool.h" -#include "rte_errno.h" +# include "rte_mbuf.h" +# include "rte_mempool.h" +# include "rte_errno.h" -#include "MBufRawPacket.h" -#include "Logger.h" -#include "DpdkDevice.h" -#ifdef USE_DPDK_KNI -#include "KniDevice.h" -#endif +# include "MBufRawPacket.h" +# include "Logger.h" +# include "DpdkDevice.h" +# ifdef USE_DPDK_KNI +# include "KniDevice.h" +# endif -#include -#include -#include +# include +# include +# include namespace pcpp { -/** - * =================== - * Class MBufRawPacket - * =================== - */ + /** + * =================== + * Class MBufRawPacket + * =================== + */ -MBufRawPacket::~MBufRawPacket() -{ - if (m_MBuf != NULL && m_FreeMbuf) + MBufRawPacket::~MBufRawPacket() { - rte_pktmbuf_free(m_MBuf); + if (m_MBuf != NULL && m_FreeMbuf) + { + rte_pktmbuf_free(m_MBuf); + } } -} -bool MBufRawPacket::init(struct rte_mempool* mempool) -{ - if (m_MBuf != NULL) + bool MBufRawPacket::init(struct rte_mempool* mempool) { - PCPP_LOG_ERROR("MBufRawPacket already initialized"); - return false; + if (m_MBuf != NULL) + { + PCPP_LOG_ERROR("MBufRawPacket already initialized"); + return false; + } + + if (mempool == NULL) + { + PCPP_LOG_ERROR("Could not initialize MBufRawPacket no mempool provided"); + return false; + } + + m_MBuf = rte_pktmbuf_alloc(mempool); + if (m_MBuf == NULL) + { + PCPP_LOG_ERROR("Couldn't allocate mbuf"); + return false; + } + + m_Mempool = mempool; + return true; } - if (mempool == NULL) + bool MBufRawPacket::init(DpdkDevice* device) { - PCPP_LOG_ERROR("Could not initialize MBufRawPacket no mempool provided"); - return false; + m_MbufDataSize = device->m_MBufDataSize; + return init(device->m_MBufMempool); } - m_MBuf = rte_pktmbuf_alloc(mempool); - if (m_MBuf == NULL) +# ifdef USE_DPDK_KNI + bool MBufRawPacket::init(KniDevice* device) { - PCPP_LOG_ERROR("Couldn't allocate mbuf"); - return false; + return init(device->m_MBufMempool); } +# endif - m_Mempool = mempool; - return true; -} - -bool MBufRawPacket::init(DpdkDevice* device) -{ - m_MbufDataSize = device->m_MBufDataSize; - return init(device->m_MBufMempool); -} - -#ifdef USE_DPDK_KNI -bool MBufRawPacket::init(KniDevice* device) -{ - return init(device->m_MBufMempool); -} -#endif - -bool MBufRawPacket::initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool) -{ - if (!init(mempool)) - return false; - - m_RawPacketSet = false; - - // mbuf is allocated with length of 0, need to adjust it to the size of other - if (rte_pktmbuf_append(m_MBuf, rawPacket->getRawDataLen()) == NULL) + bool MBufRawPacket::initFromRawPacket(const RawPacket* rawPacket, struct rte_mempool* mempool) { - PCPP_LOG_ERROR("Couldn't append " << rawPacket->getRawDataLen() << " bytes to mbuf"); - return false; - } + if (!init(mempool)) + return false; - m_RawData = rte_pktmbuf_mtod(m_MBuf, uint8_t*); - m_RawDataLen = rte_pktmbuf_pkt_len(m_MBuf); + m_RawPacketSet = false; - copyDataFrom(*rawPacket, false); + // mbuf is allocated with length of 0, need to adjust it to the size of other + if (rte_pktmbuf_append(m_MBuf, rawPacket->getRawDataLen()) == NULL) + { + PCPP_LOG_ERROR("Couldn't append " << rawPacket->getRawDataLen() << " bytes to mbuf"); + return false; + } - return true; -} + m_RawData = rte_pktmbuf_mtod(m_MBuf, uint8_t*); + m_RawDataLen = rte_pktmbuf_pkt_len(m_MBuf); -bool MBufRawPacket::initFromRawPacket(const RawPacket* rawPacket, DpdkDevice* device) -{ - return initFromRawPacket(rawPacket, device->m_MBufMempool); -} + copyDataFrom(*rawPacket, false); -#ifdef USE_DPDK_KNI -bool MBufRawPacket::initFromRawPacket(const RawPacket* rawPacket, KniDevice* device) -{ - return initFromRawPacket(rawPacket, device->m_MBufMempool); -} -#endif + return true; + } -MBufRawPacket::MBufRawPacket(const MBufRawPacket& other) -{ - m_DeleteRawDataAtDestructor = false; - m_MBuf = NULL; - m_RawDataLen = 0; - m_RawPacketSet = false; - m_RawData = NULL; - m_Mempool = other.m_Mempool; - m_MbufDataSize = other.m_MbufDataSize; - - rte_mbuf* newMbuf = rte_pktmbuf_alloc(m_Mempool); - if (newMbuf == NULL) + bool MBufRawPacket::initFromRawPacket(const RawPacket* rawPacket, DpdkDevice* device) { - PCPP_LOG_ERROR("Couldn't allocate mbuf"); - return; + return initFromRawPacket(rawPacket, device->m_MBufMempool); } - // mbuf is allocated with length of 0, need to adjust it to the size of other - if (rte_pktmbuf_append(newMbuf, other.m_RawDataLen) == NULL) +# ifdef USE_DPDK_KNI + bool MBufRawPacket::initFromRawPacket(const RawPacket* rawPacket, KniDevice* device) { - PCPP_LOG_ERROR("Couldn't append " << other.m_RawDataLen << " bytes to mbuf"); - return; + return initFromRawPacket(rawPacket, device->m_MBufMempool); } +# endif + + MBufRawPacket::MBufRawPacket(const MBufRawPacket& other) + { + m_DeleteRawDataAtDestructor = false; + m_MBuf = NULL; + m_RawDataLen = 0; + m_RawPacketSet = false; + m_RawData = NULL; + m_Mempool = other.m_Mempool; + m_MbufDataSize = other.m_MbufDataSize; + + rte_mbuf* newMbuf = rte_pktmbuf_alloc(m_Mempool); + if (newMbuf == NULL) + { + PCPP_LOG_ERROR("Couldn't allocate mbuf"); + return; + } - setMBuf(newMbuf, other.m_TimeStamp); + // mbuf is allocated with length of 0, need to adjust it to the size of other + if (rte_pktmbuf_append(newMbuf, other.m_RawDataLen) == NULL) + { + PCPP_LOG_ERROR("Couldn't append " << other.m_RawDataLen << " bytes to mbuf"); + return; + } - m_RawPacketSet = false; + setMBuf(newMbuf, other.m_TimeStamp); - copyDataFrom(other, false); -} + m_RawPacketSet = false; -MBufRawPacket& MBufRawPacket::operator=(const MBufRawPacket& other) -{ - if (m_MBuf == NULL) - { - PCPP_LOG_ERROR("MBufRawPacket isn't initialized"); - return *this; + copyDataFrom(other, false); } - // adjust the size of the mbuf to the new data - if (m_RawDataLen < other.m_RawDataLen) + MBufRawPacket& MBufRawPacket::operator=(const MBufRawPacket& other) { - if (rte_pktmbuf_append(m_MBuf, other.m_RawDataLen - m_RawDataLen) == NULL) + if (m_MBuf == NULL) { - PCPP_LOG_ERROR("Couldn't append " << (other.m_RawDataLen - m_RawDataLen) << " bytes to mbuf"); + PCPP_LOG_ERROR("MBufRawPacket isn't initialized"); return *this; } - } - else if (m_RawDataLen > other.m_RawDataLen) - { - if (rte_pktmbuf_adj(m_MBuf, m_RawDataLen - other.m_RawDataLen) == NULL) + + // adjust the size of the mbuf to the new data + if (m_RawDataLen < other.m_RawDataLen) { - PCPP_LOG_ERROR("Couldn't remove " << m_RawDataLen - other.m_RawDataLen << " bytes to mbuf"); - return *this; + if (rte_pktmbuf_append(m_MBuf, other.m_RawDataLen - m_RawDataLen) == NULL) + { + PCPP_LOG_ERROR("Couldn't append " << (other.m_RawDataLen - m_RawDataLen) << " bytes to mbuf"); + return *this; + } + } + else if (m_RawDataLen > other.m_RawDataLen) + { + if (rte_pktmbuf_adj(m_MBuf, m_RawDataLen - other.m_RawDataLen) == NULL) + { + PCPP_LOG_ERROR("Couldn't remove " << m_RawDataLen - other.m_RawDataLen << " bytes to mbuf"); + return *this; + } } - } - - m_RawPacketSet = false; - copyDataFrom(other, false); + m_RawPacketSet = false; - return *this; -} + copyDataFrom(other, false); -bool MBufRawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType, int frameLength) -{ - if (rawDataLen > m_MbufDataSize) - { - PCPP_LOG_ERROR("Cannot set raw data which length is larger than mBuf max size. mBuf max length: " << m_MbufDataSize << "; requested length: " << rawDataLen); - return false; + return *this; } - if (m_MBuf == NULL) + bool MBufRawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType, + int frameLength) { - if (!(init(m_Mempool))) + if (rawDataLen > m_MbufDataSize) { - PCPP_LOG_ERROR("Couldn't allocate new mBuf"); + PCPP_LOG_ERROR("Cannot set raw data which length is larger than mBuf max size. mBuf max length: " + << m_MbufDataSize << "; requested length: " << rawDataLen); return false; } - } - // adjust the size of the mbuf to the new data - if (m_RawDataLen < rawDataLen) - { - if (rte_pktmbuf_append(m_MBuf, rawDataLen - m_RawDataLen) == NULL) + if (m_MBuf == NULL) { - PCPP_LOG_ERROR("Couldn't append " << (rawDataLen - m_RawDataLen) << " bytes to mbuf"); - return false; + if (!(init(m_Mempool))) + { + PCPP_LOG_ERROR("Couldn't allocate new mBuf"); + return false; + } } - } - else if (m_RawDataLen > rawDataLen) - { - if (rte_pktmbuf_adj(m_MBuf, m_RawDataLen - rawDataLen) == NULL) + + // adjust the size of the mbuf to the new data + if (m_RawDataLen < rawDataLen) { - PCPP_LOG_ERROR("Couldn't remove " << (m_RawDataLen - rawDataLen) << " bytes to mbuf"); - return false; + if (rte_pktmbuf_append(m_MBuf, rawDataLen - m_RawDataLen) == NULL) + { + PCPP_LOG_ERROR("Couldn't append " << (rawDataLen - m_RawDataLen) << " bytes to mbuf"); + return false; + } + } + else if (m_RawDataLen > rawDataLen) + { + if (rte_pktmbuf_adj(m_MBuf, m_RawDataLen - rawDataLen) == NULL) + { + PCPP_LOG_ERROR("Couldn't remove " << (m_RawDataLen - rawDataLen) << " bytes to mbuf"); + return false; + } } - } - - m_RawData = rte_pktmbuf_mtod(m_MBuf, uint8_t*); - m_RawDataLen = rte_pktmbuf_pkt_len(m_MBuf); - memcpy(m_RawData, pRawData, m_RawDataLen); - delete [] pRawData; - m_TimeStamp = timestamp; - m_RawPacketSet = true; - m_FrameLength = frameLength; - m_LinkLayerType = layerType; - return true; -} + m_RawData = rte_pktmbuf_mtod(m_MBuf, uint8_t*); + m_RawDataLen = rte_pktmbuf_pkt_len(m_MBuf); + memcpy(m_RawData, pRawData, m_RawDataLen); + delete[] pRawData; + m_TimeStamp = timestamp; + m_RawPacketSet = true; + m_FrameLength = frameLength; + m_LinkLayerType = layerType; -void MBufRawPacket::clear() -{ - if (m_MBuf != NULL && m_FreeMbuf) - { - rte_pktmbuf_free(m_MBuf); + return true; } - m_MBuf = NULL; + void MBufRawPacket::clear() + { + if (m_MBuf != NULL && m_FreeMbuf) + { + rte_pktmbuf_free(m_MBuf); + } - m_RawData = NULL; + m_MBuf = NULL; - RawPacket::clear(); -} + m_RawData = NULL; -void MBufRawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) -{ - if (m_MBuf == NULL) - { - PCPP_LOG_ERROR("MBufRawPacket not initialized. Please call the init() method"); - return; //TODO: need to return false here or something + RawPacket::clear(); } - char* startOfNewlyAppendedData = rte_pktmbuf_append(m_MBuf, dataToAppendLen); - if (startOfNewlyAppendedData == NULL) + void MBufRawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) { - PCPP_LOG_ERROR("Couldn't append " << dataToAppendLen << " bytes to RawPacket - not enough room in mBuf"); - return; //TODO: need to return false here or something - } + if (m_MBuf == NULL) + { + PCPP_LOG_ERROR("MBufRawPacket not initialized. Please call the init() method"); + return; // TODO: need to return false here or something + } - RawPacket::appendData(dataToAppend, dataToAppendLen); + char* startOfNewlyAppendedData = rte_pktmbuf_append(m_MBuf, dataToAppendLen); + if (startOfNewlyAppendedData == NULL) + { + PCPP_LOG_ERROR("Couldn't append " << dataToAppendLen << " bytes to RawPacket - not enough room in mBuf"); + return; // TODO: need to return false here or something + } - PCPP_LOG_DEBUG("Appended " << dataToAppendLen << " bytes to MBufRawPacket"); -} + RawPacket::appendData(dataToAppend, dataToAppendLen); -void MBufRawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) -{ - if (m_MBuf == NULL) - { - PCPP_LOG_ERROR("MBufRawPacket not initialized. Please call the init() method"); - return; //TODO: need to return false here or something + PCPP_LOG_DEBUG("Appended " << dataToAppendLen << " bytes to MBufRawPacket"); } - char* startOfNewlyAppendedData = rte_pktmbuf_append(m_MBuf, dataToInsertLen); - if (startOfNewlyAppendedData == NULL) + void MBufRawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) { - PCPP_LOG_ERROR("Couldn't append " << dataToInsertLen << " bytes to RawPacket - not enough room in mBuf"); - return; //TODO: need to return false here or something - } + if (m_MBuf == NULL) + { + PCPP_LOG_ERROR("MBufRawPacket not initialized. Please call the init() method"); + return; // TODO: need to return false here or something + } - RawPacket::insertData(atIndex, dataToInsert, dataToInsertLen); + char* startOfNewlyAppendedData = rte_pktmbuf_append(m_MBuf, dataToInsertLen); + if (startOfNewlyAppendedData == NULL) + { + PCPP_LOG_ERROR("Couldn't append " << dataToInsertLen << " bytes to RawPacket - not enough room in mBuf"); + return; // TODO: need to return false here or something + } - PCPP_LOG_DEBUG("Inserted " << dataToInsertLen << " bytes to MBufRawPacket"); -} + RawPacket::insertData(atIndex, dataToInsert, dataToInsertLen); -bool MBufRawPacket::removeData(int atIndex, size_t numOfBytesToRemove) -{ - if (m_MBuf == NULL) - { - PCPP_LOG_ERROR("MBufRawPacket not initialized. Please call the init() method"); - return false; + PCPP_LOG_DEBUG("Inserted " << dataToInsertLen << " bytes to MBufRawPacket"); } - if (!RawPacket::removeData(atIndex, numOfBytesToRemove)) - return false; - - if (rte_pktmbuf_trim(m_MBuf, numOfBytesToRemove) != 0) + bool MBufRawPacket::removeData(int atIndex, size_t numOfBytesToRemove) { - PCPP_LOG_ERROR("Couldn't trim the mBuf"); - return false; - } + if (m_MBuf == NULL) + { + PCPP_LOG_ERROR("MBufRawPacket not initialized. Please call the init() method"); + return false; + } + + if (!RawPacket::removeData(atIndex, numOfBytesToRemove)) + return false; - PCPP_LOG_DEBUG("Trimmed " << numOfBytesToRemove << " bytes from MBufRawPacket"); + if (rte_pktmbuf_trim(m_MBuf, numOfBytesToRemove) != 0) + { + PCPP_LOG_ERROR("Couldn't trim the mBuf"); + return false; + } - return true; -} + PCPP_LOG_DEBUG("Trimmed " << numOfBytesToRemove << " bytes from MBufRawPacket"); -bool MBufRawPacket::reallocateData(size_t newBufferLength) -{ - if ((int)newBufferLength < m_RawDataLen) - { - PCPP_LOG_ERROR("Cannot reallocate mBuf raw packet to a smaller size. Current data length: " << m_RawDataLen << "; requested length: " << newBufferLength); - return false; + return true; } - if ((int)newBufferLength > m_MbufDataSize) + bool MBufRawPacket::reallocateData(size_t newBufferLength) { - PCPP_LOG_ERROR("Cannot reallocate mBuf raw packet to a size larger than mBuf data. mBuf max length: " << m_MbufDataSize << "; requested length: " << newBufferLength); - return false; - } + if ((int)newBufferLength < m_RawDataLen) + { + PCPP_LOG_ERROR("Cannot reallocate mBuf raw packet to a smaller size. Current data length: " + << m_RawDataLen << "; requested length: " << newBufferLength); + return false; + } - // no need to do any memory allocation because mbuf is already allocated + if ((int)newBufferLength > m_MbufDataSize) + { + PCPP_LOG_ERROR("Cannot reallocate mBuf raw packet to a size larger than mBuf data. mBuf max length: " + << m_MbufDataSize << "; requested length: " << newBufferLength); + return false; + } - return true; -} + // no need to do any memory allocation because mbuf is already allocated -void MBufRawPacket::setMBuf(struct rte_mbuf* mBuf, timespec timestamp) -{ - if (m_MBuf != NULL && m_FreeMbuf) - rte_pktmbuf_free(m_MBuf); + return true; + } - if (mBuf == NULL) + void MBufRawPacket::setMBuf(struct rte_mbuf* mBuf, timespec timestamp) { - PCPP_LOG_ERROR("mbuf to set is NULL"); - return; - } + if (m_MBuf != NULL && m_FreeMbuf) + rte_pktmbuf_free(m_MBuf); + + if (mBuf == NULL) + { + PCPP_LOG_ERROR("mbuf to set is NULL"); + return; + } - m_MBuf = mBuf; - RawPacket::setRawData(rte_pktmbuf_mtod(mBuf, const uint8_t*), rte_pktmbuf_pkt_len(mBuf), timestamp, LINKTYPE_ETHERNET); -} + m_MBuf = mBuf; + RawPacket::setRawData(rte_pktmbuf_mtod(mBuf, const uint8_t*), rte_pktmbuf_pkt_len(mBuf), timestamp, + LINKTYPE_ETHERNET); + } -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP -#endif /* USE_DPDK */ +#endif /* USE_DPDK */ diff --git a/Pcap++/src/NetworkUtils.cpp b/Pcap++/src/NetworkUtils.cpp index 774688a156..06e26f5315 100644 --- a/Pcap++/src/NetworkUtils.cpp +++ b/Pcap++/src/NetworkUtils.cpp @@ -15,433 +15,417 @@ #include "NetworkUtils.h" #include "EndianPortable.h" #ifdef _MSC_VER -#include "SystemUtils.h" +# include "SystemUtils.h" #endif #ifndef ETIMEDOUT -#define ETIMEDOUT 10060 +# define ETIMEDOUT 10060 #endif -#define DNS_PORT 53 - +#define DNS_PORT 53 namespace pcpp { -const int NetworkUtils::DefaultTimeout = 5; + const int NetworkUtils::DefaultTimeout = 5; + struct ArpingReceivedData + { + std::mutex& mutex; + std::condition_variable& cond; + IPv4Address ipAddr; + clock_t start; + MacAddress result; + double arpResponseTime; + }; -struct ArpingReceivedData -{ - std::mutex &mutex; - std::condition_variable &cond; - IPv4Address ipAddr; - clock_t start; - MacAddress result; - double arpResponseTime; -}; + static void arpPacketReceived(RawPacket* rawPacket, PcapLiveDevice*, void* userCookie) + { + // extract timestamp of packet + clock_t receiveTime = clock(); + // get the data from the main thread + ArpingReceivedData* data = (ArpingReceivedData*)userCookie; -static void arpPacketReceived(RawPacket* rawPacket, PcapLiveDevice*, void* userCookie) -{ - // extract timestamp of packet - clock_t receiveTime = clock(); + // parse the response packet + Packet packet(rawPacket); - // get the data from the main thread - ArpingReceivedData* data = (ArpingReceivedData*)userCookie; + // verify that it's an ARP packet (although it must be because I set an ARP reply filter on the interface) + if (!packet.isPacketOfType(ARP)) + return; - // parse the response packet - Packet packet(rawPacket); + // extract the ARP layer from the packet + ArpLayer* arpReplyLayer = packet.getLayerOfType(true); // lookup in reverse order + if (arpReplyLayer == nullptr) + return; - // verify that it's an ARP packet (although it must be because I set an ARP reply filter on the interface) - if (!packet.isPacketOfType(ARP)) - return; + // verify it's the right ARP response + if (arpReplyLayer->getArpHeader()->hardwareType != htobe16(1) /* Ethernet */ + || arpReplyLayer->getArpHeader()->protocolType != htobe16(PCPP_ETHERTYPE_IP)) + return; - // extract the ARP layer from the packet - ArpLayer* arpReplyLayer = packet.getLayerOfType(true); // lookup in reverse order - if (arpReplyLayer == nullptr) - return; + // verify the ARP response is the response for out request (and not some arbitrary ARP response) + if (arpReplyLayer->getSenderIpAddr() != data->ipAddr) + return; - // verify it's the right ARP response - if (arpReplyLayer->getArpHeader()->hardwareType != htobe16(1) /* Ethernet */ - || arpReplyLayer->getArpHeader()->protocolType != htobe16(PCPP_ETHERTYPE_IP)) - return; + // measure response time + double diffticks = receiveTime - data->start; + double diffms = (diffticks * 1000) / CLOCKS_PER_SEC; - // verify the ARP response is the response for out request (and not some arbitrary ARP response) - if (arpReplyLayer->getSenderIpAddr() != data->ipAddr) - return; + data->arpResponseTime = diffms; + data->result = arpReplyLayer->getSenderMacAddress(); - // measure response time - double diffticks = receiveTime-data->start; - double diffms = (diffticks*1000)/CLOCKS_PER_SEC; + // signal the main thread the ARP reply was received + data->cond.notify_one(); + } - data->arpResponseTime = diffms; - data->result = arpReplyLayer->getSenderMacAddress(); + MacAddress NetworkUtils::getMacAddress(IPv4Address ipAddr, PcapLiveDevice* device, double& arpResponseTimeMS, + MacAddress sourceMac, IPv4Address sourceIP, int arpTimeout) const + { + MacAddress result = MacAddress::Zero; - // signal the main thread the ARP reply was received - data->cond.notify_one(); -} + // open the device if not already opened + bool closeDeviceAtTheEnd = false; + if (!device->isOpened()) + { + closeDeviceAtTheEnd = true; + if (!device->open()) + { + PCPP_LOG_ERROR("Cannot open device"); + return result; + } + } + if (sourceMac == MacAddress::Zero) + sourceMac = device->getMacAddress(); -MacAddress NetworkUtils::getMacAddress(IPv4Address ipAddr, PcapLiveDevice* device, double& arpResponseTimeMS, - MacAddress sourceMac, IPv4Address sourceIP, int arpTimeout) const -{ - MacAddress result = MacAddress::Zero; + if (sourceIP == IPv4Address::Zero) + sourceIP = device->getIPv4Address(); - // open the device if not already opened - bool closeDeviceAtTheEnd = false; - if (!device->isOpened()) - { - closeDeviceAtTheEnd = true; - if (!device->open()) - { - PCPP_LOG_ERROR("Cannot open device"); - return result; - } - } + if (arpTimeout <= 0) + arpTimeout = NetworkUtils::DefaultTimeout; - if (sourceMac == MacAddress::Zero) - sourceMac = device->getMacAddress(); + // create an ARP request from sourceMac and sourceIP and ask for target IP - if (sourceIP == IPv4Address::Zero) - sourceIP = device->getIPv4Address(); + Packet arpRequest(100); - if (arpTimeout <= 0) - arpTimeout = NetworkUtils::DefaultTimeout; + MacAddress destMac(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); + EthLayer ethLayer(sourceMac, destMac); - // create an ARP request from sourceMac and sourceIP and ask for target IP + ArpLayer arpLayer(ARP_REQUEST, sourceMac, destMac, sourceIP, ipAddr); - Packet arpRequest(100); + if (!arpRequest.addLayer(ðLayer)) + { + PCPP_LOG_ERROR("Couldn't build Eth layer for ARP request"); + return result; + } - MacAddress destMac(0xff, 0xff, 0xff, 0xff, 0xff, 0xff); - EthLayer ethLayer(sourceMac, destMac); + if (!arpRequest.addLayer(&arpLayer)) + { + PCPP_LOG_ERROR("Couldn't build ARP layer for ARP request"); + return result; + } - ArpLayer arpLayer(ARP_REQUEST, sourceMac, destMac, sourceIP, ipAddr); + arpRequest.computeCalculateFields(); - if (!arpRequest.addLayer(ðLayer)) - { - PCPP_LOG_ERROR("Couldn't build Eth layer for ARP request"); - return result; - } + // set a filter for the interface to intercept only ARP response packets + ArpFilter arpFilter(ARP_REPLY); + if (!device->setFilter(arpFilter)) + { + PCPP_LOG_ERROR("Couldn't set ARP filter for device"); + return result; + } - if (!arpRequest.addLayer(&arpLayer)) - { - PCPP_LOG_ERROR("Couldn't build ARP layer for ARP request"); - return result; - } + // since packet capture is done on another thread, I use a conditional mutex with timeout to synchronize between + // the capture thread and the main thread. When the capture thread starts running the main thread is blocking on + // the conditional mutex. When the ARP response is captured the capture thread signals the main thread and the + // main thread stops capturing and continues to the next iteration. If a timeout passes and no ARP response is + // captured, the main thread stops capturing - arpRequest.computeCalculateFields(); + std::mutex mutex; + std::condition_variable cond; - // set a filter for the interface to intercept only ARP response packets - ArpFilter arpFilter(ARP_REPLY); - if (!device->setFilter(arpFilter)) - { - PCPP_LOG_ERROR("Couldn't set ARP filter for device"); - return result; - } + // this is the token that passes between the 2 threads. It contains pointers to the conditional mutex, the + // target IP for identifying the ARP response, the iteration index and a timestamp to calculate the response + // time + ArpingReceivedData data = { mutex, cond, ipAddr, clock(), MacAddress::Zero, 0 }; - // since packet capture is done on another thread, I use a conditional mutex with timeout to synchronize between the capture - // thread and the main thread. When the capture thread starts running the main thread is blocking on the conditional mutex. - // When the ARP response is captured the capture thread signals the main thread and the main thread stops capturing and continues - // to the next iteration. If a timeout passes and no ARP response is captured, the main thread stops capturing - - std::mutex mutex; - std::condition_variable cond; - - // this is the token that passes between the 2 threads. It contains pointers to the conditional mutex, the target IP for identifying - // the ARP response, the iteration index and a timestamp to calculate the response time - ArpingReceivedData data = { - mutex, - cond, - ipAddr, - clock(), - MacAddress::Zero, - 0 - }; + struct timeval now; + gettimeofday(&now, nullptr); - struct timeval now; - gettimeofday(&now,nullptr); + // start capturing. The capture is done on another thread, hence "arpPacketReceived" is running on that thread + device->startCapture(arpPacketReceived, &data); - // start capturing. The capture is done on another thread, hence "arpPacketReceived" is running on that thread - device->startCapture(arpPacketReceived, &data); + // send the ARP request + device->sendPacket(&arpRequest); - // send the ARP request - device->sendPacket(&arpRequest); + // block on the conditional mutex until capture thread signals or until timeout expires + // cppcheck-suppress localMutex + std::unique_lock lock(mutex); + std::cv_status res = cond.wait_for(lock, std::chrono::seconds(arpTimeout)); - // block on the conditional mutex until capture thread signals or until timeout expires - // cppcheck-suppress localMutex - std::unique_lock lock(mutex); - std::cv_status res = cond.wait_for(lock, std::chrono::seconds(arpTimeout)); + // stop the capturing thread + device->stopCapture(); - // stop the capturing thread - device->stopCapture(); + // check if timeout expired + if (res == std::cv_status::timeout) + { + PCPP_LOG_ERROR("ARP request time out"); + return result; + } + + if (closeDeviceAtTheEnd) + device->close(); + else + device->clearFilter(); + + result = data.result; + arpResponseTimeMS = data.arpResponseTime; - // check if timeout expired - if (res == std::cv_status::timeout) - { - PCPP_LOG_ERROR("ARP request time out"); return result; } - if (closeDeviceAtTheEnd) - device->close(); - else - device->clearFilter(); + struct DNSReceivedData + { + std::mutex& mutex; + std::condition_variable& cond; + std::string hostname; + uint16_t transactionID; + clock_t start; + IPv4Address result; + uint32_t ttl; + double dnsResponseTime; + }; - result = data.result; - arpResponseTimeMS = data.arpResponseTime; + static void dnsResponseReceived(RawPacket* rawPacket, PcapLiveDevice*, void* userCookie) + { + // extract timestamp of packet + clock_t receiveTime = clock(); - return result; -} + // get data from the main thread + DNSReceivedData* data = (DNSReceivedData*)userCookie; + // parse the response packet + Packet packet(rawPacket); + // verify that it's an DNS packet (although it must be because DNS port filter was set on the interface) + if (!packet.isPacketOfType(DNS)) + return; -struct DNSReceivedData -{ - std::mutex &mutex; - std::condition_variable &cond; - std::string hostname; - uint16_t transactionID; - clock_t start; - IPv4Address result; - uint32_t ttl; - double dnsResponseTime; -}; - -static void dnsResponseReceived(RawPacket* rawPacket, PcapLiveDevice*, void* userCookie) -{ - // extract timestamp of packet - clock_t receiveTime = clock(); + // extract the DNS layer from the packet + DnsLayer* dnsResponseLayer = packet.getLayerOfType(true); // lookup in reverse order + if (dnsResponseLayer == nullptr) + return; - // get data from the main thread - DNSReceivedData* data = (DNSReceivedData*)userCookie; + // verify it's the right DNS response + if (dnsResponseLayer->getDnsHeader()->queryOrResponse != 1 /* DNS response */ + || dnsResponseLayer->getDnsHeader()->numberOfAnswers < htobe16(1) || + dnsResponseLayer->getDnsHeader()->transactionID != htobe16(data->transactionID)) + { + return; + } - // parse the response packet - Packet packet(rawPacket); + // DNS resolving can be recursive as many DNS responses contain multiple answers with recursive canonical names + // (CNAME) for the hostname. For example: a DNS response for www.a.com can have multiple answers: + //- First with CNAME: www.a.com -> www.b.com + //- Second with CNAME: www.b.com -> www.c.com + //- Third with resolving: www.c.com -> 1.1.1.1 + // So the search must be recursive until an IPv4 resolving is found or until no hostname or canonical name are + // found (and then return) - // verify that it's an DNS packet (although it must be because DNS port filter was set on the interface) - if (!packet.isPacketOfType(DNS)) - return; + std::string hostToFind = data->hostname; - // extract the DNS layer from the packet - DnsLayer* dnsResponseLayer = packet.getLayerOfType(true); // lookup in reverse order - if (dnsResponseLayer == nullptr) - return; + DnsResource* dnsAnswer = nullptr; - // verify it's the right DNS response - if (dnsResponseLayer->getDnsHeader()->queryOrResponse != 1 /* DNS response */ - || dnsResponseLayer->getDnsHeader()->numberOfAnswers < htobe16(1) - || dnsResponseLayer->getDnsHeader()->transactionID != htobe16(data->transactionID)) - { - return; - } + while (true) + { + dnsAnswer = dnsResponseLayer->getAnswer(hostToFind, true); + + // if response doesn't contain hostname or cname - return + if (dnsAnswer == nullptr) + { + PCPP_LOG_DEBUG("DNS answer doesn't contain hostname '" << hostToFind << "'"); + return; + } + + DnsType dnsType = dnsAnswer->getDnsType(); + // if answer contains IPv4 resolving - break the loop and return the IP address + if (dnsType == DNS_TYPE_A) + { + PCPP_LOG_DEBUG("Found IPv4 resolving for hostname '" << hostToFind << "'"); + break; + } + // if answer contains a cname - continue to search this cname in the packet - hopefully find the IP + // resolving + else if (dnsType == DNS_TYPE_CNAME) + { + PCPP_LOG_DEBUG("Got a DNS response for hostname '" << hostToFind << "' with CNAME '" + << dnsAnswer->getData()->toString() << "'"); + hostToFind = dnsAnswer->getData()->toString(); + } + // if answer is of type other than A or CNAME (for example AAAA - IPv6) - type is not supported - return + else + { + PCPP_LOG_DEBUG("Got a DNS response with type which is not A or CNAME"); + return; + } + } + // if we got here it means an IPv4 resolving was found - // DNS resolving can be recursive as many DNS responses contain multiple answers with recursive canonical names (CNAME) for - // the hostname. For example: a DNS response for www.a.com can have multiple answers: - //- First with CNAME: www.a.com -> www.b.com - //- Second with CNAME: www.b.com -> www.c.com - //- Third with resolving: www.c.com -> 1.1.1.1 - // So the search must be recursive until an IPv4 resolving is found or until no hostname or canonical name are found (and then return) + // measure response time + clock_t diffticks = receiveTime - data->start; + double diffms = (diffticks * 1000.0) / CLOCKS_PER_SEC; - std::string hostToFind = data->hostname; + data->dnsResponseTime = diffms; + data->result = dnsAnswer->getData()->castAs()->getIpAddress(); + data->ttl = dnsAnswer->getTTL(); - DnsResource* dnsAnswer = nullptr; + // signal the main thread the ARP reply was received + data->cond.notify_one(); + } - while (true) + IPv4Address NetworkUtils::getIPv4Address(const std::string& hostname, PcapLiveDevice* device, + double& dnsResponseTimeMS, uint32_t& dnsTTL, int dnsTimeout, + IPv4Address dnsServerIP, IPv4Address gatewayIP) const { - dnsAnswer = dnsResponseLayer->getAnswer(hostToFind, true); + IPv4Address result = IPv4Address::Zero; - // if response doesn't contain hostname or cname - return - if (dnsAnswer == nullptr) + // open the device if not already opened + bool closeDeviceAtTheEnd = false; + if (!device->isOpened()) { - PCPP_LOG_DEBUG("DNS answer doesn't contain hostname '" << hostToFind << "'"); - return; + closeDeviceAtTheEnd = true; + if (!device->open()) + { + PCPP_LOG_ERROR("Cannot open device"); + return result; + } } - DnsType dnsType = dnsAnswer->getDnsType(); - // if answer contains IPv4 resolving - break the loop and return the IP address - if (dnsType == DNS_TYPE_A) - { - PCPP_LOG_DEBUG("Found IPv4 resolving for hostname '" << hostToFind << "'"); - break; - } - // if answer contains a cname - continue to search this cname in the packet - hopefully find the IP resolving - else if (dnsType == DNS_TYPE_CNAME) + // first - resolve gateway MAC address + + // if gateway IP wasn't provided - try to find the default gateway + if (gatewayIP == IPv4Address::Zero) { - PCPP_LOG_DEBUG("Got a DNS response for hostname '" << hostToFind << "' with CNAME '" << dnsAnswer->getData()->toString() << "'"); - hostToFind = dnsAnswer->getData()->toString(); + gatewayIP = device->getDefaultGateway(); } - // if answer is of type other than A or CNAME (for example AAAA - IPv6) - type is not supported - return - else + + if (gatewayIP == IPv4Address::Zero) { - PCPP_LOG_DEBUG("Got a DNS response with type which is not A or CNAME"); - return; + PCPP_LOG_ERROR("Gateway address isn't valid or couldn't find default gateway"); + return result; } - } - // if we got here it means an IPv4 resolving was found - - // measure response time - clock_t diffticks = receiveTime-data->start; - double diffms = (diffticks*1000.0)/CLOCKS_PER_SEC; - data->dnsResponseTime = diffms; - data->result = dnsAnswer->getData()->castAs()->getIpAddress(); - data->ttl = dnsAnswer->getTTL(); + // send the ARP request to find gateway MAC address + double arpResTime; + MacAddress gatewayMacAddress = getMacAddress(gatewayIP, device, arpResTime); - // signal the main thread the ARP reply was received - data->cond.notify_one(); -} - - -IPv4Address NetworkUtils::getIPv4Address(const std::string& hostname, PcapLiveDevice* device, double& dnsResponseTimeMS, uint32_t& dnsTTL, - int dnsTimeout, IPv4Address dnsServerIP, IPv4Address gatewayIP) const -{ - IPv4Address result = IPv4Address::Zero; - - // open the device if not already opened - bool closeDeviceAtTheEnd = false; - if (!device->isOpened()) - { - closeDeviceAtTheEnd = true; - if (!device->open()) + if (gatewayMacAddress == MacAddress::Zero) { - PCPP_LOG_ERROR("Cannot open device"); + PCPP_LOG_ERROR("Couldn't resolve gateway MAC address"); return result; } - } - // first - resolve gateway MAC address + if (dnsTimeout <= 0) + dnsTimeout = NetworkUtils::DefaultTimeout; - // if gateway IP wasn't provided - try to find the default gateway - if (gatewayIP == IPv4Address::Zero) - { - gatewayIP = device->getDefaultGateway(); - } - - if (gatewayIP == IPv4Address::Zero) - { - PCPP_LOG_ERROR("Gateway address isn't valid or couldn't find default gateway"); - return result; - } + // validate DNS server IP. If it wasn't provided - set the system-configured DNS server + if (dnsServerIP == IPv4Address::Zero && device->getDnsServers().size() > 0) + { + dnsServerIP = device->getDnsServers().at(0); + } - // send the ARP request to find gateway MAC address - double arpResTime; - MacAddress gatewayMacAddress = getMacAddress(gatewayIP, device, arpResTime); + if (dnsServerIP == IPv4Address::Zero) + { + PCPP_LOG_ERROR("DNS server IP wasn't provided and couldn't find system-configured DNS server"); + return result; + } - if (gatewayMacAddress == MacAddress::Zero) - { - PCPP_LOG_ERROR("Couldn't resolve gateway MAC address"); - return result; - } + // create DNS request - if (dnsTimeout <= 0) - dnsTimeout = NetworkUtils::DefaultTimeout; + Packet dnsRequest(100); + MacAddress sourceMac = device->getMacAddress(); + EthLayer ethLayer(sourceMac, gatewayMacAddress, PCPP_ETHERTYPE_IP); + IPv4Layer ipLayer(device->getIPv4Address(), dnsServerIP); + ipLayer.getIPv4Header()->timeToLive = 128; - // validate DNS server IP. If it wasn't provided - set the system-configured DNS server - if (dnsServerIP == IPv4Address::Zero && device->getDnsServers().size() > 0) - { - dnsServerIP = device->getDnsServers().at(0); - } + // randomize source port to a number >= 10000 + int srcPortLowest = 10000; + int srcPortRange = 65535 - srcPortLowest; + uint16_t srcPort = (rand() % srcPortRange) + srcPortLowest; + UdpLayer udpLayer(srcPort, DNS_PORT); - if (dnsServerIP == IPv4Address::Zero) - { - PCPP_LOG_ERROR("DNS server IP wasn't provided and couldn't find system-configured DNS server"); - return result; - } + // create the DNS request for the hostname + DnsLayer dnsLayer; - // create DNS request + // randomize transaction ID + uint16_t transactionID = rand() % 65535; + dnsLayer.getDnsHeader()->transactionID = htobe16(transactionID); + dnsLayer.addQuery(hostname, DNS_TYPE_A, DNS_CLASS_IN); - Packet dnsRequest(100); - MacAddress sourceMac = device->getMacAddress(); - EthLayer ethLayer(sourceMac, gatewayMacAddress, PCPP_ETHERTYPE_IP); - IPv4Layer ipLayer(device->getIPv4Address(), dnsServerIP); - ipLayer.getIPv4Header()->timeToLive = 128; + // add all layers to packet + if (!dnsRequest.addLayer(ðLayer) || !dnsRequest.addLayer(&ipLayer) || !dnsRequest.addLayer(&udpLayer) || + !dnsRequest.addLayer(&dnsLayer)) + { + PCPP_LOG_ERROR("Couldn't construct DNS query"); + return result; + } - // randomize source port to a number >= 10000 - int srcPortLowest = 10000; - int srcPortRange = 65535 - srcPortLowest; - uint16_t srcPort = (rand() % srcPortRange) + srcPortLowest; - UdpLayer udpLayer(srcPort, DNS_PORT); + dnsRequest.computeCalculateFields(); - // create the DNS request for the hostname - DnsLayer dnsLayer; + // set a DNS response filter on the device + PortFilter dnsResponseFilter(53, SRC); + if (!device->setFilter(dnsResponseFilter)) + { + PCPP_LOG_ERROR("Couldn't set DNS response filter"); + return result; + } - // randomize transaction ID - uint16_t transactionID = rand() % 65535; - dnsLayer.getDnsHeader()->transactionID = htobe16(transactionID); - dnsLayer.addQuery(hostname, DNS_TYPE_A, DNS_CLASS_IN); + // since packet capture is done on another thread, I use a conditional mutex with timeout to synchronize between + // the capture thread and the main thread. When the capture thread starts running the main thread is blocking on + // the conditional mutex. When the DNS response are captured the capture thread signals the main thread and the + // main thread stops capturing and continues to the next iteration. if a timeout passes and no DNS response is + // captured, the main thread stops capturing - // add all layers to packet - if (!dnsRequest.addLayer(ðLayer) || !dnsRequest.addLayer(&ipLayer) || !dnsRequest.addLayer(&udpLayer) || !dnsRequest.addLayer(&dnsLayer)) - { - PCPP_LOG_ERROR("Couldn't construct DNS query"); - return result; - } + std::mutex mutex; + std::condition_variable cond; - dnsRequest.computeCalculateFields(); + // this is the token that passes between the 2 threads + DNSReceivedData data = { mutex, cond, hostname, transactionID, clock(), IPv4Address::Zero, 0, 0 }; - // set a DNS response filter on the device - PortFilter dnsResponseFilter(53, SRC); - if (!device->setFilter(dnsResponseFilter)) - { - PCPP_LOG_ERROR("Couldn't set DNS response filter"); - return result; - } + struct timeval now; + gettimeofday(&now, nullptr); - // since packet capture is done on another thread, I use a conditional mutex with timeout to synchronize between the capture - // thread and the main thread. When the capture thread starts running the main thread is blocking on the conditional mutex. - // When the DNS response are captured the capture thread signals the main thread and the main thread stops capturing and continues - // to the next iteration. if a timeout passes and no DNS response is captured, the main thread stops capturing - - std::mutex mutex; - std::condition_variable cond; - - // this is the token that passes between the 2 threads - DNSReceivedData data = { - mutex, - cond, - hostname, - transactionID, - clock(), - IPv4Address::Zero, - 0, - 0 - }; + // start capturing. The capture is done on another thread, hence "dnsResponseReceived" is running on that thread + device->startCapture(dnsResponseReceived, &data); + // send the DNS request + device->sendPacket(&dnsRequest); - struct timeval now; - gettimeofday(&now,nullptr); + // block on the conditional mutex until capture thread signals or until timeout expires + // cppcheck-suppress localMutex + std::unique_lock lock(mutex); + std::cv_status res = cond.wait_for(lock, std::chrono::seconds(dnsTimeout)); - // start capturing. The capture is done on another thread, hence "dnsResponseReceived" is running on that thread - device->startCapture(dnsResponseReceived, &data); + // stop the capturing thread + device->stopCapture(); - // send the DNS request - device->sendPacket(&dnsRequest); + // check if timeout expired + if (res == std::cv_status::timeout) + { + PCPP_LOG_ERROR("DNS request time out"); + return result; + } - // block on the conditional mutex until capture thread signals or until timeout expires - // cppcheck-suppress localMutex - std::unique_lock lock(mutex); - std::cv_status res = cond.wait_for(lock, std::chrono::seconds(dnsTimeout)); + if (closeDeviceAtTheEnd) + device->close(); + else + device->clearFilter(); - // stop the capturing thread - device->stopCapture(); + result = data.result; + dnsResponseTimeMS = data.dnsResponseTime; + dnsTTL = data.ttl; - // check if timeout expired - if (res == std::cv_status::timeout) - { - PCPP_LOG_ERROR("DNS request time out"); return result; } - if (closeDeviceAtTheEnd) - device->close(); - else - device->clearFilter(); - - result = data.result; - dnsResponseTimeMS = data.dnsResponseTime; - dnsTTL = data.ttl; - - return result; -} - -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/src/PcapDevice.cpp b/Pcap++/src/PcapDevice.cpp index a8bc77267e..b0e704dae1 100644 --- a/Pcap++/src/PcapDevice.cpp +++ b/Pcap++/src/PcapDevice.cpp @@ -7,64 +7,63 @@ namespace pcpp { -IPcapDevice::~IPcapDevice() -{ -} + IPcapDevice::~IPcapDevice() + {} -bool IPcapDevice::setFilter(std::string filterAsString) -{ - PCPP_LOG_DEBUG("Filter to be set: '" << filterAsString << "'"); - if (!m_DeviceOpened) + bool IPcapDevice::setFilter(std::string filterAsString) { - PCPP_LOG_ERROR("Device not Opened!! cannot set filter"); - return false; - } + PCPP_LOG_DEBUG("Filter to be set: '" << filterAsString << "'"); + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device not Opened!! cannot set filter"); + return false; + } - struct bpf_program prog; - PCPP_LOG_DEBUG("Compiling the filter '" << filterAsString << "'"); - if (pcap_compile(m_PcapDescriptor, &prog, filterAsString.c_str(), 1, 0) < 0) - { - /* - * Print out appropriate text, followed by the error message - * generated by the packet capture library. - */ - PCPP_LOG_ERROR("Error compiling filter. Error message is: " << pcap_geterr(m_PcapDescriptor)); - return false; - } + struct bpf_program prog; + PCPP_LOG_DEBUG("Compiling the filter '" << filterAsString << "'"); + if (pcap_compile(m_PcapDescriptor, &prog, filterAsString.c_str(), 1, 0) < 0) + { + /* + * Print out appropriate text, followed by the error message + * generated by the packet capture library. + */ + PCPP_LOG_ERROR("Error compiling filter. Error message is: " << pcap_geterr(m_PcapDescriptor)); + return false; + } - PCPP_LOG_DEBUG("Setting the compiled filter"); - if (pcap_setfilter(m_PcapDescriptor, &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. - */ - PCPP_LOG_ERROR("Error setting a compiled filter. Error message is: " << pcap_geterr(m_PcapDescriptor)); - pcap_freecode(&prog); - return false; - } + PCPP_LOG_DEBUG("Setting the compiled filter"); + if (pcap_setfilter(m_PcapDescriptor, &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. + */ + PCPP_LOG_ERROR("Error setting a compiled filter. Error message is: " << pcap_geterr(m_PcapDescriptor)); + pcap_freecode(&prog); + return false; + } - PCPP_LOG_DEBUG("Filter set successfully"); + PCPP_LOG_DEBUG("Filter set successfully"); - pcap_freecode(&prog); + pcap_freecode(&prog); - return true; -} + return true; + } -bool IPcapDevice::clearFilter() -{ - return setFilter(""); -} + bool IPcapDevice::clearFilter() + { + return setFilter(""); + } -bool IPcapDevice::matchPacketWithFilter(GeneralFilter& filter, RawPacket* rawPacket) -{ - return filter.matchPacketWithFilter(rawPacket); -} + bool IPcapDevice::matchPacketWithFilter(GeneralFilter& filter, RawPacket* rawPacket) + { + return filter.matchPacketWithFilter(rawPacket); + } -std::string IPcapDevice::getPcapLibVersionInfo() -{ - return std::string(pcap_lib_version()); -} + std::string IPcapDevice::getPcapLibVersionInfo() + { + return std::string(pcap_lib_version()); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 82e1f59870..167224b615 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -14,976 +14,998 @@ namespace pcpp { -template -constexpr size_t ARRAY_SIZE(T (&)[N]) { return N; } + template constexpr size_t ARRAY_SIZE(T (&)[N]) + { + return N; + } -struct pcap_file_header -{ - uint32_t magic; - uint16_t version_major; - uint16_t version_minor; - int32_t thiszone; - uint32_t sigfigs; - uint32_t snaplen; - uint32_t linktype; -}; - -struct packet_header -{ - uint32_t tv_sec; - uint32_t tv_usec; - uint32_t caplen; - uint32_t len; -}; + struct pcap_file_header + { + uint32_t magic; + uint16_t version_major; + uint16_t version_minor; + int32_t thiszone; + uint32_t sigfigs; + uint32_t snaplen; + uint32_t linktype; + }; -static bool checkNanoSupport() -{ + struct packet_header + { + uint32_t tv_sec; + uint32_t tv_usec; + uint32_t caplen; + uint32_t len; + }; + + static bool checkNanoSupport() + { #if defined(PCAP_TSTAMP_PRECISION_NANO) - return true; + return true; #else - PCPP_LOG_DEBUG( - "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " - "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); - return false; + PCPP_LOG_DEBUG( + "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " + "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); + return false; #endif -} - -// ~~~~~~~~~~~~~~~~~~~ -// IFileDevice members -// ~~~~~~~~~~~~~~~~~~~ - -IFileDevice::IFileDevice(const std::string& fileName) : IPcapDevice() -{ - m_FileName = fileName; -} - -IFileDevice::~IFileDevice() -{ - IFileDevice::close(); -} + } -std::string IFileDevice::getFileName() const -{ - return m_FileName; -} + // ~~~~~~~~~~~~~~~~~~~ + // IFileDevice members + // ~~~~~~~~~~~~~~~~~~~ -void IFileDevice::close() -{ - if (m_PcapDescriptor != nullptr) + IFileDevice::IFileDevice(const std::string& fileName) : IPcapDevice() { - pcap_close(m_PcapDescriptor); - PCPP_LOG_DEBUG("Successfully closed file reader device for filename '" << m_FileName << "'"); - m_PcapDescriptor = nullptr; + m_FileName = fileName; } - m_DeviceOpened = false; -} - - -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// IFileReaderDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~ - -IFileReaderDevice::IFileReaderDevice(const std::string& fileName) : IFileDevice(fileName) -{ - m_NumOfPacketsNotParsed = 0; - m_NumOfPacketsRead = 0; -} - -IFileReaderDevice* IFileReaderDevice::getReader(const std::string& fileName) -{ - const auto extensionPos = fileName.find_last_of('.'); - const auto fileExtension = extensionPos != std::string::npos ? fileName.substr(extensionPos) : ""; - - if (fileExtension == ".pcapng" || fileExtension == ".zstd" || fileExtension == ".zst") - return new PcapNgFileReaderDevice(fileName); - else if (fileExtension == ".snoop") - return new SnoopFileReaderDevice(fileName); - - return new PcapFileReaderDevice(fileName); -} - -uint64_t IFileReaderDevice::getFileSize() const -{ - std::ifstream fileStream(m_FileName.c_str(), std::ifstream::ate | std::ifstream::binary); - return fileStream.tellg(); -} + IFileDevice::~IFileDevice() + { + IFileDevice::close(); + } -int IFileReaderDevice::getNextPackets(RawPacketVector& packetVec, int numOfPacketsToRead) -{ - int numOfPacketsRead = 0; + std::string IFileDevice::getFileName() const + { + return m_FileName; + } - for (; numOfPacketsToRead < 0 || numOfPacketsRead < numOfPacketsToRead; numOfPacketsRead++) + void IFileDevice::close() { - RawPacket* newPacket = new RawPacket(); - bool packetRead = getNextPacket(*newPacket); - if (packetRead) + if (m_PcapDescriptor != nullptr) { - packetVec.pushBack(newPacket); - } - else - { - delete newPacket; - break; + pcap_close(m_PcapDescriptor); + PCPP_LOG_DEBUG("Successfully closed file reader device for filename '" << m_FileName << "'"); + m_PcapDescriptor = nullptr; } + + m_DeviceOpened = false; } - return numOfPacketsRead; -} + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + // IFileReaderDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~ -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// SnoopFileReaderDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + IFileReaderDevice::IFileReaderDevice(const std::string& fileName) : IFileDevice(fileName) + { + m_NumOfPacketsNotParsed = 0; + m_NumOfPacketsRead = 0; + } -SnoopFileReaderDevice::~SnoopFileReaderDevice() -{ - m_snoopFile.close(); -} + IFileReaderDevice* IFileReaderDevice::getReader(const std::string& fileName) + { + const auto extensionPos = fileName.find_last_of('.'); + const auto fileExtension = extensionPos != std::string::npos ? fileName.substr(extensionPos) : ""; -bool SnoopFileReaderDevice::open() -{ - m_NumOfPacketsRead = 0; - m_NumOfPacketsNotParsed = 0; + if (fileExtension == ".pcapng" || fileExtension == ".zstd" || fileExtension == ".zst") + return new PcapNgFileReaderDevice(fileName); + else if (fileExtension == ".snoop") + return new SnoopFileReaderDevice(fileName); - m_snoopFile.open(m_FileName.c_str(), std::ifstream::binary); - if (!m_snoopFile.is_open()) - { - PCPP_LOG_ERROR("Cannot open snoop reader device for filename '" << m_FileName << "'"); - m_snoopFile.close(); - return false; + return new PcapFileReaderDevice(fileName); } - snoop_file_header_t snoop_file_header; - m_snoopFile.read((char*)&snoop_file_header, sizeof(snoop_file_header_t)); - if (!m_snoopFile) + uint64_t IFileReaderDevice::getFileSize() const { - PCPP_LOG_ERROR("Cannot read snoop file header for '" << m_FileName << "'"); - m_snoopFile.close(); - return false; + std::ifstream fileStream(m_FileName.c_str(), std::ifstream::ate | std::ifstream::binary); + return fileStream.tellg(); } - if(be64toh(snoop_file_header.identification_pattern) != 0x736e6f6f70000000 && be32toh(snoop_file_header.version_number) == 2) - return false; - - // 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 */ - }; - uint32_t datalink_type = be32toh(snoop_file_header.datalink_type); - if (datalink_type > ARRAY_SIZE(snoop_encap) - 1) + int IFileReaderDevice::getNextPackets(RawPacketVector& packetVec, int numOfPacketsToRead) { - PCPP_LOG_ERROR("Cannot read data link type for '" << m_FileName << "'"); - m_snoopFile.close(); - return false; - } + int numOfPacketsRead = 0; - m_PcapLinkLayerType = snoop_encap[datalink_type]; + for (; numOfPacketsToRead < 0 || numOfPacketsRead < numOfPacketsToRead; numOfPacketsRead++) + { + RawPacket* newPacket = new RawPacket(); + bool packetRead = getNextPacket(*newPacket); + if (packetRead) + { + packetVec.pushBack(newPacket); + } + else + { + delete newPacket; + break; + } + } - PCPP_LOG_DEBUG("Successfully opened file reader device for filename '" << m_FileName << "'"); - m_DeviceOpened = true; - return true; -} + return numOfPacketsRead; + } -void SnoopFileReaderDevice::getStatistics(PcapStats& stats) const -{ - stats.packetsRecv = m_NumOfPacketsRead; - stats.packetsDrop = m_NumOfPacketsNotParsed; - stats.packetsDropByInterface = 0; - PCPP_LOG_DEBUG("Statistics received for reader device for filename '" << m_FileName << "'"); -} + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // SnoopFileReaderDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -bool SnoopFileReaderDevice::getNextPacket(RawPacket& rawPacket) -{ - rawPacket.clear(); - if (m_DeviceOpened != true) + SnoopFileReaderDevice::~SnoopFileReaderDevice() { - PCPP_LOG_ERROR("File device '" << m_FileName << "' not opened"); - return false; - } - snoop_packet_header_t snoop_packet_header; - m_snoopFile.read((char*)&snoop_packet_header, sizeof(snoop_packet_header_t)); - if(!m_snoopFile) { - return false; - } - size_t packetSize = be32toh(snoop_packet_header.included_length); - if(packetSize > 15000) { - return false; - } - std::unique_ptr packetData(new char[packetSize]); - m_snoopFile.read(packetData.get(), packetSize); - if(!m_snoopFile) { - return false; + m_snoopFile.close(); } - timespec ts = { static_cast(be32toh(snoop_packet_header.time_sec)), static_cast(be32toh(snoop_packet_header.time_usec)) * 1000 }; - if (!rawPacket.setRawData((const uint8_t*)packetData.release(), packetSize, ts, static_cast(m_PcapLinkLayerType))) + + bool SnoopFileReaderDevice::open() { - PCPP_LOG_ERROR("Couldn't set data to raw packet"); - return false; - } - size_t pad = be32toh(snoop_packet_header.packet_record_length) - (sizeof(snoop_packet_header_t) + be32toh(snoop_packet_header.included_length)); - m_snoopFile.ignore(pad); - if(!m_snoopFile) { - return false; - } + m_NumOfPacketsRead = 0; + m_NumOfPacketsNotParsed = 0; - m_NumOfPacketsRead++; - return true; -} + m_snoopFile.open(m_FileName.c_str(), std::ifstream::binary); + if (!m_snoopFile.is_open()) + { + PCPP_LOG_ERROR("Cannot open snoop reader device for filename '" << m_FileName << "'"); + m_snoopFile.close(); + return false; + } -void SnoopFileReaderDevice::close() -{ - m_snoopFile.close(); - m_DeviceOpened = false; - PCPP_LOG_DEBUG("File reader closed for file '" << m_FileName << "'"); -} + snoop_file_header_t snoop_file_header; + m_snoopFile.read((char*)&snoop_file_header, sizeof(snoop_file_header_t)); + if (!m_snoopFile) + { + PCPP_LOG_ERROR("Cannot read snoop file header for '" << m_FileName << "'"); + m_snoopFile.close(); + return false; + } + if (be64toh(snoop_file_header.identification_pattern) != 0x736e6f6f70000000 && + be32toh(snoop_file_header.version_number) == 2) + return false; -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// PcapFileReaderDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // 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 */ + }; + uint32_t datalink_type = be32toh(snoop_file_header.datalink_type); + if (datalink_type > ARRAY_SIZE(snoop_encap) - 1) + { + PCPP_LOG_ERROR("Cannot read data link type for '" << m_FileName << "'"); + m_snoopFile.close(); + return false; + } + m_PcapLinkLayerType = snoop_encap[datalink_type]; -bool PcapFileReaderDevice::open() -{ - m_NumOfPacketsRead = 0; - m_NumOfPacketsNotParsed = 0; + PCPP_LOG_DEBUG("Successfully opened file reader device for filename '" << m_FileName << "'"); + m_DeviceOpened = true; + return true; + } - if (m_PcapDescriptor != nullptr) + void SnoopFileReaderDevice::getStatistics(PcapStats& stats) const { - PCPP_LOG_DEBUG("Pcap descriptor already opened. Nothing to do"); - return true; + stats.packetsRecv = m_NumOfPacketsRead; + stats.packetsDrop = m_NumOfPacketsNotParsed; + stats.packetsDropByInterface = 0; + PCPP_LOG_DEBUG("Statistics received for reader device for filename '" << m_FileName << "'"); } - char errbuf[PCAP_ERRBUF_SIZE]; -#if defined(PCAP_TSTAMP_PRECISION_NANO) - m_PcapDescriptor = pcap_open_offline_with_tstamp_precision(m_FileName.c_str(), PCAP_TSTAMP_PRECISION_NANO, errbuf); -#else - m_PcapDescriptor = pcap_open_offline(m_FileName.c_str(), errbuf); -#endif - if (m_PcapDescriptor == nullptr) + bool SnoopFileReaderDevice::getNextPacket(RawPacket& rawPacket) { - PCPP_LOG_ERROR("Cannot open file reader device for filename '" << m_FileName << "': " << errbuf); - m_DeviceOpened = false; - return false; + rawPacket.clear(); + if (m_DeviceOpened != true) + { + PCPP_LOG_ERROR("File device '" << m_FileName << "' not opened"); + return false; + } + snoop_packet_header_t snoop_packet_header; + m_snoopFile.read((char*)&snoop_packet_header, sizeof(snoop_packet_header_t)); + if (!m_snoopFile) + { + return false; + } + size_t packetSize = be32toh(snoop_packet_header.included_length); + if (packetSize > 15000) + { + return false; + } + std::unique_ptr packetData(new char[packetSize]); + m_snoopFile.read(packetData.get(), packetSize); + if (!m_snoopFile) + { + return false; + } + timespec ts = { static_cast(be32toh(snoop_packet_header.time_sec)), + static_cast(be32toh(snoop_packet_header.time_usec)) * 1000 }; + if (!rawPacket.setRawData((const uint8_t*)packetData.release(), packetSize, ts, + static_cast(m_PcapLinkLayerType))) + { + PCPP_LOG_ERROR("Couldn't set data to raw packet"); + return false; + } + size_t pad = be32toh(snoop_packet_header.packet_record_length) - + (sizeof(snoop_packet_header_t) + be32toh(snoop_packet_header.included_length)); + m_snoopFile.ignore(pad); + if (!m_snoopFile) + { + return false; + } + + m_NumOfPacketsRead++; + return true; } - int linkLayer = pcap_datalink(m_PcapDescriptor); - if (!RawPacket::isLinkTypeValid(linkLayer)) + void SnoopFileReaderDevice::close() { - PCPP_LOG_ERROR("Invalid link layer (" << linkLayer << ") for reader device filename '" << m_FileName << "'"); - pcap_close(m_PcapDescriptor); - m_PcapDescriptor = nullptr; + m_snoopFile.close(); m_DeviceOpened = false; - return false; + PCPP_LOG_DEBUG("File reader closed for file '" << m_FileName << "'"); } - m_PcapLinkLayerType = static_cast(linkLayer); + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PcapFileReaderDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + bool PcapFileReaderDevice::open() + { + m_NumOfPacketsRead = 0; + m_NumOfPacketsNotParsed = 0; + + if (m_PcapDescriptor != nullptr) + { + PCPP_LOG_DEBUG("Pcap descriptor already opened. Nothing to do"); + return true; + } + + char errbuf[PCAP_ERRBUF_SIZE]; #if defined(PCAP_TSTAMP_PRECISION_NANO) - m_Precision = static_cast(pcap_get_tstamp_precision(m_PcapDescriptor)); - std::string precisionStr = (m_Precision == FileTimestampPrecision::Nanoseconds) ? "nanoseconds" : "microseconds"; + m_PcapDescriptor = + pcap_open_offline_with_tstamp_precision(m_FileName.c_str(), PCAP_TSTAMP_PRECISION_NANO, errbuf); #else - m_Precision = FileTimestampPrecision::Microseconds; - std::string precisionStr = "microseconds"; + m_PcapDescriptor = pcap_open_offline(m_FileName.c_str(), errbuf); #endif - PCPP_LOG_DEBUG("Successfully opened file reader device for filename '" << m_FileName << "' with precision " << precisionStr); - m_DeviceOpened = true; - return true; -} - -bool PcapFileReaderDevice::isNanoSecondPrecisionSupported() -{ - return checkNanoSupport(); -} + if (m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("Cannot open file reader device for filename '" << m_FileName << "': " << errbuf); + m_DeviceOpened = false; + return false; + } -void PcapFileReaderDevice::getStatistics(PcapStats& stats) const -{ - stats.packetsRecv = m_NumOfPacketsRead; - stats.packetsDrop = m_NumOfPacketsNotParsed; - stats.packetsDropByInterface = 0; - PCPP_LOG_DEBUG("Statistics received for reader device for filename '" << m_FileName << "'"); -} + int linkLayer = pcap_datalink(m_PcapDescriptor); + if (!RawPacket::isLinkTypeValid(linkLayer)) + { + PCPP_LOG_ERROR("Invalid link layer (" << linkLayer << ") for reader device filename '" << m_FileName + << "'"); + pcap_close(m_PcapDescriptor); + m_PcapDescriptor = nullptr; + m_DeviceOpened = false; + return false; + } -bool PcapFileReaderDevice::getNextPacket(RawPacket& rawPacket) -{ - rawPacket.clear(); - if (m_PcapDescriptor == nullptr) - { - PCPP_LOG_ERROR("File device '" << m_FileName << "' not opened"); - return false; - } - pcap_pkthdr pkthdr; - const uint8_t* pPacketData = pcap_next(m_PcapDescriptor, &pkthdr); - if (pPacketData == nullptr) - { - PCPP_LOG_DEBUG("Packet could not be read. Probably end-of-file"); - return false; - } + m_PcapLinkLayerType = static_cast(linkLayer); - uint8_t* pMyPacketData = new uint8_t[pkthdr.caplen]; - memcpy(pMyPacketData, pPacketData, pkthdr.caplen); #if defined(PCAP_TSTAMP_PRECISION_NANO) - timespec ts = { pkthdr.ts.tv_sec, static_cast(pkthdr.ts.tv_usec) }; //because we opened with nano second precision 'tv_usec' is actually nanos + m_Precision = static_cast(pcap_get_tstamp_precision(m_PcapDescriptor)); + std::string precisionStr = + (m_Precision == FileTimestampPrecision::Nanoseconds) ? "nanoseconds" : "microseconds"; #else - struct timeval ts = pkthdr.ts; + m_Precision = FileTimestampPrecision::Microseconds; + std::string precisionStr = "microseconds"; #endif - if (!rawPacket.setRawData(pMyPacketData, pkthdr.caplen, ts, static_cast(m_PcapLinkLayerType), pkthdr.len)) - { - PCPP_LOG_ERROR("Couldn't set data to raw packet"); - return false; + PCPP_LOG_DEBUG("Successfully opened file reader device for filename '" << m_FileName << "' with precision " + << precisionStr); + m_DeviceOpened = true; + return true; } - m_NumOfPacketsRead++; - return true; -} - -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// PcapNgFileReaderDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -PcapNgFileReaderDevice::PcapNgFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName) -{ - m_LightPcapNg = nullptr; -} - -bool PcapNgFileReaderDevice::open() -{ - m_NumOfPacketsRead = 0; - m_NumOfPacketsNotParsed = 0; - - if (m_LightPcapNg != nullptr) + bool PcapFileReaderDevice::isNanoSecondPrecisionSupported() { - PCPP_LOG_DEBUG("pcapng descriptor already opened. Nothing to do"); - return true; + return checkNanoSupport(); } - m_LightPcapNg = light_pcapng_open_read(m_FileName.c_str(), LIGHT_FALSE); - if (m_LightPcapNg == nullptr) + void PcapFileReaderDevice::getStatistics(PcapStats& stats) const { - PCPP_LOG_ERROR("Cannot open pcapng reader device for filename '" << m_FileName << "'"); - m_DeviceOpened = false; - return false; + stats.packetsRecv = m_NumOfPacketsRead; + stats.packetsDrop = m_NumOfPacketsNotParsed; + stats.packetsDropByInterface = 0; + PCPP_LOG_DEBUG("Statistics received for reader device for filename '" << m_FileName << "'"); } - PCPP_LOG_DEBUG("Successfully opened pcapng reader device for filename '" << m_FileName << "'"); - m_DeviceOpened = true; - return true; -} - -bool PcapNgFileReaderDevice::getNextPacket(RawPacket& rawPacket, std::string& packetComment) -{ - rawPacket.clear(); - packetComment = ""; - - if (m_LightPcapNg == nullptr) + bool PcapFileReaderDevice::getNextPacket(RawPacket& rawPacket) { - PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); - return false; + rawPacket.clear(); + if (m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("File device '" << m_FileName << "' not opened"); + return false; + } + pcap_pkthdr pkthdr; + const uint8_t* pPacketData = pcap_next(m_PcapDescriptor, &pkthdr); + if (pPacketData == nullptr) + { + PCPP_LOG_DEBUG("Packet could not be read. Probably end-of-file"); + return false; + } + + uint8_t* pMyPacketData = new uint8_t[pkthdr.caplen]; + memcpy(pMyPacketData, pPacketData, pkthdr.caplen); +#if defined(PCAP_TSTAMP_PRECISION_NANO) + // because we opened with nano second precision 'tv_usec' is actually nanos + timespec ts = { pkthdr.ts.tv_sec, static_cast(pkthdr.ts.tv_usec) }; +#else + struct timeval ts = pkthdr.ts; +#endif + if (!rawPacket.setRawData(pMyPacketData, pkthdr.caplen, ts, static_cast(m_PcapLinkLayerType), + pkthdr.len)) + { + PCPP_LOG_ERROR("Couldn't set data to raw packet"); + return false; + } + m_NumOfPacketsRead++; + return true; } - light_packet_header pktHeader; - const uint8_t* pktData = nullptr; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PcapNgFileReaderDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - if (!light_get_next_packet((light_pcapng_t*)m_LightPcapNg, &pktHeader, &pktData)) + PcapNgFileReaderDevice::PcapNgFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName) { - PCPP_LOG_DEBUG("Packet could not be read. Probably end-of-file"); - return false; + m_LightPcapNg = nullptr; } - while (!m_BpfWrapper.matchPacketWithFilter(pktData, pktHeader.captured_length, pktHeader.timestamp, pktHeader.data_link)) + bool PcapNgFileReaderDevice::open() { - if (!light_get_next_packet((light_pcapng_t*)m_LightPcapNg, &pktHeader, &pktData)) + m_NumOfPacketsRead = 0; + m_NumOfPacketsNotParsed = 0; + + if (m_LightPcapNg != nullptr) { - PCPP_LOG_DEBUG("Packet could not be read. Probably end-of-file"); + PCPP_LOG_DEBUG("pcapng descriptor already opened. Nothing to do"); + return true; + } + + m_LightPcapNg = light_pcapng_open_read(m_FileName.c_str(), LIGHT_FALSE); + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Cannot open pcapng reader device for filename '" << m_FileName << "'"); + m_DeviceOpened = false; return false; } - } - uint8_t* myPacketData = new uint8_t[pktHeader.captured_length]; - memcpy(myPacketData, pktData, pktHeader.captured_length); - const LinkLayerType linkType = static_cast(pktHeader.data_link); - if (linkType == LinkLayerType::LINKTYPE_INVALID) - { - PCPP_LOG_ERROR("Link layer type of raw packet could not be determined"); + PCPP_LOG_DEBUG("Successfully opened pcapng reader device for filename '" << m_FileName << "'"); + m_DeviceOpened = true; + return true; } - if (!rawPacket.setRawData(myPacketData, pktHeader.captured_length, pktHeader.timestamp, linkType, pktHeader.original_length)) + bool PcapNgFileReaderDevice::getNextPacket(RawPacket& rawPacket, std::string& packetComment) { - PCPP_LOG_ERROR("Couldn't set data to raw packet"); - return false; - } - - if (pktHeader.comment != nullptr && pktHeader.comment_length > 0) - packetComment = std::string(pktHeader.comment, pktHeader.comment_length); + rawPacket.clear(); + packetComment = ""; - m_NumOfPacketsRead++; - return true; -} + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); + return false; + } -bool PcapNgFileReaderDevice::getNextPacket(RawPacket& rawPacket) -{ - std::string temp; - return getNextPacket(rawPacket, temp); -} + light_packet_header pktHeader; + const uint8_t* pktData = nullptr; -void PcapNgFileReaderDevice::getStatistics(PcapStats& stats) const -{ - stats.packetsRecv = m_NumOfPacketsRead; - stats.packetsDrop = m_NumOfPacketsNotParsed; - stats.packetsDropByInterface = 0; - PCPP_LOG_DEBUG("Statistics received for pcapng reader device for filename '" << m_FileName << "'"); -} + if (!light_get_next_packet((light_pcapng_t*)m_LightPcapNg, &pktHeader, &pktData)) + { + PCPP_LOG_DEBUG("Packet could not be read. Probably end-of-file"); + return false; + } -bool PcapNgFileReaderDevice::setFilter(std::string filterAsString) -{ - return m_BpfWrapper.setFilter(filterAsString); -} + while (!m_BpfWrapper.matchPacketWithFilter(pktData, pktHeader.captured_length, pktHeader.timestamp, + pktHeader.data_link)) + { + if (!light_get_next_packet((light_pcapng_t*)m_LightPcapNg, &pktHeader, &pktData)) + { + PCPP_LOG_DEBUG("Packet could not be read. Probably end-of-file"); + return false; + } + } -void PcapNgFileReaderDevice::close() -{ - if (m_LightPcapNg == nullptr) - return; + uint8_t* myPacketData = new uint8_t[pktHeader.captured_length]; + memcpy(myPacketData, pktData, pktHeader.captured_length); + const LinkLayerType linkType = static_cast(pktHeader.data_link); + if (linkType == LinkLayerType::LINKTYPE_INVALID) + { + PCPP_LOG_ERROR("Link layer type of raw packet could not be determined"); + } - light_pcapng_close((light_pcapng_t*)m_LightPcapNg); - m_LightPcapNg = nullptr; + if (!rawPacket.setRawData(myPacketData, pktHeader.captured_length, pktHeader.timestamp, linkType, + pktHeader.original_length)) + { + PCPP_LOG_ERROR("Couldn't set data to raw packet"); + return false; + } - m_DeviceOpened = false; - PCPP_LOG_DEBUG("File reader closed for file '" << m_FileName << "'"); -} + if (pktHeader.comment != nullptr && pktHeader.comment_length > 0) + packetComment = std::string(pktHeader.comment, pktHeader.comment_length); + m_NumOfPacketsRead++; + return true; + } -std::string PcapNgFileReaderDevice::getOS() const -{ - if (m_LightPcapNg == nullptr) + bool PcapNgFileReaderDevice::getNextPacket(RawPacket& rawPacket) { - PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); - return ""; + std::string temp; + return getNextPacket(rawPacket, temp); } - light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); - if (fileInfo == nullptr) - return ""; - char* res = fileInfo->os_desc; - size_t len = fileInfo->os_desc_size; - if (len == 0 || res == nullptr) - return ""; - - return std::string(res, len); -} + void PcapNgFileReaderDevice::getStatistics(PcapStats& stats) const + { + stats.packetsRecv = m_NumOfPacketsRead; + stats.packetsDrop = m_NumOfPacketsNotParsed; + stats.packetsDropByInterface = 0; + PCPP_LOG_DEBUG("Statistics received for pcapng reader device for filename '" << m_FileName << "'"); + } -std::string PcapNgFileReaderDevice::getHardware() const -{ - if (m_LightPcapNg == nullptr) + bool PcapNgFileReaderDevice::setFilter(std::string filterAsString) { - PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); - return ""; + return m_BpfWrapper.setFilter(filterAsString); } - light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); - if (fileInfo == nullptr) - return ""; - char* res = fileInfo->hardware_desc; - size_t len = fileInfo->hardware_desc_size; - if (len == 0 || res == nullptr) - return ""; + void PcapNgFileReaderDevice::close() + { + if (m_LightPcapNg == nullptr) + return; - return std::string(res, len); -} + light_pcapng_close((light_pcapng_t*)m_LightPcapNg); + m_LightPcapNg = nullptr; -std::string PcapNgFileReaderDevice::getCaptureApplication() const -{ - if (m_LightPcapNg == nullptr) - { - PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); - return ""; + m_DeviceOpened = false; + PCPP_LOG_DEBUG("File reader closed for file '" << m_FileName << "'"); } - light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); - if (fileInfo == nullptr) - return ""; - char* res = fileInfo->user_app_desc; - size_t len = fileInfo->user_app_desc_size; - if (len == 0 || res == nullptr) - return ""; + std::string PcapNgFileReaderDevice::getOS() const + { + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); + return ""; + } + + light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); + if (fileInfo == nullptr) + return ""; + char* res = fileInfo->os_desc; + size_t len = fileInfo->os_desc_size; + if (len == 0 || res == nullptr) + return ""; - return std::string(res, len); -} + return std::string(res, len); + } -std::string PcapNgFileReaderDevice::getCaptureFileComment() const -{ - if (m_LightPcapNg == nullptr) + std::string PcapNgFileReaderDevice::getHardware() const { - PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); - return ""; + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); + return ""; + } + + light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); + if (fileInfo == nullptr) + return ""; + char* res = fileInfo->hardware_desc; + size_t len = fileInfo->hardware_desc_size; + if (len == 0 || res == nullptr) + return ""; + + return std::string(res, len); } - light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); - if (fileInfo == nullptr) - return ""; - char* res = fileInfo->file_comment; - size_t len = fileInfo->file_comment_size; - if (len == 0 || res == nullptr) - return ""; + std::string PcapNgFileReaderDevice::getCaptureApplication() const + { + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); + return ""; + } - return std::string(res, len); -} + light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); + if (fileInfo == nullptr) + return ""; + char* res = fileInfo->user_app_desc; + size_t len = fileInfo->user_app_desc_size; + if (len == 0 || res == nullptr) + return ""; + return std::string(res, len); + } -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// IFileWriterDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~ + std::string PcapNgFileReaderDevice::getCaptureFileComment() const + { + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened"); + return ""; + } -IFileWriterDevice:: IFileWriterDevice(const std::string& fileName) : IFileDevice(fileName) -{ - m_NumOfPacketsNotWritten = 0; - m_NumOfPacketsWritten = 0; -} + light_pcapng_file_info* fileInfo = light_pcang_get_file_info((light_pcapng_t*)m_LightPcapNg); + if (fileInfo == nullptr) + return ""; + char* res = fileInfo->file_comment; + size_t len = fileInfo->file_comment_size; + if (len == 0 || res == nullptr) + return ""; + return std::string(res, len); + } -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// PcapFileWriterDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // ~~~~~~~~~~~~~~~~~~~~~~~~~ + // IFileWriterDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~ -PcapFileWriterDevice::PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType, bool nanosecondsPrecision) : IFileWriterDevice(fileName) -{ - m_PcapDumpHandler = nullptr; - m_NumOfPacketsNotWritten = 0; - m_NumOfPacketsWritten = 0; - m_PcapLinkLayerType = linkLayerType; - m_AppendMode = false; -#if defined(PCAP_TSTAMP_PRECISION_NANO) - m_Precision = nanosecondsPrecision ? FileTimestampPrecision::Nanoseconds : FileTimestampPrecision::Microseconds; -#else - if (nanosecondsPrecision) + IFileWriterDevice::IFileWriterDevice(const std::string& fileName) : IFileDevice(fileName) { - PCPP_LOG_ERROR( - "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " - "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); + m_NumOfPacketsNotWritten = 0; + m_NumOfPacketsWritten = 0; } - m_Precision = FileTimestampPrecision::Microseconds; -#endif - m_File = nullptr; -} -void PcapFileWriterDevice::closeFile() -{ - if (m_AppendMode && m_File != nullptr) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PcapFileWriterDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + PcapFileWriterDevice::PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType, + bool nanosecondsPrecision) + : IFileWriterDevice(fileName) { - fclose(m_File); + m_PcapDumpHandler = nullptr; + m_NumOfPacketsNotWritten = 0; + m_NumOfPacketsWritten = 0; + m_PcapLinkLayerType = linkLayerType; + m_AppendMode = false; +#if defined(PCAP_TSTAMP_PRECISION_NANO) + m_Precision = nanosecondsPrecision ? FileTimestampPrecision::Nanoseconds : FileTimestampPrecision::Microseconds; +#else + if (nanosecondsPrecision) + { + PCPP_LOG_ERROR( + "PcapPlusPlus was compiled without nano precision support which requires libpcap > 1.5.1. Please " + "recompile PcapPlusPlus with nano precision support to use this feature. Using default microsecond precision"); + } + m_Precision = FileTimestampPrecision::Microseconds; +#endif m_File = nullptr; } -} -bool PcapFileWriterDevice::writePacket(RawPacket const& packet) -{ - if ((!m_AppendMode && m_PcapDescriptor == nullptr) || (m_PcapDumpHandler == nullptr)) + void PcapFileWriterDevice::closeFile() { - PCPP_LOG_ERROR("Device not opened"); - m_NumOfPacketsNotWritten++; - return false; + if (m_AppendMode && m_File != nullptr) + { + fclose(m_File); + m_File = nullptr; + } } - if (packet.getLinkLayerType() != m_PcapLinkLayerType) + bool PcapFileWriterDevice::writePacket(RawPacket const& packet) { - PCPP_LOG_ERROR("Cannot write a packet with a different link layer type"); - m_NumOfPacketsNotWritten++; - return false; - } + if ((!m_AppendMode && m_PcapDescriptor == nullptr) || (m_PcapDumpHandler == nullptr)) + { + PCPP_LOG_ERROR("Device not opened"); + m_NumOfPacketsNotWritten++; + return false; + } + + if (packet.getLinkLayerType() != m_PcapLinkLayerType) + { + PCPP_LOG_ERROR("Cannot write a packet with a different link layer type"); + m_NumOfPacketsNotWritten++; + return false; + } - pcap_pkthdr pktHdr; - pktHdr.caplen = ((RawPacket&)packet).getRawDataLen(); - pktHdr.len = ((RawPacket&)packet).getFrameLength(); - timespec packet_timestamp = ((RawPacket&)packet).getPacketTimeStamp(); + pcap_pkthdr pktHdr; + pktHdr.caplen = ((RawPacket&)packet).getRawDataLen(); + pktHdr.len = ((RawPacket&)packet).getFrameLength(); + timespec packet_timestamp = ((RawPacket&)packet).getPacketTimeStamp(); #if defined(PCAP_TSTAMP_PRECISION_NANO) - if (m_Precision != FileTimestampPrecision::Nanoseconds) - { - TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packet_timestamp); - } - else - { - pktHdr.ts.tv_sec = packet_timestamp.tv_sec; - pktHdr.ts.tv_usec = packet_timestamp.tv_nsec; - } + if (m_Precision != FileTimestampPrecision::Nanoseconds) + { + TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packet_timestamp); + } + else + { + pktHdr.ts.tv_sec = packet_timestamp.tv_sec; + pktHdr.ts.tv_usec = packet_timestamp.tv_nsec; + } #else - TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packet_timestamp); + TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packet_timestamp); #endif - if (!m_AppendMode) - pcap_dump((uint8_t*)m_PcapDumpHandler, &pktHdr, ((RawPacket&)packet).getRawData()); - else - { - // Below are actually the lines run by pcap_dump. The reason I had to put them instead pcap_dump is that on Windows using WinPcap/Npcap - // you can't pass pointers between libraries compiled with different compilers. In this case - PcapPlusPlus and WinPcap/Npcap weren't - // compiled with the same compiler so it's impossible to fopen a file in PcapPlusPlus, pass the pointer to WinPcap/Npcap and use the - // FILE* pointer there. Doing this throws an exception. So the only option when implementing append to pcap is to write all relevant - // WinPcap/Npcap code that handles opening/closing/writing to pcap files inside PcapPlusPlus code - - // the reason to create this packet_header struct is timeval has different sizes in 32-bit and 64-bit systems, - // but pcap format uses the 32-bit timeval version, so we need to align timeval to that - packet_header pktHdrTemp; - pktHdrTemp.tv_sec = pktHdr.ts.tv_sec; - pktHdrTemp.tv_usec = pktHdr.ts.tv_usec; - pktHdrTemp.caplen = pktHdr.caplen; - pktHdrTemp.len = pktHdr.len; - fwrite(&pktHdrTemp, sizeof(pktHdrTemp), 1, m_File); - fwrite(((RawPacket&)packet).getRawData(), pktHdrTemp.caplen, 1, m_File); - } - PCPP_LOG_DEBUG("Packet written successfully to '" << m_FileName << "'"); - m_NumOfPacketsWritten++; - return true; -} - -bool PcapFileWriterDevice::writePackets(const RawPacketVector& packets) -{ - for (RawPacketVector::ConstVectorIterator iter = packets.begin(); iter != packets.end(); iter++) - { - if (!writePacket(**iter)) - return false; + if (!m_AppendMode) + pcap_dump((uint8_t*)m_PcapDumpHandler, &pktHdr, ((RawPacket&)packet).getRawData()); + else + { + // Below are actually the lines run by pcap_dump. The reason I had to put them instead pcap_dump is that on + // Windows using WinPcap/Npcap you can't pass pointers between libraries compiled with different compilers. + // In this case - PcapPlusPlus and WinPcap/Npcap weren't compiled with the same compiler so it's impossible + // to fopen a file in PcapPlusPlus, pass the pointer to WinPcap/Npcap and use the FILE* pointer there. Doing + // this throws an exception. So the only option when implementing append to pcap is to write all relevant + // WinPcap/Npcap code that handles opening/closing/writing to pcap files inside PcapPlusPlus code + + // the reason to create this packet_header struct is timeval has different sizes in 32-bit and 64-bit + // systems, but pcap format uses the 32-bit timeval version, so we need to align timeval to that + packet_header pktHdrTemp; + pktHdrTemp.tv_sec = pktHdr.ts.tv_sec; + pktHdrTemp.tv_usec = pktHdr.ts.tv_usec; + pktHdrTemp.caplen = pktHdr.caplen; + pktHdrTemp.len = pktHdr.len; + fwrite(&pktHdrTemp, sizeof(pktHdrTemp), 1, m_File); + fwrite(((RawPacket&)packet).getRawData(), pktHdrTemp.caplen, 1, m_File); + } + PCPP_LOG_DEBUG("Packet written successfully to '" << m_FileName << "'"); + m_NumOfPacketsWritten++; + return true; } - return true; -} + bool PcapFileWriterDevice::writePackets(const RawPacketVector& packets) + { + for (RawPacketVector::ConstVectorIterator iter = packets.begin(); iter != packets.end(); iter++) + { + if (!writePacket(**iter)) + return false; + } -bool PcapFileWriterDevice::isNanoSecondPrecisionSupported() -{ - return checkNanoSupport(); -} + return true; + } -bool PcapFileWriterDevice::open() -{ - if (m_PcapDescriptor != nullptr) + bool PcapFileWriterDevice::isNanoSecondPrecisionSupported() { - PCPP_LOG_DEBUG("Pcap descriptor already opened. Nothing to do"); - return true; + return checkNanoSupport(); } - switch(m_PcapLinkLayerType) + bool PcapFileWriterDevice::open() { + if (m_PcapDescriptor != nullptr) + { + PCPP_LOG_DEBUG("Pcap descriptor already opened. Nothing to do"); + return true; + } + + switch (m_PcapLinkLayerType) + { case LINKTYPE_RAW: case LINKTYPE_DLT_RAW2: - PCPP_LOG_ERROR("The only Raw IP link type supported in libpcap/WinPcap/Npcap is LINKTYPE_DLT_RAW1, please use that instead"); + PCPP_LOG_ERROR( + "The only Raw IP link type supported in libpcap/WinPcap/Npcap is LINKTYPE_DLT_RAW1, please use that instead"); return false; default: break; - } + } - m_NumOfPacketsNotWritten = 0; - m_NumOfPacketsWritten = 0; + m_NumOfPacketsNotWritten = 0; + m_NumOfPacketsWritten = 0; #if defined(PCAP_TSTAMP_PRECISION_NANO) - m_PcapDescriptor = pcap_open_dead_with_tstamp_precision(m_PcapLinkLayerType, PCPP_MAX_PACKET_SIZE, static_cast(m_Precision)); + m_PcapDescriptor = pcap_open_dead_with_tstamp_precision(m_PcapLinkLayerType, PCPP_MAX_PACKET_SIZE, + static_cast(m_Precision)); #else - m_PcapDescriptor = pcap_open_dead(m_PcapLinkLayerType, PCPP_MAX_PACKET_SIZE); + m_PcapDescriptor = pcap_open_dead(m_PcapLinkLayerType, PCPP_MAX_PACKET_SIZE); #endif - if (m_PcapDescriptor == nullptr) - { - PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName << "': pcap_open_dead returned NULL"); - m_DeviceOpened = false; - return false; - } + if (m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName + << "': pcap_open_dead returned NULL"); + m_DeviceOpened = false; + return false; + } + m_PcapDumpHandler = pcap_dump_open(m_PcapDescriptor, m_FileName.c_str()); + if (m_PcapDumpHandler == nullptr) + { + PCPP_LOG_ERROR("Error opening file writer device for file '" + << m_FileName << "': pcap_dump_open returned NULL with error: '" + << pcap_geterr(m_PcapDescriptor) << "'"); + m_DeviceOpened = false; + return false; + } - m_PcapDumpHandler = pcap_dump_open(m_PcapDescriptor, m_FileName.c_str()); - if (m_PcapDumpHandler == nullptr) - { - PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName << "': pcap_dump_open returned NULL with error: '" << pcap_geterr(m_PcapDescriptor) << "'"); - m_DeviceOpened = false; - return false; + m_DeviceOpened = true; + PCPP_LOG_DEBUG("File writer device for file '" << m_FileName << "' opened successfully"); + return true; } - m_DeviceOpened = true; - PCPP_LOG_DEBUG("File writer device for file '" << m_FileName << "' opened successfully"); - return true; -} - -void PcapFileWriterDevice::flush() -{ - if (!m_DeviceOpened) - return; - - if (!m_AppendMode && pcap_dump_flush(m_PcapDumpHandler) == -1) - { - PCPP_LOG_ERROR("Error while flushing the packets to file"); - } - // in append mode it's impossible to use pcap_dump_flush, see comment above pcap_dump - else if (m_AppendMode && fflush(m_File) == EOF) + void PcapFileWriterDevice::flush() { - PCPP_LOG_ERROR("Error while flushing the packets to file"); + if (!m_DeviceOpened) + return; + + if (!m_AppendMode && pcap_dump_flush(m_PcapDumpHandler) == -1) + { + PCPP_LOG_ERROR("Error while flushing the packets to file"); + } + // in append mode it's impossible to use pcap_dump_flush, see comment above pcap_dump + else if (m_AppendMode && fflush(m_File) == EOF) + { + PCPP_LOG_ERROR("Error while flushing the packets to file"); + } } -} + void PcapFileWriterDevice::close() + { + if (!m_DeviceOpened) + return; -void PcapFileWriterDevice::close() -{ - if (!m_DeviceOpened) - return; + flush(); - flush(); + IFileDevice::close(); - IFileDevice::close(); + if (!m_AppendMode && m_PcapDumpHandler != nullptr) + { + pcap_dump_close(m_PcapDumpHandler); + } + else if (m_AppendMode && m_File != nullptr) + { + // in append mode it's impossible to use pcap_dump_close, see comment above pcap_dump + fclose(m_File); + } - if (!m_AppendMode && m_PcapDumpHandler != nullptr) - { - pcap_dump_close(m_PcapDumpHandler); + m_PcapDumpHandler = nullptr; + m_File = nullptr; + PCPP_LOG_DEBUG("File writer closed for file '" << m_FileName << "'"); } - else if (m_AppendMode && m_File != nullptr) + + void PcapFileWriterDevice::getStatistics(PcapStats& stats) const { - // in append mode it's impossible to use pcap_dump_close, see comment above pcap_dump - fclose(m_File); + stats.packetsRecv = m_NumOfPacketsWritten; + stats.packetsDrop = m_NumOfPacketsNotWritten; + stats.packetsDropByInterface = 0; + PCPP_LOG_DEBUG("Statistics received for writer device for filename '" << m_FileName << "'"); } - m_PcapDumpHandler = nullptr; - m_File = nullptr; - PCPP_LOG_DEBUG("File writer closed for file '" << m_FileName << "'"); -} - -void PcapFileWriterDevice::getStatistics(PcapStats& stats) const -{ - stats.packetsRecv = m_NumOfPacketsWritten; - stats.packetsDrop = m_NumOfPacketsNotWritten; - stats.packetsDropByInterface = 0; - PCPP_LOG_DEBUG("Statistics received for writer device for filename '" << m_FileName << "'"); -} - -bool PcapFileWriterDevice::open(bool appendMode) -{ - if (!appendMode) - return open(); + bool PcapFileWriterDevice::open(bool appendMode) + { + if (!appendMode) + return open(); - m_AppendMode = appendMode; + m_AppendMode = appendMode; #if !defined(_WIN32) - m_File = fopen(m_FileName.c_str(), "r+"); + m_File = fopen(m_FileName.c_str(), "r+"); #else - m_File = fopen(m_FileName.c_str(), "rb+"); + m_File = fopen(m_FileName.c_str(), "rb+"); #endif - if (m_File == nullptr) - { - PCPP_LOG_ERROR("Cannot open '" << m_FileName << "' for reading and writing"); - return false; - } + if (m_File == nullptr) + { + PCPP_LOG_ERROR("Cannot open '" << m_FileName << "' for reading and writing"); + return false; + } - pcap_file_header pcapFileHeader; - int amountRead = fread(&pcapFileHeader, 1, sizeof(pcapFileHeader), m_File); - if (amountRead != sizeof(pcap_file_header)) - { - if (ferror(m_File)) - PCPP_LOG_ERROR("Cannot read pcap header from file '" << m_FileName << "', error was: " << errno); - else - PCPP_LOG_ERROR("Cannot read pcap header from file '" << m_FileName << "', unknown error"); + pcap_file_header pcapFileHeader; + int amountRead = fread(&pcapFileHeader, 1, sizeof(pcapFileHeader), m_File); + if (amountRead != sizeof(pcap_file_header)) + { + if (ferror(m_File)) + PCPP_LOG_ERROR("Cannot read pcap header from file '" << m_FileName << "', error was: " << errno); + else + PCPP_LOG_ERROR("Cannot read pcap header from file '" << m_FileName << "', unknown error"); - closeFile(); - return false; + closeFile(); + return false; + } + + LinkLayerType linkLayerType = static_cast(pcapFileHeader.linktype); + if (linkLayerType != m_PcapLinkLayerType) + { + PCPP_LOG_ERROR( + "Pcap file has a different link layer type than the one chosen in PcapFileWriterDevice c'tor, " + << linkLayerType << ", " << m_PcapLinkLayerType); + closeFile(); + return false; + } + + if (fseek(m_File, 0, SEEK_END) == -1) + { + PCPP_LOG_ERROR("Cannot read pcap file '" << m_FileName << "' to it's end, error was: " << errno); + closeFile(); + return false; + } + + m_PcapDumpHandler = ((pcap_dumper_t*)m_File); + + m_DeviceOpened = true; + PCPP_LOG_DEBUG("File writer device for file '" << m_FileName << "' opened successfully in append mode"); + return true; } - LinkLayerType linkLayerType = static_cast(pcapFileHeader.linktype); - if (linkLayerType != m_PcapLinkLayerType) + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PcapNgFileWriterDevice members + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + PcapNgFileWriterDevice::PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel) + : IFileWriterDevice(fileName) { - PCPP_LOG_ERROR("Pcap file has a different link layer type than the one chosen in PcapFileWriterDevice c'tor, " << linkLayerType << ", " << m_PcapLinkLayerType); - closeFile(); - return false; + m_LightPcapNg = nullptr; + m_CompressionLevel = compressionLevel; } - if (fseek(m_File, 0, SEEK_END) == -1) + bool PcapNgFileWriterDevice::open(const std::string& os, const std::string& hardware, const std::string& captureApp, + const std::string& fileComment) { - PCPP_LOG_ERROR("Cannot read pcap file '" << m_FileName << "' to it's end, error was: " << errno); - closeFile(); - return false; - } + if (m_LightPcapNg != nullptr) + { + PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do"); + return true; + } - m_PcapDumpHandler = ((pcap_dumper_t *)m_File); + m_NumOfPacketsNotWritten = 0; + m_NumOfPacketsWritten = 0; - m_DeviceOpened = true; - PCPP_LOG_DEBUG("File writer device for file '" << m_FileName << "' opened successfully in append mode"); - return true; -} + light_pcapng_file_info* info = + light_create_file_info(os.c_str(), hardware.c_str(), captureApp.c_str(), fileComment.c_str()); + m_LightPcapNg = light_pcapng_open_write(m_FileName.c_str(), info, m_CompressionLevel); + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName + << "': light_pcapng_open_write returned NULL"); -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// PcapNgFileWriterDevice members -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + light_free_file_info(info); -PcapNgFileWriterDevice::PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel) : IFileWriterDevice(fileName) -{ - m_LightPcapNg = nullptr; - m_CompressionLevel = compressionLevel; -} + m_DeviceOpened = false; + return false; + } -bool PcapNgFileWriterDevice::open(const std::string& os, const std::string& hardware, const std::string& captureApp, const std::string& fileComment) -{ - if (m_LightPcapNg != nullptr) - { - PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do"); + m_DeviceOpened = true; + PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully"); return true; } - m_NumOfPacketsNotWritten = 0; - m_NumOfPacketsWritten = 0; - - light_pcapng_file_info* info = light_create_file_info(os.c_str(), hardware.c_str(), captureApp.c_str(), fileComment.c_str()); - - m_LightPcapNg = light_pcapng_open_write(m_FileName.c_str(), info, m_CompressionLevel); - if (m_LightPcapNg == nullptr) + bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet, const std::string& comment) { - PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName << "': light_pcapng_open_write returned NULL"); + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Device not opened"); + m_NumOfPacketsNotWritten++; + return false; + } - light_free_file_info(info); + if (!m_BpfWrapper.matchPacketWithFilter(&packet)) + { + return false; + } - m_DeviceOpened = false; - return false; - } + light_packet_header pktHeader; + pktHeader.captured_length = ((RawPacket&)packet).getRawDataLen(); + pktHeader.original_length = ((RawPacket&)packet).getFrameLength(); + pktHeader.timestamp = ((RawPacket&)packet).getPacketTimeStamp(); + pktHeader.data_link = (uint16_t)packet.getLinkLayerType(); + pktHeader.interface_id = 0; + if (!comment.empty()) + { + pktHeader.comment = (char*)comment.c_str(); + pktHeader.comment_length = static_cast(comment.size()); + } + else + { + pktHeader.comment = nullptr; + pktHeader.comment_length = 0; + } - m_DeviceOpened = true; - PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully"); - return true; -} + const uint8_t* pktData = ((RawPacket&)packet).getRawData(); -bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet, const std::string& comment) -{ - if (m_LightPcapNg == nullptr) - { - PCPP_LOG_ERROR("Device not opened"); - m_NumOfPacketsNotWritten++; - return false; + light_write_packet((light_pcapng_t*)m_LightPcapNg, &pktHeader, pktData); + m_NumOfPacketsWritten++; + return true; } - if (!m_BpfWrapper.matchPacketWithFilter(&packet)) + bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet) { - return false; + return writePacket(packet, std::string()); } - light_packet_header pktHeader; - pktHeader.captured_length = ((RawPacket&)packet).getRawDataLen(); - pktHeader.original_length = ((RawPacket&)packet).getFrameLength(); - pktHeader.timestamp = ((RawPacket&)packet).getPacketTimeStamp(); - pktHeader.data_link = (uint16_t)packet.getLinkLayerType(); - pktHeader.interface_id = 0; - if (!comment.empty()) + bool PcapNgFileWriterDevice::writePackets(const RawPacketVector& packets) { - pktHeader.comment = (char*)comment.c_str(); - pktHeader.comment_length = static_cast(comment.size()); + for (RawPacketVector::ConstVectorIterator iter = packets.begin(); iter != packets.end(); iter++) + { + if (!writePacket(**iter)) + return false; + } + + return true; } - else + + bool PcapNgFileWriterDevice::open() { - pktHeader.comment = nullptr; - pktHeader.comment_length = 0; - } + if (m_LightPcapNg != nullptr) + { + PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do"); + return true; + } - const uint8_t* pktData = ((RawPacket&)packet).getRawData(); + m_NumOfPacketsNotWritten = 0; + m_NumOfPacketsWritten = 0; - light_write_packet((light_pcapng_t*)m_LightPcapNg, &pktHeader, pktData); - m_NumOfPacketsWritten++; - return true; -} + light_pcapng_file_info* info = light_create_default_file_info(); -bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet) -{ - return writePacket(packet, std::string()); -} + m_LightPcapNg = light_pcapng_open_write(m_FileName.c_str(), info, m_CompressionLevel); + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName + << "': light_pcapng_open_write returned NULL"); -bool PcapNgFileWriterDevice::writePackets(const RawPacketVector& packets) -{ - for (RawPacketVector::ConstVectorIterator iter = packets.begin(); iter != packets.end(); iter++) - { - if (!writePacket(**iter)) + light_free_file_info(info); + + m_DeviceOpened = false; return false; - } + } - return true; -} + m_DeviceOpened = true; + PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully"); + return true; + } -bool PcapNgFileWriterDevice::open() -{ - if (m_LightPcapNg != nullptr) + bool PcapNgFileWriterDevice::open(bool appendMode) { - PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do"); + if (!appendMode) + return open(); + + m_NumOfPacketsNotWritten = 0; + m_NumOfPacketsWritten = 0; + + m_LightPcapNg = light_pcapng_open_append(m_FileName.c_str()); + if (m_LightPcapNg == nullptr) + { + PCPP_LOG_ERROR("Error opening file writer device in append mode for file '" + << m_FileName << "': light_pcapng_open_append returned NULL"); + m_DeviceOpened = false; + return false; + } + + m_DeviceOpened = true; + PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully"); return true; } - m_NumOfPacketsNotWritten = 0; - m_NumOfPacketsWritten = 0; + void PcapNgFileWriterDevice::flush() + { + if (!m_DeviceOpened || m_LightPcapNg == nullptr) + return; - light_pcapng_file_info* info = light_create_default_file_info(); + light_pcapng_flush((light_pcapng_t*)m_LightPcapNg); + PCPP_LOG_DEBUG("File writer flushed to file '" << m_FileName << "'"); + } - m_LightPcapNg = light_pcapng_open_write(m_FileName.c_str(), info, m_CompressionLevel); - if (m_LightPcapNg == nullptr) + void PcapNgFileWriterDevice::close() { - PCPP_LOG_ERROR("Error opening file writer device for file '" << m_FileName << "': light_pcapng_open_write returned NULL"); + if (m_LightPcapNg == nullptr) + return; - light_free_file_info(info); + light_pcapng_close((light_pcapng_t*)m_LightPcapNg); + m_LightPcapNg = nullptr; m_DeviceOpened = false; - return false; + PCPP_LOG_DEBUG("File writer closed for file '" << m_FileName << "'"); } - m_DeviceOpened = true; - PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully"); - return true; -} - -bool PcapNgFileWriterDevice::open(bool appendMode) -{ - if (!appendMode) - return open(); - - m_NumOfPacketsNotWritten = 0; - m_NumOfPacketsWritten = 0; - - m_LightPcapNg = light_pcapng_open_append(m_FileName.c_str()); - if (m_LightPcapNg == nullptr) + void PcapNgFileWriterDevice::getStatistics(PcapStats& stats) const { - PCPP_LOG_ERROR("Error opening file writer device in append mode for file '" << m_FileName << "': light_pcapng_open_append returned NULL"); - m_DeviceOpened = false; - return false; + stats.packetsRecv = m_NumOfPacketsWritten; + stats.packetsDrop = m_NumOfPacketsNotWritten; + stats.packetsDropByInterface = 0; + PCPP_LOG_DEBUG("Statistics received for pcap-ng writer device for filename '" << m_FileName << "'"); } - m_DeviceOpened = true; - PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully"); - return true; - -} - -void PcapNgFileWriterDevice::flush() -{ - if (!m_DeviceOpened || m_LightPcapNg == nullptr) - return; - - light_pcapng_flush((light_pcapng_t*)m_LightPcapNg); - PCPP_LOG_DEBUG("File writer flushed to file '" << m_FileName << "'"); -} - -void PcapNgFileWriterDevice::close() -{ - if (m_LightPcapNg == nullptr) - return; - - light_pcapng_close((light_pcapng_t*)m_LightPcapNg); - m_LightPcapNg = nullptr; - - m_DeviceOpened = false; - PCPP_LOG_DEBUG("File writer closed for file '" << m_FileName << "'"); -} - -void PcapNgFileWriterDevice::getStatistics(PcapStats& stats) const -{ - stats.packetsRecv = m_NumOfPacketsWritten; - stats.packetsDrop = m_NumOfPacketsNotWritten; - stats.packetsDropByInterface = 0; - PCPP_LOG_DEBUG("Statistics received for pcap-ng writer device for filename '" << m_FileName << "'"); -} - -bool PcapNgFileWriterDevice::setFilter(std::string filterAsString) -{ - return m_BpfWrapper.setFilter(filterAsString); -} - + bool PcapNgFileWriterDevice::setFilter(std::string filterAsString) + { + return m_BpfWrapper.setFilter(filterAsString); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/src/PcapFilter.cpp b/Pcap++/src/PcapFilter.cpp index eb850077bf..c3d905e856 100644 --- a/Pcap++/src/PcapFilter.cpp +++ b/Pcap++/src/PcapFilter.cpp @@ -7,7 +7,7 @@ #include #include #if defined(_WIN32) -#include +# include #endif #include "pcap.h" #include "RawPacket.h" @@ -16,359 +16,367 @@ namespace pcpp { -static const int DEFAULT_SNAPLEN = 9000; + static const int DEFAULT_SNAPLEN = 9000; -bool GeneralFilter::matchPacketWithFilter(RawPacket* rawPacket) -{ - std::string filterStr; - parseToString(filterStr); - - if (!m_BpfWrapper.setFilter(filterStr)) - return false; + bool GeneralFilter::matchPacketWithFilter(RawPacket* rawPacket) + { + std::string filterStr; + parseToString(filterStr); - return m_BpfWrapper.matchPacketWithFilter(rawPacket); -} + if (!m_BpfWrapper.setFilter(filterStr)) + return false; -namespace internal -{ - void BpfProgramDeleter::operator()(bpf_program* ptr) const - { - pcap_freecode(ptr); - delete ptr; + return m_BpfWrapper.matchPacketWithFilter(rawPacket); } -} -BpfFilterWrapper::BpfFilterWrapper() : m_LinkType(LinkLayerType::LINKTYPE_ETHERNET) {} + namespace internal + { + void BpfProgramDeleter::operator()(bpf_program* ptr) const + { + pcap_freecode(ptr); + delete ptr; + } + } // namespace internal -BpfFilterWrapper::BpfFilterWrapper(const BpfFilterWrapper& other) : BpfFilterWrapper() { setFilter(other.m_FilterStr, other.m_LinkType); } + BpfFilterWrapper::BpfFilterWrapper() : m_LinkType(LinkLayerType::LINKTYPE_ETHERNET) + {} -BpfFilterWrapper& BpfFilterWrapper::operator=(const BpfFilterWrapper &other) -{ - setFilter(other.m_FilterStr, other.m_LinkType); - return *this; -} + BpfFilterWrapper::BpfFilterWrapper(const BpfFilterWrapper& other) : BpfFilterWrapper() + { + setFilter(other.m_FilterStr, other.m_LinkType); + } -bool BpfFilterWrapper::setFilter(const std::string& filter, LinkLayerType linkType) -{ - if (filter.empty()) + BpfFilterWrapper& BpfFilterWrapper::operator=(const BpfFilterWrapper& other) { - freeProgram(); - return true; + setFilter(other.m_FilterStr, other.m_LinkType); + return *this; } - if (filter != m_FilterStr || linkType != m_LinkType) + bool BpfFilterWrapper::setFilter(const std::string& filter, LinkLayerType linkType) { - auto pcap = std::unique_ptr(pcap_open_dead(linkType, DEFAULT_SNAPLEN)); - if (pcap == nullptr) + if (filter.empty()) { - return false; + freeProgram(); + return true; } - std::unique_ptr newProg = std::unique_ptr(new bpf_program); - int ret = pcap_compile(pcap.get(), newProg.get(), filter.c_str(), 1, 0); - if (ret < 0) + if (filter != m_FilterStr || linkType != m_LinkType) { - return false; + auto pcap = std::unique_ptr(pcap_open_dead(linkType, DEFAULT_SNAPLEN)); + if (pcap == nullptr) + { + return false; + } + + std::unique_ptr newProg = std::unique_ptr(new bpf_program); + int ret = pcap_compile(pcap.get(), newProg.get(), filter.c_str(), 1, 0); + if (ret < 0) + { + return false; + } + + // Reassigns ownership of the bpf program to a new unique_ptr with a custom deleter as it now requires + // specialized cleanup. + m_Program = std::unique_ptr(newProg.release()); + m_FilterStr = filter; + m_LinkType = linkType; } - // Reassigns ownership of the bpf program to a new unique_ptr with a custom deleter as it now requires specialized cleanup. - m_Program = std::unique_ptr(newProg.release()); - m_FilterStr = filter; - m_LinkType = linkType; + return true; } - return true; -} - -void BpfFilterWrapper::freeProgram() -{ - m_Program = nullptr; - m_FilterStr.clear(); -} - -bool BpfFilterWrapper::matchPacketWithFilter(const RawPacket* rawPacket) -{ - return matchPacketWithFilter(rawPacket->getRawData(), rawPacket->getRawDataLen(), rawPacket->getPacketTimeStamp(), rawPacket->getLinkLayerType()); -} - -bool BpfFilterWrapper::matchPacketWithFilter(const uint8_t* packetData, uint32_t packetDataLength, timespec packetTimestamp, uint16_t linkType) -{ - if (m_FilterStr.empty()) - return true; + void BpfFilterWrapper::freeProgram() + { + m_Program = nullptr; + m_FilterStr.clear(); + } - if (!setFilter(std::string(m_FilterStr), static_cast(linkType))) + bool BpfFilterWrapper::matchPacketWithFilter(const RawPacket* rawPacket) { - return false; + return matchPacketWithFilter(rawPacket->getRawData(), rawPacket->getRawDataLen(), + rawPacket->getPacketTimeStamp(), rawPacket->getLinkLayerType()); } - struct pcap_pkthdr pktHdr; - pktHdr.caplen = packetDataLength; - pktHdr.len = packetDataLength; - TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packetTimestamp); + bool BpfFilterWrapper::matchPacketWithFilter(const uint8_t* packetData, uint32_t packetDataLength, + timespec packetTimestamp, uint16_t linkType) + { + if (m_FilterStr.empty()) + return true; - return (pcap_offline_filter(m_Program.get(), &pktHdr, packetData) != 0); -} + if (!setFilter(std::string(m_FilterStr), static_cast(linkType))) + { + return false; + } -void BPFStringFilter::parseToString(std::string& result) -{ - result = m_FilterStr; -} + struct pcap_pkthdr pktHdr; + pktHdr.caplen = packetDataLength; + pktHdr.len = packetDataLength; + TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packetTimestamp); -bool BPFStringFilter::verifyFilter() -{ - return m_BpfWrapper.setFilter(m_FilterStr); -} + return (pcap_offline_filter(m_Program.get(), &pktHdr, packetData) != 0); + } -void IFilterWithDirection::parseDirection(std::string& directionAsString) -{ - switch (m_Dir) + void BPFStringFilter::parseToString(std::string& result) { - case SRC: - directionAsString = "src"; - break; - case DST: - directionAsString = "dst"; - break; - default: //SRC_OR_DST: - directionAsString = "src or dst"; - break; + result = m_FilterStr; } -} -std::string IFilterWithOperator::parseOperator() -{ - switch(m_Operator) + bool BPFStringFilter::verifyFilter() { - case EQUALS: - return "="; - case NOT_EQUALS: - return "!="; - case GREATER_THAN: - return ">"; - case GREATER_OR_EQUAL: - return ">="; - case LESS_THAN: - return "<"; - case LESS_OR_EQUAL: - return "<="; - default: - return ""; + return m_BpfWrapper.setFilter(m_FilterStr); } -} - -void IPFilter::parseToString(std::string& result) -{ - std::string dir; - std::string ipAddr = m_Network.toString(); - std::string ipProto = m_Network.isIPv6Network() ? "ip6" : "ip"; - - parseDirection(dir); - result.reserve(ipProto.size() + dir.size() + ipAddr.size() + 10 /* Hard-coded strings */); - result = ipProto; - result += " and "; - result += dir; - result += " net "; - result += ipAddr; -} + void IFilterWithDirection::parseDirection(std::string& directionAsString) + { + switch (m_Dir) + { + case SRC: + directionAsString = "src"; + break; + case DST: + directionAsString = "dst"; + break; + default: // SRC_OR_DST: + directionAsString = "src or dst"; + break; + } + } -void IPv4IDFilter::parseToString(std::string& result) -{ - std::string op = parseOperator(); - std::ostringstream stream; - stream << m_IpID; - result = "ip[4:2] " + op + ' ' + stream.str(); -} + std::string IFilterWithOperator::parseOperator() + { + switch (m_Operator) + { + case EQUALS: + return "="; + case NOT_EQUALS: + return "!="; + case GREATER_THAN: + return ">"; + case GREATER_OR_EQUAL: + return ">="; + case LESS_THAN: + return "<"; + case LESS_OR_EQUAL: + return "<="; + default: + return ""; + } + } -void IPv4TotalLengthFilter::parseToString(std::string& result) -{ - std::string op = parseOperator(); - std::ostringstream stream; - stream << m_TotalLength; - result = "ip[2:2] " + op + ' ' + stream.str(); -} + void IPFilter::parseToString(std::string& result) + { + std::string dir; + std::string ipAddr = m_Network.toString(); + std::string ipProto = m_Network.isIPv6Network() ? "ip6" : "ip"; -void PortFilter::portToString(uint16_t portAsInt) -{ - std::ostringstream stream; - stream << portAsInt; - m_Port = stream.str(); -} + parseDirection(dir); -PortFilter::PortFilter(uint16_t port, Direction dir) : IFilterWithDirection(dir) -{ - portToString(port); -} + result.reserve(ipProto.size() + dir.size() + ipAddr.size() + 10 /* Hard-coded strings */); + result = ipProto; + result += " and "; + result += dir; + result += " net "; + result += ipAddr; + } -void PortFilter::parseToString(std::string& result) -{ - std::string dir; - parseDirection(dir); - result = dir + " port " + m_Port; -} + void IPv4IDFilter::parseToString(std::string& result) + { + std::string op = parseOperator(); + std::ostringstream stream; + stream << m_IpID; + result = "ip[4:2] " + op + ' ' + stream.str(); + } -void PortRangeFilter::parseToString(std::string& result) -{ - std::string dir; - parseDirection(dir); + void IPv4TotalLengthFilter::parseToString(std::string& result) + { + std::string op = parseOperator(); + std::ostringstream stream; + stream << m_TotalLength; + result = "ip[2:2] " + op + ' ' + stream.str(); + } - std::ostringstream fromPortStream; - fromPortStream << static_cast(m_FromPort); - std::ostringstream toPortStream; - toPortStream << static_cast(m_ToPort); + void PortFilter::portToString(uint16_t portAsInt) + { + std::ostringstream stream; + stream << portAsInt; + m_Port = stream.str(); + } - result = dir + " portrange " + fromPortStream.str() + '-' + toPortStream.str(); -} + PortFilter::PortFilter(uint16_t port, Direction dir) : IFilterWithDirection(dir) + { + portToString(port); + } -void MacAddressFilter::parseToString(std::string& result) -{ - if (getDir() != SRC_OR_DST) + void PortFilter::parseToString(std::string& result) { std::string dir; parseDirection(dir); - result = "ether " + dir + ' ' + m_MacAddress.toString(); + result = dir + " port " + m_Port; } - else - result = "ether host " + m_MacAddress.toString(); -} -void EtherTypeFilter::parseToString(std::string& result) -{ - std::ostringstream stream; - stream << "0x" << std::hex << m_EtherType; - result = "ether proto " + stream.str(); -} + void PortRangeFilter::parseToString(std::string& result) + { + std::string dir; + parseDirection(dir); -CompositeFilter::CompositeFilter(const std::vector& filters) : m_FilterList(filters) {} + std::ostringstream fromPortStream; + fromPortStream << static_cast(m_FromPort); + std::ostringstream toPortStream; + toPortStream << static_cast(m_ToPort); -void CompositeFilter::removeFilter(GeneralFilter* filter) -{ - for(auto it = m_FilterList.cbegin(); it != m_FilterList.cend(); ++it) + result = dir + " portrange " + fromPortStream.str() + '-' + toPortStream.str(); + } + + void MacAddressFilter::parseToString(std::string& result) { - if (*it == filter) + if (getDir() != SRC_OR_DST) { - m_FilterList.erase(it); - break; + std::string dir; + parseDirection(dir); + result = "ether " + dir + ' ' + m_MacAddress.toString(); } + else + result = "ether host " + m_MacAddress.toString(); } -} -void CompositeFilter::setFilters(const std::vector& filters) -{ - m_FilterList = filters; -} + void EtherTypeFilter::parseToString(std::string& result) + { + std::ostringstream stream; + stream << "0x" << std::hex << m_EtherType; + result = "ether proto " + stream.str(); + } -void NotFilter::parseToString(std::string& result) -{ - std::string innerFilterAsString; - m_FilterToInverse->parseToString(innerFilterAsString); - result = "not (" + innerFilterAsString + ')'; -} + CompositeFilter::CompositeFilter(const std::vector& filters) : m_FilterList(filters) + {} -void ProtoFilter::parseToString(std::string& result) -{ - std::ostringstream stream; + void CompositeFilter::removeFilter(GeneralFilter* filter) + { + for (auto it = m_FilterList.cbegin(); it != m_FilterList.cend(); ++it) + { + if (*it == filter) + { + m_FilterList.erase(it); + break; + } + } + } - switch (m_ProtoFamily) + void CompositeFilter::setFilters(const std::vector& filters) { - case TCP: - result = "tcp"; - break; - case UDP: - result = "udp"; - break; - case ICMP: - result = "icmp"; - break; - case VLAN: - result = "vlan"; - break; - case IPv4: - result = "ip"; - break; - case IPv6: - result = "ip6"; - break; - case ARP: - result = "arp"; - break; - case Ethernet: - result = "ether"; - break; - case GRE: - stream << "proto " << PACKETPP_IPPROTO_GRE; - result = stream.str(); - break; - case IGMP: - stream << "proto " << PACKETPP_IPPROTO_IGMP; - result = stream.str(); - break; - default: - break; + m_FilterList = filters; } -} -void ArpFilter::parseToString(std::string& result) -{ - std::ostringstream sstream; - sstream << "arp[7] = " << m_OpCode; - result += sstream.str(); -} + void NotFilter::parseToString(std::string& result) + { + std::string innerFilterAsString; + m_FilterToInverse->parseToString(innerFilterAsString); + result = "not (" + innerFilterAsString + ')'; + } -void VlanFilter::parseToString(std::string& result) -{ - std::ostringstream stream; - stream << m_VlanID; - result = "vlan " + stream.str(); -} + void ProtoFilter::parseToString(std::string& result) + { + std::ostringstream stream; -void TcpFlagsFilter::parseToString(std::string& result) -{ - if (m_TcpFlagsBitMask == 0) + switch (m_ProtoFamily) + { + case TCP: + result = "tcp"; + break; + case UDP: + result = "udp"; + break; + case ICMP: + result = "icmp"; + break; + case VLAN: + result = "vlan"; + break; + case IPv4: + result = "ip"; + break; + case IPv6: + result = "ip6"; + break; + case ARP: + result = "arp"; + break; + case Ethernet: + result = "ether"; + break; + case GRE: + stream << "proto " << PACKETPP_IPPROTO_GRE; + result = stream.str(); + break; + case IGMP: + stream << "proto " << PACKETPP_IPPROTO_IGMP; + result = stream.str(); + break; + default: + break; + } + } + + void ArpFilter::parseToString(std::string& result) { - result.clear(); - return; + std::ostringstream sstream; + sstream << "arp[7] = " << m_OpCode; + result += sstream.str(); } - result = "tcp[tcpflags] & ("; - if ((m_TcpFlagsBitMask & tcpFin) != 0) - result += "tcp-fin|"; - if ((m_TcpFlagsBitMask & tcpSyn) != 0) - result += "tcp-syn|"; - if ((m_TcpFlagsBitMask & tcpRst) != 0) - result += "tcp-rst|"; - if ((m_TcpFlagsBitMask & tcpPush) != 0) - result += "tcp-push|"; - if ((m_TcpFlagsBitMask & tcpAck) != 0) - result += "tcp-ack|"; - if ((m_TcpFlagsBitMask & tcpUrg) != 0) - result += "tcp-urg|"; - - // replace the last '|' character - result[result.size() - 1] = ')'; - - if (m_MatchOption == MatchOneAtLeast) - result += " != 0"; - else //m_MatchOption == MatchAll + void VlanFilter::parseToString(std::string& result) { std::ostringstream stream; - stream << static_cast(m_TcpFlagsBitMask); - result += " = " + stream.str(); + stream << m_VlanID; + result = "vlan " + stream.str(); } -} -void TcpWindowSizeFilter::parseToString(std::string& result) -{ - std::ostringstream stream; - stream << m_WindowSize; - result = "tcp[14:2] " + parseOperator() + ' ' + stream.str(); -} + void TcpFlagsFilter::parseToString(std::string& result) + { + if (m_TcpFlagsBitMask == 0) + { + result.clear(); + return; + } -void UdpLengthFilter::parseToString(std::string& result) -{ - std::ostringstream stream; - stream << m_Length; - result = "udp[4:2] " + parseOperator() + ' ' + stream.str(); -} + result = "tcp[tcpflags] & ("; + if ((m_TcpFlagsBitMask & tcpFin) != 0) + result += "tcp-fin|"; + if ((m_TcpFlagsBitMask & tcpSyn) != 0) + result += "tcp-syn|"; + if ((m_TcpFlagsBitMask & tcpRst) != 0) + result += "tcp-rst|"; + if ((m_TcpFlagsBitMask & tcpPush) != 0) + result += "tcp-push|"; + if ((m_TcpFlagsBitMask & tcpAck) != 0) + result += "tcp-ack|"; + if ((m_TcpFlagsBitMask & tcpUrg) != 0) + result += "tcp-urg|"; + + // replace the last '|' character + result[result.size() - 1] = ')'; + + if (m_MatchOption == MatchOneAtLeast) + result += " != 0"; + else // m_MatchOption == MatchAll + { + std::ostringstream stream; + stream << static_cast(m_TcpFlagsBitMask); + result += " = " + stream.str(); + } + } + + void TcpWindowSizeFilter::parseToString(std::string& result) + { + std::ostringstream stream; + stream << m_WindowSize; + result = "tcp[14:2] " + parseOperator() + ' ' + stream.str(); + } + + void UdpLengthFilter::parseToString(std::string& result) + { + std::ostringstream stream; + stream << m_Length; + result = "udp[4:2] " + parseOperator() + ' ' + stream.str(); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/src/PcapLiveDevice.cpp b/Pcap++/src/PcapLiveDevice.cpp index aeee7bb093..77b26494bd 100644 --- a/Pcap++/src/PcapLiveDevice.cpp +++ b/Pcap++/src/PcapLiveDevice.cpp @@ -6,9 +6,9 @@ #include "PcapLiveDevice.h" #include "PcapLiveDeviceList.h" #include "Packet.h" -#ifndef _MSC_VER -#include -#endif // ! _MSC_VER +#ifndef _MSC_VER +# include +#endif // ! _MSC_VER #include "pcap.h" #include #include "Logger.h" @@ -24,32 +24,31 @@ // The definition of BPF_MAJOR_VERSION is required to support Npcap. In Npcap there are // compilation errors due to struct redefinition when including both Packet32.h and pcap.h // This define statement eliminates these errors -#ifndef BPF_MAJOR_VERSION -#define BPF_MAJOR_VERSION 1 -#endif // BPF_MAJOR_VERSION -#include -#include -#include -#include +# ifndef BPF_MAJOR_VERSION +# define BPF_MAJOR_VERSION 1 +# endif // BPF_MAJOR_VERSION +# include +# include +# include +# include #else -#include -#include -#include -#include -#include -#endif // if defined(_WIN32) +# include +# include +# include +# include +# include +#endif // if defined(_WIN32) #if defined(__APPLE__) -#include -#include -#include +# include +# include +# include #endif #if defined(__FreeBSD__) -#include -#include +# include +# include #endif - // TODO: FIX FreeBSD // On Mac OS X and FreeBSD timeout of -1 causes pcap_open_live to fail. // A value of 1ms first solve the issue but since Jan. 2024 an issue @@ -57,699 +56,729 @@ // After multiple test a 10ms is the minimum to fix pcap_breakloop(). // On Linux and Windows this is not the case so we keep the -1 value #if defined(__FreeBSD__) -#define LIBPCAP_OPEN_LIVE_TIMEOUT 10 +# define LIBPCAP_OPEN_LIVE_TIMEOUT 10 #elif defined(__APPLE__) -#define LIBPCAP_OPEN_LIVE_TIMEOUT 1 +# define LIBPCAP_OPEN_LIVE_TIMEOUT 1 #else -#define LIBPCAP_OPEN_LIVE_TIMEOUT -1 +# define LIBPCAP_OPEN_LIVE_TIMEOUT -1 #endif -static const char *NFLOG_IFACE = "nflog"; +static const char* NFLOG_IFACE = "nflog"; static const int DEFAULT_SNAPLEN = 9000; namespace pcpp { #ifdef HAS_SET_DIRECTION_ENABLED -static pcap_direction_t directionTypeMap(PcapLiveDevice::PcapDirection direction) -{ - switch (direction) + static pcap_direction_t directionTypeMap(PcapLiveDevice::PcapDirection direction) { - case PcapLiveDevice::PCPP_IN: return PCAP_D_IN; - case PcapLiveDevice::PCPP_OUT: return PCAP_D_OUT; - case PcapLiveDevice::PCPP_INOUT: return PCAP_D_INOUT; + switch (direction) + { + case PcapLiveDevice::PCPP_IN: + return PCAP_D_IN; + case PcapLiveDevice::PCPP_OUT: + return PCAP_D_OUT; + case PcapLiveDevice::PCPP_INOUT: + return PCAP_D_INOUT; + } } -} #endif + PcapLiveDevice::PcapLiveDevice(pcap_if_t* pInterface, bool calculateMTU, bool calculateMacAddress, + bool calculateDefaultGateway) + : IPcapDevice(), m_PcapSendDescriptor(nullptr), m_PcapSelectableFd(-1), m_DefaultGateway(IPv4Address::Zero), + m_UsePoll(false) + { + m_DeviceMtu = 0; + m_LinkType = LINKTYPE_ETHERNET; + m_IsLoopback = (pInterface->flags & 0x1) == PCAP_IF_LOOPBACK; -PcapLiveDevice::PcapLiveDevice(pcap_if_t* pInterface, bool calculateMTU, bool calculateMacAddress, bool calculateDefaultGateway) : - IPcapDevice(), m_PcapSendDescriptor(nullptr), m_PcapSelectableFd(-1), m_DefaultGateway(IPv4Address::Zero), m_UsePoll(false) -{ - m_DeviceMtu = 0; - m_LinkType = LINKTYPE_ETHERNET; + m_Name = pInterface->name; + if (pInterface->description != nullptr) + m_Description = pInterface->description; + PCPP_LOG_DEBUG("Added live device: name=" << m_Name << "; desc=" << m_Description); + PCPP_LOG_DEBUG(" Addresses:"); + while (pInterface->addresses != nullptr) + { + m_Addresses.insert(m_Addresses.end(), *(pInterface->addresses)); + pInterface->addresses = pInterface->addresses->next; + if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && pInterface->addresses != nullptr && + pInterface->addresses->addr != nullptr) + { + std::array addrAsString; + internal::sockaddr2string(pInterface->addresses->addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG(" " << addrAsString.data()); + } + } - m_IsLoopback = (pInterface->flags & 0x1) == PCAP_IF_LOOPBACK; + if (calculateMTU) + { + setDeviceMtu(); + PCPP_LOG_DEBUG(" MTU: " << m_DeviceMtu); + } - m_Name = pInterface->name; - if (pInterface->description != nullptr) - m_Description = pInterface->description; - PCPP_LOG_DEBUG("Added live device: name=" << m_Name << "; desc=" << m_Description); - PCPP_LOG_DEBUG(" Addresses:"); - while (pInterface->addresses != nullptr) - { - m_Addresses.insert(m_Addresses.end(), *(pInterface->addresses)); - pInterface->addresses = pInterface->addresses->next; - if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && pInterface->addresses != nullptr && pInterface->addresses->addr != nullptr) + if (calculateDefaultGateway) { - std::array addrAsString; - internal::sockaddr2string(pInterface->addresses->addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG(" " << addrAsString.data()); + setDefaultGateway(); + PCPP_LOG_DEBUG(" Default Gateway: " << m_DefaultGateway); } - } - if (calculateMTU) - { - setDeviceMtu(); - PCPP_LOG_DEBUG(" MTU: " << m_DeviceMtu); + // init all other members + m_CaptureThreadStarted = false; + m_StatsThreadStarted = false; + m_StopThread = false; + m_CaptureThread = {}; + m_StatsThread = {}; + m_cbOnPacketArrives = nullptr; + m_cbOnStatsUpdate = nullptr; + m_cbOnPacketArrivesBlockingMode = nullptr; + m_cbOnPacketArrivesBlockingModeUserCookie = nullptr; + m_IntervalToUpdateStats = 0; + m_cbOnPacketArrivesUserCookie = nullptr; + m_cbOnStatsUpdateUserCookie = nullptr; + m_CaptureCallbackMode = true; + m_CapturedPackets = nullptr; + if (calculateMacAddress) + { + setDeviceMacAddress(); + PCPP_LOG_DEBUG(" MAC addr: " << m_MacAddress); + } } - if (calculateDefaultGateway) + void PcapLiveDevice::onPacketArrives(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet) { - setDefaultGateway(); - PCPP_LOG_DEBUG(" Default Gateway: " << m_DefaultGateway); - } + PcapLiveDevice* pThis = reinterpret_cast(user); + if (pThis == nullptr) + { + PCPP_LOG_ERROR("Unable to extract PcapLiveDevice instance"); + return; + } - //init all other members - m_CaptureThreadStarted = false; - m_StatsThreadStarted = false; - m_StopThread = false; - m_CaptureThread = {}; - m_StatsThread = {}; - m_cbOnPacketArrives = nullptr; - m_cbOnStatsUpdate = nullptr; - m_cbOnPacketArrivesBlockingMode = nullptr; - m_cbOnPacketArrivesBlockingModeUserCookie = nullptr; - m_IntervalToUpdateStats = 0; - m_cbOnPacketArrivesUserCookie = nullptr; - m_cbOnStatsUpdateUserCookie = nullptr; - m_CaptureCallbackMode = true; - m_CapturedPackets = nullptr; - if (calculateMacAddress) - { - setDeviceMacAddress(); - PCPP_LOG_DEBUG(" MAC addr: " << m_MacAddress); - } -} + RawPacket rawPacket(packet, pkthdr->caplen, pkthdr->ts, false, pThis->getLinkType()); -void PcapLiveDevice::onPacketArrives(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet) -{ - PcapLiveDevice* pThis = reinterpret_cast(user); - if (pThis == nullptr) - { - PCPP_LOG_ERROR("Unable to extract PcapLiveDevice instance"); - return; + if (pThis->m_cbOnPacketArrives != nullptr) + pThis->m_cbOnPacketArrives(&rawPacket, pThis, pThis->m_cbOnPacketArrivesUserCookie); } - RawPacket rawPacket(packet, pkthdr->caplen, pkthdr->ts, false, pThis->getLinkType()); - - if (pThis->m_cbOnPacketArrives != nullptr) - pThis->m_cbOnPacketArrives(&rawPacket, pThis, pThis->m_cbOnPacketArrivesUserCookie); -} - -void PcapLiveDevice::onPacketArrivesNoCallback(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet) -{ - PcapLiveDevice* pThis = reinterpret_cast(user); - if (pThis == nullptr) + void PcapLiveDevice::onPacketArrivesNoCallback(uint8_t* user, const struct pcap_pkthdr* pkthdr, + const uint8_t* packet) { - PCPP_LOG_ERROR("Unable to extract PcapLiveDevice instance"); - return; - } - - uint8_t* packetData = new uint8_t[pkthdr->caplen]; - memcpy(packetData, packet, pkthdr->caplen); - RawPacket* rawPacketPtr = new RawPacket(packetData, pkthdr->caplen, pkthdr->ts, true, pThis->getLinkType()); - pThis->m_CapturedPackets->pushBack(rawPacketPtr); -} + PcapLiveDevice* pThis = reinterpret_cast(user); + if (pThis == nullptr) + { + PCPP_LOG_ERROR("Unable to extract PcapLiveDevice instance"); + return; + } -void PcapLiveDevice::onPacketArrivesBlockingMode(uint8_t* user, const struct pcap_pkthdr* pkthdr, const uint8_t* packet) -{ - PcapLiveDevice* pThis = reinterpret_cast(user); - if (pThis == nullptr) - { - PCPP_LOG_ERROR("Unable to extract PcapLiveDevice instance"); - return; + uint8_t* packetData = new uint8_t[pkthdr->caplen]; + memcpy(packetData, packet, pkthdr->caplen); + RawPacket* rawPacketPtr = new RawPacket(packetData, pkthdr->caplen, pkthdr->ts, true, pThis->getLinkType()); + pThis->m_CapturedPackets->pushBack(rawPacketPtr); } - RawPacket rawPacket(packet, pkthdr->caplen, pkthdr->ts, false, pThis->getLinkType()); + void PcapLiveDevice::onPacketArrivesBlockingMode(uint8_t* user, const struct pcap_pkthdr* pkthdr, + const uint8_t* packet) + { + PcapLiveDevice* pThis = reinterpret_cast(user); + if (pThis == nullptr) + { + PCPP_LOG_ERROR("Unable to extract PcapLiveDevice instance"); + return; + } - if (pThis->m_cbOnPacketArrivesBlockingMode != nullptr) - if (pThis->m_cbOnPacketArrivesBlockingMode(&rawPacket, pThis, pThis->m_cbOnPacketArrivesBlockingModeUserCookie)) - pThis->m_StopThread = true; -} + RawPacket rawPacket(packet, pkthdr->caplen, pkthdr->ts, false, pThis->getLinkType()); -void PcapLiveDevice::captureThreadMain() -{ - PCPP_LOG_DEBUG("Started capture thread for device '" << m_Name << "'"); - m_CaptureThreadStarted = true; + if (pThis->m_cbOnPacketArrivesBlockingMode != nullptr) + if (pThis->m_cbOnPacketArrivesBlockingMode(&rawPacket, pThis, + pThis->m_cbOnPacketArrivesBlockingModeUserCookie)) + pThis->m_StopThread = true; + } - if (m_CaptureCallbackMode) + void PcapLiveDevice::captureThreadMain() { - while (!m_StopThread) + PCPP_LOG_DEBUG("Started capture thread for device '" << m_Name << "'"); + m_CaptureThreadStarted = true; + + if (m_CaptureCallbackMode) { - if (pcap_dispatch(m_PcapDescriptor, -1, onPacketArrives, reinterpret_cast(this)) == -1) + while (!m_StopThread) { - PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); - m_StopThread = true; + if (pcap_dispatch(m_PcapDescriptor, -1, onPacketArrives, reinterpret_cast(this)) == -1) + { + PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + m_StopThread = true; + } } } - } - else - { - while (!m_StopThread) + else { - if (pcap_dispatch(m_PcapDescriptor, 100, onPacketArrivesNoCallback, reinterpret_cast(this)) == -1) + while (!m_StopThread) { - PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); - m_StopThread = true; + if (pcap_dispatch(m_PcapDescriptor, 100, onPacketArrivesNoCallback, reinterpret_cast(this)) == + -1) + { + PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + m_StopThread = true; + } } } + PCPP_LOG_DEBUG("Ended capture thread for device '" << m_Name << "'"); } - PCPP_LOG_DEBUG("Ended capture thread for device '" << m_Name << "'"); -} - -void PcapLiveDevice::statsThreadMain() -{ - PCPP_LOG_DEBUG("Started stats thread for device '" << m_Name << "'"); - while (!m_StopThread) - { - PcapStats stats; - getStatistics(stats); - m_cbOnStatsUpdate(stats, m_cbOnStatsUpdateUserCookie); - multiPlatformSleep(m_IntervalToUpdateStats); - } - PCPP_LOG_DEBUG("Ended stats thread for device '" << m_Name << "'"); -} - -pcap_t* PcapLiveDevice::doOpen(const DeviceConfiguration& config) -{ - char errbuf[PCAP_ERRBUF_SIZE] = {'\0'}; - std::string device_name = m_Name; - if (device_name == NFLOG_IFACE) + void PcapLiveDevice::statsThreadMain() { - device_name += ":" + std::to_string(config.nflogGroup & 0xffff); + PCPP_LOG_DEBUG("Started stats thread for device '" << m_Name << "'"); + while (!m_StopThread) + { + PcapStats stats; + getStatistics(stats); + m_cbOnStatsUpdate(stats, m_cbOnStatsUpdateUserCookie); + multiPlatformSleep(m_IntervalToUpdateStats); + } + PCPP_LOG_DEBUG("Ended stats thread for device '" << m_Name << "'"); } - pcap_t* pcap = pcap_create(device_name.c_str(), errbuf); - if (!pcap) - { - PCPP_LOG_ERROR(errbuf); - return pcap; - } - int ret = pcap_set_snaplen(pcap, config.snapshotLength <= 0 ? DEFAULT_SNAPLEN : config.snapshotLength); - if (ret != 0) - { - PCPP_LOG_ERROR(pcap_geterr(pcap)); - } - ret = pcap_set_promisc(pcap, config.mode); - if (ret != 0) + pcap_t* PcapLiveDevice::doOpen(const DeviceConfiguration& config) { - PCPP_LOG_ERROR(pcap_geterr(pcap)); - } + char errbuf[PCAP_ERRBUF_SIZE] = { '\0' }; + std::string device_name = m_Name; - int timeout = (config.packetBufferTimeoutMs <= 0 ? LIBPCAP_OPEN_LIVE_TIMEOUT : config.packetBufferTimeoutMs); - ret = pcap_set_timeout(pcap, timeout); - if (ret != 0) - { - PCPP_LOG_ERROR(pcap_geterr(pcap)); - } + if (device_name == NFLOG_IFACE) + { + device_name += ":" + std::to_string(config.nflogGroup & 0xffff); + } - if (config.packetBufferSize >= 100) - { - ret = pcap_set_buffer_size(pcap, config.packetBufferSize); + pcap_t* pcap = pcap_create(device_name.c_str(), errbuf); + if (!pcap) + { + PCPP_LOG_ERROR(errbuf); + return pcap; + } + int ret = pcap_set_snaplen(pcap, config.snapshotLength <= 0 ? DEFAULT_SNAPLEN : config.snapshotLength); + if (ret != 0) + { + PCPP_LOG_ERROR(pcap_geterr(pcap)); + } + ret = pcap_set_promisc(pcap, config.mode); if (ret != 0) { PCPP_LOG_ERROR(pcap_geterr(pcap)); } - } - -#ifdef HAS_PCAP_IMMEDIATE_MODE - ret = pcap_set_immediate_mode(pcap, 1); - if (ret == 0) - { - PCPP_LOG_DEBUG("Immediate mode is activated"); - } - else - { - PCPP_LOG_ERROR("Failed to activate immediate mode, error code: '" << ret << "', error message: '" << pcap_geterr(pcap) << "'"); - } -#endif - ret = pcap_activate(pcap); - if (ret != 0) - { - PCPP_LOG_ERROR(pcap_geterr(pcap)); - pcap_close(pcap); - return nullptr; - } + int timeout = (config.packetBufferTimeoutMs <= 0 ? LIBPCAP_OPEN_LIVE_TIMEOUT : config.packetBufferTimeoutMs); + ret = pcap_set_timeout(pcap, timeout); + if (ret != 0) + { + PCPP_LOG_ERROR(pcap_geterr(pcap)); + } -#ifdef HAS_SET_DIRECTION_ENABLED - pcap_direction_t directionToSet = directionTypeMap(config.direction); - ret = pcap_setdirection(pcap, directionToSet); - if (ret == 0) - { - if (config.direction == PCPP_IN) + if (config.packetBufferSize >= 100) { - PCPP_LOG_DEBUG("Only incoming traffics will be captured"); + ret = pcap_set_buffer_size(pcap, config.packetBufferSize); + if (ret != 0) + { + PCPP_LOG_ERROR(pcap_geterr(pcap)); + } } - else if (config.direction == PCPP_OUT) + +#ifdef HAS_PCAP_IMMEDIATE_MODE + ret = pcap_set_immediate_mode(pcap, 1); + if (ret == 0) { - PCPP_LOG_DEBUG("Only outgoing traffics will be captured"); + PCPP_LOG_DEBUG("Immediate mode is activated"); } else { - PCPP_LOG_DEBUG("Both incoming and outgoing traffics will be captured"); + PCPP_LOG_ERROR("Failed to activate immediate mode, error code: '" << ret << "', error message: '" + << pcap_geterr(pcap) << "'"); } - } - else - { - PCPP_LOG_ERROR("Failed to set direction for capturing packets, error code: '" << ret << "', error message: '" << pcap_geterr(pcap) << "'"); - } #endif - if (pcap) - { - int dlt = pcap_datalink(pcap); - const char* dlt_name = pcap_datalink_val_to_name(dlt); - if (dlt_name) + ret = pcap_activate(pcap); + if (ret != 0) + { + PCPP_LOG_ERROR(pcap_geterr(pcap)); + pcap_close(pcap); + return nullptr; + } + +#ifdef HAS_SET_DIRECTION_ENABLED + pcap_direction_t directionToSet = directionTypeMap(config.direction); + ret = pcap_setdirection(pcap, directionToSet); + if (ret == 0) { - PCPP_LOG_DEBUG("link-type " << dlt << ": " << dlt_name << " (" << pcap_datalink_val_to_description(dlt) << ")"); + if (config.direction == PCPP_IN) + { + PCPP_LOG_DEBUG("Only incoming traffics will be captured"); + } + else if (config.direction == PCPP_OUT) + { + PCPP_LOG_DEBUG("Only outgoing traffics will be captured"); + } + else + { + PCPP_LOG_DEBUG("Both incoming and outgoing traffics will be captured"); + } } else { - PCPP_LOG_DEBUG("link-type " << dlt); + PCPP_LOG_ERROR("Failed to set direction for capturing packets, error code: '" + << ret << "', error message: '" << pcap_geterr(pcap) << "'"); } +#endif + + if (pcap) + { + int dlt = pcap_datalink(pcap); + const char* dlt_name = pcap_datalink_val_to_name(dlt); + if (dlt_name) + { + PCPP_LOG_DEBUG("link-type " << dlt << ": " << dlt_name << " (" << pcap_datalink_val_to_description(dlt) + << ")"); + } + else + { + PCPP_LOG_DEBUG("link-type " << dlt); + } - m_LinkType = static_cast(dlt); + m_LinkType = static_cast(dlt); + } + return pcap; } - return pcap; -} -bool PcapLiveDevice::open(const DeviceConfiguration& config) -{ - if (m_DeviceOpened) + bool PcapLiveDevice::open(const DeviceConfiguration& config) { - PCPP_LOG_DEBUG("Device '" << m_Name << "' already opened"); - return true; - } + if (m_DeviceOpened) + { + PCPP_LOG_DEBUG("Device '" << m_Name << "' already opened"); + return true; + } - m_PcapDescriptor = doOpen(config); + m_PcapDescriptor = doOpen(config); - // It's not possible to have two open instances of the same NFLOG device:group - if (m_Name == NFLOG_IFACE) - { - m_PcapSendDescriptor = nullptr; - } - else - { - m_PcapSendDescriptor = doOpen(config); - } + // It's not possible to have two open instances of the same NFLOG device:group + if (m_Name == NFLOG_IFACE) + { + m_PcapSendDescriptor = nullptr; + } + else + { + m_PcapSendDescriptor = doOpen(config); + } - if (m_PcapDescriptor == nullptr || (m_Name != NFLOG_IFACE && m_PcapSendDescriptor == nullptr)) - { - m_DeviceOpened = false; - return false; - } + if (m_PcapDescriptor == nullptr || (m_Name != NFLOG_IFACE && m_PcapSendDescriptor == nullptr)) + { + m_DeviceOpened = false; + return false; + } - PCPP_LOG_DEBUG("Device '" << m_Name << "' opened"); + PCPP_LOG_DEBUG("Device '" << m_Name << "' opened"); - m_DeviceOpened = true; + m_DeviceOpened = true; - if(!config.usePoll) - { - m_UsePoll = false; - m_PcapSelectableFd = -1; - } - else - { + if (!config.usePoll) + { + m_UsePoll = false; + m_PcapSelectableFd = -1; + } + else + { #if !defined(_WIN32) - m_UsePoll = true; - m_PcapSelectableFd = pcap_get_selectable_fd(m_PcapSendDescriptor); + m_UsePoll = true; + m_PcapSelectableFd = pcap_get_selectable_fd(m_PcapSendDescriptor); #else - PCPP_LOG_ERROR("Windows doesn't support poll(), ignoring the `usePoll` parameter"); + PCPP_LOG_ERROR("Windows doesn't support poll(), ignoring the `usePoll` parameter"); #endif - } - - return true; -} + } -bool PcapLiveDevice::open() -{ - DeviceConfiguration defaultConfig; - return open(defaultConfig); -} + return true; + } -void PcapLiveDevice::close() -{ - if (m_PcapDescriptor == nullptr && m_PcapSendDescriptor == nullptr) + bool PcapLiveDevice::open() { - PCPP_LOG_DEBUG("Device '" << m_Name << "' already closed"); - return; + DeviceConfiguration defaultConfig; + return open(defaultConfig); } - bool sameDescriptor = (m_PcapDescriptor == m_PcapSendDescriptor); - pcap_close(m_PcapDescriptor); - PCPP_LOG_DEBUG("Receive pcap descriptor closed"); - if (!sameDescriptor) + void PcapLiveDevice::close() { - pcap_close(m_PcapSendDescriptor); - PCPP_LOG_DEBUG("Send pcap descriptor closed"); - } + if (m_PcapDescriptor == nullptr && m_PcapSendDescriptor == nullptr) + { + PCPP_LOG_DEBUG("Device '" << m_Name << "' already closed"); + return; + } - m_DeviceOpened = false; - PCPP_LOG_DEBUG("Device '" << m_Name << "' closed"); -} + bool sameDescriptor = (m_PcapDescriptor == m_PcapSendDescriptor); + pcap_close(m_PcapDescriptor); + PCPP_LOG_DEBUG("Receive pcap descriptor closed"); + if (!sameDescriptor) + { + pcap_close(m_PcapSendDescriptor); + PCPP_LOG_DEBUG("Send pcap descriptor closed"); + } -PcapLiveDevice* PcapLiveDevice::clone() const -{ - std::unique_ptr interfaceList; - try - { - interfaceList = internal::getAllLocalPcapDevices(); - } - catch (const std::exception& e) - { - PCPP_LOG_ERROR(e.what()); - return nullptr; + m_DeviceOpened = false; + PCPP_LOG_DEBUG("Device '" << m_Name << "' closed"); } - for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next) + PcapLiveDevice* PcapLiveDevice::clone() const { - if (!std::strcmp(currInterface->name, getName().c_str())) + std::unique_ptr interfaceList; + try { - return cloneInternal(*currInterface); + interfaceList = internal::getAllLocalPcapDevices(); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR(e.what()); + return nullptr; } - } - - PCPP_LOG_ERROR("Can't find interface " << getName().c_str()); - return nullptr; -} -PcapLiveDevice* PcapLiveDevice::cloneInternal(pcap_if_t& devInterface) const -{ - return new PcapLiveDevice(&devInterface, true, true, true); -} + for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; + currInterface = currInterface->next) + { + if (!std::strcmp(currInterface->name, getName().c_str())) + { + return cloneInternal(*currInterface); + } + } -bool PcapLiveDevice::startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie) -{ - return startCapture(std::move(onPacketArrives), onPacketArrivesUserCookie, 0, nullptr, nullptr); -} + PCPP_LOG_ERROR("Can't find interface " << getName().c_str()); + return nullptr; + } -bool PcapLiveDevice::startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie) -{ - return startCapture(nullptr, nullptr, intervalInSecondsToUpdateStats, std::move(onStatsUpdate), onStatsUpdateUserCookie); -} + PcapLiveDevice* PcapLiveDevice::cloneInternal(pcap_if_t& devInterface) const + { + return new PcapLiveDevice(&devInterface, true, true, true); + } -bool PcapLiveDevice::startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie) -{ - if (!m_DeviceOpened || m_PcapDescriptor == nullptr) + bool PcapLiveDevice::startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie) { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); - return false; + return startCapture(std::move(onPacketArrives), onPacketArrivesUserCookie, 0, nullptr, nullptr); } - if (m_CaptureThreadStarted) + bool PcapLiveDevice::startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, + void* onStatsUpdateUserCookie) { - PCPP_LOG_ERROR("Device '" << m_Name << "' already capturing traffic"); - return false; + return startCapture(nullptr, nullptr, intervalInSecondsToUpdateStats, std::move(onStatsUpdate), + onStatsUpdateUserCookie); } - m_IntervalToUpdateStats = intervalInSecondsToUpdateStats; + bool PcapLiveDevice::startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, + int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, + void* onStatsUpdateUserCookie) + { + if (!m_DeviceOpened || m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); + return false; + } - m_CaptureCallbackMode = true; - m_cbOnPacketArrives = std::move(onPacketArrives); - m_cbOnPacketArrivesUserCookie = onPacketArrivesUserCookie; + if (m_CaptureThreadStarted) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' already capturing traffic"); + return false; + } - m_CaptureThread = std::thread(&pcpp::PcapLiveDevice::captureThreadMain, this); + m_IntervalToUpdateStats = intervalInSecondsToUpdateStats; - // Wait thread to be start - // C++20 = m_CaptureThreadStarted.wait(true); - while (m_CaptureThreadStarted != true) { - std::this_thread::yield(); - } - PCPP_LOG_DEBUG("Successfully created capture thread for device '" << m_Name << "'. Thread id: " << m_CaptureThread.get_id()); + m_CaptureCallbackMode = true; + m_cbOnPacketArrives = std::move(onPacketArrives); + m_cbOnPacketArrivesUserCookie = onPacketArrivesUserCookie; - if (onStatsUpdate != nullptr && intervalInSecondsToUpdateStats > 0) - { - m_cbOnStatsUpdate = std::move(onStatsUpdate); - m_cbOnStatsUpdateUserCookie = onStatsUpdateUserCookie; - m_StatsThread = std::thread(&pcpp::PcapLiveDevice::statsThreadMain, this); - m_StatsThreadStarted = true; - PCPP_LOG_DEBUG("Successfully created stats thread for device '" << m_Name << "'. Thread id: " << m_StatsThread.get_id()); - } + m_CaptureThread = std::thread(&pcpp::PcapLiveDevice::captureThreadMain, this); - return true; -} + // Wait thread to be start + // C++20 = m_CaptureThreadStarted.wait(true); + while (m_CaptureThreadStarted != true) + { + std::this_thread::yield(); + } + PCPP_LOG_DEBUG("Successfully created capture thread for device '" + << m_Name << "'. Thread id: " << m_CaptureThread.get_id()); -bool PcapLiveDevice::startCapture(RawPacketVector& capturedPacketsVector) -{ - if (!m_DeviceOpened || m_PcapDescriptor == nullptr) - { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); - return false; - } + if (onStatsUpdate != nullptr && intervalInSecondsToUpdateStats > 0) + { + m_cbOnStatsUpdate = std::move(onStatsUpdate); + m_cbOnStatsUpdateUserCookie = onStatsUpdateUserCookie; + m_StatsThread = std::thread(&pcpp::PcapLiveDevice::statsThreadMain, this); + m_StatsThreadStarted = true; + PCPP_LOG_DEBUG("Successfully created stats thread for device '" + << m_Name << "'. Thread id: " << m_StatsThread.get_id()); + } - if (captureActive()) - { - PCPP_LOG_ERROR("Device '" << m_Name << "' already capturing traffic"); - return false; + return true; } - m_CapturedPackets = &capturedPacketsVector; - m_CapturedPackets->clear(); + bool PcapLiveDevice::startCapture(RawPacketVector& capturedPacketsVector) + { + if (!m_DeviceOpened || m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); + return false; + } - m_CaptureCallbackMode = false; - m_CaptureThread = std::thread(&pcpp::PcapLiveDevice::captureThreadMain, this); - // Wait thread to be start - // C++20 = m_CaptureThreadStarted.wait(true); - while (m_CaptureThreadStarted != true) { - std::this_thread::yield(); - } + if (captureActive()) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' already capturing traffic"); + return false; + } - PCPP_LOG_DEBUG("Successfully created capture thread for device '" << m_Name << "'. Thread id: " << m_CaptureThread.get_id()); + m_CapturedPackets = &capturedPacketsVector; + m_CapturedPackets->clear(); - return true; -} + m_CaptureCallbackMode = false; + m_CaptureThread = std::thread(&pcpp::PcapLiveDevice::captureThreadMain, this); + // Wait thread to be start + // C++20 = m_CaptureThreadStarted.wait(true); + while (m_CaptureThreadStarted != true) + { + std::this_thread::yield(); + } + PCPP_LOG_DEBUG("Successfully created capture thread for device '" + << m_Name << "'. Thread id: " << m_CaptureThread.get_id()); -int PcapLiveDevice::startCaptureBlockingMode(OnPacketArrivesStopBlocking onPacketArrives, void* userCookie, const double timeout) -{ - if (!m_DeviceOpened || m_PcapDescriptor == nullptr) - { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); - return 0; + return true; } - if (captureActive()) + int PcapLiveDevice::startCaptureBlockingMode(OnPacketArrivesStopBlocking onPacketArrives, void* userCookie, + const double timeout) { - PCPP_LOG_ERROR("Device '" << m_Name << "' already capturing traffic"); - return 0; - } + if (!m_DeviceOpened || m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); + return 0; + } + + if (captureActive()) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' already capturing traffic"); + return 0; + } - m_cbOnPacketArrives = nullptr; - m_cbOnStatsUpdate = nullptr; - m_cbOnPacketArrivesUserCookie = nullptr; - m_cbOnStatsUpdateUserCookie = nullptr; + m_cbOnPacketArrives = nullptr; + m_cbOnStatsUpdate = nullptr; + m_cbOnPacketArrivesUserCookie = nullptr; + m_cbOnStatsUpdateUserCookie = nullptr; - m_cbOnPacketArrivesBlockingMode = std::move(onPacketArrives); - m_cbOnPacketArrivesBlockingModeUserCookie = userCookie; + m_cbOnPacketArrivesBlockingMode = std::move(onPacketArrives); + m_cbOnPacketArrivesBlockingModeUserCookie = userCookie; - m_CaptureThreadStarted = true; - m_StopThread = false; + m_CaptureThreadStarted = true; + m_StopThread = false; - const int64_t timeoutMs = timeout * 1000; // timeout unit is seconds, let's change it to milliseconds - auto startTime = std::chrono::steady_clock::now(); - auto currentTime = startTime; + const int64_t timeoutMs = timeout * 1000; // timeout unit is seconds, let's change it to milliseconds + auto startTime = std::chrono::steady_clock::now(); + auto currentTime = startTime; #if !defined(_WIN32) - struct pollfd pcapPollFd; - memset(&pcapPollFd, 0, sizeof(pcapPollFd)); - pcapPollFd.fd = m_PcapSelectableFd; - pcapPollFd.events = POLLIN; + struct pollfd pcapPollFd; + memset(&pcapPollFd, 0, sizeof(pcapPollFd)); + pcapPollFd.fd = m_PcapSelectableFd; + pcapPollFd.events = POLLIN; #endif - bool shouldReturnError = false; + bool shouldReturnError = false; - if(timeoutMs <= 0) - { - while (!m_StopThread) + if (timeoutMs <= 0) { - if(pcap_dispatch(m_PcapDescriptor, -1, onPacketArrivesBlockingMode, reinterpret_cast(this)) == -1) + while (!m_StopThread) { - PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); - shouldReturnError = true; - m_StopThread = true; + if (pcap_dispatch(m_PcapDescriptor, -1, onPacketArrivesBlockingMode, + reinterpret_cast(this)) == -1) + { + PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + shouldReturnError = true; + m_StopThread = true; + } } } - } - else - { - while (!m_StopThread && std::chrono::duration_cast(currentTime - startTime).count() < timeoutMs ) + else { - if(m_UsePoll) + while (!m_StopThread && + std::chrono::duration_cast(currentTime - startTime).count() < timeoutMs) { + if (m_UsePoll) + { #if !defined(_WIN32) - int64_t pollTimeoutMs = timeoutMs - std::chrono::duration_cast(currentTime - startTime).count(); - pollTimeoutMs = std::max(pollTimeoutMs, (int64_t)0); // poll will be in blocking mode if negative value + int64_t pollTimeoutMs = + timeoutMs - + std::chrono::duration_cast(currentTime - startTime).count(); + // poll will be in blocking mode if negative value + pollTimeoutMs = std::max(pollTimeoutMs, static_cast(0)); - int ready = poll(&pcapPollFd, 1, pollTimeoutMs); // wait the packets until timeout + int ready = poll(&pcapPollFd, 1, pollTimeoutMs); // wait the packets until timeout - if(ready > 0) - { - if(pcap_dispatch(m_PcapDescriptor, -1, onPacketArrivesBlockingMode, reinterpret_cast(this)) == -1) + if (ready > 0) { - PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + if (pcap_dispatch(m_PcapDescriptor, -1, onPacketArrivesBlockingMode, + reinterpret_cast(this)) == -1) + { + PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + shouldReturnError = true; + m_StopThread = true; + } + } + else if (ready < 0) + { + PCPP_LOG_ERROR("poll() got error '" << strerror(errno) << "'"); shouldReturnError = true; m_StopThread = true; } - } - else if(ready < 0) - { - PCPP_LOG_ERROR("poll() got error '" << strerror(errno) << "'"); - shouldReturnError = true; - m_StopThread = true; - } #else - PCPP_LOG_ERROR("Windows doesn't support poll()"); - shouldReturnError = true; - m_StopThread = true; -#endif - } - else - { - if(pcap_dispatch(m_PcapDescriptor, -1, onPacketArrivesBlockingMode, reinterpret_cast(this)) == -1) - { - PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + PCPP_LOG_ERROR("Windows doesn't support poll()"); shouldReturnError = true; m_StopThread = true; +#endif } - } - currentTime = std::chrono::steady_clock::now(); + else + { + if (pcap_dispatch(m_PcapDescriptor, -1, onPacketArrivesBlockingMode, + reinterpret_cast(this)) == -1) + { + PCPP_LOG_ERROR("pcap_dispatch returned an error: " << pcap_geterr(m_PcapDescriptor)); + shouldReturnError = true; + m_StopThread = true; + } + } + currentTime = std::chrono::steady_clock::now(); + } } - } - m_CaptureThreadStarted = false; - m_StopThread = false; - m_cbOnPacketArrivesBlockingMode = nullptr; - m_cbOnPacketArrivesBlockingModeUserCookie = nullptr; + m_CaptureThreadStarted = false; + m_StopThread = false; + m_cbOnPacketArrivesBlockingMode = nullptr; + m_cbOnPacketArrivesBlockingModeUserCookie = nullptr; - if (shouldReturnError) - { - return 0; - } + if (shouldReturnError) + { + return 0; + } - if (std::chrono::duration_cast(currentTime - startTime).count() >= timeoutMs ) - { - return -1; + if (std::chrono::duration_cast(currentTime - startTime).count() >= timeoutMs) + { + return -1; + } + return 1; } - return 1; -} - -void PcapLiveDevice::stopCapture() -{ - // in blocking mode stop capture isn't relevant - if (m_cbOnPacketArrivesBlockingMode != nullptr) - return; - m_StopThread = true; - if (m_CaptureThreadStarted) + void PcapLiveDevice::stopCapture() { - pcap_breakloop(m_PcapDescriptor); - PCPP_LOG_DEBUG("Stopping capture thread, waiting for it to join..."); - m_CaptureThread.join(); - m_CaptureThreadStarted = false; - PCPP_LOG_DEBUG("Capture thread stopped for device '" << m_Name << "'"); - } - PCPP_LOG_DEBUG("Capture thread stopped for device '" << m_Name << "'"); - if (m_StatsThreadStarted) - { - PCPP_LOG_DEBUG("Stopping stats thread, waiting for it to join..."); - m_StatsThread.join(); - m_StatsThreadStarted = false; - PCPP_LOG_DEBUG("Stats thread stopped for device '" << m_Name << "'"); - } - - m_StopThread = false; -} + // in blocking mode stop capture isn't relevant + if (m_cbOnPacketArrivesBlockingMode != nullptr) + return; -bool PcapLiveDevice::captureActive() -{ - return m_CaptureThreadStarted; -} + m_StopThread = true; + if (m_CaptureThreadStarted) + { + pcap_breakloop(m_PcapDescriptor); + PCPP_LOG_DEBUG("Stopping capture thread, waiting for it to join..."); + m_CaptureThread.join(); + m_CaptureThreadStarted = false; + PCPP_LOG_DEBUG("Capture thread stopped for device '" << m_Name << "'"); + } + PCPP_LOG_DEBUG("Capture thread stopped for device '" << m_Name << "'"); + if (m_StatsThreadStarted) + { + PCPP_LOG_DEBUG("Stopping stats thread, waiting for it to join..."); + m_StatsThread.join(); + m_StatsThreadStarted = false; + PCPP_LOG_DEBUG("Stats thread stopped for device '" << m_Name << "'"); + } -void PcapLiveDevice::getStatistics(PcapStats& stats) const -{ - pcap_stat pcapStats; - if (pcap_stats(m_PcapDescriptor, &pcapStats) < 0) - { - PCPP_LOG_ERROR("Error getting statistics from live device '" << m_Name << "'"); + m_StopThread = false; } - stats.packetsRecv = pcapStats.ps_recv; - stats.packetsDrop = pcapStats.ps_drop; - stats.packetsDropByInterface = pcapStats.ps_ifdrop; -} - -bool PcapLiveDevice::doMtuCheck(int packetPayloadLength) const -{ - if (packetPayloadLength > static_cast(m_DeviceMtu)) + bool PcapLiveDevice::captureActive() { - PCPP_LOG_ERROR("Payload length [" << packetPayloadLength << "] is larger than device MTU [" << m_DeviceMtu << "]"); - return false; + return m_CaptureThreadStarted; } - return true; -} -bool PcapLiveDevice::sendPacket(RawPacket const& rawPacket, bool checkMtu) -{ - if (checkMtu) + void PcapLiveDevice::getStatistics(PcapStats& stats) const { - RawPacket* rPacket = const_cast(&rawPacket); - Packet parsedPacket = Packet(rPacket, OsiModelDataLinkLayer); - return sendPacket(&parsedPacket, true); - } - // Send packet without Mtu check - return sendPacket(rawPacket.getRawData(), rawPacket.getRawDataLen()); -} + pcap_stat pcapStats; + if (pcap_stats(m_PcapDescriptor, &pcapStats) < 0) + { + PCPP_LOG_ERROR("Error getting statistics from live device '" << m_Name << "'"); + } -bool PcapLiveDevice::sendPacket(const uint8_t* packetData, int packetDataLength, int packetPayloadLength) -{ - return doMtuCheck(packetPayloadLength) && sendPacket(packetData, packetDataLength); -} + stats.packetsRecv = pcapStats.ps_recv; + stats.packetsDrop = pcapStats.ps_drop; + stats.packetsDropByInterface = pcapStats.ps_ifdrop; + } -bool PcapLiveDevice::sendPacket(const uint8_t* packetData, int packetDataLength, bool checkMtu, pcpp::LinkLayerType linkType) -{ - if (checkMtu) + bool PcapLiveDevice::doMtuCheck(int packetPayloadLength) const { - timeval time; - gettimeofday(&time, nullptr); - pcpp::RawPacket rawPacket(packetData, packetDataLength, time, false, linkType); - Packet parsedPacket = Packet(&rawPacket, pcpp::OsiModelDataLinkLayer); - return sendPacket(&parsedPacket, true); + if (packetPayloadLength > static_cast(m_DeviceMtu)) + { + PCPP_LOG_ERROR("Payload length [" << packetPayloadLength << "] is larger than device MTU [" << m_DeviceMtu + << "]"); + return false; + } + return true; } - if (!m_DeviceOpened) + bool PcapLiveDevice::sendPacket(RawPacket const& rawPacket, bool checkMtu) { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened!"); - return false; + if (checkMtu) + { + RawPacket* rPacket = const_cast(&rawPacket); + Packet parsedPacket = Packet(rPacket, OsiModelDataLinkLayer); + return sendPacket(&parsedPacket, true); + } + // Send packet without Mtu check + return sendPacket(rawPacket.getRawData(), rawPacket.getRawDataLen()); } - if (packetDataLength == 0) + bool PcapLiveDevice::sendPacket(const uint8_t* packetData, int packetDataLength, int packetPayloadLength) { - PCPP_LOG_ERROR("Trying to send a packet with length 0"); - return false; + return doMtuCheck(packetPayloadLength) && sendPacket(packetData, packetDataLength); } - if (pcap_sendpacket(m_PcapSendDescriptor, packetData, packetDataLength) == -1) + bool PcapLiveDevice::sendPacket(const uint8_t* packetData, int packetDataLength, bool checkMtu, + pcpp::LinkLayerType linkType) { - PCPP_LOG_ERROR("Error sending packet: " << pcap_geterr(m_PcapSendDescriptor)); - return false; - } + if (checkMtu) + { + timeval time; + gettimeofday(&time, nullptr); + pcpp::RawPacket rawPacket(packetData, packetDataLength, time, false, linkType); + Packet parsedPacket = Packet(&rawPacket, pcpp::OsiModelDataLinkLayer); + return sendPacket(&parsedPacket, true); + } - PCPP_LOG_DEBUG("Packet sent successfully. Packet length: " << packetDataLength); - return true; -} + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened!"); + return false; + } -bool PcapLiveDevice::sendPacket(Packet* packet, bool checkMtu) -{ - RawPacket* rawPacket = packet->getRawPacket(); - if (checkMtu) + if (packetDataLength == 0) + { + PCPP_LOG_ERROR("Trying to send a packet with length 0"); + return false; + } + + if (pcap_sendpacket(m_PcapSendDescriptor, packetData, packetDataLength) == -1) + { + PCPP_LOG_ERROR("Error sending packet: " << pcap_geterr(m_PcapSendDescriptor)); + return false; + } + + PCPP_LOG_DEBUG("Packet sent successfully. Packet length: " << packetDataLength); + return true; + } + + bool PcapLiveDevice::sendPacket(Packet* packet, bool checkMtu) { - int packetPayloadLength = 0; - switch (packet->getFirstLayer()->getOsiModelLayer()) + RawPacket* rawPacket = packet->getRawPacket(); + if (checkMtu) { + int packetPayloadLength = 0; + switch (packet->getFirstLayer()->getOsiModelLayer()) + { case (pcpp::OsiModelDataLinkLayer): packetPayloadLength = static_cast(packet->getFirstLayer()->getLayerPayloadSize()); break; @@ -759,502 +788,507 @@ bool PcapLiveDevice::sendPacket(Packet* packet, bool checkMtu) default: // if packet layer is not known, do not perform MTU check. return sendPacket(*rawPacket, false); + } + return doMtuCheck(packetPayloadLength) && sendPacket(*rawPacket, false); } - return doMtuCheck(packetPayloadLength) && sendPacket(*rawPacket, false); + return sendPacket(*rawPacket, false); } - return sendPacket(*rawPacket, false); -} -int PcapLiveDevice::sendPackets(RawPacket* rawPacketsArr, int arrLength, bool checkMtu) -{ - int packetsSent = 0; - for (int i = 0; i < arrLength; i++) + int PcapLiveDevice::sendPackets(RawPacket* rawPacketsArr, int arrLength, bool checkMtu) { - if (sendPacket(rawPacketsArr[i], checkMtu)) - packetsSent++; - } + int packetsSent = 0; + for (int i = 0; i < arrLength; i++) + { + if (sendPacket(rawPacketsArr[i], checkMtu)) + packetsSent++; + } - PCPP_LOG_DEBUG(packetsSent << " packets sent successfully. " << arrLength-packetsSent << " packets not sent"); - return packetsSent; -} + PCPP_LOG_DEBUG(packetsSent << " packets sent successfully. " << arrLength - packetsSent << " packets not sent"); + return packetsSent; + } -int PcapLiveDevice::sendPackets(Packet** packetsArr, int arrLength, bool checkMtu) -{ - int packetsSent = 0; - for (int i = 0; i < arrLength; i++) + int PcapLiveDevice::sendPackets(Packet** packetsArr, int arrLength, bool checkMtu) { - if (sendPacket(packetsArr[i], checkMtu)) - packetsSent++; - } + int packetsSent = 0; + for (int i = 0; i < arrLength; i++) + { + if (sendPacket(packetsArr[i], checkMtu)) + packetsSent++; + } - PCPP_LOG_DEBUG(packetsSent << " packets sent successfully. " << arrLength-packetsSent << " packets not sent"); - return packetsSent; -} + PCPP_LOG_DEBUG(packetsSent << " packets sent successfully. " << arrLength - packetsSent << " packets not sent"); + return packetsSent; + } -int PcapLiveDevice::sendPackets(const RawPacketVector& rawPackets, bool checkMtu) -{ - int packetsSent = 0; - for (RawPacketVector::ConstVectorIterator iter = rawPackets.begin(); iter != rawPackets.end(); iter++) + int PcapLiveDevice::sendPackets(const RawPacketVector& rawPackets, bool checkMtu) { - if (sendPacket(**iter, checkMtu)) - packetsSent++; - } + int packetsSent = 0; + for (RawPacketVector::ConstVectorIterator iter = rawPackets.begin(); iter != rawPackets.end(); iter++) + { + if (sendPacket(**iter, checkMtu)) + packetsSent++; + } - PCPP_LOG_DEBUG(packetsSent << " packets sent successfully. " << (rawPackets.size()-packetsSent) << " packets not sent"); - return packetsSent; -} + PCPP_LOG_DEBUG(packetsSent << " packets sent successfully. " << (rawPackets.size() - packetsSent) + << " packets not sent"); + return packetsSent; + } -void PcapLiveDevice::setDeviceMtu() -{ + void PcapLiveDevice::setDeviceMtu() + { #if defined(_WIN32) - if (m_IsLoopback) - { - PCPP_LOG_DEBUG("Npcap Loopback Adapter - MTU is insignificant, setting MTU to max value (0xffffffff)"); - m_DeviceMtu = 0xffffffff; - return; - } + if (m_IsLoopback) + { + PCPP_LOG_DEBUG("Npcap Loopback Adapter - MTU is insignificant, setting MTU to max value (0xffffffff)"); + m_DeviceMtu = 0xffffffff; + return; + } - uint32_t mtuValue = 0; - LPADAPTER adapter = PacketOpenAdapter(const_cast(m_Name.c_str())); - if (adapter == NULL) - { - PCPP_LOG_ERROR("Error in retrieving MTU: Adapter is NULL"); - return; - } + uint32_t mtuValue = 0; + LPADAPTER adapter = PacketOpenAdapter(const_cast(m_Name.c_str())); + if (adapter == NULL) + { + PCPP_LOG_ERROR("Error in retrieving MTU: Adapter is NULL"); + return; + } - uint8_t buffer[512]; - PACKET_OID_DATA* oidData = reinterpret_cast(buffer); - oidData->Oid = OID_GEN_MAXIMUM_TOTAL_SIZE; - oidData->Length = sizeof(uint32_t); - memcpy(oidData->Data, &mtuValue, sizeof(uint32_t)); - if (PacketRequest(adapter, false, oidData)) - { - if (oidData->Length <= sizeof(uint32_t)) - { - /* 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. - // TODO: think of a better way to always get the right value - if (mtuValue == 1514) + uint8_t buffer[512]; + PACKET_OID_DATA* oidData = reinterpret_cast(buffer); + oidData->Oid = OID_GEN_MAXIMUM_TOTAL_SIZE; + oidData->Length = sizeof(uint32_t); + memcpy(oidData->Data, &mtuValue, sizeof(uint32_t)); + if (PacketRequest(adapter, false, oidData)) + { + if (oidData->Length <= sizeof(uint32_t)) + { + /* 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. + // TODO: think of a better way to always get the right value + if (mtuValue == 1514) + { + mtuValue = 1500; + } + m_DeviceMtu = mtuValue; + } + else { - mtuValue = 1500; + /* 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; } - m_DeviceMtu = mtuValue; } else { - /* 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; + PCPP_LOG_ERROR("Error in retrieving MTU: PacketRequest failed"); } - } - else - { - PCPP_LOG_ERROR("Error in retrieving MTU: PacketRequest failed"); - } #else - struct ifreq ifr; + struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, m_Name.c_str(), sizeof(ifr.ifr_name) - 1); + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, m_Name.c_str(), sizeof(ifr.ifr_name) - 1); - int socketfd = -1; - try - { - socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (ioctl(socketfd, SIOCGIFMTU, &ifr) == -1) + int socketfd = -1; + try + { + socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (ioctl(socketfd, SIOCGIFMTU, &ifr) == -1) + { + PCPP_LOG_DEBUG("Error in retrieving MTU: ioctl() returned -1"); + m_DeviceMtu = 0; + return; + } + m_DeviceMtu = ifr.ifr_mtu; + } + catch (const std::exception& e) { - PCPP_LOG_DEBUG("Error in retrieving MTU: ioctl() returned -1"); + PCPP_LOG_ERROR("Error in retrieving MTU: " << e.what()); m_DeviceMtu = 0; - return; } - m_DeviceMtu = ifr.ifr_mtu; - } - catch(const std::exception& e) - { - PCPP_LOG_ERROR("Error in retrieving MTU: " << e.what()); - m_DeviceMtu = 0; - } - if(socketfd != -1) - { - ::close(socketfd); - } + if (socketfd != -1) + { + ::close(socketfd); + } #endif -} + } -void PcapLiveDevice::setDeviceMacAddress() -{ + void PcapLiveDevice::setDeviceMacAddress() + { #if defined(_WIN32) - LPADAPTER adapter = PacketOpenAdapter(const_cast(m_Name.c_str())); - if (adapter == NULL) - { - PCPP_LOG_ERROR("Error in retrieving MAC address: Adapter is NULL"); - return; - } + LPADAPTER adapter = PacketOpenAdapter(const_cast(m_Name.c_str())); + if (adapter == NULL) + { + PCPP_LOG_ERROR("Error in retrieving MAC address: Adapter is NULL"); + return; + } - uint8_t buffer[512]; - PACKET_OID_DATA* oidData = reinterpret_cast(buffer); - oidData->Oid = OID_802_3_CURRENT_ADDRESS; - oidData->Length = 6; - oidData->Data[0] = 0; - if (PacketRequest(adapter, false, oidData)) - { - if (oidData->Length == 6) + uint8_t buffer[512]; + PACKET_OID_DATA* oidData = reinterpret_cast(buffer); + oidData->Oid = OID_802_3_CURRENT_ADDRESS; + oidData->Length = 6; + oidData->Data[0] = 0; + if (PacketRequest(adapter, false, oidData)) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warray-bounds" - /* 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 - PCPP_LOG_DEBUG(" MAC address: " << m_MacAddress); + if (oidData->Length == 6) + { +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Warray-bounds" + /* 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 + PCPP_LOG_DEBUG(" MAC address: " << m_MacAddress); + } + else + { + /* 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; + } } else { - /* 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; + PCPP_LOG_DEBUG("Error in retrieving MAC address: PacketRequest failed"); } - } - else - { - PCPP_LOG_DEBUG("Error in retrieving MAC address: PacketRequest failed"); - } #elif defined(__linux__) - struct ifreq ifr; + struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, m_Name.c_str(), sizeof(ifr.ifr_name) - 1); + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, m_Name.c_str(), sizeof(ifr.ifr_name) - 1); + int socketfd = -1; + try + { + socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (ioctl(socketfd, SIOCGIFHWADDR, &ifr) == -1) + { + PCPP_LOG_DEBUG("Error in retrieving MAC address: ioctl() returned -1"); + return; + } - int socketfd = -1; - try - { - socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (ioctl(socketfd, SIOCGIFHWADDR, &ifr) == -1) + m_MacAddress = MacAddress(ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2], + ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); + } + catch (const std::exception& e) { - PCPP_LOG_DEBUG("Error in retrieving MAC address: ioctl() returned -1"); - return; + PCPP_LOG_ERROR("Error in retrieving MAC address: " << e.what()); } - m_MacAddress = MacAddress(ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1], ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3], ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]); - } - catch(const std::exception& e) - { - PCPP_LOG_ERROR("Error in retrieving MAC address: " << e.what()); - } - - if(socketfd != -1) - { - ::close(socketfd); - } + if (socketfd != -1) + { + ::close(socketfd); + } #elif defined(__APPLE__) || defined(__FreeBSD__) - int mib[6]; - size_t len; - - mib[0] = CTL_NET; - mib[1] = AF_ROUTE; - mib[2] = 0; - mib[3] = AF_LINK; - mib[4] = NET_RT_IFLIST; - mib[5] = if_nametoindex(m_Name.c_str()); - - if (mib[5] == 0){ - PCPP_LOG_DEBUG("Error in retrieving MAC address: if_nametoindex error"); - return; - } + int mib[6]; + size_t len; - if (sysctl(mib, 6, nullptr, &len, nullptr, 0) < 0) - { - PCPP_LOG_DEBUG("Error in retrieving MAC address: sysctl 1 error"); - return; - } + mib[0] = CTL_NET; + mib[1] = AF_ROUTE; + mib[2] = 0; + mib[3] = AF_LINK; + mib[4] = NET_RT_IFLIST; + mib[5] = if_nametoindex(m_Name.c_str()); - uint8_t buf[len]; + if (mib[5] == 0) + { + PCPP_LOG_DEBUG("Error in retrieving MAC address: if_nametoindex error"); + return; + } - if (sysctl(mib, 6, buf, &len, nullptr, 0) < 0) - { - PCPP_LOG_DEBUG("Error in retrieving MAC address: sysctl 2 error"); - return; - } + if (sysctl(mib, 6, nullptr, &len, nullptr, 0) < 0) + { + PCPP_LOG_DEBUG("Error in retrieving MAC address: sysctl 1 error"); + return; + } + + uint8_t buf[len]; - struct if_msghdr*ifm = (struct if_msghdr *)buf; - struct sockaddr_dl* sdl = (struct sockaddr_dl *)(ifm + 1); - uint8_t* ptr = (uint8_t*)LLADDR(sdl); - m_MacAddress = MacAddress(ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + if (sysctl(mib, 6, buf, &len, nullptr, 0) < 0) + { + PCPP_LOG_DEBUG("Error in retrieving MAC address: sysctl 2 error"); + return; + } + + struct if_msghdr* ifm = (struct if_msghdr*)buf; + struct sockaddr_dl* sdl = (struct sockaddr_dl*)(ifm + 1); + uint8_t* ptr = (uint8_t*)LLADDR(sdl); + m_MacAddress = MacAddress(ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); #endif -} + } -void PcapLiveDevice::setDefaultGateway() -{ + void PcapLiveDevice::setDefaultGateway() + { #if defined(_WIN32) - ULONG outBufLen = sizeof (IP_ADAPTER_INFO); - std::vector buffer(outBufLen); - PIP_ADAPTER_INFO adapterInfo = reinterpret_cast(buffer.data()); - DWORD retVal = 0; + ULONG outBufLen = sizeof(IP_ADAPTER_INFO); + std::vector buffer(outBufLen); + PIP_ADAPTER_INFO adapterInfo = reinterpret_cast(buffer.data()); + DWORD retVal = 0; - retVal = GetAdaptersInfo(adapterInfo, &outBufLen); - if (retVal == ERROR_BUFFER_OVERFLOW) - { - buffer.resize(outBufLen); - // Repins the adapter info pointer to the vector data pointer as the vector might be reallocated during the resize. - adapterInfo = reinterpret_cast(buffer.data()); retVal = GetAdaptersInfo(adapterInfo, &outBufLen); - } + if (retVal == ERROR_BUFFER_OVERFLOW) + { + buffer.resize(outBufLen); + // Repins the adapter info pointer to the vector data pointer as the vector might be reallocated during the + // resize. + adapterInfo = reinterpret_cast(buffer.data()); + retVal = GetAdaptersInfo(adapterInfo, &outBufLen); + } - if (retVal == NO_ERROR) - { - PIP_ADAPTER_INFO curAdapterInfo = adapterInfo; - while (curAdapterInfo != NULL) + if (retVal == NO_ERROR) { - if (m_Name.find(curAdapterInfo->AdapterName) != std::string::npos) + PIP_ADAPTER_INFO curAdapterInfo = adapterInfo; + while (curAdapterInfo != NULL) { - try - { - m_DefaultGateway = IPv4Address(curAdapterInfo->GatewayList.IpAddress.String); - } - catch(const std::exception& e) + if (m_Name.find(curAdapterInfo->AdapterName) != std::string::npos) { - PCPP_LOG_ERROR("Error retrieving default gateway address: " << e.what()); + try + { + m_DefaultGateway = IPv4Address(curAdapterInfo->GatewayList.IpAddress.String); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: " << e.what()); + } + break; } - break; - } - curAdapterInfo = curAdapterInfo->Next; + curAdapterInfo = curAdapterInfo->Next; + } } - } - else - { - PCPP_LOG_ERROR("Error retrieving default gateway address"); - } -#elif defined(__linux__) - std::ifstream routeFile("/proc/net/route"); - std::string line; - while (std::getline(routeFile, line)) - { - std::stringstream lineStream(line); - std::string interfaceName; - std::getline(lineStream, interfaceName, '\t'); - if (interfaceName != m_Name) - continue; - - std::string interfaceDest; - std::getline(lineStream, interfaceDest, '\t'); - if (interfaceDest != "00000000") - continue; - - std::string interfaceGateway; - std::getline(lineStream, interfaceGateway, '\t'); - - uint32_t interfaceGatewayIPInt; - std::stringstream interfaceGatewayStream; - interfaceGatewayStream << std::hex << interfaceGateway; - interfaceGatewayStream >> interfaceGatewayIPInt; - try + else { - m_DefaultGateway = IPv4Address(interfaceGatewayIPInt); + PCPP_LOG_ERROR("Error retrieving default gateway address"); } - catch(const std::exception& e) +#elif defined(__linux__) + std::ifstream routeFile("/proc/net/route"); + std::string line; + while (std::getline(routeFile, line)) { - PCPP_LOG_ERROR("Error retrieving default gateway address: " << e.what()); + std::stringstream lineStream(line); + std::string interfaceName; + std::getline(lineStream, interfaceName, '\t'); + if (interfaceName != m_Name) + continue; + + std::string interfaceDest; + std::getline(lineStream, interfaceDest, '\t'); + if (interfaceDest != "00000000") + continue; + + std::string interfaceGateway; + std::getline(lineStream, interfaceGateway, '\t'); + + uint32_t interfaceGatewayIPInt; + std::stringstream interfaceGatewayStream; + interfaceGatewayStream << std::hex << interfaceGateway; + interfaceGatewayStream >> interfaceGatewayIPInt; + try + { + m_DefaultGateway = IPv4Address(interfaceGatewayIPInt); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: " << e.what()); + } } - } #elif defined(__APPLE__) - //route message struct for communication in APPLE device - struct BSDRoutingMessage - { - struct rt_msghdr header; - char messageSpace[512]; - }; - - struct BSDRoutingMessage routingMessage; - // It creates a raw socket that can be used for routing-related operations - int sockfd = socket(PF_ROUTE, SOCK_RAW, 0); - if (sockfd < 0) - { - PCPP_LOG_ERROR("Error retrieving default gateway address: couldn't get open routing socket"); - return ; - } - memset(reinterpret_cast(&routingMessage), 0, sizeof(routingMessage)); - routingMessage.header.rtm_msglen = sizeof(struct rt_msghdr); - routingMessage.header.rtm_version = RTM_VERSION; - routingMessage.header.rtm_type = RTM_GET; - routingMessage.header.rtm_addrs = RTA_DST | RTA_NETMASK ; - routingMessage.header.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; - routingMessage.header.rtm_msglen += 2 * sizeof(sockaddr_in); - - if (write(sockfd, reinterpret_cast(&routingMessage), routingMessage.header.rtm_msglen) < 0) - { - PCPP_LOG_ERROR("Error retrieving default gateway address: couldn't write into the routing socket"); - return; - } + // route message struct for communication in APPLE device + struct BSDRoutingMessage + { + struct rt_msghdr header; + char messageSpace[512]; + }; + + struct BSDRoutingMessage routingMessage; + // It creates a raw socket that can be used for routing-related operations + int sockfd = socket(PF_ROUTE, SOCK_RAW, 0); + if (sockfd < 0) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: couldn't get open routing socket"); + return; + } + memset(reinterpret_cast(&routingMessage), 0, sizeof(routingMessage)); + routingMessage.header.rtm_msglen = sizeof(struct rt_msghdr); + routingMessage.header.rtm_version = RTM_VERSION; + routingMessage.header.rtm_type = RTM_GET; + routingMessage.header.rtm_addrs = RTA_DST | RTA_NETMASK; + routingMessage.header.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; + routingMessage.header.rtm_msglen += 2 * sizeof(sockaddr_in); + + if (write(sockfd, reinterpret_cast(&routingMessage), routingMessage.header.rtm_msglen) < 0) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: couldn't write into the routing socket"); + return; + } - // Read the response from the route socket - if (read(sockfd, reinterpret_cast(&routingMessage), sizeof(routingMessage)) < 0) - { - PCPP_LOG_ERROR("Error retrieving default gateway address: couldn't read from the routing socket"); - return; - } + // Read the response from the route socket + if (read(sockfd, reinterpret_cast(&routingMessage), sizeof(routingMessage)) < 0) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: couldn't read from the routing socket"); + return; + } - struct in_addr *gateAddr = nullptr; - struct sockaddr *sa = nullptr; - char* spacePtr = (reinterpret_cast(&routingMessage.header + 1)); - auto rtmAddrs = routingMessage.header.rtm_addrs; - int index = 1; - auto roundUpClosestMultiple = [](int multiple, int num) { - return ((num+multiple - 1) / multiple) * multiple; - }; - while (rtmAddrs) - { - if (rtmAddrs & 1) + struct in_addr* gateAddr = nullptr; + struct sockaddr* sa = nullptr; + char* spacePtr = (reinterpret_cast(&routingMessage.header + 1)); + auto rtmAddrs = routingMessage.header.rtm_addrs; + int index = 1; + auto roundUpClosestMultiple = [](int multiple, int num) { + return ((num + multiple - 1) / multiple) * multiple; + }; + while (rtmAddrs) { - sa = reinterpret_cast(spacePtr); - if (index == RTA_GATEWAY) + if (rtmAddrs & 1) { - gateAddr = internal::sockaddr2in_addr(sa); - break; + sa = reinterpret_cast(spacePtr); + if (index == RTA_GATEWAY) + { + gateAddr = internal::sockaddr2in_addr(sa); + break; + } + spacePtr += sa->sa_len > 0 ? roundUpClosestMultiple(sizeof(uint32_t), sa->sa_len) : sizeof(uint32_t); } - spacePtr += sa->sa_len > 0 ? roundUpClosestMultiple(sizeof(uint32_t), sa->sa_len) : sizeof(uint32_t); + index++; + rtmAddrs >>= 1; } - index++; - rtmAddrs >>= 1; - } - if (gateAddr == nullptr) - { - PCPP_LOG_ERROR("Error retrieving default gateway address: Empty Message related to gate"); - return; - } - try - { - m_DefaultGateway = IPv4Address(gateAddr->s_addr); - } - catch(const std::exception& e) - { - PCPP_LOG_ERROR("Error retrieving default gateway address: "<< inet_ntoa(*gateAddr) << ": " << e.what()); - } + if (gateAddr == nullptr) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: Empty Message related to gate"); + return; + } + try + { + m_DefaultGateway = IPv4Address(gateAddr->s_addr); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR("Error retrieving default gateway address: " << inet_ntoa(*gateAddr) << ": " << e.what()); + } #elif defined(__FreeBSD__) - std::string command = "netstat -nr | grep default | grep " + m_Name; - std::string ifaceInfo = executeShellCommand(command); - if (ifaceInfo == "") - { - PCPP_LOG_DEBUG("Error retrieving default gateway address: couldn't get netstat output"); - return; - } - - // remove the word "default" - ifaceInfo.erase(0, 7); + std::string command = "netstat -nr | grep default | grep " + m_Name; + std::string ifaceInfo = executeShellCommand(command); + if (ifaceInfo == "") + { + PCPP_LOG_DEBUG("Error retrieving default gateway address: couldn't get netstat output"); + return; + } - // remove spaces - while (ifaceInfo.at(0) == ' ') - ifaceInfo.erase(0,1); + // remove the word "default" + ifaceInfo.erase(0, 7); - // erase string after gateway IP address - ifaceInfo.resize(ifaceInfo.find(' ', 0)); + // remove spaces + while (ifaceInfo.at(0) == ' ') + ifaceInfo.erase(0, 1); - try - { - m_DefaultGateway = IPv4Address(ifaceInfo); - } - catch(const std::exception& e) - { - PCPP_LOG_ERROR("Error retrieving default gateway address: "<< ifaceInfo << ": " << e.what()); - } -#endif -} + // erase string after gateway IP address + ifaceInfo.resize(ifaceInfo.find(' ', 0)); -std::vector PcapLiveDevice::getIPAddresses() const -{ - std::vector results; - for (const auto& address : m_Addresses) - { - in_addr* ipv4Addr = internal::try_sockaddr2in_addr(address.addr); - if (ipv4Addr != nullptr) + try { - results.push_back(IPv4Address(ipv4Addr->s_addr)); - continue; + m_DefaultGateway = IPv4Address(ifaceInfo); } - - in6_addr* ipv6Addr = internal::try_sockaddr2in6_addr(address.addr); - if (ipv6Addr != nullptr) + catch (const std::exception& e) { - results.push_back(IPv6Address(ipv6Addr->s6_addr)); - continue; + PCPP_LOG_ERROR("Error retrieving default gateway address: " << ifaceInfo << ": " << e.what()); } +#endif } - return results; -} - -IPv4Address PcapLiveDevice::getIPv4Address() const -{ - for(const auto& addrIter : m_Addresses) + std::vector PcapLiveDevice::getIPAddresses() const { - if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addrIter.addr != nullptr) + std::vector results; + for (const auto& address : m_Addresses) { - std::array addrAsString; - internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); - } + in_addr* ipv4Addr = internal::try_sockaddr2in_addr(address.addr); + if (ipv4Addr != nullptr) + { + results.push_back(IPv4Address(ipv4Addr->s_addr)); + continue; + } - in_addr* currAddr = internal::try_sockaddr2in_addr(addrIter.addr); - if (currAddr == nullptr) - { - PCPP_LOG_DEBUG("Address is NULL"); - continue; + in6_addr* ipv6Addr = internal::try_sockaddr2in6_addr(address.addr); + if (ipv6Addr != nullptr) + { + results.push_back(IPv6Address(ipv6Addr->s6_addr)); + continue; + } } - try - { - return IPv4Address(currAddr->s_addr); - } - catch (const std::exception&) - { - continue; - } + return results; } - return IPv4Address::Zero; -} - -IPv6Address PcapLiveDevice::getIPv6Address() const -{ - for (const auto& addrIter : m_Addresses) + IPv4Address PcapLiveDevice::getIPv4Address() const { - if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addrIter.addr != nullptr) + for (const auto& addrIter : m_Addresses) { - std::array addrAsString; - internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addrIter.addr != nullptr) + { + std::array addrAsString; + internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + } + + in_addr* currAddr = internal::try_sockaddr2in_addr(addrIter.addr); + if (currAddr == nullptr) + { + PCPP_LOG_DEBUG("Address is NULL"); + continue; + } + + try + { + return IPv4Address(currAddr->s_addr); + } + catch (const std::exception&) + { + continue; + } } - in6_addr *currAddr = internal::try_sockaddr2in6_addr(addrIter.addr); - if (currAddr == nullptr) + + return IPv4Address::Zero; + } + + IPv6Address PcapLiveDevice::getIPv6Address() const + { + for (const auto& addrIter : m_Addresses) { - PCPP_LOG_DEBUG("Address is NULL"); - continue; + if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addrIter.addr != nullptr) + { + std::array addrAsString; + internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + } + in6_addr* currAddr = internal::try_sockaddr2in6_addr(addrIter.addr); + if (currAddr == nullptr) + { + PCPP_LOG_DEBUG("Address is NULL"); + continue; + } + return IPv6Address(currAddr->s6_addr); } - return IPv6Address(currAddr->s6_addr); + return IPv6Address::Zero; } - return IPv6Address::Zero; -} -IPv4Address PcapLiveDevice::getDefaultGateway() const -{ - return m_DefaultGateway; -} + IPv4Address PcapLiveDevice::getDefaultGateway() const + { + return m_DefaultGateway; + } -const std::vector& PcapLiveDevice::getDnsServers() const -{ - return PcapLiveDeviceList::getInstance().getDnsServers(); -} + const std::vector& PcapLiveDevice::getDnsServers() const + { + return PcapLiveDeviceList::getInstance().getDnsServers(); + } -PcapLiveDevice::~PcapLiveDevice() -{ -} + PcapLiveDevice::~PcapLiveDevice() + {} -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/src/PcapLiveDeviceList.cpp b/Pcap++/src/PcapLiveDeviceList.cpp index 8763d536a1..e65cd23d2f 100644 --- a/Pcap++/src/PcapLiveDeviceList.cpp +++ b/Pcap++/src/PcapLiveDeviceList.cpp @@ -13,391 +13,395 @@ #include #include #if defined(_WIN32) -#include -#include -#include "WinPcapLiveDevice.h" +# include +# include +# include "WinPcapLiveDevice.h" #elif defined(__APPLE__) -#include +# include #elif defined(__FreeBSD__) -#include -#include +# include +# include #endif - namespace pcpp { namespace { - void syncPointerVectors(std::vector> const& mainVector, std::vector& viewVector) + void syncPointerVectors(std::vector> const& mainVector, + std::vector& viewVector) { viewVector.resize(mainVector.size()); // Full update of all elements of the view vector to synchronize them with the main vector. std::transform(mainVector.begin(), mainVector.end(), viewVector.begin(), [](const std::unique_ptr& ptr) { return ptr.get(); }); } - } + } // namespace -PcapLiveDeviceList::PcapLiveDeviceList() : m_LiveDeviceList(fetchAllLocalDevices()), m_DnsServers(fetchDnsServers()) -{ - syncPointerVectors(m_LiveDeviceList, m_LiveDeviceListView); -} - -std::vector> PcapLiveDeviceList::fetchAllLocalDevices() -{ - std::vector> deviceList; - std::unique_ptr interfaceList; - try + PcapLiveDeviceList::PcapLiveDeviceList() : m_LiveDeviceList(fetchAllLocalDevices()), m_DnsServers(fetchDnsServers()) { - interfaceList = internal::getAllLocalPcapDevices(); - } - catch (const std::exception& e) - { - PCPP_LOG_ERROR(e.what()); + syncPointerVectors(m_LiveDeviceList, m_LiveDeviceListView); } - PCPP_LOG_DEBUG("Pcap lib version info: " << IPcapDevice::getPcapLibVersionInfo()); + std::vector> PcapLiveDeviceList::fetchAllLocalDevices() + { + std::vector> deviceList; + std::unique_ptr interfaceList; + try + { + interfaceList = internal::getAllLocalPcapDevices(); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR(e.what()); + } + PCPP_LOG_DEBUG("Pcap lib version info: " << IPcapDevice::getPcapLibVersionInfo()); - for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next) - { + for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; + currInterface = currInterface->next) + { #if defined(_WIN32) - auto dev = std::unique_ptr(new WinPcapLiveDevice(currInterface, true, true, true)); -#else //__linux__, __APPLE__, __FreeBSD__ - auto dev = std::unique_ptr(new PcapLiveDevice(currInterface, true, true, true)); + auto dev = std::unique_ptr(new WinPcapLiveDevice(currInterface, true, true, true)); +#else //__linux__, __APPLE__, __FreeBSD__ + auto dev = std::unique_ptr(new PcapLiveDevice(currInterface, true, true, true)); #endif - deviceList.push_back(std::move(dev)); + deviceList.push_back(std::move(dev)); + } + return deviceList; } - return deviceList; -} -std::vector PcapLiveDeviceList::fetchDnsServers() -{ - std::vector dnsServers; -#if defined(_WIN32) - FIXED_INFO* fixedInfo; - ULONG ulOutBufLen; - DWORD dwRetVal; - IP_ADDR_STRING* pIPAddr; - - std::array bufferOnStack; - fixedInfo = reinterpret_cast(bufferOnStack.data()); - ulOutBufLen = bufferOnStack.size(); - - dwRetVal = GetNetworkParams( fixedInfo, &ulOutBufLen ); - std::vector bufferOnHeap; - if(ERROR_BUFFER_OVERFLOW == dwRetVal) + std::vector PcapLiveDeviceList::fetchDnsServers() { - // Stack buffer was not enough. Allocating a heap buffer. - bufferOnHeap.resize(ulOutBufLen); - fixedInfo = reinterpret_cast(bufferOnHeap.data()); - ulOutBufLen = bufferOnHeap.size(); - // Retrying to get network info. - dwRetVal = GetNetworkParams(fixedInfo, &ulOutBufLen); - } + std::vector dnsServers; +#if defined(_WIN32) + FIXED_INFO* fixedInfo; + ULONG ulOutBufLen; + DWORD dwRetVal; + IP_ADDR_STRING* pIPAddr; - if (dwRetVal != 0) - PCPP_LOG_ERROR("Call to GetNetworkParams failed. Return Value: " << std::hex << dwRetVal); - else - { - int dnsServerCounter = 0; - try - { - dnsServers.push_back(IPv4Address(fixedInfo->DnsServerList.IpAddress.String)); - PCPP_LOG_DEBUG("Default DNS server IP #" << dnsServerCounter++ << ": " << fixedInfo->DnsServerList.IpAddress.String); - } - catch(const std::exception&) + std::array bufferOnStack; + fixedInfo = reinterpret_cast(bufferOnStack.data()); + ulOutBufLen = bufferOnStack.size(); + + dwRetVal = GetNetworkParams(fixedInfo, &ulOutBufLen); + std::vector bufferOnHeap; + if (ERROR_BUFFER_OVERFLOW == dwRetVal) { - PCPP_LOG_DEBUG("Failed to parse default DNS server IP address: " << fixedInfo->DnsServerList.IpAddress.String); + // Stack buffer was not enough. Allocating a heap buffer. + bufferOnHeap.resize(ulOutBufLen); + fixedInfo = reinterpret_cast(bufferOnHeap.data()); + ulOutBufLen = bufferOnHeap.size(); + // Retrying to get network info. + dwRetVal = GetNetworkParams(fixedInfo, &ulOutBufLen); } - pIPAddr = fixedInfo->DnsServerList.Next; - while ( pIPAddr ) + if (dwRetVal != 0) + PCPP_LOG_ERROR("Call to GetNetworkParams failed. Return Value: " << std::hex << dwRetVal); + else { + int dnsServerCounter = 0; try { - dnsServers.push_back(IPv4Address(pIPAddr->IpAddress.String)); - PCPP_LOG_DEBUG("Default DNS server IP #" << dnsServerCounter++ << ": " << pIPAddr->IpAddress.String); + dnsServers.push_back(IPv4Address(fixedInfo->DnsServerList.IpAddress.String)); + PCPP_LOG_DEBUG("Default DNS server IP #" << dnsServerCounter++ << ": " + << fixedInfo->DnsServerList.IpAddress.String); } - catch(const std::exception&) + catch (const std::exception&) + { + PCPP_LOG_DEBUG( + "Failed to parse default DNS server IP address: " << fixedInfo->DnsServerList.IpAddress.String); + } + + pIPAddr = fixedInfo->DnsServerList.Next; + while (pIPAddr) { - PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << pIPAddr->IpAddress.String); + try + { + dnsServers.push_back(IPv4Address(pIPAddr->IpAddress.String)); + PCPP_LOG_DEBUG("Default DNS server IP #" << dnsServerCounter++ << ": " + << pIPAddr->IpAddress.String); + } + catch (const std::exception&) + { + PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << pIPAddr->IpAddress.String); + } + pIPAddr = pIPAddr->Next; } - pIPAddr = pIPAddr -> Next; } - } #elif defined(__linux__) - // verify that nmcli exist - std::string command = "command -v nmcli >/dev/null 2>&1 || { echo 'nmcli not installed'; }"; - std::string nmcliExists = executeShellCommand(command); - if (nmcliExists != "") - { - PCPP_LOG_DEBUG("Error retrieving DNS server list: nmcli doesn't exist"); - return {}; - } + // verify that nmcli exist + std::string command = "command -v nmcli >/dev/null 2>&1 || { echo 'nmcli not installed'; }"; + std::string nmcliExists = executeShellCommand(command); + if (nmcliExists != "") + { + PCPP_LOG_DEBUG("Error retrieving DNS server list: nmcli doesn't exist"); + return {}; + } - // check nmcli major version (0 or 1) - command = "nmcli -v | awk -F' ' '{print $NF}' | awk -F'.' '{print $1}'"; - std::string nmcliMajorVer = executeShellCommand(command); - nmcliMajorVer.erase(std::remove(nmcliMajorVer.begin(), nmcliMajorVer.end(), '\n'), nmcliMajorVer.end()); - PCPP_LOG_DEBUG("Found nmcli. nmcli major version is: '" << nmcliMajorVer << "'"); + // check nmcli major version (0 or 1) + command = "nmcli -v | awk -F' ' '{print $NF}' | awk -F'.' '{print $1}'"; + std::string nmcliMajorVer = executeShellCommand(command); + nmcliMajorVer.erase(std::remove(nmcliMajorVer.begin(), nmcliMajorVer.end(), '\n'), nmcliMajorVer.end()); + PCPP_LOG_DEBUG("Found nmcli. nmcli major version is: '" << nmcliMajorVer << "'"); - // build nmcli command according to its major version - if (nmcliMajorVer == "0") - command = "nmcli dev list | grep IP4.DNS"; - else - command = "nmcli dev show | grep IP4.DNS"; + // build nmcli command according to its major version + if (nmcliMajorVer == "0") + command = "nmcli dev list | grep IP4.DNS"; + else + command = "nmcli dev show | grep IP4.DNS"; - std::string dnsServersInfo = executeShellCommand(command); - if (dnsServersInfo == "") - { - PCPP_LOG_DEBUG("Error retrieving DNS server list: call to nmcli gave no output"); - return {}; - } + std::string dnsServersInfo = executeShellCommand(command); + if (dnsServersInfo == "") + { + PCPP_LOG_DEBUG("Error retrieving DNS server list: call to nmcli gave no output"); + return {}; + } - std::istringstream stream(dnsServersInfo); - std::string line; - int i = 1; - while(std::getline(stream, line)) - { - std::istringstream lineStream(line); - std::string headline; - std::string dnsIP; - lineStream >> headline; - lineStream >> dnsIP; - IPv4Address dnsIPAddr; - try + std::istringstream stream(dnsServersInfo); + std::string line; + int i = 1; + while (std::getline(stream, line)) { - dnsIPAddr = IPv4Address(dnsIP); + std::istringstream lineStream(line); + std::string headline; + std::string dnsIP; + lineStream >> headline; + lineStream >> dnsIP; + IPv4Address dnsIPAddr; + try + { + dnsIPAddr = IPv4Address(dnsIP); + } + catch (const std::exception& e) + { + PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << dnsIP << ": " << e.what()); + continue; + } + + if (std::find(dnsServers.begin(), dnsServers.end(), dnsIPAddr) == dnsServers.end()) + { + dnsServers.push_back(dnsIPAddr); + PCPP_LOG_DEBUG("Default DNS server IP #" << i++ << ": " << dnsIPAddr); + } } - catch(const std::exception& e) +#elif defined(__APPLE__) + + SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, CFSTR("iked"), nullptr, nullptr); + if (dynRef == nullptr) { - PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << dnsIP << ": " << e.what()); - continue; + PCPP_LOG_DEBUG("Couldn't set DNS server list: failed to retrieve SCDynamicStore"); + return {}; } - if (std::find(dnsServers.begin(), dnsServers.end(), dnsIPAddr) == dnsServers.end()) + CFDictionaryRef dnsDict = (CFDictionaryRef)SCDynamicStoreCopyValue(dynRef, CFSTR("State:/Network/Global/DNS")); + + if (dnsDict == nullptr) { - dnsServers.push_back(dnsIPAddr); - PCPP_LOG_DEBUG("Default DNS server IP #" << i++ << ": " << dnsIPAddr); + PCPP_LOG_DEBUG("Couldn't set DNS server list: failed to get DNS dictionary"); + CFRelease(dynRef); + return {}; } - } -#elif defined(__APPLE__) - SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, CFSTR("iked"), nullptr, nullptr); - if (dynRef == nullptr) - { - PCPP_LOG_DEBUG("Couldn't set DNS server list: failed to retrieve SCDynamicStore"); - return {}; - } + CFArrayRef serverAddresses = (CFArrayRef)CFDictionaryGetValue(dnsDict, CFSTR("ServerAddresses")); + + if (serverAddresses == nullptr) + { + PCPP_LOG_DEBUG("Couldn't set DNS server list: server addresses array is null"); + CFRelease(dynRef); + CFRelease(dnsDict); + return {}; + } - CFDictionaryRef dnsDict = (CFDictionaryRef)SCDynamicStoreCopyValue(dynRef,CFSTR("State:/Network/Global/DNS")); + CFIndex count = CFArrayGetCount(serverAddresses); + for (CFIndex i = 0; i < count; i++) + { + CFStringRef serverAddress = (CFStringRef)CFArrayGetValueAtIndex(serverAddresses, i); - if (dnsDict == nullptr) - { - PCPP_LOG_DEBUG("Couldn't set DNS server list: failed to get DNS dictionary"); - CFRelease(dynRef); - return {}; - } + if (serverAddress == nullptr) + continue; - CFArrayRef serverAddresses = (CFArrayRef)CFDictionaryGetValue(dnsDict, CFSTR("ServerAddresses")); + uint8_t buf[20]; + char* serverAddressCString = (char*)buf; + CFStringGetCString(serverAddress, serverAddressCString, 20, kCFStringEncodingUTF8); + try + { + dnsServers.push_back(IPv4Address(serverAddressCString)); + PCPP_LOG_DEBUG("Default DNS server IP #" << (int)(i + 1) << ": " << serverAddressCString); + } + catch (const std::exception& e) + { + PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << serverAddressCString << ": " << e.what()); + } + } - if (serverAddresses == nullptr) - { - PCPP_LOG_DEBUG("Couldn't set DNS server list: server addresses array is null"); CFRelease(dynRef); CFRelease(dnsDict); - return {}; - } - CFIndex count = CFArrayGetCount(serverAddresses); - for (CFIndex i = 0; i < count; i++) - { - CFStringRef serverAddress = (CFStringRef)CFArrayGetValueAtIndex(serverAddresses, i); +#elif defined(__FreeBSD__) - if (serverAddress == nullptr) - continue; + res_init(); - uint8_t buf[20]; - char* serverAddressCString = (char*)buf; - CFStringGetCString(serverAddress, serverAddressCString, 20, kCFStringEncodingUTF8); - try - { - dnsServers.push_back(IPv4Address(serverAddressCString)); - PCPP_LOG_DEBUG("Default DNS server IP #" << (int)(i+1) << ": " << serverAddressCString); - } - catch(const std::exception& e) + for (int i = 0; i < _res.nscount; i++) { - PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << serverAddressCString << ": " << e.what()); - } - } - - CFRelease(dynRef); - CFRelease(dnsDict); + sockaddr* saddr = (sockaddr*)&_res.nsaddr_list[i]; + if (saddr == nullptr) + continue; + in_addr* inaddr = internal::try_sockaddr2in_addr(saddr); + if (inaddr == nullptr) + continue; -#elif defined(__FreeBSD__) + try + { + dnsServers.push_back(IPv4Address(internal::in_addr2int(*inaddr))); + } + catch (const std::exception& e) + { + PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << internal::in_addr2int(*inaddr) << ": " + << e.what()); + } + } - res_init(); +#endif + return dnsServers; + } - for (int i = 0; i < _res.nscount; i++) + PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPAddress& ipAddr) const { - sockaddr* saddr = (sockaddr*)&_res.nsaddr_list[i]; - if (saddr == nullptr) - continue; - in_addr* inaddr = internal::try_sockaddr2in_addr(saddr); - if (inaddr == nullptr) - continue; - - try + if (ipAddr.getType() == IPAddress::IPv4AddressType) { - dnsServers.push_back(IPv4Address(internal::in_addr2int(*inaddr))); + return getPcapLiveDeviceByIp(ipAddr.getIPv4()); } - catch(const std::exception& e) + else // IPAddress::IPv6AddressType { - PCPP_LOG_DEBUG("Failed to parse DNS server IP address: " << internal::in_addr2int(*inaddr) << ": " << e.what()); + return getPcapLiveDeviceByIp(ipAddr.getIPv6()); } } -#endif - return dnsServers; -} - -PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPAddress& ipAddr) const -{ - if (ipAddr.getType() == IPAddress::IPv4AddressType) + PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv4Address& ipAddr) const { - return getPcapLiveDeviceByIp(ipAddr.getIPv4()); - } - else //IPAddress::IPv6AddressType - { - return getPcapLiveDeviceByIp(ipAddr.getIPv6()); - } -} - -PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv4Address& ipAddr) const -{ - PCPP_LOG_DEBUG("Searching all live devices..."); - for(const auto& devicePtr : m_LiveDeviceList) - { - PCPP_LOG_DEBUG("Searching device '" << devicePtr->m_Name << "'. Searching all addresses..."); - for(const auto& addressInfo : devicePtr->m_Addresses) + PCPP_LOG_DEBUG("Searching all live devices..."); + for (const auto& devicePtr : m_LiveDeviceList) { - if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addressInfo.addr != nullptr) + PCPP_LOG_DEBUG("Searching device '" << devicePtr->m_Name << "'. Searching all addresses..."); + for (const auto& addressInfo : devicePtr->m_Addresses) { - std::array addrAsString; - internal::sockaddr2string(addressInfo.addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); - } - - in_addr* currAddr = internal::try_sockaddr2in_addr(addressInfo.addr); - if (currAddr == nullptr) - { - PCPP_LOG_DEBUG("Address is nullptr"); - continue; - } - - if (*currAddr == ipAddr) - { - PCPP_LOG_DEBUG("Found matched address!"); - return devicePtr.get(); + if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addressInfo.addr != nullptr) + { + std::array addrAsString; + internal::sockaddr2string(addressInfo.addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + } + + in_addr* currAddr = internal::try_sockaddr2in_addr(addressInfo.addr); + if (currAddr == nullptr) + { + PCPP_LOG_DEBUG("Address is nullptr"); + continue; + } + + if (*currAddr == ipAddr) + { + PCPP_LOG_DEBUG("Found matched address!"); + return devicePtr.get(); + } } } - } - return nullptr; -} + return nullptr; + } -PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv6Address& ip6Addr) const -{ - PCPP_LOG_DEBUG("Searching all live devices..."); - for(const auto& devicePtr : m_LiveDeviceList) + PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv6Address& ip6Addr) const { - PCPP_LOG_DEBUG("Searching device '" << devicePtr->m_Name << "'. Searching all addresses..."); - for(const auto& addressInfo : devicePtr->m_Addresses) + PCPP_LOG_DEBUG("Searching all live devices..."); + for (const auto& devicePtr : m_LiveDeviceList) { - if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addressInfo.addr != nullptr) + PCPP_LOG_DEBUG("Searching device '" << devicePtr->m_Name << "'. Searching all addresses..."); + for (const auto& addressInfo : devicePtr->m_Addresses) { - std::array addrAsString; - internal::sockaddr2string(addressInfo.addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); - } - - in6_addr* currAddr = internal::try_sockaddr2in6_addr(addressInfo.addr); - if (currAddr == nullptr) - { - PCPP_LOG_DEBUG("Address is nullptr"); - continue; - } - - if (*currAddr == ip6Addr) - { - PCPP_LOG_DEBUG("Found matched address!"); - return devicePtr.get(); + if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addressInfo.addr != nullptr) + { + std::array addrAsString; + internal::sockaddr2string(addressInfo.addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + } + + in6_addr* currAddr = internal::try_sockaddr2in6_addr(addressInfo.addr); + if (currAddr == nullptr) + { + PCPP_LOG_DEBUG("Address is nullptr"); + continue; + } + + if (*currAddr == ip6Addr) + { + PCPP_LOG_DEBUG("Found matched address!"); + return devicePtr.get(); + } } } - } - - return nullptr; -} -PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const std::string& ipAddrAsString) const -{ - IPAddress ipAddr; - try - { - ipAddr = IPAddress(ipAddrAsString); - } - catch(const std::exception&) - { - PCPP_LOG_ERROR("IP address is not valid: " + ipAddrAsString); return nullptr; } - PcapLiveDevice* result = PcapLiveDeviceList::getPcapLiveDeviceByIp(ipAddr); - return result; -} - + PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const std::string& ipAddrAsString) const + { + IPAddress ipAddr; + try + { + ipAddr = IPAddress(ipAddrAsString); + } + catch (const std::exception&) + { + PCPP_LOG_ERROR("IP address is not valid: " + ipAddrAsString); + return nullptr; + } -PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByName(const std::string& name) const -{ - PCPP_LOG_DEBUG("Searching all live devices..."); - auto devIter = std::find_if(m_LiveDeviceList.begin(), m_LiveDeviceList.end(), - [&name](const std::unique_ptr& dev) { return dev->getName() == name; }); + PcapLiveDevice* result = PcapLiveDeviceList::getPcapLiveDeviceByIp(ipAddr); + return result; + } - if (devIter == m_LiveDeviceList.end()) + PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByName(const std::string& name) const { - PCPP_LOG_DEBUG("Found no live device with name '" << name << "'"); - return nullptr; - } + PCPP_LOG_DEBUG("Searching all live devices..."); + auto devIter = + std::find_if(m_LiveDeviceList.begin(), m_LiveDeviceList.end(), + [&name](const std::unique_ptr& dev) { return dev->getName() == name; }); - return devIter->get(); -} + if (devIter == m_LiveDeviceList.end()) + { + PCPP_LOG_DEBUG("Found no live device with name '" << name << "'"); + return nullptr; + } -PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIpOrName(const std::string& ipOrName) const -{ - try - { - IPAddress interfaceIP = IPAddress(ipOrName); - return PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(interfaceIP); + return devIter->get(); } - catch (std::exception&) + + PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIpOrName(const std::string& ipOrName) const { - return PcapLiveDeviceList::getInstance().getPcapLiveDeviceByName(ipOrName); + try + { + IPAddress interfaceIP = IPAddress(ipOrName); + return PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(interfaceIP); + } + catch (std::exception&) + { + return PcapLiveDeviceList::getInstance().getPcapLiveDeviceByName(ipOrName); + } } -} -PcapLiveDeviceList* PcapLiveDeviceList::clone() -{ - return new PcapLiveDeviceList; -} + PcapLiveDeviceList* PcapLiveDeviceList::clone() + { + return new PcapLiveDeviceList; + } -void PcapLiveDeviceList::reset() -{ - m_LiveDeviceListView.clear(); + void PcapLiveDeviceList::reset() + { + m_LiveDeviceListView.clear(); - m_LiveDeviceList = fetchAllLocalDevices(); - m_DnsServers = fetchDnsServers(); + m_LiveDeviceList = fetchAllLocalDevices(); + m_DnsServers = fetchDnsServers(); - syncPointerVectors(m_LiveDeviceList, m_LiveDeviceListView); -} + syncPointerVectors(m_LiveDeviceList, m_LiveDeviceListView); + } -} // namespace pcpp +} // namespace pcpp diff --git a/Pcap++/src/PcapRemoteDevice.cpp b/Pcap++/src/PcapRemoteDevice.cpp index 1ee9b24060..b2ebdb4763 100644 --- a/Pcap++/src/PcapRemoteDevice.cpp +++ b/Pcap++/src/PcapRemoteDevice.cpp @@ -1,140 +1,141 @@ #if defined(_WIN32) -#define LOG_MODULE PcapLogModuleRemoteDevice - -#include "PcapRemoteDevice.h" -#include "Logger.h" -#include "pcap.h" +# define LOG_MODULE PcapLogModuleRemoteDevice +# include "PcapRemoteDevice.h" +# include "Logger.h" +# include "pcap.h" namespace pcpp { -pcap_rmtauth PcapRemoteAuthentication::getPcapRmAuth() const -{ - pcap_rmtauth result; - result.type = RPCAP_RMTAUTH_PWD; - result.username = const_cast(userName.c_str()); - result.password = const_cast(password.c_str()); - return result; -} - -PcapRemoteDevice::PcapRemoteDevice(pcap_if_t* iface, std::shared_ptr remoteAuthentication, const IPAddress& remoteMachineIP, uint16_t remoteMachinePort) - : PcapLiveDevice(iface, false, false, false) - , m_RemoteMachineIpAddress(remoteMachineIP) - , m_RemoteMachinePort(remoteMachinePort) - , m_RemoteAuthentication(std::move(remoteAuthentication)) -{ - PCPP_LOG_DEBUG("MTU calculation isn't supported for remote devices. Setting MTU to 1514"); - m_DeviceMtu = 1514; -} - - -bool PcapRemoteDevice::open() -{ - char errbuf[PCAP_ERRBUF_SIZE]; - int flags = PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_NOCAPTURE_RPCAP; //PCAP_OPENFLAG_DATATX_UDP doesn't always work - PCPP_LOG_DEBUG("Opening device '" << m_Name << "'"); - pcap_rmtauth* pRmAuth = nullptr; - pcap_rmtauth rmAuth; - if (m_RemoteAuthentication != nullptr) + pcap_rmtauth PcapRemoteAuthentication::getPcapRmAuth() const { - rmAuth = m_RemoteAuthentication->getPcapRmAuth(); - pRmAuth = &rmAuth; + pcap_rmtauth result; + result.type = RPCAP_RMTAUTH_PWD; + result.username = const_cast(userName.c_str()); + result.password = const_cast(password.c_str()); + return result; } - m_PcapDescriptor = pcap_open(m_Name.c_str(), PCPP_MAX_PACKET_SIZE, flags, 250, pRmAuth, errbuf); - if (m_PcapDescriptor == nullptr) + PcapRemoteDevice::PcapRemoteDevice(pcap_if_t* iface, std::shared_ptr remoteAuthentication, + const IPAddress& remoteMachineIP, uint16_t remoteMachinePort) + : PcapLiveDevice(iface, false, false, false), m_RemoteMachineIpAddress(remoteMachineIP), + m_RemoteMachinePort(remoteMachinePort), m_RemoteAuthentication(std::move(remoteAuthentication)) { - PCPP_LOG_ERROR("Error opening device. Error was: " << errbuf); - m_DeviceOpened = false; - return false; + PCPP_LOG_DEBUG("MTU calculation isn't supported for remote devices. Setting MTU to 1514"); + m_DeviceMtu = 1514; } - //in Remote devices there shouldn't be 2 separate descriptors - m_PcapSendDescriptor = m_PcapDescriptor; + bool PcapRemoteDevice::open() + { + char errbuf[PCAP_ERRBUF_SIZE]; + int flags = + PCAP_OPENFLAG_PROMISCUOUS | PCAP_OPENFLAG_NOCAPTURE_RPCAP; // PCAP_OPENFLAG_DATATX_UDP doesn't always work + PCPP_LOG_DEBUG("Opening device '" << m_Name << "'"); + pcap_rmtauth* pRmAuth = nullptr; + pcap_rmtauth rmAuth; + if (m_RemoteAuthentication != nullptr) + { + rmAuth = m_RemoteAuthentication->getPcapRmAuth(); + pRmAuth = &rmAuth; + } + + m_PcapDescriptor = pcap_open(m_Name.c_str(), PCPP_MAX_PACKET_SIZE, flags, 250, pRmAuth, errbuf); + if (m_PcapDescriptor == nullptr) + { + PCPP_LOG_ERROR("Error opening device. Error was: " << errbuf); + m_DeviceOpened = false; + return false; + } - //setFilter requires that m_DeviceOpened == true - m_DeviceOpened = true; + // in Remote devices there shouldn't be 2 separate descriptors + m_PcapSendDescriptor = m_PcapDescriptor; - //for some reason if a filter is not set than WinPcap throws an exception. So Here is a generic filter that catches all traffic - if (!setFilter("ether proto (\\ip or \\ip6 or \\arp or \\rarp or \\decnet or \\sca or \\lat or \\mopdl or \\moprc or \\iso or \\stp or \\ipx or \\netbeui or 0x80F3)")) //0x80F3 == AARP - { - PCPP_LOG_ERROR("Error setting the filter. Error was: " << Logger::getInstance().getLastError()); - m_DeviceOpened = false; - return false; - } + // setFilter requires that m_DeviceOpened == true + m_DeviceOpened = true; - PCPP_LOG_DEBUG("Device '" << m_Name << "' opened"); + // for some reason if a filter is not set than WinPcap throws an exception. So Here is a generic filter that + // catches all traffic + if (!setFilter( + "ether proto (\\ip or \\ip6 or \\arp or \\rarp or \\decnet or \\sca or \\lat or \\mopdl or \\moprc or \\iso or \\stp or \\ipx or \\netbeui or 0x80F3)")) // 0x80F3 == AARP + { + PCPP_LOG_ERROR("Error setting the filter. Error was: " << Logger::getInstance().getLastError()); + m_DeviceOpened = false; + return false; + } - return true; -} + PCPP_LOG_DEBUG("Device '" << m_Name << "' opened"); -void* PcapRemoteDevice::remoteDeviceCaptureThreadMain(void* ptr) -{ - PcapRemoteDevice* pThis = static_cast(ptr); - if (pThis == nullptr) - { - PCPP_LOG_ERROR("Capture thread: Unable to extract PcapLiveDevice instance"); - return 0; + return true; } - PCPP_LOG_DEBUG("Started capture thread for device '" << pThis->m_Name << "'"); + void* PcapRemoteDevice::remoteDeviceCaptureThreadMain(void* ptr) + { + PcapRemoteDevice* pThis = static_cast(ptr); + if (pThis == nullptr) + { + PCPP_LOG_ERROR("Capture thread: Unable to extract PcapLiveDevice instance"); + return 0; + } + + PCPP_LOG_DEBUG("Started capture thread for device '" << pThis->m_Name << "'"); - pcap_pkthdr* pkthdr; - const uint8_t* pktData; + pcap_pkthdr* pkthdr; + const uint8_t* pktData; - if (pThis->m_CaptureCallbackMode) - { - while (!pThis->m_StopThread) + if (pThis->m_CaptureCallbackMode) { - if (pcap_next_ex(pThis->m_PcapDescriptor, &pkthdr, &pktData) > 0) - onPacketArrives(reinterpret_cast(pThis), pkthdr, pktData); + while (!pThis->m_StopThread) + { + if (pcap_next_ex(pThis->m_PcapDescriptor, &pkthdr, &pktData) > 0) + onPacketArrives(reinterpret_cast(pThis), pkthdr, pktData); + } } - } - else - { - while (!pThis->m_StopThread) + else { - if (pcap_next_ex(pThis->m_PcapDescriptor, &pkthdr, &pktData) > 0) - onPacketArrivesNoCallback(reinterpret_cast(pThis), pkthdr, pktData); + while (!pThis->m_StopThread) + { + if (pcap_next_ex(pThis->m_PcapDescriptor, &pkthdr, &pktData) > 0) + onPacketArrivesNoCallback(reinterpret_cast(pThis), pkthdr, pktData); + } } + PCPP_LOG_DEBUG("Ended capture thread for device '" << pThis->m_Name << "'"); + return 0; } - PCPP_LOG_DEBUG("Ended capture thread for device '" << pThis->m_Name << "'"); - return 0; -} -ThreadStart PcapRemoteDevice::getCaptureThreadStart() -{ - return &remoteDeviceCaptureThreadMain; -} + ThreadStart PcapRemoteDevice::getCaptureThreadStart() + { + return &remoteDeviceCaptureThreadMain; + } -void PcapRemoteDevice::getStatistics(PcapStats& stats) const -{ - int allocatedMemory; - pcap_stat* tempStats = pcap_stats_ex(m_PcapDescriptor, &allocatedMemory); - if (allocatedMemory < static_cast(sizeof(pcap_stat))) + void PcapRemoteDevice::getStatistics(PcapStats& stats) const { - PCPP_LOG_ERROR("Error getting statistics from live device '" << m_Name << "': WinPcap did not allocate the entire struct"); - return; + int allocatedMemory; + pcap_stat* tempStats = pcap_stats_ex(m_PcapDescriptor, &allocatedMemory); + if (allocatedMemory < static_cast(sizeof(pcap_stat))) + { + PCPP_LOG_ERROR("Error getting statistics from live device '" + << m_Name << "': WinPcap did not allocate the entire struct"); + return; + } + stats.packetsRecv = tempStats->ps_capt; + stats.packetsDrop = static_cast(tempStats->ps_drop) + tempStats->ps_netdrop; + stats.packetsDropByInterface = tempStats->ps_ifdrop; } - stats.packetsRecv = tempStats->ps_capt; - stats.packetsDrop = static_cast(tempStats->ps_drop) + tempStats->ps_netdrop; - stats.packetsDropByInterface = tempStats->ps_ifdrop; -} -uint32_t PcapRemoteDevice::getMtu() const -{ - PCPP_LOG_DEBUG("MTU isn't supported for remote devices"); - return 0; -} + uint32_t PcapRemoteDevice::getMtu() const + { + PCPP_LOG_DEBUG("MTU isn't supported for remote devices"); + return 0; + } -MacAddress PcapRemoteDevice::getMacAddress() const -{ - PCPP_LOG_ERROR("MAC address isn't supported for remote devices"); - return MacAddress::Zero; -} + MacAddress PcapRemoteDevice::getMacAddress() const + { + PCPP_LOG_ERROR("MAC address isn't supported for remote devices"); + return MacAddress::Zero; + } -} // namespace pcpp +} // namespace pcpp -#endif // _WIN32 +#endif // _WIN32 diff --git a/Pcap++/src/PcapRemoteDeviceList.cpp b/Pcap++/src/PcapRemoteDeviceList.cpp index bc479a2caf..a3d89ee89b 100644 --- a/Pcap++/src/PcapRemoteDeviceList.cpp +++ b/Pcap++/src/PcapRemoteDeviceList.cpp @@ -1,15 +1,15 @@ #if defined(_WIN32) -#define LOG_MODULE PcapLogModuleRemoteDevice +# define LOG_MODULE PcapLogModuleRemoteDevice -#include "PcapRemoteDeviceList.h" -#include "Logger.h" -#include "IpUtils.h" -#include "PcapUtils.h" -#include "IpAddressUtils.h" -#include "pcap.h" -#include -#include +# include "PcapRemoteDeviceList.h" +# include "Logger.h" +# include "IpUtils.h" +# include "PcapUtils.h" +# include "IpAddressUtils.h" +# include "pcap.h" +# include +# include namespace pcpp { @@ -20,20 +20,22 @@ namespace pcpp * 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. + * @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) + std::unique_ptr getAllRemotePcapDevices( + const IPAddress& ipAddress, uint16_t port, pcap_rmtauth* pRmAuth = nullptr) { PCPP_LOG_DEBUG("Searching remote devices on IP: " << ipAddress << " and port: " << port); std::array remoteCaptureString; std::array errorBuf; if (pcap_createsrcstr(remoteCaptureString.data(), PCAP_SRC_IFREMOTE, ipAddress.toString().c_str(), - std::to_string(port).c_str(), nullptr, errorBuf.data()) != 0) + std::to_string(port).c_str(), nullptr, errorBuf.data()) != 0) { throw std::runtime_error("Error creating the remote connection string. Error: " + - std::string(errorBuf.begin(), errorBuf.end())); + std::string(errorBuf.begin(), errorBuf.end())); } PCPP_LOG_DEBUG("Remote capture string: " << remoteCaptureString.data()); @@ -42,194 +44,200 @@ namespace pcpp if (pcap_findalldevs_ex(remoteCaptureString.data(), pRmAuth, &interfaceListRaw, errorBuf.data()) < 0) { throw std::runtime_error("Error retrieving device on remote machine. Error: " + - std::string(errorBuf.begin(), errorBuf.end())); + std::string(errorBuf.begin(), errorBuf.end())); } return std::unique_ptr(interfaceListRaw); } - } - -PcapRemoteDeviceList::PcapRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, std::shared_ptr remoteAuth, std::vector deviceList) - : m_RemoteDeviceList(std::move(deviceList)) - , m_RemoteMachineIpAddress(ipAddress) - , m_RemoteMachinePort(port) - , m_RemoteAuthentication(std::move(remoteAuth)) -{} - -PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port) -{ - auto result = PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port); - return result.release(); -} + } // namespace -std::unique_ptr PcapRemoteDeviceList::createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port) -{ - return PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port, nullptr); -} - -PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication* remoteAuth) -{ - auto result = PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port, remoteAuth); - return result.release(); -} + PcapRemoteDeviceList::PcapRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, + std::shared_ptr remoteAuth, + std::vector deviceList) + : m_RemoteDeviceList(std::move(deviceList)), m_RemoteMachineIpAddress(ipAddress), m_RemoteMachinePort(port), + m_RemoteAuthentication(std::move(remoteAuth)) + {} -std::unique_ptr PcapRemoteDeviceList::createRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication const* remoteAuth) -{ - std::shared_ptr pRemoteAuthCopy; - pcap_rmtauth* pRmAuth = nullptr; - pcap_rmtauth rmAuth; - if (remoteAuth != nullptr) + PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port) { - PCPP_LOG_DEBUG("Authentication requested. Username: " << remoteAuth->userName << ", Password: " << remoteAuth->password); - pRemoteAuthCopy = std::make_shared(*remoteAuth); - rmAuth = pRemoteAuthCopy->getPcapRmAuth(); - pRmAuth = &rmAuth; + auto result = PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port); + return result.release(); } - std::unique_ptr interfaceList; - try + std::unique_ptr PcapRemoteDeviceList::createRemoteDeviceList(const IPAddress& ipAddress, + uint16_t port) { - interfaceList = getAllRemotePcapDevices(ipAddress, port, pRmAuth); + return PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port, nullptr); } - catch (const std::exception& e) + + PcapRemoteDeviceList* PcapRemoteDeviceList::getRemoteDeviceList(const IPAddress& ipAddress, uint16_t port, + PcapRemoteAuthentication* remoteAuth) { - PCPP_LOG_ERROR(e.what()); - return nullptr; + auto result = PcapRemoteDeviceList::createRemoteDeviceList(ipAddress, port, remoteAuth); + return result.release(); } - std::vector devices; - try + std::unique_ptr PcapRemoteDeviceList::createRemoteDeviceList( + const IPAddress& ipAddress, uint16_t port, PcapRemoteAuthentication const* remoteAuth) { - for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next) + std::shared_ptr pRemoteAuthCopy; + pcap_rmtauth* pRmAuth = nullptr; + pcap_rmtauth rmAuth; + if (remoteAuth != nullptr) { - auto pNewRemoteDevice = std::unique_ptr(new PcapRemoteDevice(currInterface, pRemoteAuthCopy, ipAddress, port)); - // Release is called after pushback to prevent memory leaks if vector reallocation fails. - // cppcheck-suppress danglingLifetime - devices.push_back(pNewRemoteDevice.get()); - pNewRemoteDevice.release(); + PCPP_LOG_DEBUG("Authentication requested. Username: " << remoteAuth->userName + << ", Password: " << remoteAuth->password); + pRemoteAuthCopy = std::make_shared(*remoteAuth); + rmAuth = pRemoteAuthCopy->getPcapRmAuth(); + pRmAuth = &rmAuth; } - } - catch (const std::exception& e) - { - for (auto device : devices) + + std::unique_ptr interfaceList; + try { - delete device; + interfaceList = getAllRemotePcapDevices(ipAddress, port, pRmAuth); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR(e.what()); + return nullptr; } - PCPP_LOG_ERROR("Error creating remote devices: " << e.what()); - return nullptr; - } - - return std::unique_ptr(new PcapRemoteDeviceList(ipAddress, port, pRemoteAuthCopy, devices)); -} -PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const std::string& ipAddrAsString) const -{ - IPAddress ipAddr; + std::vector devices; + try + { + for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; + currInterface = currInterface->next) + { + auto pNewRemoteDevice = std::unique_ptr( + new PcapRemoteDevice(currInterface, pRemoteAuthCopy, ipAddress, port)); + // Release is called after pushback to prevent memory leaks if vector reallocation fails. + // cppcheck-suppress danglingLifetime + devices.push_back(pNewRemoteDevice.get()); + pNewRemoteDevice.release(); + } + } + catch (const std::exception& e) + { + for (auto device : devices) + { + delete device; + } + PCPP_LOG_ERROR("Error creating remote devices: " << e.what()); + return nullptr; + } - try - { - ipAddr = IPAddress(ipAddrAsString); + return std::unique_ptr( + new PcapRemoteDeviceList(ipAddress, port, pRemoteAuthCopy, devices)); } - catch (std::exception&) + + PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const std::string& ipAddrAsString) const { - PCPP_LOG_ERROR("IP address no valid: " + ipAddrAsString); - return nullptr; - } + IPAddress ipAddr; - PcapRemoteDevice* result = getRemoteDeviceByIP(ipAddr); - return result; -} + try + { + ipAddr = IPAddress(ipAddrAsString); + } + catch (std::exception&) + { + PCPP_LOG_ERROR("IP address no valid: " + ipAddrAsString); + return nullptr; + } -PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPAddress& ipAddr) const -{ - if (ipAddr.getType() == IPAddress::IPv4AddressType) - { - return getRemoteDeviceByIP(ipAddr.getIPv4()); - } - else //IPAddress::IPv6AddressType - { - return getRemoteDeviceByIP(ipAddr.getIPv6()); + PcapRemoteDevice* result = getRemoteDeviceByIP(ipAddr); + return result; } -} - -PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPv4Address& ip4Addr) const -{ - PCPP_LOG_DEBUG("Searching all remote devices in list..."); - for(ConstRemoteDeviceListIterator devIter = m_RemoteDeviceList.begin(); devIter != m_RemoteDeviceList.end(); devIter++) + PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPAddress& ipAddr) const { - PCPP_LOG_DEBUG("Searching device '" << (*devIter)->m_Name << "'. Searching all addresses..."); - for(const auto &addrIter : (*devIter)->m_Addresses) + if (ipAddr.getType() == IPAddress::IPv4AddressType) { - if (Logger::getInstance().isDebugEnabled(PcapLogModuleRemoteDevice) && addrIter.addr != NULL) - { - std::array addrAsString; - internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); - } - - in_addr* currAddr = internal::try_sockaddr2in_addr(addrIter.addr); - if (currAddr == NULL) - { - PCPP_LOG_DEBUG("Address is NULL"); - continue; - } - - if (*currAddr == ip4Addr) - { - PCPP_LOG_DEBUG("Found matched address!"); - return (*devIter); - } + return getRemoteDeviceByIP(ipAddr.getIPv4()); + } + else // IPAddress::IPv6AddressType + { + return getRemoteDeviceByIP(ipAddr.getIPv6()); } } - return NULL; - -} - -PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPv6Address& ip6Addr) const -{ - PCPP_LOG_DEBUG("Searching all remote devices in list..."); - for(ConstRemoteDeviceListIterator devIter = m_RemoteDeviceList.begin(); devIter != m_RemoteDeviceList.end(); devIter++) + PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPv4Address& ip4Addr) const { - PCPP_LOG_DEBUG("Searching device '" << (*devIter)->m_Name << "'. Searching all addresses..."); - for(const auto &addrIter : (*devIter)->m_Addresses) + PCPP_LOG_DEBUG("Searching all remote devices in list..."); + for (ConstRemoteDeviceListIterator devIter = m_RemoteDeviceList.begin(); devIter != m_RemoteDeviceList.end(); + devIter++) { - if (Logger::getInstance().isDebugEnabled(PcapLogModuleRemoteDevice) && addrIter.addr != NULL) + PCPP_LOG_DEBUG("Searching device '" << (*devIter)->m_Name << "'. Searching all addresses..."); + for (const auto& addrIter : (*devIter)->m_Addresses) { - std::array addrAsString; - internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); - PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + if (Logger::getInstance().isDebugEnabled(PcapLogModuleRemoteDevice) && addrIter.addr != NULL) + { + std::array addrAsString; + internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + } + + in_addr* currAddr = internal::try_sockaddr2in_addr(addrIter.addr); + if (currAddr == NULL) + { + PCPP_LOG_DEBUG("Address is NULL"); + continue; + } + + if (*currAddr == ip4Addr) + { + PCPP_LOG_DEBUG("Found matched address!"); + return (*devIter); + } } + } - in6_addr* currAddr = internal::try_sockaddr2in6_addr(addrIter.addr); - if (currAddr == NULL) - { - PCPP_LOG_DEBUG("Address is NULL"); - continue; - } + return NULL; + } - if (*currAddr == ip6Addr) + PcapRemoteDevice* PcapRemoteDeviceList::getRemoteDeviceByIP(const IPv6Address& ip6Addr) const + { + PCPP_LOG_DEBUG("Searching all remote devices in list..."); + for (ConstRemoteDeviceListIterator devIter = m_RemoteDeviceList.begin(); devIter != m_RemoteDeviceList.end(); + devIter++) + { + PCPP_LOG_DEBUG("Searching device '" << (*devIter)->m_Name << "'. Searching all addresses..."); + for (const auto& addrIter : (*devIter)->m_Addresses) { - PCPP_LOG_DEBUG("Found matched address!"); - return (*devIter); + if (Logger::getInstance().isDebugEnabled(PcapLogModuleRemoteDevice) && addrIter.addr != NULL) + { + std::array addrAsString; + internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size()); + PCPP_LOG_DEBUG("Searching address " << addrAsString.data()); + } + + in6_addr* currAddr = internal::try_sockaddr2in6_addr(addrIter.addr); + if (currAddr == NULL) + { + PCPP_LOG_DEBUG("Address is NULL"); + continue; + } + + if (*currAddr == ip6Addr) + { + PCPP_LOG_DEBUG("Found matched address!"); + return (*devIter); + } } } - } - return NULL; - -} + return NULL; + } -PcapRemoteDeviceList::~PcapRemoteDeviceList() -{ - while (m_RemoteDeviceList.size() > 0) + PcapRemoteDeviceList::~PcapRemoteDeviceList() { - RemoteDeviceListIterator devIter = m_RemoteDeviceList.begin(); - delete (*devIter); - m_RemoteDeviceList.erase(devIter); + while (m_RemoteDeviceList.size() > 0) + { + RemoteDeviceListIterator devIter = m_RemoteDeviceList.begin(); + delete (*devIter); + m_RemoteDeviceList.erase(devIter); + } } -} -} // namespace pcpp +} // namespace pcpp -#endif // _WIN32 +#endif // _WIN32 diff --git a/Pcap++/src/PcapUtils.cpp b/Pcap++/src/PcapUtils.cpp index b3df4eca44..df8ee5f4c7 100644 --- a/Pcap++/src/PcapUtils.cpp +++ b/Pcap++/src/PcapUtils.cpp @@ -6,8 +6,14 @@ namespace pcpp { namespace internal { - void PcapCloseDeleter::operator()(pcap_t* ptr) const { pcap_close(ptr); } + void PcapCloseDeleter::operator()(pcap_t* ptr) const + { + pcap_close(ptr); + } - void PcapFreeAllDevsDeleter::operator()(pcap_if_t* ptr) const { pcap_freealldevs(ptr); } - } -} + void PcapFreeAllDevsDeleter::operator()(pcap_if_t* ptr) const + { + pcap_freealldevs(ptr); + } + } // namespace internal +} // namespace pcpp diff --git a/Pcap++/src/PfRingDevice.cpp b/Pcap++/src/PfRingDevice.cpp index 12bb910714..ece3c711d0 100644 --- a/Pcap++/src/PfRingDevice.cpp +++ b/Pcap++/src/PfRingDevice.cpp @@ -2,889 +2,905 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModulePfRingDevice +# define LOG_MODULE PcapLogModulePfRingDevice -#include "PfRingDevice.h" -#include "EthLayer.h" -#include "VlanLayer.h" -#include "Logger.h" -#include -#include -#include -#include +# include "PfRingDevice.h" +# include "EthLayer.h" +# include "VlanLayer.h" +# include "Logger.h" +# include +# include +# include +# include - -#define DEFAULT_PF_RING_SNAPLEN 1600 +# define DEFAULT_PF_RING_SNAPLEN 1600 namespace pcpp { - -PfRingDevice::PfRingDevice(const char* deviceName) : m_MacAddress(MacAddress::Zero) -{ - m_NumOfOpenedRxChannels = 0; - m_DeviceOpened = false; - m_DeviceName = std::string(deviceName); - m_InterfaceIndex = -1; - m_StopThread = true; - m_OnPacketsArriveCallback = NULL; - m_OnPacketsArriveUserCookie = NULL; - m_ReentrantMode = false; - m_HwClockEnabled = false; - m_DeviceMTU = 0; - m_IsFilterCurrentlySet = false; - - m_PfRingDescriptors = new pfring*[MAX_NUM_RX_CHANNELS]; -} - -PfRingDevice::~PfRingDevice() -{ - close(); - delete [] m_PfRingDescriptors; -} - - -bool PfRingDevice::open() -{ - if (m_DeviceOpened) + PfRingDevice::PfRingDevice(const char* deviceName) : m_MacAddress(MacAddress::Zero) { - PCPP_LOG_ERROR("Device already opened"); - return false; - } + m_NumOfOpenedRxChannels = 0; + m_DeviceOpened = false; + m_DeviceName = std::string(deviceName); + m_InterfaceIndex = -1; + m_StopThread = true; + m_OnPacketsArriveCallback = NULL; + m_OnPacketsArriveUserCookie = NULL; + m_ReentrantMode = false; + m_HwClockEnabled = false; + m_DeviceMTU = 0; + m_IsFilterCurrentlySet = false; - m_NumOfOpenedRxChannels = 0; + m_PfRingDescriptors = new pfring*[MAX_NUM_RX_CHANNELS]; + } - PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "]"); - int res = openSingleRxChannel(m_DeviceName.c_str(), &m_PfRingDescriptors[0]); - if (res == 0) + PfRingDevice::~PfRingDevice() { - PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "]"); - m_NumOfOpenedRxChannels = 1; - m_DeviceOpened = true; - return true; + close(); + delete[] m_PfRingDescriptors; } - else if (res == 1) - PCPP_LOG_ERROR("Couldn't open a ring on device [" << m_DeviceName << "]"); - else if (res == 2) - PCPP_LOG_ERROR("Unable to enable ring for device [" << m_DeviceName << "]"); - return false; -} + bool PfRingDevice::open() + { + if (m_DeviceOpened) + { + PCPP_LOG_ERROR("Device already opened"); + return false; + } + m_NumOfOpenedRxChannels = 0; -bool PfRingDevice::openSingleRxChannel(uint8_t channelId) -{ - uint8_t channelIds[1] = { channelId }; - return openMultiRxChannels(channelIds, 1); -} + PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "]"); + int res = openSingleRxChannel(m_DeviceName.c_str(), &m_PfRingDescriptors[0]); + if (res == 0) + { + PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "]"); + m_NumOfOpenedRxChannels = 1; + m_DeviceOpened = true; + return true; + } + else if (res == 1) + PCPP_LOG_ERROR("Couldn't open a ring on device [" << m_DeviceName << "]"); + else if (res == 2) + PCPP_LOG_ERROR("Unable to enable ring for device [" << m_DeviceName << "]"); -int PfRingDevice::openSingleRxChannel(const char* deviceName, pfring** ring) -{ - if (m_DeviceOpened) - { - PCPP_LOG_ERROR("Device already opened"); return false; } - uint32_t flags = PF_RING_PROMISC | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; - *ring = pfring_open(deviceName, DEFAULT_PF_RING_SNAPLEN, flags); - - if (*ring == NULL) - { - return 1; - } - PCPP_LOG_DEBUG("pfring_open Succeeded for device [" << m_DeviceName << "]"); - - if (getIsHwClockEnable()) + bool PfRingDevice::openSingleRxChannel(uint8_t channelId) { - setPfRingDeviceClock(*ring); - PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]"); + uint8_t channelIds[1] = { channelId }; + return openMultiRxChannels(channelIds, 1); } - if (pfring_enable_rss_rehash(*ring) < 0 || pfring_enable_ring(*ring) < 0) + int PfRingDevice::openSingleRxChannel(const char* deviceName, pfring** ring) { - pfring_close(*ring); - return 2; - } + if (m_DeviceOpened) + { + PCPP_LOG_ERROR("Device already opened"); + return false; + } - PCPP_LOG_DEBUG("pfring enabled for device [" << m_DeviceName << "]"); + uint32_t flags = PF_RING_PROMISC | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; + *ring = pfring_open(deviceName, DEFAULT_PF_RING_SNAPLEN, flags); - return 0; -} + if (*ring == NULL) + { + return 1; + } + PCPP_LOG_DEBUG("pfring_open Succeeded for device [" << m_DeviceName << "]"); -bool PfRingDevice::setPfRingDeviceClock(pfring* ring) -{ - struct timespec ltime; - if (clock_gettime(CLOCK_REALTIME, <ime) != 0) - { - PCPP_LOG_ERROR("Could not set pfring devices clock, clock_gettime failed"); - return false; - } + if (getIsHwClockEnable()) + { + setPfRingDeviceClock(*ring); + PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]"); + } - if (pfring_set_device_clock(ring, <ime) < 0) - { - PCPP_LOG_DEBUG("Could not set pfring devices clock, pfring_set_device_clock failed"); - return false; - } + if (pfring_enable_rss_rehash(*ring) < 0 || pfring_enable_ring(*ring) < 0) + { + pfring_close(*ring); + return 2; + } - return true; -} + PCPP_LOG_DEBUG("pfring enabled for device [" << m_DeviceName << "]"); -bool PfRingDevice::openMultiRxChannels(const uint8_t* channelIds, int numOfChannelIds) -{ - if (m_DeviceOpened) - { - PCPP_LOG_ERROR("Device already opened"); - return false; + return 0; } - // I needed to add this verification because PF_RING doesn't provide it. - // It allows opening the device on a channel that doesn't exist, but of course no packets will be captured - uint8_t totalChannels = getTotalNumOfRxChannels(); - for (int i = 0; i < numOfChannelIds; i++) + bool PfRingDevice::setPfRingDeviceClock(pfring* ring) { - uint8_t channelId = channelIds[i]; - if (channelId >= totalChannels) + struct timespec ltime; + if (clock_gettime(CLOCK_REALTIME, <ime) != 0) { - PCPP_LOG_ERROR("Trying to open the device with a RX channel that doesn't exist. Total RX channels are [" << (int)totalChannels << "], tried to open channel [" << (int)channelId << "]"); + PCPP_LOG_ERROR("Could not set pfring devices clock, clock_gettime failed"); return false; } - } - - m_NumOfOpenedRxChannels = 0; - for (int i = 0; i < numOfChannelIds; i++) - { - uint8_t channelId = channelIds[i]; - std::ostringstream ringNameStream; - ringNameStream << m_DeviceName << "@" << (int)channelId; - std::string ringName = ringNameStream.str(); - PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "] on channel [" << channelId << "]. Channel name [" << ringName << "]"); - int res = openSingleRxChannel(ringName.c_str(), &m_PfRingDescriptors[i]); - if (res == 0) + if (pfring_set_device_clock(ring, <ime) < 0) { - PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "] on channel [" << channelId << "]. Channel name [" << ringName << "]"); - m_NumOfOpenedRxChannels++; - continue; + PCPP_LOG_DEBUG("Could not set pfring devices clock, pfring_set_device_clock failed"); + return false; } - else if (res == 1) - PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "] for device [" << m_DeviceName << "]"); - else if (res == 2) - PCPP_LOG_ERROR("Unable to enable ring on channel [" << (int)channelId << "] for device [" << m_DeviceName << "]"); - break; + return true; } - if (m_NumOfOpenedRxChannels < numOfChannelIds) + bool PfRingDevice::openMultiRxChannels(const uint8_t* channelIds, int numOfChannelIds) { - // if an error occurred, close all rings from index=0 to index=m_NumOfOpenedRxChannels-1 - // there's no need to close m_PfRingDescriptors[m_NumOfOpenedRxChannels] because it has already been - // closed by openSingleRxChannel - for (int i = 0; i < m_NumOfOpenedRxChannels-1; i++) + if (m_DeviceOpened) { - pfring_close(m_PfRingDescriptors[i]); + PCPP_LOG_ERROR("Device already opened"); + return false; + } + + // I needed to add this verification because PF_RING doesn't provide it. + // It allows opening the device on a channel that doesn't exist, but of course no packets will be captured + uint8_t totalChannels = getTotalNumOfRxChannels(); + for (int i = 0; i < numOfChannelIds; i++) + { + uint8_t channelId = channelIds[i]; + if (channelId >= totalChannels) + { + PCPP_LOG_ERROR("Trying to open the device with a RX channel that doesn't exist. Total RX channels are [" + << (int)totalChannels << "], tried to open channel [" << (int)channelId << "]"); + return false; + } } m_NumOfOpenedRxChannels = 0; - return false; - } - m_DeviceOpened = true; + for (int i = 0; i < numOfChannelIds; i++) + { + uint8_t channelId = channelIds[i]; + std::ostringstream ringNameStream; + ringNameStream << m_DeviceName << "@" << (int)channelId; + std::string ringName = ringNameStream.str(); + PCPP_LOG_DEBUG("Trying to open device [" << m_DeviceName << "] on channel [" << channelId + << "]. Channel name [" << ringName << "]"); + int res = openSingleRxChannel(ringName.c_str(), &m_PfRingDescriptors[i]); + if (res == 0) + { + PCPP_LOG_DEBUG("Succeeded opening device [" << m_DeviceName << "] on channel [" << channelId + << "]. Channel name [" << ringName << "]"); + m_NumOfOpenedRxChannels++; + continue; + } + else if (res == 1) + PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "] for device [" << m_DeviceName + << "]"); + else if (res == 2) + PCPP_LOG_ERROR("Unable to enable ring on channel [" << (int)channelId << "] for device [" + << m_DeviceName << "]"); - return true; -} + break; + } -bool PfRingDevice::openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist) -{ - if (m_DeviceOpened) - { - PCPP_LOG_ERROR("Device already opened"); - return false; - } + if (m_NumOfOpenedRxChannels < numOfChannelIds) + { + // if an error occurred, close all rings from index=0 to index=m_NumOfOpenedRxChannels-1 + // there's no need to close m_PfRingDescriptors[m_NumOfOpenedRxChannels] because it has already been + // closed by openSingleRxChannel + for (int i = 0; i < m_NumOfOpenedRxChannels - 1; i++) + { + pfring_close(m_PfRingDescriptors[i]); + } - m_NumOfOpenedRxChannels = 0; + m_NumOfOpenedRxChannels = 0; + return false; + } - if (numOfRxChannelsToOpen > MAX_NUM_RX_CHANNELS) - { - PCPP_LOG_ERROR("Cannot open more than [" << MAX_NUM_RX_CHANNELS << "] channels"); - return false; + m_DeviceOpened = true; + + return true; } - uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; + bool PfRingDevice::openMultiRxChannels(uint8_t numOfRxChannelsToOpen, ChannelDistribution dist) + { + if (m_DeviceOpened) + { + PCPP_LOG_ERROR("Device already opened"); + return false; + } + + m_NumOfOpenedRxChannels = 0; - uint8_t numOfRxChannelsOnNIC = getTotalNumOfRxChannels(); - PCPP_LOG_DEBUG("NIC has " << (int)numOfRxChannelsOnNIC << " RX channels"); + if (numOfRxChannelsToOpen > MAX_NUM_RX_CHANNELS) + { + PCPP_LOG_ERROR("Cannot open more than [" << MAX_NUM_RX_CHANNELS << "] channels"); + return false; + } - uint8_t numOfRingsPerRxChannel = numOfRxChannelsToOpen / numOfRxChannelsOnNIC; - uint8_t remainderRings = numOfRxChannelsToOpen % numOfRxChannelsOnNIC; + uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; - cluster_type clusterType = (dist == RoundRobin) ? cluster_round_robin : cluster_per_flow; + uint8_t numOfRxChannelsOnNIC = getTotalNumOfRxChannels(); + PCPP_LOG_DEBUG("NIC has " << (int)numOfRxChannelsOnNIC << " RX channels"); - int ringsOpen = 0; - for (uint8_t channelId = 0; channelId < numOfRxChannelsOnNIC; channelId++) - { - // no more channels to open - if (numOfRingsPerRxChannel == 0 && remainderRings == 0) - break; + uint8_t numOfRingsPerRxChannel = numOfRxChannelsToOpen / numOfRxChannelsOnNIC; + uint8_t remainderRings = numOfRxChannelsToOpen % numOfRxChannelsOnNIC; - std::ostringstream ringName; - ringName << m_DeviceName << "@" << (int)channelId; + cluster_type clusterType = (dist == RoundRobin) ? cluster_round_robin : cluster_per_flow; - // open numOfRingsPerRxChannel rings per RX channel - for (uint8_t ringId = 0; ringId < numOfRingsPerRxChannel; ringId++) + int ringsOpen = 0; + for (uint8_t channelId = 0; channelId < numOfRxChannelsOnNIC; channelId++) { - m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags); - if (m_PfRingDescriptors[ringsOpen] == NULL) - { - PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]"); + // no more channels to open + if (numOfRingsPerRxChannel == 0 && remainderRings == 0) break; + + std::ostringstream ringName; + ringName << m_DeviceName << "@" << (int)channelId; + + // open numOfRingsPerRxChannel rings per RX channel + for (uint8_t ringId = 0; ringId < numOfRingsPerRxChannel; ringId++) + { + m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags); + if (m_PfRingDescriptors[ringsOpen] == NULL) + { + PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]"); + break; + } + + // setting a cluster for all rings in the same channel to enable hashing between them + if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId + 1, clusterType) < 0) + { + PCPP_LOG_ERROR("Couldn't set ring [" << (int)ringId << "] in channel [" << (int)channelId + << "] to the cluster [" << (int)(channelId + 1) << "]"); + break; + } + + ringsOpen++; } - // setting a cluster for all rings in the same channel to enable hashing between them - if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId+1, clusterType) < 0) + // open one more ring if remainder > 0 + if (remainderRings > 0) { - PCPP_LOG_ERROR("Couldn't set ring [" << (int)ringId << "] in channel [" << (int)channelId << "] to the cluster [" << (int)(channelId+1) << "]"); - break; + m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags); + if (m_PfRingDescriptors[ringsOpen] == NULL) + { + PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]"); + break; + } + + // setting a cluster for all rings in the same channel to enable hashing between them + if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId + 1, clusterType) < 0) + { + PCPP_LOG_ERROR("Couldn't set ring [" << (int)(numOfRingsPerRxChannel + 1) << "] in channel [" + << (int)channelId << "] to the cluster [" + << (int)(channelId + 1) << "]"); + break; + } + + ringsOpen++; + remainderRings--; + PCPP_LOG_DEBUG("Opened " << (int)(numOfRingsPerRxChannel + 1) << " rings on channel [" << (int)channelId + << "]"); } + else + PCPP_LOG_DEBUG("Opened " << (int)numOfRingsPerRxChannel << " rings on channel [" << (int)channelId + << "]"); + } - ringsOpen++; + if (ringsOpen < numOfRxChannelsToOpen) + { + for (uint8_t i = 0; i < ringsOpen; i++) + pfring_close(m_PfRingDescriptors[i]); + return false; } - // open one more ring if remainder > 0 - if (remainderRings > 0) + if (getIsHwClockEnable()) { - m_PfRingDescriptors[ringsOpen] = pfring_open(ringName.str().c_str(), DEFAULT_PF_RING_SNAPLEN, flags); - if (m_PfRingDescriptors[ringsOpen] == NULL) + for (int i = 0; i < ringsOpen; i++) { - PCPP_LOG_ERROR("Couldn't open a ring on channel [" << (int)channelId << "]"); - break; + if (setPfRingDeviceClock(m_PfRingDescriptors[i])) + PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]"); } + } - // setting a cluster for all rings in the same channel to enable hashing between them - if (pfring_set_cluster(m_PfRingDescriptors[ringsOpen], channelId+1, clusterType) < 0) + // enable all rings + for (int i = 0; i < ringsOpen; i++) + { + if (pfring_enable_rss_rehash(m_PfRingDescriptors[i]) < 0 || pfring_enable_ring(m_PfRingDescriptors[i]) < 0) { - PCPP_LOG_ERROR("Couldn't set ring [" << (int)(numOfRingsPerRxChannel+1) << "] in channel [" << (int)channelId << "] to the cluster [" << (int)(channelId+1) << "]"); - break; + PCPP_LOG_ERROR("Unable to enable ring [" << i << "] for device [" << m_DeviceName << "]"); + // close all pfring's that were enabled until now + for (int j = 0; j < ringsOpen; j++) + pfring_close(m_PfRingDescriptors[j]); + return false; } - - ringsOpen++; - remainderRings--; - PCPP_LOG_DEBUG("Opened " << (int)(numOfRingsPerRxChannel+1) << " rings on channel [" << (int)channelId << "]"); } - else - PCPP_LOG_DEBUG("Opened " << (int)numOfRingsPerRxChannel << " rings on channel [" << (int)channelId << "]"); - } - if (ringsOpen < numOfRxChannelsToOpen) - { - for (uint8_t i = 0; i < ringsOpen; i++) - pfring_close(m_PfRingDescriptors[i]); - return false; + m_NumOfOpenedRxChannels = ringsOpen; + + m_DeviceOpened = true; + return true; } - if (getIsHwClockEnable()) + uint8_t PfRingDevice::getTotalNumOfRxChannels() const { - for (int i = 0; i < ringsOpen; i++) + if (m_NumOfOpenedRxChannels > 0) + { + uint8_t res = pfring_get_num_rx_channels(m_PfRingDescriptors[0]); + return res; + } + else { - if (setPfRingDeviceClock(m_PfRingDescriptors[i])) - PCPP_LOG_DEBUG("H/W clock set for device [" << m_DeviceName << "]"); + uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; + pfring* ring = pfring_open(m_DeviceName.c_str(), DEFAULT_PF_RING_SNAPLEN, flags); + uint8_t res = pfring_get_num_rx_channels(ring); + pfring_close(ring); + return res; } } - // enable all rings - for (int i = 0; i < ringsOpen; i++) + SystemCore PfRingDevice::getCurrentCoreId() const + { + return SystemCores::IdToSystemCore[sched_getcpu()]; + } + + bool PfRingDevice::setFilter(std::string filterAsString) { - if (pfring_enable_rss_rehash(m_PfRingDescriptors[i]) < 0 || pfring_enable_ring(m_PfRingDescriptors[i]) < 0) + if (!m_DeviceOpened) { - PCPP_LOG_ERROR("Unable to enable ring [" << i << "] for device [" << m_DeviceName << "]"); - // close all pfring's that were enabled until now - for (int j = 0; j 0) - { - uint8_t res = pfring_get_num_rx_channels(m_PfRingDescriptors[0]); - return res; + PCPP_LOG_DEBUG("Successfully set filter '" << filterAsString << "'"); + return true; } - else + + bool PfRingDevice::clearFilter() { - uint32_t flags = PF_RING_PROMISC | PF_RING_REENTRANT | PF_RING_HW_TIMESTAMP | PF_RING_DNA_SYMMETRIC_RSS; - pfring* ring = pfring_open(m_DeviceName.c_str(), DEFAULT_PF_RING_SNAPLEN, flags); - uint8_t res = pfring_get_num_rx_channels(ring); - pfring_close(ring); - return res; - } -} + if (!m_IsFilterCurrentlySet) + return true; + for (int i = 0; i < m_NumOfOpenedRxChannels; i++) + { + int res = pfring_remove_bpf_filter(m_PfRingDescriptors[i]); + if (res < 0) + { + PCPP_LOG_ERROR("Couldn't remove filter"); + return false; + } + } -SystemCore PfRingDevice::getCurrentCoreId() const -{ - return SystemCores::IdToSystemCore[sched_getcpu()]; -} + m_IsFilterCurrentlySet = false; + PCPP_LOG_DEBUG("Successfully removed filter from all open RX channels"); + return true; + } -bool PfRingDevice::setFilter(std::string filterAsString) -{ - if (!m_DeviceOpened) + bool PfRingDevice::isFilterCurrentlySet() const { - PCPP_LOG_ERROR("Device not opened"); - return false; + return m_IsFilterCurrentlySet; } - for (int i = 0; i < m_NumOfOpenedRxChannels; i++) + void PfRingDevice::close() { - int res = pfring_set_bpf_filter(m_PfRingDescriptors[i], (char*)filterAsString.c_str()); - if(res < 0) - { - if (res == PF_RING_ERROR_NOT_SUPPORTED) - PCPP_LOG_ERROR("BPF filtering isn't supported on current PF_RING version. Please re-compile PF_RING with the --enable-bpf flag"); - else - PCPP_LOG_ERROR("Couldn't set filter '" << filterAsString << "'"); - return false; - } + for (int i = 0; i < m_NumOfOpenedRxChannels; i++) + pfring_close(m_PfRingDescriptors[i]); + m_DeviceOpened = false; + clearCoreConfiguration(); + m_NumOfOpenedRxChannels = 0; + m_IsFilterCurrentlySet = false; + PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] closed"); } - m_IsFilterCurrentlySet = true; + bool PfRingDevice::initCoreConfigurationByCoreMask(CoreMask coreMask) + { + int i = 0; + int numOfCores = getNumOfCores(); + clearCoreConfiguration(); + while ((coreMask != 0) && (i < numOfCores)) + { + if (coreMask & 1) + { + m_CoreConfiguration[i].IsInUse = true; + } - PCPP_LOG_DEBUG("Successfully set filter '" << filterAsString << "'"); - return true; -} + coreMask = coreMask >> 1; + i++; + } + if (coreMask != 0) // this mean coreMask contains a core that doesn't exist + { + PCPP_LOG_ERROR("Trying to use a core [" << i << "] that doesn't exist while machine has " << numOfCores + << " cores"); + clearCoreConfiguration(); + return false; + } -bool PfRingDevice::clearFilter() -{ - if (!m_IsFilterCurrentlySet) return true; + } - for (int i = 0; i < m_NumOfOpenedRxChannels; i++) + bool PfRingDevice::startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, + void* onPacketsArriveUserCookie, CoreMask coreMask) { - int res = pfring_remove_bpf_filter(m_PfRingDescriptors[i]); - if(res < 0) + if (!m_StopThread) { - PCPP_LOG_ERROR("Couldn't remove filter"); + PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time"); return false; } - } - - m_IsFilterCurrentlySet = false; - - PCPP_LOG_DEBUG("Successfully removed filter from all open RX channels"); - return true; -} - - -bool PfRingDevice::isFilterCurrentlySet() const -{ - return m_IsFilterCurrentlySet; -} + if (!initCoreConfigurationByCoreMask(coreMask)) + return false; -void PfRingDevice::close() -{ - for (int i = 0; i < m_NumOfOpenedRxChannels; i++) - pfring_close(m_PfRingDescriptors[i]); - m_DeviceOpened = false; - clearCoreConfiguration(); - m_NumOfOpenedRxChannels = 0; - m_IsFilterCurrentlySet = false; - PCPP_LOG_DEBUG("Device [" << m_DeviceName << "] closed"); -} - -bool PfRingDevice::initCoreConfigurationByCoreMask(CoreMask coreMask) -{ - int i = 0; - int numOfCores = getNumOfCores(); - clearCoreConfiguration(); - while ((coreMask != 0) && (i < numOfCores)) - { - if (coreMask & 1) + if (m_NumOfOpenedRxChannels != getCoresInUseCount()) { - m_CoreConfiguration[i].IsInUse = true; + PCPP_LOG_ERROR("Cannot use a different number of channels and cores. Opened " + << m_NumOfOpenedRxChannels << " channels but set " << getCoresInUseCount() + << " cores in core mask"); + clearCoreConfiguration(); + return false; } - coreMask = coreMask >> 1; - i++; - } + std::mutex mutex; + std::condition_variable cond; + int startThread = 0; - if (coreMask != 0) // this mean coreMask contains a core that doesn't exist - { - PCPP_LOG_ERROR("Trying to use a core [" << i << "] that doesn't exist while machine has " << numOfCores << " cores"); - clearCoreConfiguration(); - return false; - } + m_StopThread = false; + int rxChannel = 0; + for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + { + if (!m_CoreConfiguration[coreId].IsInUse) + continue; + + m_ReentrantMode = true; + + m_OnPacketsArriveCallback = onPacketsArrive; + m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; + + // create a new thread + m_CoreConfiguration[coreId].Channel = m_PfRingDescriptors[rxChannel++]; + m_CoreConfiguration[coreId].RxThread = + std::thread(&pcpp::PfRingDevice::captureThreadMain, this, &cond, &mutex, &startThread); + + // set affinity to cores + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(coreId, &cpuset); + int err = pthread_setaffinity_np(m_CoreConfiguration[coreId].RxThread.native_handle(), sizeof(cpu_set_t), + &cpuset); + if (err != 0) + { + PCPP_LOG_ERROR("Error while binding thread to core " << coreId << ": errno=" << err); + startThread = 1; + clearCoreConfiguration(); + return false; + } + } - return true; -} + startThread = 2; + cond.notify_all(); -bool PfRingDevice::startCaptureMultiThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie, CoreMask coreMask) -{ - if (!m_StopThread) - { - PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time"); - return false; + return true; } - if (!initCoreConfigurationByCoreMask(coreMask)) - return false; - - if (m_NumOfOpenedRxChannels != getCoresInUseCount()) + bool PfRingDevice::startCaptureSingleThread(OnPfRingPacketsArriveCallback onPacketsArrive, + void* onPacketsArriveUserCookie) { - PCPP_LOG_ERROR("Cannot use a different number of channels and cores. Opened " << m_NumOfOpenedRxChannels << " channels but set " << getCoresInUseCount() << " cores in core mask"); - clearCoreConfiguration(); - return false; - } + if (!m_StopThread) + { + PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time"); + return false; + } - std::mutex mutex; - std::condition_variable cond; - int startThread = 0; + if (m_NumOfOpenedRxChannels != 1) + { + PCPP_LOG_ERROR("Cannot start capturing on a single thread when more than 1 RX channel is opened"); + return false; + } - m_StopThread = false; - int rxChannel = 0; - for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) - { - if (!m_CoreConfiguration[coreId].IsInUse) - continue; + PCPP_LOG_DEBUG("Trying to start capturing on a single thread for device [" << m_DeviceName << "]"); - m_ReentrantMode = true; + clearCoreConfiguration(); m_OnPacketsArriveCallback = onPacketsArrive; m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; - // create a new thread - m_CoreConfiguration[coreId].Channel = m_PfRingDescriptors[rxChannel++]; - m_CoreConfiguration[coreId].RxThread = std::thread(&pcpp::PfRingDevice::captureThreadMain, this, &cond, &mutex, &startThread); + m_StopThread = false; + + m_ReentrantMode = false; + + std::mutex mutex; + std::condition_variable cond; + int startThread = 0; - // set affinity to cores cpu_set_t cpuset; CPU_ZERO(&cpuset); - CPU_SET(coreId, &cpuset); - int err = pthread_setaffinity_np(m_CoreConfiguration[coreId].RxThread.native_handle(), sizeof(cpu_set_t), &cpuset); - if(err != 0) + 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].IsAffinitySet = false; + int err = pthread_setaffinity_np(m_CoreConfiguration[0].RxThread.native_handle(), sizeof(cpu_set_t), &cpuset); + if (err != 0) { - PCPP_LOG_ERROR("Error while binding thread to core " << coreId << ": errno=" << err); startThread = 1; + PCPP_LOG_ERROR("Error while binding thread to core 0: errno=" << err); clearCoreConfiguration(); return false; } - } - - startThread = 2; - cond.notify_all(); - - return true; -} + startThread = 2; + cond.notify_all(); -bool PfRingDevice::startCaptureSingleThread(OnPfRingPacketsArriveCallback onPacketsArrive, void* onPacketsArriveUserCookie) -{ - if (!m_StopThread) - { - PCPP_LOG_ERROR("Device already capturing. Cannot start 2 capture sessions at the same time"); - return false; + PCPP_LOG_DEBUG("Capturing started for device [" << m_DeviceName << "]"); + return true; } - if (m_NumOfOpenedRxChannels != 1) + void PfRingDevice::stopCapture() { - PCPP_LOG_ERROR("Cannot start capturing on a single thread when more than 1 RX channel is opened"); - return false; - } - - PCPP_LOG_DEBUG("Trying to start capturing on a single thread for device [" << m_DeviceName << "]"); - - clearCoreConfiguration(); - - m_OnPacketsArriveCallback = onPacketsArrive; - m_OnPacketsArriveUserCookie = onPacketsArriveUserCookie; - - m_StopThread = false; - - m_ReentrantMode = false; + PCPP_LOG_DEBUG("Trying to stop capturing on device [" << m_DeviceName << "]"); + m_StopThread = true; + for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + { + if (!m_CoreConfiguration[coreId].IsInUse) + continue; + m_CoreConfiguration[coreId].RxThread.join(); + PCPP_LOG_DEBUG("Thread on core [" << coreId << "] stopped"); + } - std::mutex mutex; - std::condition_variable cond; - int startThread = 0; + PCPP_LOG_DEBUG("All capturing threads stopped"); + } - 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].IsAffinitySet = false; - int err = pthread_setaffinity_np(m_CoreConfiguration[0].RxThread.native_handle(), sizeof(cpu_set_t), &cpuset); - if(err != 0) + void PfRingDevice::captureThreadMain(std::condition_variable* startCond, std::mutex* startMutex, + const int* startState) { - startThread = 1; - PCPP_LOG_ERROR("Error while binding thread to core 0: errno=" << err); - clearCoreConfiguration(); - return false; - } - startThread = 2; - cond.notify_all(); + while (*startState == 0) + { + std::unique_lock lock(*startMutex); + startCond->wait_for(lock, std::chrono::milliseconds(100)); + } + if (*startState == 1) + { + return; + } - PCPP_LOG_DEBUG("Capturing started for device [" << m_DeviceName << "]"); - return true; -} + int coreId = this->getCurrentCoreId().Id; + pfring* ring = NULL; -void PfRingDevice::stopCapture() -{ - PCPP_LOG_DEBUG("Trying to stop capturing on device [" << m_DeviceName << "]"); - m_StopThread = true; - for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) - { - if (!m_CoreConfiguration[coreId].IsInUse) - continue; - m_CoreConfiguration[coreId].RxThread.join(); - PCPP_LOG_DEBUG("Thread on core [" << coreId << "] stopped"); - } + PCPP_LOG_DEBUG("Starting capture thread " << coreId); - PCPP_LOG_DEBUG("All capturing threads stopped"); -} + ring = this->m_CoreConfiguration[coreId].Channel; -void PfRingDevice::captureThreadMain(std::condition_variable* startCond, std::mutex* startMutex, const int* startState) -{ - while (*startState == 0) - { - std::unique_lock lock(*startMutex); - startCond->wait_for(lock, std::chrono::milliseconds(100)); - } - if (*startState == 1) - { - return; - } + if (ring == NULL) + { + PCPP_LOG_ERROR("Couldn't find ring for core " << coreId << ". Exiting capture thread"); + return; + } - int coreId = this->getCurrentCoreId().Id; - pfring* ring = NULL; + while (!this->m_StopThread) + { + // if buffer is NULL PF_RING avoids copy of the data + uint8_t* buffer = NULL; + uint32_t bufferLen = 0; - PCPP_LOG_DEBUG("Starting capture thread " << coreId); + // in multi-threaded mode flag PF_RING_REENTRANT is set, and this flag doesn't work with zero copy + // so I need to allocate a buffer and set buffer to point to it + if (this->m_ReentrantMode) + { + uint8_t tempBuffer[PCPP_MAX_PACKET_SIZE]; + buffer = tempBuffer; + bufferLen = PCPP_MAX_PACKET_SIZE; + } - ring = this->m_CoreConfiguration[coreId].Channel; + struct pfring_pkthdr pktHdr; + int recvRes = pfring_recv(ring, &buffer, bufferLen, &pktHdr, 0); + if (recvRes > 0) + { + // if caplen < len it means we don't have the whole packet. Treat this case as packet drop + // TODO: add this packet to dropped packet stats + // if (pktHdr.caplen != pktHdr.len) + // { + // PCPP_LOG_ERROR("Packet dropped due to len != caplen"); + // continue; + // } + + RawPacket rawPacket(buffer, pktHdr.caplen, pktHdr.ts, false); + this->m_OnPacketsArriveCallback(&rawPacket, 1, coreId, this, this->m_OnPacketsArriveUserCookie); + } + else if (recvRes < 0) + { + // cppcheck-suppress shiftNegative + PCPP_LOG_ERROR("pfring_recv returned an error: [Err=" << recvRes << "]"); + } + } - if (ring == NULL) - { - PCPP_LOG_ERROR("Couldn't find ring for core " << coreId << ". Exiting capture thread"); - return; + PCPP_LOG_DEBUG("Exiting capture thread " << coreId); } - while (!this->m_StopThread) + void PfRingDevice::getThreadStatistics(SystemCore core, PfRingStats& stats) const { - // if buffer is NULL PF_RING avoids copy of the data - uint8_t* buffer = NULL; - uint32_t bufferLen = 0; + pfring* ring = NULL; + uint8_t coreId = core.Id; - // in multi-threaded mode flag PF_RING_REENTRANT is set, and this flag doesn't work with zero copy - // so I need to allocate a buffer and set buffer to point to it - if (this->m_ReentrantMode) - { - uint8_t tempBuffer[PCPP_MAX_PACKET_SIZE]; - buffer = tempBuffer; - bufferLen = PCPP_MAX_PACKET_SIZE; - } + ring = m_CoreConfiguration[coreId].Channel; - struct pfring_pkthdr pktHdr; - int recvRes = pfring_recv(ring, &buffer, bufferLen, &pktHdr, 0); - if (recvRes > 0) + if (ring != NULL) { - // if caplen < len it means we don't have the whole packet. Treat this case as packet drop - // TODO: add this packet to dropped packet stats -// if (pktHdr.caplen != pktHdr.len) -// { -// PCPP_LOG_ERROR("Packet dropped due to len != caplen"); -// continue; -// } - - RawPacket rawPacket(buffer, pktHdr.caplen, pktHdr.ts, false); - this->m_OnPacketsArriveCallback(&rawPacket, 1, coreId, this, this->m_OnPacketsArriveUserCookie); + pfring_stat tempStats; + if (pfring_stats(ring, &tempStats) < 0) + { + PCPP_LOG_ERROR("Can't retrieve statistics for core [" << (int)coreId << "], pfring_stats failed"); + return; + } + stats.drop = (uint64_t)tempStats.drop; + stats.recv = (uint64_t)tempStats.recv; } - else if (recvRes < 0) + else { - // cppcheck-suppress shiftNegative - PCPP_LOG_ERROR("pfring_recv returned an error: [Err=" << recvRes << "]"); + PCPP_LOG_ERROR("Core [" << (int)coreId << "] is not in use, can't retrieve statistics"); } } - PCPP_LOG_DEBUG("Exiting capture thread " << coreId); -} - -void PfRingDevice::getThreadStatistics(SystemCore core, PfRingStats& stats) const -{ - pfring* ring = NULL; - uint8_t coreId = core.Id; - - ring = m_CoreConfiguration[coreId].Channel; + void PfRingDevice::getCurrentThreadStatistics(PfRingStats& stats) const + { + getThreadStatistics(getCurrentCoreId(), stats); + } - if (ring != NULL) + void PfRingDevice::getStatistics(PfRingStats& stats) const { - pfring_stat tempStats; - if (pfring_stats(ring, &tempStats) < 0) + stats.drop = 0; + stats.recv = 0; + + for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) { - PCPP_LOG_ERROR("Can't retrieve statistics for core [" << (int)coreId << "], pfring_stats failed"); - return; + if (!m_CoreConfiguration[coreId].IsInUse) + continue; + + PfRingStats tempStat = {}; + getThreadStatistics(SystemCores::IdToSystemCore[coreId], tempStat); + stats.drop += tempStat.drop; + stats.recv += tempStat.recv; + + if (!m_CoreConfiguration[coreId].IsAffinitySet) + break; } - stats.drop = (uint64_t)tempStats.drop; - stats.recv = (uint64_t)tempStats.recv; } - else + + void PfRingDevice::clearCoreConfiguration() { - PCPP_LOG_ERROR("Core [" << (int)coreId << "] is not in use, can't retrieve statistics"); + for (int i = 0; i < MAX_NUM_OF_CORES; i++) + m_CoreConfiguration[i].clear(); } -} - -void PfRingDevice::getCurrentThreadStatistics(PfRingStats& stats) const -{ - getThreadStatistics(getCurrentCoreId(), stats); -} -void PfRingDevice::getStatistics(PfRingStats& stats) const -{ - stats.drop = 0; - stats.recv = 0; - - for (int coreId = 0; coreId < MAX_NUM_OF_CORES; coreId++) + int PfRingDevice::getCoresInUseCount() const { - if (!m_CoreConfiguration[coreId].IsInUse) - continue; - - PfRingStats tempStat = {}; - getThreadStatistics(SystemCores::IdToSystemCore[coreId], tempStat); - stats.drop += tempStat.drop; - stats.recv += tempStat.recv; + int res = 0; + for (int i = 0; i < MAX_NUM_OF_CORES; i++) + if (m_CoreConfiguration[i].IsInUse) + res++; - if (!m_CoreConfiguration[coreId].IsAffinitySet) - break; + return res; } -} -void PfRingDevice::clearCoreConfiguration() -{ - for (int i = 0; i < MAX_NUM_OF_CORES; i++) - m_CoreConfiguration[i].clear(); -} - -int PfRingDevice::getCoresInUseCount() const -{ - int res = 0; - for (int i = 0; i < MAX_NUM_OF_CORES; i++) - if (m_CoreConfiguration[i].IsInUse) - res++; - - return res; -} + void PfRingDevice::setPfRingDeviceAttributes() + { + if (m_InterfaceIndex > -1) + return; -void PfRingDevice::setPfRingDeviceAttributes() -{ - if (m_InterfaceIndex > -1) - return; + pfring* ring = NULL; + bool closeRing = false; + if (m_NumOfOpenedRxChannels > 0) + ring = m_PfRingDescriptors[0]; + else + { + uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS; + ring = pfring_open(m_DeviceName.c_str(), DEFAULT_PF_RING_SNAPLEN, flags); + closeRing = true; + } - pfring* ring = NULL; - bool closeRing = false; - if (m_NumOfOpenedRxChannels > 0) - ring = m_PfRingDescriptors[0]; - else - { - uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS; - ring = pfring_open(m_DeviceName.c_str(), DEFAULT_PF_RING_SNAPLEN, flags); - closeRing = true; - } + if (ring == NULL) + { + PCPP_LOG_ERROR( + "Could not open a pfring for setting device attributes: MAC address, interface index and HW clock"); + return; + } - if (ring == NULL) - { - PCPP_LOG_ERROR("Could not open a pfring for setting device attributes: MAC address, interface index and HW clock"); - return; - } + // set device MAC address - // set device MAC address + uint8_t macAddress[6]; + if (pfring_get_bound_device_address(ring, macAddress) < 0) + PCPP_LOG_ERROR("Unable to read the device MAC address for interface '" << m_DeviceName << "'"); + else + m_MacAddress = MacAddress(macAddress); - uint8_t macAddress[6]; - if (pfring_get_bound_device_address(ring, macAddress) < 0) - PCPP_LOG_ERROR("Unable to read the device MAC address for interface '" << m_DeviceName << "'"); - else - m_MacAddress = MacAddress(macAddress); + // set interface ID + if (pfring_get_bound_device_ifindex(ring, &m_InterfaceIndex) < 0) + PCPP_LOG_ERROR("Unable to read interface index of device"); - // set interface ID - if (pfring_get_bound_device_ifindex(ring, &m_InterfaceIndex) < 0) - PCPP_LOG_ERROR("Unable to read interface index of device"); + // try to set hardware device clock + m_HwClockEnabled = setPfRingDeviceClock(ring); - // try to set hardware device clock - m_HwClockEnabled = setPfRingDeviceClock(ring); + // set interface MTU + int mtu = pfring_get_mtu_size(ring); + if (mtu < 0) + // cppcheck-suppress shiftNegative + PCPP_LOG_ERROR("Could not get MTU. pfring_get_mtu_size returned an error: " << mtu); + else + m_DeviceMTU = mtu + sizeof(ether_header) + sizeof(vlan_header); - // set interface MTU - int mtu = pfring_get_mtu_size(ring); - if (mtu < 0) - // cppcheck-suppress shiftNegative - PCPP_LOG_ERROR("Could not get MTU. pfring_get_mtu_size returned an error: " << mtu); - else - m_DeviceMTU = mtu + sizeof(ether_header) + sizeof(vlan_header); + if (Logger::getInstance().isDebugEnabled(PcapLogModulePfRingDevice)) + { + std::string hwEnabled = (m_HwClockEnabled ? "enabled" : "disabled"); + PCPP_LOG_DEBUG("Capturing from " << m_DeviceName << " [" << m_MacAddress + << "][ifIndex: " << m_InterfaceIndex << "][MTU: " << m_DeviceMTU + << "], HW clock " << hwEnabled); + } - if (Logger::getInstance().isDebugEnabled(PcapLogModulePfRingDevice)) - { - std::string hwEnabled = (m_HwClockEnabled ? "enabled" : "disabled"); - PCPP_LOG_DEBUG("Capturing from " << m_DeviceName << " [" << m_MacAddress << "][ifIndex: " << m_InterfaceIndex << "][MTU: " << m_DeviceMTU << "], HW clock " << hwEnabled); + if (closeRing) + pfring_close(ring); } + bool PfRingDevice::sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues) + { + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device is not opened. Cannot send packets"); + return false; + } - if (closeRing) - pfring_close(ring); -} - + uint8_t flushTxAsUint = (flushTxQueues ? 1 : 0); -bool PfRingDevice::sendData(const uint8_t* packetData, int packetDataLength, bool flushTxQueues) -{ - if (!m_DeviceOpened) - { - PCPP_LOG_ERROR("Device is not opened. Cannot send packets"); - return false; - } +# define MAX_TRIES 5 - uint8_t flushTxAsUint = (flushTxQueues? 1 : 0); + int tries = 0; + int res = 0; + while (tries < MAX_TRIES) + { + // don't allow sending of data larger than the MTU, otherwise pfring_send will fail + if (packetDataLength > m_DeviceMTU) + packetDataLength = m_DeviceMTU; - #define MAX_TRIES 5 + // if the device is opened, m_PfRingDescriptors[0] will always be set and enables + res = pfring_send(m_PfRingDescriptors[0], (char*)packetData, packetDataLength, flushTxAsUint); - int tries = 0; - int res = 0; - while (tries < MAX_TRIES) - { - // don't allow sending of data larger than the MTU, otherwise pfring_send will fail - if (packetDataLength > m_DeviceMTU) - packetDataLength = m_DeviceMTU; + // res == -1 means it's an error coming from "sendto" which is the Linux API PF_RING is using to send + // packets errno == ENOBUFS means write buffer is full. PF_RING driver expects the userspace to handle this + // case My implementation is to sleep for 10 usec and try again + if (res == -1 && errno == ENOBUFS) + { + tries++; + PCPP_LOG_DEBUG( + "Try #" + << tries + << ": Got ENOBUFS (write buffer full) error while sending packet. Sleeping 20 usec and trying again"); + usleep(2000); + } + else + break; + } - // if the device is opened, m_PfRingDescriptors[0] will always be set and enables - res = pfring_send(m_PfRingDescriptors[0], (char*)packetData, packetDataLength, flushTxAsUint); + if (tries >= MAX_TRIES) + { + PCPP_LOG_ERROR("Tried to send data " << MAX_TRIES << " times but write buffer is full"); + return false; + } - // res == -1 means it's an error coming from "sendto" which is the Linux API PF_RING is using to send packets - // errno == ENOBUFS means write buffer is full. PF_RING driver expects the userspace to handle this case - // My implementation is to sleep for 10 usec and try again - if (res == -1 && errno == ENOBUFS) + if (res < 0) { - tries++; - PCPP_LOG_DEBUG("Try #" << tries << ": Got ENOBUFS (write buffer full) error while sending packet. Sleeping 20 usec and trying again"); - usleep(2000); + // res == -1 means it's an error coming from "sendto" which is the Linux API PF_RING is using to send + // packets + if (res == -1) + PCPP_LOG_ERROR("Error sending packet: Linux errno: " << strerror(errno) << " [" << errno << "]"); + else + PCPP_LOG_ERROR("Error sending packet: pfring_send returned an error: " + << res << " , errno: " << strerror(errno) << " [" << errno << "]"); + return false; } - else - break; + else if (res != packetDataLength) + { + PCPP_LOG_ERROR("Couldn't send all bytes, only " << res << " bytes out of " << packetDataLength + << " bytes were sent"); + return false; + } + + return true; } - if (tries >= MAX_TRIES) + bool PfRingDevice::sendPacket(const uint8_t* packetData, int packetDataLength) { - PCPP_LOG_ERROR("Tried to send data " << MAX_TRIES << " times but write buffer is full"); - return false; + return sendData(packetData, packetDataLength, true); } - if (res < 0) + bool PfRingDevice::sendPacket(const RawPacket& rawPacket) { - // res == -1 means it's an error coming from "sendto" which is the Linux API PF_RING is using to send packets - if (res == -1) - PCPP_LOG_ERROR("Error sending packet: Linux errno: " << strerror(errno) << " [" << errno << "]"); - else - PCPP_LOG_ERROR("Error sending packet: pfring_send returned an error: " << res << " , errno: " << strerror(errno)<< " [" << errno << "]"); - return false; - } else if (res != packetDataLength) + return sendData(rawPacket.getRawData(), rawPacket.getRawDataLen(), true); + } + + bool PfRingDevice::sendPacket(const Packet& packet) { - PCPP_LOG_ERROR("Couldn't send all bytes, only " << res << " bytes out of " << packetDataLength << " bytes were sent"); - return false; + return sendData(packet.getRawPacketReadOnly()->getRawData(), packet.getRawPacketReadOnly()->getRawDataLen(), + true); } - return true; -} + int PfRingDevice::sendPackets(const RawPacket* rawPacketsArr, int arrLength) + { + int packetsSent = 0; + for (int i = 0; i < arrLength; i++) + { + if (!sendData(rawPacketsArr[i].getRawData(), rawPacketsArr[i].getRawDataLen(), false)) + break; + else + packetsSent++; + } -bool PfRingDevice::sendPacket(const uint8_t* packetData, int packetDataLength) -{ - return sendData(packetData, packetDataLength, true); -} + // The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC + pfring_flush_tx_packets(m_PfRingDescriptors[0]); + PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " raw packets were sent successfully"); -bool PfRingDevice::sendPacket(const RawPacket& rawPacket) -{ - return sendData(rawPacket.getRawData(), rawPacket.getRawDataLen(), true); -} + return packetsSent; + } + int PfRingDevice::sendPackets(const Packet** packetsArr, int arrLength) + { + int packetsSent = 0; + for (int i = 0; i < arrLength; i++) + { + if (!sendData(packetsArr[i]->getRawPacketReadOnly()->getRawData(), + packetsArr[i]->getRawPacketReadOnly()->getRawDataLen(), false)) + break; + else + packetsSent++; + } -bool PfRingDevice::sendPacket(const Packet& packet) -{ - return sendData(packet.getRawPacketReadOnly()->getRawData(), packet.getRawPacketReadOnly()->getRawDataLen(), true); -} + // The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC + pfring_flush_tx_packets(m_PfRingDescriptors[0]); + PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " packets were sent successfully"); -int PfRingDevice::sendPackets(const RawPacket* rawPacketsArr, int arrLength) -{ - int packetsSent = 0; - for (int i = 0; i < arrLength; i++) - { - if (!sendData(rawPacketsArr[i].getRawData(), rawPacketsArr[i].getRawDataLen(), false)) - break; - else - packetsSent++; + return packetsSent; } - // The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC - pfring_flush_tx_packets(m_PfRingDescriptors[0]); + int PfRingDevice::sendPackets(const RawPacketVector& rawPackets) + { + int packetsSent = 0; + for (RawPacketVector::ConstVectorIterator iter = rawPackets.begin(); iter != rawPackets.end(); iter++) + { + if (!sendData((*iter)->getRawData(), (*iter)->getRawDataLen(), false)) + break; + else + packetsSent++; + } - PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " raw packets were sent successfully"); + // The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC + pfring_flush_tx_packets(m_PfRingDescriptors[0]); - return packetsSent; -} + PCPP_LOG_DEBUG(packetsSent << " out of " << rawPackets.size() << " raw packets were sent successfully"); -int PfRingDevice::sendPackets(const Packet** packetsArr, int arrLength) -{ - int packetsSent = 0; - for (int i = 0; i < arrLength; i++) - { - if (!sendData(packetsArr[i]->getRawPacketReadOnly()->getRawData(), packetsArr[i]->getRawPacketReadOnly()->getRawDataLen(), false)) - break; - else - packetsSent++; + return packetsSent; } - // The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC - pfring_flush_tx_packets(m_PfRingDescriptors[0]); - - PCPP_LOG_DEBUG(packetsSent << " out of " << arrLength << " packets were sent successfully"); + PfRingDevice::CoreConfiguration::CoreConfiguration() : Channel(NULL), IsInUse(false), IsAffinitySet(true) + {} - return packetsSent; -} - -int PfRingDevice::sendPackets(const RawPacketVector& rawPackets) -{ - int packetsSent = 0; - for (RawPacketVector::ConstVectorIterator iter = rawPackets.begin(); iter != rawPackets.end(); iter++) + void PfRingDevice::CoreConfiguration::clear() { - if (!sendData((*iter)->getRawData(), (*iter)->getRawDataLen(), false)) - break; - else - packetsSent++; + Channel = NULL; + IsInUse = false; + IsAffinitySet = true; } - // The following method isn't supported in PF_RING aware drivers, probably only in DNA and ZC - pfring_flush_tx_packets(m_PfRingDescriptors[0]); - - PCPP_LOG_DEBUG(packetsSent << " out of " << rawPackets.size() << " raw packets were sent successfully"); - - return packetsSent; -} - -PfRingDevice::CoreConfiguration::CoreConfiguration() - : Channel(NULL), IsInUse(false), IsAffinitySet(true) -{ -} - -void PfRingDevice::CoreConfiguration::clear() -{ - Channel = NULL; - IsInUse = false; - IsAffinitySet = true; -} - -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/PfRingDeviceList.cpp b/Pcap++/src/PfRingDeviceList.cpp index e2f1489c48..1b9dae42f5 100644 --- a/Pcap++/src/PfRingDeviceList.cpp +++ b/Pcap++/src/PfRingDeviceList.cpp @@ -2,16 +2,16 @@ // GCOVR_EXCL_START -#define LOG_MODULE PcapLogModulePfRingDevice +# define LOG_MODULE PcapLogModulePfRingDevice -#include -#include -#include "PfRingDeviceList.h" -#include "SystemUtils.h" -#include "DeviceUtils.h" -#include "Logger.h" -#include "pcap.h" -#include "pfring.h" +# include +# include +# include "PfRingDeviceList.h" +# include "SystemUtils.h" +# include "DeviceUtils.h" +# include "Logger.h" +# include "pcap.h" +# include "pfring.h" namespace pcpp { @@ -25,7 +25,10 @@ namespace pcpp */ struct PfRingCloseDeleter { - void operator()(pfring* ptr) const { pfring_close(ptr); } + void operator()(pfring* ptr) const + { + pfring_close(ptr); + } }; /** @@ -44,91 +47,93 @@ namespace pcpp std::array versionAsString; std::snprintf(versionAsString.data(), versionAsString.size(), "PF_RING v.%u.%u.%u\n", - (version & 0xFFFF0000) >> 16, - (version & 0x0000FF00) >> 8, - version & 0x000000FF); + (version & 0xFFFF0000) >> 16, (version & 0x0000FF00) >> 8, version & 0x000000FF); return std::string(versionAsString.data()); } - } + } // namespace /// @endcond -PfRingDeviceList::PfRingDeviceList() -{ - m_PfRingVersion = ""; - - bool moduleLoaded = false; - try - { - // if there is some result the module must be loaded - moduleLoaded = !(executeShellCommand("lsmod | grep pf_ring").empty()); - } - catch (const std::exception& e) + PfRingDeviceList::PfRingDeviceList() { - PCPP_LOG_ERROR("PF_RING load error: " << e.what()); - moduleLoaded = false; - } + m_PfRingVersion = ""; - if (!moduleLoaded) - { - PCPP_LOG_ERROR("PF_RING kernel module isn't loaded. Please run: 'sudo insmod /kernel/pf_ring.ko'"); - return; - } + bool moduleLoaded = false; + try + { + // if there is some result the module must be loaded + moduleLoaded = !(executeShellCommand("lsmod | grep pf_ring").empty()); + } + catch (const std::exception& e) + { + PCPP_LOG_ERROR("PF_RING load error: " << e.what()); + moduleLoaded = false; + } - PCPP_LOG_DEBUG("PF_RING kernel module is loaded"); + if (!moduleLoaded) + { + PCPP_LOG_ERROR( + "PF_RING kernel module isn't loaded. Please run: 'sudo insmod /kernel/pf_ring.ko'"); + return; + } - PCPP_LOG_DEBUG("PfRingDeviceList init: searching all interfaces on machine"); - try - { - auto interfaceList = internal::getAllLocalPcapDevices(); + PCPP_LOG_DEBUG("PF_RING kernel module is loaded"); - for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next) + PCPP_LOG_DEBUG("PfRingDeviceList init: searching all interfaces on machine"); + try { - uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS; - auto ring = std::unique_ptr(pfring_open(currInterface->name, 128, flags)); - if (ring != nullptr) + auto interfaceList = internal::getAllLocalPcapDevices(); + + for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; + currInterface = currInterface->next) { - if (m_PfRingVersion.empty()) + uint32_t flags = PF_RING_PROMISC | PF_RING_DNA_SYMMETRIC_RSS; + auto ring = std::unique_ptr(pfring_open(currInterface->name, 128, flags)); + if (ring != nullptr) { - m_PfRingVersion = readPfRingVersion(ring.get()); - PCPP_LOG_DEBUG("PF_RING version is: " << m_PfRingVersion); + if (m_PfRingVersion.empty()) + { + m_PfRingVersion = readPfRingVersion(ring.get()); + PCPP_LOG_DEBUG("PF_RING version is: " << m_PfRingVersion); + } + std::unique_ptr newDev = + std::unique_ptr(new PfRingDevice(currInterface->name)); + m_PfRingDeviceList.push_back(std::move(newDev)); + PCPP_LOG_DEBUG("Found interface: " << currInterface->name); } - std::unique_ptr newDev = std::unique_ptr(new PfRingDevice(currInterface->name)); - m_PfRingDeviceList.push_back(std::move(newDev)); - PCPP_LOG_DEBUG("Found interface: " << currInterface->name); } } - } - catch (const std::runtime_error& e) - { - PCPP_LOG_ERROR("PfRingDeviceList init error: " << e.what()); - } - - PCPP_LOG_DEBUG("PfRingDeviceList init end"); + catch (const std::runtime_error& e) + { + PCPP_LOG_ERROR("PfRingDeviceList init error: " << e.what()); + } - // Full update of all elements of the view vector to synchronize them with the main vector. - m_PfRingDeviceListView.resize(m_PfRingDeviceList.size()); - std::transform(m_PfRingDeviceList.begin(), m_PfRingDeviceList.end(), m_PfRingDeviceListView.begin(), - [](const std::unique_ptr& ptr) { return ptr.get(); }); -} + PCPP_LOG_DEBUG("PfRingDeviceList init end"); -PfRingDevice* PfRingDeviceList::getPfRingDeviceByName(const std::string &devName) const -{ - PCPP_LOG_DEBUG("Searching all live devices..."); - auto devIter = std::find_if(m_PfRingDeviceList.begin(), m_PfRingDeviceList.end(), - [&devName](const std::unique_ptr& dev) { return dev->getDeviceName() == devName; }); + // Full update of all elements of the view vector to synchronize them with the main vector. + m_PfRingDeviceListView.resize(m_PfRingDeviceList.size()); + std::transform(m_PfRingDeviceList.begin(), m_PfRingDeviceList.end(), m_PfRingDeviceListView.begin(), + [](const std::unique_ptr& ptr) { return ptr.get(); }); + } - if (devIter == m_PfRingDeviceList.end()) + PfRingDevice* PfRingDeviceList::getPfRingDeviceByName(const std::string& devName) const { - PCPP_LOG_DEBUG("Found no PF_RING devices with name '" << devName << "'"); - return nullptr; - } + PCPP_LOG_DEBUG("Searching all live devices..."); + auto devIter = std::find_if( + m_PfRingDeviceList.begin(), m_PfRingDeviceList.end(), + [&devName](const std::unique_ptr& dev) { return dev->getDeviceName() == devName; }); - return devIter->get(); -} + if (devIter == m_PfRingDeviceList.end()) + { + PCPP_LOG_DEBUG("Found no PF_RING devices with name '" << devName << "'"); + return nullptr; + } + + return devIter->get(); + } -} // namespace pcpp +} // namespace pcpp // GCOVR_EXCL_STOP diff --git a/Pcap++/src/RawSocketDevice.cpp b/Pcap++/src/RawSocketDevice.cpp index c4651439af..e4c2ac5fac 100644 --- a/Pcap++/src/RawSocketDevice.cpp +++ b/Pcap++/src/RawSocketDevice.cpp @@ -2,13 +2,13 @@ #include "EndianPortable.h" #include #ifdef __linux__ -#include -#include -#include -#include -#include -#include -#include +# include +# include +# include +# include +# include +# include +# include #endif #include #include "Logger.h" @@ -24,545 +24,548 @@ namespace pcpp #if defined(_WIN32) -#ifndef SIO_RCVALL +# ifndef SIO_RCVALL /* SIO_RCVALL defined on w2k and later. Not defined in Mingw32 */ /* 0x98000001 = _WSAIOW(IOC_VENDOR,1) */ -# define SIO_RCVALL 0x98000001 -#endif // SIO_RCVALL +# define SIO_RCVALL 0x98000001 +# endif // SIO_RCVALL -class WinSockInitializer -{ -private: - static bool m_IsInitialized; - -public: - - static void initialize() + class WinSockInitializer { - if (m_IsInitialized) - return; + private: + static bool m_IsInitialized; - // Load Winsock - WSADATA wsaData; - int res = WSAStartup(MAKEWORD(2,2), &wsaData); - if (res != 0) + public: + static void initialize() { - PCPP_LOG_ERROR("WSAStartup failed with error code: " << res); - m_IsInitialized = false; - } + if (m_IsInitialized) + return; - m_IsInitialized = true; - } -}; + // Load Winsock + WSADATA wsaData; + int res = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (res != 0) + { + PCPP_LOG_ERROR("WSAStartup failed with error code: " << res); + m_IsInitialized = false; + } -bool WinSockInitializer::m_IsInitialized = false; + m_IsInitialized = true; + } + }; -#endif // defined(_WIN32) + bool WinSockInitializer::m_IsInitialized = false; -struct SocketContainer -{ +#endif // defined(_WIN32) + + struct SocketContainer + { #if defined(_WIN32) - SOCKET fd; + SOCKET fd; #elif defined(__linux__) - int fd; - int interfaceIndex; - std::string interfaceName; + int fd; + int interfaceIndex; + std::string interfaceName; #endif -}; + }; -RawSocketDevice::RawSocketDevice(const IPAddress& interfaceIP) : IDevice(), m_Socket(nullptr) -{ + RawSocketDevice::RawSocketDevice(const IPAddress& interfaceIP) : IDevice(), m_Socket(nullptr) + { #if defined(_WIN32) - WinSockInitializer::initialize(); - m_InterfaceIP = interfaceIP; - m_SockFamily = (m_InterfaceIP.getType() == IPAddress::IPv4AddressType ? IPv4 : IPv6); + WinSockInitializer::initialize(); + m_InterfaceIP = interfaceIP; + m_SockFamily = (m_InterfaceIP.getType() == IPAddress::IPv4AddressType ? IPv4 : IPv6); #elif defined(__linux__) - m_InterfaceIP = interfaceIP; - m_SockFamily = Ethernet; + m_InterfaceIP = interfaceIP; + m_SockFamily = Ethernet; #else - m_SockFamily = Ethernet; + m_SockFamily = Ethernet; #endif -} - + } -RawSocketDevice::~RawSocketDevice() -{ - close(); -} + RawSocketDevice::~RawSocketDevice() + { + close(); + } -RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawPacket, bool blocking, double timeout) -{ + RawSocketDevice::RecvPacketResult RawSocketDevice::receivePacket(RawPacket& rawPacket, bool blocking, + double timeout) + { #if defined(_WIN32) - if (!isOpened()) - { - PCPP_LOG_ERROR("Device is not open"); - return RecvError; - } + if (!isOpened()) + { + PCPP_LOG_ERROR("Device is not open"); + return RecvError; + } - SOCKET fd = ((SocketContainer*)m_Socket)->fd; - char* buffer = new char[RAW_SOCKET_BUFFER_LEN]; - memset(buffer, 0, RAW_SOCKET_BUFFER_LEN); + SOCKET fd = ((SocketContainer*)m_Socket)->fd; + char* buffer = new char[RAW_SOCKET_BUFFER_LEN]; + memset(buffer, 0, RAW_SOCKET_BUFFER_LEN); - // value of 0 timeout means disabling timeout - if (timeout < 0) - timeout = 0; + // value of 0 timeout means disabling timeout + if (timeout < 0) + timeout = 0; - u_long blockingMode = (blocking? 0 : 1); - ioctlsocket(fd, FIONBIO, &blockingMode); + u_long blockingMode = (blocking ? 0 : 1); + ioctlsocket(fd, FIONBIO, &blockingMode); - DWORD timeoutVal = timeout * 1000; // convert to milliseconds - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal)); + DWORD timeoutVal = timeout * 1000; // convert to milliseconds + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal)); - //recvfrom(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0, (struct sockaddr*)&sockAddr,(socklen_t*)&sockAddrLen); - int bufferLen = recv(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0); - if (bufferLen < 0) - { - delete [] buffer; - int errorCode = 0; - RecvPacketResult error = getError(errorCode); + // recvfrom(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0, (struct sockaddr*)&sockAddr,(socklen_t*)&sockAddrLen); + int bufferLen = recv(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0); + if (bufferLen < 0) + { + delete[] buffer; + int errorCode = 0; + RecvPacketResult error = getError(errorCode); - if (error == RecvError) - PCPP_LOG_ERROR("Error reading from recvfrom. Error code is " << errorCode); + if (error == RecvError) + PCPP_LOG_ERROR("Error reading from recvfrom. Error code is " << errorCode); - return error; - } + return error; + } - if (bufferLen > 0) - { - timeval time; - gettimeofday(&time, NULL); - rawPacket.setRawData((const uint8_t*)buffer, bufferLen, time, LINKTYPE_DLT_RAW1); - return RecvSuccess; - } + if (bufferLen > 0) + { + timeval time; + gettimeofday(&time, NULL); + rawPacket.setRawData((const uint8_t*)buffer, bufferLen, time, LINKTYPE_DLT_RAW1); + return RecvSuccess; + } - PCPP_LOG_ERROR("Buffer length is zero"); - delete [] buffer; - return RecvError; + PCPP_LOG_ERROR("Buffer length is zero"); + delete[] buffer; + return RecvError; #elif defined(__linux__) - if (!isOpened()) - { - PCPP_LOG_ERROR("Device is not open"); - return RecvError; - } + if (!isOpened()) + { + PCPP_LOG_ERROR("Device is not open"); + return RecvError; + } - int fd = ((SocketContainer*)m_Socket)->fd; - char* buffer = new char[RAW_SOCKET_BUFFER_LEN]; - memset(buffer, 0, RAW_SOCKET_BUFFER_LEN); + int fd = ((SocketContainer*)m_Socket)->fd; + char* buffer = new char[RAW_SOCKET_BUFFER_LEN]; + memset(buffer, 0, RAW_SOCKET_BUFFER_LEN); - // value of 0 timeout means disabling timeout - if (timeout < 0) - timeout = 0; + // value of 0 timeout means disabling timeout + if (timeout < 0) + timeout = 0; - // set blocking or non-blocking flag - int flags = fcntl(fd, F_GETFL, 0); - if (flags == -1) - { - delete [] buffer; - PCPP_LOG_ERROR("Cannot get socket flags"); - return RecvError; - } - flags = (blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK)); - if (fcntl(fd, F_SETFL, flags) != 0) - { - delete [] buffer; - PCPP_LOG_ERROR("Cannot set socket non-blocking flag"); - return RecvError; - } + // set blocking or non-blocking flag + int flags = fcntl(fd, F_GETFL, 0); + if (flags == -1) + { + delete[] buffer; + PCPP_LOG_ERROR("Cannot get socket flags"); + return RecvError; + } + flags = (blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK)); + if (fcntl(fd, F_SETFL, flags) != 0) + { + delete[] buffer; + PCPP_LOG_ERROR("Cannot set socket non-blocking flag"); + return RecvError; + } - // set timeout on socket - struct timeval timeoutVal; - timeoutVal.tv_sec = static_cast(timeout); - timeoutVal.tv_usec = static_cast((timeout - timeoutVal.tv_sec) * 1000000); - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal)); + // set timeout on socket + struct timeval timeoutVal; + timeoutVal.tv_sec = static_cast(timeout); + timeoutVal.tv_usec = static_cast((timeout - timeoutVal.tv_sec) * 1000000); + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeoutVal, sizeof(timeoutVal)); - int bufferLen = recv(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0); - if (bufferLen < 0) - { - delete [] buffer; - int errorCode = errno; - RecvPacketResult error = getError(errorCode); + int bufferLen = recv(fd, buffer, RAW_SOCKET_BUFFER_LEN, 0); + if (bufferLen < 0) + { + delete[] buffer; + int errorCode = errno; + RecvPacketResult error = getError(errorCode); - if (error == RecvError) - PCPP_LOG_ERROR("Error reading from recvfrom. Error code is " << errorCode); + if (error == RecvError) + PCPP_LOG_ERROR("Error reading from recvfrom. Error code is " << errorCode); - return error; - } + return error; + } - if (bufferLen > 0) - { - timeval time; - gettimeofday(&time, NULL); - rawPacket.setRawData((const uint8_t*)buffer, bufferLen, time, LINKTYPE_ETHERNET); - return RecvSuccess; - } + if (bufferLen > 0) + { + timeval time; + gettimeofday(&time, NULL); + rawPacket.setRawData((const uint8_t*)buffer, bufferLen, time, LINKTYPE_ETHERNET); + return RecvSuccess; + } - PCPP_LOG_ERROR("Buffer length is zero"); - delete [] buffer; - return RecvError; + PCPP_LOG_ERROR("Buffer length is zero"); + delete[] buffer; + return RecvError; #else - PCPP_LOG_ERROR("Raw socket are not supported on this platform"); - return RecvError; + PCPP_LOG_ERROR("Raw socket are not supported on this platform"); + return RecvError; #endif -} - -int RawSocketDevice::receivePackets(RawPacketVector& packetVec, double timeout, int& failedRecv) -{ - if (!isOpened()) - { - PCPP_LOG_ERROR("Device is not open"); - return 0; } - int64_t timeoutMilli = timeout * 1000; + int RawSocketDevice::receivePackets(RawPacketVector& packetVec, double timeout, int& failedRecv) + { + if (!isOpened()) + { + PCPP_LOG_ERROR("Device is not open"); + return 0; + } - int packetCount = 0; - failedRecv = 0; + int64_t timeoutMilli = timeout * 1000; - auto start = std::chrono::steady_clock::now(); + int packetCount = 0; + failedRecv = 0; - while (true) - { - auto now = std::chrono::steady_clock::now(); - auto elapsedMilli = std::chrono::duration_cast(now - start).count(); - double elapsedSec = static_cast(elapsedMilli) / 1000; + auto start = std::chrono::steady_clock::now(); - if (elapsedMilli >= timeoutMilli) + while (true) { - break; - } + auto now = std::chrono::steady_clock::now(); + auto elapsedMilli = std::chrono::duration_cast(now - start).count(); + double elapsedSec = static_cast(elapsedMilli) / 1000; - RawPacket* rawPacket = new RawPacket(); - if (receivePacket(*rawPacket, true, elapsedSec) == RecvSuccess) - { - packetVec.pushBack(rawPacket); - packetCount++; - } - else - { - failedRecv++; - delete rawPacket; + if (elapsedMilli >= timeoutMilli) + { + break; + } + + RawPacket* rawPacket = new RawPacket(); + if (receivePacket(*rawPacket, true, elapsedSec) == RecvSuccess) + { + packetVec.pushBack(rawPacket); + packetCount++; + } + else + { + failedRecv++; + delete rawPacket; + } } - } - return packetCount; -} + return packetCount; + } -bool RawSocketDevice::sendPacket(const RawPacket* rawPacket) -{ + bool RawSocketDevice::sendPacket(const RawPacket* rawPacket) + { #if defined(_WIN32) - PCPP_LOG_ERROR("Sending packets with raw socket are not supported on Windows"); - return 0; + PCPP_LOG_ERROR("Sending packets with raw socket are not supported on Windows"); + return 0; #elif defined(__linux__) - if (!isOpened()) - { - PCPP_LOG_ERROR("Device is not open"); - return false; - } + if (!isOpened()) + { + PCPP_LOG_ERROR("Device is not open"); + return false; + } - Packet packet((RawPacket*)rawPacket, OsiModelDataLinkLayer); - if (!packet.isPacketOfType(pcpp::Ethernet)) - { - PCPP_LOG_ERROR("Can't send non-Ethernet packets"); - return false; - } + Packet packet((RawPacket*)rawPacket, OsiModelDataLinkLayer); + if (!packet.isPacketOfType(pcpp::Ethernet)) + { + PCPP_LOG_ERROR("Can't send non-Ethernet packets"); + return false; + } - int fd = ((SocketContainer*)m_Socket)->fd; + int fd = ((SocketContainer*)m_Socket)->fd; - sockaddr_ll addr; - memset(&addr, 0, sizeof(struct sockaddr_ll)); - addr.sll_family = htobe16(PF_PACKET); - addr.sll_protocol = htobe16(ETH_P_ALL); - addr.sll_halen = 6; - addr.sll_ifindex = ((SocketContainer*)m_Socket)->interfaceIndex; + sockaddr_ll addr; + memset(&addr, 0, sizeof(struct sockaddr_ll)); + addr.sll_family = htobe16(PF_PACKET); + addr.sll_protocol = htobe16(ETH_P_ALL); + addr.sll_halen = 6; + addr.sll_ifindex = ((SocketContainer*)m_Socket)->interfaceIndex; - EthLayer* ethLayer = packet.getLayerOfType(); - MacAddress dstMac = ethLayer->getDestMac(); - dstMac.copyTo((uint8_t*)&(addr.sll_addr)); + EthLayer* ethLayer = packet.getLayerOfType(); + MacAddress dstMac = ethLayer->getDestMac(); + dstMac.copyTo((uint8_t*)&(addr.sll_addr)); - if (::sendto(fd, ((RawPacket*)rawPacket)->getRawData(), ((RawPacket*)rawPacket)->getRawDataLen(), 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) - { - PCPP_LOG_ERROR("Failed to send packet. Error was: '" << strerror(errno) << "'"); - return false; - } + if (::sendto(fd, ((RawPacket*)rawPacket)->getRawData(), ((RawPacket*)rawPacket)->getRawDataLen(), 0, + (struct sockaddr*)&addr, sizeof(addr)) == -1) + { + PCPP_LOG_ERROR("Failed to send packet. Error was: '" << strerror(errno) << "'"); + return false; + } - return true; + return true; #else - PCPP_LOG_ERROR("Raw socket are not supported on this platform"); - return 0; + PCPP_LOG_ERROR("Raw socket are not supported on this platform"); + return 0; #endif -} + } -int RawSocketDevice::sendPackets(const RawPacketVector& packetVec) -{ + int RawSocketDevice::sendPackets(const RawPacketVector& packetVec) + { #if defined(_WIN32) - PCPP_LOG_ERROR("Sending packets with raw socket are not supported on Windows"); - return false; + PCPP_LOG_ERROR("Sending packets with raw socket are not supported on Windows"); + return false; #elif defined(__linux__) - if (!isOpened()) - { - PCPP_LOG_ERROR("Device is not open"); - return 0; - } + if (!isOpened()) + { + PCPP_LOG_ERROR("Device is not open"); + return 0; + } - int fd = ((SocketContainer*)m_Socket)->fd; + int fd = ((SocketContainer*)m_Socket)->fd; - sockaddr_ll addr; - memset(&addr, 0, sizeof(struct sockaddr_ll)); - addr.sll_family = htobe16(PF_PACKET); - addr.sll_protocol = htobe16(ETH_P_ALL); - addr.sll_halen = 6; - addr.sll_ifindex = ((SocketContainer*)m_Socket)->interfaceIndex; + sockaddr_ll addr; + memset(&addr, 0, sizeof(struct sockaddr_ll)); + addr.sll_family = htobe16(PF_PACKET); + addr.sll_protocol = htobe16(ETH_P_ALL); + addr.sll_halen = 6; + addr.sll_ifindex = ((SocketContainer*)m_Socket)->interfaceIndex; - int sendCount = 0; + int sendCount = 0; - for (RawPacketVector::ConstVectorIterator iter = packetVec.begin(); iter != packetVec.end(); iter++) - { - Packet packet(*iter, OsiModelDataLinkLayer); - if (!packet.isPacketOfType(pcpp::Ethernet)) + for (RawPacketVector::ConstVectorIterator iter = packetVec.begin(); iter != packetVec.end(); iter++) { - PCPP_LOG_DEBUG("Can't send non-Ethernet packets"); - continue; - } + Packet packet(*iter, OsiModelDataLinkLayer); + if (!packet.isPacketOfType(pcpp::Ethernet)) + { + PCPP_LOG_DEBUG("Can't send non-Ethernet packets"); + continue; + } - EthLayer* ethLayer = packet.getLayerOfType(); - MacAddress dstMac = ethLayer->getDestMac(); - dstMac.copyTo((uint8_t*)&(addr.sll_addr)); + EthLayer* ethLayer = packet.getLayerOfType(); + MacAddress dstMac = ethLayer->getDestMac(); + dstMac.copyTo((uint8_t*)&(addr.sll_addr)); - if (::sendto(fd, (*iter)->getRawData(), (*iter)->getRawDataLen(), 0, (struct sockaddr*)&addr, sizeof(addr)) == -1) - { - PCPP_LOG_DEBUG("Failed to send packet. Error was: '" << strerror(errno) << "'"); - continue; - } + if (::sendto(fd, (*iter)->getRawData(), (*iter)->getRawDataLen(), 0, (struct sockaddr*)&addr, + sizeof(addr)) == -1) + { + PCPP_LOG_DEBUG("Failed to send packet. Error was: '" << strerror(errno) << "'"); + continue; + } - sendCount++; - } + sendCount++; + } - return sendCount; + return sendCount; #else - PCPP_LOG_ERROR("Raw socket are not supported on this platform"); - return false; + PCPP_LOG_ERROR("Raw socket are not supported on this platform"); + return false; #endif -} - + } -bool RawSocketDevice::open() -{ + bool RawSocketDevice::open() + { #if defined(_WIN32) - int family = (m_SockFamily == IPv4 ? AF_INET : AF_INET6); - SOCKET fd = socket(family, SOCK_RAW, IPPROTO_IP); - if ((int)fd == SOCKET_ERROR) - { - int error = WSAGetLastError(); - std::string additionalMessage = ""; - if (error == WSAEACCES) - additionalMessage = ", you may not be running with administrative privileges which is required for opening raw sockets on Windows"; - PCPP_LOG_ERROR("Failed to create raw socket. Error code was " << error << " " << additionalMessage); - return false; - } + int family = (m_SockFamily == IPv4 ? AF_INET : AF_INET6); + SOCKET fd = socket(family, SOCK_RAW, IPPROTO_IP); + if ((int)fd == SOCKET_ERROR) + { + int error = WSAGetLastError(); + std::string additionalMessage = ""; + if (error == WSAEACCES) + additionalMessage = + ", you may not be running with administrative privileges which is required for opening raw sockets on Windows"; + PCPP_LOG_ERROR("Failed to create raw socket. Error code was " << error << " " << additionalMessage); + return false; + } - void* localAddr = NULL; - struct sockaddr_in localAddrIPv4; - struct sockaddr_in6 localAddrIPv6; - size_t localAddrSize = 0; + void* localAddr = NULL; + struct sockaddr_in localAddrIPv4; + struct sockaddr_in6 localAddrIPv6; + size_t localAddrSize = 0; - if (m_SockFamily == IPv4) - { - localAddrIPv4.sin_family = family; - int res = inet_pton(family, m_InterfaceIP.toString().c_str(), &localAddrIPv4.sin_addr.s_addr); - if (res <= 0) + if (m_SockFamily == IPv4) + { + localAddrIPv4.sin_family = family; + int res = inet_pton(family, m_InterfaceIP.toString().c_str(), &localAddrIPv4.sin_addr.s_addr); + if (res <= 0) + { + PCPP_LOG_ERROR("inet_pton failed, probably IP address provided is in bad format"); + closesocket(fd); + return false; + } + localAddrIPv4.sin_port = 0; // Any local port will do + localAddr = &localAddrIPv4; + localAddrSize = sizeof(localAddrIPv4); + } + else + { + localAddrIPv6.sin6_family = family; + int res = inet_pton(AF_INET6, m_InterfaceIP.toString().c_str(), &localAddrIPv6.sin6_addr.s6_addr); + if (res <= 0) + { + PCPP_LOG_ERROR("inet_pton failed, probably IP address provided is in bad format"); + closesocket(fd); + return false; + } + localAddrIPv6.sin6_port = 0; // Any local port will do + localAddrIPv6.sin6_scope_id = 0; + localAddr = &localAddrIPv6; + localAddrSize = sizeof(localAddrIPv6); + } + + if (bind(fd, (struct sockaddr*)localAddr, localAddrSize) == SOCKET_ERROR) { - PCPP_LOG_ERROR("inet_pton failed, probably IP address provided is in bad format"); + PCPP_LOG_ERROR("Failed to bind to interface. Error code was '" << WSAGetLastError() << "'"); closesocket(fd); return false; } - localAddrIPv4.sin_port = 0; // Any local port will do - localAddr = &localAddrIPv4; - localAddrSize = sizeof(localAddrIPv4); - } - else - { - localAddrIPv6.sin6_family = family; - int res = inet_pton(AF_INET6, m_InterfaceIP.toString().c_str(), &localAddrIPv6.sin6_addr.s6_addr); - if (res <= 0) + + int n = 1; + DWORD dwBytesRet; + if (WSAIoctl(fd, SIO_RCVALL, &n, sizeof(n), NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) { - PCPP_LOG_ERROR("inet_pton failed, probably IP address provided is in bad format"); + PCPP_LOG_ERROR("Call to WSAIotcl(" << std::hex << SIO_RCVALL << ") failed with error code " + << WSAGetLastError()); closesocket(fd); return false; } - localAddrIPv6.sin6_port = 0; // Any local port will do - localAddrIPv6.sin6_scope_id = 0; - localAddr = &localAddrIPv6; - localAddrSize = sizeof(localAddrIPv6); - } - if (bind(fd, (struct sockaddr *)localAddr, localAddrSize) == SOCKET_ERROR) - { - PCPP_LOG_ERROR("Failed to bind to interface. Error code was '" << WSAGetLastError() << "'"); - closesocket(fd); - return false; - } - - int n = 1; - DWORD dwBytesRet; - if (WSAIoctl(fd, SIO_RCVALL, &n, sizeof(n), NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) - { - PCPP_LOG_ERROR("Call to WSAIotcl(" << std::hex << SIO_RCVALL << ") failed with error code " << WSAGetLastError()); - closesocket(fd); - return false; - } + m_Socket = new SocketContainer(); + ((SocketContainer*)m_Socket)->fd = fd; - m_Socket = new SocketContainer(); - ((SocketContainer*)m_Socket)->fd = fd; + m_DeviceOpened = true; - m_DeviceOpened = true; - - return true; + return true; #elif defined(__linux__) -#if defined(__ANDROID_API__) && __ANDROID_API__ < 24 - PCPP_LOG_ERROR("Raw sockets aren't supported in Android API < 24"); - return false; -#else - - int fd = socket(AF_PACKET, SOCK_RAW, htobe16(ETH_P_ALL)); - if (fd < 0) - { - PCPP_LOG_ERROR("Failed to create raw socket. Error code was " << errno); +# if defined(__ANDROID_API__) && __ANDROID_API__ < 24 + PCPP_LOG_ERROR("Raw sockets aren't supported in Android API < 24"); return false; - } +# else - // find interface name and index from IP address - struct ifaddrs* addrs; - getifaddrs(&addrs); - std::string ifaceName = ""; - int ifaceIndex = -1; - for (struct ifaddrs* curAddr = addrs; curAddr != NULL; curAddr = curAddr->ifa_next) - { - if (curAddr->ifa_addr && (curAddr->ifa_flags & IFF_UP)) + int fd = socket(AF_PACKET, SOCK_RAW, htobe16(ETH_P_ALL)); + if (fd < 0) { - if (curAddr->ifa_addr->sa_family == AF_INET) + PCPP_LOG_ERROR("Failed to create raw socket. Error code was " << errno); + return false; + } + + // find interface name and index from IP address + struct ifaddrs* addrs; + getifaddrs(&addrs); + std::string ifaceName = ""; + int ifaceIndex = -1; + for (struct ifaddrs* curAddr = addrs; curAddr != NULL; curAddr = curAddr->ifa_next) + { + if (curAddr->ifa_addr && (curAddr->ifa_flags & IFF_UP)) { - struct sockaddr_in* sockAddr = (struct sockaddr_in*)(curAddr->ifa_addr); - char addrAsCharArr[32]; - inet_ntop(curAddr->ifa_addr->sa_family, (void *)&(sockAddr->sin_addr), addrAsCharArr, sizeof(addrAsCharArr)); - if (!strcmp(m_InterfaceIP.toString().c_str(), addrAsCharArr)) + if (curAddr->ifa_addr->sa_family == AF_INET) { - ifaceName = curAddr->ifa_name; - ifaceIndex = if_nametoindex(curAddr->ifa_name); + struct sockaddr_in* sockAddr = (struct sockaddr_in*)(curAddr->ifa_addr); + char addrAsCharArr[32]; + inet_ntop(curAddr->ifa_addr->sa_family, (void*)&(sockAddr->sin_addr), addrAsCharArr, + sizeof(addrAsCharArr)); + if (!strcmp(m_InterfaceIP.toString().c_str(), addrAsCharArr)) + { + ifaceName = curAddr->ifa_name; + ifaceIndex = if_nametoindex(curAddr->ifa_name); + } } - } - else if (curAddr->ifa_addr->sa_family == AF_INET6) - { - struct sockaddr_in6* sockAddr = (struct sockaddr_in6*)(curAddr->ifa_addr); - char addrAsCharArr[40]; - inet_ntop(curAddr->ifa_addr->sa_family, (void *)&(sockAddr->sin6_addr), addrAsCharArr, sizeof(addrAsCharArr)); - if (!strcmp(m_InterfaceIP.toString().c_str(), addrAsCharArr)) + else if (curAddr->ifa_addr->sa_family == AF_INET6) { - ifaceName = curAddr->ifa_name; - ifaceIndex = if_nametoindex(curAddr->ifa_name); + struct sockaddr_in6* sockAddr = (struct sockaddr_in6*)(curAddr->ifa_addr); + char addrAsCharArr[40]; + inet_ntop(curAddr->ifa_addr->sa_family, (void*)&(sockAddr->sin6_addr), addrAsCharArr, + sizeof(addrAsCharArr)); + if (!strcmp(m_InterfaceIP.toString().c_str(), addrAsCharArr)) + { + ifaceName = curAddr->ifa_name; + ifaceIndex = if_nametoindex(curAddr->ifa_name); + } } } - } - } - freeifaddrs(addrs); + freeifaddrs(addrs); - if (ifaceName == "" || ifaceIndex < 0) - { - PCPP_LOG_ERROR("Cannot detect interface name or index from IP address"); - ::close(fd); - return false; - } + if (ifaceName == "" || ifaceIndex < 0) + { + PCPP_LOG_ERROR("Cannot detect interface name or index from IP address"); + ::close(fd); + return false; + } - // bind raw socket to interface - struct ifreq ifr; - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifaceName.c_str()); - if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1) - { - PCPP_LOG_ERROR("Cannot bind raw socket to interface '" << ifaceName << "'"); - ::close(fd); - return false; - } + // bind raw socket to interface + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifaceName.c_str()); + if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(ifr)) == -1) + { + PCPP_LOG_ERROR("Cannot bind raw socket to interface '" << ifaceName << "'"); + ::close(fd); + return false; + } - m_Socket = new SocketContainer(); - ((SocketContainer*)m_Socket)->fd = fd; - ((SocketContainer*)m_Socket)->interfaceIndex = ifaceIndex; - ((SocketContainer*)m_Socket)->interfaceName = ifaceName; + m_Socket = new SocketContainer(); + ((SocketContainer*)m_Socket)->fd = fd; + ((SocketContainer*)m_Socket)->interfaceIndex = ifaceIndex; + ((SocketContainer*)m_Socket)->interfaceName = ifaceName; - m_DeviceOpened = true; + m_DeviceOpened = true; - return true; -#endif // __ANDROID_API__ + return true; +# endif // __ANDROID_API__ #else - PCPP_LOG_ERROR("Raw socket are not supported on this platform"); - return false; + PCPP_LOG_ERROR("Raw socket are not supported on this platform"); + return false; #endif -} + } -void RawSocketDevice::close() -{ - if (m_Socket != nullptr && isOpened()) + void RawSocketDevice::close() { - SocketContainer* sockContainer = (SocketContainer*)m_Socket; + if (m_Socket != nullptr && isOpened()) + { + SocketContainer* sockContainer = (SocketContainer*)m_Socket; #if defined(_WIN32) - closesocket(sockContainer->fd); + closesocket(sockContainer->fd); #elif defined(__linux__) - ::close(sockContainer->fd); + ::close(sockContainer->fd); #endif - delete sockContainer; - m_Socket = nullptr; - m_DeviceOpened = false; + delete sockContainer; + m_Socket = nullptr; + m_DeviceOpened = false; + } } -} -RawSocketDevice::RecvPacketResult RawSocketDevice::getError(int& errorCode) const -{ + RawSocketDevice::RecvPacketResult RawSocketDevice::getError(int& errorCode) const + { #if defined(_WIN32) - errorCode = WSAGetLastError(); - if (errorCode == WSAEWOULDBLOCK) - return RecvWouldBlock; - if (errorCode == WSAETIMEDOUT) - return RecvTimeout; + errorCode = WSAGetLastError(); + if (errorCode == WSAEWOULDBLOCK) + return RecvWouldBlock; + if (errorCode == WSAETIMEDOUT) + return RecvTimeout; - return RecvError; + return RecvError; #elif defined(__linux__) - if ((errorCode == EAGAIN) || (errorCode == EWOULDBLOCK)) - return RecvWouldBlock; + if ((errorCode == EAGAIN) || (errorCode == EWOULDBLOCK)) + return RecvWouldBlock; - return RecvError; + return RecvError; #else - return RecvError; + return RecvError; #endif -} + } -} +} // namespace pcpp diff --git a/Pcap++/src/WinPcapLiveDevice.cpp b/Pcap++/src/WinPcapLiveDevice.cpp index c6a6a1121f..cf363aded7 100644 --- a/Pcap++/src/WinPcapLiveDevice.cpp +++ b/Pcap++/src/WinPcapLiveDevice.cpp @@ -1,136 +1,143 @@ #if defined(_WIN32) -#define LOG_MODULE PcapLogModuleWinPcapLiveDevice +# define LOG_MODULE PcapLogModuleWinPcapLiveDevice -#include "WinPcapLiveDevice.h" -#include "Logger.h" -#include "TimespecTimeval.h" -#include "pcap.h" +# include "WinPcapLiveDevice.h" +# include "Logger.h" +# include "TimespecTimeval.h" +# include "pcap.h" namespace pcpp { -WinPcapLiveDevice::WinPcapLiveDevice(pcap_if_t* iface, bool calculateMTU, bool calculateMacAddress, bool calculateDefaultGateway) : PcapLiveDevice(iface, calculateMTU, calculateMacAddress, calculateDefaultGateway) -{ - m_MinAmountOfDataToCopyFromKernelToApplication = 16000; -} - -bool WinPcapLiveDevice::startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie) -{ - if (!m_DeviceOpened || m_PcapDescriptor == NULL) + WinPcapLiveDevice::WinPcapLiveDevice(pcap_if_t* iface, bool calculateMTU, bool calculateMacAddress, + bool calculateDefaultGateway) + : PcapLiveDevice(iface, calculateMTU, calculateMacAddress, calculateDefaultGateway) { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); - return false; + m_MinAmountOfDataToCopyFromKernelToApplication = 16000; } - //Put the interface in capture mode - if (pcap_setmode(m_PcapDescriptor, MODE_CAPT) < 0) + bool WinPcapLiveDevice::startCapture(OnPacketArrivesCallback onPacketArrives, void* onPacketArrivesUserCookie, + int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, + void* onStatsUpdateUserCookie) { - PCPP_LOG_ERROR("Error setting the capture mode for device '" << m_Name << "'"); - return false; - } + if (!m_DeviceOpened || m_PcapDescriptor == NULL) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); + return false; + } - return PcapLiveDevice::startCapture(onPacketArrives, onPacketArrivesUserCookie, intervalInSecondsToUpdateStats, onStatsUpdate, onStatsUpdateUserCookie); -} + // Put the interface in capture mode + if (pcap_setmode(m_PcapDescriptor, MODE_CAPT) < 0) + { + PCPP_LOG_ERROR("Error setting the capture mode for device '" << m_Name << "'"); + return false; + } -bool WinPcapLiveDevice::startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, void* onStatsUpdateUserCookie) -{ - if (!m_DeviceOpened || m_PcapDescriptor == NULL) - { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); - return false; + return PcapLiveDevice::startCapture(onPacketArrives, onPacketArrivesUserCookie, intervalInSecondsToUpdateStats, + onStatsUpdate, onStatsUpdateUserCookie); } - //Put the interface in statistics mode - if (pcap_setmode(m_PcapDescriptor, MODE_STAT) < 0) + bool WinPcapLiveDevice::startCapture(int intervalInSecondsToUpdateStats, OnStatsUpdateCallback onStatsUpdate, + void* onStatsUpdateUserCookie) { - PCPP_LOG_ERROR("Error setting the statistics mode for device '" << m_Name << "'"); - return false; - } + if (!m_DeviceOpened || m_PcapDescriptor == NULL) + { + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); + return false; + } - return PcapLiveDevice::startCapture(intervalInSecondsToUpdateStats, onStatsUpdate, onStatsUpdateUserCookie); -} + // Put the interface in statistics mode + if (pcap_setmode(m_PcapDescriptor, MODE_STAT) < 0) + { + PCPP_LOG_ERROR("Error setting the statistics mode for device '" << m_Name << "'"); + return false; + } -int WinPcapLiveDevice::sendPackets(RawPacket* rawPacketsArr, int arrLength) -{ - if (!m_DeviceOpened || m_PcapDescriptor == NULL) - { - PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); - return 0; + return PcapLiveDevice::startCapture(intervalInSecondsToUpdateStats, onStatsUpdate, onStatsUpdateUserCookie); } - int dataSize = 0; - int packetsSent = 0; - for (int i = 0; i < arrLength; i++) - dataSize += rawPacketsArr[i].getRawDataLen(); - - pcap_send_queue* sendQueue = pcap_sendqueue_alloc(dataSize + arrLength*sizeof(pcap_pkthdr)); - PCPP_LOG_DEBUG("Allocated send queue of size " << (dataSize + arrLength*sizeof(pcap_pkthdr))); - struct pcap_pkthdr* packetHeader = new struct pcap_pkthdr[arrLength]; - for (int i = 0; i < arrLength; i++) + int WinPcapLiveDevice::sendPackets(RawPacket* rawPacketsArr, int arrLength) { - packetHeader[i].caplen = rawPacketsArr[i].getRawDataLen(); - packetHeader[i].len = rawPacketsArr[i].getRawDataLen(); - timespec packet_time = rawPacketsArr[i].getPacketTimeStamp(); - TIMESPEC_TO_TIMEVAL(&packetHeader[i].ts, &packet_time); - if (pcap_sendqueue_queue(sendQueue, &packetHeader[i], rawPacketsArr[i].getRawData()) == -1) + if (!m_DeviceOpened || m_PcapDescriptor == NULL) { - PCPP_LOG_ERROR("pcap_send_queue is too small for all packets. Sending only " << i << " packets"); - break; + PCPP_LOG_ERROR("Device '" << m_Name << "' not opened"); + return 0; } - packetsSent++; - } - PCPP_LOG_DEBUG(packetsSent << " packets were queued successfully"); + int dataSize = 0; + int packetsSent = 0; + for (int i = 0; i < arrLength; i++) + dataSize += rawPacketsArr[i].getRawDataLen(); - int res; - if ((res = pcap_sendqueue_transmit(m_PcapDescriptor, sendQueue, 0)) < (int)(sendQueue->len)) - { - PCPP_LOG_ERROR("An error occurred sending the packets: " << pcap_geterr(m_PcapDescriptor) << ". Only " << res << " bytes were sent"); - packetsSent = 0; - dataSize = 0; + pcap_send_queue* sendQueue = pcap_sendqueue_alloc(dataSize + arrLength * sizeof(pcap_pkthdr)); + PCPP_LOG_DEBUG("Allocated send queue of size " << (dataSize + arrLength * sizeof(pcap_pkthdr))); + struct pcap_pkthdr* packetHeader = new struct pcap_pkthdr[arrLength]; for (int i = 0; i < arrLength; i++) { - dataSize += rawPacketsArr[i].getRawDataLen(); - if (dataSize > res) + packetHeader[i].caplen = rawPacketsArr[i].getRawDataLen(); + packetHeader[i].len = rawPacketsArr[i].getRawDataLen(); + timespec packet_time = rawPacketsArr[i].getPacketTimeStamp(); + TIMESPEC_TO_TIMEVAL(&packetHeader[i].ts, &packet_time); + if (pcap_sendqueue_queue(sendQueue, &packetHeader[i], rawPacketsArr[i].getRawData()) == -1) { - return packetsSent; + PCPP_LOG_ERROR("pcap_send_queue is too small for all packets. Sending only " << i << " packets"); + break; } packetsSent++; } - return packetsSent; - } - PCPP_LOG_DEBUG("Packets were sent successfully"); - pcap_sendqueue_destroy(sendQueue); - PCPP_LOG_DEBUG("Send queue destroyed"); + PCPP_LOG_DEBUG(packetsSent << " packets were queued successfully"); - delete[] packetHeader; - return packetsSent; -} + int res; + if ((res = pcap_sendqueue_transmit(m_PcapDescriptor, sendQueue, 0)) < (int)(sendQueue->len)) + { + PCPP_LOG_ERROR("An error occurred sending the packets: " << pcap_geterr(m_PcapDescriptor) << ". Only " + << res << " bytes were sent"); + packetsSent = 0; + dataSize = 0; + for (int i = 0; i < arrLength; i++) + { + dataSize += rawPacketsArr[i].getRawDataLen(); + if (dataSize > res) + { + return packetsSent; + } + packetsSent++; + } + return packetsSent; + } + PCPP_LOG_DEBUG("Packets were sent successfully"); -bool WinPcapLiveDevice::setMinAmountOfDataToCopyFromKernelToApplication(int size) -{ - if (!m_DeviceOpened) - { - PCPP_LOG_ERROR("Device not opened"); - return false; + pcap_sendqueue_destroy(sendQueue); + PCPP_LOG_DEBUG("Send queue destroyed"); + + delete[] packetHeader; + return packetsSent; } - if (pcap_setmintocopy(m_PcapDescriptor, size) != 0) + bool WinPcapLiveDevice::setMinAmountOfDataToCopyFromKernelToApplication(int size) { - PCPP_LOG_ERROR("pcap_setmintocopy failed"); - return false; + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device not opened"); + return false; + } + + if (pcap_setmintocopy(m_PcapDescriptor, size) != 0) + { + PCPP_LOG_ERROR("pcap_setmintocopy failed"); + return false; + } + m_MinAmountOfDataToCopyFromKernelToApplication = size; + return true; } - m_MinAmountOfDataToCopyFromKernelToApplication = size; - return true; -} -WinPcapLiveDevice* WinPcapLiveDevice::cloneInternal(pcap_if_t& devInterface) const -{ - return new WinPcapLiveDevice(&devInterface, true, true, true); -} + WinPcapLiveDevice* WinPcapLiveDevice::cloneInternal(pcap_if_t& devInterface) const + { + return new WinPcapLiveDevice(&devInterface, true, true, true); + } -} // namespace pcpp +} // namespace pcpp -#endif // _WIN32 +#endif // _WIN32 diff --git a/Pcap++/src/XdpDevice.cpp b/Pcap++/src/XdpDevice.cpp index 16e77a4169..d089127a5c 100644 --- a/Pcap++/src/XdpDevice.cpp +++ b/Pcap++/src/XdpDevice.cpp @@ -16,604 +16,619 @@ namespace pcpp { -struct xsk_umem_info { - struct xsk_ring_prod fq; - struct xsk_ring_cons cq; - struct xsk_umem *umem; -}; + struct xsk_umem_info + { + struct xsk_ring_prod fq; + struct xsk_ring_cons cq; + struct xsk_umem* umem; + }; -struct xsk_socket_info -{ - struct xsk_ring_cons rx; - struct xsk_ring_prod tx; - struct xsk_socket *xsk; -}; + struct xsk_socket_info + { + struct xsk_ring_cons rx; + struct xsk_ring_prod tx; + struct xsk_socket* xsk; + }; -#define DEFAULT_UMEM_NUM_FRAMES (XSK_RING_PROD__DEFAULT_NUM_DESCS * 2) -#define DEFAULT_FILL_RING_SIZE (XSK_RING_PROD__DEFAULT_NUM_DESCS * 2) +#define DEFAULT_UMEM_NUM_FRAMES (XSK_RING_PROD__DEFAULT_NUM_DESCS * 2) +#define DEFAULT_FILL_RING_SIZE (XSK_RING_PROD__DEFAULT_NUM_DESCS * 2) #define DEFAULT_COMPLETION_RING_SIZE XSK_RING_PROD__DEFAULT_NUM_DESCS -#define DEFAULT_BATCH_SIZE 64 -#define IS_POWER_OF_TWO(num) (num && ((num & (num - 1)) == 0)) +#define DEFAULT_BATCH_SIZE 64 +#define IS_POWER_OF_TWO(num) (num && ((num & (num - 1)) == 0)) + XdpDevice::XdpUmem::XdpUmem(uint16_t numFrames, uint16_t frameSize, uint32_t fillRingSize, + uint32_t completionRingSize) + { + size_t bufferSize = numFrames * frameSize; -XdpDevice::XdpUmem::XdpUmem(uint16_t numFrames, uint16_t frameSize, uint32_t fillRingSize, uint32_t completionRingSize) -{ - size_t bufferSize = numFrames * frameSize; + if (posix_memalign(&m_Buffer, getpagesize(), bufferSize)) + { + throw std::runtime_error("Could not allocate buffer memory for UMEM"); + } - if (posix_memalign(&m_Buffer, getpagesize(), bufferSize)) - { - throw std::runtime_error("Could not allocate buffer memory for UMEM"); - } + struct xsk_umem_config cfg = { .fill_size = fillRingSize, + .comp_size = completionRingSize, + .frame_size = frameSize, + .frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM, + .flags = 0 }; - struct xsk_umem_config cfg = { - .fill_size = fillRingSize, - .comp_size = completionRingSize, - .frame_size = frameSize, - .frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM, - .flags = 0 - }; + struct xsk_umem_info* umem = new xsk_umem_info; + memset(umem, 0, sizeof(xsk_umem_info)); - struct xsk_umem_info* umem = new xsk_umem_info; - memset(umem, 0, sizeof(xsk_umem_info)); + int ret = xsk_umem__create(&umem->umem, m_Buffer, bufferSize, &umem->fq, &umem->cq, &cfg); + if (ret) + { + throw std::runtime_error("Could not allocate UMEM - xsk_umem__create() returned " + std::to_string(ret)); + } - int ret = xsk_umem__create(&umem->umem, m_Buffer, bufferSize, &umem->fq, &umem->cq, &cfg); - if (ret) - { - throw std::runtime_error("Could not allocate UMEM - xsk_umem__create() returned " + std::to_string(ret)); + m_UmemInfo = umem; + + for (uint16_t i = 0; i < numFrames; i++) + { + m_FreeFrames.push_back(i * frameSize); + } + + m_FrameSize = frameSize; + m_FrameCount = numFrames; } - m_UmemInfo = umem; + XdpDevice::XdpUmem::~XdpUmem() + { + xsk_umem__delete(static_cast(m_UmemInfo)->umem); + free(m_Buffer); + } - for (uint16_t i = 0; i < numFrames; i++) + const uint8_t* XdpDevice::XdpUmem::getDataPtr(uint64_t addr) const { - m_FreeFrames.push_back(i * frameSize); + return static_cast(xsk_umem__get_data(m_Buffer, addr)); } - m_FrameSize = frameSize; - m_FrameCount = numFrames; -} + void XdpDevice::XdpUmem::setData(uint64_t addr, const uint8_t* data, size_t dataLen) + { + auto dataPtr = static_cast(xsk_umem__get_data(m_Buffer, addr)); + memcpy(dataPtr, data, dataLen); + } -XdpDevice::XdpUmem::~XdpUmem() -{ - xsk_umem__delete(static_cast(m_UmemInfo)->umem); - free(m_Buffer); -} + std::pair> XdpDevice::XdpUmem::allocateFrames(uint32_t count) + { + if (m_FreeFrames.size() < count) + { + PCPP_LOG_ERROR("Not enough frames to allocate. Requested: " << count + << ", available: " << m_FreeFrames.size()); + return { false, {} }; + } -const uint8_t* XdpDevice::XdpUmem::getDataPtr(uint64_t addr) const -{ - return static_cast(xsk_umem__get_data(m_Buffer, addr)); -} + std::vector result; + for (uint32_t i = 0; i < count; i++) + { + result.push_back(m_FreeFrames.back()); + m_FreeFrames.pop_back(); + } -void XdpDevice::XdpUmem::setData(uint64_t addr, const uint8_t* data, size_t dataLen) -{ - auto dataPtr = static_cast(xsk_umem__get_data(m_Buffer, addr)); - memcpy(dataPtr, data, dataLen); -} + return { true, result }; + } -std::pair> XdpDevice::XdpUmem::allocateFrames(uint32_t count) -{ - if (m_FreeFrames.size() < count) + void XdpDevice::XdpUmem::freeFrame(uint64_t addr) { - PCPP_LOG_ERROR("Not enough frames to allocate. Requested: " << count << ", available: " << m_FreeFrames.size()); - return {false, {} }; + auto frame = (uint64_t)((addr / m_FrameSize) * m_FrameSize); + m_FreeFrames.push_back(frame); } - std::vector result; - for (uint32_t i = 0; i < count; i++) + XdpDevice::XdpDevice(std::string interfaceName) + : m_InterfaceName(std::move(interfaceName)), m_Config(nullptr), m_ReceivingPackets(false), m_Umem(nullptr), + m_SocketInfo(nullptr) { - result.push_back(m_FreeFrames.back()); - m_FreeFrames.pop_back(); + memset(&m_Stats, 0, sizeof(m_Stats)); + memset(&m_PrevStats, 0, sizeof(m_PrevStats)); } - return {true, result}; -} - -void XdpDevice::XdpUmem::freeFrame(uint64_t addr) -{ - auto frame = (uint64_t )((addr / m_FrameSize) * m_FrameSize); - m_FreeFrames.push_back(frame); -} - -XdpDevice::XdpDevice(std::string interfaceName) : - m_InterfaceName(std::move(interfaceName)), m_Config(nullptr), m_ReceivingPackets(false), m_Umem(nullptr), m_SocketInfo(nullptr) -{ - memset(&m_Stats, 0, sizeof(m_Stats)); - memset(&m_PrevStats, 0, sizeof(m_PrevStats)); -} - -XdpDevice::~XdpDevice() -{ - close(); -} - -bool XdpDevice::receivePackets(OnPacketsArrive onPacketsArrive, void* onPacketsArriveUserCookie, int timeoutMS) -{ - if (!m_DeviceOpened) + XdpDevice::~XdpDevice() { - PCPP_LOG_ERROR("Device is not open"); - return false; + close(); } - auto socketInfo = static_cast(m_SocketInfo); + bool XdpDevice::receivePackets(OnPacketsArrive onPacketsArrive, void* onPacketsArriveUserCookie, int timeoutMS) + { + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device is not open"); + return false; + } - m_ReceivingPackets = true; - uint32_t rxId = 0; + auto socketInfo = static_cast(m_SocketInfo); - pollfd pollFds[1]; - pollFds[0] = { - .fd = xsk_socket__fd(socketInfo->xsk), - .events = POLLIN - }; + m_ReceivingPackets = true; + uint32_t rxId = 0; - while (m_ReceivingPackets) - { - checkCompletionRing(); + pollfd pollFds[1]; + pollFds[0] = { .fd = xsk_socket__fd(socketInfo->xsk), .events = POLLIN }; - auto pollResult = poll(pollFds, 1, timeoutMS); - if (pollResult == 0 && timeoutMS != 0) + while (m_ReceivingPackets) { - m_Stats.rxPollTimeout++; - m_ReceivingPackets = false; - return true; - } - if (pollResult < 0) - { - m_ReceivingPackets = false; - if (errno != EINTR) + checkCompletionRing(); + + auto pollResult = poll(pollFds, 1, timeoutMS); + if (pollResult == 0 && timeoutMS != 0) { - PCPP_LOG_ERROR("poll() returned an error: " << errno); - return false; + m_Stats.rxPollTimeout++; + m_ReceivingPackets = false; + return true; + } + if (pollResult < 0) + { + m_ReceivingPackets = false; + if (errno != EINTR) + { + PCPP_LOG_ERROR("poll() returned an error: " << errno); + return false; + } + + return true; } - return true; - } - - uint32_t receivedPacketsCount = xsk_ring_cons__peek(&socketInfo->rx, m_Config->rxTxBatchSize, &rxId); + uint32_t receivedPacketsCount = xsk_ring_cons__peek(&socketInfo->rx, m_Config->rxTxBatchSize, &rxId); - if (!receivedPacketsCount) - { - continue; - } + if (!receivedPacketsCount) + { + continue; + } - m_Stats.rxPackets += receivedPacketsCount; + m_Stats.rxPackets += receivedPacketsCount; - RawPacket rawPacketsArr[receivedPacketsCount]; + RawPacket rawPacketsArr[receivedPacketsCount]; - for (uint32_t i = 0; i < receivedPacketsCount; i++) - { - uint64_t addr = xsk_ring_cons__rx_desc(&socketInfo->rx, rxId + i)->addr; - uint32_t len = xsk_ring_cons__rx_desc(&socketInfo->rx, rxId + i)->len; + for (uint32_t i = 0; i < receivedPacketsCount; i++) + { + uint64_t addr = xsk_ring_cons__rx_desc(&socketInfo->rx, rxId + i)->addr; + uint32_t len = xsk_ring_cons__rx_desc(&socketInfo->rx, rxId + i)->len; - auto data = m_Umem->getDataPtr(addr); - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - rawPacketsArr[i].initWithRawData(data, static_cast(len), ts); + auto data = m_Umem->getDataPtr(addr); + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + rawPacketsArr[i].initWithRawData(data, static_cast(len), ts); - m_Stats.rxBytes += len; + m_Stats.rxBytes += len; - m_Umem->freeFrame(addr); - } + m_Umem->freeFrame(addr); + } - onPacketsArrive(rawPacketsArr, receivedPacketsCount, this, onPacketsArriveUserCookie); + onPacketsArrive(rawPacketsArr, receivedPacketsCount, this, onPacketsArriveUserCookie); - xsk_ring_cons__release(&socketInfo->rx, receivedPacketsCount); - m_Stats.rxRingId = rxId + receivedPacketsCount; + xsk_ring_cons__release(&socketInfo->rx, receivedPacketsCount); + m_Stats.rxRingId = rxId + receivedPacketsCount; - if (!populateFillRing(receivedPacketsCount, rxId)) - { - m_ReceivingPackets = false; + if (!populateFillRing(receivedPacketsCount, rxId)) + { + m_ReceivingPackets = false; + } } - } - return true; -} - -void XdpDevice::stopReceivePackets() -{ - m_ReceivingPackets = false; -} + return true; + } -bool XdpDevice::sendPackets(const std::function& getPacketAt, const std::function& getPacketCount, bool waitForTxCompletion, int waitForTxCompletionTimeoutMS) -{ - if (!m_DeviceOpened) + void XdpDevice::stopReceivePackets() { - PCPP_LOG_ERROR("Device is not open"); - return false; + m_ReceivingPackets = false; } - auto socketInfo = static_cast(m_SocketInfo); + bool XdpDevice::sendPackets(const std::function& getPacketAt, + const std::function& getPacketCount, bool waitForTxCompletion, + int waitForTxCompletionTimeoutMS) + { + if (!m_DeviceOpened) + { + PCPP_LOG_ERROR("Device is not open"); + return false; + } - checkCompletionRing(); + auto socketInfo = static_cast(m_SocketInfo); - uint32_t txId = 0; - uint32_t packetCount = getPacketCount(); + checkCompletionRing(); - auto frameResponse = m_Umem->allocateFrames(packetCount); - if (!frameResponse.first) - { - return false; - } + uint32_t txId = 0; + uint32_t packetCount = getPacketCount(); - if (xsk_ring_prod__reserve(&socketInfo->tx, packetCount, &txId) < packetCount) - { - for (auto frame : frameResponse.second) + auto frameResponse = m_Umem->allocateFrames(packetCount); + if (!frameResponse.first) { - m_Umem->freeFrame(frame); + return false; } - PCPP_LOG_ERROR("Cannot reserve " << packetCount << " tx slots"); - return false; - } - for (uint32_t i = 0; i < packetCount; i++) - { - if (getPacketAt(i).getRawDataLen() > m_Umem->getFrameSize()) + if (xsk_ring_prod__reserve(&socketInfo->tx, packetCount, &txId) < packetCount) { - PCPP_LOG_ERROR("Cannot send packets with data length (" << getPacketAt(i).getRawDataLen() << ") greater than UMEM frame size (" << m_Umem->getFrameSize() << ")"); + for (auto frame : frameResponse.second) + { + m_Umem->freeFrame(frame); + } + PCPP_LOG_ERROR("Cannot reserve " << packetCount << " tx slots"); return false; } - } - uint64_t sentBytes = 0; - for (uint32_t i = 0; i < packetCount; i++) - { - uint64_t frame = frameResponse.second[i]; - m_Umem->setData(frame, getPacketAt(i).getRawData(), getPacketAt(i).getRawDataLen()); + for (uint32_t i = 0; i < packetCount; i++) + { + if (getPacketAt(i).getRawDataLen() > m_Umem->getFrameSize()) + { + PCPP_LOG_ERROR("Cannot send packets with data length (" << getPacketAt(i).getRawDataLen() + << ") greater than UMEM frame size (" + << m_Umem->getFrameSize() << ")"); + return false; + } + } - struct xdp_desc* txDesc = xsk_ring_prod__tx_desc(&socketInfo->tx, txId + i); - txDesc->addr = frame; - txDesc->len = getPacketAt(i).getRawDataLen(); + uint64_t sentBytes = 0; + for (uint32_t i = 0; i < packetCount; i++) + { + uint64_t frame = frameResponse.second[i]; + m_Umem->setData(frame, getPacketAt(i).getRawData(), getPacketAt(i).getRawDataLen()); - sentBytes += txDesc->len; + struct xdp_desc* txDesc = xsk_ring_prod__tx_desc(&socketInfo->tx, txId + i); + txDesc->addr = frame; + txDesc->len = getPacketAt(i).getRawDataLen(); - } + sentBytes += txDesc->len; + } - xsk_ring_prod__submit(&socketInfo->tx, packetCount); - m_Stats.txSentPackets += packetCount; - m_Stats.txSentBytes += sentBytes; - m_Stats.txRingId = txId + packetCount; + xsk_ring_prod__submit(&socketInfo->tx, packetCount); + m_Stats.txSentPackets += packetCount; + m_Stats.txSentBytes += sentBytes; + m_Stats.txRingId = txId + packetCount; - if (waitForTxCompletion) - { - uint32_t completedPackets = checkCompletionRing(); + if (waitForTxCompletion) + { + uint32_t completedPackets = checkCompletionRing(); - pollfd pollFds[1]; - pollFds[0] = { - .fd = xsk_socket__fd(socketInfo->xsk), - .events = POLLOUT - }; + pollfd pollFds[1]; + pollFds[0] = { .fd = xsk_socket__fd(socketInfo->xsk), .events = POLLOUT }; - while (completedPackets < packetCount) - { - auto pollResult = poll(pollFds, 1, waitForTxCompletionTimeoutMS); - if (pollResult == 0 && waitForTxCompletionTimeoutMS != 0) - { - PCPP_LOG_ERROR("Wait for TX completion timed out"); - return false; - } - if (pollResult < 0) + while (completedPackets < packetCount) { - PCPP_LOG_ERROR("poll() returned an error: " << errno); - return false; + auto pollResult = poll(pollFds, 1, waitForTxCompletionTimeoutMS); + if (pollResult == 0 && waitForTxCompletionTimeoutMS != 0) + { + PCPP_LOG_ERROR("Wait for TX completion timed out"); + return false; + } + if (pollResult < 0) + { + PCPP_LOG_ERROR("poll() returned an error: " << errno); + return false; + } + + completedPackets += checkCompletionRing(); } - - completedPackets += checkCompletionRing(); } - } - - return true; -} -bool XdpDevice::sendPackets(const RawPacketVector& packets, bool waitForTxCompletion, int waitForTxCompletionTimeoutMS) -{ - return sendPackets([&](uint32_t i) { return *packets.at(static_cast(i)); }, [&]() { return packets.size(); }, waitForTxCompletion, waitForTxCompletionTimeoutMS); -} + return true; + } -bool XdpDevice::sendPackets(RawPacket packets[], size_t packetCount, bool waitForTxCompletion, int waitForTxCompletionTimeoutMS) -{ - return sendPackets([&](uint32_t i) { return packets[i]; }, [&]() { return static_cast(packetCount); }, waitForTxCompletion, waitForTxCompletionTimeoutMS); -} + bool XdpDevice::sendPackets(const RawPacketVector& packets, bool waitForTxCompletion, + int waitForTxCompletionTimeoutMS) + { + return sendPackets([&](uint32_t i) { return *packets.at(static_cast(i)); }, + [&]() { return packets.size(); }, waitForTxCompletion, waitForTxCompletionTimeoutMS); + } -bool XdpDevice::populateFillRing(uint32_t count, uint32_t rxId) -{ - auto frameResponse = m_Umem->allocateFrames(count); - if (!frameResponse.first) + bool XdpDevice::sendPackets(RawPacket packets[], size_t packetCount, bool waitForTxCompletion, + int waitForTxCompletionTimeoutMS) { - return false; + return sendPackets([&](uint32_t i) { return packets[i]; }, [&]() { return static_cast(packetCount); }, + waitForTxCompletion, waitForTxCompletionTimeoutMS); } - bool result = populateFillRing(frameResponse.second, rxId); - if (!result) + bool XdpDevice::populateFillRing(uint32_t count, uint32_t rxId) { - for (auto frame : frameResponse.second) + auto frameResponse = m_Umem->allocateFrames(count); + if (!frameResponse.first) { - m_Umem->freeFrame(frame); + return false; } - } - return result; -} - -bool XdpDevice::populateFillRing(const std::vector& addresses, uint32_t rxId) -{ - auto umem = static_cast(m_Umem->getInfo()); - auto count = static_cast(addresses.size()); + bool result = populateFillRing(frameResponse.second, rxId); + if (!result) + { + for (auto frame : frameResponse.second) + { + m_Umem->freeFrame(frame); + } + } - uint32_t ret = xsk_ring_prod__reserve(&umem->fq,count, &rxId); - if (ret != count) - { - PCPP_LOG_ERROR("xsk_ring_prod__reserve returned: " << ret << "; expected: " << count); - return false; + return result; } - for (uint32_t i = 0; i < count; i++) + bool XdpDevice::populateFillRing(const std::vector& addresses, uint32_t rxId) { - *xsk_ring_prod__fill_addr(&umem->fq, rxId + i) = addresses[i]; - } + auto umem = static_cast(m_Umem->getInfo()); + auto count = static_cast(addresses.size()); - xsk_ring_prod__submit(&umem->fq, count); - m_Stats.fqRingId = rxId + count; + uint32_t ret = xsk_ring_prod__reserve(&umem->fq, count, &rxId); + if (ret != count) + { + PCPP_LOG_ERROR("xsk_ring_prod__reserve returned: " << ret << "; expected: " << count); + return false; + } - return true; -} + for (uint32_t i = 0; i < count; i++) + { + *xsk_ring_prod__fill_addr(&umem->fq, rxId + i) = addresses[i]; + } -uint32_t XdpDevice::checkCompletionRing() -{ - uint32_t cqId = 0; - auto umemInfo = static_cast(m_Umem->getInfo()); + xsk_ring_prod__submit(&umem->fq, count); + m_Stats.fqRingId = rxId + count; - auto socketInfo = static_cast(m_SocketInfo); - if (xsk_ring_prod__needs_wakeup(&socketInfo->tx)) - { - sendto(xsk_socket__fd(socketInfo->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); + return true; } - uint32_t completedCount = xsk_ring_cons__peek(&umemInfo->cq, m_Config->rxTxBatchSize, &cqId); - - if (completedCount) + uint32_t XdpDevice::checkCompletionRing() { - for (uint32_t i = 0; i < completedCount; i++) + uint32_t cqId = 0; + auto umemInfo = static_cast(m_Umem->getInfo()); + + auto socketInfo = static_cast(m_SocketInfo); + if (xsk_ring_prod__needs_wakeup(&socketInfo->tx)) { - uint64_t addr = *xsk_ring_cons__comp_addr(&umemInfo->cq, cqId + i); - m_Umem->freeFrame(addr); + sendto(xsk_socket__fd(socketInfo->xsk), NULL, 0, MSG_DONTWAIT, NULL, 0); } - xsk_ring_cons__release(&umemInfo->cq, completedCount); - m_Stats.cqRingId = cqId + completedCount; - } + uint32_t completedCount = xsk_ring_cons__peek(&umemInfo->cq, m_Config->rxTxBatchSize, &cqId); - m_Stats.txCompletedPackets += completedCount; - return completedCount; -} + if (completedCount) + { + for (uint32_t i = 0; i < completedCount; i++) + { + uint64_t addr = *xsk_ring_cons__comp_addr(&umemInfo->cq, cqId + i); + m_Umem->freeFrame(addr); + } -bool XdpDevice::configureSocket() -{ - auto socketInfo = new xsk_socket_info(); + xsk_ring_cons__release(&umemInfo->cq, completedCount); + m_Stats.cqRingId = cqId + completedCount; + } - auto umemInfo = static_cast(m_Umem->getInfo()); + m_Stats.txCompletedPackets += completedCount; + return completedCount; + } - struct xsk_socket_config xskConfig; - xskConfig.rx_size = m_Config->txSize; - xskConfig.tx_size = m_Config->rxSize; - xskConfig.libbpf_flags = 0; - xskConfig.xdp_flags = 0; - xskConfig.bind_flags = 0; - if (m_Config->attachMode == XdpDeviceConfiguration::SkbMode) + bool XdpDevice::configureSocket() { - xskConfig.xdp_flags = XDP_FLAGS_SKB_MODE; - xskConfig.bind_flags &= ~XDP_ZEROCOPY; - xskConfig.bind_flags |= XDP_COPY; + auto socketInfo = new xsk_socket_info(); + + auto umemInfo = static_cast(m_Umem->getInfo()); + + struct xsk_socket_config xskConfig; + xskConfig.rx_size = m_Config->txSize; + xskConfig.tx_size = m_Config->rxSize; + xskConfig.libbpf_flags = 0; + xskConfig.xdp_flags = 0; + xskConfig.bind_flags = 0; + if (m_Config->attachMode == XdpDeviceConfiguration::SkbMode) + { + xskConfig.xdp_flags = XDP_FLAGS_SKB_MODE; + xskConfig.bind_flags &= ~XDP_ZEROCOPY; + xskConfig.bind_flags |= XDP_COPY; + } + else if (m_Config->attachMode == XdpDeviceConfiguration::DriverMode) + { + xskConfig.xdp_flags = XDP_FLAGS_DRV_MODE; + } + + int ret = xsk_socket__create(&socketInfo->xsk, m_InterfaceName.c_str(), 0, umemInfo->umem, &socketInfo->rx, + &socketInfo->tx, &xskConfig); + if (ret) + { + PCPP_LOG_ERROR("xsk_socket__create returned an error: " << ret); + delete socketInfo; + return false; + } + + m_SocketInfo = socketInfo; + return true; } - else if (m_Config->attachMode == XdpDeviceConfiguration::DriverMode) + + bool XdpDevice::initUmem() { - xskConfig.xdp_flags = XDP_FLAGS_DRV_MODE; + m_Umem = new XdpUmem(m_Config->umemNumFrames, m_Config->umemFrameSize, m_Config->fillRingSize, + m_Config->completionRingSize); + return true; } - int ret = xsk_socket__create(&socketInfo->xsk, m_InterfaceName.c_str(), 0, umemInfo->umem, - &socketInfo->rx, &socketInfo->tx, &xskConfig); - if (ret) + bool XdpDevice::initConfig() { - PCPP_LOG_ERROR("xsk_socket__create returned an error: " << ret); - delete socketInfo; - return false; - } + if (!m_Config) + { + m_Config = new XdpDeviceConfiguration(); + } - m_SocketInfo = socketInfo; - return true; -} + uint16_t numFrames = m_Config->umemNumFrames ? m_Config->umemNumFrames : DEFAULT_UMEM_NUM_FRAMES; + uint16_t frameSize = m_Config->umemFrameSize ? m_Config->umemFrameSize : getpagesize(); + uint32_t fillRingSize = m_Config->fillRingSize ? m_Config->fillRingSize : DEFAULT_FILL_RING_SIZE; + uint32_t completionRingSize = + m_Config->completionRingSize ? m_Config->completionRingSize : DEFAULT_COMPLETION_RING_SIZE; + uint32_t rxSize = m_Config->rxSize ? m_Config->rxSize : XSK_RING_CONS__DEFAULT_NUM_DESCS; + uint32_t txSize = m_Config->txSize ? m_Config->txSize : XSK_RING_PROD__DEFAULT_NUM_DESCS; + uint32_t batchSize = m_Config->rxTxBatchSize ? m_Config->rxTxBatchSize : DEFAULT_BATCH_SIZE; -bool XdpDevice::initUmem() -{ - m_Umem = new XdpUmem(m_Config->umemNumFrames, m_Config->umemFrameSize, m_Config->fillRingSize, m_Config->completionRingSize); - return true; -} + if (frameSize != getpagesize()) + { + PCPP_LOG_ERROR("UMEM frame size must match the memory page size (" << getpagesize() << ")"); + return false; + } -bool XdpDevice::initConfig() -{ - if (!m_Config) - { - m_Config = new XdpDeviceConfiguration(); - } + if (!(IS_POWER_OF_TWO(fillRingSize) && IS_POWER_OF_TWO(completionRingSize) && IS_POWER_OF_TWO(rxSize) && + IS_POWER_OF_TWO(txSize))) + { + PCPP_LOG_ERROR("All ring sizes (fill ring, completion ring, rx ring, tx ring) should be a power of two"); + return false; + } - uint16_t numFrames = m_Config->umemNumFrames ? m_Config->umemNumFrames : DEFAULT_UMEM_NUM_FRAMES; - uint16_t frameSize = m_Config->umemFrameSize ? m_Config->umemFrameSize : getpagesize(); - uint32_t fillRingSize = m_Config->fillRingSize ? m_Config->fillRingSize : DEFAULT_FILL_RING_SIZE; - uint32_t completionRingSize = m_Config->completionRingSize ? m_Config->completionRingSize : DEFAULT_COMPLETION_RING_SIZE; - uint32_t rxSize = m_Config->rxSize ? m_Config->rxSize : XSK_RING_CONS__DEFAULT_NUM_DESCS; - uint32_t txSize = m_Config->txSize ? m_Config->txSize : XSK_RING_PROD__DEFAULT_NUM_DESCS; - uint32_t batchSize = m_Config->rxTxBatchSize ? m_Config->rxTxBatchSize : DEFAULT_BATCH_SIZE; + if (fillRingSize > numFrames) + { + PCPP_LOG_ERROR("Fill ring size (" << fillRingSize + << ") must be lower or equal to the total number of UMEM frames (" + << numFrames << ")"); + return false; + } - if (frameSize != getpagesize()) - { - PCPP_LOG_ERROR("UMEM frame size must match the memory page size (" << getpagesize() << ")"); - return false; - } + if (completionRingSize > numFrames) + { + PCPP_LOG_ERROR("Completion ring size (" << completionRingSize + << ") must be lower or equal to the total number of UMEM frames (" + << numFrames << ")"); + return false; + } - if (!(IS_POWER_OF_TWO(fillRingSize) && IS_POWER_OF_TWO(completionRingSize) && IS_POWER_OF_TWO(rxSize) && IS_POWER_OF_TWO(txSize))) - { - PCPP_LOG_ERROR("All ring sizes (fill ring, completion ring, rx ring, tx ring) should be a power of two"); - return false; - } + if (rxSize > numFrames) + { + PCPP_LOG_ERROR("RX size (" << rxSize << ") must be lower or equal to the total number of UMEM frames (" + << numFrames << ")"); + return false; + } - if (fillRingSize > numFrames) - { - PCPP_LOG_ERROR("Fill ring size (" << fillRingSize << ") must be lower or equal to the total number of UMEM frames (" << numFrames << ")"); - return false; - } + if (txSize > numFrames) + { + PCPP_LOG_ERROR("TX size (" << txSize << ") must be lower or equal to the total number of UMEM frames (" + << numFrames << ")"); + return false; + } - if (completionRingSize > numFrames) - { - PCPP_LOG_ERROR("Completion ring size (" << completionRingSize << ") must be lower or equal to the total number of UMEM frames (" << numFrames << ")"); - return false; - } + if (batchSize > rxSize || batchSize > txSize) + { + PCPP_LOG_ERROR("RX/TX batch size (" << batchSize << ") must be lower or equal to RX/TX ring size"); + return false; + } - if (rxSize > numFrames) - { - PCPP_LOG_ERROR("RX size (" << rxSize << ") must be lower or equal to the total number of UMEM frames (" << numFrames << ")"); - return false; - } + m_Config->umemNumFrames = numFrames; + m_Config->umemFrameSize = frameSize; + m_Config->fillRingSize = fillRingSize; + m_Config->completionRingSize = completionRingSize; + m_Config->rxSize = rxSize; + m_Config->txSize = txSize; + m_Config->rxTxBatchSize = batchSize; - if (txSize > numFrames) - { - PCPP_LOG_ERROR("TX size (" << txSize << ") must be lower or equal to the total number of UMEM frames (" << numFrames << ")"); - return false; + return true; } - if (batchSize > rxSize || batchSize > txSize) + bool XdpDevice::open() { - PCPP_LOG_ERROR("RX/TX batch size (" << batchSize << ") must be lower or equal to RX/TX ring size"); - return false; - } + if (m_DeviceOpened) + { + PCPP_LOG_ERROR("Device already opened"); + return false; + } - m_Config->umemNumFrames = numFrames; - m_Config->umemFrameSize = frameSize; - m_Config->fillRingSize = fillRingSize; - m_Config->completionRingSize = completionRingSize; - m_Config->rxSize = rxSize; - m_Config->txSize = txSize; - m_Config->rxTxBatchSize = batchSize; + if (!(initConfig() && initUmem() && + populateFillRing(std::min(m_Config->fillRingSize, static_cast(m_Config->umemNumFrames / 2))) && + configureSocket())) + { + if (m_Umem) + { + delete m_Umem; + m_Umem = nullptr; + } + if (m_Config) + { + delete m_Config; + m_Config = nullptr; + } + return false; + } - return true; -} + memset(&m_Stats, 0, sizeof(m_Stats)); + memset(&m_PrevStats, 0, sizeof(m_PrevStats)); -bool XdpDevice::open() -{ - if (m_DeviceOpened) + m_DeviceOpened = true; + return m_DeviceOpened; + } + + bool XdpDevice::open(const XdpDeviceConfiguration& config) { - PCPP_LOG_ERROR("Device already opened"); - return false; + m_Config = new XdpDeviceConfiguration(config); + return open(); } - if (!(initConfig() && - initUmem() && - populateFillRing(std::min(m_Config->fillRingSize, static_cast(m_Config->umemNumFrames / 2))) && - configureSocket())) + void XdpDevice::close() { - if (m_Umem) + if (m_DeviceOpened) { + auto socketInfo = static_cast(m_SocketInfo); + xsk_socket__delete(socketInfo->xsk); + m_DeviceOpened = false; delete m_Umem; - m_Umem = nullptr; - } - if (m_Config) - { delete m_Config; m_Config = nullptr; + m_Umem = nullptr; } - return false; } - memset(&m_Stats, 0, sizeof(m_Stats)); - memset(&m_PrevStats, 0 ,sizeof(m_PrevStats)); - - m_DeviceOpened = true; - return m_DeviceOpened; -} - -bool XdpDevice::open(const XdpDeviceConfiguration& config) -{ - m_Config = new XdpDeviceConfiguration(config); - return open(); -} - -void XdpDevice::close() -{ - if (m_DeviceOpened) + bool XdpDevice::getSocketStats() { auto socketInfo = static_cast(m_SocketInfo); - xsk_socket__delete(socketInfo->xsk); - m_DeviceOpened = false; - delete m_Umem; - delete m_Config; - m_Config = nullptr; - m_Umem = nullptr; - } -} - -bool XdpDevice::getSocketStats() -{ - auto socketInfo = static_cast(m_SocketInfo); - int fd = xsk_socket__fd(socketInfo->xsk); + int fd = xsk_socket__fd(socketInfo->xsk); - struct xdp_statistics socketStats; - socklen_t optlen = sizeof(socketStats); + struct xdp_statistics socketStats; + socklen_t optlen = sizeof(socketStats); - int err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &socketStats, &optlen); - if (err) - { - PCPP_LOG_ERROR("Error getting stats from socket, return error: " << err); - return false; - } + int err = getsockopt(fd, SOL_XDP, XDP_STATISTICS, &socketStats, &optlen); + if (err) + { + PCPP_LOG_ERROR("Error getting stats from socket, return error: " << err); + return false; + } - if (optlen != sizeof(struct xdp_statistics)) - { - PCPP_LOG_ERROR("Error getting stats from socket: optlen (" << optlen << ") != expected size (" << sizeof(struct xdp_statistics) << ")"); - return false; - } + if (optlen != sizeof(struct xdp_statistics)) + { + PCPP_LOG_ERROR("Error getting stats from socket: optlen (" << optlen << ") != expected size (" + << sizeof(struct xdp_statistics) << ")"); + return false; + } - m_Stats.rxDroppedInvalidPackets = socketStats.rx_invalid_descs; - m_Stats.rxDroppedRxRingFullPackets = socketStats.rx_ring_full; - m_Stats.rxDroppedFillRingPackets = socketStats.rx_fill_ring_empty_descs; - m_Stats.rxDroppedTotalPackets = m_Stats.rxDroppedFillRingPackets + m_Stats.rxDroppedRxRingFullPackets + m_Stats.rxDroppedInvalidPackets + socketStats.rx_dropped; - m_Stats.txDroppedInvalidPackets = socketStats.tx_invalid_descs; + m_Stats.rxDroppedInvalidPackets = socketStats.rx_invalid_descs; + m_Stats.rxDroppedRxRingFullPackets = socketStats.rx_ring_full; + m_Stats.rxDroppedFillRingPackets = socketStats.rx_fill_ring_empty_descs; + m_Stats.rxDroppedTotalPackets = m_Stats.rxDroppedFillRingPackets + m_Stats.rxDroppedRxRingFullPackets + + m_Stats.rxDroppedInvalidPackets + socketStats.rx_dropped; + m_Stats.txDroppedInvalidPackets = socketStats.tx_invalid_descs; - return true; -} + return true; + } #define nanosec_gap(begin, end) ((end.tv_sec - begin.tv_sec) * 1000000000.0 + (end.tv_nsec - begin.tv_nsec)) -XdpDevice::XdpDeviceStats XdpDevice::getStatistics() -{ - timespec timestamp; - clock_gettime(CLOCK_MONOTONIC, ×tamp); + XdpDevice::XdpDeviceStats XdpDevice::getStatistics() + { + timespec timestamp; + clock_gettime(CLOCK_MONOTONIC, ×tamp); - m_Stats.timestamp = timestamp; + m_Stats.timestamp = timestamp; - if (m_DeviceOpened) - { - getSocketStats(); - m_Stats.umemFreeFrames = m_Umem->getFreeFrameCount(); - m_Stats.umemAllocatedFrames = m_Umem->getFrameCount() - m_Stats.umemFreeFrames; - } - else - { - m_Stats.umemFreeFrames = 0; - m_Stats.umemAllocatedFrames = 0; - } + if (m_DeviceOpened) + { + getSocketStats(); + m_Stats.umemFreeFrames = m_Umem->getFreeFrameCount(); + m_Stats.umemAllocatedFrames = m_Umem->getFrameCount() - m_Stats.umemFreeFrames; + } + else + { + m_Stats.umemFreeFrames = 0; + m_Stats.umemAllocatedFrames = 0; + } - double secsElapsed = (double)nanosec_gap(m_PrevStats.timestamp, timestamp) / 1000000000.0; - m_Stats.rxPacketsPerSec = static_cast((m_Stats.rxPackets - m_PrevStats.rxPackets) / secsElapsed); - m_Stats.rxBytesPerSec = static_cast((m_Stats.rxBytes - m_PrevStats.rxBytes) / secsElapsed); - m_Stats.txSentPacketsPerSec = static_cast((m_Stats.txSentPackets - m_PrevStats.txSentPackets) / secsElapsed); - m_Stats.txSentBytesPerSec = static_cast((m_Stats.txSentBytes - m_PrevStats.txSentBytes) / secsElapsed); - m_Stats.txCompletedPacketsPerSec = static_cast((m_Stats.txCompletedPackets - m_PrevStats.txCompletedPackets) / secsElapsed); + double secsElapsed = (double)nanosec_gap(m_PrevStats.timestamp, timestamp) / 1000000000.0; + m_Stats.rxPacketsPerSec = static_cast((m_Stats.rxPackets - m_PrevStats.rxPackets) / secsElapsed); + m_Stats.rxBytesPerSec = static_cast((m_Stats.rxBytes - m_PrevStats.rxBytes) / secsElapsed); + m_Stats.txSentPacketsPerSec = + static_cast((m_Stats.txSentPackets - m_PrevStats.txSentPackets) / secsElapsed); + m_Stats.txSentBytesPerSec = + static_cast((m_Stats.txSentBytes - m_PrevStats.txSentBytes) / secsElapsed); + m_Stats.txCompletedPacketsPerSec = + static_cast((m_Stats.txCompletedPackets - m_PrevStats.txCompletedPackets) / secsElapsed); - m_PrevStats.timestamp = timestamp; - m_PrevStats.rxPackets = m_Stats.rxPackets; - m_PrevStats.rxBytes = m_Stats.rxBytes; - m_PrevStats.txSentPackets = m_Stats.txSentPackets; - m_PrevStats.txSentBytes = m_Stats.txSentBytes; - m_PrevStats.txCompletedPackets = m_Stats.txCompletedPackets; + m_PrevStats.timestamp = timestamp; + m_PrevStats.rxPackets = m_Stats.rxPackets; + m_PrevStats.rxBytes = m_Stats.rxBytes; + m_PrevStats.txSentPackets = m_Stats.txSentPackets; + m_PrevStats.txSentBytes = m_Stats.txSentBytes; + m_PrevStats.txCompletedPackets = m_Stats.txCompletedPackets; - return m_Stats; -} + return m_Stats; + } -} +} // namespace pcpp