mirror of
https://github.com/mfontanini/libtins
synced 2026-01-26 12:01:34 +01:00
Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67c81199fb | ||
|
|
fe22186623 | ||
|
|
bbac2ece52 | ||
|
|
ba9a2155ca | ||
|
|
00619e0500 | ||
|
|
64da67ca56 | ||
|
|
3943700830 | ||
|
|
142b6f62cb | ||
|
|
dfd2701ee4 | ||
|
|
850bb9b642 | ||
|
|
b7e61f4c76 | ||
|
|
e2a14d8898 | ||
|
|
ba0c820852 | ||
|
|
df509e7e36 | ||
|
|
fa87e1b6f6 | ||
|
|
812be7966d | ||
|
|
f89cc9f076 | ||
|
|
638bf9b34b | ||
|
|
eb997f5438 | ||
|
|
18cbab4fc7 | ||
|
|
7cd2b2c396 | ||
|
|
2601493752 | ||
|
|
7204fbd688 | ||
|
|
c302e659d7 | ||
|
|
54e4e4b0f4 | ||
|
|
6a17e59032 | ||
|
|
e3aedc56ed | ||
|
|
3b006c15db | ||
|
|
177d0b4621 | ||
|
|
24ac038c30 | ||
|
|
a619e4ff98 | ||
|
|
14bb185d7a | ||
|
|
137b56d5a7 | ||
|
|
ed2b3c12d5 | ||
|
|
1650b60234 | ||
|
|
c20c82bcb5 | ||
|
|
5858132261 | ||
|
|
16f5795243 | ||
|
|
e90e377b73 | ||
|
|
222611b377 | ||
|
|
b447c664e1 | ||
|
|
468159e6d2 | ||
|
|
cd40b232e7 | ||
|
|
1166094a2f | ||
|
|
b3d874d6a8 | ||
|
|
553b1fb255 | ||
|
|
94939dd0fa | ||
|
|
0774a8dcad | ||
|
|
f46dee9f19 | ||
|
|
5b082a82b2 | ||
|
|
07012648fb | ||
|
|
ce409dbc7e | ||
|
|
16e77146ab | ||
|
|
a87c4a64f5 | ||
|
|
9e61286a59 | ||
|
|
8da102fb48 | ||
|
|
750c3556d9 | ||
|
|
28663b0e93 | ||
|
|
731e36e373 | ||
|
|
608b48f25c | ||
|
|
de247fcbc8 | ||
|
|
7bc4d38470 | ||
|
|
a926b75224 | ||
|
|
064439236c | ||
|
|
0c40a0714b | ||
|
|
d74520768b | ||
|
|
3385df9cc9 | ||
|
|
18c31b20f5 | ||
|
|
7387912ca1 | ||
|
|
0d52763a61 | ||
|
|
86b505f998 | ||
|
|
62a803c55c | ||
|
|
0573808aeb | ||
|
|
22b4435c81 | ||
|
|
b803959e11 | ||
|
|
2f16497bf8 | ||
|
|
78aa7d1787 | ||
|
|
ba2216e6e9 | ||
|
|
74e3d909e6 | ||
|
|
5e52091ecf | ||
|
|
dafb299ea3 | ||
|
|
659bec56d7 | ||
|
|
8c1bea6f84 | ||
|
|
d8d1dc003b | ||
|
|
c2bb52b82f | ||
|
|
1f5456b18b | ||
|
|
dc702f4fd6 | ||
|
|
2a8101eef3 | ||
|
|
20702ddaff | ||
|
|
f4e2701705 | ||
|
|
776ae4e83b | ||
|
|
2158c7a92e | ||
|
|
b53bad7b29 | ||
|
|
6c92bcdad1 | ||
|
|
b949e56d15 | ||
|
|
18ff3e7b6a | ||
|
|
559b1fb89a | ||
|
|
1e78ef0752 | ||
|
|
602ada7820 | ||
|
|
57ac099703 | ||
|
|
eb7628eca4 | ||
|
|
c26e4943c2 | ||
|
|
7e90c8be6a | ||
|
|
3659d89c25 | ||
|
|
db992d42e5 | ||
|
|
5571a270d4 | ||
|
|
b18c2cefec | ||
|
|
3f204321ce | ||
|
|
63603b8ac8 | ||
|
|
fa79582b89 | ||
|
|
342e2c77a7 | ||
|
|
7848e28b62 | ||
|
|
544aa1b339 | ||
|
|
de4791f0c7 | ||
|
|
915f506f3a | ||
|
|
f29566d6d9 | ||
|
|
e4f747164c | ||
|
|
683550b297 | ||
|
|
971fdf7d1c | ||
|
|
1038c6f7f3 | ||
|
|
8efc0271f5 | ||
|
|
9ac5e597e6 | ||
|
|
f7fc5fae1d | ||
|
|
f44b253a42 | ||
|
|
8f85a6e557 |
28
.github/workflows/tests.yaml
vendored
Normal file
28
.github/workflows/tests.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: Tests
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
Ubuntu-Tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install libpcap
|
||||||
|
run: sudo apt-get install -y libpcap-dev
|
||||||
|
|
||||||
|
- name: Initialize submodules
|
||||||
|
run: git submodule init && git submodule update
|
||||||
|
|
||||||
|
- name: Initialize build system
|
||||||
|
run: mkdir build && cd build && cmake ..
|
||||||
|
|
||||||
|
- name: Build tests
|
||||||
|
run: cmake --build build --target tests
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: ctest build
|
||||||
120
CHANGES.md
120
CHANGES.md
@@ -1,3 +1,123 @@
|
|||||||
|
##### v4.5 - Sun Aug 20 04:46:53 PM UTC 2023
|
||||||
|
|
||||||
|
- Add VXLAN support (#501)
|
||||||
|
|
||||||
|
- Add `FileSniffer` constructor taking a `FILE*` (#499).
|
||||||
|
|
||||||
|
- Remove use of deprecated `std::iterator` (#481).
|
||||||
|
|
||||||
|
- Add missing `algorithm` header include (#497).
|
||||||
|
|
||||||
|
- Validate high order two bits of first dns label octet (#494).
|
||||||
|
|
||||||
|
- Use `CMAKE_INSTALL_LIBDIR` in `CONF_CMAKE_INSTALL_DIR` (#472).
|
||||||
|
|
||||||
|
- Ignore IPv6 packets with payload after one with no Next Header (#500).
|
||||||
|
|
||||||
|
- Fix unqualified `std::move` call warnings on clang (#488).
|
||||||
|
|
||||||
|
- Fix incorrect IP address range calculation when using /0 prefix (#484) (#486).
|
||||||
|
|
||||||
|
- Fall back to system GTest if available (#473).
|
||||||
|
|
||||||
|
- Fix compilation issue on android (#471).
|
||||||
|
|
||||||
|
- Fix DNS parser reading garbage on misreported packet size (#468).
|
||||||
|
|
||||||
|
- Fix DNS parser misinterpreting bad label size (#466).
|
||||||
|
|
||||||
|
##### v4.4 - Thu Feb 17 14:41:59 UTC 2022
|
||||||
|
|
||||||
|
- Add RFC8335 extended echo types to `ICMP` and `ICMPv6` (#426)
|
||||||
|
|
||||||
|
- Handle loops in DNS name decompression (#444)
|
||||||
|
|
||||||
|
- Fix Windows' `interface` macro colliding with uses of that identifier in the code (#458)
|
||||||
|
|
||||||
|
- Sending IPv6 packets to a link-scope destination address now uses the right interface index (#448)
|
||||||
|
|
||||||
|
- Fix incorrect endian being used for ICMP's `gateway` and `address_mask` (#437)
|
||||||
|
|
||||||
|
- Socket in `PacketSender::open_l3_socket` is now closed if `setsockopt` fails (#433)
|
||||||
|
|
||||||
|
- Fix various incorrect doxygen documentation comments (#439).
|
||||||
|
|
||||||
|
- Fix infinite loop when querying the routing table in \*BSD (#427)
|
||||||
|
|
||||||
|
##### v4.3 - Fri Sep 18 03:08:33 UTC 2020
|
||||||
|
|
||||||
|
- Assign a PDUType to `Dot11ControlTA` (#420)
|
||||||
|
|
||||||
|
- Don't consider IPv6 ESP header a normal extension header (#374)
|
||||||
|
|
||||||
|
- Don't include non-existing headers when installed without libpcap (#382)
|
||||||
|
|
||||||
|
- Add `IPv6Address::is_local_unicast` (#369)
|
||||||
|
|
||||||
|
- Fix memory leak in `PacketWriter` (#343)
|
||||||
|
|
||||||
|
- Fix memory leaks in `OfflinePacketFilter` (#343)
|
||||||
|
|
||||||
|
- Fix detection of new TCP stream (#335)
|
||||||
|
|
||||||
|
- Introduce `TCP::has_flags` (#334)
|
||||||
|
|
||||||
|
- Fix padding calculations in RadioTapWriter (#333)
|
||||||
|
|
||||||
|
##### v4.2 - Fri Mar 8 04:15:13 UTC 2019
|
||||||
|
|
||||||
|
- Updated location of installed CMake files in unix systems (#331)
|
||||||
|
|
||||||
|
- Fix check to detect cross compilation (#330)
|
||||||
|
|
||||||
|
- Allow getting a PDU's advertised size and use it in `PacketWriter` (#324)
|
||||||
|
|
||||||
|
- Install DLLs in right directory (#326)
|
||||||
|
|
||||||
|
- Add missing Dot11 tagged option types (#305)
|
||||||
|
|
||||||
|
- Add support for DLT_RAW (#313)
|
||||||
|
|
||||||
|
- Fix potential invalid memory accesses when parsing RadioTap (#322)
|
||||||
|
|
||||||
|
##### v4.1 - Tue Dec 11 02:08:48 UTC 2018
|
||||||
|
|
||||||
|
- Fix serialization for QinQ (#316)
|
||||||
|
|
||||||
|
- Added base class access specifier for socket_close_error (#306)
|
||||||
|
|
||||||
|
- Rewrote hw_address_to_string to not require a stringstream (#299)
|
||||||
|
|
||||||
|
- Make RadioTapParser::skip_to_field check for end of buffer (#296)
|
||||||
|
|
||||||
|
- Ensure local include directory comes before system. (#293)
|
||||||
|
|
||||||
|
- Calculate IP option sizes properly (#288)
|
||||||
|
|
||||||
|
- Add parsing of well known IPv6 extension headers (#287)
|
||||||
|
|
||||||
|
- Add missing operators to address classes (#275)
|
||||||
|
|
||||||
|
- Add version macros in config.h
|
||||||
|
|
||||||
|
- Don't assume IPv6 uses ICMPv6 underneath
|
||||||
|
|
||||||
|
- Allow users to specify library install dir
|
||||||
|
|
||||||
|
- Use Sleep windows function passing milliseconds as parameter
|
||||||
|
|
||||||
|
- Implement IPv6::recv_response
|
||||||
|
|
||||||
|
- Don't use nullptr in non C++11 code
|
||||||
|
|
||||||
|
- Ignore (possibly malformed) options after EOL (#281)
|
||||||
|
|
||||||
|
- Don't include dot11.h in tins.h if it is not configured in the library (#277)
|
||||||
|
|
||||||
|
- Fix memory leak in PDU's move assignment operator
|
||||||
|
|
||||||
|
- Append padding to IPv6 options
|
||||||
|
|
||||||
##### v4.0 - Mon Dec 4 00:04:30 UTC 2017
|
##### v4.0 - Mon Dec 4 00:04:30 UTC 2017
|
||||||
|
|
||||||
- Add parent PDU to each PDU.
|
- Add parent PDU to each PDU.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
|
||||||
PROJECT(libtins)
|
PROJECT(libtins)
|
||||||
|
|
||||||
OPTION(LIBTINS_BUILD_EXAMPLES "Build examples" ON)
|
OPTION(LIBTINS_BUILD_EXAMPLES "Build examples" ON)
|
||||||
@@ -45,9 +45,10 @@ ELSE(LIBTINS_BUILD_SHARED)
|
|||||||
ENDIF(LIBTINS_BUILD_SHARED)
|
ENDIF(LIBTINS_BUILD_SHARED)
|
||||||
|
|
||||||
# The version number.
|
# The version number.
|
||||||
SET(LIBTINS_VERSION_MAJOR 4)
|
SET(TINS_VERSION_MAJOR 4)
|
||||||
SET(LIBTINS_VERSION_MINOR 0)
|
SET(TINS_VERSION_MINOR 6)
|
||||||
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
|
SET(TINS_VERSION_PATCH 0)
|
||||||
|
SET(LIBTINS_VERSION "${TINS_VERSION_MAJOR}.${TINS_VERSION_MINOR}")
|
||||||
|
|
||||||
# Required Packages
|
# Required Packages
|
||||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
|
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
|
||||||
@@ -224,18 +225,22 @@ IF(DOXYGEN_FOUND)
|
|||||||
)
|
)
|
||||||
ENDIF(DOXYGEN_FOUND)
|
ENDIF(DOXYGEN_FOUND)
|
||||||
|
|
||||||
# The library output directory
|
|
||||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
|
||||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
|
||||||
|
|
||||||
# Configuration file
|
# Configuration file
|
||||||
CONFIGURE_FILE(
|
CONFIGURE_FILE(
|
||||||
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
|
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
|
||||||
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
|
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
IF (NOT CMAKE_INSTALL_LIBDIR)
|
||||||
|
SET(CMAKE_INSTALL_LIBDIR lib)
|
||||||
|
ENDIF()
|
||||||
|
IF (NOT CMAKE_INSTALL_BINDIR)
|
||||||
|
SET(CMAKE_INSTALL_BINDIR bin)
|
||||||
|
ENDIF()
|
||||||
|
# The library output directory
|
||||||
|
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||||
|
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||||
# Support for pkg-config
|
# Support for pkg-config
|
||||||
SET(CMAKE_INSTALL_LIBDIR lib)
|
|
||||||
SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
|
SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
|
SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||||
SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||||
@@ -298,7 +303,13 @@ IF(LIBTINS_BUILD_TESTS)
|
|||||||
ENABLE_TESTING()
|
ENABLE_TESTING()
|
||||||
ADD_SUBDIRECTORY(tests)
|
ADD_SUBDIRECTORY(tests)
|
||||||
ELSE()
|
ELSE()
|
||||||
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
|
FIND_PACKAGE(GTest QUIET)
|
||||||
|
IF(${GTest_FOUND})
|
||||||
|
ENABLE_TESTING()
|
||||||
|
ADD_SUBDIRECTORY(tests)
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
|
||||||
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
@@ -306,6 +317,12 @@ ENDIF()
|
|||||||
# CMake project configuration export
|
# CMake project configuration export
|
||||||
# **********************************
|
# **********************************
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
set(CONF_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/libtins")
|
||||||
|
else()
|
||||||
|
set(CONF_CMAKE_INSTALL_DIR CMake)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Add all targets to the build-tree export set
|
# Add all targets to the build-tree export set
|
||||||
EXPORT(
|
EXPORT(
|
||||||
TARGETS tins
|
TARGETS tins
|
||||||
@@ -332,13 +349,13 @@ INSTALL(
|
|||||||
FILES
|
FILES
|
||||||
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
|
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
|
||||||
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
|
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
|
||||||
DESTINATION CMake
|
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
|
||||||
COMPONENT dev
|
COMPONENT dev
|
||||||
)
|
)
|
||||||
|
|
||||||
# Install the export set for use with the install-tree
|
# Install the export set for use with the install-tree
|
||||||
INSTALL(
|
INSTALL(
|
||||||
EXPORT libtinsTargets
|
EXPORT libtinsTargets
|
||||||
DESTINATION CMake
|
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
|
||||||
COMPONENT dev
|
COMPONENT dev
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ easier.
|
|||||||
|
|
||||||
Pull requests are very welcomed. When doing a pull request please:
|
Pull requests are very welcomed. When doing a pull request please:
|
||||||
|
|
||||||
* Base your PR branch on the `develop` branch. This is **almost always** pointing to the
|
* Notice that your code will be compiled and tests will be run automatically by the travis and
|
||||||
same commit as `master`, so you shouldn't have any issues changing the destination branch
|
|
||||||
to `develop` at the time you try to do the pull request if you based your code on `master`.
|
|
||||||
* Your code will be compiled and tests will be run automatically by the travis and
|
|
||||||
appveyor CI tools. If your code has issues on any of the tested platforms (GNU/Linux, Windows
|
appveyor CI tools. If your code has issues on any of the tested platforms (GNU/Linux, Windows
|
||||||
and OSX), please fix it or otherwise the PR won't be merged.
|
and OSX), please fix it or otherwise the PR won't be merged.
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if (NOT CMAKE_CXX_COMPILER_LOADED)
|
|||||||
message(FATAL_ERROR "CheckCXX11Features modules only works if language CXX is enabled")
|
message(FATAL_ERROR "CheckCXX11Features modules only works if language CXX is enabled")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.3)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
#
|
#
|
||||||
### Check for needed compiler flags
|
### Check for needed compiler flags
|
||||||
@@ -79,14 +79,14 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
|||||||
set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||||
set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||||
|
|
||||||
if (CROSS_COMPILING)
|
if (CMAKE_CROSSCOMPILING)
|
||||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}"
|
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}"
|
||||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||||
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}"
|
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}"
|
||||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||||
else (CROSS_COMPILING)
|
else (CMAKE_CROSSCOMPILING)
|
||||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||||
"${_bindir}" "${_SRCFILE}"
|
"${_bindir}" "${_SRCFILE}"
|
||||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||||
@@ -105,7 +105,7 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
|||||||
set(${RESULT_VAR} FALSE)
|
set(${RESULT_VAR} FALSE)
|
||||||
endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||||
endif (CROSS_COMPILING)
|
endif (CMAKE_CROSSCOMPILING)
|
||||||
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}"
|
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}"
|
||||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||||
|
|||||||
@@ -1366,7 +1366,8 @@ INCLUDE_FILE_PATTERNS =
|
|||||||
# instead of the = operator.
|
# instead of the = operator.
|
||||||
|
|
||||||
PREDEFINED = "TINS_IS_CXX11=1" \
|
PREDEFINED = "TINS_IS_CXX11=1" \
|
||||||
"TINS_HAVE_WPA2_CALLBACKS=1"
|
"TINS_HAVE_WPA2_CALLBACKS=1" \
|
||||||
|
"TINS_HAVE_DOT11=1"
|
||||||
|
|
||||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||||
# this tag can be used to specify a list of macro names that should be expanded.
|
# this tag can be used to specify a list of macro names that should be expanded.
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void do_arp_spoofing(NetworkInterface iface,
|
|||||||
sender.send(to_gw, iface);
|
sender.send(to_gw, iface);
|
||||||
sender.send(to_victim, iface);
|
sender.send(to_victim, iface);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sleep(5);
|
Sleep(5000);
|
||||||
#else
|
#else
|
||||||
sleep(5);
|
sleep(5);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ bool Scanner::callback(PDU& pdu) {
|
|||||||
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
|
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
|
||||||
}
|
}
|
||||||
// Is SYN flag on? Then port is open!
|
// Is SYN flag on? Then port is open!
|
||||||
else if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
else if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
|
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ private:
|
|||||||
const IP& ip = pdu.rfind_pdu<IP>();
|
const IP& ip = pdu.rfind_pdu<IP>();
|
||||||
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
||||||
// We'll only close a connection when seeing a SYN|ACK
|
// We'll only close a connection when seeing a SYN|ACK
|
||||||
if (tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
if (tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
// Create an ethernet header flipping the addresses
|
// Create an ethernet header flipping the addresses
|
||||||
EthernetII packet(eth.src_addr(), eth.dst_addr());
|
EthernetII packet(eth.src_addr(), eth.dst_addr());
|
||||||
// Do the same for IP
|
// Do the same for IP
|
||||||
|
|||||||
@@ -40,9 +40,13 @@ namespace Tins {
|
|||||||
* \brief AddressRange iterator class.
|
* \brief AddressRange iterator class.
|
||||||
*/
|
*/
|
||||||
template<typename Address>
|
template<typename Address>
|
||||||
class AddressRangeIterator : public std::iterator<std::forward_iterator_tag, const Address> {
|
class AddressRangeIterator {
|
||||||
public:
|
public:
|
||||||
typedef typename std::iterator<std::forward_iterator_tag, const Address>::value_type value_type;
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
typedef const Address value_type;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef const Address* pointer;
|
||||||
|
typedef const Address& reference;
|
||||||
|
|
||||||
struct end_iterator {
|
struct end_iterator {
|
||||||
|
|
||||||
|
|||||||
@@ -31,4 +31,9 @@
|
|||||||
/* Have libpcap */
|
/* Have libpcap */
|
||||||
#cmakedefine TINS_HAVE_PCAP
|
#cmakedefine TINS_HAVE_PCAP
|
||||||
|
|
||||||
|
/* Version macros */
|
||||||
|
#define TINS_VERSION_MAJOR ${TINS_VERSION_MAJOR}
|
||||||
|
#define TINS_VERSION_MINOR ${TINS_VERSION_MINOR}
|
||||||
|
#define TINS_VERSION_PATCH ${TINS_VERSION_PATCH}
|
||||||
|
|
||||||
#endif // TINS_CONFIG_H
|
#endif // TINS_CONFIG_H
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class Dot3;
|
|||||||
class SLL;
|
class SLL;
|
||||||
class Loopback;
|
class Loopback;
|
||||||
class PPI;
|
class PPI;
|
||||||
|
class IP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \struct DataLinkType
|
* \struct DataLinkType
|
||||||
@@ -73,6 +74,7 @@ TINS_MAKE_DATA_LINK_TYPE(Loopback, DLT_LOOP)
|
|||||||
TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI)
|
TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI)
|
||||||
TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11)
|
TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11)
|
||||||
TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO)
|
TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO)
|
||||||
|
TINS_MAKE_DATA_LINK_TYPE(IP, DLT_RAW)
|
||||||
|
|
||||||
#undef TINS_MAKE_DATA_LINK_TYPE
|
#undef TINS_MAKE_DATA_LINK_TYPE
|
||||||
|
|
||||||
|
|||||||
@@ -652,7 +652,7 @@ public:
|
|||||||
// Getters
|
// Getters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the id field.
|
* \brief Getter for the id field.
|
||||||
*
|
*
|
||||||
* \return uint16_t containing the value of the id field.
|
* \return uint16_t containing the value of the id field.
|
||||||
*/
|
*/
|
||||||
@@ -661,7 +661,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the query response field.
|
* \brief Getter for the query response field.
|
||||||
*
|
*
|
||||||
* \return QRType containing the value of the query response
|
* \return QRType containing the value of the query response
|
||||||
* field.
|
* field.
|
||||||
@@ -671,7 +671,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the opcode field.
|
* \brief Getter for the opcode field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the opcode field.
|
* \return uint8_t containing the value of the opcode field.
|
||||||
*/
|
*/
|
||||||
@@ -680,7 +680,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the authoritative answer field.
|
* \brief Getter for the authoritative answer field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the authoritative
|
* \return uint8_t containing the value of the authoritative
|
||||||
* answer field.
|
* answer field.
|
||||||
@@ -690,7 +690,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the truncated field.
|
* \brief Getter for the truncated field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the truncated field.
|
* \return uint8_t containing the value of the truncated field.
|
||||||
*/
|
*/
|
||||||
@@ -699,7 +699,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the recursion desired field.
|
* \brief Getter for the recursion desired field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the recursion
|
* \return uint8_t containing the value of the recursion
|
||||||
* desired field.
|
* desired field.
|
||||||
@@ -709,7 +709,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the recursion available field.
|
* \brief Getter for the recursion available field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the recursion
|
* \return uint8_t containing the value of the recursion
|
||||||
* available field.
|
* available field.
|
||||||
@@ -719,7 +719,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the z desired field.
|
* \brief Getter for the z desired field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the z field.
|
* \return uint8_t containing the value of the z field.
|
||||||
*/
|
*/
|
||||||
@@ -728,7 +728,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the authenticated data field.
|
* \brief Getter for the authenticated data field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the authenticated
|
* \return uint8_t containing the value of the authenticated
|
||||||
* data field.
|
* data field.
|
||||||
@@ -738,7 +738,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the checking disabled field.
|
* \brief Getter for the checking disabled field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the checking
|
* \return uint8_t containing the value of the checking
|
||||||
* disabled field.
|
* disabled field.
|
||||||
@@ -748,7 +748,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the rcode field.
|
* \brief Getter for the rcode field.
|
||||||
*
|
*
|
||||||
* \return uint8_t containing the value of the rcode field.
|
* \return uint8_t containing the value of the rcode field.
|
||||||
*/
|
*/
|
||||||
@@ -757,7 +757,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the questions field.
|
* \brief Getter for the questions field.
|
||||||
*
|
*
|
||||||
* \return uint16_t containing the value of the questions field.
|
* \return uint16_t containing the value of the questions field.
|
||||||
*/
|
*/
|
||||||
@@ -766,7 +766,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the answers field.
|
* \brief Getter for the answers field.
|
||||||
*
|
*
|
||||||
* \return uint16_t containing the value of the answers field.
|
* \return uint16_t containing the value of the answers field.
|
||||||
*/
|
*/
|
||||||
@@ -775,7 +775,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the authority field.
|
* \brief Getter for the authority field.
|
||||||
*
|
*
|
||||||
* \return uint16_t containing the value of the authority field.
|
* \return uint16_t containing the value of the authority field.
|
||||||
*/
|
*/
|
||||||
@@ -784,7 +784,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Setter for the additional field.
|
* \brief Getter for the additional field.
|
||||||
*
|
*
|
||||||
* \return uint16_t containing the value of the additional field.
|
* \return uint16_t containing the value of the additional field.
|
||||||
*/
|
*/
|
||||||
@@ -1034,7 +1034,8 @@ private:
|
|||||||
uint32_t compose_name(const uint8_t* ptr, char* out_ptr) const;
|
uint32_t compose_name(const uint8_t* ptr, char* out_ptr) const;
|
||||||
void convert_records(const uint8_t* ptr,
|
void convert_records(const uint8_t* ptr,
|
||||||
const uint8_t* end,
|
const uint8_t* end,
|
||||||
resources_type& res) const;
|
resources_type& res,
|
||||||
|
const uint16_t rr_count) const;
|
||||||
void skip_to_section_end(Memory::InputMemoryStream& stream,
|
void skip_to_section_end(Memory::InputMemoryStream& stream,
|
||||||
const uint32_t num_records) const;
|
const uint32_t num_records) const;
|
||||||
void skip_to_dname_end(Memory::InputMemoryStream& stream) const;
|
void skip_to_dname_end(Memory::InputMemoryStream& stream) const;
|
||||||
|
|||||||
@@ -127,9 +127,148 @@ public:
|
|||||||
ERP_INFORMATION,
|
ERP_INFORMATION,
|
||||||
TS_DELAY,
|
TS_DELAY,
|
||||||
TCLAS_PROCESSING,
|
TCLAS_PROCESSING,
|
||||||
QOS_CAPABILITY = 46,
|
HT_CAPABILITY,
|
||||||
|
QOS_CAPABILITY,
|
||||||
RSN = 48,
|
RSN = 48,
|
||||||
EXT_SUPPORTED_RATES = 50,
|
EXT_SUPPORTED_RATES = 50,
|
||||||
|
AP_CHANNEL_REPORT,
|
||||||
|
NEIGHBOR_REPORT,
|
||||||
|
RCPI,
|
||||||
|
MOBILITY_DOMAIN_MDE,
|
||||||
|
FAST_BSS_TRANSITION_FTE,
|
||||||
|
TIMEOUT_INTERVAL,
|
||||||
|
RIC_DATA_RDE,
|
||||||
|
DSE_REG_LOC,
|
||||||
|
SUPPORTED_OP_CLASSES,
|
||||||
|
EXT_CH_SWITCH_ANNOUNCEMENT,
|
||||||
|
HT_OPERATION,
|
||||||
|
SEC_CH_OFFSET,
|
||||||
|
BSS_AVG_ACCESS_DELAY,
|
||||||
|
ANTENNA,
|
||||||
|
RSNI,
|
||||||
|
MEASUREMENT_PILOT_TRANSMISSION,
|
||||||
|
BSS_AVAIL_ADMISSION_CAPACITY,
|
||||||
|
BSS_AC_ACCESS_DELAY,
|
||||||
|
TIME_ADVERTISEMENT,
|
||||||
|
RM_ENABLED_CAP,
|
||||||
|
MULTIPLE_BSSID,
|
||||||
|
BSS_2040_COEX,
|
||||||
|
BSS_2040_INTOLERANT_CH_REPORT,
|
||||||
|
OVERLAPPING_BSS_SCAN_PARAM,
|
||||||
|
RIC_DESCRIPTOR,
|
||||||
|
MGMT_MIC,
|
||||||
|
EVENT_REQ = 78,
|
||||||
|
EVENT_REPORT,
|
||||||
|
DIAG_REQ,
|
||||||
|
DIAG_REPORT,
|
||||||
|
LOCATION_PARAMS,
|
||||||
|
NONTRANSMITTED_BSSID_CAP,
|
||||||
|
SSID_LIST,
|
||||||
|
MULTIPLE_BSSID_INDEX,
|
||||||
|
FMS_DESCRIPTOR,
|
||||||
|
FMS_REQ,
|
||||||
|
FMS_RESP,
|
||||||
|
QOS_TRAFFIC_CAP,
|
||||||
|
BSS_MAX_IDLE_PERIOD,
|
||||||
|
TFS_REQ,
|
||||||
|
TFS_RESP,
|
||||||
|
WNM_SLEEP_MODE,
|
||||||
|
TIM_BROADCAST_REQ,
|
||||||
|
TIM_BROADCAST_RESP,
|
||||||
|
COLLOCATED_INTERFERENCE_REPORT,
|
||||||
|
CH_USAGE,
|
||||||
|
TIME_ZONE,
|
||||||
|
DMS_REQ,
|
||||||
|
DMS_RESP,
|
||||||
|
LINK_ID,
|
||||||
|
WAKEUP_SCHEDULE,
|
||||||
|
CH_SWITCH_TIMING,
|
||||||
|
PTI_CONTROL,
|
||||||
|
TPU_BUFFER_STATUS,
|
||||||
|
INTERWORKING,
|
||||||
|
ADVERTISEMENT_PROTOCOL,
|
||||||
|
EXPEDITED_BANDWIDTH_REQ,
|
||||||
|
QOS_MAP,
|
||||||
|
ROAMING_CONSORTIUM,
|
||||||
|
EMERG_ALERT_ID,
|
||||||
|
MESH_CONFIG,
|
||||||
|
MESH_ID,
|
||||||
|
MESH_LINK_METRIC_REPORT,
|
||||||
|
CONGESTION_NOTIFICATION,
|
||||||
|
MESH_PEERING_MGMT,
|
||||||
|
MESH_CH_SWITCH_PARAMS,
|
||||||
|
MESH_AWAKE_WINDOW,
|
||||||
|
BEACON_TIMING,
|
||||||
|
MCCAOP_SETUP_REQ,
|
||||||
|
MCCAOP_SETUP_REPLY,
|
||||||
|
MCCAOP_ADVERTISEMENT,
|
||||||
|
MCCAOP_TEARDOWN,
|
||||||
|
GANN,
|
||||||
|
RANN,
|
||||||
|
EXT_CAP,
|
||||||
|
PREQ = 130,
|
||||||
|
PREP,
|
||||||
|
PERR,
|
||||||
|
PXU = 137,
|
||||||
|
PXUC,
|
||||||
|
AUTH_MESH_PEER_EX,
|
||||||
|
MIC,
|
||||||
|
DEST_URI,
|
||||||
|
UAPSD_COEX,
|
||||||
|
DMG_WAKEUP_SCHEDULE,
|
||||||
|
EXT_SCHEDULE,
|
||||||
|
STA_AVAIL,
|
||||||
|
DMG_TSPEC,
|
||||||
|
NEXT_DMG_ATI,
|
||||||
|
DMG_CAP,
|
||||||
|
DMG_OP = 151,
|
||||||
|
DMG_BSS_PARAM_CHG,
|
||||||
|
DMG_BEAM_REFINEMENT,
|
||||||
|
CH_MEASUREMENT_FEEDBACK,
|
||||||
|
AWAKE_WINDOW = 157,
|
||||||
|
MULTIBAND,
|
||||||
|
ADDBA_ESXT,
|
||||||
|
NEXTPCP_LIST,
|
||||||
|
PCP_HANDOVER,
|
||||||
|
DMG_LINK_MARGIN,
|
||||||
|
SWITCHING_STREAM,
|
||||||
|
SESSION_TRANSITION,
|
||||||
|
DYNAMIC_TONE_PAIRING_REPORT,
|
||||||
|
CLUSTER_REPORT,
|
||||||
|
RELAY_CAP,
|
||||||
|
RELAY_TRANSFER_PARAM_SET,
|
||||||
|
BEAMLINK_MAINTENANCE,
|
||||||
|
MULTIPLE_MAC_SUBLAYERS,
|
||||||
|
UPID,
|
||||||
|
DMG_LINK_ADAPTATION_ACK,
|
||||||
|
MCCAOP_ADV_OVERVIEW = 174,
|
||||||
|
QUIET_PERIOD_REQ,
|
||||||
|
QUIET_PERIOD_RESP = 177,
|
||||||
|
QMF_POLICY = 181,
|
||||||
|
ECAPC_POLICY = 182,
|
||||||
|
CLUSTER_TIME_OFFSET,
|
||||||
|
INTRA_ACCESS_CAT_PRIORITY,
|
||||||
|
SCS_DESCRIPTOR,
|
||||||
|
QLOAD_REPORT,
|
||||||
|
HCCA_TXOP_UPDATE_COUNT,
|
||||||
|
HIGHER_LAYER_STREAM_ID,
|
||||||
|
GCR_GROUP_ADDR,
|
||||||
|
ANTENNA_SECTOR_ID_PATTERN,
|
||||||
|
VHT_CAP,
|
||||||
|
VHT_OP,
|
||||||
|
EXT_BSS_LOAD,
|
||||||
|
WIDE_BANDWIDTH_CH_SWITCH,
|
||||||
|
TRANSMIT_POWER_ENVELOPE,
|
||||||
|
CH_SWITCH_WRAPPER,
|
||||||
|
AID,
|
||||||
|
QUIET_CHANNEL,
|
||||||
|
OP_MODE_NOTIFY,
|
||||||
|
UPSIM,
|
||||||
|
REDUCED_NEIGHBOR_REPORT,
|
||||||
|
TVHT_OP,
|
||||||
|
DEV_LOC = 204,
|
||||||
|
WHITE_SPACE_MAP,
|
||||||
|
FINE_TUNING_MEASUREMENT_PARAMS,
|
||||||
VENDOR_SPECIFIC = 221
|
VENDOR_SPECIFIC = 221
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
class TINS_API Dot11ControlTA : public Dot11Control {
|
class TINS_API Dot11ControlTA : public Dot11Control {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* \brief This PDU's flag.
|
||||||
|
*/
|
||||||
|
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL_TA;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the target address field.
|
* \brief Getter for the target address field.
|
||||||
*/
|
*/
|
||||||
@@ -109,6 +114,15 @@ public:
|
|||||||
* \param addr The new target address.
|
* \param addr The new target address.
|
||||||
*/
|
*/
|
||||||
void target_addr(const address_type& addr);
|
void target_addr(const address_type& addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check whether this PDU matches the specified flag.
|
||||||
|
* \param flag The flag to match
|
||||||
|
* \sa PDU::matches_flag
|
||||||
|
*/
|
||||||
|
bool matches_flag(PDUType flag) const {
|
||||||
|
return flag == pdu_flag || Dot11::matches_flag(flag);
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* \brief Constructor for creating a 802.11 control frame TA PDU
|
* \brief Constructor for creating a 802.11 control frame TA PDU
|
||||||
|
|||||||
@@ -64,8 +64,26 @@ public:
|
|||||||
class malformed_packet : public exception_base {
|
class malformed_packet : public exception_base {
|
||||||
public:
|
public:
|
||||||
malformed_packet() : exception_base("Malformed packet") { }
|
malformed_packet() : exception_base("Malformed packet") { }
|
||||||
|
malformed_packet(const std::string& message) : exception_base(message) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Exception thrown when a DNS decompression pointer is out of bounds.
|
||||||
|
*/
|
||||||
|
class dns_decompression_pointer_out_of_bounds : public malformed_packet {
|
||||||
|
public:
|
||||||
|
dns_decompression_pointer_out_of_bounds() : malformed_packet("DNS decompression: pointer out of bounds") { }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Exception thrown when a DNS decompression pointer loops.
|
||||||
|
*/
|
||||||
|
class dns_decompression_pointer_loops : public malformed_packet {
|
||||||
|
public:
|
||||||
|
dns_decompression_pointer_loops() : malformed_packet("DNS decompression: pointer loops") { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Exception thrown when serializing a packet fails.
|
* \brief Exception thrown when serializing a packet fails.
|
||||||
*/
|
*/
|
||||||
@@ -128,7 +146,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* \brief Exception thrown when PacketSender fails to close a socket.
|
* \brief Exception thrown when PacketSender fails to close a socket.
|
||||||
*/
|
*/
|
||||||
class socket_close_error : exception_base {
|
class socket_close_error : public exception_base {
|
||||||
public:
|
public:
|
||||||
socket_close_error(const std::string& msg)
|
socket_close_error(const std::string& msg)
|
||||||
: exception_base(msg) { }
|
: exception_base(msg) { }
|
||||||
@@ -204,6 +222,15 @@ public:
|
|||||||
option_payload_too_large() : exception_base("Option payload too large") { }
|
option_payload_too_large() : exception_base("Option payload too large") { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Exception thrown when an IPv6 extension header is being
|
||||||
|
* created from invalid data
|
||||||
|
*/
|
||||||
|
class invalid_ipv6_extension_header : public exception_base {
|
||||||
|
public:
|
||||||
|
invalid_ipv6_extension_header() : exception_base("Invalid IPv6 extension header") { }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Generic pcap error
|
* \brief Generic pcap error
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end
|
|||||||
TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
|
TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
|
||||||
const uint8_t* start2, const uint8_t* end2);
|
const uint8_t* start2, const uint8_t* end2);
|
||||||
|
|
||||||
|
TINS_API bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
|
||||||
|
const uint8_t* start2, const uint8_t* end2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \endcond
|
* \endcond
|
||||||
*/
|
*/
|
||||||
@@ -268,6 +271,39 @@ public:
|
|||||||
return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
|
return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this HWAddress for less-than equality.
|
||||||
|
*
|
||||||
|
* \param rhs The HWAddress to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is equal or less-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator<=(const HWAddress& rhs) const {
|
||||||
|
return !operator>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this HWAddress for greater-than inequality.
|
||||||
|
*
|
||||||
|
* \param rhs The HWAddress to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is greater-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator>(const HWAddress& rhs) const {
|
||||||
|
return Internals::hw_address_gt_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this HWAddress for greater-than equality.
|
||||||
|
*
|
||||||
|
* \param rhs The HWAddress to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is equal or greater-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator>=(const HWAddress& rhs) const {
|
||||||
|
return !operator<(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Apply a mask to this address
|
* \brief Apply a mask to this address
|
||||||
*
|
*
|
||||||
@@ -282,6 +318,32 @@ public:
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Apply a mask to this address
|
||||||
|
*
|
||||||
|
* \param mask The mask to be applied
|
||||||
|
* \return The result of applying the mask to this address
|
||||||
|
*/
|
||||||
|
HWAddress operator|(const HWAddress& mask) const {
|
||||||
|
HWAddress<n> output = *this;
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
output[i] = output[i] | mask[i];
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief not operator
|
||||||
|
* \return The result of applying the mask to this address
|
||||||
|
*/
|
||||||
|
HWAddress operator~() const {
|
||||||
|
HWAddress<n> output = *this;
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
output[i] = ~output[i];
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves the size of this address.
|
* \brief Retrieves the size of this address.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ public:
|
|||||||
INFO_REQUEST = 15,
|
INFO_REQUEST = 15,
|
||||||
INFO_REPLY = 16,
|
INFO_REPLY = 16,
|
||||||
ADDRESS_MASK_REQUEST = 17,
|
ADDRESS_MASK_REQUEST = 17,
|
||||||
ADDRESS_MASK_REPLY = 18
|
ADDRESS_MASK_REPLY = 18,
|
||||||
|
EXTENDED_ECHO_REQUEST = 42,
|
||||||
|
EXTENDED_ECHO_REPLY = 43
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -318,7 +320,7 @@ public:
|
|||||||
* \return Returns the gateway field value.
|
* \return Returns the gateway field value.
|
||||||
*/
|
*/
|
||||||
address_type gateway() const {
|
address_type gateway() const {
|
||||||
return address_type(Endian::be_to_host(header_.un.gateway));
|
return address_type(header_.un.gateway);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -381,7 +383,7 @@ public:
|
|||||||
* \return Returns the address mask value.
|
* \return Returns the address mask value.
|
||||||
*/
|
*/
|
||||||
address_type address_mask() const {
|
address_type address_mask() const {
|
||||||
return address_type(Endian::be_to_host(orig_timestamp_or_address_mask_));
|
return address_type(orig_timestamp_or_address_mask_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#ifndef TINS_ICMPV6_H
|
#ifndef TINS_ICMPV6_H
|
||||||
#define TINS_ICMPV6_H
|
#define TINS_ICMPV6_H
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tins/macros.h>
|
#include <tins/macros.h>
|
||||||
#include <tins/pdu.h>
|
#include <tins/pdu.h>
|
||||||
@@ -92,7 +93,9 @@ public:
|
|||||||
MULTICAST_ROUTER_ADVERT = 151,
|
MULTICAST_ROUTER_ADVERT = 151,
|
||||||
MULTICAST_ROUTER_SOLICIT = 152,
|
MULTICAST_ROUTER_SOLICIT = 152,
|
||||||
MULTICAST_ROUTER_TERMINATE = 153,
|
MULTICAST_ROUTER_TERMINATE = 153,
|
||||||
RPL_CONTROL_MSG = 155
|
RPL_CONTROL_MSG = 155,
|
||||||
|
EXTENDED_ECHO_REQUEST = 160,
|
||||||
|
EXTENDED_ECHO_REPLY = 161
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,7 +176,7 @@ public:
|
|||||||
|
|
||||||
addr_list_type(const addresses_type& addresses = addresses_type())
|
addr_list_type(const addresses_type& addresses = addresses_type())
|
||||||
: addresses(addresses) {
|
: addresses(addresses) {
|
||||||
std::fill(reserved, reserved + sizeof(reserved), 0);
|
std::fill(reserved, reserved + sizeof(reserved), static_cast<uint8_t>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static addr_list_type from_option(const option& opt);
|
static addr_list_type from_option(const option& opt);
|
||||||
@@ -199,7 +202,7 @@ public:
|
|||||||
|
|
||||||
naack_type(uint8_t code = 0, uint8_t status = 0)
|
naack_type(uint8_t code = 0, uint8_t status = 0)
|
||||||
: code(code), status(status) {
|
: code(code), status(status) {
|
||||||
std::fill(reserved, reserved + 4, 0);
|
std::fill(reserved, reserved + 4, static_cast<uint8_t>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static naack_type from_option(const option& opt);
|
static naack_type from_option(const option& opt);
|
||||||
@@ -323,7 +326,7 @@ public:
|
|||||||
* The key_hash member will be 0-initialized.
|
* The key_hash member will be 0-initialized.
|
||||||
*/
|
*/
|
||||||
rsa_sign_type() {
|
rsa_sign_type() {
|
||||||
std::fill(key_hash, key_hash + sizeof(key_hash), 0);
|
std::fill(key_hash, key_hash + sizeof(key_hash), static_cast<uint8_t>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static rsa_sign_type from_option(const option& opt);
|
static rsa_sign_type from_option(const option& opt);
|
||||||
@@ -489,7 +492,7 @@ public:
|
|||||||
|
|
||||||
timestamp_type(uint64_t timestamp = 0)
|
timestamp_type(uint64_t timestamp = 0)
|
||||||
: timestamp(timestamp) {
|
: timestamp(timestamp) {
|
||||||
std::fill(reserved, reserved + sizeof(reserved), 0);
|
std::fill(reserved, reserved + sizeof(reserved), static_cast<uint8_t>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static timestamp_type from_option(const option& opt);
|
static timestamp_type from_option(const option& opt);
|
||||||
|
|||||||
@@ -174,9 +174,9 @@ public:
|
|||||||
option_identifier(OptionNumber number, OptionClass op_class,
|
option_identifier(OptionNumber number, OptionClass op_class,
|
||||||
small_uint<1> copied)
|
small_uint<1> copied)
|
||||||
#if TINS_IS_LITTLE_ENDIAN
|
#if TINS_IS_LITTLE_ENDIAN
|
||||||
: number(number), op_class(op_class), copied(copied) {}
|
: number(static_cast<uint8_t>(number)), op_class(static_cast<uint8_t>(op_class)), copied(copied) {}
|
||||||
#else
|
#else
|
||||||
: copied(copied), op_class(op_class), number(number) {}
|
: copied(copied), op_class(static_cast<uint8_t>(op_class)), number(static_cast<uint8_t>(number)) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -281,6 +281,10 @@ public:
|
|||||||
|
|
||||||
/* Getters */
|
/* Getters */
|
||||||
|
|
||||||
|
uint32_t advertised_size() const {
|
||||||
|
return static_cast<uint32_t>(tot_len());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the header length field.
|
* \brief Getter for the header length field.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#include <tins/cxxstd.h>
|
#include <tins/cxxstd.h>
|
||||||
#include <tins/macros.h>
|
#include <tins/macros.h>
|
||||||
|
|
||||||
@@ -135,6 +135,38 @@ public:
|
|||||||
return ip_addr_ < rhs.ip_addr_;
|
return ip_addr_ < rhs.ip_addr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this address for less-than equality.
|
||||||
|
*
|
||||||
|
* \param rhs The address to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is equal or less-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator<=(const IPv4Address& rhs) const {
|
||||||
|
return !operator>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compare this IPv4Address for greater-than inequality.
|
||||||
|
*
|
||||||
|
* \param rhs The address to be compared.
|
||||||
|
* \return bool indicating whether this address is greater-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator>(const IPv4Address& rhs) const {
|
||||||
|
return ip_addr_ > rhs.ip_addr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this address for greater-than equality.
|
||||||
|
*
|
||||||
|
* \param rhs The address to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is equal or greater-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator>=(const IPv4Address& rhs) const {
|
||||||
|
return !operator<(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Apply a mask to this address
|
* \brief Apply a mask to this address
|
||||||
*
|
*
|
||||||
@@ -143,6 +175,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
IPv4Address operator&(const IPv4Address& mask) const;
|
IPv4Address operator&(const IPv4Address& mask) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Apply a mask to this address
|
||||||
|
*
|
||||||
|
* \param mask The mask to be applied
|
||||||
|
* \return The result of applying the mask to this address
|
||||||
|
*/
|
||||||
|
IPv4Address operator|(const IPv4Address& mask) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* not operator (invert)
|
||||||
|
*/
|
||||||
|
IPv4Address operator~() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Returns true if this is a private IPv4 address.
|
* \brief Returns true if this is a private IPv4 address.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
typedef std::vector<ext_header> headers_type;
|
typedef std::vector<ext_header> headers_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type used to store an extension header option.
|
||||||
|
*/
|
||||||
|
typedef std::pair<uint8_t, std::vector<uint8_t> > header_option_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The values used to identify extension headers.
|
* The values used to identify extension headers.
|
||||||
*/
|
*/
|
||||||
@@ -105,6 +110,46 @@ public:
|
|||||||
*/
|
*/
|
||||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief The type used to store Hop-By-Hop Extension Headers
|
||||||
|
*/
|
||||||
|
struct hop_by_hop_header {
|
||||||
|
std::vector<header_option_type> options;
|
||||||
|
|
||||||
|
static hop_by_hop_header from_extension_header(const ext_header& hdr);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* \brief The type used to store Destination Routing Extension Headers
|
||||||
|
*/
|
||||||
|
struct destination_routing_header {
|
||||||
|
std::vector<header_option_type> options;
|
||||||
|
|
||||||
|
static destination_routing_header from_extension_header(const ext_header& hdr);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The type used to store Routing Extension headers
|
||||||
|
*/
|
||||||
|
struct routing_header {
|
||||||
|
uint8_t routing_type;
|
||||||
|
uint8_t segments_left;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
|
||||||
|
static routing_header from_extension_header(const ext_header& hdr);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief The type used to store Fragment Extension headers
|
||||||
|
*/
|
||||||
|
struct fragment_header {
|
||||||
|
uint16_t fragment_offset;
|
||||||
|
bool more_fragments;
|
||||||
|
uint32_t identification;
|
||||||
|
|
||||||
|
static fragment_header from_extension_header(const ext_header& hdr);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Constructs an IPv6 object.
|
* \brief Constructs an IPv6 object.
|
||||||
*
|
*
|
||||||
@@ -298,6 +343,14 @@ public:
|
|||||||
* \sa PDU::send()
|
* \sa PDU::send()
|
||||||
*/
|
*/
|
||||||
void send(PacketSender& sender, const NetworkInterface &);
|
void send(PacketSender& sender, const NetworkInterface &);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Receives a matching response for this packet.
|
||||||
|
*
|
||||||
|
* \sa PDU::recv_response
|
||||||
|
* \param sender The packet sender which will receive the packet.
|
||||||
|
*/
|
||||||
|
PDU* recv_response(PacketSender& sender, const NetworkInterface &);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -356,6 +409,8 @@ private:
|
|||||||
uint32_t calculate_headers_size() const;
|
uint32_t calculate_headers_size() const;
|
||||||
static void write_header(const ext_header& header, Memory::OutputMemoryStream& stream);
|
static void write_header(const ext_header& header, Memory::OutputMemoryStream& stream);
|
||||||
static bool is_extension_header(uint8_t header_id);
|
static bool is_extension_header(uint8_t header_id);
|
||||||
|
static uint32_t get_padding_size(const ext_header& header);
|
||||||
|
static std::vector<header_option_type> parse_header_options(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
TINS_BEGIN_PACK
|
TINS_BEGIN_PACK
|
||||||
struct ipv6_header {
|
struct ipv6_header {
|
||||||
|
|||||||
@@ -161,6 +161,39 @@ public:
|
|||||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this address for less-than equality.
|
||||||
|
*
|
||||||
|
* \param rhs The address to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is equal or less-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator<=(const IPv6Address& rhs) const {
|
||||||
|
return !operator>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this address for greater-than inequality.
|
||||||
|
*
|
||||||
|
* \param rhs The address to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is greater-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator>(const IPv6Address& rhs) const {
|
||||||
|
return std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Compares this address for greater-than equality.
|
||||||
|
*
|
||||||
|
* \param rhs The address to be compared to.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether this address is equal or greater-than rhs.
|
||||||
|
*/
|
||||||
|
bool operator>=(const IPv6Address& rhs) const {
|
||||||
|
return !operator<(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Helper function which copies the address into an output
|
* \brief Helper function which copies the address into an output
|
||||||
* iterator.
|
* iterator.
|
||||||
@@ -197,6 +230,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool is_multicast() const;
|
bool is_multicast() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return true if this is a Link-Local unicast IPv6 address.
|
||||||
|
*
|
||||||
|
* This method returns true if this address is in the address range
|
||||||
|
* fe80::/10, false otherwise
|
||||||
|
*/
|
||||||
|
bool is_local_unicast() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Returns the size of an IPv6 Address.
|
* \brief Returns the size of an IPv6 Address.
|
||||||
*
|
*
|
||||||
@@ -218,7 +259,17 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Applies a mask to an address
|
* Applies a mask to an address
|
||||||
*/
|
*/
|
||||||
TINS_API friend IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs);
|
IPv6Address operator&(const IPv6Address& rhs) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* or a mask to an address
|
||||||
|
*/
|
||||||
|
IPv6Address operator|(const IPv6Address& rhs) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* not operator (invert)
|
||||||
|
*/
|
||||||
|
IPv6Address operator~() const ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(const char* addr);
|
void init(const char* addr);
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ public:
|
|||||||
* \return The LLC frame format.
|
* \return The LLC frame format.
|
||||||
*/
|
*/
|
||||||
uint8_t type() {
|
uint8_t type() {
|
||||||
return type_;
|
return static_cast<uint8_t>(type_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,7 +245,7 @@ public:
|
|||||||
* \return The sender send sequence number if format is INFORMATION else 0.
|
* \return The sender send sequence number if format is INFORMATION else 0.
|
||||||
*/
|
*/
|
||||||
uint8_t send_seq_number() {
|
uint8_t send_seq_number() {
|
||||||
return (type() == INFORMATION) ? (control_field.info.send_seq_num) : 0;
|
return static_cast<uint8_t>((type() == INFORMATION) ? (control_field.info.send_seq_num) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -119,6 +119,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
NetworkInterface(IPv4Address ip);
|
NetworkInterface(IPv4Address ip);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a NetworkInterface from an ipv6 address.
|
||||||
|
*
|
||||||
|
* This abstracted interface will be the one that would be the gateway
|
||||||
|
* when sending a packet to the given ip.
|
||||||
|
*
|
||||||
|
* \param ip The ipv6 address being looked up.
|
||||||
|
*/
|
||||||
|
NetworkInterface(IPv6Address ipv6);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for this interface's identifier.
|
* \brief Getter for this interface's identifier.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ class PDU;
|
|||||||
* - Those that don't contain a link layer PDU. In this case, the
|
* - Those that don't contain a link layer PDU. In this case, the
|
||||||
* kernel will be responsible for picking the appropriate network interface
|
* kernel will be responsible for picking the appropriate network interface
|
||||||
* based on the destination address.
|
* based on the destination address.
|
||||||
*
|
* - Exception: <a href="https://datatracker.ietf.org/doc/html/rfc2553#section-3.3">RFC2553</a>
|
||||||
|
* requires IPv6 link-scope address have a interface defined.
|
||||||
|
* .
|
||||||
* \par Note for Windows users:
|
* \par Note for Windows users:
|
||||||
* Sending layer 3 PDUs (without a link layer protocol) is very restricted
|
* Sending layer 3 PDUs (without a link layer protocol) is very restricted
|
||||||
* on Windows (<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx">link</a>).
|
* on Windows (<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx">link</a>).
|
||||||
@@ -131,6 +133,7 @@ public:
|
|||||||
ARP_SOCKET,
|
ARP_SOCKET,
|
||||||
ICMP_SOCKET,
|
ICMP_SOCKET,
|
||||||
IPV6_SOCKET,
|
IPV6_SOCKET,
|
||||||
|
ICMPV6_SOCKET,
|
||||||
SOCKETS_END
|
SOCKETS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ public:
|
|||||||
ICMPv6,
|
ICMPv6,
|
||||||
SLL,
|
SLL,
|
||||||
DHCPv6,
|
DHCPv6,
|
||||||
|
DOT1AD,
|
||||||
DOT1Q,
|
DOT1Q,
|
||||||
PPPOE,
|
PPPOE,
|
||||||
STP,
|
STP,
|
||||||
@@ -178,6 +179,9 @@ public:
|
|||||||
IPSEC_ESP,
|
IPSEC_ESP,
|
||||||
PKTAP,
|
PKTAP,
|
||||||
MPLS,
|
MPLS,
|
||||||
|
DOT11_CONTROL_TA,
|
||||||
|
VXLAN,
|
||||||
|
RTP,
|
||||||
UNKNOWN = 999,
|
UNKNOWN = 999,
|
||||||
USER_DEFINED_PDU = 1000
|
USER_DEFINED_PDU = 1000
|
||||||
};
|
};
|
||||||
@@ -244,8 +248,9 @@ public:
|
|||||||
* \param rhs The PDU to be moved.
|
* \param rhs The PDU to be moved.
|
||||||
*/
|
*/
|
||||||
PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
|
PDU& operator=(PDU &&rhs) TINS_NOEXCEPT {
|
||||||
|
delete inner_pdu_;
|
||||||
|
inner_pdu_ = 0;
|
||||||
std::swap(inner_pdu_, rhs.inner_pdu_);
|
std::swap(inner_pdu_, rhs.inner_pdu_);
|
||||||
rhs.inner_pdu_ = 0;
|
|
||||||
if (inner_pdu_) {
|
if (inner_pdu_) {
|
||||||
inner_pdu_->parent_pdu(this);
|
inner_pdu_->parent_pdu(this);
|
||||||
}
|
}
|
||||||
@@ -279,6 +284,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
uint32_t size() const;
|
uint32_t size() const;
|
||||||
|
|
||||||
|
/** \brief The whole chain of PDU's advertised size, including this one.
|
||||||
|
*
|
||||||
|
* Returns the sum of this and all children PDU's advertised size.
|
||||||
|
*/
|
||||||
|
virtual uint32_t advertised_size() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Getter for the inner PDU.
|
* \brief Getter for the inner PDU.
|
||||||
* \return The current inner PDU. Might be a null pointer.
|
* \return The current inner PDU. Might be a null pointer.
|
||||||
|
|||||||
@@ -106,8 +106,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
template <typename Concrete>
|
template <typename Concrete>
|
||||||
bool operator==(const PDUIteratorBase<Concrete>& lhs, const PDUIteratorBase<Concrete>& rhs) {
|
bool operator==(const PDUIteratorBase<Concrete>& lhs, const PDUIteratorBase<Concrete>& rhs) {
|
||||||
const PDU* lhs_pdu = &*static_cast<const Concrete&>(lhs);
|
const PDU* lhs_pdu = static_cast<const Concrete&>(lhs).operator->();
|
||||||
const PDU* rhs_pdu = &*static_cast<const Concrete&>(rhs);
|
const PDU* rhs_pdu = static_cast<const Concrete&>(rhs).operator->();
|
||||||
return lhs_pdu == rhs_pdu;
|
return lhs_pdu == rhs_pdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ public:
|
|||||||
|
|
||||||
template <typename OtherIterator>
|
template <typename OtherIterator>
|
||||||
PDUIteratorRange(const PDUIteratorRange<OtherIterator>& other)
|
PDUIteratorRange(const PDUIteratorRange<OtherIterator>& other)
|
||||||
: start_(&*other.begin()), end_(&*other.end()) {
|
: start_(other.begin().operator->()), end_(other.end().operator->()) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public:
|
|||||||
* \param data The payload to use.
|
* \param data The payload to use.
|
||||||
*/
|
*/
|
||||||
RawPDU(payload_type&& data)
|
RawPDU(payload_type&& data)
|
||||||
: payload_(move(data)) { }
|
: payload_(std::move(data)) { }
|
||||||
#endif // TINS_IS_CXX11
|
#endif // TINS_IS_CXX11
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
328
include/tins/rtp.h
Normal file
328
include/tins/rtp.h
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
#ifndef TINS_RTP_H
|
||||||
|
#define TINS_RTP_H
|
||||||
|
|
||||||
|
#include <tins/endianness.h>
|
||||||
|
#include <tins/pdu.h>
|
||||||
|
#include <tins/pdu_option.h>
|
||||||
|
#include <tins/small_uint.h>
|
||||||
|
|
||||||
|
namespace Tins {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class RTP
|
||||||
|
* \brief Represents a RTP PDU.
|
||||||
|
*
|
||||||
|
* This class represents a RTP PDU.
|
||||||
|
*
|
||||||
|
* \sa RawPDU
|
||||||
|
*/
|
||||||
|
class TINS_API RTP : public PDU {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \brief This PDU's flag.
|
||||||
|
*/
|
||||||
|
static const PDU::PDUType pdu_flag = PDU::RTP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type used to store CSRC identifiers.
|
||||||
|
*/
|
||||||
|
typedef std::vector<uint32_t> csrc_ids_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type used to store extension header data.
|
||||||
|
*/
|
||||||
|
typedef std::vector<uint32_t> extension_header_data_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
RTP();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a RTP object from a buffer.
|
||||||
|
*
|
||||||
|
* \param data The buffer from which this PDU will be constructed.
|
||||||
|
* \param size The size of the data buffer.
|
||||||
|
*/
|
||||||
|
RTP(const uint8_t* data, uint32_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the version.
|
||||||
|
*/
|
||||||
|
small_uint<2> version() const { return header_.version; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the padding bit.
|
||||||
|
*/
|
||||||
|
small_uint<1> padding_bit() const { return header_.padding; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the extension bit.
|
||||||
|
*/
|
||||||
|
small_uint<1> extension_bit() const { return header_.extension; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the CSRC count.
|
||||||
|
*/
|
||||||
|
small_uint<4> csrc_count() const { return header_.csrc_count; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the marker bit.
|
||||||
|
*/
|
||||||
|
small_uint<1> marker_bit() const { return header_.marker; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the payload type.
|
||||||
|
*/
|
||||||
|
small_uint<7> payload_type() const { return header_.payload_type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the sequence number.
|
||||||
|
*/
|
||||||
|
uint16_t sequence_number() const { return Endian::be_to_host(header_.seq_num); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the timestamp.
|
||||||
|
*/
|
||||||
|
uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the SSRC identifier.
|
||||||
|
*/
|
||||||
|
uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the CSRC identifiers.
|
||||||
|
*/
|
||||||
|
const csrc_ids_type& csrc_ids() const {
|
||||||
|
return csrc_ids_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the padding size.
|
||||||
|
*/
|
||||||
|
uint8_t padding_size() const { return padding_size_; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the extension header profile.
|
||||||
|
*/
|
||||||
|
uint16_t extension_profile() const { return Endian::be_to_host(ext_header_.profile); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the extension header length.
|
||||||
|
*/
|
||||||
|
uint16_t extension_length() const { return Endian::be_to_host(ext_header_.length); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the extension header data.
|
||||||
|
*/
|
||||||
|
const extension_header_data_type& extension_data() const {
|
||||||
|
return ext_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the version.
|
||||||
|
* \param version The new version.
|
||||||
|
*/
|
||||||
|
void version(small_uint<2> version) { header_.version = version; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the extension bit.
|
||||||
|
* \param extension The new extension bit.
|
||||||
|
*/
|
||||||
|
void extension_bit(small_uint<1> extension) { header_.extension = extension; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the marker bit.
|
||||||
|
* \param marker The new marker bit.
|
||||||
|
*/
|
||||||
|
void marker_bit(small_uint<1> marker) { header_.marker = marker; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the payload type.
|
||||||
|
* \param payload_type The new payload type.
|
||||||
|
*/
|
||||||
|
void payload_type(small_uint<7> payload_type) { header_.payload_type = payload_type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the sequence number.
|
||||||
|
* \param seq_num The new sequence number.
|
||||||
|
*/
|
||||||
|
void sequence_number(uint16_t seq_num) { header_.seq_num = Endian::host_to_be(seq_num); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the timestamp.
|
||||||
|
* \param timestamp The new timestamp.
|
||||||
|
*/
|
||||||
|
void timestamp(uint32_t timestamp) { header_.timestamp = Endian::host_to_be(timestamp); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the SSRC identifier.
|
||||||
|
* \param ssrc_id The new SSRC identifier.
|
||||||
|
*/
|
||||||
|
void ssrc_id(uint32_t ssrc_id) { header_.ssrc_id = Endian::host_to_be(ssrc_id); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the padding size.
|
||||||
|
* \param size The new padding size.
|
||||||
|
*/
|
||||||
|
void padding_size(uint8_t size) {
|
||||||
|
padding_bit(size > 0);
|
||||||
|
padding_size_ = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the extension header profile.
|
||||||
|
* \param profile The new extension header profile.
|
||||||
|
*/
|
||||||
|
void extension_profile(uint16_t profile) { ext_header_.profile = Endian::host_to_be(profile); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a word of extension header data.
|
||||||
|
*
|
||||||
|
* The word is added after the last word of extension header data.
|
||||||
|
*
|
||||||
|
* \param value The value of the extension header data to be added.
|
||||||
|
*/
|
||||||
|
void add_extension_data(const uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Removes a word of extension header data.
|
||||||
|
*
|
||||||
|
* If there are multiple words of extension header data of the given value,
|
||||||
|
* only the first one will be removed.
|
||||||
|
*
|
||||||
|
* \param value The value of the extension header data to be removed.
|
||||||
|
* \return true if the extension header data was removed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool remove_extension_data(const uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searches for extension header data that matches the given value.
|
||||||
|
* \param value The extension header data to be searched.
|
||||||
|
* \return true if the extension header data was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_extension_data(const uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Adds a CSRC identifier.
|
||||||
|
*
|
||||||
|
* The CSRC identifier is added after the last CSRC identifier in the extension
|
||||||
|
* header.
|
||||||
|
*
|
||||||
|
* \param csrc_id The CSRC identifier to be added
|
||||||
|
*/
|
||||||
|
void add_csrc_id(const uint32_t csrc_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Removes a CSRC identifier.
|
||||||
|
*
|
||||||
|
* If there are multiple CSRC identifiers of the given value, only the first one
|
||||||
|
* will be removed.
|
||||||
|
*
|
||||||
|
* \param value The value of the CSRC identifier to be removed.
|
||||||
|
* \return true if the CSRC identifier was removed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool remove_csrc_id(const uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Searches for a CSRC identifier that matches the given value.
|
||||||
|
* \param value The CSRC identifier to be searched.
|
||||||
|
* \return true if the CSRC identifier was found, false otherwise.
|
||||||
|
*/
|
||||||
|
bool search_csrc_id(const uint32_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns the RTP packet's header length.
|
||||||
|
*
|
||||||
|
* This method overrides PDU::header_size.
|
||||||
|
*
|
||||||
|
* \return An uint32_t with the header's size.
|
||||||
|
* \sa PDU::header_size
|
||||||
|
*/
|
||||||
|
uint32_t header_size() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns the RTP packet's trailer length.
|
||||||
|
*
|
||||||
|
* This method overrides PDU::trailer_size.
|
||||||
|
*
|
||||||
|
* \return An uint32_t with the trailer's size.
|
||||||
|
* \sa PDU::trailer_size
|
||||||
|
*/
|
||||||
|
uint32_t trailer_size() const { return static_cast<uint32_t>(padding_size_); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the PDU's type.
|
||||||
|
* \sa PDU::pdu_type
|
||||||
|
*/
|
||||||
|
PDUType pdu_type() const { return pdu_flag; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \sa PDU::clone
|
||||||
|
*/
|
||||||
|
RTP *clone() const { return new RTP(*this); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TINS_BEGIN_PACK
|
||||||
|
struct rtp_header {
|
||||||
|
#if TINS_IS_BIG_ENDIAN
|
||||||
|
uint16_t version:2,
|
||||||
|
padding:1,
|
||||||
|
extension:1,
|
||||||
|
csrc_count:4,
|
||||||
|
marker:1,
|
||||||
|
payload_type:7;
|
||||||
|
#elif TINS_IS_LITTLE_ENDIAN
|
||||||
|
uint16_t csrc_count:4,
|
||||||
|
extension:1,
|
||||||
|
padding:1,
|
||||||
|
version:2,
|
||||||
|
payload_type:7,
|
||||||
|
marker:1;
|
||||||
|
#endif
|
||||||
|
uint16_t seq_num;
|
||||||
|
uint32_t timestamp;
|
||||||
|
uint32_t ssrc_id;
|
||||||
|
} TINS_END_PACK;
|
||||||
|
|
||||||
|
TINS_BEGIN_PACK
|
||||||
|
struct rtp_extension_header {
|
||||||
|
uint16_t profile;
|
||||||
|
uint16_t length;
|
||||||
|
} TINS_END_PACK;
|
||||||
|
|
||||||
|
void write_serialization(uint8_t* buffer, uint32_t size);
|
||||||
|
csrc_ids_type::const_iterator search_csrc_id_iterator(const uint32_t csrc_id) const;
|
||||||
|
csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id);
|
||||||
|
extension_header_data_type::const_iterator search_extension_data_iterator(const uint32_t data) const;
|
||||||
|
extension_header_data_type::iterator search_extension_data_iterator(const uint32_t data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the padding bit.
|
||||||
|
* \param padding The new padding bit.
|
||||||
|
*/
|
||||||
|
void padding_bit(small_uint<1> padding) { header_.padding = padding; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the CSRC count. Hidden from the public interface.
|
||||||
|
* \param csrc_count The new CSRC count.
|
||||||
|
*/
|
||||||
|
void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the extension header length. Hidden from the public interface.
|
||||||
|
* \param length The new extension header length.
|
||||||
|
*/
|
||||||
|
void extension_length(uint16_t length) { ext_header_.length = Endian::host_to_be(length); }
|
||||||
|
|
||||||
|
rtp_header header_;
|
||||||
|
csrc_ids_type csrc_ids_;
|
||||||
|
rtp_extension_header ext_header_;
|
||||||
|
extension_header_data_type ext_data_;
|
||||||
|
uint8_t padding_size_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Tins
|
||||||
|
|
||||||
|
#endif // TINS_RTP_H
|
||||||
@@ -406,10 +406,17 @@ private:
|
|||||||
*/
|
*/
|
||||||
class TINS_API FileSniffer : public BaseSniffer {
|
class TINS_API FileSniffer : public BaseSniffer {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Constructs an instance of FileSniffer.
|
||||||
|
* \param fp The pcap file which will be parsed.
|
||||||
|
* \param configuration A SnifferConfiguration to be used on the file.
|
||||||
|
*/
|
||||||
|
FileSniffer(FILE *fp, const SnifferConfiguration& configuration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Constructs an instance of FileSniffer.
|
* \brief Constructs an instance of FileSniffer.
|
||||||
* \param file_name The pcap file which will be parsed.
|
* \param file_name The pcap file which will be parsed.
|
||||||
* \param filter A capture filter to be used on the file.(optional);
|
* \param configuration A SnifferConfiguration to be used on the file.
|
||||||
*/
|
*/
|
||||||
FileSniffer(const std::string& file_name, const SnifferConfiguration& configuration);
|
FileSniffer(const std::string& file_name, const SnifferConfiguration& configuration);
|
||||||
|
|
||||||
@@ -418,9 +425,18 @@ public:
|
|||||||
*
|
*
|
||||||
* \brief Constructs an instance of FileSniffer.
|
* \brief Constructs an instance of FileSniffer.
|
||||||
* \param file_name The pcap file which will be parsed.
|
* \param file_name The pcap file which will be parsed.
|
||||||
* \param filter A capture filter to be used on the file.(optional);
|
* \param filter A capture filter to be used on the file. (optional)
|
||||||
*/
|
*/
|
||||||
FileSniffer(const std::string& file_name, const std::string& filter = "");
|
FileSniffer(const std::string& file_name, const std::string& filter = "");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \deprecated Use the constructor that takes a SnifferConfiguration instead.
|
||||||
|
*
|
||||||
|
* \brief Constructs an instance of FileSniffer.
|
||||||
|
* \param fp The pcap file which will be parsed.
|
||||||
|
* \param filter A capture filter to be used on the file. (optional)
|
||||||
|
*/
|
||||||
|
FileSniffer(FILE *fp, const std::string& filter = "");
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -449,8 +465,14 @@ HandlerProxy<T> make_sniffer_handler(T* ptr,
|
|||||||
/**
|
/**
|
||||||
* \brief Iterates over packets sniffed by a BaseSniffer.
|
* \brief Iterates over packets sniffed by a BaseSniffer.
|
||||||
*/
|
*/
|
||||||
class SnifferIterator : public std::iterator<std::forward_iterator_tag, Packet> {
|
class SnifferIterator {
|
||||||
public:
|
public:
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
typedef Packet value_type;
|
||||||
|
typedef std::ptrdiff_t difference_type;
|
||||||
|
typedef Packet* pointer;
|
||||||
|
typedef Packet& reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a SnifferIterator.
|
* Constructs a SnifferIterator.
|
||||||
* \param sniffer The sniffer to iterate.
|
* \param sniffer The sniffer to iterate.
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ public:
|
|||||||
* \code
|
* \code
|
||||||
* TCP tcp = ...;
|
* TCP tcp = ...;
|
||||||
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
* if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
||||||
* // It's a SYN+ACK!
|
* // It's a SYN+ACK, but not SYN+ACK+ECN!
|
||||||
* }
|
* }
|
||||||
* \endcode
|
* \endcode
|
||||||
*
|
*
|
||||||
@@ -296,6 +296,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
small_uint<12> flags() const;
|
small_uint<12> flags() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check if the given flags are set.
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* TCP tcp = ...;
|
||||||
|
* if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
|
* // It's a SYN+ACK, but it also possible that other flags are set!
|
||||||
|
* // it is equivalent to: (tcp.flags() & (TCP::SYN | TCP::ACK)) == (TCP::SYN | TCP::ACK)
|
||||||
|
* }
|
||||||
|
* \endcode
|
||||||
|
*
|
||||||
|
* \param check_flags
|
||||||
|
* \return true if all check_flags are set
|
||||||
|
*/
|
||||||
|
bool has_flags(small_uint<12> check_flags) const;
|
||||||
|
|
||||||
/* Setters */
|
/* Setters */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -40,23 +40,28 @@
|
|||||||
#include <tins/llc.h>
|
#include <tins/llc.h>
|
||||||
#include <tins/icmp.h>
|
#include <tins/icmp.h>
|
||||||
#include <tins/icmpv6.h>
|
#include <tins/icmpv6.h>
|
||||||
|
#if defined(TINS_HAVE_DOT11)
|
||||||
#include <tins/dot11.h>
|
#include <tins/dot11.h>
|
||||||
|
#endif
|
||||||
#include <tins/dot1q.h>
|
#include <tins/dot1q.h>
|
||||||
#include <tins/dot3.h>
|
#include <tins/dot3.h>
|
||||||
#include <tins/ip.h>
|
#include <tins/ip.h>
|
||||||
#include <tins/ipv6.h>
|
#include <tins/ipv6.h>
|
||||||
#include <tins/mpls.h>
|
#include <tins/mpls.h>
|
||||||
#include <tins/packet_sender.h>
|
#include <tins/packet_sender.h>
|
||||||
#include <tins/packet_writer.h>
|
|
||||||
#include <tins/pdu.h>
|
#include <tins/pdu.h>
|
||||||
#include <tins/radiotap.h>
|
#include <tins/radiotap.h>
|
||||||
#include <tins/rawpdu.h>
|
#include <tins/rawpdu.h>
|
||||||
#include <tins/snap.h>
|
#include <tins/snap.h>
|
||||||
#include <tins/sniffer.h>
|
|
||||||
#include <tins/tcp.h>
|
#include <tins/tcp.h>
|
||||||
#include <tins/udp.h>
|
#include <tins/udp.h>
|
||||||
#include <tins/utils.h>
|
#include <tins/utils.h>
|
||||||
|
#if defined(TINS_HAVE_PCAP)
|
||||||
|
#include <tins/packet_writer.h>
|
||||||
|
#include <tins/sniffer.h>
|
||||||
|
#include <tins/ppi.h>
|
||||||
#include <tins/tcp_stream.h>
|
#include <tins/tcp_stream.h>
|
||||||
|
#endif
|
||||||
#include <tins/crypto.h>
|
#include <tins/crypto.h>
|
||||||
#include <tins/pdu_cacher.h>
|
#include <tins/pdu_cacher.h>
|
||||||
#include <tins/rsn_information.h>
|
#include <tins/rsn_information.h>
|
||||||
@@ -73,7 +78,8 @@
|
|||||||
#include <tins/pdu_allocator.h>
|
#include <tins/pdu_allocator.h>
|
||||||
#include <tins/ipsec.h>
|
#include <tins/ipsec.h>
|
||||||
#include <tins/ip_reassembler.h>
|
#include <tins/ip_reassembler.h>
|
||||||
#include <tins/ppi.h>
|
|
||||||
#include <tins/pdu_iterator.h>
|
#include <tins/pdu_iterator.h>
|
||||||
|
#include <tins/vxlan.h>
|
||||||
|
#include <tins/rtp.h>
|
||||||
|
|
||||||
#endif // TINS_TINS_H
|
#endif // TINS_TINS_H
|
||||||
|
|||||||
@@ -114,7 +114,11 @@ public:
|
|||||||
RadioTap::option current_option();
|
RadioTap::option current_option();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the pointer at which the current option is located
|
* \brief Gets the pointer at which the current option is located
|
||||||
|
*
|
||||||
|
* A past-the-end pointer may be returned in case of malformed input or
|
||||||
|
* end of data. Its validity must be checked (e.g. using
|
||||||
|
* \ref RadioTapParser.has_fields) before dereference.
|
||||||
*/
|
*/
|
||||||
const uint8_t* current_option_ptr() const;
|
const uint8_t* current_option_ptr() const;
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,14 @@ struct Route6Entry {
|
|||||||
template<typename ForwardIterator>
|
template<typename ForwardIterator>
|
||||||
void route_entries(ForwardIterator output);
|
void route_entries(ForwardIterator output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves entries in the routing table.
|
||||||
|
*
|
||||||
|
* \brief output ForwardIterator in which entries will be stored.
|
||||||
|
*/
|
||||||
|
template<typename ForwardIterator>
|
||||||
|
void route6_entries(ForwardIterator output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves entries in the routing table.
|
* \brief Retrieves entries in the routing table.
|
||||||
*
|
*
|
||||||
@@ -117,6 +125,7 @@ void route_entries(ForwardIterator output);
|
|||||||
*/
|
*/
|
||||||
TINS_API std::vector<RouteEntry> route_entries();
|
TINS_API std::vector<RouteEntry> route_entries();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves entries in the routing table.
|
* \brief Retrieves entries in the routing table.
|
||||||
*
|
*
|
||||||
@@ -146,6 +155,19 @@ TINS_API std::set<std::string> network_interfaces();
|
|||||||
*/
|
*/
|
||||||
TINS_API bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr);
|
TINS_API bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Finds the gateway's IP address for the given IP
|
||||||
|
* address.
|
||||||
|
*
|
||||||
|
* \param ip The IP address for which the default gateway will
|
||||||
|
* be searched.
|
||||||
|
* \param gw_addr This parameter will contain the gateway's IP
|
||||||
|
* address in case it is found.
|
||||||
|
*
|
||||||
|
* \return bool indicating whether the lookup was successfull.
|
||||||
|
*/
|
||||||
|
TINS_API bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr);
|
||||||
|
|
||||||
} // Utils
|
} // Utils
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|
||||||
@@ -158,4 +180,13 @@ void Tins::Utils::route_entries(ForwardIterator output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ForwardIterator>
|
||||||
|
void Tins::Utils::route6_entries(ForwardIterator output) {
|
||||||
|
std::vector<Route6Entry> entries = route6_entries();
|
||||||
|
for (size_t i = 0; i < entries.size(); ++i) {
|
||||||
|
*output = entries[i];
|
||||||
|
++output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // TINS_ROUTING_UTILS_H
|
#endif // TINS_ROUTING_UTILS_H
|
||||||
|
|||||||
98
include/tins/vxlan.h
Normal file
98
include/tins/vxlan.h
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
#ifndef TINS_VXLAN_H
|
||||||
|
#define TINS_VXLAN_H
|
||||||
|
|
||||||
|
#include <tins/pdu.h>
|
||||||
|
#include <tins/small_uint.h>
|
||||||
|
|
||||||
|
namespace Tins {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class VXLAN
|
||||||
|
* \brief Represents a VXLAN PDU.
|
||||||
|
*
|
||||||
|
* This class represents a VXLAN PDU.
|
||||||
|
*
|
||||||
|
* \sa RawPDU
|
||||||
|
*/
|
||||||
|
class TINS_API VXLAN : public PDU {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* \brief This PDU's flag.
|
||||||
|
*/
|
||||||
|
static const PDU::PDUType pdu_flag = PDU::VXLAN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a VXLAN PDU.
|
||||||
|
*
|
||||||
|
* \param vni VXLAN Network Identifier.
|
||||||
|
*/
|
||||||
|
VXLAN(const small_uint<24> vni = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs a VXLAN object from a buffer and adds
|
||||||
|
* the Ethernet II PDU.
|
||||||
|
*
|
||||||
|
* \param buffer The buffer from which this PDU will be constructed.
|
||||||
|
* \param total_sz The total size of the buffer.
|
||||||
|
*/
|
||||||
|
VXLAN(const uint8_t* buffer, uint32_t total_sz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the flags.
|
||||||
|
*/
|
||||||
|
uint8_t get_flags() const { return Endian::be_to_host(header_.flags) >> 24; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the VNI.
|
||||||
|
*/
|
||||||
|
small_uint<24> get_vni() const { return Endian::be_to_host(header_.vni) >> 8; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the flags.
|
||||||
|
* \param new_flags The new flags.
|
||||||
|
*/
|
||||||
|
void set_flags(uint8_t new_flags) { header_.flags = Endian::host_to_be(new_flags << 24); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Setter for the VNI.
|
||||||
|
* \param new_vni The new VNI.
|
||||||
|
*/
|
||||||
|
void set_vni(small_uint<24> new_vni) { header_.vni = Endian::host_to_be(new_vni << 8); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Returns the VXLAN frame's header length.
|
||||||
|
*
|
||||||
|
* This method overrides PDU::header_size. This size includes the
|
||||||
|
* payload and options size.
|
||||||
|
*
|
||||||
|
* \return An uint32_t with the header's size.
|
||||||
|
* \sa PDU::header_size
|
||||||
|
*/
|
||||||
|
uint32_t header_size() const { return sizeof(header_); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Getter for the PDU's type.
|
||||||
|
* \sa PDU::pdu_type
|
||||||
|
*/
|
||||||
|
PDUType pdu_type() const { return pdu_flag; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \sa PDU::clone
|
||||||
|
*/
|
||||||
|
VXLAN *clone() const { return new VXLAN(*this); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TINS_BEGIN_PACK
|
||||||
|
struct vxlan_header {
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t vni;
|
||||||
|
} TINS_END_PACK;
|
||||||
|
|
||||||
|
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||||
|
|
||||||
|
vxlan_header header_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Tins
|
||||||
|
|
||||||
|
#endif // TINS_VXLAN_H
|
||||||
@@ -8,10 +8,10 @@ IF(HAVE_PCAP_TIMESTAMP_PRECISION)
|
|||||||
ADD_DEFINITIONS("-DHAVE_PCAP_TIMESTAMP_PRECISION=1")
|
ADD_DEFINITIONS("-DHAVE_PCAP_TIMESTAMP_PRECISION=1")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
INCLUDE_DIRECTORIES(BEFORE
|
||||||
${LIBTINS_INCLUDE_DIR}
|
|
||||||
${OPENSSL_INCLUDE_DIR}
|
${OPENSSL_INCLUDE_DIR}
|
||||||
${PCAP_INCLUDE_DIR}
|
${PCAP_INCLUDE_DIR}
|
||||||
|
${LIBTINS_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
@@ -54,6 +54,7 @@ set(SOURCES
|
|||||||
radiotap.cpp
|
radiotap.cpp
|
||||||
rawpdu.cpp
|
rawpdu.cpp
|
||||||
rsn_information.cpp
|
rsn_information.cpp
|
||||||
|
rtp.cpp
|
||||||
sll.cpp
|
sll.cpp
|
||||||
snap.cpp
|
snap.cpp
|
||||||
stp.cpp
|
stp.cpp
|
||||||
@@ -73,6 +74,7 @@ set(SOURCES
|
|||||||
utils/routing_utils.cpp
|
utils/routing_utils.cpp
|
||||||
utils/resolve_utils.cpp
|
utils/resolve_utils.cpp
|
||||||
utils/pdu_utils.cpp
|
utils/pdu_utils.cpp
|
||||||
|
vxlan.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
@@ -130,6 +132,7 @@ set(HEADERS
|
|||||||
${LIBTINS_INCLUDE_DIR}/tins/radiotap.h
|
${LIBTINS_INCLUDE_DIR}/tins/radiotap.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/rawpdu.h
|
${LIBTINS_INCLUDE_DIR}/tins/rawpdu.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/rsn_information.h
|
${LIBTINS_INCLUDE_DIR}/tins/rsn_information.h
|
||||||
|
${LIBTINS_INCLUDE_DIR}/tins/rtp.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/sll.h
|
${LIBTINS_INCLUDE_DIR}/tins/sll.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/small_uint.h
|
${LIBTINS_INCLUDE_DIR}/tins/small_uint.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/snap.h
|
${LIBTINS_INCLUDE_DIR}/tins/snap.h
|
||||||
@@ -151,6 +154,7 @@ set(HEADERS
|
|||||||
${LIBTINS_INCLUDE_DIR}/tins/utils/routing_utils.h
|
${LIBTINS_INCLUDE_DIR}/tins/utils/routing_utils.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/utils/resolve_utils.h
|
${LIBTINS_INCLUDE_DIR}/tins/utils/resolve_utils.h
|
||||||
${LIBTINS_INCLUDE_DIR}/tins/utils/pdu_utils.h
|
${LIBTINS_INCLUDE_DIR}/tins/utils/pdu_utils.h
|
||||||
|
${LIBTINS_INCLUDE_DIR}/tins/vxlan.h
|
||||||
)
|
)
|
||||||
|
|
||||||
SET(DOT11_DEPENDENT_SOURCES
|
SET(DOT11_DEPENDENT_SOURCES
|
||||||
@@ -219,8 +223,9 @@ SET_TARGET_PROPERTIES(tins PROPERTIES VERSION ${LIBTINS_VERSION} SOVERSION ${LIB
|
|||||||
INSTALL(
|
INSTALL(
|
||||||
TARGETS tins
|
TARGETS tins
|
||||||
EXPORT libtinsTargets
|
EXPORT libtinsTargets
|
||||||
LIBRARY DESTINATION lib
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
ARCHIVE DESTINATION lib
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
COMPONENT dev
|
COMPONENT dev
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -705,8 +705,11 @@ WPA2Decrypter::bssids_map::const_iterator WPA2Decrypter::find_ap(const Dot11Data
|
|||||||
|
|
||||||
bool WPA2Decrypter::decrypt(PDU& pdu) {
|
bool WPA2Decrypter::decrypt(PDU& pdu) {
|
||||||
if (capturer_.process_packet(pdu)) {
|
if (capturer_.process_packet(pdu)) {
|
||||||
try_add_keys(pdu.rfind_pdu<Dot11Data>(), capturer_.handshakes().front());
|
Dot11Data* data = pdu.find_pdu<Dot11Data>();
|
||||||
capturer_.clear_handshakes();
|
if (data) {
|
||||||
|
try_add_keys(*data, capturer_.handshakes().front());
|
||||||
|
capturer_.clear_handshakes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (const Dot11Beacon* beacon = pdu.find_pdu<Dot11Beacon>()) {
|
else if (const Dot11Beacon* beacon = pdu.find_pdu<Dot11Beacon>()) {
|
||||||
if (aps_.count(beacon->addr3()) == 0) {
|
if (aps_.count(beacon->addr3()) == 0) {
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ Tins::PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size
|
|||||||
return new Tins::IEEE802_3(buffer, size);
|
return new Tins::IEEE802_3(buffer, size);
|
||||||
case Tins::PDU::PPPOE:
|
case Tins::PDU::PPPOE:
|
||||||
return new Tins::PPPoE(buffer, size);
|
return new Tins::PPPoE(buffer, size);
|
||||||
|
case Tins::PDU::RAW:
|
||||||
|
return new Tins::RawPDU(buffer, size);
|
||||||
#ifdef TINS_HAVE_DOT11
|
#ifdef TINS_HAVE_DOT11
|
||||||
case Tins::PDU::RADIOTAP:
|
case Tins::PDU::RADIOTAP:
|
||||||
return new Tins::RadioTap(buffer, size);
|
return new Tins::RadioTap(buffer, size);
|
||||||
@@ -211,6 +213,8 @@ Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag) {
|
|||||||
return Constants::Ethernet::ARP;
|
return Constants::Ethernet::ARP;
|
||||||
case PDU::DOT1Q:
|
case PDU::DOT1Q:
|
||||||
return Constants::Ethernet::VLAN;
|
return Constants::Ethernet::VLAN;
|
||||||
|
case PDU::DOT1AD:
|
||||||
|
return Constants::Ethernet::QINQ;
|
||||||
case PDU::PPPOE:
|
case PDU::PPPOE:
|
||||||
return Constants::Ethernet::PPPOED;
|
return Constants::Ethernet::PPPOED;
|
||||||
case PDU::MPLS:
|
case PDU::MPLS:
|
||||||
@@ -238,6 +242,9 @@ PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag) {
|
|||||||
return PDU::ARP;
|
return PDU::ARP;
|
||||||
case Constants::Ethernet::VLAN:
|
case Constants::Ethernet::VLAN:
|
||||||
return PDU::DOT1Q;
|
return PDU::DOT1Q;
|
||||||
|
case Constants::Ethernet::QINQ:
|
||||||
|
case Constants::Ethernet::OLD_QINQ:
|
||||||
|
return PDU::DOT1AD;
|
||||||
case Constants::Ethernet::PPPOED:
|
case Constants::Ethernet::PPPOED:
|
||||||
return PDU::PPPOE;
|
return PDU::PPPOE;
|
||||||
//case PDU::RSNEAPOL
|
//case PDU::RSNEAPOL
|
||||||
|
|||||||
32
src/dns.cpp
32
src/dns.cpp
@@ -86,14 +86,18 @@ void DNS::skip_to_dname_end(InputMemoryStream& stream) const {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((value & 0xc0)) {
|
const uint8_t offset_discriminator = value & 0xc0;
|
||||||
// This is an offset label, skip the second byte and we're done
|
if (offset_discriminator == 0xc0) {
|
||||||
|
// This is an offset pointer, skip the second byte and we're done
|
||||||
stream.skip(1);
|
stream.skip(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else if (offset_discriminator == 0) {
|
||||||
// This is an actual label, skip its contents
|
// This is an actual label, skip its contents
|
||||||
stream.skip(value);
|
stream.skip(value);
|
||||||
|
} else {
|
||||||
|
// high order two bits of the first octet of a label must be either 11 or 00
|
||||||
|
throw malformed_packet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -336,9 +340,13 @@ uint32_t DNS::compose_name(const uint8_t* ptr, char* out_ptr) const {
|
|||||||
const uint8_t* end = &records_data_[0] + records_data_.size();
|
const uint8_t* end = &records_data_[0] + records_data_.size();
|
||||||
const uint8_t* end_ptr = 0;
|
const uint8_t* end_ptr = 0;
|
||||||
char* current_out_ptr = out_ptr;
|
char* current_out_ptr = out_ptr;
|
||||||
|
uint8_t pointer_counter = 0;
|
||||||
while (*ptr) {
|
while (*ptr) {
|
||||||
|
if (pointer_counter++ > 30){
|
||||||
|
throw dns_decompression_pointer_loops();
|
||||||
|
}
|
||||||
// It's an offset
|
// It's an offset
|
||||||
if ((*ptr & 0xc0)) {
|
if (((*ptr & 0xc0) == 0xc0)) {
|
||||||
if (TINS_UNLIKELY(ptr + sizeof(uint16_t) > end)) {
|
if (TINS_UNLIKELY(ptr + sizeof(uint16_t) > end)) {
|
||||||
throw malformed_packet();
|
throw malformed_packet();
|
||||||
}
|
}
|
||||||
@@ -347,7 +355,7 @@ uint32_t DNS::compose_name(const uint8_t* ptr, char* out_ptr) const {
|
|||||||
index = Endian::be_to_host(index) & 0x3fff;
|
index = Endian::be_to_host(index) & 0x3fff;
|
||||||
// Check that the offset is neither too low or too high
|
// Check that the offset is neither too low or too high
|
||||||
if (index < 0x0c || (&records_data_[0] + (index - 0x0c)) >= end) {
|
if (index < 0x0c || (&records_data_[0] + (index - 0x0c)) >= end) {
|
||||||
throw malformed_packet();
|
throw dns_decompression_pointer_out_of_bounds();
|
||||||
}
|
}
|
||||||
// We've probably found the end of the original domain name. Save it.
|
// We've probably found the end of the original domain name. Save it.
|
||||||
if (end_ptr == 0) {
|
if (end_ptr == 0) {
|
||||||
@@ -410,10 +418,11 @@ void DNS::inline_convert_v4(uint32_t value, char* output) {
|
|||||||
// Parses records in some section.
|
// Parses records in some section.
|
||||||
void DNS::convert_records(const uint8_t* ptr,
|
void DNS::convert_records(const uint8_t* ptr,
|
||||||
const uint8_t* end,
|
const uint8_t* end,
|
||||||
resources_type& res) const {
|
resources_type& res,
|
||||||
|
const uint16_t rr_count) const {
|
||||||
InputMemoryStream stream(ptr, end - ptr);
|
InputMemoryStream stream(ptr, end - ptr);
|
||||||
char dname[256], small_addr_buf[256];
|
char dname[256], small_addr_buf[256];
|
||||||
while (stream) {
|
while (stream && (res.size() < rr_count)) {
|
||||||
string data;
|
string data;
|
||||||
bool used_small_buffer = false;
|
bool used_small_buffer = false;
|
||||||
// Retrieve the record's domain name.
|
// Retrieve the record's domain name.
|
||||||
@@ -573,7 +582,8 @@ DNS::resources_type DNS::answers() const {
|
|||||||
convert_records(
|
convert_records(
|
||||||
&records_data_[0] + answers_idx_,
|
&records_data_[0] + answers_idx_,
|
||||||
&records_data_[0] + authority_idx_,
|
&records_data_[0] + authority_idx_,
|
||||||
res
|
res,
|
||||||
|
answers_count()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@@ -585,7 +595,8 @@ DNS::resources_type DNS::authority() const {
|
|||||||
convert_records(
|
convert_records(
|
||||||
&records_data_[0] + authority_idx_,
|
&records_data_[0] + authority_idx_,
|
||||||
&records_data_[0] + additional_idx_,
|
&records_data_[0] + additional_idx_,
|
||||||
res
|
res,
|
||||||
|
authority_count()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
@@ -597,7 +608,8 @@ DNS::resources_type DNS::additional() const {
|
|||||||
convert_records(
|
convert_records(
|
||||||
&records_data_[0] + additional_idx_,
|
&records_data_[0] + additional_idx_,
|
||||||
&records_data_[0] + records_data_.size(),
|
&records_data_[0] + records_data_.size(),
|
||||||
res
|
res,
|
||||||
|
additional_count()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@@ -107,15 +107,10 @@ uint32_t Dot1Q::trailer_size() const {
|
|||||||
void Dot1Q::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
void Dot1Q::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
||||||
OutputMemoryStream stream(buffer, total_sz);
|
OutputMemoryStream stream(buffer, total_sz);
|
||||||
if (inner_pdu()) {
|
if (inner_pdu()) {
|
||||||
Constants::Ethernet::e flag;
|
Constants::Ethernet::e flag = Constants::Ethernet::UNKNOWN;
|
||||||
PDUType type = inner_pdu()->pdu_type();
|
PDUType type = inner_pdu()->pdu_type();
|
||||||
if (type == PDU::DOT1Q) {
|
// Set the appropriate payload type flag
|
||||||
flag = Constants::Ethernet::QINQ;
|
flag = Internals::pdu_flag_to_ether_type(type);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Set the appropriate payload type flag
|
|
||||||
flag = Internals::pdu_flag_to_ether_type(type);
|
|
||||||
}
|
|
||||||
if (flag != Constants::Ethernet::UNKNOWN) {
|
if (flag != Constants::Ethernet::UNKNOWN) {
|
||||||
payload_type(static_cast<uint16_t>(flag));
|
payload_type(static_cast<uint16_t>(flag));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ bool EthernetII::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
|||||||
void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
||||||
OutputMemoryStream stream(buffer, total_sz);
|
OutputMemoryStream stream(buffer, total_sz);
|
||||||
if (inner_pdu()) {
|
if (inner_pdu()) {
|
||||||
Constants::Ethernet::e flag;
|
Constants::Ethernet::e flag = Constants::Ethernet::UNKNOWN;
|
||||||
const PDUType type = inner_pdu()->pdu_type();
|
const PDUType type = inner_pdu()->pdu_type();
|
||||||
// Dirty trick to successfully tag PPPoE session/discovery packets
|
// Dirty trick to successfully tag PPPoE session/discovery packets
|
||||||
if (type == PDU::PPPOE) {
|
if (type == PDU::PPPOE) {
|
||||||
@@ -164,6 +164,17 @@ void EthernetII::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
|||||||
flag = (pppoe->code() == 0) ? Constants::Ethernet::PPPOES
|
flag = (pppoe->code() == 0) ? Constants::Ethernet::PPPOES
|
||||||
: Constants::Ethernet::PPPOED;
|
: Constants::Ethernet::PPPOED;
|
||||||
}
|
}
|
||||||
|
// Dirty trick: Double Dot1Q is interpreted as Dot1AD
|
||||||
|
else if (type == PDU::DOT1Q) {
|
||||||
|
flag = Internals::pdu_flag_to_ether_type(type);
|
||||||
|
|
||||||
|
if (inner_pdu()->inner_pdu()) {
|
||||||
|
const PDUType inner_type = inner_pdu()->inner_pdu()->pdu_type();
|
||||||
|
if (inner_type == PDU::DOT1Q) {
|
||||||
|
flag = Constants::Ethernet::QINQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
flag = Internals::pdu_flag_to_ether_type(type);
|
flag = Internals::pdu_flag_to_ether_type(type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,32 +34,35 @@
|
|||||||
#include <tins/exceptions.h>
|
#include <tins/exceptions.h>
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::ostream;
|
|
||||||
using std::hex;
|
|
||||||
using std::ostringstream;
|
|
||||||
using std::lexicographical_compare;
|
using std::lexicographical_compare;
|
||||||
using std::equal;
|
using std::equal;
|
||||||
|
|
||||||
namespace Tins {
|
namespace Tins {
|
||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
|
||||||
void storage_to_string(ostream& output, uint8_t value) {
|
|
||||||
output << hex;
|
|
||||||
if (value < 0x10) {
|
|
||||||
output << '0';
|
|
||||||
}
|
|
||||||
output << (unsigned)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
string hw_address_to_string(const uint8_t* ptr, size_t count) {
|
string hw_address_to_string(const uint8_t* ptr, size_t count) {
|
||||||
ostringstream output;
|
string output;
|
||||||
|
output.reserve(count*3);
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
output << ":";
|
output += ":";
|
||||||
}
|
}
|
||||||
storage_to_string(output, ptr[i]);
|
|
||||||
|
char j = ptr[i];
|
||||||
|
char upper = (j >> 4) & 0x0F;
|
||||||
|
if (upper > 9)
|
||||||
|
upper += 'a'-10;
|
||||||
|
else
|
||||||
|
upper += '0';
|
||||||
|
char lower = j & 0x0F;
|
||||||
|
if (lower > 9)
|
||||||
|
lower += 'a'-10;
|
||||||
|
else
|
||||||
|
lower += '0';
|
||||||
|
output += upper;
|
||||||
|
output += lower;
|
||||||
}
|
}
|
||||||
return output.str();
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_to_hw_address(const string& hw_addr, uint8_t* output, size_t output_size) {
|
void string_to_hw_address(const string& hw_addr, uint8_t* output, size_t output_size) {
|
||||||
@@ -113,5 +116,10 @@ bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
|
|||||||
return lexicographical_compare(start1, end1, start2, end2);
|
return lexicographical_compare(start1, end1, start2, end2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
|
||||||
|
const uint8_t* start2, const uint8_t* end2) {
|
||||||
|
return lexicographical_compare(start2, end2, start1, end1);
|
||||||
|
}
|
||||||
|
|
||||||
} // Internals
|
} // Internals
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ void ICMP::sequence(uint16_t new_seq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ICMP::gateway(address_type new_gw) {
|
void ICMP::gateway(address_type new_gw) {
|
||||||
header_.un.gateway = Endian::host_to_be(static_cast<uint32_t>(new_gw));
|
header_.un.gateway = static_cast<uint32_t>(new_gw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICMP::mtu(uint16_t new_mtu) {
|
void ICMP::mtu(uint16_t new_mtu) {
|
||||||
@@ -122,7 +122,7 @@ void ICMP::transmit_timestamp(uint32_t new_timestamp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ICMP::address_mask(address_type new_mask) {
|
void ICMP::address_mask(address_type new_mask) {
|
||||||
orig_timestamp_or_address_mask_ = Endian::host_to_be(static_cast<uint32_t>(new_mask));
|
orig_timestamp_or_address_mask_ = static_cast<uint32_t>(new_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ICMP::header_size() const {
|
uint32_t ICMP::header_size() const {
|
||||||
|
|||||||
@@ -321,7 +321,12 @@ void IP::add_option(const option& opt) {
|
|||||||
uint32_t IP::calculate_options_size() const {
|
uint32_t IP::calculate_options_size() const {
|
||||||
uint32_t options_size = 0;
|
uint32_t options_size = 0;
|
||||||
for (options_type::const_iterator iter = options_.begin(); iter != options_.end(); ++iter) {
|
for (options_type::const_iterator iter = options_.begin(); iter != options_.end(); ++iter) {
|
||||||
options_size += 1 + iter->data_size();
|
options_size += sizeof(uint8_t);
|
||||||
|
const option_identifier option_id = iter->option();
|
||||||
|
// Only add length field and data size for non [NOOP, EOL] options
|
||||||
|
if (option_id.op_class != CONTROL || option_id.number > NOOP) {
|
||||||
|
options_size += sizeof(uint8_t) + iter->data_size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return options_size;
|
return options_size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const AddressRange<IPv4Address> loopback_range = IPv4Address("127.0.0.0") / 8;
|
|||||||
const AddressRange<IPv4Address> multicast_range = IPv4Address("224.0.0.0") / 4;
|
const AddressRange<IPv4Address> multicast_range = IPv4Address("224.0.0.0") / 4;
|
||||||
|
|
||||||
IPv4Address IPv4Address::from_prefix_length(uint32_t prefix_length) {
|
IPv4Address IPv4Address::from_prefix_length(uint32_t prefix_length) {
|
||||||
return IPv4Address(Endian::host_to_be(0xffffffff << (32 - prefix_length)));
|
return IPv4Address(prefix_length ? Endian::host_to_be(0xffffffff << (32 - prefix_length)) : 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPv4Address::IPv4Address(uint32_t ip)
|
IPv4Address::IPv4Address(uint32_t ip)
|
||||||
@@ -153,4 +153,12 @@ IPv4Address IPv4Address::operator&(const IPv4Address& mask) const {
|
|||||||
return IPv4Address(Endian::be_to_host(ip_addr_ & mask.ip_addr_));
|
return IPv4Address(Endian::be_to_host(ip_addr_ & mask.ip_addr_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPv4Address IPv4Address::operator|(const IPv4Address& mask) const {
|
||||||
|
return IPv4Address(Endian::be_to_host(ip_addr_ | mask.ip_addr_));
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv4Address IPv4Address::operator~() const {
|
||||||
|
return IPv4Address(Endian::be_to_host(~ip_addr_));
|
||||||
|
}
|
||||||
|
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|||||||
112
src/ipv6.cpp
112
src/ipv6.cpp
@@ -32,6 +32,9 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#else
|
#else
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#endif
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#endif
|
#endif
|
||||||
#include <tins/ipv6.h>
|
#include <tins/ipv6.h>
|
||||||
@@ -43,6 +46,7 @@
|
|||||||
#include <tins/memory_helpers.h>
|
#include <tins/memory_helpers.h>
|
||||||
#include <tins/detail/pdu_helpers.h>
|
#include <tins/detail/pdu_helpers.h>
|
||||||
|
|
||||||
|
using std::make_pair;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
using Tins::Memory::InputMemoryStream;
|
using Tins::Memory::InputMemoryStream;
|
||||||
@@ -69,6 +73,49 @@ PDU::metadata IPv6::extract_metadata(const uint8_t *buffer, uint32_t total_sz) {
|
|||||||
return metadata(header_size, pdu_flag, PDU::UNKNOWN);
|
return metadata(header_size, pdu_flag, PDU::UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPv6::hop_by_hop_header IPv6::hop_by_hop_header::from_extension_header(const ext_header& hdr) {
|
||||||
|
if (TINS_UNLIKELY(hdr.option() != HOP_BY_HOP)) {
|
||||||
|
throw invalid_ipv6_extension_header();
|
||||||
|
}
|
||||||
|
hop_by_hop_header header;
|
||||||
|
header.options = parse_header_options(hdr.data_ptr(), hdr.data_size());
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6::destination_routing_header IPv6::destination_routing_header::from_extension_header(const ext_header& hdr) {
|
||||||
|
if (TINS_UNLIKELY(hdr.option() != DESTINATION_ROUTING_OPTIONS)) {
|
||||||
|
throw invalid_ipv6_extension_header();
|
||||||
|
}
|
||||||
|
destination_routing_header header;
|
||||||
|
header.options = parse_header_options(hdr.data_ptr(), hdr.data_size());
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6::routing_header IPv6::routing_header::from_extension_header(const ext_header& hdr) {
|
||||||
|
if (TINS_UNLIKELY(hdr.option() != ROUTING)) {
|
||||||
|
throw invalid_ipv6_extension_header();
|
||||||
|
}
|
||||||
|
Memory::InputMemoryStream stream(hdr.data_ptr(), hdr.data_size());
|
||||||
|
routing_header header;
|
||||||
|
header.routing_type = stream.read<uint8_t>();
|
||||||
|
header.segments_left = stream.read<uint8_t>();
|
||||||
|
header.data.assign(stream.pointer(), stream.pointer() + stream.size());
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6::fragment_header IPv6::fragment_header::from_extension_header(const ext_header& hdr) {
|
||||||
|
if (TINS_UNLIKELY(hdr.option() != FRAGMENT)) {
|
||||||
|
throw invalid_ipv6_extension_header();
|
||||||
|
}
|
||||||
|
Memory::InputMemoryStream stream(hdr.data_ptr(), hdr.data_size());
|
||||||
|
fragment_header header;
|
||||||
|
uint16_t field = stream.read_be<uint16_t>();
|
||||||
|
header.fragment_offset = field >> 3;
|
||||||
|
header.more_fragments = field & 1;
|
||||||
|
header.identification = stream.read_be<uint32_t>();
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU* /*child*/)
|
IPv6::IPv6(address_type ip_dst, address_type ip_src, PDU* /*child*/)
|
||||||
: header_(), next_header_() {
|
: header_(), next_header_() {
|
||||||
version(6);
|
version(6);
|
||||||
@@ -83,7 +130,7 @@ IPv6::IPv6(const uint8_t* buffer, uint32_t total_sz) {
|
|||||||
uint32_t actual_payload_length = payload_length();
|
uint32_t actual_payload_length = payload_length();
|
||||||
bool is_payload_fragmented = false;
|
bool is_payload_fragmented = false;
|
||||||
while (stream) {
|
while (stream) {
|
||||||
if (is_extension_header(current_header)) {
|
if (is_extension_header(current_header) && current_header != NO_NEXT_HEADER) {
|
||||||
if (current_header == FRAGMENT) {
|
if (current_header == FRAGMENT) {
|
||||||
is_payload_fragmented = true;
|
is_payload_fragmented = true;
|
||||||
}
|
}
|
||||||
@@ -160,8 +207,40 @@ IPv6::IPv6(const uint8_t* buffer, uint32_t total_sz) {
|
|||||||
bool IPv6::is_extension_header(uint8_t header_id) {
|
bool IPv6::is_extension_header(uint8_t header_id) {
|
||||||
return header_id == HOP_BY_HOP || header_id == DESTINATION_ROUTING_OPTIONS
|
return header_id == HOP_BY_HOP || header_id == DESTINATION_ROUTING_OPTIONS
|
||||||
|| header_id == ROUTING || header_id == FRAGMENT || header_id == AUTHENTICATION
|
|| header_id == ROUTING || header_id == FRAGMENT || header_id == AUTHENTICATION
|
||||||
|| header_id == SECURITY_ENCAPSULATION || header_id == DESTINATION_OPTIONS
|
|| header_id == DESTINATION_OPTIONS || header_id == MOBILITY
|
||||||
|| header_id == MOBILITY || header_id == NO_NEXT_HEADER;
|
|| header_id == NO_NEXT_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t IPv6::get_padding_size(const ext_header& header) {
|
||||||
|
const uint32_t padding = (header.data_size() + sizeof(uint8_t) * 2) % 8;
|
||||||
|
return padding == 0 ? 0 : (8 - padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<IPv6::header_option_type> IPv6::parse_header_options(const uint8_t* data, size_t size) {
|
||||||
|
Memory::InputMemoryStream stream(data, size);
|
||||||
|
vector<header_option_type> options;
|
||||||
|
|
||||||
|
while (stream.size() > 0) {
|
||||||
|
try {
|
||||||
|
uint8_t option = stream.read<uint8_t>();
|
||||||
|
if (option == PAD_1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint8_t size = stream.read<uint8_t>();
|
||||||
|
if (size > stream.size()) {
|
||||||
|
throw invalid_ipv6_extension_header();
|
||||||
|
}
|
||||||
|
if (option != PAD_N) {
|
||||||
|
options.push_back(make_pair(option, vector<uint8_t>(stream.pointer(),
|
||||||
|
stream.pointer() +
|
||||||
|
size)));
|
||||||
|
}
|
||||||
|
stream.skip(size);
|
||||||
|
} catch (const malformed_packet&) {
|
||||||
|
throw invalid_ipv6_extension_header();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPv6::version(small_uint<4> new_version) {
|
void IPv6::version(small_uint<4> new_version) {
|
||||||
@@ -290,18 +369,27 @@ void IPv6::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BSD
|
#ifndef BSD
|
||||||
void IPv6::send(PacketSender& sender, const NetworkInterface &) {
|
void IPv6::send(PacketSender& sender, const NetworkInterface& interface) {
|
||||||
struct sockaddr_in6 link_addr;
|
sockaddr_in6 link_addr;
|
||||||
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
|
const PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
|
||||||
link_addr.sin6_family = AF_INET6;
|
link_addr.sin6_family = AF_INET6;
|
||||||
link_addr.sin6_port = 0;
|
link_addr.sin6_port = 0;
|
||||||
memcpy((uint8_t*)&link_addr.sin6_addr, header_.dst_addr, address_type::address_size);
|
// Required to set sin6_scope_id to interface index as stated in RFC2553.
|
||||||
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMP) {
|
// https://datatracker.ietf.org/doc/html/rfc2553#section-3.3
|
||||||
type = PacketSender::ICMP_SOCKET;
|
if (IPv6Address(header_.dst_addr).is_local_unicast()) {
|
||||||
|
link_addr.sin6_scope_id = interface.id();
|
||||||
}
|
}
|
||||||
|
memcpy((uint8_t*)&link_addr.sin6_addr, header_.dst_addr, address_type::address_size);
|
||||||
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
|
sender.send_l3(*this, (struct sockaddr*)&link_addr, sizeof(link_addr), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDU* IPv6::recv_response(PacketSender& sender, const NetworkInterface &) {
|
||||||
|
PacketSender::SocketType type = PacketSender::IPV6_SOCKET;
|
||||||
|
if (inner_pdu() && inner_pdu()->pdu_type() == PDU::ICMPv6) {
|
||||||
|
type = PacketSender::ICMPV6_SOCKET;
|
||||||
|
}
|
||||||
|
return sender.recv_l3(*this, 0, sizeof(sockaddr_in6), type);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void IPv6::add_ext_header(const ext_header& header) {
|
void IPv6::add_ext_header(const ext_header& header) {
|
||||||
@@ -337,6 +425,8 @@ uint32_t IPv6::calculate_headers_size() const {
|
|||||||
uint32_t output = 0;
|
uint32_t output = 0;
|
||||||
for (const_iterator iter = ext_headers_.begin(); iter != ext_headers_.end(); ++iter) {
|
for (const_iterator iter = ext_headers_.begin(); iter != ext_headers_.end(); ++iter) {
|
||||||
output += static_cast<uint32_t>(iter->data_size() + sizeof(uint8_t) * 2);
|
output += static_cast<uint32_t>(iter->data_size() + sizeof(uint8_t) * 2);
|
||||||
|
output += get_padding_size(*iter);
|
||||||
|
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -346,6 +436,8 @@ void IPv6::write_header(const ext_header& header, OutputMemoryStream& stream) {
|
|||||||
stream.write(header.option());
|
stream.write(header.option());
|
||||||
stream.write(length);
|
stream.write(length);
|
||||||
stream.write(header.data_ptr(), header.data_size());
|
stream.write(header.data_ptr(), header.data_size());
|
||||||
|
// Append padding
|
||||||
|
stream.fill(get_padding_size(header), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace Tins {
|
|||||||
|
|
||||||
const IPv6Address loopback_address = "::1";
|
const IPv6Address loopback_address = "::1";
|
||||||
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
|
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
|
||||||
|
const AddressRange<IPv6Address> local_unicast_range = IPv6Address("fe80::") / 10;
|
||||||
|
|
||||||
IPv6Address IPv6Address::from_prefix_length(uint32_t prefix_length) {
|
IPv6Address IPv6Address::from_prefix_length(uint32_t prefix_length) {
|
||||||
IPv6Address address;
|
IPv6Address address;
|
||||||
@@ -138,17 +139,41 @@ bool IPv6Address::is_multicast() const {
|
|||||||
return multicast_range.contains(*this);
|
return multicast_range.contains(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IPv6Address::is_local_unicast() const {
|
||||||
|
return local_unicast_range.contains(*this);
|
||||||
|
}
|
||||||
|
|
||||||
ostream& operator<<(ostream& os, const IPv6Address& addr) {
|
ostream& operator<<(ostream& os, const IPv6Address& addr) {
|
||||||
return os << addr.to_string();
|
return os << addr.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs) {
|
IPv6Address IPv6Address::operator&(const IPv6Address& rhs) const {
|
||||||
IPv6Address output = lhs;
|
IPv6Address result = *this;
|
||||||
IPv6Address::iterator addr_iter = output.begin();
|
IPv6Address::iterator addr_iter = result.begin();
|
||||||
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
|
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
|
||||||
*addr_iter = *addr_iter & *it;
|
*addr_iter = *addr_iter & *it;
|
||||||
}
|
}
|
||||||
return output;
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6Address IPv6Address::operator|(const IPv6Address& rhs) const {
|
||||||
|
IPv6Address result = *this;
|
||||||
|
IPv6Address::iterator addr_iter = result.begin();
|
||||||
|
for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) {
|
||||||
|
*addr_iter = *addr_iter | *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPv6Address IPv6Address::operator~() const {
|
||||||
|
IPv6Address result = *this;
|
||||||
|
for (IPv6Address::iterator addr_iter = result.begin(); addr_iter != result.end(); ++addr_iter) {
|
||||||
|
*addr_iter = ~*addr_iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|||||||
@@ -257,6 +257,35 @@ NetworkInterface::NetworkInterface(IPv4Address ip)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkInterface::NetworkInterface(IPv6Address ipv6)
|
||||||
|
: iface_id_(0) {
|
||||||
|
typedef vector<Utils::Route6Entry> entries_type;
|
||||||
|
|
||||||
|
if (ipv6 == "::1") {
|
||||||
|
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||||
|
iface_id_ = resolve_index("lo0");
|
||||||
|
#else
|
||||||
|
iface_id_ = resolve_index("lo");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const Utils::Route6Entry* best_match = 0;
|
||||||
|
entries_type entries;
|
||||||
|
Utils::route6_entries(std::back_inserter(entries));
|
||||||
|
for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
|
||||||
|
if ((ipv6 & it->mask) == it->destination) {
|
||||||
|
if (!best_match || it->mask > best_match->mask || it->metric < best_match->metric) {
|
||||||
|
best_match = &*it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!best_match) {
|
||||||
|
throw invalid_interface();
|
||||||
|
}
|
||||||
|
iface_id_ = resolve_index(best_match->interface.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string NetworkInterface::name() const {
|
string NetworkInterface::name() const {
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
char iface_name[IF_NAMESIZE];
|
char iface_name[IF_NAMESIZE];
|
||||||
@@ -302,7 +331,7 @@ NetworkInterface::Info NetworkInterface::info() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#else // _WIN32
|
#else // _WIN32
|
||||||
|
#if !defined(ANDROID) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 24)
|
||||||
struct ifaddrs* ifaddrs = 0;
|
struct ifaddrs* ifaddrs = 0;
|
||||||
struct ifaddrs* if_it = 0;
|
struct ifaddrs* if_it = 0;
|
||||||
getifaddrs(&ifaddrs);
|
getifaddrs(&ifaddrs);
|
||||||
@@ -312,7 +341,9 @@ NetworkInterface::Info NetworkInterface::info() const {
|
|||||||
if (ifaddrs) {
|
if (ifaddrs) {
|
||||||
freeifaddrs(ifaddrs);
|
freeifaddrs(ifaddrs);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
throw new std::runtime_error("android ifaddr not supported");
|
||||||
|
#endif
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
// If we didn't even get the hw address or ip address, this went wrong
|
// If we didn't even get the hw address or ip address, this went wrong
|
||||||
|
|||||||
@@ -37,11 +37,14 @@ using std::string;
|
|||||||
namespace Tins {
|
namespace Tins {
|
||||||
|
|
||||||
OfflinePacketFilter::OfflinePacketFilter(const OfflinePacketFilter& other) {
|
OfflinePacketFilter::OfflinePacketFilter(const OfflinePacketFilter& other) {
|
||||||
*this = other;
|
string_filter_ = other.string_filter_;
|
||||||
|
init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
|
||||||
}
|
}
|
||||||
|
|
||||||
OfflinePacketFilter& OfflinePacketFilter::operator=(const OfflinePacketFilter& other) {
|
OfflinePacketFilter& OfflinePacketFilter::operator=(const OfflinePacketFilter& other) {
|
||||||
string_filter_ = other.string_filter_;
|
string_filter_ = other.string_filter_;
|
||||||
|
pcap_freecode(&filter_);
|
||||||
|
pcap_close(handle_);
|
||||||
init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
|
init(string_filter_, pcap_datalink(other.handle_), pcap_snapshot(other.handle_));
|
||||||
return* this;
|
return* this;
|
||||||
}
|
}
|
||||||
@@ -58,8 +61,14 @@ void OfflinePacketFilter::init(const string& pcap_filter,
|
|||||||
link_type,
|
link_type,
|
||||||
snap_len
|
snap_len
|
||||||
);
|
);
|
||||||
|
if (!handle_) {
|
||||||
|
throw pcap_open_failed();
|
||||||
|
}
|
||||||
if (pcap_compile(handle_, &filter_, pcap_filter.c_str(), 1, 0xffffffff) == -1) {
|
if (pcap_compile(handle_, &filter_, pcap_filter.c_str(), 1, 0xffffffff) == -1) {
|
||||||
throw invalid_pcap_filter(pcap_geterr(handle_));
|
string error(pcap_geterr(handle_));
|
||||||
|
pcap_freecode(&filter_);
|
||||||
|
pcap_close(handle_);
|
||||||
|
throw invalid_pcap_filter(error.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ PacketSender::PacketSender(const NetworkInterface& iface,
|
|||||||
types_[IP_RAW_SOCKET] = IPPROTO_RAW;
|
types_[IP_RAW_SOCKET] = IPPROTO_RAW;
|
||||||
types_[IPV6_SOCKET] = IPPROTO_RAW;
|
types_[IPV6_SOCKET] = IPPROTO_RAW;
|
||||||
types_[ICMP_SOCKET] = IPPROTO_ICMP;
|
types_[ICMP_SOCKET] = IPPROTO_ICMP;
|
||||||
|
types_[ICMPV6_SOCKET] = IPPROTO_ICMPV6;
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketSender::~PacketSender() {
|
PacketSender::~PacketSender() {
|
||||||
@@ -251,8 +252,9 @@ void PacketSender::open_l3_socket(SocketType type) {
|
|||||||
throw invalid_socket_type();
|
throw invalid_socket_type();
|
||||||
}
|
}
|
||||||
if (sockets_[type] == INVALID_RAW_SOCKET) {
|
if (sockets_[type] == INVALID_RAW_SOCKET) {
|
||||||
|
const bool is_v6 = (type == IPV6_SOCKET || type == ICMPV6_SOCKET);
|
||||||
socket_type sockfd;
|
socket_type sockfd;
|
||||||
sockfd = socket((type == IPV6_SOCKET) ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
|
sockfd = socket(is_v6 ? AF_INET6 : AF_INET, SOCK_RAW, socktype);
|
||||||
if (sockfd < 0) {
|
if (sockfd < 0) {
|
||||||
throw socket_open_error(make_error_string());
|
throw socket_open_error(make_error_string());
|
||||||
}
|
}
|
||||||
@@ -263,8 +265,13 @@ void PacketSender::open_l3_socket(SocketType type) {
|
|||||||
#else
|
#else
|
||||||
typedef const char* option_ptr;
|
typedef const char* option_ptr;
|
||||||
#endif
|
#endif
|
||||||
const int level = (type == IPV6_SOCKET) ? IPPROTO_IPV6 : IPPROTO_IP;
|
const int level = (is_v6) ? IPPROTO_IPV6 : IPPROTO_IP;
|
||||||
if (setsockopt(sockfd, level, IP_HDRINCL, (option_ptr)&on, sizeof(on)) != 0) {
|
if (setsockopt(sockfd, level, IP_HDRINCL, (option_ptr)&on, sizeof(on)) != 0) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
::close(sockfd);
|
||||||
|
#else
|
||||||
|
::closesocket(sockfd);
|
||||||
|
#endif
|
||||||
throw socket_open_error(make_error_string());
|
throw socket_open_error(make_error_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,12 +70,12 @@ void PacketWriter::write(Packet& packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PacketWriter::write(PDU& pdu, const struct timeval& tv) {
|
void PacketWriter::write(PDU& pdu, const struct timeval& tv) {
|
||||||
PDU::serialization_type buffer = pdu.serialize();
|
|
||||||
struct pcap_pkthdr header;
|
struct pcap_pkthdr header;
|
||||||
memset(&header, 0, sizeof(header));
|
memset(&header, 0, sizeof(header));
|
||||||
header.ts = tv;
|
header.ts = tv;
|
||||||
|
header.len = static_cast<bpf_u_int32>(pdu.advertised_size());
|
||||||
|
PDU::serialization_type buffer = pdu.serialize();
|
||||||
header.caplen = static_cast<bpf_u_int32>(buffer.size());
|
header.caplen = static_cast<bpf_u_int32>(buffer.size());
|
||||||
header.len = static_cast<bpf_u_int32>(buffer.size());
|
|
||||||
pcap_dump((u_char*)dumper_, &header, &buffer[0]);
|
pcap_dump((u_char*)dumper_, &header, &buffer[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,8 +86,9 @@ void PacketWriter::init(const string& file_name, int link_type) {
|
|||||||
}
|
}
|
||||||
dumper_ = pcap_dump_open(handle_, file_name.c_str());
|
dumper_ = pcap_dump_open(handle_, file_name.c_str());
|
||||||
if (!dumper_) {
|
if (!dumper_) {
|
||||||
|
string error(pcap_geterr(handle_));
|
||||||
pcap_close(handle_);
|
pcap_close(handle_);
|
||||||
throw pcap_error(pcap_geterr(handle_));
|
throw pcap_error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,14 @@ uint32_t PDU::size() const {
|
|||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t PDU::advertised_size() const {
|
||||||
|
uint32_t result = header_size() + trailer_size();
|
||||||
|
if (inner_pdu_) {
|
||||||
|
result += inner_pdu()->advertised_size();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void PDU::send(PacketSender &, const NetworkInterface &) {
|
void PDU::send(PacketSender &, const NetworkInterface &) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
195
src/rtp.cpp
Normal file
195
src/rtp.cpp
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <tins/exceptions.h>
|
||||||
|
#include <tins/internals.h>
|
||||||
|
#include <tins/memory_helpers.h>
|
||||||
|
#include <tins/rtp.h>
|
||||||
|
|
||||||
|
using std::logic_error;
|
||||||
|
using Tins::Memory::InputMemoryStream;
|
||||||
|
using Tins::Memory::OutputMemoryStream;
|
||||||
|
|
||||||
|
namespace Tins {
|
||||||
|
|
||||||
|
RTP::RTP()
|
||||||
|
: header_(), ext_header_(), padding_size_(0) {
|
||||||
|
version(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTP::RTP(const uint8_t* buffer, uint32_t total_sz) {
|
||||||
|
InputMemoryStream stream(buffer, total_sz);
|
||||||
|
stream.read(header_);
|
||||||
|
|
||||||
|
small_uint<4> csrc_count_ = csrc_count();
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < csrc_count_; ++i) {
|
||||||
|
uint32_t csrc_id;
|
||||||
|
stream.read(csrc_id);
|
||||||
|
csrc_ids_.push_back(csrc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_bit() == 1) {
|
||||||
|
stream.read(ext_header_);
|
||||||
|
for (uint32_t i = 0; i < extension_length(); ++i) {
|
||||||
|
uint32_t data;
|
||||||
|
stream.read(data);
|
||||||
|
ext_data_.push_back(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
padding_size_ = 0;
|
||||||
|
|
||||||
|
const uint8_t* data_ptr = stream.pointer();
|
||||||
|
const size_t data_size = stream.size();
|
||||||
|
|
||||||
|
if (padding_bit() == 1) {
|
||||||
|
if (data_size > 0) {
|
||||||
|
stream.skip(data_size - sizeof(uint8_t));
|
||||||
|
stream.read(padding_size_);
|
||||||
|
} else {
|
||||||
|
throw malformed_packet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding_size() == 0) {
|
||||||
|
throw malformed_packet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding_size() > data_size) {
|
||||||
|
throw malformed_packet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_size > padding_size()) {
|
||||||
|
inner_pdu(
|
||||||
|
Internals::pdu_from_flag(
|
||||||
|
PDU::RAW,
|
||||||
|
data_ptr,
|
||||||
|
data_size - padding_size()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t RTP::header_size() const {
|
||||||
|
uint32_t extension_size = 0;
|
||||||
|
if (extension_bit() == 1) {
|
||||||
|
extension_size = sizeof(ext_header_) + (extension_length() * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
return static_cast<uint32_t>(sizeof(header_) + (csrc_ids_.size() * sizeof(uint32_t)) + extension_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTP::add_csrc_id(const uint32_t csrc_id) {
|
||||||
|
small_uint<4> csrc_count_ = csrc_count();
|
||||||
|
if (TINS_UNLIKELY(csrc_count_ >= 15)) {
|
||||||
|
throw logic_error("Maximum number of CSRC IDs reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
csrc_ids_.push_back(Endian::host_to_be(csrc_id));
|
||||||
|
csrc_count(csrc_count_ + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTP::remove_csrc_id(const uint32_t csrc_id) {
|
||||||
|
small_uint<4> csrc_count_ = csrc_count();
|
||||||
|
if (csrc_count_ == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
csrc_ids_type::iterator iter = search_csrc_id_iterator(Endian::host_to_be(csrc_id));
|
||||||
|
if (iter == csrc_ids_.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
csrc_ids_.erase(iter);
|
||||||
|
csrc_count(csrc_count_ - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTP::search_csrc_id(const uint32_t csrc_id) {
|
||||||
|
csrc_ids_type::const_iterator iter = search_csrc_id_iterator(Endian::host_to_be(csrc_id));
|
||||||
|
return (iter != csrc_ids_.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
RTP::csrc_ids_type::const_iterator RTP::search_csrc_id_iterator(const uint32_t csrc_id) const {
|
||||||
|
return std::find(csrc_ids_.cbegin(), csrc_ids_.cend(), csrc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTP::csrc_ids_type::iterator RTP::search_csrc_id_iterator(const uint32_t csrc_id) {
|
||||||
|
return std::find(csrc_ids_.begin(), csrc_ids_.end(), csrc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTP::add_extension_data(const uint32_t value) {
|
||||||
|
if (TINS_UNLIKELY(extension_length() >= 65535)) {
|
||||||
|
throw logic_error("Maximum number of extension data reached");
|
||||||
|
}
|
||||||
|
|
||||||
|
extension_bit(1);
|
||||||
|
ext_data_.push_back(Endian::host_to_be(value));
|
||||||
|
extension_length(extension_length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTP::remove_extension_data(const uint32_t value) {
|
||||||
|
if (extension_bit() == 0 || extension_length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension_header_data_type::iterator iter = search_extension_data_iterator(Endian::host_to_be(value));
|
||||||
|
if (iter == ext_data_.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ext_data_.erase(iter);
|
||||||
|
|
||||||
|
extension_length(extension_length() - 1);
|
||||||
|
|
||||||
|
if (extension_length() == 0) {
|
||||||
|
extension_bit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTP::search_extension_data(const uint32_t value) {
|
||||||
|
if (extension_bit() == 0 || extension_length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension_header_data_type::const_iterator iter = search_extension_data_iterator(Endian::host_to_be(value));
|
||||||
|
return (iter != ext_data_.cend());
|
||||||
|
}
|
||||||
|
|
||||||
|
RTP::extension_header_data_type::const_iterator RTP::search_extension_data_iterator(const uint32_t data) const {
|
||||||
|
return std::find(ext_data_.cbegin(), ext_data_.cend(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
RTP::extension_header_data_type::iterator RTP::search_extension_data_iterator(const uint32_t data) {
|
||||||
|
return std::find(ext_data_.begin(), ext_data_.end(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTP::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
||||||
|
OutputMemoryStream stream(buffer, total_sz);
|
||||||
|
stream.write(header_);
|
||||||
|
|
||||||
|
for (auto csrc_id : csrc_ids_) {
|
||||||
|
stream.write(csrc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_bit() == 1) {
|
||||||
|
stream.write(ext_header_);
|
||||||
|
for (auto data : ext_data_) {
|
||||||
|
stream.write(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (padding_bit() == 1) {
|
||||||
|
if (padding_size() > 0) {
|
||||||
|
if (inner_pdu()) {
|
||||||
|
stream.skip(inner_pdu()->size());
|
||||||
|
}
|
||||||
|
stream.fill(padding_size() - 1, 0);
|
||||||
|
stream.write(padding_size());
|
||||||
|
} else {
|
||||||
|
throw pdu_not_serializable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Tins
|
||||||
@@ -224,7 +224,7 @@ void BaseSniffer::set_extract_raw_pdus(bool value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BaseSniffer::set_pcap_sniffing_method(PcapSniffingMethod method) {
|
void BaseSniffer::set_pcap_sniffing_method(PcapSniffingMethod method) {
|
||||||
if (method == nullptr) {
|
if (method == 0) {
|
||||||
throw std::runtime_error("Sniffing method cannot be null");
|
throw std::runtime_error("Sniffing method cannot be null");
|
||||||
}
|
}
|
||||||
pcap_sniffing_method_ = method;
|
pcap_sniffing_method_ = method;
|
||||||
@@ -391,6 +391,20 @@ void Sniffer::set_rfmon(bool rfmon_enabled) {
|
|||||||
|
|
||||||
// **************************** FileSniffer ****************************
|
// **************************** FileSniffer ****************************
|
||||||
|
|
||||||
|
FileSniffer::FileSniffer(FILE *fp,
|
||||||
|
const SnifferConfiguration& configuration) {
|
||||||
|
char error[PCAP_ERRBUF_SIZE];
|
||||||
|
pcap_t* phandle = pcap_fopen_offline(fp, error);
|
||||||
|
if (!phandle) {
|
||||||
|
throw pcap_error(error);
|
||||||
|
}
|
||||||
|
set_pcap_handle(phandle);
|
||||||
|
|
||||||
|
// Configure the sniffer
|
||||||
|
configuration.configure_sniffer_pre_activation(*this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
FileSniffer::FileSniffer(const string& file_name,
|
FileSniffer::FileSniffer(const string& file_name,
|
||||||
const SnifferConfiguration& configuration) {
|
const SnifferConfiguration& configuration) {
|
||||||
char error[PCAP_ERRBUF_SIZE];
|
char error[PCAP_ERRBUF_SIZE];
|
||||||
@@ -420,6 +434,22 @@ FileSniffer::FileSniffer(const string& file_name, const string& filter) {
|
|||||||
config.configure_sniffer_pre_activation(*this);
|
config.configure_sniffer_pre_activation(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileSniffer::FileSniffer(FILE *fp, const string& filter) {
|
||||||
|
SnifferConfiguration config;
|
||||||
|
config.set_filter(filter);
|
||||||
|
|
||||||
|
char error[PCAP_ERRBUF_SIZE];
|
||||||
|
pcap_t* phandle = pcap_fopen_offline(fp, error);
|
||||||
|
if (!phandle) {
|
||||||
|
throw pcap_error(error);
|
||||||
|
}
|
||||||
|
set_pcap_handle(phandle);
|
||||||
|
|
||||||
|
// Configure the sniffer
|
||||||
|
config.configure_sniffer_pre_activation(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************ SnifferConfiguration ************************
|
// ************************ SnifferConfiguration ************************
|
||||||
|
|
||||||
const unsigned SnifferConfiguration::DEFAULT_SNAP_LEN = 65535;
|
const unsigned SnifferConfiguration::DEFAULT_SNAP_LEN = 65535;
|
||||||
|
|||||||
12
src/tcp.cpp
12
src/tcp.cpp
@@ -81,7 +81,11 @@ TCP::TCP(const uint8_t* buffer, uint32_t total_sz) {
|
|||||||
|
|
||||||
while (stream.pointer() < header_end) {
|
while (stream.pointer() < header_end) {
|
||||||
const OptionTypes option_type = (OptionTypes)stream.read<uint8_t>();
|
const OptionTypes option_type = (OptionTypes)stream.read<uint8_t>();
|
||||||
if (option_type <= NOP) {
|
if (option_type == EOL) {
|
||||||
|
stream.skip(header_end - stream.pointer());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (option_type == NOP) {
|
||||||
#if TINS_IS_CXX11
|
#if TINS_IS_CXX11
|
||||||
add_option(option_type, 0);
|
add_option(option_type, 0);
|
||||||
#else
|
#else
|
||||||
@@ -253,6 +257,10 @@ small_uint<12> TCP::flags() const {
|
|||||||
return (header_.res1 << 8) | header_.flags_8;
|
return (header_.res1 << 8) | header_.flags_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TCP::has_flags(small_uint<12> check_flags) const {
|
||||||
|
return (flags() & check_flags) == check_flags;
|
||||||
|
}
|
||||||
|
|
||||||
void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
|
void TCP::set_flag(Flags tcp_flag, small_uint<1> value) {
|
||||||
switch (tcp_flag) {
|
switch (tcp_flag) {
|
||||||
case FIN:
|
case FIN:
|
||||||
@@ -309,7 +317,7 @@ void TCP::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
|||||||
|
|
||||||
if (options_size < total_options_size) {
|
if (options_size < total_options_size) {
|
||||||
const uint16_t padding = total_options_size - options_size;
|
const uint16_t padding = total_options_size - options_size;
|
||||||
stream.fill(padding, 1);
|
stream.fill(padding, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t check = 0;
|
uint32_t check = 0;
|
||||||
|
|||||||
@@ -33,8 +33,6 @@
|
|||||||
|
|
||||||
#include <tins/detail/sequence_number_helpers.h>
|
#include <tins/detail/sequence_number_helpers.h>
|
||||||
|
|
||||||
using std::move;
|
|
||||||
|
|
||||||
using Tins::Internals::seq_compare;
|
using Tins::Internals::seq_compare;
|
||||||
|
|
||||||
namespace Tins {
|
namespace Tins {
|
||||||
@@ -67,7 +65,7 @@ bool DataTracker::process_payload(uint32_t seq, payload_type payload) {
|
|||||||
}
|
}
|
||||||
bool added_some = false;
|
bool added_some = false;
|
||||||
// Store this payload
|
// Store this payload
|
||||||
store_payload(seq, move(payload));
|
store_payload(seq, std::move(payload));
|
||||||
// Keep looping while the fragments seq is lower or equal to our seq
|
// Keep looping while the fragments seq is lower or equal to our seq
|
||||||
buffered_payload_type::iterator iter = buffered_payload_.find(seq_number_);
|
buffered_payload_type::iterator iter = buffered_payload_.find(seq_number_);
|
||||||
while (iter != buffered_payload_.end() && seq_compare(iter->first, seq_number_) <= 0) {
|
while (iter != buffered_payload_.end() && seq_compare(iter->first, seq_number_) <= 0) {
|
||||||
@@ -85,7 +83,7 @@ bool DataTracker::process_payload(uint32_t seq, payload_type payload) {
|
|||||||
payload.begin(),
|
payload.begin(),
|
||||||
payload.begin() + (seq_number_ - iter->first)
|
payload.begin() + (seq_number_ - iter->first)
|
||||||
);
|
);
|
||||||
store_payload(seq_number_, move(iter->second));
|
store_payload(seq_number_, std::move(iter->second));
|
||||||
iter = erase_iterator(iter);
|
iter = erase_iterator(iter);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -158,14 +156,14 @@ void DataTracker::store_payload(uint32_t seq, payload_type payload) {
|
|||||||
// New segment, store it
|
// New segment, store it
|
||||||
if (iter == buffered_payload_.end()) {
|
if (iter == buffered_payload_.end()) {
|
||||||
total_buffered_bytes_ += payload.size();
|
total_buffered_bytes_ += payload.size();
|
||||||
buffered_payload_.insert(make_pair(seq, move(payload)));
|
buffered_payload_.insert(make_pair(seq, std::move(payload)));
|
||||||
}
|
}
|
||||||
else if (iter->second.size() < payload.size()) {
|
else if (iter->second.size() < payload.size()) {
|
||||||
// Increment by the diff between sizes
|
// Increment by the diff between sizes
|
||||||
total_buffered_bytes_ += (payload.size() - iter->second.size());
|
total_buffered_bytes_ += (payload.size() - iter->second.size());
|
||||||
// If we already have payload on this position but it's a shorter
|
// If we already have payload on this position but it's a shorter
|
||||||
// chunk than the new one, replace it
|
// chunk than the new one, replace it
|
||||||
iter->second = move(payload);
|
iter->second = std::move(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ void Flow::process_packet(PDU& pdu) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// can process either way, since it will abort immediately if not needed
|
// can process either way, since it will abort immediately if not needed
|
||||||
if (data_tracker_.process_payload(tcp->seq(), move(raw->payload()))) {
|
if (data_tracker_.process_payload(tcp->seq(), std::move(raw->payload()))) {
|
||||||
if (on_data_callback_) {
|
if (on_data_callback_) {
|
||||||
on_data_callback_(*this);
|
on_data_callback_(*this);
|
||||||
}
|
}
|
||||||
@@ -127,19 +127,19 @@ void Flow::advance_sequence(uint32_t seq) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Flow::update_state(const TCP& tcp) {
|
void Flow::update_state(const TCP& tcp) {
|
||||||
if ((tcp.flags() & TCP::FIN) != 0) {
|
if (tcp.has_flags(TCP::FIN)) {
|
||||||
state_ = FIN_SENT;
|
state_ = FIN_SENT;
|
||||||
}
|
}
|
||||||
else if ((tcp.flags() & TCP::RST) != 0) {
|
else if (tcp.has_flags(TCP::RST)) {
|
||||||
state_ = RST_SENT;
|
state_ = RST_SENT;
|
||||||
}
|
}
|
||||||
else if (state_ == SYN_SENT && (tcp.flags() & TCP::ACK) != 0) {
|
else if (state_ == SYN_SENT && tcp.has_flags(TCP::ACK)) {
|
||||||
#ifdef TINS_HAVE_ACK_TRACKER
|
#ifdef TINS_HAVE_ACK_TRACKER
|
||||||
ack_tracker_ = AckTracker(tcp.ack_seq());
|
ack_tracker_ = AckTracker(tcp.ack_seq());
|
||||||
#endif // TINS_HAVE_ACK_TRACKER
|
#endif // TINS_HAVE_ACK_TRACKER
|
||||||
state_ = ESTABLISHED;
|
state_ = ESTABLISHED;
|
||||||
}
|
}
|
||||||
else if (state_ == UNKNOWN && (tcp.flags() & TCP::SYN) != 0) {
|
else if (state_ == UNKNOWN && tcp.has_flags(TCP::SYN)) {
|
||||||
// This is the server's state, sending it's first SYN|ACK
|
// This is the server's state, sending it's first SYN|ACK
|
||||||
#ifdef TINS_HAVE_ACK_TRACKER
|
#ifdef TINS_HAVE_ACK_TRACKER
|
||||||
ack_tracker_ = AckTracker(tcp.ack_seq());
|
ack_tracker_ = AckTracker(tcp.ack_seq());
|
||||||
|
|||||||
@@ -59,9 +59,11 @@ Stream::Stream(PDU& packet, const timestamp_type& ts)
|
|||||||
client_hw_addr_ = eth->src_addr();
|
client_hw_addr_ = eth->src_addr();
|
||||||
server_hw_addr_ = eth->dst_addr();
|
server_hw_addr_ = eth->dst_addr();
|
||||||
}
|
}
|
||||||
const TCP& tcp = packet.rfind_pdu<TCP>();
|
const TCP* tcp = packet.find_pdu<TCP>();
|
||||||
// If this is not the first packet of a stream (SYN), then it's a partial stream
|
if (tcp) {
|
||||||
is_partial_stream_ = tcp.flags() != TCP::SYN;
|
// If this is not the first packet of a stream (SYN), then it's a partial stream
|
||||||
|
is_partial_stream_ = !tcp->has_flags(TCP::SYN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::process_packet(PDU& packet, const timestamp_type& ts) {
|
void Stream::process_packet(PDU& packet, const timestamp_type& ts) {
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
|
|||||||
if (iter == streams_.end()) {
|
if (iter == streams_.end()) {
|
||||||
// Start tracking if they're either SYNs or they contain data (attach
|
// Start tracking if they're either SYNs or they contain data (attach
|
||||||
// to an already running flow).
|
// to an already running flow).
|
||||||
if (tcp->flags() == TCP::SYN || (attach_to_flows_ && tcp->find_pdu<RawPDU>() != 0)) {
|
// Start on client's SYN, not on server's SYN+ACK
|
||||||
|
const bool is_syn = tcp->has_flags(TCP::SYN) && !tcp->has_flags(TCP::ACK);
|
||||||
|
if (is_syn || (attach_to_flows_ && tcp->find_pdu<RawPDU>() != 0)) {
|
||||||
iter = streams_.insert(make_pair(identifier, Stream(packet, ts))).first;
|
iter = streams_.insert(make_pair(identifier, Stream(packet, ts))).first;
|
||||||
iter->second.setup_flows_callbacks();
|
iter->second.setup_flows_callbacks();
|
||||||
if (on_new_connection_) {
|
if (on_new_connection_) {
|
||||||
@@ -93,7 +95,7 @@ void StreamFollower::process_packet(PDU& packet, const timestamp_type& ts) {
|
|||||||
else {
|
else {
|
||||||
throw callback_not_set();
|
throw callback_not_set();
|
||||||
}
|
}
|
||||||
if (tcp->flags() != TCP::SYN) {
|
if (!is_syn) {
|
||||||
// assume the connection is established
|
// assume the connection is established
|
||||||
iter->second.client_flow().state(Flow::ESTABLISHED);
|
iter->second.client_flow().state(Flow::ESTABLISHED);
|
||||||
iter->second.server_flow().state(Flow::ESTABLISHED);
|
iter->second.server_flow().state(Flow::ESTABLISHED);
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ bool TCPStream::generic_process(uint32_t& my_seq,
|
|||||||
|
|
||||||
bool TCPStream::update(IP* ip, TCP* tcp) {
|
bool TCPStream::update(IP* ip, TCP* tcp) {
|
||||||
if (!syn_ack_sent_) {
|
if (!syn_ack_sent_) {
|
||||||
if (tcp->flags() == (TCP::SYN | TCP::ACK)) {
|
if (tcp->has_flags(TCP::SYN | TCP::ACK)) {
|
||||||
server_seq_ = tcp->seq() + 1;
|
server_seq_ = tcp->seq() + 1;
|
||||||
client_seq_ = tcp->ack_seq();
|
client_seq_ = tcp->ack_seq();
|
||||||
syn_ack_sent_ = true;
|
syn_ack_sent_ = true;
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ string to_string(PDU::PDUType pduType) {
|
|||||||
ENUM_TEXT(ICMPv6);
|
ENUM_TEXT(ICMPv6);
|
||||||
ENUM_TEXT(SLL);
|
ENUM_TEXT(SLL);
|
||||||
ENUM_TEXT(DHCPv6);
|
ENUM_TEXT(DHCPv6);
|
||||||
|
ENUM_TEXT(DOT1AD);
|
||||||
ENUM_TEXT(DOT1Q);
|
ENUM_TEXT(DOT1Q);
|
||||||
ENUM_TEXT(PPPOE);
|
ENUM_TEXT(PPPOE);
|
||||||
ENUM_TEXT(STP);
|
ENUM_TEXT(STP);
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ const RadioTapParser::FieldMetadata RadioTapParser::RADIOTAP_METADATA[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const uint32_t RadioTapParser::MAX_RADIOTAP_FIELD = sizeof(RADIOTAP_METADATA) /
|
const uint32_t RadioTapParser::MAX_RADIOTAP_FIELD = sizeof(RADIOTAP_METADATA) /
|
||||||
sizeof(FieldMetadata) + 1;
|
sizeof(FieldMetadata);
|
||||||
|
|
||||||
#if TINS_IS_LITTLE_ENDIAN
|
#if TINS_IS_LITTLE_ENDIAN
|
||||||
TINS_BEGIN_PACK
|
TINS_BEGIN_PACK
|
||||||
@@ -131,13 +131,10 @@ struct RadioTapFlags {
|
|||||||
} TINS_END_PACK;
|
} TINS_END_PACK;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t size, size_t n) {
|
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, size_t n) {
|
||||||
uint32_t offset = (buffer - buffer_start) & (n - 1);
|
uint32_t offset = (buffer - buffer_start) & (n - 1);
|
||||||
if (offset) {
|
if (offset) {
|
||||||
offset = n - offset;
|
offset = n - offset;
|
||||||
if (TINS_UNLIKELY(offset > size)) {
|
|
||||||
throw malformed_packet();
|
|
||||||
}
|
|
||||||
buffer += offset;
|
buffer += offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +230,7 @@ bool RadioTapParser::skip_to_field(RadioTap::PresentFlags flag) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RadioTapParser::has_fields() const {
|
bool RadioTapParser::has_fields() const {
|
||||||
return current_bit_ != MAX_RADIOTAP_FIELD;
|
return current_bit_ != MAX_RADIOTAP_FIELD && current_ptr_ < end_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RadioTapParser::has_field(RadioTap::PresentFlags flag) const {
|
bool RadioTapParser::has_field(RadioTap::PresentFlags flag) const {
|
||||||
@@ -281,7 +278,7 @@ bool RadioTapParser::advance_to_next_field() {
|
|||||||
if (current_bit_ < MAX_RADIOTAP_FIELD) {
|
if (current_bit_ < MAX_RADIOTAP_FIELD) {
|
||||||
const uint8_t* radiotap_start = start_ - sizeof(uint32_t);
|
const uint8_t* radiotap_start = start_ - sizeof(uint32_t);
|
||||||
// Skip and align the buffer
|
// Skip and align the buffer
|
||||||
align_buffer(radiotap_start, current_ptr_, end_ - radiotap_start,
|
align_buffer(radiotap_start, current_ptr_,
|
||||||
RADIOTAP_METADATA[current_bit_].alignment);
|
RADIOTAP_METADATA[current_bit_].alignment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,11 +41,12 @@ namespace Tins {
|
|||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
uint32_t calculate_padding(uint32_t alignment, uint32_t offset) {
|
uint32_t calculate_padding(uint32_t alignment, uint32_t offset) {
|
||||||
return offset % alignment;
|
uint32_t extra = offset % alignment;
|
||||||
|
return extra == 0 ? 0 : alignment - extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t get_bit(uint32_t value) {
|
uint32_t get_bit(uint32_t value) {
|
||||||
return log(value) / log(2);
|
return round(log2(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
RadioTapWriter::RadioTapWriter(vector<uint8_t>& buffer)
|
RadioTapWriter::RadioTapWriter(vector<uint8_t>& buffer)
|
||||||
@@ -54,7 +55,7 @@ RadioTapWriter::RadioTapWriter(vector<uint8_t>& buffer)
|
|||||||
|
|
||||||
void RadioTapWriter::write_option(const RadioTap::option& option) {
|
void RadioTapWriter::write_option(const RadioTap::option& option) {
|
||||||
const uint32_t bit = get_bit(option.option());
|
const uint32_t bit = get_bit(option.option());
|
||||||
if (bit > RadioTapParser::MAX_RADIOTAP_FIELD) {
|
if (bit >= RadioTapParser::MAX_RADIOTAP_FIELD) {
|
||||||
throw malformed_option();
|
throw malformed_option();
|
||||||
}
|
}
|
||||||
const bool is_empty = buffer_.empty();
|
const bool is_empty = buffer_.empty();
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ vector<char> query_route_table(int family) {
|
|||||||
throw exception_base("sysctl failed");
|
throw exception_base("sysctl failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf.resize(len);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,17 +413,21 @@ set<string> network_interfaces() {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
set<string> network_interfaces() {
|
set<string> network_interfaces() {
|
||||||
set<string> output;
|
#if !defined(ANDROID) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 24)
|
||||||
struct ifaddrs* ifaddrs = 0;
|
set<string> output;
|
||||||
struct ifaddrs* if_it = 0;
|
struct ifaddrs* ifaddrs = 0;
|
||||||
getifaddrs(&ifaddrs);
|
struct ifaddrs* if_it = 0;
|
||||||
for (if_it = ifaddrs; if_it; if_it = if_it->ifa_next) {
|
getifaddrs(&ifaddrs);
|
||||||
output.insert(if_it->ifa_name);
|
for (if_it = ifaddrs; if_it; if_it = if_it->ifa_next) {
|
||||||
}
|
output.insert(if_it->ifa_name);
|
||||||
if (ifaddrs) {
|
}
|
||||||
freeifaddrs(ifaddrs);
|
if (ifaddrs) {
|
||||||
}
|
freeifaddrs(ifaddrs);
|
||||||
|
}
|
||||||
return output;
|
return output;
|
||||||
|
#else
|
||||||
|
throw std::runtime_error("android ifaddr not supported");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
@@ -439,5 +444,17 @@ bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr) {
|
||||||
|
typedef vector<Route6Entry> entries_type;
|
||||||
|
entries_type entries =route6_entries();
|
||||||
|
for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) {
|
||||||
|
if ((ip & it->mask) == it->destination) {
|
||||||
|
gw_addr = it->gateway;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // Utils
|
} // Utils
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|||||||
36
src/vxlan.cpp
Normal file
36
src/vxlan.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <tins/internals.h>
|
||||||
|
#include <tins/memory_helpers.h>
|
||||||
|
#include <tins/small_uint.h>
|
||||||
|
#include <tins/vxlan.h>
|
||||||
|
|
||||||
|
using Tins::Memory::InputMemoryStream;
|
||||||
|
using Tins::Memory::OutputMemoryStream;
|
||||||
|
|
||||||
|
namespace Tins {
|
||||||
|
|
||||||
|
VXLAN::VXLAN(const small_uint<24> vni) {
|
||||||
|
set_flags(8);
|
||||||
|
set_vni(vni);
|
||||||
|
}
|
||||||
|
|
||||||
|
VXLAN::VXLAN(const uint8_t* buffer, uint32_t total_sz) {
|
||||||
|
InputMemoryStream stream(buffer, total_sz);
|
||||||
|
stream.read(header_);
|
||||||
|
// If there is any size left
|
||||||
|
if (stream) {
|
||||||
|
inner_pdu(
|
||||||
|
Internals::pdu_from_flag(
|
||||||
|
PDU::ETHERNET_II,
|
||||||
|
stream.pointer(),
|
||||||
|
stream.size()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VXLAN::write_serialization(uint8_t* buffer, uint32_t total_sz) {
|
||||||
|
OutputMemoryStream stream(buffer, total_sz);
|
||||||
|
stream.write(header_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Tins
|
||||||
@@ -62,7 +62,7 @@ private:
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ActiveTestRunner::add_test() {
|
void ActiveTestRunner::add_test() {
|
||||||
tests_.emplace_back(new T(packet_sender_, configuration_));
|
tests_.emplace_back(std::unique_ptr<T>(new T(packet_sender_, configuration_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TINS_ACTIVE_TEST_RUNNER_H
|
#endif // TINS_ACTIVE_TEST_RUNNER_H
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ CREATE_TEST(pppoe)
|
|||||||
CREATE_TEST(raw_pdu)
|
CREATE_TEST(raw_pdu)
|
||||||
CREATE_TEST(rc4_eapol)
|
CREATE_TEST(rc4_eapol)
|
||||||
CREATE_TEST(rsn_eapol)
|
CREATE_TEST(rsn_eapol)
|
||||||
|
CREATE_TEST(rtp)
|
||||||
CREATE_TEST(sll)
|
CREATE_TEST(sll)
|
||||||
CREATE_TEST(snap)
|
CREATE_TEST(snap)
|
||||||
CREATE_TEST(stp)
|
CREATE_TEST(stp)
|
||||||
@@ -70,6 +71,7 @@ CREATE_TEST(tcp)
|
|||||||
CREATE_TEST(tcp_ip)
|
CREATE_TEST(tcp_ip)
|
||||||
CREATE_TEST(udp)
|
CREATE_TEST(udp)
|
||||||
CREATE_TEST(utils)
|
CREATE_TEST(utils)
|
||||||
|
CREATE_TEST(vxlan)
|
||||||
|
|
||||||
IF(LIBTINS_ENABLE_PCAP)
|
IF(LIBTINS_ENABLE_PCAP)
|
||||||
CREATE_TEST(offline_packet_filter)
|
CREATE_TEST(offline_packet_filter)
|
||||||
|
|||||||
@@ -12,11 +12,19 @@ using namespace Tins;
|
|||||||
|
|
||||||
class AddressRangeTest : public testing::Test {
|
class AddressRangeTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
|
void contain_tests0(const IPv4Range& range);
|
||||||
|
void contain_tests0(const IPv6Range& range);
|
||||||
void contain_tests24(const IPv4Range& range);
|
void contain_tests24(const IPv4Range& range);
|
||||||
void contain_tests24(const IPv6Range& range);
|
void contain_tests24(const IPv6Range& range);
|
||||||
void contain_tests26(const IPv4Range& range);
|
void contain_tests26(const IPv4Range& range);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void AddressRangeTest::contain_tests0(const IPv4Range& range) {
|
||||||
|
EXPECT_TRUE(range.contains("0.0.0.0"));
|
||||||
|
EXPECT_TRUE(range.contains("192.168.1.1"));
|
||||||
|
EXPECT_TRUE(range.contains("255.255.255.255"));
|
||||||
|
}
|
||||||
|
|
||||||
void AddressRangeTest::contain_tests24(const IPv4Range& range) {
|
void AddressRangeTest::contain_tests24(const IPv4Range& range) {
|
||||||
EXPECT_TRUE(range.contains("192.168.0.0"));
|
EXPECT_TRUE(range.contains("192.168.0.0"));
|
||||||
EXPECT_TRUE(range.contains("192.168.0.1"));
|
EXPECT_TRUE(range.contains("192.168.0.1"));
|
||||||
@@ -33,6 +41,12 @@ void AddressRangeTest::contain_tests26(const IPv4Range& range) {
|
|||||||
EXPECT_FALSE(range.contains("192.168.254.191"));
|
EXPECT_FALSE(range.contains("192.168.254.191"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddressRangeTest::contain_tests0(const IPv6Range& range) {
|
||||||
|
EXPECT_TRUE(range.contains("::"));
|
||||||
|
EXPECT_TRUE(range.contains("dead::1:1"));
|
||||||
|
EXPECT_TRUE(range.contains("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
|
||||||
|
}
|
||||||
|
|
||||||
void AddressRangeTest::contain_tests24(const IPv6Range& range) {
|
void AddressRangeTest::contain_tests24(const IPv6Range& range) {
|
||||||
EXPECT_TRUE(range.contains("dead::1"));
|
EXPECT_TRUE(range.contains("dead::1"));
|
||||||
EXPECT_TRUE(range.contains("dead::1fee"));
|
EXPECT_TRUE(range.contains("dead::1fee"));
|
||||||
@@ -42,13 +56,22 @@ void AddressRangeTest::contain_tests24(const IPv6Range& range) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AddressRangeTest, Contains) {
|
TEST_F(AddressRangeTest, Contains) {
|
||||||
|
contain_tests0(IPv4Range("0.0.0.0", "255.255.255.255"));
|
||||||
|
contain_tests0(IPv4Range::from_mask("0.0.0.0", "0.0.0.0"));
|
||||||
|
contain_tests0(IPv4Range::from_mask("0.0.0.0", IPv4Address::from_prefix_length(0)));
|
||||||
contain_tests24(IPv4Range("192.168.0.0", "192.168.0.255"));
|
contain_tests24(IPv4Range("192.168.0.0", "192.168.0.255"));
|
||||||
contain_tests24(IPv4Range::from_mask("192.168.0.0", "255.255.255.0"));
|
contain_tests24(IPv4Range::from_mask("192.168.0.0", "255.255.255.0"));
|
||||||
|
contain_tests24(IPv4Range::from_mask("192.168.0.0", IPv4Address::from_prefix_length(24)));
|
||||||
contain_tests26(IPv4Range("192.168.254.192", "192.168.254.255"));
|
contain_tests26(IPv4Range("192.168.254.192", "192.168.254.255"));
|
||||||
contain_tests26(IPv4Range::from_mask("192.168.254.192", "255.255.255.192"));
|
contain_tests26(IPv4Range::from_mask("192.168.254.192", "255.255.255.192"));
|
||||||
|
contain_tests26(IPv4Range::from_mask("192.168.254.192", IPv4Address::from_prefix_length(26)));
|
||||||
|
|
||||||
|
contain_tests0(IPv6Range("::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
|
||||||
|
contain_tests0(IPv6Range::from_mask("::", "::"));
|
||||||
|
contain_tests0(IPv6Range::from_mask("::", IPv6Address::from_prefix_length(0)));
|
||||||
contain_tests24(IPv6Range("dead::0", "dead::ffff"));
|
contain_tests24(IPv6Range("dead::0", "dead::ffff"));
|
||||||
contain_tests24(IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
|
contain_tests24(IPv6Range::from_mask("dead::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0"));
|
||||||
|
contain_tests24(IPv6Range::from_mask("dead::0", IPv6Address::from_prefix_length(112)));
|
||||||
|
|
||||||
{
|
{
|
||||||
AddressRange<HWAddress<6> > range("00:00:00:00:00:00", "00:00:00:00:00:ff");
|
AddressRange<HWAddress<6> > range("00:00:00:00:00:00", "00:00:00:00:00:ff");
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const uint8_t DHCPTest::expected_packet[] = {
|
|||||||
TEST_F(DHCPTest, DefaultConstructor) {
|
TEST_F(DHCPTest, DefaultConstructor) {
|
||||||
DHCP dhcp;
|
DHCP dhcp;
|
||||||
EXPECT_EQ(dhcp.htype(), 1);
|
EXPECT_EQ(dhcp.htype(), 1);
|
||||||
EXPECT_EQ(dhcp.hlen(), (const size_t)EthernetII::address_type::address_size);
|
EXPECT_EQ(dhcp.hlen(), (size_t)EthernetII::address_type::address_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DHCPTest, CopyConstructor) {
|
TEST_F(DHCPTest, CopyConstructor) {
|
||||||
@@ -280,7 +280,7 @@ TEST_F(DHCPTest, ConstructorFromBuffer) {
|
|||||||
|
|
||||||
EXPECT_EQ(dhcp1.opcode(), DHCP::DISCOVER);
|
EXPECT_EQ(dhcp1.opcode(), DHCP::DISCOVER);
|
||||||
EXPECT_EQ(dhcp1.htype(), 1);
|
EXPECT_EQ(dhcp1.htype(), 1);
|
||||||
ASSERT_EQ(dhcp1.hlen(), (const size_t)EthernetII::address_type::address_size);
|
ASSERT_EQ(dhcp1.hlen(), (size_t)EthernetII::address_type::address_size);
|
||||||
EXPECT_EQ(dhcp1.hops(), 0x1f);
|
EXPECT_EQ(dhcp1.hops(), 0x1f);
|
||||||
EXPECT_EQ(dhcp1.xid(), 0x3fab23deU);
|
EXPECT_EQ(dhcp1.xid(), 0x3fab23deU);
|
||||||
EXPECT_EQ(dhcp1.secs(), 0x9f1a);
|
EXPECT_EQ(dhcp1.secs(), 0x9f1a);
|
||||||
|
|||||||
@@ -551,3 +551,113 @@ TEST_F(DNSTest, SOARecordSerialize) {
|
|||||||
EXPECT_EQ(0x8ad71928U, r2.expire());
|
EXPECT_EQ(0x8ad71928U, r2.expire());
|
||||||
EXPECT_EQ(0x1ad92871U, r2.minimum_ttl());
|
EXPECT_EQ(0x1ad92871U, r2.minimum_ttl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DNSTest, BadLabelSize) {
|
||||||
|
const uint8_t header[] = {
|
||||||
|
0x45, 0xbc, // ID
|
||||||
|
0x81, 0x80, // response, recursion desired, recursion available, no error
|
||||||
|
0x00, 0x01, // QDCOUNT
|
||||||
|
0x00, 0x00, // ANCOUNT
|
||||||
|
0x00, 0x00, // NSCOUNT
|
||||||
|
0x00, 0x00 // ARCOUNT
|
||||||
|
};
|
||||||
|
size_t payload_sz{sizeof(header)};
|
||||||
|
uint8_t payload[512];
|
||||||
|
|
||||||
|
// copy header
|
||||||
|
std::copy(header,
|
||||||
|
header + payload_sz,
|
||||||
|
payload);
|
||||||
|
|
||||||
|
// add bad length
|
||||||
|
const size_t bad_label_len{0x80};
|
||||||
|
const size_t label_offset = payload_sz;
|
||||||
|
payload[payload_sz++] = bad_label_len;
|
||||||
|
|
||||||
|
// fill label for incorrect length and terminate
|
||||||
|
std::fill(payload + payload_sz,
|
||||||
|
payload + payload_sz + bad_label_len,
|
||||||
|
'a');
|
||||||
|
payload_sz += bad_label_len;
|
||||||
|
payload[payload_sz++] = 0x0;
|
||||||
|
|
||||||
|
// add type and class
|
||||||
|
const uint8_t type_class[] = {
|
||||||
|
0x00, 0x01,
|
||||||
|
0x00, 0x01
|
||||||
|
};
|
||||||
|
std::copy(type_class,
|
||||||
|
type_class + sizeof(type_class),
|
||||||
|
payload + payload_sz);
|
||||||
|
payload_sz += sizeof(type_class);
|
||||||
|
|
||||||
|
// invalid high two bits of label first octest is detected early now
|
||||||
|
try {
|
||||||
|
const DNS packet(payload, payload_sz);
|
||||||
|
FAIL();
|
||||||
|
} catch (malformed_packet& mp) {
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the other invalid value of high two bits in label size
|
||||||
|
payload[label_offset] = 0x10;
|
||||||
|
try {
|
||||||
|
const DNS packet(payload, payload_sz);
|
||||||
|
FAIL();
|
||||||
|
} catch (malformed_packet& mp) {
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DNSTest, BadPacketLength) {
|
||||||
|
|
||||||
|
// valid response packet with RR's in all sections
|
||||||
|
const uint8_t payload[] = {
|
||||||
|
0x74,0xa9,0x85,0x80,0x00,0x01,0x00,0x02,0x00,0x01,0x00,0x04,0x08,0x5f,0x73,0x65,0x72,
|
||||||
|
0x76,0x69,0x63,0x65,0x04,0x5f,0x74,0x63,0x70,0x05,0x77,0x69,0x66,0x69,0x36,0x03,
|
||||||
|
0x6c,0x61,0x6e,0x00,0x00,0x21,0x00,0x01,0xc0,0x0c,0x00,0x21,0x00,0x01,0x00,0x01,
|
||||||
|
0x51,0x80,0x00,0x16,0x00,0x00,0x00,0x03,0x00,0x09,0x04,0x66,0x61,0x73,0x74,0x05,
|
||||||
|
0x77,0x69,0x66,0x69,0x36,0x03,0x6c,0x61,0x6e,0x00,0xc0,0x0c,0x00,0x21,0x00,0x01,
|
||||||
|
0x00,0x01,0x51,0x80,0x00,0x16,0x00,0x00,0x00,0x01,0x00,0x09,0x04,0x73,0x6c,0x6f,
|
||||||
|
0x77,0x05,0x77,0x69,0x66,0x69,0x36,0x03,0x6c,0x61,0x6e,0x00,0xc0,0x62,0x00,0x02,
|
||||||
|
0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x05,0x02,0x70,0x69,0xc0,0x62,0xc0,0x5d,0x00,
|
||||||
|
0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x0a,0x18,0x00,0x02,0xc0,0x3b,0x00,
|
||||||
|
0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x0a,0x18,0x00,0x02,0xc0,0x79,0x00,
|
||||||
|
0x01,0x00,0x01,0x00,0x01,0x51,0x80,0x00,0x04,0x0a,0x18,0x00,0x02,0x00,0x00,0x29,
|
||||||
|
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x0a,0x00,0x18,0x86,0x1f,0x14,0x0f,
|
||||||
|
0x41,0xfa,0xf3,0x95,0x48,0x6e,0x79,0x61,0x61,0x78,0x32,0x0f,0x44,0x5d,0x21,0x47,
|
||||||
|
0x85,0x83,0x9a,0x95
|
||||||
|
};
|
||||||
|
|
||||||
|
// valid DNS message but misreport packet size;
|
||||||
|
// before fix, parser headed into uncharted waters on requesting additional section
|
||||||
|
|
||||||
|
// buffer with space for valid packet plus garbage bytes
|
||||||
|
const size_t bigsz{512};
|
||||||
|
uint8_t big_packet[bigsz];
|
||||||
|
|
||||||
|
// copy valid packet
|
||||||
|
std::copy(payload,
|
||||||
|
payload + sizeof(payload),
|
||||||
|
big_packet);
|
||||||
|
|
||||||
|
// fill additional bytes with junk
|
||||||
|
std::fill(big_packet + sizeof(payload),
|
||||||
|
big_packet + bigsz,
|
||||||
|
0x5A);
|
||||||
|
|
||||||
|
// initial packet parse ok
|
||||||
|
const DNS packet(big_packet, bigsz);
|
||||||
|
|
||||||
|
// RR's parse ok now
|
||||||
|
EXPECT_EQ(packet.questions_count(), 1);
|
||||||
|
EXPECT_EQ(packet.answers_count(), 2);
|
||||||
|
EXPECT_EQ(packet.authority_count(), 1);
|
||||||
|
EXPECT_EQ(packet.additional_count(), 4);
|
||||||
|
EXPECT_EQ(packet.queries().size(), 1U);
|
||||||
|
EXPECT_EQ(packet.answers().size(), 2U);
|
||||||
|
EXPECT_EQ(packet.authority().size(), 1U);
|
||||||
|
EXPECT_EQ(packet.additional().size(), 4U);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,17 @@ TEST_F(Dot1QTest, Serialize) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Dot1QTest, SerializeCraftedPacket)
|
||||||
|
{
|
||||||
|
EthernetII pkt = EthernetII() / Dot1Q(10) / IP("192.168.1.2") / TCP(23, 45) / RawPDU("asdasdasd");
|
||||||
|
PDU::serialization_type buffer = pkt.serialize();
|
||||||
|
EXPECT_EQ(buffer[12], 0x81);
|
||||||
|
EXPECT_EQ(buffer[13], 0x00);
|
||||||
|
EthernetII pkt2(&buffer[0], buffer.size());
|
||||||
|
const Dot1Q &q1 = pkt2.rfind_pdu<Dot1Q>();
|
||||||
|
EXPECT_EQ(10, q1.id());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(Dot1QTest, PayloadType) {
|
TEST_F(Dot1QTest, PayloadType) {
|
||||||
Dot1Q dot1;
|
Dot1Q dot1;
|
||||||
dot1.payload_type(0x9283);
|
dot1.payload_type(0x9283);
|
||||||
@@ -86,6 +97,12 @@ TEST_F(Dot1QTest, QinQ) {
|
|||||||
EthernetII pkt = EthernetII() / Dot1Q(10) / Dot1Q(42) / IP("192.168.1.2") /
|
EthernetII pkt = EthernetII() / Dot1Q(10) / Dot1Q(42) / IP("192.168.1.2") /
|
||||||
TCP(23, 45) / RawPDU("asdasdasd");
|
TCP(23, 45) / RawPDU("asdasdasd");
|
||||||
PDU::serialization_type buffer = pkt.serialize();
|
PDU::serialization_type buffer = pkt.serialize();
|
||||||
|
// First PID of the serialized packet should be Dot1AD = 0x88a8
|
||||||
|
EXPECT_EQ(buffer[12], 0x88);
|
||||||
|
EXPECT_EQ(buffer[13], 0xa8);
|
||||||
|
// Second PID of the serialized packet chouls be Dot1Q = 0x8100
|
||||||
|
EXPECT_EQ(buffer[16], 0x81);
|
||||||
|
EXPECT_EQ(buffer[17], 0x00);
|
||||||
EthernetII pkt2(&buffer[0], buffer.size());
|
EthernetII pkt2(&buffer[0], buffer.size());
|
||||||
const Dot1Q& q1 = pkt2.rfind_pdu<Dot1Q>();
|
const Dot1Q& q1 = pkt2.rfind_pdu<Dot1Q>();
|
||||||
ASSERT_TRUE(q1.inner_pdu() != NULL);
|
ASSERT_TRUE(q1.inner_pdu() != NULL);
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ TEST_F(HWAddressTest, LessThanOperator) {
|
|||||||
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
|
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
|
||||||
EXPECT_LT(addr2, addr1);
|
EXPECT_LT(addr2, addr1);
|
||||||
EXPECT_LT(addr2, bcast);
|
EXPECT_LT(addr2, bcast);
|
||||||
|
EXPECT_LE(addr1, addr1);
|
||||||
std::map<HWAddress<6>, int> dict;
|
std::map<HWAddress<6>, int> dict;
|
||||||
dict[addr1] = 12;
|
dict[addr1] = 12;
|
||||||
dict[addr2] = 15;
|
dict[addr2] = 15;
|
||||||
@@ -59,6 +60,20 @@ TEST_F(HWAddressTest, LessThanOperator) {
|
|||||||
EXPECT_EQ(dict[addr2], 15);
|
EXPECT_EQ(dict[addr2], 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HWAddressTest, GreaterThanOperator) {
|
||||||
|
HWAddress<6> addr1(byte_address), addr2(empty_addr);
|
||||||
|
HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff";
|
||||||
|
EXPECT_GT(addr1, addr2);
|
||||||
|
EXPECT_GT(bcast, addr2);
|
||||||
|
EXPECT_GE(addr1, addr1);
|
||||||
|
std::map<HWAddress<6>, int> dict;
|
||||||
|
dict[addr1] = 12;
|
||||||
|
dict[addr2] = 15;
|
||||||
|
EXPECT_EQ(dict[addr1], 12);
|
||||||
|
EXPECT_EQ(dict[addr2], 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_F(HWAddressTest, CopyConstructor) {
|
TEST_F(HWAddressTest, CopyConstructor) {
|
||||||
HWAddress<6> addr1(byte_address), addr2(addr1);
|
HWAddress<6> addr1(byte_address), addr2(addr1);
|
||||||
@@ -115,3 +130,18 @@ TEST_F(HWAddressTest, Mask) {
|
|||||||
address_type("de:ad:be:ef:00:00") & address_type("ff:ff:ff:f0:00:00")
|
address_type("de:ad:be:ef:00:00") & address_type("ff:ff:ff:f0:00:00")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HWAddressTest, OrMask) {
|
||||||
|
typedef HWAddress<6> address_type;
|
||||||
|
EXPECT_EQ(
|
||||||
|
address_type("ff:ff:ff:ff:fe:be"),
|
||||||
|
address_type("de:ad:be:ef:fe:be") | address_type("ff:ff:ff:f0:00:00")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(HWAddressTest, NotMask) {
|
||||||
|
typedef HWAddress<6> address_type;
|
||||||
|
EXPECT_EQ(
|
||||||
|
address_type("00:00:00:0f:ff:ff"), ~address_type("ff:ff:ff:f0:00:00")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,8 +47,19 @@ TEST(IPAddressTest, LessThanOperator) {
|
|||||||
EXPECT_LT(addr1, "192.168.1.2");
|
EXPECT_LT(addr1, "192.168.1.2");
|
||||||
EXPECT_LT(addr1, "192.168.0.226");
|
EXPECT_LT(addr1, "192.168.0.226");
|
||||||
EXPECT_LT(addr1, "193.0.0.0");
|
EXPECT_LT(addr1, "193.0.0.0");
|
||||||
|
EXPECT_LE(addr1, addr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IPAddressTest, GreaterThanOperator) {
|
||||||
|
IPv4Address addr1(ip_string), addr2(ip_string);
|
||||||
|
EXPECT_FALSE(addr1 < addr2);
|
||||||
|
EXPECT_GT(addr1, "192.167.1.2");
|
||||||
|
EXPECT_GT(addr1, "192.167.0.226");
|
||||||
|
EXPECT_GT(addr1, "191.0.0.0");
|
||||||
|
EXPECT_GE(addr1, addr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(IPAddressTest, IsPrivate) {
|
TEST(IPAddressTest, IsPrivate) {
|
||||||
EXPECT_TRUE(IPv4Address("192.168.0.1").is_private());
|
EXPECT_TRUE(IPv4Address("192.168.0.1").is_private());
|
||||||
EXPECT_TRUE(IPv4Address("192.168.133.7").is_private());
|
EXPECT_TRUE(IPv4Address("192.168.133.7").is_private());
|
||||||
@@ -112,6 +123,26 @@ TEST(IPAddressTest, Mask) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IPAddressTest, OrMask) {
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv4Address("255.255.255.1"),
|
||||||
|
IPv4Address("192.168.100.1") | IPv4Address("255.255.255.0")
|
||||||
|
);
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv4Address("255.255.1.2"),
|
||||||
|
IPv4Address("192.255.1.2") | IPv4Address("255.128.0.0")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IPAddressTest, NotMask) {
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv4Address("0.0.0.255"), ~IPv4Address("255.255.255.0")
|
||||||
|
);
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv4Address("0.127.255.255"),~IPv4Address("255.128.0.0")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(IPv4AddressTest, Size) {
|
TEST(IPv4AddressTest, Size) {
|
||||||
EXPECT_EQ(4UL, IPv4Address("127.0.0.1").size());
|
EXPECT_EQ(4UL, IPv4Address("127.0.0.1").size());
|
||||||
EXPECT_EQ(4UL, IPv4Address().size());
|
EXPECT_EQ(4UL, IPv4Address().size());
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ using namespace Tins;
|
|||||||
class IPTest : public testing::Test {
|
class IPTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
static const uint8_t expected_packet[], fragmented_packet[],
|
static const uint8_t expected_packet[], fragmented_packet[],
|
||||||
fragmented_ether_ip_packet[], tot_len_zero_packet[];
|
fragmented_ether_ip_packet[], tot_len_zero_packet[],
|
||||||
|
options_packet[];
|
||||||
|
|
||||||
void test_equals(const IP& ip1, const IP& ip2);
|
void test_equals(const IP& ip1, const IP& ip2);
|
||||||
void test_overwrite_source_address(IP& ip);
|
void test_overwrite_source_address(IP& ip);
|
||||||
@@ -450,6 +451,26 @@ const uint8_t IPTest::tot_len_zero_packet[] = {
|
|||||||
, 0, 0, 0, 0, 0
|
, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t IPTest::options_packet[] = {
|
||||||
|
0, 160, 204, 59, 191, 250, 16, 54, 233, 241, 145, 224, 8, 0, 72, 0,
|
||||||
|
0, 242, 0, 1, 0, 0, 128, 17, 233, 177, 192, 168, 0, 4, 220, 113,
|
||||||
|
61, 150, 130, 11, 0, 16, 0, 0, 0, 0, 120, 120, 120, 0, 143, 243,
|
||||||
|
26, 48, 0, 210, 82, 251, 92, 3, 98, 243, 14, 149, 245, 46, 106,
|
||||||
|
244, 99, 187, 143, 32, 82, 21, 116, 83, 205, 114, 68, 236, 121, 23,
|
||||||
|
98, 220, 15, 75, 139, 145, 57, 154, 24, 92, 35, 84, 179, 123, 191,
|
||||||
|
141, 122, 43, 42, 172, 212, 85, 117, 54, 227, 157, 155, 192, 52,
|
||||||
|
206, 57, 242, 150, 236, 164, 202, 143, 4, 3, 200, 56, 106, 36, 202,
|
||||||
|
38, 4, 12, 29, 108, 72, 89, 23, 180, 94, 81, 238, 41, 84, 146, 126,
|
||||||
|
185, 84, 104, 249, 166, 43, 188, 14, 141, 89, 245, 254, 222, 236,
|
||||||
|
173, 140, 121, 146, 77, 14, 132, 36, 8, 113, 162, 92, 174, 188,
|
||||||
|
214, 148, 64, 227, 220, 34, 193, 139, 234, 144, 213, 89, 74, 95,
|
||||||
|
177, 180, 145, 26, 248, 29, 238, 146, 249, 247, 75, 26, 155, 36, 8,
|
||||||
|
188, 34, 176, 73, 92, 242, 194, 185, 67, 67, 214, 235, 137, 67,
|
||||||
|
158, 144, 27, 235, 221, 252, 44, 227, 25, 229, 172, 166, 214, 6, 6,
|
||||||
|
136, 21, 173, 84, 20, 109, 140, 182, 114, 179, 167, 196, 250, 56,
|
||||||
|
169, 152, 160, 18, 136, 245, 138, 101, 177, 107, 121, 74, 204, 180,
|
||||||
|
193, 228, 135, 37
|
||||||
|
};
|
||||||
|
|
||||||
TEST_F(IPTest, DefaultConstructor) {
|
TEST_F(IPTest, DefaultConstructor) {
|
||||||
IP ip;
|
IP ip;
|
||||||
@@ -854,3 +875,11 @@ TEST_F(IPTest, SerializeAfterInnerPduRemoved) {
|
|||||||
EthernetII eth2(&buffer[0], buffer.size());
|
EthernetII eth2(&buffer[0], buffer.size());
|
||||||
EXPECT_EQ(eth1.size(), eth2.size());
|
EXPECT_EQ(eth1.size(), eth2.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(IPTest, ParseSerializeOptions) {
|
||||||
|
EthernetII packet(options_packet, sizeof(options_packet));
|
||||||
|
PDU::serialization_type serialized = packet.serialize();
|
||||||
|
|
||||||
|
const vector<uint8_t> buffer(options_packet, options_packet + sizeof(options_packet));
|
||||||
|
EXPECT_EQ(buffer, serialized);
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,6 +70,14 @@ TEST(IPv6AddressTest, LessThanOperator) {
|
|||||||
EXPECT_LT(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:5"));
|
EXPECT_LT(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:5"));
|
||||||
EXPECT_LT(IPv6Address("::1"), IPv6Address("::5"));
|
EXPECT_LT(IPv6Address("::1"), IPv6Address("::5"));
|
||||||
EXPECT_LT(IPv6Address("1::"), IPv6Address("2::"));
|
EXPECT_LT(IPv6Address("1::"), IPv6Address("2::"));
|
||||||
|
EXPECT_LE(IPv6Address("1::"), IPv6Address("1::"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IPv6AddressTest, GreaterThanOperator) {
|
||||||
|
EXPECT_GT(IPv6Address("17f8:0::0:5"), IPv6Address("17f8::1"));
|
||||||
|
EXPECT_GT(IPv6Address("::5"), IPv6Address("::1"));
|
||||||
|
EXPECT_GT(IPv6Address("2::"), IPv6Address("1::"));
|
||||||
|
EXPECT_GE(IPv6Address("2::"), IPv6Address("2::"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(IPv6AddressTest, OutputOperator) {
|
TEST(IPv6AddressTest, OutputOperator) {
|
||||||
@@ -124,6 +132,33 @@ TEST(IPv6AddressTest, MaskAddress) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(IPv6AddressTest, OrMaskAddress) {
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv6Address("ffff:ffff:adad:beef::"),
|
||||||
|
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ffff::")
|
||||||
|
);
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv6Address("ffff:ffef:adad:beef::"),
|
||||||
|
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ff00::")
|
||||||
|
);
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv6Address("ffff:feef:adad:beef::"),
|
||||||
|
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:f000::")
|
||||||
|
);
|
||||||
|
EXPECT_EQ(
|
||||||
|
IPv6Address("ffff:feef:adad:beef::"),
|
||||||
|
IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:e000::")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(IPv6AddressTest, NotMaskAddress) {
|
||||||
|
EXPECT_EQ(IPv6Address("::ffff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff::"));
|
||||||
|
EXPECT_EQ(IPv6Address("::ff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:ff00::"));
|
||||||
|
EXPECT_EQ(IPv6Address("::fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:f000::"));
|
||||||
|
EXPECT_EQ(IPv6Address("::1fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:e000::"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(IPv6AddressTest, Size) {
|
TEST(IPv6AddressTest, Size) {
|
||||||
EXPECT_EQ(16UL, IPv6Address("dead:beef::1").size());
|
EXPECT_EQ(16UL, IPv6Address("dead:beef::1").size());
|
||||||
EXPECT_EQ(16UL, IPv6Address().size());
|
EXPECT_EQ(16UL, IPv6Address().size());
|
||||||
|
|||||||
@@ -360,3 +360,63 @@ TEST_F(IPv6Test, OptionAddition) {
|
|||||||
EXPECT_TRUE(ipv6.search_header(IPv6::ROUTING) != 0);
|
EXPECT_TRUE(ipv6.search_header(IPv6::ROUTING) != 0);
|
||||||
EXPECT_TRUE(ipv6.search_header(IPv6::AUTHENTICATION) != 0);
|
EXPECT_TRUE(ipv6.search_header(IPv6::AUTHENTICATION) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(IPv6Test, HopByHopPadding) {
|
||||||
|
IPv6 ipv6_header;
|
||||||
|
ipv6_header.add_header(IPv6::ExtensionHeader::HOP_BY_HOP);
|
||||||
|
EXPECT_EQ(48UL, ipv6_header.serialize().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IPv6Test, HopByHopParsing) {
|
||||||
|
EthernetII pkt(hop_by_hop_options, sizeof(hop_by_hop_options));
|
||||||
|
IPv6& ipv6 = pkt.rfind_pdu<IPv6>();
|
||||||
|
|
||||||
|
const IPv6::headers_type& headers = ipv6.headers();
|
||||||
|
EXPECT_EQ(1UL, headers.size());
|
||||||
|
|
||||||
|
const IPv6::ext_header* ext_header = ipv6.search_header(IPv6::ExtensionHeader::HOP_BY_HOP);
|
||||||
|
EXPECT_TRUE(ext_header != NULL);
|
||||||
|
|
||||||
|
const IPv6::hop_by_hop_header hbh_header = IPv6::hop_by_hop_header::from_extension_header(*ext_header);
|
||||||
|
EXPECT_EQ(1UL, hbh_header.options.size());
|
||||||
|
EXPECT_EQ(5, hbh_header.options[0].first);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IPv6Test, HopByHopExtensionHeader) {
|
||||||
|
const uint8_t options[] = {42, 3, 0, 0, 0, 86, 0, 17, 2, 0, 0, 1, 2, 0, 0};
|
||||||
|
IPv6::ext_header hdr(IPv6::HOP_BY_HOP, options, options + sizeof(options));
|
||||||
|
|
||||||
|
IPv6::hop_by_hop_header header = IPv6::hop_by_hop_header::from_extension_header(hdr);
|
||||||
|
EXPECT_EQ(3UL, header.options.size());
|
||||||
|
EXPECT_EQ(42, header.options[0].first);
|
||||||
|
EXPECT_EQ(86, header.options[1].first);
|
||||||
|
EXPECT_EQ(17, header.options[2].first);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IPv6Test, DestinationRoutingExtensionHeader) {
|
||||||
|
EXPECT_THROW(IPv6::destination_routing_header::from_extension_header(IPv6::HOP_BY_HOP),
|
||||||
|
invalid_ipv6_extension_header);
|
||||||
|
|
||||||
|
IPv6::destination_routing_header header = IPv6::destination_routing_header::from_extension_header(IPv6::DESTINATION_ROUTING_OPTIONS);
|
||||||
|
EXPECT_EQ(0UL, header.options.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IPv6Test, RoutingExtensionHeader) {
|
||||||
|
const uint8_t header_data[] = {42, 17, 0, 0, 0, 0, 0};
|
||||||
|
IPv6::ext_header hdr(IPv6::ROUTING, header_data, header_data + sizeof(header_data));
|
||||||
|
|
||||||
|
IPv6::routing_header header = IPv6::routing_header::from_extension_header(hdr);
|
||||||
|
EXPECT_EQ(42, header.routing_type);
|
||||||
|
EXPECT_EQ(17, header.segments_left);
|
||||||
|
EXPECT_EQ(5UL, header.data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IPv6Test, FragmentExtensionHeader) {
|
||||||
|
const uint8_t header_data[] = {128, 1, 0, 0, 0, 42};
|
||||||
|
IPv6::ext_header hdr(IPv6::FRAGMENT, header_data, header_data + sizeof(header_data));
|
||||||
|
|
||||||
|
IPv6::fragment_header header = IPv6::fragment_header::from_extension_header(hdr);
|
||||||
|
EXPECT_EQ(4096, header.fragment_offset);
|
||||||
|
EXPECT_TRUE(header.more_fragments);
|
||||||
|
EXPECT_EQ(42UL, header.identification);
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ TEST_F(NetworkInterfaceTest, ConstructorFromString) {
|
|||||||
TEST_F(NetworkInterfaceTest, ConstructorFromIp) {
|
TEST_F(NetworkInterfaceTest, ConstructorFromIp) {
|
||||||
NetworkInterface iface(IPv4Address("127.0.0.1"));
|
NetworkInterface iface(IPv4Address("127.0.0.1"));
|
||||||
EXPECT_EQ(iface.name(), iface_name);
|
EXPECT_EQ(iface.name(), iface_name);
|
||||||
|
NetworkInterface i6face(IPv6Address("::1"));
|
||||||
|
EXPECT_EQ(i6face.name(), iface_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(NetworkInterfaceTest, Id) {
|
TEST_F(NetworkInterfaceTest, Id) {
|
||||||
|
|||||||
@@ -83,6 +83,14 @@ TEST_F(PDUTest, OperatorConcatOnPacket) {
|
|||||||
EXPECT_TRUE(std::equal(raw->payload().begin(), raw->payload().end(), raw_payload.begin()));
|
EXPECT_TRUE(std::equal(raw->payload().begin(), raw->payload().end(), raw_payload.begin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if TINS_IS_CXX11
|
||||||
|
TEST_F(PDUTest, MoveAssignment) {
|
||||||
|
IP packet = IP("192.168.0.1") / TCP(22, 52);
|
||||||
|
packet = IP("1.2.3.4");
|
||||||
|
EXPECT_TRUE(packet.inner_pdu() == 0);
|
||||||
|
}
|
||||||
|
#endif // TINS_IS_CXX11
|
||||||
|
|
||||||
TEST_F(PDUTest, TinsCast) {
|
TEST_F(PDUTest, TinsCast) {
|
||||||
PDU* null_pdu = 0;
|
PDU* null_pdu = 0;
|
||||||
TCP tcp;
|
TCP tcp;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public:
|
|||||||
static const uint8_t expected_packet[], expected_packet1[],
|
static const uint8_t expected_packet[], expected_packet1[],
|
||||||
expected_packet2[], expected_packet3[],
|
expected_packet2[], expected_packet3[],
|
||||||
expected_packet4[], expected_packet5[],
|
expected_packet4[], expected_packet5[],
|
||||||
expected_packet6[];
|
expected_packet6[], expected_packet7[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t RadioTapTest::expected_packet[] = {
|
const uint8_t RadioTapTest::expected_packet[] = {
|
||||||
@@ -324,6 +324,57 @@ const uint8_t RadioTapTest::expected_packet6[] = {
|
|||||||
164, 143, 87, 89, 97, 79, 145, 16, 48, 248, 198, 140, 48
|
164, 143, 87, 89, 97, 79, 145, 16, 48, 248, 198, 140, 48
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t RadioTapTest::expected_packet7[] = {
|
||||||
|
0, 255, 255, 0, 0, 240, 96, 235, 105, 143, 60, 180, 134, 221, 96,
|
||||||
|
0, 0, 0, 2, 164, 17, 64, 50, 73, 237, 197, 18, 75, 232, 197, 18,
|
||||||
|
72, 232, 197, 18, 72, 232, 71, 50, 73, 237, 125, 18, 75, 249, 195,
|
||||||
|
18, 72, 232, 197, 18, 239, 232, 197, 169, 236, 43, 206, 48, 166, 9,
|
||||||
|
84, 151, 88, 20, 229, 233, 39, 55, 108, 16, 104, 206, 107, 0, 53,
|
||||||
|
186, 70, 2, 164, 18, 0, 44, 150, 132, 3, 0, 1, 0, 0, 0, 6, 0, 1,
|
||||||
|
12, 67, 79, 56, 48, 49, 77, 49, 56, 48, 49, 57, 49, 13, 97, 122,
|
||||||
|
99, 111, 114, 114, 101, 99, 116, 105, 111, 110, 115, 5, 108, 111,
|
||||||
|
99, 97, 108, 0, 0, 6, 0, 1, 0, 0, 6, 0, 1, 0, 1, 81, 128, 0, 64, 1,
|
||||||
|
97, 12, 114, 111, 111, 116, 45, 115, 101, 114, 118, 101, 114, 115,
|
||||||
|
3, 110, 101, 116, 0, 5, 110, 115, 116, 108, 100, 12, 118, 101, 114,
|
||||||
|
105, 115, 105, 103, 110, 45, 103, 114, 115, 3, 99, 111, 109, 0,
|
||||||
|
120, 42, 86, 53, 0, 0, 7, 8, 0, 0, 3, 132, 0, 9, 58, 128, 0, 1, 81,
|
||||||
|
128, 5, 108, 111, 97, 110, 115, 0, 0, 47, 0, 1, 0, 1, 81, 128, 0,
|
||||||
|
15, 5, 108, 111, 99, 117, 115, 0, 0, 6, 32, 0, 0, 0, 0, 19, 0, 0,
|
||||||
|
47, 0, 1, 0, 1, 81, 128, 0, 14, 3, 97, 97, 97, 0, 0, 7, 26, 0, 0,
|
||||||
|
0, 0, 3, 128, 0, 0, 46, 0, 1, 0, 1, 81, 128, 0, 147, 0, 6, 8, 0, 0,
|
||||||
|
1, 81, 128, 87, 17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 23, 89,
|
||||||
|
103, 40, 110, 160, 29, 93, 75, 23, 152, 78, 76, 255, 197, 241, 39,
|
||||||
|
189, 75, 31, 226, 166, 224, 55, 9, 100, 96, 27, 180, 130, 25, 199,
|
||||||
|
101, 176, 122, 115, 169, 75, 199, 174, 203, 181, 165, 16, 159, 111,
|
||||||
|
84, 166, 162, 242, 43, 255, 148, 16, 118, 212, 144, 118, 67, 113,
|
||||||
|
59, 31, 224, 181, 103, 41, 238, 3, 174, 153, 106, 80, 171, 124,
|
||||||
|
162, 186, 167, 108, 66, 140, 244, 97, 170, 127, 170, 252, 124, 139,
|
||||||
|
246, 150, 166, 208, 191, 15, 64, 250, 217, 195, 6, 39, 246, 71,
|
||||||
|
204, 248, 143, 71, 121, 44, 149, 98, 145, 203, 102, 74, 220, 240,
|
||||||
|
180, 8, 218, 171, 76, 194, 62, 241, 85, 94, 72, 28, 192, 125, 0,
|
||||||
|
46, 0, 30, 0, 1, 81, 128, 0, 147, 0, 47, 8, 1, 0, 1, 81, 128, 87,
|
||||||
|
17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 159, 85, 2, 138, 56, 31,
|
||||||
|
91, 69, 9, 81, 254, 59, 65, 14, 76, 208, 107, 158, 159, 118, 92,
|
||||||
|
38, 52, 210, 139, 201, 40, 32, 135, 48, 252, 254, 64, 135, 97, 24,
|
||||||
|
253, 193, 114, 103, 214, 39, 14, 218, 50, 22, 60, 15, 208, 85, 152,
|
||||||
|
119, 21, 169, 236, 43, 206, 48, 166, 9, 84, 151, 88, 20, 229, 233,
|
||||||
|
39, 55, 108, 83, 104, 206, 107, 253, 252, 203, 24, 90, 216, 48,
|
||||||
|
191, 44, 38, 161, 228, 97, 84, 197, 138, 7, 206, 54, 244, 52, 153,
|
||||||
|
26, 232, 221, 182, 130, 29, 57, 193, 218, 124, 99, 68, 78, 161,
|
||||||
|
113, 120, 4, 155, 62, 94, 21, 89, 212, 33, 122, 42, 72, 5, 42, 172,
|
||||||
|
87, 70, 122, 0, 0, 46, 0, 1, 0, 1, 81, 128, 0, 147, 0, 47, 8, 0, 0,
|
||||||
|
1, 81, 128, 87, 17, 30, 16, 87, 3, 225, 0, 236, 199, 0, 131, 10,
|
||||||
|
126, 206, 35, 167, 184, 76, 112, 237, 170, 253, 123, 131, 162, 186,
|
||||||
|
243, 100, 237, 217, 17, 187, 90, 115, 28, 62, 89, 112, 69, 16, 227,
|
||||||
|
159, 162, 42, 212, 216, 246, 149, 118, 20, 105, 70, 196, 64, 48,
|
||||||
|
65, 216, 187, 25, 142, 138, 171, 229, 5, 251, 167, 181, 93, 62, 78,
|
||||||
|
204, 130, 147, 131, 168, 13, 120, 116, 115, 115, 107, 98, 53, 113,
|
||||||
|
111, 110, 56, 115, 110, 9, 95, 107, 101, 114, 98, 101, 114, 111,
|
||||||
|
115, 4, 95, 116, 99, 243, 21, 33, 14, 178, 86, 218, 241, 92, 120,
|
||||||
|
80, 120, 138, 155, 39, 74, 89, 32, 154, 143, 135, 103, 206, 121,
|
||||||
|
227, 234
|
||||||
|
};
|
||||||
|
|
||||||
TEST_F(RadioTapTest, DefaultConstructor) {
|
TEST_F(RadioTapTest, DefaultConstructor) {
|
||||||
RadioTap radio;
|
RadioTap radio;
|
||||||
EXPECT_TRUE((radio.flags() & RadioTap::FCS) != 0);
|
EXPECT_TRUE((radio.flags() & RadioTap::FCS) != 0);
|
||||||
@@ -437,6 +488,10 @@ TEST_F(RadioTapTest, ConstructorFromBuffer5) {
|
|||||||
EXPECT_EQ(0x05, radio.mcs().mcs);
|
EXPECT_EQ(0x05, radio.mcs().mcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RadioTapTest, ConstructorFromBuffer6) {
|
||||||
|
EXPECT_THROW(RadioTap(expected_packet7, sizeof(expected_packet7)), malformed_packet);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(RadioTapTest, Serialize) {
|
TEST_F(RadioTapTest, Serialize) {
|
||||||
RadioTap radio(expected_packet, sizeof(expected_packet));
|
RadioTap radio(expected_packet, sizeof(expected_packet));
|
||||||
RadioTap::serialization_type buffer = radio.serialize();
|
RadioTap::serialization_type buffer = radio.serialize();
|
||||||
@@ -704,4 +759,27 @@ TEST_F(RadioTapTest, RadioTapWritingEmptyBuffer) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RadioTapTest, RadioTapWritingInvalidOption) {
|
||||||
|
vector<uint8_t> buffer(4, 0);
|
||||||
|
RadioTapWriter writer(buffer);
|
||||||
|
uint8_t foo = 0;
|
||||||
|
RadioTap::option option((RadioTap::PresentFlags)(1 << RadioTapParser::MAX_RADIOTAP_FIELD), sizeof(foo), &foo);
|
||||||
|
EXPECT_THROW(writer.write_option(option), malformed_option);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RadioTapTest, RadioTapWriterAlignment) {
|
||||||
|
vector<uint8_t> buffer(4, 0);
|
||||||
|
RadioTapWriter writer(buffer);
|
||||||
|
uint8_t flags = 10;
|
||||||
|
uint8_t xchannel[sizeof(RadioTap::xchannel_type)] = {
|
||||||
|
1, 2, 3, 4, 5, 6, 7, 8
|
||||||
|
};
|
||||||
|
writer.write_option(RadioTap::option(RadioTap::FLAGS, sizeof(flags), &flags));
|
||||||
|
writer.write_option(RadioTap::option(RadioTap::XCHANNEL, sizeof(xchannel), xchannel));
|
||||||
|
vector<uint8_t> expected = {
|
||||||
|
2, 0, 4, 0, 10, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||||
|
};
|
||||||
|
EXPECT_EQ(buffer, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // TINS_HAVE_DOT11
|
#endif // TINS_HAVE_DOT11
|
||||||
|
|||||||
292
tests/src/rtp_test.cpp
Normal file
292
tests/src/rtp_test.cpp
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <string>
|
||||||
|
#include <tins/endianness.h>
|
||||||
|
#include <tins/ethernetII.h>
|
||||||
|
#include <tins/ip.h>
|
||||||
|
#include <tins/udp.h>
|
||||||
|
#include <tins/pdu.h>
|
||||||
|
#include <tins/rawpdu.h>
|
||||||
|
#include <tins/small_uint.h>
|
||||||
|
#include <tins/rtp.h>
|
||||||
|
|
||||||
|
#define PACKET_SIZE 60ul
|
||||||
|
#define CSRC_COUNT 5
|
||||||
|
#define EXTENSION_LENGTH 2
|
||||||
|
#define PAYLOAD_SIZE 12
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Tins;
|
||||||
|
|
||||||
|
class RTPTest : public testing::Test {
|
||||||
|
public:
|
||||||
|
static const uint8_t expected_packet[PACKET_SIZE];
|
||||||
|
static const uint8_t invalid_packet_one[];
|
||||||
|
static const uint8_t invalid_packet_two[];
|
||||||
|
static const uint8_t packet_with_zero_padding_value[];
|
||||||
|
static const uint8_t packet_without_data_one[];
|
||||||
|
static const uint8_t packet_without_data_two[];
|
||||||
|
static const uint8_t packet_with_zero_extension_length[];
|
||||||
|
static const small_uint<2> version;
|
||||||
|
static const small_uint<1> padding;
|
||||||
|
static const small_uint<1> extension;
|
||||||
|
static const small_uint<4> csrc_count;
|
||||||
|
static const small_uint<1> marker;
|
||||||
|
static const small_uint<7> payload_type;
|
||||||
|
static const uint16_t sequence_number;
|
||||||
|
static const uint32_t timestamp;
|
||||||
|
static const uint32_t ssrc_id;
|
||||||
|
static const uint32_t csrc_ids[CSRC_COUNT];
|
||||||
|
static const uint16_t profile;
|
||||||
|
static const uint16_t extension_length;
|
||||||
|
static const uint32_t extension_data[EXTENSION_LENGTH];
|
||||||
|
static const uint8_t padding_size;
|
||||||
|
static const uint8_t payload[PAYLOAD_SIZE];
|
||||||
|
static const uint16_t dport, sport;
|
||||||
|
static const IP::address_type dst_ip, src_ip;
|
||||||
|
static const EthernetII::address_type dst_addr, src_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::expected_packet[PACKET_SIZE] = {
|
||||||
|
0xb5, 0xaa, 0xa4, 0x10,
|
||||||
|
0xde, 0xad, 0xbe, 0xef,
|
||||||
|
0xab, 0xcd, 0xad, 0xbc,
|
||||||
|
0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x04,
|
||||||
|
0x00, 0x00, 0x00, 0x05,
|
||||||
|
0x01, 0x01, 0x00, 0x02,
|
||||||
|
0x77, 0x00, 0x00, 0x00,
|
||||||
|
0x88, 0x00, 0x00, 0x00,
|
||||||
|
0x42, 0x42, 0x42, 0x42,
|
||||||
|
0x42, 0x42, 0x42, 0x42,
|
||||||
|
0x42, 0x42, 0x42, 0x42,
|
||||||
|
0x00, 0x00, 0x00, 0x04,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::invalid_packet_one[] = {
|
||||||
|
160, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0xff,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::invalid_packet_two[] = {
|
||||||
|
160, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::packet_with_zero_padding_value[] = {
|
||||||
|
160, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::packet_without_data_one[] = {
|
||||||
|
128, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::packet_without_data_two[] = {
|
||||||
|
160, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t RTPTest::packet_with_zero_extension_length[] = {
|
||||||
|
144, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0x56, 0x97, 0, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const small_uint<2> RTPTest::version = 2;
|
||||||
|
const small_uint<1> RTPTest::padding = 1;
|
||||||
|
const small_uint<1> RTPTest::extension = 1;
|
||||||
|
const small_uint<4> RTPTest::csrc_count = CSRC_COUNT;
|
||||||
|
const small_uint<1> RTPTest::marker = 1;
|
||||||
|
const small_uint<7> RTPTest::payload_type = 42;
|
||||||
|
const uint16_t RTPTest::sequence_number = 42000;
|
||||||
|
const uint32_t RTPTest::timestamp = 0xdeadbeef;
|
||||||
|
const uint32_t RTPTest::ssrc_id = 0xabcdadbc;
|
||||||
|
const uint32_t RTPTest::csrc_ids[CSRC_COUNT] = { 1, 2, 3, 4, 5 };
|
||||||
|
const uint16_t RTPTest::profile = 0x0101;
|
||||||
|
const uint16_t RTPTest::extension_length = EXTENSION_LENGTH;
|
||||||
|
const uint32_t RTPTest::extension_data[EXTENSION_LENGTH] = { 0x77000000, 0x88000000 };
|
||||||
|
const uint8_t RTPTest::padding_size = 4;
|
||||||
|
const uint8_t RTPTest::payload[PAYLOAD_SIZE] = {
|
||||||
|
0x42, 0x42, 0x42, 0x42,
|
||||||
|
0x42, 0x42, 0x42, 0x42,
|
||||||
|
0x42, 0x42, 0x42, 0x42,
|
||||||
|
};
|
||||||
|
const uint16_t RTPTest::dport = 5004;
|
||||||
|
const uint16_t RTPTest::sport = 30000;
|
||||||
|
const IP::address_type RTPTest::dst_ip = IP::address_type{"2.2.2.2"};
|
||||||
|
const IP::address_type RTPTest::src_ip = IP::address_type{"1.1.1.1"};
|
||||||
|
const EthernetII::address_type RTPTest::dst_addr = EthernetII::address_type{"aa:bb:cc:dd:ee:ff"};
|
||||||
|
const EthernetII::address_type RTPTest::src_addr = EthernetII::address_type{"8a:8b:8c:8d:8e:8f"};
|
||||||
|
|
||||||
|
TEST_F(RTPTest, DefaultConstructor) {
|
||||||
|
auto const rtp = RTP{};
|
||||||
|
EXPECT_EQ(rtp.version(), version);
|
||||||
|
EXPECT_EQ(rtp.padding_bit(), 0);
|
||||||
|
EXPECT_EQ(rtp.extension_bit(), 0);
|
||||||
|
EXPECT_EQ(rtp.csrc_count(), 0);
|
||||||
|
EXPECT_EQ(rtp.marker_bit(), 0);
|
||||||
|
EXPECT_EQ(rtp.payload_type(), 0);
|
||||||
|
EXPECT_EQ(rtp.sequence_number(), 0);
|
||||||
|
EXPECT_EQ(rtp.timestamp(), 0);
|
||||||
|
EXPECT_EQ(rtp.ssrc_id(), 0);
|
||||||
|
EXPECT_EQ(rtp.csrc_ids().size(), 0);
|
||||||
|
EXPECT_EQ(rtp.extension_profile(), 0);
|
||||||
|
EXPECT_EQ(rtp.extension_length(), 0);
|
||||||
|
EXPECT_EQ(rtp.extension_data().size(), 0);
|
||||||
|
EXPECT_EQ(rtp.padding_size(), 0);
|
||||||
|
EXPECT_EQ(rtp.header_size(), 12);
|
||||||
|
EXPECT_EQ(rtp.trailer_size(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, Serialize) {
|
||||||
|
auto rtp = RTP{};
|
||||||
|
rtp.version(version);
|
||||||
|
rtp.padding_size(padding_size);
|
||||||
|
rtp.extension_bit(extension);
|
||||||
|
rtp.marker_bit(marker);
|
||||||
|
rtp.payload_type(payload_type);
|
||||||
|
rtp.sequence_number(sequence_number);
|
||||||
|
rtp.timestamp(timestamp);
|
||||||
|
rtp.ssrc_id(ssrc_id);
|
||||||
|
|
||||||
|
for (auto csrc_id : csrc_ids) {
|
||||||
|
rtp.add_csrc_id(csrc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtp.extension_profile(profile);
|
||||||
|
|
||||||
|
for (auto data : extension_data) {
|
||||||
|
rtp.add_extension_data(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto raw_pdu = RawPDU(payload, PAYLOAD_SIZE);
|
||||||
|
rtp.inner_pdu(raw_pdu);
|
||||||
|
|
||||||
|
EXPECT_EQ(rtp.header_size(), PACKET_SIZE - PAYLOAD_SIZE - padding_size);
|
||||||
|
EXPECT_EQ(rtp.trailer_size(), padding_size);
|
||||||
|
|
||||||
|
auto serialized = rtp.serialize();
|
||||||
|
ASSERT_EQ(serialized.size(), PACKET_SIZE);
|
||||||
|
EXPECT_TRUE(std::equal(serialized.begin(), serialized.end(), expected_packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, ConstructorFromBuffer) {
|
||||||
|
auto rtp = RTP{expected_packet, PACKET_SIZE};
|
||||||
|
EXPECT_EQ(rtp.version(), version);
|
||||||
|
EXPECT_EQ(rtp.padding_bit(), padding);
|
||||||
|
EXPECT_EQ(rtp.extension_bit(), extension);
|
||||||
|
EXPECT_EQ(rtp.csrc_count(), csrc_count);
|
||||||
|
EXPECT_EQ(rtp.marker_bit(), marker);
|
||||||
|
EXPECT_EQ(rtp.payload_type(), payload_type);
|
||||||
|
EXPECT_EQ(rtp.sequence_number(), sequence_number);
|
||||||
|
EXPECT_EQ(rtp.timestamp(), timestamp);
|
||||||
|
EXPECT_EQ(rtp.ssrc_id(), ssrc_id);
|
||||||
|
|
||||||
|
auto csrc_id_values = rtp.csrc_ids();
|
||||||
|
for (size_t i = 0; i < csrc_count; ++i) {
|
||||||
|
EXPECT_EQ(csrc_id_values[i], Endian::host_to_be(csrc_ids[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(rtp.extension_profile(), profile);
|
||||||
|
EXPECT_EQ(rtp.extension_length(), extension_length);
|
||||||
|
|
||||||
|
auto extension_data_values = rtp.extension_data();
|
||||||
|
for (size_t i = 0; i < extension_length; ++i) {
|
||||||
|
EXPECT_EQ(extension_data_values[i], Endian::host_to_be(extension_data[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(rtp.padding_size(), padding_size);
|
||||||
|
EXPECT_EQ(rtp.header_size(), PACKET_SIZE - PAYLOAD_SIZE - padding_size);
|
||||||
|
|
||||||
|
auto inner_pdu_payload = rtp.inner_pdu()->serialize();
|
||||||
|
EXPECT_TRUE(std::equal(inner_pdu_payload.begin(), inner_pdu_payload.end(), payload));
|
||||||
|
|
||||||
|
auto raw_pdu = RawPDU(payload, PAYLOAD_SIZE);
|
||||||
|
auto raw_pdu_payload = raw_pdu.serialize();
|
||||||
|
EXPECT_EQ(rtp.inner_pdu()->size(), raw_pdu.size());
|
||||||
|
EXPECT_EQ(inner_pdu_payload, raw_pdu_payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, SearchAndRemoveCSRCID) {
|
||||||
|
auto rtp = RTP{};
|
||||||
|
|
||||||
|
for (auto csrc_id : csrc_ids) {
|
||||||
|
rtp.add_csrc_id(csrc_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < csrc_count; ++i) {
|
||||||
|
EXPECT_TRUE(rtp.search_csrc_id(csrc_ids[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_FALSE(rtp.search_csrc_id(0));
|
||||||
|
EXPECT_FALSE(rtp.remove_csrc_id(0));
|
||||||
|
EXPECT_TRUE(rtp.remove_csrc_id(csrc_ids[0]));
|
||||||
|
EXPECT_FALSE(rtp.search_csrc_id(csrc_ids[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, SearchAndRemoveExtensionData) {
|
||||||
|
auto rtp = RTP{};
|
||||||
|
|
||||||
|
for (auto data : extension_data) {
|
||||||
|
rtp.add_extension_data(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < extension_length; ++i) {
|
||||||
|
EXPECT_TRUE(rtp.search_extension_data(extension_data[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_FALSE(rtp.search_extension_data(0));
|
||||||
|
EXPECT_FALSE(rtp.remove_extension_data(0));
|
||||||
|
EXPECT_TRUE(rtp.remove_extension_data(extension_data[0]));
|
||||||
|
EXPECT_FALSE(rtp.search_extension_data(extension_data[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, OuterUDP) {
|
||||||
|
auto pkt = EthernetII{dst_addr, src_addr} / IP{dst_ip, src_ip} / UDP{dport, sport} / RTP{expected_packet, PACKET_SIZE};
|
||||||
|
|
||||||
|
auto udp = pkt.find_pdu<UDP>();
|
||||||
|
ASSERT_TRUE(udp != nullptr);
|
||||||
|
EXPECT_EQ(udp->dport(), dport);
|
||||||
|
EXPECT_EQ(udp->sport(), sport);
|
||||||
|
|
||||||
|
auto rtp = udp->find_pdu<RTP>();
|
||||||
|
ASSERT_TRUE(rtp != nullptr);
|
||||||
|
EXPECT_EQ(rtp->header_size(), PACKET_SIZE - PAYLOAD_SIZE - padding_size);
|
||||||
|
EXPECT_EQ(rtp->trailer_size(), padding_size);
|
||||||
|
EXPECT_EQ(rtp->size(), PACKET_SIZE);
|
||||||
|
EXPECT_EQ(rtp->inner_pdu()->size(), PAYLOAD_SIZE);
|
||||||
|
auto inner_pdu_payload = rtp->inner_pdu()->serialize();
|
||||||
|
EXPECT_TRUE(std::equal(inner_pdu_payload.begin(), inner_pdu_payload.end(), payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, PaddingSizeTooLarge) {
|
||||||
|
EXPECT_THROW((RTP{invalid_packet_one, sizeof(invalid_packet_one)}), malformed_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, PaddingBitSetWithoutPadding) {
|
||||||
|
EXPECT_THROW((RTP{invalid_packet_two, sizeof(invalid_packet_two)}), malformed_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, PacketWithInvalidZeroPaddingValue) {
|
||||||
|
EXPECT_THROW((RTP{packet_with_zero_padding_value, sizeof(packet_with_zero_padding_value)}), malformed_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, PacketWithoutData) {
|
||||||
|
auto rtp = RTP{packet_without_data_one, sizeof(packet_without_data_one)};
|
||||||
|
EXPECT_EQ(rtp.size(), sizeof(packet_without_data_one));
|
||||||
|
EXPECT_EQ(rtp.header_size(), sizeof(packet_without_data_one));
|
||||||
|
EXPECT_EQ(rtp.inner_pdu(), nullptr);
|
||||||
|
EXPECT_EQ(rtp.padding_size(), 0);
|
||||||
|
|
||||||
|
const uint8_t padding_size_ = 7;
|
||||||
|
rtp = RTP{packet_without_data_two, sizeof(packet_without_data_two)};
|
||||||
|
EXPECT_EQ(rtp.size(), sizeof(packet_without_data_two));
|
||||||
|
EXPECT_EQ(rtp.header_size(), sizeof(packet_without_data_two) - padding_size_);
|
||||||
|
EXPECT_EQ(rtp.inner_pdu(), nullptr);
|
||||||
|
EXPECT_EQ(rtp.padding_size(), padding_size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(RTPTest, PacketWithZeroExtensionLength) {
|
||||||
|
auto rtp = RTP{packet_with_zero_extension_length, sizeof(packet_with_zero_extension_length)};
|
||||||
|
EXPECT_EQ(rtp.size(), sizeof(packet_with_zero_extension_length));
|
||||||
|
EXPECT_EQ(rtp.header_size(), sizeof(packet_with_zero_extension_length));
|
||||||
|
EXPECT_EQ(rtp.extension_profile(), 0x5697);
|
||||||
|
EXPECT_EQ(rtp.extension_length(), 0);
|
||||||
|
EXPECT_EQ(rtp.extension_data().size(), 0);
|
||||||
|
}
|
||||||
@@ -13,7 +13,8 @@ using namespace Tins;
|
|||||||
class TCPTest : public testing::Test {
|
class TCPTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
static const uint8_t expected_packet[], checksum_packet[],
|
static const uint8_t expected_packet[], checksum_packet[],
|
||||||
partial_packet[];
|
partial_packet[],
|
||||||
|
malformed_option_after_eol_packet[];
|
||||||
|
|
||||||
void test_equals(const TCP& tcp1, const TCP& tcp2);
|
void test_equals(const TCP& tcp1, const TCP& tcp2);
|
||||||
};
|
};
|
||||||
@@ -36,6 +37,11 @@ const uint8_t TCPTest::partial_packet[] = {
|
|||||||
142, 210, 0, 80, 60, 158, 102, 111, 10, 2, 46, 161, 80, 24, 0, 229, 247, 192, 0, 0
|
142, 210, 0, 80, 60, 158, 102, 111, 10, 2, 46, 161, 80, 24, 0, 229, 247, 192, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uint8_t TCPTest::malformed_option_after_eol_packet[] = {
|
||||||
|
127, 77, 79, 29, 241, 218, 229, 70, 95, 174, 209, 35, 96, 2, 113,
|
||||||
|
218, 0, 0, 31, 174, 0, 1, 2, 4
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
TEST_F(TCPTest, DefaultConstructor) {
|
TEST_F(TCPTest, DefaultConstructor) {
|
||||||
TCP tcp;
|
TCP tcp;
|
||||||
@@ -271,6 +277,11 @@ TEST_F(TCPTest, SpoofedOptions) {
|
|||||||
EXPECT_EQ(pdu.serialize().size(), pdu.size());
|
EXPECT_EQ(pdu.serialize().size(), pdu.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(TCPTest, MalformedOptionAfterEOL) {
|
||||||
|
TCP tcp(malformed_option_after_eol_packet, sizeof(malformed_option_after_eol_packet));
|
||||||
|
EXPECT_EQ(0U, tcp.options().size());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(TCPTest, RemoveOption) {
|
TEST_F(TCPTest, RemoveOption) {
|
||||||
TCP tcp(22, 987);
|
TCP tcp(22, 987);
|
||||||
uint8_t a[] = { 1,2,3,4,5,6 };
|
uint8_t a[] = { 1,2,3,4,5,6 };
|
||||||
|
|||||||
94
tests/src/vxlan_test.cpp
Normal file
94
tests/src/vxlan_test.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <string>
|
||||||
|
#include <tins/ethernetII.h>
|
||||||
|
#include <tins/ip.h>
|
||||||
|
#include <tins/tcp.h>
|
||||||
|
#include <tins/udp.h>
|
||||||
|
#include <tins/pdu.h>
|
||||||
|
#include <tins/small_uint.h>
|
||||||
|
#include <tins/vxlan.h>
|
||||||
|
|
||||||
|
#define PACKET_SIZE 68ul
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace Tins;
|
||||||
|
|
||||||
|
class VXLANTest : public testing::Test {
|
||||||
|
public:
|
||||||
|
static const uint8_t expected_packet[PACKET_SIZE];
|
||||||
|
static const uint8_t flags;
|
||||||
|
static const uint16_t dport, sport, p_type;
|
||||||
|
static const small_uint<24> vni;
|
||||||
|
static const IP::address_type dst_ip, src_ip;
|
||||||
|
static const EthernetII::address_type dst_addr, src_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t VXLANTest::expected_packet[PACKET_SIZE] = {
|
||||||
|
0x08, 0x00, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xff, 0x00,
|
||||||
|
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
|
||||||
|
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t VXLANTest::flags = 8;
|
||||||
|
const uint16_t VXLANTest::dport = 4789;
|
||||||
|
const uint16_t VXLANTest::sport = 19627;
|
||||||
|
const uint16_t VXLANTest::p_type = 0xd0ab;
|
||||||
|
const small_uint<24> VXLANTest::vni = 0xffffff;
|
||||||
|
const IP::address_type VXLANTest::dst_ip = IP::address_type{"2.2.2.2"};
|
||||||
|
const IP::address_type VXLANTest::src_ip = IP::address_type{"1.1.1.1"};
|
||||||
|
const EthernetII::address_type VXLANTest::dst_addr = EthernetII::address_type{"aa:bb:cc:dd:ee:ff"};
|
||||||
|
const EthernetII::address_type VXLANTest::src_addr = EthernetII::address_type{"8a:8b:8c:8d:8e:8f"};
|
||||||
|
|
||||||
|
TEST_F(VXLANTest, Flags) {
|
||||||
|
auto const vxlan = VXLAN{};
|
||||||
|
EXPECT_EQ(vxlan.get_flags(), flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(VXLANTest, VNI) {
|
||||||
|
auto const vxlan = VXLAN{vni};
|
||||||
|
EXPECT_EQ(vxlan.get_vni(), vni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(VXLANTest, Find) {
|
||||||
|
auto const pdu = VXLAN{} / EthernetII{dst_addr, src_addr};
|
||||||
|
auto const eth = pdu.find_pdu<EthernetII>();
|
||||||
|
ASSERT_TRUE(eth != nullptr);
|
||||||
|
EXPECT_EQ(eth->dst_addr(), dst_addr);
|
||||||
|
EXPECT_EQ(eth->src_addr(), src_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(VXLANTest, Serialize) {
|
||||||
|
auto eth = EthernetII{dst_addr, src_addr};
|
||||||
|
eth.payload_type(p_type);
|
||||||
|
auto vxlan = VXLAN{vni};
|
||||||
|
vxlan.inner_pdu(eth);
|
||||||
|
auto serialized = vxlan.serialize();
|
||||||
|
ASSERT_EQ(serialized.size(), PACKET_SIZE);
|
||||||
|
EXPECT_TRUE(std::equal(serialized.begin(), serialized.end(), expected_packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(VXLANTest, ConstructorFromBuffer) {
|
||||||
|
auto vxlan = VXLAN{expected_packet, PACKET_SIZE};
|
||||||
|
EXPECT_EQ(vxlan.get_vni(), vni);
|
||||||
|
EXPECT_EQ(vxlan.get_flags(), flags);
|
||||||
|
auto const eth = vxlan.find_pdu<EthernetII>();
|
||||||
|
ASSERT_TRUE(eth != nullptr);
|
||||||
|
EXPECT_EQ(eth->dst_addr(), dst_addr);
|
||||||
|
EXPECT_EQ(eth->src_addr(), src_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(VXLANTest, OuterUDP) {
|
||||||
|
auto pkt = IP{dst_ip, src_ip} / UDP{dport, sport} / VXLAN{expected_packet, PACKET_SIZE};
|
||||||
|
auto const udp = pkt.find_pdu<UDP>();
|
||||||
|
ASSERT_TRUE(udp != nullptr);
|
||||||
|
EXPECT_EQ(udp->dport(), dport);
|
||||||
|
EXPECT_EQ(udp->sport(), sport);
|
||||||
|
auto const vxlan = udp->find_pdu<VXLAN>();
|
||||||
|
ASSERT_TRUE(vxlan != nullptr);
|
||||||
|
EXPECT_EQ(vxlan->get_flags(), flags);
|
||||||
|
EXPECT_EQ(vxlan->get_vni(), vni);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user