1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 18:55:58 +01:00

70 Commits
v3.3 ... v3.4

Author SHA1 Message Date
Matias Fontanini
bfe9f9f4a5 Update changelog 2016-03-09 20:25:09 -08:00
Matias Fontanini
c082dfad67 Minor changes on TCPIP::StreamFollower 2016-03-06 13:40:10 -08:00
Matias Fontanini
331bc57b44 Update version 2016-03-05 16:07:11 -08:00
Matias Fontanini
b7e20f550e Use proper bssid/client hw when calling handshake captured callback 2016-03-05 10:56:03 -08:00
Matias Fontanini
e15ef0d837 Add info members directly into NetworkInterface 2016-03-05 10:33:50 -08:00
Matias Fontanini
08fd9e2d69 Check the secure bit on HandshakeCapturer to detect 2nd packet 2016-03-05 09:37:22 -08:00
Matias Fontanini
3a99213c0b Rename IPv6AddressPrefix to IPv6Prefix 2016-03-02 21:34:21 -08:00
Matias Fontanini
ad71158268 Add IPv6 addresses to NetworkInterface::Info 2016-03-02 21:13:50 -08:00
Matias Fontanini
186d23c920 Set OPENSSL_* variables to empty string if not found 2016-02-28 08:51:44 -08:00
Matias Fontanini
cfbf88bb5f Make *MemoryStream use size_t rather than uint32_t 2016-02-28 08:12:05 -08:00
Matias Fontanini
1681981fe8 Add WPA2Decrypter callback interface 2016-02-28 08:01:04 -08:00
Matias Fontanini
3e84b07a01 Set MACOSX_RPATH to ON 2016-02-27 07:57:07 -08:00
Matias Fontanini
b087c964d4 Don't fail configuration if openssl is missing 2016-02-27 07:50:56 -08:00
Matias Fontanini
bf70a94921 Build layer 5 as RawPDU if IPv6 has fragment header 2016-02-22 20:37:48 -08:00
Matias Fontanini
e5282f8a3c Fix compilation warnings 2016-02-21 18:50:47 -08:00
Matias Fontanini
5920185288 Add defragmenter example 2016-02-21 18:28:59 -08:00
Matias Fontanini
92f0249d2b Cleanup IPv4Reassembler 2016-02-21 18:20:06 -08:00
Matias Fontanini
016cfeecc6 Don't build examples on travis
Clang on OSX uses gcc 4.6's headers and apparently the chrono header
fails to build
2016-02-21 15:12:00 -08:00
Matias Fontanini
8bf0c355f4 Fix examples so they build on gcc 4.6 2016-02-21 14:59:19 -08:00
Matias Fontanini
fa4178de09 Fix flag value for sniffer's immediate mode 2016-02-21 14:42:24 -08:00
Matias Fontanini
04578b109f Build examples on travis 2016-02-21 09:44:00 -08:00
Matias Fontanini
9dabb6f570 Fix IP fragment reassemble when packet has flags DF+MF 2016-02-21 09:23:44 -08:00
Matias Fontanini
8812153491 Remove extra include on tins.h 2016-02-21 09:14:14 -08:00
Matias Fontanini
17da10d76e Add extract_metadata to main PDU classes 2016-02-20 22:19:12 -08:00
Matias Fontanini
dae25b3381 Fix examples to make them work on Windows 2016-02-20 11:13:04 -08:00
Matias Fontanini
745071af65 Use Utils::sum_range straight into ICMP checksum value 2016-02-20 11:02:20 -08:00
Matias Fontanini
f3448f1797 Use timercmp/sub and std::chrono to subtract timevals 2016-02-20 10:51:35 -08:00
Matias Fontanini
dad6091706 Build examples against local libtins build 2016-02-20 09:55:48 -08:00
Matias Fontanini
6d6eb9c5d7 Add uninstall target 2016-02-20 09:19:42 -08:00
Matias Fontanini
64b84fa91d Prefix HAVE_ config.h macros with TINS_ 2016-02-20 09:10:48 -08:00
Matias Fontanini
bac8388cec Merge pull request #130 from jopann/develop
Fixed comment spelling
2016-02-19 09:02:14 -08:00
Josh Hunter
e69d0d7ce9 Fixed comment spelling 2016-02-19 10:27:56 -06:00
Matias Fontanini
b326546229 Add checks for std::chrono and std::function 2016-02-18 20:52:18 -08:00
Matias Fontanini
5c22cc7985 Use compiler intrinsics to swap bytes 2016-02-18 20:35:37 -08:00
Matias Fontanini
bd31b3648f Change CheckCXX11Features into CheckCXXFeatures 2016-02-18 20:11:36 -08:00
Matias Fontanini
3c595e6225 Merge pull request #129 from einarjon/master
Add missing TINS_API to PDU classes. Fix ICMPv6 enums
2016-02-18 14:55:33 -08:00
Einar Gunnarsson
ed40dd423d Merge remote-tracking branch 'upstream/master' 2016-02-18 15:34:32 +01:00
Matias Fontanini
0e5d7d7ae0 Use C++11 mode by default 2016-02-17 21:04:28 -08:00
Matias Fontanini
9ef6f7a612 Initialize ACK tracker correctly 2016-02-17 20:10:22 -08:00
Matias Fontanini
da923aa63c Update Doxygen file to enable C++11 support flag 2016-02-17 20:02:07 -08:00
Einar Jón
f88d94cbaa Remove TINS_API from template PDU class 2016-02-17 19:16:15 +01:00
Einar Gunnarsson
6403d1908d add missing TINS_API to PDU classes. Extend/fix ICMPv6 enum values and unify naming 2016-02-17 17:51:54 +01:00
Matias Fontanini
423dbf2404 Return an empty string for dot11 ssid, if ssid is present but empty
References issue mentioned in #128
2016-02-16 21:28:59 -08:00
Matias Fontanini
af6b0fdbb2 Update README.md for TCP ACK tracker disabling 2016-02-15 18:19:38 -08:00
Matias Fontanini
8e7eb25558 Implement new TCP stream follower mechanism 2016-02-15 18:10:33 -08:00
Matias Fontanini
91a724fe2d Add HTTP requests example 2016-02-15 08:29:14 -08:00
Matias Fontanini
eb1c43d293 Throw proper exceptions 2016-02-14 16:51:10 -08:00
Matias Fontanini
4123764a48 Execute out of order callback even for seq < current_seq 2016-02-14 08:56:25 -08:00
Matias Fontanini
abe94ece52 Allow asking whether segment was acked 2016-02-13 22:45:11 -08:00
Matias Fontanini
2498ebf7d6 Fix ACK tracker tests build 2016-02-13 21:26:46 -08:00
Matias Fontanini
f8445c2e5c Fix travis build script 2016-02-13 20:34:39 -08:00
Matias Fontanini
116eb9f1c1 Add initial ACK tracking code 2016-02-13 20:24:15 -08:00
Matias Fontanini
48c068b84a Add callbacks for stream termination events 2016-02-13 11:23:08 -08:00
Matias Fontanini
20a3868e82 Track Stream timestamps and add timeout to StreamFollower 2016-02-11 21:18:48 -08:00
Matias Fontanini
85d7401520 Store MSS value on Flows 2016-02-10 21:24:15 -08:00
Matias Fontanini
3b848060aa Change tcp_ip directory structure 2016-02-10 20:56:13 -08:00
Matias Fontanini
69fc5ff54b Add support for out of order data packet detection 2016-02-10 20:56:13 -08:00
Matias Fontanini
8db6032303 Add hardware addresses to Stream 2016-02-10 20:56:13 -08:00
Matias Fontanini
549c0e97d0 Add Flow::ignore_data_packets 2016-02-10 20:56:13 -08:00
Matias Fontanini
c3861cf54e Fill address arrays with 0x00 2016-02-10 20:56:13 -08:00
Matias Fontanini
7c1453662f Fix compilation issues 2016-02-10 20:56:13 -08:00
Matias Fontanini
5b60b79fd8 Document new TCP stream classes 2016-02-10 20:56:13 -08:00
Matias Fontanini
07b5d74179 Refactor TCP stream code and add http_dump example 2016-02-10 20:56:13 -08:00
Matias Fontanini
76b0c919b9 Add initial code for new TCP reassembly mechanism 2016-02-10 20:56:13 -08:00
Matias Fontanini
785ee7b47b Use ExternalProject_Add rather than including the gtest directory 2016-02-09 20:35:15 -08:00
Matias Fontanini
64b267c7ea Add friendly name to interface info example 2016-02-06 16:04:51 -08:00
Matias Fontanini
0832184896 Add CONTRIBUTING.md file 2016-02-06 16:04:07 -08:00
Matias Fontanini
5d41316b9a Rename IP header member to header_ 2016-02-04 20:37:24 -08:00
Matias Fontanini
602ead5de5 Fix invalid private method name on PacketSender 2016-02-04 20:27:51 -08:00
Matias Fontanini
72e038b9bf Fix invalid endian on IP fragment offset on OSX 2016-02-04 20:20:14 -08:00
168 changed files with 5012 additions and 537 deletions

View File

@@ -15,6 +15,7 @@ addons:
packages:
- libpcap-dev
- libssl-dev
- libboost-all-dev
before_script:
- mkdir build

52
CHANGES
View File

@@ -1,3 +1,55 @@
v3.4 - Wed Mar 9 20:24:54 PST 2016
- Check the secure bit on HandshakeCapturer to detect 2nd packet
- Add info members directly into NetworkInterface
- Add IPv6 addresses to NetworkInterface::Info
- Make *MemoryStream use size_t rather than uint32_t
- Add WPA2Decrypter callback interface
- Set MACOSX_RPATH to ON
- Don't fail configuration if openssl is missing
- Build layer 5 as RawPDU if IPv6 has fragment header
- Fix examples so they build on gcc 4.6
- Fix flag value for sniffer's immediate mode
- Fix IP fragment reassemble when packet has flags DF+MF
- Add extract_metadata to main PDU classes
- Fix examples to make them work on Windows
- Use timercmp/sub and std::chrono to subtract timevals on PacketSender
- Build examples against local libtins build
- Add uninstall target
- Prefix HAVE_ config.h macros with TINS_
- Use compiler intrinsics to swap bytes
- Use C++11 mode by default
- Add missing TINS_API to PDU classes.
- Extend/fix ICMPv6 enum values and unify naming
- Return an empty string for dot11 ssid, if ssid is present but empty
- Implement new TCP stream follower mechanism
- Use ExternalProject_Add rather than including the gtest directory
- Fix invalid endian on IP fragment offset on OSX
v3.3 - Sun Jan 31 21:06:04 PST 2016
- Add TCP connection close example

View File

@@ -21,6 +21,11 @@ ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
ENDIF()
IF(APPLE)
# This is set to ON as of policy CMP0042
SET(CMAKE_MACOSX_RPATH ON)
ENDIF()
# Build output checks
OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON)
IF(LIBTINS_BUILD_SHARED)
@@ -38,7 +43,7 @@ ENDIF(LIBTINS_BUILD_SHARED)
# The version number.
SET(LIBTINS_VERSION_MAJOR 3)
SET(LIBTINS_VERSION_MINOR 3)
SET(LIBTINS_VERSION_MINOR 4)
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
# Required Packages
@@ -56,21 +61,33 @@ IF(WIN32)
ADD_DEFINITIONS(-DNOMINMAX)
ENDIF(WIN32)
INCLUDE(ExternalProject)
# *******************
# Compilation options
# *******************
# Always check for C++ features
INCLUDE(CheckCXXFeatures)
IF(HAS_GCC_BUILTIN_SWAP)
SET(TINS_HAVE_GCC_BUILTIN_SWAP ON)
ENDIF()
# C++11 support
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" OFF)
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" ON)
IF(LIBTINS_ENABLE_CXX11)
SET(HAVE_CXX11 ON)
INCLUDE(CheckCXX11Features)
IF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
# We only use declval and decltype on gcc/clang as VC fails to build that code,
# at least on VC2013
IF(HAS_CXX11_RVALUE_REFERENCES AND HAS_CXX11_FUNCTIONAL AND HAS_CXX11_CHRONO AND
((HAS_CXX11_DECLVAL AND HAS_CXX11_DECLTYPE) OR MSVC))
SET(TINS_HAVE_CXX11 ON)
MESSAGE(STATUS "Enabling C++11 features")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}")
ELSE(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
MESSAGE(FATAL_ERROR "C++11 features requested but the compiler does not support them.")
ENDIF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
ELSE()
MESSAGE(WARNING "The compiler doesn't support the necessary C++11 features. "
"Disabling C++11 on this build")
ENDIF()
ELSE(LIBTINS_ENABLE_CXX11)
MESSAGE(
WARNING
@@ -83,17 +100,46 @@ ENDIF(LIBTINS_ENABLE_CXX11)
OPTION(LIBTINS_ENABLE_DOT11 "Compile libtins with IEEE 802.11 support" ON)
OPTION(LIBTINS_ENABLE_WPA2 "Compile libtins with WPA2 decryption features (requires OpenSSL)" ON)
IF(LIBTINS_ENABLE_DOT11)
SET(HAVE_DOT11 ON)
SET(TINS_HAVE_DOT11 ON)
MESSAGE(STATUS "Enabling IEEE 802.11 support.")
IF(LIBTINS_ENABLE_WPA2)
FIND_PACKAGE(OpenSSL REQUIRED)
SET(HAVE_WPA2_DECRYPTION ON)
MESSAGE(STATUS "Enabling WPA2 decryption support.")
FIND_PACKAGE(OpenSSL)
IF(OPENSSL_FOUND)
SET(TINS_HAVE_WPA2_DECRYPTION ON)
MESSAGE(STATUS "Enabling WPA2 decryption support.")
ELSE()
MESSAGE(WARNING "Disabling WPA2 decryption support since OpenSSL was not found")
# Default this to empty strings
SET(OPENSSL_INCLUDE_DIR "")
SET(OPENSSL_LIBRARIES "")
ENDIF()
ELSE(LIBTINS_ENABLE_WPA2)
MESSAGE(STATUS "Disabling WPA2 decryption support.")
ENDIF(LIBTINS_ENABLE_WPA2)
ENDIF(LIBTINS_ENABLE_DOT11)
OPTION(LIBTINS_ENABLE_ACK_TRACKER "Enable TCP ACK tracking support" ON)
IF(LIBTINS_ENABLE_ACK_TRACKER AND TINS_HAVE_CXX11)
FIND_PACKAGE(Boost)
IF (Boost_FOUND)
MESSAGE(STATUS "Enabling TCP ACK tracking support.")
INCLUDE_DIRECTORIES(Boost_INCLUDE_DIRS)
SET(TINS_HAVE_ACK_TRACKER ON)
ELSE()
MESSAGE(WARNING "Disabling ACK tracking support as boost.icl was not found")
SET(TINS_HAVE_ACK_TRACKER OFF)
ENDIF()
ELSE()
SET(TINS_HAVE_ACK_TRACKER OFF)
MESSAGE(STATUS "Disabling ACK tracking support")
ENDIF()
OPTION(LIBTINS_ENABLE_WPA2_CALLBACKS "Enable WPA2 callback interface" ON)
IF(LIBTINS_ENABLE_WPA2_CALLBACKS AND TINS_HAVE_WPA2_DECRYPTION AND TINS_HAVE_CXX11)
SET(STATUS "Enabling WPA2 callback interface")
SET(TINS_HAVE_WPA2_CALLBACKS ON)
ENDIF()
# Use pcap_sendpacket to send l2 packets rather than raw sockets
IF(WIN32)
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
@@ -104,7 +150,7 @@ ENDIF(WIN32)
OPTION(LIBTINS_USE_PCAP_SENDPACKET "Use pcap_sendpacket to send l2 packets"
${USE_PCAP_SENDPACKET_DEFAULT})
IF(LIBTINS_USE_PCAP_SENDPACKET)
SET(HAVE_PACKET_SENDER_PCAP_SENDPACKET ON)
SET(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET ON)
MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.")
ENDIF(LIBTINS_USE_PCAP_SENDPACKET)
@@ -149,6 +195,17 @@ INSTALL(
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
)
# Confiugure the uninstall script
CONFIGURE_FILE(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY
)
# Add uninstall target
ADD_CUSTOM_TARGET(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
# ******************
# Add subdirectories
# ******************
@@ -160,11 +217,23 @@ ADD_SUBDIRECTORY(src)
IF(EXISTS "${CMAKE_SOURCE_DIR}/googletest/CMakeLists.txt")
# Enable tests and add the test directory
MESSAGE(STATUS "Tests have been enabled")
SET(gtest_force_shared_crt ON CACHE BOOL "Always use /MD")
SET(BUILD_GMOCK OFF)
SET(BUILD_GTEST ON)
SET(GOOGLETEST_ROOT ${CMAKE_SOURCE_DIR}/googletest)
SET(GOOGLETEST_INCLUDE ${GOOGLETEST_ROOT}/googletest/include)
SET(GOOGLETEST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/googletest)
SET(GOOGLETEST_LIBRARY ${GOOGLETEST_BINARY_DIR}/googletest)
ExternalProject_Add(
googletest
DOWNLOAD_COMMAND ""
SOURCE_DIR ${GOOGLETEST_ROOT}
BINARY_DIR ${GOOGLETEST_BINARY_DIR}
CMAKE_CACHE_ARGS "-DBUILD_GTEST:bool=ON" "-DBUILD_GMOCK:bool=OFF"
"-Dgtest_force_shared_crt:bool=ON"
INSTALL_COMMAND ""
)
# Make sure we build googletest before anything else
ADD_DEPENDENCIES(tins googletest)
ENABLE_TESTING()
ADD_SUBDIRECTORY(googletest)
ADD_SUBDIRECTORY(tests)
ELSE()
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")

30
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,30 @@
# Contributing
Bug reports and enhancements to the library are really valued and appreciated!
# Bug reports
If you find a bug, please report it! Bugs on the library are taken seriously
and a patch for them is usually pushed on the same day.
When reporting a bug, please make sure to indicate the platform (e.g. GNU/Linux, Windows, OSX)
in which you came across the issue, as this is essential to finding the cause.
## Packet parsing bugs
If you find a bug related to packet parsing (e.g. a field on a packet contains an
invalid value), please try to provide a pcap file that contains the packet that
was incorrectly parsed. Doing this will make it very simple to find the issue, plus
you will be asked to provide this file anyway, so this just makes things
easier.
# Pull requests
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
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
and OSX), please fix it or otherwise the PR won't be merged.

View File

@@ -36,6 +36,7 @@ cmake ../
make
```
### Static/shared build
Note that by default, only the shared object is compiled. If you would
like to generate a static library file, run:
@@ -46,6 +47,8 @@ cmake ../ -DLIBTINS_BUILD_SHARED=0
The generated static/shared library files will be located in the
_build/lib_ directory.
### C++11 support
libtins is noticeable faster if you enable _C++11_ support. Therefore,
if your compiler supports this standard, then you should enable it.
In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch:
@@ -54,6 +57,22 @@ In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch:
cmake ../ -DLIBTINS_ENABLE_CXX11=1
```
### TCP ACK tracker
The TCP ACK tracker feature requires the boost.icl library (header only).
This feature is enabled by default but will be disabled if the boost
headers are not found. You can disable this feature by using:
```Shell
cmake ../ -DLIBTINS_ENABLE_ACK_TRACKER=0
```
If your boost installation is on some non-standard path, use
the parameters shown on the
[CMake FindBoost help](https://cmake.org/cmake/help/v3.0/module/FindBoost.html)
### WPA2 decryption
If you want to disable _WPA2_ decryption support, which will remove
openssl as a dependency for compilation, use the
_LIBTINS_ENABLE_WPA2_ switch:
@@ -62,6 +81,8 @@ _LIBTINS_ENABLE_WPA2_ switch:
cmake ../ -DLIBTINS_ENABLE_WPA2=0
```
### IEEE 802.11 support
If you want to disable IEEE 802.11 support(this will also disable
RadioTap and WPA2 decryption), which will reduce the size of the
resulting library in around 20%, use the _LIBTINS_ENABLE_DOT11_ switch:
@@ -119,3 +140,8 @@ You might want to have a look at the examples located in the "examples"
directory. The same samples can be found online at:
http://libtins.github.io/examples/
## Contributing ##
If you want to report a bug or make a pull request, please have a look at
the [contributing](CONTRIBUTING.md) file before doing so.

View File

@@ -10,6 +10,7 @@
# HAS_CXX11_CONSTEXPR - constexpr keyword
# HAS_CXX11_CSTDINT_H - cstdint header
# HAS_CXX11_DECLTYPE - decltype keyword
# HAS_CXX11_DECLVAL - declval feature
# HAS_CXX11_FUNC - __func__ preprocessor constant
# HAS_CXX11_INITIALIZER_LIST - initializer list
# HAS_CXX11_LAMBDA - lambdas
@@ -68,11 +69,11 @@ endif ()
function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
if (NOT DEFINED ${RESULT_VAR})
set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11_${FEATURE_NAME}")
set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${FEATURE_NAME}")
set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXX11Features/cxx11-test-${FEATURE_NAME})
set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXXFeatures/cxx-test-${FEATURE_NAME})
set(_LOG_NAME "\"${FEATURE_NAME}\"")
message(STATUS "Checking C++11 support for ${_LOG_NAME}")
message(STATUS "Checking C++ support for ${_LOG_NAME}")
set(_SRCFILE "${_SRCFILE_BASE}.cpp")
set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
@@ -116,27 +117,31 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
if (${RESULT_VAR})
message(STATUS "Checking C++11 support for ${_LOG_NAME}: works")
message(STATUS "Checking C++ support for ${_LOG_NAME}: works")
else (${RESULT_VAR})
message(STATUS "Checking C++11 support for ${_LOG_NAME}: not supported")
message(STATUS "Checking C++ support for ${_LOG_NAME}: not supported")
endif (${RESULT_VAR})
set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++ support for ${_LOG_NAME}")
endif (NOT DEFINED ${RESULT_VAR})
endfunction(cxx11_check_feature)
cxx11_check_feature("__func__" HAS_CXX11_FUNC)
cxx11_check_feature("auto" HAS_CXX11_AUTO)
cxx11_check_feature("auto_ret_type" HAS_CXX11_AUTO_RET_TYPE)
cxx11_check_feature("class_override_final" HAS_CXX11_CLASS_OVERRIDE)
cxx11_check_feature("constexpr" HAS_CXX11_CONSTEXPR)
cxx11_check_feature("cstdint" HAS_CXX11_CSTDINT_H)
#cxx11_check_feature("regex" HAS_CXX11_LIB_REGEX)
#cxx11_check_feature("__func__" HAS_CXX11_FUNC)
#cxx11_check_feature("auto" HAS_CXX11_AUTO)
#cxx11_check_feature("auto_ret_type" HAS_CXX11_AUTO_RET_TYPE)
#cxx11_check_feature("class_override_final" HAS_CXX11_CLASS_OVERRIDE)
#cxx11_check_feature("constexpr" HAS_CXX11_CONSTEXPR)
#cxx11_check_feature("cstdint" HAS_CXX11_CSTDINT_H)
#cxx11_check_feature("lambda" HAS_CXX11_LAMBDA)
#cxx11_check_feature("long_long" HAS_CXX11_LONG_LONG)
#cxx11_check_feature("nullptr" HAS_CXX11_NULLPTR)
#cxx11_check_feature("sizeof_member" HAS_CXX11_SIZEOF_MEMBER)
#cxx11_check_feature("static_assert" HAS_CXX11_STATIC_ASSERT)
#cxx11_check_feature("variadic_templates" HAS_CXX11_VARIADIC_TEMPLATES)
cxx11_check_feature("decltype" HAS_CXX11_DECLTYPE)
cxx11_check_feature("declval" HAS_CXX11_DECLVAL)
cxx11_check_feature("initializer_list" HAS_CXX11_INITIALIZER_LIST)
cxx11_check_feature("lambda" HAS_CXX11_LAMBDA)
cxx11_check_feature("long_long" HAS_CXX11_LONG_LONG)
cxx11_check_feature("nullptr" HAS_CXX11_NULLPTR)
cxx11_check_feature("regex" HAS_CXX11_LIB_REGEX)
cxx11_check_feature("rvalue-references" HAS_CXX11_RVALUE_REFERENCES)
cxx11_check_feature("sizeof_member" HAS_CXX11_SIZEOF_MEMBER)
cxx11_check_feature("static_assert" HAS_CXX11_STATIC_ASSERT)
cxx11_check_feature("variadic_templates" HAS_CXX11_VARIADIC_TEMPLATES)
cxx11_check_feature("functional" HAS_CXX11_FUNCTIONAL)
cxx11_check_feature("chrono" HAS_CXX11_CHRONO)
cxx11_check_feature("builtin-swap" HAS_GCC_BUILTIN_SWAP)

View File

@@ -0,0 +1,8 @@
#include <stdint.h>
int main() {
uint16_t u16 = __builtin_bswap16(0x9812U);
uint32_t u32 = __builtin_bswap32(0x9812ad81U);
uint64_t u64 = __builtin_bswap64(0x9812ad81f61a890dU);
return (u16 > 0 && u32 > 0 && u64 > 0) ? 0 : 1;
}

View File

@@ -0,0 +1,9 @@
#include <chrono>
using namespace std::chrono;
int main() {
system_clock::time_point tp = system_clock::now();
milliseconds ms = duration_cast<milliseconds>(tp.time_since_epoch());
return (ms.count() > 0) ? 0 : 1;
}

View File

@@ -0,0 +1,19 @@
// Example code taken from http://en.cppreference.com/w/cpp/utility/declval
#include <utility>
#include <iostream>
struct Default { int foo() const { return 1; } };
struct NonDefault
{
NonDefault(const NonDefault&) { }
int foo() const { return 1; }
};
int main()
{
decltype(Default().foo()) n1 = 1; // type of n1 is int
decltype(std::declval<NonDefault>().foo()) n2 = n1; // type of n2 is int
return (n1 == 1 && n2 == 1) ? 0 : 1;
}

View File

@@ -0,0 +1,11 @@
#include <functional>
int add(int x, int y) {
return x + y;
}
int main() {
std::function<int(int, int)> func;
func = std::bind(&add, std::placeholders::_1, std::placeholders::_2);
return (func(2, 2) == 4) ? 0 : 1;
}

View File

@@ -19,7 +19,7 @@ before_build:
- mkdir build
- cd build
- if "%platform%"=="x64" ( set GENERATOR="Visual Studio 12 Win64" ) else ( set GENERATOR="Visual Studio 12" )
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0 -DLIBTINS_ENABLE_CXX11=1
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0
build:
project: C:/projects/libtins/build/libtins.sln
verbosity: minimal
@@ -37,7 +37,7 @@ after_build:
- 7z a libtins-%platform%-%Configuration%.zip libtins
test_script:
- cd c:\projects\libtins\build
- ctest -C %Configuration%
- ctest -C %Configuration% -V
deploy_script:
- ps: Push-AppveyorArtifact "install\libtins-$env:Platform-$env:Configuration.zip"
skip_commits:

View File

@@ -0,0 +1,23 @@
# Taken from https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

View File

@@ -1365,7 +1365,8 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED =
PREDEFINED = "TINS_IS_CXX11=1" \
"TINS_HAVE_WPA2_CALLBACKS=1"
# 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.

View File

@@ -1,73 +1,81 @@
FIND_PACKAGE(libtins QUIET)
FIND_PACKAGE(Threads QUIET)
FIND_PACKAGE(Boost COMPONENTS regex)
IF(libtins_FOUND)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples)
INCLUDE_DIRECTORIES(
${LIBTINS_INCLUDE_DIRS}
${PCAP_INCLUDE_DIR}
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples)
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/../include
${PCAP_INCLUDE_DIR}
)
LINK_LIBRARIES(tins)
IF(TINS_HAVE_CXX11)
SET(LIBTINS_CXX11_EXAMPLES
arpmonitor
dns_queries
dns_spoof
dns_stats
stream_dump
icmp_responses
interfaces_info
tcp_connection_close
traceroute
wps_detect
)
LINK_LIBRARIES(${LIBTINS_LIBRARIES})
IF(HAVE_CXX11)
SET(LIBTINS_CXX11_EXAMPLES
arpmonitor
dns_queries
dns_spoof
dns_stats
icmp_responses
interfaces_info
tcp_connection_close
traceroute
wps_detect
)
ELSE(HAVE_CXX11)
MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.")
ENDIF(HAVE_CXX11)
ADD_CUSTOM_TARGET(
examples DEPENDS
arpspoofing
${LIBTINS_CXX11_EXAMPLES}
beacon_display
portscan
route_table
)
ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp)
ADD_EXECUTABLE(route_table EXCLUDE_FROM_ALL route_table.cpp)
IF(HAVE_CXX11)
ADD_EXECUTABLE(arpmonitor EXCLUDE_FROM_ALL arpmonitor.cpp)
ADD_EXECUTABLE(dns_queries EXCLUDE_FROM_ALL dns_queries.cpp)
ADD_EXECUTABLE(dns_spoof EXCLUDE_FROM_ALL dns_spoof.cpp)
ADD_EXECUTABLE(icmp_responses EXCLUDE_FROM_ALL icmp_responses.cpp)
ADD_EXECUTABLE(interfaces_info EXCLUDE_FROM_ALL interfaces_info.cpp)
ADD_EXECUTABLE(tcp_connection_close EXCLUDE_FROM_ALL tcp_connection_close.cpp)
ADD_EXECUTABLE(wps_detect EXCLUDE_FROM_ALL wps_detect.cpp)
ENDIF(HAVE_CXX11)
ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp)
if(THREADS_FOUND)
IF(HAVE_CXX11)
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
ADD_EXECUTABLE(dns_stats EXCLUDE_FROM_ALL dns_stats.cpp)
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(dns_stats ${CMAKE_THREAD_LIBS_INIT})
ENDIF(HAVE_CXX11)
IF(WIN32)
MESSAGE(WARNING "Disabling portscan example since it doesn't compile on Windows.")
ELSE()
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
ENDIF()
IF(Boost_REGEX_FOUND)
SET(LIBTINS_CXX11_EXAMPLES ${LIBTINS_CXX11_EXAMPLES} http_requests)
ELSE()
MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.")
MESSAGE(WARNING "Disabling HTTP requests example since boost.regex was not found")
ENDIF()
ELSE(libtins_FOUND)
MESSAGE(
WARNING
"Disabling examples since libtins is not installed. "
"Run cmake again once it is installed in order to compile them."
)
ENDIF(libtins_FOUND)
ELSE(TINS_HAVE_CXX11)
MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.")
ENDIF(TINS_HAVE_CXX11)
ADD_CUSTOM_TARGET(
examples DEPENDS
arpspoofing
${LIBTINS_CXX11_EXAMPLES}
beacon_display
portscan
route_table
defragmenter
)
# Make sure we first build libtins
ADD_DEPENDENCIES(examples tins)
ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp)
ADD_EXECUTABLE(route_table EXCLUDE_FROM_ALL route_table.cpp)
ADD_EXECUTABLE(defragmenter EXCLUDE_FROM_ALL defragmenter.cpp)
IF(TINS_HAVE_CXX11)
ADD_EXECUTABLE(arpmonitor EXCLUDE_FROM_ALL arpmonitor.cpp)
ADD_EXECUTABLE(dns_queries EXCLUDE_FROM_ALL dns_queries.cpp)
ADD_EXECUTABLE(dns_spoof EXCLUDE_FROM_ALL dns_spoof.cpp)
ADD_EXECUTABLE(stream_dump EXCLUDE_FROM_ALL stream_dump.cpp)
ADD_EXECUTABLE(icmp_responses EXCLUDE_FROM_ALL icmp_responses.cpp)
ADD_EXECUTABLE(interfaces_info EXCLUDE_FROM_ALL interfaces_info.cpp)
ADD_EXECUTABLE(tcp_connection_close EXCLUDE_FROM_ALL tcp_connection_close.cpp)
ADD_EXECUTABLE(wps_detect EXCLUDE_FROM_ALL wps_detect.cpp)
IF (Boost_REGEX_FOUND)
ADD_EXECUTABLE(http_requests EXCLUDE_FROM_ALL http_requests.cpp)
TARGET_LINK_LIBRARIES(http_requests ${Boost_LIBRARIES})
ENDIF()
ENDIF(TINS_HAVE_CXX11)
ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp)
if(THREADS_FOUND)
IF(TINS_HAVE_CXX11)
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
ADD_EXECUTABLE(dns_stats EXCLUDE_FROM_ALL dns_stats.cpp)
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
TARGET_LINK_LIBRARIES(dns_stats ${CMAKE_THREAD_LIBS_INIT})
ENDIF(TINS_HAVE_CXX11)
IF(WIN32)
MESSAGE(WARNING "Disabling portscan example since it doesn't compile on Windows.")
ELSE()
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
ENDIF()
ELSE()
MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.")
ENDIF()

118
examples/defragmenter.cpp Normal file
View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <string>
#include <stdexcept>
#include "tins/ip.h"
#include "tins/ip_reassembler.h"
#include "tins/sniffer.h"
#include "tins/packet_writer.h"
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::exception;
using Tins::IPv4Reassembler;
using Tins::IP;
using Tins::Packet;
using Tins::FileSniffer;
using Tins::PacketWriter;
using Tins::DataLinkType;
// This example reads packets from a pcap file and writes them to a new file.
// If any IPv4 fragmented packets are found in the input file, then they will
// be reassembled before writing them, so instead of the individual fragments
// it will write the whole packet.
class Defragmenter {
public:
// Construct the sniffer and the packet writer using the sniffer's
// data link type
Defragmenter(const string& input_file, const string& output_file)
: sniffer_(input_file),
writer_(output_file, (PacketWriter::LinkType)sniffer_.link_type()),
total_reassembled_(0) {
}
void run() {
Packet packet;
// Read packets and keep going until there's no more packets to read
while (packet = sniffer_.next_packet()) {
// Try to reassemble the packet
IPv4Reassembler::PacketStatus status = reassembler_.process(*packet.pdu());
// If we did reassemble it, increase this counter
if (status == IPv4Reassembler::REASSEMBLED) {
total_reassembled_++;
}
// Regardless, we'll write it into the output file unless it's fragmented
// (and not yet reassembled)
if (status != IPv4Reassembler::FRAGMENTED) {
writer_.write(packet);
}
}
}
uint64_t total_packets_reassembled() const {
return total_reassembled_;
}
private:
FileSniffer sniffer_;
IPv4Reassembler reassembler_;
PacketWriter writer_;
uint64_t total_reassembled_;
};
int main(int argc, char* argv[]) {
if (argc != 3) {
cout << "Usage: " << argv[0] << " <input-file> <output-file>" << endl;
return 1;
}
try {
// Build the defragmented
Defragmenter defragmenter(argv[1], argv[2]);
cout << "Processing " << argv[1] << endl;
cout << "Writing results to " << argv[2] << endl;
// Run!
defragmenter.run();
cout << "Done" << endl;
cout << "Reassembled: " << defragmenter.total_packets_reassembled()
<< " packet(s)" << endl;
}
catch (exception& ex) {
cerr << "Error: " << ex.what() << endl;
}
}

View File

@@ -31,6 +31,9 @@
#define NOMINMAX
#endif // _WIN32
// Fix for gcc 4.6
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream>
#include <mutex>
#include <chrono>
@@ -65,8 +68,8 @@ using namespace Tins;
template<typename Duration>
class statistics {
public:
using duration_type = Duration;
using locker_type = lock_guard<mutex>;
typedef Duration duration_type;
typedef lock_guard<mutex> locker_type;
struct information {
duration_type average, worst;
@@ -108,18 +111,18 @@ private:
class dns_monitor {
public:
// The response times are measured in milliseconds
using duration_type = milliseconds;
typedef milliseconds duration_type;
// The statistics type used.
using statistics_type = statistics<duration_type>;
typedef statistics<duration_type> statistics_type;
void run(BaseSniffer& sniffer);
const statistics_type& stats() const {
return m_stats;
}
private:
using packet_info = tuple<IPv4Address, IPv4Address, uint16_t>;
using clock_type = system_clock;
using time_point_type = clock_type::time_point;
typedef tuple<IPv4Address, IPv4Address, uint16_t> packet_info;
typedef system_clock clock_type;
typedef clock_type::time_point time_point_type;
bool callback(const PDU& pdu);
static packet_info make_packet_info(const PDU& pdu, const DNS& dns);

147
examples/http_requests.cpp Normal file
View File

@@ -0,0 +1,147 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/regex.hpp>
#include "tins/tcp_ip/stream_follower.h"
#include "tins/sniffer.h"
using std::string;
using std::cout;
using std::cerr;
using std::endl;
using std::exception;
using boost::regex;
using boost::match_results;
using Tins::PDU;
using Tins::Sniffer;
using Tins::SnifferConfiguration;
using Tins::TCPIP::Stream;
using Tins::TCPIP::StreamFollower;
// This example captures and follows TCP streams seen on port 80. It will
// wait until both the client and server send data and then apply a regex
// to both payloads, extrating some information and printing it.
// Don't buffer more than 3kb of data in either request/response
const size_t MAX_PAYLOAD = 3 * 1024;
// The regex to be applied on the request. This will extract the HTTP
// method being used, the request's path and the Host header value.
regex request_regex("([\\w]+) ([^ ]+).+\r\nHost: ([\\d\\w\\.-]+)\r\n");
// The regex to be applied on the response. This finds the response code.
regex response_regex("HTTP/[^ ]+ ([\\d]+)");
void on_server_data(Stream& stream) {
match_results<Stream::payload_type::const_iterator> client_match;
match_results<Stream::payload_type::const_iterator> server_match;
const Stream::payload_type& client_payload = stream.client_payload();
const Stream::payload_type& server_payload = stream.server_payload();
// Run the regexes on client/server payloads
bool valid = regex_search(server_payload.begin(), server_payload.end(),
server_match, response_regex) &&
regex_search(client_payload.begin(), client_payload.end(),
client_match, request_regex);
// If we matched both the client and the server regexes
if (valid) {
// Extract all fields
string method = string(client_match[1].first, client_match[1].second);
string url = string(client_match[2].first, client_match[2].second);
string host = string(client_match[3].first, client_match[3].second);
string response_code = string(server_match[1].first, server_match[1].second);
// Now print them
cout << method << " http://" << host << url << " -> " << response_code << endl;
// Once we've seen the first request on this stream, ignore it
stream.ignore_client_data();
stream.ignore_server_data();
}
// Just in case the server returns invalid data, stop at 3kb
if (stream.server_payload().size() > MAX_PAYLOAD) {
stream.ignore_server_data();
}
}
void on_client_data(Stream& stream) {
// Don't hold more than 3kb of data from the client's flow
if (stream.client_payload().size() > MAX_PAYLOAD) {
stream.ignore_client_data();
}
}
void on_new_connection(Stream& stream) {
stream.client_data_callback(&on_client_data);
stream.server_data_callback(&on_server_data);
// Don't automatically cleanup the stream's data, as we'll manage
// the buffer ourselves and let it grow until we see a full request
// and response
stream.auto_cleanup_payloads(false);
}
int main(int argc, char* argv[]) {
if (argc != 2) {
cout << "Usage: " << argv[0] << " <interface>" << endl;
return 1;
}
try {
// Construct the sniffer configuration object
SnifferConfiguration config;
// Get packets as quickly as possible
config.set_immediate_mode(true);
// Only capture TCP traffic sent from/to port 80
config.set_filter("tcp port 80");
// Construct the sniffer we'll use
Sniffer sniffer(argv[1], config);
cout << "Starting capture on interface " << argv[1] << endl;
// Now construct the stream follower
StreamFollower follower;
// We just need to specify the callback to be executed when a new
// stream is captured. In this stream, you should define which callbacks
// will be executed whenever new data is sent on that stream
// (see on_new_connection)
follower.new_stream_callback(&on_new_connection);
// Now start capturing. Every time there's a new packet, call
// follower.process_packet
sniffer.sniff_loop([&](PDU& packet) {
follower.process_packet(packet);
return true;
});
}
catch (exception& ex) {
cerr << "Error: " << ex.what() << endl;
return 1;
}
}

View File

@@ -29,11 +29,14 @@
#include <string>
#include <iostream>
#include <sstream>
#include <tins/network_interface.h>
using std::cout;
using std::wcout;
using std::endl;
using std::string;
using std::ostringstream;
using namespace Tins;
@@ -50,12 +53,35 @@ int main() {
NetworkInterface::Info info = iface.info();
// Now print all of this info.
cout << name << ": " << endl;
cout << " HW address: " << info.hw_addr << endl
<< " IP address: " << info.ip_addr << endl
<< " Netmask: " << info.netmask << endl
<< " Broadcast: " << info.bcast_addr << endl
<< " Iface index: " << iface.id() << endl
<< " Status: " << "interface " << status << endl << endl;
cout << name;
#ifdef _WIN32
// If this is running on Windows, also print the friendly name
wcout << " (" << iface.friendly_name() << ")";
#endif // _WIN32
cout << ": " << endl;
string ipv6_string;
if (info.ipv6_addrs.empty()) {
ipv6_string = "(none)";
}
else {
ostringstream oss;
for (size_t i = 0; i < info.ipv6_addrs.size(); ++i) {
const NetworkInterface::IPv6Prefix& prefix = info.ipv6_addrs[i];
if (i > 0) {
oss << ", ";
}
oss << prefix.address << "/" << prefix.prefix_length;
}
ipv6_string = oss.str();
}
cout << " HW address: " << info.hw_addr << endl
<< " IP address: " << info.ip_addr << endl
<< " IPv6 addresses: " << ipv6_string << endl
<< " Netmask: " << info.netmask << endl
<< " Broadcast: " << info.bcast_addr << endl
<< " Iface index: " << iface.id() << endl
<< " Status: " << "interface " << status << endl << endl;
}
}

162
examples/stream_dump.cpp Normal file
View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <sstream>
#include "tins/tcp_ip/stream_follower.h"
#include "tins/sniffer.h"
#include "tins/packet.h"
#include "tins/ip_address.h"
#include "tins/ipv6_address.h"
using std::cout;
using std::cerr;
using std::endl;
using std::bind;
using std::string;
using std::to_string;
using std::ostringstream;
using std::exception;
using Tins::Sniffer;
using Tins::SnifferConfiguration;
using Tins::PDU;
using Tins::TCPIP::StreamFollower;
using Tins::TCPIP::Stream;
// This example takes an interface and a port as an argument and
// it listens for TCP streams on the given interface and port.
// It will reassemble TCP streams and show the traffic sent by
// both the client and the server.
// Convert the client endpoint to a readable string
string client_endpoint(const Stream& stream) {
ostringstream output;
// Use the IPv4 or IPv6 address depending on which protocol the
// connection uses
if (stream.is_v6()) {
output << stream.client_addr_v6();
}
else {
output << stream.client_addr_v4();
}
output << ":" << stream.client_port();
return output.str();
}
// Convert the server endpoint to a readable string
string server_endpoint(const Stream& stream) {
ostringstream output;
if (stream.is_v6()) {
output << stream.server_addr_v6();
}
else {
output << stream.server_addr_v4();
}
output << ":" << stream.server_port();
return output.str();
}
// Concat both endpoints to get a readable stream identifier
string stream_identifier(const Stream& stream) {
ostringstream output;
output << client_endpoint(stream) << " - " << server_endpoint(stream);
return output.str();
}
// Whenever there's new client data on the stream, this callback is executed.
void on_client_data(Stream& stream) {
// Construct a string out of the contents of the client's payload
string data(stream.client_payload().begin(), stream.client_payload().end());
// Now print it, prepending some information about the stream
cout << client_endpoint(stream) << " >> "
<< server_endpoint(stream) << ": " << endl << data << endl;
}
// Whenever there's new server data on the stream, this callback is executed.
// This does the same thing as on_client_data
void on_server_data(Stream& stream) {
string data(stream.server_payload().begin(), stream.server_payload().end());
cout << server_endpoint(stream) << " >> "
<< client_endpoint(stream) << ": " << endl << data << endl;
}
// When a connection is closed, this callback is executed.
void on_connection_closed(Stream& stream) {
cout << "[+] Connection closed: " << stream_identifier(stream) << endl;
}
// When a new connection is captured, this callback will be executed.
void on_new_connection(Stream& stream) {
// Print some information about the new connection
cout << "[+] New connection " << stream_identifier(stream) << endl;
// Now configure the callbacks on it.
// First, we want on_client_data to be called every time there's new client data
stream.client_data_callback(&on_client_data);
// Same thing for server data, but calling on_server_data
stream.server_data_callback(&on_server_data);
// When the connection is closed, call on_connection_closed
stream.stream_closed_callback(&on_connection_closed);
}
int main(int argc, char* argv[]) {
if (argc != 3) {
cout << "Usage: " << argv[0] << " <interface> <port>" << endl;
return 1;
}
try {
// Construct the sniffer configuration object
SnifferConfiguration config;
// Only capture TCP traffic sent from/to the given port
config.set_filter("tcp port " + to_string(stoi(string(argv[2]))));
// Construct the sniffer we'll use
Sniffer sniffer(argv[1], config);
cout << "Starting capture on interface " << argv[1] << endl;
// Now construct the stream follower
StreamFollower follower;
// We just need to specify the callback to be executed when a new
// stream is captured. In this stream, you should define which callbacks
// will be executed whenever new data is sent on that stream
// (see on_new_connection)
follower.new_stream_callback(&on_new_connection);
// Now start capturing. Every time there's a new packet, call
// follower.process_packet
sniffer.sniff_loop([&](PDU& packet) {
follower.process_packet(packet);
return true;
});
}
catch (exception& ex) {
cerr << "Error: " << ex.what() << endl;
return 1;
}
}

View File

@@ -29,6 +29,7 @@
#include <iostream>
#include <string>
#include <functional>
#include <tins/tins.h>
using std::string;

View File

@@ -31,6 +31,9 @@
#define NOMINMAX
#endif // _WIN32
// Fix for gcc 4.6
#define _GLIBCXX_USE_NANOSLEEP
#include <iostream>
#include <chrono>
#include <thread>
@@ -128,7 +131,7 @@ private:
}
sender.send(ip);
// Give him a little time
// Give it a little time
sleep_for(milliseconds(100));
}
running = false;

View File

@@ -5,3 +5,4 @@ INSTALL(
COMPONENT Headers
)
ADD_SUBDIRECTORY(dot11)
ADD_SUBDIRECTORY(tcp_ip)

View File

@@ -72,6 +72,14 @@ public:
REPLY = 0x0002
};
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructs an ARP object using the provided addresses.
*

View File

@@ -333,7 +333,7 @@ protected:
vend_type& vend() { return vend_; }
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
private:
/**
* Struct that represents the Bootp datagram.
*/
@@ -355,6 +355,7 @@ private:
uint8_t file[128];
} TINS_END_PACK;
private:
bootp_header bootp_;
vend_type vend_;
};

View File

@@ -2,15 +2,24 @@
#define TINS_CONFIG_H
/* Define if the compiler supports basic C++11 syntax */
#cmakedefine HAVE_CXX11
#cmakedefine TINS_HAVE_CXX11
/* Have IEEE 802.11 support */
#cmakedefine HAVE_DOT11
#cmakedefine TINS_HAVE_DOT11
/* Have WPA2 decryption library */
#cmakedefine HAVE_WPA2_DECRYPTION
#cmakedefine TINS_HAVE_WPA2_DECRYPTION
/* Use pcap_sendpacket to send l2 packets */
#cmakedefine HAVE_PACKET_SENDER_PCAP_SENDPACKET
#cmakedefine TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
/* Have TCP ACK tracking */
#cmakedefine TINS_HAVE_ACK_TRACKER
/* Have GCC builtin swap */
#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP
/* Have WPA2Decrypter callbacks */
#cmakedefine TINS_HAVE_WPA2_CALLBACKS
#endif // TINS_CONFIG_H

View File

@@ -29,13 +29,16 @@
#include "config.h"
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
#if !defined(TINS_CRYPTO_H) && defined(TINS_HAVE_DOT11)
#define TINS_CRYPTO_H
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#ifdef TINS_HAVE_WPA2_CALLBACKS
#include <functional>
#endif // TINS_HAVE_WPA2_CALLBACKS
#include "utils.h"
#include "snap.h"
#include "rawpdu.h"
@@ -52,7 +55,7 @@ namespace Crypto {
struct RC4Key;
#ifdef HAVE_WPA2_DECRYPTION
#ifdef TINS_HAVE_WPA2_DECRYPTION
namespace WPA2 {
/**
@@ -160,12 +163,19 @@ public:
* \return The generated PMK.
*/
const pmk_type& pmk() const;
/**
* \brief Getter for the SSID
* \return The access point's SSID
*/
const std::string& ssid() const;
private:
pmk_type pmk_;
std::string ssid_;
};
} // WPA2
#endif // HAVE_WPA2_DECRYPTION
#endif // TINS_HAVE_WPA2_DECRYPTION
/**
* \brief RC4 Key abstraction.
@@ -240,7 +250,7 @@ private:
std::vector<uint8_t> key_buffer_;
};
#ifdef HAVE_WPA2_DECRYPTION
#ifdef TINS_HAVE_WPA2_DECRYPTION
/**
* \brief Decrypts WPA2-encrypted traffic.
*
@@ -275,6 +285,32 @@ public:
*/
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
#ifdef TINS_HAVE_WPA2_CALLBACKS
/**
* \brief The type used to store the callback type used when a new access
* point is found.
*
* The first argument to the function will be the access point's SSID and
* the second one its BSSID.
*/
typedef std::function<void(const std::string&,
const address_type&)> ap_found_callback_type;
/**
* The type used to store the callback type used when a new handshake
* is captured.
*
* The first argument to the function will be the access point's SSID and
* the second one its BSSID. The third argument will be the client's hardware
* address.
*/
typedef std::function<void(const std::string&,
const address_type&,
const address_type&)> handshake_captured_callback_type;
#endif // TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Adds an access points's information.
*
@@ -353,6 +389,30 @@ public:
*/
bool decrypt(PDU& pdu);
#ifdef TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Sets the handshake captured callback
*
* This callback will be executed every time a new handshake is captured.
*
* \sa handshake_captured_callback_type
* \param callback The new callback to be set
*/
void handshake_captured_callback(const handshake_captured_callback_type& callback);
/**
* \brief Sets the access point found callback
*
* This callback will be executed every time a new access point is found, that's
* advertising an SSID added when calling add_ap_data.
*
* \sa ap_found_callback_type
* \param callback The new callback to be set
*/
void ap_found_callback(const ap_found_callback_type& callback);
#endif // TINS_HAVE_WPA2_CALLBACKS
/**
* \brief Getter for the keys on this decrypter
*
@@ -381,8 +441,12 @@ private:
pmks_map pmks_;
bssids_map aps_;
keys_map keys_;
#ifdef TINS_HAVE_WPA2_CALLBACKS
handshake_captured_callback_type handshake_captured_callback_;
ap_found_callback_type ap_found_callback_;
#endif // TINS_HAVE_WPA2_CALLBACKS
};
#endif // HAVE_WPA2_DECRYPTION
#endif // TINS_HAVE_WPA2_DECRYPTION
/**
* \brief Pluggable decrypter object which can be used to decrypt
@@ -459,7 +523,7 @@ void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator
template<typename Functor>
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor);
#ifdef HAVE_WPA2_DECRYPTION
#ifdef TINS_HAVE_WPA2_DECRYPTION
/**
* \brief Wrapper function to create a DecrypterProxy using a
* WPA2Decrypter as the Decrypter template parameter.
@@ -471,7 +535,7 @@ template<typename Functor>
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor& functor) {
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
}
#endif // HAVE_WPA2_DECRYPTION
#endif // TINS_HAVE_WPA2_DECRYPTION
// Implementation section

View File

@@ -40,7 +40,7 @@
#define TINS_CXXSTD_GCC_FIX 0
#endif // __GXX_EXPERIMENTAL_CXX0X__
#if !defined(TINS_IS_CXX11) && defined(HAVE_CXX11)
#if !defined(TINS_IS_CXX11) && defined(TINS_HAVE_CXX11)
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800)
#elif !defined(TINS_IS_CXX11)
#define TINS_IS_CXX11 0

View File

@@ -172,6 +172,14 @@ public:
*/
typedef std::list<option> options_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Creates an instance of DHCP.
*

View File

@@ -412,6 +412,14 @@ public:
*/
typedef std::vector<uint8_t> interface_id_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* Default constructor.
*/
@@ -854,7 +862,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -589,6 +589,14 @@ public:
typedef IPv4Address address_type;
typedef IPv6Address address_v6_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Default constructor.
*

View File

@@ -29,7 +29,7 @@
#include "config.h"
#if !defined(TINS_DOT_11) && defined(HAVE_DOT11)
#if !defined(TINS_DOT_11) && defined(TINS_HAVE_DOT11)
#define TINS_DOT_11
#include "dot11/dot11_base.h"

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_ASSOC_H
#include "../dot11/dot11_mgmt.h"

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_AUTH_H
#include "../dot11/dot11_mgmt.h"

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_H
#include <list>

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_BEACON_H
#include "../dot11/dot11_mgmt.h"

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_CONTROL_H

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_DATA_H
#include "../dot11/dot11_base.h"

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_MGMT_H

View File

@@ -29,7 +29,7 @@
#include "../config.h"
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(HAVE_DOT11)
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(TINS_HAVE_DOT11)
#define TINS_DOT11_DOT11_PROBE_H

View File

@@ -48,6 +48,14 @@ public:
*/
static const PDU::PDUType pdu_flag = PDU::DOT1Q;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* Default constructor
*/
@@ -73,7 +81,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
@@ -192,7 +200,7 @@ private:
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
TINS_BEGIN_PACK
struct dot1q_hdr {
struct dot1q_header {
#if TINS_IS_BIG_ENDIAN
uint16_t priority:3,
cfi:1,
@@ -207,9 +215,9 @@ private:
#endif
} TINS_END_PACK;
static uint16_t get_id(const dot1q_hdr* hdr);
static uint16_t get_id(const dot1q_header* hdr);
dot1q_hdr header_;
dot1q_header header_;
bool append_padding_;
};
}

View File

@@ -60,6 +60,14 @@ public:
*/
static const address_type BROADCAST;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructor for creating an Dot3 PDU
*
@@ -71,7 +79,7 @@ public:
* \param child The PDU which will be set as the inner PDU.
*/
Dot3(const address_type& dst_hw_addr = address_type(),
const address_type& src_hw_addr = address_type());
const address_type& src_hw_addr = address_type());
/**
* \brief Constructs a Dot3 object from a buffer and adds a
@@ -145,12 +153,12 @@ public:
*/
uint32_t header_size() const;
#if !defined(_WIN32) || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
#if !defined(_WIN32) || defined(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/**
* \sa PDU::send()
*/
void send(PacketSender& sender, const NetworkInterface& iface);
#endif // !_WIN32 || HAVE_PACKET_SENDER_PCAP_SENDPACKET
#endif // !_WIN32 || TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
/**
* \brief Check whether ptr points to a valid response for this PDU.

View File

@@ -69,6 +69,14 @@ public:
EAPOL_WPA = 254
};
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Static method to instantiate the correct EAPOL subclass
* based on a raw buffer.
@@ -338,7 +346,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* This method overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
@@ -603,7 +611,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* This method overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size

View File

@@ -42,6 +42,7 @@
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
#elif defined(_WIN32)
#include <cstdlib>
// Assume windows == little endian. fixme later
#define TINS_IS_LITTLE_ENDIAN 1
#define TINS_IS_BIG_ENDIAN 0
@@ -51,6 +52,19 @@
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
#endif
// Define macros to swap bytes using compiler intrinsics when possible
#if defined(_MSC_VER)
#define TINS_BYTE_SWAP_16(data) _byteswap_ushort(data)
#define TINS_BYTE_SWAP_32(data) _byteswap_ulong(data)
#define TINS_BYTE_SWAP_64(data) _byteswap_uint64(data)
#elif defined(TINS_HAVE_GCC_BUILTIN_SWAP)
#define TINS_BYTE_SWAP_16(data) __builtin_bswap16(data)
#define TINS_BYTE_SWAP_32(data) __builtin_bswap32(data)
#define TINS_BYTE_SWAP_64(data) __builtin_bswap64(data)
#else
#define TINS_NO_BYTE_SWAP_INTRINSICS
#endif
namespace Tins {
namespace Endian {
@@ -70,7 +84,11 @@ inline uint8_t do_change_endian(uint8_t data) {
* \param data The data to convert.
*/
inline uint16_t do_change_endian(uint16_t data) {
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
#else
return TINS_BYTE_SWAP_16(data);
#endif
}
/**
@@ -79,8 +97,12 @@ inline uint16_t do_change_endian(uint16_t data) {
* \param data The data to convert.
*/
inline uint32_t do_change_endian(uint32_t data) {
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
#else
return TINS_BYTE_SWAP_32(data);
#endif
}
/**
@@ -89,8 +111,12 @@ inline uint32_t do_change_endian(uint32_t data) {
* \param data The data to convert.
*/
inline uint64_t do_change_endian(uint64_t data) {
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
(do_change_endian(((uint32_t)(data >> 32)))));
#else
return TINS_BYTE_SWAP_64(data);
#endif
}
/**

View File

@@ -60,6 +60,14 @@ public:
*/
static const address_type BROADCAST;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructs an ethernet II PDU.
*

View File

@@ -200,6 +200,17 @@ public:
}
};
/**
* \brief Exception thrown when a feature has been disabled
* at compile time.
*/
class feature_disabled : public exception_base {
public:
const char* what() const throw() {
return "Feature disabled";
}
};
/**
* \brief Exception thrown when a payload is too large to fit
* into a PDUOption.
@@ -273,6 +284,36 @@ public:
}
};
/**
* \brief Exception thrown when a stream is not found
*/
class stream_not_found : public exception_base {
public:
const char* what() const throw() {
return "Stream not found";
}
};
/**
* \brief Exception thrown when a required callback for an object is not set
*/
class callback_not_set : public exception_base {
public:
const char* what() const throw() {
return "Callback not set";
}
};
/**
* \brief Exception thrown when an invalid packet is provided to some function
*/
class invalid_packet : public exception_base {
public:
const char* what() const throw() {
return "Invalid packet";
}
};
namespace Crypto {
namespace WPA2 {
/**

View File

@@ -29,7 +29,7 @@
#include "config.h"
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(TINS_HAVE_DOT11)
#define TINS_HANDSHAKE_CAPTURER_H
#include <vector>

View File

@@ -92,6 +92,14 @@ public:
ADDRESS_MASK_REPLY = 18
};
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Creates an instance of ICMP.
*
@@ -379,7 +387,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* This method overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size
@@ -389,7 +397,7 @@ public:
/**
* \brief Returns the trailer size.
*
* This metod overrides PDU::trailer_size. This size will hold the extensions size
* This method overrides PDU::trailer_size. This size will hold the extensions size
*
* \sa PDU::header_size
*/

View File

@@ -80,14 +80,20 @@ public:
NEIGHBOUR_SOLICIT = 135,
NEIGHBOUR_ADVERT = 136,
REDIRECT = 137,
ROUTER_RENUMBER = 137,
ROUTER_RENUMBER = 138,
NI_QUERY = 139,
NI_REPLY = 140,
MLD2_REPORT = 143,
DHAAD_REQUEST = 144,
DHAAD_REPLY = 145,
MOBILE_PREFIX_SOL = 146,
MOBILE_PREFIX_ADV = 147
MOBILE_PREFIX_SOLICIT = 146,
MOBILE_PREFIX_ADVERT = 147,
CERT_PATH_SOLICIT = 148,
CERT_PATH_ADVERT = 149,
MULTICAST_ROUTER_ADVERT = 151,
MULTICAST_ROUTER_SOLICIT = 152,
MULTICAST_ROUTER_TERMINATE = 153,
RPL_CONTROL_MSG = 155
};
/**
@@ -1027,7 +1033,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* This method overrides PDU::header_size. This size includes the
* payload and options size. \sa PDU::header_size
*/
uint32_t header_size() const;
@@ -1035,7 +1041,7 @@ public:
/**
* \brief Returns the trailer size.
*
* This metod overrides PDU::trailer_size. This size will hold the extensions size
* This method overrides PDU::trailer_size. This size will hold the extensions size
*
* \sa PDU::header_size
*/

View File

@@ -128,7 +128,9 @@ PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer,
PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size);
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag);
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag);
uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment);
void try_parse_icmp_extensions(Memory::InputMemoryStream& stream,
@@ -177,6 +179,9 @@ bool decrement(HWAddress<n>& addr) {
return decrement_buffer(addr);
}
// Compares sequence numbers as defined by RFC 1982.
int seq_compare(uint32_t seq1, uint32_t seq2);
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
template<size_t n>

View File

@@ -246,6 +246,14 @@ public:
*/
typedef std::list<option> options_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructor for building the IP PDU.
*
@@ -280,7 +288,7 @@ public:
* \return The number of dwords the header occupies in an uin8_t.
*/
small_uint<4> head_len() const {
return this->ip_.ihl;
return this->header_.ihl;
}
/**
@@ -289,7 +297,7 @@ public:
* \return The this IP PDU's type of service.
*/
uint8_t tos() const {
return ip_.tos;
return header_.tos;
}
/**
@@ -298,7 +306,7 @@ public:
* \return The total length of this IP PDU.
*/
uint16_t tot_len() const {
return Endian::be_to_host(ip_.tot_len);
return Endian::be_to_host(header_.tot_len);
}
/**
@@ -307,7 +315,7 @@ public:
* \return The id for this IP PDU.
*/
uint16_t id() const {
return Endian::be_to_host(ip_.id);
return Endian::be_to_host(header_.id);
}
/**
@@ -321,7 +329,7 @@ public:
* \sa IP::flags
*/
TINS_DEPRECATED(uint16_t frag_off() const) {
return Endian::be_to_host(ip_.frag_off);
return Endian::be_to_host(header_.frag_off);
}
/**
@@ -333,7 +341,7 @@ public:
* \return The fragment offset, measured in units of 8 byte blocks
*/
small_uint<13> fragment_offset() const {
return Endian::be_to_host(ip_.frag_off) & 0x1fff;
return Endian::be_to_host(header_.frag_off) & 0x1fff;
}
/**
@@ -342,7 +350,7 @@ public:
* \return The IP flags field
*/
Flags flags() const {
return static_cast<Flags>(Endian::be_to_host(ip_.frag_off) >> 13);
return static_cast<Flags>(Endian::be_to_host(header_.frag_off) >> 13);
}
/**
@@ -351,7 +359,7 @@ public:
* \return The time to live for this IP PDU.
*/
uint8_t ttl() const {
return ip_.ttl;
return header_.ttl;
}
/**
@@ -360,7 +368,7 @@ public:
* \return The protocol for this IP PDU.
*/
uint8_t protocol() const {
return ip_.protocol;
return header_.protocol;
}
/**
@@ -369,7 +377,7 @@ public:
* \return The checksum for this IP PDU.
*/
uint16_t checksum() const {
return Endian::be_to_host(ip_.check);
return Endian::be_to_host(header_.check);
}
/**
@@ -378,7 +386,7 @@ public:
* \return The source address for this IP PDU.
*/
address_type src_addr() const {
return address_type(ip_.saddr);
return address_type(header_.saddr);
}
/**
@@ -386,7 +394,7 @@ public:
* \return The destination address for this IP PDU.
*/
address_type dst_addr() const {
return address_type(ip_.daddr);
return address_type(header_.daddr);
}
/**
@@ -394,7 +402,7 @@ public:
* \return The version for this IP PDU.
*/
small_uint<4> version() const {
return ip_.version;
return header_.version;
}
/**
@@ -675,7 +683,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
@@ -760,7 +768,7 @@ private:
options_type::iterator search_option_iterator(option_identifier id);
void update_padded_options_size();
ip_header ip_;
ip_header header_;
uint16_t options_size_, padded_options_size_;
options_type ip_options_;
};

View File

@@ -93,32 +93,61 @@ private:
/**
* \brief Reassembles fragmented IP packets.
*
* This class is fairly simple: just feed packets into it using IPv4Reassembler::process.
* If the return value is IPv4Reassembler::FRAGMENTED, then the packet is fragmented
* and we haven't yet seen the missing fragments, hence we can't reassemble it.
* If the function returns either IPv4Reassembler::NOT_FRAGMENTED (meaning the
* packet wasn't fragmented) or IPv4Reassembler::REASSEMBLED (meaning the packet was
* fragmented but it's now reassembled), then you can process the packet normally.
*
* Simple example:
*
* \code
* IPv4Reassembler reassembler;
* Sniffer sniffer = ...;
* sniffer.sniff_loop([&](PDU& pdu) {
* // Process it in any case, unless it's fragmented (and can't be reassembled yet)
* if (reassembler.process(pdu) != IPv4Reassembler::FRAGMENTED) {
* // Now actually process the packet
* process_packet(pdu);
* }
* });
* \endcode
*/
class TINS_API IPv4Reassembler {
public:
/**
* The status of each processed packet.
*/
enum packet_status {
NOT_FRAGMENTED,
FRAGMENTED,
REASSEMBLED
enum PacketStatus {
NOT_FRAGMENTED, ///< The given packet is not fragmented
FRAGMENTED, ///< The given packet is fragmented and can't be reassembled yet
REASSEMBLED ///< The given packet was fragmented but is now reassembled
};
TINS_DEPRECATED(typedef PacketStatus packet_status);
/**
* The type used to represent the overlapped segment reassembly
* technique to be used.
*/
enum OverlappingTechnique {
NONE
};
/**
* The type used to represent the overlapped segment
* reassembly technique to be used.
* Default constructor
*/
enum overlapping_technique {
NONE
};
IPv4Reassembler();
/**
* Constructs an IPV4Reassembler.
*
* \param technique The technique to be used for reassembling
* overlapped fragments.
*/
IPv4Reassembler(overlapping_technique technique = NONE);
IPv4Reassembler(OverlappingTechnique technique);
/**
* \brief Processes a PDU and tries to reassemble it.
@@ -134,7 +163,7 @@ public:
* fragmented or REASSEMBLED if the packet was fragmented
* but has now been reassembled.
*/
packet_status process(PDU& pdu);
PacketStatus process(PDU& pdu);
/**
* Removes all of the packets and data stored.
@@ -161,7 +190,7 @@ private:
address_pair make_address_pair(IPv4Address addr1, IPv4Address addr2) const;
streams_type streams_;
overlapping_technique technique_;
OverlappingTechnique technique_;
};
/**
@@ -190,10 +219,12 @@ public:
*/
bool operator()(PDU& pdu) {
// Forward it unless it's fragmented.
if(reassembler_.process(pdu) != IPv4Reassembler::FRAGMENTED)
if (reassembler_.process(pdu) != IPv4Reassembler::FRAGMENTED) {
return functor_(pdu);
else
}
else {
return true;
}
}
private:
IPv4Reassembler reassembler_;
@@ -210,7 +241,7 @@ template<typename Functor>
IPv4ReassemblerProxy<Functor> make_ipv4_reassembler_proxy(Functor func) {
return IPv4ReassemblerProxy<Functor>(func);
}
}
} // Tins
#endif // TINS_IP_REASSEMBLER_H

View File

@@ -146,7 +146,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;
@@ -237,7 +237,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -89,6 +89,14 @@ public:
NO_NEXT_HEADER = 59
};
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief Constructs an IPv6 object.
*
@@ -251,7 +259,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -47,7 +47,7 @@ namespace Tins {
*/
namespace Memory {
inline void read_data(const uint8_t* buffer, uint8_t* output_buffer, uint32_t size) {
inline void read_data(const uint8_t* buffer, uint8_t* output_buffer, size_t size) {
std::memcpy(output_buffer, buffer, size);
}
@@ -56,7 +56,7 @@ void read_value(const uint8_t* buffer, T& value) {
std::memcpy(&value, buffer, sizeof(value));
}
inline void write_data(uint8_t* buffer, const uint8_t* ptr, uint32_t size) {
inline void write_data(uint8_t* buffer, const uint8_t* ptr, size_t size) {
std::memcpy(buffer, ptr, size);
}
@@ -67,7 +67,7 @@ void write_value(uint8_t* buffer, const T& value) {
class InputMemoryStream {
public:
InputMemoryStream(const uint8_t* buffer, uint32_t total_sz)
InputMemoryStream(const uint8_t* buffer, size_t total_sz)
: buffer_(buffer), size_(total_sz) {
}
@@ -75,7 +75,7 @@ public:
: buffer_(&data[0]), size_(data.size()) {
}
void skip(uint32_t size) {
void skip(size_t size) {
if (TINS_UNLIKELY(size > size_)) {
throw malformed_packet();
}
@@ -83,7 +83,7 @@ public:
size_ -= size;
}
bool can_read(uint32_t byte_count) const {
bool can_read(size_t byte_count) const {
return TINS_LIKELY(size_ >= byte_count);
}
@@ -142,7 +142,7 @@ public:
skip(HWAddress<n>::address_size);
}
void read(void* output_buffer, uint32_t output_buffer_size) {
void read(void* output_buffer, size_t output_buffer_size) {
if (!can_read(output_buffer_size)) {
throw malformed_packet();
}
@@ -154,11 +154,11 @@ public:
return buffer_;
}
uint32_t size() const {
size_t size() const {
return size_;
}
void size(uint32_t new_size) {
void size(size_t new_size) {
size_ = new_size;
}
@@ -167,12 +167,12 @@ public:
}
private:
const uint8_t* buffer_;
uint32_t size_;
size_t size_;
};
class OutputMemoryStream {
public:
OutputMemoryStream(uint8_t* buffer, uint32_t total_sz)
OutputMemoryStream(uint8_t* buffer, size_t total_sz)
: buffer_(buffer), size_(total_sz) {
}
@@ -180,7 +180,7 @@ public:
: buffer_(&buffer[0]), size_(buffer.size()) {
}
void skip(uint32_t size) {
void skip(size_t size) {
if (TINS_UNLIKELY(size > size_)) {
throw malformed_packet();
}
@@ -209,7 +209,7 @@ public:
template <typename ForwardIterator>
void write(ForwardIterator start, ForwardIterator end) {
const uint32_t length = std::distance(start, end);
const size_t length = std::distance(start, end);
if (TINS_UNLIKELY(size_ < length)) {
throw serialization_error();
}
@@ -217,7 +217,7 @@ public:
skip(length);
}
void write(const uint8_t* ptr, uint32_t length) {
void write(const uint8_t* ptr, size_t length) {
write(ptr, ptr + length);
}
@@ -234,7 +234,7 @@ public:
write(address.begin(), address.end());
}
void fill(uint32_t size, uint8_t value) {
void fill(size_t size, uint8_t value) {
if (TINS_UNLIKELY(size_ < size)) {
throw serialization_error();
}
@@ -246,12 +246,12 @@ public:
return buffer_;
}
uint32_t size() const {
size_t size() const {
return size_;
}
private:
uint8_t* buffer_;
uint32_t size_;
size_t size_;
};
/**

View File

@@ -40,9 +40,10 @@ namespace Tins {
class ICMPExtension;
/**
* \class MPLS
* \brief Represents an MPLS PDU
*/
class MPLS : public PDU {
class TINS_API MPLS : public PDU {
public:
/**
* \brief This PDU's flag.

View File

@@ -36,6 +36,7 @@
#include "macros.h"
#include "hw_address.h"
#include "ip_address.h"
#include "ipv6_address.h"
namespace Tins {
@@ -55,11 +56,20 @@ public:
*/
typedef HWAddress<6> address_type;
/**
*
*/
struct IPv6Prefix {
IPv6Address address;
uint32_t prefix_length;
};
/**
* \brief Struct that holds an interface's addresses.
*/
struct Info {
IPv4Address ip_addr, netmask, bcast_addr;
std::vector<IPv6Prefix> ipv6_addrs;
address_type hw_addr;
bool is_up;
};
@@ -191,6 +201,31 @@ public:
*/
bool is_up() const;
/**
* \brief Retrieves the hardware address for this interface.
*/
address_type hw_address() const;
/**
* \brief Retrieves the IPv4 address for this interface.
*/
IPv4Address ipv4_address() const;
/**
* \brief Retrieves the IPv4 netmask for this interface.
*/
IPv4Address ipv4_mask() const;
/**
* \brief Retrieves the broadcast IPv4 address for this interface.
*/
IPv4Address ipv4_broadcast() const;
/**
* \brief Retrieves the IPv6 addresses for this interface.
*/
std::vector<IPv6Prefix> ipv6_addresses() const;
/**
* \brief Compares this interface for equality.
*

View File

@@ -148,11 +148,19 @@ public:
/**
* \brief Constructs a Packet from a PDU* and a Timestamp.
*
* The PDU* is cloned using PDU::clone.
* The PDU is cloned using PDU::clone.
*/
Packet(const PDU* apdu, const Timestamp& tstamp)
: pdu_(apdu->clone()), ts_(tstamp) { }
/**
* \brief Constructs a Packet from a PDU& and a Timestamp.
*
* The PDU is cloned using PDU::clone.
*/
Packet(const PDU& apdu, const Timestamp& tstamp)
: pdu_(apdu.clone()), ts_(tstamp) { }
/**
* \brief Constructs a Packet from a PDU* and a Timestamp.
*

View File

@@ -37,9 +37,9 @@
#include <stdint.h>
#include <map>
#include "config.h"
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
#ifdef TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
#include <pcap.h>
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
#endif // TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
#include "network_interface.h"
#include "macros.h"
#include "cxxstd.h"
@@ -184,14 +184,14 @@ public:
*/
~PacketSender();
#if !defined(_WIN32) || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
#if !defined(_WIN32) || defined(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/**
* \brief Opens a layer 2 socket.
*
* If this operation fails, then a socket_open_error will be thrown.
*/
void open_l2_socket(const NetworkInterface& iface = NetworkInterface());
#endif // !_WIN32 || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
#endif // !_WIN32 || defined(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/**
* \brief Opens a layer 3 socket, using the corresponding protocol
@@ -324,7 +324,7 @@ public:
#endif // _WIN32
#if !defined(_WIN32) || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
#if !defined(_WIN32) || defined(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
/**
* \brief Sends a level 2 PDU.
*
@@ -342,7 +342,7 @@ public:
*/
void send_l2(PDU& pdu, struct sockaddr* link_addr, uint32_t len_addr,
const NetworkInterface& iface = NetworkInterface());
#endif // !_WIN32 || HAVE_PACKET_SENDER_PCAP_SENDPACKET
#endif // !_WIN32 || TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
/**
* \brief Receives a layer 3 PDU response to a previously sent PDU.
@@ -384,18 +384,17 @@ private:
PacketSender(const PacketSender&);
PacketSender& operator=(const PacketSender&);
int find_type(SocketType type);
int timeval_subtract (struct timeval* result, struct timeval* x, struct timeval* y);
#ifndef _WIN32
bool ether_socket_initialized(const NetworkInterface& iface = NetworkInterface()) const;
int getether_socket_(const NetworkInterface& iface = NetworkInterface());
int get_ether_socket(const NetworkInterface& iface = NetworkInterface());
#endif
template<typename T>
void send(PDU& pdu, const NetworkInterface& iface) {
static_cast<T&>(pdu).send(*this, iface);
}
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
#ifdef TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
pcap_t* make_pcap_handle(const NetworkInterface& iface) const;
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
#endif // TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
PDU* recv_match_loop(const std::vector<int>& sockets,
PDU& pdu,
@@ -418,10 +417,10 @@ private:
#if defined(BSD) || defined(__FreeBSD_kernel__)
int buffer_size_;
#endif // BSD
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
#ifdef TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
typedef std::map<NetworkInterface, pcap_t*> PcapHandleMap;
PcapHandleMap pcap_handles_;
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
#endif // TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
};
} // Tins

View File

@@ -179,6 +179,7 @@ public:
IPSEC_ESP,
PKTAP,
MPLS,
UNKNOWN = 999,
USER_DEFINED_PDU = 1000
};
@@ -188,6 +189,37 @@ public:
*/
static const endian_type endianness = BE;
/**
* \brief Type used to store a PDU header's data.
*/
struct metadata {
/**
* \brief Default constructor
*/
metadata();
/**
* \brief Constructs an instance of metadata using the given values
*/
metadata(uint32_t header_size, PDUType current_type, PDUType next_type);
/**
* The total header size for the current protocol
*/
uint32_t header_size;
/**
* The current PDU type
*/
PDUType current_pdu_type;
/**
* The next PDU type
*/
PDUType next_pdu_type;
};
/**
* \brief Default constructor.
*/

View File

@@ -368,7 +368,7 @@ public:
}
real_size_ = rhs.real_size_;
if (real_size_ > small_buffer_size) {
payload_.big_buffer_ptr = nullptr;
payload_.big_buffer_ptr = 0;
std::swap(payload_.big_buffer_ptr, rhs.payload_.big_buffer_ptr);
rhs.real_size_ = 0;
}

View File

@@ -74,7 +74,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size.
* This method overrides PDU::header_size.
* \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -102,7 +102,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -167,7 +167,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -29,7 +29,7 @@
#include "config.h"
#if !defined(TINS_RADIOTAP_H) && defined(HAVE_DOT11)
#if !defined(TINS_RADIOTAP_H) && defined(TINS_HAVE_DOT11)
#define TINS_RADIOTAP_H
#include "macros.h"

View File

@@ -152,7 +152,7 @@ public:
*
* This returns the same as RawPDU::payload_size().
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -29,7 +29,7 @@
#include "config.h"
#if !defined(TINS_RSN_INFORMATION) && defined(HAVE_DOT11)
#if !defined(TINS_RSN_INFORMATION) && defined(TINS_HAVE_DOT11)
#define TINS_RSN_INFORMATION
#include <stdint.h>

View File

@@ -156,7 +156,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -71,7 +71,7 @@ public:
* This constructor is available only in C++11.
*/
BaseSniffer(BaseSniffer &&rhs) TINS_NOEXCEPT
: handle_(nullptr), mask_(), extract_raw_(false) {
: handle_(0), mask_(), extract_raw_(false) {
*this = std::move(rhs);
}
@@ -596,7 +596,7 @@ protected:
RFMON = 4,
PACKET_FILTER = 8,
IMMEDIATE_MODE = 16,
DIRECTION = 16
DIRECTION = 32
};
void configure_sniffer_pre_activation(Sniffer& sniffer) const;

View File

@@ -194,7 +194,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. \sa PDU::header_size
* This method overrides PDU::header_size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -139,6 +139,14 @@ public:
*/
typedef std::vector<uint32_t> sack_type;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief TCP constructor.
*
@@ -503,7 +511,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* This method overrides PDU::header_size. This size includes the
* payload and options size.
*
* \sa PDU::header_size

View File

@@ -0,0 +1,6 @@
FILE(GLOB INCLUDE_FILES "*.h")
INSTALL(
FILES ${INCLUDE_FILES}
DESTINATION include/tins/tcp_ip
COMPONENT Headers
)

View File

@@ -0,0 +1,155 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TCP_IP_ACK_TRACKER_H
#define TINS_TCP_IP_ACK_TRACKER_H
#include "../config.h"
#ifdef TINS_HAVE_ACK_TRACKER
#include <vector>
#include <boost/icl/interval_set.hpp>
namespace Tins {
class PDU;
namespace TCPIP {
/**
* \brief Represents an acknowledged segment range
*
* The interval represented by this range is a closed interval [first, last].
*/
class AckedRange {
public:
typedef boost::icl::discrete_interval<uint32_t> interval_type;
/**
* \brief Constructs an acked range
*
* \param first The first acked byte
* \param last The last acked byte (inclusive)
*/
AckedRange(uint32_t first, uint32_t last);
/**
* \brief Gets the next acked interval in this range
*
* If has_next() == false, then this returns an empty interval
*/
interval_type next();
/**
* Indicates whether there is still some non-consumed acked-interval in this
* range
*/
bool has_next() const;
/**
* Gets the first index acked by this range
*/
uint32_t first() const;
/**
* Gets the last index acked by this range
*/
uint32_t last() const;
private:
uint32_t first_;
uint32_t last_;
};
/**
* \brief Allows tracking acknowledged intervals in a TCP stream
*/
class AckTracker {
public:
/**
* The type used to store ACKed intervals
*/
typedef boost::icl::interval_set<uint32_t> interval_set_type;
/**
* Default constructor
*/
AckTracker();
/**
* \brief Construct an instance using some attributes
*
* \param intial_ack The initial ACK number to use
* \param use_sack Indicate whether to use Selective ACKs to track ACK numbers
*/
AckTracker(uint32_t initial_ack, bool use_sack = true);
/**
* \brief Process a packet
*/
void process_packet(const PDU& packet);
/**
* \brief Indicates whether Selective ACKs should be processed
*/
void use_sack();
/**
* Retrieves the current ACK number in this tracker
*/
uint32_t ack_number() const;
/**
* \brief Retrieves all acked intervals by Selective ACKs
*/
const interval_set_type& acked_intervals() const;
/**
* \brief Indicates whether the given segment has been already ACKed
*
* \param sequence_number The segment's sequence number
* \param length The segment's length
*/
bool is_segment_acked(uint32_t sequence_number, uint32_t length) const;
private:
void process_sack(const std::vector<uint32_t>& sack);
void cleanup_sacked_intervals(uint32_t old_ack, uint32_t new_ack);
interval_set_type acked_intervals_;
uint32_t ack_number_;
bool use_sack_;
};
} // TCPIP
} // Tins
#endif // TINS_HAVE_ACK_TRACKER
#endif // TINS_TCP_IP_ACK_TRACKER_H

336
include/tins/tcp_ip/flow.h Normal file
View File

@@ -0,0 +1,336 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TCP_IP_FLOW_H
#define TINS_TCP_IP_FLOW_H
#include "../cxxstd.h"
// This classes use C++11 features
#if TINS_IS_CXX11
#include <vector>
#include <array>
#include <map>
#include <functional>
#include <stdint.h>
#include "../macros.h"
#include "ack_tracker.h"
#include "../hw_address.h"
namespace Tins {
class PDU;
class TCP;
class IPv4Address;
class IPv6Address;
namespace TCPIP {
/**
* \brief Represents an unidirectional TCP flow between 2 endpoints
*
* This class will keep the state for all the traffic sent by
* one of the peers in a TCP connection. This contains the sequence number,
* payload ready to be read and buffered payload, along with some other
* properties of the flow.
*
* A TCP stream (see class Stream) is made out of 2 Flows, so you should
* probably have a look at that class first.
*
* You shouldn't normally need to interact with this class. Stream already
* provides proxys to most of its Flow's attributes.
*/
class TINS_API Flow {
public:
/**
* \brief Enum that indicates the state of this flow.
*
* Note that although similar, this is not mapped to a TCP state-machine
* state. This is mostly used internally to know which packets the flow is
* expecting and to know when it's done sending data.
*/
enum State {
UNKNOWN,
SYN_SENT,
ESTABLISHED,
FIN_SENT,
RST_SENT
};
/**
* The type used to store the payload
*/
typedef std::vector<uint8_t> payload_type;
/**
* The type used to store the buffered payload
*/
typedef std::map<uint32_t, payload_type> buffered_payload_type;
/**
* The type used to store the callback called when new data is available
*/
typedef std::function<void(Flow&)> data_available_callback_type;
/**
* \brief The type used to store the callback called when data is buffered
*
* The arguments are the flow, the sequence number and payload that will
* be buffered.
*/
typedef std::function<void(Flow&,
uint32_t,
const payload_type&)> flow_packet_callback_type;
/**
* Construct a Flow from an IPv4 address
*
* \param dst_address This flow's destination address
* \param dst_port This flow's destination port
* \param sequence_number The initial sequence number to be used
*/
Flow(const IPv4Address& dst_address, uint16_t dst_port,
uint32_t sequence_number);
/**
* Construct a Flow from an IPv6 address
*
* \param dst_address This flow's destination address
* \param dst_port This flow's destination port
* \param sequence_number The initial sequence number to be used
*/
Flow(const IPv6Address& dst_address, uint16_t dst_port,
uint32_t sequence_number);
/**
* \brief Sets the callback that will be executed when data is readable
*
* Whenever this flow has readable data, this callback will be executed.
* By readable, this means that there's non-out-of-order data captured.
*
* \param callback The callback to be executed
*/
void data_callback(const data_available_callback_type& callback);
/**
* \brief Sets the callback that will be executed when out of order data arrives
*
* Whenever this flow receives out-of-order data, this callback will be
* executed.
*
* \param callback The callback to be executed
*/
void out_of_order_callback(const flow_packet_callback_type& callback);
/**
* \brief Processes a packet.
*
* If this packet contains data and starts or overlaps with the current
* sequence number, then the data will be appended to this flow's payload
* and the data_callback will be executed.
*
* If this packet contains out-of-order data, it will be buffered and the
* buffering_callback will be executed.
*
* \param pdu The packet to be processed
* \sa Flow::data_callback
* \sa Flow::buffering_callback
*/
void process_packet(PDU& pdu);
/**
* Indicates whether this flow uses IPv6 addresses
*/
bool is_v6() const;
/**
* \brief Indicates whether this flow is finished
*
* A finished is considered to be finished if either it sent a
* packet with the FIN or RST flags on.
*/
bool is_finished() const;
/**
* \brief Indicates whether a packet belongs to this flow
*
* Since Flow represents a unidirectional stream, this will only check
* the destination endpoint and not the source one.
*
* \param packet The packet to be checked
*/
bool packet_belongs(const PDU& packet) const;
/**
* \brief Retrieves the IPv4 destination address
*
* Note that it's only safe to execute this method if is_v6() == false
*/
IPv4Address dst_addr_v4() const;
/**
* \brief Retrieves the IPv6 destination address
*
* Note that it's only safe to execute this method if is_v6() == true
*/
IPv6Address dst_addr_v6() const;
/**
* Retrieves this flow's destination port
*/
uint16_t dport() const;
/**
* Retrieves this flow's payload (const)
*/
const payload_type& payload() const;
/**
* Retrieves this flow's destination port
*/
payload_type& payload();
/**
* Retrieves this flow's state
*/
State state() const;
/**
* Retrieves this flow's sequence number
*/
uint32_t sequence_number() const;
/**
* Retrieves this flow's buffered payload (const)
*/
const buffered_payload_type& buffered_payload() const;
/**
* Retrieves this flow's buffered payload
*/
buffered_payload_type& buffered_payload();
/**
* Retrieves this flow's total buffered bytes
*/
uint32_t total_buffered_bytes() const;
/**
* Sets the state of this flow
*
* \param new_state The new state of this flow
*/
void state(State new_state);
/**
* \brief Sets whether this flow should ignore data packets
*
* If the data packets are ignored then the flow will just be
* followed to keep track of its state.
*/
void ignore_data_packets();
/**
* \brief Returns the MSS for this Flow.
*
* If the MSS option wasn't provided by the peer, -1 is returned
*/
int mss() const;
/**
* \brief Indicates whether this Flow supports selective acknowledgements
*/
bool sack_permitted() const;
/**
* \brief Enables tracking of ACK numbers
*
* This requires having the boost.icl library. If the library is not installed
* or ACK tracking was disabled when compiling the library, then this method
* will throw an exception.
*/
void enable_ack_tracking();
/**
* \brief Indicates whether ACK number tracking is enabled
*/
bool ack_tracking_enabled() const;
#ifdef TINS_HAVE_ACK_TRACKER
/**
* Retrieves the ACK tracker for this Flow (const)
*/
const AckTracker& ack_tracker() const;
/**
* Retrieves the ACK tracker for this Flow
*/
AckTracker& ack_tracker();
#endif // TINS_HAVE_ACK_TRACKER
private:
// Compress all flags into just one struct using bitfields
struct flags {
flags() : ignore_data_packets(0), sack_permitted(0), ack_tracking(0) {
}
uint32_t is_v6:1,
ignore_data_packets:1,
sack_permitted:1,
ack_tracking:1;
};
void store_payload(uint32_t seq, payload_type payload);
buffered_payload_type::iterator erase_iterator(buffered_payload_type::iterator iter);
void update_state(const TCP& tcp);
void initialize();
payload_type payload_;
buffered_payload_type buffered_payload_;
uint32_t seq_number_;
uint32_t total_buffered_bytes_;
std::array<uint8_t, 16> dest_address_;
uint16_t dest_port_;
data_available_callback_type on_data_callback_;
flow_packet_callback_type on_out_of_order_callback_;
State state_;
int mss_;
flags flags_;
#ifdef TINS_HAVE_ACK_TRACKER
AckTracker ack_tracker_;
#endif // TINS_HAVE_ACK_TRACKER
};
} // TCPIP
} // TINS
#endif // TINS_IS_CXX11
#endif // TINS_TCP_IP_FLOW_H

View File

@@ -0,0 +1,398 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TCP_IP_STREAM_H
#define TINS_TCP_IP_STREAM_H
#include "../cxxstd.h"
// This classes use C++11 features
#if TINS_IS_CXX11
#include <vector>
#include <array>
#include <map>
#include <functional>
#include <chrono>
#include <stdint.h>
#include "../macros.h"
#include "../hw_address.h"
#include "flow.h"
namespace Tins {
class PDU;
class TCP;
class IPv4Address;
class IPv6Address;
namespace TCPIP {
/**
* \brief Represents a TCP stream
*
* A TCP stream is made out of 2 Flows, one in each direction, plus
* some other attributes and callbacks.
*
* This class works using callbacks. Whenever the stream is created, you should
* set at least the client/server callbacks so you are notified whenever the
* client/server has sent data. Note that setting these is not mandatory, so
* you can subscribe to just the callbacks you need.
*
* \sa Stream::auto_cleanup_payloads
*/
class TINS_API Stream {
public:
/**
* The type used to store payloads
*/
typedef Flow::payload_type payload_type;
/**
* The type used to represent timestamps
*/
typedef std::chrono::microseconds timestamp_type;
/**
* The type used for callbacks
*/
typedef std::function<void(Stream&)> stream_callback_type;
/**
* The type used for packet-triggered callbacks
*
* /sa Flow::buffering_callback
*/
typedef std::function<void(Stream&,
uint32_t,
const payload_type&)> stream_packet_callback_type;
/**
* The type used to store hardware addresses
*/
typedef HWAddress<6> hwaddress_type;
/**
* \brief Constructs a TCP stream using the provided packet.
*
* \param initial_packet The first packet of the stream
* \param ts The first packet's timestamp
*/
Stream(PDU& initial_packet, const timestamp_type& ts = timestamp_type());
/**
* \brief Processes this packet.
*
* This will forward the packet appropriately to the client
* or server flow.
*
* \param packet The packet to be processed
* \param ts The packet's timestamp
*/
void process_packet(PDU& packet, const timestamp_type& ts);
/**
* \brief Processes this packet.
*
* This will forward the packet appropriately to the client
* or server flow.
*
* \param packet The packet to be processed
*/
void process_packet(PDU& packet);
/**
* Getter for the client flow
*/
Flow& client_flow();
/**
* Getter for the client flow (const)
*/
const Flow& client_flow() const;
/**
* Getter for the server flow
*/
Flow& server_flow();
/**
* Getter for the server flow (const)
*/
const Flow& server_flow() const;
/**
* \brief Indicates whether this stream is finished.
*
* This stream is finished if either peer sent a packet with
* the RST flag on, or both peers sent a FIN.
*/
bool is_finished() const;
/**
* Indicates whether this packet uses IPv6 addresses
*/
bool is_v6() const;
/**
* \brief Retrieves the client's IPv4 address
*
* Note that it's only valid to call this method if is_v6() == false
*/
IPv4Address client_addr_v4() const;
/**
* \brief Retrieves the client's IPv6 address
*
* Note that it's only valid to call this method if is_v6() == true
*/
IPv6Address client_addr_v6() const;
/**
* \brief Retrieves the client's hardware address.
*
* Note that this is not the actual hardware address of the client, but
* just the address seen from packets coming from it. If the client
* is on another network, then this will be the address of the last
* device (switch, route, etc) the packet went through.
*/
const hwaddress_type& client_hw_addr() const;
/**
* \brief Retrieves the server's hardware address.
*
* Note that this is not the actual hardware address of the server, but
* just the address seen from packets coming from it. If the server
* is on another network, then this will be the address of the last
* device (switch, route, etc) the packet went through.
*/
const hwaddress_type& server_hw_addr() const;
/**
* \brief Retrieves the server's IPv4 address
*
* Note that it's only valid to call this method if is_v6() == false
*/
IPv4Address server_addr_v4() const;
/**
* \brief Retrieves the server's IPv6 address
*
* Note that it's only valid to call this method if is_v6() == true
*/
IPv6Address server_addr_v6() const;
/**
* Getter for the client's port
*/
uint16_t client_port() const;
/**
* Getter for the server's port
*/
uint16_t server_port() const;
/**
* Getter for the client's payload (const)
*/
const payload_type& client_payload() const;
/**
* Getter for the client's payload
*/
payload_type& client_payload();
/**
* Getter for the server's payload (const)
*/
const payload_type& server_payload() const;
/**
* Getter for the server's payload
*/
payload_type& server_payload();
/**
* Getter for the creation time of this stream
*/
const timestamp_type& create_time() const;
/**
* Getter for the last seen time of this stream
*/
const timestamp_type& last_seen() const;
/**
* \brief Sets the callback to be executed when the stream is closed
*
* \param callback The callback to be set
*/
void stream_closed_callback(const stream_callback_type& callback);
/**
* \brief Sets the callback to be executed when there's client data
*
* \sa Flow::data_callback
* \param callback The callback to be set
*/
void client_data_callback(const stream_callback_type& callback);
/**
* \brief Sets the callback to be executed when there's server data
*
* \sa Flow::data_callback
* \param callback The callback to be set
*/
void server_data_callback(const stream_callback_type& callback);
/**
* \brief Sets the callback to be executed when there's new buffered
* client data
*
* \sa Flow::buffering_callback
* \param callback The callback to be set
*/
void client_out_of_order_callback(const stream_packet_callback_type& callback);
/**
* \brief Sets the callback to be executed when there's new buffered
* client data
*
* \sa Flow::buffering_callback
* \param callback The callback to be set
*/
void server_out_of_order_callback(const stream_packet_callback_type& callback);
/**
* \brief Indicates that the data packets sent by the client should be
* ignored
*
* \sa Flow::ignore_data_packets
*/
void ignore_client_data();
/**
* \brief Indicates that the data packets sent by the server should be
* ignored
*
* \sa Flow::ignore_data_packets
*/
void ignore_server_data();
/**
* \brief Sets the internal callbacks.
*
* This shouldn't normally need to be called except if you're constructing
* this object and then moving it around before persisting it somewhere.
*/
void setup_flows_callbacks();
/**
* \brief Indicates whether each flow's payloads should be automatically
* erased.
*
* If this property is true, then whenever there's new data for a stream,
* the appropriate callback will be executed and then the payload will be
* erased.
*
* If this property is false, then the payload <b>will not</b> be erased
* and the user is responsible for clearing the payload vector.
*
* Setting this property to false is useful if it's desired to hold all
* of the data sent on the stream before processing it. Note that this
* can lead to the memory growing a lot.
*
* This property is true by default.
*
* \param value The value to be set for this property
*/
void auto_cleanup_payloads(bool value);
/**
* \brief Indicates whether the client flow's payloads should be
* automatically erased.
*
* \sa auto_cleanup_payloads
*/
void auto_cleanup_client_data(bool value);
/**
* \brief Indicates whether the server flow's payloads should be
* automatically erased.
*
* \sa auto_cleanup_payloads
*/
void auto_cleanup_server_data(bool value);
/**
* Enables tracking of acknowledged segments
*
* \sa Flow::enable_ack_tracking
*/
void enable_ack_tracking();
/**
* \brief Indicates whether ACK number tracking is enabled for this stream
*/
bool ack_tracking_enabled() const;
private:
static Flow extract_client_flow(const PDU& packet);
static Flow extract_server_flow(const PDU& packet);
void on_client_flow_data(const Flow& flow);
void on_server_flow_data(const Flow& flow);
void on_client_out_of_order(const Flow& flow,
uint32_t seq,
const payload_type& payload);
void on_server_out_of_order(const Flow& flow,
uint32_t seq,
const payload_type& payload);
Flow client_flow_;
Flow server_flow_;
stream_callback_type on_stream_closed_;
stream_callback_type on_client_data_callback_;
stream_callback_type on_server_data_callback_;
stream_packet_callback_type on_client_out_of_order_callback_;
stream_packet_callback_type on_server_out_of_order_callback_;
hwaddress_type client_hw_addr_;
hwaddress_type server_hw_addr_;
timestamp_type create_time_;
timestamp_type last_seen_;
bool auto_cleanup_client_;
bool auto_cleanup_server_;
};
} // TCPIP
} // Tins
#endif // TINS_IS_CXX11
#endif // TINS_TCP_IP_STREAM_H

View File

@@ -0,0 +1,251 @@
/*
* Copyright (c) 2016, Matias Fontanini
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TINS_TCP_IP_STREAM_FOLLOWER_H
#define TINS_TCP_IP_STREAM_FOLLOWER_H
#include "../cxxstd.h"
// This classes use C++11 features
#if TINS_IS_CXX11
#include <map>
#include "stream.h"
namespace Tins {
class PDU;
class TCP;
class IPv4Address;
class IPv6Address;
class Packet;
namespace TCPIP {
/**
* \brief Represents a class that follows TCP and reassembles streams
*
* This class processes packets and whenever it detects a new connection
* being open, it starts tracking it. This will follow all data sent by
* each peer and make it available to the user in a simple way.
*
* In order to use this class, just create an instance and set the
* new stream callback to some function that you want:
*
* \code
* void on_new_stream(TCPStream& stream) {
* // Do something with it.
* // This is the perfect time to set the stream's client/server
* // write callbacks so you are notified whenever there's new
* // data on the stream
* }
*
* // Create it
* StreamFollower follower;
* // Set the callback
* follower.new_stream_callback(&on_new_stream);
* \endcode
*/
class TINS_API StreamFollower {
public:
/**
* \brief The type used for callbacks
*/
typedef Stream::stream_callback_type stream_callback_type;
/**
* Enum to indicate the reason why a stream was terminated
*/
enum TerminationReason {
TIMEOUT, ///< The stream was terminated due to a timeout
BUFFERED_DATA, ///< The stream was terminated because it had too much buffered data
SACKED_SEGMENTS ///< The stream was terminated because it had too many SACKed segments
};
/**
* \brief The type used for stream termination callbacks
*
* \sa StreamFollower::stream_termination_callback
*/
typedef std::function<void(Stream&, TerminationReason)> stream_termination_callback_type;
/**
* \brief Unique identifies a stream.
*
* This struct is used to track TCP streams. It keeps track of minimum and maximum
* addresses/ports in a stream to match packets coming from any of the 2 endpoints
* into the same object.
*/
struct stream_id {
/**
* The type used to store each endpoint's address
*/
typedef std::array<uint8_t, 16> address_type;
/**
* Default constructor
*/
stream_id();
/**
* Constructs a stream_id
*
* \param client_addr Client's address
* \param client_port Port's port
* \param server_addr Server's address
* \param server_port Server's port
*/
stream_id(const address_type& client_addr, uint16_t client_port,
const address_type& server_addr, uint16_t server_port);
bool operator<(const stream_id& rhs) const;
bool operator==(const stream_id& rhs) const;
address_type min_address;
address_type max_address;
uint16_t min_address_port;
uint16_t max_address_port;
static address_type serialize(IPv4Address address);
static address_type serialize(const IPv6Address& address);
};
/**
* Default constructor
*/
StreamFollower();
/**
* \brief Processes a packet
*
* This will detect if this packet belongs to an existing stream
* and process it, or if it belongs to a new one, in which case it
* starts tracking it.
*
* \param packet The packet to be processed
*/
void process_packet(PDU& packet);
/**
* \brief Processes a packet
*
* This will detect if this packet belongs to an existing stream
* and process it, or if it belongs to a new one, in which case it
* starts tracking it.
*
* \param packet The packet to be processed
*/
void process_packet(Packet& packet);
/**
* \brief Sets the callback to be executed when a new stream is captured.
*
* Whenever a new stream is captured, the provided callback will be
* executed.
*
* \param callback The callback to be set
*/
void new_stream_callback(const stream_callback_type& callback);
/**
* \brief Sets the stream termination callback
*
* A stream is terminated when either:
*
* * It contains too much buffered data.
* * No packets have been seen for some time interval.
*
* \param callback The callback to be executed on stream termination
* \sa StreamFollower::stream_keep_alive
*/
void stream_termination_callback(const stream_termination_callback_type& callback);
/**
* \brief Sets the maximum time a stream will be followed without capturing
* packets that belong to it.
*
* \param keep_alive The maximum time to keep unseen streams
*/
template <typename Rep, typename Period>
void stream_keep_alive(const std::chrono::duration<Rep, Period>& keep_alive) {
stream_keep_alive_ = keep_alive;
}
/**
* Finds the stream identified by the provided arguments.
*
* \param client_addr The client's address
* \param client_port The client's port
* \param server_addr The server's address
* \param server_addr The server's port
*/
Stream& find_stream(const IPv4Address& client_addr, uint16_t client_port,
const IPv4Address& server_addr, uint16_t server_port);
/**
* Finds the stream identified by the provided arguments.
*
* \param client_addr The client's address
* \param client_port The client's port
* \param server_addr The server's address
* \param server_addr The server's port
*/
Stream& find_stream(const IPv6Address& client_addr, uint16_t client_port,
const IPv6Address& server_addr, uint16_t server_port);
private:
typedef Stream::timestamp_type timestamp_type;
static const size_t DEFAULT_MAX_BUFFERED_CHUNKS;
static const size_t DEFAULT_MAX_SACKED_INTERVALS;
static const uint32_t DEFAULT_MAX_BUFFERED_BYTES;
static const timestamp_type DEFAULT_KEEP_ALIVE;
typedef std::map<stream_id, Stream> streams_type;
static stream_id make_stream_id(const PDU& packet);
Stream& find_stream(const stream_id& id);
void process_packet(PDU& packet, const timestamp_type& ts);
void cleanup_streams(const timestamp_type& now);
streams_type streams_;
stream_callback_type on_new_connection_;
stream_termination_callback_type on_stream_termination_;
size_t max_buffered_chunks_;
uint32_t max_buffered_bytes_;
timestamp_type last_cleanup_;
timestamp_type stream_keep_alive_;
bool attach_to_flows_;
};
} // TCPIP
} // Tins
#endif // TINS_IS_CXX11
#endif // TINS_TCP_IP_STREAM_FOLLOWER_H

View File

@@ -60,13 +60,21 @@ namespace Tins {
*
* \sa RawPDU
*/
class UDP : public PDU {
class TINS_API UDP : public PDU {
public:
/**
* \brief This PDU's flag.
*/
static const PDU::PDUType pdu_flag = PDU::UDP;
/**
* \brief Extracts metadata for this protocol based on the buffer provided
*
* \param buffer Pointer to a buffer
* \param total_sz Size of the buffer pointed by buffer
*/
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
/**
* \brief UDP constructor.
*
@@ -158,7 +166,7 @@ public:
/**
* \brief Returns the header size.
*
* This metod overrides PDU::header_size. This size includes the
* This method overrides PDU::header_size. This size includes the
* payload and options size. \sa PDU::header_size
*/
uint32_t header_size() const;

View File

@@ -53,6 +53,10 @@ ADD_LIBRARY(
snap.cpp
sniffer.cpp
tcp.cpp
tcp_ip/ack_tracker.cpp
tcp_ip/flow.cpp
tcp_ip/stream.cpp
tcp_ip/stream_follower.cpp
tcp_stream.cpp
udp.cpp
utils.cpp

View File

@@ -43,6 +43,13 @@ using Tins::Memory::OutputMemoryStream;
namespace Tins {
PDU::metadata ARP::extract_metadata(const uint8_t *buffer, uint32_t total_sz) {
if (TINS_UNLIKELY(total_sz < sizeof(arp_header))) {
throw malformed_packet();
}
return metadata(sizeof(arp_header), pdu_flag, PDU::UNKNOWN);
}
ARP::ARP(ipaddress_type target_ip,
ipaddress_type sender_ip,
const hwaddress_type& target_hw,

View File

@@ -29,13 +29,13 @@
#include "crypto.h"
#ifdef HAVE_DOT11
#ifdef TINS_HAVE_DOT11
#ifdef HAVE_WPA2_DECRYPTION
#ifdef TINS_HAVE_WPA2_DECRYPTION
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/aes.h>
#endif // HAVE_WPA2_DECRYPTION
#endif // TINS_HAVE_WPA2_DECRYPTION
#include "dot11/dot11_data.h"
#include "dot11/dot11_beacon.h"
#include "exceptions.h"
@@ -130,7 +130,7 @@ PDU* WEPDecrypter::decrypt(RawPDU& raw, const string& password) {
}
}
#ifdef HAVE_WPA2_DECRYPTION
#ifdef TINS_HAVE_WPA2_DECRYPTION
// WPA2Decrypter
using WPA2::SessionKeys;
@@ -491,7 +491,7 @@ bool SessionKeys::uses_ccmp() const {
// supplicant_data
SupplicantData::SupplicantData(const string& psk, const string& ssid)
: pmk_(SessionKeys::PMK_SIZE) {
: pmk_(SessionKeys::PMK_SIZE), ssid_(ssid) {
PKCS5_PBKDF2_HMAC_SHA1(
psk.c_str(),
psk.size(),
@@ -506,6 +506,11 @@ SupplicantData::SupplicantData(const string& psk, const string& ssid)
const SupplicantData::pmk_type& SupplicantData::pmk() const {
return pmk_;
}
const string& SupplicantData::ssid() const {
return ssid_;
}
} // namespace WPA2
void WPA2Decrypter::add_ap_data(const string& psk, const string& ssid) {
@@ -525,6 +530,12 @@ void WPA2Decrypter::add_access_point(const string& ssid, const address_type& add
throw runtime_error("Supplicant data not registered");
}
aps_.insert(make_pair(addr, it->second));
#ifdef TINS_HAVE_WPA2_CALLBACKS
if (ap_found_callback_) {
ap_found_callback_(ssid, addr);
}
#endif // TINS_HAVE_WPA2_CALLBACKS
}
void WPA2Decrypter::add_decryption_keys(const addr_pair& addresses,
@@ -540,6 +551,14 @@ void WPA2Decrypter::try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs)
try {
SessionKeys session(hs, it->second.pmk());
keys_[addr_p] = session;
#ifdef TINS_HAVE_WPA2_CALLBACKS
if (handshake_captured_callback_) {
address_type bssid = dot11.bssid_addr();
address_type client = (bssid == addr_p.first) ? addr_p.second
: addr_p.first;
handshake_captured_callback_(it->second.ssid(), bssid, client);
}
#endif // TINS_HAVE_WPA2_CALLBACKS
}
catch(WPA2::invalid_handshake&) {
@@ -629,9 +648,21 @@ bool WPA2Decrypter::decrypt(PDU& pdu) {
return false;
}
#endif // HAVE_WPA2_DECRYPTION
#ifdef TINS_HAVE_WPA2_CALLBACKS
void WPA2Decrypter::handshake_captured_callback(const handshake_captured_callback_type& callback) {
handshake_captured_callback_ = callback;
}
void WPA2Decrypter::ap_found_callback(const ap_found_callback_type& callback) {
ap_found_callback_ = callback;
}
#endif // TINS_HAVE_WPA2_CALLBACKS
#endif // TINS_HAVE_WPA2_DECRYPTION
} // namespace Crypto
} // namespace Tins
#endif // HAVE_DOT11
#endif // TINS_HAVE_DOT11

Some files were not shown because too many files have changed in this diff Show More