mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 10:45:57 +01:00
Compare commits
159 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b0976571e | ||
|
|
8ab48106d6 | ||
|
|
3036f9ce91 | ||
|
|
88d8f99676 | ||
|
|
fb4e5086fd | ||
|
|
58e3a7a687 | ||
|
|
f54399c45c | ||
|
|
0cf3dd3342 | ||
|
|
d7df3a449e | ||
|
|
dc1a5a6982 | ||
|
|
3d21ad7bec | ||
|
|
757e54dc08 | ||
|
|
ced645fb02 | ||
|
|
c1e479f523 | ||
|
|
ca56cc10dd | ||
|
|
75add84741 | ||
|
|
3d3d7b8506 | ||
|
|
b21154a926 | ||
|
|
2169b1f71f | ||
|
|
d84f10cf08 | ||
|
|
f5a82b1a17 | ||
|
|
2c16aaaecd | ||
|
|
d7e0d17154 | ||
|
|
2b7714500c | ||
|
|
03ad7f3ae7 | ||
|
|
756dd97fc7 | ||
|
|
7bffa7801d | ||
|
|
4ba9085eeb | ||
|
|
c4a2fed112 | ||
|
|
df3bca099a | ||
|
|
53e2c58f0b | ||
|
|
d7a9816246 | ||
|
|
67d31fd62c | ||
|
|
afe778d03c | ||
|
|
7a2ae6b7d5 | ||
|
|
481c51b4c7 | ||
|
|
38239be472 | ||
|
|
31ca9a6cc8 | ||
|
|
49af3714e8 | ||
|
|
36216107ec | ||
|
|
02e2b278de | ||
|
|
9750f46c6d | ||
|
|
13c05fbdb1 | ||
|
|
6d90b0ce32 | ||
|
|
6b82e50c03 | ||
|
|
530cc56922 | ||
|
|
0a16d8f462 | ||
|
|
e3c382efa0 | ||
|
|
fb43cb738b | ||
|
|
6e026fcb66 | ||
|
|
187e7b1ca3 | ||
|
|
8aff1b4afe | ||
|
|
45546eee39 | ||
|
|
a35b086d12 | ||
|
|
3e23bcc73c | ||
|
|
35d5045db4 | ||
|
|
65b7919ebf | ||
|
|
4b9f998784 | ||
|
|
b07deba105 | ||
|
|
534bdaf30b | ||
|
|
87c4963533 | ||
|
|
978041a9a2 | ||
|
|
30445f1e97 | ||
|
|
693cef04df | ||
|
|
9d0a2d4f3e | ||
|
|
2cf61403e1 | ||
|
|
69b26bd637 | ||
|
|
cec69ee261 | ||
|
|
891f4ac4d7 | ||
|
|
af71a4eca7 | ||
|
|
dd0b9ecde4 | ||
|
|
6dec68128d | ||
|
|
ab61907a06 | ||
|
|
9c9994f129 | ||
|
|
97e6a99c5e | ||
|
|
d09450980a | ||
|
|
79c0023f75 | ||
|
|
3b23d68a10 | ||
|
|
fe48586eef | ||
|
|
848d8348ae | ||
|
|
da3bf12671 | ||
|
|
d447009779 | ||
|
|
2c2c92325d | ||
|
|
b451a9eae0 | ||
|
|
c42c18f5df | ||
|
|
8bb837eda8 | ||
|
|
6b6636b0bb | ||
|
|
316bb12946 | ||
|
|
cab0ba8b9a | ||
|
|
0a2fdfcd42 | ||
|
|
43217549eb | ||
|
|
0f3441ccf6 | ||
|
|
9c25f635eb | ||
|
|
3ec8ab868e | ||
|
|
8d28bfe7a1 | ||
|
|
46f5d7a0cd | ||
|
|
8400079bce | ||
|
|
68c750810f | ||
|
|
0dee5618f2 | ||
|
|
76c6511e0c | ||
|
|
2f2a705127 | ||
|
|
b0faebd135 | ||
|
|
2bf2b222e0 | ||
|
|
c42cd0114f | ||
|
|
5cd0c8e41b | ||
|
|
8276dca22e | ||
|
|
d4e632f513 | ||
|
|
325de4abca | ||
|
|
e651770018 | ||
|
|
d1ffecb132 | ||
|
|
460e87cb43 | ||
|
|
a607ab380c | ||
|
|
a7a63483df | ||
|
|
9de57e1b23 | ||
|
|
f229f9a81e | ||
|
|
62260ab93b | ||
|
|
c108f6e4e6 | ||
|
|
5c8fdd2b6c | ||
|
|
34bf1f23f7 | ||
|
|
ae503523e4 | ||
|
|
e64e0ce27b | ||
|
|
93ed4f537e | ||
|
|
995abd4d00 | ||
|
|
0dcbe6ffbe | ||
|
|
745ebfb904 | ||
|
|
c5b9afaf83 | ||
|
|
f4ccba93e6 | ||
|
|
308cbcdc40 | ||
|
|
eb5598be7c | ||
|
|
830da2488b | ||
|
|
530ac79ba4 | ||
|
|
213b812520 | ||
|
|
8c2b56e286 | ||
|
|
147c1a4315 | ||
|
|
2fa4c2ade3 | ||
|
|
621af33a81 | ||
|
|
0d9fe13166 | ||
|
|
1a9cd63397 | ||
|
|
e2f96123a3 | ||
|
|
96fc1a3749 | ||
|
|
f2ed64293b | ||
|
|
bf807be7bd | ||
|
|
437911eacd | ||
|
|
2d89f1548d | ||
|
|
c8b3b8d2b8 | ||
|
|
7d7aae5929 | ||
|
|
fc950f643b | ||
|
|
4bfec7b358 | ||
|
|
3478c7b09a | ||
|
|
a326463160 | ||
|
|
ebad686987 | ||
|
|
3791fc0ee6 | ||
|
|
40a8354125 | ||
|
|
bb683c9f79 | ||
|
|
5edd5932ba | ||
|
|
021f596cf0 | ||
|
|
992d187b04 | ||
|
|
d6d2434482 | ||
|
|
811270760a |
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "googletest"]
|
||||
path = googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
ignore = dirty
|
||||
26
.travis.yml
Normal file
26
.travis.yml
Normal file
@@ -0,0 +1,26 @@
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libpcap-dev
|
||||
- libssl-dev
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. -DLIBTINS_ENABLE_CXX11=1
|
||||
- make tests
|
||||
|
||||
script:
|
||||
- ctest -V
|
||||
178
CHANGES
178
CHANGES
@@ -1,4 +1,169 @@
|
||||
v3.2
|
||||
v3.3 - Sun Jan 31 21:06:04 PST 2016
|
||||
|
||||
- Add TCP connection close example
|
||||
|
||||
- Move implementations on utils.h to utils.cpp
|
||||
|
||||
- Add ICMPv6 Multicast Listener Query Messages support
|
||||
|
||||
- Add ICMPv6 Multicast Listener Report Message support
|
||||
|
||||
- Make DNS::Query and DNS::Resource lowercase and deprecate the old names
|
||||
|
||||
- Change DNS::query/resource::type to query_type and deprecate old name
|
||||
|
||||
- Add DNS Start Of Authority parsing and serialization
|
||||
|
||||
- Parse and serialize MX preference field correctly
|
||||
|
||||
- Add NetworkInterface::friendly_name to get Windows friendly names
|
||||
|
||||
- Mask 16 bits on random number generated on traceroute example
|
||||
|
||||
- Fix TCP sequence number addition/subtraction when wrapping around
|
||||
|
||||
- Use 802.1ad protocol flag when seralizing stacked Dot1Q
|
||||
|
||||
- Code cleanup and use same syntax on the entire project
|
||||
|
||||
- Correctly serialize PPPoE session packets
|
||||
|
||||
- Fix IPv6 extension headers parsing/serialization
|
||||
|
||||
- Include examples before src to avoid duplicate tins target issue
|
||||
|
||||
- Add MPLS PDU and hook it up with ICMP extensions
|
||||
|
||||
- Set UDP checksum to 0xffff if it's 0
|
||||
|
||||
- Don't define TINS_STATIC in config.h
|
||||
|
||||
- Fix invalid RSNEAPOL parsing issue
|
||||
|
||||
- Remove special clang on OSX case when building gtest
|
||||
|
||||
- Update pseudoheader_checksum signature
|
||||
|
||||
- Fix overall checksum calculation
|
||||
|
||||
- Set ICMP payload length without padding if no extensions are present
|
||||
|
||||
- Export classes on Windows shared lib builds
|
||||
|
||||
- Use google/googletest submodule and update to HEAD
|
||||
|
||||
- Remove unused cassert header inclusions
|
||||
|
||||
- Add input/output memory stream classes port PDU classes to use them
|
||||
|
||||
- Add extensions for ICMP/ICMPv6
|
||||
|
||||
- Fix RSNInformation issues on big endian architectures
|
||||
|
||||
- Add IP::fragment_offset and IP::flags
|
||||
|
||||
- Don't set Ethernet type if inner PDU type is unknown
|
||||
|
||||
- Don't run IP source address overwrite tests on OSX
|
||||
|
||||
- Always calculate IP/IPv6 checksum
|
||||
|
||||
- Fix invalid constant value on PPPoE
|
||||
|
||||
- Define default constructor for PKTAP
|
||||
|
||||
- Guard 802.11 parsing code on PPI around HAVE_DOT11
|
||||
|
||||
- Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end
|
||||
|
||||
- Fix DataLinkType typo on doxygen docs
|
||||
|
||||
- Update docs on sniff_loop handle persistency
|
||||
|
||||
- Use uint32_t for DNS resource TTL setter
|
||||
|
||||
- Erase streams when they're reassembed on IPv4Reassembler
|
||||
|
||||
- Make all exceptions derive from exception_base
|
||||
|
||||
- Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6
|
||||
|
||||
- Allow HW addresses to be 00:00:00:00:00 on NetworkInterface::info
|
||||
|
||||
- Increment option size when adding a new DHCPv6 option
|
||||
|
||||
- Use NOMINMAX on examples
|
||||
|
||||
- Add metric field to RouteEntry
|
||||
|
||||
- Allow setting immediate mode on Sniffer
|
||||
|
||||
- Use one flags field for all flags on SnifferConfiguration
|
||||
|
||||
- Add ICMP responses example
|
||||
|
||||
- Add interfaces_info example
|
||||
|
||||
- Fix bug on SessionKeys::SessionKeys
|
||||
|
||||
- Fix compilation errors on android platform
|
||||
|
||||
- Fix example compilation on Windows
|
||||
|
||||
- Add PacketWriter::write overload that takes a Packet
|
||||
|
||||
- Use different IP addresses on IP tests depending on OS
|
||||
|
||||
- Allow retrieving keys on WPA2Decrypter
|
||||
|
||||
- Add NetworkInterface::is_up and NetworkInterface::info
|
||||
|
||||
- Add NetworkInterface::Info::is_up
|
||||
|
||||
- Fix compilation warnings on Windows x64
|
||||
|
||||
- Fix FindPCAP.cmake to find winpcap on x64
|
||||
|
||||
- Fix more tests warnings triggered on Windows
|
||||
|
||||
- Fix tests compilation warnings on Windows
|
||||
|
||||
- Fix error on VC triggered by pcap redefining the "inline" keyword
|
||||
|
||||
- Soften DNS parsing rules
|
||||
|
||||
- Replace WIN32 macro with _WIN32
|
||||
|
||||
- Fix IPv6Address::to_string on Windows
|
||||
|
||||
- Fix DNS issues triggered on VC
|
||||
|
||||
- Add google test as git submodule
|
||||
|
||||
- Perserve IP protocol when using RawPDU
|
||||
|
||||
- Use pcap_sendpacket by default to send packets on Windows
|
||||
|
||||
- Don't allow receiving l2 packets on windows
|
||||
|
||||
- Added RadioTap channel map type
|
||||
|
||||
- Made rsn_information() a const member function to make Dot11ManagementFrame
|
||||
immutable
|
||||
|
||||
- Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
|
||||
|
||||
- Use one integer field for all flags on TCP
|
||||
|
||||
- Fix invalid DNS IPv4 address parsing on big endian arch
|
||||
|
||||
- Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0
|
||||
|
||||
- Add Dot11 radio measurement name corresponding to IEEE 802.11-2012
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v3.2 - Fri Mar 20 22:12:23 PST 2015
|
||||
|
||||
- Added include guard for config.h.
|
||||
|
||||
@@ -79,6 +244,8 @@ conversion on integral constant.
|
||||
|
||||
- IPv4Address now uses inet_pton when constructing from string.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v3.1 - Sun Aug 24 21:39:43 ART 2014
|
||||
|
||||
- Fixed ICMPv6 checksum error on serialization.
|
||||
@@ -87,6 +254,8 @@ v3.1 - Sun Aug 24 21:39:43 ART 2014
|
||||
|
||||
- Changed the build system to CMake.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v3.0 - Thu Aug 7 21:39:09 ART 2014
|
||||
|
||||
- Timestamps can now be constructed from std::chrono::duration.
|
||||
@@ -150,6 +319,8 @@ PDU types.
|
||||
|
||||
- Fixed bug triggered by not including the string header.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v2.0 - Thu Jan 23 11:09:38 ART 2014
|
||||
|
||||
- DNSResourceRecord was removed. Now DNS records are added using
|
||||
@@ -204,6 +375,8 @@ capture size.
|
||||
|
||||
- Added tins_cast as a replacement for dynamic_cast on PDUs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v1.2 - Mon oct 7 23:33:49 ART 2013
|
||||
|
||||
- Added BaseSniffer::begin and BaseSniffer::end.
|
||||
@@ -298,6 +471,8 @@ that used them.
|
||||
|
||||
- Added Utils::resolve_domain and Utils::resolve_domain6
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v0.3 - Thu Jan 31 16:47:27 ART 2013
|
||||
|
||||
- Added IPv6, ICMPv6 and DHCPv6 classes.
|
||||
@@ -317,6 +492,7 @@ pseudo protocol.
|
||||
|
||||
- Fixed several bugs in DNS.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
v0.2 - Sat Oct 20 11:26:40 2012
|
||||
|
||||
|
||||
@@ -9,8 +9,17 @@ ELSE(NOT CMAKE_BUILD_TYPE)
|
||||
MESSAGE(STATUS "Using specified '${CMAKE_BUILD_TYPE}' build type.")
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# Default compilation settings
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
# Compilation flags.
|
||||
IF(MSVC)
|
||||
# Don't always use Wall, since VC's /Wall is ridiculously verbose.
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3")
|
||||
# Disable VC secure checks, since these are not really issues.
|
||||
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS=1")
|
||||
ADD_DEFINITIONS("-D_SCL_SECURE_NO_WARNINGS=1")
|
||||
ADD_DEFINITIONS("-DNOGDI=1")
|
||||
ELSE()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
ENDIF()
|
||||
|
||||
# Build output checks
|
||||
OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON)
|
||||
@@ -24,11 +33,12 @@ IF(LIBTINS_BUILD_SHARED)
|
||||
ELSE(LIBTINS_BUILD_SHARED)
|
||||
MESSAGE(STATUS "Build will generate a static library.")
|
||||
SET(LIBTINS_TYPE STATIC)
|
||||
ADD_DEFINITIONS("-DTINS_STATIC=1")
|
||||
ENDIF(LIBTINS_BUILD_SHARED)
|
||||
|
||||
# The version number.
|
||||
SET(LIBTINS_VERSION_MAJOR 3)
|
||||
SET(LIBTINS_VERSION_MINOR 2)
|
||||
SET(LIBTINS_VERSION_MINOR 3)
|
||||
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
|
||||
|
||||
# Required Packages
|
||||
@@ -43,12 +53,14 @@ IF(WIN32)
|
||||
SET(LIBTINS_OS_LIBS Ws2_32.lib Iphlpapi.lib)
|
||||
|
||||
# Add the NOMINMAX macro to avoid Windows' min and max macros.
|
||||
# While compiling on windows, for some reason, WIN32 is not defined,
|
||||
# maybe we could fix this later, but it's OK for now.
|
||||
ADD_DEFINITIONS(-DNOMINMAX -DWIN32)
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
ENDIF(WIN32)
|
||||
|
||||
# *******************
|
||||
# Compilation options
|
||||
# *******************
|
||||
|
||||
# C++11 support
|
||||
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" OFF)
|
||||
IF(LIBTINS_ENABLE_CXX11)
|
||||
SET(HAVE_CXX11 ON)
|
||||
@@ -67,6 +79,7 @@ ELSE(LIBTINS_ENABLE_CXX11)
|
||||
"as it increases the library's performance")
|
||||
ENDIF(LIBTINS_ENABLE_CXX11)
|
||||
|
||||
# IEEE 802.11 and WPA2 decryption support
|
||||
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)
|
||||
@@ -81,6 +94,20 @@ IF(LIBTINS_ENABLE_DOT11)
|
||||
ENDIF(LIBTINS_ENABLE_WPA2)
|
||||
ENDIF(LIBTINS_ENABLE_DOT11)
|
||||
|
||||
# Use pcap_sendpacket to send l2 packets rather than raw sockets
|
||||
IF(WIN32)
|
||||
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
|
||||
ELSE(WIN32)
|
||||
SET(USE_PCAP_SENDPACKET_DEFAULT OFF)
|
||||
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)
|
||||
MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.")
|
||||
ENDIF(LIBTINS_USE_PCAP_SENDPACKET)
|
||||
|
||||
# Add a target to generate API documentation using Doxygen
|
||||
FIND_PACKAGE(Doxygen QUIET)
|
||||
IF(DOXYGEN_FOUND)
|
||||
@@ -97,6 +124,7 @@ IF(DOXYGEN_FOUND)
|
||||
)
|
||||
ENDIF(DOXYGEN_FOUND)
|
||||
|
||||
# The library output directory
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||
|
||||
@@ -107,25 +135,44 @@ CONFIGURE_FILE(
|
||||
)
|
||||
|
||||
# Support for pkg-config
|
||||
set(CMAKE_INSTALL_LIBDIR lib)
|
||||
set(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(pkgconfig_version ${LIBTINS_VERSION})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
|
||||
SET(CMAKE_INSTALL_LIBDIR lib)
|
||||
SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
SET(pkgconfig_version ${LIBTINS_VERSION})
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
|
||||
|
||||
install(
|
||||
INSTALL(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
|
||||
ENABLE_TESTING()
|
||||
# ******************
|
||||
# Add subdirectories
|
||||
# ******************
|
||||
ADD_SUBDIRECTORY(include)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
ADD_SUBDIRECTORY(src)
|
||||
|
||||
# Only include googletest if the git submodule has been fetched
|
||||
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)
|
||||
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")
|
||||
ENDIF()
|
||||
|
||||
# **********************************
|
||||
# CMake project configuration export
|
||||
# **********************************
|
||||
|
||||
# Add all targets to the build-tree export set
|
||||
EXPORT(
|
||||
|
||||
32
README.md
32
README.md
@@ -1,5 +1,7 @@
|
||||
libtins
|
||||
=======
|
||||
# libtins
|
||||
|
||||
[](https://travis-ci.org/mfontanini/libtins)
|
||||
[](https://ci.appveyor.com/project/mfontanini/libtins/branch/master)
|
||||
|
||||
libtins is a high-level, multiplatform C++ network packet sniffing and
|
||||
crafting library.
|
||||
@@ -85,6 +87,32 @@ in order to invalidate it, you should run(as root):
|
||||
ldconfig
|
||||
```
|
||||
|
||||
## Running tests ##
|
||||
|
||||
You may want to run the unit tests on your system so you make sure
|
||||
everything works. In order to do so, you need to follow these steps:
|
||||
|
||||
```Shell
|
||||
# This will fetch the googletest submodule, needed for tests
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# Use any options you want
|
||||
cmake ..
|
||||
|
||||
# Compile tests
|
||||
make tests
|
||||
|
||||
# Run them
|
||||
make test
|
||||
```
|
||||
|
||||
If you find that any tests fail, please create an ticket in the
|
||||
issue tracker indicating the platform and architecture you're using.
|
||||
|
||||
## Examples ##
|
||||
|
||||
You might want to have a look at the examples located in the "examples"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# PCAP_LIBRARY The libpcap library (possibly includes a thread
|
||||
# library e.g. required by pf_ring's libpcap)
|
||||
# HAVE_PF_RING If a found version of libpcap supports PF_RING
|
||||
# HAVE_PCAP_IMMEDIATE_MODE If the version of libpcap found supports immediate mode
|
||||
|
||||
find_path(PCAP_ROOT_DIR
|
||||
NAMES include/pcap.h
|
||||
@@ -28,9 +29,17 @@ find_path(PCAP_INCLUDE_DIR
|
||||
HINTS ${PCAP_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
set (HINT_DIR ${PCAP_ROOT_DIR}/lib)
|
||||
|
||||
# On x64 windows, we should look also for the .lib at /lib/x64/
|
||||
# as this is the default path for the WinPcap developer's pack
|
||||
if (${CMAKE_SIZEOF_VOID_P} EQUAL 8 AND WIN32)
|
||||
set (HINT_DIR ${PCAP_ROOT_DIR}/lib/x64/ ${HINT_DIR})
|
||||
endif ()
|
||||
|
||||
find_library(PCAP_LIBRARY
|
||||
NAMES pcap wpcap
|
||||
HINTS ${PCAP_ROOT_DIR}/lib
|
||||
HINTS ${HINT_DIR}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
@@ -65,6 +74,7 @@ endif (NOT PCAP_LINKS_SOLO)
|
||||
include(CheckFunctionExists)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
|
||||
check_function_exists(pcap_get_pfring_id HAVE_PF_RING)
|
||||
check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
mark_as_advanced(
|
||||
|
||||
44
cmake/appveyor.yml
Normal file
44
cmake/appveyor.yml
Normal file
@@ -0,0 +1,44 @@
|
||||
version: 1.0.{build}
|
||||
configuration:
|
||||
- debug
|
||||
- release
|
||||
platform:
|
||||
- Win32
|
||||
- x64
|
||||
clone_depth: 1
|
||||
install:
|
||||
- git clone https://github.com/mfontanini/winpcap-installer.git
|
||||
- cd winpcap-installer
|
||||
- winpcap-boundary-meter-4.1.3.exe /S
|
||||
- cd ..
|
||||
- appveyor DownloadFile http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip
|
||||
- 7z x .\WpdPack_4_1_2.zip -oc:\
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
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
|
||||
build:
|
||||
project: C:/projects/libtins/build/libtins.sln
|
||||
verbosity: minimal
|
||||
after_build:
|
||||
- mkdir install\libtins\include
|
||||
- mkdir install\libtins\lib
|
||||
- cd install\libtins
|
||||
- copy C:\projects\libtins\build\lib\%Configuration%\tins.lib lib
|
||||
- xcopy C:\projects\libtins\include include /s /e
|
||||
- del include\CMakeLists.txt
|
||||
- del include\tins\CMakeLists.txt
|
||||
- del include\tins\config.h.in
|
||||
- del include\tins\dot11\CMakeLists.txt
|
||||
- cd ..\
|
||||
- 7z a libtins-%platform%-%Configuration%.zip libtins
|
||||
test_script:
|
||||
- cd c:\projects\libtins\build
|
||||
- ctest -C %Configuration%
|
||||
deploy_script:
|
||||
- ps: Push-AppveyorArtifact "install\libtins-$env:Platform-$env:Configuration.zip"
|
||||
skip_commits:
|
||||
message: /Update documentation.*/
|
||||
@@ -3,7 +3,10 @@ FIND_PACKAGE(Threads QUIET)
|
||||
|
||||
IF(libtins_FOUND)
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples)
|
||||
INCLUDE_DIRECTORIES(${LIBTINS_INCLUDE_DIRS})
|
||||
INCLUDE_DIRECTORIES(
|
||||
${LIBTINS_INCLUDE_DIRS}
|
||||
${PCAP_INCLUDE_DIR}
|
||||
)
|
||||
LINK_LIBRARIES(${LIBTINS_LIBRARIES})
|
||||
|
||||
IF(HAVE_CXX11)
|
||||
@@ -12,8 +15,11 @@ IF(libtins_FOUND)
|
||||
dns_queries
|
||||
dns_spoof
|
||||
dns_stats
|
||||
wps_detect
|
||||
icmp_responses
|
||||
interfaces_info
|
||||
tcp_connection_close
|
||||
traceroute
|
||||
wps_detect
|
||||
)
|
||||
ELSE(HAVE_CXX11)
|
||||
MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.")
|
||||
@@ -25,14 +31,18 @@ IF(libtins_FOUND)
|
||||
${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(dns_stats EXCLUDE_FROM_ALL dns_stats.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)
|
||||
|
||||
@@ -41,14 +51,19 @@ IF(libtins_FOUND)
|
||||
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)
|
||||
|
||||
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
|
||||
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
|
||||
ELSE(THREADS_FOUND)
|
||||
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(THREADS_FOUND)
|
||||
ENDIF()
|
||||
ELSE(libtins_FOUND)
|
||||
MESSAGE(
|
||||
WARNING
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,21 +32,25 @@
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::map;
|
||||
using std::bind;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
class arp_monitor {
|
||||
public:
|
||||
void run(Sniffer &sniffer);
|
||||
void run(Sniffer& sniffer);
|
||||
private:
|
||||
bool callback(const PDU &pdu);
|
||||
bool callback(const PDU& pdu);
|
||||
|
||||
std::map<IPv4Address, HWAddress<6>> addresses;
|
||||
map<IPv4Address, HWAddress<6>> addresses;
|
||||
};
|
||||
|
||||
void arp_monitor::run(Sniffer &sniffer)
|
||||
{
|
||||
void arp_monitor::run(Sniffer& sniffer) {
|
||||
sniffer.sniff_loop(
|
||||
std::bind(
|
||||
bind(
|
||||
&arp_monitor::callback,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
@@ -54,36 +58,34 @@ void arp_monitor::run(Sniffer &sniffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool arp_monitor::callback(const PDU &pdu)
|
||||
{
|
||||
bool arp_monitor::callback(const PDU& pdu) {
|
||||
// Retrieve the ARP layer
|
||||
const ARP &arp = pdu.rfind_pdu<ARP>();
|
||||
const ARP& arp = pdu.rfind_pdu<ARP>();
|
||||
// Is it an ARP reply?
|
||||
if(arp.opcode() == ARP::REPLY) {
|
||||
if (arp.opcode() == ARP::REPLY) {
|
||||
// Let's check if there's already an entry for this address
|
||||
auto iter = addresses.find(arp.sender_ip_addr());
|
||||
if(iter == addresses.end()) {
|
||||
if (iter == addresses.end()) {
|
||||
// We haven't seen this address. Save it.
|
||||
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
|
||||
std::cout << "[INFO] " << arp.sender_ip_addr() << " is at "
|
||||
<< arp.sender_hw_addr() << std::endl;
|
||||
cout << "[INFO] " << arp.sender_ip_addr() << " is at "
|
||||
<< arp.sender_hw_addr() << std::endl;
|
||||
}
|
||||
else {
|
||||
// We've seen this address. If it's not the same HW address, inform it
|
||||
if(arp.sender_hw_addr() != iter->second) {
|
||||
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
|
||||
<< iter->second << " but also at " << arp.sender_hw_addr()
|
||||
<< std::endl;
|
||||
if (arp.sender_hw_addr() != iter->second) {
|
||||
cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
|
||||
<< iter->second << " but also at " << arp.sender_hw_addr()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>\n";
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
arp_monitor monitor;
|
||||
@@ -92,9 +94,14 @@ int main(int argc, char *argv[])
|
||||
config.set_promisc_mode(true);
|
||||
config.set_filter("arp");
|
||||
|
||||
// Sniff on the provided interface in promiscuous mode
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
// Only capture arp packets
|
||||
monitor.run(sniffer);
|
||||
try {
|
||||
// Sniff on the provided interface in promiscuous mode
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
// Only capture arp packets
|
||||
monitor.run(sniffer);
|
||||
}
|
||||
catch (std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,20 +32,29 @@
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif // _WIN32
|
||||
#include <tins/arp.h>
|
||||
#include <tins/network_interface.h>
|
||||
#include <tins/utils.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/packet_sender.h>
|
||||
|
||||
using namespace std;
|
||||
using std::cout;
|
||||
using std::runtime_error;
|
||||
using std::endl;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
|
||||
void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
|
||||
const NetworkInterface::Info &info)
|
||||
{
|
||||
void do_arp_spoofing(NetworkInterface iface,
|
||||
IPv4Address gw,
|
||||
IPv4Address victim,
|
||||
const NetworkInterface::Info& info) {
|
||||
PacketSender sender;
|
||||
EthernetII::address_type gw_hw, victim_hw;
|
||||
|
||||
@@ -74,17 +83,23 @@ void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
|
||||
* performed by any routers. */
|
||||
EthernetII to_gw = EthernetII(gw_hw, info.hw_addr) / gw_arp;
|
||||
EthernetII to_victim = EthernetII(victim_hw, info.hw_addr) / victim_arp;
|
||||
while(true) {
|
||||
while (true) {
|
||||
// Just send them once every 5 seconds.
|
||||
sender.send(to_gw, iface);
|
||||
sender.send(to_victim, iface);
|
||||
sleep(5);
|
||||
#ifdef _WIN32
|
||||
Sleep(5);
|
||||
#else
|
||||
sleep(5);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc != 3 && cout << "Usage: " << *argv << " <Gateway> <Victim>\n")
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
cout << "Usage: " <<* argv << " <Gateway> <Victim>" << endl;
|
||||
return 1;
|
||||
}
|
||||
IPv4Address gw, victim;
|
||||
EthernetII::address_type own_hw;
|
||||
try {
|
||||
@@ -92,7 +107,7 @@ int main(int argc, char *argv[]) {
|
||||
gw = argv[1];
|
||||
victim = argv[2];
|
||||
}
|
||||
catch(...) {
|
||||
catch (...) {
|
||||
cout << "Invalid ip found...\n";
|
||||
return 2;
|
||||
}
|
||||
@@ -106,15 +121,15 @@ int main(int argc, char *argv[]) {
|
||||
// Find the interface hardware and ip address.
|
||||
info = iface.addresses();
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
catch (runtime_error& ex) {
|
||||
cout << ex.what() << endl;
|
||||
return 3;
|
||||
}
|
||||
try {
|
||||
do_arp_spoofing(iface, gw, victim, info);
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
std::cout << "Runtime error: " << ex.what() << std::endl;
|
||||
catch (runtime_error& ex) {
|
||||
cout << "Runtime error: " << ex.what() << endl;
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,21 +32,27 @@
|
||||
#include <string>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::set;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
using std::runtime_error;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
class BeaconSniffer {
|
||||
public:
|
||||
void run(const std::string &iface);
|
||||
void run(const string& iface);
|
||||
private:
|
||||
typedef Dot11::address_type address_type;
|
||||
typedef std::set<address_type> ssids_type;
|
||||
typedef set<address_type> ssids_type;
|
||||
|
||||
bool callback(PDU &pdu);
|
||||
bool callback(PDU& pdu);
|
||||
|
||||
ssids_type ssids;
|
||||
};
|
||||
|
||||
void BeaconSniffer::run(const std::string &iface) {
|
||||
void BeaconSniffer::run(const std::string& iface) {
|
||||
SnifferConfiguration config;
|
||||
config.set_promisc_mode(true);
|
||||
config.set_filter("type mgt subtype beacon");
|
||||
@@ -55,28 +61,28 @@ void BeaconSniffer::run(const std::string &iface) {
|
||||
sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback));
|
||||
}
|
||||
|
||||
bool BeaconSniffer::callback(PDU &pdu) {
|
||||
bool BeaconSniffer::callback(PDU& pdu) {
|
||||
// Get the Dot11 layer
|
||||
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
const Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
// All beacons must have from_ds == to_ds == 0
|
||||
if(!beacon.from_ds() && !beacon.to_ds()) {
|
||||
if (!beacon.from_ds() && !beacon.to_ds()) {
|
||||
// Get the AP address
|
||||
address_type addr = beacon.addr2();
|
||||
// Look it up in our set
|
||||
ssids_type::iterator it = ssids.find(addr);
|
||||
if(it == ssids.end()) {
|
||||
if (it == ssids.end()) {
|
||||
// First time we encounter this BSSID.
|
||||
try {
|
||||
/* If no ssid option is set, then Dot11::ssid will throw
|
||||
* a std::runtime_error.
|
||||
*/
|
||||
std::string ssid = beacon.ssid();
|
||||
string ssid = beacon.ssid();
|
||||
// Save it so we don't show it again.
|
||||
ssids.insert(addr);
|
||||
// Display the tuple "address - ssid".
|
||||
std::cout << addr << " - " << ssid << std::endl;
|
||||
cout << addr << " - " << ssid << endl;
|
||||
}
|
||||
catch(std::runtime_error&) {
|
||||
catch (runtime_error&) {
|
||||
// No ssid, just ignore it.
|
||||
}
|
||||
}
|
||||
@@ -85,10 +91,11 @@ bool BeaconSniffer::callback(PDU &pdu) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// By default, sniff wlan0
|
||||
std::string interface = "wlan0";
|
||||
if(argc == 2)
|
||||
interface = argv[1];
|
||||
if (argc != 2) {
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
string interface = argv[1];
|
||||
BeaconSniffer sniffer;
|
||||
sniffer.run(interface);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,10 +30,12 @@
|
||||
#include <tins/tins.h>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
bool callback(const PDU &pdu)
|
||||
{
|
||||
bool callback(const PDU& pdu) {
|
||||
// The packet probably looks like this:
|
||||
//
|
||||
// EthernetII / IP / UDP / RawPDU
|
||||
@@ -43,15 +45,15 @@ bool callback(const PDU &pdu)
|
||||
DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
|
||||
|
||||
// Retrieve the queries and print the domain name:
|
||||
for(const auto &query : dns.queries())
|
||||
std::cout << query.dname() << std::endl;
|
||||
for (const auto& query : dns.queries()) {
|
||||
cout << query.dname() << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
// Sniff on the provided interface in promiscuos mode
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,12 +30,14 @@
|
||||
#include <tins/tins.h>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
PacketSender sender;
|
||||
|
||||
bool callback(const PDU &pdu)
|
||||
{
|
||||
bool callback(const PDU& pdu) {
|
||||
// The packet probably looks like this:
|
||||
//
|
||||
// EthernetII / IP / UDP / RawPDU
|
||||
@@ -48,10 +50,10 @@ bool callback(const PDU &pdu)
|
||||
DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
|
||||
|
||||
// Is it a DNS query?
|
||||
if(dns.type() == DNS::QUERY) {
|
||||
if (dns.type() == DNS::QUERY) {
|
||||
// Let's see if there's any query for an "A" record.
|
||||
for(const auto &query : dns.queries()) {
|
||||
if(query.type() == DNS::A) {
|
||||
for (const auto& query : dns.queries()) {
|
||||
if (query.query_type() == DNS::A) {
|
||||
// Here's one! Let's add an answer.
|
||||
dns.add_answer(
|
||||
DNS::Resource(
|
||||
@@ -66,16 +68,16 @@ bool callback(const PDU &pdu)
|
||||
}
|
||||
}
|
||||
// Have we added some answers?
|
||||
if(dns.answers_count() > 0) {
|
||||
if (dns.answers_count() > 0) {
|
||||
// It's a response now
|
||||
dns.type(DNS::RESPONSE);
|
||||
// Recursion is available(just in case)
|
||||
dns.recursion_available(1);
|
||||
// Build our packet
|
||||
auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) /
|
||||
IP(ip.src_addr(), ip.dst_addr()) /
|
||||
UDP(udp.sport(), udp.dport()) /
|
||||
dns;
|
||||
IP(ip.src_addr(), ip.dst_addr()) /
|
||||
UDP(udp.sport(), udp.dport()) /
|
||||
dns;
|
||||
// Send it!
|
||||
sender.send(pkt);
|
||||
}
|
||||
@@ -83,10 +85,9 @@ bool callback(const PDU &pdu)
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
// Sniff on the provided interface in promiscuos mode
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,6 +27,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif // _WIN32
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
@@ -35,6 +39,25 @@
|
||||
#include <algorithm>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::thread;
|
||||
using std::string;
|
||||
using std::bind;
|
||||
using std::map;
|
||||
using std::mutex;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using std::exception;
|
||||
using std::lock_guard;
|
||||
using std::tuple;
|
||||
using std::make_tuple;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::system_clock;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
// Holds the DNS response time statistics. The response time is
|
||||
@@ -43,7 +66,7 @@ template<typename Duration>
|
||||
class statistics {
|
||||
public:
|
||||
using duration_type = Duration;
|
||||
using locker_type = std::lock_guard<std::mutex>;
|
||||
using locker_type = lock_guard<mutex>;
|
||||
|
||||
struct information {
|
||||
duration_type average, worst;
|
||||
@@ -51,42 +74,41 @@ public:
|
||||
};
|
||||
|
||||
statistics()
|
||||
: m_duration(), m_worst(duration_type::min()), m_count()
|
||||
{
|
||||
: m_duration(), m_worst(duration_type::min()), m_count() {
|
||||
|
||||
}
|
||||
|
||||
void add_response_time(const duration_type& duration)
|
||||
{
|
||||
void add_response_time(const duration_type& duration) {
|
||||
locker_type _(m_lock);
|
||||
m_duration += duration;
|
||||
m_count++;
|
||||
m_worst = std::max(m_worst, duration);
|
||||
m_worst = max(m_worst, duration);
|
||||
}
|
||||
|
||||
information get_information() const
|
||||
{
|
||||
information get_information() const {
|
||||
locker_type _(m_lock);
|
||||
if(m_count == 0)
|
||||
if(m_count == 0) {
|
||||
return { };
|
||||
else
|
||||
}
|
||||
else {
|
||||
return { m_duration / m_count, m_worst, m_count };
|
||||
}
|
||||
};
|
||||
private:
|
||||
duration_type m_duration, m_worst;
|
||||
size_t m_count;
|
||||
mutable std::mutex m_lock;
|
||||
mutable mutex m_lock;
|
||||
};
|
||||
|
||||
// Sniffs and tracks DNS queries. When a matching DNS response is found,
|
||||
// the response time is added to a statistics object.
|
||||
//
|
||||
// This class performs *no cleanup* on data associated with queries that
|
||||
// This class performs* no cleanup* on data associated with queries that
|
||||
// weren't answered.
|
||||
class dns_monitor {
|
||||
public:
|
||||
// The response times are measured in milliseconds
|
||||
using duration_type = std::chrono::milliseconds;
|
||||
using duration_type = milliseconds;
|
||||
// The statistics type used.
|
||||
using statistics_type = statistics<duration_type>;
|
||||
|
||||
@@ -95,21 +117,20 @@ public:
|
||||
return m_stats;
|
||||
}
|
||||
private:
|
||||
using packet_info = std::tuple<IPv4Address, IPv4Address, uint16_t>;
|
||||
using clock_type = std::chrono::steady_clock;
|
||||
using time_point_type = std::chrono::time_point<clock_type>;
|
||||
using packet_info = tuple<IPv4Address, IPv4Address, uint16_t>;
|
||||
using clock_type = system_clock;
|
||||
using time_point_type = clock_type::time_point;
|
||||
|
||||
bool callback(const PDU& pdu);
|
||||
static packet_info make_packet_info(const PDU& pdu, const DNS& dns);
|
||||
|
||||
statistics_type m_stats;
|
||||
std::map<packet_info, time_point_type> m_packet_info;
|
||||
map<packet_info, time_point_type> m_packet_info;
|
||||
};
|
||||
|
||||
void dns_monitor::run(BaseSniffer& sniffer)
|
||||
{
|
||||
void dns_monitor::run(BaseSniffer& sniffer) {
|
||||
sniffer.sniff_loop(
|
||||
std::bind(
|
||||
bind(
|
||||
&dns_monitor::callback,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
@@ -117,13 +138,12 @@ void dns_monitor::run(BaseSniffer& sniffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool dns_monitor::callback(const PDU& pdu)
|
||||
{
|
||||
bool dns_monitor::callback(const PDU& pdu) {
|
||||
auto now = clock_type::now();
|
||||
auto dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
|
||||
auto info = make_packet_info(pdu, dns);
|
||||
// If it's a query, add the sniff time to our map.
|
||||
if(dns.type() == DNS::QUERY) {
|
||||
if (dns.type() == DNS::QUERY) {
|
||||
m_packet_info.insert(
|
||||
std::make_pair(info, now)
|
||||
);
|
||||
@@ -131,11 +151,11 @@ bool dns_monitor::callback(const PDU& pdu)
|
||||
else {
|
||||
// It's a response, we need to find the query in our map.
|
||||
auto iter = m_packet_info.find(info);
|
||||
if(iter != m_packet_info.end()) {
|
||||
if (iter != m_packet_info.end()) {
|
||||
// We found the query, let's add the response time to the
|
||||
// statistics object.
|
||||
m_stats.add_response_time(
|
||||
std::chrono::duration_cast<duration_type>(now - iter->second)
|
||||
duration_cast<duration_type>(now - iter->second)
|
||||
);
|
||||
// Forget about the query.
|
||||
m_packet_info.erase(iter);
|
||||
@@ -148,44 +168,48 @@ bool dns_monitor::callback(const PDU& pdu)
|
||||
// hold the same DNS id as belonging to the same query.
|
||||
//
|
||||
// This function retrieves a tuple (addr, addr, id) that will achieve it.
|
||||
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info
|
||||
{
|
||||
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info {
|
||||
const auto& ip = pdu.rfind_pdu<IP>();
|
||||
return std::make_tuple(
|
||||
return make_tuple(
|
||||
// smallest address first
|
||||
std::min(ip.src_addr(), ip.dst_addr()),
|
||||
min(ip.src_addr(), ip.dst_addr()),
|
||||
// largest address second
|
||||
std::max(ip.src_addr(), ip.dst_addr()),
|
||||
max(ip.src_addr(), ip.dst_addr()),
|
||||
dns.id()
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>\n";
|
||||
return 1;
|
||||
int main(int argc, char* argv[]) {
|
||||
string iface;
|
||||
if (argc == 2) {
|
||||
// Use the provided interface
|
||||
iface = argv[1];
|
||||
}
|
||||
else {
|
||||
// Use the default interface
|
||||
iface = NetworkInterface::default_interface().name();
|
||||
}
|
||||
try {
|
||||
SnifferConfiguration config;
|
||||
config.set_promisc_mode(true);
|
||||
config.set_filter("udp and dst port 53");
|
||||
Sniffer sniffer(argv[1], config);
|
||||
config.set_filter("udp and port 53");
|
||||
Sniffer sniffer(iface, config);
|
||||
dns_monitor monitor;
|
||||
std::thread thread(
|
||||
thread thread(
|
||||
[&]() {
|
||||
monitor.run(sniffer);
|
||||
}
|
||||
);
|
||||
while(true) {
|
||||
while (true) {
|
||||
auto info = monitor.stats().get_information();
|
||||
std::cout << "\rAverage " << info.average.count()
|
||||
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
|
||||
<< info.count;
|
||||
std::cout.flush();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
cout << "\rAverage " << info.average.count()
|
||||
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
|
||||
<< info.count << " ";
|
||||
cout.flush();
|
||||
sleep_for(seconds(1));
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex) {
|
||||
std::cout << "[-] Error: " << ex.what() << std::endl;
|
||||
catch (exception& ex) {
|
||||
cout << "[-] Error: " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
140
examples/icmp_responses.cpp
Normal file
140
examples/icmp_responses.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 <stdexcept>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::bind;
|
||||
using std::string;
|
||||
using std::runtime_error;
|
||||
using std::exception;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
// This class captured packets on an interface, using the specified filter
|
||||
// and will respond with ICMP error packets whenever a packet is captured.
|
||||
// The response mechanism is pretty naive as it generates a packet which
|
||||
// has swapped HW and IP addresses (dst as src, src as dst).
|
||||
class ICMPResponder {
|
||||
public:
|
||||
// Use the given interface and ICMP type/code on responses
|
||||
ICMPResponder(string iface, int type, int code)
|
||||
: m_iface(iface), m_sender(iface), m_type(type), m_code(code) {
|
||||
|
||||
}
|
||||
|
||||
// Run using the given filter
|
||||
void run(const string& filter) {
|
||||
// Initialize the configuration
|
||||
SnifferConfiguration config;
|
||||
// Use promiscuous mode
|
||||
config.set_promisc_mode(true);
|
||||
// Use this packet filter
|
||||
config.set_filter(filter);
|
||||
// Use immediate mode (we don't want to buffer packets, we want the mright away).
|
||||
config.set_immediate_mode(true);
|
||||
|
||||
// Now create the Sniffer
|
||||
Sniffer sniffer(m_iface, config);
|
||||
if (sniffer.link_type() != DLT_EN10MB) {
|
||||
throw runtime_error("Ethernet interfaces only supported");
|
||||
}
|
||||
// Start the sniffing! For each packet, ICMPReponder::callback will be called
|
||||
sniffer.sniff_loop(bind(&ICMPResponder::callback, this, std::placeholders::_1));
|
||||
}
|
||||
private:
|
||||
// Extracts the payload to be used over the ICMP layer in the response.
|
||||
// This will be the entire IP header + 8 bytes of the next header.
|
||||
RawPDU extract_icmp_payload(IP& pdu) {
|
||||
PDU::serialization_type buffer = pdu.serialize();
|
||||
// Use whole IP + 8 bytes of next header.
|
||||
size_t end_index = pdu.header_size() + 8;
|
||||
return RawPDU(buffer.begin(), buffer.begin() + end_index);
|
||||
}
|
||||
|
||||
// Generates an ICMP response given a packet.
|
||||
EthernetII generate_response(PDU& pdu) {
|
||||
// Find Ethernet and IP headers.
|
||||
EthernetII& received_eth = pdu.rfind_pdu<EthernetII>();
|
||||
IP& received_ip = pdu.rfind_pdu<IP>();
|
||||
|
||||
// Create an Ethernet response, flipping the addresses
|
||||
EthernetII output(received_eth.src_addr(), received_eth.dst_addr());
|
||||
// Append an IP PDU, again flipping addresses.
|
||||
//output /= IP(received_ip.src_addr(), received_ip.dst_addr());
|
||||
output /= IP(received_ip.src_addr(), "8.8.8.8");
|
||||
|
||||
// Now generate the ICMP layer using the type and code provided.
|
||||
ICMP icmp;
|
||||
icmp.type(static_cast<ICMP::Flags>(m_type));
|
||||
icmp.code(m_code);
|
||||
// Append the ICMP layer to our packet
|
||||
output /= icmp;
|
||||
// Extract the payload to be used over ICMP.
|
||||
output /= extract_icmp_payload(received_ip);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Packet capture callback
|
||||
bool callback(PDU& pdu) {
|
||||
// Generate a response for this packet
|
||||
EthernetII response = generate_response(pdu);
|
||||
// Send this packet!
|
||||
m_sender.send(response);
|
||||
return true;
|
||||
}
|
||||
|
||||
string m_iface;
|
||||
PacketSender m_sender;
|
||||
int m_type;
|
||||
int m_code;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
const int type = 3;
|
||||
const int code = 0;
|
||||
if (argc < 3) {
|
||||
cout << "Usage: " << argv[0] << " <interface> <pcap_filter>" << endl;
|
||||
return 1;
|
||||
}
|
||||
string iface = argv[1];
|
||||
string filter = argv[2];
|
||||
try {
|
||||
ICMPResponder responder(iface, type, code);
|
||||
responder.run(filter);
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cout << "Error: " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
61
examples/interfaces_info.cpp
Normal file
61
examples/interfaces_info.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 <tins/network_interface.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
int main() {
|
||||
// Get all interfaces and iterate over them.
|
||||
for (const NetworkInterface& iface : NetworkInterface::all()) {
|
||||
// Get the name of this interface
|
||||
string name = iface.name();
|
||||
|
||||
// "stringify" the status of the interface
|
||||
string status = iface.is_up() ? "up" : "down";
|
||||
|
||||
// Get this interface's information (addresses).
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -44,22 +44,30 @@
|
||||
#include <tins/utils.h>
|
||||
#include <tins/packet_sender.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
using std::setw;
|
||||
using std::string;
|
||||
using std::set;
|
||||
using std::runtime_error;
|
||||
|
||||
using namespace std;
|
||||
using namespace Tins;
|
||||
|
||||
typedef std::pair<Sniffer*, std::string> sniffer_data;
|
||||
typedef pair<Sniffer*, string> sniffer_data;
|
||||
|
||||
class Scanner {
|
||||
public:
|
||||
Scanner(const NetworkInterface& interface, const IPv4Address& address,
|
||||
const vector<string>& ports);
|
||||
Scanner(const NetworkInterface& interface,
|
||||
const IPv4Address& address,
|
||||
const vector<string>& ports);
|
||||
|
||||
void run();
|
||||
private:
|
||||
void send_syns(const NetworkInterface &iface, IPv4Address dest_ip);
|
||||
bool callback(PDU &pdu);
|
||||
static void *thread_proc(void *param);
|
||||
void send_syns(const NetworkInterface& iface, IPv4Address dest_ip);
|
||||
bool callback(PDU& pdu);
|
||||
static void* thread_proc(void* param);
|
||||
void launch_sniffer();
|
||||
|
||||
NetworkInterface iface;
|
||||
@@ -68,37 +76,35 @@ private:
|
||||
Sniffer sniffer;
|
||||
};
|
||||
|
||||
Scanner::Scanner(const NetworkInterface& interface, const IPv4Address& address,
|
||||
const vector<string>& ports)
|
||||
: iface(interface), host_to_scan(address), sniffer(interface.name())
|
||||
{
|
||||
Scanner::Scanner(const NetworkInterface& interface,
|
||||
const IPv4Address& address,
|
||||
const vector<string>& ports)
|
||||
: iface(interface), host_to_scan(address), sniffer(interface.name()) {
|
||||
sniffer.set_filter(
|
||||
"tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0"
|
||||
);
|
||||
for(size_t i = 0; i < ports.size(); ++i) {
|
||||
for (size_t i = 0; i < ports.size(); ++i) {
|
||||
ports_to_scan.insert(atoi(ports[i].c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void *Scanner::thread_proc(void *param) {
|
||||
Scanner *data = (Scanner*)param;
|
||||
void* Scanner::thread_proc(void* param) {
|
||||
Scanner* data = (Scanner*)param;
|
||||
data->launch_sniffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Scanner::launch_sniffer()
|
||||
{
|
||||
void Scanner::launch_sniffer() {
|
||||
sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback));
|
||||
}
|
||||
|
||||
/* Our scan handler. This will receive SYNs and RSTs and inform us
|
||||
* the scanned port's status.
|
||||
*/
|
||||
bool Scanner::callback(PDU &pdu)
|
||||
{
|
||||
bool Scanner::callback(PDU& pdu) {
|
||||
// Find the layers we want.
|
||||
const IP &ip = pdu.rfind_pdu<IP>();
|
||||
const TCP &tcp = pdu.rfind_pdu<TCP>();
|
||||
const IP& ip = pdu.rfind_pdu<IP>();
|
||||
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
||||
// Check if the host that we're scanning sent this packet and
|
||||
// the source port is one of those that we scanned.
|
||||
if(ip.src_addr() == host_to_scan && ports_to_scan.count(tcp.sport()) == 1) {
|
||||
@@ -117,8 +123,7 @@ bool Scanner::callback(PDU &pdu)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scanner::run()
|
||||
{
|
||||
void Scanner::run() {
|
||||
pthread_t thread;
|
||||
// Launch our sniff thread.
|
||||
pthread_create(&thread, 0, &Scanner::thread_proc, this);
|
||||
@@ -126,25 +131,25 @@ void Scanner::run()
|
||||
send_syns(iface, host_to_scan);
|
||||
|
||||
// Wait for our sniffer.
|
||||
void *dummy;
|
||||
void* dummy;
|
||||
pthread_join(thread, &dummy);
|
||||
}
|
||||
|
||||
// Send syns to the given ip address, using the destination ports provided.
|
||||
void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) {
|
||||
void Scanner::send_syns(const NetworkInterface& iface, IPv4Address dest_ip) {
|
||||
// Retrieve the addresses.
|
||||
NetworkInterface::Info info = iface.addresses();
|
||||
PacketSender sender;
|
||||
// Allocate the IP PDU
|
||||
IP ip = IP(dest_ip, info.ip_addr) / TCP();
|
||||
// Get the reference to the TCP PDU
|
||||
TCP &tcp = ip.rfind_pdu<TCP>();
|
||||
TCP& tcp = ip.rfind_pdu<TCP>();
|
||||
// Set the SYN flag on.
|
||||
tcp.set_flag(TCP::SYN, 1);
|
||||
// Just some random port.
|
||||
tcp.sport(1337);
|
||||
cout << "Sending SYNs..." << endl;
|
||||
for(set<uint16_t>::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) {
|
||||
for (set<uint16_t>::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) {
|
||||
// Set the new port and send the packet!
|
||||
tcp.dport(*it);
|
||||
sender.send(ip);
|
||||
@@ -163,7 +168,7 @@ void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) {
|
||||
sender.send(eth, iface);
|
||||
}
|
||||
|
||||
void scan(int argc, char *argv[]) {
|
||||
void scan(int argc, char* argv[]) {
|
||||
IPv4Address ip(argv[1]);
|
||||
// Resolve the interface which will be our gateway
|
||||
NetworkInterface iface(ip);
|
||||
@@ -176,13 +181,15 @@ void scan(int argc, char *argv[]) {
|
||||
scanner.run();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 3 && cout << "Usage: " << *argv << " <IPADDR> <port1> [port2] [port3]\n")
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 3) {
|
||||
cout << "Usage: " <<* argv << " <IPADDR> <port1> [port2] [port3]" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
scan(argc, argv);
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
catch(runtime_error& ex) {
|
||||
cout << "Error - " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
52
examples/route_table.cpp
Normal file
52
examples/route_table.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 <iomanip>
|
||||
#include <vector>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::setw;
|
||||
using std::vector;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
int main() {
|
||||
vector<Utils::RouteEntry> entries = Utils::route_entries();
|
||||
for (size_t i = 0; i < entries.size(); ++i) {
|
||||
cout << "Entry " << setw(2) << i << ": " << endl
|
||||
<< "Interface: " << entries[i].interface << endl
|
||||
<< "Destination: " << entries[i].destination << endl
|
||||
<< "Gateway: " << entries[i].gateway << endl
|
||||
<< "Genmask: " << entries[i].mask << endl
|
||||
<< "Metric: " << entries[i].metric << endl << endl;
|
||||
}
|
||||
}
|
||||
106
examples/tcp_connection_close.cpp
Normal file
106
examples/tcp_connection_close.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 <tins/tins.h>
|
||||
|
||||
using std::string;
|
||||
using std::bind;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::exception;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
// This example will capture TCP packets and send packet that will reset
|
||||
// the connection when it captures a packet with the SYN and ACK flags on.
|
||||
class tcp_connection_closer {
|
||||
public:
|
||||
tcp_connection_closer() {
|
||||
|
||||
}
|
||||
|
||||
void run(const string& interface) {
|
||||
using std::placeholders::_1;
|
||||
// Make the PacketSender use this interface by default
|
||||
sender_.default_interface(interface);
|
||||
|
||||
// Create the sniffer configuration
|
||||
SnifferConfiguration config;
|
||||
config.set_filter("tcp");
|
||||
// We want to get the packets as fast as possible
|
||||
config.set_immediate_mode(true);
|
||||
// Create the sniffer and start the capture
|
||||
Sniffer sniffer(interface, config);
|
||||
sniffer.sniff_loop(bind(&tcp_connection_closer::callback, this, _1));
|
||||
}
|
||||
private:
|
||||
bool callback(const PDU& pdu) {
|
||||
const EthernetII& eth = pdu.rfind_pdu<EthernetII>();
|
||||
const IP& ip = pdu.rfind_pdu<IP>();
|
||||
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
||||
// We'll only close a connection when seeing a SYN|ACK
|
||||
if (tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
||||
// Create an ethernet header flipping the addresses
|
||||
EthernetII packet(eth.src_addr(), eth.dst_addr());
|
||||
// Do the same for IP
|
||||
packet /= IP(ip.src_addr(), ip.dst_addr());
|
||||
// Flip TCP ports
|
||||
TCP response_tcp(tcp.sport(), tcp.dport());
|
||||
// Set RST|ACK flags
|
||||
response_tcp.flags(TCP::RST | TCP::ACK);
|
||||
// Use the right sequence and ack numbers
|
||||
response_tcp.seq(tcp.ack_seq());
|
||||
response_tcp.ack_seq(tcp.seq());
|
||||
// Add this PDU to the packet we'll send
|
||||
packet /= response_tcp;
|
||||
// Send it!
|
||||
sender_.send(packet);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PacketSender sender_;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
cout << "Usage: " << *argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
tcp_connection_closer closer;
|
||||
closer.run(argv[1]);
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cout << "[-] Error: " << ex.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,15 +27,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif // _WIN32
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::move;
|
||||
using std::map;
|
||||
using std::min;
|
||||
using std::setw;
|
||||
using std::atomic;
|
||||
using std::runtime_error;
|
||||
using std::string;
|
||||
using std::to_string;
|
||||
using std::thread;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::lock_guard;
|
||||
using std::mutex;
|
||||
using std::random_device;
|
||||
using std::numeric_limits;
|
||||
using std::bind;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
class Traceroute {
|
||||
@@ -43,20 +69,21 @@ public:
|
||||
typedef std::map<uint16_t, IPv4Address> result_type;
|
||||
|
||||
Traceroute(NetworkInterface interface, IPv4Address address)
|
||||
: iface(interface), addr(address) { }
|
||||
: iface(interface), addr(address), lowest_dest_ttl(numeric_limits<int>::max()) {
|
||||
sequence = random_device()() & 0xffff;
|
||||
}
|
||||
|
||||
result_type trace() {
|
||||
// ICMPs that aren't sent from us.
|
||||
SnifferConfiguration config;
|
||||
config.set_snap_len(500);
|
||||
config.set_promisc_mode(false);
|
||||
// ICMPs that aren't sent from us.
|
||||
config.set_filter(
|
||||
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string());
|
||||
Sniffer sniffer(iface.name(), config);
|
||||
|
||||
PacketSender sender;
|
||||
// Create our handler
|
||||
auto handler = std::bind(
|
||||
auto handler = bind(
|
||||
&Traceroute::sniff_callback,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
@@ -64,90 +91,117 @@ public:
|
||||
// We're running
|
||||
running = true;
|
||||
// Start the sniff thread
|
||||
std::thread sniff_thread(
|
||||
&Sniffer::sniff_loop<decltype(handler)>,
|
||||
&sniffer,
|
||||
handler,
|
||||
0
|
||||
thread sniff_thread(
|
||||
[&]() {
|
||||
sniffer.sniff_loop(handler);
|
||||
}
|
||||
);
|
||||
send_packets(sender);
|
||||
sniff_thread.join();
|
||||
// If the final hop responded, add its address at the appropriate ttl
|
||||
if (lowest_dest_ttl != numeric_limits<int>::max()) {
|
||||
results[lowest_dest_ttl] = addr;
|
||||
}
|
||||
// Clear our results and return what we've found
|
||||
return std::move(results);
|
||||
return move(results);
|
||||
}
|
||||
private:
|
||||
typedef std::map<uint16_t, size_t> ttl_map;
|
||||
typedef map<uint16_t, size_t> ttl_map;
|
||||
|
||||
void send_packets(PacketSender &sender) {
|
||||
void send_packets(PacketSender& sender) {
|
||||
// ICMPs are icmp-requests by default
|
||||
IP ip = IP(addr, iface.addresses().ip_addr) / ICMP();
|
||||
// We'll find at most 10 hops.
|
||||
ICMP& icmp = ip.rfind_pdu<ICMP>();
|
||||
icmp.sequence(sequence);
|
||||
// We'll find at most 20 hops.
|
||||
|
||||
for(auto i = 1; i <= 10; ++i) {
|
||||
// Set this "unique" id
|
||||
ip.id(i);
|
||||
for (auto i = 1; i <= 20; ++i) {
|
||||
// Set this ICMP id
|
||||
icmp.id(i);
|
||||
// Set the time-to-live option
|
||||
ip.ttl(i);
|
||||
|
||||
// Critical section
|
||||
{
|
||||
std::lock_guard<std::mutex> _(lock);
|
||||
lock_guard<mutex> _(lock);
|
||||
ttls[i] = i;
|
||||
}
|
||||
|
||||
sender.send(ip);
|
||||
// Give him a little time
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
sleep_for(milliseconds(100));
|
||||
}
|
||||
running = false;
|
||||
sender.send(ip);
|
||||
}
|
||||
|
||||
bool sniff_callback(PDU &pdu) {
|
||||
const IP &ip = pdu.rfind_pdu<IP>();
|
||||
ttl_map::const_iterator iter;
|
||||
// Fetch the IP PDU attached to the ICMP response
|
||||
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
|
||||
// Critical section
|
||||
{
|
||||
std::lock_guard<std::mutex> _(lock);
|
||||
iter = ttls.find(inner_ip.id());
|
||||
}
|
||||
bool sniff_callback(PDU& pdu) {
|
||||
// Find IP and ICMP PDUs
|
||||
const IP& ip = pdu.rfind_pdu<IP>();
|
||||
const ICMP& icmp = pdu.rfind_pdu<ICMP>();
|
||||
// Check if this is an ICMP TTL exceeded error response
|
||||
if (icmp.type() == ICMP::TIME_EXCEEDED) {
|
||||
// Fetch the IP PDU attached to the ICMP response
|
||||
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
|
||||
// Now get the ICMP layer
|
||||
const ICMP& inner_icmp = inner_ip.rfind_pdu<ICMP>();
|
||||
// Make sure this is one of our packets.
|
||||
if (inner_icmp.sequence() == sequence) {
|
||||
ttl_map::const_iterator iter;
|
||||
|
||||
// It's an actual response
|
||||
if(iter != ttls.end()) {
|
||||
// Store it
|
||||
results[inner_ip.id()] = ip.src_addr();
|
||||
// Critical section
|
||||
{
|
||||
std::lock_guard<std::mutex> _(lock);
|
||||
iter = ttls.find(inner_icmp.id());
|
||||
}
|
||||
|
||||
// It's an actual response
|
||||
if(iter != ttls.end()) {
|
||||
// Store it
|
||||
results[inner_icmp.id()] = ip.src_addr();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise, this could be the final hop making an echo response
|
||||
else if (icmp.type() == ICMP::ECHO_REPLY && icmp.sequence() == sequence &&
|
||||
ip.src_addr() == addr) {
|
||||
// Keep the lowest ttl seen for the destination.
|
||||
lowest_dest_ttl = min(lowest_dest_ttl, static_cast<int>(icmp.id()));
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
NetworkInterface iface;
|
||||
IPv4Address addr;
|
||||
std::atomic<bool> running;
|
||||
atomic<bool> running;
|
||||
ttl_map ttls;
|
||||
result_type results;
|
||||
std::mutex lock;
|
||||
mutex lock;
|
||||
uint16_t sequence;
|
||||
int lowest_dest_ttl;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc <= 1 && std::cout << "Usage: " << *argv << " <IP_ADDRESS>\n")
|
||||
if (argc <= 1) {
|
||||
cout << "Usage: " <<* argv << " <ip_address>" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
IPv4Address addr((std::string(argv[1])));
|
||||
IPv4Address addr = string(argv[1]);
|
||||
Traceroute tracer(addr, addr);
|
||||
auto results = tracer.trace();
|
||||
if(results.empty())
|
||||
std::cout << "No hops found" << std::endl;
|
||||
if (results.empty()) {
|
||||
cout << "No hops found" << endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "Results: " << std::endl;
|
||||
for(const auto &entry : results) {
|
||||
std::cout << entry.first << " - " << entry.second << std::endl;
|
||||
cout << "Results: " << endl;
|
||||
for(const auto& entry : results) {
|
||||
cout << setw(2) << entry.first << " - " << entry.second << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
std::cout << "Error - " << ex.what() << std::endl;
|
||||
catch (runtime_error& ex) {
|
||||
cout << "Error - " << ex.what() << endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -41,11 +41,11 @@ std::set<HWAddress<6>> addrs;
|
||||
const HWAddress<3> expected_oui("00:50:F2");
|
||||
|
||||
bool handler(const PDU& pdu) {
|
||||
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
const Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
// Only process it once
|
||||
if(addrs.insert(beacon.addr3()).second) {
|
||||
// Iterate the tagged options
|
||||
for(const auto &opt : beacon.options()) {
|
||||
for(const auto& opt : beacon.options()) {
|
||||
// Is this a vendor-specific tag?
|
||||
if(opt.option() == Dot11::VENDOR_SPECIFIC) {
|
||||
// Make sure there's enough size for the OUI + identifier
|
||||
@@ -63,9 +63,9 @@ bool handler(const PDU& pdu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <DEVICE>\n";
|
||||
std::cout << "Usage: " <<* argv << " <DEVICE>\n";
|
||||
return 1;
|
||||
}
|
||||
// Only sniff beacons
|
||||
|
||||
1
googletest
Submodule
1
googletest
Submodule
Submodule googletest added at 13206d6f53
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -53,9 +53,8 @@ public:
|
||||
*
|
||||
* \param first The address held by this iterator.
|
||||
*/
|
||||
AddressRangeIterator(const value_type &addr)
|
||||
: addr(addr), reached_end(false)
|
||||
{
|
||||
AddressRangeIterator(const value_type& address)
|
||||
: address_(address), reached_end_(false) {
|
||||
|
||||
}
|
||||
|
||||
@@ -64,24 +63,23 @@ public:
|
||||
*
|
||||
* \param first The address held by this iterator.
|
||||
*/
|
||||
AddressRangeIterator(const value_type &address, end_iterator)
|
||||
: addr(address)
|
||||
{
|
||||
reached_end = Internals::increment(addr);
|
||||
AddressRangeIterator(const value_type& address, end_iterator)
|
||||
: address_(address) {
|
||||
reached_end_ = Internals::increment(address_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current address pointed by this iterator.
|
||||
*/
|
||||
const value_type& operator*() const {
|
||||
return addr;
|
||||
return address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a pointer to the current address pointed by this iterator.
|
||||
*/
|
||||
const value_type* operator->() const {
|
||||
return &addr;
|
||||
return& address_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,8 +87,8 @@ public:
|
||||
*
|
||||
* \param rhs The iterator with which to compare.
|
||||
*/
|
||||
bool operator==(const AddressRangeIterator &rhs) const {
|
||||
return reached_end == rhs.reached_end && addr == rhs.addr;
|
||||
bool operator==(const AddressRangeIterator& rhs) const {
|
||||
return reached_end_ == rhs.reached_end_ && address_ == rhs.address_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +96,7 @@ public:
|
||||
*
|
||||
* \param rhs The iterator with which to compare.
|
||||
*/
|
||||
bool operator!=(const AddressRangeIterator &rhs) const {
|
||||
bool operator!=(const AddressRangeIterator& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
@@ -106,8 +104,8 @@ public:
|
||||
* Increments this iterator.
|
||||
*/
|
||||
AddressRangeIterator& operator++() {
|
||||
reached_end = Internals::increment(addr);
|
||||
return *this;
|
||||
reached_end_ = Internals::increment(address_);
|
||||
return* this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,8 +117,8 @@ public:
|
||||
return copy;
|
||||
}
|
||||
private:
|
||||
Address addr;
|
||||
bool reached_end;
|
||||
Address address_;
|
||||
bool reached_end_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -135,7 +133,7 @@ private:
|
||||
*
|
||||
* \code
|
||||
* auto range = IPv4Address("192.168.5.0") / 24;
|
||||
* for(const auto &addr : range) {
|
||||
* for(const auto& addr : range) {
|
||||
* // process 192.168.5.1-254, .0 and .255 are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
@@ -151,7 +149,7 @@ private:
|
||||
*
|
||||
* \code
|
||||
* AddressRange<IPv4Address> range("192.168.5.0", "192.168.5.255");
|
||||
* for(const auto &addr : range) {
|
||||
* for(const auto& addr : range) {
|
||||
* // process 192.168.5.0-255, no addresses are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
@@ -197,11 +195,11 @@ public:
|
||||
* \param only_hosts Indicates whether only host addresses
|
||||
* should be accessed when using iterators.
|
||||
*/
|
||||
AddressRange(const address_type &first, const address_type &last, bool only_hosts = false)
|
||||
: first(first), last(last), only_hosts(only_hosts)
|
||||
{
|
||||
if(last < first)
|
||||
AddressRange(const address_type& first, const address_type& last, bool only_hosts = false)
|
||||
: first_(first), last_(last), only_hosts_(only_hosts){
|
||||
if (last_ < first_) {
|
||||
throw std::runtime_error("Invalid address range");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +209,7 @@ public:
|
||||
* \param first The base address.
|
||||
* \param mask The network mask to be used.
|
||||
*/
|
||||
static AddressRange from_mask(const address_type &first, const address_type &mask) {
|
||||
static AddressRange from_mask(const address_type& first, const address_type& mask) {
|
||||
return AddressRange<address_type>(
|
||||
first,
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
@@ -224,8 +222,8 @@ public:
|
||||
* \param addr The address to test.
|
||||
* \return a bool indicating whether the address is in the range.
|
||||
*/
|
||||
bool contains(const address_type &addr) const {
|
||||
return (first < addr && addr < last) || addr == first || addr == last;
|
||||
bool contains(const address_type& addr) const {
|
||||
return (first_ < addr && addr < last_) || addr == first_ || addr == last_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,9 +231,10 @@ public:
|
||||
* \brief const_iterator pointing to the beginning of this range.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
address_type addr = first;
|
||||
if(only_hosts)
|
||||
address_type addr = first_;
|
||||
if (only_hosts_) {
|
||||
Internals::increment(addr);
|
||||
}
|
||||
return const_iterator(addr);
|
||||
}
|
||||
|
||||
@@ -244,9 +243,10 @@ public:
|
||||
* \brief const_iterator pointing to the end of this range.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
address_type addr = last;
|
||||
if(only_hosts)
|
||||
address_type addr = last_;
|
||||
if (only_hosts_) {
|
||||
Internals::decrement(addr);
|
||||
}
|
||||
return const_iterator(addr, typename const_iterator::end_iterator());
|
||||
}
|
||||
|
||||
@@ -266,21 +266,23 @@ public:
|
||||
*/
|
||||
bool is_iterable() const {
|
||||
// Since first < last, it's iterable
|
||||
if(!only_hosts)
|
||||
if (!only_hosts_) {
|
||||
return true;
|
||||
}
|
||||
// We need that distance(first, last) >= 4
|
||||
address_type addr(first);
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
address_type addr(first_);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
// If there's overflow before the last iteration, we're done
|
||||
if(Internals::increment(addr) && i != 2)
|
||||
if (Internals::increment(addr) && i != 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If addr <= last, it's OK.
|
||||
return addr < last || addr == last;
|
||||
return addr < last_ || addr == last_;
|
||||
}
|
||||
private:
|
||||
address_type first, last;
|
||||
bool only_hosts;
|
||||
address_type first_, last_;
|
||||
bool only_hosts_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -299,12 +301,13 @@ typedef AddressRange<IPv6Address> IPv6Range;
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
template<size_t n>
|
||||
AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
|
||||
if(mask > 48)
|
||||
AddressRange<HWAddress<n> > operator/(const HWAddress<n>& addr, int mask) {
|
||||
if (mask > 48) {
|
||||
throw std::logic_error("Prefix length cannot exceed 48");
|
||||
}
|
||||
HWAddress<n> last_addr;
|
||||
typename HWAddress<n>::iterator it = last_addr.begin();
|
||||
while(mask > 8) {
|
||||
while (mask > 8) {
|
||||
*it = 0xff;
|
||||
++it;
|
||||
mask -= 8;
|
||||
@@ -318,14 +321,14 @@ AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
IPv6Range operator/(const IPv6Address &addr, int mask);
|
||||
IPv6Range operator/(const IPv6Address& addr, int mask);
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv4Range from a base IPv4Address and a mask.
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
IPv4Range operator/(const IPv4Address &addr, int mask);
|
||||
IPv4Range operator/(const IPv4Address& addr, int mask);
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_ADDRESS_RANGE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -38,280 +38,299 @@
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
class NetworkInterface;
|
||||
class EthernetII;
|
||||
|
||||
class NetworkInterface;
|
||||
class EthernetII;
|
||||
|
||||
/**
|
||||
* \class ARP
|
||||
* \brief Represents an ARP PDU.
|
||||
*
|
||||
*/
|
||||
class TINS_API ARP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the hardware address.
|
||||
*/
|
||||
typedef HWAddress<6> hwaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the IP address.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \class ARP
|
||||
* \brief Represents an ARP PDU.
|
||||
*
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class ARP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the hardware address.
|
||||
*/
|
||||
typedef HWAddress<6> hwaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the IP address.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ARP;
|
||||
|
||||
/**
|
||||
* \brief Enum which indicates the type of ARP packet.
|
||||
*/
|
||||
enum Flags {
|
||||
REQUEST = 0x0001,
|
||||
REPLY = 0x0002
|
||||
};
|
||||
static const PDU::PDUType pdu_flag = PDU::ARP;
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object using the provided addresses.
|
||||
*
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static member functions.
|
||||
*
|
||||
* \sa ARP::make_arp_request
|
||||
* \sa ARP::make_arp_reply
|
||||
*
|
||||
* \param target_ip The target IP address.
|
||||
* \param sender_ip The sender IP address.
|
||||
* \param target_hw The target hardware address.
|
||||
* \param sender_hw The sender hardware address.
|
||||
*/
|
||||
ARP(ipaddress_type target_ip = ipaddress_type(),
|
||||
ipaddress_type sender_ip = ipaddress_type(),
|
||||
const hwaddress_type &target_hw = hwaddress_type(),
|
||||
const hwaddress_type &sender_hw = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ARP header in the buffer,
|
||||
* a malformed_packet exception is thrown.
|
||||
*
|
||||
* If the buffer is bigger than the size of the ARP header,
|
||||
* then the extra data is stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ARP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the sender's hardware address.
|
||||
*
|
||||
* \return The sender hardware address.
|
||||
*/
|
||||
hwaddress_type sender_hw_addr() const { return _arp.ar_sha; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sender's IP address.
|
||||
*
|
||||
* \return The sender IP address.
|
||||
*/
|
||||
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's hardware address.
|
||||
*
|
||||
* \return The target hardware address.
|
||||
*/
|
||||
hwaddress_type target_hw_addr() const { return _arp.ar_tha; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's IP address.
|
||||
*
|
||||
* \return The target IP address.
|
||||
*/
|
||||
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address format field.
|
||||
*
|
||||
* \return The hardware address format.
|
||||
*/
|
||||
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address format field.
|
||||
*
|
||||
* \return The protocol address format.
|
||||
*/
|
||||
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address length field.
|
||||
*
|
||||
* \return The hardware address length.
|
||||
*/
|
||||
uint8_t hw_addr_length() const { return _arp.ar_hln; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address length field.
|
||||
*
|
||||
* \return The protocol address length.
|
||||
*/
|
||||
uint8_t prot_addr_length() const { return _arp.ar_pln; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ARP opcode field.
|
||||
*
|
||||
* \return The ARP opcode.
|
||||
*/
|
||||
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the ARP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's hardware address.
|
||||
*
|
||||
* \param new_snd_hw_addr The new sender hardware address.
|
||||
*/
|
||||
void sender_hw_addr(const hwaddress_type &new_snd_hw_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's IP address.
|
||||
*
|
||||
* \param new_snd_ip_addr The new sender IP address.
|
||||
*/
|
||||
void sender_ip_addr(ipaddress_type new_snd_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's hardware address.
|
||||
*
|
||||
* \param new_tgt_hw_addr The new target hardware address.
|
||||
*/
|
||||
void target_hw_addr(const hwaddress_type &new_tgt_hw_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's IP address.
|
||||
*
|
||||
* \param new_tgt_ip_addr The new target IP address.
|
||||
*/
|
||||
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address format field.
|
||||
*
|
||||
* \param new_hw_addr_fmt The new hardware address format.
|
||||
*/
|
||||
void hw_addr_format(uint16_t new_hw_addr_fmt);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address format field.
|
||||
*
|
||||
* \param new_prot_addr_fmt The new protocol address format.
|
||||
*/
|
||||
void prot_addr_format(uint16_t new_prot_addr_fmt);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address length field.
|
||||
*
|
||||
* \param new_hw_addr_len The new hardware address length.
|
||||
*/
|
||||
void hw_addr_length(uint8_t new_hw_addr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address length field.
|
||||
*
|
||||
* \param new_prot_addr_len The new protocol address length.
|
||||
*/
|
||||
void prot_addr_length(uint8_t new_prot_addr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ARP opcode field.
|
||||
*
|
||||
* \param new_opcode Flag enum value of the ARP opcode to set.
|
||||
*/
|
||||
void opcode(Flags new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Request within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Request PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthernetII object containing the ARP Request.
|
||||
*/
|
||||
static EthernetII make_arp_request(ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Reply within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Reply PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_tgt The target's hardware address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthetnetII containing the ARP Replay.
|
||||
*/
|
||||
static EthernetII make_arp_reply(ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
|
||||
const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ARP *clone() const {
|
||||
return new ARP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct arphdr {
|
||||
uint16_t ar_hrd; /* format of hardware address */
|
||||
uint16_t ar_pro; /* format of protocol address */
|
||||
uint8_t ar_hln; /* length of hardware address */
|
||||
uint8_t ar_pln; /* length of protocol address */
|
||||
uint16_t ar_op; /* ARP opcode (command) */
|
||||
|
||||
/* sender hardware address */
|
||||
uint8_t ar_sha[hwaddress_type::address_size];
|
||||
/* sender IP address */
|
||||
uint32_t ar_sip;
|
||||
/* target hardware address */
|
||||
uint8_t ar_tha[hwaddress_type::address_size];
|
||||
/* target IP address */
|
||||
uint32_t ar_tip;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
arphdr _arp;
|
||||
/**
|
||||
* \brief Enum which indicates the type of ARP packet.
|
||||
*/
|
||||
enum Flags {
|
||||
REQUEST = 0x0001,
|
||||
REPLY = 0x0002
|
||||
};
|
||||
}
|
||||
#endif //TINS_ARP_H
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object using the provided addresses.
|
||||
*
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static member functions.
|
||||
*
|
||||
* \sa ARP::make_arp_request
|
||||
* \sa ARP::make_arp_reply
|
||||
*
|
||||
* \param target_ip The target IP address.
|
||||
* \param sender_ip The sender IP address.
|
||||
* \param target_hw The target hardware address.
|
||||
* \param sender_hw The sender hardware address.
|
||||
*/
|
||||
ARP(ipaddress_type target_ip = ipaddress_type(),
|
||||
ipaddress_type sender_ip = ipaddress_type(),
|
||||
const hwaddress_type& target_hw = hwaddress_type(),
|
||||
const hwaddress_type& sender_hw = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ARP header in the buffer,
|
||||
* a malformed_packet exception is thrown.
|
||||
*
|
||||
* If the buffer is bigger than the size of the ARP header,
|
||||
* then the extra data is stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ARP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the sender's hardware address.
|
||||
*
|
||||
* \return The sender hardware address.
|
||||
*/
|
||||
hwaddress_type sender_hw_addr() const {
|
||||
return header_.sender_hw_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sender's IP address.
|
||||
*
|
||||
* \return The sender IP address.
|
||||
*/
|
||||
ipaddress_type sender_ip_addr() const {
|
||||
return ipaddress_type(header_.sender_ip_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's hardware address.
|
||||
*
|
||||
* \return The target hardware address.
|
||||
*/
|
||||
hwaddress_type target_hw_addr() const {
|
||||
return header_.target_hw_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's IP address.
|
||||
*
|
||||
* \return The target IP address.
|
||||
*/
|
||||
ipaddress_type target_ip_addr() const {
|
||||
return ipaddress_type(header_.target_ip_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address format field.
|
||||
*
|
||||
* \return The hardware address format.
|
||||
*/
|
||||
uint16_t hw_addr_format() const {
|
||||
return Endian::be_to_host(header_.hw_address_format);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address format field.
|
||||
*
|
||||
* \return The protocol address format.
|
||||
*/
|
||||
uint16_t prot_addr_format() const {
|
||||
return Endian::be_to_host(header_.proto_address_format);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address length field.
|
||||
*
|
||||
* \return The hardware address length.
|
||||
*/
|
||||
uint8_t hw_addr_length() const {
|
||||
return header_.hw_address_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address length field.
|
||||
*
|
||||
* \return The protocol address length.
|
||||
*/
|
||||
uint8_t prot_addr_length() const {
|
||||
return header_.proto_address_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ARP opcode field.
|
||||
*
|
||||
* \return The ARP opcode.
|
||||
*/
|
||||
uint16_t opcode() const {
|
||||
return Endian::be_to_host(header_.opcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the ARP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's hardware address.
|
||||
*
|
||||
* \param address The new sender hardware address.
|
||||
*/
|
||||
void sender_hw_addr(const hwaddress_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's IP address.
|
||||
*
|
||||
* \param address The new sender IP address.
|
||||
*/
|
||||
void sender_ip_addr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's hardware address.
|
||||
*
|
||||
* \param address The new target hardware address.
|
||||
*/
|
||||
void target_hw_addr(const hwaddress_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's IP address.
|
||||
*
|
||||
* \param address The new target IP address.
|
||||
*/
|
||||
void target_ip_addr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address format field.
|
||||
*
|
||||
* \param format The new hardware address format.
|
||||
*/
|
||||
void hw_addr_format(uint16_t format);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address format field.
|
||||
*
|
||||
* \param format The new protocol address format.
|
||||
*/
|
||||
void prot_addr_format(uint16_t format);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address length field.
|
||||
*
|
||||
* \param length The new hardware address length.
|
||||
*/
|
||||
void hw_addr_length(uint8_t length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address length field.
|
||||
*
|
||||
* \param length The new protocol address length.
|
||||
*/
|
||||
void prot_addr_length(uint8_t length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ARP opcode field.
|
||||
*
|
||||
* \param code Flag enum value of the ARP opcode to set.
|
||||
*/
|
||||
void opcode(Flags code);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Request within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Request PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthernetII object containing the ARP Request.
|
||||
*/
|
||||
static EthernetII make_arp_request(ipaddress_type target,
|
||||
ipaddress_type sender,
|
||||
const hwaddress_type& hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Reply within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Reply PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_tgt The target's hardware address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthetnetII containing the ARP Replay.
|
||||
*/
|
||||
static EthernetII make_arp_reply(ipaddress_type target,
|
||||
ipaddress_type sender,
|
||||
const hwaddress_type& hw_tgt = hwaddress_type(),
|
||||
const hwaddress_type& hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ARP* clone() const {
|
||||
return new ARP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct arp_header {
|
||||
uint16_t hw_address_format;
|
||||
uint16_t proto_address_format;
|
||||
uint8_t hw_address_length;
|
||||
uint8_t proto_address_length;
|
||||
uint16_t opcode;
|
||||
uint8_t sender_hw_address[hwaddress_type::address_size];
|
||||
uint32_t sender_ip_address;
|
||||
uint8_t target_hw_address[hwaddress_type::address_size];
|
||||
uint32_t target_ip_address;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
arp_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ARP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,325 +39,326 @@
|
||||
#include "ip_address.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class BootP
|
||||
* \brief Represents a BootP PDU
|
||||
*/
|
||||
class TINS_API BootP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \class BootP
|
||||
* \brief Class representing a BootP packet.
|
||||
* The type of the IP addresses.
|
||||
*/
|
||||
class BootP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the IP addresses.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the chaddr field.
|
||||
*/
|
||||
typedef HWAddress<16> chaddr_type;
|
||||
|
||||
/**
|
||||
* The type of the vend field.
|
||||
*/
|
||||
typedef std::vector<uint8_t> vend_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::BOOTP;
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \brief Enum which contains the different opcodes BootP messages.
|
||||
*/
|
||||
enum OpCodes {
|
||||
BOOTREQUEST = 1,
|
||||
BOOTREPLY = 2
|
||||
};
|
||||
/**
|
||||
* The type of the chaddr field.
|
||||
*/
|
||||
typedef HWAddress<16> chaddr_type;
|
||||
|
||||
/**
|
||||
* The type of the vend field.
|
||||
*/
|
||||
typedef std::vector<uint8_t> vend_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::BOOTP;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of BootP.
|
||||
*
|
||||
* This sets the size of the vend field to 64, as the BootP RFC
|
||||
* states.
|
||||
*/
|
||||
BootP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a BootP object from a buffer .
|
||||
*
|
||||
* If there's not enough size for a BootP header, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \param vend_field_size The vend field size to allocate.
|
||||
* Subclasses might use 0 to provide their own interpretation of this field.
|
||||
*/
|
||||
BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the opcode field.
|
||||
* \return The opcode field for this BootP PDU.
|
||||
*/
|
||||
uint8_t opcode() const { return _bootp.opcode; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the htype field.
|
||||
* \return The htype field for this BootP PDU.
|
||||
*/
|
||||
uint8_t htype() const { return _bootp.htype; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hlen field.
|
||||
* \return The hlen field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hlen() const { return _bootp.hlen; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hops field.
|
||||
* \return The hops field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hops() const { return _bootp.hops; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the xid field.
|
||||
* \return The xid field for this BootP PDU.
|
||||
*/
|
||||
uint32_t xid() const { return Endian::be_to_host(_bootp.xid); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the secs field.
|
||||
* \return The secs field for this BootP PDU.
|
||||
*/
|
||||
uint16_t secs() const { return Endian::be_to_host(_bootp.secs); }
|
||||
|
||||
/** \brief Getter for the padding field.
|
||||
* \return The padding field for this BootP PDU.
|
||||
*/
|
||||
uint16_t padding() const { return Endian::be_to_host(_bootp.padding); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ciaddr field.
|
||||
* \return The ciaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the yiaddr field.
|
||||
* \return The yiaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the siaddr field.
|
||||
* \return The siaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the giaddr field.
|
||||
* \return The giaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the chaddr field.
|
||||
* \return The chddr field for this BootP PDU.
|
||||
*/
|
||||
chaddr_type chaddr() const { return _bootp.chaddr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sname field.
|
||||
* \return The sname field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t *sname() const { return _bootp.sname; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the file field.
|
||||
* \return The file field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t *file() const { return _bootp.file; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
const vend_type &vend() const { return _vend; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
* \param new_opcode The opcode to be set.
|
||||
*/
|
||||
void opcode(uint8_t new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Setter for the htype field.
|
||||
* \param new_htype The htype to be set.
|
||||
*/
|
||||
void htype(uint8_t new_htype);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hlen field.
|
||||
* \param new_hlen The hlen to be set.
|
||||
*/
|
||||
void hlen(uint8_t new_hlen);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hops field.
|
||||
* \param new_hops The hops to be set.
|
||||
*/
|
||||
void hops(uint8_t new_hops);
|
||||
|
||||
/**
|
||||
* \brief Setter for the xid field.
|
||||
* \param new_xid The xid to be set.
|
||||
*/
|
||||
void xid(uint32_t new_xid);
|
||||
|
||||
/**
|
||||
* \brief Setter for the secs field.
|
||||
* \param new_secs The secs to be set.
|
||||
*/
|
||||
void secs(uint16_t new_secs);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param new_padding The padding to be set.
|
||||
*/
|
||||
void padding(uint16_t new_padding);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ciaddr field.
|
||||
* \param new_ciaddr The ciaddr to be set.
|
||||
*/
|
||||
void ciaddr(ipaddress_type new_ciaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the yiaddr field.
|
||||
* \param new_yiaddr The yiaddr to be set.
|
||||
*/
|
||||
void yiaddr(ipaddress_type new_yiaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the siaddr field.
|
||||
* \param new_siaddr The siaddr to be set.
|
||||
*/
|
||||
void siaddr(ipaddress_type new_siaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the giaddr field.
|
||||
* \param new_giaddr The giaddr to be set.
|
||||
*/
|
||||
void giaddr(ipaddress_type new_giaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the chaddr field.
|
||||
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
|
||||
* \param new_chaddr The chaddr to be set.
|
||||
*/
|
||||
template<size_t n>
|
||||
void chaddr(const HWAddress<n> &new_chaddr) {
|
||||
// Copy the new addr
|
||||
uint8_t *end = std::copy(
|
||||
new_chaddr.begin(),
|
||||
new_chaddr.begin() + std::min(n, sizeof(_bootp.chaddr)),
|
||||
_bootp.chaddr
|
||||
);
|
||||
// Fill what's left with zeros
|
||||
if(end < _bootp.chaddr + chaddr_type::address_size)
|
||||
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sname field.
|
||||
* \param new_sname The sname to be set.
|
||||
*/
|
||||
void sname(const uint8_t *new_sname);
|
||||
|
||||
/**
|
||||
* \brief Setter for the file field.
|
||||
* \param new_file The file to be set.
|
||||
*/
|
||||
void file(const uint8_t *new_file);
|
||||
|
||||
/**
|
||||
* \brief Setter for the vend field.
|
||||
* \param new_vend The vend to be set.
|
||||
*/
|
||||
void vend(const vend_type &new_vend);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This returns true if the xid field is equal.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
BootP *clone() const {
|
||||
return new BootP(*this);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*
|
||||
* This getter can be used by subclasses to avoid copying the
|
||||
* vend field around.
|
||||
*
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct bootphdr {
|
||||
uint8_t opcode;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t padding;
|
||||
uint32_t ciaddr;
|
||||
uint32_t yiaddr;
|
||||
uint32_t siaddr;
|
||||
uint32_t giaddr;
|
||||
uint8_t chaddr[16];
|
||||
uint8_t sname[64];
|
||||
uint8_t file[128];
|
||||
} TINS_END_PACK;
|
||||
|
||||
bootphdr _bootp;
|
||||
vend_type _vend;
|
||||
/**
|
||||
* \brief Enum which contains the different opcodes BootP messages.
|
||||
*/
|
||||
enum OpCodes {
|
||||
BOOTREQUEST = 1,
|
||||
BOOTREPLY = 2
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of BootP.
|
||||
*
|
||||
* This sets the size of the vend field to 64, as the BootP RFC
|
||||
* states.
|
||||
*/
|
||||
BootP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a BootP object from a buffer .
|
||||
*
|
||||
* If there's not enough size for a BootP header, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \param vend_field_size The vend field size to allocate.
|
||||
* Subclasses might use 0 to provide their own interpretation of this field.
|
||||
*/
|
||||
BootP(const uint8_t* buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the opcode field.
|
||||
* \return The opcode field for this BootP PDU.
|
||||
*/
|
||||
uint8_t opcode() const { return bootp_.opcode; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the htype field.
|
||||
* \return The htype field for this BootP PDU.
|
||||
*/
|
||||
uint8_t htype() const { return bootp_.htype; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hlen field.
|
||||
* \return The hlen field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hlen() const { return bootp_.hlen; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hops field.
|
||||
* \return The hops field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hops() const { return bootp_.hops; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the xid field.
|
||||
* \return The xid field for this BootP PDU.
|
||||
*/
|
||||
uint32_t xid() const { return Endian::be_to_host(bootp_.xid); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the secs field.
|
||||
* \return The secs field for this BootP PDU.
|
||||
*/
|
||||
uint16_t secs() const { return Endian::be_to_host(bootp_.secs); }
|
||||
|
||||
/** \brief Getter for the padding field.
|
||||
* \return The padding field for this BootP PDU.
|
||||
*/
|
||||
uint16_t padding() const { return Endian::be_to_host(bootp_.padding); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ciaddr field.
|
||||
* \return The ciaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type ciaddr() const { return ipaddress_type(bootp_.ciaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the yiaddr field.
|
||||
* \return The yiaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type yiaddr() const { return ipaddress_type(bootp_.yiaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the siaddr field.
|
||||
* \return The siaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type siaddr() const { return ipaddress_type(bootp_.siaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the giaddr field.
|
||||
* \return The giaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type giaddr() const { return ipaddress_type(bootp_.giaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the chaddr field.
|
||||
* \return The chddr field for this BootP PDU.
|
||||
*/
|
||||
chaddr_type chaddr() const { return bootp_.chaddr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sname field.
|
||||
* \return The sname field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t* sname() const { return bootp_.sname; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the file field.
|
||||
* \return The file field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t* file() const { return bootp_.file; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
const vend_type& vend() const { return vend_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
* \param code The opcode to be set.
|
||||
*/
|
||||
void opcode(uint8_t code);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware type field.
|
||||
* \param type The hardware type field value to be set.
|
||||
*/
|
||||
void htype(uint8_t type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hlen field.
|
||||
* \param length The hlen field value to be set.
|
||||
*/
|
||||
void hlen(uint8_t length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hops field.
|
||||
* \param count The hops field value to be set.
|
||||
*/
|
||||
void hops(uint8_t count);
|
||||
|
||||
/**
|
||||
* \brief Setter for the xid field.
|
||||
* \param identifier The xid to be set.
|
||||
*/
|
||||
void xid(uint32_t identifier);
|
||||
|
||||
/**
|
||||
* \brief Setter for the secs field.
|
||||
* \param value The secs to be set.
|
||||
*/
|
||||
void secs(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param value The padding to be set.
|
||||
*/
|
||||
void padding(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ciaddr field.
|
||||
* \param address The ciaddr to be set.
|
||||
*/
|
||||
void ciaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the yiaddr field.
|
||||
* \param address The yiaddr to be set.
|
||||
*/
|
||||
void yiaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the siaddr field.
|
||||
* \param address The siaddr to be set.
|
||||
*/
|
||||
void siaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the giaddr field.
|
||||
* \param address The giaddr to be set.
|
||||
*/
|
||||
void giaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the chaddr field.
|
||||
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
|
||||
* \param new_chaddr The chaddr to be set.
|
||||
*/
|
||||
template<size_t n>
|
||||
void chaddr(const HWAddress<n>& new_chaddr) {
|
||||
// Copy the new addr
|
||||
uint8_t* end = std::copy(
|
||||
new_chaddr.begin(),
|
||||
new_chaddr.begin() + std::min(n, sizeof(bootp_.chaddr)),
|
||||
bootp_.chaddr
|
||||
);
|
||||
// Fill what's left with zeros
|
||||
if (end < bootp_.chaddr + chaddr_type::address_size) {
|
||||
std::fill(end, bootp_.chaddr + chaddr_type::address_size, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sname field.
|
||||
* \param new_sname The sname to be set.
|
||||
*/
|
||||
void sname(const uint8_t* new_sname);
|
||||
|
||||
/**
|
||||
* \brief Setter for the file field.
|
||||
* \param new_file The file to be set.
|
||||
*/
|
||||
void file(const uint8_t* new_file);
|
||||
|
||||
/**
|
||||
* \brief Setter for the vend field.
|
||||
* \param newvend_ The vend to be set.
|
||||
*/
|
||||
void vend(const vend_type& newvend_);
|
||||
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This returns true if the xid field is equal.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
BootP* clone() const {
|
||||
return new BootP(*this);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*
|
||||
* This getter can be used by subclasses to avoid copying the
|
||||
* vend field around.
|
||||
*
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct bootp_header {
|
||||
uint8_t opcode;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t padding;
|
||||
uint32_t ciaddr;
|
||||
uint32_t yiaddr;
|
||||
uint32_t siaddr;
|
||||
uint32_t giaddr;
|
||||
uint8_t chaddr[16];
|
||||
uint8_t sname[64];
|
||||
uint8_t file[128];
|
||||
} TINS_END_PACK;
|
||||
|
||||
bootp_header bootp_;
|
||||
vend_type vend_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_BOOTP_H
|
||||
|
||||
@@ -10,4 +10,7 @@
|
||||
/* Have WPA2 decryption library */
|
||||
#cmakedefine HAVE_WPA2_DECRYPTION
|
||||
|
||||
/* Use pcap_sendpacket to send l2 packets */
|
||||
#cmakedefine HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
#endif // TINS_CONFIG_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,130 +31,133 @@
|
||||
#define TINS_CONSTANTS_H
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Constants used in protocols.
|
||||
*/
|
||||
namespace Constants {
|
||||
/** \cond */
|
||||
struct IP {
|
||||
/** \endcond */
|
||||
enum e {
|
||||
PROTO_IP = 0, /* Dummy protocol for TCP. */
|
||||
PROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
|
||||
PROTO_ICMP = 1, /* Internet Control Message Protocol. */
|
||||
PROTO_IGMP = 2, /* Internet Group Management Protocol. */
|
||||
PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
|
||||
PROTO_TCP = 6, /* Transmission Control Protocol. */
|
||||
PROTO_EGP = 8, /* Exterior Gateway Protocol. */
|
||||
PROTO_PUP = 12, /* PUP protocol. */
|
||||
PROTO_UDP = 17, /* User Datagram Protocol. */
|
||||
PROTO_IDP = 22, /* XNS IDP protocol. */
|
||||
PROTO_TP = 29, /* SO Transport Protocol Class 4. */
|
||||
PROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
|
||||
PROTO_IPV6 = 41, /* IPv6 header. */
|
||||
PROTO_ROUTING = 43, /* IPv6 routing header. */
|
||||
PROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
|
||||
PROTO_RSVP = 46, /* Reservation Protocol. */
|
||||
PROTO_GRE = 47, /* General Routing Encapsulation. */
|
||||
PROTO_ESP = 50, /* encapsulating security payload. */
|
||||
PROTO_AH = 51, /* authentication header. */
|
||||
PROTO_ICMPV6 = 58, /* ICMPv6. */
|
||||
PROTO_NONE = 59, /* IPv6 no next header. */
|
||||
PROTO_DSTOPTS = 60, /* IPv6 destination options. */
|
||||
PROTO_MTP = 92, /* Multicast Transport Protocol. */
|
||||
PROTO_ENCAP = 98, /* Encapsulation Header. */
|
||||
PROTO_PIM = 103, /* Protocol Independent Multicast. */
|
||||
PROTO_COMP = 108, /* Compression Header Protocol. */
|
||||
PROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
|
||||
PROTO_UDPLITE = 136, /* UDP-Lite protocol. */
|
||||
PROTO_RAW = 255 /* Raw IP packets. */
|
||||
};
|
||||
};
|
||||
|
||||
struct Ethernet {
|
||||
enum e {
|
||||
UNKNOWN = 0,
|
||||
//~ PUP = 0x0200, /* Xerox PUP */
|
||||
SPRITE = 0x0500, /* Sprite */
|
||||
IP = 0x0800, /* IP */
|
||||
ARP = 0x0806, /* Address resolution */
|
||||
REVARP = 0x8035, /* Reverse ARP */
|
||||
AT = 0x809B, /* AppleTalk protocol */
|
||||
AARP = 0x80F3, /* AppleTalk ARP */
|
||||
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */
|
||||
IPX = 0x8137, /* IPX */
|
||||
IPV6 = 0x86dd, /* IP protocol version 6 */
|
||||
PPPOED = 0x8863, /* PPPoE Discovery */
|
||||
PPPOES = 0x8864, /* PPPoE Session */
|
||||
EAPOL = 0x888e, /* EAPOL */
|
||||
LOOPBACK = 0x9000 /* used to test interfaces */
|
||||
};
|
||||
};
|
||||
|
||||
struct ARP {
|
||||
enum e {
|
||||
NETROM = 0, /* From KA9Q: NET/ROM pseudo. */
|
||||
ETHER = 1, /* Ethernet 10/100Mbps. */
|
||||
EETHER = 2, /* Experimental Ethernet. */
|
||||
AX25 = 3, /* AX.25 Level 2. */
|
||||
PRONET = 4, /* PROnet token ring. */
|
||||
CHAOS = 5, /* Chaosnet. */
|
||||
IEEE802 = 6, /* IEEE 802.2 Ethernet/TR/TB. */
|
||||
ARCNET = 7, /* ARCnet. */
|
||||
APPLETLK = 8, /* APPLEtalk. */
|
||||
DLCI = 15, /* Frame Relay DLCI. */
|
||||
ATM = 19, /* ATM. */
|
||||
METRICOM = 23, /* Metricom STRIP (new IANA id). */
|
||||
IEEE1394 = 24, /* IEEE 1394 IPv4 - RFC 2734. */
|
||||
EUI64 = 27, /* EUI-64. */
|
||||
INFINIBAND = 32, /* InfiniBand. */
|
||||
SLIP = 256,
|
||||
CSLIP = 257,
|
||||
SLIP6 = 258,
|
||||
CSLIP6 = 259,
|
||||
RSRVD = 260, /* Notional KISS type. */
|
||||
ADAPT = 264,
|
||||
ROSE = 270,
|
||||
X25 = 271, /* CCITT X.25. */
|
||||
HWX25 = 272, /* Boards with X.25 in firmware. */
|
||||
PPP = 512,
|
||||
CISCO = 513, /* Cisco HDLC. */
|
||||
HDLC = CISCO,
|
||||
LAPB = 516, /* LAPB. */
|
||||
DDCMP = 517, /* Digital's DDCMP. */
|
||||
RAWHDLC = 518, /* Raw HDLC. */
|
||||
TUNNEL = 768, /* IPIP tunnel. */
|
||||
TUNNEL6 = 769, /* IPIP6 tunnel. */
|
||||
FRAD = 770, /* Frame Relay Access Device. */
|
||||
SKIP = 771, /* SKIP vif. */
|
||||
LOOPBACK = 772, /* Loopback device. */
|
||||
LOCALTLK = 773, /* Localtalk device. */
|
||||
FDDI = 774, /* Fiber Distributed Data Interface. */
|
||||
BIF = 775, /* AP1000 BIF. */
|
||||
SIT = 776, /* sit0 device - IPv6-in-IPv4. */
|
||||
IPDDP = 777, /* IP-in-DDP tunnel. */
|
||||
IPGRE = 778, /* GRE over IP. */
|
||||
PIMREG = 779, /* PIMSM register interface. */
|
||||
HIPPI = 780, /* High Performance Parallel I'face. */
|
||||
ASH = 781, /* (Nexus Electronics) Ash. */
|
||||
ECONET = 782, /* Acorn Econet. */
|
||||
IRDA = 783, /* Linux-IrDA. */
|
||||
FCPP = 784, /* Point to point fibrechanel. */
|
||||
FCAL = 785, /* Fibrechanel arbitrated loop. */
|
||||
FCPL = 786, /* Fibrechanel public loop. */
|
||||
FCFABRIC = 787, /* Fibrechanel fabric. */
|
||||
IEEE802_TR = 800, /* Magic type ident for TR. */
|
||||
IEEE80211 = 801, /* IEEE 802.11. */
|
||||
IEEE80211_PRISM = 802, /* IEEE 802.11 + Prism2 header. */
|
||||
IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */
|
||||
IEEE802154 = 804, /* IEEE 802.15.4 header. */
|
||||
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
|
||||
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
|
||||
NONE = 0xFFFE /* Zero header length. */
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constants used in protocols.
|
||||
*/
|
||||
namespace Constants {
|
||||
/** \cond */
|
||||
struct IP {
|
||||
/** \endcond */
|
||||
enum e {
|
||||
PROTO_IP = 0, // Dummy protocol for TCP.
|
||||
PROTO_HOPOPTS = 0, // IPv6 Hop-by-Hop options.
|
||||
PROTO_ICMP = 1, // Internet Control Message Protocol.
|
||||
PROTO_IGMP = 2, // Internet Group Management Protocol.
|
||||
PROTO_IPIP = 4, // IPIP tunnels (older KA9Q tunnels use 94).
|
||||
PROTO_TCP = 6, // Transmission Control Protocol.
|
||||
PROTO_EGP = 8, // Exterior Gateway Protocol.
|
||||
PROTO_PUP = 12, // PUP protocol.
|
||||
PROTO_UDP = 17, // User Datagram Protocol.
|
||||
PROTO_IDP = 22, // XNS IDP protocol.
|
||||
PROTO_TP = 29, // SO Transport Protocol Class 4.
|
||||
PROTO_DCCP = 33, // Datagram Congestion Control Protocol.
|
||||
PROTO_IPV6 = 41, // IPv6 header.
|
||||
PROTO_ROUTING = 43, // IPv6 routing header.
|
||||
PROTO_FRAGMENT = 44, // IPv6 fragmentation header.
|
||||
PROTO_RSVP = 46, // Reservation Protocol.
|
||||
PROTO_GRE = 47, // General Routing Encapsulation.
|
||||
PROTO_ESP = 50, // encapsulating security payload.
|
||||
PROTO_AH = 51, // authentication header.
|
||||
PROTO_ICMPV6 = 58, // ICMPv6.
|
||||
PROTO_NONE = 59, // IPv6 no next header.
|
||||
PROTO_DSTOPTS = 60, // IPv6 destination options.
|
||||
PROTO_MTP = 92, // Multicast Transport Protocol.
|
||||
PROTO_ENCAP = 98, // Encapsulation Header.
|
||||
PROTO_PIM = 103, // Protocol Independent Multicast.
|
||||
PROTO_COMP = 108, // Compression Header Protocol.
|
||||
PROTO_SCTP = 132, // Stream Control Transmission Protocol.
|
||||
PROTO_UDPLITE = 136, // UDP-Lite protocol.
|
||||
PROTO_RAW = 255 // Raw IP packets.
|
||||
};
|
||||
};
|
||||
|
||||
struct Ethernet {
|
||||
enum e {
|
||||
UNKNOWN = 0,
|
||||
SPRITE = 0x0500, // Sprite
|
||||
IP = 0x0800, // IP
|
||||
ARP = 0x0806, // Address resolution
|
||||
MPLS = 0x8847, // MPLS
|
||||
REVARP = 0x8035, // Reverse ARP
|
||||
AT = 0x809B, // AppleTalk protocol
|
||||
AARP = 0x80F3, // AppleTalk ARP
|
||||
VLAN = 0x8100, // IEEE 802.1Q VLAN tagging
|
||||
QINQ = 0x88a8, // IEEE 802.1ad VLAN tagging
|
||||
OLD_QINQ = 0x9100, // IEEE 802.1ad VLAN tagging (old, deprecated, value)
|
||||
IPX = 0x8137, // IPX
|
||||
IPV6 = 0x86dd, // IP protocol version 6
|
||||
PPPOED = 0x8863, // PPPoE Discovery
|
||||
PPPOES = 0x8864, // PPPoE Session
|
||||
EAPOL = 0x888e, // EAPOL
|
||||
LOOPBACK = 0x9000 // used to test interfaces
|
||||
};
|
||||
};
|
||||
|
||||
struct ARP {
|
||||
enum e {
|
||||
NETROM = 0, // From KA9Q: NET/ROM pseudo.
|
||||
ETHER = 1, // Ethernet 10/100Mbps.
|
||||
EETHER = 2, // Experimental Ethernet.
|
||||
AX25 = 3, // AX.25 Level 2.
|
||||
PRONET = 4, // PROnet token ring.
|
||||
CHAOS = 5, // Chaosnet.
|
||||
IEEE802 = 6, // IEEE 802.2 Ethernet/TR/TB.
|
||||
ARCNET = 7, // ARCnet.
|
||||
APPLETLK = 8, // APPLEtalk.
|
||||
DLCI = 15, // Frame Relay DLCI.
|
||||
ATM = 19, // ATM.
|
||||
METRICOM = 23, // Metricom STRIP (new IANA id).
|
||||
IEEE1394 = 24, // IEEE 1394 IPv4 - RFC 2734.
|
||||
EUI64 = 27, // EUI-64.
|
||||
INFINIBAND = 32, // InfiniBand.
|
||||
SLIP = 256,
|
||||
CSLIP = 257,
|
||||
SLIP6 = 258,
|
||||
CSLIP6 = 259,
|
||||
RSRVD = 260, // Notional KISS type.
|
||||
ADAPT = 264,
|
||||
ROSE = 270,
|
||||
X25 = 271, // CCITT X.25.
|
||||
HWX25 = 272, // Boards with X.25 in firmware.
|
||||
PPP = 512,
|
||||
CISCO = 513, // Cisco HDLC.
|
||||
HDLC = CISCO,
|
||||
LAPB = 516, // LAPB.
|
||||
DDCMP = 517, // Digital's DDCMP.
|
||||
RAWHDLC = 518, // Raw HDLC.
|
||||
TUNNEL = 768, // IPIP tunnel.
|
||||
TUNNEL6 = 769, // IPIP6 tunnel.
|
||||
FRAD = 770, // Frame Relay Access Device.
|
||||
SKIP = 771, // SKIP vif.
|
||||
LOOPBACK = 772, // Loopback device.
|
||||
LOCALTLK = 773, // Localtalk device.
|
||||
FDDI = 774, // Fiber Distributed Data Interface.
|
||||
BIF = 775, // AP1000 BIF.
|
||||
SIT = 776, // sit0 device - IPv6-in-IPv4.
|
||||
IPDDP = 777, // IP-in-DDP tunnel.
|
||||
IPGRE = 778, // GRE over IP.
|
||||
PIMREG = 779, // PIMSM register interface.
|
||||
HIPPI = 780, // High Performance Parallel I'face.
|
||||
ASH = 781, // (Nexus Electronics) Ash.
|
||||
ECONET = 782, // Acorn Econet.
|
||||
IRDA = 783, // Linux-IrDA.
|
||||
FCPP = 784, // Point to point fibrechanel.
|
||||
FCAL = 785, // Fibrechanel arbitrated loop.
|
||||
FCPL = 786, // Fibrechanel public loop.
|
||||
FCFABRIC = 787, // Fibrechanel fabric.
|
||||
IEEE802_TR = 800, // Magic type ident for TR.
|
||||
IEEE80211 = 801, // IEEE 802.11.
|
||||
IEEE80211_PRISM = 802, // IEEE 802.11 + Prism2 header.
|
||||
IEEE80211_RADIOTAP = 803, // IEEE 802.11 + radiotap header.
|
||||
IEEE802154 = 804, // IEEE 802.15.4 header.
|
||||
IEEE802154_PHY = 805, // IEEE 802.15.4 PHY header.
|
||||
VOID_TYPE = 0xFFFF, // Void type, nothing is known.
|
||||
NONE = 0xFFFE // Zero header length.
|
||||
};
|
||||
};
|
||||
|
||||
} // Constants
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_CONSTANTS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,377 +39,503 @@
|
||||
#include "utils.h"
|
||||
#include "snap.h"
|
||||
#include "rawpdu.h"
|
||||
#include "macros.h"
|
||||
#include "handshake_capturer.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class PDU;
|
||||
class Dot11;
|
||||
class Dot11Data;
|
||||
|
||||
namespace Crypto {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
struct RC4Key;
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
namespace WPA2 {
|
||||
class invalid_handshake : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "invalid handshake";
|
||||
}
|
||||
};
|
||||
class SessionKeys {
|
||||
public:
|
||||
typedef Internals::byte_array<80> ptk_type;
|
||||
typedef Internals::byte_array<32> pmk_type;
|
||||
|
||||
SessionKeys();
|
||||
SessionKeys(const RSNHandshake &hs, const pmk_type &pmk);
|
||||
SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
private:
|
||||
SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const;
|
||||
|
||||
ptk_type ptk;
|
||||
bool is_ccmp;
|
||||
};
|
||||
|
||||
class SupplicantData {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
typedef SessionKeys::pmk_type pmk_type;
|
||||
|
||||
SupplicantData(const std::string &psk, const std::string &ssid);
|
||||
|
||||
const pmk_type &pmk() const;
|
||||
private:
|
||||
pmk_type pmk_;
|
||||
};
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
struct RC4Key;
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
namespace WPA2 {
|
||||
|
||||
/**
|
||||
* \brief Class that represents the keys used to decrypt a session.
|
||||
*/
|
||||
class TINS_API SessionKeys {
|
||||
public:
|
||||
/**
|
||||
* \endcond
|
||||
* The size of the Pairwise Master Key.
|
||||
*/
|
||||
static const size_t PMK_SIZE;
|
||||
|
||||
/**
|
||||
* \brief RC4 Key abstraction.
|
||||
* The size of the Pairwise Transient Key.
|
||||
*/
|
||||
struct RC4Key {
|
||||
static const size_t data_size = 256;
|
||||
|
||||
/**
|
||||
* \brief Initializes the key using the provided iterator range.
|
||||
*
|
||||
* \param start The start of the range.
|
||||
* \param end The end of the range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RC4Key(ForwardIterator start, ForwardIterator end);
|
||||
|
||||
/**
|
||||
* The actual key data.
|
||||
*/
|
||||
uint8_t data[data_size];
|
||||
};
|
||||
static const size_t PTK_SIZE;
|
||||
|
||||
/**
|
||||
* \brief Decrypts WEP-encrypted traffic.
|
||||
* The type used to hold the PTK (this has to be PTK_SIZE bytes long).
|
||||
*/
|
||||
class WEPDecrypter {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
typedef std::vector<uint8_t> ptk_type;
|
||||
|
||||
/**
|
||||
* The type used to hold the PMK (this has to be PMK_SIZE bytes long).
|
||||
*/
|
||||
typedef std::vector<uint8_t> pmk_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs a WEPDecrypter object.
|
||||
*/
|
||||
WEPDecrypter();
|
||||
|
||||
/**
|
||||
* \brief Adds a decryption password.
|
||||
*
|
||||
* \param addr The access point's BSSID.
|
||||
* \param password The password which will be used to decrypt
|
||||
* packets sent from and to the AP identifier by the BSSID addr.
|
||||
*/
|
||||
void add_password(const address_type &addr, const std::string &password);
|
||||
|
||||
/**
|
||||
* \brief Removes a decryption password
|
||||
*
|
||||
* \param addr The BSSID of the access point.
|
||||
*/
|
||||
void remove_password(const address_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or there is no password associated
|
||||
* with the Dot11 packet's BSSID, then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the given password.
|
||||
* If the CRC found after decrypting is invalid, false is
|
||||
* returned.
|
||||
*
|
||||
* \return false if no decryption was performed or decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU &pdu);
|
||||
private:
|
||||
typedef std::map<address_type, std::string> passwords_type;
|
||||
|
||||
PDU *decrypt(RawPDU &raw, const std::string &password);
|
||||
|
||||
passwords_type passwords;
|
||||
std::vector<uint8_t> key_buffer;
|
||||
};
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Decrypts WPA2-encrypted traffic.
|
||||
* Default constructs a SessionKeys object.
|
||||
*/
|
||||
SessionKeys();
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance using the provided PTK and a flag
|
||||
* indicating whether it should use ccmp.
|
||||
*
|
||||
* This class takes valid PSK and SSID tuples, captures client handshakes,
|
||||
* and decrypts their traffic afterwards.
|
||||
* \param ptk The PTK to use.
|
||||
* \param is_ccmp Indicates whether to use CCMP to decrypt this traffic.
|
||||
*/
|
||||
class WPA2Decrypter {
|
||||
public:
|
||||
/*
|
||||
* \brief The type used to store Dot11 addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Adds an access points's information.
|
||||
*
|
||||
* This associates an SSID with a PSK, and allows the decryption of
|
||||
* any BSSIDs that broadcast the same SSID.
|
||||
*
|
||||
* The decrypter will inspect beacon frames, looking for SSID tags
|
||||
* that contain the given SSID.
|
||||
*
|
||||
* Note that using this overload, the decryption of data frames and
|
||||
* handshake capturing will be disabled until any access point
|
||||
* broadcasts the provided SSID(this shouldn't take long at all).
|
||||
* If this is not the desired behaviour, then you should check out
|
||||
* the ovther add_ap_data overload.
|
||||
*
|
||||
* \param psk The PSK associated with the SSID.
|
||||
* \param ssid The network's SSID.
|
||||
*/
|
||||
void add_ap_data(const std::string &psk, const std::string &ssid);
|
||||
|
||||
/**
|
||||
* \brief Adds a access points's information, including its BSSID.
|
||||
*
|
||||
* This overload can be used if the BSSID associated with this SSID is
|
||||
* known beforehand. The addr parameter indicates which specific BSSID
|
||||
* is associated to the SSID.
|
||||
*
|
||||
* Note that if any other access point broadcasts the provided SSID,
|
||||
* it will be taken into account as well.
|
||||
*
|
||||
* \param psk The PSK associated with this SSID.
|
||||
* \param ssid The network's SSID.
|
||||
* \param addr The access point's BSSID.
|
||||
*/
|
||||
void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or no PSK was associated with the SSID
|
||||
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
|
||||
* was captured for the client involved in the communication,
|
||||
* then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the generated PTK.
|
||||
* If the resulting MIC is invalid, then the packet is left intact.
|
||||
*
|
||||
* \return false if no decryption was performed, or the decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU &pdu);
|
||||
private:
|
||||
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
|
||||
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
|
||||
typedef std::pair<address_type, address_type> addr_pair;
|
||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
||||
|
||||
void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs);
|
||||
addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) {
|
||||
return (addr1 < addr2) ?
|
||||
std::make_pair(addr1, addr2) :
|
||||
std::make_pair(addr2, addr1);
|
||||
}
|
||||
addr_pair extract_addr_pair(const Dot11Data &dot11);
|
||||
addr_pair extract_addr_pair_dst(const Dot11Data &dot11);
|
||||
bssids_map::const_iterator find_ap(const Dot11Data &dot11);
|
||||
void add_access_point(const std::string &ssid, const address_type &addr);
|
||||
|
||||
RSNHandshakeCapturer capturer;
|
||||
pmks_map pmks;
|
||||
bssids_map aps;
|
||||
keys_map keys;
|
||||
};
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
SessionKeys(const ptk_type& ptk, bool is_ccmp);
|
||||
|
||||
/**
|
||||
* \brief Pluggable decrypter object which can be used to decrypt
|
||||
* data on sniffing sessions.
|
||||
*
|
||||
* This class holds a decrypter object and a functor, and implements
|
||||
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
|
||||
* decrypts packets and forwards them to the given functor.
|
||||
* \brief Constructs an instance using a handshake and a PMK.
|
||||
*
|
||||
* This will internally construct the PTK from the input parameters.
|
||||
*
|
||||
* \param hs The handshake to use.
|
||||
* \param pmk The PMK to use.
|
||||
*/
|
||||
template<typename Functor, typename Decrypter>
|
||||
class DecrypterProxy {
|
||||
public:
|
||||
/**
|
||||
* The type of the functor object.
|
||||
*/
|
||||
typedef Functor functor_type;
|
||||
|
||||
/**
|
||||
* The type of the decrypter object.
|
||||
*/
|
||||
typedef Decrypter decrypter_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an object from a functor and a decrypter.
|
||||
* \param func The functor to be used to forward decrypted
|
||||
* packets.
|
||||
* \param decrypter The decrypter which will be used to decrypt
|
||||
* packets
|
||||
*/
|
||||
DecrypterProxy(const functor_type &func,
|
||||
const decrypter_type &decr = decrypter_type());
|
||||
|
||||
/**
|
||||
* \brief Retrieves a reference to the decrypter object.
|
||||
*/
|
||||
decrypter_type &decrypter();
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const reference to the decrypter object.
|
||||
*/
|
||||
const decrypter_type &decrypter() const;
|
||||
|
||||
/**
|
||||
* \brief The operator() which decrypts packets and forwards
|
||||
* them to the functor.
|
||||
*/
|
||||
bool operator() (PDU &pdu);
|
||||
private:
|
||||
Functor functor_;
|
||||
decrypter_type decrypter_;
|
||||
};
|
||||
SessionKeys(const RSNHandshake& hs, const pmk_type& pmk);
|
||||
|
||||
/**
|
||||
* \brief Performs RC4 encription/decryption of the given byte range,
|
||||
* using the provided key.
|
||||
*
|
||||
* The decrypted range will be copied to the OutputIterator provided.
|
||||
*
|
||||
* \param start The beginning of the range.
|
||||
* \param start The end of the range.
|
||||
* \param key The key to be used.
|
||||
* \param output The iterator in which to write the output.
|
||||
* \brief Decrypts a unicast packet.
|
||||
*
|
||||
* \param dot11 The encrypted packet to decrypt.
|
||||
* \param raw The raw layer on the packet to decrypt.
|
||||
* \return A SNAP layer containing the decrypted traffic or a null pointer
|
||||
* if decryption failed.
|
||||
*/
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output);
|
||||
SNAP* decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
|
||||
|
||||
/**
|
||||
* \brief Gets the PTK for this session keys.
|
||||
* \return The Pairwise Transcient Key.
|
||||
*/
|
||||
const ptk_type& get_ptk() const;
|
||||
|
||||
/**
|
||||
* \brief Indicates whether CCMP is used to decrypt packets
|
||||
* /return true iff CCMP is used.
|
||||
*/
|
||||
bool uses_ccmp() const;
|
||||
private:
|
||||
SNAP* ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
|
||||
SNAP* tkip_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
|
||||
RC4Key generate_rc4_key(const Dot11Data& dot11, const RawPDU& raw) const;
|
||||
|
||||
ptk_type ptk_;
|
||||
bool is_ccmp_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Represents a WPA2 supplicant's data.
|
||||
*
|
||||
* Objects of this class can be given the pre-shared key and the SSID
|
||||
* of some access point, and this will generate the Pairwise Master Key
|
||||
* from those parameters.
|
||||
*/
|
||||
class TINS_API SupplicantData {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the PMK.
|
||||
*/
|
||||
typedef SessionKeys::pmk_type pmk_type;
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WEPDecrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
* \brief Constructs a SupplicantData.
|
||||
* \param psk The pre-shared key.
|
||||
* \param ssid The access point's SSID.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor);
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
SupplicantData(const std::string& psk, const std::string& ssid);
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WPA2Decrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
* \brief Getter for the PMK.
|
||||
* \return The generated PMK.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor &functor) {
|
||||
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
// Implementation section
|
||||
|
||||
// DecrypterProxy
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(
|
||||
const functor_type &func, const decrypter_type& decr)
|
||||
: functor_(func), decrypter_(decr)
|
||||
{
|
||||
|
||||
}
|
||||
const pmk_type& pmk() const;
|
||||
private:
|
||||
pmk_type pmk_;
|
||||
};
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter()
|
||||
{
|
||||
return decrypter_;
|
||||
}
|
||||
} // WPA2
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() const
|
||||
{
|
||||
return decrypter_;
|
||||
}
|
||||
/**
|
||||
* \brief RC4 Key abstraction.
|
||||
*/
|
||||
struct RC4Key {
|
||||
static const size_t data_size = 256;
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU &pdu)
|
||||
{
|
||||
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor)
|
||||
{
|
||||
return DecrypterProxy<Functor, WEPDecrypter>(functor);
|
||||
}
|
||||
|
||||
// RC4 stuff
|
||||
|
||||
/**
|
||||
* \brief Initializes the key using the provided iterator range.
|
||||
*
|
||||
* \param start The start of the range.
|
||||
* \param end The end of the range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
|
||||
for(size_t i = 0; i < data_size; ++i)
|
||||
data[i] = i;
|
||||
size_t j = 0;
|
||||
ForwardIterator iter = start;
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
j = (j + data[i] + *iter++) % 256;
|
||||
if(iter == end)
|
||||
iter = start;
|
||||
std::swap(data[i], data[j]);
|
||||
}
|
||||
}
|
||||
RC4Key(ForwardIterator start, ForwardIterator end);
|
||||
|
||||
/**
|
||||
* The actual key data.
|
||||
*/
|
||||
uint8_t data[data_size];
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Decrypts WEP-encrypted traffic.
|
||||
*/
|
||||
class TINS_API WEPDecrypter {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs a WEPDecrypter object.
|
||||
*/
|
||||
WEPDecrypter();
|
||||
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output) {
|
||||
size_t i = 0, j = 0;
|
||||
while(start != end) {
|
||||
i = (i + 1) % RC4Key::data_size;
|
||||
j = (j + key.data[i]) % RC4Key::data_size;
|
||||
std::swap(key.data[i], key.data[j]);
|
||||
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
|
||||
/**
|
||||
* \brief Adds a decryption password.
|
||||
*
|
||||
* \param addr The access point's BSSID.
|
||||
* \param password The password which will be used to decrypt
|
||||
* packets sent from and to the AP identifier by the BSSID addr.
|
||||
*/
|
||||
void add_password(const address_type& addr, const std::string& password);
|
||||
|
||||
/**
|
||||
* \brief Removes a decryption password
|
||||
*
|
||||
* \param addr The BSSID of the access point.
|
||||
*/
|
||||
void remove_password(const address_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or there is no password associated
|
||||
* with the Dot11 packet's BSSID, then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the given password.
|
||||
* If the CRC found after decrypting is invalid, false is
|
||||
* returned.
|
||||
*
|
||||
* \return false if no decryption was performed or decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU& pdu);
|
||||
private:
|
||||
typedef std::map<address_type, std::string> passwords_type;
|
||||
|
||||
PDU* decrypt(RawPDU& raw, const std::string& password);
|
||||
|
||||
passwords_type passwords_;
|
||||
std::vector<uint8_t> key_buffer_;
|
||||
};
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Decrypts WPA2-encrypted traffic.
|
||||
*
|
||||
* This class takes valid PSK and SSID tuples, captures client handshakes,
|
||||
* and decrypts their traffic afterwards.
|
||||
*/
|
||||
class TINS_API WPA2Decrypter {
|
||||
public:
|
||||
/*
|
||||
* \brief The type used to store Dot11 addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Represents a pair of mac addresses.
|
||||
*
|
||||
* This is used to identify a host and the access point to which
|
||||
* it is connected. The first element in the pair will always de
|
||||
* lower or equal than the second one, so that given any host and
|
||||
* the access point it's connected to, we can uniquely identify
|
||||
* it with an address pair.
|
||||
*/
|
||||
typedef std::pair<address_type, address_type> addr_pair;
|
||||
|
||||
/**
|
||||
* \brief Maps an address pair to the session keys.
|
||||
*
|
||||
* This type associates an address pair (host, access point) with the
|
||||
* session keys, as generated using the packets seen on a handshake.
|
||||
*
|
||||
* \sa addr_pair
|
||||
*/
|
||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
||||
|
||||
/**
|
||||
* \brief Adds an access points's information.
|
||||
*
|
||||
* This associates an SSID with a PSK, and allows the decryption of
|
||||
* any BSSIDs that broadcast the same SSID.
|
||||
*
|
||||
* The decrypter will inspect beacon frames, looking for SSID tags
|
||||
* that contain the given SSID.
|
||||
*
|
||||
* Note that using this overload, the decryption of data frames and
|
||||
* handshake capturing will be disabled until any access point
|
||||
* broadcasts the provided SSID(this shouldn't take long at all).
|
||||
* If this is not the desired behaviour, then you should check out
|
||||
* the ovther add_ap_data overload.
|
||||
*
|
||||
* \param psk The PSK associated with the SSID.
|
||||
* \param ssid The network's SSID.
|
||||
*/
|
||||
void add_ap_data(const std::string& psk, const std::string& ssid);
|
||||
|
||||
/**
|
||||
* \brief Adds a access points's information, including its BSSID.
|
||||
*
|
||||
* This overload can be used if the BSSID associated with this SSID is
|
||||
* known beforehand. The addr parameter indicates which specific BSSID
|
||||
* is associated to the SSID.
|
||||
*
|
||||
* Note that if any other access point broadcasts the provided SSID,
|
||||
* it will be taken into account as well.
|
||||
*
|
||||
* \param psk The PSK associated with this SSID.
|
||||
* \param ssid The network's SSID.
|
||||
* \param addr The access point's BSSID.
|
||||
*/
|
||||
void add_ap_data(const std::string& psk,
|
||||
const std::string& ssid,
|
||||
const address_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Explicitly add decryption keys.
|
||||
*
|
||||
* This method associates a pair (host, access point) with the given decryption keys.
|
||||
* All encrypted packets sent between the given addresses will be decrypted using the
|
||||
* provided keys.
|
||||
*
|
||||
* This method shouldn't normally be required. The WPA2Decrypter will be waiting for
|
||||
* handshakes and will automatically extract the session keys, decrypting all
|
||||
* encrypted packets with them. You should only use this method if for some reason
|
||||
* you know the actual keys being used (because you checked and stored the keys_map
|
||||
* somewhere).
|
||||
*
|
||||
* The actual order of the addresses doesn't matter, this method will make sure
|
||||
* they're sorted.
|
||||
*
|
||||
* \param addresses The address pair (host, access point) to associate.
|
||||
* \param session_keys The keys to use when decrypting messages sent between the
|
||||
* given addresses.
|
||||
*/
|
||||
void add_decryption_keys(const addr_pair& addresses,
|
||||
const WPA2::SessionKeys& session_keys);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or no PSK was associated with the SSID
|
||||
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
|
||||
* was captured for the client involved in the communication,
|
||||
* then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the generated PTK.
|
||||
* If the resulting MIC is invalid, then the packet is left intact.
|
||||
*
|
||||
* \return false if no decryption was performed, or the decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU& pdu);
|
||||
|
||||
/**
|
||||
* \brief Getter for the keys on this decrypter
|
||||
*
|
||||
* The returned map will be populated every time a new, complete, handshake
|
||||
* is captured.
|
||||
*
|
||||
* \return The WPA2Decrypter keys map.
|
||||
*/
|
||||
const keys_map& get_keys() const;
|
||||
private:
|
||||
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
|
||||
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
|
||||
|
||||
void try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs);
|
||||
addr_pair make_addr_pair(const address_type& addr1, const address_type& addr2) {
|
||||
return (addr1 < addr2) ?
|
||||
std::make_pair(addr1, addr2) :
|
||||
std::make_pair(addr2, addr1);
|
||||
}
|
||||
addr_pair extract_addr_pair(const Dot11Data& dot11);
|
||||
addr_pair extract_addr_pair_dst(const Dot11Data& dot11);
|
||||
bssids_map::const_iterator find_ap(const Dot11Data& dot11);
|
||||
void add_access_point(const std::string& ssid, const address_type& addr);
|
||||
|
||||
RSNHandshakeCapturer capturer_;
|
||||
pmks_map pmks_;
|
||||
bssids_map aps_;
|
||||
keys_map keys_;
|
||||
};
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
/**
|
||||
* \brief Pluggable decrypter object which can be used to decrypt
|
||||
* data on sniffing sessions.
|
||||
*
|
||||
* This class holds a decrypter object and a functor, and implements
|
||||
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
|
||||
* decrypts packets and forwards them to the given functor.
|
||||
*/
|
||||
template<typename Functor, typename Decrypter>
|
||||
class DecrypterProxy {
|
||||
public:
|
||||
/**
|
||||
* The type of the functor object.
|
||||
*/
|
||||
typedef Functor functor_type;
|
||||
|
||||
/**
|
||||
* The type of the decrypter object.
|
||||
*/
|
||||
typedef Decrypter decrypter_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an object from a functor and a decrypter.
|
||||
* \param func The functor to be used to forward decrypted
|
||||
* packets.
|
||||
* \param decrypter The decrypter which will be used to decrypt
|
||||
* packets
|
||||
*/
|
||||
DecrypterProxy(const functor_type& func,
|
||||
const decrypter_type& decr = decrypter_type());
|
||||
|
||||
/**
|
||||
* \brief Retrieves a reference to the decrypter object.
|
||||
*/
|
||||
decrypter_type& decrypter();
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const reference to the decrypter object.
|
||||
*/
|
||||
const decrypter_type& decrypter() const;
|
||||
|
||||
/**
|
||||
* \brief The operator() which decrypts packets and forwards
|
||||
* them to the functor.
|
||||
*/
|
||||
bool operator() (PDU& pdu);
|
||||
private:
|
||||
Functor functor_;
|
||||
decrypter_type decrypter_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Performs RC4 encription/decryption of the given byte range,
|
||||
* using the provided key.
|
||||
*
|
||||
* The decrypted range will be copied to the OutputIterator provided.
|
||||
*
|
||||
* \param start The beginning of the range.
|
||||
* \param start The end of the range.
|
||||
* \param key The key to be used.
|
||||
* \param output The iterator in which to write the output.
|
||||
*/
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator output);
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WEPDecrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor);
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WPA2Decrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor& functor) {
|
||||
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
// Implementation section
|
||||
|
||||
// DecrypterProxy
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(const functor_type& func,
|
||||
const decrypter_type& decr)
|
||||
: functor_(func), decrypter_(decr) {
|
||||
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() {
|
||||
return decrypter_;
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() const {
|
||||
return decrypter_;
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU& pdu) {
|
||||
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor) {
|
||||
return DecrypterProxy<Functor, WEPDecrypter>(functor);
|
||||
}
|
||||
|
||||
// RC4 stuff
|
||||
|
||||
template<typename ForwardIterator>
|
||||
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
|
||||
for (size_t i = 0; i < data_size; ++i) {
|
||||
data[i] = static_cast<uint8_t>(i);
|
||||
}
|
||||
size_t j = 0;
|
||||
ForwardIterator iter = start;
|
||||
for (size_t i = 0; i < data_size; ++i) {
|
||||
j = (j + data[i] + *iter++) % 256;
|
||||
if(iter == end) {
|
||||
iter = start;
|
||||
}
|
||||
std::swap(data[i], data[j]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key& key, OutputIterator output) {
|
||||
size_t i = 0, j = 0;
|
||||
while (start != end) {
|
||||
i = (i + 1) % RC4Key::data_size;
|
||||
j = (j + key.data[i]) % RC4Key::data_size;
|
||||
std::swap(key.data[i], key.data[j]);
|
||||
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
|
||||
}
|
||||
}
|
||||
|
||||
} // Crypto
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_CRYPTO_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,6 +30,8 @@
|
||||
#ifndef TINS_CXXSTD_H
|
||||
#define TINS_CXXSTD_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
@@ -38,8 +40,10 @@
|
||||
#define TINS_CXXSTD_GCC_FIX 0
|
||||
#endif // __GXX_EXPERIMENTAL_CXX0X__
|
||||
|
||||
#ifndef TINS_IS_CXX11
|
||||
#if !defined(TINS_IS_CXX11) && defined(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
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
namespace Tins{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,481 +30,497 @@
|
||||
#ifndef TINS_DHCP_H
|
||||
#define TINS_DHCP_H
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "bootp.h"
|
||||
#include "macros.h"
|
||||
#include "pdu_option.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class DHCP
|
||||
* \brief Represents the DHCP PDU.
|
||||
*
|
||||
* This class represents a DHCP PDU. It contains helpers methods
|
||||
* which make it easy to set/get specific option values.
|
||||
*
|
||||
* Note that when adding options, the "End" option is not added
|
||||
* automatically, so you will have to add it yourself.
|
||||
*
|
||||
* Options can be retrieved easily from DHCP PDUs:
|
||||
*
|
||||
* \code
|
||||
* // Sniff a packet from somewhere
|
||||
* DHCP dhcp = get_dhcp_from_somewhere();
|
||||
*
|
||||
* // This retrieves the Domain Name Servers option and converts
|
||||
* // it to a std::vector<IPv4Address>. Note that if this option
|
||||
* // is not present, an option_not_found exception is thrown.
|
||||
* for(const auto& address : dhcp.domain_name_servers()) {
|
||||
* // address is an ip
|
||||
* }
|
||||
*
|
||||
* \endcode
|
||||
|
||||
/**
|
||||
* \class DHCP
|
||||
* \brief Represents the DHCP PDU.
|
||||
*
|
||||
* This class represents a DHCP PDU. It contains helpers methods
|
||||
* which make it easy to set/get specific option values.
|
||||
*
|
||||
* Note that when adding options, the "End" option is not added
|
||||
* automatically, so you will have to add it yourself.
|
||||
*
|
||||
* Options can be retrieved easily from DHCP PDUs:
|
||||
*
|
||||
* \code
|
||||
* // Sniff a packet from somewhere
|
||||
* DHCP dhcp = get_dhcp_from_somewhere();
|
||||
*
|
||||
* // This retrieves the Domain Name Servers option and converts
|
||||
* // it to a std::vector<IPv4Address>. Note that if this option
|
||||
* // is not present, an option_not_found exception is thrown.
|
||||
* for(const auto& address : dhcp.domain_name_servers()) {
|
||||
* // address is an ip
|
||||
* }
|
||||
*
|
||||
* \endcode
|
||||
*/
|
||||
class TINS_API DHCP : public BootP {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
class DHCP : public BootP {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCP;
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCP;
|
||||
|
||||
/**
|
||||
* DHCP flags.
|
||||
*/
|
||||
enum Flags {
|
||||
DISCOVER = 1,
|
||||
OFFER = 2,
|
||||
REQUEST = 3,
|
||||
DECLINE = 4,
|
||||
ACK = 5,
|
||||
NAK = 6,
|
||||
RELEASE = 7,
|
||||
INFORM = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* DHCP flags.
|
||||
*/
|
||||
enum Flags {
|
||||
DISCOVER = 1,
|
||||
OFFER = 2,
|
||||
REQUEST = 3,
|
||||
DECLINE = 4,
|
||||
ACK = 5,
|
||||
NAK = 6,
|
||||
RELEASE = 7,
|
||||
INFORM = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief DHCP options enum.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
PAD,
|
||||
SUBNET_MASK,
|
||||
TIME_OFFSET,
|
||||
ROUTERS,
|
||||
TIME_SERVERS,
|
||||
NAME_SERVERS,
|
||||
DOMAIN_NAME_SERVERS,
|
||||
LOG_SERVERS,
|
||||
COOKIE_SERVERS,
|
||||
LPR_SERVERS,
|
||||
IMPRESS_SERVERS,
|
||||
RESOURCE_LOCATION_SERVERS,
|
||||
HOST_NAME,
|
||||
BOOT_SIZE,
|
||||
MERIT_DUMP,
|
||||
DOMAIN_NAME,
|
||||
SWAP_SERVER,
|
||||
ROOT_PATH,
|
||||
EXTENSIONS_PATH,
|
||||
IP_FORWARDING,
|
||||
NON_LOCAL_SOURCE_ROUTING,
|
||||
POLICY_FILTER,
|
||||
MAX_DGRAM_REASSEMBLY,
|
||||
DEFAULT_IP_TTL,
|
||||
PATH_MTU_AGING_TIMEOUT,
|
||||
PATH_MTU_PLATEAU_TABLE,
|
||||
INTERFACE_MTU,
|
||||
ALL_SUBNETS_LOCAL,
|
||||
BROADCAST_ADDRESS,
|
||||
PERFORM_MASK_DISCOVERY,
|
||||
MASK_SUPPLIER,
|
||||
ROUTER_DISCOVERY,
|
||||
ROUTER_SOLICITATION_ADDRESS,
|
||||
STATIC_ROUTES,
|
||||
TRAILER_ENCAPSULATION,
|
||||
ARP_CACHE_TIMEOUT,
|
||||
IEEE802_3_ENCAPSULATION,
|
||||
DEFAULT_TCP_TTL,
|
||||
TCP_KEEPALIVE_INTERVAL,
|
||||
TCP_KEEPALIVE_GARBAGE,
|
||||
NIS_DOMAIN,
|
||||
NIS_SERVERS,
|
||||
NTP_SERVERS,
|
||||
VENDOR_ENCAPSULATED_OPTIONS,
|
||||
NETBIOS_NAME_SERVERS,
|
||||
NETBIOS_DD_SERVER,
|
||||
NETBIOS_NODE_TYPE,
|
||||
NETBIOS_SCOPE,
|
||||
FONT_SERVERS,
|
||||
X_DISPLAY_MANAGER,
|
||||
DHCP_REQUESTED_ADDRESS,
|
||||
DHCP_LEASE_TIME,
|
||||
DHCP_OPTION_OVERLOAD,
|
||||
DHCP_MESSAGE_TYPE,
|
||||
DHCP_SERVER_IDENTIFIER,
|
||||
DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHCP_MESSAGE,
|
||||
DHCP_MAX_MESSAGE_SIZE,
|
||||
DHCP_RENEWAL_TIME,
|
||||
DHCP_REBINDING_TIME,
|
||||
VENDOR_CLASS_IDENTIFIER,
|
||||
DHCP_CLIENT_IDENTIFIER,
|
||||
NWIP_DOMAIN_NAME,
|
||||
NWIP_SUBOPTIONS,
|
||||
USER_CLASS = 77,
|
||||
FQDN = 81,
|
||||
DHCP_AGENT_OPTIONS = 82,
|
||||
SUBNET_SELECTION = 118,
|
||||
AUTHENTICATE = 210,
|
||||
END = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* The DHCP option type.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, DHCP> option;
|
||||
|
||||
/**
|
||||
* The type used to store the DHCP options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of DHCP.
|
||||
*
|
||||
* This sets the hwtype and hlen fields to match the ethernet
|
||||
* type and length.
|
||||
*/
|
||||
DHCP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DHCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a BootP header, or any of
|
||||
* the TLV options contains an invalid size field, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DHCP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief DHCP options enum.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
PAD,
|
||||
SUBNET_MASK,
|
||||
TIME_OFFSET,
|
||||
ROUTERS,
|
||||
TIME_SERVERS,
|
||||
NAME_SERVERS,
|
||||
DOMAIN_NAME_SERVERS,
|
||||
LOG_SERVERS,
|
||||
COOKIE_SERVERS,
|
||||
LPR_SERVERS,
|
||||
IMPRESS_SERVERS,
|
||||
RESOURCE_LOCATION_SERVERS,
|
||||
HOST_NAME,
|
||||
BOOT_SIZE,
|
||||
MERIT_DUMP,
|
||||
DOMAIN_NAME,
|
||||
SWAP_SERVER,
|
||||
ROOT_PATH,
|
||||
EXTENSIONS_PATH,
|
||||
IP_FORWARDING,
|
||||
NON_LOCAL_SOURCE_ROUTING,
|
||||
POLICY_FILTER,
|
||||
MAX_DGRAM_REASSEMBLY,
|
||||
DEFAULT_IP_TTL,
|
||||
PATH_MTU_AGING_TIMEOUT,
|
||||
PATH_MTU_PLATEAU_TABLE,
|
||||
INTERFACE_MTU,
|
||||
ALL_SUBNETS_LOCAL,
|
||||
BROADCAST_ADDRESS,
|
||||
PERFORM_MASK_DISCOVERY,
|
||||
MASK_SUPPLIER,
|
||||
ROUTER_DISCOVERY,
|
||||
ROUTER_SOLICITATION_ADDRESS,
|
||||
STATIC_ROUTES,
|
||||
TRAILER_ENCAPSULATION,
|
||||
ARP_CACHE_TIMEOUT,
|
||||
IEEE802_3_ENCAPSULATION,
|
||||
DEFAULT_TCP_TTL,
|
||||
TCP_KEEPALIVE_INTERVAL,
|
||||
TCP_KEEPALIVE_GARBAGE,
|
||||
NIS_DOMAIN,
|
||||
NIS_SERVERS,
|
||||
NTP_SERVERS,
|
||||
VENDOR_ENCAPSULATED_OPTIONS,
|
||||
NETBIOS_NAME_SERVERS,
|
||||
NETBIOS_DD_SERVER,
|
||||
NETBIOS_NODE_TYPE,
|
||||
NETBIOS_SCOPE,
|
||||
FONT_SERVERS,
|
||||
X_DISPLAY_MANAGER,
|
||||
DHCP_REQUESTED_ADDRESS,
|
||||
DHCP_LEASE_TIME,
|
||||
DHCP_OPTION_OVERLOAD,
|
||||
DHCP_MESSAGE_TYPE,
|
||||
DHCP_SERVER_IDENTIFIER,
|
||||
DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHCP_MESSAGE,
|
||||
DHCP_MAX_MESSAGE_SIZE,
|
||||
DHCP_RENEWAL_TIME,
|
||||
DHCP_REBINDING_TIME,
|
||||
VENDOR_CLASS_IDENTIFIER,
|
||||
DHCP_CLIENT_IDENTIFIER,
|
||||
NWIP_DOMAIN_NAME,
|
||||
NWIP_SUBOPTIONS,
|
||||
USER_CLASS = 77,
|
||||
FQDN = 81,
|
||||
DHCP_AGENT_OPTIONS = 82,
|
||||
SUBNET_SELECTION = 118,
|
||||
AUTHENTICATE = 210,
|
||||
END = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* The DHCP option type.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, DHCP> option;
|
||||
|
||||
/**
|
||||
* The type used to store the DHCP options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of DHCP.
|
||||
*
|
||||
* This sets the hwtype and hlen fields to match the ethernet
|
||||
* type and length.
|
||||
*/
|
||||
DHCP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DHCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a BootP header, or any of
|
||||
* the TLV options contains an invalid size field, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DHCP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option& opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
*
|
||||
* The option is move-constructed.
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
*
|
||||
* The option is move-constructed.
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
options_.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Removes a DHCP option.
|
||||
*
|
||||
* If there are multiple options of the given type, only the first one
|
||||
* will be removed.
|
||||
*
|
||||
* \param type The type of the option to be removed.
|
||||
* \return true if the option was removed, false otherwise.
|
||||
*/
|
||||
bool remove_option(OptionTypes type);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \param opt_flag The flag to be searched.
|
||||
* \return A pointer to the option, or 0 if it was not found.
|
||||
*/
|
||||
const option* search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \param opt_flag The flag to be searched.
|
||||
* \return A pointer to the option, or 0 if it was not found.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \brief Adds a type option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param type The type of this DHCP PDU.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Adds an end option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* The END option is not added automatically. You should explicitly
|
||||
* add it at the end of the DHCP options for the PDU to be
|
||||
* standard-compliant.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* \brief Adds a server identifier option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param ip The server's IP address.
|
||||
*/
|
||||
void server_identifier(ipaddress_type ip);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP address lease time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease time.
|
||||
*/
|
||||
void lease_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a lease renewal time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease renew time.
|
||||
*/
|
||||
void renewal_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a rebind time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease rebind time.
|
||||
*/
|
||||
void rebind_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a subnet mask option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param mask The subnet mask.
|
||||
*/
|
||||
void subnet_mask(ipaddress_type mask);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param routers A list of ip addresses.
|
||||
*/
|
||||
void routers(const std::vector<ipaddress_type> &routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param dns A list of ip addresses.
|
||||
*/
|
||||
void domain_name_servers(const std::vector<ipaddress_type> &dns);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The broadcast address.
|
||||
*/
|
||||
void broadcast(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a requested address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The requested address.
|
||||
*/
|
||||
void requested_ip(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The domain name.
|
||||
*/
|
||||
void domain_name(const std::string &name);
|
||||
/**
|
||||
* \brief Adds a type option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param type The type of this DHCP PDU.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Adds an end option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* The END option is not added automatically. You should explicitly
|
||||
* add it at the end of the DHCP options for the PDU to be
|
||||
* standard-compliant.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* \brief Adds a server identifier option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param ip The server's IP address.
|
||||
*/
|
||||
void server_identifier(ipaddress_type ip);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP address lease time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease time.
|
||||
*/
|
||||
void lease_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a lease renewal time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease renew time.
|
||||
*/
|
||||
void renewal_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a rebind time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease rebind time.
|
||||
*/
|
||||
void rebind_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a subnet mask option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param mask The subnet mask.
|
||||
*/
|
||||
void subnet_mask(ipaddress_type mask);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param routers A list of ip addresses.
|
||||
*/
|
||||
void routers(const std::vector<ipaddress_type>& routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param dns A list of ip addresses.
|
||||
*/
|
||||
void domain_name_servers(const std::vector<ipaddress_type>& dns);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The broadcast address.
|
||||
*/
|
||||
void broadcast(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a requested address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The requested address.
|
||||
*/
|
||||
void requested_ip(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The domain name.
|
||||
*/
|
||||
void domain_name(const std::string& name);
|
||||
|
||||
/**
|
||||
* \brief Adds a hostname option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The hostname.
|
||||
*/
|
||||
void hostname(const std::string &name);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Searchs for a type option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint8_t containing the type option.
|
||||
*/
|
||||
uint8_t type() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a server identifier option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the server identifier.
|
||||
*/
|
||||
ipaddress_type server_identifier() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the lease time.
|
||||
*/
|
||||
uint32_t lease_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease renewal time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the renewal time.
|
||||
*/
|
||||
uint32_t renewal_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a rebind time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the rebind time.
|
||||
*/
|
||||
uint32_t rebind_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a subnet mask option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the subnet mask.
|
||||
*/
|
||||
ipaddress_type subnet_mask() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a routers option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::vector<ipaddress_type> Containing the routers
|
||||
* option data.
|
||||
*/
|
||||
std::vector<ipaddress_type> routers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a dns option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::list<ipaddress_type> Contanining the DNS servers
|
||||
* provided.
|
||||
*/
|
||||
std::vector<ipaddress_type> domain_name_servers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a broadcast option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the broadcast address.
|
||||
*/
|
||||
ipaddress_type broadcast() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a requested option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the requested IP address.
|
||||
*/
|
||||
ipaddress_type requested_ip() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a domain name option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the domain name.
|
||||
*/
|
||||
std::string domain_name() const;
|
||||
/**
|
||||
* \brief Adds a hostname option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The hostname.
|
||||
*/
|
||||
void hostname(const std::string& name);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Searchs for a type option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint8_t containing the type option.
|
||||
*/
|
||||
uint8_t type() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a server identifier option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the server identifier.
|
||||
*/
|
||||
ipaddress_type server_identifier() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the lease time.
|
||||
*/
|
||||
uint32_t lease_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease renewal time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the renewal time.
|
||||
*/
|
||||
uint32_t renewal_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a rebind time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the rebind time.
|
||||
*/
|
||||
uint32_t rebind_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a subnet mask option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the subnet mask.
|
||||
*/
|
||||
ipaddress_type subnet_mask() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a routers option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::vector<ipaddress_type> Containing the routers
|
||||
* option data.
|
||||
*/
|
||||
std::vector<ipaddress_type> routers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a dns option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::list<ipaddress_type> Contanining the DNS servers
|
||||
* provided.
|
||||
*/
|
||||
std::vector<ipaddress_type> domain_name_servers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a broadcast option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the broadcast address.
|
||||
*/
|
||||
ipaddress_type broadcast() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a requested option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the requested IP address.
|
||||
*/
|
||||
ipaddress_type requested_ip() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a domain name option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the domain name.
|
||||
*/
|
||||
std::string domain_name() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a hostname option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the hostname.
|
||||
*/
|
||||
std::string hostname() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the options list.
|
||||
* \return The option list.
|
||||
*/
|
||||
const options_type options() const { return _options; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCP *clone() const {
|
||||
return new DHCP(*this);
|
||||
/**
|
||||
* \brief Searchs for a hostname option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the hostname.
|
||||
*/
|
||||
std::string hostname() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the options list.
|
||||
* \return The option list.
|
||||
*/
|
||||
const options_type options() const { return options_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCP* clone() const {
|
||||
return new DHCP(*this);
|
||||
}
|
||||
private:
|
||||
static const uint32_t MAX_DHCP_SIZE;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
template <typename T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option* option = search_option(opt);
|
||||
if (!option) {
|
||||
throw option_not_found();
|
||||
}
|
||||
private:
|
||||
static const uint32_t MAX_DHCP_SIZE;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
void internal_add_option(const option& opt);
|
||||
serialization_type serialize_list(const std::vector<ipaddress_type>& ip_list);
|
||||
options_type::const_iterator search_option_iterator(OptionTypes opt) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes opt);
|
||||
|
||||
options_type options_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option)
|
||||
throw option_not_found();
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
void internal_add_option(const option &opt);
|
||||
serialization_type serialize_list(const std::vector<ipaddress_type> &ip_list);
|
||||
|
||||
options_type _options;
|
||||
uint32_t _size;
|
||||
};
|
||||
}
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DHCP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,17 +33,24 @@
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "pdu_option.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
|
||||
class OutputMemoryStream;
|
||||
|
||||
} // Memory
|
||||
|
||||
/**
|
||||
* \class DHCPv6
|
||||
* \brief Represents a DHCPv6 PDU.
|
||||
*/
|
||||
class DHCPv6 : public PDU {
|
||||
class TINS_API DHCPv6 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* Represents a DHCPv6 option.
|
||||
@@ -182,7 +189,7 @@ public:
|
||||
const options_type& options = options_type())
|
||||
: id(id), t1(t1), t2(t2), options(options) {}
|
||||
|
||||
static ia_na_type from_option(const option &opt);
|
||||
static ia_na_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -199,7 +206,7 @@ public:
|
||||
const options_type& options = options_type())
|
||||
: id(id), options(options) {}
|
||||
|
||||
static ia_ta_type from_option(const option &opt);
|
||||
static ia_ta_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -218,7 +225,7 @@ public:
|
||||
: address(address), preferred_lifetime(preferred_lifetime),
|
||||
valid_lifetime(valid_lifetime), options(options) {}
|
||||
|
||||
static ia_address_type from_option(const option &opt);
|
||||
static ia_address_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -233,11 +240,11 @@ public:
|
||||
|
||||
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
|
||||
uint8_t rdm = 0, uint64_t replay_detection = 0,
|
||||
const auth_info_type &auth_info = auth_info_type())
|
||||
const auth_info_type& auth_info = auth_info_type())
|
||||
: protocol(protocol), algorithm(algorithm), rdm(rdm),
|
||||
replay_detection(replay_detection), auth_info(auth_info) {}
|
||||
|
||||
static authentication_type from_option(const option &opt);
|
||||
static authentication_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -247,10 +254,10 @@ public:
|
||||
uint16_t code;
|
||||
std::string message;
|
||||
|
||||
status_code_type(uint16_t code = 0, const std::string &message = "")
|
||||
status_code_type(uint16_t code = 0, const std::string& message = "")
|
||||
: code(code), message(message) { }
|
||||
|
||||
static status_code_type from_option(const option &opt);
|
||||
static status_code_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -263,10 +270,10 @@ public:
|
||||
data_type data;
|
||||
|
||||
vendor_info_type(uint32_t enterprise_number = 0,
|
||||
const data_type &data = data_type())
|
||||
const data_type& data = data_type())
|
||||
: enterprise_number(enterprise_number), data(data) { }
|
||||
|
||||
static vendor_info_type from_option(const option &opt);
|
||||
static vendor_info_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
|
||||
@@ -283,13 +290,10 @@ public:
|
||||
typedef std::vector<class_option_data_type> data_type;
|
||||
data_type data;
|
||||
|
||||
user_class_type(const data_type &data = data_type())
|
||||
: data(data)
|
||||
{
|
||||
user_class_type(const data_type& data = data_type())
|
||||
: data(data) { }
|
||||
|
||||
}
|
||||
|
||||
static user_class_type from_option(const option &opt);
|
||||
static user_class_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -302,11 +306,11 @@ public:
|
||||
class_data_type vendor_class_data;
|
||||
|
||||
vendor_class_type(uint32_t enterprise_number = 0,
|
||||
const class_data_type &vendor_class_data = class_data_type())
|
||||
const class_data_type& vendor_class_data = class_data_type())
|
||||
: enterprise_number(enterprise_number),
|
||||
vendor_class_data(vendor_class_data) { }
|
||||
|
||||
static vendor_class_type from_option(const option &opt);
|
||||
static vendor_class_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -322,12 +326,12 @@ public:
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
const lladdress_type& lladdress = lladdress_type())
|
||||
: hw_type(hw_type), time(time), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static duid_llt from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -341,12 +345,12 @@ public:
|
||||
identifier_type identifier;
|
||||
|
||||
duid_en(uint32_t enterprise_number = 0,
|
||||
const identifier_type &identifier = identifier_type())
|
||||
const identifier_type& identifier = identifier_type())
|
||||
: enterprise_number(enterprise_number), identifier(identifier) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static duid_en from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -360,12 +364,12 @@ public:
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_ll(uint16_t hw_type = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
const lladdress_type& lladdress = lladdress_type())
|
||||
: hw_type(hw_type), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static duid_ll from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -378,19 +382,19 @@ public:
|
||||
uint16_t id;
|
||||
data_type data;
|
||||
|
||||
duid_type(uint16_t id = 0, const data_type &data = data_type())
|
||||
duid_type(uint16_t id = 0, const data_type& data = data_type())
|
||||
: id(id), data(data) {}
|
||||
|
||||
duid_type(const duid_llt &identifier)
|
||||
duid_type(const duid_llt& identifier)
|
||||
: id(duid_llt::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_en &identifier)
|
||||
duid_type(const duid_en& identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_ll &identifier)
|
||||
duid_type(const duid_ll& identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
static duid_type from_option(const option &opt);
|
||||
static duid_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -423,7 +427,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
|
||||
DHCPv6(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -433,7 +437,7 @@ public:
|
||||
* \return The stored message type field.
|
||||
*/
|
||||
MessageType msg_type() const {
|
||||
return static_cast<MessageType>(header_data[0]);
|
||||
return static_cast<MessageType>(header_data_[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,7 +445,9 @@ public:
|
||||
*
|
||||
* \return The stored hop count field.
|
||||
*/
|
||||
uint8_t hop_count() const { return header_data[1]; }
|
||||
uint8_t hop_count() const {
|
||||
return header_data_[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the transaction id field.
|
||||
@@ -449,7 +455,7 @@ public:
|
||||
* \return The stored transaction id field.
|
||||
*/
|
||||
small_uint<24> transaction_id() const {
|
||||
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3];
|
||||
return (header_data_[1] << 16) | (header_data_[2] << 8) | header_data_[3];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,21 +463,27 @@ public:
|
||||
*
|
||||
* \return The stored peer address field.
|
||||
*/
|
||||
const ipaddress_type &peer_address() const { return peer_addr; }
|
||||
const ipaddress_type& peer_address() const {
|
||||
return peer_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the link address field.
|
||||
*
|
||||
* \return The stored link address field.
|
||||
*/
|
||||
const ipaddress_type &link_address() const { return link_addr; }
|
||||
const ipaddress_type& link_address() const {
|
||||
return link_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the DHCPv6 options.
|
||||
*
|
||||
* \return The stored options.
|
||||
*/
|
||||
const options_type &options() const { return options_; }
|
||||
const options_type& options() const {
|
||||
return options_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
/**
|
||||
@@ -500,14 +512,14 @@ public:
|
||||
*
|
||||
* \param count The new peer address.
|
||||
*/
|
||||
void peer_address(const ipaddress_type &addr);
|
||||
void peer_address(const ipaddress_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the link address field.
|
||||
*
|
||||
* \param count The new link address.
|
||||
*/
|
||||
void link_address(const ipaddress_type &addr);
|
||||
void link_address(const ipaddress_type& addr);
|
||||
|
||||
// Option getters
|
||||
|
||||
@@ -673,7 +685,7 @@ public:
|
||||
*
|
||||
* \param value The new IA_NA option data.
|
||||
*/
|
||||
void ia_na(const ia_na_type &value);
|
||||
void ia_na(const ia_na_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association for Temporary
|
||||
@@ -681,21 +693,21 @@ public:
|
||||
*
|
||||
* \param value The new IA_TA option data.
|
||||
*/
|
||||
void ia_ta(const ia_ta_type &value);
|
||||
void ia_ta(const ia_ta_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association Address option.
|
||||
*
|
||||
* \param value The new IA Address option data.
|
||||
*/
|
||||
void ia_address(const ia_address_type &value);
|
||||
void ia_address(const ia_address_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association Address option.
|
||||
*
|
||||
* \param value The new Option Request option data.
|
||||
*/
|
||||
void option_request(const option_request_type &value);
|
||||
void option_request(const option_request_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Preference option.
|
||||
@@ -716,28 +728,28 @@ public:
|
||||
*
|
||||
* \param value The new Relay Message option data.
|
||||
*/
|
||||
void relay_message(const relay_msg_type &value);
|
||||
void relay_message(const relay_msg_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authentication option.
|
||||
*
|
||||
* \param value The new Authentication option data.
|
||||
*/
|
||||
void authentication(const authentication_type &value);
|
||||
void authentication(const authentication_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Unicast option.
|
||||
*
|
||||
* \param value The new Server Unicast option data.
|
||||
*/
|
||||
void server_unicast(const ipaddress_type &value);
|
||||
void server_unicast(const ipaddress_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Status Code option.
|
||||
*
|
||||
* \param value The new Status Code option data.
|
||||
*/
|
||||
void status_code(const status_code_type &value);
|
||||
void status_code(const status_code_type& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Rapid Commit option.
|
||||
@@ -749,28 +761,28 @@ public:
|
||||
*
|
||||
* \param value The new User Class option data.
|
||||
*/
|
||||
void user_class(const user_class_type &value);
|
||||
void user_class(const user_class_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Vendor Class option.
|
||||
*
|
||||
* \param value The new Vendor Class option data.
|
||||
*/
|
||||
void vendor_class(const vendor_class_type &value);
|
||||
void vendor_class(const vendor_class_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Vendor-specific Information option.
|
||||
*
|
||||
* \param value The new Vendor-specific Information option data.
|
||||
*/
|
||||
void vendor_info(const vendor_info_type &value);
|
||||
void vendor_info(const vendor_info_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Interface ID option.
|
||||
*
|
||||
* \param value The new Interface ID option data.
|
||||
*/
|
||||
void interface_id(const interface_id_type &value);
|
||||
void interface_id(const interface_id_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Reconfigure Message option.
|
||||
@@ -789,14 +801,14 @@ public:
|
||||
*
|
||||
* \param value The new Client Identifier option data.
|
||||
*/
|
||||
void client_id(const duid_type &value);
|
||||
void client_id(const duid_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Identifier option.
|
||||
*
|
||||
* \param value The new Server Identifier option data.
|
||||
*/
|
||||
void server_id(const duid_type &value);
|
||||
void server_id(const duid_type& value);
|
||||
|
||||
// Other stuff
|
||||
|
||||
@@ -813,18 +825,29 @@ public:
|
||||
*
|
||||
* \param opt The option to be added
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
void add_option(const option& opt);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \brief Removes a DHCPv6 option.
|
||||
*
|
||||
* If there are multiple options of the given type, only the first one
|
||||
* will be removed.
|
||||
*
|
||||
* \param type The type of the option to be removed.
|
||||
* \return true if the option was removed, false otherwise.
|
||||
*/
|
||||
bool remove_option(OptionTypes type);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given type.
|
||||
*
|
||||
* If the option is not found, a null pointer is returned.
|
||||
* Deleting the returned pointer will result in <b>undefined
|
||||
* behaviour</b>.
|
||||
*
|
||||
* \param id The option identifier to be searched.
|
||||
* \param type The option identifier to be searched.
|
||||
*/
|
||||
const option *search_option(OptionTypes id) const;
|
||||
const option* search_option(OptionTypes type) const;
|
||||
|
||||
// PDU stuff
|
||||
|
||||
@@ -836,62 +859,70 @@ public:
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCPv6 *clone() const {
|
||||
DHCPv6* clone() const {
|
||||
return new DHCPv6(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
uint8_t* write_option(const option &option, uint8_t* buffer) const;
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
|
||||
void write_option(const option& option, Memory::OutputMemoryStream& stream) const;
|
||||
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes type);
|
||||
|
||||
template<template <typename> class Functor>
|
||||
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option || Functor<uint32_t>()(option->data_size(), size))
|
||||
template <template <typename> class Functor>
|
||||
const option* safe_search_option(OptionTypes opt, uint32_t size) const {
|
||||
const option* option = search_option(opt);
|
||||
if (!option || Functor<uint32_t>()(option->data_size(), size)) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return option;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option)
|
||||
const option* option = search_option(opt);
|
||||
if (!option) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
uint8_t header_data[4];
|
||||
uint32_t options_size;
|
||||
ipaddress_type link_addr, peer_addr;
|
||||
uint8_t header_data_[4];
|
||||
uint32_t options_size_;
|
||||
ipaddress_type link_addr_, peer_addr_;
|
||||
options_type options_;
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
|
||||
template<typename InputIterator>
|
||||
void class_option_data2option(InputIterator start, InputIterator end,
|
||||
std::vector<uint8_t>& buffer, size_t start_index = 0)
|
||||
{
|
||||
void class_option_data2option(InputIterator start,
|
||||
InputIterator end,
|
||||
std::vector<uint8_t>& buffer,
|
||||
size_t start_index = 0) {
|
||||
size_t index = start_index;
|
||||
uint16_t uint16_t_buffer;
|
||||
while(start != end) {
|
||||
while (start != end) {
|
||||
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(start->size());
|
||||
uint16_t_buffer = Endian::host_to_be(static_cast<uint16_t>(start->size()));
|
||||
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
|
||||
index += sizeof(uint16_t);
|
||||
std::copy(start->begin(), start->end(), buffer.begin() + index);
|
||||
@@ -902,28 +933,30 @@ void class_option_data2option(InputIterator start, InputIterator end,
|
||||
}
|
||||
|
||||
template<typename OutputType>
|
||||
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
|
||||
{
|
||||
OutputType option2class_option_data(const uint8_t* ptr, uint32_t total_sz) {
|
||||
typedef typename OutputType::value_type value_type;
|
||||
OutputType output;
|
||||
size_t index = 0;
|
||||
while(index + 2 < total_sz) {
|
||||
while (index + 2 < total_sz) {
|
||||
uint16_t size;
|
||||
std::memcpy(&size, ptr + index, sizeof(uint16_t));
|
||||
size = Endian::be_to_host(size);
|
||||
index += sizeof(uint16_t);
|
||||
if(index + size > total_sz)
|
||||
if (index + size > total_sz) {
|
||||
throw option_not_found();
|
||||
}
|
||||
output.push_back(
|
||||
value_type(ptr + index, ptr + index + size)
|
||||
);
|
||||
index += size;
|
||||
}
|
||||
if(index != total_sz)
|
||||
if (index != total_sz) {
|
||||
throw malformed_option();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // Internals
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DHCPV6_H
|
||||
|
||||
1572
include/tins/dns.h
1572
include/tins/dns.h
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,13 +33,14 @@
|
||||
#define TINS_DOT11_DOT11_ASSOC_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing a Disassociation frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11Disassoc : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11Disassoc : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -55,8 +56,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Disassoc(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Disassoc(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Disassoc object from a buffer and
|
||||
@@ -72,14 +73,16 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Disassoc(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the reason code field.
|
||||
*
|
||||
* \return The stored reason code.
|
||||
*/
|
||||
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
|
||||
uint16_t reason_code() const {
|
||||
return Endian::le_to_host(body_.reason_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the reason code field.
|
||||
@@ -100,10 +103,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -116,24 +121,24 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Disassoc *clone() const {
|
||||
Dot11Disassoc* clone() const {
|
||||
return new Dot11Disassoc(*this);
|
||||
}
|
||||
private:
|
||||
struct DisassocBody {
|
||||
struct dot11_disassoc_body {
|
||||
uint16_t reason_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
DisassocBody _body;
|
||||
dot11_disassoc_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Association Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11AssocRequest : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11AssocRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -149,8 +154,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11AssocRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11AssocRequest(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11AssocRequest object from a buffer
|
||||
@@ -166,7 +171,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11AssocRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -174,7 +179,9 @@ public:
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -182,14 +189,18 @@ public:
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the listen interval field.
|
||||
*
|
||||
* \return The stored listen interval field.
|
||||
*/
|
||||
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
|
||||
uint16_t listen_interval() const {
|
||||
return Endian::le_to_host(body_.listen_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the listen interval field.
|
||||
@@ -210,10 +221,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -226,25 +239,25 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11AssocRequest *clone() const {
|
||||
Dot11AssocRequest* clone() const {
|
||||
return new Dot11AssocRequest(*this);
|
||||
}
|
||||
private:
|
||||
struct AssocReqBody {
|
||||
struct dot11_assoc_request_body {
|
||||
capability_information capability;
|
||||
uint16_t listen_interval;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
AssocReqBody _body;
|
||||
dot11_assoc_request_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Association Response frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11AssocResponse : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11AssocResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -260,8 +273,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11AssocResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11AssocResponse(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates a Dot11AssocResponse object
|
||||
@@ -277,7 +290,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11AssocResponse(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information field.
|
||||
@@ -285,7 +298,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information field.
|
||||
@@ -293,21 +308,27 @@ public:
|
||||
* \return A reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
uint16_t status_code() const {
|
||||
return Endian::le_to_host(body_.status_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the AID field.
|
||||
*
|
||||
* \return The stored AID field.
|
||||
*/
|
||||
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
|
||||
uint16_t aid() const {
|
||||
return Endian::le_to_host(body_.aid);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code.
|
||||
@@ -335,10 +356,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -351,26 +374,26 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11AssocResponse *clone() const {
|
||||
Dot11AssocResponse* clone() const {
|
||||
return new Dot11AssocResponse(*this);
|
||||
}
|
||||
private:
|
||||
struct AssocRespBody {
|
||||
struct dot11_assoc_response_body {
|
||||
capability_information capability;
|
||||
uint16_t status_code;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
AssocRespBody _body;
|
||||
dot11_assoc_response_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ReAssocRequest : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ReAssocRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -386,8 +409,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ReAssocRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ReAssocRequest(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11AssocRequest object from a buffer
|
||||
@@ -403,7 +426,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ReAssocRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -411,7 +434,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -419,21 +444,27 @@ public:
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the listen interval field.
|
||||
*
|
||||
* \return The stored listen interval.
|
||||
*/
|
||||
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
|
||||
uint16_t listen_interval() const {
|
||||
return Endian::le_to_host(body_.listen_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the current ap field.
|
||||
*
|
||||
* \return The current ap.
|
||||
*/
|
||||
address_type current_ap() const { return _body.current_ap; }
|
||||
address_type current_ap() const {
|
||||
return body_.current_ap;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the listen interval field.
|
||||
@@ -447,7 +478,7 @@ public:
|
||||
*
|
||||
* \param new_current_ap The address of the current ap.
|
||||
*/
|
||||
void current_ap(const address_type &new_current_ap);
|
||||
void current_ap(const address_type& new_current_ap);
|
||||
|
||||
/**
|
||||
* \brief Returns the frame's header length.
|
||||
@@ -461,10 +492,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -477,26 +510,26 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11ReAssocRequest *clone() const {
|
||||
Dot11ReAssocRequest* clone() const {
|
||||
return new Dot11ReAssocRequest(*this);
|
||||
}
|
||||
private:
|
||||
struct ReAssocReqBody {
|
||||
struct dot11_reassoc_request_body {
|
||||
capability_information capability;
|
||||
uint16_t listen_interval;
|
||||
uint8_t current_ap[address_type::address_size];
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
ReAssocReqBody _body;
|
||||
dot11_reassoc_request_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 ReAssociation Response frame.
|
||||
*
|
||||
*/
|
||||
class Dot11ReAssocResponse : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ReAssocResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -512,8 +545,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ReAssocResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ReAssocResponse(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ReAssocResponse object from a buffer
|
||||
@@ -529,7 +562,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ReAssocResponse(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -537,7 +570,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -545,21 +580,27 @@ public:
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
uint16_t status_code() const {
|
||||
return Endian::le_to_host(body_.status_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the AID field.
|
||||
*
|
||||
* \return The stored AID field value.
|
||||
*/
|
||||
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
|
||||
uint16_t aid() const {
|
||||
return Endian::le_to_host(body_.aid);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code field.
|
||||
@@ -587,10 +628,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -603,20 +646,21 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11ReAssocResponse *clone() const {
|
||||
Dot11ReAssocResponse* clone() const {
|
||||
return new Dot11ReAssocResponse(*this);
|
||||
}
|
||||
private:
|
||||
struct ReAssocRespBody {
|
||||
struct dot11_reassoc_response_body {
|
||||
capability_information capability;
|
||||
uint16_t status_code;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
ReAssocRespBody _body;
|
||||
dot11_reassoc_response_body body_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_ASSOC_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,12 +33,13 @@
|
||||
#define TINS_DOT11_DOT11_AUTH_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief IEEE 802.11 Authentication Request frame.
|
||||
*/
|
||||
class Dot11Authentication : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11Authentication : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -54,8 +55,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Authentication(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Authentication(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Authentication object from a buffer
|
||||
@@ -71,28 +72,33 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Authentication(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Authentication(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authetication Algorithm Number field.
|
||||
*
|
||||
* \return The stored authentication algorithm number.
|
||||
*/
|
||||
uint16_t auth_algorithm() const {return Endian::le_to_host(_body.auth_algorithm); }
|
||||
uint16_t auth_algorithm() const {
|
||||
return Endian::le_to_host(body_.auth_algorithm); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authetication Sequence Number field.
|
||||
*
|
||||
* \return The stored authentication sequence number.
|
||||
*/
|
||||
uint16_t auth_seq_number() const {return Endian::le_to_host(_body.auth_seq_number); }
|
||||
uint16_t auth_seq_number() const {
|
||||
return Endian::le_to_host(body_.auth_seq_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
uint16_t status_code() const {
|
||||
return Endian::le_to_host(body_.status_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authetication Algorithm Number field.
|
||||
@@ -129,10 +135,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -145,27 +153,26 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Authentication *clone() const {
|
||||
Dot11Authentication* clone() const {
|
||||
return new Dot11Authentication(*this);
|
||||
}
|
||||
private:
|
||||
struct AuthBody {
|
||||
struct dot11_auth_body {
|
||||
uint16_t auth_algorithm;
|
||||
uint16_t auth_seq_number;
|
||||
uint16_t status_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
AuthBody _body;
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
dot11_auth_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 Deauthentication frame.
|
||||
*
|
||||
*/
|
||||
class Dot11Deauthentication : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11Deauthentication : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -181,8 +188,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Deauthentication(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Deauthentication(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Deauthentication object from a buffer
|
||||
@@ -198,14 +205,16 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Deauthentication(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the reason code field.
|
||||
*
|
||||
* \return The reason code to be set.
|
||||
*/
|
||||
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
|
||||
uint16_t reason_code() const {
|
||||
return Endian::le_to_host(body_.reason_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the reason code field.
|
||||
@@ -226,10 +235,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -242,19 +253,19 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Deauthentication *clone() const {
|
||||
Dot11Deauthentication* clone() const {
|
||||
return new Dot11Deauthentication(*this);
|
||||
}
|
||||
private:
|
||||
struct DeauthBody {
|
||||
struct dot11_deauth_body {
|
||||
uint16_t reason_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
DeauthBody _body;
|
||||
dot11_deauth_body body_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
|
||||
#endif // TINS_DOT11_DOT11_AUTH_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -42,12 +42,17 @@
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class InputMemoryStream;
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
class RSNInformation;
|
||||
|
||||
/**
|
||||
* \brief Class representing an 802.11 frame.
|
||||
*/
|
||||
class Dot11 : public PDU {
|
||||
class TINS_API Dot11 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type used to store hardware addresses.
|
||||
@@ -187,7 +192,7 @@ public:
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
*/
|
||||
Dot11(const address_type &dst_hw_addr = address_type());
|
||||
Dot11(const address_type& dst_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs 802.11 PDU from a buffer and adds all
|
||||
@@ -201,91 +206,115 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol version field.
|
||||
*
|
||||
* \return The stored protocol version field.
|
||||
*/
|
||||
small_uint<2> protocol() const { return _header.control.protocol; }
|
||||
small_uint<2> protocol() const {
|
||||
return header_.control.protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Type field.
|
||||
*
|
||||
* \return The stored Type field.
|
||||
*/
|
||||
small_uint<2> type() const { return _header.control.type; }
|
||||
small_uint<2> type() const {
|
||||
return header_.control.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Subtype field.
|
||||
*
|
||||
* \return The stored Subtype field.
|
||||
*/
|
||||
small_uint<4> subtype() const { return _header.control.subtype; }
|
||||
small_uint<4> subtype() const {
|
||||
return header_.control.subtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the To-DS field.
|
||||
*
|
||||
* \return The stored To-DS field.
|
||||
*/
|
||||
small_uint<1> to_ds() const { return _header.control.to_ds; }
|
||||
small_uint<1> to_ds() const {
|
||||
return header_.control.to_ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the From-DS field.
|
||||
*
|
||||
* \return The stored From-DS field.
|
||||
*/
|
||||
small_uint<1> from_ds() const { return _header.control.from_ds; }
|
||||
small_uint<1> from_ds() const {
|
||||
return header_.control.from_ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the More-Frag field.
|
||||
*
|
||||
* \return The stored More-Frag field.
|
||||
*/
|
||||
small_uint<1> more_frag() const { return _header.control.more_frag; }
|
||||
small_uint<1> more_frag() const {
|
||||
return header_.control.more_frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Retry field.
|
||||
*
|
||||
* \return The stored Retry field.
|
||||
*/
|
||||
small_uint<1> retry() const { return _header.control.retry; }
|
||||
small_uint<1> retry() const {
|
||||
return header_.control.retry;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Power-Management field.
|
||||
*
|
||||
* \return The stored Power-Management field.
|
||||
*/
|
||||
small_uint<1> power_mgmt() const { return _header.control.power_mgmt; }
|
||||
small_uint<1> power_mgmt() const {
|
||||
return header_.control.power_mgmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the WEP field.
|
||||
*
|
||||
* \return The stored WEP field.
|
||||
*/
|
||||
small_uint<1> wep() const { return _header.control.wep; }
|
||||
small_uint<1> wep() const {
|
||||
return header_.control.wep;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Order field.
|
||||
*
|
||||
* \return The stored Order field.
|
||||
*/
|
||||
small_uint<1> order() const { return _header.control.order; }
|
||||
small_uint<1> order() const {
|
||||
return header_.control.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Duration-ID field.
|
||||
*
|
||||
* \return The stored Duration-ID field.
|
||||
*/
|
||||
uint16_t duration_id() const { return Endian::le_to_host(_header.duration_id); }
|
||||
uint16_t duration_id() const {
|
||||
return Endian::le_to_host(header_.duration_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the first address.
|
||||
*
|
||||
* \return The stored first address.
|
||||
*/
|
||||
address_type addr1() const { return _header.addr1; }
|
||||
address_type addr1() const {
|
||||
return header_.addr1;
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
@@ -371,7 +400,7 @@ public:
|
||||
*
|
||||
* \param new_addr1 The new first address.
|
||||
*/
|
||||
void addr1(const address_type &new_addr1);
|
||||
void addr1(const address_type& new_addr1);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
@@ -382,18 +411,18 @@ public:
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#ifndef WIN32
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this Dot11 PDU.
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
void add_option(const option& opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
@@ -405,35 +434,48 @@ public:
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
options_.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Removes a Dot11 option.
|
||||
*
|
||||
* If there are multiple options of the given type, only the first one
|
||||
* will be removed.
|
||||
*
|
||||
* \param type The type of the option to be removed.
|
||||
* \return true if the option was removed, false otherwise.
|
||||
*/
|
||||
bool remove_option(OptionTypes type);
|
||||
|
||||
/**
|
||||
* \brief Looks up a tagged option in the option list.
|
||||
*
|
||||
* The returned pointer <b>must not</b> be free'd.
|
||||
*
|
||||
* \param opt The option identifier.
|
||||
* \param type The option identifier.
|
||||
* \return The option found, or 0 if no such option has been set.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
const option* search_option(OptionTypes type) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11 *clone() const {
|
||||
Dot11* clone() const {
|
||||
return new Dot11(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -446,7 +488,9 @@ public:
|
||||
*
|
||||
* \return The options list.
|
||||
*/
|
||||
const options_type &options() const { return _options; }
|
||||
const options_type& options() const {
|
||||
return options_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates an Dot11 PDU from a buffer.
|
||||
@@ -462,18 +506,18 @@ public:
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \return The allocated Dot11 PDU.
|
||||
*/
|
||||
static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static Dot11* from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
protected:
|
||||
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz);
|
||||
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val);
|
||||
virtual void write_ext_header(Memory::OutputMemoryStream& stream) { }
|
||||
virtual void write_fixed_parameters(Memory::OutputMemoryStream& stream) { }
|
||||
void parse_tagged_parameters(Memory::InputMemoryStream& stream);
|
||||
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t* val);
|
||||
protected:
|
||||
/**
|
||||
* Struct that represents the 802.11 header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ieee80211_header {
|
||||
struct dot11_header {
|
||||
TINS_BEGIN_PACK
|
||||
struct {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
@@ -507,16 +551,19 @@ protected:
|
||||
|
||||
} TINS_END_PACK;
|
||||
private:
|
||||
Dot11(const ieee80211_header *header_ptr);
|
||||
Dot11(const dot11_header* header_ptr);
|
||||
|
||||
void internal_add_option(const option &opt);
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void internal_add_option(const option& opt);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes type);
|
||||
|
||||
|
||||
ieee80211_header _header;
|
||||
uint32_t _options_size;
|
||||
options_type _options;
|
||||
dot11_header header_;
|
||||
uint32_t options_size_;
|
||||
options_type options_;
|
||||
};
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,134 +33,147 @@
|
||||
#define TINS_DOT11_DOT11_BEACON_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Represents an IEEE 802.11 Beacon.
|
||||
*
|
||||
*/
|
||||
class TINS_API Dot11Beacon : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief Class representing an 802.11 Beacon.
|
||||
*
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class Dot11Beacon : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Beacon.
|
||||
*
|
||||
* Constructs a 802.11 Beacon taking destination and source
|
||||
* hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Beacon(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Beacon.
|
||||
*
|
||||
* Constructs a 802.11 Beacon taking destination and source
|
||||
* hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Beacon(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Beacon object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Beacon(const uint8_t *buffer, uint32_t total_sz);
|
||||
/**
|
||||
* \brief Constructs a Dot11Beacon object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Beacon(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const {
|
||||
return Endian::le_to_host(body_.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const {
|
||||
return Endian::le_to_host(body_.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information structure.
|
||||
*
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability; }
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information structure.
|
||||
*
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability; }
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
*
|
||||
* \param new_timestamp The timestamp to be set.
|
||||
*/
|
||||
void timestamp(uint64_t new_timestamp);
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
*
|
||||
* \param new_timestamp The timestamp to be set.
|
||||
*/
|
||||
void timestamp(uint64_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the interval field.
|
||||
*
|
||||
* \param new_interval The interval to be set.
|
||||
*/
|
||||
void interval(uint16_t new_interval);
|
||||
/**
|
||||
* \brief Setter for the interval field.
|
||||
*
|
||||
* \param new_interval The interval to be set.
|
||||
*/
|
||||
void interval(uint16_t new_interval);
|
||||
|
||||
/**
|
||||
* \brief Returns the frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/**
|
||||
* \brief Returns the frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
/**
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Beacon *clone() const {
|
||||
return new Dot11Beacon(*this);
|
||||
}
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Beacon* clone() const {
|
||||
return new Dot11Beacon(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct BeaconBody {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct dot11_beacon_body {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
dot11_beacon_body body_;
|
||||
};
|
||||
|
||||
BeaconBody _body;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_BEACON_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,12 +34,13 @@
|
||||
#define TINS_DOT11_DOT11_CONTROL_H
|
||||
|
||||
#include "../dot11/dot11_base.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class that represents an 802.11 control frame.
|
||||
* \brief Represents an IEEE 802.11 control frame.
|
||||
*/
|
||||
class Dot11Control : public Dot11 {
|
||||
class TINS_API Dot11Control : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -54,7 +55,7 @@ public:
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
*/
|
||||
Dot11Control(const address_type &dst_addr = address_type());
|
||||
Dot11Control(const address_type& dst_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Control object from a buffer and
|
||||
@@ -70,21 +71,23 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Control(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Control(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_CONTROL; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,18 +95,20 @@ public:
|
||||
* \brief Class that represents an abstraction of the 802.11 control frames
|
||||
* that contain a target address.
|
||||
*/
|
||||
class Dot11ControlTA : public Dot11Control {
|
||||
class TINS_API Dot11ControlTA : public Dot11Control {
|
||||
public:
|
||||
/**
|
||||
* \brief Getter for the target address field.
|
||||
*/
|
||||
address_type target_addr() const { return _taddr; }
|
||||
address_type target_addr() const {
|
||||
return taddr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the target address field.
|
||||
* \param addr The new target address.
|
||||
*/
|
||||
void target_addr(const address_type &addr);
|
||||
void target_addr(const address_type& addr);
|
||||
protected:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 control frame TA PDU
|
||||
@@ -114,8 +119,8 @@ protected:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11ControlTA(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11ControlTA(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ControlTA object from a buffer and
|
||||
@@ -131,7 +136,7 @@ protected:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ControlTA(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Returns the 802.11 frame's header length.
|
||||
@@ -144,18 +149,20 @@ protected:
|
||||
/**
|
||||
* \brief Getter for the control ta additional fields size.
|
||||
*/
|
||||
uint32_t controlta_size() const { return _taddr.size() + sizeof(ieee80211_header); }
|
||||
uint32_t controlta_size() const {
|
||||
return static_cast<uint32_t>(taddr_.size() + sizeof(dot11_header));
|
||||
}
|
||||
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
private:
|
||||
|
||||
address_type _taddr;
|
||||
address_type taddr_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 RTS frame.
|
||||
*/
|
||||
class Dot11RTS : public Dot11ControlTA {
|
||||
class TINS_API Dot11RTS : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -171,8 +178,8 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11RTS(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11RTS(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11RTS object from a buffer and adds all
|
||||
@@ -187,14 +194,14 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11RTS(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11RTS(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11RTS *clone() const {
|
||||
Dot11RTS* clone() const {
|
||||
return new Dot11RTS(*this);
|
||||
}
|
||||
|
||||
@@ -202,10 +209,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -214,7 +223,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11PSPoll : public Dot11ControlTA {
|
||||
class TINS_API Dot11PSPoll : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -230,8 +239,8 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11PSPoll(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11PSPoll(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11PSPoll object from a buffer and
|
||||
@@ -247,14 +256,14 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11PSPoll(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11PSPoll *clone() const {
|
||||
Dot11PSPoll* clone() const {
|
||||
return new Dot11PSPoll(*this);
|
||||
}
|
||||
|
||||
@@ -262,10 +271,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -274,7 +285,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11CFEnd : public Dot11ControlTA {
|
||||
class TINS_API Dot11CFEnd : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -290,8 +301,8 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11CFEnd(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11CFEnd(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11CFEnd object from a buffer and adds
|
||||
@@ -307,14 +318,14 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11CFEnd(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11CFEnd *clone() const {
|
||||
Dot11CFEnd* clone() const {
|
||||
return new Dot11CFEnd(*this);
|
||||
}
|
||||
|
||||
@@ -322,19 +333,21 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11EndCFAck : public Dot11ControlTA {
|
||||
class TINS_API Dot11EndCFAck : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -350,8 +363,8 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11EndCFAck(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11EndCFAck(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11EndCFAck frame object from a buffer
|
||||
@@ -367,14 +380,14 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11EndCFAck(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11EndCFAck *clone() const {
|
||||
Dot11EndCFAck* clone() const {
|
||||
return new Dot11EndCFAck(*this);
|
||||
}
|
||||
|
||||
@@ -382,19 +395,21 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11Ack : public Dot11Control {
|
||||
class TINS_API Dot11Ack : public Dot11Control {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -409,7 +424,7 @@ public:
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
*/
|
||||
Dot11Ack(const address_type &dst_addr = address_type());
|
||||
Dot11Ack(const address_type& dst_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Ack frame object from a buffer and
|
||||
@@ -425,14 +440,14 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Ack(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Ack(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Ack *clone() const {
|
||||
Dot11Ack* clone() const {
|
||||
return new Dot11Ack(*this);
|
||||
}
|
||||
|
||||
@@ -440,22 +455,24 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an 802.11 Block Ack Request PDU.
|
||||
*/
|
||||
class Dot11BlockAckRequest : public Dot11ControlTA {
|
||||
class TINS_API Dot11BlockAckRequest : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -471,8 +488,8 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11BlockAckRequest(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11BlockAckRequest(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11BlockAckRequest object from a buffer
|
||||
@@ -488,7 +505,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11BlockAckRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getter */
|
||||
|
||||
@@ -498,9 +515,9 @@ public:
|
||||
*/
|
||||
small_uint<4> bar_control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _bar_control & 0xf;
|
||||
return bar_control_ & 0xf;
|
||||
#else
|
||||
return (_bar_control >> 8) & 0xf;
|
||||
return (bar_control_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -510,9 +527,9 @@ public:
|
||||
*/
|
||||
small_uint<12> start_sequence() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_start_sequence >> 4) & 0xfff;
|
||||
return (start_sequence_ >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -522,9 +539,9 @@ public:
|
||||
*/
|
||||
small_uint<4> fragment_number() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _start_sequence & 0xf;
|
||||
return start_sequence_ & 0xf;
|
||||
#else
|
||||
return (_start_sequence >> 8) & 0xf;
|
||||
return (start_sequence_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -561,7 +578,7 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11BlockAckRequest *clone() const {
|
||||
Dot11BlockAckRequest* clone() const {
|
||||
return new Dot11BlockAckRequest(*this);
|
||||
}
|
||||
|
||||
@@ -569,29 +586,29 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
private:
|
||||
void init_block_ack();
|
||||
|
||||
uint16_t _bar_control;
|
||||
uint16_t _start_sequence;
|
||||
uint16_t bar_control_;
|
||||
uint16_t start_sequence_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an 802.11 block ack frame.
|
||||
*/
|
||||
class Dot11BlockAck : public Dot11ControlTA {
|
||||
class TINS_API Dot11BlockAck : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -612,8 +629,8 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11BlockAck(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11BlockAck(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11BlockAck frame object from a buffer
|
||||
@@ -629,7 +646,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11BlockAck(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
@@ -639,9 +656,9 @@ public:
|
||||
*/
|
||||
small_uint<4> bar_control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _bar_control & 0xf;
|
||||
return bar_control_ & 0xf;
|
||||
#else
|
||||
return (_bar_control >> 8) & 0xf;
|
||||
return (bar_control_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -651,9 +668,9 @@ public:
|
||||
*/
|
||||
small_uint<12> start_sequence() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_start_sequence >> 4) & 0xfff;
|
||||
return (start_sequence_ >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -663,9 +680,9 @@ public:
|
||||
*/
|
||||
small_uint<4> fragment_number() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _start_sequence & 0xf;
|
||||
return start_sequence_ & 0xf;
|
||||
#else
|
||||
return (_start_sequence >> 8) & 0xf;
|
||||
return (start_sequence_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -704,27 +721,31 @@ public:
|
||||
*
|
||||
* \return The bitmap field.
|
||||
*/
|
||||
const uint8_t *bitmap() const { return _bitmap; }
|
||||
const uint8_t* bitmap() const {
|
||||
return bitmap_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the bitmap field.
|
||||
* \param bit The new bitmap field to be set.
|
||||
*/
|
||||
void bitmap(const uint8_t *bit);
|
||||
void bitmap(const uint8_t* bit);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -732,15 +753,16 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11BlockAck *clone() const {
|
||||
Dot11BlockAck* clone() const {
|
||||
return new Dot11BlockAck(*this);
|
||||
}
|
||||
private:
|
||||
void init_block_ack();
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
|
||||
uint16_t _bar_control, _start_sequence;
|
||||
uint8_t _bitmap[bitmap_size];
|
||||
uint16_t bar_control_, start_sequence_;
|
||||
uint8_t bitmap_[bitmap_size];
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_CONTROL_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,9 +33,14 @@
|
||||
#define TINS_DOT11_DOT11_DATA_H
|
||||
|
||||
#include "../dot11/dot11_base.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
class Dot11Data : public Dot11 {
|
||||
|
||||
/**
|
||||
* \brief Represents an IEEE 802.11 data frame
|
||||
*/
|
||||
class TINS_API Dot11Data : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -51,8 +56,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Data(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Data(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Data object from a buffer and adds
|
||||
@@ -68,21 +73,25 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Data(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Data(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the second address.
|
||||
*
|
||||
* \return The stored second address.
|
||||
*/
|
||||
address_type addr2() const { return _ext_header.addr2; }
|
||||
address_type addr2() const {
|
||||
return ext_header_.addr2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the third address.
|
||||
*
|
||||
* \return The stored third address.
|
||||
*/
|
||||
address_type addr3() const { return _ext_header.addr3; }
|
||||
address_type addr3() const {
|
||||
return ext_header_.addr3;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
@@ -91,9 +100,9 @@ public:
|
||||
*/
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
return ext_header_.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
return (ext_header_.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -104,9 +113,9 @@ public:
|
||||
*/
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
return (ext_header_.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(ext_header_.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -115,21 +124,23 @@ public:
|
||||
*
|
||||
* \return The fourth address.
|
||||
*/
|
||||
address_type addr4() const { return _addr4; }
|
||||
address_type addr4() const {
|
||||
return addr4_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the second address.
|
||||
*
|
||||
* \param new_addr2 The second address to be set.
|
||||
*/
|
||||
void addr2(const address_type &new_addr2);
|
||||
void addr2(const address_type& new_addr2);
|
||||
|
||||
/**
|
||||
* \brief Setter for the third address.
|
||||
*
|
||||
* \param new_addr3 The third address to be set.
|
||||
*/
|
||||
void addr3(const address_type &new_addr3);
|
||||
void addr3(const address_type& new_addr3);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
@@ -150,7 +161,7 @@ public:
|
||||
*
|
||||
* \param new_addr4 The fourth address to be set.
|
||||
*/
|
||||
void addr4(const address_type &new_addr4);
|
||||
void addr4(const address_type& new_addr4);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the frame's source address.
|
||||
@@ -161,10 +172,12 @@ public:
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
if (!from_ds() && !to_ds()) {
|
||||
return addr2();
|
||||
if(!from_ds() && to_ds())
|
||||
}
|
||||
if (!from_ds() && to_ds()) {
|
||||
return addr2();
|
||||
}
|
||||
return addr3();
|
||||
}
|
||||
|
||||
@@ -177,10 +190,12 @@ public:
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
if (!from_ds() && !to_ds()) {
|
||||
return addr1();
|
||||
if(!from_ds() && to_ds())
|
||||
}
|
||||
if (!from_ds() && to_ds()) {
|
||||
return addr3();
|
||||
}
|
||||
return addr1();
|
||||
}
|
||||
|
||||
@@ -193,10 +208,12 @@ public:
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type bssid_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
if (!from_ds() && !to_ds()) {
|
||||
return addr3();
|
||||
if(!from_ds() && to_ds())
|
||||
}
|
||||
if (!from_ds() && to_ds()) {
|
||||
return addr1();
|
||||
}
|
||||
return addr2();
|
||||
}
|
||||
|
||||
@@ -212,10 +229,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -228,33 +247,28 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Data *clone() const {
|
||||
Dot11Data* clone() const {
|
||||
return new Dot11Data(*this);
|
||||
}
|
||||
protected:
|
||||
TINS_BEGIN_PACK
|
||||
struct ExtendedHeader {
|
||||
struct dot11_extended_header {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
uint16_t frag_seq;
|
||||
} TINS_END_PACK;
|
||||
|
||||
struct no_inner_pdu { };
|
||||
Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu);
|
||||
Dot11Data(const uint8_t* buffer, uint32_t total_sz, no_inner_pdu);
|
||||
|
||||
uint32_t init(const uint8_t *buffer, uint32_t total_sz);
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
uint32_t data_frame_size() {
|
||||
return Dot11::header_size() + sizeof(_ext_header) +
|
||||
((from_ds() && to_ds()) ? _addr4.size() : 0);
|
||||
}
|
||||
uint32_t init(const uint8_t* buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
private:
|
||||
ExtendedHeader _ext_header;
|
||||
address_type _addr4;
|
||||
dot11_extended_header ext_header_;
|
||||
address_type addr4_;
|
||||
};
|
||||
|
||||
class Dot11QoSData : public Dot11Data {
|
||||
class TINS_API Dot11QoSData : public Dot11Data {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -270,8 +284,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11QoSData(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11QoSData(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructors Dot11QoSData object from a buffer and adds
|
||||
@@ -287,14 +301,16 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11QoSData(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11QoSData(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the QOS Control field.
|
||||
*
|
||||
* \return The stored QOS Control field value.
|
||||
*/
|
||||
uint16_t qos_control() const { return Endian::le_to_host(_qos_control); }
|
||||
uint16_t qos_control() const {
|
||||
return Endian::le_to_host(qos_control_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the QOS Control field.
|
||||
@@ -316,7 +332,7 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11QoSData *clone() const {
|
||||
Dot11QoSData* clone() const {
|
||||
return new Dot11QoSData(*this);
|
||||
}
|
||||
|
||||
@@ -324,21 +340,22 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_QOS_DATA; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Data::matches_flag(flag);
|
||||
}
|
||||
private:
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
|
||||
uint16_t _qos_control;
|
||||
uint16_t qos_control_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,12 +36,13 @@
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include "../dot11/dot11_base.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Abstract class that englobes all Management frames in the 802.11 protocol.
|
||||
* \brief Base class for all management frames in the IEEE 802.11 protocol.
|
||||
*/
|
||||
class Dot11ManagementFrame : public Dot11 {
|
||||
class TINS_API Dot11ManagementFrame : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* The supported rates container type.
|
||||
@@ -53,6 +54,11 @@ public:
|
||||
*/
|
||||
typedef std::vector<std::pair<uint8_t, uint8_t> > channels_type;
|
||||
|
||||
/**
|
||||
* The channel map container type.
|
||||
*/
|
||||
typedef std::vector<std::pair<uint8_t, uint8_t> > channel_map_type;
|
||||
|
||||
/**
|
||||
* The requested information container type.
|
||||
*/
|
||||
@@ -63,6 +69,12 @@ public:
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_MANAGEMENT;
|
||||
|
||||
/**
|
||||
* \brief Enum used in the reason code field.
|
||||
*
|
||||
* This enumeration can be used to get or set the reason code field in a
|
||||
* Deauthentication or Disassociation
|
||||
*/
|
||||
enum ReasonCodes {
|
||||
UNSPECIFIED = 1,
|
||||
PREV_AUTH_NOT_VALID = 2,
|
||||
@@ -97,6 +109,21 @@ public:
|
||||
REQUESTED_BY_STA_TIMEOUT = 39,
|
||||
PEER_STA_NOT_SUPPORT_CIPHER = 45
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum that represents the map field within a channels map field.
|
||||
*
|
||||
* These bitmasks can be used to get or set the second value of
|
||||
* ibss_dfs_params().channel_map
|
||||
*/
|
||||
enum MapMask {
|
||||
BSS = 0x1,
|
||||
OFDM_PREAMBLE = 0x2,
|
||||
UNIDENTIFIED_SIGNAL = 0x4,
|
||||
RADAR = 0x8,
|
||||
UNMEASURED = 0x10,
|
||||
RESERVED = 0xE0
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the IEEE 802.11 frames' capability information.
|
||||
@@ -105,39 +132,39 @@ public:
|
||||
class capability_information {
|
||||
private:
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t _ess:1,
|
||||
_ibss:1,
|
||||
_cf_poll:1,
|
||||
_cf_poll_req:1,
|
||||
_privacy:1,
|
||||
_short_preamble:1,
|
||||
_pbcc:1,
|
||||
_channel_agility:1,
|
||||
_spectrum_mgmt:1,
|
||||
_qos:1,
|
||||
_sst:1,
|
||||
_apsd:1,
|
||||
_reserved:1,
|
||||
_dsss_ofdm:1,
|
||||
_delayed_block_ack:1,
|
||||
_immediate_block_ack:1;
|
||||
uint16_t ess_:1,
|
||||
ibss_:1,
|
||||
cf_poll_:1,
|
||||
cf_poll_req_:1,
|
||||
privacy_:1,
|
||||
short_preamble_:1,
|
||||
pbcc_:1,
|
||||
channel_agility_:1,
|
||||
spectrum_mgmt_:1,
|
||||
qos_:1,
|
||||
sst_:1,
|
||||
apsd_:1,
|
||||
radio_measurement_:1,
|
||||
dsss_ofdm_:1,
|
||||
delayed_block_ack_:1,
|
||||
immediate_block_ack_:1;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint16_t _channel_agility:1,
|
||||
_pbcc:1,
|
||||
_short_preamble:1,
|
||||
_privacy:1,
|
||||
_cf_poll_req:1,
|
||||
_cf_poll:1,
|
||||
_ibss:1,
|
||||
_ess:1,
|
||||
_immediate_block_ack:1,
|
||||
_delayed_block_ack:1,
|
||||
_dsss_ofdm:1,
|
||||
_reserved:1,
|
||||
_apsd:1,
|
||||
_sst:1,
|
||||
_qos:1,
|
||||
_spectrum_mgmt:1;
|
||||
uint16_t channel_agility_:1,
|
||||
pbcc_:1,
|
||||
short_preamble_:1,
|
||||
privacy_:1,
|
||||
cf_poll_req_:1,
|
||||
cf_poll_:1,
|
||||
ibss_:1,
|
||||
ess_:1,
|
||||
immediate_block_ack_:1,
|
||||
delayed_block_ack_:1,
|
||||
dsss_ofdm_:1,
|
||||
radio_measurement_:1,
|
||||
apsd_:1,
|
||||
sst_:1,
|
||||
qos_:1,
|
||||
spectrum_mgmt_:1;
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
@@ -145,225 +172,288 @@ public:
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool ess() const { return _ess; }
|
||||
bool ess() const {
|
||||
return ess_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ibss flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool ibss() const { return _ibss; }
|
||||
bool ibss() const {
|
||||
return ibss_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the cf_poll flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool cf_poll() const { return _cf_poll; }
|
||||
bool cf_poll() const {
|
||||
return cf_poll_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the cf_poll_req flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool cf_poll_req() const { return _cf_poll_req; }
|
||||
bool cf_poll_req() const {
|
||||
return cf_poll_req_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the privacy flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool privacy() const { return _privacy; }
|
||||
bool privacy() const {
|
||||
return privacy_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the short_preamble flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool short_preamble() const { return _short_preamble; }
|
||||
bool short_preamble() const {
|
||||
return short_preamble_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pbcc flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool pbcc() const { return _pbcc; }
|
||||
bool pbcc() const {
|
||||
return pbcc_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel_agility flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool channel_agility() const { return _channel_agility; }
|
||||
bool channel_agility() const {
|
||||
return channel_agility_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the spectrum_mgmt flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool spectrum_mgmt() const { return _spectrum_mgmt; }
|
||||
bool spectrum_mgmt() const {
|
||||
return spectrum_mgmt_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the qos flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool qos() const { return _qos; }
|
||||
bool qos() const {
|
||||
return qos_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sst flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool sst() const { return _sst; }
|
||||
bool sst() const {
|
||||
return sst_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the apsd flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool apsd() const { return _apsd; }
|
||||
bool apsd() const {
|
||||
return apsd_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the reserved flag.
|
||||
* \brief Getter for the radio measurement flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool reserved() const { return _reserved; }
|
||||
bool radio_measurement() const {
|
||||
return radio_measurement_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the dsss_ofdm flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool dsss_ofdm() const { return _dsss_ofdm; }
|
||||
bool dsss_ofdm() const {
|
||||
return dsss_ofdm_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the delayed_block_ack flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool delayed_block_ack() const { return _delayed_block_ack; }
|
||||
bool delayed_block_ack() const {
|
||||
return delayed_block_ack_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the immediate_block_ack flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool immediate_block_ack() const { return _immediate_block_ack; }
|
||||
bool immediate_block_ack() const {
|
||||
return immediate_block_ack_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the ess flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void ess(bool new_value) { _ess = new_value; }
|
||||
void ess(bool new_value) {
|
||||
ess_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the ibss flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void ibss(bool new_value) { _ibss = new_value; }
|
||||
void ibss(bool new_value) {
|
||||
ibss_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the cf_poll flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void cf_poll(bool new_value) { _cf_poll = new_value; }
|
||||
void cf_poll(bool new_value) {
|
||||
cf_poll_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the cf_poll_req flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void cf_poll_req(bool new_value) { _cf_poll_req = new_value; }
|
||||
void cf_poll_req(bool new_value) {
|
||||
cf_poll_req_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the privacy flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void privacy(bool new_value) { _privacy = new_value; }
|
||||
void privacy(bool new_value) {
|
||||
privacy_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the short_preamble flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void short_preamble(bool new_value) { _short_preamble = new_value; }
|
||||
void short_preamble(bool new_value) {
|
||||
short_preamble_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the pbcc flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void pbcc(bool new_value) { _pbcc = new_value; }
|
||||
void pbcc(bool new_value) {
|
||||
pbcc_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the channel_agility flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void channel_agility(bool new_value) { _channel_agility = new_value; }
|
||||
void channel_agility(bool new_value) {
|
||||
channel_agility_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the spectrum_mgmt flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void spectrum_mgmt(bool new_value) { _spectrum_mgmt = new_value; }
|
||||
void spectrum_mgmt(bool new_value) {
|
||||
spectrum_mgmt_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the qos flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void qos(bool new_value) { _qos = new_value; }
|
||||
void qos(bool new_value) {
|
||||
qos_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sst flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void sst(bool new_value) { _sst = new_value; }
|
||||
void sst(bool new_value) {
|
||||
sst_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the apsd flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void apsd(bool new_value) { _apsd = new_value; }
|
||||
void apsd(bool new_value) {
|
||||
apsd_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the reserved flag.
|
||||
* \brief Setter for the radio measurement flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void reserved(bool new_value) { _reserved = new_value; }
|
||||
void radio_measurement(bool new_value) {
|
||||
radio_measurement_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the dsss_ofdm flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void dsss_ofdm(bool new_value) { _dsss_ofdm = new_value; }
|
||||
void dsss_ofdm(bool new_value) {
|
||||
dsss_ofdm_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the delayed_block_ack flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void delayed_block_ack(bool new_value) { _delayed_block_ack = new_value; }
|
||||
void delayed_block_ack(bool new_value) {
|
||||
delayed_block_ack_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the immediate_block_ack flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void immediate_block_ack(bool new_value) { _immediate_block_ack = new_value; }
|
||||
|
||||
void immediate_block_ack(bool new_value) {
|
||||
immediate_block_ack_ = new_value;
|
||||
}
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
@@ -375,12 +465,14 @@ public:
|
||||
|
||||
fh_params_set() {}
|
||||
|
||||
fh_params_set(uint16_t dwell_time, uint8_t hop_set,
|
||||
uint8_t hop_pattern, uint8_t hop_index)
|
||||
fh_params_set(uint16_t dwell_time,
|
||||
uint8_t hop_set,
|
||||
uint8_t hop_pattern,
|
||||
uint8_t hop_index)
|
||||
: dwell_time(dwell_time), hop_set(hop_set),
|
||||
hop_pattern(hop_pattern), hop_index(hop_index) {}
|
||||
|
||||
static fh_params_set from_option(const option &opt);
|
||||
static fh_params_set from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -392,13 +484,15 @@ public:
|
||||
|
||||
cf_params_set() {}
|
||||
|
||||
cf_params_set(uint8_t cfp_count, uint8_t cfp_period,
|
||||
uint16_t cfp_max_duration, uint16_t cfp_dur_remaining)
|
||||
cf_params_set(uint8_t cfp_count,
|
||||
uint8_t cfp_period,
|
||||
uint16_t cfp_max_duration,
|
||||
uint16_t cfp_dur_remaining)
|
||||
: cfp_count(cfp_count), cfp_period(cfp_period),
|
||||
cfp_max_duration(cfp_max_duration),
|
||||
cfp_dur_remaining(cfp_dur_remaining) {}
|
||||
|
||||
static cf_params_set from_option(const option &opt);
|
||||
static cf_params_set from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -409,16 +503,17 @@ public:
|
||||
|
||||
address_type dfs_owner;
|
||||
uint8_t recovery_interval;
|
||||
channels_type channel_map;
|
||||
channel_map_type channel_map;
|
||||
|
||||
ibss_dfs_params() {}
|
||||
|
||||
ibss_dfs_params(const address_type &addr,
|
||||
uint8_t recovery_interval, const channels_type &channels)
|
||||
ibss_dfs_params(const address_type& addr,
|
||||
uint8_t recovery_interval,
|
||||
const channel_map_type& channel_map)
|
||||
: dfs_owner(addr), recovery_interval(recovery_interval),
|
||||
channel_map(channels) {}
|
||||
channel_map(channel_map) {}
|
||||
|
||||
static ibss_dfs_params from_option(const option &opt);
|
||||
static ibss_dfs_params from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -433,12 +528,14 @@ public:
|
||||
|
||||
country_params() {}
|
||||
|
||||
country_params(const std::string &country, const byte_array &first,
|
||||
const byte_array &number, const byte_array &max)
|
||||
country_params(const std::string& country,
|
||||
const byte_array& first,
|
||||
const byte_array& number,
|
||||
const byte_array& max)
|
||||
: country(country), first_channel(first), number_channels(number),
|
||||
max_transmit_power(max) {}
|
||||
|
||||
static country_params from_option(const option &opt);
|
||||
static country_params from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -452,12 +549,15 @@ public:
|
||||
|
||||
fh_pattern_type() {}
|
||||
|
||||
fh_pattern_type(uint8_t flag, uint8_t sets, uint8_t modulus,
|
||||
uint8_t offset, const byte_array& table)
|
||||
fh_pattern_type(uint8_t flag,
|
||||
uint8_t sets,
|
||||
uint8_t modulus,
|
||||
uint8_t offset,
|
||||
const byte_array& table)
|
||||
: flag(flag), number_of_sets(sets), modulus(modulus),
|
||||
offset(offset), random_table(table) {}
|
||||
|
||||
static fh_pattern_type from_option(const option &opt);
|
||||
static fh_pattern_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -468,10 +568,12 @@ public:
|
||||
|
||||
channel_switch_type() {}
|
||||
|
||||
channel_switch_type(uint8_t mode, uint8_t channel, uint8_t count)
|
||||
channel_switch_type(uint8_t mode,
|
||||
uint8_t channel,
|
||||
uint8_t count)
|
||||
: switch_mode(mode), new_channel(channel), switch_count(count) { }
|
||||
|
||||
static channel_switch_type from_option(const option &opt);
|
||||
static channel_switch_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -483,12 +585,14 @@ public:
|
||||
|
||||
quiet_type() {}
|
||||
|
||||
quiet_type(uint8_t count, uint8_t period, uint16_t duration,
|
||||
uint16_t offset)
|
||||
quiet_type(uint8_t count,
|
||||
uint8_t period,
|
||||
uint16_t duration,
|
||||
uint16_t offset)
|
||||
: quiet_count(count), quiet_period(period),
|
||||
quiet_duration(duration), quiet_offset(offset) {}
|
||||
|
||||
static quiet_type from_option(const option &opt);
|
||||
static quiet_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -501,12 +605,11 @@ public:
|
||||
|
||||
bss_load_type() {}
|
||||
|
||||
bss_load_type(uint16_t count, uint8_t utilization,
|
||||
uint16_t capacity)
|
||||
bss_load_type(uint16_t count, uint8_t utilization, uint16_t capacity)
|
||||
: station_count(count), available_capacity(capacity),
|
||||
channel_utilization(utilization) {}
|
||||
|
||||
static bss_load_type from_option(const option &opt);
|
||||
static bss_load_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -518,12 +621,14 @@ public:
|
||||
|
||||
tim_type() {}
|
||||
|
||||
tim_type(uint8_t count, uint8_t period, uint8_t control,
|
||||
const byte_array &bitmap)
|
||||
tim_type(uint8_t count,
|
||||
uint8_t period,
|
||||
uint8_t control,
|
||||
const byte_array& bitmap)
|
||||
: dtim_count(count), dtim_period(period), bitmap_control(control),
|
||||
partial_virtual_bitmap(bitmap) {}
|
||||
|
||||
static tim_type from_option(const option &opt);
|
||||
static tim_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -535,11 +640,11 @@ public:
|
||||
oui_type oui;
|
||||
byte_array data;
|
||||
|
||||
vendor_specific_type(const oui_type &oui = oui_type(),
|
||||
const byte_array &data = byte_array())
|
||||
vendor_specific_type(const oui_type& oui = oui_type(),
|
||||
const byte_array& data = byte_array())
|
||||
: oui(oui), data(data) { }
|
||||
|
||||
static vendor_specific_type from_bytes(const uint8_t *buffer, uint32_t sz);
|
||||
static vendor_specific_type from_bytes(const uint8_t* buffer, uint32_t sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -552,14 +657,18 @@ public:
|
||||
*
|
||||
* \return address_type containing the second address.
|
||||
*/
|
||||
address_type addr2() const { return _ext_header.addr2; }
|
||||
address_type addr2() const {
|
||||
return ext_header_.addr2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the third address.
|
||||
*
|
||||
* \return address_type containing the third address.
|
||||
*/
|
||||
address_type addr3() const { return _ext_header.addr3; }
|
||||
address_type addr3() const {
|
||||
return ext_header_.addr3;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number.
|
||||
@@ -568,9 +677,9 @@ public:
|
||||
*/
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
return ext_header_.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
return (ext_header_.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -581,9 +690,9 @@ public:
|
||||
*/
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
return (ext_header_.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(ext_header_.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -592,21 +701,23 @@ public:
|
||||
*
|
||||
* \return The stored fourth address.
|
||||
*/
|
||||
const address_type &addr4() const { return _addr4; }
|
||||
const address_type& addr4() const {
|
||||
return addr4_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the second address.
|
||||
*
|
||||
* \param new_addr2 The new second address to be set.
|
||||
*/
|
||||
void addr2(const address_type &new_addr2);
|
||||
void addr2(const address_type& new_addr2);
|
||||
|
||||
/**
|
||||
* \brief Setter for the third address.
|
||||
*
|
||||
* \param new_addr3 The new third address to be set.
|
||||
*/
|
||||
void addr3(const address_type &new_addr3);
|
||||
void addr3(const address_type& new_addr3);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number.
|
||||
@@ -627,7 +738,7 @@ public:
|
||||
*
|
||||
* \param new_addr4 The new fourth address to be set.
|
||||
*/
|
||||
void addr4(const address_type &new_addr4);
|
||||
void addr4(const address_type& new_addr4);
|
||||
|
||||
// Option setter helpers
|
||||
|
||||
@@ -636,7 +747,7 @@ public:
|
||||
*
|
||||
* \param new_ssid The SSID to be set.
|
||||
*/
|
||||
void ssid(const std::string &new_ssid);
|
||||
void ssid(const std::string& new_ssid);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the RSN information option.
|
||||
@@ -650,14 +761,14 @@ public:
|
||||
*
|
||||
* \param new_rates The new rates to be set.
|
||||
*/
|
||||
void supported_rates(const rates_type &new_rates);
|
||||
void supported_rates(const rates_type& new_rates);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the extended supported rates option.
|
||||
*
|
||||
* \param new_rates The new rates to be set.
|
||||
*/
|
||||
void extended_supported_rates(const rates_type &new_rates);
|
||||
void extended_supported_rates(const rates_type& new_rates);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the QoS capabilities option.
|
||||
@@ -683,7 +794,7 @@ public:
|
||||
*
|
||||
* \param new_channels A list of channels to be set.
|
||||
*/
|
||||
void supported_channels(const channels_type &new_channels);
|
||||
void supported_channels(const channels_type& new_channels);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the EDCA Parameter Set.
|
||||
@@ -707,7 +818,7 @@ public:
|
||||
*
|
||||
* \param fh_params The new FH parameter set value.
|
||||
*/
|
||||
void fh_parameter_set(const fh_params_set &fh_params);
|
||||
void fh_parameter_set(const fh_params_set& fh_params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the DS parameter tagged option.
|
||||
@@ -721,7 +832,7 @@ public:
|
||||
*
|
||||
* \param params The new CF parameter set value.
|
||||
*/
|
||||
void cf_parameter_set(const cf_params_set ¶ms);
|
||||
void cf_parameter_set(const cf_params_set& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the IBSS parameter set tagged option.
|
||||
@@ -735,14 +846,14 @@ public:
|
||||
*
|
||||
* \param params The IBSS DFS data to be set.
|
||||
*/
|
||||
void ibss_dfs(const ibss_dfs_params ¶ms);
|
||||
void ibss_dfs(const ibss_dfs_params& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the country tagged option.
|
||||
*
|
||||
* \param params The data to be used for this country option.
|
||||
*/
|
||||
void country(const country_params ¶ms);
|
||||
void country(const country_params& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the FH parameters set tagged option.
|
||||
@@ -757,7 +868,7 @@ public:
|
||||
*
|
||||
* \param params The data to be used for this FH pattern table option.
|
||||
*/
|
||||
void fh_pattern_table(const fh_pattern_type ¶ms);
|
||||
void fh_pattern_table(const fh_pattern_type& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Power Constraint tagged option.
|
||||
@@ -771,14 +882,14 @@ public:
|
||||
*
|
||||
* \param data The value of the Channel Switch option.
|
||||
*/
|
||||
void channel_switch(const channel_switch_type &data);
|
||||
void channel_switch(const channel_switch_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Quiet tagged option.
|
||||
*
|
||||
* \param data The value of the quiet count field.
|
||||
*/
|
||||
void quiet(const quiet_type &data);
|
||||
void quiet(const quiet_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the TPC Report tagged option.
|
||||
@@ -800,28 +911,28 @@ public:
|
||||
*
|
||||
* \param data The value to set in this bss load option.
|
||||
*/
|
||||
void bss_load(const bss_load_type &data);
|
||||
void bss_load(const bss_load_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the TIM tagged option.
|
||||
*
|
||||
* \brief data The value to set in this tim option.
|
||||
*/
|
||||
void tim(const tim_type &data);
|
||||
void tim(const tim_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Challenge Text tagged option.
|
||||
*
|
||||
* \brief text The challenge text to be added.
|
||||
*/
|
||||
void challenge_text(const std::string &text);
|
||||
void challenge_text(const std::string& text);
|
||||
|
||||
/**
|
||||
* \brief Helper method to add a Vendor Specific tagged option.
|
||||
*
|
||||
* \brief text The option to be added.
|
||||
*/
|
||||
void vendor_specific(const vendor_specific_type &data);
|
||||
void vendor_specific(const vendor_specific_type& data);
|
||||
|
||||
// Option searching helpers
|
||||
|
||||
@@ -834,7 +945,7 @@ public:
|
||||
*
|
||||
* \return std::string containing the ssid.
|
||||
*/
|
||||
RSNInformation rsn_information();
|
||||
RSNInformation rsn_information() const;
|
||||
|
||||
/**
|
||||
* \brief Helper method to search for this PDU's SSID.
|
||||
@@ -1096,10 +1207,12 @@ public:
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -1108,15 +1221,15 @@ public:
|
||||
}
|
||||
protected:
|
||||
TINS_BEGIN_PACK
|
||||
struct ExtendedHeader {
|
||||
struct dot11_extended_header {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
uint16_t frag_seq;
|
||||
} TINS_END_PACK;
|
||||
|
||||
|
||||
Dot11ManagementFrame(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ManagementFrame(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ManagementFrame object from a buffer
|
||||
@@ -1132,29 +1245,30 @@ protected:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ManagementFrame(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
|
||||
uint32_t management_frame_size() {
|
||||
return sizeof(ieee80211_header) + sizeof(_ext_header) +
|
||||
((from_ds() && to_ds()) ? address_type::address_size : 0);
|
||||
return Dot11ManagementFrame::header_size();
|
||||
}
|
||||
private:
|
||||
static uint8_t *serialize_rates(const rates_type &rates);
|
||||
static rates_type deserialize_rates(const option *option);
|
||||
static std::vector<uint8_t> serialize_rates(const rates_type& rates);
|
||||
static rates_type deserialize_rates(const option* option);
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(OptionTypes opt_type) const {
|
||||
const option *opt = search_option(opt_type);
|
||||
if(!opt)
|
||||
const option* opt = search_option(opt_type);
|
||||
if (!opt) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return opt->to<T>();
|
||||
}
|
||||
|
||||
ExtendedHeader _ext_header;
|
||||
address_type _addr4;
|
||||
dot11_extended_header ext_header_;
|
||||
address_type addr4_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_MGMT_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,13 +34,14 @@
|
||||
#define TINS_DOT11_DOT11_PROBE_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include "../macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ProbeRequest : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ProbeRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -56,8 +57,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ProbeRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ProbeRequest(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ProbeRequest object from a buffer
|
||||
@@ -73,16 +74,18 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ProbeRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_PROBE_REQ; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -105,7 +108,7 @@ public:
|
||||
* \brief Class representing an Probe Response frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ProbeResponse : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ProbeResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -121,8 +124,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ProbeResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ProbeResponse(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ProbeResponse object from a buffer
|
||||
@@ -138,21 +141,25 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ProbeResponse(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
|
||||
uint64_t timestamp() const {
|
||||
return Endian::le_to_host(body_.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
|
||||
uint16_t interval() const {
|
||||
return Endian::le_to_host(body_.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -160,7 +167,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -168,7 +177,9 @@ public:
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
@@ -208,26 +219,26 @@ public:
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
|
||||
private:
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct ProbeResp {
|
||||
struct dot11_probe_response_header {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
|
||||
ProbeResp _body;
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
dot11_probe_response_header body_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_PROBE_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,15 +31,17 @@
|
||||
#define TINS_DOT1Q_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class Dot1Q
|
||||
* Represents an IEEE 802.1q PDU.
|
||||
*/
|
||||
class Dot1Q : public PDU {
|
||||
class TINS_API Dot1Q : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -64,7 +66,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot1Q(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot1Q(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -86,7 +88,7 @@ public:
|
||||
* \return The stored priority field value.
|
||||
*/
|
||||
small_uint<3> priority() const {
|
||||
return _header.priority;
|
||||
return header_.priority;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +96,7 @@ public:
|
||||
* \return The stored CFI field value.
|
||||
*/
|
||||
small_uint<1> cfi() const {
|
||||
return _header.cfi;
|
||||
return header_.cfi;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,9 +105,9 @@ public:
|
||||
*/
|
||||
small_uint<12> id() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _header.idL | (_header.idH << 8);
|
||||
return header_.idL | (header_.idH << 8);
|
||||
#else
|
||||
return _header.id;
|
||||
return header_.id;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -114,19 +116,21 @@ public:
|
||||
* \return The stored type field value.
|
||||
*/
|
||||
uint16_t payload_type() const {
|
||||
return Endian::be_to_host(_header.type);
|
||||
return Endian::be_to_host(header_.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot1Q *clone() const {
|
||||
Dot1Q* clone() const {
|
||||
return new Dot1Q(*this);
|
||||
}
|
||||
|
||||
@@ -135,7 +139,7 @@ public:
|
||||
* appended at the end of this packet.
|
||||
*/
|
||||
bool append_padding() const {
|
||||
return _append_padding;
|
||||
return append_padding_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
@@ -177,15 +181,15 @@ public:
|
||||
void append_padding(bool value);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct dot1q_hdr {
|
||||
@@ -203,10 +207,10 @@ private:
|
||||
#endif
|
||||
} TINS_END_PACK;
|
||||
|
||||
static uint16_t get_id(const dot1q_hdr *hdr);
|
||||
static uint16_t get_id(const dot1q_hdr* hdr);
|
||||
|
||||
dot1q_hdr _header;
|
||||
bool _append_padding;
|
||||
dot1q_hdr header_;
|
||||
bool append_padding_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,162 +33,169 @@
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "config.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class Dot3
|
||||
* \brief Class representing an IEEE 802.3 PDU.
|
||||
/**
|
||||
* \class Dot3
|
||||
* \brief Class representing an IEEE 802.3 PDU.
|
||||
*/
|
||||
class TINS_API Dot3 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The address type.
|
||||
*/
|
||||
class Dot3 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The address type.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
|
||||
|
||||
/**
|
||||
* \brief Represents the Dot3 broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
/**
|
||||
* \brief Represents the Dot3 broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating an Dot3 PDU
|
||||
*
|
||||
* Constructor that builds an Dot3 PDU taking the interface name,
|
||||
* destination's and source's MAC.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
* \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());
|
||||
/**
|
||||
* \brief Constructor for creating an Dot3 PDU
|
||||
*
|
||||
* Constructor that builds an Dot3 PDU taking the interface name,
|
||||
* destination's and source's MAC.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
* \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());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot3 object from a buffer and adds a
|
||||
* LLC object with the remaining data as the inner PDU.
|
||||
*
|
||||
* If there is not enough size for a Dot3 header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot3(const uint8_t *buffer, uint32_t total_sz);
|
||||
/**
|
||||
* \brief Constructs a Dot3 object from a buffer and adds a
|
||||
* LLC object with the remaining data as the inner PDU.
|
||||
*
|
||||
* If there is not enough size for a Dot3 header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot3(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination hardware address.
|
||||
*
|
||||
* \return The destination hardware address.
|
||||
*/
|
||||
address_type dst_addr() const { return _eth.dst_mac; }
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination hardware address.
|
||||
*
|
||||
* \return The destination hardware address.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
return header_.dst_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the source hardware address.
|
||||
*
|
||||
* \return The source hardware address.
|
||||
*/
|
||||
address_type src_addr() const { return _eth.src_mac; }
|
||||
/**
|
||||
* \brief Getter for the source hardware address.
|
||||
*
|
||||
* \return The source hardware address.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
return header_.src_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field value.
|
||||
*/
|
||||
uint16_t length() const { return Endian::be_to_host(_eth.length); };
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field value.
|
||||
*/
|
||||
uint16_t length() const {
|
||||
return Endian::be_to_host(header_.length);
|
||||
}
|
||||
|
||||
/* Setters */
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_mac The new destination hardware address.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_mac);
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param address The new destination hardware address.
|
||||
*/
|
||||
void dst_addr(const address_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_mac The new source hardware address.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_mac);
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param address The new source hardware address.
|
||||
*/
|
||||
void src_addr(const address_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
*
|
||||
* \param new_length uint16_t with the new value of the length field.
|
||||
*/
|
||||
void length(uint16_t new_length);
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
*
|
||||
* \param value The new value for the length field
|
||||
*/
|
||||
void length(uint16_t value);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the Dot3 frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
// Virtual methods
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
/**
|
||||
* \brief Returns the Dot3 frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#if !defined(_WIN32) || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // !_WIN32 || HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot3 *clone() const {
|
||||
return new Dot3(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethhdr {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t length;
|
||||
} TINS_END_PACK;
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot3* clone() const {
|
||||
return new Dot3(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct dot3_header {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t length;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
ethhdr _eth;
|
||||
};
|
||||
}
|
||||
dot3_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DOT3_H
|
||||
|
||||
1425
include/tins/eapol.h
1425
include/tins/eapol.h
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -41,7 +41,7 @@
|
||||
#include <sys/endian.h>
|
||||
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
|
||||
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
|
||||
#elif defined(WIN32)
|
||||
#elif defined(_WIN32)
|
||||
// Assume windows == little endian. fixme later
|
||||
#define TINS_IS_LITTLE_ENDIAN 1
|
||||
#define TINS_IS_BIG_ENDIAN 0
|
||||
@@ -51,187 +51,183 @@
|
||||
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace Tins {
|
||||
namespace Endian {
|
||||
|
||||
/**
|
||||
* \brief "Changes" a 8-bit integral value's endianess. This is an
|
||||
* identity function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint8_t do_change_endian(uint8_t data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 16-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint16_t do_change_endian(uint16_t data) {
|
||||
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 32-bit integral value's endianess.
|
||||
*
|
||||
* \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));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 64-bit integral value's endianess.
|
||||
*
|
||||
* \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)))));
|
||||
}
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
// Helpers to convert
|
||||
template<typename T>
|
||||
struct conversion_dispatch_helper {
|
||||
static T dispatch(T data) {
|
||||
return do_change_endian(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<size_t>
|
||||
struct conversion_dispatcher;
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint8_t)>
|
||||
: public conversion_dispatch_helper<uint8_t> { };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint16_t)>
|
||||
: public conversion_dispatch_helper<uint16_t> { };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint32_t)>
|
||||
: public conversion_dispatch_helper<uint32_t> { };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint64_t)>
|
||||
: public conversion_dispatch_helper<uint64_t> { };
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Changes an integral value's endianess.
|
||||
*
|
||||
* This dispatchs to the corresponding function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T change_endian(T data) {
|
||||
return conversion_dispatcher<sizeof(T)>::dispatch(data);
|
||||
}
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
/**
|
||||
* \brief "Changes" a 8-bit integral value's endianess. This is an
|
||||
* identity function.
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint8_t do_change_endian(uint8_t data) {
|
||||
return data;
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 16-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint16_t do_change_endian(uint16_t data) {
|
||||
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Changes a 32-bit integral value's endianess.
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \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));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 64-bit integral value's endianess.
|
||||
*
|
||||
* \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)))));
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
// Helpers to convert
|
||||
template<typename T>
|
||||
struct conversion_dispatch_helper {
|
||||
static T dispatch(T data) {
|
||||
return do_change_endian(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<size_t>
|
||||
struct conversion_dispatcher;
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint8_t)>
|
||||
: public conversion_dispatch_helper<uint8_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint16_t)>
|
||||
: public conversion_dispatch_helper<uint16_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint32_t)>
|
||||
: public conversion_dispatch_helper<uint32_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint64_t)>
|
||||
: public conversion_dispatch_helper<uint64_t>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Changes an integral value's endianess.
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* This dispatchs to the corresponding function.
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T change_endian(T data) {
|
||||
return conversion_dispatcher<sizeof(T)>::dispatch(data);
|
||||
inline T host_to_le(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Endian
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ENDIANNESS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,173 +33,178 @@
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "config.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class EthernetII
|
||||
* \brief Represents an Ethernet II PDU.
|
||||
*/
|
||||
class TINS_API EthernetII : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \class EthernetII
|
||||
* \brief Represents an Ethernet II PDU.
|
||||
* \brief The hardware address type.
|
||||
*/
|
||||
class EthernetII : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The hardware address type.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
|
||||
|
||||
/**
|
||||
* \brief Represents the ethernetII broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
/**
|
||||
* \brief Represents the ethernetII broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* \brief Constructs an ethernet II PDU.
|
||||
*
|
||||
* \param dst_hw_addr address_type containing the destination's MAC.
|
||||
* \param src_hw_addr address_type containing the source's MAC.
|
||||
*/
|
||||
EthernetII(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
/**
|
||||
* \brief Constructs an ethernet II PDU.
|
||||
*
|
||||
* \param dst_hw_addr address_type containing the destination's MAC.
|
||||
* \param src_hw_addr address_type containing the source's MAC.
|
||||
*/
|
||||
EthernetII(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a EthernetII object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a EthernetII header in the
|
||||
* buffer, a malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
EthernetII(const uint8_t *buffer, uint32_t total_sz);
|
||||
/**
|
||||
* \brief Constructs a EthernetII object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a EthernetII header in the
|
||||
* buffer, a malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
EthernetII(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination's hardware address.
|
||||
*
|
||||
* \return address_type containing the destination hardware
|
||||
* address.
|
||||
*/
|
||||
address_type dst_addr() const { return _eth.dst_mac; }
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination's hardware address.
|
||||
*
|
||||
* \return address_type containing the destination hardware
|
||||
* address.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
return header_.dst_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the source's hardware address.
|
||||
*
|
||||
* \return address_type containing the source hardware address.
|
||||
*/
|
||||
address_type src_addr() const { return _eth.src_mac; }
|
||||
/**
|
||||
* \brief Getter for the source's hardware address.
|
||||
*
|
||||
* \return address_type containing the source hardware address.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
return header_.src_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload_type
|
||||
* \return The payload type.
|
||||
*/
|
||||
uint16_t payload_type() const { return Endian::be_to_host(_eth.payload_type); };
|
||||
/**
|
||||
* \brief Getter for the payload_type
|
||||
* \return The payload type.
|
||||
*/
|
||||
uint16_t payload_type() const {
|
||||
return Endian::be_to_host(header_.payload_type);
|
||||
}
|
||||
|
||||
/* Setters */
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_addr the destination hardware address to be set.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_addr);
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_addr the destination hardware address to be set.
|
||||
*/
|
||||
void dst_addr(const address_type& new_dst_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_addr the source hardware address to be set.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_addr);
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_addr the source hardware address to be set.
|
||||
*/
|
||||
void src_addr(const address_type& new_src_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload type.
|
||||
*
|
||||
* \param new_payload_type the new value of the payload type field.
|
||||
*/
|
||||
void payload_type(uint16_t new_payload_type);
|
||||
/**
|
||||
* \brief Setter for the payload type.
|
||||
*
|
||||
* \param new_payload_type the new value of the payload type field.
|
||||
*/
|
||||
void payload_type(uint16_t new_payload_type);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the ethernet frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the ethernet II frame's padding.
|
||||
*
|
||||
* \return An uint32_t with the padding size.
|
||||
* \sa PDU::trailer_size()
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the ethernet frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the ethernet II frame's padding.
|
||||
*
|
||||
* \return An uint32_t with the padding size.
|
||||
* \sa PDU::trailer_size()
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
// Windows does not support sending L2 PDUs.
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::ETHERNET_II; }
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
EthernetII *clone() const {
|
||||
return new EthernetII(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethhdr {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t payload_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
EthernetII* clone() const {
|
||||
return new EthernetII(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethernet_header {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t payload_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
ethhdr _eth;
|
||||
};
|
||||
|
||||
}
|
||||
ethernet_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ETHERNET_II_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,14 +34,24 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Base class for all libtins exceptions.
|
||||
*/
|
||||
class exception_base : public std::runtime_error {
|
||||
public:
|
||||
exception_base()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
exception_base(const std::string& message)
|
||||
: std::runtime_error(message) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an option is not found.
|
||||
*/
|
||||
class option_not_found : public std::runtime_error {
|
||||
class option_not_found : public exception_base {
|
||||
public:
|
||||
option_not_found()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
// try to avoid allocations by doing this.
|
||||
const char* what() const throw() {
|
||||
return "Option not found";
|
||||
@@ -51,24 +61,28 @@ public:
|
||||
/**
|
||||
* \brief Exception thrown when a malformed packet is parsed.
|
||||
*/
|
||||
class malformed_packet : public std::runtime_error {
|
||||
class malformed_packet : public exception_base {
|
||||
public:
|
||||
malformed_packet()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Malformed packet";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when serializing a packet fails.
|
||||
*/
|
||||
class serialization_error : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Serialization error";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
|
||||
*/
|
||||
class pdu_not_found : public std::runtime_error {
|
||||
class pdu_not_found : public exception_base {
|
||||
public:
|
||||
pdu_not_found()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "PDU not found";
|
||||
}
|
||||
@@ -78,23 +92,29 @@ public:
|
||||
* \brief Exception thrown when PDU::send requires a valid interface,
|
||||
* but an invalid is used.
|
||||
*/
|
||||
class invalid_interface : public std::runtime_error {
|
||||
class invalid_interface : public exception_base {
|
||||
public:
|
||||
invalid_interface()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Invalid interface";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid string representation of an address
|
||||
* is provided
|
||||
*/
|
||||
class invalid_address : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Invalid address";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a field is not present in frame.
|
||||
*/
|
||||
class field_not_present : public std::runtime_error {
|
||||
class field_not_present : public exception_base {
|
||||
public:
|
||||
field_not_present()
|
||||
: std::runtime_error(std::string()) { }
|
||||
const char* what() const throw() {
|
||||
return "Field not present";
|
||||
}
|
||||
@@ -103,37 +123,37 @@ public:
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to open a socket.
|
||||
*/
|
||||
class socket_open_error : public std::runtime_error {
|
||||
class socket_open_error : public exception_base {
|
||||
public:
|
||||
socket_open_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
socket_open_error(const std::string& msg)
|
||||
: exception_base(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to close a socket.
|
||||
*/
|
||||
class socket_close_error : public std::runtime_error {
|
||||
class socket_close_error : exception_base {
|
||||
public:
|
||||
socket_close_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
socket_close_error(const std::string& msg)
|
||||
: exception_base(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to write on a socket.
|
||||
*/
|
||||
class socket_write_error : public std::runtime_error {
|
||||
class socket_write_error : public exception_base {
|
||||
public:
|
||||
socket_write_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
socket_write_error(const std::string& msg)
|
||||
: exception_base(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid socket type is provided
|
||||
* to PacketSender.
|
||||
*/
|
||||
class invalid_socket_type : public std::exception {
|
||||
class invalid_socket_type : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
const char* what() const throw() {
|
||||
return "The provided socket type is invalid";
|
||||
}
|
||||
};
|
||||
@@ -142,9 +162,9 @@ public:
|
||||
* \brief Exception thrown when an unkown link layer PDU type is
|
||||
* found while sniffing.
|
||||
*/
|
||||
class unknown_link_type : public std::exception {
|
||||
class unknown_link_type : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
const char* what() const throw() {
|
||||
return "The sniffed link layer PDU type is unknown";
|
||||
}
|
||||
};
|
||||
@@ -152,9 +172,9 @@ public:
|
||||
/**
|
||||
* \brief Exception thrown when a malformed option is found.
|
||||
*/
|
||||
class malformed_option : public std::exception {
|
||||
class malformed_option : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
const char* what() const throw() {
|
||||
return "Malformed option";
|
||||
}
|
||||
};
|
||||
@@ -162,9 +182,9 @@ public:
|
||||
/**
|
||||
* \brief Exception thrown when a call to tins_cast fails.
|
||||
*/
|
||||
class bad_tins_cast : public std::exception {
|
||||
class bad_tins_cast : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
const char* what() const throw() {
|
||||
return "Bad Tins cast";
|
||||
}
|
||||
};
|
||||
@@ -173,13 +193,100 @@ public:
|
||||
* \brief Exception thrown when sniffing a protocol that
|
||||
* has been disabled at compile time.
|
||||
*/
|
||||
class protocol_disabled : public std::exception {
|
||||
class protocol_disabled : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
const char* what() const throw() {
|
||||
return "Protocol disabled";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a payload is too large to fit
|
||||
* into a PDUOption.
|
||||
*/
|
||||
class option_payload_too_large : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Option payload too large";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generic pcap error
|
||||
*/
|
||||
class pcap_error : public exception_base {
|
||||
public:
|
||||
pcap_error(const char* message) : exception_base(message) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid pcap filter is compiled
|
||||
*/
|
||||
class invalid_pcap_filter : public exception_base {
|
||||
public:
|
||||
invalid_pcap_filter(const char* message) : exception_base(message) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when serialiation of a non-serializable PDU
|
||||
* is attempted
|
||||
*/
|
||||
class pdu_not_serializable : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "PDU not serializable";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when opening a pcap handle fails
|
||||
*/
|
||||
class pcap_open_failed : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Failed to create pcap handle";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a function not supported on the current OS
|
||||
* is called
|
||||
*/
|
||||
class unsupported_function : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Function is not supported on this OS";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid domain name is parsed
|
||||
*/
|
||||
class invalid_domain_name : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Invalid domain name";
|
||||
}
|
||||
};
|
||||
|
||||
namespace Crypto {
|
||||
namespace WPA2 {
|
||||
/**
|
||||
* \brief Exception thrown when an invalid WPA2 handshake is found.
|
||||
*/
|
||||
class invalid_handshake : public exception_base {
|
||||
public:
|
||||
const char* what() const throw() {
|
||||
return "Invalid WPA2 handshake";
|
||||
}
|
||||
};
|
||||
} // WPA2
|
||||
} // Crypto
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_EXCEPTIONS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -29,141 +29,142 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
|
||||
#define TINS_HANDSHAKE_CAPTURER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include "hw_address.h"
|
||||
#include "macros.h"
|
||||
#include "eapol.h"
|
||||
|
||||
// .h
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Generic EAPOL handshake.
|
||||
*
|
||||
* Stores both the client and supplicant addresses, as well as
|
||||
* all of the EAPOL packets used during the handshake.
|
||||
*/
|
||||
template<typename T>
|
||||
class EAPOLHandshake {
|
||||
public:
|
||||
typedef std::vector<T> container_type;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Generic EAPOL handshake.
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
EAPOLHandshake() { }
|
||||
|
||||
/**
|
||||
* Constructs an EAPOLHandshake object.
|
||||
*
|
||||
* \param client_address The client address.
|
||||
* \param supplicant_address The supplicant address.
|
||||
* \param cont The container that holds the EAPOL packets used
|
||||
* in the handshake.
|
||||
*/
|
||||
EAPOLHandshake(const address_type& client_address,
|
||||
const address_type& supplicant_address,
|
||||
const container_type& cont)
|
||||
: cl_address_(client_address), suppl_address_(supplicant_address),
|
||||
handshake_(cont) {
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type& client_address() const {
|
||||
return cl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type& supplicant_address() const {
|
||||
return suppl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const container_type&
|
||||
*/
|
||||
const container_type& handshake() const {
|
||||
return handshake_;
|
||||
}
|
||||
private:
|
||||
address_type cl_address_, suppl_address_;
|
||||
container_type handshake_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store RSN handshakes.
|
||||
*/
|
||||
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
|
||||
|
||||
/**
|
||||
* Captures 802.1X RSN handshakes.
|
||||
*/
|
||||
class TINS_API RSNHandshakeCapturer {
|
||||
public:
|
||||
/**
|
||||
* The type of handshakes that will be captured.
|
||||
*/
|
||||
typedef RSNHandshake handshake_type;
|
||||
|
||||
/**
|
||||
* The type in which all of the captured handshakes
|
||||
* will be stored.
|
||||
*/
|
||||
typedef std::vector<handshake_type> handshakes_type;
|
||||
|
||||
/**
|
||||
* \brief Processes a packet.
|
||||
*
|
||||
* This will fetch the RSNEAPOL layer, if any, and store
|
||||
* it in an intermediate storage. When a handshake is
|
||||
* completed, it will be stored separately.
|
||||
*
|
||||
* Stores both the client and supplicant addresses, as well as
|
||||
* all of the EAPOL packets used during the handshake.
|
||||
* \sa RSNHandshakeCapturer::handshakes
|
||||
*/
|
||||
template<typename T>
|
||||
class EAPOLHandshake {
|
||||
public:
|
||||
typedef std::vector<T> container_type;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
EAPOLHandshake() { }
|
||||
bool process_packet(const PDU& pdu);
|
||||
|
||||
/**
|
||||
* Constructs an EAPOLHandshake object.
|
||||
*
|
||||
* \param client_address The client address.
|
||||
* \param supplicant_address The supplicant address.
|
||||
* \param cont The container that holds the EAPOL packets used
|
||||
* in the handshake.
|
||||
*/
|
||||
EAPOLHandshake(const address_type &client_address,
|
||||
const address_type &supplicant_address, const container_type &cont)
|
||||
: cl_address_(client_address), suppl_address_(supplicant_address),
|
||||
handshake_(cont)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type &client_address() const {
|
||||
return cl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type &supplicant_address() const {
|
||||
return suppl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const container_type&
|
||||
*/
|
||||
const container_type &handshake() const {
|
||||
return handshake_;
|
||||
}
|
||||
private:
|
||||
address_type cl_address_, suppl_address_;
|
||||
container_type handshake_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store RSN handshakes.
|
||||
* \brief Retrieves the completed handshakes.
|
||||
*
|
||||
* This will return the handshakes that have been completed
|
||||
* so far. A handshake is completed when the 4-way handshake
|
||||
* is captured.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::clear_handshakes
|
||||
*/
|
||||
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
|
||||
|
||||
const handshakes_type& handshakes() const {
|
||||
return completed_handshakes_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures 802.1X RSN handshakes.
|
||||
* \brief Clears the completed handshakes.
|
||||
*
|
||||
* Since completed handshakes are stored in a std::vector,
|
||||
* it is advisable to remove all of them once they have been
|
||||
* processed.
|
||||
*/
|
||||
class RSNHandshakeCapturer {
|
||||
public:
|
||||
/**
|
||||
* The type of handshakes that will be captured.
|
||||
*/
|
||||
typedef RSNHandshake handshake_type;
|
||||
void clear_handshakes() {
|
||||
completed_handshakes_.clear();
|
||||
}
|
||||
private:
|
||||
typedef handshake_type::address_type address_type;
|
||||
typedef handshake_type::container_type eapol_list;
|
||||
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
|
||||
|
||||
/**
|
||||
* The type in which all of the captured handshakes
|
||||
* will be stored.
|
||||
*/
|
||||
typedef std::vector<handshake_type> handshakes_type;
|
||||
|
||||
/**
|
||||
* \brief Processes a packet.
|
||||
*
|
||||
* This will fetch the RSNEAPOL layer, if any, and store
|
||||
* it in an intermediate storage. When a handshake is
|
||||
* completed, it will be stored separately.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::handshakes
|
||||
*/
|
||||
bool process_packet(const PDU &pdu);
|
||||
bool do_insert(const handshake_map::key_type& key, const RSNEAPOL* eapol,
|
||||
size_t expected);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the completed handshakes.
|
||||
*
|
||||
* This will return the handshakes that have been completed
|
||||
* so far. A handshake is completed when the 4-way handshake
|
||||
* is captured.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::clear_handshakes
|
||||
*/
|
||||
const handshakes_type &handshakes() const {
|
||||
return completed_handshakes_;
|
||||
}
|
||||
handshake_map handshakes_;
|
||||
handshakes_type completed_handshakes_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Clears the completed handshakes.
|
||||
*
|
||||
* Since completed handshakes are stored in a std::vector,
|
||||
* it is advisable to remove all of them once they have been
|
||||
* processed.
|
||||
*/
|
||||
void clear_handshakes() {
|
||||
completed_handshakes_.clear();
|
||||
}
|
||||
private:
|
||||
typedef handshake_type::address_type address_type;
|
||||
typedef handshake_type::container_type eapol_list;
|
||||
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
|
||||
|
||||
bool do_insert(const handshake_map::key_type &key, const RSNEAPOL *eapol,
|
||||
size_t expected);
|
||||
|
||||
handshake_map handshakes_;
|
||||
handshakes_type completed_handshakes_;
|
||||
};
|
||||
}
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_HANDSHAKE_CAPTURER_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class HWAddress
|
||||
* \brief Represents a hardware address.
|
||||
@@ -107,10 +108,12 @@ public:
|
||||
* \param ptr The pointer from which to construct this address.
|
||||
*/
|
||||
HWAddress(const storage_type* ptr = 0) {
|
||||
if(ptr)
|
||||
std::copy(ptr, ptr + address_size, buffer);
|
||||
else
|
||||
if (ptr) {
|
||||
std::copy(ptr, ptr + address_size, buffer_);
|
||||
}
|
||||
else {
|
||||
std::fill(begin(), end(), storage_type());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,15 +127,15 @@ public:
|
||||
*
|
||||
* \param address The hex-notation address to be parsed.
|
||||
*/
|
||||
HWAddress(const std::string &address) {
|
||||
convert(address, buffer);
|
||||
HWAddress(const std::string& address) {
|
||||
convert(address, buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Overload provided basically for string literals.
|
||||
*
|
||||
* This constructor takes a const char array of i elements in
|
||||
* hex-notation. \sa HWAddress::HWAddress(const std::string &address)
|
||||
* hex-notation. \sa HWAddress::HWAddress(const std::string& address)
|
||||
*
|
||||
* This is mostly used when providing string literals. If this where
|
||||
* a const char*, then there would be an ambiguity when providing
|
||||
@@ -143,7 +146,7 @@ public:
|
||||
*/
|
||||
template<size_t i>
|
||||
HWAddress(const char (&address)[i]) {
|
||||
convert(address, buffer);
|
||||
convert(address, buffer_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +162,7 @@ public:
|
||||
* \param rhs The HWAddress to be constructed from.
|
||||
*/
|
||||
template<size_t i>
|
||||
HWAddress(const HWAddress<i> &rhs) {
|
||||
HWAddress(const HWAddress<i>& rhs) {
|
||||
// Fill extra bytes
|
||||
std::fill(
|
||||
// Copy as most as we can
|
||||
@@ -181,7 +184,7 @@ public:
|
||||
* \return iterator.
|
||||
*/
|
||||
iterator begin() {
|
||||
return buffer;
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +194,7 @@ public:
|
||||
* \return const_iterator.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
return buffer;
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +204,7 @@ public:
|
||||
* \return iterator.
|
||||
*/
|
||||
iterator end() {
|
||||
return buffer + address_size;
|
||||
return buffer_ + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +214,7 @@ public:
|
||||
* \return const_iterator.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
return buffer + address_size;
|
||||
return buffer_ + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +224,7 @@ public:
|
||||
*
|
||||
* \return bool indicating whether addresses are equal.
|
||||
*/
|
||||
bool operator==(const HWAddress &rhs) const {
|
||||
bool operator==(const HWAddress& rhs) const {
|
||||
return std::equal(begin(), end(), rhs.begin());
|
||||
}
|
||||
|
||||
@@ -232,7 +235,7 @@ public:
|
||||
*
|
||||
* \return bool indicating whether addresses are distinct.
|
||||
*/
|
||||
bool operator!=(const HWAddress &rhs) const {
|
||||
bool operator!=(const HWAddress& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
@@ -243,7 +246,7 @@ public:
|
||||
*
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator<(const HWAddress &rhs) const {
|
||||
bool operator<(const HWAddress& rhs) const {
|
||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
@@ -260,14 +263,14 @@ public:
|
||||
* \brief Indicates whether this is a broadcast address.
|
||||
*/
|
||||
bool is_broadcast() const {
|
||||
return *this == broadcast;
|
||||
return* this == broadcast;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this is a multicast address.
|
||||
*/
|
||||
bool is_multicast() const {
|
||||
return (buffer[0] & 0x01);
|
||||
return (*begin() & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,7 +287,7 @@ public:
|
||||
*/
|
||||
std::string to_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << *this;
|
||||
oss <<* this;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -294,7 +297,7 @@ public:
|
||||
* \param i The element to retrieve.
|
||||
*/
|
||||
storage_type operator[](size_t i) const {
|
||||
return buffer[i];
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,14 +307,14 @@ public:
|
||||
* \param addr The parameter to be written.
|
||||
* \return std::ostream& pointing to the os parameter.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &os, const HWAddress &addr) {
|
||||
friend std::ostream& operator<<(std::ostream& os, const HWAddress& addr) {
|
||||
std::transform(
|
||||
addr.begin(),
|
||||
addr.end() - 1,
|
||||
std::ostream_iterator<std::string>(os, ":"),
|
||||
&HWAddress::storage_to_string
|
||||
);
|
||||
return os << storage_to_string(addr.buffer[HWAddress::address_size-1]);
|
||||
return os << storage_to_string(addr.begin()[HWAddress::address_size - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,80 +328,104 @@ public:
|
||||
* But since some PDUs return a HWAddress<> by value, this function
|
||||
* can be used to avoid temporaries.
|
||||
*
|
||||
* \param iter The output iterator in which to store this address.
|
||||
* \param output The output iterator in which to store this address.
|
||||
* \return OutputIterator pointing to one-past the last position
|
||||
* written.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
OutputIterator copy(OutputIterator iter) const {
|
||||
return std::copy(begin(), end(), iter);
|
||||
OutputIterator copy(OutputIterator output) const {
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter) {
|
||||
*output++ = *iter;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
private:
|
||||
template<typename OutputIterator>
|
||||
static void convert(const std::string &hw_addr, OutputIterator output);
|
||||
static void convert(const std::string& hw_addr, OutputIterator output);
|
||||
|
||||
static HWAddress<n> make_broadcast_address() {
|
||||
// Build a buffer made of n 0xff bytes
|
||||
uint8_t buffer[n];
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
buffer[i] = 0xff;
|
||||
}
|
||||
return HWAddress<n>(buffer);
|
||||
}
|
||||
|
||||
static std::string storage_to_string(storage_type element) {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex;
|
||||
if(element < 0x10)
|
||||
if (element < 0x10) {
|
||||
oss << '0';
|
||||
}
|
||||
oss << (unsigned)element;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
storage_type buffer[n];
|
||||
storage_type buffer_[n];
|
||||
};
|
||||
|
||||
template<size_t n, typename Storage>
|
||||
template<typename OutputIterator>
|
||||
void HWAddress<n, Storage>::convert(const std::string &hw_addr,
|
||||
OutputIterator output)
|
||||
{
|
||||
void HWAddress<n, Storage>::convert(const std::string& hw_addr,
|
||||
OutputIterator output) {
|
||||
unsigned i(0);
|
||||
size_t count(0);
|
||||
storage_type tmp;
|
||||
while(i < hw_addr.size() && count < n) {
|
||||
while (i < hw_addr.size() && count < n) {
|
||||
const unsigned end = i+2;
|
||||
tmp = storage_type();
|
||||
while(i < end) {
|
||||
if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f')
|
||||
while (i < end) {
|
||||
if (hw_addr[i] >= 'a' && hw_addr[i] <= 'f') {
|
||||
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10);
|
||||
else if(hw_addr[i] >= 'A' && hw_addr[i] <= 'F')
|
||||
}
|
||||
else if (hw_addr[i] >= 'A' && hw_addr[i] <= 'F') {
|
||||
tmp = (tmp << 4) | (hw_addr[i] - 'A' + 10);
|
||||
else if(hw_addr[i] >= '0' && hw_addr[i] <= '9')
|
||||
}
|
||||
else if (hw_addr[i] >= '0' && hw_addr[i] <= '9') {
|
||||
tmp = (tmp << 4) | (hw_addr[i] - '0');
|
||||
else if(hw_addr[i] == ':')
|
||||
}
|
||||
else if (hw_addr[i] == ':') {
|
||||
break;
|
||||
else
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Invalid byte found");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
*(output++) = tmp;
|
||||
count++;
|
||||
if(i < hw_addr.size()) {
|
||||
if(hw_addr[i] == ':')
|
||||
if (i < hw_addr.size()) {
|
||||
if (hw_addr[i] == ':') {
|
||||
i++;
|
||||
else
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error("Invalid separator");
|
||||
}
|
||||
}
|
||||
}
|
||||
while(count++ < n) {
|
||||
while (count++ < n) {
|
||||
*(output++) = storage_type();
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t n, typename Storage>
|
||||
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast("ff:ff:ff:ff:ff:ff");
|
||||
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast = make_broadcast_address();
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
namespace std {
|
||||
|
||||
// Specialization of std::hash for HWAddress
|
||||
template<size_t n>
|
||||
struct hash<Tins::HWAddress<n>> {
|
||||
size_t operator()(const Tins::HWAddress<n> &addr) const {
|
||||
size_t operator()(const Tins::HWAddress<n>& addr) const {
|
||||
return std::hash<std::string>()(addr.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
#endif // TINS_HWADDRESS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
// Windows likes to define macros with not-so-common-names, which break
|
||||
// this code
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#ifdef TIMESTAMP_REQUEST
|
||||
#undef TIMESTAMP_REQUEST
|
||||
#endif // TIMESTAMP_REQUEST
|
||||
@@ -40,369 +40,469 @@
|
||||
#ifdef TIMESTAMP_REPLY
|
||||
#undef TIMESTAMP_REPLY
|
||||
#endif // TIMESTAMP_REPLY
|
||||
#endif // WIN32
|
||||
#endif // _WIN32
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
#include "icmp_extension.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
|
||||
class InputMemoryStream;
|
||||
|
||||
} // Memory
|
||||
|
||||
/**
|
||||
* \class ICMP
|
||||
* \brief Class that represents an ICMP PDU.
|
||||
*
|
||||
* ICMP is the representation of the ICMP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
*/
|
||||
class TINS_API ICMP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ICMP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
|
||||
/** \brief ICMP flags
|
||||
*/
|
||||
enum Flags {
|
||||
ECHO_REPLY = 0,
|
||||
DEST_UNREACHABLE = 3,
|
||||
SOURCE_QUENCH = 4,
|
||||
REDIRECT = 5,
|
||||
ECHO_REQUEST = 8,
|
||||
TIME_EXCEEDED = 11,
|
||||
PARAM_PROBLEM = 12,
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16,
|
||||
ADDRESS_MASK_REQUEST = 17,
|
||||
ADDRESS_MASK_REPLY = 18
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of ICMP.
|
||||
*
|
||||
* If no flag is specified, then ECHO_REQUEST will be used.
|
||||
* \param flag The type flag which will be set.
|
||||
*/
|
||||
ICMP(Flags flag = ECHO_REQUEST);
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ICMP header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* Any extra data in the buffer will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ICMP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Sets the code field.
|
||||
*
|
||||
* \param new_code The code which will be stored in the ICMP struct.
|
||||
*/
|
||||
void code(uint8_t new_code);
|
||||
|
||||
/** \brief Sets the type field.
|
||||
*
|
||||
* \param type The type which will be stored in the ICMP struct.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id uint16_t with the new id.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence field.
|
||||
*
|
||||
* \param new_seq uint16_t with the new sequence.
|
||||
*/
|
||||
void sequence(uint16_t new_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the gateway field.
|
||||
*
|
||||
* \param new_gw The new value for the gateway field.
|
||||
*/
|
||||
void gateway(address_type new_gw);
|
||||
|
||||
/**
|
||||
* \brief Setter for the mtu field.
|
||||
*
|
||||
* \param new_mtu uint16_t with the new sequence.
|
||||
*/
|
||||
void mtu(uint16_t new_mtu);
|
||||
|
||||
/**
|
||||
* \brief Setter for the pointer field.
|
||||
*
|
||||
* \param new_pointer uint8_t with the new pointer.
|
||||
*/
|
||||
void pointer(uint8_t new_pointer);
|
||||
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void original_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the receive timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the address mask field.
|
||||
*
|
||||
* \param new_mask the value to be set.
|
||||
*/
|
||||
void address_mask(address_type new_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets echo reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets destination unreachable for this PDU.
|
||||
*/
|
||||
void set_dest_unreachable();
|
||||
|
||||
/**
|
||||
* \brief Sets time exceeded flag for this PDU.
|
||||
*
|
||||
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
|
||||
* exceeded, otherwise it will represent a fragment reassembly
|
||||
* time exceeded.
|
||||
*/
|
||||
void set_time_exceeded(bool ttl_exceeded = true);
|
||||
|
||||
/**
|
||||
* \brief Sets parameter problem flag for this PDU.
|
||||
*
|
||||
* \param set_pointer Indicates whether a pointer to the bad octet
|
||||
* is provided.
|
||||
* \param bad_octet Identifies the octet in which the error was
|
||||
* detected. If set_pointer == false, it is ignored.
|
||||
*/
|
||||
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
|
||||
|
||||
/**
|
||||
* \brief Sets source quench flag for this PDU.
|
||||
*/
|
||||
void set_source_quench();
|
||||
|
||||
/**
|
||||
* \brief Sets redirect flag for this PDU.
|
||||
*
|
||||
* \param icode The code to be set.
|
||||
* \param address Address of the gateway to which traffic should
|
||||
* be sent.
|
||||
*/
|
||||
void set_redirect(uint8_t icode, address_type address);
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP type flag.
|
||||
*
|
||||
* \return The type flag for this ICMP PDU.
|
||||
*/
|
||||
Flags type() const {
|
||||
return (Flags)header_.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP code flag.
|
||||
*
|
||||
* \return The code flag for this ICMP PDU.
|
||||
*/
|
||||
uint8_t code() const {
|
||||
return header_.code;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return Returns the checksum as an unit16_t.
|
||||
*/
|
||||
uint16_t checksum() const {
|
||||
return Endian::be_to_host(header_.check);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo id.
|
||||
*
|
||||
* \return Returns the echo id.
|
||||
*/
|
||||
uint16_t id() const {
|
||||
return Endian::be_to_host(header_.un.echo.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo sequence number.
|
||||
*
|
||||
* \return Returns the echo sequence number.
|
||||
*/
|
||||
uint16_t sequence() const {
|
||||
return Endian::be_to_host(header_.un.echo.sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the gateway field.
|
||||
*
|
||||
* \return Returns the gateway field value.
|
||||
*/
|
||||
address_type gateway() const {
|
||||
return address_type(Endian::be_to_host(header_.un.gateway));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pointer field.
|
||||
*
|
||||
* \return Returns the pointer field value.
|
||||
*/
|
||||
uint8_t pointer() const {
|
||||
return header_.un.rfc4884.pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
*
|
||||
* \return Returns the length field value.
|
||||
*/
|
||||
uint8_t length() const {
|
||||
return header_.un.rfc4884.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the mtu field.
|
||||
*
|
||||
* \return Returns the mtu field value.
|
||||
*/
|
||||
uint16_t mtu() const {
|
||||
return Endian::be_to_host(header_.un.frag.mtu);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the original timestamp field.
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const {
|
||||
return Endian::be_to_host(orig_timestamp_or_address_mask_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
*
|
||||
* \return Returns the receive timestamp value.
|
||||
*/
|
||||
uint32_t receive_timestamp() const {
|
||||
return Endian::be_to_host(recv_timestamp_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the transmit timestamp field.
|
||||
*
|
||||
* \return Returns the transmit timestamp value.
|
||||
*/
|
||||
uint32_t transmit_timestamp() const {
|
||||
return Endian::be_to_host(trans_timestamp_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the address mask field.
|
||||
*
|
||||
* \return Returns the address mask value.
|
||||
*/
|
||||
address_type address_mask() const {
|
||||
return address_type(Endian::be_to_host(orig_timestamp_or_address_mask_));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size.
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the trailer size.
|
||||
*
|
||||
* This metod overrides PDU::trailer_size. This size will hold the extensions size
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \class ICMP
|
||||
* \brief Class that represents an ICMP PDU.
|
||||
* \brief Getter for the extensions field.
|
||||
*
|
||||
* ICMP is the representation of the ICMP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
* \return The extensions field
|
||||
*/
|
||||
class ICMP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ICMP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
const ICMPExtensionsStructure& extensions() const {
|
||||
return extensions_;
|
||||
}
|
||||
|
||||
/** \brief ICMP flags
|
||||
*/
|
||||
enum Flags {
|
||||
ECHO_REPLY = 0,
|
||||
DEST_UNREACHABLE = 3,
|
||||
SOURCE_QUENCH = 4,
|
||||
REDIRECT = 5,
|
||||
ECHO_REQUEST = 8,
|
||||
TIME_EXCEEDED = 11,
|
||||
PARAM_PROBLEM = 12,
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16,
|
||||
ADDRESS_MASK_REQUEST = 17,
|
||||
ADDRESS_MASK_REPLY = 18
|
||||
};
|
||||
/**
|
||||
* \brief Getter for the extensions field.
|
||||
*
|
||||
* \return The extensions field
|
||||
*/
|
||||
ICMPExtensionsStructure& extensions() {
|
||||
return extensions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of ICMP.
|
||||
*
|
||||
* If no flag is specified, then ECHO_REQUEST will be used.
|
||||
* \param flag The type flag which will be set.
|
||||
*/
|
||||
ICMP(Flags flag = ECHO_REQUEST);
|
||||
/**
|
||||
* \brief Indicates whether this object contains ICMP extensions
|
||||
*/
|
||||
bool has_extensions() const {
|
||||
return !extensions_.extensions().empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ICMP header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* Any extra data in the buffer will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ICMP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Sets the code field.
|
||||
*
|
||||
* \param new_code The code which will be stored in the ICMP struct.
|
||||
*/
|
||||
void code(uint8_t new_code);
|
||||
/**
|
||||
* \brief Sets whether the length field will be set for packets that use it
|
||||
*
|
||||
* As defined in RFC 4884, some ICMP packet types can have a length field. This
|
||||
* method controlers whether the length field is set or not.
|
||||
*
|
||||
* Note that this only indicates that the packet should use this field. The
|
||||
* actual value will be set during the packet's serialization.
|
||||
*
|
||||
* Note that, in order to br RFC compliant, if the size of the encapsulated
|
||||
* PDU is greater than 128, the length field will always be set, regardless
|
||||
* of whether this method was called or not.
|
||||
*
|
||||
* /param value true iff the length field should be set appropriately
|
||||
*/
|
||||
void use_length_field(bool value);
|
||||
|
||||
/** \brief Sets the type field.
|
||||
*
|
||||
* \param type The type which will be stored in the ICMP struct.
|
||||
*/
|
||||
void type(Flags type);
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id uint16_t with the new id.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence field.
|
||||
*
|
||||
* \param new_seq uint16_t with the new sequence.
|
||||
*/
|
||||
void sequence(uint16_t new_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the gateway field.
|
||||
*
|
||||
* \param new_gw The new value for the gateway field.
|
||||
*/
|
||||
void gateway(address_type new_gw);
|
||||
|
||||
/**
|
||||
* \brief Setter for the mtu field.
|
||||
*
|
||||
* \param new_mtu uint16_t with the new sequence.
|
||||
*/
|
||||
void mtu(uint16_t new_mtu);
|
||||
|
||||
/**
|
||||
* \brief Setter for the pointer field.
|
||||
*
|
||||
* \param new_pointer uint8_t with the new pointer.
|
||||
*/
|
||||
void pointer(uint8_t new_pointer);
|
||||
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void original_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the receive timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the address mask field.
|
||||
*
|
||||
* \param new_mask the value to be set.
|
||||
*/
|
||||
void address_mask(address_type new_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets echo reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets destination unreachable for this PDU.
|
||||
*/
|
||||
void set_dest_unreachable();
|
||||
|
||||
/**
|
||||
* \brief Sets time exceeded flag for this PDU.
|
||||
*
|
||||
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
|
||||
* exceeded, otherwise it will represent a fragment reassembly
|
||||
* time exceeded.
|
||||
*/
|
||||
void set_time_exceeded(bool ttl_exceeded = true);
|
||||
|
||||
/**
|
||||
* \brief Sets parameter problem flag for this PDU.
|
||||
*
|
||||
* \param set_pointer Indicates wether a pointer to the bad octet
|
||||
* is provided.
|
||||
* \param bad_octet Identifies the octet in which the error was
|
||||
* detected. If set_pointer == false, it is ignored.
|
||||
*/
|
||||
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
|
||||
|
||||
/**
|
||||
* \brief Sets source quench flag for this PDU.
|
||||
*/
|
||||
void set_source_quench();
|
||||
|
||||
/**
|
||||
* \brief Sets redirect flag for this PDU.
|
||||
*
|
||||
* \param icode The code to be set.
|
||||
* \param address Address of the gateway to which traffic should
|
||||
* be sent.
|
||||
*/
|
||||
void set_redirect(uint8_t icode, address_type address);
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP type flag.
|
||||
*
|
||||
* \return The type flag for this ICMP PDU.
|
||||
*/
|
||||
Flags type() const { return (Flags)_icmp.type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP code flag.
|
||||
*
|
||||
* \return The code flag for this ICMP PDU.
|
||||
*/
|
||||
uint8_t code() const { return _icmp.code; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return Returns the checksum as an unit16_t.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_icmp.check); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo id.
|
||||
*
|
||||
* \return Returns the echo id.
|
||||
*/
|
||||
uint16_t id() const { return Endian::be_to_host(_icmp.un.echo.id); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo sequence number.
|
||||
*
|
||||
* \return Returns the echo sequence number.
|
||||
*/
|
||||
uint16_t sequence() const { return Endian::be_to_host(_icmp.un.echo.sequence); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the gateway field.
|
||||
*
|
||||
* \return Returns the gateway field value.
|
||||
*/
|
||||
address_type gateway() const {
|
||||
return address_type(Endian::be_to_host(_icmp.un.gateway));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pointer field.
|
||||
*
|
||||
* \return Returns the pointer field value.
|
||||
*/
|
||||
uint8_t pointer() const { return this->_icmp.un.pointer; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the mtu field.
|
||||
*
|
||||
* \return Returns the mtu field value.
|
||||
*/
|
||||
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the original timestamp field.
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
*
|
||||
* \return Returns the receive timestamp value.
|
||||
*/
|
||||
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the transmit timestamp field.
|
||||
*
|
||||
* \return Returns the transmit timestamp value.
|
||||
*/
|
||||
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the address mask field.
|
||||
*
|
||||
* \return Returns the address mask value.
|
||||
*/
|
||||
address_type address_mask() const {
|
||||
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::ICMP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ICMP *clone() const {
|
||||
return new ICMP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct icmphdr {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t check;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo;
|
||||
uint32_t gateway;
|
||||
struct {
|
||||
uint16_t unused;
|
||||
uint16_t mtu;
|
||||
} frag;
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ICMP* clone() const {
|
||||
return new ICMP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct icmp_header {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t check;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo;
|
||||
uint32_t gateway;
|
||||
struct {
|
||||
uint16_t unused;
|
||||
uint16_t mtu;
|
||||
} frag;
|
||||
struct {
|
||||
uint8_t pointer;
|
||||
} un;
|
||||
} TINS_END_PACK;
|
||||
uint8_t length;
|
||||
uint16_t unused;
|
||||
} rfc4884;
|
||||
} un;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void checksum(uint16_t new_check);
|
||||
|
||||
/** \brief Serialices this ICMP PDU.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
* \param total_sz The size available in the buffer.
|
||||
* \param parent The PDU that's one level below this one on the stack.
|
||||
*/
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void checksum(uint16_t new_check);
|
||||
|
||||
/** \brief Serialices this ICMP PDU.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
* \param total_sz The size available in the buffer.
|
||||
* \param parent The PDU that's one level below this one on the stack.
|
||||
*/
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
uint32_t get_adjusted_inner_pdu_size() const;
|
||||
void try_parse_extensions(Memory::InputMemoryStream& stream);
|
||||
bool are_extensions_allowed() const;
|
||||
|
||||
icmphdr _icmp;
|
||||
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
|
||||
};
|
||||
}
|
||||
icmp_header header_;
|
||||
uint32_t orig_timestamp_or_address_mask_, recv_timestamp_, trans_timestamp_;
|
||||
ICMPExtensionsStructure extensions_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ICMP_H
|
||||
|
||||
308
include/tins/icmp_extension.h
Normal file
308
include/tins/icmp_extension.h
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* 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_ICMP_EXTENSION_H
|
||||
#define TINS_ICMP_EXTENSION_H
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "small_uint.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class MPLS;
|
||||
|
||||
/**
|
||||
* \brief Class that represents an ICMP extension object
|
||||
*/
|
||||
class TINS_API ICMPExtension {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the payload
|
||||
*/
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
|
||||
/**
|
||||
* The type that will be returned when serializing an extensions
|
||||
* structure object
|
||||
*/
|
||||
typedef std::vector<uint8_t> serialization_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*/
|
||||
ICMPExtension();
|
||||
|
||||
/**
|
||||
* \brief Constructor taking class and type
|
||||
*
|
||||
* \param ext_class The extension class
|
||||
* \param ext_type The extension sub-type
|
||||
*/
|
||||
ICMPExtension(uint8_t ext_class, uint8_t ext_type);
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP extension from a buffer
|
||||
*
|
||||
* \param buffer The input buffer
|
||||
* \param total_sz The input buffer size
|
||||
*/
|
||||
ICMPExtension(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Setter for the extension class field
|
||||
*
|
||||
* \param value The new extension class field value
|
||||
*/
|
||||
void extension_class(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the extension sub-type field
|
||||
*
|
||||
* \param value The new extension sub-type field value
|
||||
*/
|
||||
void extension_type(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
*
|
||||
* \param value The new payload field value
|
||||
*/
|
||||
void payload(const payload_type& value);
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension class field
|
||||
*
|
||||
* \return The extension class field value
|
||||
*/
|
||||
uint8_t extension_class() const {
|
||||
return extension_class_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension sub-type field
|
||||
*
|
||||
* \return The extension sub-type field value
|
||||
*/
|
||||
uint8_t extension_type() const {
|
||||
return extension_type_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension payload field
|
||||
*
|
||||
* \return The extension payload field value
|
||||
*/
|
||||
const payload_type& payload() const {
|
||||
return payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets the size of this ICMP extension
|
||||
*
|
||||
* This returns the basic header size + the payload size
|
||||
*
|
||||
* \return The size of this extension
|
||||
*/
|
||||
uint32_t size() const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension into a buffer
|
||||
*
|
||||
* \param buffer The output buffer in which to store the serialization
|
||||
* \param buffer_size The size of the output buffer
|
||||
*/
|
||||
void serialize(uint8_t* buffer, uint32_t buffer_size) const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension object
|
||||
*
|
||||
* \return The serialized extension
|
||||
*/
|
||||
serialization_type serialize() const;
|
||||
private:
|
||||
static const uint32_t BASE_HEADER_SIZE;
|
||||
|
||||
payload_type payload_;
|
||||
uint8_t extension_class_, extension_type_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an ICMP extensions structure
|
||||
*/
|
||||
class TINS_API ICMPExtensionsStructure {
|
||||
public:
|
||||
/**
|
||||
* The minimum ICMP payload size that has to be present when the PDU
|
||||
* contains extensions.
|
||||
*/
|
||||
static const uint32_t MINIMUM_ICMP_PAYLOAD;
|
||||
|
||||
/**
|
||||
* The type that will be returned when serializing an extensions
|
||||
* structure object
|
||||
*/
|
||||
typedef ICMPExtension::serialization_type serialization_type;
|
||||
|
||||
/**
|
||||
* The type used to store the list of ICMP extensions in this structure
|
||||
*/
|
||||
typedef std::list<ICMPExtension> extensions_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*
|
||||
* This sets the version to 2, as specified in RFC 4884
|
||||
*/
|
||||
ICMPExtensionsStructure();
|
||||
|
||||
/**
|
||||
* \brief Constructor from a buffer.
|
||||
*
|
||||
* This constructor will find, parse and store the extension
|
||||
* stack in the buffer.
|
||||
*/
|
||||
ICMPExtensionsStructure(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field
|
||||
*
|
||||
* \param value The new version field value
|
||||
*/
|
||||
void version(small_uint<4> value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the reserved field
|
||||
*
|
||||
* \param value The new reserved field value
|
||||
*/
|
||||
void reserved(small_uint<12> value);
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field
|
||||
*
|
||||
* \return The version field value
|
||||
*/
|
||||
small_uint<4> version() const {
|
||||
uint16_t value = Endian::be_to_host(version_and_reserved_);
|
||||
return (value >> 12) & 0xf;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the reserved field
|
||||
*
|
||||
* \return The reserved field value
|
||||
*/
|
||||
small_uint<12> reserved() const {
|
||||
uint16_t value = Endian::be_to_host(version_and_reserved_);
|
||||
return value & 0xfff;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field
|
||||
*
|
||||
* \return The checksum field value
|
||||
*/
|
||||
uint16_t checksum() const {
|
||||
return Endian::be_to_host(checksum_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the extensions stored by this structure
|
||||
*
|
||||
* \return The extensions stored in this structure
|
||||
*/
|
||||
const extensions_type& extensions() const {
|
||||
return extensions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds an extension to this structure
|
||||
*
|
||||
* \param extension The extension to be added
|
||||
*/
|
||||
void add_extension(const ICMPExtension& extension);
|
||||
|
||||
/**
|
||||
* \brief Adds an MPLS extension to this structure
|
||||
*
|
||||
* This will construct an extension using the provided MPLS packet as
|
||||
* its payload. The class and type fields will be set appropriately.
|
||||
*
|
||||
* \param extension The MPLS payload to be used for the new extension
|
||||
*/
|
||||
void add_extension(MPLS& mpls);
|
||||
|
||||
/**
|
||||
* \brief Gets the size of this ICMP extensions structure
|
||||
*
|
||||
* \return The size of this structure
|
||||
*/
|
||||
uint32_t size() const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension structure into a buffer
|
||||
*
|
||||
* \param buffer The output buffer in which to store the serialization
|
||||
* \param buffer_size The size of the output buffer
|
||||
*/
|
||||
void serialize(uint8_t* buffer, uint32_t buffer_size);
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension structure
|
||||
*
|
||||
* \return The serialized extension structure
|
||||
*/
|
||||
serialization_type serialize();
|
||||
|
||||
/**
|
||||
* \brief Validates if the given input contains a valid extension structure
|
||||
*
|
||||
* The validation is performed by calculating the checksum of the input
|
||||
* and comparing to the checksum value in the input buffer.
|
||||
*
|
||||
* \param buffer The input buffer
|
||||
* \param total_sz The size of the input buffer
|
||||
* \return true iff the buffer contains a valid ICMP extensions structure
|
||||
*/
|
||||
static bool validate_extensions(const uint8_t* buffer, uint32_t total_sz);
|
||||
private:
|
||||
static const uint32_t BASE_HEADER_SIZE;
|
||||
|
||||
uint16_t version_and_reserved_;
|
||||
uint16_t checksum_;
|
||||
extensions_type extensions_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ICMP_EXTENSION_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -45,10 +45,16 @@
|
||||
* \cond
|
||||
*/
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
|
||||
class InputMemoryStream;
|
||||
} // Memory
|
||||
class IPv4Address;
|
||||
class IPv6Address;
|
||||
class ICMPExtensionsStructure;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
template<size_t n>
|
||||
class byte_array {
|
||||
public:
|
||||
@@ -69,7 +75,7 @@ public:
|
||||
std::copy(start, n, data);
|
||||
}
|
||||
|
||||
uint8_t &operator[](size_t i) {
|
||||
uint8_t& operator[](size_t i) {
|
||||
return data[i];
|
||||
}
|
||||
|
||||
@@ -100,8 +106,8 @@ private:
|
||||
uint8_t data[n];
|
||||
};
|
||||
|
||||
void skip_line(std::istream &input);
|
||||
bool from_hex(const std::string &str, uint32_t &result);
|
||||
void skip_line(std::istream& input);
|
||||
bool from_hex(const std::string& str, uint32_t& result);
|
||||
|
||||
template<bool, typename T = void>
|
||||
struct enable_if {
|
||||
@@ -113,70 +119,76 @@ struct enable_if<false, T> {
|
||||
|
||||
};
|
||||
|
||||
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
|
||||
PDU* pdu_from_flag(Constants::Ethernet::e flag, const uint8_t* buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
|
||||
PDU* pdu_from_flag(Constants::IP::e flag, const uint8_t* buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_dlt_flag(int flag, const uint8_t *buffer,
|
||||
PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
|
||||
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);
|
||||
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType 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,
|
||||
uint32_t payload_length, ICMPExtensionsStructure& extensions);
|
||||
|
||||
template<typename T>
|
||||
bool increment_buffer(T &addr) {
|
||||
bool increment_buffer(T& addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0xff) {
|
||||
while (it >= addr.begin() && *it == 0xff) {
|
||||
*it = 0;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
if (it < addr.begin()) {
|
||||
return true;
|
||||
}
|
||||
(*it)++;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decrement_buffer(T &addr) {
|
||||
bool decrement_buffer(T& addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0) {
|
||||
while (it >= addr.begin() && *it == 0) {
|
||||
*it = 0xff;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
if (it < addr.begin()) {
|
||||
return true;
|
||||
}
|
||||
(*it)--;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool increment(IPv4Address &addr);
|
||||
bool increment(IPv6Address &addr);
|
||||
bool decrement(IPv4Address &addr);
|
||||
bool decrement(IPv6Address &addr);
|
||||
bool increment(IPv4Address& addr);
|
||||
bool increment(IPv6Address& addr);
|
||||
bool decrement(IPv4Address& addr);
|
||||
bool decrement(IPv6Address& addr);
|
||||
template<size_t n>
|
||||
bool increment(HWAddress<n> &addr) {
|
||||
bool increment(HWAddress<n>& addr) {
|
||||
return increment_buffer(addr);
|
||||
}
|
||||
template<size_t n>
|
||||
bool decrement(HWAddress<n> &addr) {
|
||||
bool decrement(HWAddress<n>& addr) {
|
||||
return decrement_buffer(addr);
|
||||
}
|
||||
|
||||
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address &mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
|
||||
template<size_t n>
|
||||
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n> &mask) {
|
||||
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n>& mask) {
|
||||
typename HWAddress<n>::iterator addr_iter = addr.begin();
|
||||
for(typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
for (typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter | ~*it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
|
||||
inline bool is_dot3(const uint8_t* ptr, size_t sz) {
|
||||
return (sz >= 13 && ptr[12] < 8);
|
||||
}
|
||||
|
||||
@@ -205,35 +217,33 @@ struct is_unsigned_integral<uint64_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
|
||||
// Part of C++14 standard library
|
||||
template<bool B, class T = void>
|
||||
using enable_if_t = typename std::enable_if<B,T>::type;
|
||||
#if TINS_IS_CXX11 && !defined(_MSC_VER)
|
||||
|
||||
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
|
||||
template <class T, class P, class=void>
|
||||
template <typename T, typename P, typename=void>
|
||||
struct accepts_type : std::false_type { };
|
||||
|
||||
template <class T, class P>
|
||||
struct accepts_type<T, P, enable_if_t<
|
||||
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
|
||||
>> : std::true_type { };
|
||||
template <typename T, typename P>
|
||||
struct accepts_type<T, P,
|
||||
typename std::enable_if<
|
||||
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
|
||||
>::type
|
||||
> : std::true_type { };
|
||||
|
||||
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
|
||||
template <class Functor, class Packet>
|
||||
template <typename Functor, typename Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
|
||||
return f(std::move(p));
|
||||
return f(std::move(p));
|
||||
}
|
||||
|
||||
template <class Functor, class Packet>
|
||||
template <typename Functor, typename Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
|
||||
return f(p);
|
||||
return f(p);
|
||||
}
|
||||
|
||||
template <class Functor, class Packet>
|
||||
template <typename Functor, typename Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
|
||||
return f(*p.pdu());
|
||||
return f(*p.pdu());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
1259
include/tins/ip.h
1259
include/tins/ip.h
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,13 +34,14 @@
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include "cxxstd.h"
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class IPv4Address
|
||||
* \brief Abstraction of an IPv4 address.
|
||||
*/
|
||||
class IPv4Address {
|
||||
class TINS_API IPv4Address {
|
||||
public:
|
||||
/**
|
||||
* The address size.
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
*
|
||||
* \param ip const char* containing the dotted-notation address.
|
||||
*/
|
||||
IPv4Address(const char *ip = 0);
|
||||
IPv4Address(const char* ip = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructor taking a std::string.
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
*
|
||||
* \param ip std::string containing the dotted-notation address.
|
||||
*/
|
||||
IPv4Address(const std::string &ip);
|
||||
IPv4Address(const std::string& ip);
|
||||
|
||||
/**
|
||||
* \brief Constructor taking a IP address represented as a
|
||||
@@ -101,8 +102,8 @@ public:
|
||||
* \param rhs The address to be compared.
|
||||
* \return bool indicating whether this address equals rhs.
|
||||
*/
|
||||
bool operator==(const IPv4Address &rhs) const {
|
||||
return ip_addr == rhs.ip_addr;
|
||||
bool operator==(const IPv4Address& rhs) const {
|
||||
return ip_addr_ == rhs.ip_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ public:
|
||||
* \return bool indicating whether this address is distinct
|
||||
* from rhs.
|
||||
*/
|
||||
bool operator!=(const IPv4Address &rhs) const {
|
||||
bool operator!=(const IPv4Address& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
@@ -122,8 +123,8 @@ public:
|
||||
* \param rhs The address to be compared.
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator< (const IPv4Address &rhs) const {
|
||||
return ip_addr < rhs.ip_addr;
|
||||
bool operator< (const IPv4Address& rhs) const {
|
||||
return ip_addr_ < rhs.ip_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,25 +176,27 @@ public:
|
||||
* \param addr The IPv4Address to be written.
|
||||
* \return std::stream& pointing to output.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &output, const IPv4Address &addr);
|
||||
friend std::ostream& operator<<(std::ostream& output, const IPv4Address& addr);
|
||||
private:
|
||||
uint32_t ip_to_int(const char* ip);
|
||||
|
||||
uint32_t ip_addr;
|
||||
uint32_t ip_addr_;
|
||||
};
|
||||
} //namespace Tins
|
||||
|
||||
} // Tins
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<Tins::IPv4Address> {
|
||||
size_t operator()(const Tins::IPv4Address &addr) const {
|
||||
size_t operator()(const Tins::IPv4Address& addr) const {
|
||||
return std::hash<uint32_t>()(addr);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
} // std
|
||||
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
#endif // TINS_IPADDRESS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,9 +33,11 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
@@ -48,13 +50,12 @@ public:
|
||||
IPv4Fragment() : offset_() { }
|
||||
|
||||
template<typename T>
|
||||
IPv4Fragment(T *pdu, uint16_t offset)
|
||||
: payload_(pdu->serialize()), offset_(offset)
|
||||
{
|
||||
IPv4Fragment(T* pdu, uint16_t offset)
|
||||
: payload_(pdu->serialize()), offset_(offset) {
|
||||
|
||||
}
|
||||
|
||||
const payload_type &payload() const {
|
||||
const payload_type& payload() const {
|
||||
return payload_;
|
||||
}
|
||||
|
||||
@@ -66,23 +67,23 @@ private:
|
||||
uint16_t offset_;
|
||||
};
|
||||
|
||||
class IPv4Stream {
|
||||
class TINS_API IPv4Stream {
|
||||
public:
|
||||
IPv4Stream();
|
||||
|
||||
void add_fragment(IP *ip);
|
||||
void add_fragment(IP* ip);
|
||||
bool is_complete() const;
|
||||
PDU *allocate_pdu() const;
|
||||
PDU* allocate_pdu() const;
|
||||
private:
|
||||
typedef std::vector<IPv4Fragment> fragments_type;
|
||||
|
||||
uint16_t extract_offset(const IP *ip);
|
||||
bool extract_more_frag(const IP *ip);
|
||||
uint16_t extract_offset(const IP* ip);
|
||||
bool extract_more_frag(const IP* ip);
|
||||
|
||||
fragments_type fragments;
|
||||
bool received_end;
|
||||
uint8_t transport_proto;
|
||||
size_t received_size, total_size;
|
||||
fragments_type fragments_;
|
||||
bool received_end_;
|
||||
uint8_t transport_proto_;
|
||||
size_t received_size_, total_size_;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
@@ -93,7 +94,7 @@ private:
|
||||
/**
|
||||
* \brief Reassembles fragmented IP packets.
|
||||
*/
|
||||
class IPv4Reassembler {
|
||||
class TINS_API IPv4Reassembler {
|
||||
public:
|
||||
/**
|
||||
* The status of each processed packet.
|
||||
@@ -133,7 +134,7 @@ public:
|
||||
* fragmented or REASSEMBLED if the packet was fragmented
|
||||
* but has now been reassembled.
|
||||
*/
|
||||
packet_status process(PDU &pdu);
|
||||
packet_status process(PDU& pdu);
|
||||
|
||||
/**
|
||||
* Removes all of the packets and data stored.
|
||||
@@ -156,11 +157,11 @@ private:
|
||||
typedef std::pair<uint16_t, address_pair> key_type;
|
||||
typedef std::map<key_type, Internals::IPv4Stream> streams_type;
|
||||
|
||||
key_type make_key(const IP *ip) const;
|
||||
key_type make_key(const IP* ip) const;
|
||||
address_pair make_address_pair(IPv4Address addr1, IPv4Address addr2) const;
|
||||
|
||||
streams_type streams;
|
||||
overlapping_technique technique;
|
||||
streams_type streams_;
|
||||
overlapping_technique technique_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -175,8 +176,7 @@ public:
|
||||
* \param func The functor object.
|
||||
*/
|
||||
IPv4ReassemblerProxy(Functor func)
|
||||
: functor_(func)
|
||||
{
|
||||
: functor_(func) {
|
||||
|
||||
}
|
||||
|
||||
@@ -188,15 +188,15 @@ public:
|
||||
* \return true if the packet wasn't forwarded, otherwise
|
||||
* the value returned by the functor.
|
||||
*/
|
||||
bool operator()(PDU &pdu) {
|
||||
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
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
IPv4Reassembler reassembler;
|
||||
IPv4Reassembler reassembler_;
|
||||
Functor functor_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,15 +31,17 @@
|
||||
#define TINS_IPSEC_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class IPSecAH
|
||||
* \brief Represents an IPSec Authentication Header.
|
||||
*/
|
||||
class IPSecAH : public PDU {
|
||||
class TINS_API IPSecAH : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -65,7 +67,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
IPSecAH(const uint8_t *buffer, uint32_t total_sz);
|
||||
IPSecAH(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -74,7 +76,7 @@ public:
|
||||
* \return The stored Next header field value.
|
||||
*/
|
||||
uint8_t next_header() const {
|
||||
return _header.next_header;
|
||||
return header_.next_header;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +84,7 @@ public:
|
||||
* \return The stored Length field value.
|
||||
*/
|
||||
uint8_t length() const {
|
||||
return _header.length;
|
||||
return header_.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +92,7 @@ public:
|
||||
* \return The stored Security Parameters Index field value.
|
||||
*/
|
||||
uint32_t spi() const {
|
||||
return Endian::be_to_host(_header.spi);
|
||||
return Endian::be_to_host(header_.spi);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,15 +100,15 @@ public:
|
||||
* \return The stored Sequence number field value.
|
||||
*/
|
||||
uint32_t seq_number() const {
|
||||
return Endian::be_to_host(_header.seq_number);
|
||||
return Endian::be_to_host(header_.seq_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICV field.
|
||||
* \return The stored ICV field value.
|
||||
*/
|
||||
const byte_array &icv() const {
|
||||
return _icv;
|
||||
const byte_array& icv() const {
|
||||
return icv_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
@@ -137,9 +139,9 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Setter for the ICV field.
|
||||
* \param new_icv The new ICV field value.
|
||||
* \param newicv_ The new ICV field value.
|
||||
*/
|
||||
void icv(const byte_array &new_icv);
|
||||
void icv(const byte_array& newicv_);
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
@@ -157,25 +159,25 @@ public:
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IPSecAH *clone() const {
|
||||
IPSecAH* clone() const {
|
||||
return new IPSecAH(*this);
|
||||
}
|
||||
private:
|
||||
struct header {
|
||||
struct ipsec_header {
|
||||
uint8_t next_header, length;
|
||||
uint32_t spi, seq_number;
|
||||
};
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
header _header;
|
||||
byte_array _icv;
|
||||
ipsec_header header_;
|
||||
byte_array icv_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Represents an IPSec Authentication Header.
|
||||
*/
|
||||
class IPSecESP : public PDU {
|
||||
class TINS_API IPSecESP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -198,7 +200,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
IPSecESP(const uint8_t *buffer, uint32_t total_sz);
|
||||
IPSecESP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -207,7 +209,7 @@ public:
|
||||
* \return The stored Security Parameters Index field value.
|
||||
*/
|
||||
uint32_t spi() const {
|
||||
return Endian::be_to_host(_header.spi);
|
||||
return Endian::be_to_host(header_.spi);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,7 +217,7 @@ public:
|
||||
* \return The stored Sequence number field value.
|
||||
*/
|
||||
uint32_t seq_number() const {
|
||||
return Endian::be_to_host(_header.seq_number);
|
||||
return Endian::be_to_host(header_.seq_number);
|
||||
}
|
||||
|
||||
// Setters
|
||||
@@ -248,17 +250,17 @@ public:
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IPSecESP *clone() const {
|
||||
IPSecESP* clone() const {
|
||||
return new IPSecESP(*this);
|
||||
}
|
||||
private:
|
||||
struct header {
|
||||
struct ipsec_header {
|
||||
uint32_t spi, seq_number;
|
||||
};
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
header _header;
|
||||
ipsec_header header_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -40,13 +40,19 @@
|
||||
#include "ipv6_address.h"
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
|
||||
class OutputMemoryStream;
|
||||
|
||||
} // Memory
|
||||
|
||||
class PacketSender;
|
||||
|
||||
/**
|
||||
* \class IPv6
|
||||
* Represents an IPv6 PDU.
|
||||
*/
|
||||
class IPv6 : public PDU {
|
||||
class TINS_API IPv6 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -92,8 +98,8 @@ public:
|
||||
* for the packet being constructed(optional).
|
||||
*/
|
||||
IPv6(address_type ip_dst = address_type(),
|
||||
address_type ip_src = address_type(),
|
||||
PDU *child = 0);
|
||||
address_type ip_src = address_type(),
|
||||
PDU* child = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv6 object from a buffer and adds all
|
||||
@@ -105,7 +111,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
IPv6(const uint8_t *buffer, uint32_t total_sz);
|
||||
IPv6(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -114,7 +120,7 @@ public:
|
||||
* \return The stored version field value.
|
||||
*/
|
||||
small_uint<4> version() const {
|
||||
return _header.version;
|
||||
return header_.version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,10 +129,10 @@ public:
|
||||
*/
|
||||
uint8_t traffic_class() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return ((_header.traffic_class << 4) & 0xf0) |
|
||||
((_header.flow_label[0] >> 4) & 0x0f);
|
||||
return ((header_.traffic_class << 4) & 0xf0) |
|
||||
((header_.flow_label[0] >> 4) & 0x0f);
|
||||
#else
|
||||
return _header.traffic_class;
|
||||
return header_.traffic_class;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -136,11 +142,11 @@ public:
|
||||
*/
|
||||
small_uint<20> flow_label() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return ((_header.flow_label[0] & 0x0f) << 16)
|
||||
| (_header.flow_label[1] << 8)
|
||||
| (_header.flow_label[2]);
|
||||
return ((header_.flow_label[0] & 0x0f) << 16)
|
||||
| (header_.flow_label[1] << 8)
|
||||
| (header_.flow_label[2]);
|
||||
#else
|
||||
return _header.flow_label;
|
||||
return header_.flow_label;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -149,7 +155,7 @@ public:
|
||||
* \return The stored payload_length field value.
|
||||
*/
|
||||
uint16_t payload_length() const {
|
||||
return Endian::be_to_host(_header.payload_length);
|
||||
return Endian::be_to_host(header_.payload_length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,7 +163,7 @@ public:
|
||||
* \return The stored next_header field value.
|
||||
*/
|
||||
uint8_t next_header() const {
|
||||
return _header.next_header;
|
||||
return header_.next_header;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,7 +171,7 @@ public:
|
||||
* \return The stored hop_limit field value.
|
||||
*/
|
||||
uint8_t hop_limit() const {
|
||||
return _header.hop_limit;
|
||||
return header_.hop_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +179,7 @@ public:
|
||||
* \return The stored src_addr field value.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
return _header.src_addr;
|
||||
return header_.src_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +187,7 @@ public:
|
||||
* \return The stored dst_addr field value.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
return _header.dst_addr;
|
||||
return header_.dst_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +195,7 @@ public:
|
||||
* \return The stored headers.
|
||||
*/
|
||||
const headers_type& headers() const {
|
||||
return ext_headers;
|
||||
return ext_headers_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
@@ -234,13 +240,13 @@ public:
|
||||
* \brief Setter for the src_addr field.
|
||||
* \param new_src_addr The new src_addr field value.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_addr);
|
||||
void src_addr(const address_type& new_src_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dst_addr field.
|
||||
* \param new_dst_addr The new dst_addr field value.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_addr);
|
||||
void dst_addr(const address_type& new_dst_addr);
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
@@ -250,18 +256,18 @@ public:
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
IPv6 *clone() const {
|
||||
IPv6* clone() const {
|
||||
return new IPv6(*this);
|
||||
}
|
||||
|
||||
@@ -275,7 +281,7 @@ public:
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &);
|
||||
void send(PacketSender& sender, const NetworkInterface &);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -283,7 +289,7 @@ public:
|
||||
*
|
||||
* \param header The extension header to be added.
|
||||
*/
|
||||
void add_ext_header(const ext_header &header);
|
||||
void add_ext_header(const ext_header& header);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an extension header that matchs the given
|
||||
@@ -295,11 +301,11 @@ public:
|
||||
*
|
||||
* \param id The header identifier to be searched.
|
||||
*/
|
||||
const ext_header *search_header(ExtensionHeader id) const;
|
||||
const ext_header* search_header(ExtensionHeader id) const;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
void set_last_next_header(uint8_t value);
|
||||
static uint8_t *write_header(const ext_header &header, uint8_t *buffer);
|
||||
static void write_header(const ext_header& header, Memory::OutputMemoryStream& stream);
|
||||
static bool is_extension_header(uint8_t header_id);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
@@ -322,9 +328,9 @@ private:
|
||||
uint8_t src_addr[16], dst_addr[16];
|
||||
} TINS_END_PACK;
|
||||
|
||||
ipv6_header _header;
|
||||
headers_type ext_headers;
|
||||
uint32_t headers_size;
|
||||
ipv6_header header_;
|
||||
headers_type ext_headers_;
|
||||
uint32_t headers_size_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,24 +34,15 @@
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include "cxxstd.h"
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* Represents an IPv6 address.
|
||||
*/
|
||||
class IPv6Address {
|
||||
class TINS_API IPv6Address {
|
||||
public:
|
||||
/**
|
||||
* The exception thrown when a malformed address is parsed.
|
||||
*/
|
||||
class malformed_address : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Malformed address";
|
||||
}
|
||||
};
|
||||
|
||||
static const size_t address_size = 16;
|
||||
|
||||
/**
|
||||
@@ -75,14 +66,14 @@ public:
|
||||
* \param addr The text representation from which to construct this
|
||||
* object.
|
||||
*/
|
||||
IPv6Address(const char *addr);
|
||||
IPv6Address(const char* addr);
|
||||
|
||||
/**
|
||||
* \brief Constructor from a text representation std::string.
|
||||
* \param addr The text representation from which to construct this
|
||||
* object.
|
||||
*/
|
||||
IPv6Address(const std::string &addr);
|
||||
IPv6Address(const std::string& addr);
|
||||
|
||||
/**
|
||||
* \brief Constructor from a buffer.
|
||||
@@ -104,21 +95,21 @@ public:
|
||||
* Returns an iterator to the beginning of this address.
|
||||
*/
|
||||
iterator begin() {
|
||||
return address;
|
||||
return address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a const iterator to the beginning of this address.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
return address;
|
||||
return address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the one-past-the-end element of this address.
|
||||
*/
|
||||
iterator end() {
|
||||
return address + address_size;
|
||||
return address_ + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,7 +117,7 @@ public:
|
||||
* address.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
return address + address_size;
|
||||
return address_ + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,8 +127,8 @@ public:
|
||||
*
|
||||
* \return bool indicating whether addresses are equal.
|
||||
*/
|
||||
bool operator==(const IPv6Address &rhs) const {
|
||||
return std::equal(begin(), end(), rhs.begin());
|
||||
bool operator==(const IPv6Address& rhs) const {
|
||||
return std::equal(begin(), end(), rhs.address_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,7 +138,7 @@ public:
|
||||
*
|
||||
* \return bool indicating whether addresses are distinct.
|
||||
*/
|
||||
bool operator!=(const IPv6Address &rhs) const {
|
||||
bool operator!=(const IPv6Address& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
@@ -158,7 +149,7 @@ public:
|
||||
*
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator<(const IPv6Address &rhs) const {
|
||||
bool operator<(const IPv6Address& rhs) const {
|
||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
@@ -205,26 +196,29 @@ public:
|
||||
* \param addr The parameter to be written.
|
||||
* \return std::ostream& pointing to the os parameter.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &os, const IPv6Address &addr) {
|
||||
friend std::ostream& operator<<(std::ostream& os, const IPv6Address& addr) {
|
||||
return os << addr.to_string();
|
||||
}
|
||||
private:
|
||||
void init(const char *addr);
|
||||
void init(const char* addr);
|
||||
|
||||
uint8_t address[address_size];
|
||||
uint8_t address_[address_size];
|
||||
};
|
||||
} //namespace Tins
|
||||
|
||||
} // Tins
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<Tins::IPv6Address> {
|
||||
size_t operator()(const Tins::IPv6Address &addr) const {
|
||||
size_t operator()(const Tins::IPv6Address& addr) const {
|
||||
return std::hash<std::string>()(addr.to_string());
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
} // std
|
||||
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
#endif // TINS_IPV6_ADDRESS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -35,369 +35,387 @@
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class LLC
|
||||
* \brief Representing a LLC frame.
|
||||
*
|
||||
* This PDU follows the standard LLC frame described in the IEEE 802.2 specs.
|
||||
*/
|
||||
class TINS_API LLC : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \class LLC
|
||||
* \brief Representing a LLC frame.
|
||||
*
|
||||
* This PDU follows the standard LLC frame described in the IEEE 802.2 specs.
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class LLC : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::LLC;
|
||||
static const PDU::PDUType pdu_flag = PDU::LLC;
|
||||
|
||||
/**
|
||||
* \brief Represents the LLC global DSAP address.
|
||||
*/
|
||||
static const uint8_t GLOBAL_DSAP_ADDR;
|
||||
|
||||
/**
|
||||
* \brief Represents the LLC NULL address.
|
||||
*/
|
||||
static const uint8_t NULL_ADDR;
|
||||
/**
|
||||
* \brief Represents the LLC global DSAP address.
|
||||
*/
|
||||
static const uint8_t GLOBAL_DSAP_ADDR;
|
||||
|
||||
/**
|
||||
* \brief Represents the LLC NULL address.
|
||||
*/
|
||||
static const uint8_t NULL_ADDR;
|
||||
|
||||
/**
|
||||
* \brief LLC Format flags.
|
||||
*/
|
||||
enum Format {
|
||||
INFORMATION = 0,
|
||||
SUPERVISORY = 1,
|
||||
UNNUMBERED = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief LLC Modifier functions.
|
||||
*/
|
||||
enum ModifierFunctions {
|
||||
UI = 0x00,
|
||||
XID = 0x1D,
|
||||
TEST = 0x07,
|
||||
SABME = 0x1E,
|
||||
DISC = 0x02,
|
||||
UA = 0x06,
|
||||
DM = 0x18,
|
||||
FRMR = 0x11
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief LLC Supervisory functions
|
||||
*/
|
||||
enum SupervisoryFunctions {
|
||||
RECEIVE_READY = 0,
|
||||
REJECT = 2,
|
||||
RECEIVE_NOT_READY = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
LLC();
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance of LLC, setting the dsap and ssap.
|
||||
* The control field is set to 0.
|
||||
* \param dsap The dsap value to be set.
|
||||
* \param ssap The ssap value to be set.
|
||||
*/
|
||||
LLC(uint8_t dsap, uint8_t ssap);
|
||||
|
||||
/**
|
||||
* \brief Constructs a LLC object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If there is not enough size for a LLC header, a malformed_packet
|
||||
* exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
LLC(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the group destination bit.
|
||||
* \param value The value to be set.
|
||||
*/
|
||||
void group(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dsap field.
|
||||
* \param new_dsap The new dsap field.
|
||||
*/
|
||||
void dsap(uint8_t new_dsap);
|
||||
|
||||
/**
|
||||
* \brief Setter for the response bit.
|
||||
* \param value The value to be set.
|
||||
*/
|
||||
void response(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ssap field.
|
||||
* \param new_ssap The new ssap field.
|
||||
*/
|
||||
void ssap(uint8_t new_ssap);
|
||||
|
||||
/**
|
||||
* \brief Setter for the LLC frame format type.
|
||||
* \param type The LLC frame format to set.
|
||||
*/
|
||||
void type(Format type);
|
||||
|
||||
/**
|
||||
* \brief Setter for sender send sequence number.
|
||||
* Only applied if format is INFORMATION.
|
||||
* \param seq_number New sender send sequence number to be set.
|
||||
*/
|
||||
void send_seq_number(uint8_t seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for sender receive sequence number.
|
||||
* Only applied if format is INFORMATION or SUPERVISORY.
|
||||
* \param seq_number New sender receive sequence number to be set.
|
||||
*/
|
||||
void receive_seq_number(uint8_t seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for the poll/final flag.
|
||||
* \param value Bool indicating the value of the flag.
|
||||
*/
|
||||
void poll_final(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the supervisory function.
|
||||
* Only applied if format is SUPERVISORY.
|
||||
* \param new_func Value to set on the supervisory function field.
|
||||
*/
|
||||
void supervisory_function(SupervisoryFunctions new_func);
|
||||
|
||||
/**
|
||||
* \brief Setter for the modifier function field.
|
||||
* Only applied if format is UNNUMBERED.
|
||||
* \param modifier_func Value to set on the modifier function field.
|
||||
*/
|
||||
void modifier_function(ModifierFunctions mod_func);
|
||||
|
||||
/**
|
||||
* \brief Add a xid information field.
|
||||
* Only applied if format is UNNUMBERED and function is XID.
|
||||
* \param xid_id XID information of the MAC sublayer.
|
||||
* \param llc_type_class Value to set the llc_type_class field.
|
||||
* \param receive_window XID sender's receive window size.
|
||||
*/
|
||||
void add_xid_information(uint8_t xid_id, uint8_t llc_type_class, uint8_t receive_window);
|
||||
|
||||
//TODO: Add Acknowledged connectionless information
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the group destination bit.
|
||||
* \return Whether the group bit is set or not.
|
||||
*/
|
||||
bool group() {return _header.dsap & 0x01; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the dsap field.
|
||||
* \return The dsap field value
|
||||
*/
|
||||
uint8_t dsap() {return _header.dsap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the response bit.
|
||||
* \return Whether the response bit is set or not.
|
||||
*/
|
||||
bool response() {return (_header.ssap & 0x01); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ssap field.
|
||||
* \return The ssap field.
|
||||
*/
|
||||
uint8_t ssap() {return _header.ssap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the LLC frame format type.
|
||||
* \return The LLC frame format.
|
||||
*/
|
||||
uint8_t type() {return _type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for sender send sequence number.
|
||||
*
|
||||
* \return The sender send sequence number if format is INFORMATION else 0.
|
||||
*/
|
||||
uint8_t send_seq_number() {
|
||||
return (type() == INFORMATION) ? (control_field.info.send_seq_num) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for sender receive sequence number.
|
||||
*
|
||||
* \return The sender receive sequence number if format is
|
||||
* INFORMATION or SUPERVISORY else 0.
|
||||
*/
|
||||
uint8_t receive_seq_number() {
|
||||
switch (type()) {
|
||||
case INFORMATION:
|
||||
return control_field.info.recv_seq_num;
|
||||
case SUPERVISORY:
|
||||
return control_field.super.recv_seq_num;
|
||||
case UNNUMBERED:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the poll/final flag.
|
||||
* \return Whether the poll/final flag is set.
|
||||
*/
|
||||
bool poll_final() {
|
||||
switch (type()) {
|
||||
case UNNUMBERED:
|
||||
return control_field.unnumbered.poll_final_bit;
|
||||
case INFORMATION:
|
||||
return control_field.info.poll_final_bit;
|
||||
case SUPERVISORY:
|
||||
return control_field.super.poll_final_bit;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the supervisory function.
|
||||
*
|
||||
* \return The supervisory function if format is SUPERVISORY else 0.
|
||||
*/
|
||||
uint8_t supervisory_function() {
|
||||
if (type() == SUPERVISORY)
|
||||
return control_field.super.supervisory_func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the modifier function field.
|
||||
*
|
||||
* \return The modifier function if format is UNNUMBERED else 0.
|
||||
*/
|
||||
uint8_t modifier_function() {
|
||||
if (type() == UNNUMBERED)
|
||||
return (control_field.unnumbered.mod_func1 << 3) + control_field.unnumbered.mod_func2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the LLC frame's header length.
|
||||
*
|
||||
* \return The header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Delete all the information fields added.
|
||||
*/
|
||||
void clear_information_fields();
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
LLC *clone() const {
|
||||
return new LLC(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct llchdr {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
} TINS_END_PACK;
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
struct info_control_field {
|
||||
uint16_t
|
||||
type_bit:1,
|
||||
send_seq_num:7,
|
||||
poll_final_bit:1,
|
||||
recv_seq_num:7;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct super_control_field {
|
||||
uint16_t type_bit:2,
|
||||
supervisory_func:2,
|
||||
unused:4,
|
||||
poll_final_bit:1,
|
||||
recv_seq_num:7;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct un_control_field {
|
||||
uint8_t type_bits:2,
|
||||
mod_func1:2,
|
||||
poll_final_bit:1,
|
||||
mod_func2:3;
|
||||
} TINS_END_PACK;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
struct info_control_field {
|
||||
uint16_t send_seq_num:7,
|
||||
type_bit:1,
|
||||
recv_seq_num:7,
|
||||
poll_final_bit:1;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct super_control_field {
|
||||
uint16_t unused:4,
|
||||
supervisory_func:2,
|
||||
type_bit:2,
|
||||
recv_seq_num:7,
|
||||
poll_final_bit:1;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct un_control_field {
|
||||
uint8_t mod_func2:3,
|
||||
poll_final_bit:1,
|
||||
mod_func1:2,
|
||||
type_bits:2;
|
||||
} TINS_END_PACK;
|
||||
#endif
|
||||
|
||||
typedef std::vector<uint8_t> field_type;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
llchdr _header;
|
||||
uint8_t control_field_length;
|
||||
union {
|
||||
info_control_field info;
|
||||
super_control_field super;
|
||||
un_control_field unnumbered;
|
||||
} control_field;
|
||||
Format _type;
|
||||
uint8_t information_field_length;
|
||||
std::list<field_type> information_fields;
|
||||
/**
|
||||
* \brief LLC Format flags.
|
||||
*/
|
||||
enum Format {
|
||||
INFORMATION = 0,
|
||||
SUPERVISORY = 1,
|
||||
UNNUMBERED = 3
|
||||
};
|
||||
|
||||
}
|
||||
/**
|
||||
* \brief LLC Modifier functions.
|
||||
*/
|
||||
enum ModifierFunctions {
|
||||
UI = 0x00,
|
||||
XID = 0x1D,
|
||||
TEST = 0x07,
|
||||
SABME = 0x1E,
|
||||
DISC = 0x02,
|
||||
UA = 0x06,
|
||||
DM = 0x18,
|
||||
FRMR = 0x11
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief LLC Supervisory functions
|
||||
*/
|
||||
enum SupervisoryFunctions {
|
||||
RECEIVE_READY = 0,
|
||||
REJECT = 2,
|
||||
RECEIVE_NOT_READY = 1
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
LLC();
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance of LLC, setting the dsap and ssap.
|
||||
* The control field is set to 0.
|
||||
* \param dsap The dsap value to be set.
|
||||
* \param ssap The ssap value to be set.
|
||||
*/
|
||||
LLC(uint8_t dsap, uint8_t ssap);
|
||||
|
||||
/**
|
||||
* \brief Constructs a LLC object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If there is not enough size for a LLC header, a malformed_packet
|
||||
* exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
LLC(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the group destination bit.
|
||||
* \param value The value to be set.
|
||||
*/
|
||||
void group(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dsap field.
|
||||
* \param new_dsap The new dsap field.
|
||||
*/
|
||||
void dsap(uint8_t new_dsap);
|
||||
|
||||
/**
|
||||
* \brief Setter for the response bit.
|
||||
* \param value The value to be set.
|
||||
*/
|
||||
void response(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ssap field.
|
||||
* \param new_ssap The new ssap field.
|
||||
*/
|
||||
void ssap(uint8_t new_ssap);
|
||||
|
||||
/**
|
||||
* \brief Setter for the LLC frame format type.
|
||||
* \param type The LLC frame format to set.
|
||||
*/
|
||||
void type(Format type);
|
||||
|
||||
/**
|
||||
* \brief Setter for sender send sequence number.
|
||||
* Only applied if format is INFORMATION.
|
||||
* \param seq_number New sender send sequence number to be set.
|
||||
*/
|
||||
void send_seq_number(uint8_t seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for sender receive sequence number.
|
||||
* Only applied if format is INFORMATION or SUPERVISORY.
|
||||
* \param seq_number New sender receive sequence number to be set.
|
||||
*/
|
||||
void receive_seq_number(uint8_t seq_number);
|
||||
|
||||
/**
|
||||
* \brief Setter for the poll/final flag.
|
||||
* \param value Bool indicating the value of the flag.
|
||||
*/
|
||||
void poll_final(bool value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the supervisory function.
|
||||
* Only applied if format is SUPERVISORY.
|
||||
* \param new_func Value to set on the supervisory function field.
|
||||
*/
|
||||
void supervisory_function(SupervisoryFunctions new_func);
|
||||
|
||||
/**
|
||||
* \brief Setter for the modifier function field.
|
||||
* Only applied if format is UNNUMBERED.
|
||||
* \param modifier_func Value to set on the modifier function field.
|
||||
*/
|
||||
void modifier_function(ModifierFunctions mod_func);
|
||||
|
||||
/**
|
||||
* \brief Add a xid information field.
|
||||
* Only applied if format is UNNUMBERED and function is XID.
|
||||
* \param xid_id XID information of the MAC sublayer.
|
||||
* \param llc_type_class Value to set the llc_type_class field.
|
||||
* \param receive_window XID sender's receive window size.
|
||||
*/
|
||||
void add_xid_information(uint8_t xid_id,
|
||||
uint8_t llc_type_class,
|
||||
uint8_t receive_window);
|
||||
|
||||
//TODO: Add Acknowledged connectionless information
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the group destination bit.
|
||||
* \return Whether the group bit is set or not.
|
||||
*/
|
||||
bool group() {
|
||||
return header_.dsap & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the dsap field.
|
||||
* \return The dsap field value
|
||||
*/
|
||||
uint8_t dsap() {
|
||||
return header_.dsap;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the response bit.
|
||||
* \return Whether the response bit is set or not.
|
||||
*/
|
||||
bool response() {
|
||||
return (header_.ssap & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ssap field.
|
||||
* \return The ssap field.
|
||||
*/
|
||||
uint8_t ssap() {
|
||||
return header_.ssap;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the LLC frame format type.
|
||||
* \return The LLC frame format.
|
||||
*/
|
||||
uint8_t type() {
|
||||
return type_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for sender send sequence number.
|
||||
*
|
||||
* \return The sender send sequence number if format is INFORMATION else 0.
|
||||
*/
|
||||
uint8_t send_seq_number() {
|
||||
return (type() == INFORMATION) ? (control_field.info.send_seq_num) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for sender receive sequence number.
|
||||
*
|
||||
* \return The sender receive sequence number if format is
|
||||
* INFORMATION or SUPERVISORY else 0.
|
||||
*/
|
||||
uint8_t receive_seq_number() {
|
||||
switch (type()) {
|
||||
case INFORMATION:
|
||||
return control_field.info.recv_seq_num;
|
||||
case SUPERVISORY:
|
||||
return control_field.super.recv_seq_num;
|
||||
case UNNUMBERED:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the poll/final flag.
|
||||
* \return Whether the poll/final flag is set.
|
||||
*/
|
||||
bool poll_final() {
|
||||
switch (type()) {
|
||||
case UNNUMBERED:
|
||||
return control_field.unnumbered.poll_final_bit;
|
||||
case INFORMATION:
|
||||
return control_field.info.poll_final_bit;
|
||||
case SUPERVISORY:
|
||||
return control_field.super.poll_final_bit;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the supervisory function.
|
||||
*
|
||||
* \return The supervisory function if format is SUPERVISORY else 0.
|
||||
*/
|
||||
uint8_t supervisory_function() {
|
||||
if (type() == SUPERVISORY) {
|
||||
return control_field.super.supervisory_func;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the modifier function field.
|
||||
*
|
||||
* \return The modifier function if format is UNNUMBERED else 0.
|
||||
*/
|
||||
uint8_t modifier_function() {
|
||||
if (type() == UNNUMBERED) {
|
||||
return (control_field.unnumbered.mod_func1 << 3) + control_field.unnumbered.mod_func2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the LLC frame's header length.
|
||||
*
|
||||
* \return The header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Delete all the information fields added.
|
||||
*/
|
||||
void clear_information_fields();
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
LLC* clone() const {
|
||||
return new LLC(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct llchdr {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
} TINS_END_PACK;
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
struct info_control_field {
|
||||
uint16_t
|
||||
type_bit:1,
|
||||
send_seq_num:7,
|
||||
poll_final_bit:1,
|
||||
recv_seq_num:7;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct super_control_field {
|
||||
uint16_t type_bit:2,
|
||||
supervisory_func:2,
|
||||
unused:4,
|
||||
poll_final_bit:1,
|
||||
recv_seq_num:7;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct un_control_field {
|
||||
uint8_t type_bits:2,
|
||||
mod_func1:2,
|
||||
poll_final_bit:1,
|
||||
mod_func2:3;
|
||||
} TINS_END_PACK;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
TINS_BEGIN_PACK
|
||||
struct info_control_field {
|
||||
uint16_t send_seq_num:7,
|
||||
type_bit:1,
|
||||
recv_seq_num:7,
|
||||
poll_final_bit:1;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct super_control_field {
|
||||
uint16_t unused:4,
|
||||
supervisory_func:2,
|
||||
type_bit:2,
|
||||
recv_seq_num:7,
|
||||
poll_final_bit:1;
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct un_control_field {
|
||||
uint8_t mod_func2:3,
|
||||
poll_final_bit:1,
|
||||
mod_func1:2,
|
||||
type_bits:2;
|
||||
} TINS_END_PACK;
|
||||
#endif
|
||||
|
||||
typedef std::vector<uint8_t> field_type;
|
||||
typedef std::list<field_type> field_list;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
llchdr header_;
|
||||
uint8_t control_field_length_;
|
||||
union {
|
||||
info_control_field info;
|
||||
super_control_field super;
|
||||
un_control_field unnumbered;
|
||||
} control_field;
|
||||
Format type_;
|
||||
uint8_t information_field_length_;
|
||||
field_list information_fields_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_IEEE8022_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,7 +34,11 @@
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
class Loopback : public PDU {
|
||||
|
||||
/**
|
||||
* \brief Represents a Loopback PDU
|
||||
*/
|
||||
class TINS_API Loopback : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's type.
|
||||
@@ -61,13 +65,15 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Loopback(const uint8_t *buffer, uint32_t total_sz);
|
||||
Loopback(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the family identifier.
|
||||
* \return The stored family identifier.
|
||||
*/
|
||||
uint32_t family() const { return _family; }
|
||||
uint32_t family() const {
|
||||
return family_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the family identifier.
|
||||
@@ -84,35 +90,38 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Loopback *clone() const {
|
||||
Loopback* clone() const {
|
||||
return new Loopback(*this);
|
||||
}
|
||||
// Null/Loopback can only be sent in *BSD
|
||||
// Null/Loopback can only be sent in* BSD
|
||||
#ifdef BSD
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // BSD
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
uint32_t _family;
|
||||
uint32_t family_;
|
||||
};
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_LOOPBACK_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,19 +34,40 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
// Packing directives....
|
||||
#include "config.h"
|
||||
|
||||
// Check if this is Visual Studio
|
||||
#ifdef _MSC_VER
|
||||
// This is Visual Studio
|
||||
#define TINS_BEGIN_PACK __pragma( pack(push, 1) )
|
||||
#define TINS_END_PACK __pragma( pack(pop) )
|
||||
#define TINS_PACKED(DECLARATION) __pragma( pack(push, 1) ) DECLARATION __pragma( pack(pop) )
|
||||
#define TINS_DEPRECATED(func) __declspec(deprecated) func
|
||||
#define TINS_NOEXCEPT
|
||||
#define TINS_LIKELY(x) (x)
|
||||
#define TINS_UNLIKELY(x) (x)
|
||||
#else
|
||||
// Not Vistual Studio. Assume this is gcc compatible
|
||||
#define TINS_BEGIN_PACK
|
||||
#define TINS_END_PACK __attribute__((packed))
|
||||
#define TINS_PACKED(DECLARATION) DECLARATION __attribute__((packed))
|
||||
#define TINS_DEPRECATED(func) func __attribute__ ((deprecated))
|
||||
#define TINS_NOEXCEPT noexcept
|
||||
#endif
|
||||
#define TINS_LIKELY(x) __builtin_expect((x),1)
|
||||
#define TINS_UNLIKELY(x) __builtin_expect((x),0)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif
|
||||
// If libtins was built into a shared library
|
||||
#if defined(_WIN32) && !defined(TINS_STATIC)
|
||||
// Export/import symbols, depending on whether we're compiling or consuming the lib
|
||||
#ifdef tins_EXPORTS
|
||||
#define TINS_API __declspec(dllexport)
|
||||
#else
|
||||
#define TINS_API __declspec(dllimport)
|
||||
#endif // tins_EXPORTS
|
||||
#else
|
||||
// Otherwise, default this to an empty macro
|
||||
#define TINS_API
|
||||
#endif // _WIN32 && !TINS_STATIC
|
||||
|
||||
#endif // TINS_MACROS_H
|
||||
|
||||
264
include/tins/memory_helpers.h
Normal file
264
include/tins/memory_helpers.h
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 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_MEMORY_HELPERS_H
|
||||
#define TINS_MEMORY_HELPERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "exceptions.h"
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "hw_address.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
namespace Memory {
|
||||
|
||||
inline void read_data(const uint8_t* buffer, uint8_t* output_buffer, uint32_t size) {
|
||||
std::memcpy(output_buffer, buffer, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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) {
|
||||
std::memcpy(buffer, ptr, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_value(uint8_t* buffer, const T& value) {
|
||||
std::memcpy(buffer, &value, sizeof(value));
|
||||
}
|
||||
|
||||
class InputMemoryStream {
|
||||
public:
|
||||
InputMemoryStream(const uint8_t* buffer, uint32_t total_sz)
|
||||
: buffer_(buffer), size_(total_sz) {
|
||||
}
|
||||
|
||||
InputMemoryStream(const std::vector<uint8_t>& data)
|
||||
: buffer_(&data[0]), size_(data.size()) {
|
||||
}
|
||||
|
||||
void skip(uint32_t size) {
|
||||
if (TINS_UNLIKELY(size > size_)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
buffer_ += size;
|
||||
size_ -= size;
|
||||
}
|
||||
|
||||
bool can_read(uint32_t byte_count) const {
|
||||
return TINS_LIKELY(size_ >= byte_count);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T read() {
|
||||
T output;
|
||||
read(output);
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T read_le() {
|
||||
return Endian::le_to_host(read<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T read_be() {
|
||||
return Endian::be_to_host(read<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read(T& value) {
|
||||
if (!can_read(sizeof(value))) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
read_value(buffer_, value);
|
||||
skip(sizeof(value));
|
||||
}
|
||||
|
||||
void read(std::vector<uint8_t>& value, size_t count) {
|
||||
if (!can_read(count)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
value.assign(pointer(), pointer() + count);
|
||||
skip(count);
|
||||
}
|
||||
|
||||
void read(IPv4Address& address) {
|
||||
address = IPv4Address(read<uint32_t>());
|
||||
}
|
||||
|
||||
void read(IPv6Address& address) {
|
||||
if (!can_read(IPv6Address::address_size)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
address = pointer();
|
||||
skip(IPv6Address::address_size);
|
||||
}
|
||||
|
||||
template <size_t n>
|
||||
void read(HWAddress<n>& address) {
|
||||
if (!can_read(HWAddress<n>::address_size)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
address = pointer();
|
||||
skip(HWAddress<n>::address_size);
|
||||
}
|
||||
|
||||
void read(void* output_buffer, uint32_t output_buffer_size) {
|
||||
if (!can_read(output_buffer_size)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
read_data(buffer_, (uint8_t*)output_buffer, output_buffer_size);
|
||||
skip(output_buffer_size);
|
||||
}
|
||||
|
||||
const uint8_t* pointer() const {
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return size_;
|
||||
}
|
||||
|
||||
void size(uint32_t new_size) {
|
||||
size_ = new_size;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return size_ > 0;
|
||||
}
|
||||
private:
|
||||
const uint8_t* buffer_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
class OutputMemoryStream {
|
||||
public:
|
||||
OutputMemoryStream(uint8_t* buffer, uint32_t total_sz)
|
||||
: buffer_(buffer), size_(total_sz) {
|
||||
}
|
||||
|
||||
OutputMemoryStream(std::vector<uint8_t>& buffer)
|
||||
: buffer_(&buffer[0]), size_(buffer.size()) {
|
||||
}
|
||||
|
||||
void skip(uint32_t size) {
|
||||
if (TINS_UNLIKELY(size > size_)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
buffer_ += size;
|
||||
size_ -= size;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write(const T& value) {
|
||||
if (TINS_UNLIKELY(size_ < sizeof(value))) {
|
||||
throw serialization_error();
|
||||
}
|
||||
write_value(buffer_, value);
|
||||
skip(sizeof(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_be(const T& value) {
|
||||
write(Endian::host_to_be(value));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_le(const T& value) {
|
||||
write(Endian::host_to_le(value));
|
||||
}
|
||||
|
||||
template <typename ForwardIterator>
|
||||
void write(ForwardIterator start, ForwardIterator end) {
|
||||
const uint32_t length = std::distance(start, end);
|
||||
if (TINS_UNLIKELY(size_ < length)) {
|
||||
throw serialization_error();
|
||||
}
|
||||
std::copy(start, end, buffer_);
|
||||
skip(length);
|
||||
}
|
||||
|
||||
void write(const uint8_t* ptr, uint32_t length) {
|
||||
write(ptr, ptr + length);
|
||||
}
|
||||
|
||||
void write(const IPv4Address& address) {
|
||||
write(static_cast<uint32_t>(address));
|
||||
}
|
||||
|
||||
void write(const IPv6Address& address) {
|
||||
write(address.begin(), address.end());
|
||||
}
|
||||
|
||||
template <size_t n>
|
||||
void write(const HWAddress<n>& address) {
|
||||
write(address.begin(), address.end());
|
||||
}
|
||||
|
||||
void fill(uint32_t size, uint8_t value) {
|
||||
if (TINS_UNLIKELY(size_ < size)) {
|
||||
throw serialization_error();
|
||||
}
|
||||
std::fill(buffer_, buffer_ + size, value);
|
||||
skip(size);
|
||||
}
|
||||
|
||||
uint8_t* pointer() {
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
uint32_t size() const {
|
||||
return size_;
|
||||
}
|
||||
private:
|
||||
uint8_t* buffer_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
} // Memory
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_MEMORY_HELPERS_H
|
||||
156
include/tins/mpls.h
Normal file
156
include/tins/mpls.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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_MPLS_H
|
||||
#define TINS_MPLS_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "macros.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class ICMPExtension;
|
||||
|
||||
/**
|
||||
* \brief Represents an MPLS PDU
|
||||
*/
|
||||
class MPLS : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::MPLS;
|
||||
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*/
|
||||
MPLS();
|
||||
|
||||
/**
|
||||
* \brief Construct an MPLS layer from an ICMP extension
|
||||
*
|
||||
* This will use the extension's payload to build this packet.
|
||||
* The extension's class and type are not checked.
|
||||
*
|
||||
*/
|
||||
MPLS(const ICMPExtension& extension);
|
||||
|
||||
/**
|
||||
* \brief Constructor from buffer
|
||||
*/
|
||||
MPLS(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the label field.
|
||||
*/
|
||||
small_uint<20> label() const {
|
||||
return (Endian::be_to_host(header_.label_high) << 4) |
|
||||
((header_.label_low_and_bottom >> 4) & 0xf);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the bottom of the stack field.
|
||||
*/
|
||||
small_uint<1> bottom_of_stack() const {
|
||||
return header_.label_low_and_bottom & 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ttl field.
|
||||
*/
|
||||
uint8_t ttl() const {
|
||||
return header_.ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the label field
|
||||
*
|
||||
* \param value The new label field value
|
||||
*/
|
||||
void label(small_uint<20> value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the bottom of the stack field
|
||||
*
|
||||
* Note that if this MPLS layer is somewhere between an Ethernet and IP
|
||||
* layers, the bottom of the stack field will be overriden and set
|
||||
* automatically. You should only set this field when constructing ICMP
|
||||
* extensions.
|
||||
*
|
||||
* \param value The new bottom of the stack field value
|
||||
*/
|
||||
void bottom_of_stack(small_uint<1> value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ttl field
|
||||
*
|
||||
* \param value The new ttl field value
|
||||
*/
|
||||
void ttl(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Returns the MPLS frame's header length.
|
||||
*
|
||||
* \return The header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
MPLS* clone() const {
|
||||
return new MPLS(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct mpls_header {
|
||||
uint16_t label_high;
|
||||
uint8_t label_low_and_bottom;
|
||||
uint8_t ttl;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
mpls_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_MPLS_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,15 +33,17 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "hw_address.h"
|
||||
#include "ip_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class NetworkInterface
|
||||
* \brief Abstraction of a network interface
|
||||
*/
|
||||
class NetworkInterface {
|
||||
class TINS_API NetworkInterface {
|
||||
public:
|
||||
/**
|
||||
* \brief The type used to store the interface's identifier.
|
||||
@@ -59,6 +61,7 @@ public:
|
||||
struct Info {
|
||||
IPv4Address ip_addr, netmask, bcast_addr;
|
||||
address_type hw_addr;
|
||||
bool is_up;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -87,14 +90,14 @@ public:
|
||||
*
|
||||
* \param name The name of the interface this object will abstract.
|
||||
*/
|
||||
NetworkInterface(const std::string &name);
|
||||
NetworkInterface(const std::string& name);
|
||||
|
||||
/**
|
||||
* \brief Constructor from const char*.
|
||||
*
|
||||
* \param name The name of the interface this object will abstract.
|
||||
*/
|
||||
NetworkInterface(const char *name);
|
||||
NetworkInterface(const char* name);
|
||||
|
||||
/**
|
||||
* \brief Constructs a NetworkInterface from an ip address.
|
||||
@@ -112,7 +115,7 @@ public:
|
||||
* \return id_type containing the identifier.
|
||||
*/
|
||||
id_type id() const {
|
||||
return iface_id;
|
||||
return iface_id_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,15 +128,44 @@ public:
|
||||
* \return std::string containing this interface's name.
|
||||
*/
|
||||
std::string name() const;
|
||||
|
||||
/**
|
||||
* \brief Retrieves this interface's friendly name.
|
||||
*
|
||||
* The name returned by this method can be more human-friendly than
|
||||
* the one returned by NetworkInterface::name, depending on the platform
|
||||
* in which it's used.
|
||||
*
|
||||
* On GNU/Linux and OSX/FreeBSD, this returns the same string as
|
||||
* NetworkInterface::name.
|
||||
*
|
||||
* On Windows, this method returns a name such as
|
||||
* "Local Area Connection 1".
|
||||
*
|
||||
* Note thaat this returns a wstring rather than a string, to comply
|
||||
* with Window's adapter's FriendlyName type.
|
||||
*
|
||||
* \return std::wstring containing this interface's name.
|
||||
*/
|
||||
std::wstring friendly_name() const;
|
||||
|
||||
/**
|
||||
* \brief Retrieve this interface's addresses.
|
||||
*
|
||||
* This method is deprecated. You should use NetworkInterface::info (this
|
||||
* is just a naming deprecation, NetworkInterface::info is equivalent).
|
||||
* \deprecated
|
||||
*/
|
||||
Info addresses() const;
|
||||
|
||||
/**
|
||||
* \brief Retrieve this interface's information.
|
||||
*
|
||||
* This method iterates through all the interface's until the
|
||||
* correct one is found. Therefore it's O(N), being N the amount
|
||||
* of interfaces in the system.
|
||||
*/
|
||||
Info addresses() const;
|
||||
Info info() const;
|
||||
|
||||
/**
|
||||
* \brief Tests whether this is a valid interface;
|
||||
@@ -142,7 +174,7 @@ public:
|
||||
* default constructor.
|
||||
*/
|
||||
operator bool() const {
|
||||
return iface_id != 0;
|
||||
return iface_id_ != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,14 +182,22 @@ public:
|
||||
* @return true iff this is a loopback device.
|
||||
*/
|
||||
bool is_loopback() const;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this interface is up.
|
||||
*
|
||||
* This is equivalent to getting the interface info and checking for the is_up
|
||||
* attribute.
|
||||
*/
|
||||
bool is_up() const;
|
||||
|
||||
/**
|
||||
* \brief Compares this interface for equality.
|
||||
*
|
||||
* \param rhs The interface being compared.
|
||||
*/
|
||||
bool operator==(const NetworkInterface &rhs) const {
|
||||
return iface_id == rhs.iface_id;
|
||||
bool operator==(const NetworkInterface& rhs) const {
|
||||
return iface_id_ == rhs.iface_id_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,13 +205,15 @@ public:
|
||||
*
|
||||
* \param rhs The interface being compared.
|
||||
*/
|
||||
bool operator!=(const NetworkInterface &rhs) const {
|
||||
bool operator!=(const NetworkInterface& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
private:
|
||||
id_type resolve_index(const char *name);
|
||||
id_type resolve_index(const char* name);
|
||||
|
||||
id_type iface_id;
|
||||
id_type iface_id_;
|
||||
};
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_NETWORK_INTERFACE_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,8 +33,10 @@
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "data_link_type.h"
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
@@ -57,7 +59,7 @@ class PDU;
|
||||
* UDP udp = get_packet();
|
||||
*
|
||||
* // Create the filter. We'll be expecting Ethernet packets.
|
||||
* OfflinePacketFilter filter("ip and port 80", DataLinkLayer<EthernetII>());
|
||||
* OfflinePacketFilter filter("ip and port 80", DataLinkType<EthernetII>());
|
||||
*
|
||||
* // We can use this directly over the inner PDU (assuming it has one)
|
||||
* // See the notes on the efficiency of doing it this way.
|
||||
@@ -74,7 +76,7 @@ class PDU;
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
class OfflinePacketFilter {
|
||||
class TINS_API OfflinePacketFilter {
|
||||
public:
|
||||
/**
|
||||
* Constructs an OfflinePacketFilter object.
|
||||
@@ -84,10 +86,10 @@ public:
|
||||
* \param snap_len The snapshot length to use.
|
||||
*/
|
||||
template<typename T>
|
||||
OfflinePacketFilter(const std::string& filter, const DataLinkType<T>& lt,
|
||||
unsigned int snap_len = 65535)
|
||||
: string_filter(filter)
|
||||
{
|
||||
OfflinePacketFilter(const std::string& filter,
|
||||
const DataLinkType<T>& lt,
|
||||
unsigned int snap_len = 65535)
|
||||
: string_filter_(filter) {
|
||||
init(filter, lt.get_type(), snap_len);
|
||||
}
|
||||
|
||||
@@ -148,9 +150,9 @@ private:
|
||||
unsigned int snap_len);
|
||||
|
||||
|
||||
pcap_t* handle;
|
||||
mutable bpf_program filter;
|
||||
std::string string_filter;
|
||||
pcap_t* handle_;
|
||||
mutable bpf_program filter_;
|
||||
std::string string_filter_;
|
||||
};
|
||||
} // Tins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,6 +39,7 @@
|
||||
* \namespace Tins
|
||||
*/
|
||||
namespace Tins {
|
||||
|
||||
template<typename WrappedType, typename TimestampType>
|
||||
class PacketWrapper;
|
||||
|
||||
@@ -101,20 +102,20 @@ public:
|
||||
* This is the timestamp in which the packet was taken out of the
|
||||
* network interface/pcap file.
|
||||
*/
|
||||
const Timestamp ×tamp() const {
|
||||
const Timestamp& timestamp() const {
|
||||
return ts_;
|
||||
}
|
||||
private:
|
||||
friend class BaseSniffer;
|
||||
friend class SnifferIterator;
|
||||
|
||||
PacketWrapper(pdu_type pdu, const Timestamp &ts)
|
||||
PacketWrapper(pdu_type pdu, const Timestamp& ts)
|
||||
: pdu_(pdu), ts_(ts) {}
|
||||
|
||||
PacketWrapper(const PacketWrapper&);
|
||||
PacketWrapper& operator=(const PacketWrapper&);
|
||||
void* operator new (size_t size);
|
||||
void operator delete (void *p);
|
||||
void operator delete (void* p);
|
||||
|
||||
pdu_type pdu_;
|
||||
timestamp_type ts_;
|
||||
@@ -149,8 +150,8 @@ public:
|
||||
*
|
||||
* The PDU* is cloned using PDU::clone.
|
||||
*/
|
||||
Packet(const PDU *apdu, const Timestamp &tstamp)
|
||||
: pdu_(apdu->clone()), ts(tstamp) { }
|
||||
Packet(const PDU* apdu, const Timestamp& tstamp)
|
||||
: pdu_(apdu->clone()), ts_(tstamp) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a PDU* and a Timestamp.
|
||||
@@ -160,8 +161,8 @@ public:
|
||||
* will be done automatically by the Packet when it goes out
|
||||
* of scope.
|
||||
*/
|
||||
Packet(PDU *apdu, const Timestamp &tstamp, own_pdu)
|
||||
: pdu_(apdu), ts(tstamp) { }
|
||||
Packet(PDU* apdu, const Timestamp& tstamp, own_pdu)
|
||||
: pdu_(apdu), ts_(tstamp) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a const PDU&.
|
||||
@@ -171,8 +172,8 @@ public:
|
||||
* This calls PDU::clone on the PDU parameter.
|
||||
*
|
||||
*/
|
||||
Packet(const PDU &rhs)
|
||||
: pdu_(rhs.clone()), ts(Timestamp::current_time()) { }
|
||||
Packet(const PDU& rhs)
|
||||
: pdu_(rhs.clone()), ts_(Timestamp::current_time()) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a RefPacket.
|
||||
@@ -180,21 +181,21 @@ public:
|
||||
* This calls PDU::clone on the RefPacket's PDU.
|
||||
*
|
||||
*/
|
||||
Packet(const RefPacket &pck)
|
||||
: pdu_(pck.pdu().clone()), ts(pck.timestamp()) { }
|
||||
Packet(const RefPacket& pck)
|
||||
: pdu_(pck.pdu().clone()), ts_(pck.timestamp()) { }
|
||||
|
||||
/**
|
||||
* \brief Constructs a Packet from a PtrPacket object.
|
||||
*/
|
||||
Packet(const PtrPacket &pck)
|
||||
: pdu_(pck.pdu()), ts(pck.timestamp()) { }
|
||||
Packet(const PtrPacket& pck)
|
||||
: pdu_(pck.pdu()), ts_(pck.timestamp()) { }
|
||||
|
||||
/**
|
||||
* \brief Copy constructor.
|
||||
*
|
||||
* This calls PDU::clone on the rhs's PDU* member.
|
||||
*/
|
||||
Packet(const Packet &rhs) : ts(rhs.timestamp()) {
|
||||
Packet(const Packet& rhs) : ts_(rhs.timestamp()) {
|
||||
pdu_ = rhs.pdu() ? rhs.pdu()->clone() : 0;
|
||||
}
|
||||
|
||||
@@ -203,20 +204,20 @@ public:
|
||||
*
|
||||
* This calls PDU::clone on the rhs's PDU* member.
|
||||
*/
|
||||
Packet& operator=(const Packet &rhs) {
|
||||
if(this != &rhs) {
|
||||
Packet& operator=(const Packet& rhs) {
|
||||
if (this != &rhs) {
|
||||
delete pdu_;
|
||||
ts = rhs.timestamp();
|
||||
ts_ = rhs.timestamp();
|
||||
pdu_ = rhs.pdu() ? rhs.pdu()->clone() : 0;
|
||||
}
|
||||
return *this;
|
||||
return* this;
|
||||
}
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* Move constructor.
|
||||
*/
|
||||
Packet(Packet &&rhs) TINS_NOEXCEPT : pdu_(rhs.pdu()), ts(rhs.timestamp()) {
|
||||
Packet(Packet &&rhs) TINS_NOEXCEPT : pdu_(rhs.pdu()), ts_(rhs.timestamp()) {
|
||||
rhs.pdu_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -224,11 +225,11 @@ public:
|
||||
* Move assignment operator.
|
||||
*/
|
||||
Packet& operator=(Packet &&rhs) TINS_NOEXCEPT {
|
||||
if(this != &rhs) {
|
||||
if (this != &rhs) {
|
||||
std::swap(pdu_, rhs.pdu_);
|
||||
ts = rhs.timestamp();
|
||||
ts_ = rhs.timestamp();
|
||||
}
|
||||
return *this;
|
||||
return* this;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -244,8 +245,8 @@ public:
|
||||
/**
|
||||
* Returns this Packet's timestamp.
|
||||
*/
|
||||
const Timestamp ×tamp() const {
|
||||
return ts;
|
||||
const Timestamp& timestamp() const {
|
||||
return ts_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,7 +254,7 @@ public:
|
||||
*
|
||||
* Caller <b>must not</b> delete the pointer. \sa Packet::release_pdu
|
||||
*/
|
||||
PDU *pdu() {
|
||||
PDU* pdu() {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
@@ -262,7 +263,7 @@ public:
|
||||
*
|
||||
* Caller <b>must not</b> delete the pointer. \sa Packet::release_pdu
|
||||
*/
|
||||
const PDU *pdu() const {
|
||||
const PDU* pdu() const {
|
||||
return pdu_;
|
||||
}
|
||||
|
||||
@@ -275,8 +276,8 @@ public:
|
||||
* when Packet's destructor is called, the stored pointer will be
|
||||
* deleted.
|
||||
*/
|
||||
PDU *release_pdu() {
|
||||
PDU *some_pdu = pdu_;
|
||||
PDU* release_pdu() {
|
||||
PDU* some_pdu = pdu_;
|
||||
pdu_ = 0;
|
||||
return some_pdu;
|
||||
}
|
||||
@@ -298,13 +299,13 @@ public:
|
||||
*
|
||||
* \param rhs The PDU to be appended.
|
||||
*/
|
||||
Packet &operator/=(const PDU &rhs) {
|
||||
Packet& operator/=(const PDU& rhs) {
|
||||
pdu_ /= rhs;
|
||||
return *this;
|
||||
return* this;
|
||||
}
|
||||
private:
|
||||
PDU *pdu_;
|
||||
Timestamp ts;
|
||||
PDU* pdu_;
|
||||
Timestamp ts_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,6 +36,10 @@
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include "config.h"
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
#include <pcap.h>
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
#include "network_interface.h"
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
@@ -44,361 +48,382 @@ struct timeval;
|
||||
struct sockaddr;
|
||||
|
||||
namespace Tins {
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \class PacketSender
|
||||
* \brief Sends packets through a network interface.
|
||||
*
|
||||
* This class allows sending packets through a network interface.
|
||||
* It can send basically two types of packets:
|
||||
*
|
||||
* - Those that contain a link layer PDU (EthernetII, SLL, etc). These
|
||||
* will be serialized and sent through an interface that has to be
|
||||
* specified. This can be done by providing it when you call
|
||||
* PacketSender::send, or set a default one using
|
||||
* PacketSender::default_interface.
|
||||
* - Those that don't contain a link layer PDU. In this case, the
|
||||
* kernel will be responsible for picking the appropriate network interface
|
||||
* based on the destination address.
|
||||
*
|
||||
* Sending packets can be done via PacketSender::send:
|
||||
*
|
||||
* \code
|
||||
* // Construct a packet which uses an EthernetII link layer.
|
||||
* EthernetII pkt1 = ...;
|
||||
*
|
||||
* // Construct a packet sender, which we'll use to send packets.
|
||||
* PacketSender sender;
|
||||
*
|
||||
* // Send it through interface eth0
|
||||
* sender.send(pkt1, "eth0");
|
||||
*
|
||||
* // Set the default interface to eth0
|
||||
* sender.default_interface("eth0");
|
||||
*
|
||||
* // This is now equivalent to the previous send.
|
||||
* sender.send(pkt1);
|
||||
*
|
||||
* // Construct a packet which has no link layer protocol.
|
||||
* IP ip = IP("192.168.0.1") / TCP(22, 928);
|
||||
*
|
||||
* // Here the kernel will figure out which interface to use and it will
|
||||
* // append the appropriate link layer protocol PDU. It will also perform
|
||||
* // the necessary ARP lookups in order to use the destination host's
|
||||
* // hardware address.
|
||||
* //
|
||||
* // libtins will find which is the appropriate source IP address to use.
|
||||
* // This will be done by the kernel as well, but it's required when
|
||||
* // calculating checksums.
|
||||
* sender.send(ip);
|
||||
* \endcode
|
||||
*
|
||||
* PacketSender also supports sending a packet and waiting for a response.
|
||||
* This can be done by using PacketSender::send_recv.
|
||||
*
|
||||
* This class opens sockets as it needs to, and closes them when the object
|
||||
* is destructed.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
* \sa PacketSender::send_recv
|
||||
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \class PacketSender
|
||||
* \brief Sends packets through a network interface.
|
||||
*
|
||||
* This class allows sending packets through a network interface.
|
||||
* It can send basically two types of packets:
|
||||
*
|
||||
* - Those that contain a link layer PDU (EthernetII, SLL, etc). These
|
||||
* will be serialized and sent through an interface that has to be
|
||||
* specified. This can be done by providing it when you call
|
||||
* PacketSender::send, or set a default one using
|
||||
* PacketSender::default_interface.
|
||||
* - Those that don't contain a link layer PDU. In this case, the
|
||||
* kernel will be responsible for picking the appropriate network interface
|
||||
* based on the destination address.
|
||||
*
|
||||
* \par Note for Windows users:
|
||||
* Sending layer 3 PDUs (without a link layer protocol) is very restricted
|
||||
* on Windows (<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx">link</a>).
|
||||
* Therefore it's recommended you always send packets which contain link layer PDUs.
|
||||
* This will use Winpcap's pcap_sendpacket to inject the packets.
|
||||
*
|
||||
* Sending packets can be done via PacketSender::send:
|
||||
*
|
||||
* \code
|
||||
* // Construct a packet which uses an EthernetII link layer.
|
||||
* EthernetII pkt1 = ...;
|
||||
*
|
||||
* // Construct a packet sender, which we'll use to send packets.
|
||||
* PacketSender sender;
|
||||
*
|
||||
* // Send it through interface eth0
|
||||
* sender.send(pkt1, "eth0");
|
||||
*
|
||||
* // Set the default interface to eth0
|
||||
* sender.default_interface("eth0");
|
||||
*
|
||||
* // This is now equivalent to the previous send.
|
||||
* sender.send(pkt1);
|
||||
*
|
||||
* // Construct a packet which has no link layer protocol.
|
||||
* IP ip = IP("192.168.0.1") / TCP(22, 928);
|
||||
*
|
||||
* // Here the kernel will figure out which interface to use and it will
|
||||
* // append the appropriate link layer protocol PDU. It will also perform
|
||||
* // the necessary ARP lookups in order to use the destination host's
|
||||
* // hardware address.
|
||||
* //
|
||||
* // libtins will find which is the appropriate source IP address to use.
|
||||
* // This will be done by the kernel as well, but it's required when
|
||||
* // calculating checksums.
|
||||
* sender.send(ip);
|
||||
* \endcode
|
||||
*
|
||||
* PacketSender also supports sending a packet and waiting for a response.
|
||||
* This can be done by using PacketSender::send_recv.
|
||||
*
|
||||
* This class opens sockets as it needs to, and closes them when the object
|
||||
* is destructed.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
* \sa PacketSender::send_recv
|
||||
*/
|
||||
class TINS_API PacketSender {
|
||||
public:
|
||||
/**
|
||||
* The default timeout for receive actions.
|
||||
*/
|
||||
class PacketSender {
|
||||
public:
|
||||
/**
|
||||
* The default timeout for receive actions.
|
||||
*/
|
||||
static const uint32_t DEFAULT_TIMEOUT;
|
||||
static const uint32_t DEFAULT_TIMEOUT;
|
||||
|
||||
/**
|
||||
* Flags to indicate the socket type.
|
||||
*/
|
||||
enum SocketType {
|
||||
ETHER_SOCKET,
|
||||
IP_TCP_SOCKET,
|
||||
IP_UDP_SOCKET,
|
||||
IP_RAW_SOCKET,
|
||||
ARP_SOCKET,
|
||||
ICMP_SOCKET,
|
||||
IPV6_SOCKET,
|
||||
SOCKETS_END
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Constructor for PacketSender objects.
|
||||
*
|
||||
* \param iface The default interface in which to send the packets.
|
||||
* \param recv_timeout The timeout which will be used when receiving responses.
|
||||
*/
|
||||
PacketSender(const NetworkInterface& iface = NetworkInterface(),
|
||||
uint32_t recv_timeout = DEFAULT_TIMEOUT,
|
||||
uint32_t usec = 0);
|
||||
|
||||
/**
|
||||
* Flags to indicate the socket type.
|
||||
*/
|
||||
enum SocketType {
|
||||
ETHER_SOCKET,
|
||||
IP_TCP_SOCKET,
|
||||
IP_UDP_SOCKET,
|
||||
IP_RAW_SOCKET,
|
||||
ARP_SOCKET,
|
||||
ICMP_SOCKET,
|
||||
IPV6_SOCKET,
|
||||
SOCKETS_END
|
||||
};
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Constructor for PacketSender objects.
|
||||
*
|
||||
* \param iface The default interface in which to send the packets.
|
||||
* \param recv_timeout The timeout which will be used when receiving responses.
|
||||
* \brief Move constructor.
|
||||
* \param rhs The sender to be moved.
|
||||
*/
|
||||
PacketSender(const NetworkInterface &iface = NetworkInterface(),
|
||||
uint32_t recv_timeout = DEFAULT_TIMEOUT, uint32_t usec = 0);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Move constructor.
|
||||
* \param rhs The sender to be moved.
|
||||
*/
|
||||
PacketSender(PacketSender &&rhs) TINS_NOEXCEPT {
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
* \param rhs The sender to be moved.
|
||||
*/
|
||||
PacketSender& operator=(PacketSender &&rhs) TINS_NOEXCEPT {
|
||||
_sockets = std::move(rhs._sockets);
|
||||
rhs._sockets = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
|
||||
#ifndef WIN32
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
_ether_socket = std::move(rhs._ether_socket);
|
||||
#else
|
||||
_ether_socket = rhs._ether_socket;
|
||||
rhs._ether_socket = INVALID_RAW_SOCKET;
|
||||
#endif
|
||||
#endif
|
||||
_types = rhs._types; // no move
|
||||
_timeout = rhs._timeout;
|
||||
_timeout_usec = rhs._timeout_usec;
|
||||
default_iface = rhs.default_iface;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief PacketSender destructor.
|
||||
*
|
||||
* This gracefully closes all open sockets.
|
||||
*/
|
||||
~PacketSender();
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \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
|
||||
|
||||
/**
|
||||
* \brief Opens a layer 3 socket, using the corresponding protocol
|
||||
* for the given flag.
|
||||
*
|
||||
* If this operation fails, then a socket_open_error will be thrown.
|
||||
* If the provided socket type is not valid, an invalid_socket_type
|
||||
* exception will be throw.
|
||||
*
|
||||
* \param type The type of socket which will be used to pick the protocol flag
|
||||
* for this socket.
|
||||
*/
|
||||
void open_l3_socket(SocketType type);
|
||||
|
||||
/**
|
||||
* \brief Closes the socket associated with the given flag.
|
||||
*
|
||||
* If the provided type is invalid, meaning no such open socket
|
||||
* exists, an invalid_socket_type exception is thrown.
|
||||
*
|
||||
* If any socket close errors are encountered, a socket_close_error
|
||||
* is thrown.
|
||||
*
|
||||
* \param type The type of the socket to be closed.
|
||||
*/
|
||||
void close_socket(SocketType type, const NetworkInterface &iface = NetworkInterface());
|
||||
|
||||
/**
|
||||
* \brief Sets the default interface.
|
||||
*
|
||||
* The interface will be used whenever PacketSender::send(PDU&)
|
||||
* is called.
|
||||
*/
|
||||
void default_interface(const NetworkInterface &iface);
|
||||
|
||||
/**
|
||||
* \brief Gets the default interface.
|
||||
*
|
||||
* \sa PacketSender::default_interface
|
||||
*/
|
||||
const NetworkInterface& default_interface() const;
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU.
|
||||
*
|
||||
* This method opens the appropriate socket, if it's not open yet,
|
||||
* and sends the PDU on the open socket.
|
||||
*
|
||||
* If any send error occurs, then a socket_write_error is thrown.
|
||||
*
|
||||
* If the PDU contains a link layer protocol, then default_interface
|
||||
* is used.
|
||||
*
|
||||
* \sa PacketSender::default_interface
|
||||
*
|
||||
* \param pdu The PDU to be sent.
|
||||
*/
|
||||
void send(PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
*
|
||||
* This overload takes a NetworkInterface. The packet is sent
|
||||
* through that interface if a link-layer PDU is present,
|
||||
* otherwise this call is equivalent to send(PDU&).
|
||||
*
|
||||
* The interface stored in the link layer PDU(if any), is restored
|
||||
* after this method ends.
|
||||
*
|
||||
* \param pdu The PDU to be sent.
|
||||
* \param iface The network interface to use.
|
||||
*/
|
||||
void send(PDU &pdu, const NetworkInterface &iface);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* This method is used to send PDUs and receive their response.
|
||||
* The packet is sent, and then a response is awaited.
|
||||
* PDU::matches_pdu is called on the packet sent in order to
|
||||
* check whether a packet received is a response.
|
||||
*
|
||||
* This will match every response to a packet. For example,
|
||||
* if you send a TCP packet, any response matching the same
|
||||
* IP addresses and ports will be taken as a response to it.
|
||||
* This also happens for other protocols, such as ARP, ICMP,
|
||||
* DHCP, DNS, IP, etc.
|
||||
*
|
||||
* If you send a packet and get an ICMP response indicating
|
||||
* an error (such as host unreachable, ttl exceeded, etc),
|
||||
* that packet will be considered a response.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
*/
|
||||
PDU *send_recv(PDU &pdu);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* Sends a packet and receives a response. This overload takes
|
||||
* a NetworkInterface.
|
||||
*
|
||||
* \sa PacketSender::send_recv(PDU&);
|
||||
* \param pdu The PDU to send.
|
||||
* \param iface The network interface in which to send and receive.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
*/
|
||||
PDU *send_recv(PDU &pdu, const NetworkInterface &iface);
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Receives a layer 2 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using
|
||||
* the corresponding flag, according to the given type of protocol, until
|
||||
* a match for the given PDU is received.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \return Returns the response PDU. If no response is received, then 0 is returned.
|
||||
*/
|
||||
PDU *recv_l2(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr,
|
||||
const NetworkInterface &iface = NetworkInterface());
|
||||
|
||||
/**
|
||||
* \brief Sends a level 2 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 2 PDU, using a raw socket, open
|
||||
* using the corresponding flag, according to the given type of
|
||||
* protocol.
|
||||
*
|
||||
* If any socket write error occurs, a socket_write_error is thrown.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \param link_addr The sockaddr struct which will be used to send the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
*/
|
||||
void send_l2(PDU &pdu, struct sockaddr* link_addr, uint32_t len_addr,
|
||||
const NetworkInterface &iface = NetworkInterface());
|
||||
#endif // WIN32
|
||||
|
||||
/**
|
||||
* \brief Receives a layer 3 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol, until a match for the given PDU is received.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \param type The socket protocol type.
|
||||
* \return Returns the response PDU. If no response is received, then 0 is returned.
|
||||
*/
|
||||
PDU *recv_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
|
||||
|
||||
/**
|
||||
* \brief Sends a level 3 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol.
|
||||
*
|
||||
* If any socket write error occurs, a socket_write_error is thrown.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \param link_addr The sockaddr struct which will be used to send the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \param type The socket protocol type.
|
||||
*/
|
||||
void send_l3(PDU &pdu, struct sockaddr *link_addr, uint32_t len_addr, SocketType type);
|
||||
private:
|
||||
static const int INVALID_RAW_SOCKET;
|
||||
|
||||
typedef std::map<SocketType, int> SocketTypeMap;
|
||||
|
||||
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 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);
|
||||
PacketSender(PacketSender &&rhs) TINS_NOEXCEPT {
|
||||
*this = std::move(rhs);
|
||||
}
|
||||
|
||||
PDU *recv_match_loop(const std::vector<int>& sockets, PDU &pdu, struct sockaddr* link_addr,
|
||||
uint32_t addrlen);
|
||||
|
||||
std::vector<int> _sockets;
|
||||
#ifndef WIN32
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
typedef std::map<uint32_t, int> BSDEtherSockets;
|
||||
BSDEtherSockets _ether_socket;
|
||||
#else
|
||||
int _ether_socket;
|
||||
/**
|
||||
* \brief Move assignment operator.
|
||||
* \param rhs The sender to be moved.
|
||||
*/
|
||||
PacketSender& operator=(PacketSender &&rhs) TINS_NOEXCEPT {
|
||||
sockets_ = std::move(rhs.sockets_);
|
||||
rhs.sockets_ = std::vector<int>(SOCKETS_END, INVALID_RAW_SOCKET);
|
||||
#ifndef _WIN32
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
ether_socket_ = std::move(rhs.ether_socket_);
|
||||
#else
|
||||
ether_socket_ = rhs.ether_socket_;
|
||||
rhs.ether_socket_ = INVALID_RAW_SOCKET;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
SocketTypeMap _types;
|
||||
uint32_t _timeout, _timeout_usec;
|
||||
NetworkInterface default_iface;
|
||||
// In BSD we need to store the buffer size, retrieved using BIOCGBLEN
|
||||
types_ = rhs.types_; // no move
|
||||
_timeout = rhs._timeout;
|
||||
timeout_usec_ = rhs.timeout_usec_;
|
||||
default_iface_ = rhs.default_iface_;
|
||||
return* this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief PacketSender destructor.
|
||||
*
|
||||
* This gracefully closes all open sockets.
|
||||
*/
|
||||
~PacketSender();
|
||||
|
||||
#if !defined(_WIN32) || defined(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)
|
||||
|
||||
/**
|
||||
* \brief Opens a layer 3 socket, using the corresponding protocol
|
||||
* for the given flag.
|
||||
*
|
||||
* If this operation fails, then a socket_open_error will be thrown.
|
||||
* If the provided socket type is not valid, an invalid_socket_type
|
||||
* exception will be throw.
|
||||
*
|
||||
* \param type The type of socket which will be used to pick the protocol flag
|
||||
* for this socket.
|
||||
*/
|
||||
void open_l3_socket(SocketType type);
|
||||
|
||||
/**
|
||||
* \brief Closes the socket associated with the given flag.
|
||||
*
|
||||
* If the provided type is invalid, meaning no such open socket
|
||||
* exists, an invalid_socket_type exception is thrown.
|
||||
*
|
||||
* If any socket close errors are encountered, a socket_close_error
|
||||
* is thrown.
|
||||
*
|
||||
* \param type The type of the socket to be closed.
|
||||
*/
|
||||
void close_socket(SocketType type, const NetworkInterface& iface = NetworkInterface());
|
||||
|
||||
/**
|
||||
* \brief Sets the default interface.
|
||||
*
|
||||
* The interface will be used whenever PacketSender::send(PDU&)
|
||||
* is called.
|
||||
*/
|
||||
void default_interface(const NetworkInterface& iface);
|
||||
|
||||
/**
|
||||
* \brief Gets the default interface.
|
||||
*
|
||||
* \sa PacketSender::default_interface
|
||||
*/
|
||||
const NetworkInterface& default_interface() const;
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU.
|
||||
*
|
||||
* This method opens the appropriate socket, if it's not open yet,
|
||||
* and sends the PDU on the open socket.
|
||||
*
|
||||
* If any send error occurs, then a socket_write_error is thrown.
|
||||
*
|
||||
* If the PDU contains a link layer protocol, then default_interface
|
||||
* is used.
|
||||
*
|
||||
* \sa PacketSender::default_interface
|
||||
*
|
||||
* \param pdu The PDU to be sent.
|
||||
*/
|
||||
void send(PDU& pdu);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU.
|
||||
*
|
||||
* \sa PacketSender::send
|
||||
*
|
||||
* This overload takes a NetworkInterface. The packet is sent
|
||||
* through that interface if a link-layer PDU is present,
|
||||
* otherwise this call is equivalent to send(PDU&).
|
||||
*
|
||||
* The interface stored in the link layer PDU(if any), is restored
|
||||
* after this method ends.
|
||||
*
|
||||
* \param pdu The PDU to be sent.
|
||||
* \param iface The network interface to use.
|
||||
*/
|
||||
void send(PDU& pdu, const NetworkInterface& iface);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* This method is used to send PDUs and receive their response.
|
||||
* The packet is sent, and then a response is awaited.
|
||||
* PDU::matches_pdu is called on the packet sent in order to
|
||||
* check whether a packet received is a response.
|
||||
*
|
||||
* This will match every response to a packet. For example,
|
||||
* if you send a TCP packet, any response matching the same
|
||||
* IP addresses and ports will be taken as a response to it.
|
||||
* This also happens for other protocols, such as ARP, ICMP,
|
||||
* DHCP, DNS, IP, etc.
|
||||
*
|
||||
* If you send a packet and get an ICMP response indicating
|
||||
* an error (such as host unreachable, ttl exceeded, etc),
|
||||
* that packet will be considered a response.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
*/
|
||||
PDU* send_recv(PDU& pdu);
|
||||
|
||||
/**
|
||||
* \brief Sends a PDU and waits for its response.
|
||||
*
|
||||
* Sends a packet and receives a response. This overload takes
|
||||
* a NetworkInterface.
|
||||
*
|
||||
* \sa PacketSender::send_recv(PDU&);
|
||||
* \param pdu The PDU to send.
|
||||
* \param iface The network interface in which to send and receive.
|
||||
* \return Returns the response PDU, 0 if not response was received.
|
||||
*/
|
||||
PDU* send_recv(PDU& pdu, const NetworkInterface& iface);
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \brief Receives a layer 2 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using
|
||||
* the corresponding flag, according to the given type of protocol, until
|
||||
* a match for the given PDU is received.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \return Returns the response PDU. If no response is received, then 0 is returned.
|
||||
*/
|
||||
PDU* recv_l2(PDU& pdu, struct sockaddr* link_addr, uint32_t len_addr,
|
||||
const NetworkInterface& iface = NetworkInterface());
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#if !defined(_WIN32) || defined(HAVE_PACKET_SENDER_PCAP_SENDPACKET)
|
||||
/**
|
||||
* \brief Sends a level 2 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 2 PDU, using a raw socket, open
|
||||
* using the corresponding flag, according to the given type of
|
||||
* protocol.
|
||||
*
|
||||
* If any socket write error occurs, a socket_write_error is thrown.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \param link_addr The sockaddr struct which will be used to send the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
*/
|
||||
void send_l2(PDU& pdu, struct sockaddr* link_addr, uint32_t len_addr,
|
||||
const NetworkInterface& iface = NetworkInterface());
|
||||
#endif // !_WIN32 || HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
/**
|
||||
* \brief Receives a layer 3 PDU response to a previously sent PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send_recv.
|
||||
*
|
||||
* This PacketSender will receive data from a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol, until a match for the given PDU is received.
|
||||
*
|
||||
* \param pdu The PDU which will try to match the responses.
|
||||
* \param link_addr The sockaddr struct which will be used to receive the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \param type The socket protocol type.
|
||||
* \return Returns the response PDU. If no response is received, then 0 is returned.
|
||||
*/
|
||||
PDU* recv_l3(PDU& pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type);
|
||||
|
||||
/**
|
||||
* \brief Sends a level 3 PDU.
|
||||
*
|
||||
* This method is used internally. You should just use PacketSender::send.
|
||||
*
|
||||
* This method sends a layer 3 PDU, using a raw socket, open using the corresponding flag,
|
||||
* according to the given type of protocol.
|
||||
*
|
||||
* If any socket write error occurs, a socket_write_error is thrown.
|
||||
*
|
||||
* \param pdu The PDU to send.
|
||||
* \param link_addr The sockaddr struct which will be used to send the PDU.
|
||||
* \param len_addr The sockaddr struct length.
|
||||
* \param type The socket protocol type.
|
||||
*/
|
||||
void send_l3(PDU& pdu, struct sockaddr* link_addr, uint32_t len_addr, SocketType type);
|
||||
private:
|
||||
static const int INVALID_RAW_SOCKET;
|
||||
|
||||
typedef std::map<SocketType, int> SocketTypeMap;
|
||||
|
||||
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());
|
||||
#endif
|
||||
template<typename T>
|
||||
void send(PDU& pdu, const NetworkInterface& iface) {
|
||||
static_cast<T&>(pdu).send(*this, iface);
|
||||
}
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
pcap_t* make_pcap_handle(const NetworkInterface& iface) const;
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
PDU* recv_match_loop(const std::vector<int>& sockets,
|
||||
PDU& pdu,
|
||||
struct sockaddr* link_addr,
|
||||
uint32_t addrlen);
|
||||
|
||||
std::vector<int> sockets_;
|
||||
#ifndef _WIN32
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
int buffer_size;
|
||||
typedef std::map<uint32_t, int> BSDEtherSockets;
|
||||
BSDEtherSockets ether_socket_;
|
||||
#else
|
||||
int ether_socket_;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
#endif
|
||||
SocketTypeMap types_;
|
||||
uint32_t _timeout, timeout_usec_;
|
||||
NetworkInterface default_iface_;
|
||||
// In BSD we need to store the buffer size, retrieved using BIOCGBLEN
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
int buffer_size_;
|
||||
#endif // BSD
|
||||
#ifdef HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
typedef std::map<NetworkInterface, pcap_t*> PcapHandleMap;
|
||||
PcapHandleMap pcap_handles_;
|
||||
#endif // HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_PACKET_SENDER_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,15 +30,19 @@
|
||||
#ifndef TINS_PACKET_WRITER_H
|
||||
#define TINS_PACKET_WRITER_H
|
||||
|
||||
#include "utils.h"
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <pcap.h>
|
||||
#include "data_link_type.h"
|
||||
#include "utils.h"
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
struct timeval;
|
||||
|
||||
namespace Tins {
|
||||
class PDU;
|
||||
class Packet;
|
||||
|
||||
/**
|
||||
* \class PacketWriter
|
||||
@@ -72,7 +76,7 @@ class PDU;
|
||||
* writer.write(vt.begin(), vt.end());
|
||||
* \endcode
|
||||
*/
|
||||
class PacketWriter {
|
||||
class TINS_API PacketWriter {
|
||||
public:
|
||||
/**
|
||||
* \brief The type of PDUs that will be written to this file (deprecated).
|
||||
@@ -111,8 +115,7 @@ public:
|
||||
* \sa PcapIdentifier.
|
||||
*/
|
||||
template<typename T>
|
||||
PacketWriter(const std::string &file_name, const DataLinkType<T>& lt)
|
||||
{
|
||||
PacketWriter(const std::string& file_name, const DataLinkType<T>& lt) {
|
||||
init(file_name, lt.get_type());
|
||||
}
|
||||
|
||||
@@ -126,7 +129,7 @@ public:
|
||||
* \param lt The link type which will be written to this file.
|
||||
* \sa LinkType.
|
||||
*/
|
||||
PacketWriter(const std::string &file_name, LinkType lt);
|
||||
PacketWriter(const std::string& file_name, LinkType lt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
@@ -150,11 +153,11 @@ public:
|
||||
* \param rhs The PacketWriter to be moved.
|
||||
*/
|
||||
PacketWriter& operator=(PacketWriter &&rhs) TINS_NOEXCEPT {
|
||||
handle = 0;
|
||||
dumper = 0;
|
||||
std::swap(handle, rhs.handle);
|
||||
std::swap(dumper, rhs.dumper);
|
||||
return *this;
|
||||
handle_ = 0;
|
||||
dumper_ = 0;
|
||||
std::swap(handle_, rhs.handle_);
|
||||
std::swap(dumper_, rhs.dumper_);
|
||||
return* this;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -167,8 +170,19 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Writes a PDU to this file.
|
||||
* \param pdu The PDU to be written.
|
||||
*/
|
||||
void write(PDU &pdu);
|
||||
void write(PDU& pdu);
|
||||
|
||||
/**
|
||||
* \brief Writes a Packet to this file.
|
||||
*
|
||||
* The timestamp used on the entry for this packet will be the Timestamp
|
||||
* object associated with this packet.
|
||||
*
|
||||
* \param packet The packet to be written.
|
||||
*/
|
||||
void write(Packet& packet);
|
||||
|
||||
/**
|
||||
* \brief Writes a PDU to this file.
|
||||
@@ -178,7 +192,7 @@ public:
|
||||
* raw and smart pointers.
|
||||
*/
|
||||
template<typename T>
|
||||
void write(T &pdu) {
|
||||
void write(T& pdu) {
|
||||
write(Utils::dereference_until_pdu(pdu));
|
||||
}
|
||||
|
||||
@@ -191,8 +205,9 @@ public:
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
void write(ForwardIterator start, ForwardIterator end) {
|
||||
while(start != end)
|
||||
while (start != end) {
|
||||
write(Utils::dereference_until_pdu(*start++));
|
||||
}
|
||||
}
|
||||
private:
|
||||
// You shall not copy
|
||||
@@ -200,9 +215,10 @@ private:
|
||||
PacketWriter& operator=(const PacketWriter&);
|
||||
|
||||
void init(const std::string& file_name, int link_type);
|
||||
void write(PDU& pdu, const struct timeval& tv);
|
||||
|
||||
pcap_t *handle;
|
||||
pcap_dumper_t *dumper;
|
||||
pcap_t* handle_;
|
||||
pcap_dumper_t* dumper_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -45,9 +45,9 @@ class IP;
|
||||
class IPv6;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
template<typename PDUType>
|
||||
PDU *default_allocator(const uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
PDU* default_allocator(const uint8_t* buffer, uint32_t size) {
|
||||
return new PDUType(buffer, size);
|
||||
}
|
||||
|
||||
@@ -58,25 +58,21 @@ public:
|
||||
typedef PDU *(*allocator_type)(const uint8_t *, uint32_t);
|
||||
|
||||
template<typename PDUType>
|
||||
static void register_allocator(id_type identifier)
|
||||
{
|
||||
static void register_allocator(id_type identifier) {
|
||||
allocators[identifier] = &default_allocator<PDUType>;
|
||||
pdu_types[PDUType::pdu_flag] = identifier;
|
||||
}
|
||||
|
||||
static PDU *allocate(id_type identifier, const uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
static PDU* allocate(id_type identifier, const uint8_t* buffer, uint32_t size) {
|
||||
typename allocators_type::const_iterator it = allocators.find(identifier);
|
||||
return (it == allocators.end()) ? 0 : (*it->second)(buffer, size);
|
||||
}
|
||||
|
||||
static bool pdu_type_registered(PDU::PDUType type)
|
||||
{
|
||||
static bool pdu_type_registered(PDU::PDUType type) {
|
||||
return pdu_types.count(type) != 0;
|
||||
}
|
||||
|
||||
static id_type pdu_type_to_id(PDU::PDUType type)
|
||||
{
|
||||
static id_type pdu_type_to_id(PDU::PDUType type) {
|
||||
typename pdu_map_types::const_iterator it = pdu_types.find(type);
|
||||
return it->second;
|
||||
}
|
||||
@@ -118,26 +114,23 @@ TINS_GENERATE_TAG_MAPPER(IPv6, uint8_t)
|
||||
#undef TINS_GENERATE_TAG_MAPPER
|
||||
|
||||
template<typename PDUType>
|
||||
PDU* allocate(
|
||||
typename pdu_tag_mapper<PDUType>::type::identifier_type id,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
PDU* allocate(typename pdu_tag_mapper<PDUType>::type::identifier_type id,
|
||||
const uint8_t* buffer,
|
||||
uint32_t size) {
|
||||
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::allocate(id, buffer, size);
|
||||
}
|
||||
|
||||
template<typename PDUType>
|
||||
bool pdu_type_registered(PDU::PDUType type)
|
||||
{
|
||||
bool pdu_type_registered(PDU::PDUType type) {
|
||||
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_registered(type);
|
||||
}
|
||||
|
||||
template<typename PDUType>
|
||||
typename pdu_tag_mapper<PDUType>::type::identifier_type pdu_type_to_id(PDU::PDUType type)
|
||||
{
|
||||
typename pdu_tag_mapper<PDUType>::type::identifier_type pdu_type_to_id(PDU::PDUType type) {
|
||||
return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_to_id(type);
|
||||
}
|
||||
} // namespace Interals
|
||||
|
||||
} // Interals
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
@@ -170,13 +163,13 @@ namespace Allocators {
|
||||
* the same way.
|
||||
*/
|
||||
template<typename PDUType, typename AllocatedType>
|
||||
void register_allocator(typename Internals::pdu_tag_mapper<PDUType>::type::identifier_type id)
|
||||
{
|
||||
void register_allocator(typename Internals::pdu_tag_mapper<PDUType>::type::identifier_type id) {
|
||||
Internals::PDUAllocator<
|
||||
typename Internals::pdu_tag_mapper<PDUType>::type
|
||||
>::template register_allocator<AllocatedType>(id);
|
||||
}
|
||||
} // namespace Allocators
|
||||
} // namespace Tins
|
||||
|
||||
} // Allocators
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_PDU_ALLOCATOR_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -52,7 +52,7 @@ namespace Tins {
|
||||
* serialized, such as performing checksums, iterate and copy options,
|
||||
* etc.
|
||||
*/
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
class PDUCacher : public PDU {
|
||||
public:
|
||||
/**
|
||||
@@ -68,14 +68,15 @@ public:
|
||||
/**
|
||||
* Default constructs the cached PDU.
|
||||
*/
|
||||
PDUCacher() : cached_size() {}
|
||||
PDUCacher()
|
||||
: cached_size_() {}
|
||||
|
||||
/**
|
||||
* Constructor from a cached_type.
|
||||
* \param pdu The PDU to be copy constructed.
|
||||
*/
|
||||
PDUCacher(const cached_type &pdu) : cached(pdu),
|
||||
cached_size() {}
|
||||
PDUCacher(const cached_type& pdu)
|
||||
: cached_(pdu), cached_size_() {}
|
||||
|
||||
/**
|
||||
* Forwards the call to the cached PDU.
|
||||
@@ -83,9 +84,10 @@ public:
|
||||
* \sa PDU::header_size.
|
||||
*/
|
||||
uint32_t header_size() const {
|
||||
if(cached_serialization.empty())
|
||||
cached_size = cached.size();
|
||||
return cached_size;
|
||||
if (cached_serialization_.empty()) {
|
||||
cached_size_ = cached_.size();
|
||||
}
|
||||
return cached_size_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +95,7 @@ public:
|
||||
*
|
||||
* \sa PDU::clone.
|
||||
*/
|
||||
PDUCacher *clone() const {
|
||||
PDUCacher* clone() const {
|
||||
return new PDUCacher<T>(*this);
|
||||
}
|
||||
|
||||
@@ -102,8 +104,8 @@ public:
|
||||
*
|
||||
* \sa PDU::send.
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface) {
|
||||
cached.send(sender, iface);
|
||||
void send(PacketSender& sender, const NetworkInterface& iface) {
|
||||
cached_.send(sender, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,8 +113,8 @@ public:
|
||||
*
|
||||
* \sa PDU::recv_responde.
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface) {
|
||||
return cached.recv_response(sender, iface);
|
||||
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface) {
|
||||
return cached_.recv_response(sender, iface);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,8 +122,8 @@ public:
|
||||
*
|
||||
* \sa PDU::matches_response.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
return cached.matches_response(ptr, total_sz);
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
||||
return cached_.matches_response(ptr, total_sz);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +132,7 @@ public:
|
||||
* \sa PDU::matches_flag.
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return cached.matches_flag(flag);
|
||||
return cached_.matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,19 +141,19 @@ public:
|
||||
* \sa PDU::pdu_type.
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return cached.pdu_type();
|
||||
return cached_.pdu_type();
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
if(cached_serialization.size() != total_sz) {
|
||||
cached_serialization = cached.serialize();
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent) {
|
||||
if (cached_serialization_.size() != total_sz) {
|
||||
cached_serialization_ = cached_.serialize();
|
||||
}
|
||||
std::copy(cached_serialization.begin(), cached_serialization.end(), buffer);
|
||||
std::copy(cached_serialization_.begin(), cached_serialization_.end(), buffer);
|
||||
}
|
||||
|
||||
cached_type cached;
|
||||
PDU::serialization_type cached_serialization;
|
||||
mutable uint32_t cached_size;
|
||||
cached_type cached_;
|
||||
PDU::serialization_type cached_serialization_;
|
||||
mutable uint32_t cached_size_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
#include "exceptions.h"
|
||||
#include "endianness.h"
|
||||
@@ -47,37 +48,41 @@ namespace Tins {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
template<typename OptionType, class PDUType>
|
||||
template <typename OptionType, typename PDUType>
|
||||
class PDUOption;
|
||||
|
||||
namespace Internals {
|
||||
template<typename T, typename X, typename PDUType>
|
||||
template <typename T, typename X, typename PDUType>
|
||||
T convert_to_integral(const PDUOption<X, PDUType> & opt) {
|
||||
if(opt.data_size() != sizeof(T))
|
||||
if (opt.data_size() != sizeof(T)) {
|
||||
throw malformed_option();
|
||||
}
|
||||
T data = *(T*)opt.data_ptr();
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
if (PDUType::endianness == PDUType::BE) {
|
||||
data = Endian::be_to_host(data);
|
||||
else
|
||||
}
|
||||
else {
|
||||
data = Endian::le_to_host(data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
template<typename T, typename = void>
|
||||
template <typename T, typename = void>
|
||||
struct converter {
|
||||
template<typename X, typename PDUType>
|
||||
template <typename X, typename PDUType>
|
||||
static T convert(const PDUOption<X, PDUType>& opt) {
|
||||
return T::from_option(opt);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct converter<uint8_t> {
|
||||
template<typename X, typename PDUType>
|
||||
template <typename X, typename PDUType>
|
||||
static uint8_t convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != 1)
|
||||
if (opt.data_size() != 1) {
|
||||
throw malformed_option();
|
||||
return *opt.data_ptr();
|
||||
}
|
||||
return* opt.data_ptr();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,8 +114,9 @@ namespace Internals {
|
||||
struct converter<HWAddress<n> > {
|
||||
template<typename X, typename PDUType>
|
||||
static HWAddress<n> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != n)
|
||||
if (opt.data_size() != n) {
|
||||
throw malformed_option();
|
||||
}
|
||||
return HWAddress<n>(opt.data_ptr());
|
||||
}
|
||||
};
|
||||
@@ -119,13 +125,16 @@ namespace Internals {
|
||||
struct converter<IPv4Address> {
|
||||
template<typename X, typename PDUType>
|
||||
static IPv4Address convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != sizeof(uint32_t))
|
||||
if (opt.data_size() != sizeof(uint32_t)) {
|
||||
throw malformed_option();
|
||||
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
}
|
||||
const uint32_t* ptr = (const uint32_t*)opt.data_ptr();
|
||||
if (PDUType::endianness == PDUType::BE) {
|
||||
return IPv4Address(*ptr);
|
||||
else
|
||||
}
|
||||
else {
|
||||
return IPv4Address(Endian::change_endian(*ptr));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -133,8 +142,9 @@ namespace Internals {
|
||||
struct converter<IPv6Address> {
|
||||
template<typename X, typename PDUType>
|
||||
static IPv6Address convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != IPv6Address::address_size)
|
||||
if (opt.data_size() != IPv6Address::address_size) {
|
||||
throw malformed_option();
|
||||
}
|
||||
return IPv6Address(opt.data_ptr());
|
||||
}
|
||||
};
|
||||
@@ -155,8 +165,8 @@ namespace Internals {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<float> convert(const PDUOption<X, PDUType>& opt) {
|
||||
std::vector<float> output;
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||
while(ptr != end) {
|
||||
const uint8_t* ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||
while (ptr != end) {
|
||||
output.push_back(float(*(ptr++) & 0x7f) / 2);
|
||||
}
|
||||
return output;
|
||||
@@ -167,18 +177,21 @@ namespace Internals {
|
||||
struct converter<std::vector<T>, typename enable_if<is_unsigned_integral<T>::value>::type> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<T> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % sizeof(T) != 0)
|
||||
if (opt.data_size() % sizeof(T) != 0) {
|
||||
throw malformed_option();
|
||||
const T *ptr = (const T*)opt.data_ptr();
|
||||
const T *end = (const T*)(opt.data_ptr() + opt.data_size());
|
||||
}
|
||||
const T* ptr = (const T*)opt.data_ptr();
|
||||
const T* end = (const T*)(opt.data_ptr() + opt.data_size());
|
||||
|
||||
std::vector<T> output(std::distance(ptr, end));
|
||||
typename std::vector<T>::iterator it = output.begin();
|
||||
while(ptr < end) {
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
while (ptr < end) {
|
||||
if (PDUType::endianness == PDUType::BE) {
|
||||
*it++ = Endian::be_to_host(*ptr++);
|
||||
else
|
||||
}
|
||||
else {
|
||||
*it++ = Endian::le_to_host(*ptr++);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -193,18 +206,19 @@ namespace Internals {
|
||||
> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<std::pair<T, U> > convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % (sizeof(T) + sizeof(U)) != 0)
|
||||
if (opt.data_size() % (sizeof(T) + sizeof(U)) != 0) {
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||
}
|
||||
const uint8_t* ptr = opt.data_ptr(), *end = ptr + opt.data_size();
|
||||
|
||||
std::vector<std::pair<T, U> > output;
|
||||
while(ptr < end) {
|
||||
while (ptr < end) {
|
||||
std::pair<T, U> data;
|
||||
data.first = *(const T*)ptr;
|
||||
ptr += sizeof(T);
|
||||
data.second = *(const U*)ptr;
|
||||
ptr += sizeof(U);
|
||||
if(PDUType::endianness == PDUType::BE) {
|
||||
if (PDUType::endianness == PDUType::BE) {
|
||||
data.first = Endian::be_to_host(data.first);
|
||||
data.second = Endian::be_to_host(data.second);
|
||||
}
|
||||
@@ -222,18 +236,21 @@ namespace Internals {
|
||||
struct converter<std::vector<IPv4Address> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<IPv4Address> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % 4 != 0)
|
||||
if (opt.data_size() % 4 != 0) {
|
||||
throw malformed_option();
|
||||
const uint32_t *ptr = (const uint32_t*)opt.data_ptr();
|
||||
const uint32_t *end = (const uint32_t*)(opt.data_ptr() + opt.data_size());
|
||||
}
|
||||
const uint32_t* ptr = (const uint32_t*)opt.data_ptr();
|
||||
const uint32_t* end = (const uint32_t*)(opt.data_ptr() + opt.data_size());
|
||||
|
||||
std::vector<IPv4Address> output(std::distance(ptr, end));
|
||||
std::vector<IPv4Address>::iterator it = output.begin();
|
||||
while(ptr < end) {
|
||||
if(PDUType::endianness == PDUType::BE)
|
||||
while (ptr < end) {
|
||||
if (PDUType::endianness == PDUType::BE) {
|
||||
*it++ = IPv4Address(*ptr++);
|
||||
else
|
||||
}
|
||||
else {
|
||||
*it++ = IPv4Address(Endian::change_endian(*ptr++));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -243,11 +260,12 @@ namespace Internals {
|
||||
struct converter<std::vector<IPv6Address> > {
|
||||
template<typename X, typename PDUType>
|
||||
static std::vector<IPv6Address> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() % IPv6Address::address_size != 0)
|
||||
if (opt.data_size() % IPv6Address::address_size != 0) {
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
|
||||
}
|
||||
const uint8_t* ptr = opt.data_ptr(), *end = opt.data_ptr() + opt.data_size();
|
||||
std::vector<IPv6Address> output;
|
||||
while(ptr < end) {
|
||||
while (ptr < end) {
|
||||
output.push_back(IPv6Address(ptr));
|
||||
ptr += IPv6Address::address_size;
|
||||
}
|
||||
@@ -264,12 +282,13 @@ namespace Internals {
|
||||
> {
|
||||
template<typename X, typename PDUType>
|
||||
static std::pair<T, U> convert(const PDUOption<X, PDUType>& opt) {
|
||||
if(opt.data_size() != sizeof(T) + sizeof(U))
|
||||
if (opt.data_size() != sizeof(T) + sizeof(U)) {
|
||||
throw malformed_option();
|
||||
}
|
||||
std::pair<T, U> output;
|
||||
std::memcpy(&output.first, opt.data_ptr(), sizeof(T));
|
||||
std::memcpy(&output.second, opt.data_ptr() + sizeof(T), sizeof(U));
|
||||
if(PDUType::endianness == PDUType::BE) {
|
||||
if (PDUType::endianness == PDUType::BE) {
|
||||
output.first = Endian::be_to_host(output.first);
|
||||
output.second = Endian::be_to_host(output.second);
|
||||
}
|
||||
@@ -297,7 +316,7 @@ namespace Internals {
|
||||
* The OptionType template parameter indicates the type that will be
|
||||
* used to store this option's identifier.
|
||||
*/
|
||||
template<typename OptionType, class PDUType>
|
||||
template <typename OptionType, typename PDUType>
|
||||
class PDUOption {
|
||||
private:
|
||||
static const int small_buffer_size = 8;
|
||||
@@ -311,8 +330,10 @@ public:
|
||||
* \param length The option's data length.
|
||||
* \param data The option's data(if any).
|
||||
*/
|
||||
PDUOption(option_type opt = option_type(), size_t length = 0, const data_type *data = 0)
|
||||
: option_(opt), size_(length) {
|
||||
PDUOption(option_type opt = option_type(),
|
||||
size_t length = 0,
|
||||
const data_type* data = 0)
|
||||
: option_(opt), size_(static_cast<uint16_t>(length)) {
|
||||
set_payload_contents(data, data + (data ? length : 0));
|
||||
}
|
||||
|
||||
@@ -342,11 +363,11 @@ public:
|
||||
PDUOption& operator=(PDUOption&& rhs) {
|
||||
option_ = rhs.option_;
|
||||
size_ = rhs.size_;
|
||||
if(real_size_ > small_buffer_size) {
|
||||
if (real_size_ > small_buffer_size) {
|
||||
delete[] payload_.big_buffer_ptr;
|
||||
}
|
||||
real_size_ = rhs.real_size_;
|
||||
if(real_size_ > small_buffer_size) {
|
||||
if (real_size_ > small_buffer_size) {
|
||||
payload_.big_buffer_ptr = nullptr;
|
||||
std::swap(payload_.big_buffer_ptr, rhs.payload_.big_buffer_ptr);
|
||||
rhs.real_size_ = 0;
|
||||
@@ -358,7 +379,7 @@ public:
|
||||
payload_.small_buffer
|
||||
);
|
||||
}
|
||||
return *this;
|
||||
return* this;
|
||||
}
|
||||
|
||||
#endif // TINS_IS_CXX11
|
||||
@@ -370,19 +391,19 @@ public:
|
||||
PDUOption& operator=(const PDUOption& rhs) {
|
||||
option_ = rhs.option_;
|
||||
size_ = rhs.size_;
|
||||
if(real_size_ > small_buffer_size) {
|
||||
if (real_size_ > small_buffer_size) {
|
||||
delete[] payload_.big_buffer_ptr;
|
||||
}
|
||||
real_size_ = rhs.real_size_;
|
||||
set_payload_contents(rhs.data_ptr(), rhs.data_ptr() + rhs.data_size());
|
||||
return *this;
|
||||
return* this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Destructor.
|
||||
*/
|
||||
~PDUOption() {
|
||||
if(real_size_ > small_buffer_size) {
|
||||
if (real_size_ > small_buffer_size) {
|
||||
delete[] payload_.big_buffer_ptr;
|
||||
}
|
||||
}
|
||||
@@ -397,7 +418,7 @@ public:
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
PDUOption(option_type opt, ForwardIterator start, ForwardIterator end)
|
||||
: option_(opt), size_(std::distance(start, end)) {
|
||||
: option_(opt), size_(static_cast<uint16_t>(std::distance(start, end))) {
|
||||
set_payload_contents(start, end);
|
||||
}
|
||||
|
||||
@@ -417,7 +438,7 @@ public:
|
||||
* \param end The end of the option data.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
PDUOption(option_type opt, size_t length, ForwardIterator start, ForwardIterator end)
|
||||
PDUOption(option_type opt, uint16_t length, ForwardIterator start, ForwardIterator end)
|
||||
: option_(opt), size_(length) {
|
||||
set_payload_contents(start, end);
|
||||
}
|
||||
@@ -447,10 +468,10 @@ public:
|
||||
*
|
||||
* \return const data_type& containing this option's value.
|
||||
*/
|
||||
const data_type *data_ptr() const {
|
||||
const data_type* data_ptr() const {
|
||||
return real_size_ <= small_buffer_size ?
|
||||
payload_.small_buffer :
|
||||
payload_.big_buffer_ptr;
|
||||
payload_.small_buffer :
|
||||
payload_.big_buffer_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -492,8 +513,12 @@ public:
|
||||
private:
|
||||
template<typename ForwardIterator>
|
||||
void set_payload_contents(ForwardIterator start, ForwardIterator end) {
|
||||
real_size_ = std::distance(start, end);
|
||||
if(real_size_ <= small_buffer_size) {
|
||||
size_t total_size = std::distance(start, end);
|
||||
if (total_size > std::numeric_limits<uint16_t>::max()) {
|
||||
throw option_payload_too_large();
|
||||
}
|
||||
real_size_ = static_cast<uint16_t>(total_size);
|
||||
if (real_size_ <= small_buffer_size) {
|
||||
std::copy(
|
||||
start,
|
||||
end,
|
||||
@@ -502,11 +527,12 @@ private:
|
||||
}
|
||||
else {
|
||||
payload_.big_buffer_ptr = new data_type[real_size_];
|
||||
std::copy(
|
||||
start,
|
||||
end,
|
||||
payload_.big_buffer_ptr
|
||||
);
|
||||
uint8_t* ptr = payload_.big_buffer_ptr;
|
||||
while (start < end) {
|
||||
*ptr = *start;
|
||||
++ptr;
|
||||
++start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,5 +543,25 @@ private:
|
||||
data_type* big_buffer_ptr;
|
||||
} payload_;
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
/*
|
||||
* \cond
|
||||
*/
|
||||
template <typename Option>
|
||||
struct option_type_equality_comparator {
|
||||
option_type_equality_comparator(typename Option::option_type type) : type(type) { }
|
||||
|
||||
bool operator()(const Option& opt) const {
|
||||
return opt.option() == type;
|
||||
}
|
||||
|
||||
typename Option::option_type type;
|
||||
};
|
||||
/*
|
||||
* \endcond
|
||||
*/
|
||||
} // Internals
|
||||
|
||||
} // namespace Tins
|
||||
#endif // TINS_PDU_OPTION_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,10 +31,14 @@
|
||||
#define TINS_PKTAP_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class PKTAP : public PDU {
|
||||
/**
|
||||
* \brief Represents a PKTAP PDU
|
||||
*/
|
||||
class TINS_API PKTAP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -63,7 +67,9 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
@@ -76,7 +82,7 @@ public:
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
PKTAP *clone() const {
|
||||
PKTAP* clone() const {
|
||||
return new PKTAP(*this);
|
||||
}
|
||||
private:
|
||||
@@ -98,8 +104,7 @@ private:
|
||||
uint8_t ecommand[20];
|
||||
};
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
pktap_header header_;
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,10 +31,12 @@
|
||||
#define TINS_PPI_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class PPI
|
||||
* \brief Represents a Per-Packet Information PDU.
|
||||
@@ -43,7 +45,7 @@ namespace Tins {
|
||||
* cannot be serialized. Therefore, it is only useful while
|
||||
* sniffing packets.
|
||||
*/
|
||||
class PPI : public PDU {
|
||||
class TINS_API PPI : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -61,7 +63,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
PPI(const uint8_t *buffer, uint32_t total_sz);
|
||||
PPI(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -70,7 +72,7 @@ public:
|
||||
* \return The stored version field value.
|
||||
*/
|
||||
uint8_t version() const {
|
||||
return _header.version;
|
||||
return header_.version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +80,7 @@ public:
|
||||
* \return The stored flags field value.
|
||||
*/
|
||||
uint8_t flags() const {
|
||||
return _header.flags;
|
||||
return header_.flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +88,7 @@ public:
|
||||
* \return The stored length field value.
|
||||
*/
|
||||
uint16_t length() const {
|
||||
return Endian::le_to_host(_header.length);
|
||||
return Endian::le_to_host(header_.length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +96,7 @@ public:
|
||||
* \return The stored Data Link Type field value.
|
||||
*/
|
||||
uint32_t dlt() const {
|
||||
return Endian::le_to_host(_header.dlt);
|
||||
return Endian::le_to_host(header_.dlt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,27 +110,30 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
PPI *clone() const {
|
||||
PPI* clone() const {
|
||||
return new PPI(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
|
||||
void parse_80211(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
struct header {
|
||||
struct ppi_header {
|
||||
uint8_t version, flags;
|
||||
uint16_t length;
|
||||
uint32_t dlt;
|
||||
};
|
||||
|
||||
header _header;
|
||||
byte_array _data;
|
||||
ppi_header header_;
|
||||
byte_array data_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "pdu_option.h"
|
||||
@@ -44,7 +45,7 @@ namespace Tins {
|
||||
* \class PPPoE
|
||||
* \brief Represents a Point-to-point protocol over Ethernet PDU.
|
||||
*/
|
||||
class PPPoE : public PDU {
|
||||
class TINS_API PPPoE : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The tag types enum.
|
||||
@@ -58,7 +59,7 @@ public:
|
||||
AC_COOKIE = 0x401,
|
||||
VENDOR_SPECIFIC = 0x501,
|
||||
RELAY_SESSION_ID = 0x101,
|
||||
SERVICE_NAME_ERROR = 0x201,
|
||||
SERVICE_NAME_ERROR = 0x102,
|
||||
AC_SYSTEM_ERROR = 0x202,
|
||||
GENERIC_ERROR = 0x302
|
||||
#else
|
||||
@@ -92,10 +93,10 @@ public:
|
||||
uint32_t vendor_id;
|
||||
data_type data;
|
||||
|
||||
vendor_spec_type(uint32_t vendor_id = 0, const data_type &data = data_type())
|
||||
vendor_spec_type(uint32_t vendor_id = 0, const data_type& data = data_type())
|
||||
: vendor_id(vendor_id), data(data) { }
|
||||
|
||||
static vendor_spec_type from_option(const tag &opt);
|
||||
static vendor_spec_type from_option(const tag& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -119,7 +120,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
PPPoE(const uint8_t *buffer, uint32_t total_sz);
|
||||
PPPoE(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -128,7 +129,7 @@ public:
|
||||
* \return The stored version field value.
|
||||
*/
|
||||
small_uint<4> version() const {
|
||||
return _header.version;
|
||||
return header_.version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +137,7 @@ public:
|
||||
* \return The stored type field value.
|
||||
*/
|
||||
small_uint<4> type() const {
|
||||
return _header.type;
|
||||
return header_.type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,7 +145,7 @@ public:
|
||||
* \return The stored code field value.
|
||||
*/
|
||||
uint8_t code() const {
|
||||
return _header.code;
|
||||
return header_.code;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,7 +153,7 @@ public:
|
||||
* \return The stored session_id field value.
|
||||
*/
|
||||
uint16_t session_id() const {
|
||||
return Endian::be_to_host(_header.session_id);
|
||||
return Endian::be_to_host(header_.session_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,7 +161,7 @@ public:
|
||||
* \return The stored payload_length field value.
|
||||
*/
|
||||
uint16_t payload_length() const {
|
||||
return Endian::be_to_host(_header.payload_length);
|
||||
return Endian::be_to_host(header_.payload_length);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,18 +174,18 @@ public:
|
||||
/**
|
||||
* \brief Returns the list of tags.
|
||||
*/
|
||||
const tags_type &tags() const {
|
||||
return _tags;
|
||||
const tags_type& tags() const {
|
||||
return tags_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
PPPoE *clone() const {
|
||||
PPPoE* clone() const {
|
||||
return new PPPoE(*this);
|
||||
}
|
||||
|
||||
const tag *search_tag(TagTypes identifier) const;
|
||||
const tag* search_tag(TagTypes identifier) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
@@ -229,7 +230,7 @@ public:
|
||||
*
|
||||
* \param option The option to be added.
|
||||
*/
|
||||
void add_tag(const tag &option);
|
||||
void add_tag(const tag& option);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
@@ -240,8 +241,8 @@ public:
|
||||
* \param option The option to be added.
|
||||
*/
|
||||
void add_tag(tag &&option) {
|
||||
_tags_size += option.data_size() + sizeof(uint16_t) * 2;
|
||||
_tags.push_back(std::move(option));
|
||||
tags_size_ += static_cast<uint16_t>(option.data_size() + sizeof(uint16_t) * 2);
|
||||
tags_.push_back(std::move(option));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -257,63 +258,63 @@ public:
|
||||
*
|
||||
* \param value The service name.
|
||||
*/
|
||||
void service_name(const std::string &value);
|
||||
void service_name(const std::string& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a AC-name tag.
|
||||
*
|
||||
* \param value The AC name.
|
||||
*/
|
||||
void ac_name(const std::string &value);
|
||||
void ac_name(const std::string& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a host-uniq tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void host_uniq(const byte_array &value);
|
||||
void host_uniq(const byte_array& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a AC-Cookie tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void ac_cookie(const byte_array &value);
|
||||
void ac_cookie(const byte_array& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Vendor-Specific tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void vendor_specific(const vendor_spec_type &value);
|
||||
void vendor_specific(const vendor_spec_type& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Relay-Session-Id tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void relay_session_id(const byte_array &value);
|
||||
void relay_session_id(const byte_array& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Service-Name-Error tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void service_name_error(const std::string &value);
|
||||
void service_name_error(const std::string& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a AC-System-Error tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void ac_system_error(const std::string &value);
|
||||
void ac_system_error(const std::string& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Generic-Error tag.
|
||||
*
|
||||
* \param value The tag's value.
|
||||
*/
|
||||
void generic_error(const std::string &value);
|
||||
void generic_error(const std::string& value);
|
||||
|
||||
// Option getters
|
||||
|
||||
@@ -389,10 +390,10 @@ public:
|
||||
*/
|
||||
std::string generic_error() const;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
template<typename T>
|
||||
void add_tag_iterable(TagTypes id, const T &data) {
|
||||
void add_tag_iterable(TagTypes id, const T& data) {
|
||||
add_tag(
|
||||
tag(
|
||||
id,
|
||||
@@ -404,14 +405,15 @@ private:
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(TagTypes id) const {
|
||||
const tag *t = search_tag(id);
|
||||
if(!t)
|
||||
const tag* t = search_tag(id);
|
||||
if (!t) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return t->to<T>();
|
||||
}
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct pppoe_hdr {
|
||||
struct pppoe_header {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t version:4,
|
||||
type:4;
|
||||
@@ -425,9 +427,9 @@ private:
|
||||
uint16_t payload_length;
|
||||
} TINS_END_PACK;
|
||||
|
||||
pppoe_hdr _header;
|
||||
tags_type _tags;
|
||||
uint16_t _tags_size;
|
||||
pppoe_header header_;
|
||||
tags_type tags_;
|
||||
uint16_t tags_size_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -37,478 +37,480 @@
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins {
|
||||
class PacketSender;
|
||||
|
||||
/**
|
||||
* \brief Class that represents the IEEE 802.11 radio tap header.
|
||||
*
|
||||
* By default, RadioTap PDUs set the necesary fields to send an 802.11
|
||||
* PDU as its inner pdu, avoiding packet drops. As a consequence,
|
||||
* the FCS-at-end flag is on, the channel is set to 1, TSFT is set to 0,
|
||||
* dbm_signal is set to 0xce, and the rx_flag and antenna fields to 0.
|
||||
class PacketSender;
|
||||
|
||||
/**
|
||||
* \brief Class that represents the IEEE 802.11 radio tap header.
|
||||
*
|
||||
* By default, RadioTap PDUs set the necesary fields to send an 802.11
|
||||
* PDU as its inner pdu, avoiding packet drops. As a consequence,
|
||||
* the FCS-at-end flag is on, the channel is set to 1, TSFT is set to 0,
|
||||
* dbm_signal is set to -50, and the rx_flag and antenna fields to 0.
|
||||
*/
|
||||
class TINS_API RadioTap : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class RadioTap : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RADIOTAP;
|
||||
|
||||
/**
|
||||
* \brief Enumeration of the different channel type flags.
|
||||
*
|
||||
* These channel type flags can be OR'd and set using the
|
||||
* RadioTap::channel() method.
|
||||
*/
|
||||
enum ChannelType {
|
||||
TURBO = 0x10,
|
||||
CCK = 0x20,
|
||||
OFDM = 0x40,
|
||||
TWO_GZ = 0x80,
|
||||
FIVE_GZ = 0x100,
|
||||
PASSIVE = 0x200,
|
||||
DYN_CCK_OFDM = 0x400,
|
||||
GFSK = 0x800
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Flags used in the present field.
|
||||
*
|
||||
* \sa RadioTap::present()
|
||||
*/
|
||||
enum PresentFlags {
|
||||
TSTF = 1 << 0,
|
||||
FLAGS = 1 << 1,
|
||||
RATE = 1 << 2,
|
||||
CHANNEL = 1 << 3,
|
||||
FHSS = 1 << 4,
|
||||
DBM_SIGNAL = 1 << 5,
|
||||
DBM_NOISE = 1 << 6,
|
||||
LOCK_QUALITY = 1 << 7,
|
||||
TX_ATTENUATION = 1 << 8,
|
||||
DB_TX_ATTENUATION = 1 << 9,
|
||||
DBM_TX_ATTENUATION = 1 << 10,
|
||||
ANTENNA = 1 << 11,
|
||||
DB_SIGNAL = 1 << 12,
|
||||
DB_NOISE = 1 << 13,
|
||||
RX_FLAGS = 1 << 14,
|
||||
TX_FLAGS = 1 << 15,
|
||||
DATA_RETRIES = 1 << 17,
|
||||
CHANNEL_PLUS = 1 << 18,
|
||||
MCS = 1 << 19
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Flags used in the RadioTap::flags() method.
|
||||
*/
|
||||
enum FrameFlags {
|
||||
CFP = 1,
|
||||
PREAMBLE = 2,
|
||||
WEP = 4,
|
||||
FRAGMENTATION = 8,
|
||||
FCS = 16,
|
||||
PADDING = 32,
|
||||
FAILED_FCS = 64,
|
||||
SHORT_GI = 128
|
||||
};
|
||||
static const PDU::PDUType pdu_flag = PDU::RADIOTAP;
|
||||
|
||||
/**
|
||||
* \brief The type used to represent the MCS flags field
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct mcs_type {
|
||||
uint8_t known;
|
||||
uint8_t flags;
|
||||
uint8_t mcs;
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
RadioTap();
|
||||
|
||||
/**
|
||||
* \brief Constructs a RadioTap object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If there is not enough size for a RadioTap header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
RadioTap(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field.
|
||||
* \param new_version The new version.
|
||||
*/
|
||||
void version(uint8_t new_version);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param new_padding The new padding.
|
||||
*/
|
||||
void padding(uint8_t new_padding);
|
||||
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
* \param new_length The new length.
|
||||
*/
|
||||
void length(uint16_t new_length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the TSFT field.
|
||||
* \param new_tsft The new TSFT
|
||||
*/
|
||||
void tsft(uint64_t new_tsft);
|
||||
|
||||
/**
|
||||
* \brief Setter for the flags field.
|
||||
* \param new_flags The new flags.
|
||||
*/
|
||||
void flags(FrameFlags new_flags);
|
||||
|
||||
/**
|
||||
* \brief Setter for the rate field.
|
||||
* \param new_rate The new rate.
|
||||
*/
|
||||
void rate(uint8_t new_rate);
|
||||
|
||||
/**
|
||||
* \brief Setter for the channel frequency and type field.
|
||||
* \param new_freq The new channel frequency.
|
||||
* \param new_type The new channel type.
|
||||
*/
|
||||
void channel(uint16_t new_freq, uint16_t new_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dbm signal field.
|
||||
* \param new_dbm_signal The new dbm signal.
|
||||
*/
|
||||
void dbm_signal(int8_t new_dbm_signal);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dbm noise field.
|
||||
* \param new_dbm_noise The new dbm noise.
|
||||
*/
|
||||
void dbm_noise(int8_t new_dbm_noise);
|
||||
|
||||
/**
|
||||
* \brief Setter for the signal quality field.
|
||||
* \param new_antenna The signal quality signal.
|
||||
*/
|
||||
void signal_quality(uint8_t new_signal_quality);
|
||||
|
||||
/**
|
||||
* \brief Setter for the antenna field.
|
||||
* \param new_antenna The antenna signal.
|
||||
*/
|
||||
void antenna(uint8_t new_antenna);
|
||||
|
||||
/**
|
||||
* \brief Setter for the db signal field.
|
||||
* \param new_antenna The db signal signal.
|
||||
*/
|
||||
void db_signal(uint8_t new_db_signal);
|
||||
|
||||
/**
|
||||
* \brief Setter for the rx flag field.
|
||||
* \param new_rx_flag The rx flags.
|
||||
*/
|
||||
void rx_flags(uint16_t new_rx_flag);
|
||||
|
||||
/**
|
||||
* \brief Setter for the tx flag field.
|
||||
* \param new_tx_flag The tx flags.
|
||||
*/
|
||||
void tx_flags(uint16_t new_tx_flag);
|
||||
|
||||
/**
|
||||
* \brief Setter for the data retries field.
|
||||
* \param new_rx_flag The data retries.
|
||||
*/
|
||||
void data_retries(uint8_t new_data_retries);
|
||||
|
||||
/**
|
||||
* \brief Setter for the MCS field.
|
||||
* \param new_rx_flag The MCS retries.
|
||||
*/
|
||||
void mcs(const mcs_type& new_mcs);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint8_t version() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the padding field.
|
||||
* \return The padding field.
|
||||
*/
|
||||
uint8_t padding() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
uint16_t length() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the tsft field.
|
||||
* \return The tsft field.
|
||||
*/
|
||||
uint64_t tsft() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the flags field.
|
||||
* \return The flags field.
|
||||
*/
|
||||
FrameFlags flags() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the rate field.
|
||||
* \return The rate field.
|
||||
*/
|
||||
uint8_t rate() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel frequency field.
|
||||
* \return The channel frequency field.
|
||||
*/
|
||||
uint16_t channel_freq() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel type field.
|
||||
* \return The channel type field.
|
||||
*/
|
||||
uint16_t channel_type() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the dbm signal field.
|
||||
* \return The dbm signal field.
|
||||
*/
|
||||
int8_t dbm_signal() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the dbm noise field.
|
||||
* \return The dbm noise field.
|
||||
*/
|
||||
int8_t dbm_noise() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the signal quality field.
|
||||
* \return The signal quality field.
|
||||
*/
|
||||
uint16_t signal_quality() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the antenna field.
|
||||
* \return The antenna field.
|
||||
*/
|
||||
uint8_t antenna() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the db signal field.
|
||||
* \return The db signal field.
|
||||
*/
|
||||
uint8_t db_signal() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel+ field.
|
||||
* \return The channel+ field.
|
||||
*/
|
||||
uint32_t channel_plus() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the data retries field
|
||||
* \return The data retries field.
|
||||
*/
|
||||
uint8_t data_retries() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the rx flags field.
|
||||
* \return The rx flags field.
|
||||
*/
|
||||
uint16_t rx_flags() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the tx flags field.
|
||||
* \return The tx flags field.
|
||||
*/
|
||||
uint16_t tx_flags() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the MCS field.
|
||||
* \return The MCS field.
|
||||
*/
|
||||
mcs_type mcs() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the present bit fields.
|
||||
*
|
||||
* Use this method and masks created from the values taken from
|
||||
* the PresentFlags enum to find out which fields are set.
|
||||
* Accessing non-initialized fields, the behaviour is undefined
|
||||
* will be undefined. It is only safe to use the getter of a field
|
||||
* if its corresponding bit flag is set in the present field.
|
||||
*/
|
||||
PresentFlags present() const {
|
||||
//return (PresentFlags)*(uint32_t*)(&_radio.it_len + 1);
|
||||
return (PresentFlags)Endian::le_to_host(_radio.flags_32);
|
||||
}
|
||||
|
||||
/** \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Returns the RadioTap frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the frame's trailer size.
|
||||
* \return The trailer's size.
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RadioTap *clone() const {
|
||||
return new RadioTap(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::RADIOTAP; }
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
struct flags_type {
|
||||
uint32_t
|
||||
tsft:1,
|
||||
flags:1,
|
||||
rate:1,
|
||||
channel:1,
|
||||
fhss:1,
|
||||
dbm_signal:1,
|
||||
dbm_noise:1,
|
||||
lock_quality:1,
|
||||
|
||||
tx_attenuation:1,
|
||||
db_tx_attenuation:1,
|
||||
dbm_tx_power:1,
|
||||
antenna:1,
|
||||
db_signal:1,
|
||||
db_noise:1,
|
||||
rx_flags:1,
|
||||
tx_flags:1,
|
||||
|
||||
reserved1:1,
|
||||
data_retries:1,
|
||||
channel_plus:1,
|
||||
mcs:1,
|
||||
reserved2:4,
|
||||
|
||||
reserved3:7,
|
||||
ext:1;
|
||||
} TINS_END_PACK;
|
||||
#else
|
||||
struct flags_type {
|
||||
uint32_t
|
||||
lock_quality:1,
|
||||
dbm_noise:1,
|
||||
dbm_signal:1,
|
||||
fhss:1,
|
||||
channel:1,
|
||||
rate:1,
|
||||
flags:1,
|
||||
tsft:1,
|
||||
|
||||
tx_flags:1,
|
||||
rx_flags:1,
|
||||
db_noise:1,
|
||||
db_signal:1,
|
||||
antenna:1,
|
||||
dbm_tx_power:1,
|
||||
db_tx_attenuation:1,
|
||||
tx_attenuation:1,
|
||||
|
||||
reserved2:4,
|
||||
mcs:1,
|
||||
channel_plus:1,
|
||||
data_retries:1,
|
||||
reserved1:1,
|
||||
|
||||
ext:1,
|
||||
reserved3:7;
|
||||
} TINS_END_PACK;
|
||||
#endif
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct radiotap_hdr {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t it_version;
|
||||
uint8_t it_pad;
|
||||
#else
|
||||
uint8_t it_pad;
|
||||
uint8_t it_version;
|
||||
#endif // TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t it_len;
|
||||
union {
|
||||
flags_type flags;
|
||||
uint32_t flags_32;
|
||||
};
|
||||
} TINS_END_PACK;
|
||||
|
||||
void init();
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
uint32_t find_extra_flag_fields_size(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
template <size_t n>
|
||||
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t& size) {
|
||||
uint32_t offset = ((buffer - buffer_start) % n);
|
||||
if(offset) {
|
||||
offset = n - offset;
|
||||
if (offset > size) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
buffer += offset;
|
||||
size -= offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
radiotap_hdr _radio;
|
||||
// present fields...
|
||||
uint64_t _tsft;
|
||||
uint16_t _channel_type, _channel_freq, _rx_flags, _signal_quality, _tx_flags;
|
||||
mcs_type _mcs;
|
||||
uint8_t _antenna, _flags, _rate, _channel, _max_power, _db_signal, _data_retries;
|
||||
int8_t _dbm_signal, _dbm_noise;
|
||||
/**
|
||||
* \brief Enumeration of the different channel type flags.
|
||||
*
|
||||
* These channel type flags can be OR'd and set using the
|
||||
* RadioTap::channel() method.
|
||||
*/
|
||||
enum ChannelType {
|
||||
TURBO = 0x10,
|
||||
CCK = 0x20,
|
||||
OFDM = 0x40,
|
||||
TWO_GZ = 0x80,
|
||||
FIVE_GZ = 0x100,
|
||||
PASSIVE = 0x200,
|
||||
DYN_CCK_OFDM = 0x400,
|
||||
GFSK = 0x800
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Flags used in the present field.
|
||||
*
|
||||
* \sa RadioTap::present()
|
||||
*/
|
||||
enum PresentFlags {
|
||||
TSTF = 1 << 0,
|
||||
FLAGS = 1 << 1,
|
||||
RATE = 1 << 2,
|
||||
CHANNEL = 1 << 3,
|
||||
FHSS = 1 << 4,
|
||||
DBM_SIGNAL = 1 << 5,
|
||||
DBM_NOISE = 1 << 6,
|
||||
LOCK_QUALITY = 1 << 7,
|
||||
TX_ATTENUATION = 1 << 8,
|
||||
DB_TX_ATTENUATION = 1 << 9,
|
||||
DBM_TX_ATTENUATION = 1 << 10,
|
||||
ANTENNA = 1 << 11,
|
||||
DB_SIGNAL = 1 << 12,
|
||||
DB_NOISE = 1 << 13,
|
||||
RX_FLAGS = 1 << 14,
|
||||
TX_FLAGS = 1 << 15,
|
||||
DATA_RETRIES = 1 << 17,
|
||||
CHANNEL_PLUS = 1 << 18,
|
||||
MCS = 1 << 19
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Flags used in the RadioTap::flags() method.
|
||||
*/
|
||||
enum FrameFlags {
|
||||
CFP = 1,
|
||||
PREAMBLE = 2,
|
||||
WEP = 4,
|
||||
FRAGMENTATION = 8,
|
||||
FCS = 16,
|
||||
PADDING = 32,
|
||||
FAILED_FCS = 64,
|
||||
SHORT_GI = 128
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief The type used to represent the MCS flags field
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct mcs_type {
|
||||
uint8_t known;
|
||||
uint8_t flags;
|
||||
uint8_t mcs;
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
RadioTap();
|
||||
|
||||
/**
|
||||
* \brief Constructs a RadioTap object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If there is not enough size for a RadioTap header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
RadioTap(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field.
|
||||
* \param new_version The new version.
|
||||
*/
|
||||
void version(uint8_t new_version);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param new_padding The new padding.
|
||||
*/
|
||||
void padding(uint8_t new_padding);
|
||||
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
* \param new_length The new length.
|
||||
*/
|
||||
void length(uint16_t new_length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the TSFT field.
|
||||
* \param new_tsft The new TSFT
|
||||
*/
|
||||
void tsft(uint64_t new_tsft);
|
||||
|
||||
/**
|
||||
* \brief Setter for the flags field.
|
||||
* \param new_flags The new flags.
|
||||
*/
|
||||
void flags(FrameFlags new_flags);
|
||||
|
||||
/**
|
||||
* \brief Setter for the rate field.
|
||||
* \param new_rate The new rate.
|
||||
*/
|
||||
void rate(uint8_t new_rate);
|
||||
|
||||
/**
|
||||
* \brief Setter for the channel frequency and type field.
|
||||
* \param new_freq The new channel frequency.
|
||||
* \param new_type The new channel type.
|
||||
*/
|
||||
void channel(uint16_t new_freq, uint16_t new_type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dbm signal field.
|
||||
* \param new_dbm_signal The new dbm signal.
|
||||
*/
|
||||
void dbm_signal(int8_t new_dbm_signal);
|
||||
|
||||
/**
|
||||
* \brief Setter for the dbm noise field.
|
||||
* \param new_dbm_noise The new dbm noise.
|
||||
*/
|
||||
void dbm_noise(int8_t new_dbm_noise);
|
||||
|
||||
/**
|
||||
* \brief Setter for the signal quality field.
|
||||
* \param new_antenna The signal quality signal.
|
||||
*/
|
||||
void signal_quality(uint8_t new_signal_quality);
|
||||
|
||||
/**
|
||||
* \brief Setter for the antenna field.
|
||||
* \param new_antenna The antenna signal.
|
||||
*/
|
||||
void antenna(uint8_t new_antenna);
|
||||
|
||||
/**
|
||||
* \brief Setter for the db signal field.
|
||||
* \param new_antenna The db signal signal.
|
||||
*/
|
||||
void db_signal(uint8_t new_db_signal);
|
||||
|
||||
/**
|
||||
* \brief Setter for the rx flag field.
|
||||
* \param new_rx_flag The rx flags.
|
||||
*/
|
||||
void rx_flags(uint16_t new_rx_flag);
|
||||
|
||||
/**
|
||||
* \brief Setter for the tx flag field.
|
||||
* \param new_tx_flag The tx flags.
|
||||
*/
|
||||
void tx_flags(uint16_t new_tx_flag);
|
||||
|
||||
/**
|
||||
* \brief Setter for the data retries field.
|
||||
* \param new_rx_flag The data retries.
|
||||
*/
|
||||
void data_retries(uint8_t new_data_retries);
|
||||
|
||||
/**
|
||||
* \brief Setter for the MCS field.
|
||||
* \param new_rx_flag The MCS retries.
|
||||
*/
|
||||
void mcs(const mcs_type& new_mcs);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint8_t version() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the padding field.
|
||||
* \return The padding field.
|
||||
*/
|
||||
uint8_t padding() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
uint16_t length() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the tsft field.
|
||||
* \return The tsft field.
|
||||
*/
|
||||
uint64_t tsft() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the flags field.
|
||||
* \return The flags field.
|
||||
*/
|
||||
FrameFlags flags() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the rate field.
|
||||
* \return The rate field.
|
||||
*/
|
||||
uint8_t rate() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel frequency field.
|
||||
* \return The channel frequency field.
|
||||
*/
|
||||
uint16_t channel_freq() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel type field.
|
||||
* \return The channel type field.
|
||||
*/
|
||||
uint16_t channel_type() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the dbm signal field.
|
||||
* \return The dbm signal field.
|
||||
*/
|
||||
int8_t dbm_signal() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the dbm noise field.
|
||||
* \return The dbm noise field.
|
||||
*/
|
||||
int8_t dbm_noise() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the signal quality field.
|
||||
* \return The signal quality field.
|
||||
*/
|
||||
uint16_t signal_quality() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the antenna field.
|
||||
* \return The antenna field.
|
||||
*/
|
||||
uint8_t antenna() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the db signal field.
|
||||
* \return The db signal field.
|
||||
*/
|
||||
uint8_t db_signal() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel+ field.
|
||||
* \return The channel+ field.
|
||||
*/
|
||||
uint32_t channel_plus() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the data retries field
|
||||
* \return The data retries field.
|
||||
*/
|
||||
uint8_t data_retries() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the rx flags field.
|
||||
* \return The rx flags field.
|
||||
*/
|
||||
uint16_t rx_flags() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the tx flags field.
|
||||
* \return The tx flags field.
|
||||
*/
|
||||
uint16_t tx_flags() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the MCS field.
|
||||
* \return The MCS field.
|
||||
*/
|
||||
mcs_type mcs() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the present bit fields.
|
||||
*
|
||||
* Use this method and masks created from the values taken from
|
||||
* the PresentFlags enum to find out which fields are set.
|
||||
* Accessing non-initialized fields, the behaviour is undefined
|
||||
* will be undefined. It is only safe to use the getter of a field
|
||||
* if its corresponding bit flag is set in the present field.
|
||||
*/
|
||||
PresentFlags present() const {
|
||||
//return (PresentFlags)*(uint32_t*)(&radio_.it_len + 1);
|
||||
return (PresentFlags)Endian::le_to_host(radio_.flags_32);
|
||||
}
|
||||
|
||||
/** \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Returns the RadioTap frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the frame's trailer size.
|
||||
* \return The trailer's size.
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RadioTap* clone() const {
|
||||
return new RadioTap(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
struct flags_type {
|
||||
uint32_t
|
||||
tsft:1,
|
||||
flags:1,
|
||||
rate:1,
|
||||
channel:1,
|
||||
fhss:1,
|
||||
dbm_signal:1,
|
||||
dbm_noise:1,
|
||||
lock_quality:1,
|
||||
|
||||
tx_attenuation:1,
|
||||
db_tx_attenuation:1,
|
||||
dbm_tx_power:1,
|
||||
antenna:1,
|
||||
db_signal:1,
|
||||
db_noise:1,
|
||||
rx_flags:1,
|
||||
tx_flags:1,
|
||||
|
||||
reserved1:1,
|
||||
data_retries:1,
|
||||
channel_plus:1,
|
||||
mcs:1,
|
||||
reserved2:4,
|
||||
|
||||
reserved3:7,
|
||||
ext:1;
|
||||
} TINS_END_PACK;
|
||||
#else
|
||||
struct flags_type {
|
||||
uint32_t
|
||||
lock_quality:1,
|
||||
dbm_noise:1,
|
||||
dbm_signal:1,
|
||||
fhss:1,
|
||||
channel:1,
|
||||
rate:1,
|
||||
flags:1,
|
||||
tsft:1,
|
||||
|
||||
tx_flags:1,
|
||||
rx_flags:1,
|
||||
db_noise:1,
|
||||
db_signal:1,
|
||||
antenna:1,
|
||||
dbm_tx_power:1,
|
||||
db_tx_attenuation:1,
|
||||
tx_attenuation:1,
|
||||
|
||||
reserved2:4,
|
||||
mcs:1,
|
||||
channel_plus:1,
|
||||
data_retries:1,
|
||||
reserved1:1,
|
||||
|
||||
ext:1,
|
||||
reserved3:7;
|
||||
} TINS_END_PACK;
|
||||
#endif
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct radiotap_hdr {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint8_t it_version;
|
||||
uint8_t it_pad;
|
||||
#else
|
||||
uint8_t it_pad;
|
||||
uint8_t it_version;
|
||||
#endif // TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t it_len;
|
||||
union {
|
||||
flags_type flags;
|
||||
uint32_t flags_32;
|
||||
};
|
||||
} TINS_END_PACK;
|
||||
|
||||
void init();
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
uint32_t find_extra_flag_fields_size(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
template <size_t n>
|
||||
void align_buffer(const uint8_t* buffer_start, const uint8_t*& buffer, uint32_t& size) {
|
||||
uint32_t offset = ((buffer - buffer_start) % n);
|
||||
if (offset) {
|
||||
offset = n - offset;
|
||||
if (offset > size) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
buffer += offset;
|
||||
size -= offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
radiotap_hdr radio_;
|
||||
// present fields...
|
||||
uint64_t tsft_;
|
||||
uint16_t channel_type_, channel_freq_, rx_flags_, signal_quality_, tx_flags_;
|
||||
mcs_type mcs_;
|
||||
uint8_t antenna_, flags_, rate_, channel_, max_power_, db_signal_, data_retries_;
|
||||
int8_t dbm_signal_, dbm_noise_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // TINS_RADIOTAP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,172 +33,179 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "cxxstd.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class PDU
|
||||
* \brief Represents a PDU which holds raw data.
|
||||
*
|
||||
* This class is a wrapper over a byte array. It can be used to hold
|
||||
* the payload sent over transport layer protocols (such as TCP or UDP).
|
||||
*
|
||||
* While sniffing, this class is the one that will hold transport layer
|
||||
* protocols' payload. You can simply convert a RawPDU into a specific
|
||||
* application layer protocol using the RawPDU::to method:
|
||||
*
|
||||
* \code
|
||||
* // Get a RawPDU from somewhere
|
||||
* RawPDU raw = get_raw_pdu();
|
||||
*
|
||||
* // Parse it as a DHCP PDU.
|
||||
* DHCP dhcp = raw.to<DHCP>();
|
||||
*
|
||||
* // Or parse it as DNS. Of course this will fail if the contents
|
||||
* // don't look like DNS
|
||||
* DNS dns = raw.to<DNS>();
|
||||
* \endcode
|
||||
/**
|
||||
* \class PDU
|
||||
* \brief Represents a PDU which holds raw data.
|
||||
*
|
||||
* This class is a wrapper over a byte array. It can be used to hold
|
||||
* the payload sent over transport layer protocols (such as TCP or UDP).
|
||||
*
|
||||
* While sniffing, this class is the one that will hold transport layer
|
||||
* protocols' payload. You can simply convert a RawPDU into a specific
|
||||
* application layer protocol using the RawPDU::to method:
|
||||
*
|
||||
* \code
|
||||
* // Get a RawPDU from somewhere
|
||||
* RawPDU raw = get_raw_pdu();
|
||||
*
|
||||
* // Parse it as a DHCP PDU.
|
||||
* DHCP dhcp = raw.to<DHCP>();
|
||||
*
|
||||
* // Or parse it as DNS. Of course this will fail if the contents
|
||||
* // don't look like DNS
|
||||
* DNS dns = raw.to<DNS>();
|
||||
* \endcode
|
||||
*/
|
||||
class TINS_API RawPDU : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the payload.
|
||||
*/
|
||||
class RawPDU : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the payload.
|
||||
*/
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RAW;
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU.
|
||||
*
|
||||
* The payload is copied, therefore the original payload's memory
|
||||
* must be freed by the user.
|
||||
* \param pload The payload which the RawPDU will contain.
|
||||
* \param size The size of the payload.
|
||||
*/
|
||||
RawPDU(const uint8_t *pload, uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief Constructs a RawPDU from an iterator range.
|
||||
*
|
||||
* The data in the iterator range is copied into the RawPDU
|
||||
* internal buffer.
|
||||
*
|
||||
* \param start The beginning of the iterator range.
|
||||
* \param end The end of the iterator range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RawPDU(ForwardIterator start, ForwardIterator end)
|
||||
: _payload(start, end) { }
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::RAW;
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU from a payload_type.
|
||||
*
|
||||
* The payload is moved into the RawPDU's internal buffer.
|
||||
*
|
||||
* \param data The payload to use.
|
||||
*/
|
||||
RawPDU(payload_type&& data)
|
||||
: _payload(move(data)) { }
|
||||
#endif // TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU.
|
||||
*
|
||||
* The payload is copied, therefore the original payload's memory
|
||||
* must be freed by the user.
|
||||
* \param pload The payload which the RawPDU will contain.
|
||||
* \param size The size of the payload.
|
||||
*/
|
||||
RawPDU(const uint8_t* pload, uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief Constructs a RawPDU from an iterator range.
|
||||
*
|
||||
* The data in the iterator range is copied into the RawPDU
|
||||
* internal buffer.
|
||||
*
|
||||
* \param start The beginning of the iterator range.
|
||||
* \param end The end of the iterator range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RawPDU(ForwardIterator start, ForwardIterator end)
|
||||
: payload_(start, end) { }
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU from an input string.
|
||||
* \brief Creates an instance of RawPDU from a payload_type.
|
||||
*
|
||||
* The payload is moved into the RawPDU's internal buffer.
|
||||
*
|
||||
* \param data The content of the payload.
|
||||
* \param data The payload to use.
|
||||
*/
|
||||
RawPDU(const std::string &data);
|
||||
RawPDU(payload_type&& data)
|
||||
: payload_(move(data)) { }
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
* \param pload The payload to be set.
|
||||
*/
|
||||
void payload(const payload_type &pload);
|
||||
/**
|
||||
* \brief Creates an instance of RawPDU from an input string.
|
||||
*
|
||||
* \param data The content of the payload.
|
||||
*/
|
||||
RawPDU(const std::string& data);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
* \param start The start of the new payload.
|
||||
* \param end The end of the new payload.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
void payload(ForwardIterator start, ForwardIterator end) {
|
||||
_payload.assign(start, end);
|
||||
}
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
* \param pload The payload to be set.
|
||||
*/
|
||||
void payload(const payload_type& pload);
|
||||
|
||||
/**
|
||||
* \brief Const getter for the payload.
|
||||
* \return The RawPDU's payload.
|
||||
*/
|
||||
const payload_type &payload() const { return _payload; }
|
||||
|
||||
/**
|
||||
* \brief Non-const getter for the payload.
|
||||
* \return The RawPDU's payload.
|
||||
*/
|
||||
payload_type &payload() { return _payload; }
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This returns the same as RawPDU::payload_size().
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the payload size.
|
||||
*
|
||||
* \return uint32_t containing the payload size.
|
||||
*/
|
||||
uint32_t payload_size() const {
|
||||
return _payload.size();
|
||||
}
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
* \param start The start of the new payload.
|
||||
* \param end The end of the new payload.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
void payload(ForwardIterator start, ForwardIterator end) {
|
||||
payload_.assign(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This always returns true, since we don't know what this
|
||||
* RawPDU is holding.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
/**
|
||||
* \brief Const getter for the payload.
|
||||
* \return The RawPDU's payload.
|
||||
*/
|
||||
const payload_type& payload() const {
|
||||
return payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Non-const getter for the payload.
|
||||
* \return The RawPDU's payload.
|
||||
*/
|
||||
payload_type& payload() {
|
||||
return payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This returns the same as RawPDU::payload_size().
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the payload size.
|
||||
*
|
||||
* \return uint32_t containing the payload size.
|
||||
*/
|
||||
uint32_t payload_size() const {
|
||||
return static_cast<uint32_t>(payload_.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::RAW; }
|
||||
|
||||
/**
|
||||
* \brief Constructs the given PDU type from the raw data stored
|
||||
* in this RawPDU.
|
||||
*/
|
||||
template<typename T>
|
||||
T to() const {
|
||||
return T(&_payload[0], _payload.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RawPDU *clone() const {
|
||||
return new RawPDU(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This always returns true, since we don't know what this
|
||||
* RawPDU is holding.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
payload_type _payload;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs the given PDU type from the raw data stored
|
||||
* in this RawPDU.
|
||||
*/
|
||||
template<typename T>
|
||||
T to() const {
|
||||
return T(&payload_[0], static_cast<uint32_t>(payload_.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
RawPDU* clone() const {
|
||||
return new RawPDU(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
payload_type payload_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_RAWPDU_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,6 +34,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
|
||||
namespace Tins{
|
||||
@@ -43,7 +44,7 @@ class PDUOption;
|
||||
/**
|
||||
* \brief Class that models the RSN information structure.
|
||||
*/
|
||||
class RSNInformation {
|
||||
class TINS_API RSNInformation {
|
||||
public:
|
||||
/**
|
||||
* \brief Enum that represents the different cypher suites.
|
||||
@@ -91,7 +92,7 @@ public:
|
||||
*
|
||||
* \param buffer The buffer from which to construct this object.
|
||||
*/
|
||||
RSNInformation(const serialization_type &buffer);
|
||||
RSNInformation(const serialization_type& buffer);
|
||||
|
||||
/**
|
||||
* \brief Constructs a RSNInformation from a buffer.
|
||||
@@ -102,7 +103,7 @@ public:
|
||||
* \param buffer The buffer from which this object will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
RSNInformation(const uint8_t *buffer, uint32_t total_sz);
|
||||
RSNInformation(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Helper function to create a WPA2-PSK RSNInformation
|
||||
@@ -147,31 +148,41 @@ public:
|
||||
* \brief Getter for the group suite field.
|
||||
* \return The group suite field.
|
||||
*/
|
||||
CypherSuites group_suite() const { return _group_suite; }
|
||||
CypherSuites group_suite() const {
|
||||
return static_cast<CypherSuites>(Endian::le_to_host<uint32_t>(group_suite_));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint16_t version() const { return Endian::le_to_host(_version); }
|
||||
uint16_t version() const {
|
||||
return Endian::le_to_host(version_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the capabilities field.
|
||||
* \return The version field.
|
||||
*/
|
||||
uint16_t capabilities() const { return Endian::le_to_host(_capabilities); }
|
||||
uint16_t capabilities() const {
|
||||
return Endian::le_to_host(capabilities_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pairwise cypher suite list.
|
||||
* \return A list of pairwise cypher suites.
|
||||
*/
|
||||
const cyphers_type &pairwise_cyphers() const { return _pairwise_cyphers; }
|
||||
const cyphers_type& pairwise_cyphers() const {
|
||||
return pairwise_cyphers_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the akm suite list.
|
||||
* \return A list of akm suites.
|
||||
*/
|
||||
const akm_type &akm_cyphers() const { return _akm_cyphers; }
|
||||
const akm_type& akm_cyphers() const {
|
||||
return akm_cyphers_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Serializes this object.
|
||||
@@ -182,14 +193,14 @@ public:
|
||||
/**
|
||||
* Constructs an RSNInformation object from a Dot11 tagged option.
|
||||
*/
|
||||
static RSNInformation from_option(const PDUOption<uint8_t, Dot11> &opt);
|
||||
static RSNInformation from_option(const PDUOption<uint8_t, Dot11>& opt);
|
||||
private:
|
||||
void init(const uint8_t *buffer, uint32_t total_sz);
|
||||
void init(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
uint16_t _version, _capabilities;
|
||||
CypherSuites _group_suite;
|
||||
akm_type _akm_cyphers;
|
||||
cyphers_type _pairwise_cyphers;
|
||||
uint16_t version_, capabilities_;
|
||||
CypherSuites group_suite_;
|
||||
akm_type akm_cyphers_;
|
||||
cyphers_type pairwise_cyphers_;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,15 +32,17 @@
|
||||
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class SLL
|
||||
* \brief Represents a Linux cooked-mode capture (SLL) PDU.
|
||||
*/
|
||||
class SLL : public PDU {
|
||||
class TINS_API SLL : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -69,7 +71,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
SLL(const uint8_t *buffer, uint32_t total_sz);
|
||||
SLL(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -78,7 +80,7 @@ public:
|
||||
* \return The stored Packet Type field value.
|
||||
*/
|
||||
uint16_t packet_type() const {
|
||||
return Endian::be_to_host(_header.packet_type);
|
||||
return Endian::be_to_host(header_.packet_type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +88,7 @@ public:
|
||||
* \return The stored LLADDR Type field value.
|
||||
*/
|
||||
uint16_t lladdr_type() const {
|
||||
return Endian::be_to_host(_header.lladdr_type);
|
||||
return Endian::be_to_host(header_.lladdr_type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +96,7 @@ public:
|
||||
* \return The stored LLADDR Length field value.
|
||||
*/
|
||||
uint16_t lladdr_len() const {
|
||||
return Endian::be_to_host(_header.lladdr_len);
|
||||
return Endian::be_to_host(header_.lladdr_len);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,7 +104,7 @@ public:
|
||||
* \return The stored Address field value.
|
||||
*/
|
||||
address_type address() const {
|
||||
return _header.address;
|
||||
return header_.address;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +112,7 @@ public:
|
||||
* \return The stored Protocol field value.
|
||||
*/
|
||||
uint16_t protocol() const {
|
||||
return Endian::be_to_host(_header.protocol);
|
||||
return Endian::be_to_host(header_.protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,7 +145,7 @@ public:
|
||||
* \brief Setter for the Address field.
|
||||
* \param new_address The new Address field value.
|
||||
*/
|
||||
void address(const address_type &new_address);
|
||||
void address(const address_type& new_address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Protocol field.
|
||||
@@ -161,20 +163,20 @@ public:
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
SLL *clone() const {
|
||||
SLL* clone() const {
|
||||
return new SLL(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct sllhdr {
|
||||
struct sll_header {
|
||||
uint16_t packet_type, lladdr_type, lladdr_len;
|
||||
uint8_t address[8];
|
||||
uint16_t protocol;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *);
|
||||
|
||||
sllhdr _header;
|
||||
sll_header header_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,7 +36,7 @@
|
||||
namespace Tins {
|
||||
class value_too_large : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
const char* what() const throw() {
|
||||
return "Value is too large";
|
||||
}
|
||||
};
|
||||
@@ -112,8 +112,9 @@ public:
|
||||
* \param val The parameter from which to copy construct.
|
||||
*/
|
||||
small_uint(repr_type val) {
|
||||
if(val > max_value)
|
||||
if (val > max_value) {
|
||||
throw value_too_large();
|
||||
}
|
||||
value = val;
|
||||
}
|
||||
|
||||
@@ -127,5 +128,6 @@ private:
|
||||
repr_type value;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_SMALL_UINT_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,140 +39,149 @@
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class SNAP
|
||||
* \brief Represents a SNAP frame.
|
||||
*
|
||||
* Note that this PDU contains the 802.3 LLC structure + SNAP frame.
|
||||
* So far only unnumbered information structure is supported.
|
||||
*/
|
||||
class TINS_API SNAP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \class SNAP
|
||||
* \brief Represents a SNAP frame.
|
||||
*
|
||||
* Note that this PDU contains the 802.3 LLC structure + SNAP frame.
|
||||
* So far only unnumbered information structure is supported.
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class SNAP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::SNAP;
|
||||
static const PDU::PDUType pdu_flag = PDU::SNAP;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of SNAP
|
||||
* This constructor sets the dsap and ssap fields to 0xaa, and
|
||||
* the id field to 3.
|
||||
*/
|
||||
SNAP();
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of SNAP
|
||||
* This constructor sets the dsap and ssap fields to 0xaa, and
|
||||
* the id field to 3.
|
||||
*/
|
||||
SNAP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a SNAP object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a SNAP header in the
|
||||
* buffer, a malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
SNAP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the Control field.
|
||||
* \param new_id The new Control to be set.
|
||||
*/
|
||||
void control(uint8_t new_control);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Organization Code field.
|
||||
* \param new_org The new Organization Code to be set.
|
||||
*/
|
||||
void org_code(small_uint<24> new_org);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Ethernet Type field.
|
||||
* \param new_eth The new Ethernet Type to be set.
|
||||
*/
|
||||
void eth_type(uint16_t new_eth);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the DSAP field.
|
||||
* \return The DSAP field.
|
||||
*/
|
||||
uint8_t dsap() const { return _snap.dsap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the SSAP field.
|
||||
* \return The SSAP field.
|
||||
*/
|
||||
uint8_t ssap() const { return _snap.ssap; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Control field.
|
||||
* \return The Control field.
|
||||
*/
|
||||
uint8_t control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_snap.control_org) & 0xff;
|
||||
#else
|
||||
return (_snap.control_org >> 24) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Organization Code field.
|
||||
* \return The Organization Code field.
|
||||
*/
|
||||
small_uint<24> org_code() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return Endian::be_to_host<uint32_t>(_snap.control_org & 0xffffff00);
|
||||
#else
|
||||
return _snap.control_org & 0xffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Ethernet Type field.
|
||||
* \return The Ethernet Type field.
|
||||
*/
|
||||
uint16_t eth_type() const { return Endian::be_to_host(_snap.eth_type); }
|
||||
|
||||
/**
|
||||
* \brief Returns the SNAP frame's header length.
|
||||
*
|
||||
* \return The header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
SNAP *clone() const {
|
||||
return new SNAP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct snaphdr {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
uint32_t control_org;
|
||||
uint16_t eth_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
snaphdr _snap;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* \brief Constructs a SNAP object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a SNAP header in the
|
||||
* buffer, a malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
SNAP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the Control field.
|
||||
* \param new_id The new Control to be set.
|
||||
*/
|
||||
void control(uint8_t new_control);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Organization Code field.
|
||||
* \param new_org The new Organization Code to be set.
|
||||
*/
|
||||
void org_code(small_uint<24> new_org);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Ethernet Type field.
|
||||
* \param new_eth The new Ethernet Type to be set.
|
||||
*/
|
||||
void eth_type(uint16_t new_eth);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the DSAP field.
|
||||
* \return The DSAP field.
|
||||
*/
|
||||
uint8_t dsap() const {
|
||||
return snap_.dsap;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the SSAP field.
|
||||
* \return The SSAP field.
|
||||
*/
|
||||
uint8_t ssap() const {
|
||||
return snap_.ssap;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Control field.
|
||||
* \return The Control field.
|
||||
*/
|
||||
uint8_t control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (snap_.control_org) & 0xff;
|
||||
#else
|
||||
return (snap_.control_org >> 24) & 0xff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Organization Code field.
|
||||
* \return The Organization Code field.
|
||||
*/
|
||||
small_uint<24> org_code() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return Endian::be_to_host<uint32_t>(snap_.control_org & 0xffffff00);
|
||||
#else
|
||||
return snap_.control_org & 0xffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Ethernet Type field.
|
||||
* \return The Ethernet Type field.
|
||||
*/
|
||||
uint16_t eth_type() const {
|
||||
return Endian::be_to_host(snap_.eth_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the SNAP frame's header length.
|
||||
*
|
||||
* \return The header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
SNAP* clone() const {
|
||||
return new SNAP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct snap_header {
|
||||
uint8_t dsap;
|
||||
uint8_t ssap;
|
||||
uint32_t control_org;
|
||||
uint16_t eth_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
snap_header snap_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_SNAP_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,6 +31,7 @@
|
||||
#define TINS_STP_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
#include "small_uint.h"
|
||||
@@ -40,7 +41,7 @@ namespace Tins {
|
||||
* \class STP
|
||||
* \brief Represents a Spanning Tree Protocol PDU.
|
||||
*/
|
||||
class STP : public PDU {
|
||||
class TINS_API STP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
@@ -79,7 +80,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
STP(const uint8_t *buffer, uint32_t total_sz);
|
||||
STP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -88,7 +89,7 @@ public:
|
||||
* \return The stored Protocol ID field value.
|
||||
*/
|
||||
uint16_t proto_id() const {
|
||||
return Endian::be_to_host(_header.proto_id);
|
||||
return Endian::be_to_host(header_.proto_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +97,7 @@ public:
|
||||
* \return The stored Protocol Version field value.
|
||||
*/
|
||||
uint8_t proto_version() const {
|
||||
return _header.proto_version;
|
||||
return header_.proto_version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,7 +105,7 @@ public:
|
||||
* \return The stored BDU Type field value.
|
||||
*/
|
||||
uint8_t bpdu_type() const {
|
||||
return _header.bpdu_type;
|
||||
return header_.bpdu_type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ public:
|
||||
* \return The stored BDU Flags field value.
|
||||
*/
|
||||
uint8_t bpdu_flags() const {
|
||||
return _header.bpdu_flags;
|
||||
return header_.bpdu_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +121,7 @@ public:
|
||||
* \return The stored Root Path Cost field value.
|
||||
*/
|
||||
uint32_t root_path_cost() const {
|
||||
return Endian::be_to_host(_header.root_path_cost);
|
||||
return Endian::be_to_host(header_.root_path_cost);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,7 +129,7 @@ public:
|
||||
* \return The stored Port ID field value.
|
||||
*/
|
||||
uint16_t port_id() const {
|
||||
return Endian::be_to_host(_header.port_id);
|
||||
return Endian::be_to_host(header_.port_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +137,7 @@ public:
|
||||
* \return The stored Message Age field value.
|
||||
*/
|
||||
uint16_t msg_age() const {
|
||||
return Endian::be_to_host(_header.msg_age) / 256;
|
||||
return Endian::be_to_host(header_.msg_age) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,7 +145,7 @@ public:
|
||||
* \return The stored Maximum Age field value.
|
||||
*/
|
||||
uint16_t max_age() const {
|
||||
return Endian::be_to_host(_header.max_age) / 256;
|
||||
return Endian::be_to_host(header_.max_age) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,7 +153,7 @@ public:
|
||||
* \return The stored Hello Time field value.
|
||||
*/
|
||||
uint16_t hello_time() const {
|
||||
return Endian::be_to_host(_header.hello_time) / 256;
|
||||
return Endian::be_to_host(header_.hello_time) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,7 +161,7 @@ public:
|
||||
* \return The stored Forward Delay field value.
|
||||
*/
|
||||
uint16_t fwd_delay() const {
|
||||
return Endian::be_to_host(_header.fwd_delay) / 256;
|
||||
return Endian::be_to_host(header_.fwd_delay) / 256;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,12 +180,14 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
STP *clone() const {
|
||||
STP* clone() const {
|
||||
return new STP(*this);
|
||||
}
|
||||
|
||||
@@ -261,13 +264,13 @@ public:
|
||||
* \brief Setter for the Root ID field.
|
||||
* \param new_fwd_delay The new Root ID field value.
|
||||
*/
|
||||
void root_id(const bpdu_id_type &id);
|
||||
void root_id(const bpdu_id_type& id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Bridge ID field.
|
||||
* \param new_fwd_delay The new Bridge ID field value.
|
||||
*/
|
||||
void bridge_id(const bpdu_id_type &id);
|
||||
void bridge_id(const bpdu_id_type& id);
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct pvt_bpdu_id {
|
||||
@@ -284,7 +287,7 @@ private:
|
||||
} TINS_END_PACK;
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct stphdr {
|
||||
struct stp_header {
|
||||
uint16_t proto_id;
|
||||
uint8_t proto_version;
|
||||
uint8_t bpdu_type;
|
||||
@@ -299,12 +302,12 @@ private:
|
||||
uint16_t fwd_delay;
|
||||
} TINS_END_PACK;
|
||||
|
||||
static bpdu_id_type convert(const pvt_bpdu_id &id);
|
||||
static pvt_bpdu_id convert(const bpdu_id_type &id);
|
||||
static bpdu_id_type convert(const pvt_bpdu_id& id);
|
||||
static pvt_bpdu_id convert(const bpdu_id_type& id);
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
stphdr _header;
|
||||
stp_header header_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include "sniffer.h"
|
||||
#include "macros.h"
|
||||
#include "tcp.h"
|
||||
#include "utils.h"
|
||||
#include "ip.h"
|
||||
@@ -50,7 +51,7 @@ class RawPDU;
|
||||
* \class TCPStream
|
||||
* \brief Represents a TCP stream.
|
||||
*/
|
||||
class TCPStream {
|
||||
class TINS_API TCPStream {
|
||||
public:
|
||||
/**
|
||||
* The stream information.
|
||||
@@ -64,7 +65,7 @@ public:
|
||||
StreamInfo(IPv4Address client, IPv4Address server,
|
||||
uint16_t cport, uint16_t sport);
|
||||
|
||||
bool operator<(const StreamInfo &rhs) const;
|
||||
bool operator<(const StreamInfo& rhs) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -78,17 +79,17 @@ public:
|
||||
* \param tcp The TCP PDU from which to take the initial parameters.
|
||||
* \param identifier This stream's identifier number
|
||||
*/
|
||||
TCPStream(IP *ip, TCP *tcp, uint64_t identifier);
|
||||
TCPStream(IP* ip, TCP* tcp, uint64_t identifier);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
TCPStream(const TCPStream &rhs);
|
||||
TCPStream(const TCPStream& rhs);
|
||||
|
||||
/**
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
TCPStream& operator=(const TCPStream &rhs);
|
||||
TCPStream& operator=(const TCPStream& rhs);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -102,7 +103,7 @@ public:
|
||||
*
|
||||
* \return const payload_type& containing the payload.
|
||||
*/
|
||||
const payload_type &client_payload() const {
|
||||
const payload_type& client_payload() const {
|
||||
return client_payload_;
|
||||
}
|
||||
|
||||
@@ -113,7 +114,7 @@ public:
|
||||
*
|
||||
* \return payload_type& containing the payload.
|
||||
*/
|
||||
payload_type &client_payload() {
|
||||
payload_type& client_payload() {
|
||||
return client_payload_;
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ public:
|
||||
*
|
||||
* \return const payload_type& containing the payload.
|
||||
*/
|
||||
const payload_type &server_payload() const {
|
||||
const payload_type& server_payload() const {
|
||||
return server_payload_;
|
||||
}
|
||||
|
||||
@@ -135,7 +136,7 @@ public:
|
||||
*
|
||||
* \return payload_type& containing the payload.
|
||||
*/
|
||||
payload_type &server_payload() {
|
||||
payload_type& server_payload() {
|
||||
return server_payload_;
|
||||
}
|
||||
|
||||
@@ -144,15 +145,15 @@ public:
|
||||
* \return uint64_t containing the identification number.
|
||||
*/
|
||||
uint64_t id() const {
|
||||
return identifier;
|
||||
return identifier_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the stream information.
|
||||
* \return const StreamInfo& containing the stream information.
|
||||
*/
|
||||
const StreamInfo &stream_info() const {
|
||||
return info;
|
||||
const StreamInfo& stream_info() const {
|
||||
return info_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +165,7 @@ public:
|
||||
* \return bool indicating whether the stream is finished.
|
||||
*/
|
||||
bool is_finished() const {
|
||||
return fin_sent;
|
||||
return fin_sent_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,25 +178,25 @@ public:
|
||||
* \return bool indicating whether any changes have been done to
|
||||
* any of the stored payloads.
|
||||
*/
|
||||
bool update(IP *ip, TCP *tcp);
|
||||
bool update(IP* ip, TCP* tcp);
|
||||
private:
|
||||
typedef std::map<uint32_t, RawPDU*> fragments_type;
|
||||
|
||||
static void free_fragments(fragments_type &frags);
|
||||
static fragments_type clone_fragments(const fragments_type &frags);
|
||||
static void free_fragments(fragments_type& frags);
|
||||
static fragments_type clone_fragments(const fragments_type& frags);
|
||||
|
||||
bool generic_process(uint32_t &my_seq, uint32_t &other_seq,
|
||||
payload_type &pload, fragments_type &frags, TCP *tcp);
|
||||
bool generic_process(uint32_t& my_seq, uint32_t& other_seq,
|
||||
payload_type& pload, fragments_type& frags, TCP* tcp);
|
||||
|
||||
void safe_insert(fragments_type &frags, uint32_t seq, RawPDU *raw);
|
||||
void safe_insert(fragments_type& frags, uint32_t seq, RawPDU* raw);
|
||||
|
||||
|
||||
uint32_t client_seq, server_seq;
|
||||
StreamInfo info;
|
||||
uint64_t identifier;
|
||||
uint32_t client_seq_, server_seq_;
|
||||
StreamInfo info_;
|
||||
uint64_t identifier_;
|
||||
payload_type client_payload_, server_payload_;
|
||||
fragments_type client_frags, server_frags;
|
||||
bool syn_ack_sent, fin_sent;
|
||||
fragments_type client_frags_, server_frags_;
|
||||
bool syn_ack_sent_, fin_sent_;
|
||||
};
|
||||
|
||||
|
||||
@@ -203,7 +204,7 @@ private:
|
||||
* \class TCPStreamFollower
|
||||
* \brief Follows TCP streams and notifies the user when data is available.
|
||||
*/
|
||||
class TCPStreamFollower {
|
||||
class TINS_API TCPStreamFollower {
|
||||
public:
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
@@ -223,7 +224,7 @@ public:
|
||||
* closed.
|
||||
*/
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
void follow_streams(BaseSniffer &sniffer, DataFunctor data_fun, EndFunctor end_fun);
|
||||
void follow_streams(BaseSniffer& sniffer, DataFunctor data_fun, EndFunctor end_fun);
|
||||
|
||||
/**
|
||||
* \brief Starts following TCP streams.
|
||||
@@ -262,7 +263,7 @@ public:
|
||||
* closed.
|
||||
*/
|
||||
template<typename DataFunctor>
|
||||
void follow_streams(BaseSniffer &sniffer, DataFunctor data_fun);
|
||||
void follow_streams(BaseSniffer& sniffer, DataFunctor data_fun);
|
||||
|
||||
/**
|
||||
* \brief Starts following TCP streams.
|
||||
@@ -291,89 +292,97 @@ private:
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
struct proxy_caller {
|
||||
bool callback(PDU &pdu) {
|
||||
bool callback(PDU& pdu) {
|
||||
return stream->callback(pdu, data_fun, end_fun);
|
||||
}
|
||||
|
||||
TCPStreamFollower *stream;
|
||||
TCPStreamFollower* stream;
|
||||
DataFunctor data_fun;
|
||||
EndFunctor end_fun;
|
||||
};
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
bool callback(PDU &pdu, const DataFunctor &fun, const EndFunctor &end_fun);
|
||||
bool callback(PDU& pdu, const DataFunctor& fun, const EndFunctor& end_fun);
|
||||
static void dummy_function(TCPStream&) { }
|
||||
|
||||
sessions_type sessions;
|
||||
uint64_t last_identifier;
|
||||
sessions_type sessions_;
|
||||
uint64_t last_identifier_;
|
||||
};
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
void TCPStreamFollower::follow_streams(BaseSniffer &sniffer, DataFunctor data_fun, EndFunctor end_fun) {
|
||||
void TCPStreamFollower::follow_streams(BaseSniffer& sniffer,
|
||||
DataFunctor data_fun,
|
||||
EndFunctor end_fun) {
|
||||
typedef proxy_caller<DataFunctor, EndFunctor> proxy_type;
|
||||
proxy_type proxy = { this, data_fun, end_fun };
|
||||
sniffer.sniff_loop(make_sniffer_handler(&proxy, &proxy_type::callback));
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename DataFunctor, typename EndFunctor>
|
||||
void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator end,
|
||||
DataFunctor data_fun, EndFunctor end_fun)
|
||||
{
|
||||
void TCPStreamFollower::follow_streams(ForwardIterator start,
|
||||
ForwardIterator end,
|
||||
DataFunctor data_fun,
|
||||
EndFunctor end_fun) {
|
||||
while(start != end) {
|
||||
if(!callback(Utils::dereference_until_pdu(start), data_fun, end_fun))
|
||||
if (!callback(Utils::dereference_until_pdu(start), data_fun, end_fun)) {
|
||||
return;
|
||||
}
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename DataFunctor>
|
||||
void TCPStreamFollower::follow_streams(BaseSniffer &sniffer, DataFunctor data_fun) {
|
||||
void TCPStreamFollower::follow_streams(BaseSniffer& sniffer, DataFunctor data_fun) {
|
||||
return follow_streams(sniffer, data_fun, dummy_function);
|
||||
}
|
||||
|
||||
template<typename ForwardIterator, typename DataFunctor>
|
||||
void TCPStreamFollower::follow_streams(ForwardIterator start, ForwardIterator end,
|
||||
DataFunctor data_fun)
|
||||
{
|
||||
void TCPStreamFollower::follow_streams(ForwardIterator start,
|
||||
ForwardIterator end,
|
||||
DataFunctor data_fun) {
|
||||
follow_streams(start, end, data_fun, dummy_function);
|
||||
}
|
||||
|
||||
template<typename DataFunctor, typename EndFunctor>
|
||||
bool TCPStreamFollower::callback(PDU &pdu, const DataFunctor &data_fun, const EndFunctor &end_fun) {
|
||||
IP *ip = pdu.find_pdu<IP>();
|
||||
TCP *tcp = pdu.find_pdu<TCP>();
|
||||
if(!ip || !tcp) {
|
||||
bool TCPStreamFollower::callback(PDU& pdu,
|
||||
const DataFunctor& data_fun,
|
||||
const EndFunctor& end_fun) {
|
||||
IP* ip = pdu.find_pdu<IP>();
|
||||
TCP* tcp = pdu.find_pdu<TCP>();
|
||||
if (!ip || !tcp) {
|
||||
return true;
|
||||
}
|
||||
TCPStream::StreamInfo info(
|
||||
ip->src_addr(), ip->dst_addr(),
|
||||
tcp->sport(), tcp->dport()
|
||||
);
|
||||
sessions_type::iterator it = sessions.find(info);
|
||||
if(it == sessions.end()) {
|
||||
sessions_type::iterator it = sessions_.find(info);
|
||||
if (it == sessions_.end()) {
|
||||
std::swap(info.client_addr, info.server_addr);
|
||||
std::swap(info.client_port, info.server_port);
|
||||
if((it = sessions.find(info)) == sessions.end()) {
|
||||
if(tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
|
||||
sessions.insert(
|
||||
if ((it = sessions_.find(info)) == sessions_.end()) {
|
||||
if (tcp->get_flag(TCP::SYN) && !tcp->get_flag(TCP::ACK)) {
|
||||
sessions_.insert(
|
||||
std::make_pair(
|
||||
info,
|
||||
TCPStream(ip, tcp, last_identifier++)
|
||||
TCPStream(ip, tcp, last_identifier_++)
|
||||
)
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if(it->second.update(ip, tcp))
|
||||
if (it->second.update(ip, tcp)) {
|
||||
data_fun(it->second);
|
||||
}
|
||||
// We're done with this stream
|
||||
if(it->second.is_finished()) {
|
||||
if (it->second.is_finished()) {
|
||||
end_fun(it->second);
|
||||
sessions.erase(it);
|
||||
sessions_.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_TCP_STREAM_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,7 +30,7 @@
|
||||
#ifndef TINS_TIMESTAMP_H
|
||||
#define TINS_TIMESTAMP_H
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
@@ -46,7 +46,7 @@ namespace Tins {
|
||||
*/
|
||||
class Timestamp {
|
||||
public:
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
typedef long seconds_type;
|
||||
typedef long microseconds_type;
|
||||
#else
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
* \brief Constructs a Timestamp which will hold the current time.
|
||||
*/
|
||||
static Timestamp current_time() {
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
//fixme
|
||||
return Timestamp();
|
||||
#else
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
* Constructs a timestamp from a timeval object.
|
||||
* \param time_val The timeval object.
|
||||
*/
|
||||
Timestamp(const timeval &time_val) : tv(time_val) {}
|
||||
Timestamp(const timeval& time_val) : tv(time_val) {}
|
||||
|
||||
/**
|
||||
* Returns the amount of seconds in this timestamp.
|
||||
@@ -121,6 +121,7 @@ public:
|
||||
private:
|
||||
timeval tv;
|
||||
};
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_TIMESTAMP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "dot3.h"
|
||||
#include "ip.h"
|
||||
#include "ipv6.h"
|
||||
#include "mpls.h"
|
||||
#include "packet_sender.h"
|
||||
#include "packet_writer.h"
|
||||
#include "pdu.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -36,150 +36,159 @@
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class UDP
|
||||
* \brief Represents an UDP PDU.
|
||||
*
|
||||
* This class represents an UDP PDU.
|
||||
*
|
||||
* While sniffing, the payload sent in each packet will be wrapped
|
||||
* in a RawPDU, which is set as the UDP object's inner_pdu. Therefore,
|
||||
* if you are sniffing and want to see the UDP packet's payload,
|
||||
* you need to do the following:
|
||||
*
|
||||
* \code
|
||||
* // Get a packet from somewhere.
|
||||
* UDP udp = ...;
|
||||
*
|
||||
* // Extract the RawPDU object.
|
||||
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
|
||||
*
|
||||
* // Finally, take the payload (this is a vector<uint8_t>)
|
||||
* const RawPDU::payload_type& payload = raw.payload();
|
||||
* \endcode
|
||||
*
|
||||
* \sa RawPDU
|
||||
/**
|
||||
* \class UDP
|
||||
* \brief Represents an UDP PDU.
|
||||
*
|
||||
* This class represents an UDP PDU.
|
||||
*
|
||||
* While sniffing, the payload sent in each packet will be wrapped
|
||||
* in a RawPDU, which is set as the UDP object's inner_pdu. Therefore,
|
||||
* if you are sniffing and want to see the UDP packet's payload,
|
||||
* you need to do the following:
|
||||
*
|
||||
* \code
|
||||
* // Get a packet from somewhere.
|
||||
* UDP udp = ...;
|
||||
*
|
||||
* // Extract the RawPDU object.
|
||||
* const RawPDU& raw = udp.rfind_pdu<RawPDU>();
|
||||
*
|
||||
* // Finally, take the payload (this is a vector<uint8_t>)
|
||||
* const RawPDU::payload_type& payload = raw.payload();
|
||||
* \endcode
|
||||
*
|
||||
* \sa RawPDU
|
||||
*/
|
||||
class UDP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class UDP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::UDP;
|
||||
static const PDU::PDUType pdu_flag = PDU::UDP;
|
||||
|
||||
/**
|
||||
* \brief UDP constructor.
|
||||
*
|
||||
* Constructs an instance of UDP. The destination and source
|
||||
* port can be provided, otherwise both of them will be 0.
|
||||
*
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* */
|
||||
UDP(uint16_t dport = 0, uint16_t sport = 0);
|
||||
|
||||
/**
|
||||
* \brief Constructs an UDP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a UDP header a malformed_packet
|
||||
* exception is thrown.
|
||||
*
|
||||
* Any extra data will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
UDP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief UDP constructor.
|
||||
*
|
||||
* Constructs an instance of UDP. The destination and source
|
||||
* port can be provided, otherwise both of them will be 0.
|
||||
*
|
||||
* \param dport Destination port.
|
||||
* \param sport Source port.
|
||||
* */
|
||||
UDP(uint16_t dport = 0, uint16_t sport = 0);
|
||||
/**
|
||||
* \brief Getter for the destination port.
|
||||
* \return The datagram's destination port.
|
||||
*/
|
||||
uint16_t dport() const {
|
||||
return Endian::be_to_host(header_.dport);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs an UDP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a UDP header a malformed_packet
|
||||
* exception is thrown.
|
||||
*
|
||||
* Any extra data will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
UDP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the destination port.
|
||||
* \return The datagram's destination port.
|
||||
*/
|
||||
uint16_t dport() const { return Endian::be_to_host(_udp.dport); }
|
||||
/**
|
||||
* \brief Getter for the source port.
|
||||
* \return The datagram's source port.
|
||||
*/
|
||||
uint16_t sport() const {
|
||||
return Endian::be_to_host(header_.sport);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the length of the datagram.
|
||||
* \return The length of the datagram.
|
||||
*/
|
||||
uint16_t length() const {
|
||||
return Endian::be_to_host(header_.len);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum of the datagram.
|
||||
* \return The datagram's checksum.
|
||||
*/
|
||||
uint16_t checksum() const {
|
||||
return Endian::be_to_host(header_.check);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the source port.
|
||||
* \return The datagram's source port.
|
||||
*/
|
||||
uint16_t sport() const { return Endian::be_to_host(_udp.sport); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the length of the datagram.
|
||||
* \return The length of the datagram.
|
||||
*/
|
||||
uint16_t length() const { return Endian::be_to_host(_udp.len); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum of the datagram.
|
||||
* \return The datagram's checksum.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_udp.check); }
|
||||
/**
|
||||
* \brief Set the destination port.
|
||||
* \param new_dport The new destination port.
|
||||
*/
|
||||
void dport(uint16_t new_dport);
|
||||
|
||||
/**
|
||||
* \brief Set the destination port.
|
||||
* \param new_dport The new destination port.
|
||||
*/
|
||||
void dport(uint16_t new_dport);
|
||||
/**
|
||||
* \brief Set the source port.
|
||||
*
|
||||
* \param new_sport The new source port.
|
||||
*/
|
||||
void sport(uint16_t new_sport);
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \param new_len The new length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
void length(uint16_t new_len);
|
||||
|
||||
/**
|
||||
* \brief Set the source port.
|
||||
*
|
||||
* \param new_sport The new source port.
|
||||
*/
|
||||
void sport(uint16_t new_sport);
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \param new_len The new length field.
|
||||
* \return The length field.
|
||||
*/
|
||||
void length(uint16_t new_len);
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This compares the source and destination ports in the provided
|
||||
* response with those stored in this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This compares the source and destination ports in the provided
|
||||
* response with those stored in this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::UDP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
UDP* clone() const {
|
||||
return new UDP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct udp_header {
|
||||
uint16_t sport;
|
||||
uint16_t dport;
|
||||
uint16_t len;
|
||||
uint16_t check;
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::UDP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
UDP *clone() const {
|
||||
return new UDP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct udphdr {
|
||||
uint16_t sport;
|
||||
uint16_t dport;
|
||||
uint16_t len;
|
||||
uint16_t check;
|
||||
} TINS_END_PACK;
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent);
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
udp_header header_;
|
||||
};
|
||||
|
||||
udphdr _udp;
|
||||
};
|
||||
}
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_UDP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,398 +30,272 @@
|
||||
#ifndef TINS_UTILS_H
|
||||
#define TINS_UTILS_H
|
||||
|
||||
#ifndef WIN32
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#undef interface
|
||||
#include "network_interface.h"
|
||||
#endif
|
||||
#include "macros.h"
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "hw_address.h"
|
||||
#include "internals.h"
|
||||
|
||||
// Fix for Windows interface define on combaseapi.h
|
||||
#undef interface
|
||||
|
||||
namespace Tins {
|
||||
class NetworkInterface;
|
||||
class PacketSender;
|
||||
class PDU;
|
||||
|
||||
/**
|
||||
* \brief Network utils namespace.
|
||||
*
|
||||
* This namespace provides utils to convert between integer IP addresses
|
||||
* and dotted notation strings, "net to host" integer conversions,
|
||||
* interface listing, etc.
|
||||
|
||||
class NetworkInterface;
|
||||
class PacketSender;
|
||||
class PDU;
|
||||
class IPv6Address;
|
||||
template <size_t n, typename Storage>
|
||||
class HWAddress;
|
||||
|
||||
/**
|
||||
* \brief Network utils namespace.
|
||||
*
|
||||
* This namespace provides utils to convert between integer IP addresses
|
||||
* and dotted notation strings, "net to host" integer conversions,
|
||||
* interface listing, etc.
|
||||
*/
|
||||
namespace Utils {
|
||||
|
||||
/**
|
||||
* Struct that represents an entry the routing table
|
||||
*/
|
||||
struct RouteEntry {
|
||||
/**
|
||||
* This interface's name.
|
||||
*/
|
||||
namespace Utils {
|
||||
/**
|
||||
* Struct that represents an entry in /proc/net/route
|
||||
*/
|
||||
struct RouteEntry {
|
||||
/**
|
||||
* This interface's name.
|
||||
*/
|
||||
std::string interface;
|
||||
|
||||
/**
|
||||
* This route entry's destination.
|
||||
*/
|
||||
IPv4Address destination;
|
||||
|
||||
/**
|
||||
* This route entry's gateway.
|
||||
*/
|
||||
IPv4Address gateway;
|
||||
|
||||
/**
|
||||
* This route entry's subnet mask.
|
||||
*/
|
||||
IPv4Address mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
* If an ip address is given, its integer representation is returned.
|
||||
* Otherwise, the domain name is resolved and its ip address is returned.
|
||||
*
|
||||
* \param to_resolve The domain name/ip address to resolve.
|
||||
*/
|
||||
IPv4Address resolve_domain(const std::string &to_resolve);
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
* If an ip address is given, its integer representation is returned.
|
||||
* Otherwise, the domain name is resolved and its ip address is returned.
|
||||
*
|
||||
* \param to_resolve The domain name/ip address to resolve.
|
||||
*/
|
||||
IPv6Address resolve_domain6(const std::string &to_resolve);
|
||||
|
||||
/**
|
||||
* \brief Resolves the hardware address for a given ip.
|
||||
*
|
||||
* If the address can't be resolved, a std::runtime_error
|
||||
* exception is thrown.
|
||||
*
|
||||
* \param iface The interface in which the packet will be sent.
|
||||
* \param ip The ip to resolve, in integer format.
|
||||
* \param sender The sender to use to send and receive the ARP requests.
|
||||
* \return HWAddress<6> containing the resolved hardware address.
|
||||
*/
|
||||
HWAddress<6> resolve_hwaddr(const NetworkInterface &iface,
|
||||
IPv4Address ip, PacketSender &sender);
|
||||
|
||||
/**
|
||||
* \brief Resolves the hardware address for a given ip.
|
||||
*
|
||||
* If the address can't be resolved, a std::runtime_error
|
||||
* exception is thrown.
|
||||
*
|
||||
* This method sends and receives the packet through
|
||||
* PacketSender::default_interface.
|
||||
*
|
||||
* \param ip The ip to resolve, in integer format.
|
||||
* \param sender The sender to use to send and receive the ARP requests.
|
||||
* \return HWAddress<6> containing the resolved hardware address.
|
||||
*/
|
||||
HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender &sender);
|
||||
|
||||
/** \brief List all network interfaces.
|
||||
*
|
||||
* Returns a set of strings, each of them representing the name
|
||||
* of a network interface. These names can be used as the input
|
||||
* interface for Utils::interface_ip, Utils::interface_hwaddr, etc.
|
||||
*/
|
||||
std::set<std::string> network_interfaces();
|
||||
|
||||
/**
|
||||
* \brief Finds the gateway's IP address for the given IP
|
||||
* address.
|
||||
*
|
||||
* \param ip The IP address for which the default gateway will
|
||||
* be searched.
|
||||
* \param gw_addr This parameter will contain the gateway's IP
|
||||
* address in case it is found.
|
||||
*
|
||||
* \return bool indicating wether the lookup was successfull.
|
||||
*/
|
||||
bool gateway_from_ip(IPv4Address ip, IPv4Address &gw_addr);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \brief output ForwardIterator in which entries will be stored.
|
||||
*/
|
||||
template<class ForwardIterator>
|
||||
void route_entries(ForwardIterator output);
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \return a vector which contains all of the route entries.
|
||||
*/
|
||||
std::vector<RouteEntry> route_entries();
|
||||
|
||||
/** \brief Returns the 32 bit crc of the given buffer.
|
||||
*
|
||||
* \param data The input buffer.
|
||||
* \param data_size The size of the input buffer.
|
||||
*/
|
||||
uint32_t crc32(const uint8_t* data, uint32_t data_size);
|
||||
|
||||
/**
|
||||
* \brief Converts a channel number to its mhz representation.
|
||||
* \param channel The channel number.
|
||||
* \return The channel's mhz representation.
|
||||
*/
|
||||
uint16_t channel_to_mhz(uint16_t channel);
|
||||
|
||||
/**
|
||||
* \brief Converts mhz units to the appropriate channel number.
|
||||
* \param mhz The mhz units to be converted.
|
||||
* \return The channel number.
|
||||
*/
|
||||
uint16_t mhz_to_channel(uint16_t mhz);
|
||||
|
||||
/**
|
||||
* \brief Converts a PDUType to a string.
|
||||
* \param pduType The PDUType to be converted.
|
||||
* \return A string representation, for example "DOT11_QOS_DATA".
|
||||
*/
|
||||
std::string to_string(PDU::PDUType pduType);
|
||||
|
||||
/** \brief Does the 16 bits sum of all 2 bytes elements between start and end.
|
||||
*
|
||||
* This is the checksum used by IP, UDP and TCP. If there's and odd number of
|
||||
* bytes, the last one is padded and added to the checksum. The checksum is performed
|
||||
* using network endiannes.
|
||||
* \param start The pointer to the start of the buffer.
|
||||
* \param end The pointer to the end of the buffer(excluding the last element).
|
||||
* \return Returns the checksum between start and end(non inclusive).
|
||||
*/
|
||||
uint32_t do_checksum(const uint8_t *start, const uint8_t *end);
|
||||
|
||||
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
|
||||
*
|
||||
* \param source_ip The source ip address.
|
||||
* \param dest_ip The destination ip address.
|
||||
* \param len The length to be included in the pseudo header.
|
||||
* \param flag The flag to use in the protocol field of the pseudo header.
|
||||
* \return The pseudo header checksum.
|
||||
*/
|
||||
uint32_t pseudoheader_checksum(IPv4Address source_ip, IPv4Address dest_ip, uint32_t len, uint32_t flag);
|
||||
|
||||
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
|
||||
*
|
||||
* \param source_ip The source ip address.
|
||||
* \param dest_ip The destination ip address.
|
||||
* \param len The length to be included in the pseudo header.
|
||||
* \param flag The flag to use in the protocol field of the pseudo header.
|
||||
* \return The pseudo header checksum.
|
||||
*/
|
||||
uint32_t pseudoheader_checksum(IPv6Address source_ip, IPv6Address dest_ip, uint32_t len, uint32_t flag);
|
||||
|
||||
/** \brief Generic function to iterate through interface and collect
|
||||
* data.
|
||||
*
|
||||
* The parameter is applied to every interface found, allowing
|
||||
* the object to collect data from them.
|
||||
* \param functor An instance of an class which implements operator(struct ifaddrs*).
|
||||
*/
|
||||
#ifndef WIN32
|
||||
template<class Functor>
|
||||
void generic_iface_loop(Functor &functor) {
|
||||
struct ifaddrs *ifaddrs = 0;
|
||||
struct ifaddrs *if_it = 0;
|
||||
getifaddrs(&ifaddrs);
|
||||
for(if_it = ifaddrs; if_it; if_it = if_it->ifa_next) {
|
||||
if(functor(if_it))
|
||||
break;
|
||||
}
|
||||
if(ifaddrs)
|
||||
freeifaddrs(ifaddrs);
|
||||
}
|
||||
#else // WIN32
|
||||
template<class Functor>
|
||||
void generic_iface_loop(Functor &functor) {
|
||||
ULONG size;
|
||||
::GetAdaptersAddresses(AF_INET, 0, 0, 0, &size);
|
||||
std::vector<uint8_t> buffer(size);
|
||||
if (::GetAdaptersAddresses(AF_INET, 0, 0, (IP_ADAPTER_ADDRESSES *)&buffer[0], &size) == ERROR_SUCCESS) {
|
||||
PIP_ADAPTER_ADDRESSES iface = (IP_ADAPTER_ADDRESSES *)&buffer[0];
|
||||
while(iface) {
|
||||
if(functor(iface))
|
||||
break;
|
||||
iface = iface->Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // WIN32
|
||||
|
||||
template <typename T>
|
||||
struct is_pdu {
|
||||
template <typename U>
|
||||
static char test(typename U::PDUType*);
|
||||
|
||||
template <typename U>
|
||||
static long test(...);
|
||||
|
||||
static const bool value = sizeof(test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the argument.
|
||||
*/
|
||||
inline PDU& dereference_until_pdu(PDU &pdu) {
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Dereferences the parameter until a PDU is found.
|
||||
*
|
||||
* This function dereferences the parameter until a PDU object
|
||||
* is found. When it's found, it is returned.
|
||||
*
|
||||
* \param value The parameter to be dereferenced.
|
||||
*/
|
||||
template<typename T>
|
||||
inline typename Internals::enable_if<!is_pdu<T>::value, PDU&>::type
|
||||
dereference_until_pdu(T &value) {
|
||||
return dereference_until_pdu(*value);
|
||||
}
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
inline std::vector<char> query_route_table() {
|
||||
int mib[6];
|
||||
std::vector<char> buf;
|
||||
size_t len;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = AF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = AF_INET;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
|
||||
throw std::runtime_error("sysctl failed");
|
||||
|
||||
buf.resize(len);
|
||||
if (sysctl(mib, 6, &buf[0], &len, NULL, 0) < 0) {
|
||||
throw std::runtime_error("sysctl failed");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
template<typename ForwardIterator>
|
||||
void parse_header(struct rt_msghdr *rtm, ForwardIterator iter)
|
||||
{
|
||||
char *ptr = (char *)(rtm + 1);
|
||||
sockaddr *sa = 0;
|
||||
|
||||
for (int i = 0; i < RTAX_MAX; i++) {
|
||||
if (rtm->rtm_addrs & (1 << i)) {
|
||||
sa = (struct sockaddr *)ptr;
|
||||
ptr += sa->sa_len;
|
||||
if (sa->sa_family == 0)
|
||||
sa = 0;
|
||||
}
|
||||
*iter++ = sa;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
template<class ForwardIterator>
|
||||
void Tins::Utils::route_entries(ForwardIterator output) {
|
||||
std::vector<char> buffer = query_route_table();
|
||||
char *next = &buffer[0], *end = &buffer[buffer.size()];
|
||||
rt_msghdr *rtm;
|
||||
std::vector<sockaddr*> sa(RTAX_MAX);
|
||||
char iface_name[IF_NAMESIZE];
|
||||
while(next < end) {
|
||||
rtm = (rt_msghdr*)next;
|
||||
parse_header(rtm, sa.begin());
|
||||
if (sa[RTAX_DST] && sa[RTAX_GATEWAY] && if_indextoname(rtm->rtm_index, iface_name)) {
|
||||
RouteEntry entry;
|
||||
entry.destination = IPv4Address(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr.s_addr);
|
||||
entry.gateway = IPv4Address(((struct sockaddr_in *)sa[RTAX_GATEWAY])->sin_addr.s_addr);
|
||||
if(sa[RTAX_GENMASK])
|
||||
entry.mask = IPv4Address(((struct sockaddr_in *)sa[RTAX_GENMASK])->sin_addr.s_addr);
|
||||
else
|
||||
entry.mask = IPv4Address(uint32_t());
|
||||
entry.interface = iface_name;
|
||||
*output++ = entry;
|
||||
}
|
||||
next += rtm->rtm_msglen;
|
||||
}
|
||||
}
|
||||
#elif defined(WIN32)
|
||||
template<class ForwardIterator>
|
||||
void Tins::Utils::route_entries(ForwardIterator output) {
|
||||
MIB_IPFORWARDTABLE *table;
|
||||
ULONG size = 0;
|
||||
char iface_name[256];
|
||||
GetIpForwardTable(0, &size, 0);
|
||||
std::vector<uint8_t> buffer(size);
|
||||
table = (MIB_IPFORWARDTABLE*)&buffer[0];
|
||||
GetIpForwardTable(table, &size, 0);
|
||||
std::string interface;
|
||||
|
||||
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||
MIB_IPFORWARDROW *row = &table->table[i];
|
||||
if(row->dwForwardType == MIB_IPROUTE_TYPE_INDIRECT) {
|
||||
RouteEntry entry;
|
||||
entry.interface = NetworkInterface::from_index(row->dwForwardIfIndex).name();
|
||||
entry.destination = IPv4Address(row->dwForwardDest);
|
||||
entry.mask = IPv4Address(row->dwForwardMask);
|
||||
entry.gateway = IPv4Address(row->dwForwardNextHop);
|
||||
*output++ = entry;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This route entry's destination.
|
||||
*/
|
||||
IPv4Address destination;
|
||||
|
||||
/**
|
||||
* This route entry's gateway.
|
||||
*/
|
||||
IPv4Address gateway;
|
||||
|
||||
/**
|
||||
* This route entry's subnet mask.
|
||||
*/
|
||||
IPv4Address mask;
|
||||
|
||||
/**
|
||||
* This route entry's metric.
|
||||
*/
|
||||
int metric;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
* If an ip address is given, its integer representation is returned.
|
||||
* Otherwise, the domain name is resolved and its ip address is returned.
|
||||
*
|
||||
* \param to_resolve The domain name/ip address to resolve.
|
||||
*/
|
||||
TINS_API IPv4Address resolve_domain(const std::string& to_resolve);
|
||||
|
||||
/**
|
||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||
*
|
||||
* If an ip address is given, its integer representation is returned.
|
||||
* Otherwise, the domain name is resolved and its ip address is returned.
|
||||
*
|
||||
* \param to_resolve The domain name/ip address to resolve.
|
||||
*/
|
||||
TINS_API IPv6Address resolve_domain6(const std::string& to_resolve);
|
||||
|
||||
/**
|
||||
* \brief Resolves the hardware address for a given ip.
|
||||
*
|
||||
* If the address can't be resolved, a std::runtime_error
|
||||
* exception is thrown.
|
||||
*
|
||||
* \param iface The interface in which the packet will be sent.
|
||||
* \param ip The ip to resolve, in integer format.
|
||||
* \param sender The sender to use to send and receive the ARP requests.
|
||||
* \return HWAddress<6> containing the resolved hardware address.
|
||||
*/
|
||||
TINS_API HWAddress<6> resolve_hwaddr(const NetworkInterface& iface,
|
||||
IPv4Address ip,
|
||||
PacketSender& sender);
|
||||
|
||||
/**
|
||||
* \brief Resolves the hardware address for a given ip.
|
||||
*
|
||||
* If the address can't be resolved, a std::runtime_error
|
||||
* exception is thrown.
|
||||
*
|
||||
* This method sends and receives the packet through
|
||||
* PacketSender::default_interface.
|
||||
*
|
||||
* \param ip The ip to resolve, in integer format.
|
||||
* \param sender The sender to use to send and receive the ARP requests.
|
||||
* \return HWAddress<6> containing the resolved hardware address.
|
||||
*/
|
||||
TINS_API HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender);
|
||||
|
||||
/** \brief List all network interfaces.
|
||||
*
|
||||
* Returns a set of strings, each of them representing the name
|
||||
* of a network interface. These names can be used as the input
|
||||
* interface for Utils::interface_ip, Utils::interface_hwaddr, etc.
|
||||
*/
|
||||
TINS_API std::set<std::string> network_interfaces();
|
||||
|
||||
/**
|
||||
* \brief Finds the gateway's IP address for the given IP
|
||||
* address.
|
||||
*
|
||||
* \param ip The IP address for which the default gateway will
|
||||
* be searched.
|
||||
* \param gw_addr This parameter will contain the gateway's IP
|
||||
* address in case it is found.
|
||||
*
|
||||
* \return bool indicating whether the lookup was successfull.
|
||||
*/
|
||||
TINS_API bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \brief output ForwardIterator in which entries will be stored.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
void route_entries(ForwardIterator output);
|
||||
|
||||
/**
|
||||
* \brief Retrieves entries in the routing table.
|
||||
*
|
||||
* \return a vector which contains all of the route entries.
|
||||
*/
|
||||
TINS_API std::vector<RouteEntry> route_entries();
|
||||
|
||||
/** \brief Returns the 32 bit crc of the given buffer.
|
||||
*
|
||||
* \param data The input buffer.
|
||||
* \param data_size The size of the input buffer.
|
||||
*/
|
||||
TINS_API uint32_t crc32(const uint8_t* data, uint32_t data_size);
|
||||
|
||||
/**
|
||||
* \brief Converts a channel number to its mhz representation.
|
||||
* \param channel The channel number.
|
||||
* \return The channel's mhz representation.
|
||||
*/
|
||||
TINS_API uint16_t channel_to_mhz(uint16_t channel);
|
||||
|
||||
/**
|
||||
* \brief Converts mhz units to the appropriate channel number.
|
||||
* \param mhz The mhz units to be converted.
|
||||
* \return The channel number.
|
||||
*/
|
||||
TINS_API uint16_t mhz_to_channel(uint16_t mhz);
|
||||
|
||||
/**
|
||||
* \brief Converts a PDUType to a string.
|
||||
* \param pduType The PDUType to be converted.
|
||||
* \return A string representation, for example "DOT11_QOS_DATA".
|
||||
*/
|
||||
TINS_API std::string to_string(PDU::PDUType pduType);
|
||||
|
||||
/**
|
||||
* \brief Does the 16 bits sum of all 2 bytes elements between start and end.
|
||||
*
|
||||
* This is the checksum used by IP, UDP and TCP. If there's and odd number of
|
||||
* bytes, the last one is padded and added to the checksum.
|
||||
* \param start The pointer to the start of the buffer.
|
||||
* \param end The pointer to the end of the buffer(excluding the last element).
|
||||
* \return Returns the checksum between start and end (non inclusive)
|
||||
* in network endian
|
||||
*/
|
||||
TINS_API uint32_t do_checksum(const uint8_t* start, const uint8_t* end);
|
||||
|
||||
/**
|
||||
* \brief Computes the 16 bit sum of the input buffer.
|
||||
*
|
||||
* If there's and odd number of bytes in the buffer, the last one is padded and
|
||||
* added to the checksum.
|
||||
* \param start The pointer to the start of the buffer.
|
||||
* \param end The pointer to the end of the buffer(excluding the last element).
|
||||
* \return Returns the checksum between start and end (non inclusive)
|
||||
* in network endian
|
||||
*/
|
||||
TINS_API uint16_t sum_range(const uint8_t* start, const uint8_t* end);
|
||||
|
||||
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
|
||||
*
|
||||
* \param source_ip The source ip address.
|
||||
* \param dest_ip The destination ip address.
|
||||
* \param len The length to be included in the pseudo header.
|
||||
* \param flag The flag to use in the protocol field of the pseudo header.
|
||||
* \return The pseudo header checksum.
|
||||
*/
|
||||
TINS_API uint32_t pseudoheader_checksum(IPv4Address source_ip,
|
||||
IPv4Address dest_ip,
|
||||
uint16_t len,
|
||||
uint16_t flag);
|
||||
|
||||
/** \brief Performs the pseudo header checksum used in TCP and UDP PDUs.
|
||||
*
|
||||
* \param source_ip The source ip address.
|
||||
* \param dest_ip The destination ip address.
|
||||
* \param len The length to be included in the pseudo header.
|
||||
* \param flag The flag to use in the protocol field of the pseudo header.
|
||||
* \return The pseudo header checksum.
|
||||
*/
|
||||
TINS_API uint32_t pseudoheader_checksum(IPv6Address source_ip,
|
||||
IPv6Address dest_ip,
|
||||
uint16_t len,
|
||||
uint16_t flag);
|
||||
|
||||
template <typename T>
|
||||
struct is_pdu {
|
||||
template <typename U>
|
||||
static char test(typename U::PDUType*);
|
||||
|
||||
template <typename U>
|
||||
static long test(...);
|
||||
|
||||
static const bool value = sizeof(test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the argument.
|
||||
*/
|
||||
inline PDU& dereference_until_pdu(PDU& pdu) {
|
||||
return pdu;
|
||||
}
|
||||
#else
|
||||
template<class ForwardIterator>
|
||||
|
||||
/**
|
||||
* \brief Dereferences the parameter until a PDU is found.
|
||||
*
|
||||
* This function dereferences the parameter until a PDU object
|
||||
* is found. When it's found, it is returned.
|
||||
*
|
||||
* \param value The parameter to be dereferenced.
|
||||
*/
|
||||
template<typename T>
|
||||
inline typename Internals::enable_if<!is_pdu<T>::value, PDU&>::type
|
||||
dereference_until_pdu(T& value) {
|
||||
return dereference_until_pdu(*value);
|
||||
}
|
||||
|
||||
} // Utils
|
||||
} // Tins
|
||||
|
||||
template<typename ForwardIterator>
|
||||
void Tins::Utils::route_entries(ForwardIterator output) {
|
||||
using namespace Tins::Internals;
|
||||
std::ifstream input("/proc/net/route");
|
||||
std::string destination, mask, gw;
|
||||
uint32_t dummy;
|
||||
skip_line(input);
|
||||
RouteEntry entry;
|
||||
while(input >> entry.interface >> destination >> gw) {
|
||||
for(unsigned i(0); i < 5; ++i)
|
||||
input >> mask;
|
||||
from_hex(destination, dummy);
|
||||
entry.destination = IPv4Address(dummy);
|
||||
from_hex(mask, dummy);
|
||||
entry.mask = IPv4Address(dummy);
|
||||
from_hex(gw, dummy);
|
||||
entry.gateway = IPv4Address(dummy);
|
||||
skip_line(input);
|
||||
*output = entry;
|
||||
std::vector<RouteEntry> entries = route_entries();
|
||||
for (size_t i = 0; i < entries.size(); ++i) {
|
||||
*output = entries[i];
|
||||
++output;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // TINS_UTILS_H
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
SET(LIBTINS_INCLUDE_DIR ../include/tins/)
|
||||
|
||||
IF(HAVE_PCAP_IMMEDIATE_MODE)
|
||||
ADD_DEFINITIONS("-DHAVE_PCAP_IMMEDIATE_MODE=1")
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
${LIBTINS_INCLUDE_DIR}
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
@@ -21,6 +25,7 @@ ADD_LIBRARY(
|
||||
dot1q.cpp
|
||||
eapol.cpp
|
||||
ethernetII.cpp
|
||||
icmp_extension.cpp
|
||||
icmp.cpp
|
||||
icmpv6.cpp
|
||||
internals.cpp
|
||||
@@ -32,6 +37,7 @@ ADD_LIBRARY(
|
||||
ipsec.cpp
|
||||
llc.cpp
|
||||
loopback.cpp
|
||||
mpls.cpp
|
||||
network_interface.cpp
|
||||
offline_packet_filter.cpp
|
||||
packet_sender.cpp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,22 +31,27 @@
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
|
||||
using std::logic_error;
|
||||
|
||||
namespace Tins {
|
||||
IPv4Range operator/(const IPv4Address &addr, int mask) {
|
||||
if(mask > 32)
|
||||
throw std::logic_error("Prefix length cannot exceed 32");
|
||||
|
||||
IPv4Range operator/(const IPv4Address& addr, int mask) {
|
||||
if (mask > 32) {
|
||||
throw logic_error("Prefix length cannot exceed 32");
|
||||
}
|
||||
return IPv4Range::from_mask(
|
||||
addr,
|
||||
IPv4Address(Endian::host_to_be(0xffffffff << (32 - mask)))
|
||||
);
|
||||
}
|
||||
|
||||
IPv6Range operator/(const IPv6Address &addr, int mask) {
|
||||
if(mask > 128)
|
||||
IPv6Range operator/(const IPv6Address& addr, int mask) {
|
||||
if (mask > 128) {
|
||||
throw std::logic_error("Prefix length cannot exceed 128");
|
||||
}
|
||||
IPv6Address last_addr;
|
||||
IPv6Address::iterator it = last_addr.begin();
|
||||
while(mask > 8) {
|
||||
while (mask > 8) {
|
||||
*it = 0xff;
|
||||
++it;
|
||||
mask -= 8;
|
||||
@@ -54,4 +59,5 @@ IPv6Range operator/(const IPv6Address &addr, int mask) {
|
||||
*it = 0xff << (8 - mask);
|
||||
return IPv6Range::from_mask(addr, last_addr);
|
||||
}
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
112
src/arp.cpp
112
src/arp.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,7 +28,6 @@
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include "arp.h"
|
||||
#include "ip.h"
|
||||
@@ -37,16 +36,18 @@
|
||||
#include "constants.h"
|
||||
#include "network_interface.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
|
||||
using std::runtime_error;
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
ARP::ARP(ipaddress_type target_ip, ipaddress_type sender_ip,
|
||||
const hwaddress_type &target_hw, const hwaddress_type &sender_hw)
|
||||
{
|
||||
memset(&_arp, 0, sizeof(arphdr));
|
||||
ARP::ARP(ipaddress_type target_ip,
|
||||
ipaddress_type sender_ip,
|
||||
const hwaddress_type& target_hw,
|
||||
const hwaddress_type& sender_hw)
|
||||
: header_() {
|
||||
hw_addr_format((uint16_t)Constants::ARP::ETHER);
|
||||
prot_addr_format((uint16_t)Constants::Ethernet::IP);
|
||||
hw_addr_length(Tins::EthernetII::address_type::address_size);
|
||||
@@ -57,93 +58,92 @@ ARP::ARP(ipaddress_type target_ip, ipaddress_type sender_ip,
|
||||
target_hw_addr(target_hw);
|
||||
}
|
||||
|
||||
ARP::ARP(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
if(total_sz < sizeof(arphdr))
|
||||
throw malformed_packet();
|
||||
memcpy(&_arp, buffer, sizeof(arphdr));
|
||||
total_sz -= sizeof(arphdr);
|
||||
//TODO: Check whether this should be removed or not.
|
||||
if(total_sz)
|
||||
inner_pdu(new RawPDU(buffer + sizeof(arphdr), total_sz));
|
||||
ARP::ARP(const uint8_t* buffer, uint32_t total_sz) {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.read(header_);
|
||||
if (stream) {
|
||||
inner_pdu(new RawPDU(stream.pointer(), stream.size()));
|
||||
}
|
||||
}
|
||||
|
||||
void ARP::sender_hw_addr(const hwaddress_type &new_snd_hw_addr) {
|
||||
std::copy(new_snd_hw_addr.begin(), new_snd_hw_addr.end(), _arp.ar_sha);
|
||||
void ARP::sender_hw_addr(const hwaddress_type& address) {
|
||||
address.copy(header_.sender_hw_address);
|
||||
}
|
||||
|
||||
void ARP::sender_ip_addr(ipaddress_type new_snd_ip_addr) {
|
||||
this->_arp.ar_sip = new_snd_ip_addr;
|
||||
void ARP::sender_ip_addr(ipaddress_type address) {
|
||||
header_.sender_ip_address = address;
|
||||
}
|
||||
|
||||
void ARP::target_hw_addr(const hwaddress_type &new_tgt_hw_addr) {
|
||||
std::copy(new_tgt_hw_addr.begin(), new_tgt_hw_addr.end(), _arp.ar_tha);
|
||||
void ARP::target_hw_addr(const hwaddress_type& address) {
|
||||
address.copy(header_.target_hw_address);
|
||||
}
|
||||
|
||||
void ARP::target_ip_addr(ipaddress_type new_tgt_ip_addr) {
|
||||
this->_arp.ar_tip = new_tgt_ip_addr;
|
||||
void ARP::target_ip_addr(ipaddress_type address) {
|
||||
header_.target_ip_address = address;
|
||||
}
|
||||
|
||||
void ARP::hw_addr_format(uint16_t new_hw_addr_fmt) {
|
||||
this->_arp.ar_hrd = Endian::host_to_be(new_hw_addr_fmt);
|
||||
void ARP::hw_addr_format(uint16_t format) {
|
||||
header_.hw_address_format = Endian::host_to_be(format);
|
||||
}
|
||||
|
||||
void ARP::prot_addr_format(uint16_t new_prot_addr_fmt) {
|
||||
this->_arp.ar_pro = Endian::host_to_be(new_prot_addr_fmt);
|
||||
void ARP::prot_addr_format(uint16_t format) {
|
||||
header_.proto_address_format = Endian::host_to_be(format);
|
||||
}
|
||||
|
||||
void ARP::hw_addr_length(uint8_t new_hw_addr_len) {
|
||||
this->_arp.ar_hln = new_hw_addr_len;
|
||||
void ARP::hw_addr_length(uint8_t length) {
|
||||
header_.hw_address_length = length;
|
||||
}
|
||||
|
||||
void ARP::prot_addr_length(uint8_t new_prot_addr_len) {
|
||||
this->_arp.ar_pln = new_prot_addr_len;
|
||||
void ARP::prot_addr_length(uint8_t length) {
|
||||
header_.proto_address_length = length;
|
||||
}
|
||||
|
||||
void ARP::opcode(Flags new_opcode) {
|
||||
this->_arp.ar_op = Endian::host_to_be<uint16_t>(new_opcode);
|
||||
void ARP::opcode(Flags code) {
|
||||
header_.opcode = Endian::host_to_be<uint16_t>(code);
|
||||
}
|
||||
|
||||
uint32_t ARP::header_size() const {
|
||||
return sizeof(arphdr);
|
||||
return sizeof(header_);
|
||||
}
|
||||
|
||||
void ARP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(arphdr));
|
||||
#endif
|
||||
memcpy(buffer, &_arp, sizeof(arphdr));
|
||||
void ARP::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *) {
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(header_);
|
||||
}
|
||||
|
||||
bool ARP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
if(total_sz < sizeof(arphdr))
|
||||
bool ARP::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
||||
if (total_sz < sizeof(header_)) {
|
||||
return false;
|
||||
const arphdr *arp_ptr = (const arphdr*)ptr;
|
||||
return arp_ptr->ar_sip == _arp.ar_tip && arp_ptr->ar_tip == _arp.ar_sip;
|
||||
}
|
||||
const arp_header* arp_ptr = (const arp_header*)ptr;
|
||||
return arp_ptr->sender_ip_address == header_.target_ip_address &&
|
||||
arp_ptr->target_ip_address == header_.sender_ip_address;
|
||||
}
|
||||
|
||||
EthernetII ARP::make_arp_request(ipaddress_type target, ipaddress_type sender,
|
||||
const hwaddress_type &hw_snd)
|
||||
{
|
||||
/* Create ARP packet and set its attributes */
|
||||
EthernetII ARP::make_arp_request(ipaddress_type target,
|
||||
ipaddress_type sender,
|
||||
const hwaddress_type& hw_snd) {
|
||||
// Create ARP packet and set its attributes
|
||||
ARP arp;
|
||||
arp.target_ip_addr(target);
|
||||
arp.sender_ip_addr(sender);
|
||||
arp.sender_hw_addr(hw_snd);
|
||||
arp.opcode(REQUEST);
|
||||
|
||||
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
|
||||
// Create the EthernetII PDU with the ARP PDU as its inner PDU
|
||||
return EthernetII(EthernetII::BROADCAST, hw_snd) / arp;
|
||||
}
|
||||
|
||||
EthernetII ARP::make_arp_reply(ipaddress_type target, ipaddress_type sender,
|
||||
const hwaddress_type &hw_tgt, const hwaddress_type &hw_snd)
|
||||
{
|
||||
/* Create ARP packet and set its attributes */
|
||||
EthernetII ARP::make_arp_reply(ipaddress_type target,
|
||||
ipaddress_type sender,
|
||||
const hwaddress_type& hw_tgt,
|
||||
const hwaddress_type& hw_snd) {
|
||||
// Create ARP packet and set its attributes
|
||||
ARP arp(target, sender, hw_tgt, hw_snd);
|
||||
arp.opcode(REPLY);
|
||||
|
||||
/* Create the EthernetII PDU with the ARP PDU as its inner PDU */
|
||||
// Create the EthernetII PDU with the ARP PDU as its inner PDU
|
||||
return EthernetII(hw_tgt, hw_snd) / arp;
|
||||
}
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
112
src/bootp.cpp
112
src/bootp.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -29,102 +29,104 @@
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include "bootp.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using std::copy;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins{
|
||||
|
||||
BootP::BootP()
|
||||
: _vend(64) {
|
||||
std::memset(&_bootp, 0, sizeof(bootphdr));
|
||||
: bootp_(), vend_(64) {
|
||||
|
||||
}
|
||||
|
||||
BootP::BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size)
|
||||
: _vend(vend_field_size)
|
||||
{
|
||||
if(total_sz < sizeof(bootphdr) + vend_field_size)
|
||||
BootP::BootP(const uint8_t* buffer, uint32_t total_sz, uint32_t vend_field_size)
|
||||
: vend_(vend_field_size) {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.read(bootp_);
|
||||
if (!stream.can_read(vend_field_size)) {
|
||||
throw malformed_packet();
|
||||
std::memcpy(&_bootp, buffer, sizeof(bootphdr));
|
||||
buffer += sizeof(bootphdr);
|
||||
total_sz -= sizeof(bootphdr);
|
||||
_vend.assign(buffer, buffer + vend_field_size);
|
||||
// Maybe RawPDU on what is left on the buffer?...
|
||||
}
|
||||
stream.read(vend_, vend_field_size);
|
||||
}
|
||||
|
||||
uint32_t BootP::header_size() const {
|
||||
return sizeof(bootphdr) + _vend.size();
|
||||
return static_cast<uint32_t>(sizeof(bootp_) + vend_.size());
|
||||
}
|
||||
|
||||
void BootP::opcode(uint8_t new_opcode) {
|
||||
_bootp.opcode = new_opcode;
|
||||
void BootP::opcode(uint8_t code) {
|
||||
bootp_.opcode = code;
|
||||
}
|
||||
|
||||
void BootP::htype(uint8_t new_htype) {
|
||||
_bootp.htype = new_htype;
|
||||
void BootP::htype(uint8_t type) {
|
||||
bootp_.htype = type;
|
||||
}
|
||||
|
||||
void BootP::hlen(uint8_t new_hlen) {
|
||||
_bootp.hlen = new_hlen;
|
||||
void BootP::hlen(uint8_t length) {
|
||||
bootp_.hlen = length;
|
||||
}
|
||||
|
||||
void BootP::hops(uint8_t new_hops) {
|
||||
_bootp.hops = new_hops;
|
||||
void BootP::hops(uint8_t count) {
|
||||
bootp_.hops = count;
|
||||
}
|
||||
|
||||
void BootP::xid(uint32_t new_xid) {
|
||||
_bootp.xid = Endian::host_to_be(new_xid);
|
||||
void BootP::xid(uint32_t identifier) {
|
||||
bootp_.xid = Endian::host_to_be(identifier);
|
||||
}
|
||||
|
||||
void BootP::secs(uint16_t new_secs) {
|
||||
_bootp.secs = Endian::host_to_be(new_secs);
|
||||
void BootP::secs(uint16_t value) {
|
||||
bootp_.secs = Endian::host_to_be(value);
|
||||
}
|
||||
|
||||
void BootP::padding(uint16_t new_padding) {
|
||||
_bootp.padding = Endian::host_to_be(new_padding);
|
||||
void BootP::padding(uint16_t value) {
|
||||
bootp_.padding = Endian::host_to_be(value);
|
||||
}
|
||||
|
||||
void BootP::ciaddr(ipaddress_type new_ciaddr) {
|
||||
_bootp.ciaddr = new_ciaddr;
|
||||
void BootP::ciaddr(ipaddress_type address) {
|
||||
bootp_.ciaddr = address;
|
||||
}
|
||||
|
||||
void BootP::yiaddr(ipaddress_type new_yiaddr) {
|
||||
_bootp.yiaddr = new_yiaddr;
|
||||
void BootP::yiaddr(ipaddress_type address) {
|
||||
bootp_.yiaddr = address;
|
||||
}
|
||||
|
||||
void BootP::siaddr(ipaddress_type new_siaddr) {
|
||||
_bootp.siaddr = new_siaddr;
|
||||
void BootP::siaddr(ipaddress_type address) {
|
||||
bootp_.siaddr = address;
|
||||
}
|
||||
|
||||
void BootP::giaddr(ipaddress_type new_giaddr) {
|
||||
_bootp.giaddr = new_giaddr;
|
||||
void BootP::giaddr(ipaddress_type address) {
|
||||
bootp_.giaddr = address;
|
||||
}
|
||||
|
||||
void BootP::sname(const uint8_t *new_sname) {
|
||||
//std::memcpy(_bootp.sname, new_sname, sizeof(_bootp.sname));
|
||||
std::copy(new_sname, new_sname + sizeof(_bootp.sname), _bootp.sname);
|
||||
void BootP::sname(const uint8_t* new_sname) {
|
||||
copy(new_sname, new_sname + sizeof(bootp_.sname), bootp_.sname);
|
||||
}
|
||||
|
||||
void BootP::file(const uint8_t *new_file) {
|
||||
//std::memcpy(_bootp.file, new_file, sizeof(_bootp.file));
|
||||
std::copy(new_file, new_file + sizeof(_bootp.file), _bootp.file);
|
||||
void BootP::file(const uint8_t* new_file) {
|
||||
copy(new_file, new_file + sizeof(bootp_.file), bootp_.file);
|
||||
}
|
||||
|
||||
void BootP::vend(const vend_type &new_vend) {
|
||||
_vend = new_vend;
|
||||
void BootP::vend(const vend_type& newvend_) {
|
||||
vend_ = newvend_;
|
||||
}
|
||||
|
||||
void BootP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(bootphdr) + _vend.size());
|
||||
#endif
|
||||
std::memcpy(buffer, &_bootp, sizeof(bootphdr));
|
||||
std::copy(_vend.begin(), _vend.end(), buffer + sizeof(bootphdr));
|
||||
void BootP::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent) {
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(bootp_);
|
||||
stream.write(vend_.begin(), vend_.end());
|
||||
}
|
||||
|
||||
bool BootP::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
if(total_sz < sizeof(bootphdr))
|
||||
bool BootP::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
||||
if (total_sz < sizeof(bootp_)) {
|
||||
return false;
|
||||
const bootphdr *bootp_ptr = (const bootphdr *)ptr;
|
||||
return bootp_ptr->xid == _bootp.xid;
|
||||
}
|
||||
}
|
||||
const bootp_header* bootp_ptr = (const bootp_header *)ptr;
|
||||
return bootp_ptr->xid == bootp_.xid;
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
394
src/crypto.cpp
394
src/crypto.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -38,43 +38,59 @@
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
#include "dot11/dot11_data.h"
|
||||
#include "dot11/dot11_beacon.h"
|
||||
#include "exceptions.h"
|
||||
|
||||
using std::string;
|
||||
using std::make_pair;
|
||||
using std::equal;
|
||||
using std::copy;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::lexicographical_compare;
|
||||
using std::fill;
|
||||
using std::runtime_error;
|
||||
|
||||
namespace Tins {
|
||||
namespace Crypto {
|
||||
|
||||
WEPDecrypter::WEPDecrypter()
|
||||
: key_buffer(4) {
|
||||
: key_buffer_(4) {
|
||||
|
||||
}
|
||||
|
||||
void WEPDecrypter::add_password(const address_type &addr, const std::string &password) {
|
||||
passwords[addr] = password;
|
||||
key_buffer.resize(std::max(3 + password.size(), key_buffer.size()));
|
||||
void WEPDecrypter::add_password(const address_type& addr, const string& password) {
|
||||
passwords_[addr] = password;
|
||||
key_buffer_.resize(max(3 + password.size(), key_buffer_.size()));
|
||||
}
|
||||
|
||||
void WEPDecrypter::remove_password(const address_type &addr) {
|
||||
passwords.erase(addr);
|
||||
void WEPDecrypter::remove_password(const address_type& addr) {
|
||||
passwords_.erase(addr);
|
||||
}
|
||||
|
||||
bool WEPDecrypter::decrypt(PDU &pdu) {
|
||||
Dot11Data *dot11 = pdu.find_pdu<Dot11Data>();
|
||||
if(dot11) {
|
||||
RawPDU *raw = dot11->find_pdu<RawPDU>();
|
||||
if(raw) {
|
||||
bool WEPDecrypter::decrypt(PDU& pdu) {
|
||||
Dot11Data* dot11 = pdu.find_pdu<Dot11Data>();
|
||||
if (dot11) {
|
||||
RawPDU* raw = dot11->find_pdu<RawPDU>();
|
||||
if (raw) {
|
||||
address_type addr;
|
||||
if(!dot11->from_ds() && !dot11->to_ds())
|
||||
if (!dot11->from_ds() && !dot11->to_ds()) {
|
||||
addr = dot11->addr3();
|
||||
else if(!dot11->from_ds() && dot11->to_ds())
|
||||
}
|
||||
else if (!dot11->from_ds() && dot11->to_ds()) {
|
||||
addr = dot11->addr1();
|
||||
else if(dot11->from_ds() && !dot11->to_ds())
|
||||
}
|
||||
else if (dot11->from_ds() && !dot11->to_ds()) {
|
||||
addr = dot11->addr2();
|
||||
else
|
||||
}
|
||||
else {
|
||||
// ????
|
||||
addr = dot11->addr3();
|
||||
passwords_type::iterator it = passwords.find(addr);
|
||||
if(it != passwords.end()) {
|
||||
}
|
||||
passwords_type::iterator it = passwords_.find(addr);
|
||||
if (it != passwords_.end()) {
|
||||
dot11->inner_pdu(decrypt(*raw, it->second));
|
||||
// If its valid, then return true
|
||||
if(dot11->inner_pdu()) {
|
||||
if (dot11->inner_pdu()) {
|
||||
// it's no longer encrypted.
|
||||
dot11->wep(0);
|
||||
return true;
|
||||
@@ -85,28 +101,31 @@ bool WEPDecrypter::decrypt(PDU &pdu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PDU *WEPDecrypter::decrypt(RawPDU &raw, const std::string &password) {
|
||||
RawPDU::payload_type &pload = raw.payload();
|
||||
PDU* WEPDecrypter::decrypt(RawPDU& raw, const string& password) {
|
||||
RawPDU::payload_type& pload = raw.payload();
|
||||
// We require at least the IV, the encrypted checksum and something to decrypt
|
||||
if(pload.size() <= 8)
|
||||
if (pload.size() <= 8) {
|
||||
return 0;
|
||||
std::copy(pload.begin(), pload.begin() + 3, key_buffer.begin());
|
||||
std::copy(password.begin(), password.end(), key_buffer.begin() + 3);
|
||||
}
|
||||
copy(pload.begin(), pload.begin() + 3, key_buffer_.begin());
|
||||
copy(password.begin(), password.end(), key_buffer_.begin() + 3);
|
||||
|
||||
// Generate the key
|
||||
RC4Key key(key_buffer.begin(), key_buffer.begin() + password.size() + 3);
|
||||
RC4Key key(key_buffer_.begin(), key_buffer_.begin() + password.size() + 3);
|
||||
rc4(pload.begin() + 4, pload.end(), key, pload.begin());
|
||||
uint32_t crc = Utils::crc32(&pload[0], pload.size() - 8);
|
||||
if(pload[pload.size() - 8] != (crc & 0xff) ||
|
||||
uint32_t payload_size = static_cast<uint32_t>(pload.size() - 8);
|
||||
uint32_t crc = Utils::crc32(&pload[0], payload_size);
|
||||
if (pload[pload.size() - 8] != (crc & 0xff) ||
|
||||
pload[pload.size() - 7] != ((crc >> 8) & 0xff) ||
|
||||
pload[pload.size() - 6] != ((crc >> 16) & 0xff) ||
|
||||
pload[pload.size() - 5] != ((crc >> 24) & 0xff))
|
||||
pload[pload.size() - 5] != ((crc >> 24) & 0xff)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
return new SNAP(&pload[0], pload.size() - 8);
|
||||
return new SNAP(&pload[0], payload_size);
|
||||
}
|
||||
catch(std::runtime_error&) {
|
||||
catch (exception_base&) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -114,17 +133,19 @@ PDU *WEPDecrypter::decrypt(RawPDU &raw, const std::string &password) {
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
// WPA2Decrypter
|
||||
|
||||
const HWAddress<6> &min(const HWAddress<6>& lhs, const HWAddress<6>& rhs) {
|
||||
using WPA2::SessionKeys;
|
||||
|
||||
const HWAddress<6>& min(const HWAddress<6>& lhs, const HWAddress<6>& rhs) {
|
||||
return lhs < rhs ? lhs : rhs;
|
||||
}
|
||||
|
||||
const HWAddress<6> &max(const HWAddress<6>& lhs, const HWAddress<6>& rhs) {
|
||||
const HWAddress<6>& max(const HWAddress<6>& lhs, const HWAddress<6>& rhs) {
|
||||
return lhs < rhs ? rhs : lhs;
|
||||
}
|
||||
|
||||
template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
|
||||
void xor_range(InputIterator1 src1, InputIterator2 src2, OutputIterator dst, size_t sz) {
|
||||
for(size_t i = 0; i < sz; ++i) {
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
*dst++ = *src1++ ^ *src2++;
|
||||
}
|
||||
}
|
||||
@@ -220,54 +241,77 @@ uint16_t lower_byte(uint16_t value) {
|
||||
return value & 0xff;
|
||||
}
|
||||
|
||||
HWAddress<6> get_bssid(const Dot11Data &dot11) {
|
||||
if(dot11.from_ds() && !dot11.to_ds())
|
||||
HWAddress<6> get_bssid(const Dot11Data& dot11) {
|
||||
if (dot11.from_ds() && !dot11.to_ds()) {
|
||||
return dot11.addr3();
|
||||
else if(!dot11.from_ds() && dot11.to_ds())
|
||||
}
|
||||
else if (!dot11.from_ds() && dot11.to_ds()) {
|
||||
return dot11.addr2();
|
||||
else
|
||||
}
|
||||
else {
|
||||
return dot11.addr2();
|
||||
}
|
||||
}
|
||||
|
||||
namespace WPA2 {
|
||||
|
||||
const size_t SessionKeys::PTK_SIZE = 80;
|
||||
const size_t SessionKeys::PMK_SIZE = 32;
|
||||
|
||||
SessionKeys::SessionKeys() {
|
||||
|
||||
}
|
||||
|
||||
SessionKeys::SessionKeys(const RSNHandshake &hs, const pmk_type &pmk) {
|
||||
uint8_t PKE[100] = "Pairwise key expansion";
|
||||
uint8_t MIC[16];
|
||||
min(hs.client_address(), hs.supplicant_address()).copy(PKE + 23);
|
||||
max(hs.client_address(), hs.supplicant_address()).copy(PKE + 29);
|
||||
const uint8_t *nonce1 = hs.handshake()[1].nonce(),
|
||||
*nonce2 = hs.handshake()[2].nonce();
|
||||
if(std::lexicographical_compare(nonce1, nonce1 + 32, nonce2, nonce2 + 32)) {
|
||||
std::copy(nonce1, nonce1 + 32, PKE + 35);
|
||||
std::copy(nonce2, nonce2 + 32, PKE + 67);
|
||||
}
|
||||
else {
|
||||
std::copy(nonce2, nonce2 + 32, PKE + 35);
|
||||
std::copy(nonce1, nonce1 + 32, PKE + 67);
|
||||
}
|
||||
for(int i(0); i < 4; ++i) {
|
||||
PKE[99] = i;
|
||||
HMAC(EVP_sha1(), pmk.begin(), pmk.size(), PKE, 100, ptk.begin() + i * 20, 0);
|
||||
}
|
||||
PDU::serialization_type buffer = const_cast<RSNEAPOL&>(hs.handshake()[3]).serialize();
|
||||
std::fill(buffer.begin() + 81, buffer.begin() + 81 + 16, 0);
|
||||
if(hs.handshake()[3].key_descriptor() == 2)
|
||||
HMAC(EVP_sha1(), ptk.begin(), 16, &buffer[0], buffer.size(), MIC, 0);
|
||||
else
|
||||
HMAC(EVP_md5(), ptk.begin(), 16, &buffer[0], buffer.size(), MIC, 0);
|
||||
|
||||
if(!std::equal(MIC, MIC + sizeof(MIC), hs.handshake()[3].mic()))
|
||||
SessionKeys::SessionKeys(const ptk_type& ptk, bool is_ccmp)
|
||||
: ptk_(ptk), is_ccmp_(is_ccmp) {
|
||||
if (ptk_.size() != PTK_SIZE) {
|
||||
throw invalid_handshake();
|
||||
is_ccmp = (hs.handshake()[3].key_descriptor() == 2);
|
||||
}
|
||||
}
|
||||
|
||||
SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
|
||||
RawPDU::payload_type &pload = raw.payload();
|
||||
SessionKeys::SessionKeys(const RSNHandshake& hs, const pmk_type& pmk)
|
||||
: ptk_(PTK_SIZE) {
|
||||
if (pmk.size() != PMK_SIZE) {
|
||||
throw invalid_handshake();
|
||||
}
|
||||
|
||||
uint8_t PKE[100] = "Pairwise key expansion";
|
||||
uint8_t MIC[20];
|
||||
is_ccmp_ = (hs.handshake()[3].key_descriptor() == 2);
|
||||
|
||||
min(hs.client_address(), hs.supplicant_address()).copy(PKE + 23);
|
||||
max(hs.client_address(), hs.supplicant_address()).copy(PKE + 29);
|
||||
const uint8_t* nonce1 = hs.handshake()[1].nonce(),
|
||||
*nonce2 = hs.handshake()[2].nonce();
|
||||
if (lexicographical_compare(nonce1, nonce1 + 32, nonce2, nonce2 + 32)) {
|
||||
copy(nonce1, nonce1 + 32, PKE + 35);
|
||||
copy(nonce2, nonce2 + 32, PKE + 67);
|
||||
}
|
||||
else {
|
||||
copy(nonce2, nonce2 + 32, PKE + 35);
|
||||
copy(nonce1, nonce1 + 32, PKE + 67);
|
||||
}
|
||||
for (int i(0); i < 4; ++i) {
|
||||
PKE[99] = i;
|
||||
HMAC(EVP_sha1(), &pmk[0], pmk.size(), PKE, 100, &ptk_[0] + i * 20, 0);
|
||||
}
|
||||
RSNEAPOL& last_hs = const_cast<RSNEAPOL&>(hs.handshake()[3]);
|
||||
PDU::serialization_type buffer = last_hs.serialize();
|
||||
fill(buffer.begin() + 81, buffer.begin() + 81 + 16, 0);
|
||||
if (is_ccmp_) {
|
||||
HMAC(EVP_sha1(), &ptk_[0], 16, &buffer[0], buffer.size(), MIC, 0);
|
||||
}
|
||||
else {
|
||||
HMAC(EVP_md5(), &ptk_[0], 16, &buffer[0], buffer.size(), MIC, 0);
|
||||
}
|
||||
|
||||
if (!equal(MIC, MIC + RSNEAPOL::mic_size, last_hs.mic())) {
|
||||
throw invalid_handshake();
|
||||
}
|
||||
}
|
||||
|
||||
SNAP* SessionKeys::ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const {
|
||||
RawPDU::payload_type& pload = raw.payload();
|
||||
uint8_t MIC[16] = {0};
|
||||
uint8_t PN[6] = {
|
||||
pload[7],
|
||||
@@ -281,8 +325,9 @@ SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) con
|
||||
uint8_t AAD[32] = {0};
|
||||
AAD[0] = 0;
|
||||
AAD[1] = 22 + 6 * int(dot11.from_ds() && dot11.to_ds());
|
||||
if(dot11.subtype() == Dot11::QOS_DATA_DATA)
|
||||
if (dot11.subtype() == Dot11::QOS_DATA_DATA) {
|
||||
AAD[1] += 2;
|
||||
}
|
||||
AAD[2] = dot11.protocol() | (dot11.type() << 2) | ((dot11.subtype() << 4) & 0x80);
|
||||
AAD[3] = 0x40 | dot11.to_ds() | (dot11.from_ds() << 1) |
|
||||
(dot11.more_frag() << 2) | (dot11.order() << 7);
|
||||
@@ -293,11 +338,12 @@ SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) con
|
||||
AAD[22] = dot11.frag_num();
|
||||
AAD[23] = 0;
|
||||
|
||||
if(dot11.from_ds() && dot11.to_ds())
|
||||
if (dot11.from_ds() && dot11.to_ds()) {
|
||||
dot11.addr4().copy(AAD + 24);
|
||||
}
|
||||
|
||||
AES_KEY ctx;
|
||||
AES_set_encrypt_key(ptk.begin() + 32, 128, &ctx);
|
||||
AES_set_encrypt_key(&ptk_[0] + 32, 128, &ctx);
|
||||
uint8_t crypted_block[16];
|
||||
size_t total_sz = raw.payload_size() - 16, offset = 8, blocks = (total_sz + 15) / 16;
|
||||
|
||||
@@ -305,7 +351,7 @@ SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) con
|
||||
counter[0] = 0x59;
|
||||
counter[1] = 0;
|
||||
dot11.addr2().copy(counter + 2);
|
||||
std::copy(PN, PN + 6, counter + 8);
|
||||
copy(PN, PN + 6, counter + 8);
|
||||
counter[14] = (total_sz >> 8) & 0xff;
|
||||
counter[15] = total_sz & 0xff;
|
||||
|
||||
@@ -319,12 +365,13 @@ SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) con
|
||||
counter[14] = counter[15] = 0;
|
||||
AES_encrypt(counter, crypted_block, &ctx);
|
||||
uint8_t nice_MIC[8];
|
||||
std::copy(pload.begin() + pload.size() - 8, pload.end(), nice_MIC);
|
||||
copy(pload.begin() + pload.size() - 8, pload.end(), nice_MIC);
|
||||
xor_range(crypted_block, nice_MIC, nice_MIC, 8);
|
||||
for(size_t i = 1; i <= blocks; ++i) {
|
||||
for (size_t i = 1; i <= blocks; ++i) {
|
||||
size_t block_sz = (i == blocks) ? (total_sz % 16) : 16;
|
||||
if(block_sz == 0)
|
||||
if (block_sz == 0) {
|
||||
block_sz = 16;
|
||||
}
|
||||
counter[14] = (i >> 8) & 0xff;
|
||||
counter[15] = i & 0xff;
|
||||
AES_encrypt(counter, crypted_block, &ctx );
|
||||
@@ -335,14 +382,17 @@ SNAP *SessionKeys::ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) con
|
||||
AES_encrypt(MIC, MIC, &ctx);
|
||||
offset += block_sz;
|
||||
}
|
||||
return (std::equal(nice_MIC, nice_MIC + sizeof(nice_MIC), MIC)) ?
|
||||
new SNAP(&pload[0], total_sz) :
|
||||
0;
|
||||
if (equal(nice_MIC, nice_MIC + sizeof(nice_MIC), MIC)) {
|
||||
return new SNAP(&pload[0], total_sz);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RC4Key SessionKeys::generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const {
|
||||
const RawPDU::payload_type &pload = raw.payload();
|
||||
const uint8_t *tk = ptk.begin() + 32;
|
||||
RC4Key SessionKeys::generate_rc4_key(const Dot11Data& dot11, const RawPDU& raw) const {
|
||||
const RawPDU::payload_type& pload = raw.payload();
|
||||
const uint8_t* tk = &ptk_[0] + 32;
|
||||
Internals::byte_array<16> rc4_key;
|
||||
uint16_t ppk[6];
|
||||
const Dot11::address_type addr = dot11.addr2();
|
||||
@@ -353,7 +403,7 @@ RC4Key SessionKeys::generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw)
|
||||
ppk[3] = join_bytes(addr[3], addr[2]);
|
||||
ppk[4] = join_bytes(addr[5], addr[4]);
|
||||
|
||||
for(size_t i = 0; i < 4; ++i) {
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
ppk[0] += sbox(ppk[4] ^ join_bytes(tk[1], tk[0]));
|
||||
ppk[1] += sbox(ppk[0] ^ join_bytes(tk[5], tk[4]));
|
||||
ppk[2] += sbox(ppk[1] ^ join_bytes(tk[9], tk[8]));
|
||||
@@ -404,33 +454,44 @@ RC4Key SessionKeys::generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw)
|
||||
return RC4Key(rc4_key.begin(), rc4_key.end());
|
||||
}
|
||||
|
||||
SNAP *SessionKeys::tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
|
||||
SNAP* SessionKeys::tkip_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const {
|
||||
// at least 20 bytes for IV + crc + stuff
|
||||
if(raw.payload_size() <= 20)
|
||||
if (raw.payload_size() <= 20) {
|
||||
return 0;
|
||||
}
|
||||
Crypto::RC4Key key = generate_rc4_key(dot11, raw);
|
||||
RawPDU::payload_type &pload = raw.payload();
|
||||
RawPDU::payload_type& pload = raw.payload();
|
||||
rc4(pload.begin() + 8, pload.end(), key, pload.begin());
|
||||
|
||||
uint32_t crc = Utils::crc32(&pload[0], pload.size() - 12);
|
||||
if(pload[pload.size() - 12] != (crc & 0xff) ||
|
||||
if (pload[pload.size() - 12] != (crc & 0xff) ||
|
||||
pload[pload.size() - 11] != ((crc >> 8) & 0xff) ||
|
||||
pload[pload.size() - 10] != ((crc >> 16) & 0xff) ||
|
||||
pload[pload.size() - 9] != ((crc >> 24) & 0xff))
|
||||
pload[pload.size() - 9] != ((crc >> 24) & 0xff)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new SNAP(&pload[0], pload.size() - 20);
|
||||
}
|
||||
|
||||
SNAP *SessionKeys::decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const {
|
||||
return is_ccmp ?
|
||||
ccmp_decrypt_unicast(dot11, raw) :
|
||||
tkip_decrypt_unicast(dot11, raw);
|
||||
SNAP* SessionKeys::decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const {
|
||||
return is_ccmp_ ?
|
||||
ccmp_decrypt_unicast(dot11, raw) :
|
||||
tkip_decrypt_unicast(dot11, raw);
|
||||
}
|
||||
|
||||
const SessionKeys::ptk_type& SessionKeys::get_ptk() const {
|
||||
return ptk_;
|
||||
}
|
||||
|
||||
bool SessionKeys::uses_ccmp() const {
|
||||
return is_ccmp_;
|
||||
}
|
||||
|
||||
// supplicant_data
|
||||
|
||||
SupplicantData::SupplicantData(const std::string &psk, const std::string &ssid) {
|
||||
SupplicantData::SupplicantData(const string& psk, const string& ssid)
|
||||
: pmk_(SessionKeys::PMK_SIZE) {
|
||||
PKCS5_PBKDF2_HMAC_SHA1(
|
||||
psk.c_str(),
|
||||
psk.size(),
|
||||
@@ -438,101 +499,126 @@ SupplicantData::SupplicantData(const std::string &psk, const std::string &ssid)
|
||||
ssid.size(),
|
||||
4096,
|
||||
pmk_.size(),
|
||||
pmk_.begin()
|
||||
&pmk_[0]
|
||||
);
|
||||
}
|
||||
|
||||
const SupplicantData::pmk_type &SupplicantData::pmk() const {
|
||||
const SupplicantData::pmk_type& SupplicantData::pmk() const {
|
||||
return pmk_;
|
||||
}
|
||||
} // namespace WPA2
|
||||
|
||||
void WPA2Decrypter::add_ap_data(const std::string &psk, const std::string &ssid) {
|
||||
pmks.insert(std::make_pair(ssid, WPA2::SupplicantData(psk, ssid)));
|
||||
void WPA2Decrypter::add_ap_data(const string& psk, const string& ssid) {
|
||||
pmks_.insert(make_pair(ssid, WPA2::SupplicantData(psk, ssid)));
|
||||
}
|
||||
|
||||
void WPA2Decrypter::add_ap_data(const std::string &psk, const std::string &ssid,
|
||||
const address_type &addr)
|
||||
{
|
||||
void WPA2Decrypter::add_ap_data(const string& psk,
|
||||
const string& ssid,
|
||||
const address_type& addr) {
|
||||
add_ap_data(psk, ssid);
|
||||
add_access_point(ssid, addr);
|
||||
}
|
||||
|
||||
void WPA2Decrypter::add_access_point(const std::string &ssid, const address_type &addr) {
|
||||
pmks_map::const_iterator it = pmks.find(ssid);
|
||||
if(it == pmks.end())
|
||||
throw std::runtime_error("supplicant data not registered");
|
||||
aps.insert(std::make_pair(addr, it->second));
|
||||
void WPA2Decrypter::add_access_point(const string& ssid, const address_type& addr) {
|
||||
pmks_map::const_iterator it = pmks_.find(ssid);
|
||||
if (it == pmks_.end()) {
|
||||
throw runtime_error("Supplicant data not registered");
|
||||
}
|
||||
aps_.insert(make_pair(addr, it->second));
|
||||
}
|
||||
|
||||
void WPA2Decrypter::try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs) {
|
||||
void WPA2Decrypter::add_decryption_keys(const addr_pair& addresses,
|
||||
const SessionKeys& session_keys) {
|
||||
addr_pair sorted_pair = make_addr_pair(addresses.first, addresses.second);
|
||||
keys_[sorted_pair] = session_keys;
|
||||
}
|
||||
|
||||
void WPA2Decrypter::try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs) {
|
||||
bssids_map::const_iterator it = find_ap(dot11);
|
||||
if(it != aps.end()) {
|
||||
if (it != aps_.end()) {
|
||||
addr_pair addr_p = extract_addr_pair(dot11);
|
||||
try {
|
||||
WPA2::SessionKeys session(hs, it->second.pmk());
|
||||
keys[addr_p] = session;
|
||||
SessionKeys session(hs, it->second.pmk());
|
||||
keys_[addr_p] = session;
|
||||
}
|
||||
catch(WPA2::invalid_handshake&) {
|
||||
|
||||
}
|
||||
catch(WPA2::invalid_handshake&) { }
|
||||
}
|
||||
}
|
||||
|
||||
WPA2Decrypter::addr_pair WPA2Decrypter::extract_addr_pair(const Dot11Data &dot11) {
|
||||
if(dot11.from_ds() && !dot11.to_ds())
|
||||
const WPA2Decrypter::keys_map& WPA2Decrypter::get_keys() const {
|
||||
return keys_;
|
||||
}
|
||||
|
||||
WPA2Decrypter::addr_pair WPA2Decrypter::extract_addr_pair(const Dot11Data& dot11) {
|
||||
if (dot11.from_ds() && !dot11.to_ds()) {
|
||||
return make_addr_pair(dot11.addr2(), dot11.addr3());
|
||||
else if(!dot11.from_ds() && dot11.to_ds())
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr2());
|
||||
else
|
||||
return make_addr_pair(dot11.addr2(), dot11.addr3());
|
||||
}
|
||||
|
||||
WPA2Decrypter::addr_pair WPA2Decrypter::extract_addr_pair_dst(const Dot11Data &dot11) {
|
||||
if(dot11.from_ds() && !dot11.to_ds())
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr2());
|
||||
else if(!dot11.from_ds() && dot11.to_ds())
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr3());
|
||||
else
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr3());
|
||||
}
|
||||
|
||||
WPA2Decrypter::bssids_map::const_iterator WPA2Decrypter::find_ap(const Dot11Data &dot11) {
|
||||
if(dot11.from_ds() && !dot11.to_ds())
|
||||
return aps.find(dot11.addr2());
|
||||
else if(!dot11.from_ds() && dot11.to_ds())
|
||||
return aps.find(dot11.addr1());
|
||||
else
|
||||
return aps.find(dot11.addr3());
|
||||
}
|
||||
|
||||
bool WPA2Decrypter::decrypt(PDU &pdu) {
|
||||
if(capturer.process_packet(pdu)) {
|
||||
try_add_keys(pdu.rfind_pdu<Dot11Data>(), capturer.handshakes().front());
|
||||
capturer.clear_handshakes();
|
||||
}
|
||||
else if(const Dot11Beacon *beacon = pdu.find_pdu<Dot11Beacon>()) {
|
||||
if(aps.count(beacon->addr3()) == 0) {
|
||||
else if (!dot11.from_ds() && dot11.to_ds()) {
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr2());
|
||||
}
|
||||
else {
|
||||
return make_addr_pair(dot11.addr2(), dot11.addr3());
|
||||
}
|
||||
}
|
||||
|
||||
WPA2Decrypter::addr_pair WPA2Decrypter::extract_addr_pair_dst(const Dot11Data& dot11) {
|
||||
if (dot11.from_ds() && !dot11.to_ds()) {
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr2());
|
||||
}
|
||||
else if (!dot11.from_ds() && dot11.to_ds()) {
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr3());
|
||||
}
|
||||
else {
|
||||
return make_addr_pair(dot11.addr1(), dot11.addr3());
|
||||
}
|
||||
}
|
||||
|
||||
WPA2Decrypter::bssids_map::const_iterator WPA2Decrypter::find_ap(const Dot11Data& dot11) {
|
||||
if (dot11.from_ds() && !dot11.to_ds()) {
|
||||
return aps_.find(dot11.addr2());
|
||||
}
|
||||
else if (!dot11.from_ds() && dot11.to_ds()) {
|
||||
return aps_.find(dot11.addr1());
|
||||
}
|
||||
else {
|
||||
return aps_.find(dot11.addr3());
|
||||
}
|
||||
}
|
||||
|
||||
bool WPA2Decrypter::decrypt(PDU& pdu) {
|
||||
if (capturer_.process_packet(pdu)) {
|
||||
try_add_keys(pdu.rfind_pdu<Dot11Data>(), capturer_.handshakes().front());
|
||||
capturer_.clear_handshakes();
|
||||
}
|
||||
else if (const Dot11Beacon* beacon = pdu.find_pdu<Dot11Beacon>()) {
|
||||
if (aps_.count(beacon->addr3()) == 0) {
|
||||
try {
|
||||
std::string ssid = beacon->ssid();
|
||||
if(pmks.count(ssid)) {
|
||||
string ssid = beacon->ssid();
|
||||
if (pmks_.count(ssid)) {
|
||||
add_access_point(ssid, beacon->addr3());
|
||||
}
|
||||
}
|
||||
catch(option_not_found&) { }
|
||||
catch(option_not_found&) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Dot11Data *data = pdu.find_pdu<Dot11Data>();
|
||||
RawPDU *raw = pdu.find_pdu<RawPDU>();
|
||||
if(data && raw && data->wep()) {
|
||||
Dot11Data* data = pdu.find_pdu<Dot11Data>();
|
||||
RawPDU* raw = pdu.find_pdu<RawPDU>();
|
||||
if (data && raw && data->wep()) {
|
||||
// search for the tuple (bssid, src_addr)
|
||||
keys_map::const_iterator it = keys.find(extract_addr_pair(*data));
|
||||
keys_map::const_iterator it = keys_.find(extract_addr_pair(*data));
|
||||
|
||||
// search for the tuple (bssid, dst_addr) if the above didn't work
|
||||
if(it == keys.end())
|
||||
it = keys.find(extract_addr_pair_dst(*data));
|
||||
if(it != keys.end()) {
|
||||
SNAP *snap = it->second.decrypt_unicast(*data, *raw);
|
||||
if(snap) {
|
||||
if (it == keys_.end()) {
|
||||
it = keys_.find(extract_addr_pair_dst(*data));
|
||||
}
|
||||
if (it != keys_.end()) {
|
||||
SNAP* snap = it->second.decrypt_unicast(*data, *raw);
|
||||
if (snap) {
|
||||
data->inner_pdu(snap);
|
||||
data->wep(0);
|
||||
return true;
|
||||
@@ -541,8 +627,10 @@ bool WPA2Decrypter::decrypt(PDU &pdu) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} // namespace WPA2
|
||||
}
|
||||
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
} // namespace Crypto
|
||||
} // namespace Tins
|
||||
|
||||
|
||||
159
src/dhcp.cpp
159
src/dhcp.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,73 +28,92 @@
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include "endianness.h"
|
||||
#include "dhcp.h"
|
||||
#include "ethernetII.h"
|
||||
#include "internals.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::list;
|
||||
using std::runtime_error;
|
||||
using std::find_if;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
// Magic cookie: uint32_t.
|
||||
DHCP::DHCP() : _size(sizeof(uint32_t)) {
|
||||
DHCP::DHCP()
|
||||
: size_(sizeof(uint32_t)) {
|
||||
opcode(BOOTREQUEST);
|
||||
htype(1); //ethernet
|
||||
hlen(EthernetII::address_type::address_size);
|
||||
}
|
||||
|
||||
DHCP::DHCP(const uint8_t *buffer, uint32_t total_sz)
|
||||
: BootP(buffer, total_sz, 0), _size(sizeof(uint32_t))
|
||||
{
|
||||
buffer += BootP::header_size() - vend().size();
|
||||
total_sz -= BootP::header_size() - vend().size();
|
||||
uint8_t args[2] = {0};
|
||||
uint32_t uint32_t_buffer;
|
||||
std::memcpy(&uint32_t_buffer, buffer, sizeof(uint32_t));
|
||||
if(total_sz < sizeof(uint32_t) || uint32_t_buffer != Endian::host_to_be<uint32_t>(0x63825363))
|
||||
DHCP::DHCP(const uint8_t* buffer, uint32_t total_sz)
|
||||
: BootP(buffer, total_sz, 0), size_(sizeof(uint32_t)) {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.skip(BootP::header_size() - vend().size());
|
||||
const uint32_t magic_number = stream.read<uint32_t>();
|
||||
if (magic_number != Endian::host_to_be<uint32_t>(0x63825363)) {
|
||||
throw malformed_packet();
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint32_t);
|
||||
while(total_sz) {
|
||||
for(unsigned i(0); i < 2; ++i) {
|
||||
args[i] = *(buffer++);
|
||||
total_sz--;
|
||||
if(args[0] == END || args[0] == PAD) {
|
||||
args[1] = 0;
|
||||
i = 2;
|
||||
}
|
||||
else if(!total_sz)
|
||||
throw malformed_packet();
|
||||
}
|
||||
// While there's data left
|
||||
while (stream) {
|
||||
OptionTypes option_type;
|
||||
uint8_t option_length = 0;
|
||||
option_type = (OptionTypes)stream.read<uint8_t>();
|
||||
// We should only read the length if it's not END nor PAD
|
||||
if (option_type != END && option_type != PAD) {
|
||||
option_length = stream.read<uint8_t>();
|
||||
}
|
||||
if(total_sz < args[1])
|
||||
// Make sure we can read the payload size
|
||||
if (!stream.can_read(option_length)) {
|
||||
throw malformed_packet();
|
||||
add_option(
|
||||
option((OptionTypes)args[0], args[1], buffer)
|
||||
);
|
||||
buffer += args[1];
|
||||
total_sz -= args[1];
|
||||
}
|
||||
add_option(option(option_type, option_length, stream.pointer()));
|
||||
stream.skip(option_length);
|
||||
}
|
||||
}
|
||||
|
||||
void DHCP::add_option(const option &opt) {
|
||||
void DHCP::add_option(const option& opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(opt);
|
||||
options_.push_back(opt);
|
||||
}
|
||||
|
||||
void DHCP::internal_add_option(const option &opt) {
|
||||
_size += opt.data_size() + (sizeof(uint8_t) << 1);
|
||||
void DHCP::internal_add_option(const option& opt) {
|
||||
size_ += static_cast<uint32_t>(opt.data_size() + (sizeof(uint8_t) << 1));
|
||||
}
|
||||
|
||||
const DHCP::option *DHCP::search_option(OptionTypes opt) const {
|
||||
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
if(it->option() == opt)
|
||||
return &(*it);
|
||||
bool DHCP::remove_option(OptionTypes type) {
|
||||
options_type::iterator iter = search_option_iterator(type);
|
||||
if (iter == options_.end()) {
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
size_ -= static_cast<uint32_t>(iter->data_size() + (sizeof(uint8_t) << 1));
|
||||
options_.erase(iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
const DHCP::option* DHCP::search_option(OptionTypes opt) const {
|
||||
// Search for the iterator. If we found something, return it, otherwise return nullptr.
|
||||
options_type::const_iterator iter = search_option_iterator(opt);
|
||||
return (iter != options_.end()) ? &*iter : 0;
|
||||
}
|
||||
|
||||
DHCP::options_type::const_iterator DHCP::search_option_iterator(OptionTypes opt) const {
|
||||
Internals::option_type_equality_comparator<option> comparator(opt);
|
||||
return find_if(options_.begin(), options_.end(), comparator);
|
||||
}
|
||||
|
||||
DHCP::options_type::iterator DHCP::search_option_iterator(OptionTypes opt) {
|
||||
Internals::option_type_equality_comparator<option> comparator(opt);
|
||||
return find_if(options_.begin(), options_.end(), comparator);
|
||||
}
|
||||
|
||||
void DHCP::type(Flags type) {
|
||||
@@ -146,22 +165,22 @@ DHCP::ipaddress_type DHCP::subnet_mask() const {
|
||||
return search_and_convert<ipaddress_type>(SUBNET_MASK);
|
||||
}
|
||||
|
||||
void DHCP::routers(const std::vector<ipaddress_type> &routers) {
|
||||
void DHCP::routers(const vector<ipaddress_type>& routers) {
|
||||
serialization_type buffer = serialize_list(routers);
|
||||
add_option(option(ROUTERS, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
std::vector<DHCP::ipaddress_type> DHCP::routers() const {
|
||||
return search_and_convert<std::vector<DHCP::ipaddress_type> >(ROUTERS);
|
||||
vector<DHCP::ipaddress_type> DHCP::routers() const {
|
||||
return search_and_convert<vector<DHCP::ipaddress_type> >(ROUTERS);
|
||||
}
|
||||
|
||||
void DHCP::domain_name_servers(const std::vector<ipaddress_type> &dns) {
|
||||
void DHCP::domain_name_servers(const vector<ipaddress_type>& dns) {
|
||||
serialization_type buffer = serialize_list(dns);
|
||||
add_option(option(DOMAIN_NAME_SERVERS, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
std::vector<DHCP::ipaddress_type> DHCP::domain_name_servers() const {
|
||||
return search_and_convert<std::vector<DHCP::ipaddress_type> >(DOMAIN_NAME_SERVERS);
|
||||
vector<DHCP::ipaddress_type> DHCP::domain_name_servers() const {
|
||||
return search_and_convert<vector<DHCP::ipaddress_type> >(DOMAIN_NAME_SERVERS);
|
||||
}
|
||||
|
||||
void DHCP::broadcast(ipaddress_type addr) {
|
||||
@@ -182,20 +201,20 @@ DHCP::ipaddress_type DHCP::requested_ip() const {
|
||||
return search_and_convert<ipaddress_type>(DHCP_REQUESTED_ADDRESS);
|
||||
}
|
||||
|
||||
void DHCP::domain_name(const string &name) {
|
||||
void DHCP::domain_name(const string& name) {
|
||||
add_option(option(DOMAIN_NAME, name.size(), (const uint8_t*)name.c_str()));
|
||||
}
|
||||
|
||||
std::string DHCP::domain_name() const {
|
||||
return search_and_convert<std::string>(DOMAIN_NAME);
|
||||
string DHCP::domain_name() const {
|
||||
return search_and_convert<string>(DOMAIN_NAME);
|
||||
}
|
||||
|
||||
void DHCP::hostname(const std::string &name) {
|
||||
void DHCP::hostname(const string& name) {
|
||||
add_option(option(HOST_NAME, name.size(), (const uint8_t*)name.c_str()));
|
||||
}
|
||||
|
||||
std::string DHCP::hostname() const {
|
||||
return search_and_convert<std::string>(HOST_NAME);
|
||||
string DHCP::hostname() const {
|
||||
return search_and_convert<string>(HOST_NAME);
|
||||
}
|
||||
|
||||
void DHCP::rebind_time(uint32_t time) {
|
||||
@@ -207,35 +226,35 @@ uint32_t DHCP::rebind_time() const {
|
||||
return search_and_convert<uint32_t>(DHCP_REBINDING_TIME);
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCP::serialize_list(const std::vector<ipaddress_type> &ip_list) {
|
||||
PDU::serialization_type DHCP::serialize_list(const vector<ipaddress_type>& ip_list) {
|
||||
serialization_type buffer(ip_list.size() * sizeof(uint32_t));
|
||||
uint32_t *ptr = (uint32_t*)&buffer[0];
|
||||
for(std::vector<ipaddress_type>::const_iterator it = ip_list.begin(); it != ip_list.end(); ++it)
|
||||
uint32_t* ptr = (uint32_t*)&buffer[0];
|
||||
typedef vector<ipaddress_type>::const_iterator iterator;
|
||||
for (iterator it = ip_list.begin(); it != ip_list.end(); ++it) {
|
||||
*(ptr++) = *it;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint32_t DHCP::header_size() const {
|
||||
return BootP::header_size() - vend().size() + _size;
|
||||
return static_cast<uint32_t>(BootP::header_size() - vend().size() + size_);
|
||||
}
|
||||
|
||||
void DHCP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= header_size());
|
||||
#endif
|
||||
if(_size) {
|
||||
vend_type &result(BootP::vend());
|
||||
result.resize(_size);
|
||||
uint8_t *ptr = &result[0] + sizeof(uint32_t);
|
||||
void DHCP::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent) {
|
||||
if (size_) {
|
||||
vend_type& result = BootP::vend();
|
||||
result.resize(size_);
|
||||
// Build a stream over the vend vector
|
||||
OutputMemoryStream stream(&result[0], result.size());
|
||||
// Magic cookie
|
||||
*((uint32_t*)&result[0]) = Endian::host_to_be<uint32_t>(0x63825363);
|
||||
for(options_type::const_iterator it = _options.begin(); it != _options.end(); ++it) {
|
||||
*(ptr++) = it->option();
|
||||
*(ptr++) = it->length_field();
|
||||
std::copy(it->data_ptr(), it->data_ptr() + it->data_size(), ptr);
|
||||
ptr += it->data_size();
|
||||
stream.write(Endian::host_to_be<uint32_t>(0x63825363));
|
||||
for (options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
||||
stream.write(it->option());
|
||||
stream.write<uint8_t>(it->length_field());
|
||||
stream.write(it->data_ptr(), it->data_size());
|
||||
}
|
||||
}
|
||||
BootP::write_serialization(buffer, total_sz, parent);
|
||||
}
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
626
src/dhcpv6.cpp
626
src/dhcpv6.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,100 +31,109 @@
|
||||
#include <algorithm>
|
||||
#include "dhcpv6.h"
|
||||
#include "exceptions.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using std::find_if;
|
||||
using std::copy;
|
||||
using std::vector;
|
||||
using std::runtime_error;
|
||||
using std::memcpy;
|
||||
using std::equal;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
DHCPv6::DHCPv6() : options_size() {
|
||||
std::fill(header_data, header_data + sizeof(header_data), 0);
|
||||
|
||||
DHCPv6::DHCPv6()
|
||||
: header_data_(), options_size_() {
|
||||
|
||||
}
|
||||
|
||||
DHCPv6::DHCPv6(const uint8_t *buffer, uint32_t total_sz)
|
||||
: options_size()
|
||||
{
|
||||
if(total_sz == 0)
|
||||
DHCPv6::DHCPv6(const uint8_t* buffer, uint32_t total_sz)
|
||||
: options_size_() {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
if (!stream) {
|
||||
throw malformed_packet();
|
||||
// Relay Agent/Server Messages
|
||||
bool is_relay_msg = (buffer[0] == 12 || buffer[0] == 13);
|
||||
uint32_t required_size = is_relay_msg ? 2 : 4;
|
||||
if(total_sz < required_size)
|
||||
throw malformed_packet();
|
||||
std::copy(buffer, buffer + required_size, header_data);
|
||||
buffer += required_size;
|
||||
total_sz -= required_size;
|
||||
if(is_relay_message()) {
|
||||
if(total_sz < ipaddress_type::address_size * 2)
|
||||
throw malformed_packet();
|
||||
link_addr = buffer;
|
||||
peer_addr = buffer + ipaddress_type::address_size;
|
||||
buffer += ipaddress_type::address_size * 2;
|
||||
total_sz -= ipaddress_type::address_size * 2;
|
||||
}
|
||||
options_size = total_sz;
|
||||
while(total_sz) {
|
||||
if(total_sz < sizeof(uint16_t) * 2)
|
||||
// Relay Agent/Server Messages
|
||||
const MessageType message_type = (MessageType)*stream.pointer();
|
||||
bool is_relay_msg = (message_type == RELAY_FORWARD || message_type == RELAY_REPLY);
|
||||
uint32_t required_size = is_relay_msg ? 2 : 4;
|
||||
stream.read(&header_data_, required_size);
|
||||
if (is_relay_message()) {
|
||||
stream.read(link_addr_);
|
||||
stream.read(peer_addr_);
|
||||
}
|
||||
while (stream) {
|
||||
uint16_t opt = stream.read_be<uint16_t>();
|
||||
uint16_t data_size = stream.read_be<uint16_t>();
|
||||
if (!stream.can_read(data_size)) {
|
||||
throw malformed_packet();
|
||||
|
||||
uint16_t opt;
|
||||
std::memcpy(&opt, buffer, sizeof(uint16_t));
|
||||
opt = Endian::be_to_host(opt);
|
||||
uint16_t data_size;
|
||||
std::memcpy(&data_size, buffer + sizeof(uint16_t), sizeof(uint16_t));
|
||||
data_size = Endian::be_to_host(data_size);
|
||||
if(total_sz - sizeof(uint16_t) * 2 < data_size)
|
||||
throw malformed_packet();
|
||||
buffer += sizeof(uint16_t) * 2;
|
||||
add_option(
|
||||
option(opt, buffer, buffer + data_size)
|
||||
);
|
||||
buffer += data_size;
|
||||
total_sz -= sizeof(uint16_t) * 2 + data_size;
|
||||
}
|
||||
add_option(option(opt, stream.pointer(), stream.pointer() + data_size));
|
||||
stream.skip(data_size);
|
||||
}
|
||||
}
|
||||
|
||||
void DHCPv6::add_option(const option &opt) {
|
||||
void DHCPv6::add_option(const option& opt) {
|
||||
options_.push_back(opt);
|
||||
options_size_ += opt.data_size() + sizeof(uint16_t) * 2;
|
||||
}
|
||||
|
||||
const DHCPv6::option *DHCPv6::search_option(OptionTypes id) const {
|
||||
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
||||
if(it->option() == static_cast<uint16_t>(id))
|
||||
return &*it;
|
||||
bool DHCPv6::remove_option(OptionTypes type) {
|
||||
options_type::iterator iter = search_option_iterator(type);
|
||||
if (iter == options_.end()) {
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
options_size_ -= iter->data_size() + sizeof(uint16_t) * 2;
|
||||
options_.erase(iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* DHCPv6::write_option(const option &opt, uint8_t* buffer) const {
|
||||
uint16_t uint16_t_buffer = Endian::host_to_be(opt.option());
|
||||
std::memcpy(buffer, &uint16_t_buffer, sizeof(uint16_t));
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(opt.length_field());
|
||||
std::memcpy(&buffer[sizeof(uint16_t)], &uint16_t_buffer, sizeof(uint16_t));
|
||||
return std::copy(
|
||||
opt.data_ptr(),
|
||||
opt.data_ptr() + opt.data_size(),
|
||||
buffer + sizeof(uint16_t) * 2
|
||||
);
|
||||
const DHCPv6::option* DHCPv6::search_option(OptionTypes type) const {
|
||||
// Search for the iterator. If we found something, return it, otherwise return nullptr.
|
||||
options_type::const_iterator iter = search_option_iterator(type);
|
||||
return (iter != options_.end()) ? &*iter : 0;
|
||||
}
|
||||
|
||||
DHCPv6::options_type::const_iterator DHCPv6::search_option_iterator(OptionTypes type) const {
|
||||
Internals::option_type_equality_comparator<option> comparator(type);
|
||||
return find_if(options_.begin(), options_.end(), comparator);
|
||||
}
|
||||
|
||||
DHCPv6::options_type::iterator DHCPv6::search_option_iterator(OptionTypes type) {
|
||||
Internals::option_type_equality_comparator<option> comparator(type);
|
||||
return find_if(options_.begin(), options_.end(), comparator);
|
||||
}
|
||||
|
||||
void DHCPv6::write_option(const option& opt, OutputMemoryStream& stream) const {
|
||||
stream.write_be<uint16_t>(opt.option());
|
||||
stream.write_be<uint16_t>(opt.length_field());
|
||||
stream.write(opt.data_ptr(), opt.data_size());
|
||||
}
|
||||
|
||||
void DHCPv6::msg_type(MessageType type) {
|
||||
header_data[0] = static_cast<uint8_t>(type);
|
||||
header_data_[0] = static_cast<uint8_t>(type);
|
||||
}
|
||||
|
||||
void DHCPv6::hop_count(uint8_t count) {
|
||||
header_data[1] = count;
|
||||
header_data_[1] = count;
|
||||
}
|
||||
|
||||
void DHCPv6::transaction_id(small_uint<24> id) {
|
||||
uint32_t id_32 = id;
|
||||
header_data[1] = id_32 >> 16;
|
||||
header_data[2] = id_32 >> 8;
|
||||
header_data[3] = id_32 & 0xff;
|
||||
header_data_[1] = id_32 >> 16;
|
||||
header_data_[2] = id_32 >> 8;
|
||||
header_data_[3] = id_32 & 0xff;
|
||||
}
|
||||
|
||||
void DHCPv6::peer_address(const ipaddress_type &addr) {
|
||||
peer_addr = addr;
|
||||
void DHCPv6::peer_address(const ipaddress_type& addr) {
|
||||
peer_addr_ = addr;
|
||||
}
|
||||
|
||||
void DHCPv6::link_address(const ipaddress_type &addr) {
|
||||
link_addr = addr;
|
||||
void DHCPv6::link_address(const ipaddress_type& addr) {
|
||||
link_addr_ = addr;
|
||||
}
|
||||
|
||||
bool DHCPv6::is_relay_message() const {
|
||||
@@ -132,27 +141,30 @@ bool DHCPv6::is_relay_message() const {
|
||||
}
|
||||
|
||||
uint32_t DHCPv6::header_size() const {
|
||||
return (is_relay_message() ? (2 + ipaddress_type::address_size * 2) : 4) + options_size;
|
||||
return (is_relay_message() ? (2 + ipaddress_type::address_size * 2) : 4) + options_size_;
|
||||
}
|
||||
|
||||
bool DHCPv6::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
if(!is_relay_message()) {
|
||||
if(total_sz < 4 || (ptr[0] == 12 || ptr[0] == 13))
|
||||
bool DHCPv6::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
||||
if (!is_relay_message()) {
|
||||
if (total_sz < 4 || (ptr[0] == 12 || ptr[0] == 13)) {
|
||||
return false;
|
||||
return std::equal(header_data + 1, header_data + 4, ptr + 1);
|
||||
}
|
||||
return equal(header_data_ + 1, header_data_ + 4, ptr + 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DHCPv6::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) {
|
||||
void DHCPv6::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU *) {
|
||||
const uint32_t required_size = is_relay_message() ? 2 : 4;
|
||||
buffer = std::copy(header_data, header_data + required_size, buffer);
|
||||
if(is_relay_message()) {
|
||||
buffer = link_addr.copy(buffer);
|
||||
buffer = peer_addr.copy(buffer);
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(header_data_, required_size);
|
||||
if (is_relay_message()) {
|
||||
stream.write(link_addr_);
|
||||
stream.write(peer_addr_);
|
||||
}
|
||||
for (options_type::const_iterator it = options_.begin(); it != options_.end(); ++it) {
|
||||
write_option(*it, stream);
|
||||
}
|
||||
for(options_type::const_iterator it = options_.begin(); it != options_.end(); ++it)
|
||||
buffer = write_option(*it, buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +213,7 @@ DHCPv6::status_code_type DHCPv6::status_code() const {
|
||||
}
|
||||
|
||||
bool DHCPv6::has_rapid_commit() const {
|
||||
return search_option(RAPID_COMMIT);
|
||||
return search_option(RAPID_COMMIT) != NULL;
|
||||
}
|
||||
|
||||
DHCPv6::user_class_type DHCPv6::user_class() const {
|
||||
@@ -225,7 +237,7 @@ uint8_t DHCPv6::reconfigure_msg() const {
|
||||
}
|
||||
|
||||
bool DHCPv6::has_reconfigure_accept() const {
|
||||
return search_option(RECONF_ACCEPT);
|
||||
return search_option(RECONF_ACCEPT) != NULL;
|
||||
}
|
||||
|
||||
DHCPv6::duid_type DHCPv6::client_id() const {
|
||||
@@ -240,147 +252,99 @@ DHCPv6::duid_type DHCPv6::server_id() const {
|
||||
// Option setters
|
||||
// ********************************************************************
|
||||
|
||||
void DHCPv6::ia_na(const ia_na_type &value) {
|
||||
std::vector<uint8_t> buffer(sizeof(uint32_t) * 3 + value.options.size());
|
||||
uint32_t *ptr = (uint32_t*)&buffer[0];
|
||||
*ptr++ = Endian::host_to_be(value.id);
|
||||
*ptr++ = Endian::host_to_be(value.t1);
|
||||
*ptr++ = Endian::host_to_be(value.t2);
|
||||
std::copy(
|
||||
value.options.begin(),
|
||||
value.options.end(),
|
||||
buffer.begin() + sizeof(uint32_t) * 3
|
||||
);
|
||||
add_option(
|
||||
option(IA_NA, buffer.begin(), buffer.end())
|
||||
);
|
||||
void DHCPv6::ia_na(const ia_na_type& value) {
|
||||
vector<uint8_t> buffer(sizeof(uint32_t) * 3 + value.options.size());
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.id);
|
||||
stream.write_be(value.t1);
|
||||
stream.write_be(value.t2);
|
||||
stream.write(value.options.begin(), value.options.end());
|
||||
add_option(option(IA_NA, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::ia_ta(const ia_ta_type &value) {
|
||||
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.options.size());
|
||||
uint32_t *ptr = (uint32_t*)&buffer[0];
|
||||
*ptr++ = Endian::host_to_be(value.id);
|
||||
std::copy(
|
||||
value.options.begin(),
|
||||
value.options.end(),
|
||||
buffer.begin() + sizeof(uint32_t)
|
||||
);
|
||||
add_option(
|
||||
option(IA_TA, buffer.begin(), buffer.end())
|
||||
);
|
||||
void DHCPv6::ia_ta(const ia_ta_type& value) {
|
||||
vector<uint8_t> buffer(sizeof(uint32_t) + value.options.size());
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.id);
|
||||
stream.write(value.options.begin(), value.options.end());
|
||||
add_option(option(IA_TA, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::ia_address(const ia_address_type &value) {
|
||||
std::vector<uint8_t> buffer(
|
||||
void DHCPv6::ia_address(const ia_address_type& value) {
|
||||
vector<uint8_t> buffer(
|
||||
sizeof(uint32_t) * 2 + ipaddress_type::address_size + value.options.size()
|
||||
);
|
||||
uint32_t *ptr = (uint32_t*)&buffer[ipaddress_type::address_size];
|
||||
value.address.copy(&buffer[0]);
|
||||
*ptr++ = Endian::host_to_be(value.preferred_lifetime);
|
||||
*ptr++ = Endian::host_to_be(value.valid_lifetime);
|
||||
std::copy(
|
||||
value.options.begin(),
|
||||
value.options.end(),
|
||||
buffer.begin() + sizeof(uint32_t) * 2 + ipaddress_type::address_size
|
||||
);
|
||||
add_option(
|
||||
option(IA_ADDR, buffer.begin(), buffer.end())
|
||||
);
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write(value.address);
|
||||
stream.write_be(value.preferred_lifetime);
|
||||
stream.write_be(value.valid_lifetime);
|
||||
stream.write(value.options.begin(), value.options.end());
|
||||
add_option(option(IA_ADDR, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::option_request(const option_request_type &value) {
|
||||
void DHCPv6::option_request(const option_request_type& value) {
|
||||
typedef option_request_type::const_iterator iterator;
|
||||
|
||||
std::vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
|
||||
size_t index = 0;
|
||||
uint16_t uint16_t_buffer;
|
||||
for(iterator it = value.begin(); it != value.end(); ++it, index += 2) {
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(*it);
|
||||
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
|
||||
vector<uint8_t> buffer(value.size() * sizeof(uint16_t));
|
||||
OutputMemoryStream stream(buffer);
|
||||
for (iterator it = value.begin(); it != value.end(); ++it) {
|
||||
stream.write_be(*it);
|
||||
}
|
||||
add_option(
|
||||
option(OPTION_REQUEST, buffer.begin(), buffer.end())
|
||||
);
|
||||
add_option(option(OPTION_REQUEST, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::preference(uint8_t value) {
|
||||
add_option(
|
||||
option(PREFERENCE, 1, &value)
|
||||
);
|
||||
add_option(option(PREFERENCE, 1, &value));
|
||||
}
|
||||
|
||||
void DHCPv6::elapsed_time(uint16_t value) {
|
||||
value = Endian::host_to_be(value);
|
||||
add_option(
|
||||
option(ELAPSED_TIME, 2, (const uint8_t*)&value)
|
||||
);
|
||||
add_option(option(ELAPSED_TIME, 2, (const uint8_t*)&value));
|
||||
}
|
||||
|
||||
void DHCPv6::relay_message(const relay_msg_type &value) {
|
||||
add_option(
|
||||
option(RELAY_MSG, value.begin(), value.end())
|
||||
);
|
||||
void DHCPv6::relay_message(const relay_msg_type& value) {
|
||||
add_option(option(RELAY_MSG, value.begin(), value.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::authentication(const authentication_type &value) {
|
||||
std::vector<uint8_t> buffer(
|
||||
void DHCPv6::authentication(const authentication_type& value) {
|
||||
vector<uint8_t> buffer(
|
||||
sizeof(uint8_t) * 3 + sizeof(uint64_t) + value.auth_info.size()
|
||||
);
|
||||
buffer[0] = value.protocol;
|
||||
buffer[1] = value.algorithm;
|
||||
buffer[2] = value.rdm;
|
||||
uint64_t uint64_t_buffer = Endian::host_to_be(value.replay_detection);
|
||||
std::memcpy(&buffer[3], &uint64_t_buffer, sizeof(uint64_t));
|
||||
std::copy(
|
||||
value.auth_info.begin(),
|
||||
value.auth_info.end(),
|
||||
buffer.begin() + sizeof(uint8_t) * 3 + sizeof(uint64_t)
|
||||
);
|
||||
add_option(
|
||||
option(AUTH, buffer.begin(), buffer.end())
|
||||
);
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write(value.protocol);
|
||||
stream.write(value.algorithm);
|
||||
stream.write(value.rdm);
|
||||
stream.write_be(value.replay_detection);
|
||||
stream.write(value.auth_info.begin(), value.auth_info.end());
|
||||
add_option(option(AUTH, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::server_unicast(const ipaddress_type &value) {
|
||||
add_option(
|
||||
option(UNICAST, value.begin(), value.end())
|
||||
);
|
||||
void DHCPv6::server_unicast(const ipaddress_type& value) {
|
||||
add_option(option(UNICAST, value.begin(), value.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::status_code(const status_code_type &value) {
|
||||
std::vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
|
||||
uint16_t uint16_t_buffer = Endian::host_to_be(value.code);
|
||||
std::memcpy(&buffer[0], &uint16_t_buffer, sizeof(uint16_t));
|
||||
std::copy(
|
||||
value.message.begin(),
|
||||
value.message.end(),
|
||||
buffer.begin() + sizeof(uint16_t)
|
||||
);
|
||||
add_option(
|
||||
option(STATUS_CODE, buffer.begin(), buffer.end())
|
||||
);
|
||||
void DHCPv6::status_code(const status_code_type& value) {
|
||||
vector<uint8_t> buffer(sizeof(uint16_t) + value.message.size());
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.code);
|
||||
stream.write(value.message.begin(), value.message.end());
|
||||
add_option(option(STATUS_CODE, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::rapid_commit() {
|
||||
add_option(
|
||||
RAPID_COMMIT
|
||||
);
|
||||
add_option(RAPID_COMMIT);
|
||||
}
|
||||
|
||||
void DHCPv6::user_class(const user_class_type &value) {
|
||||
std::vector<uint8_t> buffer;
|
||||
void DHCPv6::user_class(const user_class_type& value) {
|
||||
vector<uint8_t> buffer;
|
||||
Internals::class_option_data2option(value.data.begin(), value.data.end(), buffer);
|
||||
add_option(
|
||||
option(USER_CLASS, buffer.begin(), buffer.end())
|
||||
);
|
||||
add_option(option(USER_CLASS, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::vendor_class(const vendor_class_type &value) {
|
||||
std::vector<uint8_t> buffer(
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
uint32_t enterprise_number = Endian::host_to_be(value.enterprise_number);
|
||||
std::memcpy(&buffer[0], &enterprise_number, sizeof(uint32_t));
|
||||
void DHCPv6::vendor_class(const vendor_class_type& value) {
|
||||
vector<uint8_t> buffer(sizeof(uint32_t));
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.enterprise_number);
|
||||
Internals::class_option_data2option(
|
||||
value.vendor_class_data.begin(),
|
||||
value.vendor_class_data.end(),
|
||||
@@ -392,276 +356,218 @@ void DHCPv6::vendor_class(const vendor_class_type &value) {
|
||||
);
|
||||
}
|
||||
|
||||
void DHCPv6::vendor_info(const vendor_info_type &value) {
|
||||
std::vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
|
||||
uint32_t enterprise_number = Endian::host_to_be(value.enterprise_number);
|
||||
std::memcpy(&buffer[0], &enterprise_number, sizeof(uint32_t));
|
||||
std::copy(
|
||||
value.data.begin(),
|
||||
value.data.end(),
|
||||
buffer.begin() + sizeof(uint32_t)
|
||||
);
|
||||
add_option(
|
||||
option(VENDOR_OPTS, buffer.begin(), buffer.end())
|
||||
);
|
||||
void DHCPv6::vendor_info(const vendor_info_type& value) {
|
||||
vector<uint8_t> buffer(sizeof(uint32_t) + value.data.size());
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.enterprise_number);
|
||||
stream.write(value.data.begin(), value.data.end());
|
||||
add_option(option(VENDOR_OPTS, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::interface_id(const interface_id_type &value) {
|
||||
add_option(
|
||||
option(INTERFACE_ID, value.begin(), value.end())
|
||||
);
|
||||
void DHCPv6::interface_id(const interface_id_type& value) {
|
||||
add_option(option(INTERFACE_ID, value.begin(), value.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::reconfigure_msg(uint8_t value) {
|
||||
add_option(
|
||||
option(RECONF_MSG, 1, &value)
|
||||
);
|
||||
add_option(option(RECONF_MSG, 1, &value));
|
||||
}
|
||||
|
||||
void DHCPv6::reconfigure_accept() {
|
||||
add_option(RECONF_ACCEPT);
|
||||
}
|
||||
|
||||
void DHCPv6::client_id(const duid_type& value) {
|
||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.id);
|
||||
stream.write(value.data.begin(), value.data.end());
|
||||
add_option(option(CLIENTID, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
void DHCPv6::server_id(const duid_type& value) {
|
||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||
OutputMemoryStream stream(buffer);
|
||||
stream.write_be(value.id);
|
||||
stream.write(value.data.begin(), value.data.end());
|
||||
add_option(option(SERVERID, buffer.begin(), buffer.end()));
|
||||
}
|
||||
|
||||
// DUIDs
|
||||
|
||||
DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
DHCPv6::duid_llt DHCPv6::duid_llt::from_bytes(const uint8_t* buffer, uint32_t total_sz) {
|
||||
// at least one byte for lladdress
|
||||
if(total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1)
|
||||
throw std::runtime_error("Not enough size for a DUID_LLT identifier");
|
||||
if (total_sz < sizeof(uint16_t) + sizeof(uint32_t) + 1) {
|
||||
throw runtime_error("Not enough size for a DUID_LLT identifier");
|
||||
}
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
duid_llt output;
|
||||
std::memcpy(&output.hw_type, buffer, sizeof(uint16_t));
|
||||
output.hw_type = Endian::be_to_host(output.hw_type);
|
||||
buffer += sizeof(uint16_t);
|
||||
std::memcpy(&output.time, buffer, sizeof(uint32_t));
|
||||
output.time = Endian::be_to_host(output.time);
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint16_t) + sizeof(uint32_t);
|
||||
output.lladdress.assign(buffer, buffer + total_sz);
|
||||
output.hw_type = stream.read_be<uint16_t>();
|
||||
output.time = stream.read_be<uint32_t>();
|
||||
stream.read(output.lladdress, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCPv6::duid_llt::serialize() const {
|
||||
serialization_type output(sizeof(uint16_t) + sizeof(uint32_t) + lladdress.size());
|
||||
uint16_t tmp_hw_type = Endian::host_to_be(hw_type);
|
||||
uint32_t tmp_time = Endian::host_to_be(time);
|
||||
std::memcpy(&output[0], &tmp_hw_type, sizeof(uint16_t));
|
||||
std::memcpy(&output[sizeof(uint16_t)], &tmp_time, sizeof(uint32_t));
|
||||
std::copy(
|
||||
lladdress.begin(),
|
||||
lladdress.end(),
|
||||
output.begin() + sizeof(uint16_t) + sizeof(uint32_t)
|
||||
);
|
||||
OutputMemoryStream stream(output);
|
||||
stream.write_be(hw_type);
|
||||
stream.write_be(time);
|
||||
stream.write(lladdress.begin(), lladdress.end());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
DHCPv6::duid_en DHCPv6::duid_en::from_bytes(const uint8_t* buffer, uint32_t total_sz) {
|
||||
// at least one byte for identifier
|
||||
if(total_sz < sizeof(uint32_t) + 1)
|
||||
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
||||
if (total_sz < sizeof(uint32_t) + 1) {
|
||||
throw runtime_error("Not enough size for a DUID_en identifier");
|
||||
}
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
duid_en output;
|
||||
std::memcpy(&output.enterprise_number, buffer, sizeof(uint32_t));
|
||||
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
|
||||
buffer += sizeof(uint32_t);
|
||||
total_sz -= sizeof(uint32_t);
|
||||
output.identifier.assign(buffer, buffer + total_sz);
|
||||
output.enterprise_number = stream.read_be<uint32_t>();
|
||||
stream.read(output.identifier, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCPv6::duid_en::serialize() const {
|
||||
serialization_type output(sizeof(uint32_t) + identifier.size());
|
||||
uint32_t tmp_enterprise_number = Endian::host_to_be(enterprise_number);
|
||||
std::memcpy(&output[0], &tmp_enterprise_number, sizeof(uint32_t));
|
||||
std::copy(
|
||||
identifier.begin(),
|
||||
identifier.end(),
|
||||
output.begin() + sizeof(uint32_t)
|
||||
);
|
||||
OutputMemoryStream stream(output);
|
||||
stream.write_be(enterprise_number);
|
||||
stream.write(identifier.begin(), identifier.end());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t *buffer, uint32_t total_sz)
|
||||
{
|
||||
DHCPv6::duid_ll DHCPv6::duid_ll::from_bytes(const uint8_t* buffer, uint32_t total_sz) {
|
||||
// at least one byte for lladdress
|
||||
if(total_sz < sizeof(uint16_t) + 1)
|
||||
throw std::runtime_error("Not enough size for a DUID_en identifier");
|
||||
if (total_sz < sizeof(uint16_t) + 1) {
|
||||
throw runtime_error("Not enough size for a DUID_en identifier");
|
||||
}
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
duid_ll output;
|
||||
std::memcpy(&output.hw_type, buffer, sizeof(uint16_t));
|
||||
output.hw_type = Endian::be_to_host(output.hw_type);
|
||||
buffer += sizeof(uint16_t);
|
||||
total_sz -= sizeof(uint16_t);
|
||||
output.lladdress.assign(buffer, buffer + total_sz);
|
||||
output.hw_type = stream.read_be<uint16_t>();
|
||||
stream.read(output.lladdress, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
PDU::serialization_type DHCPv6::duid_ll::serialize() const {
|
||||
serialization_type output(sizeof(uint16_t) + lladdress.size());
|
||||
uint16_t tmp_hw_type = Endian::host_to_be(hw_type);
|
||||
std::memcpy(&output[0], &tmp_hw_type, sizeof(uint16_t));
|
||||
std::copy(
|
||||
lladdress.begin(),
|
||||
lladdress.end(),
|
||||
output.begin() + sizeof(uint16_t)
|
||||
);
|
||||
OutputMemoryStream stream(output);
|
||||
stream.write_be(hw_type);
|
||||
stream.write(lladdress.begin(), lladdress.end());
|
||||
return output;
|
||||
}
|
||||
|
||||
void DHCPv6::client_id(const duid_type &value) {
|
||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||
uint16_t tmp_id = Endian::host_to_be(value.id);
|
||||
std::memcpy(&buffer[0], &tmp_id, sizeof(uint16_t));
|
||||
std::copy(
|
||||
value.data.begin(),
|
||||
value.data.end(),
|
||||
buffer.begin() + sizeof(uint16_t)
|
||||
);
|
||||
add_option(
|
||||
option(CLIENTID, buffer.begin(), buffer.end())
|
||||
);
|
||||
}
|
||||
|
||||
void DHCPv6::server_id(const duid_type &value) {
|
||||
serialization_type buffer(sizeof(uint16_t) + value.data.size());
|
||||
uint16_t tmp_id = Endian::host_to_be(value.id);
|
||||
std::memcpy(&buffer[0], &tmp_id, sizeof(uint16_t));
|
||||
std::copy(
|
||||
value.data.begin(),
|
||||
value.data.end(),
|
||||
buffer.begin() + sizeof(uint16_t)
|
||||
);
|
||||
add_option(
|
||||
option(SERVERID, buffer.begin(), buffer.end())
|
||||
);
|
||||
}
|
||||
|
||||
// Options
|
||||
|
||||
DHCPv6::ia_na_type DHCPv6::ia_na_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint32_t) * 3)
|
||||
DHCPv6::ia_na_type DHCPv6::ia_na_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint32_t) * 3) {
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr() + sizeof(uint32_t) * 3;
|
||||
const uint32_t *ptr_32 = (const uint32_t*)opt.data_ptr();
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
DHCPv6::ia_na_type output;
|
||||
output.id = Endian::be_to_host(*ptr_32++);
|
||||
output.t1 = Endian::be_to_host(*ptr_32++);
|
||||
output.t2 = Endian::be_to_host(*ptr_32++);
|
||||
output.options.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||
output.id = stream.read_be<uint32_t>();
|
||||
output.t1 = stream.read_be<uint32_t>();
|
||||
output.t2 = stream.read_be<uint32_t>();
|
||||
stream.read(output.options, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::ia_ta_type DHCPv6::ia_ta_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint32_t))
|
||||
DHCPv6::ia_ta_type DHCPv6::ia_ta_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint32_t)) {
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr() + sizeof(uint32_t);
|
||||
const uint32_t *ptr_32 = (const uint32_t*)opt.data_ptr();
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
DHCPv6::ia_ta_type output;
|
||||
output.id = Endian::be_to_host(*ptr_32++);
|
||||
output.options.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||
output.id = stream.read_be<uint32_t>();
|
||||
stream.read(output.options, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::ia_address_type DHCPv6::ia_address_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint32_t) * 2 + DHCPv6::ipaddress_type::address_size)
|
||||
DHCPv6::ia_address_type DHCPv6::ia_address_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint32_t) * 2 + DHCPv6::ipaddress_type::address_size) {
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr() + sizeof(uint32_t) * 2 + ipaddress_type::address_size;
|
||||
const uint32_t *ptr_32 = (const uint32_t*)(opt.data_ptr() + ipaddress_type::address_size);
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
DHCPv6::ia_address_type output;
|
||||
output.address = opt.data_ptr();
|
||||
output.preferred_lifetime = Endian::be_to_host(*ptr_32++);
|
||||
output.valid_lifetime = Endian::be_to_host(*ptr_32++);
|
||||
output.options.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||
stream.read(output.address);
|
||||
output.preferred_lifetime = stream.read_be<uint32_t>();
|
||||
output.valid_lifetime = stream.read_be<uint32_t>();
|
||||
stream.read(output.options, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::authentication_type DHCPv6::authentication_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint8_t) * 3 + sizeof(uint64_t))
|
||||
DHCPv6::authentication_type DHCPv6::authentication_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint8_t) * 3 + sizeof(uint64_t)) {
|
||||
throw malformed_option();
|
||||
const uint8_t *ptr = opt.data_ptr();
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
authentication_type output;
|
||||
output.protocol = *ptr++;
|
||||
output.algorithm = *ptr++;
|
||||
output.rdm = *ptr++;
|
||||
std::memcpy(&output.replay_detection, ptr, sizeof(uint64_t));
|
||||
output.replay_detection = Endian::be_to_host(output.replay_detection);
|
||||
ptr += sizeof(uint64_t);
|
||||
output.auth_info.assign(ptr, opt.data_ptr() + opt.data_size());
|
||||
output.protocol = stream.read<uint8_t>();
|
||||
output.algorithm = stream.read<uint8_t>();
|
||||
output.rdm = stream.read<uint8_t>();
|
||||
output.replay_detection = stream.read_be<uint64_t>();
|
||||
stream.read(output.auth_info, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::status_code_type DHCPv6::status_code_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint16_t))
|
||||
DHCPv6::status_code_type DHCPv6::status_code_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint16_t)) {
|
||||
throw malformed_option();
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
status_code_type output;
|
||||
std::memcpy(&output.code, opt.data_ptr(), sizeof(uint16_t));
|
||||
output.code = Endian::be_to_host(output.code);
|
||||
output.message.assign(
|
||||
opt.data_ptr() + sizeof(uint16_t),
|
||||
opt.data_ptr() + opt.data_size()
|
||||
);
|
||||
output.code = stream.read_be<uint16_t>();
|
||||
output.message.assign(stream.pointer(), stream.pointer() + stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::vendor_info_type DHCPv6::vendor_info_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint32_t))
|
||||
DHCPv6::vendor_info_type DHCPv6::vendor_info_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint32_t)) {
|
||||
throw malformed_option();
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
vendor_info_type output;
|
||||
std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t));
|
||||
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
|
||||
output.data.assign(
|
||||
opt.data_ptr() + sizeof(uint32_t),
|
||||
opt.data_ptr() + opt.data_size()
|
||||
);
|
||||
output.enterprise_number = stream.read_be<uint32_t>();
|
||||
stream.read(output.data, stream.size());
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::vendor_class_type DHCPv6::vendor_class_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint32_t))
|
||||
DHCPv6::vendor_class_type DHCPv6::vendor_class_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint32_t)) {
|
||||
throw malformed_option();
|
||||
}
|
||||
typedef vendor_class_type::class_data_type data_type;
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
vendor_class_type output;
|
||||
std::memcpy(&output.enterprise_number, opt.data_ptr(), sizeof(uint32_t));
|
||||
output.enterprise_number = Endian::be_to_host(output.enterprise_number);
|
||||
output.enterprise_number = stream.read_be<uint32_t>();
|
||||
output.vendor_class_data = Internals::option2class_option_data<data_type>(
|
||||
opt.data_ptr() + sizeof(uint32_t),
|
||||
opt.data_size() - sizeof(uint32_t)
|
||||
stream.pointer(),
|
||||
stream.size()
|
||||
);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
DHCPv6::duid_type DHCPv6::duid_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint16_t) + 1)
|
||||
DHCPv6::duid_type DHCPv6::duid_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint16_t) + 1) {
|
||||
throw malformed_option();
|
||||
|
||||
uint16_t uint16_t_buffer;
|
||||
std::memcpy(&uint16_t_buffer, opt.data_ptr(), sizeof(uint16_t));
|
||||
}
|
||||
InputMemoryStream stream(opt.data_ptr(), opt.data_size());
|
||||
uint16_t id = stream.read_be<uint16_t>();
|
||||
return duid_type(
|
||||
Endian::be_to_host(uint16_t_buffer),
|
||||
serialization_type(
|
||||
opt.data_ptr() + sizeof(uint16_t),
|
||||
opt.data_ptr() + opt.data_size()
|
||||
)
|
||||
id,
|
||||
serialization_type(stream.pointer(), stream.pointer() + stream.size())
|
||||
);
|
||||
}
|
||||
|
||||
DHCPv6::user_class_type DHCPv6::user_class_type::from_option(const option &opt)
|
||||
{
|
||||
if(opt.data_size() < sizeof(uint16_t))
|
||||
DHCPv6::user_class_type DHCPv6::user_class_type::from_option(const option& opt) {
|
||||
if (opt.data_size() < sizeof(uint16_t)) {
|
||||
throw malformed_option();
|
||||
}
|
||||
user_class_type output;
|
||||
output.data = Internals::option2class_option_data<data_type>(
|
||||
opt.data_ptr(), opt.data_size()
|
||||
opt.data_ptr(), static_cast<uint32_t>(opt.data_size())
|
||||
);
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
658
src/dns.cpp
658
src/dns.cpp
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2016, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#include <utility>
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
@@ -38,448 +37,461 @@
|
||||
#include "ipv6_address.h"
|
||||
#include "exceptions.h"
|
||||
#include "rawpdu.h"
|
||||
#include "endianness.h"
|
||||
#include "memory_helpers.h"
|
||||
|
||||
using std::string;
|
||||
using std::copy;
|
||||
using std::memcpy;
|
||||
using std::list;
|
||||
using std::make_pair;
|
||||
|
||||
using Tins::Memory::InputMemoryStream;
|
||||
using Tins::Memory::OutputMemoryStream;
|
||||
|
||||
namespace Tins {
|
||||
|
||||
DNS::DNS()
|
||||
: answers_idx(), authority_idx(), additional_idx()
|
||||
{
|
||||
std::memset(&dns, 0, sizeof(dns));
|
||||
: header_(), answers_idx_(), authority_idx_(), additional_idx_() {
|
||||
}
|
||||
|
||||
DNS::DNS(const uint8_t *buffer, uint32_t total_sz)
|
||||
: answers_idx(), authority_idx(), additional_idx()
|
||||
{
|
||||
if(total_sz < sizeof(dnshdr))
|
||||
throw malformed_packet();
|
||||
std::memcpy(&dns, buffer, sizeof(dnshdr));
|
||||
records_data.assign(
|
||||
buffer + sizeof(dnshdr),
|
||||
buffer + total_sz
|
||||
);
|
||||
DNS::DNS(const uint8_t* buffer, uint32_t total_sz)
|
||||
: answers_idx_(), authority_idx_(), additional_idx_() {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
stream.read(header_);
|
||||
stream.read(records_data_, stream.size());
|
||||
// Avoid doing this if there's no data. Otherwise VS's asserts fail.
|
||||
if(!records_data.empty()) {
|
||||
buffer = &records_data[0];
|
||||
const uint8_t *end = &records_data[0] + records_data.size(), *prev_start = buffer;
|
||||
if (!records_data_.empty()) {
|
||||
InputMemoryStream stream(records_data_);
|
||||
uint16_t nquestions = questions_count();
|
||||
for(uint16_t i(0); i < nquestions; ++i) {
|
||||
buffer = find_dname_end(buffer);
|
||||
if((buffer + (sizeof(uint16_t) * 2)) > end)
|
||||
throw malformed_packet();
|
||||
buffer += sizeof(uint16_t) * 2;
|
||||
for (uint16_t i(0); i < nquestions; ++i) {
|
||||
skip_to_dname_end(stream);
|
||||
stream.skip(sizeof(uint16_t) * 2);
|
||||
}
|
||||
answers_idx = buffer - prev_start;
|
||||
authority_idx = find_section_end(&records_data[0] + answers_idx, answers_count()) - &records_data[0];
|
||||
additional_idx = find_section_end(&records_data[0] + authority_idx, authority_count()) - &records_data[0];
|
||||
const uint8_t* base_offset = &records_data_[0];
|
||||
answers_idx_ = static_cast<uint32_t>(stream.pointer() - base_offset);
|
||||
skip_to_section_end(stream, answers_count());
|
||||
authority_idx_ = static_cast<uint32_t>(stream.pointer() - base_offset);
|
||||
skip_to_section_end(stream, authority_count());
|
||||
additional_idx_ = static_cast<uint32_t>(stream.pointer() - base_offset);
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* DNS::find_dname_end(const uint8_t *ptr) const {
|
||||
const uint8_t *end = &records_data[0] + records_data.size();
|
||||
while(ptr < end) {
|
||||
if(*ptr == 0) {
|
||||
++ptr;
|
||||
void DNS::skip_to_dname_end(InputMemoryStream& stream) const {
|
||||
while (stream) {
|
||||
uint8_t value = stream.read<uint8_t>();
|
||||
if (value == 0) {
|
||||
// Found the ending null byte, we're done
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if((*ptr & 0xc0)) {
|
||||
ptr += sizeof(uint16_t);
|
||||
if ((value & 0xc0)) {
|
||||
// This is an offset label, skip the second byte and we're done
|
||||
stream.skip(1);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
uint8_t size = *ptr;
|
||||
ptr += size + 1;
|
||||
// This is an actual label, skip its contents
|
||||
stream.skip(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const uint8_t *DNS::find_section_end(const uint8_t *ptr, const uint32_t num_records) const {
|
||||
const uint8_t *end = &records_data[0] + records_data.size();
|
||||
uint16_t uint16_t_buffer;
|
||||
for(uint32_t i = 0; i < num_records; ++i) {
|
||||
ptr = find_dname_end(ptr);
|
||||
if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end)
|
||||
void DNS::skip_to_section_end(InputMemoryStream& stream,
|
||||
const uint32_t num_records) const {
|
||||
for (uint32_t i = 0; i < num_records; ++i) {
|
||||
skip_to_dname_end(stream);
|
||||
stream.skip(sizeof(uint16_t) * 2 + sizeof(uint32_t));
|
||||
uint16_t data_size = stream.read_be<uint16_t>();
|
||||
if (!stream.can_read(data_size)) {
|
||||
throw malformed_packet();
|
||||
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
|
||||
std::memcpy(&uint16_t_buffer, ptr, sizeof(uint16_t));
|
||||
uint16_t data_size = Endian::be_to_host(uint16_t_buffer); // Data size
|
||||
ptr += sizeof(uint16_t);
|
||||
if(ptr + data_size > end)
|
||||
throw malformed_packet();
|
||||
ptr += data_size;
|
||||
}
|
||||
stream.skip(data_size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint32_t DNS::header_size() const {
|
||||
return sizeof(dns) + records_data.size();
|
||||
return static_cast<uint32_t>(sizeof(header_) + records_data_.size());
|
||||
}
|
||||
|
||||
void DNS::id(uint16_t new_id) {
|
||||
dns.id = Endian::host_to_be(new_id);
|
||||
header_.id = Endian::host_to_be(new_id);
|
||||
}
|
||||
|
||||
void DNS::type(QRType new_qr) {
|
||||
dns.qr = new_qr;
|
||||
header_.qr = new_qr;
|
||||
}
|
||||
|
||||
void DNS::opcode(uint8_t new_opcode) {
|
||||
dns.opcode = new_opcode;
|
||||
header_.opcode = new_opcode;
|
||||
}
|
||||
|
||||
void DNS::authoritative_answer(uint8_t new_aa) {
|
||||
dns.aa = new_aa;
|
||||
header_.aa = new_aa;
|
||||
}
|
||||
|
||||
void DNS::truncated(uint8_t new_tc) {
|
||||
dns.tc = new_tc;
|
||||
header_.tc = new_tc;
|
||||
}
|
||||
|
||||
void DNS::recursion_desired(uint8_t new_rd) {
|
||||
dns.rd = new_rd;
|
||||
header_.rd = new_rd;
|
||||
}
|
||||
|
||||
void DNS::recursion_available(uint8_t new_ra) {
|
||||
dns.ra = new_ra;
|
||||
header_.ra = new_ra;
|
||||
}
|
||||
|
||||
void DNS::z(uint8_t new_z) {
|
||||
dns.z = new_z;
|
||||
header_.z = new_z;
|
||||
}
|
||||
|
||||
void DNS::authenticated_data(uint8_t new_ad) {
|
||||
dns.ad = new_ad;
|
||||
header_.ad = new_ad;
|
||||
}
|
||||
|
||||
void DNS::checking_disabled(uint8_t new_cd) {
|
||||
dns.cd = new_cd;
|
||||
header_.cd = new_cd;
|
||||
}
|
||||
|
||||
void DNS::rcode(uint8_t new_rcode) {
|
||||
dns.rcode = new_rcode;
|
||||
header_.rcode = new_rcode;
|
||||
}
|
||||
|
||||
bool DNS::contains_dname(uint16_t type) {
|
||||
return type == MX || type == CNAME ||
|
||||
type == PTR || type == NS;
|
||||
return type == MX || type == CNAME || type == PTR || type == NS;
|
||||
}
|
||||
|
||||
void DNS::add_query(const Query &query) {
|
||||
void DNS::add_query(const query& query) {
|
||||
string new_str = encode_domain_name(query.dname());
|
||||
// Type (2 bytes) + Class (2 Bytes)
|
||||
size_t previous_length = new_str.size();
|
||||
// Epand the string to hold: Type (2 bytes) + Class (2 Bytes)
|
||||
new_str.insert(new_str.end(), sizeof(uint16_t) * 2, ' ');
|
||||
uint16_t uint16_t_buffer;
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(query.type());
|
||||
std::memcpy(&new_str[new_str.size() - 4], &uint16_t_buffer, sizeof(uint16_t));
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(query.query_class());
|
||||
std::memcpy(&new_str[new_str.size() - 2], &uint16_t_buffer, sizeof(uint16_t));
|
||||
// Build a stream at the end
|
||||
OutputMemoryStream stream(
|
||||
(uint8_t*)&new_str[0] + previous_length,
|
||||
sizeof(uint16_t) * 2
|
||||
);
|
||||
stream.write_be<uint16_t>(query.query_type());
|
||||
stream.write_be<uint16_t>(query.query_class());
|
||||
|
||||
uint32_t offset = new_str.size(), threshold = answers_idx;
|
||||
update_records(answers_idx, answers_count(), threshold, offset);
|
||||
update_records(authority_idx, authority_count(), threshold, offset);
|
||||
update_records(additional_idx, additional_count(), threshold, offset);
|
||||
records_data.insert(
|
||||
records_data.begin() + threshold,
|
||||
uint32_t offset = static_cast<uint32_t>(new_str.size()), threshold = answers_idx_;
|
||||
update_records(answers_idx_, answers_count(), threshold, offset);
|
||||
update_records(authority_idx_, authority_count(), threshold, offset);
|
||||
update_records(additional_idx_, additional_count(), threshold, offset);
|
||||
records_data_.insert(
|
||||
records_data_.begin() + threshold,
|
||||
new_str.begin(),
|
||||
new_str.end()
|
||||
);
|
||||
dns.questions = Endian::host_to_be<uint16_t>(
|
||||
questions_count() + 1
|
||||
);
|
||||
header_.questions = Endian::host_to_be(static_cast<uint16_t>(questions_count() + 1));
|
||||
}
|
||||
|
||||
void DNS::add_answer(const Resource &resource) {
|
||||
void DNS::add_answer(const resource& resource) {
|
||||
sections_type sections;
|
||||
sections.push_back(std::make_pair(&authority_idx, authority_count()));
|
||||
sections.push_back(std::make_pair(&additional_idx, additional_count()));
|
||||
sections.push_back(make_pair(&authority_idx_, authority_count()));
|
||||
sections.push_back(make_pair(&additional_idx_, additional_count()));
|
||||
add_record(resource, sections);
|
||||
dns.answers = Endian::host_to_be<uint16_t>(
|
||||
header_.answers = Endian::host_to_be<uint16_t>(
|
||||
answers_count() + 1
|
||||
);
|
||||
}
|
||||
|
||||
void DNS::add_record(const Resource &resource, const sections_type §ions) {
|
||||
void DNS::add_record(const resource& resource, const sections_type& sections) {
|
||||
// We need to check that the data provided is correct. Otherwise, the sections
|
||||
// will end up being inconsistent.
|
||||
IPv4Address v4_addr;
|
||||
IPv6Address v6_addr;
|
||||
std::string buffer = encode_domain_name(resource.dname()), encoded_data;
|
||||
string buffer = encode_domain_name(resource.dname()),
|
||||
encoded_data;
|
||||
// By default the data size is the length of the data field.
|
||||
uint32_t data_size = resource.data().size();
|
||||
if(resource.type() == A) {
|
||||
size_t data_size = resource.data().size();
|
||||
if (resource.query_type() == A) {
|
||||
v4_addr = resource.data();
|
||||
data_size = 4;
|
||||
}
|
||||
else if(resource.type() == AAAA) {
|
||||
else if (resource.query_type() == AAAA) {
|
||||
v6_addr = resource.data();
|
||||
data_size = IPv6Address::address_size;
|
||||
}
|
||||
else if(contains_dname(resource.type())) {
|
||||
else if (contains_dname(resource.query_type())) {
|
||||
encoded_data = encode_domain_name(resource.data());
|
||||
data_size = encoded_data.size();
|
||||
}
|
||||
uint32_t offset = buffer.size() + sizeof(uint16_t) * 3 + sizeof(uint32_t) + data_size,
|
||||
threshold = sections.empty() ? records_data.size() : *sections.front().first;
|
||||
// Skip the preference field
|
||||
if(resource.type() == MX) {
|
||||
size_t offset = buffer.size() + sizeof(uint16_t) * 3 + sizeof(uint32_t) + data_size,
|
||||
threshold = sections.empty() ? records_data_.size() :* sections.front().first;
|
||||
// Take into account the MX preference field
|
||||
if (resource.query_type() == MX) {
|
||||
offset += sizeof(uint16_t);
|
||||
}
|
||||
for(size_t i = 0; i < sections.size(); ++i) {
|
||||
update_records(*sections[i].first, sections[i].second, threshold, offset);
|
||||
for (size_t i = 0; i < sections.size(); ++i) {
|
||||
update_records(
|
||||
*sections[i].first,
|
||||
sections[i].second,
|
||||
static_cast<uint32_t>(threshold),
|
||||
static_cast<uint32_t>(offset)
|
||||
);
|
||||
}
|
||||
|
||||
records_data.insert(
|
||||
records_data.begin() + threshold,
|
||||
records_data_.insert(
|
||||
records_data_.begin() + threshold,
|
||||
offset,
|
||||
0
|
||||
);
|
||||
uint8_t *ptr = std::copy(
|
||||
buffer.begin(),
|
||||
buffer.end(),
|
||||
&records_data[threshold]
|
||||
);
|
||||
|
||||
uint16_t uint16_t_buffer;
|
||||
uint32_t uint32_t_buffer;
|
||||
|
||||
uint16_t_buffer = Endian::host_to_be(resource.type());
|
||||
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
|
||||
ptr += sizeof(uint16_t);
|
||||
uint16_t_buffer = Endian::host_to_be(resource.query_class());
|
||||
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
|
||||
ptr += sizeof(uint16_t);
|
||||
uint32_t_buffer = Endian::host_to_be(resource.ttl());
|
||||
std::memcpy(ptr, &uint32_t_buffer, sizeof(uint32_t));
|
||||
ptr += sizeof(uint32_t);
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(
|
||||
data_size + (resource.type() == MX ? 2 : 0)
|
||||
);
|
||||
std::memcpy(ptr, &uint16_t_buffer, sizeof(uint16_t));
|
||||
ptr += sizeof(uint16_t);
|
||||
if(resource.type() == MX) {
|
||||
ptr += sizeof(uint16_t);
|
||||
OutputMemoryStream stream(&records_data_[0] + threshold, offset);
|
||||
stream.write(buffer.begin(), buffer.end());
|
||||
stream.write_be(resource.query_type());
|
||||
stream.write_be(resource.query_class());
|
||||
stream.write_be(resource.ttl());
|
||||
stream.write_be<uint16_t>(data_size + (resource.query_type() == MX ? 2 : 0));
|
||||
if (resource.query_type() == MX) {
|
||||
stream.write_be(resource.preference());
|
||||
}
|
||||
if(resource.type() == A) {
|
||||
uint32_t ip_int = v4_addr;
|
||||
std::memcpy(ptr, &ip_int, sizeof(ip_int));
|
||||
if (resource.query_type() == A) {
|
||||
stream.write(v4_addr);
|
||||
}
|
||||
else if(resource.type() == AAAA) {
|
||||
std::copy(v6_addr.begin(), v6_addr.end(), ptr);
|
||||
else if (resource.query_type() == AAAA) {
|
||||
stream.write(v6_addr);
|
||||
}
|
||||
else if(!encoded_data.empty()) {
|
||||
std::copy(encoded_data.begin(), encoded_data.end(), ptr);
|
||||
else if (!encoded_data.empty()) {
|
||||
stream.write(encoded_data.begin(), encoded_data.end());
|
||||
}
|
||||
else {
|
||||
std::copy(resource.data().begin(), resource.data().end(), ptr);
|
||||
stream.write(resource.data().begin(), resource.data().end());
|
||||
}
|
||||
}
|
||||
|
||||
void DNS::add_authority(const Resource &resource) {
|
||||
void DNS::add_authority(const resource& resource) {
|
||||
sections_type sections;
|
||||
sections.push_back(std::make_pair(&additional_idx, additional_count()));
|
||||
sections.push_back(make_pair(&additional_idx_, additional_count()));
|
||||
add_record(resource, sections);
|
||||
dns.authority = Endian::host_to_be<uint16_t>(
|
||||
header_.authority = Endian::host_to_be<uint16_t>(
|
||||
authority_count() + 1
|
||||
);
|
||||
}
|
||||
|
||||
void DNS::add_additional(const Resource &resource){
|
||||
void DNS::add_additional(const resource& resource){
|
||||
add_record(resource, sections_type());
|
||||
dns.additional = Endian::host_to_be<uint16_t>(
|
||||
header_.additional = Endian::host_to_be<uint16_t>(
|
||||
additional_count() + 1
|
||||
);
|
||||
}
|
||||
|
||||
std::string DNS::encode_domain_name(const std::string &dn) {
|
||||
std::string output;
|
||||
string DNS::encode_domain_name(const string& dn) {
|
||||
string output;
|
||||
size_t last_index(0), index;
|
||||
if(!dn.empty()) {
|
||||
while((index = dn.find('.', last_index+1)) != string::npos) {
|
||||
output.push_back(index - last_index);
|
||||
if (!dn.empty()) {
|
||||
while ((index = dn.find('.', last_index+1)) != string::npos) {
|
||||
output.push_back(static_cast<char>(index - last_index));
|
||||
output.append(dn.begin() + last_index, dn.begin() + index);
|
||||
last_index = index + 1; //skip dot
|
||||
}
|
||||
output.push_back(dn.size() - last_index);
|
||||
output.push_back(static_cast<char>(dn.size() - last_index));
|
||||
output.append(dn.begin() + last_index, dn.end());
|
||||
}
|
||||
output.push_back('\0');
|
||||
return output;
|
||||
}
|
||||
|
||||
// The output buffer should be at least 256 bytes long. This used to use
|
||||
// a std::string but it worked about 50% slower, so this is somehow
|
||||
// unsafe but a lot faster.
|
||||
const uint8_t* DNS::compose_name(const uint8_t *ptr, char *out_ptr) const {
|
||||
const uint8_t *end = &records_data[0] + records_data.size();
|
||||
const uint8_t *end_ptr = 0;
|
||||
char *current_out_ptr = out_ptr;
|
||||
while(*ptr) {
|
||||
// It's an offset
|
||||
if((*ptr & 0xc0)) {
|
||||
if(ptr + sizeof(uint16_t) > end)
|
||||
throw malformed_packet();
|
||||
uint16_t index;
|
||||
std::memcpy(&index, ptr, sizeof(uint16_t));
|
||||
index = Endian::be_to_host(index) & 0x3fff;
|
||||
// Check that the offset is neither too low or too high
|
||||
if(index < 0x0c || (&records_data[0] + (index - 0x0c)) >= ptr)
|
||||
throw malformed_packet();
|
||||
// We've probably found the end of the original domain name. Save it.
|
||||
if(end_ptr == 0)
|
||||
end_ptr = ptr + sizeof(uint16_t);
|
||||
// Now this is our pointer
|
||||
ptr = &records_data[index - 0x0c];
|
||||
string DNS::decode_domain_name(const string& domain_name) {
|
||||
string output;
|
||||
if (domain_name.empty()) {
|
||||
return output;
|
||||
}
|
||||
const uint8_t* ptr = (const uint8_t*)&domain_name[0];
|
||||
const uint8_t* end = ptr + domain_name.size();
|
||||
while (*ptr) {
|
||||
// We can't handle offsets
|
||||
if ((*ptr & 0xc0)) {
|
||||
throw invalid_domain_name();
|
||||
}
|
||||
else {
|
||||
// It's a label, grab its size.
|
||||
uint8_t size = *ptr;
|
||||
ptr++;
|
||||
if(ptr + size > end || current_out_ptr - out_ptr + size + 1 > 255)
|
||||
if (ptr + size > end) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
// Append a dot if it's not the first one.
|
||||
if(current_out_ptr != out_ptr)
|
||||
if (!output.empty()) {
|
||||
output.push_back('.');
|
||||
}
|
||||
output.insert(output.end(), ptr, ptr + size);
|
||||
ptr += size;
|
||||
}
|
||||
if (output.size() > 256) {
|
||||
throw invalid_domain_name();
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
// The output buffer should be at least 256 bytes long. This used to use
|
||||
// a std::string but it worked about 50% slower, so this is somehow
|
||||
// unsafe but a lot faster.
|
||||
uint32_t DNS::compose_name(const uint8_t* ptr, char* out_ptr) const {
|
||||
const uint8_t* start_ptr = ptr;
|
||||
const uint8_t* end = &records_data_[0] + records_data_.size();
|
||||
const uint8_t* end_ptr = 0;
|
||||
char* current_out_ptr = out_ptr;
|
||||
while (*ptr) {
|
||||
// It's an offset
|
||||
if ((*ptr & 0xc0)) {
|
||||
if (ptr + sizeof(uint16_t) > end) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
uint16_t index;
|
||||
memcpy(&index, ptr, sizeof(uint16_t));
|
||||
index = Endian::be_to_host(index) & 0x3fff;
|
||||
// Check that the offset is neither too low or too high
|
||||
if (index < 0x0c || (&records_data_[0] + (index - 0x0c)) >= end) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
// We've probably found the end of the original domain name. Save it.
|
||||
if (end_ptr == 0) {
|
||||
end_ptr = ptr + sizeof(uint16_t);
|
||||
}
|
||||
// Now this is our pointer
|
||||
ptr = &records_data_[index - 0x0c];
|
||||
}
|
||||
else {
|
||||
// It's a label, grab its size.
|
||||
uint8_t size = *ptr;
|
||||
ptr++;
|
||||
if (ptr + size > end || current_out_ptr - out_ptr + size + 1 > 255) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
// Append a dot if it's not the first one.
|
||||
if (current_out_ptr != out_ptr) {
|
||||
*current_out_ptr++ = '.';
|
||||
std::copy(
|
||||
ptr,
|
||||
ptr + size,
|
||||
current_out_ptr
|
||||
);
|
||||
}
|
||||
copy(ptr, ptr + size, current_out_ptr);
|
||||
current_out_ptr += size;
|
||||
ptr += size;
|
||||
}
|
||||
}
|
||||
// Add the null terminator.
|
||||
*current_out_ptr = 0;
|
||||
return end_ptr ? end_ptr : (ptr + 1);
|
||||
if (!end_ptr) {
|
||||
end_ptr = ptr + 1;
|
||||
}
|
||||
return end_ptr - start_ptr;
|
||||
}
|
||||
|
||||
void DNS::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) {
|
||||
#ifdef TINS_DEBUG
|
||||
assert(total_sz >= sizeof(dns) + records_data.size());//extra_size);
|
||||
#endif
|
||||
std::memcpy(buffer, &dns, sizeof(dns));
|
||||
buffer += sizeof(dns);
|
||||
std::copy(records_data.begin(), records_data.end(), buffer);
|
||||
void DNS::write_serialization(uint8_t* buffer, uint32_t total_sz, const PDU* parent) {
|
||||
OutputMemoryStream stream(buffer, total_sz);
|
||||
stream.write(header_);
|
||||
stream.write(records_data_.begin(), records_data_.end());
|
||||
}
|
||||
|
||||
// Optimization. Creating an IPv4Address and then using IPv4Address::to_string
|
||||
// was quite slow. The output buffer should be able to hold an IPv4 address.
|
||||
void DNS::inline_convert_v4(uint32_t value, char *output) {
|
||||
void DNS::inline_convert_v4(uint32_t value, char* output) {
|
||||
output += sprintf(
|
||||
output,
|
||||
"%d.%d.%d.%d",
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
value & 0xff,
|
||||
(value >> 8) & 0xff,
|
||||
(value >> 16) & 0xff,
|
||||
(value >> 24) & 0xff
|
||||
#else
|
||||
(value >> 24) & 0xff,
|
||||
(value >> 16) & 0xff,
|
||||
(value >> 8) & 0xff,
|
||||
value & 0xff
|
||||
#endif // TINS_IS_LITTLE_ENDIAN
|
||||
);
|
||||
*output = 0;
|
||||
}
|
||||
|
||||
// Parses records in some section.
|
||||
void DNS::convert_records(const uint8_t *ptr, const uint8_t *end, resources_type &res) const {
|
||||
void DNS::convert_records(const uint8_t* ptr,
|
||||
const uint8_t* end,
|
||||
resources_type& res) const {
|
||||
InputMemoryStream stream(ptr, end - ptr);
|
||||
char dname[256], small_addr_buf[256];
|
||||
while(ptr < end) {
|
||||
std::string addr;
|
||||
while (stream) {
|
||||
string data;
|
||||
bool used_small_buffer = false;
|
||||
// Retrieve the record's domain name.
|
||||
ptr = compose_name(ptr, dname);
|
||||
// 3 uint16_t fields: Type + Class + Data size
|
||||
// 1 uint32_t field: TTL
|
||||
if(ptr + sizeof(uint16_t) * 3 + sizeof(uint32_t) > end)
|
||||
throw malformed_packet();
|
||||
stream.skip(compose_name(stream.pointer(), dname));
|
||||
// Retrieve the following fields.
|
||||
uint16_t type, qclass, data_size;
|
||||
uint16_t type, qclass, data_size, preference = 0;
|
||||
uint32_t ttl;
|
||||
std::memcpy(&type, ptr, sizeof(uint16_t)); // Type
|
||||
type = Endian::be_to_host(type);
|
||||
ptr += sizeof(uint16_t);
|
||||
std::memcpy(&qclass, ptr, sizeof(uint16_t)); // Class
|
||||
qclass = Endian::be_to_host(qclass);
|
||||
ptr += sizeof(uint16_t);
|
||||
std::memcpy(&ttl, ptr, sizeof(uint32_t)); // TTL
|
||||
ttl = Endian::be_to_host(ttl);
|
||||
ptr += sizeof(uint32_t);
|
||||
std::memcpy(&data_size, ptr, sizeof(uint16_t)); // Data size
|
||||
data_size = Endian::be_to_host(data_size);
|
||||
ptr += sizeof(uint16_t);
|
||||
// Skip the preference field if it's MX
|
||||
if(type == MX) {
|
||||
if(data_size < 2)
|
||||
throw malformed_packet();
|
||||
ptr += 2;
|
||||
data_size -= 2;
|
||||
type = stream.read_be<uint16_t>();
|
||||
qclass = stream.read_be<uint16_t>();
|
||||
ttl = stream.read_be<uint32_t>();
|
||||
data_size = stream.read_be<uint16_t>();
|
||||
// Read the preference field if it's MX
|
||||
if (type == MX) {
|
||||
preference = stream.read_be<uint16_t>();
|
||||
data_size -= sizeof(uint16_t);
|
||||
}
|
||||
if(ptr + data_size > end)
|
||||
if (!stream.can_read(data_size)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case AAAA:
|
||||
if(data_size != 16)
|
||||
throw malformed_packet();
|
||||
addr = IPv6Address(ptr).to_string();
|
||||
data = stream.read<IPv6Address>().to_string();
|
||||
break;
|
||||
case A:
|
||||
if(data_size == 4) {
|
||||
uint32_t uint32_t_buffer;
|
||||
std::memcpy(&uint32_t_buffer, ptr, sizeof(uint32_t));
|
||||
inline_convert_v4(uint32_t_buffer, small_addr_buf);
|
||||
used_small_buffer = true;
|
||||
}
|
||||
else
|
||||
throw malformed_packet();
|
||||
inline_convert_v4(stream.read<uint32_t>(), small_addr_buf);
|
||||
used_small_buffer = true;
|
||||
break;
|
||||
case NS:
|
||||
case CNAME:
|
||||
case DNAM:
|
||||
case PTR:
|
||||
case MX:
|
||||
compose_name(ptr, small_addr_buf);
|
||||
compose_name(stream.pointer(), small_addr_buf);
|
||||
stream.skip(data_size);
|
||||
used_small_buffer = true;
|
||||
break;
|
||||
default:
|
||||
if(data_size < sizeof(small_addr_buf) - 1) {
|
||||
std::copy(
|
||||
ptr,
|
||||
ptr + data_size,
|
||||
small_addr_buf
|
||||
);
|
||||
// null terminator
|
||||
small_addr_buf[data_size] = 0;
|
||||
used_small_buffer = true;
|
||||
case SOA:
|
||||
{
|
||||
stream.skip(compose_name(stream.pointer(), small_addr_buf));
|
||||
data = encode_domain_name(small_addr_buf);
|
||||
stream.skip(compose_name(stream.pointer(), small_addr_buf));
|
||||
data += encode_domain_name(small_addr_buf);
|
||||
const uint32_t size_left = sizeof(uint32_t) * 5;
|
||||
if (!stream.can_read(size_left)) {
|
||||
throw malformed_packet();
|
||||
}
|
||||
data.insert(data.end(), stream.pointer(), stream.pointer() + size_left);
|
||||
stream.skip(size_left);
|
||||
}
|
||||
else
|
||||
addr.assign(ptr, ptr + data_size);
|
||||
break;
|
||||
default:
|
||||
data.assign(stream.pointer(), stream.pointer() + data_size);
|
||||
stream.skip(data_size);
|
||||
break;
|
||||
}
|
||||
ptr += data_size;
|
||||
res.push_back(
|
||||
Resource(
|
||||
resource(
|
||||
dname,
|
||||
(used_small_buffer) ? small_addr_buf : addr,
|
||||
(used_small_buffer) ? small_addr_buf : data,
|
||||
type,
|
||||
qclass,
|
||||
ttl
|
||||
ttl,
|
||||
preference
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// no length checks, records should already be valid
|
||||
uint8_t *DNS::update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset) {
|
||||
while(*ptr != 0) {
|
||||
if((*ptr & 0xc0)) {
|
||||
uint8_t* DNS::update_dname(uint8_t* ptr, uint32_t threshold, uint32_t offset) {
|
||||
while (*ptr != 0) {
|
||||
if ((*ptr & 0xc0)) {
|
||||
uint16_t index;
|
||||
std::memcpy(&index, ptr, sizeof(uint16_t));
|
||||
memcpy(&index, ptr, sizeof(uint16_t));
|
||||
index = Endian::be_to_host(index) & 0x3fff;
|
||||
if(index > threshold) {
|
||||
if (index > threshold) {
|
||||
index = Endian::host_to_be<uint16_t>((index + offset) | 0xc000);
|
||||
std::memcpy(ptr, &index, sizeof(uint16_t));
|
||||
memcpy(ptr, &index, sizeof(uint16_t));
|
||||
}
|
||||
ptr += sizeof(uint16_t);
|
||||
break;
|
||||
@@ -493,24 +505,27 @@ uint8_t *DNS::update_dname(uint8_t *ptr, uint32_t threshold, uint32_t offset) {
|
||||
|
||||
// Updates offsets in domain names inside records.
|
||||
// No length checks, records are already valid.
|
||||
void DNS::update_records(uint32_t §ion_start, uint32_t num_records, uint32_t threshold, uint32_t offset) {
|
||||
if(records_data.size() > section_start) {
|
||||
uint8_t *ptr = &records_data[section_start];
|
||||
for(uint32_t i = 0; i < num_records; ++i) {
|
||||
void DNS::update_records(uint32_t& section_start,
|
||||
uint32_t num_records,
|
||||
uint32_t threshold,
|
||||
uint32_t offset) {
|
||||
if (section_start < records_data_.size()) {
|
||||
uint8_t* ptr = &records_data_[section_start];
|
||||
for (uint32_t i = 0; i < num_records; ++i) {
|
||||
ptr = update_dname(ptr, threshold, offset);
|
||||
uint16_t type;
|
||||
std::memcpy(&type, ptr, sizeof(uint16_t));
|
||||
memcpy(&type, ptr, sizeof(uint16_t));
|
||||
type = Endian::be_to_host(type);
|
||||
ptr += sizeof(uint16_t) * 2 + sizeof(uint32_t);
|
||||
uint16_t size;
|
||||
std::memcpy(&size, ptr, sizeof(uint16_t));
|
||||
memcpy(&size, ptr, sizeof(uint16_t));
|
||||
size = Endian::be_to_host(size);
|
||||
ptr += sizeof(uint16_t);
|
||||
if(type == MX) {
|
||||
if (type == MX) {
|
||||
ptr += sizeof(uint16_t);
|
||||
size -= sizeof(uint16_t);
|
||||
}
|
||||
if(contains_dname(type)) {
|
||||
if (contains_dname(type)) {
|
||||
update_dname(ptr, threshold, offset);
|
||||
}
|
||||
ptr += size;
|
||||
@@ -521,26 +536,16 @@ void DNS::update_records(uint32_t §ion_start, uint32_t num_records, uint32_t
|
||||
|
||||
DNS::queries_type DNS::queries() const {
|
||||
queries_type output;
|
||||
if(!records_data.empty()) {
|
||||
const uint8_t *ptr = &records_data[0],
|
||||
*end = &records_data[0] + answers_idx;
|
||||
if (!records_data_.empty()) {
|
||||
InputMemoryStream stream(&records_data_[0], answers_idx_);
|
||||
char buffer[256];
|
||||
uint16_t tmp_query_type;
|
||||
uint16_t tmp_query_class;
|
||||
while(ptr < end) {
|
||||
ptr = compose_name(ptr, buffer);
|
||||
if(ptr + sizeof(uint16_t) * 2 > end)
|
||||
throw malformed_packet();
|
||||
std::memcpy(&tmp_query_type, ptr, sizeof(uint16_t));
|
||||
std::memcpy(&tmp_query_class, ptr + 2, sizeof(uint16_t));
|
||||
while (stream) {
|
||||
stream.skip(compose_name(stream.pointer(), buffer));
|
||||
uint16_t query_type = stream.read_be<uint16_t>();
|
||||
uint16_t query_class = stream.read_be<uint16_t>();
|
||||
output.push_back(
|
||||
Query(
|
||||
buffer,
|
||||
(QueryType)Endian::be_to_host(tmp_query_type),
|
||||
(QueryClass)Endian::be_to_host(tmp_query_class)
|
||||
)
|
||||
query(buffer, (QueryType)query_type, (QueryClass)query_class)
|
||||
);
|
||||
ptr += sizeof(uint16_t) * 2;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
@@ -548,10 +553,10 @@ DNS::queries_type DNS::queries() const {
|
||||
|
||||
DNS::resources_type DNS::answers() const {
|
||||
resources_type res;
|
||||
if(records_data.size() >= authority_idx) {
|
||||
if (answers_idx_ < records_data_.size()) {
|
||||
convert_records(
|
||||
&records_data[answers_idx],
|
||||
&records_data[authority_idx],
|
||||
&records_data_[0] + answers_idx_,
|
||||
&records_data_[0] + authority_idx_,
|
||||
res
|
||||
);
|
||||
}
|
||||
@@ -560,10 +565,10 @@ DNS::resources_type DNS::answers() const {
|
||||
|
||||
DNS::resources_type DNS::authority() const {
|
||||
resources_type res;
|
||||
if(records_data.size() >= additional_idx) {
|
||||
if (authority_idx_ < records_data_.size()) {
|
||||
convert_records(
|
||||
&records_data[authority_idx],
|
||||
&records_data[additional_idx],
|
||||
&records_data_[0] + authority_idx_,
|
||||
&records_data_[0] + additional_idx_,
|
||||
res
|
||||
);
|
||||
}
|
||||
@@ -572,20 +577,109 @@ DNS::resources_type DNS::authority() const {
|
||||
|
||||
DNS::resources_type DNS::additional() const {
|
||||
resources_type res;
|
||||
if(records_data.size() >= additional_idx) {
|
||||
if (additional_idx_ < records_data_.size()) {
|
||||
convert_records(
|
||||
&records_data[additional_idx],
|
||||
&records_data[records_data.size()],
|
||||
&records_data_[0] + additional_idx_,
|
||||
&records_data_[0] + records_data_.size(),
|
||||
res
|
||||
);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool DNS::matches_response(const uint8_t *ptr, uint32_t total_sz) const {
|
||||
if(total_sz < sizeof(dnshdr))
|
||||
bool DNS::matches_response(const uint8_t* ptr, uint32_t total_sz) const {
|
||||
if (total_sz < sizeof(header_)) {
|
||||
return false;
|
||||
const dnshdr *hdr = (const dnshdr*)ptr;
|
||||
return hdr->id == dns.id;
|
||||
}
|
||||
const dns_header* hdr = (const dns_header*)ptr;
|
||||
return hdr->id == header_.id;
|
||||
}
|
||||
|
||||
// SOA record
|
||||
|
||||
DNS::soa_record::soa_record()
|
||||
: serial_(0), refresh_(0), retry_(0), expire_(0) {
|
||||
|
||||
}
|
||||
|
||||
DNS::soa_record::soa_record(const string& mname,
|
||||
const string& rname,
|
||||
uint32_t serial,
|
||||
uint32_t refresh,
|
||||
uint32_t retry,
|
||||
uint32_t expire,
|
||||
uint32_t minimum_ttl)
|
||||
: mname_(mname), rname_(rname), serial_(serial), refresh_(refresh), retry_(retry),
|
||||
expire_(expire), minimum_ttl_(minimum_ttl) {
|
||||
|
||||
}
|
||||
|
||||
DNS::soa_record::soa_record(const uint8_t* buffer, uint32_t total_sz) {
|
||||
init(buffer, total_sz);
|
||||
}
|
||||
|
||||
DNS::soa_record::soa_record(const DNS::resource& resource) {
|
||||
init((const uint8_t*)&resource.data()[0], resource.data().size());
|
||||
}
|
||||
|
||||
void DNS::soa_record::mname(const string& value) {
|
||||
mname_ = value;
|
||||
}
|
||||
|
||||
void DNS::soa_record::rname(const string& value) {
|
||||
rname_ = value;
|
||||
}
|
||||
|
||||
void DNS::soa_record::serial(uint32_t value) {
|
||||
serial_ = value;
|
||||
}
|
||||
|
||||
void DNS::soa_record::refresh(uint32_t value) {
|
||||
refresh_ = value;
|
||||
}
|
||||
|
||||
void DNS::soa_record::retry(uint32_t value) {
|
||||
retry_ = value;
|
||||
}
|
||||
|
||||
void DNS::soa_record::expire(uint32_t value) {
|
||||
expire_ = value;
|
||||
}
|
||||
|
||||
void DNS::soa_record::minimum_ttl(uint32_t value) {
|
||||
minimum_ttl_ = value;
|
||||
}
|
||||
|
||||
PDU::serialization_type DNS::soa_record::serialize() const {
|
||||
string encoded_mname = DNS::encode_domain_name(mname_);
|
||||
string encoded_rname = DNS::encode_domain_name(rname_);
|
||||
PDU::serialization_type output(
|
||||
encoded_mname.size() + encoded_rname.size() + sizeof(uint32_t) * 5
|
||||
);
|
||||
OutputMemoryStream stream(output);
|
||||
stream.write(encoded_mname.begin(), encoded_mname.end());
|
||||
stream.write(encoded_rname.begin(), encoded_rname.end());
|
||||
stream.write_be(serial_);
|
||||
stream.write_be(refresh_);
|
||||
stream.write_be(retry_);
|
||||
stream.write_be(expire_);
|
||||
stream.write_be(minimum_ttl_);
|
||||
return output;
|
||||
}
|
||||
|
||||
void DNS::soa_record::init(const uint8_t* buffer, uint32_t total_sz) {
|
||||
InputMemoryStream stream(buffer, total_sz);
|
||||
string domain = (const char*)stream.pointer();
|
||||
mname_ = DNS::decode_domain_name(domain);
|
||||
stream.skip(domain.size() + 1);
|
||||
domain = (const char*)stream.pointer();
|
||||
stream.skip(domain.size() + 1);
|
||||
rname_ = DNS::decode_domain_name(domain);
|
||||
serial_ = stream.read_be<uint32_t>();
|
||||
refresh_ = stream.read_be<uint32_t>();
|
||||
retry_ = stream.read_be<uint32_t>();
|
||||
expire_ = stream.read_be<uint32_t>();
|
||||
minimum_ttl_ = stream.read_be<uint32_t>();
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user